Index: tags/2.1.2/AUTHORS =================================================================== --- tags/2.1.2/AUTHORS (nonexistent) +++ tags/2.1.2/AUTHORS (revision 24813) @@ -0,0 +1,12 @@ +pcb-rnd maintainer: Tibor 'Igor2' Palinkas +contact: http://repo.hu/projects/pcb-rnd/contact.html + +An always up-to-date list of developers and contributors can be found at +http://repo.hu/cgi-bin/pcb-rnd-people.cgi + +PCB was originally written by Thomas Nau +Development was later taken over by harry eaton +The port to GTK was done by Bill Wilson +Dan McMahill converted the build system from imake to autoconf/automake. +DJ Delorie wrote the trace optimizer, added symbolic flag support and +many other improvements. Index: tags/2.1.2/COPYING =================================================================== --- tags/2.1.2/COPYING (nonexistent) +++ tags/2.1.2/COPYING (revision 24813) @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. Index: tags/2.1.2/Changelog =================================================================== --- tags/2.1.2/Changelog (nonexistent) +++ tags/2.1.2/Changelog (revision 24813) @@ -0,0 +1,1104 @@ +pcb-rnd 2.1.2 (r24805) +~~~~~~~~~~~~~~~~~~~~~~ + [act_draw] + -Fix: TextNew() syntax: missing font ID + -Add: do undo by default; optional first argument to suppress undo + + [autoroute] + -Fix: reset last subnet state when hitting a terminal + -Split: route data network mapping into a separate function from the overgrown main route data prepare function + -Split: mapping code: "line add" to a separate, reusable function + -Split: connection mapping: misc "object box add" into a separate, reusable function + -Add: code for the new netlist API + + [cam] + -Fix: virtual layers can be referenced by name + -Fix: _begin() should reset the struct even if cam is disabled, to make sure all states the exporter may check on are 0 + -Fix: don't crash if plugin has no arguments + -Add: file name templating + -Add: accept comments + -Add: cam() action accepts key=value options to set the base + -Add: prefix mkdir can return the file name + -Add: cam job configs for the old gerber exporter naming styles, where applicable + -Add: cam job configs for a few commonly used fabs + -Add: cam job configs for a few commonly used naming styles in other EDAs + -Add: cam dialog box + -Add: hidden cam exporter so that 'pcb-rnd -x cam jobname [pcb-rnd-options] filename' works + -Add: menu item for cam exporting, bound to {f c} + + [core] + -Fix: data dynflag clear shall be recursive so subc parts are cleared too + -Fix: while drawing slots, make sure to use the same layer that was set + -Fix: proper string handling in key quote for unrecognised key error + -Fix: hid_nogui, reading the stdin, takes EOF as cancel + -Fix: don't pop up an extra dialog for footprints-not-found in quiet mode + -Fix: don't crash on file not found while importing a netlist + -Fix: don't call hid ->log directly, uses pcb_message() + -Fix: throw an error on file load error (e.g. non-existing file) if there is no GUI + -Fix: do not draw broken bounding box of the xor drawn attached 'A' for text tool font placement + -Fix: the error message for not doing something to a locked object, also include the type name of the object to ease debugging + -Fix: allow the remove tool to operate on subc floaters even in non-loose-subc + -Fix: verbose action logging should go to stderr, not stdout + -Fix: plug_io calls GetStyles() directly, through C API to avoid action verbose prints + -Fix: text flag post-change: if dyntext flag changes, recalculate the bounding box because the display text likely changed too + -Fix: export() without arguments shouldn't crash but throw an error + -Fix: allow removing warnings on the first click after board load + -Fix: clear the warn cache flag only if we are clearing the WARN flag on all objects + -Fix: pcb_menu_default.c is a generated file, make distclean should remove it + -Fix: text rendering: invalid memory access on drawing the thin-drawn and xor-drawn version of the invalid/unspecified symbol + -Cleanup: box.h shouldn't depend on move.h; box.h is the lower level construct + -Cleanup: merge copy.[ch] into move.[ch] for compactness + -Cleanup: completly remove NLS _("") + -Rename: project file root prefix is not "geda-" but "coraleda-" because there's zero chance geda would ever use this project file format + -Rename: PCB_MOVE to PCB_MOVE_POINT - name too generic; move PCB_MOVE_POINT from move.h to box.h - all box and point helper macros are there + -Move: ClipInhibit() action from experimental features to core; add menu checkbox + -Change: exporting an empty board is useful in some situation - it should be only a warning, not an error + -Change: allow '*' in IDs, for kicad compatibility + -Split: route_draw.h from route.h to avoid unwanted hid.h dependency + -Add: render terminal IDs using a configurable template + -Add: safe_fs wrapper for pcb_mkdir, file size query, pcb_is_dir() + -Add: quoted string print variant that doesn't print the wrapping quotes but leaves that to the caller + -Add: include lihata node location (file:line) in keydesc parse error messages + -Add: LoadFrom() has a better function name for loading a footprint to buffer, deprecating the Element based name + -Add: throw error message on unknown first arg in LoadFrom + -Add: extend pcb_drc_lines() so that it can stop on the first blocker and return the mid-point coords + -Add: optional as-drawn-annotation of polygons + -Add: function to fix up IDs (subc refdes, terminal ID) by replacing invalid chars with underscore + + [hidlib] + -Cleanup: move layer visibility related calls from hid_flags to layer_vis (for hidlib clean) + -Split: hidlib: the common parts from main init and uninit sequence moved to hid_init - to be reused in a hidlib initialization + -Split: file_loaded from build_run, for hidlib + -Change: funchash should be in hidlib (generic keyword hash) + -Add: split OBJS and OBJS_C99 in preparation for a hidlib + + [dad] + -Fix: split _DEFAULT and use the _NUM and _PTR default setter to avoid int<->ptr casts + -Fix: runtime hide/unhide should deal with wltop[] in both lesstif and gtk, to affect the possible framing/scrolling as well + -Fix: autorun shall set table hid_ctx so that callback functions can access it + -Fix: retovr invalid memory handling: can not be part of the context because the context may be free'd by the caller too soon + -Fix: AUTORUN shall allocate retovrt and lock the dialog against new widgets + -Fix: don't deref ret-override struct fields if it's already NULL + -Fix: make flags an explicit field of the attribute struct - abusing max_val makes it impossible to use with numeric values + -Fix: trace mod key states even if the command prompt is open + -Add: infra for compound widgets + -Add: spinbox: compound widget for a DAD based universal spinbox + -Add: HATF for tightly packed boxes (used in spinbox buttons) + -Add: PCB_HATF_HIDE for initial widget hide + -Add: dynamic settable help text (tooltip) so that spinbox can set the error message for the warning widget + -Change: the export dialog doesn't depend on PCB_HATF_LABEL, but creates labels locally + -Change: the flagedit dialog doesn't depend on PCB_HATF_LABEL but creates labels locally + -Del: PCB_HATF_LABEL - no implicit labels anymore + + [dialogs] + -Fix: printcalibrate: don't crash if there's no printer but print error and return + -Fix: prompt-for 'enter key' handler: need a pointer to the pointer of return override, as it will be filled in by DLG_RUN() after widget creation + -Fix: the prompt-for action accepts NULL default string (uses "") + -Fix: remember all export attr widget ID, not only the first one per exporter, because it is not trivial (and rather fragile) to calculate further IDs + -Fix: layer bindings dialog: expfill on the table + -Fix: padstack dialog, generator tab: do not derive shapes if the initial shape generation failed + -Add: export dialog: if an exporter has more than 12 settings, rather add a scroll to the vbox so the dialog box won't grow too large + -Cleanup: move printer calibration out from core to the dialogs plugin - it's gui-only + -Split: compile dlg_about, dlg_comm_m, dlg_export, dlg_flag_edit, dlg_fontsel, dlg_layer_binding, dlg_layer_flags, dlg_lib_pstk, dlg_padstack as separate objects for speed + + [doc] + -Fix: typo: not closed in action ref + -Del: remove AdjustSizes() doc (action is getting removed) + -Update: datasheet: format support update, move gEDA down in the priorities + -Change: restructure the 7805 tutorial to be the generic work-from-schematics-editor tutorial, removing gschem references + -Add: tutorial: no-sch for beginners + -Add: tutorial: 15/step5 id for direct ref + -Add: tutorial: 16 (working from a tEDAx netlist) + -Add: datasheet: mention edakrill direct footprint access + -Add: explain dad _DEFAULT_VAL() and _DEFAULT_PTR() + -Add: action doc: Netlist, LiveScript, ClaimNet, OpenemsExcitation + -Add: document the cam syntax extension for multiple layers + -Add: cam examples on virtual layers (for exporting drills) + -Add: cam doc: document file name templating + -Add: script install genht 1.0.1 is too old for this + -Add: auto-generated table of all dialog boxes for the appendix + + [drc] + -Fix: missing cast caused overflow on circle shape hole ring break check, missing legit broken rings + + [export_dxf] + -Fix: do export internal copper layers when explicitly requested by cam + + [export_gerber] + -Fix: do not export DOC layers in non-cam mode, the old name-style code gets confused + -Add: coordinate format enum, support for higher precision output + -Add: in cam mode, allow exporting route/drill files in gerber + + [export_ipcd356] + -Fix: typo: invalid memory clear for heavy terminals + -Fix: test feature struct reset should overwrite the whole struct (sizeof() dereference bug) + + [export_ps] + -Fix: don't crash in calibration if there's no lpr specified + + [export_xy] + -Fix: pre-rotation pad width calculation (e.g. for the Macrofab template) works for non-90 deg rotation too + + [extedit] + -Fix: avoid double-remove of watches, some HIDs (e.g. lesstif) won't tolerate that + -Add: extedit(selected) and extedit(buffer) + + [find] + -Fix: don't clear mark on incremental search - we don't need to revisit objects already visited + -Fix: pcb_check_and_open_file() shouldn't use stat directly, but the compat_fs call for checking if a file is readable + -Cleanup: move pcb_check_and_open_file() from core to export_oldconn, that's the only user + -Add: incremental search from object + -Add: macro to check if an object is already marked by a find context + + [font] + -Fix: get rid of global fontsel object, make the code and API reentrant + -Fix: remember fontedit target object by id, not by object pointer so the dialog won't crash if the object is gone + -Fix: object font dialogs: on replacing the board, close all text object font edit dialogs - the are sure invalid for the new board + -Add: make object fontsel dialogs non-modal, keep them on a double linked list, don't let two dialogs open for the same text object + + [fp_fs] + -Fix: uninitialized libshell + + [fsd] (the new file selection dialog API) + -Del: old, per-HID save() and load() actions and associated custom file selection code + -Del: old filechooser and orphaned fileio action file from gtk + -Cleanup: move file selector flags from macros to an enum + -Cleanup: name prefix flags + -Cleanup: centralize ImportGUI(), remove the per HID implementation and related orphaned dialog box code + -Add: gtk: new fileselect implementation with subdialog support + -Add: lesstif: new fileselect implementation with subdialog support + + + [gerber] + -Fix: make sure to open a new file if cam file name template changed file + -Fix: premature uninit of cam caused unwanted drill file export when using the cam syntax + -Fix: verbose output should go to stderr, not stdout + -Split: move out and generalize the aperture code from the gerber exporter into separate source files + -Split: excellon exporting from gerber exporting; excellon can be called separately now + -Change: allow cam to export assembly layers + -Add: excellon: per plated/unplated file name option, overridden by the CAM file name when present + -Add: gerber verbose mode is also turned on by conf rc/verbose + -Add: make the new default the pcb-rnd name style + + [gtk] + -Fix: tooltip code with the new netlist won't crash if there's no refdes or terminal ID + -Fix: old library dialog refresh: make not a dir messages more explicit + -Fix: don't call hid ->log directly, use pcb_message() + -Fix: terminal tooltip shouldn't attempt to resolve netname if refdes or terminal ID is missing + -Fix: gdk special color set should never trigger a conf change, that'd result in an infinite loop + -Fix: old gtk-only DAD spinbox: save wltop[] properly + -Fix: DAD set on string values should save the new value with strdup + -Fix: don't unregister menus if the GUI is not active + -Fix: typo in the gdk render poly vertex optimization made offset polygons grow tentacles sometimes + -Fix: slipping tap bug + -Fix: window placement: have to query the window's geometry from the configure event, the data the event delivers does not include decoration (the "wandering window bug") + -Fix: use explicit label widgets for the parametric footprint parameter dialog - implicit names are not supported anymore + -Fix: param lib dialog: do not free non-allocated const char * string field name + -Del: ghid_scrolled_vbox(), ghid_scrolled_selection(), bu_check_button, ghid_table_coord_entry(), ghid_table_spin_button(), pcb_gtk_g_strdup(), util_str.[ch], util_gtk_debug.h, ghid_framed_vbox_end(), coord entry builder, text_view builder - no user + -Del: obsolete action: LogShowOnAppend() + -Cleanup: excess memory allocations and string copies on building top window titlebar + -Cleanup: remove unnecessary includes from the preview widget + -Add: DAD text scroll-to-bottom implementation + -Add: call the renderer's special color set callback upon conf change that affects those colors (this used to be a hackish direct call from the gtk-only config code) + + [hid] + -Fix: fallback no-gui hid: always print the "progress bar" if GUI is not the no-gui hid; in this state we are printing the progress bar for another HID + -Fix: do not draw the progress bar before GUI_INIT (fall back on the no-gui progress inidication) with HIDs that don't support opening DAD dialog before the GUI_INIT event (lesstif) + -Fix: always strdup HID string/path arguments parsed because the caller may free them + -Fix: don't crash when default hid argument string value is NULL + -Del: the old ->log() API, only ->logv() is in use now + -Cleanup: centralize the benchmark action to simplify the HID API + -Add: centralize user-lead code, replace the circles with an alternating arrow + -Add: DAD text scroll-to-end hid callback + -Add: hid property bit to indicate if markup in DAD text is possible + -Add: attribute dialog: raise window call + -Add: infra for hiding non-conventional export plugins from the export dialog, e.g. export_test and loghid and vfs later + + [import_edif] + -Fix: binary char leaked in to source code + + [import_netlist] + -Fix: uninitialized rat commands + + [import_sch] + -Cleanup: remove direct netlist dependency - rather use actions + + [io_eagle] + -Cleanup: resolve subc rotation TODO (precise vs. lossless) + -Add: poly clip inhibit during load to speed up + + [io_kicad] + -Cleanup: remove unused vars, remove, debug printfs + -Cleanup: code compaction on excess {}, compact var declaration + -Fix: text rotation: keep floating point rotation, use 'direction' only for centering and mirroring + -Cleanup: remove code dup in gr_text coord/rotation conversion with macros + -Cleanup: simplify text size X and size Y conversion + -Add: throw a warning if text size X and Y don't match, use the average + -Cleanup: simplify text thickness conversion and add a TODO for justification + -Cleanup: simplify the calculation for text rotation/mirror + -Fix: centralize GLYPH_WIDTH config and turn it into a macro + -Clenaup: remove gr_text/fp_text code duplication + -Add: create subc text on the right layer with subc offset and rotation applied + -Add: support for fp_text hide + -Add: warn for unknown effect argument + -Add: support for text thickness + -Add: create mech layer group for adhes layers and doc groups for courtyard and fab + -Cleanup: remove code dup: generalize gr_line parser to also handle fp_line and segment + -Fix: properly round coords after conversion + -Cleanup: rewrite gr_arc with the low level field parse macros + -Cleanup: remove code dup: gr_arc handles fp_arc as well + -Cleanup: via parsing: use the low level field parser macros, remove code duplications + -Cleanup: do not special case silk or top/bottom copper layer creation, layer stack parsing should handle it + -Fix: better error handling in the module code + -Add: preserve kicad module attributes as kicad_attr_* subc attribute + -Cleanup: reduce module parse code length by splitting fp_text out to a function + -Cleanup: split pad parser out from module parser, into a separate function, because it is large + -Cleanup: pad parse: simplify pad layer logics + -Fix: don't silently ignore unhandled pad child node, throw an error + -Fix: fp_line and fp_arc parsing error means module parsing error + -Cleanup: always use the layer id type, not int, for storing layer IDs + -Cleanup: compact the zone code, get more warnings and errors + -Add: ignore zone filled=yes and priority value + -Cleanup: all kicad_error() and kicad_warning() point to the right node + -Cleanup: use the COORD conversion macros for polygon vertex x;y instead of code duplication + -Cleanup: remove excess/redundant (node->str == NULL) checks + -Cleanup: centralize "ignore value but throw an error if it is NULL", optionally with also warning for duplicate arguments (remove code duplication) + -Cleanup: centralize layer parser to reduce code duplication + -Cleanup: remove CamelCase from read.c + -Fix: do not round module rotation, use a double + -Add: parse general/area for a mid-prio fallback to missing page size; use the central page size table + -Add: text object creation needs to get parent ("module") rotation because refdes text has this also embedded in the text rotation and that needs to be compensated to avoid double rotation + -Add: read pad_to_mask_clearance from the setup subtree using a table based loader + -Add: apply setup/pad_to_mask_clearance on smd and thr pads + -Add: create netlist on load; parse net of pads, add pads to the netlist + -Fix: don't create subc with invalid refdes, fix up the name with underscores + -Fix: filter pin names (terminal IDs), fix them up with underscore until they are valid + -Add: support for pad paste_ratio + -Fix: make unknown module parameter a fatal error + -Del: unused/dead code for via name: you don't name vias in pcb-rnd + -Add: layer parse shall count signal layers first - we can not depend on layer names in some old layers and KiCad's file format is just too broken to solve this without some guessing + -Add: accept "power" and "mixed" layers as copper layers, and use a better terminology for variables (copper instead of signal); remember layer type as layer attribute + -Add: parse the layer stackup by considering, IDs, names _and_ file version, trying to figure old board files; handle random foreign layer names and reverse order stack + -Add: force-reorder copper layers by layer number (used as emulated array index) to make sure internal layers are ordered properly, independently of what order they appear in the file - also consider KiCad's layer order switch after version 3 + -Cleanup: replace the old, hardwired C code based layer guesser with a data driven, generic, scoring algorithm + -Fix: don't warn for missing font: kicad doesn't embed font in the board file + -Add: parse multiple string children of text justify node, remember the alignment + -Add: consider left/right/center alignment in text placement + -Fix: caculate and use real text bounding box for fine placement/alignment/justify, instead of guessing from string length + -Fix: do not create hidden text objects (CUCP#42) + -Add: segment status: load 0x40000 as PCB_FLAG_LOCK (CUCP#40) + -Add: parse "layers" and "blind" for vias, throw error on contradiction or if layers don't resolve + -Add: support for loading and creating blind/buried vias (CUCP#41) + -Add: parse and apply "layers" subtree of pads + -Fix: do not ignore pad rotation; apply it considering subc rotation + -Add: allow loading any file format version from 2017 + -Fix: convert file version as long, not int - values like 20170000 are just too large, we must have at least 31 bits + -Add: support for round rect pads + -Add: parse pad options and mask/paste margins + -Fix: when loading a module as pcb, call the module parser + -Add: when loading footprint as pcb, create all layers the parser will need in advance + -Fix: throw an error if padstack ends up with no shape on any layer + -Add: parse fp_poly fields and create fp polygons + -Add: support for np_thru_hole pads + -Add: parse and create oval holes as slots + -Add: auto-create a mech layer for plated slots so they show up properly + -Add: ignore drill offset with a warning + -Add: handle empty (layers) in smd: assume *.Cu and throw a warning + -Add: ignore the autoplace* subtrees in modules + -Fix: some old files are defining thru-hole pads without drill geometry - improvise 0.5 mm for now + + [io_lihata] + -Fix: netlist patch typo mixed up "del" and "add" on load + -Fix: read: tolerate tailing whitespace in integer values + -Fix: do not crash when reading polygons with no contour + -Fix: free broken poly when reporting parse error + + [io_pcb] + -Fix: uninitialized fcmd + -Cleanup: move pcb_tmp_data_save() from core to io_pcb, the only user + + [layer] + -Fix: don't crash if virtual layer purpose comparison is requested but the virtual layer has no purpose string + + [lesstif] + -Fix: tree table binding: append new tree node at the right level when it has an existing sibling + -Fix: mem. err: dont manually unmanage a managed widget + -Fix: DAD close memory bug: do not wait for the dialog's widget if it is already destroyed + -Fix: tree table: various memory handling errors + -Fix: DAD result copy-back: always set default_val and make only the part that copes to results[] optional + -Fix: DAD text widget respects EXPFILL + -Fix: DAD: read/copy back the result even if there is no callback function registered for a widget - the readout may be async + -Fix: pack boxes as tight as possible + -Fix: DAD set on string values should save the new value with strdup + -Fix: do not load the background image if it is an empty string + -Fix: typo in hex digit converter of xpm + -Fix: call GetStyles() directly through C API to avoid verbose trace + -Cleanup: publish wait-for-dialog API and remove code duplication on it + -Cleanup: move box helper to dlg_attr_box + -Change: centralize the window geometry query code for window placement and make it query the real window size, don't rely on the config event data + -Del: AdjustSizes() - use the preferences dialog instead + -Add: integrate the new FillBox widget and replace the old RowColumn (no exp/fill support yet) + -Add: replace the non-portable motif tabbed widget with a local pages widget implementation + -Add: subbox DAD + -Add: new fileselect implementation + -Add: tree table: finish DAD binding + -Add: DAD text: scroll-to-bottom implementation + -Add: DAD text: respect the SCROLL flag + -Add: menu system: process and create popups/ - even tho there is no code to open popup menus at the moment, the key bindings are required + + [lib_compat_help] + -Fix: handle rotated square old pads properly: do the 90 deg rotation or throw an error on non-90-deg + -Add: paper size def for USLetter, required by kicad + + [lib_polyhelp] + -Fix: rewrite polyhatch(interactive) with DAD to fix the missing input labels problem + + [log] + -Fix: print pending log messages after a failed export with -x + -Cleanup: simplify the error.h API: file-system specific error messages have a central template and are macros instead of functions (wrappers around pcb_message()) + -Add: remember all log lines for a persistent log system, free all on exit + -Add: log append event so that the GUI can react + -Add: LogDialog() action, new log dialog code (using DAD) + -Add: conf node: rc/dup_log_to_stderr to allow reproducing error messages to stderr (console support) + -Add: Log() action with Clear command + -Add: the batch HID doesn't print debug messages unless verbose is set + + [mincut] + -Del: stub API - switched to the event API + -Del: obsolete "ignore" argument + -Cleanup: remove global variables, use local contexts + + [netlist] + -Change: full netlist engine rewrite from scratch + -Fix: do not assume the first terminal we are searching from actually exists - missing first terminal left the find state uninitialized + -Change: don't use intrusive popup for indicating footprint not found, just write an error in the log, that normally should pop up the log window and works better on CLI too + -Add: look up offender net on short circuit + -Add: short deduplication using a hash table + -Add: short indication event so that the netlist code does not need to depend on the mincut stub + -Add: rat draw: accept the situation that neither terminal is in a net - that's when a new net is created + -Add: use the user provided net name when creating a new net - create a netlist patch entry + -Add: case insensitive net search by name, standardize how user input is looked up + -Add: ClaimNet() for mapping existing objecrts as network + -Add: Netlist() rename and merge (action and GUI) + + [pcblib] + -Add: openscad models for the standard smd between 01005 and 1206 + + [propedit] + -Fix: memory handling error: set property only if address prefix matches + -Fix: flag and attribute sets are not recursive in subc + -Fix: propedit(object) should pick subc part padstack before subc + -Add: expose layer group type bits by name (read-only) + + [ps] + -Split: move out paper sizes to common code to lib_compat_help (io_kicad needs it too) + + [puller] + -Fix: make dependency on glib explicit + + [rat] + -Add: prepare the API for rat lines to remember their anchor objects + -Add: implementation of pcb_rat_anchor_guess() + + [report] + -Add: netlength warns for incomplete/shorted nets + -Add: warn for polygons/text objects in net length + + [res] + -Del: "Edit name of" menu - redundant; hotkey submenus for {e t} text edit and {e r} refdes edit moved to text and subc context menu; the rest are accessible more easily from the property editor + -Add: menu item for invert selection + + [rubberband] + -Move: move and rewrite the remove-rats-upon-object-removal from the rubber band code to core - it has nothing to do with rubber banding + -Cleanup: remove the old attempt for rubber band manipulation after refdes rename - there are too many corner cases, rather just erase all rats and let the user re-optimize them + + [scconfig] + -Fix: disable the script plugin if there's no system installed fungw found + -Fix: when enabling dialogs, draw_csect and draw_fontsel need to be enabled too + -Fix: do not -I or -l glib for core, even if glib is found on the system, as core does not depend on it in any way + -Fix: make distclean removes gmon.out which may be created during the -pg test + + [script] + -Fix: browse scripts dialog missing EXPFILL for proper layout + -Add: dialog live scripting + -Add: live script: list all fungw scripting plugins available + -Add: scripting anchor in the default menu file; live script dialog menu + + [shape] + -Fix: initial round rect rounding radius should be 1/10th of the width to result in a valid round rect shape that can be generated + -Fix: generate the new shape on tab change + + [subc] + -Fix: missing cast for subc rotation (may have caused truncation) + -Cleanup: const correctness on parent obj lookup + -Add: editor/subc_conv_refdes conf node special value "" means "do not create the refdes attrib, but create the refdes text", which will result in the printout with DYNTEXT + + [tests] + -Add: test cases for the new rat geo code (with shortest path on any object vs. any object) + -Add: netlist geo test case for polygon hole + -Add: run the drc_pstk_hbrk tests by default + + [tests/RTT] + -Fix: do not run on Proto or default (save some CPU cycles on uninteresting input) + -Update: rat.svg ref (it is exported despite of being empty) + -Update: rat.bom ref missing TEST author + -Update: layer_spc.bom missing TEST author (empty boards are exported now) + -Update: stderr filter for the new, more accurate warning/error messages on empty export and friends + -Update: eps refs for 'empty board exported' + -Update: ps refs for 'empty board is exported' + -Update: XY refs for 'empty board is exported' + -Update: gerber refs for 'empty board is exported' + -Update: svg refs for 'empty board is exported' + -Update: png refs for 'empty board is exported' + -Add: more SVG warning filter (for elliptical arc) + -Add: make sure gerber is generated with the fixed name style (explicit) + + [tool] + -Fix: box selection should be triggered only if there is a valid box (box is in the second state); fixes: random right click selections + + [util] + -Update: gsch2pcb-rnd to the new error API + -Add: script to list all dialog boxes + + [vfs] + -Add: plugin for exporting/exposing a board as a filesystem via FUSE or Midnight Commander vfs + +pcb-rnd 2.1.1 (r23079) +~~~~~~~~~~~~~~~~~~~~~~ + [portability] + -Change: #warnings translated to TODO() for portability + + [boardflip] + -Del: remove the plugin - mirror functionality already implemented in core, wrapper action moved to core + + [calay] + -Add: plugin for importing calay netlists + -Add: import menu item for calay netlist + + [cam] + -Cleanup: remove excess memory allocation on default output file name derivation + -Cleanup: default file name derivation does not need to remember the last set file name, this should be handled centrally later on + -Fix: missing else blocked purpose supplement to be interpreted + + [color] + -Add: centralize color parsing and handling + + [core] + -Fix: draw: expose_begin() and expose_end() needs to save all gc's as well else nested calls will result in NULL gcs after the first end() + -Fix: do not block-select invisible padstacks - a padstack is considered visible only if either the padstack virtual layer or the hole virtual layer is on + -Fix: mem handling error: do not free the memory passed to object change name, it would result in invalid name saved with the object + -Fix: freeze undo for mirroring subc data and buffer data as they should not be on undo list on per object basis + -Fix: arc hash and eq start angles for side-mirror + -Fix: properly combine transformation rotation angle and transformation side mirror for arc start angle hash and eq + -Fix: box selection should be triggered only if there is a valid box (box is in the second state); fixes: random right click selections + -Del: old CreateMenu() syntax with 6+ arguments + -Del: do not use hid->show_item, call the pinout() action from Display(pinout) + -Cleanup: remove alignment_distance conf node - nothing uses it + -Add: Select(invert) - invert selection (common function in vector graphic tools) + -Add: --dump-version and DumpVersion() - script parsable version query + -Add: idpath API to remember object IDs recursively through subcircuits + -Add: optional, caller specified transformations in expose-all + -Add: API for drawing layers with color fade + -Add: pcb-printf %mN takes the unit set by %m+ and uses it without any modification or override + -Add: config node to change layer group rendering: any other-group layers are rendered with the invisible objects color + -Add: config node and rendering mod for black_current_group option (high contrast rendering) + -Add: text: hash and eq rot degree, font ID and thickness + + [dad] + -Change: DAD dialogs need to use explicit close buttons - implicit per hid buttons are all removed + -Add: new widgets: picture, picture button, color picker, text edit + -Add: API: default/starting window size hint (optional) + + [dialogs] + -Fix: the new export dialog copies back the current attribute values from the dialog to exporter data after the dialog is closed - preserves users settings, but also fixes the memory handling error after export file name modification + -Fix: export dialog and flag dialog content can grow and fill available screen space + -Fix: PromptFor(): escape or WM close won't return the new string but an error so cancel is not confused with ok + -Change: new layer property dialog and layer group property dialog with DAD and add close buttons + -Move: plugins dialog from core to the dialogs plugin + -Add: PrintGUI - generalize the export dialog so it can list printers + -Add: GUI support for shape swap in the padstack editor dialog + -Add: padstack proto edit dialog inidicates with parenthesis and tooltip text if a layer is not available + -Add: padstack editor: button for duplicating the prototype (to detach) + -Add: dup proto button in pstk lib dialog + -Add: local config for window placement + -Add: default window size for layer binding dialogs + -Add: pressing enter on the PromptFor() entry closes the dialog + -Add: fallback color pick implementation + -Add: generic viewlist + -Add: new, HID-agnostic pinout dialog with extra pin ID features + -Add: preferences dialog: config tree view tab + -Add: preferences dialog: color tab content + + [doc] + -Del: all references to GPMI + -Del: gtk3: preferences dialog - not gtk-specific anymore + -Fix: plugin dev: conf inclusion needs one more tmpasm line + -Change: rewrite the action doc for Print() - we can now have multiple printer plugins + -Add: motivation: log slots and mech/doc layers + -Add: link the conf system from the doc index + + [drc] + -Cleanup: don't use global var to pass object to append in violation + -Del: remove the old, gtk-only drc dialog + -Split: old DRC algo: monolithic logics into shorter functions + -Add: new, view list based DRC dialog + -Add: extend the poly plow callback with a void * user data so that callbacks can have a context + -Add: remember 2 groups of offending objects per drc violation (red and blue groups) + -Add: introduce generic drc API/infra, decouple the old DRC algo from the GUI + -Add: DRC check: object-beyond-drawing-area + -Add: progress bar while running the old DRC algo + + [export_png] + -Add: set DPI on bitmap export + + [export_ps] + -Del: ps_bloat - use CAM layer transformations instead + -Fix: don't print implicit outline layer on all layers unless it is explicitly requested by the user + -Fix: wrong help text for drill helper + -Add: --drill-helper-size to force a specific diameter for all drilled hole when--drill-helper is set + + [export_stat] + -Fix: board size and area are calculated from the data width/height, not the drawing area's, when there's an explicit outline + -Fix: don't export empty board id as (null) but as empty string + + [export_xy] + -Fix: use %mN to make sure decimil and centimil are not converted + -Add: rewrite the pnp-origin find code so that it works with any object type + + [extedit] + -Fix: allow editing the external editor command + -Fix: use pclose() for popen() + + [find] + -Fix: netlist find/select should work by net name + -Fix: use the event system to run the drc, don't use direct function call as the drc is implemented in (potentially multiple) plugin(s) + -Cleanup: simplify internal DRCFind() API: no need to pass legacy type/ptr1/ptr2/ptr3 + -Change: rewrite the search algorithm and APIs + -Move: split/move export code for the old connection format from core into a new plugin: export_oldconn + -Add: use dynamically allocated flags for internal marking (instead of abusing global/static flags) + + [flag] + -Add: dynamic object flags for algoritmic uses + + [fp_fs] + -Fix: invalid memory handling (read beyond end of the string) on search path append + + [fungw] + -Fix: simplified action call wrapper returns -1 if result can not be converted to int + -Add: action name but binary args call shortcut + + [gpmi] + -Del: please use fungw instead + + [gsch2pcb-rnd] + -Fix: potential buffer overrun + + [gtk] + -Fix: print coords for parametric footprints only in sane units + -Del: get rid of the EditLayerGroups action (centralized) + -Del: get rid of wt preview kinds - there is only one kind, the generic one + -Del: get rid of local vertical and horizontal compactness config node, use the new, central node: appearance/compact + -Del: old, gtk-only preferences dialog + -Cleanup: netlist dialog: code dup on select/find button - rather use the action + -Update: DoWindow(preferences) throws a warning instead of invoking the old preferences + -Change: switch over from old, gtk-only window placement code to new, centralized code from the dialogs plugin + -Change: the old library dialog uses generic preview instead of pinout-specific preview + -Add: implement the clipboard API + + [hid] + -Del: report_dialog API - use DAD instead + -Del: remove unused API "can_mask_clear_rats" - got irrelevant with composite rendering + -Del: block hook API - nothing used it, there is no provision of ever using it + -Del: remove lesstif-only ConfirmAction (there's a generic action for this now: MessageBox) + -Del: old, per hid print action - already reimplemented using DAD as PrintGUI() in dialogs + -Cleanup: API CHANGE: remove confirm dialog and close confirm dialog API - reimplemented with DAD, no need for each HID to duplicate that code + -Add: clipboard API + -Add: rewrite the fontsel dialog using DAD + -Add: generic, DAD based user input dialog box to replace the per hid implementation + -Add: new, generic message box to replace the per HID implementation + -Add: DAD based progress bar dialog to replace the per HID implementation + -Add: make hid iteration API explicit instead of burried in the progress bar widget update + -Add: central Print() action that wraps the GUI action or throws a warning on CLI + -Add: centralize and unify window placement infra + + [hid_gtk2_gl] + -Fix: pcb_color_t mishandling + + [import_ttf] + -Update: #includes for latest scconfig and devuan's setup where there's no freetype2/freetype/*.h only freetype2/*.h + + [io] + -Add: "type" parameter in save incompatibility call to make the API compatible with pcb_view_t + -Add: when enabled and available, display io incompatibility in a view list instead of dumping logs + -Add: make io incompatibility view list dialog style (list vs. simple) configurable + -Add: do not automatically print the incompatibility list in quiet mode on CLI + + [io_eagle] + -Fix: read unsigned bitfield, not integer, from binary layer block + -Fix: fix PCB_MESSAGE format followed by hard fail on invalid layer number + -Fix: make eagle binary derived linetype attribute clearer and more explicit + -Fix: refined errors messages relating to failure to retrieve layer numbers + -Fix: bump bbox for all vertices of binary polygons, not every second vertex + -Fix: read binary arc bytes as bitfields, extract clockwise flags, and apply sign flags as required + -Fix: signed 3 byte coordinate reads from binary arc and wire blocks defining arcs now read properly + -Fix: negative flags now being properly applied to calculated arc centre, and arc stop-start coords + + [io_lihata] + -Fix: reading a board without silk layers is not an error above v1 + -Fix: do not write v1 board if top or bottom silk is missing + -Fix: break parsing and return error on broken embedded font + -Optimization: calculate the silk ordering on write only for lihata v1 - new versions of the format don't need this hack and ignored the result + + [io_pcb] + -Fix: when creating two initial layers for an element load, set them up properly (making them bound, silk and parent pointing to data) + -Fix: do not mess with the board layers when element is loaded as pcb - the layers are already set up properly + -Fix: incompat warning desc param mixup and unnecessary newline + -Fix: don't throw top silk layer warning for bottom silk if the subc is on the bottom side + -Fix: save elements and pads with the onsolder flag if they are on the bottom side + -Change: allow padstacks to have the onsolder flag in compatibility mode + + [io_tedax] + -Fix: plugin classification: it's a full IO plugin, not an import plugin + -Add: code for saving and loading: stackup, layer, netlist, drc and board + + [layer] + -Fix: search.c won't assume existing silk layers anymore + -Fix: make sure layer bound fields are empty when creating layer binding from real layers to avoid segfaults on uninitialized fields later + -Del: do not assert on existing top/bottom silk, they are not mandatory anymore + -Del: protection mechanism that wouldn't let users to remove top/bottom silk - they are safe to remove now + -Cleanup: memory leak on layer del: free fields + -Cleanup: rename layer free to layer free fields as it does not free the layer pointer + + [lesstif] + -Fix: don't use strcasecmp() because of portability + -Fix: process events in progress bar busy loop (for cancel) + -Fix: use a label box (hbox) for better alignment of old style attribute dialogs - fixes export dialog too large + -Fix: invalid memory write after WM close of DAD dialogs in lesstif + -Del: get rid of EditLayerGroups and the local csect preview + -Del: custom preview code for csect - we need only the generic preview for DAD now + -Del: local net find/select algo in the netlist window, in favor of the central algo + -Cleanup: use a much simpler call to create attribute dialogs: no need for implicit buttons anyway + -Add: window placement for the library, netlist and log window + + [pcblib] + -Fix: parametric footprint: wrong conversion of cmil and dmil to mil + -Fix: parametric footprint: convert default parameter dims even if they are not mm or mil but some other unit + -Fix: help text override for the local defautls in *sop() + -Fix: so() and its derivatives should list pin_* params in the help - they have no pins at all + -Fix: do convert explicit mil value coord properly even if there's no mil fallback + -Add: help text extraction: default value override + + [propedit] + -Fix: propedit menu actions: do not mess with selection, use the new scope syntax + -Add: new, non-modal, HID-agnostic DAD dialog for propedit + -Add: use a tree for properties instead of a flat list + -Add: scoping: specific objects (by ID), all selected objects, layer, layer group, board + + [pstk] + -Fix: corner case: hole is always thru-hole if there's no top or bottom copper layer, because we'd count from those + -Fix: respect override color on rendering + -Fix: hash eq/compare bugs on rot angle and mirror + -Add: new color config nodes for non-current layer padstack color, one for terminals and one for non-terminals ("vias") - these are used instead of the invisible color + + [query] + -Fix: duplicated clearance value for line and arc query access + -Add: return polygon clearance if poly-clears-poly flag is set + + [report] + -Del: use DAD instead of the report_dialog API of HID + -Add: Report(netlength) uses the new find API + + [menu] + -Fix: make refdes-only subc ID display more explicit and add an user defined fallback menu item + -Update: layer group edit brings up the new preferences window instead of the old + -Add: change font in text object context menu + -Add: menu items for rendering overrides: black current group and invis other groups + + [scconfig] + -Fix: loud error for unknown --buildin + -Fix: "recursive" dep resolver so that hid -> dialogs -> fontsel dep chain does the right thing + -Add: detect _Pragma(message) and prepare for replacing #warnings + -Add: need to detect gdImageSetResoltuion() as some versions of gd doesn't have it + -Fix: use --disable instead of --Disable for internal feature disabling - it is case sensitive + -Del: references to retired plugin nelma + -Fix: when glib is not available, disable gtk using the right flags + -Add: ./configure --man1dir can change manual page path to non-FHS + -Fix: do not disable lib_gtk_config - it's long gone + + [shape] + -Add: per corner control of round rect generation + -Add: resolution factor for rounding arc to make round corner arc emulation use less or more segments + + [subc] + -Fix: rounding trick so that rotation angles that are supposed to be round are got back as round + -Fix: negating host trans should negate the sin/cos calc too + -Fix: coord hasher assumes negated host trans + -Fix: angle hasher assumes negative transformation + -Add: extend subc host transformation readout with an option t return the negative transformation + -Add: make automatic refdes text on subc conversion configurable (and optional) + +pcb-rnd 2.1.0 (r21060) +~~~~~~~~~~~~~~~~~~~~~~ + [act_draw] + -Add: new plugin to host basic drawing actions: LineNew, ArcNew, TextNew, PstkNew, polygon creation + + [ar_cpcb] + -Add: import/export/autoroute plugin for external auto-router c-pcb + + [asm] + -Add: hand assembly helper plugin + + [cam] + -Add: parse supplements: purpose field, transformations + + [conf] + -Fix: ignore rc/library_shell from board and project fields - might be unsafe + -Fix: ignore all command conf nodes from unsafe sources while doing a conf merge instead of waiting until popen() - this way valid values from safe sources are not masked + + [core] + -Fix: ChkView() action shall return the state value properly for named virtual layers + -Fix: arc remove op: do not clear the parent field before unregistering the arc - arc unreg will do it anyway + -Fix: call end_layer for each set_layer in board boundary draw + -Fix: do not let empty-bbox footprints load as board to avoid a slowdown/crash + -Fix: don't crash when the rat code announces a short circuit for an unknown net + -Fix: file name pattern subs: shorter name that also includes PCB for anonymous files in %F + -Fix: heavy terminal poly color mixup on HIDs that turned off layer indication gfx + -Fix: initialize all fields of dummy text object before drawing in drawing stub error message + -Fix: keep side flip operations together in the same serial group of undo + -Fix: make text thickness change operation undoable + -Fix: pcb_backup() should always use the same, configured pattern, which should have the file name and the PID to minimize the chance of accidental overwrite of backup files + -Fix: refuse to execute on-selected operations on objects that are locked + -Fix: search_data_by_loc return value when nothing matched + -Fix: search_data_by_loc shouldn't pass object as const, the callback may need to change the object + -Fix: survive nonexisting silk layers in draw (silk color determination is optional) + -Fix: use the layer recipe for unbound subc layers to avoid a crash on NULL layer ptr + -Fix: wrong plug footprint temp var initialization (potential buffer overrun) + -Fix: don't throw error on font load cancel + -Fix: when destroying font with arcs in it, do not unreg the arcs, they are not registered + -Del: no need to pass layer pointer to many object draw functions + -Change: CreateMenu(): new, simplified syntax (plus compatibility with the old syntax for now) + -Change: off-limits default color is a bit darker so that holes and slots stick out more + -Change: the lock tool uses the log through Report() instead of spamming the desktop with popups + -Cleanup: data init/new and uninit/free terminology: free should free the pointer + -Cleanup: remove CamelCase from draw code + -Cleanup: remove CursorX, CursorY and Zoom from the board struct - these are not board specific properties but GUI/editor specific ones + -Add: 'quiet' option in path resolve to suppress error log for the case the caller checks the result and handles broken substs + -Add: -x -list- prints a script readable list of export plugins + -Add: NewGroup() accepts a 4th argument to set the comb bits of the new layer + -Add: bump default2.lht to v6 and add mech layers + -Add: bump default4.lht to v6 and add mech layers + -Add: change refdes action and menu - change name too often picks up the wrong object + -Add: check hid_conf registration leftovers on uninit, in debug mode + -Add: extend MoveLayer() so it can be used to move a layer into a different group from CLI + -Add: gettimeofday() wrapper to fix a compilation bug on IRIX + -Add: give the caller a chance to set rat id on creation + -Add: helper code for generic 2d transformation matrices + -Add: id->obj hash in data + -Add: new standard object call: reg/unreg for ID administration + -Add: pass an extended draw info structure from the top of drawing requests all way through the recursion to the bottom calls; this will help injecting object rendering transformations + -Add: pstk creation gets an optional id (that will let io_lihata enforce id on pads later) + -Add: silently ignore the "connected" flag (it is not supported) + -Add: simplified text render call API - to be used with preview widget drawing + -Add: standard obj call: text/poly pre/post + -Add: config setting for using basename of the board in export files comments/headers instead of the full path (to fix path leaking) + + [dad] + -Fix: memory leak: free all fields of a dialog, not only the last + -Fix: tolerate NULL pointer in preview free callbacks + -Fix: autorun didn't deliver the return value so it was impossible to detect a cancel + -Add: tree-table widget: API + -Add: tree-table widget: gtk implementation + -Add: progress bar widget: API + -Add: progress bar widget: gtk and lesstif implementation + -Add: hpane and vpane widget: API + -Add: hpane and vpane widget: gtk and lesstif implementation + -Add: preview widget: API + -Add: preview widget: gtk implementation + -Add: dad() action + -Add: scripted dialogs: free tree table rows + + [diag] + -Fix: data integrity: rewrite checks from LYT_OUTLINE to LYT_BOUNDARY + -Fix: data integrity: considers global rat lines + -Add: data integrity: check for the new ID hash + -Add: data integrity: check for layer->group->layer links + -Add: data integrity: test for duplicate layer entry in group and for group->layer->group links + + [dialogs] + -Fix: make it clear that group edit is about not logical, but physical layers + -Fix: padstack edit shall allow setting hole dia to 0, that's how hole is removed + -Fix: when regenerating the padstack shape, invalidate the drawing so the new shape shows up + -Fix: padstack editor doesn't silently ignore unknown shapes layer types, but throw an error + -Rename: layer and group GUI editing is not only about flags, rename the actions to be more clear about the purpose + -Add: undo dialog + -Add: 'change type' combo box in the group type/name dialog + -Add: support for layer group location change from the GUI + -Add: layer group flags dialog: purpose field, location field + -Add: purpose field in layer bindings + -Add: new pinout dialog + -Add: pstklib: padstack library dialog, with preview + -Add: padstack dialog: the prototype button invokes the pstklib dialog for selecting a new proto + + [doc] + -Fix: some layer groups are 'maybe' for compositing + -Fix: lesstif SwapSides should have S mentioned in the syntax + -Fix: internal units is not 1/100 mil anymore + -Update: edit and update acompnet content + -Update: bridges: add xschem and c-pcb + -Update: mark gpmi deprecated + -Del: remove nelma (plugin retired) + -Del: old shorthand command summary from the code - don't advertise these actions + -Move: action doc moved from code to doc action appendix (and script that generates the output doc and links) + -Add: lihata v6 change log + -Add: lihata board format spec: explain that padstack shape layer mask needs to contain no more than 1 location bits + -Add: new terminology: the "main type" of layer groups + -Add: actions are sorted and dedup'd in the appendix + -Add: cam layer supplements + -Add: coralEDA link in index + -Add: eagle and protel compatibility on main page + -Add: Mageia and Fedora have official package + -Add: FAQ + -Add: FAQ entry for dsn missing holes on import + -Add: FAQ entries on DSN import vs. silk, mask and paste + -Add: developer doc: object API: document reg/unreg, pre/post API + -Add: rosetta: DAD examples + -Add: explain what a pup file is for + -Add: developer doc: detailed description of the basic infra of a plugin + -Add: document geda/pcb format extensions + -Add: extend the datasheet with data model points + -Add: Zoom() doc with selected and found + -Add: document the purpose of CycleDrag() + -Add: scripting: document AddTimer() + -Add: scripting: LoadScript(), UnloadScript(), ReloadScript() and ListScripts() + -Add: scripting: ScriptPersistency() and script action preunload() + -Add: scripting: Oneliner() + -Add: DAD documentation + + [export_gerber] + -Fix: handle multiple outline layers + -Fix: drill file end marker is M30 + -Workaround: OSHpark import doesn't take G00 in separate line + -Add: support for drilled (G85) slots and routed (G00) slots + + [export_png] + -Fix: more robust outline coord cheat for working around gd's broken line clipping + -Fix: workaround on alpha+photomode if the core sets the boundary layer twice (when mech layers are missing) + -Fix: multi-step outline draw: let all layer groups be drawn + -Change: draw rectangles by drawing lines to guarantee the right brush + -Change: mark png-bloat obsolete (use cam transformations instead) + + [export_ps] + -Fix: handle multiple route layers + -Fix: more robust and efficient way to determine if there's explicit outline + -Fix: reproduce the implicit outline using the same line width that draw.c in core does + -Change: mark ps-bloat obsolete - use cam layer transformations instead + + [export_stat] + -Fix: when deciding if a subc is smd or not, count slots for through-hole + -Add: upgrade for counting slots + + [export_svg] + -Fix: don't write the group of empty layers + + [gsch2pcb-rnd] + -Fix: -q inhibits printing the instructions and the no-method-specified warning + + [gtk] + -Fix: key presses doesn't mean the cursor has entered the view - fixes bug: getxy returned valid-looking coords instead of asking the user if there was no crosshair but keyboard input + -Fix: use all screen space for the command entry + -Fix: the print dialog needs to get the gtk common struct instead of topwin because of the preview API + -Fix: old pinout preview should call the new zoomto API to get the footprint zoomed + -Fix: set definite drawing area size for the font selector + -Fix: preview: set initial size request and canvas size of pinout windows so the zoom logics can calculate the initial zoom level + -Fix: library preview: more accurate initial zoom with all floaters included + -Fix: when setting up the preview widget for csect, set default width and height so that zoomto does the right thing (fixes: graphics does not appear) + -Fix: apply horizontal and vertical compactness from conf change events, not hardwired calls from gui config so direct conf change is applied too + -Fix: DAD: when creating a new box for a frame (requested in flags), respect the EXPFILL flag + -Fix: DAD: if caller's close callback destroys the modal dialog, make sure the original response (wheter it was ok or cancel) is preserved and returned + -Fix: apply xoffs/yoffs margin correction to layer previews as well + -Fix: preview popup is on the right click (in-line with the default menu config) + -Fix: proper rounding in screen<->coord conversion (fixes the slipping tab bug) + -Fix: after entering a new value, even if with new unit, preserve the text, don't overwrite it with canonical form until it's necessary (for stepping or clamping) + -Change: split the layer selector widget to have a separate section for in-stack and out-of-stack layers + -Change: replace local cli history implementation with the central one from lib_hid_common + -Change: tune status line print: use shorter bolds to decrease horizontal size + -Cleanup: CLI's main loop is in the context, not a global var + -Del: remove the separate command window entry - does not play well together with the new CLI ideas, doesn't fit in the unified GUI approach and didn't seem to get much use anyway + -Del: route style dialog: no 'save style as default' any more: route style is not in the config, the default board should be edited + -Del: text direction from the advanced search dialog + -Del: bu_notebook and framed notebook page builder: no code uses it + -Add: advanced search tabs: rotation and thickness text fields are available in query() + -Add: advanced search: tab entry for host layer's purpose + -Add: resize grip on top window + -Add: route style dialog: entry to text thickness + -Add: route style dialog has a text scale entry + -Add: new, more generic preview widget API, compatible with the DAD idea + -Add: on top win close, close the command entry first, as it has its own main loop that can block everything - fixes bug: can't exit while command entry is open + + [hid] + -Change: API CHANGE: pass on purpose and purpi to layer group set so that decisions can be made based on subtype of mech/doc layers later + -Change: API CHANGE: pass on editable "caller xform" struct pointer to the set layer API so exporters can configure the core to do transformations on drawing + -Fix: give control to the HIDs about whether heavy term layer indication gfx shall be drawn or not + -Add: remove menu by cookie if not by path + -Add: cli central history API + + [hid_gtk2_gl] + -Fix: do not draw the crosshair if the cursor is not in the drawing area (follow lesstif and gtk2+gdk on this) + + [hid_gtk3_cairo] + -Fix: do not draw the crosshair if mouse cursor is not in the drawing area (unify behavior across HIDs - untested) + + [hid_lesstif] + -Fix: typo in action handling code made zoom() (a.k.a. zoom extent) a syntax error + -Fix: lesstif Zoom() must do the same as gtk Zoom() + -Add: load/save/append to the central command line history + + [io_dsn] + -Add: full board parse/load + + [io_kicad] + -Fix: fp_circle is a 360 degree arc + + [io_kicad_legacy] + -Fix: scaling of exported legacy module library fixed, and integer decidegree pad rotations enforced + + [io_lihata] + -Fix: don't attempt to fix up the outline layers if there's no board (subc loaded) + -Fix: properly return NULL for failed padstack write + -Fix: warn for saving text thickness in route style only under v6 + -Fix: create polygon with the right ID on load + -Fix: load lines, rats, arcs, text, padstacks, and subcircuits with the right ID, create them only with the right ID + -Fix: warn for empty layer type in padstack proto shape on load + -Fix: when saving padtsacks with slot to lihata v5, do not save the slot shape with empty layer type but omit it - causes less confusion and on broken files + -Del: 'no_id' from parse_line(): we always need to have an ID because of the ID registration + -Change: do not save layer visibility bit in v6, warn when it is loaded from v6 + -Add: lihata board format version 6, for supporting new layers types and slots, new text props + -Add: when loading pre-v6 lihata, make sure the outline layer's comb is marked 'auto' + -Add: save noshape thermal as an explicit flag from v6 up + + [io_pcb] + -Fix: recover from broken group string - create intern copper layer for any layer that is not referenced from the group string + -Fix: do poly clipping only once during load - shorter load times + -Fix: do not save duplicate element attributes (footprint, value and refdes - they are saved as property in this old format) + -Fix: do not lose multiple special layers on load, even tho only the first one is placed in the right group + -Del: pcb format documentation from the .y file - pcb-rnd should not attempt to document alien formats, we should leave this task to the maintainer of the format (geda/pcb in this case) + -Add: warn the user when saving a NetListPatch - geda/pcb won't like it + -Add: fix up broken (unlinked) outline layers after load (it's probably pstoedit that generates such files) + + [layer] + -API CHANGE: creating a new bound layer gets a purpose string + -Fix: whether the implicit outline layer needs to be drawn does not depend on how many outline objects got draw, but really depends on how many outline objects there were on those layers + -Fix: when fixing up outline layer (e.g. after loading from old file formats), set the auto comb flag on the layers (to allow padstack use) + -Fix: ask the hid whether plated and unplated slots should be drawn only if they exist + -Fix: when creating real layers for bound layers, set new layer's object type to PCB_OBJ_LAYER + -Fix: #tbs: do not let the user remove top/bottom silk groups (temporary workaround) + -Del: PCB_LYT_ASSY, PCB_LYT_FAB, PCB_LYT_CSECT - use the purpose field instead + -Del: PCB_LYT_UDRILL and PCB_LYT_PDRILL - use the purpose field instead + -Del: PCB_LYT_OUTLINE - use BOUNDARY and purpose + -Change: side-based silk+doc layer rendering to make sure about layer order; properly draw global doc layers (between intern and current-side doc layers) + -Add: DOC and MECH layer types + -Add: purpose field + -Add: draw mech layers together with boundary layers, at the end + -Add: when drawing boundaries and mech layers, pick best candidate for unplated and plated slots + -Add: NewGroup() action for making it easy creating new layers from the menu (with context menu) + -Add: DupGroup(): new action and menu item for duplicating a layer group + + [nelma] + -Del: retire the plugin - upstream stopped maintenance and there was no user either (openems and other sims will take the role) + + [oldactions] + -Del: Return() - something we never used + + [polygon] + -Fix: rewrite the polygon offset code based on the colinear-corner-shift idea to avoid line-line intersections + -Fix: when a layer is moved to a different group, reclip all polygons of the layer automatically + -Change: expose the API of polygon offset low level - to be reused by padstacks + -Add: polygon offset cache normal vector calculator + -Add: draw_info bloat transformation works on polygons + + [propedit] + -Fix: use the undoable text rotation change API + -Del: text direction - use text rotation instead + -Change: rename text rotation to direction to match the code and make room for real rotation + -Add: code for handling text thickness and partial code for handling text rotation + -Add: layer group purpose field + -Add: missing code for removing attributes from board + + [pstk] + -Fix: use ortho-grow for padstack shape offseting for more accurate results of derive/grow/shrink + -Fix: do not crash if prototype is empty + -Fix: missing 'else' made wireframe/thin draw poly shape filled + -Fix: throw a loud error when a padstack with empty shape layer is broken up + -Add: no-thermal clearance for hshadow should trace the hole or slot shape + -Add: slot support: convert to pstk: accept one boundary or mech layer for slot + -Add: hshadow support (special shape for clearance around the hole, without copper) + -Add: low level pcb_pstk_shape_at_() that can be forced to return the shape even if thermal is NOSHAPE + -Add: padstack draw respects the noshape thermal and inhibits drawing + -Add: the thermal tool cycles through the no-shape bit now + -Add: special treatment of off-board padstacks: do not clip or undo + -Add: low level proto call for replacing the geometry in-place, without creating a new proto + -Add: utility function to count prototype usage under data + -Add: utility function for removing a padstack prototype + + [query] + -Change: rename text rotation to text direction to make room for the real rot field + -Cleanup: layer is a searchable object now, let the low level code search/list layers, but disable it from high level for now to keep compatibility + -Add: support for text rot and thickness + -Add: access layer purpose (group's purpose) + + [res/menu] + -Fix: editing layer or layer group properties should unselect all so nothing else is edited + -Del: mnemonics from the menu files (for HID API simplification) + -Change: better key binding for the plugin management dialog: {p m p} + -Add: integrity check in the maintenance menu + -Add: change refdes submenu in subc context menu + -Add: dedicated submenu for user scripts + -Add: subc layer binding in the subc context popup menu + + [tests/rtt] + -Fix: unify how pcb-rnd is executed; proper from-src-dir execution + -Fix: use basename in ps/eps export to get reproducible output + -Add: slot/mech example + -Add: visual compare script, format-independent + -Add: valgrind flags: detect memory leaks + + [rubberband_orig] + -Fix: rat line connected to multiple terminals on the same coord would move the rat endpoint multiple times when the subc is moved + -Update: moving a line with rubberband will remain connected to arcs by inserting a new route. + -Update: Moving a line point that is connected to an arc will insert a new route to ensure that the arc remains connected. + + [scale] + -Add: low level: text, arc, poly, line, padstack scaling + -Add: pcb_data_t and buffer scaler functions + -Add: ScaleBuffer() action + + [scconfig] + -Fix: stroke: insert the internal conf file to DEPDEP so make dep runs even when stroke is disabled + -Fix: cam, export_xy, fp_wget: explain enough of the internal conf so make dep works even if they are disabled + -Fix: remove --with-intl - it can render pcb-rnd unusable while we don't really have support for non-english locales + -Fix: detect popen(), missing popen is fatal (make the dependency explicit) + -Change: centralize the plugin internal conf mechanism + -Add: detect SIGPIPE and if present, set it to ignore to avoid external programs to exit pcb-rnd + + [script] + -Add: fungw engine (glue code) for "scripting" in C + -Add: Zoom(get) - useful for scripts + -Add: action AddTimer() and a minimalistic timer implementation + -Add: script data persistency: action for reloading and removing data + -Add: dialog frame for a script dialog + + [subc] + -Fix: do not change the subc pointer when moving to other side, rather do it in-place so pointers are not messed up (as reported by celem with autoplace) + -Fix: preview displays terminal labels when enabled + -Fix: when drawing preview do not draw the label of non-owned terminals + -Fix: memory leak on subc-in-buffer breakup + -Fix: subc dup needs to set layer struct type to PCB_OBJ_LAYER else the object is broken + -Fix: do not double-unreg objects on subc destroy (caused asserts on undo) + -Fix: display subc ID (red subc marking overlay) even if refdes is NULL - what we display is configurable and may differ from the refdes + -Fix: side flip: put only the subc flip on the undo list, not each subc part's flip, to avoid double-flip attempt on undo + + [text] + -Add: text string render: use transformation matrix instead of manual transformation calculations (preparing for arbitrary angle rotation) + -Add: buffer free rotation: also rotate text + -Add: user selectable text thickness + -Change: io_lihata saves only rot, not direction from v6 Index: tags/2.1.2/Changelog.1.0.x.gz =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/Changelog.1.0.x.gz =================================================================== --- tags/2.1.2/Changelog.1.0.x.gz (nonexistent) +++ tags/2.1.2/Changelog.1.0.x.gz (revision 24813) Property changes on: tags/2.1.2/Changelog.1.0.x.gz ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/Changelog.1.1.x.gz =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/Changelog.1.1.x.gz =================================================================== --- tags/2.1.2/Changelog.1.1.x.gz (nonexistent) +++ tags/2.1.2/Changelog.1.1.x.gz (revision 24813) Property changes on: tags/2.1.2/Changelog.1.1.x.gz ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/Changelog.1.2.x.gz =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/Changelog.1.2.x.gz =================================================================== --- tags/2.1.2/Changelog.1.2.x.gz (nonexistent) +++ tags/2.1.2/Changelog.1.2.x.gz (revision 24813) Property changes on: tags/2.1.2/Changelog.1.2.x.gz ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/Changelog.2.0.x.gz =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/Changelog.2.0.x.gz =================================================================== --- tags/2.1.2/Changelog.2.0.x.gz (nonexistent) +++ tags/2.1.2/Changelog.2.0.x.gz (revision 24813) Property changes on: tags/2.1.2/Changelog.2.0.x.gz ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/INSTALL =================================================================== --- tags/2.1.2/INSTALL (nonexistent) +++ tags/2.1.2/INSTALL (revision 24813) @@ -0,0 +1,70 @@ +1. Installation + +Run ./configure. + +Run make. + +Run make install. + +For compile-time options run ./configure --help + +2. Running from source + +cd src && ./pcb-rnd + +(Note: it is important to cd to src to run pcb-rnd from source; src/pcb-rnd +won't work unless pcb-rnd is installed). + +If this doesn't work, please refer to doc/UNIX.txt or doc-rnd/mac.txt + +-- + +PCB is organized into: + src/ a core program that deals with all of the internal + database procedures + src_plugins/ a collection of plugins + src_3rd/ third-party minilibs (dependencies, not integral parts) + pcblib/ a basic footprint library + tests/ automated tests to check whether pcb-rnd works properly + util/ utility programs like gsch2pcb-rnd + + +./configure will try to static link most plugins and disable ones that +have missing dependencies. This process can be controlled using configure +command line switches, see ./configure --help. + +After running ./configure with your selected options, run + + make + +to build pcb-rnd. You can try out the program by running + + cd src + ./pcb-rnd + +prior to installation (CWD _must_ be src/). + +To install PCB after it has been built run: + + make install + +from the top level directory. An alternative installation method +is the link-install, which places symlinks instead of copying files so +no subsequent make install is needed after a recompilation if no new +files appeared (useful for developers): + + make linstall + +-------- Summary of dependencies -------------------- +For users: + - C compiler + - make + - optional: glib and gtk if you are using the gtk frontend + - optional: gtkglext if you need opengl rendering + - optional: motif or lesstif if you are using the lesstif frontend + - optional: gdlib if you are using the png HID + +For developers: + - flex + - bison + Index: tags/2.1.2/Makefile =================================================================== --- tags/2.1.2/Makefile (nonexistent) +++ tags/2.1.2/Makefile (revision 24813) @@ -0,0 +1,56 @@ +all: FORCE + cd src_3rd/puplug/util && $(MAKE) CC=$(PCB_RND_HOST_CC) + cd src && $(MAKE) + cd util && $(MAKE) + cd pcblib && $(MAKE) +# cd doc && $(MAKE) + +test: FORCE + cd tests && $(MAKE) test + +clean: FORCE + cd src && $(MAKE) clean + cd util && $(MAKE) clean + cd pcblib && $(MAKE) clean +# cd doc && $(MAKE) clean + cd tests && $(MAKE) clean + cd src_3rd/sphash && $(MAKE) clean + cd src_3rd/puplug && $(MAKE) clean + cd src_3rd/libminuid && $(MAKE) clean ; true + cd src_3rd/libuundo && $(MAKE) clean ; true + +distclean: FORCE + $(MAKE) clean ; true +# cd doc && $(MAKE) distclean + cd src && $(MAKE) distclean + cd util/gsch2pcb-rnd && $(MAKE) distclean + cd src_3rd/genlist && $(MAKE) clean ; true + cd src_3rd/genregex && $(MAKE) clean ; true + cd src_3rd/genvector && $(MAKE) clean ; true + cd src_3rd/liblihata && $(MAKE) clean ; true + cd src_3rd/liblihata/genht && $(MAKE) clean ; true + cd src_3rd/qparse && $(MAKE) clean ; true + cd scconfig && $(MAKE) distclean ; true + + +install: FORCE + cd src && $(MAKE) install + cd util && $(MAKE) install + cd pcblib && $(MAKE) install + cd doc && $(MAKE) install + +linstall: FORCE + cd src && $(MAKE) linstall + cd util && $(MAKE) linstall + cd pcblib && $(MAKE) linstall + cd doc && $(MAKE) linstall + +uninstall: FORCE + cd src && $(MAKE) uninstall + cd util && $(MAKE) uninstall + cd pcblib && $(MAKE) uninstall + cd doc && $(MAKE) uninstall + +include Makefile.conf + +FORCE: Index: tags/2.1.2/Makefile.conf.in =================================================================== --- tags/2.1.2/Makefile.conf.in (nonexistent) +++ tags/2.1.2/Makefile.conf.in (revision 24813) @@ -0,0 +1,26 @@ +print [@# generated by ./configure, do not modify + +# Compatibility with autotools on DESTDIR - Debian really wants this +# Still keep install_root as well, because that has a better name +Install_root=$(install_root)$(DESTDIR) + +# prefix is @/local/prefix@ +DOCDIR=$(Install_root)@/local/prefix@/share/doc/pcb-rnd +LIBDIR=$(Install_root)@/local/prefix@/lib/pcb-rnd +BINDIR=$(Install_root)@/local/prefix@/bin +ETCDIR=$(Install_root)/etc +DATADIR=$(Install_root)@/local/prefix@/share/pcb-rnd +MAN1DIR=$(Install_root)@/local/prefix@@/local/man1dir@ +RM=@/host/fstools/rm@ +CP=@/host/fstools/cp@ +LN=@/host/fstools/ln@ +MKDIR=@/host/fstools/mkdir@ +SCCBOX=$(ROOT)/scconfig/sccbox +EXE=@/target/sys/ext_exe@ +PCB_RND_HOST_CC=@/host/cc/cc@ + +# The installation directoried to be used from within binaries (with +# install_root/DESTDIR removed) +LIBDIR_INSTALLED=@/local/prefix@/lib/pcb-rnd + +@] Index: tags/2.1.2/README =================================================================== --- tags/2.1.2/README (nonexistent) +++ tags/2.1.2/README (revision 24813) @@ -0,0 +1,28 @@ +pcb-rnd is a modular PCB layout editor. + +It is hosted at http://repo.hu/projects/pcb-rnd +Soruce code: svn://repo.hu/pcb-rnd/trunk + +For installing the release refer to the file 'INSTALL'. +For additional information read the manual (doc-orig/pcb.pdf) + +If you are updating you may wish to read the ChangeLog + +Contact: + email: http://repo.hu/projects/pcb-rnd/contact.html + chat & IRC: http://repo.hu/projects/pcb-rnd/irc.html + + +Pcb-rnd was forked from gEDA/PCB in 2013 +------------------------------------------------------------------------- + COPYRIGHT + +PCB is covered by the GNU General Public License. See the individual +files for the exact copyright notices. + + Contact addresses for paper mail and Email: + harry eaton + 6697 Buttonhole Court + Columbia, MD 21044 + haceaton@aplcomm.jhuapl.edu + Index: tags/2.1.2/Release_notes =================================================================== --- tags/2.1.2/Release_notes (nonexistent) +++ tags/2.1.2/Release_notes (revision 24813) @@ -0,0 +1,34 @@ +pcb-rnd 2.1.2 +~~~~~~~~~~~~~ + +This release of pcb-rnd focuses on code cleanup and fixin bugs. The three +major cleanups are the full netlist code rewrite, introduction of +CAM jobs which will long term replace the more limited gerber name +styles, and refactoring the KiCad file read code for more proper operation. + +Feature highlight: + +1. CAM jobs from the command line with -x and from the GUI with the + cam export dialog using {f c} + +2. live scripting: dialog box with a script editor for real time + development and experimentation with scripting + +3. almost complete KiCad load support for files generated with version 4 + or older + +4. optional gerber drill files + +5. option to directly export in the excellon format, without any gerber + +6. full netlist code rewrite: support for network mapping, renaming, merging + +7. actions and GUI for starting a board without a netlist and build + the netlist from within pcb-rnd + +8. new netlist dialog with enhanced functionality (same code for all HIDs) + +9. new log window with enhanced functionality (same code for all HIDs); + log is persistent (messages before GUI startup are not lost); + export log to file button/action + Index: tags/2.1.2/config.h.in =================================================================== --- tags/2.1.2/config.h.in (nonexistent) +++ tags/2.1.2/config.h.in (revision 24813) @@ -0,0 +1,282 @@ +print [@ /***** Generated by scconfig - DO NOT EDIT *****/ + +/* Source: config.h.in; to regenerate run ./configure */ + +#ifndef PCB_CONFIG_H +#define PCB_CONFIG_H + +/****************************************************************************/ +/* Static defines to enable extra features on some systems; once we get + testers on those systems, we can remove them and see if scconfig figured + everything. */ + +/* Enable extensions on AIX 3, Interix. */ +#ifndef _ALL_SOURCE +# define _ALL_SOURCE 1 +#endif +/* Enable threading extensions on Solaris. */ +#ifndef _POSIX_PTHREAD_SEMANTICS +# define _POSIX_PTHREAD_SEMANTICS 1 +#endif +/* Enable extensions on HP NonStop. */ +#ifndef _TANDEM_SOURCE +# define _TANDEM_SOURCE 1 +#endif +/* Enable general extensions on Solaris. */ +#ifndef __EXTENSIONS__ +# define __EXTENSIONS__ 1 +#endif + +/****************************************************************************/ +/* Package properties */ + +/* Name of package */ +#define PCB_PACKAGE "pcb" + +/* Name of this program's gettext domain */ +#define GETTEXT_PACKAGE "pcb" + +/****************************************************************************/ +/* These ones are already autodetected by scconfig */ +@] + +print {\n\n/* Macro to add a funciton attribute to suppress "function unused" for static inline functions declared in .h files */\n} +print_ternary ?cc/func_attr/unused/presents {#define PCB_FUNC_UNUSED __attribute__((unused))} {#define PCB_FUNC_UNUSED} + +print {\n\n/* inline, as detected ("inline" or empty) */\n} +print_ternary ?cc/inline {#define PCB_INLINE_DETECTED inline} {#define PCB_INLINE_DETECTED /* no inline */} + +print {\n\n/* final, combined keywords and attributes for an inline function */\n} +print {#define PCB_INLINE static PCB_INLINE_DETECTED PCB_FUNC_UNUSED\n\n} + +print {\n\n/* Wether setenv() works */\n} +print_ternary ?libs/env/setenv/presents {#define PCB_HAVE_SETENV 1} {/* #undef PCB_HAVE_SETENV */} + +print {\n\n/* Wether putenv() works */\n} +print_ternary ?libs/env/putenv/presents {#define PCB_HAVE_PUTENV 1} {/* #undef PCB_HAVE_PUTENV */} + +print {\n\n/* Wether usleep() works */\n} +print_ternary ?libs/time/usleep/presents {#define PCB_HAVE_USLEEP 1} {/* #undef PCB_HAVE_USLEEP */} + +print {\n\n/* Wether win32 Sleep() works */\n} +print_ternary ?libs/time/Sleep/presents {#define PCB_HAVE_WSLEEP 1} {/* #undef PCB_HAVE_WSLEEP */} + +print {\n\n/* Wether select() works */\n} +print_ternary ?libs/socket/select/presents {#define PCB_HAVE_SELECT 1} {/* #undef PCB_HAVE_SELECT */} + +print {\n\n/* Define to 1 if you have the `snprintf' function. */\n} +print_ternary ?libs/snprintf {#define HAVE_SNPRINTF 1} {/* #undef HAVE_SNPRINTF */} + +print {\n\n/* Define to 1 if you have the `vsnprintf' function. */\n} +print_ternary ?libs/vsnprintf {#define HAVE_VSNPRINTF 1} {/* #undef HAVE_VSNPRINTF */} + +print {\n\n/* Define to 1 if you have the `getcwd' function. */\n} +print_ternary ?libs/fs/getcwd/presents {#define HAVE_GETCWD 1} {/* #undef HAVE_GETCWD */} + +print {\n\n/* Define to 1 if you have the `_getcwd' function. */\n} +print_ternary ?libs/fs/_getcwd/presents {#define HAVE__GETCWD 1} {/* #undef HAVE__GETCWD */} + +print {\n\n/* Define to 1 if you have the `getwd' function. */\n} +print_ternary ?libs/fs/_getwd/presents {#define HAVE_GETWD 1} {/* #undef HAVE_GETWD */} + +print {\n\n/* Define to 1 if you have the header file. */\n} +print_ternary ?libs/gui/gd/presents {#define HAVE_GD_H 1} {/* #undef HAVE_GD_H */} + +print {\n\n/* Define to 1 if you have the `gdImageGif' function. */\n} +print_ternary ?libs/gui/gd/gdImageGif/presents {#define HAVE_GDIMAGEGIF 1} {/* #undef HAVE_GDIMAGEGIF */} + +print {\n\n/* Define to 1 if you have the `gdImageJpeg' function. */\n} +print_ternary ?libs/gui/gd/gdImageJpeg/presents {#define HAVE_GDIMAGEJPEG 1} {/* #undef HAVE_GDIMAGEJPEG */} + +print {\n\n/* Define to 1 if you have the `gdImagePng' function. */\n} +print_ternary ?libs/gui/gd/gdImagePng/presents {#define HAVE_GDIMAGEPNG 1} {/* #undef HAVE_GDIMAGEPNG */} + +print {\n\n/* Define to 1 if you have the `gdImageSetResolution' function. */\n} +print_ternary ?libs/gui/gd/gdImageSetResolution/presents {#define HAVE_GD_RESOLUTION 1} {/* #undef HAVE_GD_RESOLUTION */} + +print {\n\n/* Define to 1 if you have the `getpwuid' function. */\n} +print_ternary ?libs/userpass/getpwuid/presents {#define HAVE_GETPWUID 1} {/* #undef HAVE_GETPWUID */} + +print {\n\n/* Define to 1 if you have the `rint' function. */\n} +print_ternary ?libs/math/rint/presents {#define HAVE_RINT 1} {/* #undef HAVE_RINT */} + +print {\n\n/* Define to 1 if you have the `round' function. */\n} +print_ternary ?libs/math/round/presents {#define HAVE_ROUND 1} {/* #undef HAVE_ROUND */} + +print {\n\n/* Wrapper for S_ISLNK(x); always return 0 if S_ISLNK doesn't exist */\n} +switch ?/target/libs/fs/stat/macros/S_ISLNK + case {^$} print {#define WRAP_S_ISLNK(x) 0}; end; + default print [@#define WRAP_S_ISLNK(x) @/target/libs/fs/stat/macros/S_ISLNK@(x)@]; end; +end; + +print {\n\n/* Define to 1 if Xinerama is available */\n} +print_ternary ?libs/gui/xinerama/presents {#define HAVE_XINERAMA 1} {/*#undef HAVE_XINERAMA */} + +print {\n\n/* Define to 1 if Xrender is available */\n} +print_ternary ?libs/gui/xrender/presents {#define HAVE_XRENDER 1} {/*#undef HAVE_XRENDER */} + +print {\n\n/* Define to 1 if we should use windows api for dynamic linking. */\n} +print_ternary ?libs/LoadLibrary/presents {#define USE_LOADLIBRARY 1} {/* #undef USE_LOADLIBRARY */} + +print {\n\n/* Define to 1 if we should use mkdtemp for creating temp files. */\n} +print_ternary ?libs/fs/mkdtemp/presents {#define HAVE_MKDTEMP 1} {/* #undef HAVE_MKDTEMP */} + +print {\n\n/* Define to 1 if you have the `realpath' function. */\n} +print_ternary ?libs/fs/realpath/presents {#define HAVE_REALPATH 1} {/* #undef HAVE_REALPATH */} + +print {\n\n/* Select which mechanism to use for running child processes. */\n} +print_ternary ?/target/libs/proc/wait/presents {#define USE_FORK_WAIT 1} {/* #undef USE_FORK_WAIT */} +print {\n} +print_ternary ?/target/libs/proc/_spawnvp/presents {#define USE_SPAWNVP 1} {/* #undef USE_SPAWNVP */} + +print {\n\n/* Select which mechanism to use for creating a directory. */\n} +print_ternary ?/target/libs/fs/mkdir/presents {#define USE_MKDIR 1} {/* #undef USE_MKDIR */} +print {\n} +print_ternary ?/target/libs/fs/_mkdir/presents {#define USE__MKDIR 1} {/* #undef USE__MKDIR */} +print [@ +#define MKDIR_NUM_ARGS 0@?/target/libs/fs/_mkdir/num_args@@?/target/libs/fs/mkdir/num_args@ +@] + +print {\n\n/* Define whether we have specific signals. */\n} +print_ternary ?signal/names/SIGPIPE/presents {#define PCB_HAVE_SIGPIPE 1} {/* #undef PCB_HAVE_SIGPIPE */} +print {\n} +print_ternary ?signal/names/SIGSEGV/presents {#define PCB_HAVE_SIGSEGV 1} {/* #undef PCB_HAVE_SIGSEGV */} +print {\n} +print_ternary ?signal/names/SIGABRT/presents {#define PCB_HAVE_SIGABRT 1} {/* #undef PCB_HAVE_SIGABRT */} +print {\n} +print_ternary ?signal/names/SIGINT/presents {#define PCB_HAVE_SIGINT 1} {/* #undef PCB_HAVE_SIGINT */} +print {\n} +print_ternary ?signal/names/SIGHUP/presents {#define PCB_HAVE_SIGHUP 1} {/* #undef PCB_HAVE_SIGHUP */} +print {\n} +print_ternary ?signal/names/SIGTERM/presents {#define PCB_HAVE_SIGTERM 1} {/* #undef PCB_HAVE_SIGTERM */} +print {\n} +print_ternary ?signal/names/SIGQUIT/presents {#define PCB_HAVE_SIGQUIT 1} {/* #undef PCB_HAVE_SIGQUIT */} +print {\n} + +print {\n/* Code warnings for TODO, portable (unlike #warning) */} +if ?cc/pragma_message +then +print [@ +#define DO_PRAGMA(arg) _Pragma(#arg) +#define TODO(x) DO_PRAGMA(message("TODO: " #x)) +@] +else +print {\n/* Not available */\n#define TODO(x)\n} +end + +print [@ + +/* The host "triplet" - it's really a pair now: machine-os */ +#define HOST "@sys/sysid@" + +/* Directory separator char */ +#define PCB_DIR_SEPARATOR_C '@sys/path_sep@' + +/* Directory separator string */ +#define PCB_DIR_SEPARATOR_S "@sys/path_sep@" + +/* Search path separator string */ +#define PCB_PATH_DELIMETER ":" + +/****************************************************************************/ +/* These are static; they are kept "just in case", for further porting */ + +/* C89 has atexit() */ +#define HAS_ATEXIT 1 + +/* C89 has this */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if you have the `canonicalize_file_name' function. + It's a GNU extension, assume we don't have it and fall back to + realpath() */ +/* #define HAVE_CANONICALIZE_FILE_NAME 1 */ +/* Define if canonicalize_file_name is not declared in system header files. */ +/* #undef NEED_DECLARATION_CANONICALIZE_FILE_NAME */ + +/****************************************************************************/ +/* Paths */ + +#define PCB_PREFIX "@/local/prefix@" +#define PCBSHAREDIR PCB_PREFIX "/share/pcb-rnd" +#define PCBLIBDIR PCB_PREFIX "/lib/pcb-rnd" + +#define BINDIR PCB_PREFIX "/bin" + +/* Relative path from bindir to exec_prefix */ +#define BINDIR_TO_EXECPREFIX ".." + +/* Version number of package */ +#define PCB_VERSION "@/local/version@" +#define PCB_REVISION "@/local/revision@" + +/* Format: abccrrrrr where a, b and c are pcb-rnd version numbers and r is + the svn revision number (optional) */ +#define PCB_API_VER @/local/apiver@ + + +/* Define to 1 if you have the `dmalloc' library (-ldmalloc); + (memory debugging without valgrind) */ +@] + +print_ternary libs/sul/dmalloc/presents {#define HAVE_LIBDMALLOC 1} {/*#undef HAVE_LIBDMALLOC */} + +print [@ +/* +The documentation says it's not necessary to include dmalloc.h. +Pros: getting source line info +Cons: can't include from here, needs to be included from the bottom of the #include list from each file +#ifdef HAVE_LIBDMALLOC +#include +#endif +*/ + +@?/local/pcb/include_stdint@ + +/* Coordinate type and properties, as detected by scconfig */ +typedef @/local/pcb/coord_type@ pcb_coord_t; +#define COORD_MAX @/local/pcb/coord_max@ +#define coord_abs pcb_coord_abs + +/* Other autodetected types */ +typedef @/local/pcb/long64@ pcb_long64_t; + +/* the dot-dir: where to save user config under ther user's home; it's used + as ~/DOT_PCB_RND/ */ +#define DOT_PCB_RND "@/local/pcb/dot_pcb_rnd@" + +/* ./configure --workaround requests: */ +@?/local/pcb/workaround_defs@ + +/* Make sure to catch usage of non-portable functions in debug mode + This is in here only because config.h should be included from every source + file. */ +#ifndef NDEBUG +# undef strdup +# undef strndup +# undef snprintf +# undef round +# undef strcasecmp +# define strdup never_use_strdup__use_pcb_strdup +# define strndup never_use_strndup__use_pcb_strndup +# define snprintf never_use_snprintf__use_pcb_snprintf +# define round never_use_round__use_pcb_round +# define strcasecmp never_use_strcasecmp__use_pcb_strcasecmp +# ifndef PCB_SAFE_FS +# undef fopen +# undef popen +# undef system +# undef remove +# undef rename +# define fopen never_use_fopen__use_pcb_fopen +# define popen never_use_popen__use_pcb_popen +# define system never_use_system__use_pcb_system +# define remove never_use_remove__use_pcb_remove +# define rename never_use_rename__use_pcb_rename +# define mkdir never_use_mkdir__use_pcb_mkdir +# endif + +#endif + +#endif +@] Index: tags/2.1.2/configure =================================================================== --- tags/2.1.2/configure (nonexistent) +++ tags/2.1.2/configure (revision 24813) @@ -0,0 +1,4 @@ +#!/bin/sh +cd scconfig +make +./configure "$@" Property changes on: tags/2.1.2/configure ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/2.1.2/data/Makefile =================================================================== --- tags/2.1.2/data/Makefile (nonexistent) +++ tags/2.1.2/data/Makefile (revision 24813) @@ -0,0 +1,64 @@ +# This Makefile is a plain old hand written one; all configuration settings +# are included from ../Makefile.conf which is scconfig generated + +theme = hicolor + +app_icon = pcb + +mime_icons = \ + application-x-pcb-layout \ + application-x-pcb-footprint \ + application-x-pcb-netlist \ + application-x-gerber \ + application-x-excellon + +app_icon_files = \ + $(app_icon:%=%-48.png) \ + $(app_icon:%=%.svg) +# $(app_icon:%=%-16.png) +# $(app_icon:%=%-22.png) +# $(app_icon:%=%-24.png) +# $(app_icon:%=%-32.png) + +mime_icon_files = \ + $(mime_icons:%=%-16.png) \ + $(mime_icons:%=%-22.png) \ + $(mime_icons:%=%-24.png) \ + $(mime_icons:%=%-32.png) \ + $(mime_icons:%=%-48.png) \ + $(mime_icons:%=%.svg) + +mime_icon_sources = \ + $(mime_icons:%=%-16.svg) \ + $(mime_icons:%=%-22.svg) \ + $(mime_icons:%=%-32.svg) \ + $(mime_icons:%=%-48.svg) + +theme_icons = \ + $(mime_icon_files:%=mimetypes,%) \ + $(app_icon_files:%=apps,%) + +all: + +install_: + ./icon-theme-installer \ + -t $(theme) \ + -m "$(MKDIR)" \ + -s `pwd` \ + -d x \ + -b "$(themedir)" \ + -x "$(CPC)" \ + -i $(theme_icons) + +install: + $(MAKE) install_ CPC="$(CP)" + +linstall: + $(MAKE) install_ CPC="$(LN)" + +uninstall: + $(RM) $(DOCDIR)/examples/tut1.pcb + +include ../Makefile.conf +themedir=$(DATADIR)/icons/$(theme) + Index: tags/2.1.2/data/README =================================================================== --- tags/2.1.2/data/README (nonexistent) +++ tags/2.1.2/data/README (revision 24813) @@ -0,0 +1,56 @@ + +PCB +------------------------------------------------------------------------------ + +README for icon data + +This file describes where the various icons came from and their license. + +The PCB layout and gerber icons and mime registration data were contributed +by Tomaz Solc, and subsequently modified by Peter Clifton, including +creation of an excellon icon file with a ruler element taken from +Tomaz's gerber icon. The footprint and netlist icons were drawn by +Peter Clifton. + +The page outline featured in all the above icons is from the GNOME icon +theme's text-x-generic icon by Jakub Steiner. + +The icons are licensed under the GPL2 license. + +Scalable versions: (128x128 canvas for the "hicolor" fallback theme). +These were scaled up from the 48x48 pixel targeted version. + +application-x-excellon.svg +application-x-gerber.svg +application-x-pcb-footprint.svg +application-x-pcb-layout.svg +application-x-pcb-netlist.svg + +Pixel targeted varients: + +application-x-excellon-{16,22,32,48}.svg +application-x-gerber-{16,22,32,48}.svg +application-x-pcb-footprint-{16,22,32,48}.svg +application-x-pcb-layout-{16,22,32,48}.svg +application-x-pcb-netlist-{16,22,32,48}.svg + + +PNG versions of the above icons were exported from Inkscape. The 24x24 pixel +versions are copied from the 22x22 version, with a 1 pixel border added: + +application-x-excellon-{16,22,24,32,48}.png +application-x-gerber-{16,22,24,32,48}.png +application-x-pcb-footprint-{16,22,24,32,48}.png +application-x-pcb-layout-{16,22,24,32,48}.png +application-x-pcb-netlist-{16,22,24,32,48}.png + +The script "regen_files" will re-export the SVG drawings to PNG and also +regenerate the windows icon file. + +The PCB application icons were created by Peter Clifton, based upon the +Gnome "text-editor" icon created by Lapo Calamandrei. The PCB specific +additions are from the mime-type icons by Tomaz Solc. +These icons are licensed under the GPL2 license. + +pcb.svg +pcb-48.png Index: tags/2.1.2/data/application-x-excellon-16.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/data/application-x-excellon-16.png =================================================================== --- tags/2.1.2/data/application-x-excellon-16.png (nonexistent) +++ tags/2.1.2/data/application-x-excellon-16.png (revision 24813) Property changes on: tags/2.1.2/data/application-x-excellon-16.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/data/application-x-excellon-16.svg =================================================================== --- tags/2.1.2/data/application-x-excellon-16.svg (nonexistent) +++ tags/2.1.2/data/application-x-excellon-16.svg (revision 24813) @@ -0,0 +1,1271 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + Excellon file + + + + + + + Peter Clifton, Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: tags/2.1.2/data/application-x-excellon-22.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/data/application-x-excellon-22.png =================================================================== --- tags/2.1.2/data/application-x-excellon-22.png (nonexistent) +++ tags/2.1.2/data/application-x-excellon-22.png (revision 24813) Property changes on: tags/2.1.2/data/application-x-excellon-22.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/data/application-x-excellon-22.svg =================================================================== --- tags/2.1.2/data/application-x-excellon-22.svg (nonexistent) +++ tags/2.1.2/data/application-x-excellon-22.svg (revision 24813) @@ -0,0 +1,1571 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + Excellon file + + + + + + + Peter Clifton, Tomaz Solc, Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: tags/2.1.2/data/application-x-excellon-24.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/data/application-x-excellon-24.png =================================================================== --- tags/2.1.2/data/application-x-excellon-24.png (nonexistent) +++ tags/2.1.2/data/application-x-excellon-24.png (revision 24813) Property changes on: tags/2.1.2/data/application-x-excellon-24.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/data/application-x-excellon-32.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/data/application-x-excellon-32.png =================================================================== --- tags/2.1.2/data/application-x-excellon-32.png (nonexistent) +++ tags/2.1.2/data/application-x-excellon-32.png (revision 24813) Property changes on: tags/2.1.2/data/application-x-excellon-32.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/data/application-x-excellon-32.svg =================================================================== --- tags/2.1.2/data/application-x-excellon-32.svg (nonexistent) +++ tags/2.1.2/data/application-x-excellon-32.svg (revision 24813) @@ -0,0 +1,1406 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + Excellon file + + + + + + + Peter Clifton, Tomaz Solc, Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: tags/2.1.2/data/application-x-excellon-48.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/data/application-x-excellon-48.png =================================================================== --- tags/2.1.2/data/application-x-excellon-48.png (nonexistent) +++ tags/2.1.2/data/application-x-excellon-48.png (revision 24813) Property changes on: tags/2.1.2/data/application-x-excellon-48.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/data/application-x-excellon-48.svg =================================================================== --- tags/2.1.2/data/application-x-excellon-48.svg (nonexistent) +++ tags/2.1.2/data/application-x-excellon-48.svg (revision 24813) @@ -0,0 +1,1283 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + Excellon file + + + + + + + Peter Clifton, Tomaz Solc, Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: tags/2.1.2/data/application-x-excellon.svg =================================================================== --- tags/2.1.2/data/application-x-excellon.svg (nonexistent) +++ tags/2.1.2/data/application-x-excellon.svg (revision 24813) @@ -0,0 +1,1289 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + Excellon file + + + + + + + Peter Clifton, Tomaz Solc, Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: tags/2.1.2/data/application-x-gerber-16.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/data/application-x-gerber-16.png =================================================================== --- tags/2.1.2/data/application-x-gerber-16.png (nonexistent) +++ tags/2.1.2/data/application-x-gerber-16.png (revision 24813) Property changes on: tags/2.1.2/data/application-x-gerber-16.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/data/application-x-gerber-16.svg =================================================================== --- tags/2.1.2/data/application-x-gerber-16.svg (nonexistent) +++ tags/2.1.2/data/application-x-gerber-16.svg (revision 24813) @@ -0,0 +1,543 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + Gerber file + + + + + + + Peter Clifton, Tomaz Solc, Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: tags/2.1.2/data/application-x-gerber-22.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/data/application-x-gerber-22.png =================================================================== --- tags/2.1.2/data/application-x-gerber-22.png (nonexistent) +++ tags/2.1.2/data/application-x-gerber-22.png (revision 24813) Property changes on: tags/2.1.2/data/application-x-gerber-22.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/data/application-x-gerber-22.svg =================================================================== --- tags/2.1.2/data/application-x-gerber-22.svg (nonexistent) +++ tags/2.1.2/data/application-x-gerber-22.svg (revision 24813) @@ -0,0 +1,608 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + Gerber file + + + + + + + Peter Clifton, Tomaz Solc, Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: tags/2.1.2/data/application-x-gerber-24.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/data/application-x-gerber-24.png =================================================================== --- tags/2.1.2/data/application-x-gerber-24.png (nonexistent) +++ tags/2.1.2/data/application-x-gerber-24.png (revision 24813) Property changes on: tags/2.1.2/data/application-x-gerber-24.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/data/application-x-gerber-32.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/data/application-x-gerber-32.png =================================================================== --- tags/2.1.2/data/application-x-gerber-32.png (nonexistent) +++ tags/2.1.2/data/application-x-gerber-32.png (revision 24813) Property changes on: tags/2.1.2/data/application-x-gerber-32.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/data/application-x-gerber-32.svg =================================================================== --- tags/2.1.2/data/application-x-gerber-32.svg (nonexistent) +++ tags/2.1.2/data/application-x-gerber-32.svg (revision 24813) @@ -0,0 +1,544 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + Gerber file + + + + + + + Peter Clifton, Tomaz Solc, Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: tags/2.1.2/data/application-x-gerber-48.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/data/application-x-gerber-48.png =================================================================== --- tags/2.1.2/data/application-x-gerber-48.png (nonexistent) +++ tags/2.1.2/data/application-x-gerber-48.png (revision 24813) Property changes on: tags/2.1.2/data/application-x-gerber-48.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/data/application-x-gerber-48.svg =================================================================== --- tags/2.1.2/data/application-x-gerber-48.svg (nonexistent) +++ tags/2.1.2/data/application-x-gerber-48.svg (revision 24813) @@ -0,0 +1,707 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + Gerber file + + + + + + + Peter Clifton, Tomaz Solc, Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: tags/2.1.2/data/application-x-gerber.svg =================================================================== --- tags/2.1.2/data/application-x-gerber.svg (nonexistent) +++ tags/2.1.2/data/application-x-gerber.svg (revision 24813) @@ -0,0 +1,712 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + Gerber file + + + + + + + Peter Clifton, Tomaz Solc, Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: tags/2.1.2/data/application-x-pcb-footprint-16.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/data/application-x-pcb-footprint-16.png =================================================================== --- tags/2.1.2/data/application-x-pcb-footprint-16.png (nonexistent) +++ tags/2.1.2/data/application-x-pcb-footprint-16.png (revision 24813) Property changes on: tags/2.1.2/data/application-x-pcb-footprint-16.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/data/application-x-pcb-footprint-16.svg =================================================================== --- tags/2.1.2/data/application-x-pcb-footprint-16.svg (nonexistent) +++ tags/2.1.2/data/application-x-pcb-footprint-16.svg (revision 24813) @@ -0,0 +1,554 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + PCB footprint + + + + + + + Peter Clifton, Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: tags/2.1.2/data/application-x-pcb-footprint-22.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/data/application-x-pcb-footprint-22.png =================================================================== --- tags/2.1.2/data/application-x-pcb-footprint-22.png (nonexistent) +++ tags/2.1.2/data/application-x-pcb-footprint-22.png (revision 24813) Property changes on: tags/2.1.2/data/application-x-pcb-footprint-22.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/data/application-x-pcb-footprint-22.svg =================================================================== --- tags/2.1.2/data/application-x-pcb-footprint-22.svg (nonexistent) +++ tags/2.1.2/data/application-x-pcb-footprint-22.svg (revision 24813) @@ -0,0 +1,573 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + PCB footprint + + + + + + + Peter Clifton, Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: tags/2.1.2/data/application-x-pcb-footprint-24.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/data/application-x-pcb-footprint-24.png =================================================================== --- tags/2.1.2/data/application-x-pcb-footprint-24.png (nonexistent) +++ tags/2.1.2/data/application-x-pcb-footprint-24.png (revision 24813) Property changes on: tags/2.1.2/data/application-x-pcb-footprint-24.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/data/application-x-pcb-footprint-32.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/data/application-x-pcb-footprint-32.png =================================================================== --- tags/2.1.2/data/application-x-pcb-footprint-32.png (nonexistent) +++ tags/2.1.2/data/application-x-pcb-footprint-32.png (revision 24813) Property changes on: tags/2.1.2/data/application-x-pcb-footprint-32.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/data/application-x-pcb-footprint-32.svg =================================================================== --- tags/2.1.2/data/application-x-pcb-footprint-32.svg (nonexistent) +++ tags/2.1.2/data/application-x-pcb-footprint-32.svg (revision 24813) @@ -0,0 +1,2302 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + PCB footprint + + + + + + + Peter Clifton, Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: tags/2.1.2/data/application-x-pcb-footprint-48.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/data/application-x-pcb-footprint-48.png =================================================================== --- tags/2.1.2/data/application-x-pcb-footprint-48.png (nonexistent) +++ tags/2.1.2/data/application-x-pcb-footprint-48.png (revision 24813) Property changes on: tags/2.1.2/data/application-x-pcb-footprint-48.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/data/application-x-pcb-footprint-48.svg =================================================================== --- tags/2.1.2/data/application-x-pcb-footprint-48.svg (nonexistent) +++ tags/2.1.2/data/application-x-pcb-footprint-48.svg (revision 24813) @@ -0,0 +1,674 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + PCB footprint + + + + + + + Peter Clifton, Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: tags/2.1.2/data/application-x-pcb-footprint.svg =================================================================== --- tags/2.1.2/data/application-x-pcb-footprint.svg (nonexistent) +++ tags/2.1.2/data/application-x-pcb-footprint.svg (revision 24813) @@ -0,0 +1,680 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + PCB footprint + + + + + + + Peter Clifton, Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: tags/2.1.2/data/application-x-pcb-layout-16.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/data/application-x-pcb-layout-16.png =================================================================== --- tags/2.1.2/data/application-x-pcb-layout-16.png (nonexistent) +++ tags/2.1.2/data/application-x-pcb-layout-16.png (revision 24813) Property changes on: tags/2.1.2/data/application-x-pcb-layout-16.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/data/application-x-pcb-layout-16.svg =================================================================== --- tags/2.1.2/data/application-x-pcb-layout-16.svg (nonexistent) +++ tags/2.1.2/data/application-x-pcb-layout-16.svg (revision 24813) @@ -0,0 +1,1333 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + PCB layout + + + + + + + Peter Clifton, Tomaz Solc, Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: tags/2.1.2/data/application-x-pcb-layout-22.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/data/application-x-pcb-layout-22.png =================================================================== --- tags/2.1.2/data/application-x-pcb-layout-22.png (nonexistent) +++ tags/2.1.2/data/application-x-pcb-layout-22.png (revision 24813) Property changes on: tags/2.1.2/data/application-x-pcb-layout-22.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/data/application-x-pcb-layout-22.svg =================================================================== --- tags/2.1.2/data/application-x-pcb-layout-22.svg (nonexistent) +++ tags/2.1.2/data/application-x-pcb-layout-22.svg (revision 24813) @@ -0,0 +1,1423 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + PCB layout + + + + + + + Peter Clifton, Tomaz Solc, Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: tags/2.1.2/data/application-x-pcb-layout-24.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/data/application-x-pcb-layout-24.png =================================================================== --- tags/2.1.2/data/application-x-pcb-layout-24.png (nonexistent) +++ tags/2.1.2/data/application-x-pcb-layout-24.png (revision 24813) Property changes on: tags/2.1.2/data/application-x-pcb-layout-24.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/data/application-x-pcb-layout-32.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/data/application-x-pcb-layout-32.png =================================================================== --- tags/2.1.2/data/application-x-pcb-layout-32.png (nonexistent) +++ tags/2.1.2/data/application-x-pcb-layout-32.png (revision 24813) Property changes on: tags/2.1.2/data/application-x-pcb-layout-32.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/data/application-x-pcb-layout-32.svg =================================================================== --- tags/2.1.2/data/application-x-pcb-layout-32.svg (nonexistent) +++ tags/2.1.2/data/application-x-pcb-layout-32.svg (revision 24813) @@ -0,0 +1,1362 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + PCB layout + + + + + + + Peter Clifton, Tomaz Solc, Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: tags/2.1.2/data/application-x-pcb-layout-48.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/data/application-x-pcb-layout-48.png =================================================================== --- tags/2.1.2/data/application-x-pcb-layout-48.png (nonexistent) +++ tags/2.1.2/data/application-x-pcb-layout-48.png (revision 24813) Property changes on: tags/2.1.2/data/application-x-pcb-layout-48.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/data/application-x-pcb-layout-48.svg =================================================================== --- tags/2.1.2/data/application-x-pcb-layout-48.svg (nonexistent) +++ tags/2.1.2/data/application-x-pcb-layout-48.svg (revision 24813) @@ -0,0 +1,1341 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + PCB layout + + + + + + + Peter Clifton, Tomaz Solc, Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: tags/2.1.2/data/application-x-pcb-layout.svg =================================================================== --- tags/2.1.2/data/application-x-pcb-layout.svg (nonexistent) +++ tags/2.1.2/data/application-x-pcb-layout.svg (revision 24813) @@ -0,0 +1,1346 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + PCB layout + + + + + + + Peter Clifton, Tomaz Solc, Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: tags/2.1.2/data/application-x-pcb-netlist-16.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/data/application-x-pcb-netlist-16.png =================================================================== --- tags/2.1.2/data/application-x-pcb-netlist-16.png (nonexistent) +++ tags/2.1.2/data/application-x-pcb-netlist-16.png (revision 24813) Property changes on: tags/2.1.2/data/application-x-pcb-netlist-16.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/data/application-x-pcb-netlist-16.svg =================================================================== --- tags/2.1.2/data/application-x-pcb-netlist-16.svg (nonexistent) +++ tags/2.1.2/data/application-x-pcb-netlist-16.svg (revision 24813) @@ -0,0 +1,530 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + PCB netlist + + + + + + + Peter Clifton, Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: tags/2.1.2/data/application-x-pcb-netlist-22.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/data/application-x-pcb-netlist-22.png =================================================================== --- tags/2.1.2/data/application-x-pcb-netlist-22.png (nonexistent) +++ tags/2.1.2/data/application-x-pcb-netlist-22.png (revision 24813) Property changes on: tags/2.1.2/data/application-x-pcb-netlist-22.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/data/application-x-pcb-netlist-22.svg =================================================================== --- tags/2.1.2/data/application-x-pcb-netlist-22.svg (nonexistent) +++ tags/2.1.2/data/application-x-pcb-netlist-22.svg (revision 24813) @@ -0,0 +1,567 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + PCB netlist + + + + + + + Peter Clifton, Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: tags/2.1.2/data/application-x-pcb-netlist-24.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/data/application-x-pcb-netlist-24.png =================================================================== --- tags/2.1.2/data/application-x-pcb-netlist-24.png (nonexistent) +++ tags/2.1.2/data/application-x-pcb-netlist-24.png (revision 24813) Property changes on: tags/2.1.2/data/application-x-pcb-netlist-24.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/data/application-x-pcb-netlist-32.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/data/application-x-pcb-netlist-32.png =================================================================== --- tags/2.1.2/data/application-x-pcb-netlist-32.png (nonexistent) +++ tags/2.1.2/data/application-x-pcb-netlist-32.png (revision 24813) Property changes on: tags/2.1.2/data/application-x-pcb-netlist-32.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/data/application-x-pcb-netlist-32.svg =================================================================== --- tags/2.1.2/data/application-x-pcb-netlist-32.svg (nonexistent) +++ tags/2.1.2/data/application-x-pcb-netlist-32.svg (revision 24813) @@ -0,0 +1,1310 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + PCB netlist + + + + + + + Peter Clifton, Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: tags/2.1.2/data/application-x-pcb-netlist-48.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/data/application-x-pcb-netlist-48.png =================================================================== --- tags/2.1.2/data/application-x-pcb-netlist-48.png (nonexistent) +++ tags/2.1.2/data/application-x-pcb-netlist-48.png (revision 24813) Property changes on: tags/2.1.2/data/application-x-pcb-netlist-48.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/data/application-x-pcb-netlist-48.svg =================================================================== --- tags/2.1.2/data/application-x-pcb-netlist-48.svg (nonexistent) +++ tags/2.1.2/data/application-x-pcb-netlist-48.svg (revision 24813) @@ -0,0 +1,451 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + PCB netlist + + + + + + + Peter Clifton, Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: tags/2.1.2/data/application-x-pcb-netlist.svg =================================================================== --- tags/2.1.2/data/application-x-pcb-netlist.svg (nonexistent) +++ tags/2.1.2/data/application-x-pcb-netlist.svg (revision 24813) @@ -0,0 +1,459 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + PCB netlist + + + + + + + Peter Clifton, Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: tags/2.1.2/data/icon-theme-installer =================================================================== --- tags/2.1.2/data/icon-theme-installer (nonexistent) +++ tags/2.1.2/data/icon-theme-installer (revision 24813) @@ -0,0 +1,183 @@ +#!/bin/sh + +# icon-theme-installer +# Copyright (C) 2006 Novell, Inc. +# Written by Aaron Bockover +# Licensed under the MIT/X11 license +# +# Modified by Peter Clifton to allow icons with numerals in the filename +# +# This script is meant to be invoked from within a Makefile/Makefile.am +# in the install-data-local and uninstall-data sections. It handles the +# task of properly installing icons into the icon theme. It requires a +# few arguments to set up its environment, and a list of files to be +# installed. The format of the file list is critical: +# +# , +# +# apps,music-player-banshee.svg +# apps,music-player-banshee-16.png +# apps,music-player-banshee-22.png +# +# is the icon theme category, for instance, apps, devices, +# actions, emblems... +# +# must have a basename in the form of: +# +# proper-theme-name[-]. +# +# Where should be either nothing, which will default to scalable +# or \-[0-9]{2}, which will expand to x. For example: +# +# music-player-banshee-16.png +# +# The here is -16 and will expand to 16x16 per the icon theme spec +# +# What follows is an example Makefile.am for icon theme installation: +# +# --------------- +# theme=hicolor +# themedir=$(datadir)/icons/$(theme) +# theme_icons = \ +# apps,music-player-banshee.svg \ +# apps,music-player-banshee-16.png \ +# apps,music-player-banshee-22.png \ +# apps,music-player-banshee-24.png \ +# apps,music-player-banshee-32.png +# +# install_icon_exec = $(top_srcdir)/build/icon-theme-installer -t $(theme) -s $(srcdir) -d "x$(DESTDIR)" -b $(themedir) -m "$(mkinstalldirs)" -x "$(INSTALL_DATA)" +# install-data-local: +# $(install_icon_exec) -i $(theme_icons) +# +# uninstall-hook: +# $(install_icon_exec) -u $(theme_icons) +# +# MAINTAINERCLEANFILES = Makefile.in +# EXTRA_DIST = $(wildcard *.svg *.png) +# --------------- +# +# Arguments to this program: +# +# -i : Install +# -u : Uninstall +# -t : Theme name (hicolor) +# -b : Theme installation dest directory [x$(DESTDIR)] - Always prefix +# this argument with x; it will be stripped but will act as a +# placeholder for zero $DESTDIRs (only set by packagers) +# -d : Theme installation directory [$(hicolordir)] +# -s : Source directory [$(srcdir)] +# -m : Command to exec for directory creation [$(mkinstalldirs)] +# -x : Command to exec for single file installation [$(INSTALL_DATA)] +# : All remainging should be category,filename pairs + +while getopts "iut:b:d:s:m:x:" flag; do + case "$flag" in + i) INSTALL=yes ;; + u) UNINSTALL=yes ;; + t) THEME_NAME=$OPTARG ;; + d) INSTALL_DEST_DIR="`echo $OPTARG | sed 's;^x;;'`" ;; + b) INSTALL_BASE_DIR=$OPTARG ;; + s) SRC_DIR=$OPTARG ;; + m) MKINSTALLDIRS_EXEC=$OPTARG ;; + x) INSTALL_DATA_EXEC=$OPTARG ;; + esac +done + +shift `expr $OPTIND - 1` + +if test "x$INSTALL" = "xyes" -a "x$UNINSTALL" = "xyes"; then + echo "Cannot pass both -i and -u" + exit 1 +elif test "x$INSTALL" = "x" -a "x$UNINSTALL" = "x"; then + echo "Must path either -i or -u" + exit 1 +fi + +if test -z "$THEME_NAME"; then + echo "Theme name required (-t hicolor)" + exit 1 +fi + +if test -z "$INSTALL_BASE_DIR"; then + echo "Base theme directory required [-d \$(hicolordir)]" + exit 1 +fi + +#if test ! -x `echo "$MKINSTALLDIRS_EXEC" | cut -f1 -d' '`; then +# echo "Cannot find '$MKINSTALLDIRS_EXEC'; You probably want to pass -m \$(mkinstalldirs)" +# exit 1 +#fi + +#if test ! -x `echo "$INSTALL_DATA_EXEC" | cut -f1 -d' '`; then +# echo "Cannot find '$INSTALL_DATA_EXEC'; You probably want to pass -x \$(INSTALL_DATA)" +# exit 1 +#fi + +if test -z "$SRC_DIR"; then + SRC_DIR=. +fi + +for icon in $@; do + size=`echo $icon | sed -n 's/.*-\([0-9]*\).*/\1/p'` + category=`echo $icon | cut -d, -f1` + build_name=`echo $icon | cut -d, -f2` + install_name=`echo $build_name | sed 's/-[0-9]\+//g'` + install_name=`basename $install_name` + + if test -z $size; then + size=scalable; + else + size=${size}x${size}; + fi + + install_dir=${INSTALL_DEST_DIR}${INSTALL_BASE_DIR}/$size/$category + install_path=$install_dir/$install_name + + if test "x$INSTALL" = "xyes"; then + echo "Installing $size $install_name into $THEME_NAME icon theme" + + $MKINSTALLDIRS_EXEC $install_dir || { + echo "Failed to create directory $install_dir" + exit 1 + } + + $INSTALL_DATA_EXEC $SRC_DIR/$build_name $install_path || { + echo "Failed to install $SRC_DIR/$build_name into $install_path" + exit 1 + } + + if test ! -e $install_path; then + echo "Failed to install $SRC_DIR/$build_name into $install_path" + exit 1 + fi + else + if test -e $install_path; then + echo "Removing $size $install_name from $THEME_NAME icon theme" + + rm $install_path || { + echo "Failed to remove $install_path" + exit 1 + } + fi + fi +done + +if test "x$INSTALL" = "xyes"; then + gtk_update_icon_cache_bin="`(which gtk-update-icon-cache || echo /opt/gnome/bin/gtk-update-icon-cache)2>/dev/null`" + gtk_update_icon_cache_bin="${GTK_UPDATE_ICON_CACHE_BIN:-$gtk_update_icon_cache_bin}" + + gtk_update_icon_cache="$gtk_update_icon_cache_bin -f -t $INSTALL_BASE_DIR" + + if test -z "$INSTALL_DEST_DIR"; then + if test -x $gtk_update_icon_cache_bin; then + echo "Updating GTK icon cache" + $gtk_update_icon_cache + else + echo "*** Icon cache not updated. Could not execute $gtk_update_icon_cache_bin" + fi + else + echo "*** Icon cache not updated. After install, run this:" + echo "*** $gtk_update_icon_cache" + fi +fi + Property changes on: tags/2.1.2/data/icon-theme-installer ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/2.1.2/data/pcb-48.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/data/pcb-48.png =================================================================== --- tags/2.1.2/data/pcb-48.png (nonexistent) +++ tags/2.1.2/data/pcb-48.png (revision 24813) Property changes on: tags/2.1.2/data/pcb-48.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/data/pcb.desktop =================================================================== --- tags/2.1.2/data/pcb.desktop (nonexistent) +++ tags/2.1.2/data/pcb.desktop (revision 24813) @@ -0,0 +1,10 @@ +[Desktop Entry] +Version=1.0 +Name=pcb-rnd PCB Designer +GenericName=PCB Design +Comment=Create and edit printed circuit board designs +Type=Application +Exec=pcb-rnd %f +Icon=pcb +MimeType=application/x-pcb-layout;application/x-pcb-footprint; +Categories=Engineering;Electronics; Index: tags/2.1.2/data/pcb.svg =================================================================== --- tags/2.1.2/data/pcb.svg (nonexistent) +++ tags/2.1.2/data/pcb.svg (revision 24813) @@ -0,0 +1,1070 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + Lapo Calamandrei + + + + Text editor + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: tags/2.1.2/data/pcb.xml =================================================================== --- tags/2.1.2/data/pcb.xml (nonexistent) +++ tags/2.1.2/data/pcb.xml (revision 24813) @@ -0,0 +1,40 @@ + + + + + PCB layout + + + + + + + + PCB footprint + + + + + + + + PCB netlist + + + + + Gerber file + + + + + + + + Excellon drill file + + + + + + Index: tags/2.1.2/data/pcb_icon.ico =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/data/pcb_icon.ico =================================================================== --- tags/2.1.2/data/pcb_icon.ico (nonexistent) +++ tags/2.1.2/data/pcb_icon.ico (revision 24813) Property changes on: tags/2.1.2/data/pcb_icon.ico ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/data/regen_files =================================================================== --- tags/2.1.2/data/regen_files (nonexistent) +++ tags/2.1.2/data/regen_files (revision 24813) @@ -0,0 +1,165 @@ +#!/bin/sh +# + +CONVERT=${CONVERT:-convert} +COMPOSITE=${COMPOSITE:-composite} +INKSCAPE=${INKSCAPE:-inkscape} +PPMTOWINICON=${PPMTOWINICON:-ppmtowinicon} + +do_inkscape=yes +do_convert=yes +do_winicon=yes + +usage() { +cat << EOF + +$0 -- Regenerate desktop icon files and windows icon files + +Options + + --help Displays this message and exits + + --skip-png Skips the regeneration of the .png file(s) + + --skip-winicon Skips the regneration of the Windows icon file(s) + +EOF + +} + +while test $# -ne 0 ; do + case $1 in + --help) + usage + exit 0 + ;; + + --skip-png) + do_inkscape=no + shift + ;; + + --skip-winicon) + do_convert=no + do_winicon=no + shift + ;; + + -*) + echo "$0: Unknown option $1" + usage + exit 1 + ;; + + *) + break + ;; + esac +done + +if test $? -ne 0 ; then + usage + exit 1 +fi + +## +## Export the SVG graphics +## + +# see if we have inkscape +if test $do_inkscape = yes ; then +${INKSCAPE} --version 2>&1 >/dev/null +if test $? -ne 0 ; then + echo "\"${INKSCAPE} --version\" failed." + echo "Make sure that inkscape is installed and functional on your system." + echo "Skipping the SVG -> PNG conversion." + do_inkscape=no +fi +fi + +if test $do_inkscape = yes ; then + echo "Export SVG graphics to png..." + + for r in 16 22 24 32 48 ; do + case ${r} in + 24) + x=-1 + y=23 + rs=22 + ;; + *) + x=0 + y=${r} + rs=${r} + ;; + esac + for f in *-${rs}.svg ; do + fb=`basename ${f} ${rs}.svg` + p="${fb}${r}.png" + echo "${f} -> ${p}" + ${INKSCAPE} --export-png=${p} --export-area=${x}:${x}:${y}:${y} ${f} + done + done +fi + +## +## Generate the windows icon file +## + +app_icon="application-x-pcb-layout" + +if test $do_convert = yes ; then +# see if we have ImageMagick +${CONVERT} --version 2>&1 >/dev/null +if test $? -ne 0 ; then + echo "\"${CONVERT} --version\" failed." + echo "Make sure that ImageMagick is installed and functional on your system." + echo "Skipping the PNG -> PPM conversion." + do_convert=no +fi +fi + +if test $do_convert = yes ; then +echo "Creating windows pbm mask files..." +${CONVERT} -channel matte -separate +matte ${app_icon}-48.png - | + ${CONVERT} -threshold 65534 -negate - 48_mask.pbm +${CONVERT} -channel matte -separate +matte ${app_icon}-32.png - | + ${CONVERT} -threshold 65534 -negate - 32_mask.pbm +${CONVERT} -channel matte -separate +matte ${app_icon}-16.png - | + ${CONVERT} -threshold 65534 -negate - 16_mask.pbm + +echo "Creating windows ppm flattened files..." +${CONVERT} -flatten -colors 16 ${app_icon}-48.png 48_16.ppm +${CONVERT} -flatten -colors 256 ${app_icon}-48.png 48_256.ppm +${CONVERT} -flatten -colors 16 ${app_icon}-32.png 32_16.ppm +${CONVERT} -flatten -colors 256 ${app_icon}-32.png 32_256.ppm +${CONVERT} -flatten -colors 16 ${app_icon}-16.png 16_16.ppm +${CONVERT} -flatten -colors 256 ${app_icon}-16.png 16_256.ppm +fi + +# see if we have netpbm +if test $do_winicon = yes ; then +${PPMTOWINICON} --version 2>&1 >/dev/null +if test $? -ne 0 ; then + echo "\"${PPMTOWINICON} --version\" failed." + echo "Make sure that netpbm is installed and functional on your system." + echo "Skipping the pbm -> windows icon conversion." + do_winicon=no +fi +fi + +if test $do_winicon = yes ; then +echo "Creating windows icon file..." +${PPMTOWINICON} -output pcb_icon.ico -andpgms\ + 48_16.ppm 48_mask.pbm 48_256.ppm 48_mask.pbm\ + 32_16.ppm 32_mask.pbm 32_256.ppm 32_mask.pbm\ + 16_16.ppm 16_mask.pbm 16_256.ppm 16_mask.pbm +fi + +rm -f \ + 48_16.ppm 48_256.ppm 48_mask.pbm\ + 32_16.ppm 32_256.ppm 32_mask.pbm\ + 16_16.ppm 16_256.ppm 16_mask.pbm + +echo "All done" + Property changes on: tags/2.1.2/data/regen_files ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/2.1.2/data/x-excellon.desktop =================================================================== --- tags/2.1.2/data/x-excellon.desktop (nonexistent) +++ tags/2.1.2/data/x-excellon.desktop (revision 24813) @@ -0,0 +1,8 @@ +[Desktop Entry] +Encoding=UTF-8 +Comment=Excellon drill file +MimeType=application/x-excellon +Type=MimeType +Icon=application-x-excellon +Patterns=*.cnc +X-KDE-IsAlso=text/plain Index: tags/2.1.2/data/x-gerber.desktop =================================================================== --- tags/2.1.2/data/x-gerber.desktop (nonexistent) +++ tags/2.1.2/data/x-gerber.desktop (revision 24813) @@ -0,0 +1,8 @@ +[Desktop Entry] +Encoding=UTF-8 +Comment=Gerber file +MimeType=application/x-gerber +Type=MimeType +Icon=application-x-gerber +Patterns=*.gbr +X-KDE-IsAlso=text/plain Index: tags/2.1.2/data/x-pcb-footprint.desktop =================================================================== --- tags/2.1.2/data/x-pcb-footprint.desktop (nonexistent) +++ tags/2.1.2/data/x-pcb-footprint.desktop (revision 24813) @@ -0,0 +1,8 @@ +[Desktop Entry] +Encoding=UTF-8 +Comment=PCB footprint +MimeType=application/x-pcb-footprint +Type=MimeType +Icon=application-x-pcb-footprint +Patterns=*.fp +X-KDE-IsAlso=text/plain Index: tags/2.1.2/data/x-pcb-layout.desktop =================================================================== --- tags/2.1.2/data/x-pcb-layout.desktop (nonexistent) +++ tags/2.1.2/data/x-pcb-layout.desktop (revision 24813) @@ -0,0 +1,8 @@ +[Desktop Entry] +Encoding=UTF-8 +Comment=PCB layout +MimeType=application/x-pcb-layout +Type=MimeType +Icon=application-x-pcb-layout +Patterns=*.pcb +X-KDE-IsAlso=text/plain Index: tags/2.1.2/data/x-pcb-netlist.desktop =================================================================== --- tags/2.1.2/data/x-pcb-netlist.desktop (nonexistent) +++ tags/2.1.2/data/x-pcb-netlist.desktop (revision 24813) @@ -0,0 +1,8 @@ +[Desktop Entry] +Encoding=UTF-8 +Comment=PCB netlist +MimeType=application/x-pcb-netlist +Type=MimeType +Icon=application-x-pcb-netlist +Patterns=*.net +X-KDE-IsAlso=text/plain Index: tags/2.1.2/doc/Autostyle.html =================================================================== --- tags/2.1.2/doc/Autostyle.html (nonexistent) +++ tags/2.1.2/doc/Autostyle.html (revision 24813) @@ -0,0 +1,16 @@ + + + + + + + +
Main + News + Doc & pool + Support + People + Events & timeline + pcb-rnd [pcb-rnd logo] +
+ Index: tags/2.1.2/doc/Autostyle.sh =================================================================== --- tags/2.1.2/doc/Autostyle.sh (nonexistent) +++ tags/2.1.2/doc/Autostyle.sh (revision 24813) @@ -0,0 +1,77 @@ +#!/bin/sh + +autostyle() +{ + awk -v "template=$1" -v "root=$ROOT" ' + BEGIN { + while((getline < template) > 0) { + if (parse_auto(RES, $0)) { + if (RES["action"] == "begin") + curr = RES["ID"] + else + reset_curr = 1 + } + if (curr != "") + AUTO[curr] = AUTO[curr] var_subs($0) "\n" + if (reset_curr) { + curr = "" + reset_curr = 0 + } + } + } + + function var_subs(s) + { + gsub("[$]ROOT[$]", root, s) + return s + } + + function parse_auto(RES, line ,tmp) + { + if (!(line ~ ".*", "", line) + line = tolower(line) + tmp = line + sub("[ \t].*$", "", tmp) + RES["ID"] = tmp + tmp = line + sub("^[^ \t]*[ \t]*", "", tmp) + RES["action"] = tmp + return 1 + } + + { + if (parse_auto(RES, $0)) { + if (RES["action"] == "begin") + skip = 1 + else if (RES["action"] == "end") { + printf("%s", AUTO[RES["ID"]]) + skip = 0 + } + next + } + } + + (!skip) { print $0 } + + ' +} + +for html in $* +do + case $html in + Autostyle.html) ;; + *) + mv $html $html.tmp + autostyle "Autostyle.html" < $html.tmp > $html + if test $? = 0 + then + rm $html.tmp + else + echo "Failed on $html, keeping the original version." + mv $html.tmp $html + fi + esac +done Property changes on: tags/2.1.2/doc/Autostyle.sh ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/2.1.2/doc/Makefile =================================================================== --- tags/2.1.2/doc/Makefile (nonexistent) +++ tags/2.1.2/doc/Makefile (revision 24813) @@ -0,0 +1,67 @@ +MENU_RES=../src/pcb-menu-default.lht +KEYLIST=../util/keylist.sh +DEBLIST=../util/devhelpers/deblist.sh +ROOT=.. + +all: keys.html user/05_ui/06_common/keytree.svg user/05_ui/06_common/keytree.txt + ROOT="" ./Autostyle.sh *.html + +include ../Makefile.conf + +user/05_ui/06_common/keytree.svg: $(MENU_RES) $(KEYLIST) + $(KEYLIST) --dot user/05_ui/06_common/src/node_names.txt $(MENU_RES) > user/05_ui/06_common/keytree.dot + dot -Tsvg < user/05_ui/06_common/keytree.dot >user/05_ui/06_common/keytree.svg + +user/05_ui/06_common/keytree.txt: $(MENU_RES) $(KEYLIST) + $(KEYLIST) --lst $(MENU_RES) > user/05_ui/06_common/keytree.txt + + +keys.html: $(MENU_RES) $(KEYLIST) + $(KEYLIST) $(MENU_RES) > keys.html + +install_main: + $(SCCBOX) $(HOW) *.html *.txt TODO $(DOCDIR)/ + +install: + $(SCCBOX) mkdir -p "$(DOCDIR)" + cd man && $(MAKE) install + cd user && $(MAKE) install + cd tutorials && $(MAKE) install + cd security && $(MAKE) install + cd conf && $(MAKE) install + cd developer && $(MAKE) install + $(MAKE) install_main HOW="install -f -d" + +linstall: + cd man && $(MAKE) linstall + cd user && $(MAKE) linstall + cd tutorials && $(MAKE) linstall + cd security && $(MAKE) linstall + cd conf && $(MAKE) linstall + cd developer && $(MAKE) linstall + $(MAKE) install_main HOW="install -f -l -d" + +uninstall: + cd man && $(MAKE) uninstall + cd user && $(MAKE) uninstall + cd tutorials && $(MAKE) uninstall + cd security && $(MAKE) uninstall + cd conf && $(MAKE) uninstall + cd developer && $(MAKE) uninstall + $(MAKE) install_main HOW="install -f -u -d" + +clean: + cd man && $(MAKE) clean + cd user && $(MAKE) clean + cd tutorials && $(MAKE) clean + cd security && $(MAKE) clean + cd conf && $(MAKE) clean + cd developer && $(MAKE) clean + +distclean: + cd man && $(MAKE) distclean + cd user && $(MAKE) distclean + cd tutorials && $(MAKE) distclean + cd security && $(MAKE) distclean + cd conf && $(MAKE) distclean + cd developer && $(MAKE) distclean Index: tags/2.1.2/doc/README =================================================================== --- tags/2.1.2/doc/README (nonexistent) +++ tags/2.1.2/doc/README (revision 24813) @@ -0,0 +1,12 @@ +pcb-rnd documentation: work in progress. + +Most notable subdirectories: + conf/ documentation of the configuration system + developer/ documentation for developers + devlog/ random thoughts and articles + man/ UNIX manual pages + resources/ logos, screenshots, artwork + security/ notifications about security-critical bugs + tutorials/ my-first-board tutorials + user/ user reference manual + Index: tags/2.1.2/doc/TODO =================================================================== --- tags/2.1.2/doc/TODO (nonexistent) +++ tags/2.1.2/doc/TODO (revision 24813) @@ -0,0 +1,292 @@ +0. old, still waiting for ack ++ BUG: kicad I/O bugs: + + BUG: does not save the netlist [TwisteR] ++ FEATURE: external editor on buffer [report: TwisteR] + +1. For the upcoming release =============================================================================== + +2. For later releases =============================================================================== +- DOC: (prio) tutorial: + - rename 7805 to 17_sch and re-enable step 3 text (uncomment) + - install all tutorial steps +- CLEANUP: (prio) hidlib: move window placement code from dialog to a separate plugin and remove dialog dependency from the hid plugins reverting r24758 [report: Igor2] +- CLEANUP: (prio) Vuokko's list of warnings on OpenBSD: bug_files/warn-obsd-r24746.log [report: Vuokko] +- BUG: (prio) setenv() LC_ALL and LANG to "C" around setlocale; remove setlocale from lib_gtk; bug_files/locale.diff [report: osetroff] +- FEATURE: excellon metric support to pair up with gerber's late feature [report: Gabriel] +- CLEANUP: remove pcb_attribute_dialog() and the label argument from the DAD API [report: igor2] +- CLEANUP/BUG: The 'As Drawn' polygon contour is not displayed if the polygon is totally clipped out of existence even though it still exists in the layout. [report: Ade] + -> need a new rtree that holds the polygons that have ->clipped == NULL for this purpose +- CLEANUP: move opendir/readdir in safe_fs from everywhere +- CLEANUP: pcb_layer_to_file_name() dest should be gds_t to avoid potential buffer overflow +- CLEANUP: remove hid_flag.h - probably merge the function into a menu related .h +- CLEANUP: DAD: centralize the coordinate input spinbox: hid_dad_spin + - remove per hid implementation, get DAD macros to build spinboxes (maybe in brave mode first) + - hid_dad_spin.[ch]: bind conf change on conf_core.editor.grid_unit, call pcb_dad_spin_widget_state() to get them updated: + - drc & size: doesn't update on mil/mm change in top win -> need a list of spinboxes to update on conf change [report: Ade] + - make the central unit infra more flexible so plugins can register new units + - make sure we don't crash when grid or config references non-existing unit or unit that has no conversion field set up yet + - propedit: relative modifications +x mils, #degrees broke [report: Igor2] +- CLEANUP: library window DAD-ification: remove pcb_act_LibraryShow() + - FEATURE: library window: allow long tags and long location text to split + - BUG: double check parametric footprint edit window: bug_files/parametric.txt [report: Piotr] +- CLEANUP: think over how to handle subc selection: selecting all parts automatically is bad for propedit; bug_files/subcsel.bug [report: Wojciech] + - BUG: adding attribute works on subc parts but deleting attribute stops after deleiting it from a subc; bug_files/subcsel.bug [report: Wojciech] +- CLEANUP: DAD close sequence: TODO#51: there are three sources to trigger hid_ctx (caller's free on modal, close button free and window destroy callback); requre the user to always call free last and add bits to track what frees are already called and free(ctx) last; test in 4 situations: (modal,nonmodal)*(close_buttons,wmclose) [report: Igor2] +- CLEANUP: color: + - remove per hid, non-backup-lib custom color structs + - COLOR_TO_STR should not use sprintf - remove stdio.h + - rewrite lesstif conv so it wouldn't use the string version anymore + - rewrite gtk conv so it wouldn't use the string version anymore + - remove src/hid_color.[ch] and src/color_cache.[ch] + - remove pcb_color_t ->str, convert only when really needed +- CLEANUP: non-modal fontsel: refresh on text font change from other source [report: Igor2] +- CLEANUP: find.c rewrite: + - CLEANUP: a new "report(NetLength)" should not care about netlists but depend on find.c only + - BUG: unplated padtsakcs shall not connect layers; problem: a padstack is either found or not, this affects all layers, there's no info about which layer is found; padstack update should check the hole/slot geo and update a bit for each shape telling whether it's connected or not + - BUG: bug_files/rat_shortest.lht: because of "don't add non-manhattan lines" part [report: pstuge] +- CLEANUP: layer order from data + - central code for building a list of layer groups ordered by draw from front to back (omit disabled/invisible layers) + - rewrite both the draw_everything() and pcb_search_obj_by_location_() layer loop to use this list +- CLEANUP/feature: pcb_subc_smash_buffer() should really copy data so it can smash multiple subcs and subc objects end up on the layer they were bound to [report: keantoken] +- CLEANUP/BUG: undo operation while drawing a multiple segment line doesn't change segment attached to the crosshair [report:wojciechk8] + - tool_line.c depends on pcb_undo()'s return value; can be fixed only when the old undo system is removed +- CAM: + - CLEANUP: move excellon to a separate plugin, move aperture to a lib plugin, make gerber depend on excellon (for backward compatibility) instead of reinventing it + - FEATURE: make the drill exporter sort drills by attributes, an user configured table telling which drill (by attribute) ends up in which file (for support for plugged vias/filled vias) [report: Vuokko] + - FEATURE: invent a generic API for both the drill attrib config table + - CLEANUP: unify how output files are accessed/checked: confirmation on overwrite + - CLEANUP: later: remove the gerber->drill dep and ask users to use the CAM instead + - CLEANUP: later: remove the hackish gerber layer suffix in favor of CAM [report: Ade] +- CLEANUP: (TT) propedit revamp: + - test under lesstif + - CLEANUP: remove Attrbute() and pcb_act_Attributes -> remove; this should be handled by the property editor when lesstif already supports it. +- FEATURE: data model: object minimal clearance value from the polygon side; final clearance should be MAX(obj->Clearance, poly->Clearance); kicad example: 1 line, 2 polygons with 2 different clearance values - see CUCP#38 provided by Karl [report: Igor2] +- FEATURE: netlist2: bug_files/ratside.txt optional rats constraints [report: Vuokko] +- FEATURE: (TT) route style upgrade to prototypes: + - BUG: set same {e s s} doesn't work on padstacks [report: Igor2] + - BUG: padstack doesn't show drc xor shape while moving - because the whole drawing is a cheat for old vias [report: igor2] + - replace the route style dialog box's via part + - proto copy to buffer - a buffer with a single padstack should also serve as a prototype copy vehicle? or just import by a list from the buffer + - load/import from buffer and file + - CLEANUP: remove PCB_MIN_PINORVIA* PCB_DEFAULT_DRILLINGHOLE macros - nothing should use them anymore + - add text font, update the pool node text_edit [report: Igor2] +- BUG: autorouter broke on polygons: bug_files/ara.lht, {a r a}, bisect; broke before r14572 [report: Igor2] +- CLEANUP: add the thin line draw optimization to the filled poly optimization, including hole, in hid_draw_helper (search for last_x); make this configurable for both (exporters shall not optimize!); remove the similar optimization from hidgl triangulation and gdk and lesstif [report: Ade, Peter] +- FEATURE: fontsel: ttf import? +- FEATURE: tedax etest save (board save too) +- FEATURE/BUG: bug_files/lines - remove zero length objects if they are created as the result of rubber banding [report: Evan] +- FEATURE: extend the CAM job script syntax so that XY and other non-layer exporters can be called [report: celem] +- FEATURE: view list: import sch. shouldn't select elements to be removed but put them on a drc list +- FEATURE: drc preview: follow board flips (should be a DAD preview flag) [report: Igor2] +- FEATURE: DOC: new examples + - blinking led with parametric footprints + - example of nonetlist: 1206 jumpers and logos +- feature plugins: + - FEATURE: autocrop doesnt undo (new layout, add some -maskmanaul content, autocrop(), & undo: gui view shifts, board size unchanged [report: Miloh] + - BUG: distalign pcb_crosshair option doesn't work as a reference point [report:Miloh] +- CLEANUP: move import_sch to import_sch_old and start a new, generic plugin +- CLEANUP/FEATURE: boardflip doesn't function properly with undo -- repro: open pcb-rnd, place 1206, boardflip(), { u u } removes placed part instead of boardflip [report: Miloh] +- FEATURE: padstack bbox: + - per layer: keep a bbox per transformed shape per prototype, then getting the bbox of a padstack ref on a specific layer is looking up the shape, then 4 integer additions [report: Wojciech] + - when calculating overall padstack bbox, ignore layers that are not present? but then a layer change would require a recalc (but this is true for subcs too!) [report: Wojciech] +- XOR rendering upgrade: + - experiment with 'emboss' kind of drawing instead of xor so rendering can stay 'direct' + - if worked: allow padstack xor draw to draw all shapes on all layers +- opengl: + - BUG: heavy swapd +/- crash with radeon AMD GL driver, fixed by exporting LIBGL_ALWAYS_SOFTWARE=t GALLIUM_DRIVER=llvmpipe [report: erich] + - BUG: --gui gtk2_gl pcb-rnd library preview pane is black ( doWindows(library) ) [report: Miloh] +- export_dsn/new io_dsn (with King Kevin and celem): + - missing global padstack (via) export: + - FEATURE: need to think over and check the spec for how to do this with no-hole padstacks + - RTT tests: thermal_layer.dsn, comp1.dsn, padstack.dsn + - BUG: elem_pads_ds: do not export line shape in padstacks as polygons, that kills round cap lines +- FEATURE: draw on move: 'Crosshair shows DRC clearance' should show the clearance also when moving a ... (not only when placing it) [report: wojciechk8] + - need to precalculate and cache clearance shape in crosshair (polyarea!) because recalculating these for padstacks would be expensive (also rewrite lines and arcs) + - padstack + - clearing polygon + - text +- SUBC: element removal: + - CLEANUP: convert pcblib to subcircuits: + - revise the value attribute - should be empty by default + - remove old install elements + - dir rename trunk/pcblib/tru-hole should handle make correctly and not walk on existing web services or user installs +- FEATURE: key rewrite: (base key swap bug (q<->a, y<->z)) + - for (punctuation): learn key for non-US users + - lesstif code upgrade for the new API + - menu file fixup on punctuation in lesstif +- FEATURE: extedit: when editing subc with pcb, save configuration and load it in the external pcb-rnd so that grid sizes and other settings are preserved [report: jg] +- FEATURE: undo on new layer from right-click menu in gtk layersel doesn't work +- FEATUER: gtk layersel: consider to provide a config setting for making open-group-name horizontal [report: istankovic] +- FEATURE: preview widget: allow to handle keys both in gtk and lesstif +- FEATURE: no-export attribute: cache a no-export attribute in a bitfield (e.g. flags like no-export for vector outputs, pixel outputs); exporter should set the bits in HID; core rendring should decide what to draw; use case: poly clearance to emulate keep-away on outline, and replace the old zero-width line trick [report: karl] +- CLEANUP: fp_fs_search: kill anything that gets ':' separated string as path list, get a config list instead +- CLEANUP: Mark + - see pool node mark_cleanup + - mark bug - ortho shouldn't use it, it should use last point (crosshair.X2); make sure nothing else abuses it [James] +- unravel the undo code + - FEATURE: grid size change should be undoable? [report:Evan] + - FEATURE: maybe other conf settings too? +- res/menu: + - FEATURE: load/swap menus (TODO#1) + - CLEANUP: search for vendor in the hid plugins, there should be no trace of it (vendor should register its in submenus with anchors) + - CLEANUP: re-add dynamic menus after a gui change: + - provide hooks and let plugins deal with a re-add as they may be added anywhere + - FEATURE: fungw: auto-remove menus by cookie (TODO#2) + - FEATURE: load new res on the fly (replace the menu system): + - low level reload code (re-add the dynamic menus too!) + - action to reload if file name is known + - gui load dialog with tags listed +- CLENAUP: decide about exporter policy: + - png exports selection (even in not-as-shown), others don't + - extend png hid attribs with a flag for this, maybe do the same for others + - document the decision in "hacking" +- FEATURE: project specific menus from extra lihata files - maybe from project.lht +- BUG: Lihata persistent save: + - flag compatibility: save unknown, string-flags as loaded by io_pcb + - ind: FONTS: second font indents incorrectly + - ind: indentation bug in inline struct therm: closing } is preceded by indentation whitespace for some reason + - keep numeric format: test all + - keep unknown subtrees + - doc/user/02_model/src/obj_arc.lht: Open/Save : Font section is embedded. Once manually removed, the file shows many diffs w.r.t original. Lihata V1 file. [report: Alain] + - BUG: lhtpers indentation: bug_files/lhtpers_ins/; breakpoint in pers_table.c:34 and debug why the newline is getting in [report: Igor2] +- query & advanced search + - FEATURE: search expr wizard should pick up the expression from the button when clicked + - CLEANUP: make a run on a large board, speed test, with -O0 and -O3: + - iteration speed (a simple @) + - eval speed (a simple @ with a lot of constants in an expr) + - geo speed + - regex and string cmp match speed vs. select by name +- CLEANUP: rewrite layer undo; take it out from old_undo; layer del breaks on undo: can't save where it was added before. Consider the whole layer move and -1 business obsolete and rather add a separate insert and remove call? + - BUG: add new layer in main window, pcb-rnd issues pcb_warning yet action is placed on undo stack [report: Miloh] +- CLEANUP: parent subc update: + - inhibit mechanism to speed things up: + - under inhibit, pcb_subc_part_changed(ps) should mark subcircuits dirty + - when inhibit drops to zero, revisit all subcircuits that are dirty + - get a common inhibit function for batch processing that turn on draw, poly clip and pcb_subc_part_changed inhibit +- FEATURE: holes should be drawn below silk and mask - this could be a config setting +- BUG: I/O bugs: + - kicad: + - BUG: parser does not process trapezoidal pad definitions [report: erich] + - BUG: parser not parsing obround pad rotation, rot, (at x y rot), see work/bug_files/obround-rotation.kicad_pcb [report: erich] + - eagle: + - BUG: eagle binary library load fails with assert when pad dimension == 0, drill != zero. Bug arises from uninitiliased st.ms_width minimum feature width DRC value. This does not manifest in XML load as it initiliased to default value of 10mil before the DRC block is read, and updated if specified in the DRC block. There is no DRC block in an eagle binary library, so a decision has to be made wrt to where a default minimum feature size is to be referred to, so that the pad/hole reading code can apply it when pad dimension is not specified at line 824 in read.c. If dimension is not present, but drill is, read.c correctly applies the DRC derived rv_pad_top at line 818 dia = eagle_get_attrc(st, subtree, "diameter", drill * (1.0+st->rv_pad_top*2.0)); Planned changes to rectangle parsing to geenrate copper rectangles, not four lines, will alter +/- eliminate the need for the rectangle read routine to have ms_width available pre DRC read. See bug_files/e-motoren.lbr. [report: Erich] + - BUG: text rotations not quite right in eagle binary format layouts. See bug_files/tvbgone3-brd-in-eagle.png. Seems 180 and 270ccw rotation are rendered as upright an 90ccw rotation. Hmm. [erich] + - BUG: valgrind shows memory leaks relating to binary load. See bug_files/e-motoren.lbr [report: erich] + - BUG: on loading bug_files/diode.lbr, pcb-rnd's clipping polygon out of existence routine seems to go into a non terminating loop [report: erich] + - layers for top and bottom soldermask, if not present in loaded eagle file, i.e. tvbgone3.brd, do not export on creating gerbers, and cannot be added easily to layout via layer prefs, since ability to add a soldermask group is lacking [erich]. + - eagle XML import fails on polygon import reported by miloh, test file alien_formats/eagle/OSHW_XML_examples/eagle_polygon_crash.brd [report: erich], due to input file containing an invalid polygon: a self intersecting poly in line 156 - consider handling "width"? + - eagle rectangle parsing should generate a rectangular feature, not a four line rectangular outline [erich] + - eagle XML wire elements need to have "curve" attribute processed, if present. i.e. arcs. Can see translate2geda for hints [report: erich] + - eagle binary format appended text block needs to be parsed and the text strings allocated to ASCII-127 references in preceding text blocks [erich] + - eagle binary format v3 and libraries do not have a DRC block specifying restring or minimum feature widths. Binary loader should add a DRC block in these cases to the tree with the minimum settings needed for padstacks and features to load sensibly. [erich]. + - bin: padstack clearances for element pins will rely on connectivity to other polygons layer by layer defined in the netlist + - bin: need to refine naming of library (.lbr) elements in loaded .lbr files; any text names in the binary tree, if starting with ASCII 127, sequentially reference strings in the text block which comes immediately after the board/design tree. In later eagle binary versions, the text block seems to become a node of the tree, but a node of arbitrary length, not 24 bytes, with length of block still encoded in first few bytes. + - bin: need to add support for non top silk (tPlace), tDocu and top copper text in read.c + - bin: layouts, once loaded, have issue where deselection of elements only deselects element pins/pads. click-drag of element or saving the layout to .lht and reloading fixes the deselection issue. Example FTSH.... library file for a header exhibits this behaviour. + - revise all I/O plugins for: + - text thickness + - text rotation + - padstacks + - new outline/mech layers and slots + - new doc layers +- FEATURE: scripting: example script that tents/untents all/selected/object vias [report: keantoken] +- BUG: lesstif clip_set() doesn't seem to affect the X clipboard +- BUG: open gl polygon rendering: white line between just-touching polygons, may need a line clearance too; bug_files/gl_poly.lht [report: keantoken, Ade] +- BUG: Rubberband move line endpoints ignores connected arc endpoints. [Fixing:Ade] +- BUG: find.c: bug_files/find_slotcop.lht: plated slot should connect to any copper layer object it is going thru ml2571 [report: Igor2] +- BUG: pref: set role to user, add new library path -> it is saved in board! [report: aron] +- BUG: bug_files/rubberx.lht: move the horizontal line upward, rubber band breaks the traces (ortho mode) [report: aron] +- BUG: wandering lesstif window (window placement bug): using icewm, open the property editor, close, open, close, open: it's displaced by decoration [report: Igor2] +- BUG: io_pcb hole clearance import: Peter's report: "bug: .fp/.pcb import..." ml2933 [report: Peter] +- BUG: bug_files/bug_silk.lht: swap board, far-side color applies only to the first silk because it's not done by group but by layer [report: Peter] +- BUG: bug_files/bug_silk.lht: while top copper layer is active, selecting/moving/deleting ojects on the bug-silk layer (diagonal line) doesn't work properly [report: Igor2] +- BUG: bug_files/drc-pstk.lht: via-line "too close" is missed [report: Peter] +- BUG: direct gerber export (with which naming style?) results in empty drill gbrs ml=2928 [report: Peter] +- BUG: png export: the no-plating mark should not be drawn on png unless 'as-shown' is enabled ml=2931 [report: Peter] +- BUG: bug_files/warn.lht: load, click to somewhere to remove the warning (orange): object flag cleared but the board is not marked as changed [report: Peter] +- BUG: bug_files/macrofab_rot/: rotation (and coords?) is off on xy for macrofab [report: celem] +- BUG: bug_files/cam_layer_bug.lht: after cam export (from gui) the mask and paste layers are visible but the layer selector is not updated - r24366 supposed to fix this [report: keantoken] +- BUG: undo: clear rats, optimize rats, delete 1 rat then undo - it should undo the rat deletion but it undos optimization +- BUG: lesstif hbox/vbox allocation issues: test with bug_files/ltf_fillbox/ patches applied, with the fontsel action; opening it multiple times will randomly show or hide the button + - fontsel() -> no buttons (if the preview has no extfill, they appear!) [report: Igor2] + - about box: if not high enough, hbox/vbox/tab gets confused [report: Igor2] + - 0 room allocated under HPANE: pstklib(), netlistdialog(), propedit(), BrowseScripts, preferences dialog config tab + - preferences dialog: library, layers tabs are unusable [report: Igor2] + +3. Long term =============================================================================== +- BUG: draw a large padstack poly (as a subc term); put some vias (padtsacks) on top of it; with gdk and gl, after the 6th via some via rings will disappear [report: James] + -> reason: order of padstack shape rendering is random + -> we should probably render large objects first then smaller ones +- BUG: gtk2_gl: RTT/arc_sizes.lht - elliptical arc corner case render bug [report: Wed] +- FEATURE: "thermal recipe" so a padstack thermal can be put in a padstack or subc and it is change with the layer binding [report: jg] +- CLEANUP: layer group rewrite: remove PCB_MAX_LAYERGRP and PCB_MAX_LAYER and make them dynamic +- FEATURE: io_pcb: new, optional "layer tag" field in mainline's file format +- FEATURE: layer binding dialog: manual layer binding (reuse csect?) +- CLEANUP: reduce + - export_bom: rewrite the string list code using htsp and/or lists + - hash in hid_attrib.c? + - gcode invents .png name locally + - get rid of gcode/lists.h, and vector.[ch] (autorouter) + - vendordrill + - search for /units, replace it with pcb-printf something + - add round down + - replace ignore_refdes, ignore_value and ignore_descr with genvector +- vendor drill plugin: + - CLEANUP: check if we want to keep vendor name + - FEATURE: vendor: be able to load multiple vendor files (project spec for skips, central for vendor) [report: celem] +- FEATURE: lihata v7 + - remove via geometry from route style + - remove netlist net ->style, should be a plain attribute (but keep the dedicated field in old versions) + - save and load rat anchor object idpath + - poly side clearance when it is introduced in the data model3 + +Lesstif: + - implement/enable local grid in lesstif (menu option is disabled) + +GTK2: + - next_gui: keep them open, hide + +FEATURES +- BUILD: menuconfig and a config file for scconfig +- menu item for export of multiple selected layout elements to discrete .fp files + +4. Low prio =============================================================================== +- FEATURE: footprint in-place replacement should match up floaters to keep their coords, as documented in ML/2304 [report: gpaubert] +- FEATURE: filled vias for via-in-pad: http://www.saturnelectronics.com/products_capabilities/via-in-pad.html +- FEATURE: depth controlled mech layers (routed) for internal cavirites: http://www.saturnelectronics.com/products_capabilities/internal-cavity_boards.html +- BUG: 1. place 0603; 2. select; 3. cut to buffer; 4. undo -> 0603 put back but selection is lost; reason: the flag is removed in the buffer, but not in an undoable way as we don't have undo on buffer [report: igor2, miloh] +- BUG?: Far-side silk text can be selected and moved when the mouse is over front-side subcircuit. (but this is what we had with elements too! -> rewrite search.c to be a 'script' config) bug_files/farsilk.lht [report: Ade] +- BUG: RTT/arc_sizes.lht - unable to move arcs which have different width and height [report: Ade] - rewrite pcb_is_point_on_arc() elliptical case at the bottom +- FEATURE: padstack label smarter print: in case of full overlap of a bottom and top "pad", arrange other-side labels to avoid overlaps [report: al3x] +- FEATURE: preferences: grid list edit on the sizes tab +- improve locking: + - FEATURE: consider a move-only lock? + - BUG: when thermal and some other operations are applied on a locked element, indicate it +- BUG: rubberband_orig: draw a 90 deg arc, a 45 deg line that ends in the endpoints of the arc; enable rubber band, move the arc: only one endpoint of the line is moved [fixing:Ade] +- FEATURE: "save as" dialog: there should be an "auto" or "guess by extension" option in the save dialog format +- CLEANUP: insert drag&drop strangeness (mainline too): + insert should just insert a new point and stop there, not starting a drag&drop + move; the new point should be marked somehow (e.g. green-find one half of the + object, like arc split does) lines can be inserted mostly only in all-dir-line + which is strange +- FEATURE: display net names on pins, vias (and maybe tracks?) when zoomed in enough +- FEATURE: DRC should warn for thin poly hair +- CLEANUP: win32 port {large} + - clean up central Makefile.in rules: + - remove cat, sed, grep where possible, use scconfig instead +- BUG: arc bug: draw an arc with one end out of the drawing area; it will be jumpy and can not be placed properly + -> AttachForCopy() calls SetCrosshairRange() that then sets crosshair max* which + - similar with lines: bug_files/dwgarea.lht; grabbing the lines for move will force them to fall within the drawing area [report: pstuge] + limits the arc to move freely. Problem: this is not arc-specific, this happens with any buffer copy! going for no-design-limit is probably better + - similar issue: can't move outline lines to coord 0;0 because of line width.[report: pstuge] +- FEATURE: while drawing a line, the temporary outline should reflect the layer color +- CLEANUP: unify gui invocation options: pcb-rnd --help gtk_[gdk|gl] and pcb-rnd --help lesstif both show and use different input methods [report:miloh] +- FEATURE: trace length calculator: + - click a line or arc or via + - start a search in two directions mapping lines, arcs and vias connected (green-highlight them, marking them found) + - stop at the first junction (anywhere where more than 2 objects are connected) + - stop at polygons + - display the number of vias and net trace length along the found objects +- CLEANUP: core lib splitup: + - gsch2pcb: generalize plugin/buildin loading for external tools, check if gsch2pcb can work from plugins +- FEATURE: revise the importer; http://repo.hu/cgi-bin/pool.cgi?cmd=show&node=make_import ; should work without an existing file [report: TwisteR] Index: tags/2.1.2/doc/TODO.cleanup =================================================================== --- tags/2.1.2/doc/TODO.cleanup (nonexistent) +++ tags/2.1.2/doc/TODO.cleanup (revision 24813) @@ -0,0 +1,4 @@ +- rename: + - conf_* +- remove menu_toggle_update_cb() +- pcb-rnd: remove dad result & rethink static export tables, rename default_val to val Index: tags/2.1.2/doc/TODO.ddrc =================================================================== --- tags/2.1.2/doc/TODO.ddrc (nonexistent) +++ tags/2.1.2/doc/TODO.ddrc (revision 24813) @@ -0,0 +1,5 @@ +Tests: + - non-pstk paste object over mask or silk + - non-pstk paste object over hole? + - polygon hair, polygon too thin - Gabriel's example: mask being too thin between smd pads + - top/bottom copper keep-away from outline layers (peel-off on cutting with some fabs) Index: tags/2.1.2/doc/TODO.hid =================================================================== --- tags/2.1.2/doc/TODO.hid (nonexistent) +++ tags/2.1.2/doc/TODO.hid (revision 24813) @@ -0,0 +1,25 @@ +HID API simplification: DAD + +- blockers: + - implementing a list/tree/table "widget" for lesstif + - implementing and testing the PCB_HATT_TREE in lesstif + - implement and test a new text/log entry HATT (API not yet specified) in lesstif + - implement and test a new text/log entry HATT (API not yet specified) in gtk + +- DAD conversion: + - rewriting the route style dialog as DAD + - write a DAD based confirm window for fallback + - rewrite the user input window as DAD + - rewrite the log dialog (depends on the text/log HATT) + (- rewrite the pinout dialog as DAD (depends on a preview HATT, which is a bigger chunk)) + - rewrite the report dialog as DAD + +HID API simplification: actions + +- obsolete actions to remove/revise: + - lesstif: AdjustStyle (lesstif has its own window!) + - lesstif: LesstifNetlistShow + +- action unification: + - Scroll is only in the gtk hid + - Popup is gtk only Index: tags/2.1.2/doc/UNIX.txt =================================================================== --- tags/2.1.2/doc/UNIX.txt (nonexistent) +++ tags/2.1.2/doc/UNIX.txt (revision 24813) @@ -0,0 +1,31 @@ +State on UNIX systems +~~~~~~~~~~~~~~~~~~~~~ + +Source releases starting from 1.1.2 should compile and run out-of-the-box +on old UNIX systems, such as IRIX. Does NOT require any GNU installed. + +Requirements: + - x11 and motif (for the GUI) + - an awk implementation that supports gsub(), e.g. nawk + +1. If your C compiler does not support #warning, run a script to patch + the source: + + # cwd is the root of the distribution + util/workarounds/unwarn_all.sh + + This will take a while and will modify a lot of .c files. + +2. ./configure + +3. make + +Considerations listed in ../INSTALL apply. + +The above procedure has been tested on IRIX 5.3 on IP22. + +Expected compilation times [minute:second]: + +./configure compile, -O0 compile -O3 system +------------------------------------------------------------------------------- +1:55 7:40 14:27 IRIX 5.3, IP22 @ 100 MHz Index: tags/2.1.2/doc/conf/Makefile =================================================================== --- tags/2.1.2/doc/conf/Makefile (nonexistent) +++ tags/2.1.2/doc/conf/Makefile (revision 24813) @@ -0,0 +1,27 @@ +ROOT=../.. +CFDIR=$(DOCDIR)/conf + + +all: + +install_all: + $(SCCBOX) mkdir -p $(CFDIR)/tree + $(SCCBOX) $(HOW) *.html *.png $(CFDIR)/ + $(SCCBOX) $(HOW) tree/*.html $(CFDIR)/tree/ + + +install: + $(MAKE) install_all HOW="install -f -d" + +linstall: + $(MAKE) install_all HOW="install -f -l -d" + +uninstall: + $(MAKE) install_all HOW="install -u" + +clean: + +distclean: + + +include $(ROOT)/Makefile.conf Index: tags/2.1.2/doc/conf/groups.html =================================================================== --- tags/2.1.2/doc/conf/groups.html (nonexistent) +++ tags/2.1.2/doc/conf/groups.html (revision 24813) @@ -0,0 +1,122 @@ + + + + pcb-rnd - config groups + + + +

The new config system in pcb-rnd

+

grouping - flat vs. tree

+The original settings and HID attribute system in pcb were both flat: +basically a list of type:key=val triplets. All settings in a few big bags; +which bag sometimes doesn't depend on some logical categorizing, but +historical reasons (e.g. which part of the code needs the given setting). +

+This works well for a small amount of settings but lack of categories or +hierarchy (or sets or groups) makes it harder to understand what setting does +what and orients users to just accept defaults. After a while it also +makes programmers think twice before adding a new setting, increasing the +crowd in a bag. This in turn results in a less configurable +system. +

+Introducing a hierarchy of settings can solve these problems by grouping +and categorizing settings. If the user is interested in how footprints are +searched, they can ignore the settings the editor/ subtree has. It is also +easier to save and reload selectively: when the hierarchy is done right, +closely related settings end up in the same category (thus the same subtree). +Thus saving or loading a subtree can fully save or restore a property of the +program, even if that property is affected by multiple settings. + +

pcb-rnd config tree

+The config tree, the full tree is, something that exists in memory. Actual +config files often contain only a subset of the tree. Multiple config files +(e.g. system level, user level, settings from the board file) are loaded and +merged to form the final config tree. The hierarchy of the tree is represented +by setting groups, which are like directories on a file system. Actual settings +are always leaves of the tree, placed in a specific group at any level (just +like in file systems). A full path to a setting is written like a +path on a file system: group1/group2/item, where group1 and group2 are +names of setting groups and item is the name of the setting. Note: unlike +with real file systems, the leading slash (representing the root) is omitted. +

+Details/constraints: +A valid path unambiguously identifies a setting (or a setting group). Settings +and groups always have exactly one parent (except for the root group that +has no parent). There is only one root of the config tree. +

+The main groups in the logical tree are: + +

+ +
(root)   (config root) +
|       +
+- rc run control (program startup) +
|       +
|   |   +
|   +- path paths automatically set up by the program at startup - do not specify these +
|       +
+- design some default settings of a new design; minimum/maximum value of some design settings +
|       +
+- editor how the pcb editor behaves - independent of HIDs or the GUI +
|   |   +
|   +- increments_mm interactive increment/decrement steps when active unit is mm +
|   |   +
|   +- increments_mil interactive increment/decrement steps when active unit is mil +
|   |   +
|   +- view default view parameters +
|       +
+- appearance how the GUI looks like - common to all GUI HIDs +
|   |   +
|   +- color layer colors, GUI colors, misc design colors +
|   |   +
|   +- pinout pin label properties +
|   |   +
|   +- messages message window properties +
|   |   +
|   +- misc non-GUI settings handled by the GUI HIDs +
|       +
+- plugins dynamic subtree for various plugin settings +
|   |   +
|   +- foo all settings of the imaginary foo plugin are registered in this group +
|       +
+- utils dynamic subtree for various plugin settings +
  |   +
  +- bar all settings of the imaginary bar utility are registered in this group +
+
+ +

dynamic subtrees

+ +The plugins/ and utils/ subtree are dynamic, which means their contents +are not defined by core pcb. +

+In plugins/ each plugin should create a group for its own settings. What +this subtree should contain depends on what plugins are actually loaded. +The benefit of this approach is that plugins can use the central config +infrastructure instead of inventing their own config files. This makes +user's life easier on many levels: single config syntax to learn; uniform +GUI (gtk HID's preferences window) to change all settings; uniform way to +save/restore parts of the settings. +

+The utils/ subtree is very similar in all aspects except that it is for +external utility programs. Utils that are closely related to pcb-rnd, such +as gsch2pcb-rnd, should work from the same configuration. +If they already load the +pcb-rnd config files it's easier to keep their settings in the same tree, +in the same format. +

+Pcb-rnd doesn't generate warning for unrecognized settings in dynamic subtrees. +This lets the user configure plugins that are not always loaded and let util +settings sit in their subtree. + +

what happens to all these settings

+ +After loading all config files they are merged: if the same setting is +described in multiple files, the higher priority wins or if the setting is +a list (e.g. library search paths) the items are merged in a final list. +At this point the full logical config tree is built. Next the textual values +from the logical tree are converted into binary (native C values like +"long int" or "double") and are saved in C variables for the code to +access them directly. + + Index: tags/2.1.2/doc/conf/index.html =================================================================== --- tags/2.1.2/doc/conf/index.html (nonexistent) +++ tags/2.1.2/doc/conf/index.html (revision 24813) @@ -0,0 +1,83 @@ + + + + pcb-rnd - config system + + + +

The new config system in pcb-rnd

+

Why, what was wrong with the old one?

+The old config system had several limitations that would have been +hard to fix keeping the original design: +
    +
  • config settings were specified in a flat list - no grouping +
  • the core had a rather static system - HIDs or plugins couldn't extend it, thus they had to invent their own config files +
  • ... this led to a variety of configuration formats; using one format not always because it was better suited for the task, but for historical reasons +
  • ... this also led to a collection of config files - again not always split by boundaries of settings, but often by arbitrary boundaries of code +
  • the old system didn't support lists or arrays well +
  • it didn't have a coherent concept of how settings from different sources would override each other +
  • ... this resulted in the rigid structure that most of the settings could come from only one place (e.g. if it's an user setting, the design won't be able to override it) +
+ +

What the new system offers

+
    +
  • unified format: lihata ... +
  • ... more future proof: generic markup language - easier to extend without having to worry about breaking the syntax +
  • ... the configuration is represented in a tree, grouped by the nature of settings +
  • ... there are arrays and lists +
  • ... a config file can overwrite a list or prepend/append to it (e.g. design-level config prepending an extra library path keeping system set paths as well) +
  • there are different sources of configuration, e.g. system-wise, user-wise, project-wise, etc. +
  • the user has the power to change default config priority per setting; e.g. normally design config overrides user config, but it's possible to mark a setting from user config so strong that it overrides even the setting read from the board file +
  • the way settings are stored is flexible and extensible so that a plugin can define their subtree of settings +
  • ... since the API even makes it easier to access such settings (vs. parsing your own config file), plugins will tend to use the unified config format/system instead of inventing their own +
  • ... the GUI (gtk's preferences dialog) thus can automatically handle the new settings +
  • ... plugins don't have to implement actions to set/toggle/query their settings for the menu system, there are generic config set/toggle/query actions the menu config can use +
  • ... plugins also get the multi-source, priority-based config mechanism +
  • ... which also means plugin settings can be automatically saved as user setting, project setting or even design setting +
  • all these are true for all kind of settings, be them GUI preferences, paths, layer colors, grid settings; there should be no exception +
+ +

How to get started

+ + + +

But isn't this more complicated for the user?

+Hopefully not much. There are a few extra features, like +multiple sources with levels that did not +exist in pcb and lists with prepend/append. Some of these +features present in other software so users should be comfortable with the ideas. +The learning curve is probably compensated by the more orthogonal system. +The syntax is also geared for simplicity and easy use with text editors. +Finally, the new preferences dialog in the GTK HID and config actions help +the user to explore how settings got used from all the config sources. There's +an intended layering in complexity: simple things can be done easily without +having to understand the whole system. +

+All in all, the extra features the user needs to learn is comparable with +the old customs that he/she can forget. + +

And did it make the code more complicated?

+The size of the code did not change much after the initial config rewrite. +The new system has new features, some of which brought in a few hundred lines of +code, but a similar amount of old code could be removed. What came in is +infrastructure, what had to go was a bunch of repetitive config parsing, +boolean-setting-accessor-action code. This means on the long run, the more +settings are added, the more the new system pays back. +

+Read access, which is far the most common way to use the config in the +code (e.g. if (setting == true) { }) is very similar to the old Settings +system. Write access needs to go through a function call API, but this +is usually a single call per setting (instead of directly modifying a +variable). +

+For plugin programmers, the new system makes life much easier as they can +plug their settings in. + + + + Index: tags/2.1.2/doc/conf/index_prog.html =================================================================== --- tags/2.1.2/doc/conf/index_prog.html (nonexistent) +++ tags/2.1.2/doc/conf/index_prog.html (revision 24813) @@ -0,0 +1,14 @@ + + + + pcb-rnd - config programmer's index + + + +

The new config system in pcb-rnd

+

Programmer's documentation

+ +TODO + + + Index: tags/2.1.2/doc/conf/index_user.html =================================================================== --- tags/2.1.2/doc/conf/index_user.html (nonexistent) +++ tags/2.1.2/doc/conf/index_user.html (revision 24813) @@ -0,0 +1,99 @@ + + + + pcb-rnd - config for users + + + +

The pcb-rnd config system

+

User documentation

+As of 1.1.0, pcb-rnd switched to a lihata based configuration system. +The purpose of this document is to describes the basic system design going into +enough details to provide the user with full control over the configuration. +The other side, how the system is implemented is described in the + programmer's manual and there is also a +checklist to assist plugin programmers. + +

Architecture: data flows, merging, dispatching

+The final configuration is a collection of values for + all known settings, arranged in a tree. The config +tree is a theoretical concept; different representations of the tree are +actually built runtime, in-memory. Pcb-rnd code, plugins and utilities +are constantly reading these in-memory representations to decide how to +carry out their tasks. +

+Config settings are imported from multiple sources: from different files, +from environment variables, from command line arguments, from the opened (.pcb +or .lht) files on load. Any source can define any part of the config tree. +When the configuration is processed, each source is read into a temporary +tree and then all the temporary trees are merged into the final +config tree. The following diagram demonstrates all configuration +related data flows. +

+[diagram] +

+The leftmost column of nodes are the sources. (Note: paths mentioned there are +the default paths, for reference, it is possible to change them compile-time.) +Along the black arrows, from left to right, each source is imported into a +tree representing a role: the role or +purpose of the source. The next +step is following the red arrows in two steps: +
    +
  • first merge all the role trees into a flat list; this determines the value of each setting; +
  • then dispatch the values to the right component of the code. +
+Some components may change some of the settings run-time. The trivial example +is the GUI (hid_gtk on this diagram) that provides menus and dialog boxes for +the user to change settings. Such a change is always fed back (blue arrow) +to the design role tree directly, from where the new value is again merged +and dispatched along the red arrows. Changes in the design role are saved +with the board file (thus the bidirectional black arrow between the source and +the in-memory tree for the design role). Occasionally the user wants to +save parts of the setting as a project setting or +as an user setting - in this case, along the dashed blue lines, the +corresponding project or user roles are modified. This again results in updating +the hash and the binary representation; these roles also have +bidirectional black arrows and their changes are also saved in the original +source. + +

Merge details

+In the new system it is up to the user to decide what settings are +system-level and what settings are user- or project-level. This is possible +because any source can define any setting. In the merging step (red arrows +between roles and the hash) it may turn out that there are overlaps (multiple +sources defining value for the same setting) or blind spots (no source +sets a given item). + +

overlaps

+Each setting in each source has a priority. The +priority can be defined in the source, or if it is not defined, each source +inherits a fallback default priority. The fallback is designed to provide +the intuitive order: cli > design > project > user > system. +

+When multiple sources are describing a value for the same setting, +priority decides the final value. Most settings are scalar: +a single integer, string or a single "yes/no" or "on/off" value (e.g. +the background color or whether polygons are thin-drawn). For scalars +the rule is simple: the higher priority value wins and all lower priority +values are discarded when putting the values into the hash. More +details: how different roles and priorities +can be used with scalars. + +

+There are some settings that are represented as an array or list of +values. They are described in a lihata list item ("li:") in the config +files and are generally called lists in this document. How lists +are merged is controlled by the merging policy, which can be +in each source, just like the priority is set. Check out the +list merging section for more details. + +

blind spots

+At the end the code does need a value for each setting, so in the final +render (after the hash) every setting must have a value. To avoid blind spots, +values not initialized, there is a built-in configuration file, compiled into +the executable. This file is loaded into role CFR_INTERNAL, and has +the lowest priority. This configuration file contains the default value for +all settings. + + + Index: tags/2.1.2/doc/conf/lists.html =================================================================== --- tags/2.1.2/doc/conf/lists.html (nonexistent) +++ tags/2.1.2/doc/conf/lists.html (revision 24813) @@ -0,0 +1,133 @@ + + + + pcb-rnd - config lists + + + +

The new config system in pcb-rnd

+

Lists and arrays

+ +Non-scalar settings are arrays or lists. Arrays can be explicitly indexed + +The default policy is always overwrite. +

+There are three active policies: overwrite, prepend and append. +When dealing with lists: +

    +
  • step 1: the output list is reset to empty +
  • step 2: all sources that describe the list are sorted by priority +
  • step 3: sources are applied in order +
+Step 3 is straight-forward: if policy is overwrite, reset the output +list and copy the source's list into the output list. If policy is +prepend (or append), keep the current output list and prepend +(or append) the list provided by the source. +

+In practice this means the user can replace, prepend or append ordered lists +from various sources. A common example is setting the library search paths. + +

examples

+ +

simple overwrite

+Config sources (ordered by priority): + +
role priority policy content +
system 200 overwrite A,B,C +
user 400 overwrite (not defined) +
project 600 overwrite D,E +
+

Merge iterations: + +
step description output list after executing this step remarks +
0. reset the output (empty)   +
1. apply system A,B,C   +
2. apply user A,B,C "not defined" doesn't mean "empty", so the list is not deleted - no change +
3. apply project D,E replace the original output because of the overwrite policy +
+

Example scenario: the project is restricted to local footprint libs; this setup +makes sure no system or user configuration injects external footprint paths. + +

empty overwrite

+Config sources (ordered by priority): + +
role priority policy content +
system 200 overwrite A,B,C +
user 400 overwrite (not defined) +
project 600 overwrite defined to be an empty list +
+

Merge iterations: + +
step description output list after executing this step remarks +
0. reset the output (empty)   +
1. apply system A,B,C   +
2. apply user A,B,C "not defined" doesn't mean "empty", so the list is not deleted - no change +
3. apply project (empty) replace the original output because of the overwrite policy +
+ +

prepend

+Config sources (ordered by priority): + +
role priority policy content +
system 200 overwrite A,B,C +
user 400 prepend (not defined) +
project 600 prepend D,E +
+

Merge iterations: + +
step description output list after executing this step remarks +
0. reset the output (empty)   +
1. apply system A,B,C   +
2. apply user A,B,C "not defined" doesn't mean "empty", so the list is not deleted - no change +
3. apply project D,E,A,B,C   +
+

Example scenario: the project has its own footprint libs with two paths; these +should be searched before system and user paths, still, system path is also +kept so stock footprints can be found. +

+This is better than hardwiring A,B,C in the project's list: A, B and C may +depend on the installation on a given system. A project file has no idea +about how the system is installed but it is assumed system installation +and the system configuration file are consistent. + +

append

+Config sources (ordered by priority): + +
role priority policy content +
system 200 overwrite A,B,C +
user 400 append (not defined) +
project 600 append D,E +
+

Merge iterations: + +
step description output list after executing this step remarks +
0. reset the output (empty)   +
1. apply system A,B,C   +
2. apply user A,B,C "not defined" doesn't mean "empty", so the list is not deleted - no change +
3. apply project A,B,C,D,E   +
+

Example scenario: the project has its own footprint libs with two paths; these +should be searched after system and user paths. This means the local footprint +lib has lower priority than the stock footprints. See system-dependent +installation remarks in the previous point. + + +

prepend+append

+Config sources (ordered by priority): + +
role priority policy content +
system 200 overwrite A,B,C +
user 400 prepend X,Y,Z +
project 600 append D,E +
+

Merge iterations: + +
step description output list after executing this step remarks +
0. reset the output (empty)   +
1. apply system A,B,C   +
2. apply user X,Y,Z,A,B,C   +
3. apply project X,Y,Z,A,B,C,D,E   +
+ + + Index: tags/2.1.2/doc/conf/merging.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/conf/merging.png =================================================================== --- tags/2.1.2/doc/conf/merging.png (nonexistent) +++ tags/2.1.2/doc/conf/merging.png (revision 24813) Property changes on: tags/2.1.2/doc/conf/merging.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/conf/noextend.html =================================================================== --- tags/2.1.2/doc/conf/noextend.html (nonexistent) +++ tags/2.1.2/doc/conf/noextend.html (revision 24813) @@ -0,0 +1,67 @@ + + + + pcb-rnd - old config + + + +

The OLD config system in pcb-rnd

+

If the config system is too static

+ +This document describes the old situation, focusing on drawbacks for +a purpose: to give a hint on why some of the design decisions are made +the way they are, in the new conf system. + +

Settings, preferences, colors, and...

+The core implemented a so called Settings. It was a flat list of items, +each bound to a C variable. There was a bunch of metadata attached to +the items: name, type, description. Generic code could query or change +the value of any setting, the C code could read and write them directly +too. The content was saved to ~/.pcb/settings. +

+On the downside, the actual items this system knew about was pretty much +static, hardwired in core. A plugin could not register its own settings. +Multiple parallel methods were present in the code to overcome this +limitation: +

    +
  • HID attributes: another way to describe name-type-metadata lists; this + was used to pass on some rc-like parameters to the GUI HIDs. It's also the + main API to describe export parameters for the export HIDs. However, + HID attributes is not well suited for saving plugin (or HID) user + preferences, it is more about a per action configuration. + +
  • The gtk HID also saved its own settings to a separate file called + ~/.pcb/preferences. + +
  • Some gtk HID settings didn't quiet fit in the preferences - the color + scheme can be saved in another file, usually under ~/.pcb/colors + +
  • A random plugin could either use the HID attributes to get a limited + service or like the gtk HID did, had to implement its own save-restore of + persistent settings. +
+ +

Meta-drawbacks

+This also introduced a more subtle drawback: the configuration was now +scattered into different files, randomly (looking from the +user's point of view). In other words, the actual structure did not reflect +some logical grouping, but mostly historical or source code organizational +reasons. +

+In turn, this also limited (again somewhat randomly) what settings can be +stored system-wise, user-wise, or on project or design level. +

+Finally, handling of file search paths was not very sophisticated. There +was the system and user configuration that reflected where the stock +library or the user's generic library were installed. And then +there was the per-project local footprint libs that had to be somehow +added too. +

+There was a hardwired way of handling the situation where multiple set +of paths were specified. In practice it was usually possible to get this +to work for the simpler cases, but it was not powerful enough to express +things like "use all system and user libraries first, then the project's local +library" vs. "the project's local library has priority over system libraries". + + + Index: tags/2.1.2/doc/conf/plugin_chk.html =================================================================== --- tags/2.1.2/doc/conf/plugin_chk.html (nonexistent) +++ tags/2.1.2/doc/conf/plugin_chk.html (revision 24813) @@ -0,0 +1,14 @@ + + + + pcb-rnd - config plugin checklist + + + +

The new config system in pcb-rnd

+

Plugin programmer's checklist

+ +TODO + + + Index: tags/2.1.2/doc/conf/prio.html =================================================================== --- tags/2.1.2/doc/conf/prio.html (nonexistent) +++ tags/2.1.2/doc/conf/prio.html (revision 24813) @@ -0,0 +1,27 @@ + + + + pcb-rnd - config priorities + + + +

The new config system in pcb-rnd

+

Priorities

+ +Priority is an integer property of each config root. +Syntax-wise it is part of the name of the config +root. In the lihata config file it is either specified or omitted. When +omitted, a role dependent default value is +used. The default values are chosen in an intuitive way, thus most +commonly the priority value is omitted. +

+For scalar settings, the highest priority +value determines the final value of a setting after the merge. If there +is a tie, role decides: the role closer to the CLI is stronger. +

+For lists and arrays, priority determines the +order of merge, which changes the order of items in the final list as +config roots prepend and append items. + + + Index: tags/2.1.2/doc/conf/scalars.html =================================================================== --- tags/2.1.2/doc/conf/scalars.html (nonexistent) +++ tags/2.1.2/doc/conf/scalars.html (revision 24813) @@ -0,0 +1,61 @@ + + + + pcb-rnd - config scalars + + + +

The new config system in pcb-rnd

+

Scalars

+ +Scalar settings have only one value after the merge. The only policy +available is overwrite - this policy is applied regardless of the +current policy setting. + +

examples

+ +

simple overwrite

+Config sources: + +
role priority policy content +
system 200 overwrite A +
user 400 overwrite (not defined) +
project 600 overwrite Q +
+

+Merge iterations: + +
step description output list after executing this step remarks +
0. reset the output (empty)   +
1. apply system A   +
2. apply user A "not defined" doesn't mean "empty", so the list is not deleted - no change +
3. apply project Q replace the original output because of the overwrite policy +
+

Example scenario: system default overridden by a project setting. + +

user-forced value

+Config sources append: + +
role priority policy content +
system 200 overwrite A +
user 650 overwrite E +
project 600 overwrite Q +
+

+Merge iterations: + +
step description output list after executing this step remarks +
0. reset the output (empty)   +
1. apply system A   +
2. apply project Q   +
3. apply user E   +
+

Example scenario: user preference enforced: even if the project file would use +'Q' for the given setting, the user prefers 'E'. This affects runtime +(the value of the setting after the merge, in other words how pcb-rnd works), +but does not change the project configuration. This allows the given user to +always use 'E' for the given setting while lets other users working on the +same project use the value set in the project file. + + + Index: tags/2.1.2/doc/conf/sources.html =================================================================== --- tags/2.1.2/doc/conf/sources.html (nonexistent) +++ tags/2.1.2/doc/conf/sources.html (revision 24813) @@ -0,0 +1,89 @@ + + + + pcb-rnd - config sources + + + +

The new config system in pcb-rnd

+

Sources

+There are different sources of configuration settings. These are +different configuration files, sometimes located on the file system. +The full list of config sources is: + + +
role default
setting
prio
location presence remarks +
internal + 100 + (compiled into the executable) + always + the ultimate fallback; allows pcb-rnd even if no other configuration file is found + + +
system + 200 + /usr/share/pcb-rnd/pcb-conf.lht + recommended + should hold system and installation specific settings, e.g. path to the system-wise installed footprint library + +
default board + 300 + /usr/share/pcb-rnd/default4.lht1 + deprecated2 + pcb editable defaults + +
user + 400 + ~/.pcb-rnd/pcb-conf.lht + recommended + store user preferences, user's common footprint lib path, etc; this is the first file the user can modify (even from the GUI) + +
environment + 500 + environment variables (TODO) + occasional + inject the same (temporary) settings in multiple pcb-rnd sessions without having to change config files + +
project + 600 + project.lht in the project directory + optional + local project settings - useful for large projects with multiple board (.lht) files + +
design + 700 + saved in the board (.lht) file + optional, common + per design deviation from the user+system config + +
cli + 800 + command line argument + occasional + inject/change a setting for a single session; useful in batch/automated processing +
+ +

+Pcb-rnd reads them all, then merges all settings into a master binary +representation. If a setting is specified in multiple sources, the one +with the higher priority wins, except for lists where it is also possible +to prepend/append items. Default priorities are designed to result +precedence in an intuitive way (e.g. design settings overwrite user settings). +However, priority can be changed per setting, resulting +in weak settings ("use this value if it was not already set") or strong settings +("I always want to use mincut, so I enable it from my user's config with high +priority and a version controlled project setting can not turn it off") + +

+Footnotes: +

    +
  • 1: the name of the default board is default4.lht for + the default 4 layer board. The standard installation also ships default2.lht + as a similar 2 layer board. The name of the default boardfile is configured + in config node rc/default_pcb_file. +
  • 2: default pcb should not contain a config subtree; it is + easier to maintain the config tree if default configuration is coming from + config files only. +
+ + Index: tags/2.1.2/doc/conf/src/Makefile =================================================================== --- tags/2.1.2/doc/conf/src/Makefile (nonexistent) +++ tags/2.1.2/doc/conf/src/Makefile (revision 24813) @@ -0,0 +1,2 @@ +../merging.png: merging.dot + dot -Tpng merging.dot > ../merging.png \ No newline at end of file Index: tags/2.1.2/doc/conf/src/merging.dot =================================================================== --- tags/2.1.2/doc/conf/src/merging.dot (nonexistent) +++ tags/2.1.2/doc/conf/src/merging.dot (revision 24813) @@ -0,0 +1,103 @@ +digraph g { + rankdir=LR; + + subgraph cluster_memtree { + label="in-memory lihata trees" + bgcolor=grey + rank=same + CFR_INTERNAL [label="CFR_INTERNAL\nultimate fallback"] + CFR_SYSTEM [label="CFR_SYSTEM\nsystem level configuration"] + CFR_DEFAULTPCB [label="CFR_DEFAULTPCB"] + CFR_USER [label="CFR_USER\nuser level configuration"] + CFR_ENV [label="CFR_ENV"] + CFR_PROJECT [label="CFR_PROJECT\nproject level configuration"] + CFR_DESIGN [label="CFR_DESIGN"] + CFR_CLI [label="CFR_CLI"] + } + + subgraph cluster_fields { + label="string -> conf_native_t hash" + bgcolor=grey + conf_fields [label="conf_fields\ncentral hash\nof all\nknown settings"] + } + + subgraph cluster_native { + label="native C structures\nper module" + bgcolor=grey + conf_core [label="conf_core\npcb-rnd core settings"] + conf_hid_gtk [label="conf_hid_gtk\nthe hid_gtk plugin's settings"] + conf_mincut [label="conf_mincut\nthe mincut plugin's settings"] + conf_report [label="conf_report\nthe report plugin's settings"] + conf_other [label="...\nother plugin's settings"] + } + + CFR_INTERNAL -> conf_fields [color=red] + CFR_SYSTEM -> conf_fields [color=red] + CFR_DEFAULTPCB -> conf_fields [color=red] + CFR_USER -> conf_fields [color=red] + CFR_ENV -> conf_fields [color=red] + CFR_PROJECT -> conf_fields [color=red] + CFR_DESIGN -> conf_fields [color=red] + CFR_CLI -> conf_fields [color=red] + + +# CFR_INTERNAL -> CFR_SYSTEM +# CFR_SYSTEM -> CFR_DEFAULTPCB +# CFR_DEFAULTPCB -> CFR_USER +# CFR_USER -> CFR_ENV +# CFR_ENV -> CFR_PROJECT +# CFR_PROJECT -> CFR_DESIGN +# CFR_DESIGN -> CFR_CLI + + conf_fields -> conf_core [color=red] + conf_fields -> conf_hid_gtk [color=red] + conf_fields -> conf_mincut [color=red] + conf_fields -> conf_report [color=red] + conf_fields -> conf_other [color=red] + + + + subgraph cluster_files { + label="config files" + bgcolor=grey + lht_system [label="/usr/share/pcb-rnd/pcb-conf.lht" shape=hexagon] + pcb_default [label="/usr/share/pcb-rnd/default.pcb" shape=hexagon] + project [label="./project.lht" shape=hexagon] + lht_user [label="~/.pcb-rnd/pcb-conf.lht" shape=hexagon] + } + + subgraph cluster_exec_env { + label="execution environment" + bgcolor=grey + env [label="environmental variables"] + cli [label="command line arguments\ne.g. -c or\npluginspecific args"] + } + + lht_internal [label="hardwired\nin the\nexecutable"] + design [label="settings\nin the\n.pcb file" shape=hexagon] + + lht_internal -> CFR_INTERNAL [label="program startup"] + lht_system -> CFR_SYSTEM [label="loaded at startup"] + pcb_default -> CFR_DEFAULTPCB [label="loadad in CreateNewPCB()"] + lht_user -> CFR_USER [label="loaded at startup" dir=both] + env -> CFR_ENV [label="built at startup"] + project -> CFR_PROJECT [label="loaded when a\nnew .pcb or project\nis loaded" dir=both] + design -> CFR_DESIGN [label="extracted when loading a design" dir=both] + cli -> CFR_CLI [label="built during\ncommand line argument\nparsing"] + + + hid_gtk [label="the GTK HID"] + + conf_core -> hid_gtk [weight=100] + conf_hid_gtk -> hid_gtk + + hid_gtk -> CFR_DESIGN [color=blue weigth=0] + hid_gtk -> CFR_PROJECT [color=blue weigth=0 style=dashed] + hid_gtk -> CFR_USER [color=blue weigth=0 style=dashed] + + + editor [label="core:\nediting pcb"] + conf_core -> editor [weight=100] + editor -> CFR_DESIGN [color=blue weigth=0] + +} \ No newline at end of file Index: tags/2.1.2/doc/conf/syntax.html =================================================================== --- tags/2.1.2/doc/conf/syntax.html (nonexistent) +++ tags/2.1.2/doc/conf/syntax.html (revision 24813) @@ -0,0 +1,53 @@ + + + + pcb-rnd - config syntax + + + +

The new config system in pcb-rnd

+

Config file syntax

+ +The config file syntax is lihata. +Most users don't need to understand most of the syntax, just follow the +patterns seen in the examples. A few thumb of rules: +
    +
  • structural nodes usually start with a ha: or li: prefix; which one needs to be used is pretty much tied to the node name; thus casual users don't need to care about what they are for, just remember them as part of the name +
  • non-structural nodes are usually given in the form of name = value; use braces around the value if it contains any non-alphanumeric, non-whitespace character +
  • list and array members should better be braced +
  • list and array separator should be semicolon (not comma) +
+ +

config root syntax

+

+A pcb-rnd config file, (or document for short) has a single root +node whose name must be li:pcb-rnd-conf-v1 - this is the signature of the +document. It is a flat list of one or more config root/ subtrees. +TODO: is this really a list or a hash? +

+Each config root is a partial description of the + config tree (which is the logical +configuration of all possible settings). Config roots have a policy and +a priority attached. This is done in the name +of the config root, which must be of the form of policy-priority, +e.g. "overwrite-300" or "append-125". The priority part (with the dash) +can be omitted (and then the per role default priority is used), e.g. +"overwrite" or "append" are valid config root names. +

+Under the config root, a tree of sections (hashes) and setting values +(text nodes) are built. These structures and values are in 1:1 +correspondence with the config tree. Excess +(unknown) keys are considered a warning (except in the plugin/ and +utils/ subtrees). Missing keys or missing subtrees is normal because a config +root can be partial. +

+TODO: examples + +

list syntax

+TODO: list syntax + +

in project files

+TODO + + + Index: tags/2.1.2/doc/conf/tree/CFN_BOOLEAN.html =================================================================== --- tags/2.1.2/doc/conf/tree/CFN_BOOLEAN.html (nonexistent) +++ tags/2.1.2/doc/conf/tree/CFN_BOOLEAN.html (revision 24813) @@ -0,0 +1,8 @@ + + +

pcb-rnd conf tree

+

type: boolean

+Boolean value: true or false. Most often used for determining whether a +feature or a (display mode) is enabled. +

+Example values: true, false, on, off, yes, no, 1, 0. Index: tags/2.1.2/doc/conf/tree/CFN_COLOR.html =================================================================== --- tags/2.1.2/doc/conf/tree/CFN_COLOR.html (nonexistent) +++ tags/2.1.2/doc/conf/tree/CFN_COLOR.html (revision 24813) @@ -0,0 +1,9 @@ + + +

pcb-rnd conf tree

+

type: color

+A color description. Use the "webcolor" format: #rrggbb, where +rr, gg and bb are 2 digit hexadecimal values for red, green and blue +components. +

+Example values: #ff0000 for red, #555555 for grey. Index: tags/2.1.2/doc/conf/tree/CFN_COORD.html =================================================================== --- tags/2.1.2/doc/conf/tree/CFN_COORD.html (nonexistent) +++ tags/2.1.2/doc/conf/tree/CFN_COORD.html (revision 24813) @@ -0,0 +1,10 @@ + + +

pcb-rnd conf tree

+

type: coord

+A coordinate: size, distance, spacing. A decimal number with an unit. Unit +can be metric (e.g. mm, cm, m) or imperial (e.g. mil). +

+Example values: 1.5mm, 15 mil + + Index: tags/2.1.2/doc/conf/tree/CFN_INCREMENTS.html =================================================================== --- tags/2.1.2/doc/conf/tree/CFN_INCREMENTS.html (nonexistent) +++ tags/2.1.2/doc/conf/tree/CFN_INCREMENTS.html (revision 24813) @@ -0,0 +1,8 @@ + + +

pcb-rnd conf tree

+

type: increments

+A collection of coordinates representing an increment configuration. +

+TODO + Index: tags/2.1.2/doc/conf/tree/CFN_INTEGER.html =================================================================== --- tags/2.1.2/doc/conf/tree/CFN_INTEGER.html (nonexistent) +++ tags/2.1.2/doc/conf/tree/CFN_INTEGER.html (revision 24813) @@ -0,0 +1,10 @@ + + +

pcb-rnd conf tree

+

type: integer

+A decimal integer value without unit. The value might be stored in a +32 bit integer; safe range is approximately -2^31 .. 2^31. +

+Example values: 4, 1500, 2545343, -6 + + Index: tags/2.1.2/doc/conf/tree/CFN_LIST.html =================================================================== --- tags/2.1.2/doc/conf/tree/CFN_LIST.html (nonexistent) +++ tags/2.1.2/doc/conf/tree/CFN_LIST.html (revision 24813) @@ -0,0 +1,10 @@ + + +

pcb-rnd conf tree

+

type: list

+An ordered list of strings. +

+Example values: +

+li:{ foo; bar; {foo/bar/with-punctuation}; 123}
+
Index: tags/2.1.2/doc/conf/tree/CFN_REAL.html =================================================================== --- tags/2.1.2/doc/conf/tree/CFN_REAL.html (nonexistent) +++ tags/2.1.2/doc/conf/tree/CFN_REAL.html (revision 24813) @@ -0,0 +1,9 @@ + + +

pcb-rnd conf tree

+

type: real

+A decimal numeric value without unit. +

+Example values: 3.141592654, 5, -12, 0 + + Index: tags/2.1.2/doc/conf/tree/CFN_STRING.html =================================================================== --- tags/2.1.2/doc/conf/tree/CFN_STRING.html (nonexistent) +++ tags/2.1.2/doc/conf/tree/CFN_STRING.html (revision 24813) @@ -0,0 +1,13 @@ + + +

pcb-rnd conf tree

+

type: string

+Text value. +

+Example values: +

+foo
+bar
+{long text with / punctuation?}
+
+ Index: tags/2.1.2/doc/conf/tree/CFN_UNIT.html =================================================================== --- tags/2.1.2/doc/conf/tree/CFN_UNIT.html (nonexistent) +++ tags/2.1.2/doc/conf/tree/CFN_UNIT.html (revision 24813) @@ -0,0 +1,9 @@ + + +

pcb-rnd conf tree

+

type: unit

+Name of a unit. +

+Example values: mm, cm, m, mil + + Index: tags/2.1.2/doc/conf/tree/appearance.html =================================================================== --- tags/2.1.2/doc/conf/tree/appearance.html (nonexistent) +++ tags/2.1.2/doc/conf/tree/appearance.html (revision 24813) @@ -0,0 +1,16 @@ + +

pcb-rnd conf tree

+

subtree: appearance

+ +
node name type flags description +
compact boolean 0 when set: optimize GUI widget arrangement for small screen; may be wasting some screen space on large screen +
rat_thickness coord 0 +
mark_size coord 0 relative marker size +
layer_alpha real 0 alpha value for layer drawing +
drill_alpha real 0 alpha value for drill drawing +
text_host_bbox boolean 0 when moving a text object, the outline thin-draw should also include the bounding box +
term_label_size real 0 size of terminal labels, in pcb font scale (100 is for the normal size) +
subc_layer_per_side boolean 0 hide top or bottom placed subcircuit annotations if the view is showing the other side +
invis_other_groups boolean 0 render non-current group layers with the inivisble color +
black_current_group boolean 0 render all layers of the current group black, for maximum contrast +
Index: tags/2.1.2/doc/conf/tree/appearance_color.html =================================================================== --- tags/2.1.2/doc/conf/tree/appearance_color.html (nonexistent) +++ tags/2.1.2/doc/conf/tree/appearance_color.html (revision 24813) @@ -0,0 +1,28 @@ + +

pcb-rnd conf tree

+

subtree: appearance/color

+ +
node name type flags description +
background color 0 background and cursor color ... +
crosshair color 0 different object colors +
cross color 0 crosshair, drc outline color +
selected color 0 generic object selection color +
via color 0 non-terminal padstack shape on current layer +
via_far color 0 non-terminal padstack shape on non-current ('far side') layer +
pin color 0 terminal padstack shape on current layer +
pin_far color 0 terminal padstack shape on non-current ('far side') layer +
pin_name color 0 on-screen terminal number/name labels +
subc color 0 on-screen subcircuit marks +
subc_nonetlist color 0 on-screen subcircuit marks for subcircuits with the nonetlist flag +
padstackmark color 0 on-screen center mark cross for padstacks +
rat color 0 on-screen rat lines +
invisible_objects color 0 other-side objects and padstack shapes on non-current layer +
connected color 0 'connected' highlight (galvanic connections found) +
warn color 0 warning highlight (e.g. object found to cause a short) +
off_limit color 0 on-screen background beyond the configured drawing area +
grid color 0 on-screen grid +
layer color 0 default layer colors; when a new layer is created, a color from this list is assigned initially +
mask color 0 default mask layer color (when a new mask layer is created) +
paste color 0 default paste layer color (when a new paste layer is created) +
element color 0 default silk layer color (when a new silk layer is created) +
Index: tags/2.1.2/doc/conf/tree/appearance_loglevels.html =================================================================== --- tags/2.1.2/doc/conf/tree/appearance_loglevels.html (nonexistent) +++ tags/2.1.2/doc/conf/tree/appearance_loglevels.html (revision 24813) @@ -0,0 +1,14 @@ + +

pcb-rnd conf tree

+

subtree: appearance/loglevels

+ +
node name type flags description +
debug_tag string 0 log style tag of debug messages +
debug_popup boolean 0 whether a debug line should pop up the log window +
info_tag string 0 log style tag of info messages +
info_popup boolean 0 whether an info line should pop up the log window +
warning_tag string 0 log style tag of warnings +
warning_popup boolean 0 whether a warning should pop up the log window +
error_tag string 0 log style tag of errors +
error_popup boolean 0 whether an error should pop up the log window +
Index: tags/2.1.2/doc/conf/tree/appearance_messages.html =================================================================== --- tags/2.1.2/doc/conf/tree/appearance_messages.html (nonexistent) +++ tags/2.1.2/doc/conf/tree/appearance_messages.html (revision 24813) @@ -0,0 +1,7 @@ + +

pcb-rnd conf tree

+

subtree: appearance/messages

+ +
node name type flags description +
char_per_line integer 0 width of an output line in characters (used by separator drawing in find.c) +
Index: tags/2.1.2/doc/conf/tree/appearance_misc.html =================================================================== --- tags/2.1.2/doc/conf/tree/appearance_misc.html (nonexistent) +++ tags/2.1.2/doc/conf/tree/appearance_misc.html (revision 24813) @@ -0,0 +1,7 @@ + +

pcb-rnd conf tree

+

subtree: appearance/misc

+ +
node name type flags description +
volume integer 0 the speakers volume -100..100 +
Index: tags/2.1.2/doc/conf/tree/appearance_padstack.html =================================================================== --- tags/2.1.2/doc/conf/tree/appearance_padstack.html (nonexistent) +++ tags/2.1.2/doc/conf/tree/appearance_padstack.html (revision 24813) @@ -0,0 +1,8 @@ + +

pcb-rnd conf tree

+

subtree: appearance/padstack

+ +
node name type flags description +
cross_thick integer 0 cross thickness in pixels - 0 means disable crosses +
cross_size coord 0 cross size in word coords - size of one arm of the cross (minus the hole radius) +
Index: tags/2.1.2/doc/conf/tree/appearance_subc.html =================================================================== --- tags/2.1.2/doc/conf/tree/appearance_subc.html (nonexistent) +++ tags/2.1.2/doc/conf/tree/appearance_subc.html (revision 24813) @@ -0,0 +1,7 @@ + +

pcb-rnd conf tree

+

subtree: appearance/subc

+ +
node name type flags description +
dash_freq integer 0 how dense the dashed outline should be; -1 means do not display the dashed outline; 0 means solid outline; 1..32 means dashed outline +
Index: tags/2.1.2/doc/conf/tree/design.html =================================================================== --- tags/2.1.2/doc/conf/tree/design.html (nonexistent) +++ tags/2.1.2/doc/conf/tree/design.html (revision 24813) @@ -0,0 +1,23 @@ + +

pcb-rnd conf tree

+

subtree: design

+ +
node name type flags description +
via_thickness coord 0 +
via_drilling_hole coord 0 +
line_thickness coord 0 +
clearance coord 0 +
bloat coord 0 minimum space between copper features on different networks +
shrink coord 0 minimum overlap between connected copper features +
min_wid coord 0 minimum copper width +
min_slk coord 0 minimum silk width +
min_drill coord 0 minimum drill diameter +
min_ring coord 0 minimum annular ring +
text_scale integer 0 text scaling in % +
text_thickness coord 0 override stroke font text thickness +
text_font_id integer 0 +
poly_isle_area real 0 polygon min area +
fab_author string 0 Full name of author for FAB drawings +
initial_layer_stack string 0 deprecated. +
paste_adjust coord 0 Adjust paste thickness +
Index: tags/2.1.2/doc/conf/tree/editor.html =================================================================== --- tags/2.1.2/doc/conf/tree/editor.html (nonexistent) +++ tags/2.1.2/doc/conf/tree/editor.html (revision 24813) @@ -0,0 +1,62 @@ + +

pcb-rnd conf tree

+

subtree: editor

+ +
node name type flags description +
grid_unit unit 0 select whether you draw in mm or mil +
grid coord 0 grid in pcb-units +
grids list 0 grid in grid-string format +
grids_idx integer 0 the index of the currently active grid from grids +
zoom real 0 default zoom +
mode integer 0 currently active mode +
buffer_number integer 0 number of the current buffer +
clear_line boolean 0 new lines/arc clear polygons. +
clear_polypoly boolean 0 new polygons clear polygons. +
full_poly boolean 0 new polygons are full polygons. +
unique_names boolean 0 OBSOLETE: force unique names +
snap_pin boolean 0 snap to pins and pads +
snap_offgrid_line boolean 0 Snap to certain off-grid points along a line. +
marker_snaps boolean 0 marker snaps to grid or snap points, as any other click +
highlight_on_point boolean 0 Highlight if crosshair is on endpoints. +
show_solder_side boolean 0 mirror output +
save_last_command boolean 0 the command entry editline always starts with the last command entered by user in the current session +
line_refraction integer 0 value for line lookahead setting +
save_in_tmp boolean 0 emergency save unsaved PCB data (despite the user clicks don't save) when: user starts a new PCB; user quits pcb-rnd. Does not affect the on-crash emergency save. +
draw_grid boolean 0 draw grid points +
all_direction_lines boolean 0 enable lines to all directions +
rubber_band_mode boolean 0 move, rotate use rubberband connections +
rubber_band_keep_midlinedir boolean 0 keep line direction when a middle line is moved +
swap_start_direction boolean 0 change starting direction after each click +
show_drc boolean 0 show drc region on crosshair +
auto_drc boolean 0 when set, PCB doesn't let you place copper that violates DRC. +
conn_find_rat boolean 0 connection find includes rats; when off, only existing galvanic connections are mapped +
show_number boolean 0 OBSOLETE: pinout shows number +
orthogonal_moves boolean 0 move items orthogonally. +
reset_after_element boolean 0 OBSOLETE: reset connections after each element while saving all connections +
auto_place boolean 0 force placement of GUI windows (dialogs), trying to override the window manager +
lock_names boolean 0 lock down text so they can not be moved or selected +
only_names boolean 0 lock down everything else but text so only text objects can be moved or selected +
thin_draw boolean 0 if set, objects on the screen are drawn as outlines (lines are drawn as center-lines). This lets you see line endpoints hidden under pins, for example. +
thin_draw_poly boolean 0 if set, polygons on the screen are drawn as outlines. +
as_drawn_poly boolean 0 if set, also draw the as-drawn outline of polygons +
wireframe_draw boolean 0 if set, lines and arcs on the screen are drawn as outlines. +
local_ref boolean 0 use local reference for moves, by setting the mark at the beginning of each move. +
check_planes boolean 0 when set, only polygons and their clearances are drawn, to see if polygons have isolated regions. +
hide_names boolean 0 when set, subc floater text objects (typical use case: refdes text) are not drawn. +
description boolean 0 obsolete - DO NOT USE - kept for compatibility +
name_on_pcb boolean 0 obsolete - DO NOT USE - kept for compatibility +
subc_id string 0 subcircuit ID template for diplaying the subcircuit label on the subcircuit layer; default to displaying the refes, if empty; syntax if the same as for DYNTEXT +
term_id string 0 terminal ID template for diplaying the subcircuit label on the subcircuit layer; default to displaying termid[intconn], if empty; syntax if the same as for DYNTEXT +
fullscreen boolean 0 hide widgets to make more room for the drawing +
move_linepoint_uses_route boolean 0 Moving a line point calculates a new line route. This allows 45/90 line modes when editing lines. +
auto_via boolean 0 when drawing traces and switching layers or when moving an object from one layer to another, try to keep connections by automatically inserting vias. +
route_radius real 0 temporary: route draw helper's arc radius at corners (factor of the trace thickness) +
io_incomp_popup boolean 0 wether to enable popping up the io incompatibility list dialog on save incompatibility errors +
io_incomp_style string 0 view listing style (list or simple), when io_incomp_popup is true +
click_time integer 0 default time for click expiration, in ms +
enable_stroke boolean 0 Enable libstroke gestures on middle mouse button when non-zero +
live_routing boolean 0 autorouter shows tracks in progress +
beep_when_finished boolean 0 flag if a signal should be produced when searching of connections is done +
undo_warning_size integer 0 warn the user when undo list exceeds this amount of kilobytes in memory +
subc_conv_refdes string 0 automatic refdes value assigned to new subcircuits on conversion from objects - if empty, no refdes text or attribute is added; if the value is , the refdes text object is added but no refdes attribute is created +
Index: tags/2.1.2/doc/conf/tree/editor_selection.html =================================================================== --- tags/2.1.2/doc/conf/tree/editor_selection.html (nonexistent) +++ tags/2.1.2/doc/conf/tree/editor_selection.html (revision 24813) @@ -0,0 +1,8 @@ + +

pcb-rnd conf tree

+

subtree: editor/selection

+ +
node name type flags description +
disable_negative boolean 0 selection box behaviour: disable the negative-direction selection - any selection box will select only what's fully within the box +
symmetric_negative boolean 0 selection box behaviour: when set, the selection direction is considered negative only if the box has negative size in the X direction +
Index: tags/2.1.2/doc/conf/tree/editor_view.html =================================================================== --- tags/2.1.2/doc/conf/tree/editor_view.html (nonexistent) +++ tags/2.1.2/doc/conf/tree/editor_view.html (revision 24813) @@ -0,0 +1,8 @@ + +

pcb-rnd conf tree

+

subtree: editor/view

+ +
node name type flags description +
flip_x boolean 0 view: flip the board along the X (horizontal) axis +
flip_y boolean 0 view: flip the board along the Y (vertical) axis +
Index: tags/2.1.2/doc/conf/tree/rc.html =================================================================== --- tags/2.1.2/doc/conf/tree/rc.html (nonexistent) +++ tags/2.1.2/doc/conf/tree/rc.html (revision 24813) @@ -0,0 +1,37 @@ + +

pcb-rnd conf tree

+

subtree: rc

+ +
node name type flags description +
verbose integer 0 +
quiet integer 0 print only errors on stderr +
dup_log_to_stderr boolean 0 copy log messages to stderr even if there is a HID that can show them +
backup_interval integer 0 time between two backups in seconds; 0 means disabled (no backups) +
hid_fallback boolean 0 if there is no explicitly specified HID (--gui) and the preferred GUI fails, automatically fall back on other HIDs, eventually running in batch mode +
brave string 0 brave mode flags: when non-empty, enable various experimental (unstable) features - useful for testers +
font_command string 0 file name template; if not empty, run this command and read its output for loading the font; %f is the file name +
file_command string 0 file name template; if not empty, run this command and read its output for loading a pcb file; %f is the file name, %p is the conf setting rc.file_path +
file_path string 0 +
library_shell string 0 +
library_search_paths list 0 +
menu_file string 0 where to load the default menu file from. If empty/unset, fall back to the legacy 'per hid ow menu file' setup. If contains slash, take it as a full path, if no slash, do a normal menu search for pcb-menu-NAME.lht +
export_basename boolean 0 if an exported file contains the source file name, remove path from it, keeping the basename only +
emergency_name string 0 file name template for emergency save anonymous .pcb files (when pcb-rnd crashes); optional field: %ld --> pid; must be shorter than 240 characters. Don't do emergency save if this item is empty. +
emergency_format string 0 if set, use this format for the backups; if unset, use the default format +
backup_name string 0 file name template for periodic backup of board files; optional fields (the usual % substitutions work) +
backup_format string 0 if set, use this format for the backups; if unset or set to 'original', use the original format +
save_command string 0 command to pipe the pcb, footprint or buffer file into, when saving (makes lihata persist impossible) +
keep_save_backups boolean 0 a copy is made before a save operation overwrites an existing file; if this setting is true, keep the copy even after a successful save +
default_font_file list 0 name of default font file (list of names to search) +
default_pcb_file list 0 +
script_filename string 0 PCB Actions script to execute on startup +
action_string string 0 PCB Actions string to execute on startup +
rat_path string 0 +
rat_command string 0 file name template; if not empty, run this command and read its output for loading a rats; %f is the file name, %p is the rc.rat_path conf setting +
preferred_gui list 0 if set, try GUI HIDs in this order when no GUI is explicitly selected +
save_final_fallback_fmt string 0 when a new file is created (by running pcb-rnd with the file name) there won't be a known format; pcb-rnd will guess from the file name (extension) but eventhat may fail. This format is the final fallback that'll be used if no other guessing mechanism worked. The user can override this by save as. +
save_fp_fmt string 0 when saving a buffer element/subcircuit, prefer this format by default +
cli_prompt string 0 plain text prompt to prefix the command entry +
cli_backend string 0 command parser action +
have_regex boolean 0 whether we have regex compiled in +
Index: tags/2.1.2/doc/conf/tree/rc_path.html =================================================================== --- tags/2.1.2/doc/conf/tree/rc_path.html (nonexistent) +++ tags/2.1.2/doc/conf/tree/rc_path.html (revision 24813) @@ -0,0 +1,13 @@ + +

pcb-rnd conf tree

+

subtree: rc/path

+ +
node name type flags description +
prefix string 0 e.g. /usr/local +
lib string 0 e.g. /usr/lib/pcb-rnd +
bin string 0 e.g. /usr/bin +
share string 0 e.g. /usr/share/pcb-rnd +
home string 0 user's home dir, determined run-time +
exec_prefix string 0 exec prefix path (extracted from argv[0]) +
design string 0 directory path of the current design, or if the current design doesn't have a file name yet +
Index: tags/2.1.2/doc/conf/tree/temp.html =================================================================== --- tags/2.1.2/doc/conf/tree/temp.html (nonexistent) +++ tags/2.1.2/doc/conf/tree/temp.html (revision 24813) @@ -0,0 +1,8 @@ + +

pcb-rnd conf tree

+

subtree: temp

+ +
node name type flags description +
rat_warn boolean 0 rats nest has set warnings +
clip_inhibit_chg boolean 0 dummy node to inform the menu about clip inhibit change +
Index: tags/2.1.2/doc/contact.html =================================================================== --- tags/2.1.2/doc/contact.html (nonexistent) +++ tags/2.1.2/doc/contact.html (revision 24813) @@ -0,0 +1,57 @@ + + + + + pcb-rnd - contact + + + + + + + + + +
Main + News + Doc & pool + Support + People + Events & timeline + pcb-rnd [pcb-rnd logo] +
+ + +

pcb-rnd - contact

+ +

Contact the project

+

+Please subscribe to the mailing list by sending "subscribe" to +pcb-rnd list.repo.hu or join IRC for + live chat (CET daytime) with other users +and developers. + +

Contact the lead developer

+

+Join IRC for live chat (CET daytime) and +look for Igor2. +

+Via email: pcbrnd igor2.repo.hu. + + +
+

+PRIVACY NOTICE: +

+This email address is provided only for personal use, exclusively for +topics directly related to the pcb-rnd project. +

+Do NOT copy it this email address to +software packages, documentation, etc. Permission is NOT granted +for collecting this email address in any list of email addresses. +Since this email address is a personal address, the + +GDPR applies while you are handling it. +

+ + Index: tags/2.1.2/doc/contrib.html =================================================================== --- tags/2.1.2/doc/contrib.html (nonexistent) +++ tags/2.1.2/doc/contrib.html (revision 24813) @@ -0,0 +1,72 @@ + + + + + pcb-rnd - contribution + + + + + + + + + +
Main + News + Doc & pool + Support + People + Events & timeline + pcb-rnd [pcb-rnd logo] +
+ + +

pcb-rnd - contribution

+ +If you are interested to help out, please +contact the lead developer. + + +

Contributing as a user

+Using pcb-rnd in production and just reporting bugs is already a huge contribution. +

+We also have a list of tasks that can be contributed by users. +

+More dedicated users can join in scheduled, systematic testing. Such testing +is split up into independent chunks that each can be done in an hour. +

+Even more dedicated users can join developing the documentation. +

+None of the above requires or assumes any programming skill. + +

Contributing as a developer

+

+The project is lead in an autocratic way by Igor2. +

+Developer freedom taken away: +

    +
  • the basic concept of pcb-rnd is set and won't change +
  • the toolchain is chosen, and won't change; the usual hot topics: svn, scconfig, C. +
  • don't add code that restricts usability for others; add code that increases usability for some; thus prefer to add code in plugins! +
+

+Developer freedom promptly granted: +

    +
  • svn commit access from day 0 +
  • work together in trunk/, not alone in a branch +
  • pcb-rnd has a strong plugin support; want to implement a strange/controversial feature? In a plugin, almost anything goes +
  • especially in plugins, work on whatever you want, even if noone else needs that feature +
+

+Coding style/indentation: there's an unified style +in core and core plugins. If you work on those parts, try to stick to it. If you +are working on a new plugin, it's still the preferred style but you can use +a different style. However, the rule is that if someone else starts hacking +that part too, he is allowed to convert the code to the unified format; but +unified format can not be converted to anything else. So it's a one way +process which long term grants unified style while not demotivates a plugin +developer by forcing a style on him in the early, "when the bulk of the code +is written" phase. + + Index: tags/2.1.2/doc/datasheet.html =================================================================== --- tags/2.1.2/doc/datasheet.html (nonexistent) +++ tags/2.1.2/doc/datasheet.html (revision 24813) @@ -0,0 +1,94 @@ + + + + pcb-rnd - datasheet + + + + + + + + + + +
Main + News + Doc & pool + Support + People + Events & timeline + pcb-rnd [pcb-rnd logo] +
+ + +

pcb-rnd - datasheet

+ + + + + + + + + + + + + + + + + +
layout characteristics + multiple layers (16 copper, compile time tunable limit) +
smd and through-hole components +
solder mask, paste, assembly drawings +
board size up to 2x2 meter at nanometer precision +
arbitrary amount of routing styles +
Design Rule Checker +
native file format + lihata (structured text tree); support for loading and saving all old file versions +
board file formats + lihata (native), tEDAx board, KiCad's s-expr kicad_pcb, geda/PCB's .pcb, Eagle (binary and xml, read-only), Protel/Autotrax (read-only), Mentor Graphics Hyperlynx +
footprint formats + lihata (native), tEDAx footprint, KiCad s-expression modules, geda/PCB's .fp +
import formats + tEDAx netlist, gEDA/gaf sch, gEDA/gaf netlist, EasyEDA netlist, dsn, edif, ipcd356, HP-GL, tEDAx +
data model: layers + copper, silk, mask, paste, plated route/cut, unplated route/cut, arbitrary documentation/misc layers +
data model: padstacks + holes, slots, blind/buried vias, different shape on different layers (including non-copper layers), arbitrary polygon shape +
data model: footprint + any object and layer supported in footprint; rich metadata; option for run-time generated footprints +
data model: DRC + named networks, rats nest, deliberate netlist changes + back annotation, logical and geometric drc checks +
export formats + gerber, png, ps, svg, bom, xy, bboard, dsn, gcode, ipcd356, lpr, dxf, kicad old pcb format, tEDAx +
UI options + gtk2, lesstif (motif), batch (automated processing) +
configurable menus, keyboard and mouse actions +
footprint library + parametric footprints written in any programming language +
optionally per system, per user, per project libs +
footprints from local files +
footprints from the web (edakrill, gedasymbols.org) +
scripting + embedded scripting using fungw (awk, python, lua, tcl, ruby, perl, javascript, lisp, shell) +
layout helpers + basic autorouter, basic autoplace, place objects in aligned grid, + asymmetric pin shapes, back annotation tracking, + trace puller, teardrops +
understands internal connections in footprints +
query mini-language for finding and selecting objects by rules +
command line mode for 2d drafting +
misc + flexible configuration system +
support for small screen (800x600) +
strong support for automated processing +
modularity (most code implemented in plugins) +
slim code, reduced external dependency, portability +
+ + + Index: tags/2.1.2/doc/developer/Makefile =================================================================== --- tags/2.1.2/doc/developer/Makefile (nonexistent) +++ tags/2.1.2/doc/developer/Makefile (revision 24813) @@ -0,0 +1,27 @@ +ROOT=../.. +DEVDIR=$(DOCDIR)/developer + +all: + +install_all: + $(SCCBOX) mkdir -p $(DEVDIR)/alien_formats $(DEVDIR)/ddrc $(DEVDIR)/hid_remote $(DEVDIR)/mods3 + $(SCCBOX) $(HOW) alien_formats/*.txt $(DEVDIR)/alien_formats/ + $(SCCBOX) $(HOW) ddrc/*.txt $(DEVDIR)/ddrc/ + $(SCCBOX) $(HOW) hid_remote/*.html hid_remote/*.svg $(DEVDIR)/hid_remote/ + $(SCCBOX) $(HOW) mods3/*.html mods3/*.png $(DEVDIR)/mods3/ + +install: + $(MAKE) install_all HOW="install -f -d" + +linstall: + $(MAKE) install_all HOW="install -f -l -d" + +uninstall: + $(MAKE) install_all HOW="install -u" + +clean: + +distclean: + + +include $(ROOT)/Makefile.conf Index: tags/2.1.2/doc/developer/action_doc.txt =================================================================== --- tags/2.1.2/doc/developer/action_doc.txt (nonexistent) +++ tags/2.1.2/doc/developer/action_doc.txt (revision 24813) @@ -0,0 +1,38 @@ +How to document actions +~~~~~~~~~~~~~~~~~~~~~~~ + +Detailed action doc lives in trunk/doc/user/09_appendix/action_src in +almost-html files. There is no html header and the standard tags in use +are restricted to: b, i, p, pre, ul, li, table, tr, td. + +There are a few extra, non-standard tags: + +- argname names an argument of the current action +- actname links to another action; actname is all lowercase + +The name of the file should be actname.html. + +Documentation policy: + + - do not document the trivial - do not write alibi docs. We do not want + action doc to just repeat the syntax description. Please explore + what the action does, all aspects, all use cases; see if the syntax + help string already covers everything and the action is trivial to use; + if so, the action does nto need any more documentation + + - after creating the html doc, please add a + /* DOC: actname.html */ + comment above the action function in the source code + + - the doc is high level in the sense that it should tell the basic ideas + behind the action, how to use it, what it is for + + - it should not tell much about what bigger scheme it fits in (that's + even higher level, plugin doc; but should cross link relevan sibling + actions) + + - it should not repeat low level info (e.g. enumerate possible arguments + from the syntax string) if no extra info is added + + - do not do custom styling, the doc format is unified + Index: tags/2.1.2/doc/developer/alien_formats/geda_pcb.txt =================================================================== --- tags/2.1.2/doc/developer/alien_formats/geda_pcb.txt (nonexistent) +++ tags/2.1.2/doc/developer/alien_formats/geda_pcb.txt (revision 24813) @@ -0,0 +1,45 @@ +Before pcb-rnd switched to lihata for native file format, we used to use +geda/pcb's format as native. Since pcb-rnd got a lot of new features and +since geda/pcb refused to cooperate, there are unfortunately some +non-intrusive local file format extensions to the geda/pcb format. + +These extensions are kept for backward compatibility: just in case a file +needs to be loaded that was produced with pre-lihata pcb-rnd. However, +new extensions are not added to the geda/pcb format. + +This file attempts to (vaguely) list the extensions. Unless otherwise +mentioned, geda/pcb will (often silently) ignore the extension and a +load-save with geda/pcb will remove the extended properties from the file +(while pcb-rnd still does proper round trips on them). + +1. .fp file: element tagging + + Any comment in an element file that starts with double # is taken + as a tag. The syntax is: ##key:value. A tag is basically the same + as an attribute, except tags are not becoming subcircuit attributes + after loading a footprint. Tags are used to ease footprint searches. + +2. .pcb and .fp file: pin shape + + Early in pcb-rnd development, years before padstacks, a minor feature + was added to allow 16 different asymmetric pin shapes. The pin shape + is saved as a flag. + +3. .pcb file: intconn + + Because elements couldn't have attributes, we abused the flag field for + storing intconn() info. + +4. .pcb file: netlist patch + + For back annotation pcb-rnd keeps track on deliberate netlist changes. + Since this feature happened before lihata got stable, it is also + saved in the old pcb format in a NetListPatch subtree. Unfortunately + pcb does NOT handle this and throws a syntax error. geda/pcb users are + required to remove this subtree manually. + +5. .pcb file: new setting: enablemincut + + Another of the first few new features in pcb-rnd was mincut for shorts. + This also happened years before lihata boards, so a new global + setting was registered, which may even be saved in a board file. Index: tags/2.1.2/doc/developer/alien_formats/hyp.txt =================================================================== --- tags/2.1.2/doc/developer/alien_formats/hyp.txt (nonexistent) +++ tags/2.1.2/doc/developer/alien_formats/hyp.txt (revision 24813) @@ -0,0 +1,630 @@ +A serias of mails sent by Koen to Igor2: + +-- + +The BOARD section comes after the header. The board section provides +enough information to draw the board outline. +The BOARD section corresponds to the pcb-rnd "outline" layer. The syntax +looks like this: + +{BOARD + (PERIMETER_SEGMENT X1=x1 Y1=y1 X2=x2 Y2=y2) + (PERIMETER_ARC X1=x1 Y1=y1 X2=x2 Y2=y2 XC=xc YC=yc R=r) +} + +PERIMETER_SEGMENT is a straight line from (x1, y1) to (x2, y2). +PERIMETER_ARC is a counterclockwise circle arc (x1, y1) to (x2, y2) with +center (xc, yc) and radius r. +x1, y1. x2, y2, xc, yc, and r are in the unit you chose in the UNITS +statement (cm or inch). +The example above shows only two, but a BOARD section typically has many +PERIMETER_SEGMENT and PERIMETER_ARC statements. + +Test the correct orientation for the arc: counterclockwise. +You can mix the PERIMETER_SEGMENT and PERIMETER_ARC any way you want. +The order does not matter. Just print one PERIMETER_SEGMENT or +PERIMETER_ARC per line. + + +-- + + +The STACKUP section defines all layers, both copper and dielectric. This +is an example of a two-sided board: + +{STACKUP + (SIGNAL T=0.003500 L="component") + (DIELECTRIC T=0.160000 L="dielectric layer 1") + (SIGNAL T=0.003500 L="solder") +} + +The above corresponds to 35um copper on 1.6mm FR4. + +Apart from SIGNAL and DIELECTRIC, there's a third type of copper layer, +PLANE, not shown here. The difference between SIGNAL and PLANE is that a +SIGNAL layer is empty by default, unless you draw something on it, while +a PLANE layer is full of copper by default. This can be used for power +and ground planes. + +The thickness T is in cm, as that is the UNIT you chose. + +The STACKUP is where you can define the properties of the material. Most +common are the bulk resistivity of the copper (BR=), or the dielectric +constant of the dielectric (ER=). + (SIGNAL T=0.000700 BR=resistivity L="component") + (DIELECTRIC T=0.002000 ER=epsilon L="dielectric layer 1") +If you don't say anything, the values default to copper on FR4, which is +what most people want. + +Look at the layer name. This is the first time we have to print a +string. +Hyperlynx will accept many strings without double quotes, but if the +string contains characters like } or ) you may have a problem. +To avoid these problems, always print a string between double quotes +(""). +eg. LAYER="Component" +If the string contains a double quote, print two double quotes. +e.g "This is a ""string"" with double quotes." + +Give all layers a name. If you don't choose a name, Hyperlynx will +choose a name for you, and it probably won't be what you want. + +-- + +A hyperlynx file looks something like this: +- header +- board outline +- stackup: definition of all layers of the board, both copper and +dielectric +- devices: parts list. +- padstack: definition of the shape of vias, pins and pads +- net: definition of all copper. A 'net' is connected copper. + - straight lines + - arcs + - polygons + - vias: references a padstack. + - pins and pads: each pin or pad references a padstack and a device. + + - unrouted segments +- footer + +I'd split this in different functions, so that the order can be changed +easily if you want to re-use the code for another export module. + +The difference between vias, pins and pads is: + - a via has a hole but is not associated with a device + - a pin has a hole and a device + - a pad does not have a hole, but has a device. + +The first piece of code is writing the header and the footer. + +The header looks like this: + +* test.hyp exported by pcb-rnd 1.2.3 on 01.01.1999 12:45 +{VERSION=2.0} +{DATA_MODE=DETAILED} +{UNITS=METRIC LENGTH} + +A line that begins with "*" is a comment. + +This says you are using centimeters for coordinates and for layer +thickness. +If you would prefer to export coordinates in inches, and layer thickness +in ounces per square foot, you could use: +{UNITS=ENGLISH WEIGHT} +Your choice. + +and the footer is: + +{END} + +If you want to, tomorrow I'll send the info for the board outline. If +there are any questions, just ask. + +-- + +After the STACKUP section, there's the DEVICES section. The DEVICES +section is the parts list of the board. + +{DEVICES + (? REF="U1" NAME="BC548" L="Top") + (? REF="R2" NAME="1K2" L="Top") + ... +} + +This is where we say which side of the board the component is soldered +on. The exact coordinates of the component are specified later, when we +handle the PINs and PADs. + +The L=layer is the layer the component is soldered on. Use the same +layer name as in the STACKUP section. + +A board needs at least one component, else there are no pins or pads to +connect the simulation to. + +-- + +A PADSTACK section describes the pads of a pin, via or pad. +You describe the pads of a via, pin or pad once, and refer to it +multiple times when creating vias, pins or pads. + +A padstack looks like this: + +{PADSTACK=name, + (layer, shape, x-size, y-size, angle, type) + ... more layers +} + +where shape is 0 for circle/ellipse, 1 for square/rectangle, 2 for +oblong. angle is the rotation in degrees, counterclockwise. + +The "type" parameter is M, A, T. +M Metal: ordinary copper pad, +A Antipad: hole around the pad on PLANE layers, +T Thermal: thermal relief. + +Thermal relief is when a pin connects to a ground plane with short, +stubby tracks, like spokes on a wheel. This makes the pin easier to +solder. If you simply connect the pin to a solid copper polygon it is +difficult to solder, because the direct connection to a big copper +surface copper cools the pin too much. +You don't have to specify the type parameter, but it doesn't hurt. + +An example: + +{PADSTACK="pad1" + ("Top", 1, 0.5, 0.5, 0, M) +} + +The padstack called "pad1" consists of a single pad on the "Top" layer, +0.5 cm square. + +If the padstack describes a pin or via, you have to specify the diameter +of the drill hole: + +{PADSTACK=name, diameter + (layer, shape, x-size, y-size, angle, type) + ... more layers +} + +{PADSTACK="stack2", 0.2 + ("Top", 0, 0.5, 0.5, 0, M) + ("Bottom", 0, 0.5, 0.5, 0, M) +} + +There are two special layer names: MDEF and ADEF. +If the layer is MDEF (without quotes) this means: size of metal pad on +all SIGNAL layers. +ADEF (without quotes) means size of the hole in the copper on all PLANE +layers. +Using MDEF and ADEF you can define a padstack for a via or pin which +will always work, even if layers are added, removed or changed in name. +Example: + +{PADSTACK="pin1", 0.2 + (MDEF, 0, 0.5, 0.5, 0, M) + (ADEF, 0, 0.5, 0.5, 0, A) +} + +For completeness: You could define thermal relief around a pad. + + (layer, shape copper, x-size copper, y-size copper, angle copper, +shape thermal relief, x-size thermal relief, y-size thermal relief, +angle thermal relief, T) +So a single layer may appear up to three times in the same PADSTACK: +once for each type (M - metal, A - antipad, T - thermal) + +The two padstacks to remember when exporting are the "pad1" and "pin1" +examples. + +A hyperlynx file contains multiple PADSTACK sections, one per padstack. + +When exporting, you have to loop over all vias, pins and pads of the +board twice: once when creating the padstacks, and once when creating +the vias, pins and pads. + +-- + +The NET section specifies a network of connected copper. A NET is not +limited to a single layer, but may be on multiple layers. + +The NET section contains subsections: + - SEG and ARC to draw line segments and circle arcs + - PIN to draw component pads and pins + - VIA for vias + - POLYGON and POLYVOID to draw polygons with holes + - POLYLINE to draw a sequence of line segments and circle arcs + - USEG to draw unrouted segments + +Each net has a name, e.g. "VCC","CLK", "GND". + +{NET="I2C_SCL" + (SEG X1=6.500000 Y1=3.000000 X2=6.625000 Y2=3.000000 +W=0.008333 L="Top") + ... other SEG, ARC, PIN, VIA, POLYGON, POLYVOID, POLYLINE, USEG +records ... +} + +A hyperlynx file contains multiple NET sections, one per network. + +Next: the subsections of the NET section. + +-- + +Often a copper trace is a sequence of straight lines and arcs, all of +the same width. + +If you have a sequence of line segments and arcs, all of the same net, +all on the same layer, all of the same width, you can draw the whole +trace as a POLYLINE: + + +{NET=name + {POLYLINE L=layer W=width ID=integer_id X=x0 Y=y0 + (LINE X=x1 Y=y1) + (CURVE X1=x2 Y1=y2 X2=x3 Y2=y3 XC=xc YC=yc R=r) + (LINE X=x4 Y=y4) + ... + } +... +} + +integer_id is a number, which is different for each polyline (and +polygon). +For integer_id, just initialize a number to 0, and increase it id++ +every time you draw a polyline or polygon. + +How is the POLYLINE above drawn? + +First a line from (x0, y0) to (x1, y1) on layer "layer" and width w is +drawn. +Then an arc counterclockwise from (x2, y2) to (x3, y3) with center (xc, +yc) and radius r is drawn. +Where the next LINE begins depends on where the CURVE ends. +The CURVE begins where the previous segment ends. +If (x1, y1) is the same as (x2, y2) the CURVE ends at (x3, y3) and a +line from (x3, y3) to (x4, y4) is drawn. +If (x1, y1) is the same as (x3, y3) the CURVE ends at (x2, y2) and a +line from (x2, y2) to (x4, y4) is drawn. + +An example: + +{NET="VCC" + {POLYLINE L="component" W=0.1 ID=1 X=6.000000 Y=5.000000 + (LINE X=8.000000 Y=5.000000) + (CURVE X1=8.000000 Y1=5.000000 X2=8.000000 Y2=5.500000 +XC=8.000000 YC=5.250000 R=0.250000) + (LINE X=6.000000 Y=5.500000) + ... + } +... +} + +You can have as many LINE and CURVE substatements as you like, and in +any order. + +-- + +A trace can be defined, not by its shape, but by its delay, +characteristic impedance and resistance. This is the unrouted segment +USEG. + +{NET=net_name + (USEG X1=x1 Y1=y1 L1=layer1 X2=x2 Y2=y2 L2=layer2 +Z=characteristic_impedance D=delay R=resistance ) + =85 +} + +This unrouted segment begins on one layer L1= and end on another L2= +. + +Another way of defining a trace is by giving width, length and layer. +The delay and characteristic impedance can be calculated from trace +width, trace length and the thickness and epsilon of the dielectric +above and below the trace. + + (USEG X1=x1 Y1=y1 L1=layer1 X2=x2 Y2=y2 L2=layer2 +ZL=trace_layer ZW=trace_width ZLEN=trace_length) + +This unrouted segment is a transmission line which begins on one layer +L1= and end on another L2= . The microstrip itself is drawn on layer +ZL=. + +This way you can simulate a trace as a lossy transmission line. +[ Note: When simulating power supply and ground planes, which are mostly +copper, the simulation model is not a transmission line but its +two-dimensional equivalent, the transmission plane. ] + +-- + +The difference between a PIN and a VIA is that a PIN belongs to a +device. + + (VIA X=x0 Y=y0 P=padstack0) + +puts a via at coordinates (x0, y0) according to padstack "padstack0". +The shape of the pads, whether the via is a through-hole via, a blind or +a buried via, is all defined in the padstack. + +Example: + + (VIA X=11.750000 Y=5.250000 P="0802pad") + +A pin + + (PIN X=x0 Y=y0 R=ref P=padstack0) + +puts a pin or pad at coordinates (x0, y0) according to padstack +"padstack0". +The reference is of the format "device_name.pin_name". This requires +that "device_name" has been defined in the "DEVICES" section. + +Example: + + (PIN X=15 Y=1 R="U1.2" P="smd04") + +Here U1.1 is pin "2" of device "U1". To avoid problems, it is better if +device and pin names do not contain the "." character. + +The shape of the pads, whether the pin is smd or through hole is defined +in the padstack. + +The simulation connects signal sources to the board at PINs, and +measures voltages at PINs. + +-- + +When all else fails, you can always represent copper as a POLYGON. + +The POLYGON syntax is very similar to the POLYLINE syntax. Just change +POLYLINE into POLYGON. + +{NET=name + {POLYGON L=layer T=POUR W=width ID=integer_id X=x0 Y=y0 + (LINE X=x1 Y=y1) + (CURVE X1=x2 Y1=y2 X2=x3 Y2=y3 XC=xc YC=yc R=r) + (LINE X=x4 Y=y4) + ... + (LINE X=xn Y=yn) + } +... +} + +The difference is that a POLYGON is closed. A POLYLINE ends at the last +point (xn, yn). +A POLYGON draws a line from the last point (xn, yn) back to (x0, y0). + +The T=POUR parameter says the inside of the polygon is filled with +copper. + +A Hyperlynx polygon has an outline of straight line segments and circle +arcs. +The W=width parameter gives the line width of the outline. You can +make a polygon bigger this way. + +In the often occurring case of a polygon of only line segments, and zero +border width, we get: + +{NET=name +... + {POLYGON L=layer T=POUR W=0.0 ID=integer_id X=x0 Y=y0 + (LINE X=x1 Y=y1) + ... + (LINE X=xn Y=yn) + } +... +} + +Example: + +{NET="VCC" + {POLYGON L="TOP" W=0.0 ID=1 X=9.000000 Y=6.500000 + (LINE X=10.000000 Y=6.500000) + (LINE X=10.000000 Y=7.000000) + (LINE X=9.500000 Y=7.000000) + (LINE X=9.500000 Y=7.500000) + (LINE X=9.000000 Y=7.500000) + (LINE X=9.000000 Y=6.500000) + } +} + +Do not forget that all polygons and polylines should have a different +ID= value. + +-- + +A POLYVOID is a hole in a POLYGON. The hole itself is shaped like a +polygon, too. The shape of the hole is a sequence of straight lines and +circle arcs: + +{NET=name +... + {POLYVOID ID=integer_id X=x0 Y=y0 + (LINE X=x1 Y=y1) + (CURVE X1=x2 Y1=y2 X2=x3 Y2=y3 XC=xc YC=yc R=r) + (LINE X=x4 Y=y4) + ... + (LINE X=xn Y=yn) + } +... +} + +The ID= value of the POLYVOID hole is the same as the ID= value of +the POLYGON you want to make a hole in. +You do not have to specify the layer of the hole, because the hole is on +the same layer as the polygon you make a hole in. + +Example: + +{NET="Ground" + {POLYGON L="component" T=POUR W=0.0 ID=3 X=9.000000 +Y=6.500000 + (LINE X=10.000000 Y=6.500000) + (LINE X=10.000000 Y=7.000000) + (LINE X=9.500000 Y=7.000000) + (LINE X=9.500000 Y=7.500000) + (LINE X=9.000000 Y=7.500000) + (LINE X=9.000000 Y=6.500000) + } + {POLYVOID ID=3 X=9.125000 Y=6.625000 + (LINE X=9.625000 Y=6.625000) + (LINE X=9.625000 Y=6.875000) + (LINE X=9.375000 Y=6.875000) + (LINE X=9.375000 Y=7.125000) + (LINE X=9.125000 Y=7.125000) + (LINE X=9.125000 Y=6.625000) + } +} + +A polygon can have several holes. Just write several POLYVOID sections. +In practice, if you only export polygons consisting of straight lines of +zero width, you get the following: + +{NET=name +... + {POLYGON L=layer T=POUR W=0.0 ID=integer_id X=x0 Y=y0 + (LINE X=x1 Y=y1) + ... + } + {POLYVOID ID=integer_id X=x0 Y=y0 + (LINE X=x1 Y=y1) + ... + } + {POLYVOID ID=integer_id X=x0 Y=y0 + (LINE X=x1 Y=y1) + ... + } +... +} + +Where integer_id is the same for the POLYGON and its POLYVOIDs. + +Don't forget to end your exported file with {END} + +This ends the Hyperlynx exporting HOWTO. + +-- + +Result (sent by Igor2 to Koen): + +> The STACKUP section defines all layers, both copper and dielectric. This is an example of a two-sided board: +> +> {STACKUP +> (SIGNAL T=0.003500 L="component") +> (DIELECTRIC T=0.160000 L="dielectric layer 1") +> (SIGNAL T=0.003500 L="solder") +> } +> +> The above corresponds to 35um copper on 1.6mm FR4. + +Deviation: we don't yet store metadata like layer thickness. We are very +close to have it, but still don't have it, so I just hardwired these +default values for now. + +> Look at the layer name. This is the first time we have to print a string. +> Hyperlynx will accept many strings without double quotes, but if the string contains characters like } or ) you may have a problem. +> To avoid these problems, always print a string between double quotes (""). +> eg. LAYER="Component" + +Because of io_kicad, pcb_printf() supports %mq, which gets a list of +characters that need quoting and a string and can decide whether quoting +is needed or not. So instead of quoting everything, I just configured this +to what seemed reasonable and we quote only what needs to be quoted. + +The list of characters that need quoting is specified only once; if we +figure there's a character left out, it's trivial to add. + +-- + +> A PADSTACK section describes the pads of a pin, via or pad. +> You describe the pads of a via, pin or pad once, and refer to it multiple times when creating vias, pins or pads. +> +> A padstack looks like this: +> +> {PADSTACK=name, +> (layer, shape, x-size, y-size, angle, type) +> ... more layers +> } + +For this I had to write a pad stack hash - in pcb-rnd we don't have +central lib/list of geometry, each via and pin specifies its own. This pad +stack hash is a hyp-independent lib, I'll move it into a separate plugin +this week. + + +> +> where shape is 0 for circle/ellipse, 1 for square/rectangle, 2 for oblong. angle is the rotation in degrees, counterclockwise. + +This is on my TODO; we have more shapes, some are asymmetrical, will have +to figure this. + +> There are two special layer names: MDEF and ADEF. +> If the layer is MDEF (without quotes) this means: size of metal pad on all SIGNAL layers. +> ADEF (without quotes) means size of the hole in the copper on all PLANE layers. +> Using MDEF and ADEF you can define a padstack for a via or pin which will always work, even if layers are added, removed or changed in name. Example: +> +> {PADSTACK="pin1", 0.2 +> (MDEF, 0, 0.5, 0.5, 0, M) +> (ADEF, 0, 0.5, 0.5, 0, A) +> } + +Diversion: at the moment pcb-rnd doesn't support anything else for +pins/vias just "same copper ring on all layers", so I used MDEF here. + +-- + +> Apart from SIGNAL and DIELECTRIC, there's a third type of copper layer, PLANE, not shown here. The difference between SIGNAL and PLANE is that a SIGNAL layer is empty by default, unless you draw something on it, while a PLANE layer is full of copper by default. This can be used for power and ground planes. + +Diversion: pcb-rnd doesn't support negative drawn copper, so I used SIGNAL +and DIELECTRIC only. + +-- + +> Often a copper trace is a sequence of straight lines and arcs, all of the same width. +> +> If you have a sequence of line segments and arcs, all of the same net, all on the same layer, all of the same width, you can draw the whole trace as a POLYLINE: +> +> +> {NET=name +> {POLYLINE L=layer W=width ID=integer_id X=x0 Y=y0 +> (LINE X=x1 Y=y1) +> (CURVE X1=x2 Y1=y2 X2=x3 Y2=y3 XC=xc YC=yc R=r) +> (LINE X=x4 Y=y4) +> ... +> } + +It's good to know; however pcb-rnd doesn't have polylines of any sort, so +we are not using this feature. + +-- + +> +> A trace can be defined, not by its shape, but by its delay, characteristic impedance and resistance. This is the unrouted segment USEG. +> +> {NET=net_name +> (USEG X1=x1 Y1=y1 L1=layer1 X2=x2 Y2=y2 L2=layer2 Z=characteristic_impedance D=delay R=resistance ) +> ? +> } +> +> This unrouted segment begins on one layer L1= and end on another L2= . + +Question: is USEG the same as rat lines in pcb-rnd? Indication of a +logical connection that is derived from the netlist but is not (yet) +realized in copper? + +-- + +The netlist feature now works. + +We're getting there. I've run some tests, and there are some +conclusions: + +- all internal layers are called "Intern" instead of the real layer +names. This is a problem, because no two layer names may be the same. +- the board is upside down + +The easiest way to check is by importing the +io_hyp/tests/test00/test00.hyp file, exporting it as hyperlynx, and +importing again. + +-- Index: tags/2.1.2/doc/developer/alien_formats/io_kicad/hatch.tar.gz =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/developer/alien_formats/io_kicad/hatch.tar.gz =================================================================== --- tags/2.1.2/doc/developer/alien_formats/io_kicad/hatch.tar.gz (nonexistent) +++ tags/2.1.2/doc/developer/alien_formats/io_kicad/hatch.tar.gz (revision 24813) Property changes on: tags/2.1.2/doc/developer/alien_formats/io_kicad/hatch.tar.gz ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/developer/alien_formats/io_kicad/hatch.txt =================================================================== --- tags/2.1.2/doc/developer/alien_formats/io_kicad/hatch.txt (nonexistent) +++ tags/2.1.2/doc/developer/alien_formats/io_kicad/hatch.txt (revision 24813) @@ -0,0 +1,30 @@ +CUCP#44 file format zone/fill: create a hatched zone on one board, plain + old polygon on another and filled_polygon on a third + +Igor2: (question) +> I see no difference in the gerber render, not sure if it's yet another +> gerbv bug or really what kicad exported. Did you see any difference on the +> on-screen rendering? +> +> If so, please make screenshots! +> +> If not, we'll need to make some more research to figure what this setting +> is for. + +Karl Hammar: (answer) + +The setting seems to be just about visual on screen appearance. + +If the hatch lines are short, just inside the border, +no hatch lines at all, or if the hatch lines fill the zone. + +Also, in kicad the zones arn't filled automatically as in pcb/pcb-rnd, +you have to manually request it. + +So you right click on the zone border, a menu appears, choose zones, and +there you can Fill zone, Remove filled areas in zone etc. + +This two stage approach is probably a performance optimization, make +the zone, draw your tracks etc., then fill the zone. Polygons can be slow. +And the hatch thing is how the zone is presented when it isn't filled. + Index: tags/2.1.2/doc/developer/alien_formats/io_kicad/margin.tar.gz =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/developer/alien_formats/io_kicad/margin.tar.gz =================================================================== --- tags/2.1.2/doc/developer/alien_formats/io_kicad/margin.tar.gz (nonexistent) +++ tags/2.1.2/doc/developer/alien_formats/io_kicad/margin.tar.gz (revision 24813) Property changes on: tags/2.1.2/doc/developer/alien_formats/io_kicad/margin.tar.gz ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/developer/alien_formats/io_kicad/margin.txt =================================================================== --- tags/2.1.2/doc/developer/alien_formats/io_kicad/margin.txt (nonexistent) +++ tags/2.1.2/doc/developer/alien_formats/io_kicad/margin.txt (revision 24813) @@ -0,0 +1,24 @@ +CUCP#50 kicad5: figure what the Margin layer is used for; provide minimalistic + kicad_pcb+gerber examples accordingly. + +#50 margin layer: (answer by Karl Hammar) + + kicad-doc/build_5.1.0/src/pcbnew/en/pcbnew.pdf p. 40/140: + + 5.3.3 Independant Technical Layers + + Edge.Cuts + This layer is reserved for the drawing of circuit board + outline. Any element (graphic, texts. . . ) placed on this layer + appears on all the other layers. Use this layer only to draw board + outlines. + + Margin + Board's edge setback outline (?). + +So the kicad folks doesn't know to explain it. + +You can draw tracks outside the Margin, but not outside the Edge.Cuts. +You can place components outside the Edge.Cuts. + +So I guess it is for the designers own information only. Index: tags/2.1.2/doc/developer/alien_formats/io_kicad/segment_status.tar.gz =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/developer/alien_formats/io_kicad/segment_status.tar.gz =================================================================== --- tags/2.1.2/doc/developer/alien_formats/io_kicad/segment_status.tar.gz (nonexistent) +++ tags/2.1.2/doc/developer/alien_formats/io_kicad/segment_status.tar.gz (revision 24813) Property changes on: tags/2.1.2/doc/developer/alien_formats/io_kicad/segment_status.tar.gz ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/developer/alien_formats/io_kicad/segment_status.txt =================================================================== --- tags/2.1.2/doc/developer/alien_formats/io_kicad/segment_status.txt (nonexistent) +++ tags/2.1.2/doc/developer/alien_formats/io_kicad/segment_status.txt (revision 24813) @@ -0,0 +1,306 @@ +CUCP#40, file format details: segment/status - by Karl Hammar + +(regarding svn diff -r24438:24439 src_plugins/io_kicad/read.c) + +I believe the status values are hexadecimal and are bitmaps as defined +in kicad/include/base_struct.h line 105..142 and used or'ed to set +STATUS_FLAGS in line 178. + +Only values: + 40000 TRACK_LOCKED + 400000 BEGIN_ONPAD + 800000 END_ONPAD +seems to be of importance. + +For details, see the chaos below. + +//////////////////////// + +I found out that I can lock the segment: +right clicking a segment/track (in kicad) gives a popup menu with an +entry "set flags"-> submenu, with lock track, lock net. I managed to +lock the track and the diff is: + +$ diff cucp/Karl/kicad_4.0.7/40_normal.kicad_pcb cucp/Karl/kicad_4.0.7/40_track_locked.kicad_pcb +109c109 +< (segment (start 104 105) (end 116 105) (width 0.25) (layer F.Cu) (net 0)) +--- +> (segment (start 104 105) (end 116 105) (width 0.25) (layer F.Cu) (net 0) (status 40000)) + + +/// + +To find out about the use I did: + +locate kicad_pcb | grep 'kicad_pcb$' | while read a; do echo "$a:"; grep status "$a"; done > ~/data + +grep -v segment data | sed -e 's/via.*status/via ... \(status/' |uniq -c + 28 (via ... (status 30)) + +## 28 = 2*14 which is installed 5.1.0 matches + matches from git repo., i.e. via/status is new for v5 + +grep segment data | sed -e 's/segment.*status/segment ... \(status/' | sort | uniq -c + 523 (segment ... (status 10)) + 1 (segment ... (status 1000000)) + 24 (segment ... (status 2)) + 633 (segment ... (status 20)) + 196 (segment ... (status 30)) + 3638 (segment ... (status 400)) + 30 (segment ... (status 400000)) + 2 (segment ... (status 400810)) + 21 (segment ... (status 402)) + 2625 (segment ... (status 420)) + 587 (segment ... (status 430)) + 5542 (segment ... (status 800)) + 28 (segment ... (status 800000)) + 4 (segment ... (status 800020)) + 6 (segment ... (status 800420)) + 27 (segment ... (status 802)) + 3894 (segment ... (status 810)) + 2 (segment ... (status 820)) + 494 (segment ... (status 830)) + 2075 (segment ... (status C00)) + 14 (segment ... (status C00000)) + 2 (segment ... (status C00030)) + 27 (segment ... (status C02)) + 10 (segment ... (status C10)) + 8 (segment ... (status C20)) + 1353 (segment ... (status C30)) + +I.e. teese are the values used: + + 2 + 10 + 20 + 30 + 400 + 402 + 420 + 430 + 800 + 802 + 810 + 820 + 830 + C00 + C02 + C10 + C20 + C30 + 400000 + 400810 + 800000 + 800020 + 800420 + C00000 + C00030 + 1000000 + +and they are probably hexadecimal (since the C). + +/// Looking at what kicad installs, v4.0.0, v4.0.1, v4.0.7 +(Versions v4.0.0, v4.0.1, v4.0.7 all gives the same numbers.) + +find /usr/local/kicad_4.0.7/ -type f -name \*.kicad_pcb -print0 | +xargs -0 grep status | +cut -f2- -d: | +sed -e 's/segment.*status/segment ... \(status/' | +sed -e 's/via.*status/via ... \(status/' | +sort | +uniq -c + 49 (segment ... (status 10)) + 8 (segment ... (status 2)) + 28 (segment ... (status 20)) + 8 (segment ... (status 30)) + 1047 (segment ... (status 400)) + 7 (segment ... (status 402)) + 343 (segment ... (status 420)) + 53 (segment ... (status 430)) + 1646 (segment ... (status 800)) + 9 (segment ... (status 802)) + 362 (segment ... (status 810)) + 70 (segment ... (status 830)) + 645 (segment ... (status C00)) + 9 (segment ... (status C02)) + 47 (segment ... (status C30)) + +/// Looking at what kicad installs, v5.1.0: + +find /usr/local/kicad_5.1.0/ -type f -name \*.kicad_pcb -print0 | +xargs -0 grep status | +cut -f2- -d: | +sed -e 's/segment.*status/segment ... \(status/' | +sed -e 's/via.*status/via ... \(status/' | +sort | +uniq -c + 148 (segment ... (status 10)) + 246 (segment ... (status 20)) + 62 (segment ... (status 30)) + 219 (segment ... (status 400)) + 11 (segment ... (status 400000)) + 1 (segment ... (status 400810)) + 798 (segment ... (status 420)) + 214 (segment ... (status 430)) + 264 (segment ... (status 800)) + 11 (segment ... (status 800000)) + 2 (segment ... (status 800020)) + 3 (segment ... (status 800420)) + 1404 (segment ... (status 810)) + 1 (segment ... (status 820)) + 142 (segment ... (status 830)) + 63 (segment ... (status C00)) + 6 (segment ... (status C00000)) + 1 (segment ... (status C00030)) + 5 (segment ... (status C10)) + 4 (segment ... (status C20)) + 606 (segment ... (status C30)) + 14 (via ... (status 30)) + +/// + +In kicad git file kicad/include/base_struct.h: +============================== +// These define are used for the .m_Flags and .m_UndoRedoStatus member of the +// class EDA_ITEM +// +// NB: DO NOT ADD FLAGS ANYWHERE BUT AT THE END: THE FLAG-SET IS STORED AS AN INTEGER IN FILES. +// +#define IS_CHANGED (1 << 0) ///< Item was edited, and modified +#define IS_LINKED (1 << 1) ///< Used in calculation to mark linked items (temporary use) +#define IN_EDIT (1 << 2) ///< Item currently edited +#define IS_MOVED (1 << 3) ///< Item being moved +#define IS_NEW (1 << 4) ///< New item, just created +#define IS_RESIZED (1 << 5) ///< Item being resized +#define IS_DRAGGED (1 << 6) ///< Item being dragged +#define IS_DELETED (1 << 7) +#define IS_WIRE_IMAGE (1 << 8) ///< Item to be drawn as wireframe while editing +#define STARTPOINT (1 << 9) +#define ENDPOINT (1 << 10) +#define SELECTED (1 << 11) +#define SELECTEDNODE (1 << 12) ///< flag indicating that the structure has already selected +#define STRUCT_DELETED (1 << 13) ///< flag indication structures to be erased +#define CANDIDATE (1 << 14) ///< flag indicating that the structure is connected +#define SKIP_STRUCT (1 << 15) ///< flag indicating that the structure should be ignored +#define DO_NOT_DRAW (1 << 16) ///< Used to disable draw function +#define IS_CANCELLED (1 << 17) ///< flag set when edit dialogs are canceled when editing a + ///< new object +#define TRACK_LOCKED (1 << 18) ///< Pcbnew: track locked: protected from global deletion +#define TRACK_AR (1 << 19) ///< Pcbnew: autorouted track +#define FLAG1 (1 << 20) ///< Pcbnew: flag used in local computations +#define FLAG0 (1 << 21) ///< Pcbnew: flag used in local computations +#define BEGIN_ONPAD (1 << 22) ///< Pcbnew: flag set for track segment starting on a pad +#define END_ONPAD (1 << 23) ///< Pcbnew: flag set for track segment ending on a pad +#define BUSY (1 << 24) ///< Pcbnew: flag indicating that the structure has + ///< already been edited, in some functions +#define HIGHLIGHTED (1 << 25) ///< item is drawn in normal colors, when the rest is darkened +#define BRIGHTENED (1 << 26) ///< item is drawn with a bright contour + +#define DP_COUPLED (1 << 27) ///< item is coupled with another item making a differential pair + ///< (applies to segments only) +#define UR_TRANSIENT (1 << 28) ///< indicates the item is owned by the undo/redo stack + + +#define EDA_ITEM_ALL_FLAGS -1 + +typedef unsigned STATUS_FLAGS; + +/** + * Class EDA_ITEM + * is a base class for most all the KiCad significant classes, used in + * schematics and boards. + */ +class EDA_ITEM : public KIGFX::VIEW_ITEM +{ +... +protected: +... + /// Flag bits for editing and other uses. + STATUS_FLAGS m_Flags; + +... +============================== + +in cucp/Karl/kicad_4.0.7/40_track_locked.kicad_pcb we have a (status 40000), +and 0x40000 = 1<<18 which is the define for TRACK_LOCKED above. + +If the status value are bitmaps (flags), theese are the flags used, their bit +position, the define according to the .h file, and the produced file +verifying this: + + 2 1 IS_LINKED + 10 4 IS_NEW + 20 5 IS_RESIZED + 400 10 ENDPOINT + 800 11 SELECTED + 40000 18 TRACK_LOCKED 40_track_locked.kicad_pcb + 400000 22 BEGIN_ONPAD 40_22.kicad_pcb + 800000 23 END_ONPAD 40_22.kicad_pcb +1000000 24 BUSY + +currently don't know how to verify the others. + +/// + +In installed dir. /usr/local/kicad_4.0.7/share/kicad/demos/ecc83/ + +fgrep "(status 400)" ecc83-pp.kicad_pcb + (segment (start 142.875 100.965) (end 138.43 100.965) (width 0.8636) (layer Cuivre) (net 2) (status 400)) + (segment (start 159.385 117.475) (end 164.465 117.475) (width 0.8636) (layer Cuivre) (net 5) (status 400)) + (segment (start 149.86 128.905) (end 150.495 129.54) (width 0.8636) (layer Cuivre) (net 6) (status 400)) + (segment (start 151.54148 107.7722) (end 152.6794 108.91012) (width 0.8636) (layer Cuivre) (net 6) (status 400)) + (segment (start 145.7706 129.1844) (end 145.415 129.54) (width 0.8636) (layer Cuivre) (net 7) (status 400)) + (segment (start 154.94 120.68048) (end 152.6794 118.41988) (width 0.8636) (layer Cuivre) (net 8) (status 400)) + +cp ecc83-pp.kicad_pcb zz.kicad_pcb + +In zz remove the (net 2) (status 400) segment, and redraw it, and +save. Then the status flag is changed to 10. + +In zz, Edit->Cleanup tracks and Vias, then save: + +fgrep "(status 4" zz.kicad_pcb + (segment (start 159.385 117.475) (end 164.465 117.475) (width 0.8636) (layer Cuivre) (net 5) (status 420)) + (segment (start 149.86 128.905) (end 150.495 129.54) (width 0.8636) (layer Cuivre) (net 6) (status 430)) + (segment (start 151.54148 107.7722) (end 152.6794 108.91012) (width 0.8636) (layer Cuivre) (net 6) (status 420)) + (segment (start 145.7706 129.1844) (end 145.415 129.54) (width 0.8636) (layer Cuivre) (net 7) (status 430)) + (segment (start 154.94 120.68048) (end 152.6794 118.41988) (width 0.8636) (layer Cuivre) (net 8) (status 420)) + +I.e. they got flags IS_RESIZED and IS_NEW. + + +Another try: + +grep segment ecc83-pp.kicad_pcb | grep status | sed -e 's/segment.*status/segment ... \(status/' | sort | uniq -c + 6 (segment ... (status 400)) + 15 (segment ... (status 800)) + 1 (segment ... (status C00)) + +# remove all status things from segments +cat ecc83-pp.kicad_pcb | sed -e 's/ (status .*)/)/' > zz.kicad_pcb + +now make gerbers of the Cuivre layer (the only cu layer with tracks) +for both files and find the diff: + +diff ecc83-pp-Cuivre.gbr zz-Cuivre.gbr +2,3c2,3 +< %TF.CreationDate,2019-04-11T20:03:57+02:00*% +< %TF.ProjectId,ecc83-pp,65636338332D70702E6B696361645F70,rev?*% +--- +> %TF.CreationDate,2019-04-11T20:03:27+02:00*% +> %TF.ProjectId,zz,7A7A2E6B696361645F70636200000000,rev?*% +7c7 +< G04 Created by KiCad (PCBNEW 4.0.7) date Thu Apr 11 20:03:57 2019* +--- +> G04 Created by KiCad (PCBNEW 4.0.7) date Thu Apr 11 20:03:27 2019* + +I.e. I think we can ignore flags <= 800. + + +I can only find one (1) file with (status 1000000): +/Net/git/kicad/demos/complex_hierarchy/complex_hierarchy.kicad_pcb +open complex_hierarchy.kicad_pcb and Save As zz.kicad_pcb gets me a +file that only differ in the use of ". +Selecting and unselecting that specific segment, then save as, removes +the status. + +I.e. I think we can ignore flags == 1000000. Index: tags/2.1.2/doc/developer/bisect.txt =================================================================== --- tags/2.1.2/doc/developer/bisect.txt (nonexistent) +++ tags/2.1.2/doc/developer/bisect.txt (revision 24813) @@ -0,0 +1,62 @@ +How to bisect +~~~~~~~~~~~~~ + +Because of the svn externs in src_3rd, it's not trivial to do bisecting +manually. There is a script to automate the process. + +Realizing disk space is cheap but developer time is expensive, the script +not just automates the checkout and compilation of specific revisions, it +also saves the resulting executable in a cache so that it can be reused +easily without a new checkout/compilation. + + +1. requirements + +Install the usual tools required for building pcb-rnd, plus gawk, xz, +subversion. + + +2. setup + +cd trunk/util/bisecter +cp bisecter.conf.in bisecter.conf + +edit bisecter.conf as needed (you might want to change the cache path) + +3. recommended process + +Open two shells, cd to trunk/util/bisecter on both. + +In the first shell, run './bisecter bisect' - this will run and +interactive script that makes suggestions on which revisions should +be tested. + +In the second shell, type './bisecter run rev args' where rev is the +revision the script in the first shell suggested, args are arguments +you'd pass to pcb-rnd. It will check out, compile and run pcb-rnd in +trunk/util/bisecter. Reproduce the bug and decide if the given revision +is broken or not. + +If it is not broken, type "good" in the first shell and press enter; +if it is broken, type "bad" in the first shell and press enter. The +script in the first shell will make a new suggestion. + +Repeat the process until the script in the first shell prints the results +and exits. + + +4. Tips and tricks + +You do not have to accept the suggested revision, you can pick the revision +you test. In that case instead of a plain "good" or "bad", type "rev good" +or "rev bad", e.g. "8663 good" or "8110 bad". + +List the executables available in your cache dir. Especially early in the +bisecting process, rather find an existing cached rev to test instead of +a new one - this will speed up the process. You can use "./bisecter near rev" +to find cached revisions near rev. + +Not all revisions can be compiled - there are a few that are broken. When +you find a broken one, try the previous or next revision until you find +one that works. + Index: tags/2.1.2/doc/developer/blog_queue.txt =================================================================== --- tags/2.1.2/doc/developer/blog_queue.txt (nonexistent) +++ tags/2.1.2/doc/developer/blog_queue.txt (revision 24813) @@ -0,0 +1,17 @@ +Ready to blog: +- subcircuit support for outline aka edge cut layers, i.e. mousebites, outlines; also slots in padstacks! +- easyeda import + +less urgent, almost finished: +- braille font +- unicode bdf bitmap dot matrix glyph insertion +- eeschema import (needs testing?) +- up vs down swipe selection blog writeup + +pre-planned/TO-DO: +- CJK glyph insertion dialogue +- FidoCadJ font creation plugin +- pcb-rnd -> MUCS export module based on existing C++ helper app +- metafont glyph -> stroked font converter + + Index: tags/2.1.2/doc/developer/bridges/index.html =================================================================== --- tags/2.1.2/doc/developer/bridges/index.html (nonexistent) +++ tags/2.1.2/doc/developer/bridges/index.html (revision 24813) @@ -0,0 +1,11 @@ + + + + pcb-rnd developer manual + + + +This document has been moved to the +user doc. + + Index: tags/2.1.2/doc/developer/bugreport.html =================================================================== --- tags/2.1.2/doc/developer/bugreport.html (nonexistent) +++ tags/2.1.2/doc/developer/bugreport.html (revision 24813) @@ -0,0 +1,149 @@ + + + + pcb-rnd - reporting bugs + + + + + + + + + + +
Main + News + Doc + People + Events & timeline + pcb-rnd [pcb-rnd logo] +
+ + +

pcb-rnd - reporting bugs

+Pcb-rnd, like any other biggish piece of software, is not a free of bugs. +When you find a bug, please report it and we will try to fix it as soon as +possible.For reporting bugs you can use any medium you can reach us on: +mostly IRC and email, whichever is easier for you. +

+Using the below table you can optionally increase the efficiency of your +bugreport by sending enough data in the initial report that we won't need +to ask for clarification. + + +
what went wrong optional extra info to help debugging + +
+ 0. For any report, please include + + what version of pcb-rnd are you using: release tarball version + number or the output of "svn info" in trunk/. + +
+ 1. Configuration problems: +
    +
  • ./configure failed +
  • ./configure didn't find a optional package XY +
  • ./configure didn't do what I wanted it to do +
      +
+ include your scconfig/config.log + +
+ 2. Build problems: + make fails + +
    +
  • include your scconfig/config.log +
  • run make clean; make >make.log 2>&1 ; send the resulting make.log +
+ +
+ 3. Installation problems: + make install fails + +
    +
  • include your scconfig/config.log +
  • run make install >makei.log 2>&1 ; send the resulting makei.log +
  • if the error is not an obvious failure of an operation with a clear error + message, please explain, in details, what you expected to happen + (what files should have copied/linked where) and what happened instead. +
+ +
+ 4. pcb-rnd doesn't find a file + + Please make sure you have installed pcb-rnd before running it, or if + you are running it from source, make sure to cd to trunk/src and + running it as ./pcb-rnd. Only these two ways are supported. If it still + fails running by one of those two, please jump to point 5. + +
+ 5. pcb-rnd run time error, non-gui-related + +
    +
  • run pcb-rnd from the command line; append >run.log 2>&1 to the command line, reproduce the error and include run.log +
  • if the error is not an obvious failure of an operation with a clear error + message, please explain, in details, what you expected to happen + and what happened instead. +
+ +
+ 6. pcb-rnd run time error, gui-related + +
    +
  • if you are using the gtk-gl hid, please also try the gdk hid with + the command line argument --gui gtk2_gdk . Please include + a sentence about whether the bug affects both HIDs or is gl-only. +
  • even for the most obvious-looking problem, please explain, in + details, what you expected to happen and what happened instead. +
+ +
+ 7. pcb-rnd crashes (segfault, assertion, abortion) + +
    +
  • Re-run ./configure with --debug and recompile (and reinstall). +
  • Run pcb-rnd from gdb: +
    • +
    • if you are running the installed version: gdb pcb-rnd +
    • if you are running from source: cd trunk/src; gdb ./pcb-rnd +
    +
  • Type this in the gdb prompt: run (optionally append a space + and the command line arguments you would have used for starting pcb-rnd) +
  • reproduce the problem +
  • type bt, copy&paste the result and include it in the bugreport +
  • if the problem is reproducible, please include a description how to + trigger it, preferrably on an empty board on a fresh start, alternatively + with an example file included +
+ + Altnerative method with core dumps: +
    +
  • ./configure --debug +
  • ulimit -c unlimited +
  • on Linux, check your core pattern (man 5 core , search for pattern; changing the core pattern requires root) +
  • in src/ run ./pcb-rnd, trigger the bug +
  • in src gdb ./pcb-rnd core (core is the default core file name, you may have a different name depending on the core pattern, see above) +
+ If you are on MacOSX, you may need to use lldb instead of gdb: lldb --core /cores/core.52381 + and the backtrace command is bt all instead od just bt. +
+ +
+ 8. pcb-rnd can't load my file + + Please include the file in your bugreport + +
+ 9. pcb-rnd loads my file but it doesn't look good + + Please include the file in your bugreport; please include a screenshot + of the file (even open in another software) to demonstrate how it + should look and a screenshot how it looked in pcb-rnd; please mark + the difference visually. +
+ + + Index: tags/2.1.2/doc/developer/c89.html =================================================================== --- tags/2.1.2/doc/developer/c89.html (nonexistent) +++ tags/2.1.2/doc/developer/c89.html (revision 24813) @@ -0,0 +1,12 @@ + + +

pcb-rnd - C89

+ +Most of the code base is written in C89, with a few exceptions +written in C99 (gtk, because it's not C89-compatible). When adding +new code, keep it C89. Especially watch out for these: +
    +
  • comment: always use /* */, never // +
  • don't mix variable declaration with code - open a new {} block, which will also scope your new variables, or better yet, split up the function into smaller, static functions, the compiler will inline them anyway +
  • try to avoid vararg macros, use vararg functions instead +
Index: tags/2.1.2/doc/developer/dad/index.html =================================================================== --- tags/2.1.2/doc/developer/dad/index.html (nonexistent) +++ tags/2.1.2/doc/developer/dad/index.html (revision 24813) @@ -0,0 +1,12 @@ + + + +

DAD: Dynamic Attribute Dialogs

+ +

Table of Contents

+ + Index: tags/2.1.2/doc/developer/dad/intro.html =================================================================== --- tags/2.1.2/doc/developer/dad/intro.html (nonexistent) +++ tags/2.1.2/doc/developer/dad/intro.html (revision 24813) @@ -0,0 +1,56 @@ + + + +

DAD: Dynamic Attribute Dialogs

+ +

History

+

+Attribute Dialogs were originally invented around the early/mid 2000s for export +HIDs to store a static, flat list of options that are then presented both +as command line options and as the GUI dialog box for export parameters. + +

Intro

+

+DAD is the dyamically allocated version, extended with new widget types for +providing tools for building more complex dialog boxes. It is not connected +with command line options in any way at the moment. +

+The list of widgets is still a flat, growing C array, often called the +table. But inside the table, widgets build as a logical tree +structure. Widgets with name that includes "BEGIN" will open a new +logical layout level that has to be closed with a PCB_DAD_END(). + +

Calling conventions

+

+A table is always built incrementally and sequentially. In this sense +the dialog box is static: once build and created, the number and +type of widgets can not be modified. The dynamic aspect is that the code +may create (and destroy) arbitrary DAD boxes, even with loops and +runtime conditions on what widgets end up in the box. +

+There are two kind of widget calls: widget creation and property set. +Property set calls always change the last created widget. This, by +convention, is often indicated by code indentation as well. For example: +

+	PCB_DAD_INTEGER(dlg, "foo");
+		PCB_DAD_MINVAL(dlg, 1);
+		PCB_DAD_MAXVAL(dlg, 10);
+		PCB_DAD_DEFAULT_NUM(dlg, 3);
+		widget_id_foo = PCB_DAD_CURRENT(dlg);
+	PCB_DAD_BUTTON(dlg, "update!");
+		PCB_DAD_CHANGE_CB(dlg, pcb_act_attr_chg);
+
+

+PCB_DAD_INTEGER() and PCB_DAD_BUTTON() are (macro) calls to create +new widgets (an integer entry and a button), the rest of the calls +change the last created widget's properties. +

+The main widget of the box, the root widget of the widget tree is +any widget. It is practical to make it a container widget (e.g. a HBOX, VBOX, +TABLE, PANE, or TABBED) so that it can host children widgets. +

+After each creation, the caller can query and store the integer widget +identifier using the PCB_DAD_CURRENT() macro. The widget identifier can +be used, together with the table, to query or change widget properties +and current value any time the dialog box is active. + Index: tags/2.1.2/doc/developer/dad/text.html =================================================================== --- tags/2.1.2/doc/developer/dad/text.html (nonexistent) +++ tags/2.1.2/doc/developer/dad/text.html (revision 24813) @@ -0,0 +1,21 @@ + + + +

DAD: Dynamic Attribute Dialogs

+

+The text widget is a tex viewer/editor that operates on a string +that may contain multiple lines. + +

Helper macro for widget creation

+

+PCB_DAD_TEXT(table, user_ctx) +creates a new text widget and installs user context. + +

User callbacks

+

+The only callback the user may provide is user_free_cb which is called +when the text widget is destroyed. Other than this, DAD caller code can not +react on events happening in the text. + + + Index: tags/2.1.2/doc/developer/dad/tree.html =================================================================== --- tags/2.1.2/doc/developer/dad/tree.html (nonexistent) +++ tags/2.1.2/doc/developer/dad/tree.html (revision 24813) @@ -0,0 +1,32 @@ + + + +

DAD: Dynamic Attribute Dialogs

+

+The table tree widget is a table containint cells arranged in a +fixed number of columns. Each cell is a dynamically allocated +char * string. + +

Helper macros for widget creation

+

+These macros, defined in hid_dad.h, are used to fill up the last +created (tree) widget with initial data. They return a row pointer. If the +row pointer is NULL, root is used - in this case insert means inserting at +the beginning of the row list, append means append at the end of the row list. +

    +
  • PCB_DAD_TREE_APPEND - append a sibling row after an existing row +
  • PCB_DAD_TREE_APPEND_UNDER - append a child node (at the end of the child list) under an existing row. +
  • PCB_DAD_TREE_INSERT - insert a new sibling row before an existing row +
  • PCB_DAD_TREE_SET_CB - install an user callback function on a tree event +
+ +

Inline functions for manipulating the tree runtime

+

+When the tree widget is already created, typically when the dialog box +is already running, the code can use hid_dad_tree.h for reading or +changing cells or rows of the tree. Any change is immediately reflected +on the GUI. Please refer to the comments in hid_dad_tree.h for details +on the functions and arguments. + + + Index: tags/2.1.2/doc/developer/dad/wbool.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/developer/dad/wbool.png =================================================================== --- tags/2.1.2/doc/developer/dad/wbool.png (nonexistent) +++ tags/2.1.2/doc/developer/dad/wbool.png (revision 24813) Property changes on: tags/2.1.2/doc/developer/dad/wbool.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/developer/dad/wbutton.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/developer/dad/wbutton.png =================================================================== --- tags/2.1.2/doc/developer/dad/wbutton.png (nonexistent) +++ tags/2.1.2/doc/developer/dad/wbutton.png (revision 24813) Property changes on: tags/2.1.2/doc/developer/dad/wbutton.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/developer/dad/wcoord.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/developer/dad/wcoord.png =================================================================== --- tags/2.1.2/doc/developer/dad/wcoord.png (nonexistent) +++ tags/2.1.2/doc/developer/dad/wcoord.png (revision 24813) Property changes on: tags/2.1.2/doc/developer/dad/wcoord.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/developer/dad/wenum.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/developer/dad/wenum.png =================================================================== --- tags/2.1.2/doc/developer/dad/wenum.png (nonexistent) +++ tags/2.1.2/doc/developer/dad/wenum.png (revision 24813) Property changes on: tags/2.1.2/doc/developer/dad/wenum.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/developer/dad/whbox.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/developer/dad/whbox.png =================================================================== --- tags/2.1.2/doc/developer/dad/whbox.png (nonexistent) +++ tags/2.1.2/doc/developer/dad/whbox.png (revision 24813) Property changes on: tags/2.1.2/doc/developer/dad/whbox.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/developer/dad/whpane.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/developer/dad/whpane.png =================================================================== --- tags/2.1.2/doc/developer/dad/whpane.png (nonexistent) +++ tags/2.1.2/doc/developer/dad/whpane.png (revision 24813) Property changes on: tags/2.1.2/doc/developer/dad/whpane.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/developer/dad/widgets.html =================================================================== --- tags/2.1.2/doc/developer/dad/widgets.html (nonexistent) +++ tags/2.1.2/doc/developer/dad/widgets.html (revision 24813) @@ -0,0 +1,275 @@ + + + +

DAD: Dynamic Attribute Dialogs

+ +

Input widgets

+

+Input widgets are leaf widgets in the widget tree that typically +implement a field where user input takes place. Available +input widgets are: + +
creation call screenshot (gtk2) description +
PCB_DAD_LABEL single line or multi line of plain text, from a string +
PCB_DAD_LABELF single line or multi line of plain text, using printf formatting +
PCB_DAD_ENUM select one value from a fixed set (typical implementation is a combo box) +
PCB_DAD_BOOL checkbox +
PCB_DAD_INTEGER set an integer value +
PCB_DAD_REAL set a real (floating point) value +
PCB_DAD_COORD set a coordinate value +
PCB_DAD_STRING input single line string value (plain text) +
PCB_DAD_BUTTON clickable push button +
PCB_DAD_PROGRESS progress bar +
PCB_DAD_TREE a list, table or tree of text data +
PCB_DAD_PREVIEW drawing area +
PCB_DAD_PICTURE static bitmap image +
PCB_DAD_PICBUTTON static bitmap button +
PCB_DAD_COLOR color button and selector +
PCB_DAD_TEXT text box (text editor) +
+ + + +

PCB_DAD_LABEL(table, text)

+

+Draw a label, which is not an input field (unmodifiable by the user). +text is copied by the call into a new allocation. The only +control text accepts is '\n', which is line break. + +

PCB_DAD_LABELF(table, (printf_args))

+

+Same as PCB_DAD_LABEL() but the text is rendered using printf. Note: +printf args, including the format string, shall be in parenthesis, e.g. +

+PCB_DAD_LABELF(dlg, ("Cats: %d", num_cats))
+
+ +

PCB_DAD_ENUM(table, choices)

+

+The user can choose one value out of an ordered list of strings. The list +is passed as a NULL terminalte char * array. The value +of the enum is an integer index into that array, 0 being the first string. +

+Typical GUI implementation is a combo box, without text editing. + +

PCB_DAD_BOOL(table, label)

+

+Ask the user about a boolean value, typically using a checkbox. The value +of the bool is an integer which is either 0 or 1. + +

PCB_DAD_INTEGER(table, label)

+

+Ask for an integer value, between a minval and a maxval. +The value is an int, which is not guaranteed to be wider than a +16 bit signed value. +

+Typical GUI implementation is a text entry, often upgraded with small buttons +to increase or decrease the value ("spinbox"). + +

PCB_DAD_REAL(table, label)

+

+Ask for a REAL (double precision floating point value), between a minval +and a maxval. +

+Typical GUI implementation is a text entry, often upgraded with small buttons +to increase or decrease the value ("spinbox"). + + +

PCB_DAD_COORD(table, label)

+

+Ask for a coordinate value, between a minval and a maxval. +The value is pcb_coord_t. +

+Typical GUI implementation is a text entry that understands unit suffix, +often upgraded with small buttons to increase or decrease the value ("spinbox"). + + +

PCB_DAD_STRING(table)

+

+Ask for a single line of plain text input. +

+The value is a dynamically allocated string. + +

PCB_DAD_BUTTON(table, text)

+

+A push button the user can click on. text is not allocated or copied +(shall be a static const string or allocated/free'd by the user). +

+There is no value, the only interface is the change callback. + + +

PCB_DAD_PROGRESS(table)

+

+Present a progress bar which is not an user input. value is a +REAL value between 0.0 and 1.0. When the code changes the value, the +GUI makes sure the dialog box is drawn and flushed, because typical use +is in a busy loop calculation. + +

PCB_DAD_TREE(table, cols, first_col_is_tree, opt_header)

+

+Present a tree-table with cols columns of text objects. When +first_col_is_tree is 1, the first column works as a tree, with +indentation and/or tree graphics and logics for collapsing/expanding subtrees. +If opt_header is not NULL, it is a NULL terminated static const +array of header strings describing the table header to be displayed, in as +many strings as cols specified. +

+A special cases: +

+ +
case parameters +
plain flat list cols=1, first_col_is_tree=0 +
tree-only cols=1, first_col_is_tree=1 +
table-only cols>1, first_col_is_tree=0 +
+

+Manipulating the data and the view are both done using + special tree-table macros. + +

PCB_DAD_PREVIEW(table, expose_cb, mouse_cb, free_cb, initial_view_box, user_ctx)

+

+Present a drawing area with callbacks to the host code to handle drawing: + +
argument meaning +
expose_cb called when (parts of) the preview needs to be redrawn +
mouse_cb called on mouse events +
free_cb called before the widget is destroyed +
initial_view_box set the initial zoom/pan to match the view box specified in drawing units +
min_sizex_px widget minimum size in x direction (width), in pixels +
min_sizey_px widget minimum size in y direction (height), in pixels +
user_ctx opaque pointer that is passed to every callback +
+ +

PCB_DAD_PICTURE(table, xpm)

+

+The pointer to a static xpm image is stored in the enumerations field. The image +is displayed in a widget without any other decoration. + +

PCB_DAD_PICBUTTON(table, xpm)

+

+The pointer to a static xpm image is stored in the enumerations field. The image +is displayed in a button tat behaves exaclty as a normal BUTTON in all other +regards. + +

PCB_DAD_COLOR(table)

+

+A button that has a solid region of the color specified in value. Unless +read-only (PCB_HATF_CLR_STATIC), when the user clicks the button a +HID-specific color selector dialog is popped up where the user can +specify a new color. + +

PCB_DAD_TEXT(table, cols, first_col_is_tree, opt_header)

+

+Free form multiline text string, edited using a HID-builtin text editor. Line +terminator is \n. +

+TODO: accessor macros + +

Layout widgets

+ + +
creation call screenshot (gtk2) description +
PCB_DAD_BEGIN_HBOX arrange children widgets in a horizontal list +
PCB_DAD_BEGIN_VBOX arrange children widgets in a vertical list +
PCB_DAD_BEGIN_HPANE split the parent box horizontally into two sections; the split ratio is adjustable
Note: "left" and "right" are the first and second children (left and right sibling) of the widget tree +
PCB_DAD_BEGIN_VPANE split the parent box vertically into two sections; the split ratio is adjustable
Note: on the screenshot "left" and "right" are the first and second children (left and right sibling) of the widget tree +
PCB_DAD_BEGIN_TABLE arrange children widgets into a n*m matrix, allocate each cell the same size
Note: on the screenshot the table is set up to have 3 columns +
PCB_DAD_BEGIN_TABBED create a "tabbed notebook" view, each children is a new tab +
+ +

Box common flags

+

+hbox, vbox and table share a few common compflags, that are defined in +hid_attrib.h, pcb_hatt_compflags_t. The explanation of what each flag does +can be found there. The most commonly used ones are PCB_HATF_FRAME, +PCB_HATF_SCROLL, PCB_HATF_EXPFILL. +

+If PCB_HATF_EXPFILL is set, the given box tries to expannd and fill, using +up all available space in its parent widget. If multiple sibling boxes +have this flag set the behaviour is unspecified; some HIDs may prefer +to grow only one box, others may evenly distribute the avaialble space +among boxes. If this flag is not set, the box uses only as much space +as its children widgets require. + + +

PCB_DAD_BEGIN_HBOX(table) and PCB_DAD_BEGIN_VBOX(table)

+

+Arrange children widgets in a horizontal or vertical row. + +

PCB_DAD_BEGIN_HPANE(table)

+

+Expect exactly two child widgets. Arrange them horizontally, with +a widget in between them that allows the user to change the space allocation +between the sides. + +

PCB_DAD_BEGIN_VPANE(table)

+

+Expect exactly two child widgets. Arrange them vertically, with +a widget in between them that allows the user to change the space allocation +between the sides. + +

PCB_DAD_BEGIN_TABLE(table, cols)

+

+Place children widgets in a table with cols columns. Widgets are +placed by filling up rows first. If there are not enough widget to finish +the last row, rightmost columns are left empty. +

+The table is homogenous, which means the cell size is the same for all cells +and is either determined by the size of the smallest cell content or if +the table fills in a larger widget space than its minimal size, then cell +space is evenly distributed. + +

PCB_DAD_BEGIN_TABBED(table, tabs)

+

+Creates a "tabbed notebook": each child widget ends up on a new +page, there is only one page shown at a time and there is a GUI way +to switch page (the tab). The list of tab names is passed as tabs, +as a NULL terminalte char * array. The number of tab names must match +the number of children widgets. The value +of is an integer index into that array, 0 being the first tab. +

+If compflag includes PCB_HATF_HIDE_TABLAB, the tab graphics are hidden - +no tab labels printed and the user can not click to switch tab. This is +useful for dialog boxes where the code needs to present different tabs +using the same screen estate. +

+If compflag PCB_HATF_LEFT_TAB is set, tab labels are presented in a vertical +row on the left side of the widget. This is useful if there are a lot of +tabs with short names. + +

PCB_DAD_DUP_ATTR(table, attr)

+

+Create a new widget by duplicating an existing one. attr is the +widget ID of the existing widget. If the widget being duplicated is a +BEGIN*, it will need a corresponding PCB_DAD_END. + + +

Property sets

+

+The raw macro call is PCB_DAD_SET_VALUE, which can change (overwrite) a named +field of the current (last created) widget. The following table lists high +level macros that usually call PCB_DAD_SET_VALUE on a specific field. +

+ +
name description +
PCB_DAD_COMPFLAG(table, val) set all compflags +
PCB_DAD_MINVAL(table, val) change the minimal value for numeric input +
PCB_DAD_MAXVAL(table, val) change the maximal value for numeric input +
PCB_DAD_DEFAULT_NUM(table, val) set the default (initial) value for numeric fields (integers, coords, bools, floats) +
PCB_DAD_DEFAULT_PTR(table, val) set the default (initial) value for pointer fields (e.g. strings) +
PCB_DAD_MINMAX(table, min, max) hange both the minimal and the maximal value for numeric input +
PCB_DAD_CHANGE_CB(table, cb) cb is a function that shall be called upon any change to the widget value +
PCB_DAD_HELP(table, val) set the help text (typically presented as a tooltip) +
+ +

Actions and scripting

+

+There is a dad() action in the dialogd plugin that exposes all the above macros. +The dialog table ID is am arbitrary unique string and commands are the macro +names without PCB_DAD, written in lowercase. +

+Please refer to scripting rosetta +project for examples. An example of a typical small dialog box is the +unit conveter +script. + Index: tags/2.1.2/doc/developer/dad/winteger.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/developer/dad/winteger.png =================================================================== --- tags/2.1.2/doc/developer/dad/winteger.png (nonexistent) +++ tags/2.1.2/doc/developer/dad/winteger.png (revision 24813) Property changes on: tags/2.1.2/doc/developer/dad/winteger.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/developer/dad/wlabel.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/developer/dad/wlabel.png =================================================================== --- tags/2.1.2/doc/developer/dad/wlabel.png (nonexistent) +++ tags/2.1.2/doc/developer/dad/wlabel.png (revision 24813) Property changes on: tags/2.1.2/doc/developer/dad/wlabel.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/developer/dad/wpicbtn.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/developer/dad/wpicbtn.png =================================================================== --- tags/2.1.2/doc/developer/dad/wpicbtn.png (nonexistent) +++ tags/2.1.2/doc/developer/dad/wpicbtn.png (revision 24813) Property changes on: tags/2.1.2/doc/developer/dad/wpicbtn.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/developer/dad/wpicture.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/developer/dad/wpicture.png =================================================================== --- tags/2.1.2/doc/developer/dad/wpicture.png (nonexistent) +++ tags/2.1.2/doc/developer/dad/wpicture.png (revision 24813) Property changes on: tags/2.1.2/doc/developer/dad/wpicture.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/developer/dad/wprogress.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/developer/dad/wprogress.png =================================================================== --- tags/2.1.2/doc/developer/dad/wprogress.png (nonexistent) +++ tags/2.1.2/doc/developer/dad/wprogress.png (revision 24813) Property changes on: tags/2.1.2/doc/developer/dad/wprogress.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/developer/dad/wreal.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/developer/dad/wreal.png =================================================================== --- tags/2.1.2/doc/developer/dad/wreal.png (nonexistent) +++ tags/2.1.2/doc/developer/dad/wreal.png (revision 24813) Property changes on: tags/2.1.2/doc/developer/dad/wreal.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/developer/dad/wstring.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/developer/dad/wstring.png =================================================================== --- tags/2.1.2/doc/developer/dad/wstring.png (nonexistent) +++ tags/2.1.2/doc/developer/dad/wstring.png (revision 24813) Property changes on: tags/2.1.2/doc/developer/dad/wstring.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/developer/dad/wtabbed.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/developer/dad/wtabbed.png =================================================================== --- tags/2.1.2/doc/developer/dad/wtabbed.png (nonexistent) +++ tags/2.1.2/doc/developer/dad/wtabbed.png (revision 24813) Property changes on: tags/2.1.2/doc/developer/dad/wtabbed.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/developer/dad/wtable.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/developer/dad/wtable.png =================================================================== --- tags/2.1.2/doc/developer/dad/wtable.png (nonexistent) +++ tags/2.1.2/doc/developer/dad/wtable.png (revision 24813) Property changes on: tags/2.1.2/doc/developer/dad/wtable.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/developer/dad/wtree.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/developer/dad/wtree.png =================================================================== --- tags/2.1.2/doc/developer/dad/wtree.png (nonexistent) +++ tags/2.1.2/doc/developer/dad/wtree.png (revision 24813) Property changes on: tags/2.1.2/doc/developer/dad/wtree.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/developer/dad/wvbox.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/developer/dad/wvbox.png =================================================================== --- tags/2.1.2/doc/developer/dad/wvbox.png (nonexistent) +++ tags/2.1.2/doc/developer/dad/wvbox.png (revision 24813) Property changes on: tags/2.1.2/doc/developer/dad/wvbox.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/developer/dad/wvpane.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/developer/dad/wvpane.png =================================================================== --- tags/2.1.2/doc/developer/dad/wvpane.png (nonexistent) +++ tags/2.1.2/doc/developer/dad/wvpane.png (revision 24813) Property changes on: tags/2.1.2/doc/developer/dad/wvpane.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/developer/data.html =================================================================== --- tags/2.1.2/doc/developer/data.html (nonexistent) +++ tags/2.1.2/doc/developer/data.html (revision 24813) @@ -0,0 +1,214 @@ + + + +

pcb-rnd internals

+ +

concepts

+ +

+Convention: typedef'd types are called pcb_*_t - the corresponding struct +is pcb_*_s. + +

board

+

+There is only one board being edited. A board is the model of the whole world +for pcb-rnd - any other, auxiliary data is only a partial description of a board. +The data struct for board is pcb_board_t. As of now, pcb-rnd edits only one +board at a time, and it is stored in a global variable called PCB. +The code is single threaded and is not reentrant. +

+Half of the board structure describes global board properties: +

    +
  • layer stack +
  • netlist +
  • editor settings (e.g. routing styles, which layers are visible) +
  • metadata (such as name of the author, size of the board). +
+The other half is the actual board data, stored in a pcb_data_t field. +

+Relevant structs, variables and functions are in board.[ch]. + +

data

+

+A pcb_data_t contains everything to describe the 2d geometry of +an existing board: +

    +
  • per-layer objects (lines, arcs, polygons, text objects) +
  • global objects (subcircuits, padstacks) +
  • temporary logical connections (rat lines) +
  • padstack prototypes (padstack shapes referenced by padstack references/instances) +
+

+Relevant structs, variables and functions are in data.[ch]. +

+However, it does not contain the layer stackup, but references to it. +This means a data_t can be copied or moved from within one board to +another, even with mismatching layer stack. When a pcb_data_t is within a +pcb_board_t, the layer references are fixed, pointing to actual layers +within the board's layer stack (e.g. "layer 3 in the stack"). Such a layer is +also called a real layer. When a +pcb_data_t is used outside of a board (e.g. as a buffer), a generalized, +recipe-like layer description is used (e.g. "second copper layer counted +from the top"). Such a layer is not a real layer, but can be bound +to a real layer. The binding means that while it keeps it's recipe-like +description, it is also referring to an actual layer of the stack of the +current PCB structure. (This happens to subcircuits: they are specified +with generalized, recipe-like layers that are bound to the board's layer stack +once the subcircuit is placed on the board.) + +

buffers

+

+Paste buffers are pcb_buffer_t; the main field is pcb_data_t. +

+Relevant structs, variables and functions are in buffer.[ch]. +

+A paste buffer doesn't have a layer stack. When data is copied from a board +to a buffer, the layer references are generalized. + +

terminology: layers and layer groups

+

+Layers are abstract canvases also serving as a logical grouping +of drawing primitives. Every layer is part of exactly one layer +group. A layer group is close to what a physical layer is on +the FR4. +

+Limitations: +

    +
  • as of now pcb-rnd does not have Z-coordinate: layers have no thickness; +
  • substrate is not represented at all in the layers stack. +
+

+The location of a layer group on of (flags are in layer.h): +

    +
  • top (component) side - PCB_LYT_TOP +
  • bottom (solder) side - PCB_LYT_BOTTOM +
  • inner or internal (e.g. signal) - PCB_LYT_INTERN +
  • global (affects all locations, e.g. the outline layer for routing) - 0 +
+

+In pcb-rnd most layer types are fully explicit: +

    +
  • copper - PCB_LYT_COPPER (not composite) +
  • silk screen - PCB_LYT_SILK +
  • mask - PCB_LYT_MASK +
  • paste - PCB_LYT_PASTE +
  • outline - PCB_LYT_OUTLINE (not composite) +
+

+The layers of a composite layer group are combined + and -, depending +on the PCB_LYC_SUB in their comb field. +

+Assumptions: there are two silk layers, one for the top and one for the bottom +side and there are always a top and a bottom copper layer. (Long term +assumptions will be removed.) The outline layer has to be global. +

+The rest of the layers are virtual layers, often just GUI hacks, e.g.: +

    +
  • Subcircuit dashed outline, subcricuit parts - no layer struct, calculated on-the-fly from the subc list +
  • fab - no layer struct, calculated on-the-fly from drill/hole data +
+ +

pcb_data_t: global data

+

+Global data affect all layers. The most trivial example is +padstack: it has a hole and potentially a copper ring on all +layers. A padstack +directly under the board's pcb_data_t is considered a "via" (by convention, +by purpose), a padstack under subcircuit's pcb_data_t is usually a "pin" +or "pad" (when has a term ID) or a "via". The quoted terms don't exist +in the code, they are just conventions. Padtsacks are vertical constructions, +they may affect multiple layers. +

+The other global object is subcircuit; using its own layer list, it potentially +can affect all layers of the board. The children objects of a subcircuit is +a pcb_data_t, which allows arbitrary (loop-free) recursion in data. + +

pcb_data_t: layer-local data

+

+The data struct has a pcb_layer_t for each logical layer, to host +the per layer objects (drawing primitives). + +

the layer struct

+

+Layer data is stored in struct pcb_layer_t. A layer has a list +for each object type (drawing primitive type): arcs, lines, polygons, etc. +These lists are local: in a tree of subcircuits, the layer list contains only +what's strictly directly on the given layer, there's no recursion. +

+Relevant structs, variables and functions are in layer.[ch]. + +

map

+ + + +

tree

+

+A tree can be built using subcircuits. The top level is always a board or +a buffer, which are essentially just different wrappers around pcb_data_t. +Then pcb_data_t can host subcircuits in it global data. A subcircuit +is also just a 3rd kind of wrapper around a pcb_data_t, which means it +opens a new level of the tree. +

+When we will start supporting subc-in-sunc this means the root is: +

    +
  • a PCB board: pcb_board_t +
  • a paste buffer: pcb_buffer_t +
+

+(When the user opens a subcircuit for editing, the root is still a pcb_board_t, +it just has a field that tells it is a fake board for a single subc. Still +the real subc to edit is in the fake board's pcb_data_t. This is needed so +we have all the global states stored in pcb_baord_t.) +

+Then the next levels are arbitrary encapsulation of subcircuits. + + +

list vs. rtree

+

+Each level of pcb_data_t has its own lists storing the local objects. +

+The root of the tree also ha an rtrees for each object type. An rtree is +a spatial data structure that provides efficient coordinate lookups. All objects, +recursively, are added in these rtrees. That means, if there's a line on the +board, that's really a line stored on a pcb_layer_t's list, and the +full tree path is somehting like this: +

+	pcb_board_t -> pcb_data_t -> pcb_layer_t -> linelist_t
+
+

+The same line is also added in the same layer's rtree (called line_tree for lines): +

+	pcb_board_t -> pcb_data_t -> pcb_layer_t -> pcb_rtree_t
+
+

+On subsequent levels, the list is the same. If a line is part of +a subcircuit, it's sitting on one of the linelists on one of the bound +layers provided by the subc: +

+	pcb_board_t -> pcb_data_t -> pcb_subclist_t -> pcb_data_t -> pcb_layer_t -> pcb_linelist_t
+
+

+The subcircuit's pcb_layer_t would also have an rtree. But instead of having +it's own rtree, it's rather linked to the root's rtree. Which means any access +to any rtree under a subc is really access to the corresponding rtree of the root! +In other words, object lists are level-local, but rtrees are tree-global. +

+This also means as a programmer, you can alsways do two kind of searches or +iterations: +

    +
  • level-local (only linear iteration is possible) +
  • global (both linear iteration and efficient, bounding box based, geometrical rtree lookups are possible) +
+

+Rationale: this way if we need to look up what's on a specific coord +(e.g. the user clicks or find.c needs to check what is connected to a given +point), we can use the global rtree's and we will get the answers without having +to recurse into subcircuits. +

+Note: layer bindings complicate this a bit. A subc layer is bound to one of +the root's real layers. When that binding is created, the rtrees are also +linked together, and all subc layer objects on the given layer are added +in the common rtree. When the layer binding needs to change, that means +we first need to unbind the subcircuit's bound layer from the root's real +layer: when we do that, we need to unlink the rtrees and remove all +the objects we added to the global tree from our subcircuit layer. Index: tags/2.1.2/doc/developer/data1.svg =================================================================== --- tags/2.1.2/doc/developer/data1.svg (nonexistent) +++ tags/2.1.2/doc/developer/data1.svg (revision 24813) @@ -0,0 +1,349 @@ + + + + + + +pcb_data + +cluster_1 + +LEGEND + + +PCBType_misc + +misc fields: +ID +Name +FileName +colors +drc settings +cursor coords +grid +layergroups +route styles +padstack protos +... + + +PCBType_flags + +flags: +Changed +ViaOn (vias drawn?) +... + + +pcb_board_t + +pcb_board_t + + +pcb_board_t->PCBType_misc + + + + +pcb_board_t->PCBType_flags + + + + +pcb_data_t + +pcb_data_t + + +pcb_board_t->pcb_data_t + + + + +DataType_listrt + +layer-independent lists and rtrees + + +pcb_data_t:s->DataType_listrt + + + + +DataType_LayerN + +LayerN: number of +layers in use + + +pcb_data_t:s->DataType_LayerN + + + + +DataType_layers + +an array of layers + + +pcb_data_t:s->DataType_layers + + + + +DataType_misc + +misc fields + + +pcb_data_t:s->DataType_misc + + + + +DataType_rtrees + +DataType_rtrees + + +pcb_data_t:s->DataType_rtrees + + + + +pcb_data_t2 +another level of +pcb_data_t +... + + +pcb_subc_t + +pcb_subc_t + + +pcb_subc_t->pcb_data_t2 + + + + +pcb_rat_line_t + +pcb_rat_line_t + + +pcb_pstk_t + +pcb_pstk_t + + +pcb_padstack_proto_t + +pcb_padstack_proto_t + + +pcb_pstk_t->pcb_padstack_proto_t + + +id +ref. + + +pcb_arc_t + +pcb_arc_t + + +pcb_line_t + +pcb_line_t + + +pcb_text_t + +pcb_text_t + + +pcb_poly_t + +pcb_poly_t + + +struct + +box: +struct + + + +PCB + +extern pcb_board_t PCB +global variable +holding the current +board + + +PCB->pcb_board_t + + + + +Buffers + +extern pcb_buffer_t Buffers[] +global variable holding +all paste buffers + + +pcb_buffer_t + +pcb_buffer_t + + +Buffers->pcb_buffer_t + + + + +pcb_buffer_t->pcb_data_t + + + + +BufferType_misc + +misc fields: +bounding box +offset + + +pcb_buffer_t->BufferType_misc + + + + +DataType_listrt->pcb_subc_t + + + + +DataType_listrt->pcb_rat_line_t + + + + +DataType_listrt->pcb_pstk_t + + + + +DataType_listrt->pcb_padstack_proto_t + + + + +pcb_layer_t + +pcb_layer_t + + +DataType_layers->pcb_layer_t + + + + +LayerType_lines + +list and rtree of lines + + +pcb_layer_t->LayerType_lines + + + + +LayerType_arcs + +list and rtree of arcs + + +pcb_layer_t->LayerType_arcs + + + + +LayerType_texts + +list and rtree of text objects + + +pcb_layer_t->LayerType_texts + + + + +LayerType_polygons + +list and rtree of polygons + + +pcb_layer_t->LayerType_polygons + + + + +LayerType_misc + +misc fields: +flags +colors + + +pcb_layer_t->LayerType_misc + + + + +LayerType_lines->pcb_line_t + + + + +LayerType_arcs->pcb_arc_t + + + + +LayerType_texts->pcb_text_t + + + + +LayerType_polygons->pcb_poly_t + + + + +round + +round: +struct field + + +diamond + +diamond: +global variable + + +grn + +green: +drawing primitive + + + Index: tags/2.1.2/doc/developer/ddrc/examples1.txt =================================================================== --- tags/2.1.2/doc/developer/ddrc/examples1.txt (nonexistent) +++ tags/2.1.2/doc/developer/ddrc/examples1.txt (revision 24813) @@ -0,0 +1,54 @@ +# Example 1: Sensitive RF elements should be close +# +# e1 is the list of elements that have the user tag RF +# e2 is a copy of e1; it's needed to get two loops (e1 vs. e2 objects form pairs) +# Assert that any two components are closer than 25 mm to each other + +rule sensitive RF elements + let e1 (type(@, element)) && (@.a.group == "RF") + let e2 e1 + assert (distance(e1, e2) < 25 mm) + +# Example 2: matched trace lengths on dram data 0 +# +# e1 is the list of dram traces +# e2 is a copy of e1 (see Example 1) +# Assert that any two net lengths are matched within 2 mm + +rule matched length dram traces + let e1 (type(@, net)) && (@.a.group == "dram_data_0") + let e2 e1 + assert abs(netlen(e1) - netlen(e2)) < 2 mm + +# Example 3: check if isolation gap is maintained between any HV and LV nets +# (Lazy: assume any copper is part of a network, compare net-to-net only) +# +# hv is the list of high voltage nets +# lv is a list of non-hv networks +# + +rule isolation gap 1 + let hv (type(@, net)) && (@.a.high_voltage) + let lv (type(@, net)) && !(@.a.high_voltage) + assert !is_closer(lv, hv, 4 mm) + +# Example 4: check if isolation gap is maintained between any HV and LV nets +# (Proper way: do not forget about copper not part of any network!) +# +# hv is the list of high voltage nets +# hvo is a list of all objects found in hv +# cp is a list of all copper object +# There are two iterators in the assert: cp (all copper objects) and hv. +# For each hv and cp pair: +# - lcomplement returns a cp object if the cp object is not in hv (i.e. +# the object is low voltage); else the return value is empty and is_closer +# returns invalid which is not a violation +# - hvo is required because cp is an object while hv is a list of nets +# (so cp is never on the hv list) +# - if there was a valid (low voltage) cp object found, + +rule isolation gap 2 + let hv (type(@, net)) && (@.a.high_voltage) + let hvo lobjs(hv) + let cp (type(@, copper)) + assert !is_closer(lcomplement(cp, hvo), hv, 4 mm) Index: tags/2.1.2/doc/developer/ddrc/proposal1.txt =================================================================== --- tags/2.1.2/doc/developer/ddrc/proposal1.txt (nonexistent) +++ tags/2.1.2/doc/developer/ddrc/proposal1.txt (revision 24813) @@ -0,0 +1,242 @@ +Dynamic DRC proposal 1: a Declarative DRC language. + +P0 A DRC program is an unordered list of rules. Rules are evaluated and + violations reported. The advantage of a declarative language is that + intermediate results can be cached and reused. + +P1 The language is intended to be human readable and human writable, but + the main goal is to let programs and scripts (e.g. netlisters) to + generate it. + +P2 A rule consists of three parts: + - the rule keyword; syntax: rule NAME + - build variables (lists) using search statements + - state assertions about those lists. + - comments, empty lines + +P3 Variables are named by the user and are local to the rule (TODO) + +P4 Lists are ordered. + +P5 A list is consists of zero or more objects. An object is: +P6 - the board +P7 - a layer +P8 - a board drawing primitive (line, arc, polygon, via, text) +P9 - an element primitive (element line, element arc(?), pin, pad, element name) +P10 - an element as a whole +P11 - a net +P61 - a 2D coordinate with or without layer information + +P12 Objects have named properties (or fields): +P13 - core attributes: for each object type a predefined set of key=value + pairs that always exist (e.g. thickness of a line, start angle of + an arc); these field names starts with "p." +P14 - user attributes: free-form key=value pairs optionally assigned by + the user; these field names start with "a." + +P15 Note: the language is case sensitive with keywords and builtins using + lowercase only. For better readability, in syntax description in this + document uppercase words are user chosen identifiers or fields. Whitespace + character sequences are usually treated as a single whitespace. (This + does not mean identifiers have to be uppercase in a program.) + + The syntax of a search statement is: + +P16 let LISTNAME EXPR + +P17 It creates a list called LISTNAME and evaluates expression EXPR to all + available objects and adds the objects that match EXPR to the list. Each + matching object is added only once. The particular order of objects on + the list is random. Object "matches EXPR" when the EXPR evaluated on + the object yields true. + +P18 The current object used in the iteration during the search is called + @. + +P19 An expression returns a value. A value can be: +P20 - an object +P21 - a list +P22 - scalar: a number or string (might be suffixed, like "42 mm") +P23 - void (empty, also known as false) + +P23 A value is considered true if: +P24 - it is an existing object +P25 - it is a non-empty list +P26 - it is a non-zero number or non-empty string +P69 - it is a valid coordinate + + An expression is one of: + + syntax meaning + ---------------------------------------------------------------- +P27 (EXPR) change precedence +P28 EXPR || EXPR logical OR (result: number) +P29 EXPR && EXPR logical AND (result: number) +P30 EXPR + EXPR add (number only) +P31 EXPR - EXPR subtract (number only) +P32 EXPR * EXPR multiply or ... (number only) +P32 EXPR / EXPR multiply or ... (number only) +P32 EXPR == EXPR the two values are equal +P33 EXPR != EXPR the two values are not equal +P71 EXPR ~ string regex match left EXPR using pattern right string +P34 EXPR > EXPR left EXPR is greater than right EXPR (number only) +P35 EXPR >= EXPR left EXPR is greater than or equal to right EXPR (number only) +P36 EXPR < EXPR left EXPR is less than right EXPR (number only) +P37 EXPR <= EXPR left EXPR is less than or equal to right EXPR (number only) +P38 !EXPR logical NOT (result: number, 0 or 1) +P39 FUNC(EXPR, EXPR, ...) call a function with 0 or more arguments +P40 EXPR.field evaluated to the value of an object field (see P45, P46) + + The syntax of an assertion is: + +P41 assert EXPR + +P42 If the EXPR in an assert evaluates to false, a DRC violation is generated. + +P43 If an assert EXPR is a list anywhere else than in a function argument, it is + evaluated for all valid members of the list (see P45, P46). For example + if there is a variable called FOO, which is a list of objects + (built using a search statement), expression + + FOO.p.thickness + + is evaluated as many times as many objects are on the list, and the + full assert is checked each case. If there is another similar list + called BAR, an expression: + + (FOO.p.thickness < BAR.p.thickness) + + will compare each possible pair of FOO and BAR objects. That is, if + FOO has 4 objects and BAR has 15 objects, that is 4*15 = 60 comparisons. + +P44 However, each list is iterated only once, even if it is referenced multiple + times in the same expression. For example, with the above lists: + + (FOO.p.clearance > 10 mil) && (FOO.p.thickness < BAR.p.thickness) + + the potential number of iterations is still 4*15, and not 4*4*15. In + practice the engine leverages lazy evaluation so if FOO.p.clearance + is smaller than 10 mil, the right size is not evaluated. See also: P45, P46. + +P45 A field reference is valid if the field exists. For example a line object + has a thickness attribute, thus the .p.thickness is valid, but a polygon + object does not have a thickness and .p.thickness on a polygon is invalid. + An user attribute reference (e.g. field .a.baz) is valid if the attribute + key exists in the given object. + +P46 Invalid fields are skipped in iterations. Thus if variable BLOBB is a list + that consists of 3 line, 2 arc and a layer objects, the following assert + will result in 2 comparisons only: + + (BLOBB.p.width >= 10 mm) + + (because only arc objects have valid .p.width field). + +P47. An invalid field in an expression is never considered an + error. In an assert statement it causes skipping an iteration. In a + search statement it evaluates to void. + +P48. A void value is never equal to anything. A void value is not equal + even to another void value. + +P49. Comments are lines starting with # + + + BUILTIN FUNCTIONS + +P70 list(LISTNAME) + Within an expression, a reference to a list may become an iterator and + refer to a single object. In case the expression needs the list, the + list() function protects LISTNAME from becoming an iterator. For + example llen(list(@)) is the number of all objects the design consists. + +P50 llen(EXPR) + Returns to the number of items of a list (an integer number >= 0). + +P51 lvalid(EXPR, field) + Returns a list of items on the list for which field is valid. + EXPR can be a list or an object. + +P52 lunion(EXPR1, EXPR2) + A new list is created; items of EXPR1 are copied to the new list in order. + Those items from EXPR2 that are not on the list already are appended, + keeping their order. The new list is returned. + + Both EXPR1 and EXPR2 can be either a list or an object. + + Note: order of arguments does matter (affects order of objects on the + resulting list). + +P53 lintersect(EXPR1, EXPR2) + A new list is created; items that are present on both EXPR1 and EXPR2 + are copied onto the new list. The new list is returned. + + Both EXPR1 and EXPR2 can be either a list or an object. + + Note 1: this function can be used as "is this object on the list" query: + list_intersection(LIST, OBJ) will result an empty list (which means false) + if OBJ is not on the list. + + Note 2: similarly, if both argument are objects, the result is false + if the two arguments are not the same object. + +P54 lcomplement(EXPR1, EXPR2) + Creates a new list with all items that are present in EXPR1 but not in + EXPR2. The new list is returned. + + Both EXPR1 and EXPR2 can be either a list or an object. + + +P55 ldiff(EXPR1, EXPR2) + Creates a new list with all items that are present either in EXPR1 or in + EXPR2 but not in both. The new list is returned. + + +P56 distance(EXPR1, EXPR2) + Calculates the shortest distance between two objects. Returns a number. + + Note: if any expression is a layer, the stack distance is calculated + (which will be 0 for now, as pcb-rnd doesn't yet know about layer thickness). + If the expression is a net, the whole shape of the net is used + (expensive! use is_closer() instead) + If the expression is the board, the operation is invalid (see P46). + +P57 is_closer(EXPR1, EXPR2, NUMBER) + Checks if EXPR1 and EXPR2 are closer to each-other than NUMBER. It uses + the classic bloat-and-find algorithm originally used by the classic DRC, + thus it is much cheaper than distance(EXPR1, EXPR2) < NUMBER. + +P58 netlen(EXPR) + Network length of EXRP1: sum of all non-overlapping trace/arc lengths that + make up a network; polygons are approximated with their average diameter + (TODO). If EXPR is an object, its length is returned. + +P59 netobjs(EXPR) + Creates and returns a list of objects consists of a net. + +P60 type(EXPR, TYPENAME) + EXPR is an object. Returns the object if it's type matches TYPENAME, else + returns void (a.k.a. false). This call is useful to decide whether an + object is of a specific type. TYPENAME is one of: + - drawing primitive type: arc, line, polygon, text, via, element + - element primitive type: element_line, element_name, pin, pad + - misc type: layer, net + - meta-type, or a group: + - copper: primitive that results in copper (arc, line, polygon, text (on copper), via, pin, pad) + - drilled: anything that drills the board (via, pin) + +P62 gridup(EXPR, NUM1, NUM2) + If expression is an object, return a list of coordinates that are on + the object, evenly spaced: +P63 - for lines and arcs, the points are evenly spaced on the centerlane with + a gap of NUM1, starting from both endpoints, having the corner case in + the middle; if NUM2 is 0, the gap at the middle may be larger than NUM1, + else it may be smaller than NUM1. +P64 - for polygons take a grid of NUM1*NUM2 spacing (NUM1 is always axis + aligned to X, NUM2 to Y). The offset of the grid is unspecified +P65 - element and text are ignored +P66 - a pad or pin is approximated with a polygon +P67 - for networks, iterate over all objects and append unique coordinates on + the resulting list +P68 There's no guarantee on the particular order of the list. + Index: tags/2.1.2/doc/developer/ddrc/requirements.txt =================================================================== --- tags/2.1.2/doc/developer/ddrc/requirements.txt (nonexistent) +++ tags/2.1.2/doc/developer/ddrc/requirements.txt (revision 24813) @@ -0,0 +1,23 @@ +The Dynamic DRC should be able to solve at least these tasks: + - check start grounding + - require element placement on same layer + - specify element proximity to each other on same layer + - specify element proximity to the edge + - specify element proximity to network or other copper feature + on the same layer + - perform copper vs. copper checks + - minimal gap between an object or network and anything else + - minimal gap between high voltage and low voltage networks + - perform copper geometry checks + - detect minimal width (high current) + - detect poly hairpin + - number and length of stubs (hight freq) + - "via cage": a given network needs to be surrounded by a set of gnd vias + - network related copper checks + - matched length lines (e.g. fast dram bus) + - balanced transmission line (distance between the tracks) + - match and/or limit number of vias + - limit layer usage + - require layer stackup properties, e.g. microstrip, stripline + - e.g. require ground poly on the next layer + - e.g. number of gaps in the ground poly the line jumps Index: tags/2.1.2/doc/developer/distros.txt =================================================================== --- tags/2.1.2/doc/developer/distros.txt (nonexistent) +++ tags/2.1.2/doc/developer/distros.txt (revision 24813) @@ -0,0 +1,47 @@ +How to request packaging (distros sorted by popularity, 2016): + +Ubuntu: + easiest is to get in Debian, Ubuntu picks up packages from sid + alternative: ubuntu-devel-discuss@lists.ubuntu.com (pending) + alternative: https://bugs.launchpad.net/ubuntu/+filebug?no-redirect&field.tag=needs-packaging + +linux mint + https://blueprints.launchpad.net/linuxmint + (same maintainer as debian?) + +slackware: + Promised (AFK, ask again in 3rd week of sept) + geda/pcb maintainer: pfeifer[dot]felix[at]googlemail[dot]com (sent mail) + https://slackbuilds.org/guidelines/ + needs an existing package + since the slackbuild needs slackware's pkgtools usually at the end of a ./configure --prefix=/usr --extrastuff..make.. make install DESTDIR=/tmp/NAMEOFPACKAGE..cd /tmp/NAMEOFPACKAGE..makepkg -l y -c n ../NAMEOFPACKAGE-123.txz + installwatch can build a package + check out #slackbuilds + +Debian: + Bdale? + (alternative: pkg-electronics-devel@lists.alioth.debian.org - pending) + (alternative: RFP through reportbug) + +fedora: + https://fedoraproject.org/wiki/Package_maintainers_wishlist?rd=PackageMaintainers/WishList + (wrote mail to cicku) + +OpenSuse: + adrian [at] suse.de (mail sent) + +Arch: + DONE! needs to be modularized + Kyle Keen (mail sent) + +Manjaro: + Same as arch + +---- +FreeBSD: + hrs [at] freebsd.org (Hiroki Sato - mail sent) + +OpenBSD: + andreas.bihlmaier [at] gmx.de -> ENOTIME, he suggests ports@openbsd.org + + Index: tags/2.1.2/doc/developer/export_openems/mesh_z.txt =================================================================== --- tags/2.1.2/doc/developer/export_openems/mesh_z.txt (nonexistent) +++ tags/2.1.2/doc/developer/export_openems/mesh_z.txt (revision 24813) @@ -0,0 +1,16 @@ +The bottom of the board by default always lands at z=0. The top is the +thicknesses of all the substrate layers added together. It is only the +substrate layers because right now the copper is just a change in +attribute on the surface of the substrate (2D) not a 3D object. + +So for the hairpinfilter example which is just 1 substrate layer of +1.5mm. It would be z=0mm for the bottom, and z=1.5mm for the top. + +That adjustment we have for z-mesh "num in substrate" is meant to +select how many lines fit inbetween those two lines. + +Technically my pcb2csx library can do both full 3D where all objects +have real thickness and the thing we do now but it eats a lot of +processing power for marginal benifit in most cases. In other words +it's not worth supporting at this point. + Index: tags/2.1.2/doc/developer/fungw_actions.txt =================================================================== --- tags/2.1.2/doc/developer/fungw_actions.txt (nonexistent) +++ tags/2.1.2/doc/developer/fungw_actions.txt (revision 24813) @@ -0,0 +1,129 @@ +Actions implemented as fungw functions +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +1. Intro + +All pcb-rnd actions are fungw functions by now. This helps the code to do +all the data type conversions easier, save a few conversions where we +don't need conversions. More importantly, this makes a more seamless +integration between user scripts and C code, whether scripts are calling +C actions or the user is executing script defined actions. + +To stay compatible with the old action mechanism, the current version +applies the following restrictions: + +- we have only one large fungw object (pcb_fgw_obj) that hosts all + functions; this emulates the old central hash of functions + +- before a function enters the object or a function is looked up in the + object, the function name is converted to lowercase; this emulates the + case intensity of the old action system, which is still essential for + the user interface (GUI or CLI command entry and menu). + +- temporarily, for the transition, there are two helper macros + PCB_OLD_ACT_BEGIN and PCB_OLD_ACT_END that can wrap old function + code, converting all arguments to a char **argv. Such old actions + should return non-zero on error, while the value of ores will always be + FGW_INT/0. New action code shall NOT use the compatibility API. + +- a single action call will result in a single fungw function call; that + is, the fungw function that serves the action is free to convert any + of the arguments. + +2. converting arguments + +Arguments are normally converted using PCB_ACT_CONVARG(); the last +argument is a statement that can make the value assignment to a local +variable if the conversion was succesful. For example fetching the 2nd +argument into a local coord: + +{ + pcb_coord_t c; + PCB_ACT_CONVARG(2, FGW_COORD, ActioName, c = fgw_coord(&argv[2])); +} + +If conversion fails or the argument is not available, the macro returns +from the function with error. Anoter variant of the macro called +PCB_ACT_MAY_CONVARG() omits the error-return part, allowing the code +to have optional arguments. + +When the coordinate conversion needs to keep extra info, e.g. whether +the coordinate was specified in absolute or relative, the special type +fgw_coords_t shall be used: + +{ + fgw_coords_t *crd; + PCB_ACT_CONVARG(1, FGW_COORDS, d1, crd = fgw_coords(&argv[1])); +} + + +3. returning + +An action function has two return values: the C function return value +and the "res" argument. If the action could not start executing code +because of a calling error, e.g. there are not enough arguments or +arguments can not be converted or the function is invoked out-of-context, +it should retrun a fungw error using the C return value. This indicates +that performing the call itself failed. + +Else, if actual action code runs, the C return value should be 0 and the +res argument should be loaded with the return value of the action. This +indicates that the call took place, the action was executed and the conclusion +is stored in res. The semantic of the result is action-specifiec. The common +convention is returning int, 0 meaning success. The shortnad for this: + +{ + PCB_ACT_IRES(0); + return 0; +} + +PCB_ACT_IRES() loads res with type and value. There are other similar, +type-specific macros available. + +4. multi-call + +Currently pcb-rnd does not depend on fungw's multi-call, thus actions are +free to convert their arguments - the same arguments will not be reused in +other actions. + +5. calling an action from another action + +There are two common cases: wrapping/dispatching and invoking. + +In the wrap/dispatch setup an outer action is called that does not alter +the arguments (not even converting them!), but has to call another action +with exactly the same arguments. This can be done by using the macro +PCB_ACT_CALL_C(). + +When an action code needs to invoke another action, there are three ways +doing it. + +5.1. string call + +The slow, string parsing way using pcb_actionl() or the more +efficient direct call. + + +5.2. direct C call + +Direct C function call is possible only if both the caller and callee +actions are in core, or are in the same plugin. Before the direct call +the caller needs to set up a fungw argv array and after the call the +array members need to be free'd using fgw_argv_free() to avoid +leaking argument memory. This needs to be done even if the caller did +not allocate any memory for argv members - the callee can allocate memory +by converting arguments. + +5.3. indirect C call + +Call pcb_find_action() to get an fgw_func_t * to the action - this holds +the C function pointer. Set up argv, make sure argv[0] is set up to be +the target function: + + fgw_func_t *fn = pcb_find_action(...); + argv[0].type = FGW_FUNC; + argv[0].val.func = fn; + +Call pcb_actionv_() with fn and the arguments. Always call fgw_argv_free() +afterward. Also call fgw_arg_free() on the res. + Index: tags/2.1.2/doc/developer/hid_remote/Makefile =================================================================== --- tags/2.1.2/doc/developer/hid_remote/Makefile (nonexistent) +++ tags/2.1.2/doc/developer/hid_remote/Makefile (revision 24813) @@ -0,0 +1,9 @@ +proto_parse.svg: proto_parse.dot fixlab.sh + ./fixlab.sh < proto_parse.dot > .proto_parse.dot + dot -Tsvg .proto_parse.dot > proto_parse.svg + + +proto_parse.png: proto_parse.dot fixlab.sh + ./fixlab.sh < proto_parse.dot > .proto_parse.dot + dot -Tpng .proto_parse.dot > proto_parse.png + Index: tags/2.1.2/doc/developer/hid_remote/fixlab.sh =================================================================== --- tags/2.1.2/doc/developer/hid_remote/fixlab.sh (nonexistent) +++ tags/2.1.2/doc/developer/hid_remote/fixlab.sh (revision 24813) @@ -0,0 +1,43 @@ +#!/bin/sh +awk ' +($2 == "->") { + + if (NF > 3) { + attr=$0 + if (!(attr ~ "[[]")) + attr = attr "[]" + } + else + attr = "[]" + + tmp = "lbl" (++lbl) + if (attr ~ "label") + extra_label="" + else + extra_label="label=\"\"" + + tmp_attr = attr + attr1=attr + attr2=attr + + if (extra_label == "") + sub("^[^[]*[[]", "[style=filled fillcolor=\"#fefefe\" shape=plaintext ", tmp_attr) + else { +# tmp_attr = "[fixedsize=true width=0 shape=plaintext " extra_label "]" + print $0 + next + } + + sub("^[^[]*[[]", "[", attr1) + sub("^[^[]*[[]", "[", attr2) + sub("label=\".*\"", "", attr1) + sub("label=\".*\"", "", attr2) + sub("[[]", "[arrowhead=none ", attr1) + + print tmp, tmp_attr + print $1, "->", tmp, attr1 + print tmp, "->", $3, attr2 + next +} +{ print $0 } +' \ No newline at end of file Property changes on: tags/2.1.2/doc/developer/hid_remote/fixlab.sh ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/2.1.2/doc/developer/hid_remote/proto_high.html =================================================================== --- tags/2.1.2/doc/developer/hid_remote/proto_high.html (nonexistent) +++ tags/2.1.2/doc/developer/hid_remote/proto_high.html (revision 24813) @@ -0,0 +1,237 @@ + + +

remote HID protocol, high level

+ +

reference

+ +

ver(protver)

+Sends the protocol version the server will speak. If the client doesn't +support that version, it should break the connection. +

+Arguments: +

    +
  • protver: an integer value; 1 for the current version +
+ +

unit(abbrev)

+Sends the coordinate unit used in subsequent communication. This is not +necessarily the unit used for displaying values on the user interface, +but the unit used to interpret numeric coordinate values sent in commands. +

+Arguments: +

    +
  • abbrev: unit name abbreviation; e.g. mm or nm or mil +
+ +

ready()

+Informs the client that the server is ready to start the session. The +client needs to answer with a Ready() message before the server proceeds. +

+Arguments: none. + + +

brddim(w h)

+Announce board dimensions. Some layers may extend beyond the board. +

+Arguments: +

    +
  • w: width (x size) in coordinate units +
  • h: height (y size) in coordinate units +
+ +

inval(x1 x2 y1 y2)

+Invalidate a rectangular section of the screen; the client should redraw +this area. Clients implementing their own mechanism to keep track on +drawing are free to ignore these requests +

+Arguments: +

    +
  • x1: left coordinate +
  • x2: right coordinate +
  • y1: top coordinate +
  • y2: bottom coordinate +
+ +

inval()

+Same as inval(x1 x2 y1 y2) but invalidates the whole screen. +

+Arguments: none + +

newlg(name group_id flags)

+Create a new layer group. +

+Arguments: +

    +
  • name: name of the layer group - names are not unique +
  • group_id: unique group ID (decimal integer, may be large) +
  • flags: a list of 3 items: location, purpose and properties. Each item is a list of values (or an empty list). +
+

+Example: +

+newlg(topassembly 16777219 ((top) (assy) (virtual)))
+
+Creates the top assembly virtual layer with ID 16777219 with the name +of "topassembly" + +

newly(name layer_id group_id)

+Create a new layer within an existing layer group. +

+Arguments: +

    +
  • name: name of the layer (can be empty, not unique) +
  • layer_id: unique ID of this layer (decimal integer, may be large) +
  • group_id: reference to a previously created layer group which this layer is part of +
+

+Example: +

+newly(soldergnd 3 11)
+
+Creates a layer 3 called "soldergnd" in group 11. + +

setlg(group_id is_empty purpose)

+Inform the client that the next set of drawing commands are for a specific +layer group. (Note: the reason for announcing groups and not layers: +all layers in that group are drawn at once; visibility +of layers within the same group are switched together.) +

+Arguments: +

    +
  • group_id: unique ID of the layer group +
  • is_empty: 1 if the layer group may be empty, 0 if the layer is not empty (TODO: this bit is not 100% reliable yet) +
  • purpose: layer group purpose field (usefil in mech/doc groups) +
+ +

makeGC()

+Request the client to make a new graphical context. The client should +allocate a GC and return an integer ID using the MadeGC(ID) message. +The ID uniquely identifies the GC; it should be small positive integer +(between 0 and 31 for now). +

+Arguments: none + +

delGC(ID)

+Inform the client that a given GC is not needed anymore. The server +will not reference the GC again and the GC can be destroyed (but graphics +drawn on the screen should not be affected). The ID may be reused by the +client in a subsequent madeGC() message). +

+Arguments: +

    +
  • ID: integer ID of the GC +
+ +

clr(gci colorstring)

+Change the color subsequent drawing commands of a given GC will use. +

+Arguments: +

    +
  • gci: ID of the GC +
  • colorstring: name of the color, specified in the usual "web" format: #rrggbb (with 3 hex numbers) +
+ +

cap(gci style)

+Set the line ending cap style. Note: the cap extends half-line-width beyond +the end coordinates, e.g. the end point of a line is the center of the round-cap +circle. +

+Arguments: +

    +
  • gci: ID of the GC +
  • style: r for round cap (circle), s for square cap, b for beveled (octagon) +
+ + +

linwid(gci width)

+Sets line width (pen tip diameter). +

+Arguments: +

    +
  • gci: ID of the GC +
  • width: diameter of the circular aperture of the pen in coord units +
+ +

setxor(gci state)

+Sets whether to perform "xor-drawing" for subsequent drawing commands in +the selected GC. +

+Arguments: +

    +
  • gci: ID of the GC +
  • xor: 0 means normal drawing, 1 means xor drawing +
+ + +

line(gci x1 y1 x2 y2)

+Draw a line using the current GC. The line inherits line width, color +and cap style from the GC. +

+Arguments: +

    +
  • gci: ID of the GC +
  • x1: 1st endpoint's X coord (in coord units) +
  • y1: 1st endpoint's Y coord (in coord units) +
  • x2: 2nd endpoint's X coord (in coord units) +
  • y2: 2nd endpoint's Y coord (in coord units) +
+ +

rect(gci x1 y1 x2 y2 filled)

+Draw a rectangle. The rectangle inherits only color from the GC. +

+Arguments: +

    +
  • gci: ID of the GC +
  • x1: 1st corner X coord (in coord units); x1 <= x2 +
  • y1: 1st corner Y coord (in coord units); y1 <= y2 +
  • x2: 2nd corner X coord (in coord units) +
  • y2: 2nd corner Y coord (in coord units) +
  • filled: 1 if the rectangle should be filled; a non-filled rectangle is a frame of 1 pixel wide lines +
+ + +

fcirc(gci cx cy r)

+Draw a filled circle. The circle inherits only color from the GC. +

+Arguments: +

    +
  • gci: ID of the GC +
  • cx1: center X coord (in coord units) +
  • cy1: center Y coord (in coord units) +
  • r: radius (in coord units) +
+ +

poly(gci len ptlist)

+Draw a filled polygon. The polygon inherits only color from the GC. +

+Arguments: +

    +
  • gci: ID of the GC +
  • len: number of contour points +
  • ptlist: an ordered list of (x y) coordinates (all in coord units) +
+ +

umask(m)

+"use mask" m. The server uses this message to make an announcement before it +starts drawing certain things. +

+Arguments: +

    +
  • m: mask name: +
      +
    • off: flush the buffer and return to non-mask operation. +
    • before: Polygons being drawn before clears. +
    • clear: Clearances being drawn. +
    • after: Polygons being drawn after clears. +
    +
+ + + Index: tags/2.1.2/doc/developer/hid_remote/proto_low.html =================================================================== --- tags/2.1.2/doc/developer/hid_remote/proto_low.html (nonexistent) +++ tags/2.1.2/doc/developer/hid_remote/proto_low.html (revision 24813) @@ -0,0 +1,146 @@ + + +

remote HID protocol, low level

+ +In this document bold words are tokens and italic words +are grammatic constructs. +

+The protocol is designed with the following goals in mind: +

    +
  • for simple/text data: compact, text format +
  • for simple/text data: easy to read/write manually +
  • for text with special characters: avoid quoting and escaping +
  • be able to embed binary data without having to recode it (e.g. in base64) +
  • to some extent be able to mix simple text and binary fields even within a single message +
  • predictable parsing: always know how much memory to allocate in advance +
  • minimalism - keep things as simple as possible +
+ + +

Tokens

+ +
token description +
( start a generic list +
) end a generic list +
{ start a binary list +
} end a binary list +
space element separator: space (ASCII dec 32) +
\n message separator: newline (ASCII dec 10) +
text-string short, alphanumeric string +
binary-string long and/or non-alnum string +
+ +

Grammar

+The communication is a pair of asynchronous message stream. The message +format is: +
+text-string generic-list \n
+or
+text-string binary-list \n
+or
+# comment \n
+
+

+where text-string is a command and generic-list is a list and holds +the arguments of. The command name can not start with a hash mark ('#') and +can not be empty. The list is the argument tree of the command. +

+As a special exception, a line may start with a hash mark ('#') to indicate +a comment. Characters up to the first newline are ignored. +

+Optional: a tolerant parser also accepts empty lines and whitespace before +a message. +

+The language has two type of lists: generic and binary. +A generic list is wrapped in parenthesis () and its children are: +

    +
  • text-string, +
  • generic-list, +
  • binary-list. +
+A binary-list is wrapped in braces {} and its children are: +
    +
  • binary-string, +
  • binary-list. +
+

+Any list can be empty. There's no whitespace after the opening token and +before the closing token, so the empty generic-list and the empty binary-list +are written as, respectively: +

+()
+{}
+
+Subsequent fields of a list has a single space in between, for +separation (this is an intentional redundancy for a binary-list). +

+Note: a generic-list can host text and binary children, but a +binary list can not host only binary children. This means if a node +of the parse tree is a binary list, the subtree will contain only binary nodes. +

+A text-string contains only English alphanumeric characters (A..Z, a..z, +0..9), underscores (_), plus and minus signs (+, -) periods (.) and +the hash mark ('#') and is at most 16 characters long. +

+A binary string encodes the length of the payload in base64 (A..Z, a..z, +, /), +has a '=' for separator then the payload in binary format. For example +

+F=hello
+
+means the 5 characters long string "hello". The maximum size of the base64 +encoded length field is 5, thus the longest binary data that can be +packed in a single field is 1 gigabyte. + +

Examples

+ +

empty-argument messages

+
+hello()\n
+foo{}\n
+
+ +

single-argument messages

+Text and binary alternative for the same content: +
+hello(world)\n
+hello{F=world}\n
+
+ +

multi-argument messages

+Text and binary alternative for the same content: +
+print(hello world !)\n
+print{E=hello F=world B=!}\n
+
+ +Note: using space between list items; don't space +before the first or after the last argument. Always emit one space between +any two list items. + +

lists in list

+Text and binary alternatives for the same content: +
+line((14.55 3.1) (44.2 0) 5)\n
+line({F=14.55 D=3.1} (44.2 0) 5)\n
+line((14.55 3.1) {E=44.2 B=0} 5)\n
+line({F=14.55 D=3.1} {E=44.2 B=0} 5)\n
+line{{F=14.55 D=3.1} {E=44.2 B=0} B=5}\n
+
+The subtree assumed in this fictional message is two x;y coordinate pairs +and a line width. In other words the arguments of line is a list (start +point), another list (end point) and a scalar (width). +

+Since all data comply to the text-string token format, +the first, simplest format is recommended. The other 4 lines demonstrate all +other valid variants. +

+It is important to note that there are constraints (derived from +the grammar) on choosing which list items can be encoded in binary: +

    +
  • a binary-string can be only on a binary-list +
  • a text-string can be only on a generic-list +
  • a generic-list can not be only under a binary-list +
+Thus if the 3rd argument, (width in this example), must be encoded as a +binary-string, it will turn it's parent, line's argument list +binary too, which in turn enforces all arguments to be binary. Index: tags/2.1.2/doc/developer/hid_remote/proto_parse.dot =================================================================== --- tags/2.1.2/doc/developer/hid_remote/proto_parse.dot (nonexistent) +++ tags/2.1.2/doc/developer/hid_remote/proto_parse.dot (revision 24813) @@ -0,0 +1,84 @@ +digraph parse_state_macine { + + +MSG [label="MSG:\nmessage lead-in\nor\nbetween\nmessages" shape=box style=filled fillcolor=yellow] +COMMENT [label="COMMENT:\nskipping comment" shape=box style=filled fillcolor=yellow] +CMD [label="CMD:\nparsing command name" shape=box style=filled fillcolor=yellow] +TSTR [label="TSTR:\nparsing test string" shape=box style=filled fillcolor=yellow] +BSTR [label="BSTR:\nparsing bin string" shape=box style=filled fillcolor=yellow] +LIST [label="LIST:\nin list" shape=box style=filled fillcolor=yellow] +ERROR [label="ERROR:\nbad input" shape=box style=filled fillcolor=red] + +######## MSG + +init [shape="diamond" style=filled fillcolor=yellow] +init -> MSG + +msg_append [label="store 1st\ncommand char"] + +MSG -> COMMENT [label="input==#" color=blue] +MSG -> MSG [label="input==\\r\\n\\t\nspace" color=blue] +MSG -> ERROR [label="input==binary"] +MSG -> msg_append [label="input==text"] +msg_append -> CMD + +######## COMMENT + +COMMENT -> MSG [label="input==\\n" color=blue] +COMMENT -> COMMENT [color=blue] + + +######## CMD +cmd_list_new [label="create new list\nmake it arg tree\nroot and current"] +cmd_list_new -> LIST +cmd_append [label="append a character\nto command name"] +cmd_append -> CMD [label="command name length\nis less than 16"] +cmd_append -> ERROR [label="command name length\nis more than 16"] +CMD -> cmd_list_new [label="input==({"] +CMD -> ERROR [label="input==binary"] +CMD -> cmd_append [label="input==text"] + +######## LIST +got_msg [label="message fully parsed\nexecute message" style=filled fillcolor=cyan] +got_msg -> MSG +pop [label="pop:\ncurrent_list = current_list->parent"] +pop -> got_msg [label="input=\\n\nand\ncurrent_list == NULL\n(arg root closed)"] +pop -> ERROR [label="input!=\\n\nand\ncurrent_list == NULL\n(unbalanced parenthesis)"] +pop -> LIST +push [label="push:\create new list\nappend it as current's sibling\nmake it current"] +push->LIST +new_str [label="create a new bin or text string\nnode and append it to\nthe current list"] +new_str -> tstr_append [label="current is generic list"] +new_str -> bstr_append [label="current is binary list"] + +LIST -> pop [label="input==)}"] +LIST -> push [label="input==({"] +LIST -> LIST [label="input==space\n(ignore)"] +LIST -> ERROR [label="input!=\\n and current == NULL\n(unbalanced parenthesis)"] +LIST -> new_str [label="input==text"] + +######## TSTR +str_fin [label="finish current string\n"] +str_fin -> LIST +str_fin_pop [label="finish current string\n"] +str_fin_pop -> pop +tstr_append [label="append to current string\n"] +tstr_append -> ERROR [label="string length > 16"] +tstr_append -> TSTR +TSTR -> str_fin [label="input==space"] +TSTR -> str_fin_pop [label="input==)}"] +TSTR -> ERROR [label="input==binary"] +TSTR -> tstr_append [label="input==text"] + +######## BSTR +read_base64 [label="store next digit\nof string length"] +read_base64 -> BSTR +bstr_append -> BSTR +BSTR -> read_base64 [label="before the ="] +BSTR -> bstr_append [label="after the ="] +BSTR -> str_fin_pop [label="last char of the string"] + +######## ERR +ERROR -> ERROR [label="can't recover"] + +} Index: tags/2.1.2/doc/developer/hid_remote/proto_parse.html =================================================================== --- tags/2.1.2/doc/developer/hid_remote/proto_parse.html (nonexistent) +++ tags/2.1.2/doc/developer/hid_remote/proto_parse.html (revision 24813) @@ -0,0 +1,38 @@ + + +Protocol parser state machine of the reference implementation: + +Legend: +
    +
  • yellow boxes are states +
  • blue arrows are optional features for a more tolerant parser +
  • round nodes are actions that shall be taken +
  • arrow with text: execute action or switch state if condition is true +
  • arrow without text: do this if no other condition is met +
+

Notes on the reference implementation

+The reference implementation builds a tree of nodes for the arguments. +Each node is either a list or a text. A node has a pointer to its parent, its +first child and its next sibling. While parsing list-of-lists, the parser +keeps a current node. A new node is either added as the last sibling of +the current node (new argument on a list) or as the first +child of the current node (first argument of a new list when the list is +open). +

+When a list is closed, the parent of the current node becomes the +new current node. +

+When parsing a new message, the current node is NULL until the argument list +is open; the new current node also becomes the argument tree root. +If the argument tree root is closed, a newline shall follow, because that's +how a message is terminated. +

+The binary string part of the state machine has 2 more internal +states: +

    +
  • a boolean indicating whether we are parsing the length or the string (before or after the '=') +
  • an integer string length +
+ + + Index: tags/2.1.2/doc/developer/hid_remote/proto_parse.svg =================================================================== --- tags/2.1.2/doc/developer/hid_remote/proto_parse.svg (nonexistent) +++ tags/2.1.2/doc/developer/hid_remote/proto_parse.svg (revision 24813) @@ -0,0 +1,597 @@ + + + + + + +parse_state_macine + + +MSG + +MSG: +message lead-in +or +between +messages + + +lbl2 + +input==# + + +MSG->lbl2 + + + +lbl3 + +input==\r\n\t +space + + +MSG->lbl3 + + + +lbl4 + +input==binary + + +MSG->lbl4 + + + +lbl5 + +input==text + + +MSG->lbl5 + + + +COMMENT + +COMMENT: +skipping comment + + +COMMENT->COMMENT + + + + +lbl7 + +input==\n + + +COMMENT->lbl7 + + + +CMD + +CMD: +parsing command name + + +lbl12 + +input==({ + + +CMD->lbl12 + + + +lbl13 + +input==binary + + +CMD->lbl13 + + + +lbl14 + +input==text + + +CMD->lbl14 + + + +TSTR + +TSTR: +parsing test string + + +lbl30 + +input==space + + +TSTR->lbl30 + + + +lbl31 + +input==)} + + +TSTR->lbl31 + + + +lbl32 + +input==binary + + +TSTR->lbl32 + + + +lbl33 + +input==text + + +TSTR->lbl33 + + + +BSTR + +BSTR: +parsing bin string + + +lbl36 + +before the = + + +BSTR->lbl36 + + + +lbl37 + +after the = + + +BSTR->lbl37 + + + +lbl38 + +last char of the string + + +BSTR->lbl38 + + + +LIST + +LIST: +in list + + +lbl21 + +input==)} + + +LIST->lbl21 + + + +lbl22 + +input==({ + + +LIST->lbl22 + + + +lbl23 + +input==space +(ignore) + + +LIST->lbl23 + + + +lbl24 + +input!=\n and current == NULL +(unbalanced parenthesis) + + +LIST->lbl24 + + + +lbl25 + +input==text + + +LIST->lbl25 + + + +ERROR + +ERROR: +bad input + + +lbl39 + +can't recover + + +ERROR->lbl39 + + + +init + +init + + +init->MSG + + + + +msg_append + +store 1st +command char + + +msg_append->CMD + + + + +lbl2->COMMENT + + + + +lbl3->MSG + + + + +lbl4->ERROR + + + + +lbl5->msg_append + + + + +lbl7->MSG + + + + +cmd_list_new + +create new list +make it arg tree +root and current + + +cmd_list_new->LIST + + + + +cmd_append + +append a character +to command name + + +lbl10 + +command name length +is less than 16 + + +cmd_append->lbl10 + + + +lbl11 + +command name length +is more than 16 + + +cmd_append->lbl11 + + + +lbl10->CMD + + + + +lbl11->ERROR + + + + +lbl12->cmd_list_new + + + + +lbl13->ERROR + + + + +lbl14->cmd_append + + + + +got_msg + +message fully parsed +execute message + + +got_msg->MSG + + + + +pop + +pop: +current_list = current_list->parent + + +pop->LIST + + + + +lbl16 + +input=\n +and +current_list == NULL +(arg root closed) + + +pop->lbl16 + + + +lbl17 + +input!=\n +and +current_list == NULL +(unbalanced parenthesis) + + +pop->lbl17 + + + +lbl16->got_msg + + + + +lbl17->ERROR + + + + +push + +push:create new list +append it as current's sibling +make it current + + +push->LIST + + + + +new_str + +create a new bin or text string +node and append it to +the current list + + +lbl19 + +current is generic list + + +new_str->lbl19 + + + +lbl20 + +current is binary list + + +new_str->lbl20 + + + +tstr_append + +append to current string + + +lbl19->tstr_append + + + + +tstr_append->TSTR + + + + +lbl28 + +string length > 16 + + +tstr_append->lbl28 + + + +bstr_append + +bstr_append + + +lbl20->bstr_append + + + + +bstr_append->BSTR + + + + +lbl21->pop + + + + +lbl22->push + + + + +lbl23->LIST + + + + +lbl24->ERROR + + + + +lbl25->new_str + + + + +str_fin + +finish current string + + +str_fin->LIST + + + + +str_fin_pop + +finish current string + + +str_fin_pop->pop + + + + +lbl28->ERROR + + + + +lbl30->str_fin + + + + +lbl31->str_fin_pop + + + + +lbl32->ERROR + + + + +lbl33->tstr_append + + + + +read_base64 + +store next digit +of string length + + +read_base64->BSTR + + + + +lbl36->read_base64 + + + + +lbl37->bstr_append + + + + +lbl38->str_fin_pop + + + + +lbl39->ERROR + + + + + Index: tags/2.1.2/doc/developer/hid_render_comp.html =================================================================== --- tags/2.1.2/doc/developer/hid_render_comp.html (nonexistent) +++ tags/2.1.2/doc/developer/hid_render_comp.html (revision 24813) @@ -0,0 +1,128 @@ + + +

HID: rendering vs. composite layers

+

+All rendering is driven by the core. The core understands the PCB stackup, +layers, layer groups, compositions within the layer groups, extra labels, +layer visibility, etc. The HID is a slave device that takes drawing +instructions and blindly executes them. +

+However, the HID has a chance to alter which layer groups are drawn, using +the set_layer_group hooks return value. + +

Bursts and layer groups

+

+The rendering is done in bursts. A burst may redraw only a small window +of the screen. Each bursts draws multiple layer groups, in Z-order, from +bottom (furthest from the eye of the user) to up (closest to the eye of +the user). Each layer group is drawn on a transparent sketch canvas. In positive mode, +objects are drawn with multiple colors on each sketch canvas. In negative mode +pixels are erased from the sketch canvas, making the affected pixels transparent again. Drawing +on a layer group (either positively or negatively) should +overwrite pixels on the same layer group. In other words, there's +no translucency between two overlapping objects drawn on the same layer +group. + +

+There is a so called output canvas, which shall be cleared to +the background color upon render_burst / start. The background +color shall be fetched from the config tree (appearance/color/background). +

+The following steps are taken by the core in a burst: +

    +
  • 1. call to the render_burst hook with start +
  • 2. set_layer_group is called for the next layer; depending on the return value, the core will skip to step 7. +
  • 3. set_drawing_mode is called with reset +
  • 4. set_drawing_mode is called with positive or negative to set draw or erase +
  • 5. objects are drawn +
  • 6. if there are subsequent composite layers, the core will jump back to 3. +
  • 7. set_drawing_mode is called with flush +
  • 8. if there are further groups, the core jumps back to step 3. +
  • 9. call to the render_burst hook with end +
+

+When set_drawing_mode / reset is called, the HID needs to +create a new sketch canvas, all pixels initialized to transparent. The +core may switch between positive and negative draw any time. When +set_drawing_mode / flush is called, the current sketch +canvas needs to be blitted onto the output (in a HID-specific way) and +the sketch canvas can be destroyed. The output canvas shall be flushed to +the screen upon render_burst / end. +

+Optional optimization: the most common case is when only positively drawn +layers are used to draw the final output. Drawing on separate sketch canvases and +blitting them onto an output buffer is a waste in this setup. To give HIDs a +chance to avoid the extra copies, set_drawing_mode calls have an +argument called direct. When the direct is set, it is safe +to directly draw on the output canvas, without allocating a sketch canvas. The +core guarantees the followings: +

    +
  • all calls of set_drawing_mode within drawing a layer group will have the same direct argument +
  • if direct is set for a layer group, set_drawing_mode will not be called with negative +
  • only the first N consecutive layer groups can be direct; once a group is drawn with direct unset, all subsequent groups will be drawn with direct unset +
+

+It is possible that the core would draw the whole board in direct +mode. It is safe to ignore the direct argument and always use the +more expensive, sketch-canvas+blitting method. + +

GCs

+

+The API contains Graphic Context, or GC for short. A GC is a pen with +properties like color and tip shape. The core will initialize multiple +GCs for the drawing and will pass a GC pointer with each drawing command. +

+Note: this concept is orthogonal to the above canvas based drawing. +Regardless of which GC is used, the object being drawn always ends up +making modifications to the currently active (sketch) canvas. +

+A GC can be initialized only after render_burst / start +and all GCs will be uninitialized before render_burst / end. + +

colors

+

+In negative drawing mode, drawing an object always clear on the current canvas, +regardless of the GC color. +

+In positive drawing mode, objects are drawn with whatever color the +current GC has. The special color "drill" is used to draw holes that go thru +all layers of the board. It is possible that a drill is drawn over existing +objects and new objects are drawn on top of a drilled hole. To get the +proper order, the HID shall set the .holes_after to 1. +

+(Note: there's no "erase" color anymore.) + + +

transition

+

+When switching over an existing HID from the old use_mask() API to the new +composite API: +

    +
  • set .poly_before to 0 +
  • set .poly_after to 0 +
  • set .enable_fake_composite to 0 +
  • set .holes_after to 1 +
  • use an empty function for .use_mask for now +
+ +

XOR drawing

+

+XOR draw is used as a mean to make an object always visible, no matter +over what background it is drawns. It is not used as a cheap draw/erase +mechanism, so HIDs are free to implement it with a different algorithm - as +long as it is guaranteed that objects drawn on the same colored background +will stick out. +

+There are two places XOR draw takes place: +

    +
  • in core's normal draw procedures (pcb_hid_expose*()), as the very last + compsiting canvas (after everything else had been drawn) +
  • in pcb_draw_attached(), whenever it is called by the HID +
+

+In both cases the drawing mode is set to PCB_HID_COMP_POSITIVE_XOR, which does +not clear the direct flag. The GC that is used for drawing the actual +objects also has its xor mode set. + + + Index: tags/2.1.2/doc/developer/import.html =================================================================== --- tags/2.1.2/doc/developer/import.html (nonexistent) +++ tags/2.1.2/doc/developer/import.html (revision 24813) @@ -0,0 +1,64 @@ + + +

pcb-rnd hacking - how importers work

+ +

Introduction

+This document describes the common aspects of import code, be it an +import_ plugin or the load part of an io_plugin, importing a footprint, +loading a board or a netlist. + +

Data structures

+ +The board is stored in pcb_board_t *. Some import code, like the one +that loads a design (an io plugin's ->parse_pcb function), gets the +target in an argument. (Other, non-import code usually operate on +the global variable that represents the current board: +pcb_board_t *PCB.). +

+In either case, pcb_board_t's most important field is pcb_data_t *data, +which holds lists and vectors to store all objects on the board. When +the target is a buffer (e.g. io plugin's ->parse_element function), it's +a pcb_buffer_t *buf which also have a pcb_data_t *data containing +the same data a board could. +

+A pcb_data_t struct in turn has three sets of important fields: +

    +
  • lists for layer-independent objects (e.g. rat lines, padstacks, subcircuits) +
  • number of layers in use (LayerN) and an array of layers (see later) +
  • rtree structures - these are used for looking up objects for locations +
+Each layer is a pcb_layer_t structure. A layer has the following fields: +
    +
  • lists for lines, texts, arcs, polygons +
  • some generic layer attributes (colors, flags, key-value pairs) +
  • an rtree struct for each object type. +
+

+Any code that needs to create objects should use the functions in obj_*.h. +The functions that operate layer-independently usually get a destination as +pcb_data_t, so they can operate both on boards and buffers. A typical +example is pcb_pstk_t *pcb_pstk_new(pcb_data_t *data, ...) that returns +NULL or the pointer to the new via that is already added to the corresponding list +of data and in the rtree. +

+Layer object creation is done referencing the layer as pcb_layer_t *. A +typical example is pcb_line_t *pcb_line_new(pcb_layer_t *layer...) +which returns NULL on error or a pointer to the new line object created (inserted +in the layer's line list, added to the rtree). +

+Code should avoid manipulating the lists and rtree structures directly. + +
+
+Figure 1. simplified map of object related data structures +
+diamond: variable; rectangle: struct; round: struct field; green: drawing primitive +
+ + +

Extra steps around creating a new board

+TODO: postproc, post*, other setup + + + + Index: tags/2.1.2/doc/developer/indent.html =================================================================== --- tags/2.1.2/doc/developer/indent.html (nonexistent) +++ tags/2.1.2/doc/developer/indent.html (revision 24813) @@ -0,0 +1,36 @@ + + +

pcb-rnd - indentation

+ +As of r1022 all old code is converted using indent(1). Our preferred +coding style is close to what the following command line produces, using +our patched version of indent(1): +
+indent --line-length256 -brs -br -nce --tab-size2 -ut -npsl  -npcs -hnl -cli2 -nsaf -sai -nsaw -ncs -c0 -cd0 -cp0
+
+

+Contributors are kindly asked to follow this style or run the above +commandline on their new code before sending a patch or committing +to svn. The style of existing code lines should not be changed, +not even the "surrounding" lines to a largish patch, especially not in the +same patch/commit with actual code changes. +

+We do not put space between the pointer-asterisk and name; indent(1) +unfortunately does this in function declaration: + + +
right wrong +
int foo(char *bar); + int foo(char * bar); +
+

+We have a patch against indent 2.2.11 to +fix this. +

+We do not use tabs for aligning code in columns; we use tabs exclusively +to indicate levels logical alignment. indent(1) attempts to align the +right-side comments using tabs. We have a patch +against indent 2.2.11 to change this when column is set to 0. + + + Index: tags/2.1.2/doc/developer/indent_cmt.patch =================================================================== --- tags/2.1.2/doc/developer/indent_cmt.patch (nonexistent) +++ tags/2.1.2/doc/developer/indent_cmt.patch (revision 24813) @@ -0,0 +1,18 @@ +diff -uri indent-2.2.11.orig/src/comments.c indent-2.2.11/src/comments.c +--- indent-2.2.11.orig/src/comments.c 2018-01-26 13:45:48.474640060 +0100 ++++ indent-2.2.11/src/comments.c 2018-01-26 14:47:06.867653819 +0100 +@@ -339,7 +339,13 @@ + start_column = count_columns (compute_label_target (), s_lab, NULL_CHAR); + } + +- if (start_column < target) ++ if (target == 0) ++ { ++ /* 0 means start right after the end of the line, adding a space, no alignment */ ++ *e_com++ = ' '; ++ column++; ++ } ++ else if (start_column < target) + { + start_column = target; + } Index: tags/2.1.2/doc/developer/indent_fdecl.patch =================================================================== --- tags/2.1.2/doc/developer/indent_fdecl.patch (nonexistent) +++ tags/2.1.2/doc/developer/indent_fdecl.patch (revision 24813) @@ -0,0 +1,17 @@ +diff -uri indent-2.2.11.orig/src/handletoken.c indent-2.2.11/src/handletoken.c +--- indent-2.2.11.orig/src/handletoken.c 2018-01-26 13:45:48.477640023 +0100 ++++ indent-2.2.11/src/handletoken.c 2018-01-26 14:23:38.923255546 +0100 +@@ -677,8 +677,11 @@ + + } + #endif +- +- parser_state_tos->want_blank = true; ++ if (parser_state_tos->in_decl) ++ parser_state_tos->want_blank = false; ++ else ++ parser_state_tos->want_blank = true; ++ + } + + /** Index: tags/2.1.2/doc/developer/io_lihata_ver.html =================================================================== --- tags/2.1.2/doc/developer/io_lihata_ver.html (nonexistent) +++ tags/2.1.2/doc/developer/io_lihata_ver.html (revision 24813) @@ -0,0 +1,95 @@ + + + + pcb-rnd - io_lihata versions + + + + + +

pcb-rnd - io_lihata versions

+

+History of io_lihata, per format version. + +

lihata board

+

v1

+

+ Feature-compatible with the gEDA/PCB file format, plus allows multiple + fonts. Same assumptions on layers: last two must be the silk layers. + +

v2

+

+ Introduce the layer stack subtree and remove layer assumptions. Save + the combining field of layers. + +

v3

+

+ New global object subtree: subcircuit. Global object element has been removed. +

+ Intconn is not a flag, but a pin/pad/terminal attribute. + +

v4

+

+ New subtree under data: padstack_prototypes, for storing padstack prototypes. + ID is the place of the padstack within the list. +

+ New object type under : ha:padstack_ref.id. + +

v5

+

+ Removed drc and isle_area_nm from the board header in favor of the config + subtree. Removed the cursor section from board header - cursor position and + zoom should not be saved or loaded. +

+ Warn for the intnoconn attribute when saving pre-v5 - pcb-rnd versions + supporting v4 or lower will most probably not understand it. +

+ Layer group and network attributes. Layer colors. +

+ Optional route style via prototype ID. +

+ Optional padstack prototype name for easier user identification of prototypes. +

+ Remove old model objects: elements, element-lines, element-arcs, + pins, pads, vias. They are still loaded if they are found in v5, + but a warning is generated and the objects are force-converted to + the new model on save. + +

v6

+

+ Extended the text object fields with optional thickness and rot fields that + will be able to override the default mechanism for determining the thickness + or the n*90 degree rotation angle (with an arbitrary value). +

+ Removed the direction field from text - use the rot field instead. +

+ New route style entries for default text thickness and text scale. +

+ New layer group types PCB_LYT_DOC and PCB_LYT_MECH are handled on load + and save. +

+ Load and save purpose field in layer groups and bound layers. +

+ The layer visibility bit is not saved any more - it was reset after load so + it only added noise to the file. +

+ When saving PCB_THERMAL_NOSHAPE, mark + it explicitly by writing "noshape" instead of just leaving the + thermal shape empty. + +

lihata subcircuit

+

v4

+ Initial version, used before board v6. + +

v6

+ Used from board v6. Allows ps_proto_v6. + +

ps_proto

+

v4

+ Initial version, used before board v6. + +

v6

+ Used from board v6. Features new layer type: PCB_LYT_MECH and + new pad shape: hshadow. + + Index: tags/2.1.2/doc/developer/lihata_format/Makefile =================================================================== --- tags/2.1.2/doc/developer/lihata_format/Makefile (nonexistent) +++ tags/2.1.2/doc/developer/lihata_format/Makefile (revision 24813) @@ -0,0 +1,23 @@ +DOTS = \ + data.dot \ + geda-project-v1.dot \ + pcb-rnd-board-v.dot \ + pcb-rnd-conf-v1.dot \ + pcb-rnd-font-v1.dot \ + pcb-rnd-subcircuit-v.dot \ + submenu.dot + +all: tree.html tree.txt $(DOTS) + +%.dot: render/render.sh render/*.awk *.lht + cd render && ./render.sh dot + for n in *.dot; do dot -Tsvg $$n > $${n%%.dot}.svg; done + +tree.html: render/render.sh render/*.awk *.lht + cd render && ./render.sh html > ../tree.html + +tree.txt: tree.html + w3m -cols 256 tree.html > tree.txt + +comm_flags.lht: ../../../src/pcb-rnd render/gen_flags.sh + cd render && ./gen_flags.sh > ../comm_flags.lht Index: tags/2.1.2/doc/developer/lihata_format/comm_attribs.lht =================================================================== --- tags/2.1.2/doc/developer/lihata_format/comm_attribs.lht (nonexistent) +++ tags/2.1.2/doc/developer/lihata_format/comm_attribs.lht (revision 24813) @@ -0,0 +1,22 @@ +ha:lht_tree_doc { ha:comm { + + ha:attributes { + type=ha + hide=1 + desc { a hash of attribute key=value pairs } + li:children { + ha:attrib-key { valtype=string; desc={attribute value}} + } + } + ha:attributes_v5p { + name=attributes + hide=1 + type=ha + desc { a hash of attribute key=value pairs } + ver={>=5} + li:children { + ha:attrib-key { valtype=string; desc={attribute value}} + } + } + +}} Index: tags/2.1.2/doc/developer/lihata_format/comm_data.lht =================================================================== --- tags/2.1.2/doc/developer/lihata_format/comm_data.lht (nonexistent) +++ tags/2.1.2/doc/developer/lihata_format/comm_data.lht (revision 24813) @@ -0,0 +1,292 @@ +ha:lht_tree_doc { ha:comm { + + ha:data { + type=ha + desc { Layers and global objects of the board } + li:children { + ha:objects { + type=li + desc { List of global (non-layer/multi-layer) objects } + li:children { + ha:padstack_ref.ID { + type=ha + ver={>=4} + desc { a padstack reference (instance) placed on the board (e.g. used as a via) } + li:children { + ha:proto = { valtype=integer; desc={padstack prototype ID to use, from the parent data's proto list }} + ha:x = { valtype=coord; desc={place padstack with origin at this horizontal coordinate }} + ha:y = { valtype=coord; desc={place padstack with origin at this vertical coordinate }} + ha:clearance = { valtype=coord; desc={global clearance; if non-zero, overrides local (per shape) clearance }} + ha:rot = { valtype=angle; desc={rotation angle in degrees }} + ha:xmirror = { valtype=integer; desc={0 or 1; if 1, mirror all shapes over the x (horizontal) axis (so that y coords are flipped)}} + ha:smirror = { valtype=integer; desc={0 or 1; if 1, mirror the layer stackup: bottom becomes top, top becomes bottom (a.k.a. "place on the other side")}} + sy:attr@dup = {/lht_tree_doc/comm/attributes} + sy:flags@dup = {/lht_tree_doc/comm/flags_padstack} + ha:thermal { + type=li + desc { list of thermal shapes, per layer } + li:children { + ha:LAYERID { + type=li + desc { integer layer ID the thermal affects; each word is a boolean flag that is either present on the list or is missing; only one shape may be present } + li:children { + ha:on = { valtype=none; desc={ thermal is present on this layer; if not present, all other thermal flags are ignored on this layer }} + ha:diag = { valtype=none; desc={ thermal graphics is not axis aligned but diagonal (rotated by 45 degrees) }} + ha:round = { valtype=none; desc={ shape: rounded edge fingers }} + ha:sharp = { valtype=none; desc={ shape: sharp edge fingers }} + ha:solid = { valtype=none; desc={ shape: no thermal relief, solid connection without clearance }} + ha:noshape = { valtype=none; ver={>=6} desc={ shape: special: omit copper shape of the padstack on this layer }} + } + } + } + } + } + } + ha:via.ID { + type=ha + ver={<=4} + desc { an old via object (loaded as padstack in the new model) } + li:children { + ha:x = { valtype=coord; desc={place padstack with origin at this horizontal coordinate }} + ha:y = { valtype=coord; desc={place padstack with origin at this vertical coordinate }} + ha:thickness = { valtype=coord; desc={copper shape dimension (diameter) }} + ha:clearance = { valtype=coord; desc={copper clearance around the copper shape }} + ha:mask = { valtype=coord; desc={mask cutout shape dimension (diameter) }} + ha:hole = { valtype=coord; desc={drill/hole diameter }} + ha:name = { valtype=string; desc={optional name attribute }} + ha:number = { valtype=string; desc={for a pin (or to-be-pin) this is the terminal ID }} + sy:attr@dup = {/lht_tree_doc/comm/attributes} + sy:flags@dup = {/lht_tree_doc/comm/flags_pinvia} + } + } + } + } + ha:layers { + type=li + desc={ordered list of layers; v1 required the order to be top-bottom physically; v1 also required silk layers to be at the end (same resrtictions as in the old .pcb format; only real (non-bound) layers have attributes)} + li:children { + ha:NAME { + type=ha + desc={a logical layer} + li:children { + ha:lid = { valtype=integer; ver={>=2} desc={layer ID}} + ha:visible = { valtype=integer; ver={<6} desc={only in real (non-boud) layers: 1 if the layer is visible, 0 if not (UI setting)}} + ha:group = { valtype=integer; desc={only in real (non-boud) layers: "parent" layer group ID }} + ha:color = { valtype=string; ver={>=5} desc={ layer color on UI, in #rrggbb format }} + ha:stack_offs = { valtype=integer; desc={only in bound layers: match offset e.g. for internal copper layers}} + ha:type { + type=ha + desc={only for bound layers: try to bind to this type of layer on the host board} + sy:children {/lht_tree_doc/comm/layer_mask/children} + } + ha:purpose = { valtype=integer; ver={>=6} desc={only in bound layers: match layer group purpose}} + ha:combining { + ver={>=2} + desc={layer combination (compositing) flags} + sy:children {/lht_tree_doc/comm/combining/children} + } + sy:attr@dup = {/lht_tree_doc/comm/attributes} + ha:objects { + type=li + desc={list of drawing primitives put on this layer} + li:children { + ha:line.ID { + type=ha + desc={round cap line} + li:children { + ha:x1 = { valtype=coord; desc={line first endpoint, horizontal offset }} + ha:y1 = { valtype=coord; desc={line first endpoint, vertical offset }} + ha:x2 = { valtype=coord; desc={line second endpoint, horizontal offset }} + ha:y2 = { valtype=coord; desc={line second endpoint, vertical offset }} + ha:thickness = { valtype=coord; desc={width of the line }} + ha:clearance = { valtype=coord; desc={copper clearance around the object }} + sy:attr@dup = {/lht_tree_doc/comm/attributes} + sy:flags@dup = {/lht_tree_doc/comm/flags_line} + sy:hvthr@dup = {/lht_tree_doc/comm/thermal_heavy} + } + } + ha:arc.ID { + type=ha + desc={round cap elliptic arc (only width==height is fully supported at the moment)} + li:children { + ha:x = { valtype=coord; desc={center, X coord}} + ha:y = { valtype=coord; desc={center, Y coord}} + ha:width = { valtype=coord; desc={radius (of the centerline of the arc) in X direction }} + ha:height = { valtype=coord; desc={radius (of the centerline of the arc) in Y direction }} + ha:thickness = { valtype=coord; desc={width of the pen the arc is drawn with }} + ha:clearance = { valtype=coord; desc={copper clearance around the object }} + ha:astart = { valtype=angle; desc={ start angle}} + ha:adelta = { valtype=angle; desc={ delta angle}} + sy:attr@dup = {/lht_tree_doc/comm/attributes} + sy:flags@dup = {/lht_tree_doc/comm/flags_arc} + sy:hvthr@dup = {/lht_tree_doc/comm/thermal_heavy} + } + } + ha:polygon.ID { + type=ha + desc={polygon, as drawn (unclipped)} + li:children { + ha:clearance = { valtype=coord; ver={>=3} desc={copper clearance around the object }} + sy:attr@dup = {/lht_tree_doc/comm/attributes} + sy:flags@dup = {/lht_tree_doc/comm/flags_polygon} + sy:hvthr@dup = {/lht_tree_doc/comm/thermal_heavy} + ha:geometry { + type=li + desc={first item is the outer contour, subsequent, optional items are holes} + li:children { + ha:contour = { valtype=coordtbl; desc={2 column table of x;y coords for the outer contour}} + ha:hole = { valtype=coordtbl; desc={2 column table of x;y coords for a hole}} + } + } + } + } + ha:text.ID { + type=ha + desc={single line text object} + li:children { + ha:x = { valtype=coord; desc={placement: X coord}} + ha:y = { valtype=coord; desc={placement: Y coord}} + ha:role = { valtype=string; desc={when part of an old element, determines which of the three hardwired text object role is used (footprint, refdes or value)}} + ha:string = { valtype=string; desc={text string (payload)}} + ha:fid = { valtype=integer; desc={font ID}} + ha:scale = { valtype=integer; desc={text size scale in %}} + ha:direction = { valtype=integer; ver={<=5} desc={rotation in 90 degree steps (0 is horizontal); between -3 and +3, inclusive. Starting from v6, the rot field shall be used instead of direction}} + ha:rot = { valtype=angle; ver={>=6} desc={rotation angle in degrees, [0..360), CCW}} + ha:thickness = { valtype=coord; ver={>=6} desc={if zero, use the default width algorithm; if non-zero use this value as rotation angle in degrees}} + sy:attr@dup = {/lht_tree_doc/comm/attributes} + sy:flags@dup = {/lht_tree_doc/comm/flags_text} + } + } + } + } + } + } + } + } + ha:padstack_prototypes { + type=li + ver = {>=4} + li:children { + ha:unused = { valtype=none; desc={placeholder for markign uunsed slot to keep slot indices for early lihata v4 }} + ha:ps_proto_v4.PID { + type=ha + desc={padstack prototype specification, as introduced in lihata board v4} + li:children { + ha:hdia = { valtype=coord; desc={hole diameter; 0 means no hole }} + ha:htop = { valtype=integer; desc={hole start: copper layer index from the top (positive) or bottom (negative) copper layer (0 means top copper layer)}} + ha:hbottom = { valtype=integer; desc={hole start: copper layer index from the bottom (positive) or top (negative) copper layer (0 means bottom copper layer)}} + ha:plated = { valtype=integer; desc={0=unplated hole; 1=plated hole}} + ha:name = { valtype=string; ver={>=5} desc={optional user assigned prototype name}} + ha:shape { + type=li + desc={shape per layer type definition} + li:children { + ha:ps_shape_v4 { + type=ha + desc={shape on a specific layer type (specified by layer_mask and combining), as specifie in lihata board v4; shape is either ps_poly, ps_line or ps_circ (only one of these will present per layer type); shape coords are relative to padstack origin; layer mask shall contain one material and at most one location bit} + li:children { + sy:layer_mask@dup = {/lht_tree_doc/comm/layer_mask} + ha:combining { + desc={layer compositing match} + sy:children = {/lht_tree_doc/comm/combining/children} + } + ha:clearance = { valtype=coord; desc={local, per-layer-type clearance; applied if global padstack clearance is 0 }} + ha:ps_poly { + type=li + desc={arbitrary convex polygon shape; contains a list of x;y coordinates } + } + ha:ps_line { + type=ha + desc={straight line shape, round or square cap} + li:children { + ha:x1 = { valtype=coord; desc={line first endpoint, horizontal offset }} + ha:y1 = { valtype=coord; desc={line first endpoint, vertical offset }} + ha:x2 = { valtype=coord; desc={line second endpoint, horizontal offset }} + ha:y2 = { valtype=coord; desc={line second endpoint, vertical offset }} + ha:thickness = { valtype=coord; desc={width of the line }} + ha:square = { valtype=integer; desc={0=round cap; 1=square cap }} + } + } + ha:ps_circ { + type=ha + desc={filled circle shape} + li:children { + ha:x = { valtype=coord; desc={center, horizontal offset }} + ha:y = { valtype=coord; desc={center, vertical offset }} + ha:dia = { valtype=coord; desc={circle diameter }} + } + } + ha:ps_hshadow { + type=te + desc={hole/slot shadow} + ver={>=6} + } + } + } + } + } + } + } + } + } + sy:subc.ID@dup {/lht_tree_doc/roots/pcb-rnd-subcircuit-v*/children/subc.ID} + ha:element.ID { + type=ha + desc={an instance (full copy) of an obsolete element footprint} + ver = {<3} + li:children { + ha:x = { valtype=coord; desc={element origin (diamond), horizontal offset }} + ha:y = { valtype=coord; desc={element origin (diamond), vertical offset }} + sy:attr@dup = {/lht_tree_doc/comm/attributes} + sy:flags@dup = {/lht_tree_doc/comm/flags_element} + ha:objects { + type=li + desc={list of special objects that make up the element; lines and arcs are always on a silk layer} + li:children { + sy:line.ID = {/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/line.ID} + sy:arc.ID = {/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/arc.ID} + sy:text.ID = {/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/text.ID} + ha:pad.ID { + type=ha + desc={SMD pad emulated using a line object; becomes a rectangle (but watch out for the cap-extended length!) when the square flag is set} + li:children { + ha:x1 = { valtype=coord; desc={line first endpoint, horizontal offset }} + ha:y1 = { valtype=coord; desc={line first endpoint, vertical offset }} + ha:x2 = { valtype=coord; desc={line second endpoint, horizontal offset }} + ha:y2 = { valtype=coord; desc={line second endpoint, vertical offset }} + ha:thickness = { valtype=coord; desc={width of the line}} + ha:clearance = { valtype=coord; desc={clearance around the line}} + ha:mask = { valtype=coord; desc={size of the mask cutout, as interpreted by gEDA/PCB}} + ha:name = { valtype=string; desc={symbolic name of the pad}} + ha:number = { valtype=string; desc={"pin number" for the netlist}} + sy:attr@dup = {/lht_tree_doc/comm/attributes} + sy:flags@dup = {/lht_tree_doc/comm/flags_pad} + } + } + ha:pin.ID { + type=ha + desc={thru-hole pin; emulated as an old-style via } + sy:children = {/lht_tree_doc/comm/data/children/objects/children/via.ID} + } + } + } + } + } + ha:rat.ID { + type=ha + desc={global rat line} + li:children { + ha:x1 = { valtype=coord; desc={line first endpoint, horizontal offset }} + ha:y1 = { valtype=coord; desc={line first endpoint, vertical offset }} + ha:x2 = { valtype=coord; desc={line second endpoint, horizontal offset }} + ha:y2 = { valtype=coord; desc={line second endpoint, vertical offset }} + ha:lgrp1 = { valtype=integer; desc={first endpoint's layer group ID }} + ha:lgrp2 = { valtype=integer; desc={second endpoint's layer group ID }} + sy:attr@dup = {/lht_tree_doc/comm/attributes} + sy:flags@dup = {/lht_tree_doc/comm/flags_line} + } + } + } + } + +}} Index: tags/2.1.2/doc/developer/lihata_format/comm_flags.lht =================================================================== --- tags/2.1.2/doc/developer/lihata_format/comm_flags.lht (nonexistent) +++ tags/2.1.2/doc/developer/lihata_format/comm_flags.lht (revision 24813) @@ -0,0 +1,124 @@ +ha:lht_tree_doc { ha:comm { + ha:flags_arc { + hide=1 + name=flags + dot_group=1 + desc={flag bits of a arc} + type=ha + li:children { + ha:found { valtype=flag; desc={If set, this object has been found by FindConnection()}} + ha:clearline { valtype=flag; desc={For lines and arcs, the line/arc will clear polygons instead of connecting to them.}} + ha:selected { valtype=flag; desc={Set when the object is selected.}} + ha:auto { valtype=flag; desc={For lines and vias, indicates that these were created by the autorouter.}} + ha:rubberend { valtype=flag; desc={For lines, used internally for rubber band moves: indicates one end already rubber banding.}} + ha:drc { valtype=flag; desc={Set for objects that fail DRC: flag like FOUND flag for DRC checking.}} + ha:lock { valtype=flag; desc={Set for locked objects.}} + ha:termname { valtype=flag; desc={when set the names of pins are shown.}} + ha:floater { valtype=flag; desc={subc part can be moved after subc placing}} + } + } + ha:flags_line { + hide=1 + name=flags + dot_group=1 + desc={flag bits of a line} + type=ha + li:children { + ha:found { valtype=flag; desc={If set, this object has been found by FindConnection()}} + ha:clearline { valtype=flag; desc={For lines and arcs, the line/arc will clear polygons instead of connecting to them.}} + ha:selected { valtype=flag; desc={Set when the object is selected.}} + ha:auto { valtype=flag; desc={For lines and vias, indicates that these were created by the autorouter.}} + ha:rubberend { valtype=flag; desc={For lines, used internally for rubber band moves: indicates one end already rubber banding.}} + ha:drc { valtype=flag; desc={Set for objects that fail DRC: flag like FOUND flag for DRC checking.}} + ha:lock { valtype=flag; desc={Set for locked objects.}} + ha:termname { valtype=flag; desc={when set the names of pins are shown.}} + ha:floater { valtype=flag; desc={subc part can be moved after subc placing}} + } + } + ha:flags_polygon { + hide=1 + name=flags + dot_group=1 + desc={flag bits of a polygon} + type=ha + li:children { + ha:found { valtype=flag; desc={If set, this object has been found by FindConnection()}} + ha:clearpoly { valtype=flag; desc={For polygons, this flag means that pins and vias will normally clear these polygons (thus, thermals are required for electrical connection). When clear, polygons will solidly connect to pins and vias. }} + ha:fullpoly { valtype=flag; desc={For polygons, the full polygon is drawn (i.e. all parts instead of only the biggest one).}} + ha:selected { valtype=flag; desc={Set when the object is selected.}} + ha:drc { valtype=flag; desc={Set for objects that fail DRC: flag like FOUND flag for DRC checking.}} + ha:lock { valtype=flag; desc={Set for locked objects.}} + ha:termname { valtype=flag; desc={when set the names of pins are shown.}} + ha:clearpolypoly { valtype=flag; desc={For polygons, apply clearance to nearby polygons}} + ha:floater { valtype=flag; desc={subc part can be moved after subc placing}} + } + } + ha:flags_text { + hide=1 + name=flags + dot_group=1 + desc={flag bits of a text} + type=ha + li:children { + ha:found { valtype=flag; desc={If set, this object has been found by FindConnection()}} + ha:clearline { valtype=flag; desc={For lines and arcs, the line/arc will clear polygons instead of connecting to them.}} + ha:selected { valtype=flag; desc={Set when the object is selected.}} + ha:onsolder { valtype=flag; desc={For text, indicates that it is on the solder side.}} + ha:drc { valtype=flag; desc={Set for objects that fail DRC: flag like FOUND flag for DRC checking.}} + ha:lock { valtype=flag; desc={Set for locked objects.}} + ha:termname { valtype=flag; desc={when set the names of pins are shown.}} + ha:dyntext { valtype=flag; desc={For text: dynamic string (substitute %patterns%)}} + ha:floater { valtype=flag; desc={subc part can be moved after subc placing}} + } + } + ha:flags_subcircuit { + hide=1 + name=flags + dot_group=1 + desc={flag bits of a subcircuit} + type=ha + li:children { + ha:found { valtype=flag; desc={If set, this object has been found by FindConnection()}} + ha:selected { valtype=flag; desc={Set when the object is selected.}} + ha:drc { valtype=flag; desc={Set for objects that fail DRC: flag like FOUND flag for DRC checking.}} + ha:lock { valtype=flag; desc={Set for locked objects.}} + ha:nonetlist { valtype=flag; desc={subcircuit is not on the netlist and should not interfere with the netlist }} + ha:termname { valtype=flag; desc={when set the names of pins are shown.}} + ha:floater { valtype=flag; desc={subc part can be moved after subc placing}} + } + } + ha:flags_padstack { + hide=1 + name=flags + dot_group=1 + desc={flag bits of a padstack} + type=ha + li:children { + ha:found { valtype=flag; desc={If set, this object has been found by FindConnection()}} + ha:hole { valtype=flag; desc={For pins and vias, this flag means that the pin or via is a hole without a copper annulus.}} + ha:clearline { valtype=flag; desc={For lines and arcs, the line/arc will clear polygons instead of connecting to them.}} + ha:selected { valtype=flag; desc={Set when the object is selected.}} + ha:auto { valtype=flag; desc={For lines and vias, indicates that these were created by the autorouter.}} + ha:warn { valtype=flag; desc={For pins, vias, and pads, set to indicate a warning.}} + ha:drc { valtype=flag; desc={Set for objects that fail DRC: flag like FOUND flag for DRC checking.}} + ha:lock { valtype=flag; desc={Set for locked objects.}} + ha:termname { valtype=flag; desc={when set the names of pins are shown.}} + ha:floater { valtype=flag; desc={subc part can be moved after subc placing}} + } + } + ha:flags_ratline { + hide=1 + name=flags + dot_group=1 + desc={flag bits of a ratline} + type=ha + li:children { + ha:found { valtype=flag; desc={If set, this object has been found by FindConnection()}} + ha:rat { valtype=flag; desc={If set for a line, indicates that this line is a rat line instead of a copper trace.}} + ha:selected { valtype=flag; desc={Set when the object is selected.}} + ha:drc { valtype=flag; desc={Set for objects that fail DRC: flag like FOUND flag for DRC checking.}} + ha:lock { valtype=flag; desc={Set for locked objects.}} + ha:floater { valtype=flag; desc={subc part can be moved after subc placing}} + } + } +} } Index: tags/2.1.2/doc/developer/lihata_format/comm_flags_old.lht =================================================================== --- tags/2.1.2/doc/developer/lihata_format/comm_flags_old.lht (nonexistent) +++ tags/2.1.2/doc/developer/lihata_format/comm_flags_old.lht (revision 24813) @@ -0,0 +1,69 @@ +ha:lht_tree_doc { ha:comm { + +# these obsolete flags are only relevant in compatibility mode; +# they are not generated by the flag dump but they will not change +# thus this file is hand-written + + ha:flags_element { + hide=1 + desc={flag bits of an element} + type=ha + dot_group=1 + li:children { + ha:found { valtype=flag; desc={If set, this object has been found by FindConnection()}} + ha:selected { valtype=flag; desc={Set when the object is selected.}} + ha:auto { valtype=flag; desc={For lines and vias, indicates that these were created by the autorouter.}} + ha:drc { valtype=flag; desc={Set for objects that fail DRC: flag like FOUND flag for DRC checking.}} + ha:lock { valtype=flag; desc={Set for locked objects.}} + ha:nonetlist { valtype=flag; desc={subcircuit is not on the netlist and should not interfere with the netlist }} + ha:termname { valtype=flag; desc={when set the names of pins are shown.}} + ha:floater { valtype=flag; desc={subc part can be moved after subc placing}} + ha:onsolder { valtype=flag; desc={element is placed on the solder side}} + } + } + ha:flags_pinvia { + hide=1 + desc={flag bits of a pin or via} + type=ha + dot_group=1 + li:children { + ha:found { valtype=flag; desc={If set, this object has been found by FindConnection()}} + ha:hole { valtype=flag; desc={For pins and vias, this flag means that the pin or via is a hole without a copper annulus.}} + ha:clearline { valtype=flag; desc={For lines and arcs, the line/arc will clear polygons instead of connecting to them.}} + ha:selected { valtype=flag; desc={Set when the object is selected.}} + ha:auto { valtype=flag; desc={For lines and vias, indicates that these were created by the autorouter.}} + ha:warn { valtype=flag; desc={For pins, vias, and pads, set to indicate a warning.}} + ha:usetherm { valtype=flag; desc={Obsolete, indicates that pins/vias should be drawn with thermal fingers.}} + ha:drc { valtype=flag; desc={Set for objects that fail DRC: flag like FOUND flag for DRC checking.}} + ha:lock { valtype=flag; desc={Set for locked objects.}} + ha:nonetlist { valtype=flag; desc={subcircuit is not on the netlist and should not interfere with the netlist }} + ha:termname { valtype=flag; desc={when set the names of pins are shown.}} + ha:floater { valtype=flag; desc={subc part can be moved after subc placing}} + ha:pin { valtype=flag; desc={object is a pin (in an element)}} + ha:via { valtype=flag; desc={object is a via}} + } + } + + ha:flags_pad { + hide=1 + desc={flag bits of a pad} + type=ha + dot_group=1 + li:children { + ha:found { valtype=flag; desc={If set, this object has been found by FindConnection()}} + ha:hole { valtype=flag; desc={For pins and vias, this flag means that the pin or via is a hole without a copper annulus.}} + ha:clearline { valtype=flag; desc={For lines and arcs, the line/arc will clear polygons instead of connecting to them.}} + ha:selected { valtype=flag; desc={Set when the object is selected.}} + ha:auto { valtype=flag; desc={For lines and vias, indicates that these were created by the autorouter.}} + ha:warn { valtype=flag; desc={For pins, vias, and pads, set to indicate a warning.}} + ha:usetherm { valtype=flag; desc={Obsolete, indicates that pins/vias should be drawn with thermal fingers.}} + ha:drc { valtype=flag; desc={Set for objects that fail DRC: flag like FOUND flag for DRC checking.}} + ha:lock { valtype=flag; desc={Set for locked objects.}} + ha:nonetlist { valtype=flag; desc={subcircuit is not on the netlist and should not interfere with the netlist }} + ha:termname { valtype=flag; desc={when set the names of pins are shown.}} + ha:floater { valtype=flag; desc={subc part can be moved after subc placing}} + ha:pin { valtype=flag; desc={object is a pin (in an element)}} + ha:via { valtype=flag; desc={object is a via}} + } + } +} } Index: tags/2.1.2/doc/developer/lihata_format/comm_lyt.lht =================================================================== --- tags/2.1.2/doc/developer/lihata_format/comm_lyt.lht (nonexistent) +++ tags/2.1.2/doc/developer/lihata_format/comm_lyt.lht (revision 24813) @@ -0,0 +1,41 @@ +ha:lht_tree_doc { ha:comm { + + ha:layer_mask { + hide=1 + type=ha + desc={layer type and location} + dot_group=1 + li:children { + ha:top { valtype=flag; desc={location: top side}} + ha:bottom { valtype=flag; desc={location: bottom side}} + ha:intern { valtype=flag; desc={location: internal}} + ha:logical { valtype=flag; desc={location: logical (not in the actual stackup)}} + ha:copper { valtype=flag; desc={material: copper}} + ha:silk { valtype=flag; desc={material: silk}} + ha:mask { valtype=flag; desc={material: mask}} + ha:paste { valtype=flag; desc={material: paste}} + ha:outline { valtype=flag; desc={"material": router path (board outline, slots, cutouts) }} + ha:substrate { valtype=flag; desc={material: substrate or insulator}} + +# ha:rat { valtype=flag; desc={(virtual: rat lines)}} +# ha:invis { valtype=flag; desc={(virtual: invisible)}} +# ha:assy { valtype=flag; desc={(virtual: assembly drawing)}} +# ha:fab { valtype=flag; desc={(virtual: fab drawing)}} +# ha:plateddrill { valtype=flag; desc={(drills: plated)}} +# ha:unplateddrill { valtype=flag; desc={(drills: unplated)}} +# ha:cross-section { valtype=flag; desc={(virtual: cross section drawing)}} +# ha:misc { valtype=flag; desc={(virtual: virtual misc layer)}} +# ha:virtual { valtype=flag; desc={(if set, the layer is not a physical layer but a drawing or documentation)}} + } + } + + ha:combining { + hide=1 + dot_group=1 + li:children { + ha:sub { valtype=flag; desc={draw in negative}} + ha:auto { valtype=flag; desc={padstacks draw their paste, mask and silk objects on the first layer (of matching type) that features the auto flag}} + } + } + +}} Index: tags/2.1.2/doc/developer/lihata_format/comm_thermal.lht =================================================================== --- tags/2.1.2/doc/developer/lihata_format/comm_thermal.lht (nonexistent) +++ tags/2.1.2/doc/developer/lihata_format/comm_thermal.lht (revision 24813) @@ -0,0 +1,17 @@ +ha:lht_tree_doc { ha:comm { + + ha:thermal_heavy { + name=thermal + type=li + hide=1 + desc { list of thermal flags for heavy terminals, on the single layer the object is on } + li:children { + ha:on { valtype=none; desc={draw any thermal only if this string is present; else normal clearance is applied}} + ha:diag { valtype=none; desc={if present, the thermal is diagonal (45 degree rotated)}} + ha:round { valtype=none; desc={if present, thermal shape is rounded}} + ha:sharp { valtype=none; desc={if present, thermal shape is sharp}} + ha:solid { valtype=none; desc={if present, there is no thermal but a solid connection ("join")}} + } + } + +}} Index: tags/2.1.2/doc/developer/lihata_format/coraleda-project-v1.svg =================================================================== --- tags/2.1.2/doc/developer/lihata_format/coraleda-project-v1.svg (nonexistent) +++ tags/2.1.2/doc/developer/lihata_format/coraleda-project-v1.svg (revision 24813) @@ -0,0 +1,303 @@ + + + + + + +ha:coraleda-project-v1 + + + +/lht_tree_doc/roots/coraleda-project-v1 + + +ha:coraleda-project-v1 + + + + + +/lht_tree_doc/roots/coraleda-project-v1/children/common + + +ha:common + + + + + +/lht_tree_doc/roots/coraleda-project-v1->/lht_tree_doc/roots/coraleda-project-v1/children/common + + + + + +dup16_/lht_tree_doc/roots/coraleda-project-v1/children/pcb-rnd-conf-v1 + +pcb-rnd-conf-v1 -> + + + + + +/lht_tree_doc/roots/coraleda-project-v1->dup16_/lht_tree_doc/roots/coraleda-project-v1/children/pcb-rnd-conf-v1 + + + + + +/lht_tree_doc/roots/coraleda-project-v1/children/common/children/name + + +name +string + + + + + +/lht_tree_doc/roots/coraleda-project-v1/children/common->/lht_tree_doc/roots/coraleda-project-v1/children/common/children/name + + + + + +/lht_tree_doc/roots/coraleda-project-v1/children/common/children/desc + + +desc +string + + + + + +/lht_tree_doc/roots/coraleda-project-v1/children/common->/lht_tree_doc/roots/coraleda-project-v1/children/common/children/desc + + + + + +/lht_tree_doc/roots/coraleda-project-v1/children/common/children/url + + +url +string + + + + + +/lht_tree_doc/roots/coraleda-project-v1/children/common->/lht_tree_doc/roots/coraleda-project-v1/children/common/children/url + + + + + +/lht_tree_doc/roots/coraleda-project-v1/children/common/children/vcs + + +vcs +string + + + + + +/lht_tree_doc/roots/coraleda-project-v1/children/common->/lht_tree_doc/roots/coraleda-project-v1/children/common/children/vcs + + + + + +/lht_tree_doc/roots/coraleda-project-v1/children/common/children/contact + + +contact +string + + + + + +/lht_tree_doc/roots/coraleda-project-v1/children/common->/lht_tree_doc/roots/coraleda-project-v1/children/common/children/contact + + + + + +/lht_tree_doc/roots/coraleda-project-v1/children/common/children/files + + +li:files + + + + + +/lht_tree_doc/roots/coraleda-project-v1/children/common->/lht_tree_doc/roots/coraleda-project-v1/children/common/children/files + + + + + +/lht_tree_doc/roots/coraleda-project-v1/children/common/children/libs + + +li:libs + + + + + +/lht_tree_doc/roots/coraleda-project-v1/children/common->/lht_tree_doc/roots/coraleda-project-v1/children/common/children/libs + + + + + +/lht_tree_doc/roots/coraleda-project-v1/children/common/children/files/children/NAME + + +ha:NAME + + + + + +/lht_tree_doc/roots/coraleda-project-v1/children/common/children/files->/lht_tree_doc/roots/coraleda-project-v1/children/common/children/files/children/NAME + + + + + +/lht_tree_doc/roots/coraleda-project-v1/children/common/children/files/children/NAME/children/path + + +path +string + + + + + +/lht_tree_doc/roots/coraleda-project-v1/children/common/children/files/children/NAME->/lht_tree_doc/roots/coraleda-project-v1/children/common/children/files/children/NAME/children/path + + + + + +/lht_tree_doc/roots/coraleda-project-v1/children/common/children/files/children/NAME/children/desc + + +desc +string + + + + + +/lht_tree_doc/roots/coraleda-project-v1/children/common/children/files/children/NAME->/lht_tree_doc/roots/coraleda-project-v1/children/common/children/files/children/NAME/children/desc + + + + + +/lht_tree_doc/roots/coraleda-project-v1/children/common/children/files/children/NAME/children/type + + +type +string + + + + + +/lht_tree_doc/roots/coraleda-project-v1/children/common/children/files/children/NAME->/lht_tree_doc/roots/coraleda-project-v1/children/common/children/files/children/NAME/children/type + + + + + +/lht_tree_doc/roots/coraleda-project-v1/children/common/children/libs/children/NAME + + +ha:NAME + + + + + +/lht_tree_doc/roots/coraleda-project-v1/children/common/children/libs->/lht_tree_doc/roots/coraleda-project-v1/children/common/children/libs/children/NAME + + + + + +/lht_tree_doc/roots/coraleda-project-v1/children/common/children/libs/children/NAME/children/path + + +path +string + + + + + +/lht_tree_doc/roots/coraleda-project-v1/children/common/children/libs/children/NAME->/lht_tree_doc/roots/coraleda-project-v1/children/common/children/libs/children/NAME/children/path + + + + + +/lht_tree_doc/roots/coraleda-project-v1/children/common/children/libs/children/NAME/children/url + + +url +string + + + + + +/lht_tree_doc/roots/coraleda-project-v1/children/common/children/libs/children/NAME->/lht_tree_doc/roots/coraleda-project-v1/children/common/children/libs/children/NAME/children/url + + + + + +/lht_tree_doc/roots/coraleda-project-v1/children/common/children/libs/children/NAME/children/desc + + +desc +string + + + + + +/lht_tree_doc/roots/coraleda-project-v1/children/common/children/libs/children/NAME->/lht_tree_doc/roots/coraleda-project-v1/children/common/children/libs/children/NAME/children/desc + + + + + +/lht_tree_doc/roots/coraleda-project-v1/children/common/children/libs/children/NAME/children/type + + +type +string + + + + + +/lht_tree_doc/roots/coraleda-project-v1/children/common/children/libs/children/NAME->/lht_tree_doc/roots/coraleda-project-v1/children/common/children/libs/children/NAME/children/type + + + + + Index: tags/2.1.2/doc/developer/lihata_format/data.svg =================================================================== --- tags/2.1.2/doc/developer/lihata_format/data.svg (nonexistent) +++ tags/2.1.2/doc/developer/lihata_format/data.svg (revision 24813) @@ -0,0 +1,5216 @@ + + + + + + +ha:data + + + +/lht_tree_doc/comm/data + + +ha:data + + + + + +/lht_tree_doc/comm/data/children/objects + + +li:objects + + + + + +/lht_tree_doc/comm/data->/lht_tree_doc/comm/data/children/objects + + + + + +/lht_tree_doc/comm/data/children/layers + + +li:layers + + + + + +/lht_tree_doc/comm/data->/lht_tree_doc/comm/data/children/layers + + + + + +/lht_tree_doc/comm/data/children/padstack_prototypes + + +li:padstack_prototypes +>=4 + + + + + +/lht_tree_doc/comm/data->/lht_tree_doc/comm/data/children/padstack_prototypes + + + + + +dup40_/lht_tree_doc/roots/pcb-rnd-subcircuit-v*/children/subc.ID + + +ha:subc.ID +>=3 + + + + + +/lht_tree_doc/comm/data->dup40_/lht_tree_doc/roots/pcb-rnd-subcircuit-v*/children/subc.ID + + + + + +/lht_tree_doc/comm/data/children/element.ID + + +ha:element.ID +<3 + + + + + +/lht_tree_doc/comm/data->/lht_tree_doc/comm/data/children/element.ID + + + + + +/lht_tree_doc/comm/data/children/rat.ID + + +ha:rat.ID + + + + + +/lht_tree_doc/comm/data->/lht_tree_doc/comm/data/children/rat.ID + + + + + +/lht_tree_doc/comm/data/children/objects/children/padstack_ref.ID + + +ha:padstack_ref.ID +>=4 + + + + + +/lht_tree_doc/comm/data/children/objects->/lht_tree_doc/comm/data/children/objects/children/padstack_ref.ID + + + + + +/lht_tree_doc/comm/data/children/objects/children/via.ID + + +ha:via.ID +<=4 + + + + + +/lht_tree_doc/comm/data/children/objects->/lht_tree_doc/comm/data/children/objects/children/via.ID + + + + + +/lht_tree_doc/comm/data/children/objects/children/padstack_ref.ID/children/proto + + +proto +integer + + + + + +/lht_tree_doc/comm/data/children/objects/children/padstack_ref.ID->/lht_tree_doc/comm/data/children/objects/children/padstack_ref.ID/children/proto + + + + + +/lht_tree_doc/comm/data/children/objects/children/padstack_ref.ID/children/x + + +x +coord + + + + + +/lht_tree_doc/comm/data/children/objects/children/padstack_ref.ID->/lht_tree_doc/comm/data/children/objects/children/padstack_ref.ID/children/x + + + + + +/lht_tree_doc/comm/data/children/objects/children/padstack_ref.ID/children/y + + +y +coord + + + + + +/lht_tree_doc/comm/data/children/objects/children/padstack_ref.ID->/lht_tree_doc/comm/data/children/objects/children/padstack_ref.ID/children/y + + + + + +/lht_tree_doc/comm/data/children/objects/children/padstack_ref.ID/children/clearance + + +clearance +coord + + + + + +/lht_tree_doc/comm/data/children/objects/children/padstack_ref.ID->/lht_tree_doc/comm/data/children/objects/children/padstack_ref.ID/children/clearance + + + + + +/lht_tree_doc/comm/data/children/objects/children/padstack_ref.ID/children/rot + + +rot +angle + + + + + +/lht_tree_doc/comm/data/children/objects/children/padstack_ref.ID->/lht_tree_doc/comm/data/children/objects/children/padstack_ref.ID/children/rot + + + + + +/lht_tree_doc/comm/data/children/objects/children/padstack_ref.ID/children/xmirror + + +xmirror +integer + + + + + +/lht_tree_doc/comm/data/children/objects/children/padstack_ref.ID->/lht_tree_doc/comm/data/children/objects/children/padstack_ref.ID/children/xmirror + + + + + +/lht_tree_doc/comm/data/children/objects/children/padstack_ref.ID/children/smirror + + +smirror +integer + + + + + +/lht_tree_doc/comm/data/children/objects/children/padstack_ref.ID->/lht_tree_doc/comm/data/children/objects/children/padstack_ref.ID/children/smirror + + + + + +dup20_/lht_tree_doc/comm/attributes + + +ha:attributes + + + + + +/lht_tree_doc/comm/data/children/objects/children/padstack_ref.ID->dup20_/lht_tree_doc/comm/attributes + + + + + +dup21_/lht_tree_doc/comm/flags_padstack + + +ha:flags + + + + + +/lht_tree_doc/comm/data/children/objects/children/padstack_ref.ID->dup21_/lht_tree_doc/comm/flags_padstack + + + + + +/lht_tree_doc/comm/data/children/objects/children/padstack_ref.ID/children/thermal + + +li:thermal + + + + + +/lht_tree_doc/comm/data/children/objects/children/padstack_ref.ID->/lht_tree_doc/comm/data/children/objects/children/padstack_ref.ID/children/thermal + + + + + +dup20_/lht_tree_doc/comm/attributes/children/attrib-key + + +attrib-key +string + + + + + +dup20_/lht_tree_doc/comm/attributes->dup20_/lht_tree_doc/comm/attributes/children/attrib-key + + + + + +dup21_/lht_tree_doc/comm/flags_padstack/children/found + + +found +flag + + + + + +dup21_/lht_tree_doc/comm/flags_padstack->dup21_/lht_tree_doc/comm/flags_padstack/children/found + + + + + +dup21_/lht_tree_doc/comm/flags_padstack/children/hole + + +hole +flag + + + + + +dup21_/lht_tree_doc/comm/flags_padstack->dup21_/lht_tree_doc/comm/flags_padstack/children/hole + + + + + +dup21_/lht_tree_doc/comm/flags_padstack/children/clearline + + +clearline +flag + + + + + +dup21_/lht_tree_doc/comm/flags_padstack->dup21_/lht_tree_doc/comm/flags_padstack/children/clearline + + + + + +dup21_/lht_tree_doc/comm/flags_padstack/children/selected + + +selected +flag + + + + + +dup21_/lht_tree_doc/comm/flags_padstack->dup21_/lht_tree_doc/comm/flags_padstack/children/selected + + + + + +dup21_/lht_tree_doc/comm/flags_padstack/children/auto + + +auto +flag + + + + + +dup21_/lht_tree_doc/comm/flags_padstack->dup21_/lht_tree_doc/comm/flags_padstack/children/auto + + + + + +dup21_/lht_tree_doc/comm/flags_padstack/children/warn + + +warn +flag + + + + + +dup21_/lht_tree_doc/comm/flags_padstack->dup21_/lht_tree_doc/comm/flags_padstack/children/warn + + + + + +dup21_/lht_tree_doc/comm/flags_padstack/children/drc + + +drc +flag + + + + + +dup21_/lht_tree_doc/comm/flags_padstack->dup21_/lht_tree_doc/comm/flags_padstack/children/drc + + + + + +dup21_/lht_tree_doc/comm/flags_padstack/children/lock + + +lock +flag + + + + + +dup21_/lht_tree_doc/comm/flags_padstack->dup21_/lht_tree_doc/comm/flags_padstack/children/lock + + + + + +dup21_/lht_tree_doc/comm/flags_padstack/children/termname + + +termname +flag + + + + + +dup21_/lht_tree_doc/comm/flags_padstack->dup21_/lht_tree_doc/comm/flags_padstack/children/termname + + + + + +dup21_/lht_tree_doc/comm/flags_padstack/children/floater + + +floater +flag + + + + + +dup21_/lht_tree_doc/comm/flags_padstack->dup21_/lht_tree_doc/comm/flags_padstack/children/floater + + + + + + + + + + + + + + +/lht_tree_doc/comm/data/children/objects/children/padstack_ref.ID/children/thermal/children/LAYERID + + +li:LAYERID + + + + + +/lht_tree_doc/comm/data/children/objects/children/padstack_ref.ID/children/thermal->/lht_tree_doc/comm/data/children/objects/children/padstack_ref.ID/children/thermal/children/LAYERID + + + + + +/lht_tree_doc/comm/data/children/objects/children/padstack_ref.ID/children/thermal/children/LAYERID/children/on + + +on +none + + + + + +/lht_tree_doc/comm/data/children/objects/children/padstack_ref.ID/children/thermal/children/LAYERID->/lht_tree_doc/comm/data/children/objects/children/padstack_ref.ID/children/thermal/children/LAYERID/children/on + + + + + +/lht_tree_doc/comm/data/children/objects/children/padstack_ref.ID/children/thermal/children/LAYERID/children/diag + + +diag +none + + + + + +/lht_tree_doc/comm/data/children/objects/children/padstack_ref.ID/children/thermal/children/LAYERID->/lht_tree_doc/comm/data/children/objects/children/padstack_ref.ID/children/thermal/children/LAYERID/children/diag + + + + + +/lht_tree_doc/comm/data/children/objects/children/padstack_ref.ID/children/thermal/children/LAYERID/children/round + + +round +none + + + + + +/lht_tree_doc/comm/data/children/objects/children/padstack_ref.ID/children/thermal/children/LAYERID->/lht_tree_doc/comm/data/children/objects/children/padstack_ref.ID/children/thermal/children/LAYERID/children/round + + + + + +/lht_tree_doc/comm/data/children/objects/children/padstack_ref.ID/children/thermal/children/LAYERID/children/sharp + + +sharp +none + + + + + +/lht_tree_doc/comm/data/children/objects/children/padstack_ref.ID/children/thermal/children/LAYERID->/lht_tree_doc/comm/data/children/objects/children/padstack_ref.ID/children/thermal/children/LAYERID/children/sharp + + + + + +/lht_tree_doc/comm/data/children/objects/children/padstack_ref.ID/children/thermal/children/LAYERID/children/solid + + +solid +none + + + + + +/lht_tree_doc/comm/data/children/objects/children/padstack_ref.ID/children/thermal/children/LAYERID->/lht_tree_doc/comm/data/children/objects/children/padstack_ref.ID/children/thermal/children/LAYERID/children/solid + + + + + +/lht_tree_doc/comm/data/children/objects/children/padstack_ref.ID/children/thermal/children/LAYERID/children/noshape + + +noshape +none +>=6 + + + + + +/lht_tree_doc/comm/data/children/objects/children/padstack_ref.ID/children/thermal/children/LAYERID->/lht_tree_doc/comm/data/children/objects/children/padstack_ref.ID/children/thermal/children/LAYERID/children/noshape + + + + + +/lht_tree_doc/comm/data/children/objects/children/via.ID/children/x + + +x +coord + + + + + +/lht_tree_doc/comm/data/children/objects/children/via.ID->/lht_tree_doc/comm/data/children/objects/children/via.ID/children/x + + + + + +/lht_tree_doc/comm/data/children/objects/children/via.ID/children/y + + +y +coord + + + + + +/lht_tree_doc/comm/data/children/objects/children/via.ID->/lht_tree_doc/comm/data/children/objects/children/via.ID/children/y + + + + + +/lht_tree_doc/comm/data/children/objects/children/via.ID/children/thickness + + +thickness +coord + + + + + +/lht_tree_doc/comm/data/children/objects/children/via.ID->/lht_tree_doc/comm/data/children/objects/children/via.ID/children/thickness + + + + + +/lht_tree_doc/comm/data/children/objects/children/via.ID/children/clearance + + +clearance +coord + + + + + +/lht_tree_doc/comm/data/children/objects/children/via.ID->/lht_tree_doc/comm/data/children/objects/children/via.ID/children/clearance + + + + + +/lht_tree_doc/comm/data/children/objects/children/via.ID/children/mask + + +mask +coord + + + + + +/lht_tree_doc/comm/data/children/objects/children/via.ID->/lht_tree_doc/comm/data/children/objects/children/via.ID/children/mask + + + + + +/lht_tree_doc/comm/data/children/objects/children/via.ID/children/hole + + +hole +coord + + + + + +/lht_tree_doc/comm/data/children/objects/children/via.ID->/lht_tree_doc/comm/data/children/objects/children/via.ID/children/hole + + + + + +/lht_tree_doc/comm/data/children/objects/children/via.ID/children/name + + +name +string + + + + + +/lht_tree_doc/comm/data/children/objects/children/via.ID->/lht_tree_doc/comm/data/children/objects/children/via.ID/children/name + + + + + +/lht_tree_doc/comm/data/children/objects/children/via.ID/children/number + + +number +string + + + + + +/lht_tree_doc/comm/data/children/objects/children/via.ID->/lht_tree_doc/comm/data/children/objects/children/via.ID/children/number + + + + + +dup22_/lht_tree_doc/comm/attributes + + +ha:attributes + + + + + +/lht_tree_doc/comm/data/children/objects/children/via.ID->dup22_/lht_tree_doc/comm/attributes + + + + + +dup23_/lht_tree_doc/comm/flags_pinvia + + +ha:flags_pinvia + + + + + +/lht_tree_doc/comm/data/children/objects/children/via.ID->dup23_/lht_tree_doc/comm/flags_pinvia + + + + + +dup22_/lht_tree_doc/comm/attributes/children/attrib-key + + +attrib-key +string + + + + + +dup22_/lht_tree_doc/comm/attributes->dup22_/lht_tree_doc/comm/attributes/children/attrib-key + + + + + +dup23_/lht_tree_doc/comm/flags_pinvia/children/found + + +found +flag + + + + + +dup23_/lht_tree_doc/comm/flags_pinvia->dup23_/lht_tree_doc/comm/flags_pinvia/children/found + + + + + +dup23_/lht_tree_doc/comm/flags_pinvia/children/hole + + +hole +flag + + + + + +dup23_/lht_tree_doc/comm/flags_pinvia->dup23_/lht_tree_doc/comm/flags_pinvia/children/hole + + + + + +dup23_/lht_tree_doc/comm/flags_pinvia/children/clearline + + +clearline +flag + + + + + +dup23_/lht_tree_doc/comm/flags_pinvia->dup23_/lht_tree_doc/comm/flags_pinvia/children/clearline + + + + + +dup23_/lht_tree_doc/comm/flags_pinvia/children/selected + + +selected +flag + + + + + +dup23_/lht_tree_doc/comm/flags_pinvia->dup23_/lht_tree_doc/comm/flags_pinvia/children/selected + + + + + +dup23_/lht_tree_doc/comm/flags_pinvia/children/auto + + +auto +flag + + + + + +dup23_/lht_tree_doc/comm/flags_pinvia->dup23_/lht_tree_doc/comm/flags_pinvia/children/auto + + + + + +dup23_/lht_tree_doc/comm/flags_pinvia/children/warn + + +warn +flag + + + + + +dup23_/lht_tree_doc/comm/flags_pinvia->dup23_/lht_tree_doc/comm/flags_pinvia/children/warn + + + + + +dup23_/lht_tree_doc/comm/flags_pinvia/children/usetherm + + +usetherm +flag + + + + + +dup23_/lht_tree_doc/comm/flags_pinvia->dup23_/lht_tree_doc/comm/flags_pinvia/children/usetherm + + + + + +dup23_/lht_tree_doc/comm/flags_pinvia/children/drc + + +drc +flag + + + + + +dup23_/lht_tree_doc/comm/flags_pinvia->dup23_/lht_tree_doc/comm/flags_pinvia/children/drc + + + + + +dup23_/lht_tree_doc/comm/flags_pinvia/children/lock + + +lock +flag + + + + + +dup23_/lht_tree_doc/comm/flags_pinvia->dup23_/lht_tree_doc/comm/flags_pinvia/children/lock + + + + + +dup23_/lht_tree_doc/comm/flags_pinvia/children/nonetlist + + +nonetlist +flag + + + + + +dup23_/lht_tree_doc/comm/flags_pinvia->dup23_/lht_tree_doc/comm/flags_pinvia/children/nonetlist + + + + + +dup23_/lht_tree_doc/comm/flags_pinvia/children/termname + + +termname +flag + + + + + +dup23_/lht_tree_doc/comm/flags_pinvia->dup23_/lht_tree_doc/comm/flags_pinvia/children/termname + + + + + +dup23_/lht_tree_doc/comm/flags_pinvia/children/floater + + +floater +flag + + + + + +dup23_/lht_tree_doc/comm/flags_pinvia->dup23_/lht_tree_doc/comm/flags_pinvia/children/floater + + + + + +dup23_/lht_tree_doc/comm/flags_pinvia/children/pin + + +pin +flag + + + + + +dup23_/lht_tree_doc/comm/flags_pinvia->dup23_/lht_tree_doc/comm/flags_pinvia/children/pin + + + + + +dup23_/lht_tree_doc/comm/flags_pinvia/children/via + + +via +flag + + + + + +dup23_/lht_tree_doc/comm/flags_pinvia->dup23_/lht_tree_doc/comm/flags_pinvia/children/via + + + + + + + + + + + + + + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME + + +ha:NAME + + + + + +/lht_tree_doc/comm/data/children/layers->/lht_tree_doc/comm/data/children/layers/children/NAME + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/lid + + +lid +integer +>=2 + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME->/lht_tree_doc/comm/data/children/layers/children/NAME/children/lid + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/visible + + +visible +integer +<6 + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME->/lht_tree_doc/comm/data/children/layers/children/NAME/children/visible + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/group + + +group +integer + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME->/lht_tree_doc/comm/data/children/layers/children/NAME/children/group + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/color + + +color +string +>=5 + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME->/lht_tree_doc/comm/data/children/layers/children/NAME/children/color + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/stack_offs + + +stack_offs +integer + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME->/lht_tree_doc/comm/data/children/layers/children/NAME/children/stack_offs + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/type + + +ha:type + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME->/lht_tree_doc/comm/data/children/layers/children/NAME/children/type + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/purpose + + +purpose +integer +>=6 + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME->/lht_tree_doc/comm/data/children/layers/children/NAME/children/purpose + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/combining + + +combining +>=2 + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME->/lht_tree_doc/comm/data/children/layers/children/NAME/children/combining + + + + + +dup26_/lht_tree_doc/comm/attributes + + +ha:attributes + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME->dup26_/lht_tree_doc/comm/attributes + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects + + +li:objects + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME->/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects + + + + + +dup24_/lht_tree_doc/comm/layer_mask/children/top + + +top +flag + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/type->dup24_/lht_tree_doc/comm/layer_mask/children/top + + + + + +dup24_/lht_tree_doc/comm/layer_mask/children/bottom + + +bottom +flag + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/type->dup24_/lht_tree_doc/comm/layer_mask/children/bottom + + + + + +dup24_/lht_tree_doc/comm/layer_mask/children/intern + + +intern +flag + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/type->dup24_/lht_tree_doc/comm/layer_mask/children/intern + + + + + +dup24_/lht_tree_doc/comm/layer_mask/children/logical + + +logical +flag + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/type->dup24_/lht_tree_doc/comm/layer_mask/children/logical + + + + + +dup24_/lht_tree_doc/comm/layer_mask/children/copper + + +copper +flag + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/type->dup24_/lht_tree_doc/comm/layer_mask/children/copper + + + + + +dup24_/lht_tree_doc/comm/layer_mask/children/silk + + +silk +flag + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/type->dup24_/lht_tree_doc/comm/layer_mask/children/silk + + + + + +dup24_/lht_tree_doc/comm/layer_mask/children/mask + + +mask +flag + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/type->dup24_/lht_tree_doc/comm/layer_mask/children/mask + + + + + +dup24_/lht_tree_doc/comm/layer_mask/children/paste + + +paste +flag + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/type->dup24_/lht_tree_doc/comm/layer_mask/children/paste + + + + + +dup24_/lht_tree_doc/comm/layer_mask/children/outline + + +outline +flag + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/type->dup24_/lht_tree_doc/comm/layer_mask/children/outline + + + + + +dup24_/lht_tree_doc/comm/layer_mask/children/substrate + + +substrate +flag + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/type->dup24_/lht_tree_doc/comm/layer_mask/children/substrate + + + + + + + + + + + + + + +dup25_/lht_tree_doc/comm/combining/children/sub + + +sub +flag + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/combining->dup25_/lht_tree_doc/comm/combining/children/sub + + + + + +dup25_/lht_tree_doc/comm/combining/children/auto + + +auto +flag + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/combining->dup25_/lht_tree_doc/comm/combining/children/auto + + + + + + +dup26_/lht_tree_doc/comm/attributes/children/attrib-key + + +attrib-key +string + + + + + +dup26_/lht_tree_doc/comm/attributes->dup26_/lht_tree_doc/comm/attributes/children/attrib-key + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/line.ID + + +ha:line.ID + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects->/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/line.ID + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/arc.ID + + +ha:arc.ID + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects->/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/arc.ID + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/polygon.ID + + +ha:polygon.ID + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects->/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/polygon.ID + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/text.ID + + +ha:text.ID + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects->/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/text.ID + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/line.ID/children/x1 + + +x1 +coord + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/line.ID->/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/line.ID/children/x1 + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/line.ID/children/y1 + + +y1 +coord + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/line.ID->/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/line.ID/children/y1 + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/line.ID/children/x2 + + +x2 +coord + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/line.ID->/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/line.ID/children/x2 + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/line.ID/children/y2 + + +y2 +coord + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/line.ID->/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/line.ID/children/y2 + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/line.ID/children/thickness + + +thickness +coord + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/line.ID->/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/line.ID/children/thickness + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/line.ID/children/clearance + + +clearance +coord + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/line.ID->/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/line.ID/children/clearance + + + + + +dup27_/lht_tree_doc/comm/attributes + + +ha:attributes + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/line.ID->dup27_/lht_tree_doc/comm/attributes + + + + + +dup28_/lht_tree_doc/comm/flags_line + + +ha:flags + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/line.ID->dup28_/lht_tree_doc/comm/flags_line + + + + + +dup29_/lht_tree_doc/comm/thermal_heavy + + +li:thermal + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/line.ID->dup29_/lht_tree_doc/comm/thermal_heavy + + + + + +dup27_/lht_tree_doc/comm/attributes/children/attrib-key + + +attrib-key +string + + + + + +dup27_/lht_tree_doc/comm/attributes->dup27_/lht_tree_doc/comm/attributes/children/attrib-key + + + + + +dup28_/lht_tree_doc/comm/flags_line/children/found + + +found +flag + + + + + +dup28_/lht_tree_doc/comm/flags_line->dup28_/lht_tree_doc/comm/flags_line/children/found + + + + + +dup28_/lht_tree_doc/comm/flags_line/children/clearline + + +clearline +flag + + + + + +dup28_/lht_tree_doc/comm/flags_line->dup28_/lht_tree_doc/comm/flags_line/children/clearline + + + + + +dup28_/lht_tree_doc/comm/flags_line/children/selected + + +selected +flag + + + + + +dup28_/lht_tree_doc/comm/flags_line->dup28_/lht_tree_doc/comm/flags_line/children/selected + + + + + +dup28_/lht_tree_doc/comm/flags_line/children/auto + + +auto +flag + + + + + +dup28_/lht_tree_doc/comm/flags_line->dup28_/lht_tree_doc/comm/flags_line/children/auto + + + + + +dup28_/lht_tree_doc/comm/flags_line/children/rubberend + + +rubberend +flag + + + + + +dup28_/lht_tree_doc/comm/flags_line->dup28_/lht_tree_doc/comm/flags_line/children/rubberend + + + + + +dup28_/lht_tree_doc/comm/flags_line/children/drc + + +drc +flag + + + + + +dup28_/lht_tree_doc/comm/flags_line->dup28_/lht_tree_doc/comm/flags_line/children/drc + + + + + +dup28_/lht_tree_doc/comm/flags_line/children/lock + + +lock +flag + + + + + +dup28_/lht_tree_doc/comm/flags_line->dup28_/lht_tree_doc/comm/flags_line/children/lock + + + + + +dup28_/lht_tree_doc/comm/flags_line/children/termname + + +termname +flag + + + + + +dup28_/lht_tree_doc/comm/flags_line->dup28_/lht_tree_doc/comm/flags_line/children/termname + + + + + +dup28_/lht_tree_doc/comm/flags_line/children/floater + + +floater +flag + + + + + +dup28_/lht_tree_doc/comm/flags_line->dup28_/lht_tree_doc/comm/flags_line/children/floater + + + + + + + + + + + + + +dup29_/lht_tree_doc/comm/thermal_heavy/children/on + + +on +none + + + + + +dup29_/lht_tree_doc/comm/thermal_heavy->dup29_/lht_tree_doc/comm/thermal_heavy/children/on + + + + + +dup29_/lht_tree_doc/comm/thermal_heavy/children/diag + + +diag +none + + + + + +dup29_/lht_tree_doc/comm/thermal_heavy->dup29_/lht_tree_doc/comm/thermal_heavy/children/diag + + + + + +dup29_/lht_tree_doc/comm/thermal_heavy/children/round + + +round +none + + + + + +dup29_/lht_tree_doc/comm/thermal_heavy->dup29_/lht_tree_doc/comm/thermal_heavy/children/round + + + + + +dup29_/lht_tree_doc/comm/thermal_heavy/children/sharp + + +sharp +none + + + + + +dup29_/lht_tree_doc/comm/thermal_heavy->dup29_/lht_tree_doc/comm/thermal_heavy/children/sharp + + + + + +dup29_/lht_tree_doc/comm/thermal_heavy/children/solid + + +solid +none + + + + + +dup29_/lht_tree_doc/comm/thermal_heavy->dup29_/lht_tree_doc/comm/thermal_heavy/children/solid + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/arc.ID/children/x + + +x +coord + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/arc.ID->/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/arc.ID/children/x + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/arc.ID/children/y + + +y +coord + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/arc.ID->/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/arc.ID/children/y + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/arc.ID/children/width + + +width +coord + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/arc.ID->/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/arc.ID/children/width + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/arc.ID/children/height + + +height +coord + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/arc.ID->/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/arc.ID/children/height + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/arc.ID/children/thickness + + +thickness +coord + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/arc.ID->/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/arc.ID/children/thickness + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/arc.ID/children/clearance + + +clearance +coord + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/arc.ID->/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/arc.ID/children/clearance + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/arc.ID/children/astart + + +astart +angle + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/arc.ID->/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/arc.ID/children/astart + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/arc.ID/children/adelta + + +adelta +angle + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/arc.ID->/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/arc.ID/children/adelta + + + + + +dup30_/lht_tree_doc/comm/attributes + + +ha:attributes + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/arc.ID->dup30_/lht_tree_doc/comm/attributes + + + + + +dup31_/lht_tree_doc/comm/flags_arc + + +ha:flags + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/arc.ID->dup31_/lht_tree_doc/comm/flags_arc + + + + + +dup32_/lht_tree_doc/comm/thermal_heavy + + +li:thermal + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/arc.ID->dup32_/lht_tree_doc/comm/thermal_heavy + + + + + +dup30_/lht_tree_doc/comm/attributes/children/attrib-key + + +attrib-key +string + + + + + +dup30_/lht_tree_doc/comm/attributes->dup30_/lht_tree_doc/comm/attributes/children/attrib-key + + + + + +dup31_/lht_tree_doc/comm/flags_arc/children/found + + +found +flag + + + + + +dup31_/lht_tree_doc/comm/flags_arc->dup31_/lht_tree_doc/comm/flags_arc/children/found + + + + + +dup31_/lht_tree_doc/comm/flags_arc/children/clearline + + +clearline +flag + + + + + +dup31_/lht_tree_doc/comm/flags_arc->dup31_/lht_tree_doc/comm/flags_arc/children/clearline + + + + + +dup31_/lht_tree_doc/comm/flags_arc/children/selected + + +selected +flag + + + + + +dup31_/lht_tree_doc/comm/flags_arc->dup31_/lht_tree_doc/comm/flags_arc/children/selected + + + + + +dup31_/lht_tree_doc/comm/flags_arc/children/auto + + +auto +flag + + + + + +dup31_/lht_tree_doc/comm/flags_arc->dup31_/lht_tree_doc/comm/flags_arc/children/auto + + + + + +dup31_/lht_tree_doc/comm/flags_arc/children/rubberend + + +rubberend +flag + + + + + +dup31_/lht_tree_doc/comm/flags_arc->dup31_/lht_tree_doc/comm/flags_arc/children/rubberend + + + + + +dup31_/lht_tree_doc/comm/flags_arc/children/drc + + +drc +flag + + + + + +dup31_/lht_tree_doc/comm/flags_arc->dup31_/lht_tree_doc/comm/flags_arc/children/drc + + + + + +dup31_/lht_tree_doc/comm/flags_arc/children/lock + + +lock +flag + + + + + +dup31_/lht_tree_doc/comm/flags_arc->dup31_/lht_tree_doc/comm/flags_arc/children/lock + + + + + +dup31_/lht_tree_doc/comm/flags_arc/children/termname + + +termname +flag + + + + + +dup31_/lht_tree_doc/comm/flags_arc->dup31_/lht_tree_doc/comm/flags_arc/children/termname + + + + + +dup31_/lht_tree_doc/comm/flags_arc/children/floater + + +floater +flag + + + + + +dup31_/lht_tree_doc/comm/flags_arc->dup31_/lht_tree_doc/comm/flags_arc/children/floater + + + + + + + + + + + + + +dup32_/lht_tree_doc/comm/thermal_heavy/children/on + + +on +none + + + + + +dup32_/lht_tree_doc/comm/thermal_heavy->dup32_/lht_tree_doc/comm/thermal_heavy/children/on + + + + + +dup32_/lht_tree_doc/comm/thermal_heavy/children/diag + + +diag +none + + + + + +dup32_/lht_tree_doc/comm/thermal_heavy->dup32_/lht_tree_doc/comm/thermal_heavy/children/diag + + + + + +dup32_/lht_tree_doc/comm/thermal_heavy/children/round + + +round +none + + + + + +dup32_/lht_tree_doc/comm/thermal_heavy->dup32_/lht_tree_doc/comm/thermal_heavy/children/round + + + + + +dup32_/lht_tree_doc/comm/thermal_heavy/children/sharp + + +sharp +none + + + + + +dup32_/lht_tree_doc/comm/thermal_heavy->dup32_/lht_tree_doc/comm/thermal_heavy/children/sharp + + + + + +dup32_/lht_tree_doc/comm/thermal_heavy/children/solid + + +solid +none + + + + + +dup32_/lht_tree_doc/comm/thermal_heavy->dup32_/lht_tree_doc/comm/thermal_heavy/children/solid + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/polygon.ID/children/clearance + + +clearance +coord +>=3 + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/polygon.ID->/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/polygon.ID/children/clearance + + + + + +dup33_/lht_tree_doc/comm/attributes + + +ha:attributes + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/polygon.ID->dup33_/lht_tree_doc/comm/attributes + + + + + +dup34_/lht_tree_doc/comm/flags_polygon + + +ha:flags + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/polygon.ID->dup34_/lht_tree_doc/comm/flags_polygon + + + + + +dup35_/lht_tree_doc/comm/thermal_heavy + + +li:thermal + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/polygon.ID->dup35_/lht_tree_doc/comm/thermal_heavy + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/polygon.ID/children/geometry + + +li:geometry + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/polygon.ID->/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/polygon.ID/children/geometry + + + + + +dup33_/lht_tree_doc/comm/attributes/children/attrib-key + + +attrib-key +string + + + + + +dup33_/lht_tree_doc/comm/attributes->dup33_/lht_tree_doc/comm/attributes/children/attrib-key + + + + + +dup34_/lht_tree_doc/comm/flags_polygon/children/found + + +found +flag + + + + + +dup34_/lht_tree_doc/comm/flags_polygon->dup34_/lht_tree_doc/comm/flags_polygon/children/found + + + + + +dup34_/lht_tree_doc/comm/flags_polygon/children/clearpoly + + +clearpoly +flag + + + + + +dup34_/lht_tree_doc/comm/flags_polygon->dup34_/lht_tree_doc/comm/flags_polygon/children/clearpoly + + + + + +dup34_/lht_tree_doc/comm/flags_polygon/children/fullpoly + + +fullpoly +flag + + + + + +dup34_/lht_tree_doc/comm/flags_polygon->dup34_/lht_tree_doc/comm/flags_polygon/children/fullpoly + + + + + +dup34_/lht_tree_doc/comm/flags_polygon/children/selected + + +selected +flag + + + + + +dup34_/lht_tree_doc/comm/flags_polygon->dup34_/lht_tree_doc/comm/flags_polygon/children/selected + + + + + +dup34_/lht_tree_doc/comm/flags_polygon/children/drc + + +drc +flag + + + + + +dup34_/lht_tree_doc/comm/flags_polygon->dup34_/lht_tree_doc/comm/flags_polygon/children/drc + + + + + +dup34_/lht_tree_doc/comm/flags_polygon/children/lock + + +lock +flag + + + + + +dup34_/lht_tree_doc/comm/flags_polygon->dup34_/lht_tree_doc/comm/flags_polygon/children/lock + + + + + +dup34_/lht_tree_doc/comm/flags_polygon/children/termname + + +termname +flag + + + + + +dup34_/lht_tree_doc/comm/flags_polygon->dup34_/lht_tree_doc/comm/flags_polygon/children/termname + + + + + +dup34_/lht_tree_doc/comm/flags_polygon/children/clearpolypoly + + +clearpolypoly +flag + + + + + +dup34_/lht_tree_doc/comm/flags_polygon->dup34_/lht_tree_doc/comm/flags_polygon/children/clearpolypoly + + + + + +dup34_/lht_tree_doc/comm/flags_polygon/children/floater + + +floater +flag + + + + + +dup34_/lht_tree_doc/comm/flags_polygon->dup34_/lht_tree_doc/comm/flags_polygon/children/floater + + + + + + + + + + + + + +dup35_/lht_tree_doc/comm/thermal_heavy/children/on + + +on +none + + + + + +dup35_/lht_tree_doc/comm/thermal_heavy->dup35_/lht_tree_doc/comm/thermal_heavy/children/on + + + + + +dup35_/lht_tree_doc/comm/thermal_heavy/children/diag + + +diag +none + + + + + +dup35_/lht_tree_doc/comm/thermal_heavy->dup35_/lht_tree_doc/comm/thermal_heavy/children/diag + + + + + +dup35_/lht_tree_doc/comm/thermal_heavy/children/round + + +round +none + + + + + +dup35_/lht_tree_doc/comm/thermal_heavy->dup35_/lht_tree_doc/comm/thermal_heavy/children/round + + + + + +dup35_/lht_tree_doc/comm/thermal_heavy/children/sharp + + +sharp +none + + + + + +dup35_/lht_tree_doc/comm/thermal_heavy->dup35_/lht_tree_doc/comm/thermal_heavy/children/sharp + + + + + +dup35_/lht_tree_doc/comm/thermal_heavy/children/solid + + +solid +none + + + + + +dup35_/lht_tree_doc/comm/thermal_heavy->dup35_/lht_tree_doc/comm/thermal_heavy/children/solid + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/polygon.ID/children/geometry/children/contour + + +contour +coordtbl + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/polygon.ID/children/geometry->/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/polygon.ID/children/geometry/children/contour + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/polygon.ID/children/geometry/children/hole + + +hole +coordtbl + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/polygon.ID/children/geometry->/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/polygon.ID/children/geometry/children/hole + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/text.ID/children/x + + +x +coord + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/text.ID->/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/text.ID/children/x + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/text.ID/children/y + + +y +coord + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/text.ID->/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/text.ID/children/y + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/text.ID/children/role + + +role +string + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/text.ID->/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/text.ID/children/role + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/text.ID/children/string + + +string +string + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/text.ID->/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/text.ID/children/string + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/text.ID/children/fid + + +fid +integer + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/text.ID->/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/text.ID/children/fid + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/text.ID/children/scale + + +scale +integer + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/text.ID->/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/text.ID/children/scale + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/text.ID/children/direction + + +direction +integer +<=5 + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/text.ID->/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/text.ID/children/direction + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/text.ID/children/rot + + +rot +angle +>=6 + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/text.ID->/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/text.ID/children/rot + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/text.ID/children/thickness + + +thickness +coord +>=6 + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/text.ID->/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/text.ID/children/thickness + + + + + +dup36_/lht_tree_doc/comm/attributes + + +ha:attributes + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/text.ID->dup36_/lht_tree_doc/comm/attributes + + + + + +dup37_/lht_tree_doc/comm/flags_text + + +ha:flags + + + + + +/lht_tree_doc/comm/data/children/layers/children/NAME/children/objects/children/text.ID->dup37_/lht_tree_doc/comm/flags_text + + + + + +dup36_/lht_tree_doc/comm/attributes/children/attrib-key + + +attrib-key +string + + + + + +dup36_/lht_tree_doc/comm/attributes->dup36_/lht_tree_doc/comm/attributes/children/attrib-key + + + + + +dup37_/lht_tree_doc/comm/flags_text/children/found + + +found +flag + + + + + +dup37_/lht_tree_doc/comm/flags_text->dup37_/lht_tree_doc/comm/flags_text/children/found + + + + + +dup37_/lht_tree_doc/comm/flags_text/children/clearline + + +clearline +flag + + + + + +dup37_/lht_tree_doc/comm/flags_text->dup37_/lht_tree_doc/comm/flags_text/children/clearline + + + + + +dup37_/lht_tree_doc/comm/flags_text/children/selected + + +selected +flag + + + + + +dup37_/lht_tree_doc/comm/flags_text->dup37_/lht_tree_doc/comm/flags_text/children/selected + + + + + +dup37_/lht_tree_doc/comm/flags_text/children/onsolder + + +onsolder +flag + + + + + +dup37_/lht_tree_doc/comm/flags_text->dup37_/lht_tree_doc/comm/flags_text/children/onsolder + + + + + +dup37_/lht_tree_doc/comm/flags_text/children/drc + + +drc +flag + + + + + +dup37_/lht_tree_doc/comm/flags_text->dup37_/lht_tree_doc/comm/flags_text/children/drc + + + + + +dup37_/lht_tree_doc/comm/flags_text/children/lock + + +lock +flag + + + + + +dup37_/lht_tree_doc/comm/flags_text->dup37_/lht_tree_doc/comm/flags_text/children/lock + + + + + +dup37_/lht_tree_doc/comm/flags_text/children/termname + + +termname +flag + + + + + +dup37_/lht_tree_doc/comm/flags_text->dup37_/lht_tree_doc/comm/flags_text/children/termname + + + + + +dup37_/lht_tree_doc/comm/flags_text/children/dyntext + + +dyntext +flag + + + + + +dup37_/lht_tree_doc/comm/flags_text->dup37_/lht_tree_doc/comm/flags_text/children/dyntext + + + + + +dup37_/lht_tree_doc/comm/flags_text/children/floater + + +floater +flag + + + + + +dup37_/lht_tree_doc/comm/flags_text->dup37_/lht_tree_doc/comm/flags_text/children/floater + + + + + + + + + + + + + +/lht_tree_doc/comm/data/children/padstack_prototypes/children/unused + + +unused +none + + + + + +/lht_tree_doc/comm/data/children/padstack_prototypes->/lht_tree_doc/comm/data/children/padstack_prototypes/children/unused + + + + + +/lht_tree_doc/comm/data/children/padstack_prototypes/children/ps_proto_v4.PID + + +ha:ps_proto_v4.PID + + + + + +/lht_tree_doc/comm/data/children/padstack_prototypes->/lht_tree_doc/comm/data/children/padstack_prototypes/children/ps_proto_v4.PID + + + + + +/lht_tree_doc/comm/data/children/padstack_prototypes/children/ps_proto_v4.PID/children/hdia + + +hdia +coord + + + + + +/lht_tree_doc/comm/data/children/padstack_prototypes/children/ps_proto_v4.PID->/lht_tree_doc/comm/data/children/padstack_prototypes/children/ps_proto_v4.PID/children/hdia + + + + + +/lht_tree_doc/comm/data/children/padstack_prototypes/children/ps_proto_v4.PID/children/htop + + +htop +integer + + + + + +/lht_tree_doc/comm/data/children/padstack_prototypes/children/ps_proto_v4.PID->/lht_tree_doc/comm/data/children/padstack_prototypes/children/ps_proto_v4.PID/children/htop + + + + + +/lht_tree_doc/comm/data/children/padstack_prototypes/children/ps_proto_v4.PID/children/hbottom + + +hbottom +integer + + + + + +/lht_tree_doc/comm/data/children/padstack_prototypes/children/ps_proto_v4.PID->/lht_tree_doc/comm/data/children/padstack_prototypes/children/ps_proto_v4.PID/children/hbottom + + + + + +/lht_tree_doc/comm/data/children/padstack_prototypes/children/ps_proto_v4.PID/children/plated + + +plated +integer + + + + + +/lht_tree_doc/comm/data/children/padstack_prototypes/children/ps_proto_v4.PID->/lht_tree_doc/comm/data/children/padstack_prototypes/children/ps_proto_v4.PID/children/plated + + + + + +/lht_tree_doc/comm/data/children/padstack_prototypes/children/ps_proto_v4.PID/children/name + + +name +string +>=5 + + + + + +/lht_tree_doc/comm/data/children/padstack_prototypes/children/ps_proto_v4.PID->/lht_tree_doc/comm/data/children/padstack_prototypes/children/ps_proto_v4.PID/children/name + + + + + +/lht_tree_doc/comm/data/children/padstack_prototypes/children/ps_proto_v4.PID/children/shape + + +li:shape + + + + + +/lht_tree_doc/comm/data/children/padstack_prototypes/children/ps_proto_v4.PID->/lht_tree_doc/comm/data/children/padstack_prototypes/children/ps_proto_v4.PID/children/shape + + + + + +/lht_tree_doc/comm/data/children/padstack_prototypes/children/ps_proto_v4.PID/children/shape/children/ps_shape_v4 + + +ha:ps_shape_v4 + + + + + +/lht_tree_doc/comm/data/children/padstack_prototypes/children/ps_proto_v4.PID/children/shape->/lht_tree_doc/comm/data/children/padstack_prototypes/children/ps_proto_v4.PID/children/shape/children/ps_shape_v4 + + + + + +dup38_/lht_tree_doc/comm/layer_mask + + +ha:layer_mask + + + + + +/lht_tree_doc/comm/data/children/padstack_prototypes/children/ps_proto_v4.PID/children/shape/children/ps_shape_v4->dup38_/lht_tree_doc/comm/layer_mask + + + + + +/lht_tree_doc/comm/data/children/padstack_prototypes/children/ps_proto_v4.PID/children/shape/children/ps_shape_v4/children/combining + + +combining + + + + + +/lht_tree_doc/comm/data/children/padstack_prototypes/children/ps_proto_v4.PID/children/shape/children/ps_shape_v4->/lht_tree_doc/comm/data/children/padstack_prototypes/children/ps_proto_v4.PID/children/shape/children/ps_shape_v4/children/combining + + + + + +/lht_tree_doc/comm/data/children/padstack_prototypes/children/ps_proto_v4.PID/children/shape/children/ps_shape_v4/children/clearance + + +clearance +coord + + + + + +/lht_tree_doc/comm/data/children/padstack_prototypes/children/ps_proto_v4.PID/children/shape/children/ps_shape_v4->/lht_tree_doc/comm/data/children/padstack_prototypes/children/ps_proto_v4.PID/children/shape/children/ps_shape_v4/children/clearance + + + + + +/lht_tree_doc/comm/data/children/padstack_prototypes/children/ps_proto_v4.PID/children/shape/children/ps_shape_v4/children/ps_poly + + +li:ps_poly + + + + + +/lht_tree_doc/comm/data/children/padstack_prototypes/children/ps_proto_v4.PID/children/shape/children/ps_shape_v4->/lht_tree_doc/comm/data/children/padstack_prototypes/children/ps_proto_v4.PID/children/shape/children/ps_shape_v4/children/ps_poly + + + + + +/lht_tree_doc/comm/data/children/padstack_prototypes/children/ps_proto_v4.PID/children/shape/children/ps_shape_v4/children/ps_line + + +ha:ps_line + + + + + +/lht_tree_doc/comm/data/children/padstack_prototypes/children/ps_proto_v4.PID/children/shape/children/ps_shape_v4->/lht_tree_doc/comm/data/children/padstack_prototypes/children/ps_proto_v4.PID/children/shape/children/ps_shape_v4/children/ps_line + + + + + +/lht_tree_doc/comm/data/children/padstack_prototypes/children/ps_proto_v4.PID/children/shape/children/ps_shape_v4/children/ps_circ + + +ha:ps_circ + + + + + +/lht_tree_doc/comm/data/children/padstack_prototypes/children/ps_proto_v4.PID/children/shape/children/ps_shape_v4->/lht_tree_doc/comm/data/children/padstack_prototypes/children/ps_proto_v4.PID/children/shape/children/ps_shape_v4/children/ps_circ + + + + + +/lht_tree_doc/comm/data/children/padstack_prototypes/children/ps_proto_v4.PID/children/shape/children/ps_shape_v4/children/ps_hshadow + + +te:ps_hshadow +>=6 + + + + + +/lht_tree_doc/comm/data/children/padstack_prototypes/children/ps_proto_v4.PID/children/shape/children/ps_shape_v4->/lht_tree_doc/comm/data/children/padstack_prototypes/children/ps_proto_v4.PID/children/shape/children/ps_shape_v4/children/ps_hshadow + + + + + +dup38_/lht_tree_doc/comm/layer_mask/children/top + + +top +flag + + + + + +dup38_/lht_tree_doc/comm/layer_mask->dup38_/lht_tree_doc/comm/layer_mask/children/top + + + + + +dup38_/lht_tree_doc/comm/layer_mask/children/bottom + + +bottom +flag + + + + + +dup38_/lht_tree_doc/comm/layer_mask->dup38_/lht_tree_doc/comm/layer_mask/children/bottom + + + + + +dup38_/lht_tree_doc/comm/layer_mask/children/intern + + +intern +flag + + + + + +dup38_/lht_tree_doc/comm/layer_mask->dup38_/lht_tree_doc/comm/layer_mask/children/intern + + + + + +dup38_/lht_tree_doc/comm/layer_mask/children/logical + + +logical +flag + + + + + +dup38_/lht_tree_doc/comm/layer_mask->dup38_/lht_tree_doc/comm/layer_mask/children/logical + + + + + +dup38_/lht_tree_doc/comm/layer_mask/children/copper + + +copper +flag + + + + + +dup38_/lht_tree_doc/comm/layer_mask->dup38_/lht_tree_doc/comm/layer_mask/children/copper + + + + + +dup38_/lht_tree_doc/comm/layer_mask/children/silk + + +silk +flag + + + + + +dup38_/lht_tree_doc/comm/layer_mask->dup38_/lht_tree_doc/comm/layer_mask/children/silk + + + + + +dup38_/lht_tree_doc/comm/layer_mask/children/mask + + +mask +flag + + + + + +dup38_/lht_tree_doc/comm/layer_mask->dup38_/lht_tree_doc/comm/layer_mask/children/mask + + + + + +dup38_/lht_tree_doc/comm/layer_mask/children/paste + + +paste +flag + + + + + +dup38_/lht_tree_doc/comm/layer_mask->dup38_/lht_tree_doc/comm/layer_mask/children/paste + + + + + +dup38_/lht_tree_doc/comm/layer_mask/children/outline + + +outline +flag + + + + + +dup38_/lht_tree_doc/comm/layer_mask->dup38_/lht_tree_doc/comm/layer_mask/children/outline + + + + + +dup38_/lht_tree_doc/comm/layer_mask/children/substrate + + +substrate +flag + + + + + +dup38_/lht_tree_doc/comm/layer_mask->dup38_/lht_tree_doc/comm/layer_mask/children/substrate + + + + + + + + + + + + + + +dup39_/lht_tree_doc/comm/combining/children/sub + + +sub +flag + + + + + +/lht_tree_doc/comm/data/children/padstack_prototypes/children/ps_proto_v4.PID/children/shape/children/ps_shape_v4/children/combining->dup39_/lht_tree_doc/comm/combining/children/sub + + + + + +dup39_/lht_tree_doc/comm/combining/children/auto + + +auto +flag + + + + + +/lht_tree_doc/comm/data/children/padstack_prototypes/children/ps_proto_v4.PID/children/shape/children/ps_shape_v4/children/combining->dup39_/lht_tree_doc/comm/combining/children/auto + + + + + + +/lht_tree_doc/comm/data/children/padstack_prototypes/children/ps_proto_v4.PID/children/shape/children/ps_shape_v4/children/ps_line/children/x1 + + +x1 +coord + + + + + +/lht_tree_doc/comm/data/children/padstack_prototypes/children/ps_proto_v4.PID/children/shape/children/ps_shape_v4/children/ps_line->/lht_tree_doc/comm/data/children/padstack_prototypes/children/ps_proto_v4.PID/children/shape/children/ps_shape_v4/children/ps_line/children/x1 + + + + + +/lht_tree_doc/comm/data/children/padstack_prototypes/children/ps_proto_v4.PID/children/shape/children/ps_shape_v4/children/ps_line/children/y1 + + +y1 +coord + + + + + +/lht_tree_doc/comm/data/children/padstack_prototypes/children/ps_proto_v4.PID/children/shape/children/ps_shape_v4/children/ps_line->/lht_tree_doc/comm/data/children/padstack_prototypes/children/ps_proto_v4.PID/children/shape/children/ps_shape_v4/children/ps_line/children/y1 + + + + + +/lht_tree_doc/comm/data/children/padstack_prototypes/children/ps_proto_v4.PID/children/shape/children/ps_shape_v4/children/ps_line/children/x2 + + +x2 +coord + + + + + +/lht_tree_doc/comm/data/children/padstack_prototypes/children/ps_proto_v4.PID/children/shape/children/ps_shape_v4/children/ps_line->/lht_tree_doc/comm/data/children/padstack_prototypes/children/ps_proto_v4.PID/children/shape/children/ps_shape_v4/children/ps_line/children/x2 + + + + + +/lht_tree_doc/comm/data/children/padstack_prototypes/children/ps_proto_v4.PID/children/shape/children/ps_shape_v4/children/ps_line/children/y2 + + +y2 +coord + + + + + +/lht_tree_doc/comm/data/children/padstack_prototypes/children/ps_proto_v4.PID/children/shape/children/ps_shape_v4/children/ps_line->/lht_tree_doc/comm/data/children/padstack_prototypes/children/ps_proto_v4.PID/children/shape/children/ps_shape_v4/children/ps_line/children/y2 + + + + + +/lht_tree_doc/comm/data/children/padstack_prototypes/children/ps_proto_v4.PID/children/shape/children/ps_shape_v4/children/ps_line/children/thickness + + +thickness +coord + + + + + +/lht_tree_doc/comm/data/children/padstack_prototypes/children/ps_proto_v4.PID/children/shape/children/ps_shape_v4/children/ps_line->/lht_tree_doc/comm/data/children/padstack_prototypes/children/ps_proto_v4.PID/children/shape/children/ps_shape_v4/children/ps_line/children/thickness + + + + + +/lht_tree_doc/comm/data/children/padstack_prototypes/children/ps_proto_v4.PID/children/shape/children/ps_shape_v4/children/ps_line/children/square + + +square +integer + + + + + +/lht_tree_doc/comm/data/children/padstack_prototypes/children/ps_proto_v4.PID/children/shape/children/ps_shape_v4/children/ps_line->/lht_tree_doc/comm/data/children/padstack_prototypes/children/ps_proto_v4.PID/children/shape/children/ps_shape_v4/children/ps_line/children/square + + + + + +/lht_tree_doc/comm/data/children/padstack_prototypes/children/ps_proto_v4.PID/children/shape/children/ps_shape_v4/children/ps_circ/children/x + + +x +coord + + + + + +/lht_tree_doc/comm/data/children/padstack_prototypes/children/ps_proto_v4.PID/children/shape/children/ps_shape_v4/children/ps_circ->/lht_tree_doc/comm/data/children/padstack_prototypes/children/ps_proto_v4.PID/children/shape/children/ps_shape_v4/children/ps_circ/children/x + + + + + +/lht_tree_doc/comm/data/children/padstack_prototypes/children/ps_proto_v4.PID/children/shape/children/ps_shape_v4/children/ps_circ/children/y + + +y +coord + + + + + +/lht_tree_doc/comm/data/children/padstack_prototypes/children/ps_proto_v4.PID/children/shape/children/ps_shape_v4/children/ps_circ->/lht_tree_doc/comm/data/children/padstack_prototypes/children/ps_proto_v4.PID/children/shape/children/ps_shape_v4/children/ps_circ/children/y + + + + + +/lht_tree_doc/comm/data/children/padstack_prototypes/children/ps_proto_v4.PID/children/shape/children/ps_shape_v4/children/ps_circ/children/dia + + +dia +coord + + + + + +/lht_tree_doc/comm/data/children/padstack_prototypes/children/ps_proto_v4.PID/children/shape/children/ps_shape_v4/children/ps_circ->/lht_tree_doc/comm/data/children/padstack_prototypes/children/ps_proto_v4.PID/children/shape/children/ps_shape_v4/children/ps_circ/children/dia + + + + + +dup40_/lht_tree_doc/roots/pcb-rnd-subcircuit-v*/children/subc.ID/children/uid + + +uid +minuid + + + + + +dup40_/lht_tree_doc/roots/pcb-rnd-subcircuit-v*/children/subc.ID->dup40_/lht_tree_doc/roots/pcb-rnd-subcircuit-v*/children/subc.ID/children/uid + + + + + +dup40_/lht_tree_doc/comm/attributes + + +ha:attributes + + + + + +dup40_/lht_tree_doc/roots/pcb-rnd-subcircuit-v*/children/subc.ID->dup40_/lht_tree_doc/comm/attributes + + + + + +dup40_/lht_tree_doc/comm/flags_subcircuit + + +ha:flags + + + + + +dup40_/lht_tree_doc/roots/pcb-rnd-subcircuit-v*/children/subc.ID->dup40_/lht_tree_doc/comm/flags_subcircuit + + + + + +dup40_/lht_tree_doc/roots/pcb-rnd-subcircuit-v*/children/subc.ID/children/data + +data -> + + + + + +dup40_/lht_tree_doc/roots/pcb-rnd-subcircuit-v*/children/subc.ID->dup40_/lht_tree_doc/roots/pcb-rnd-subcircuit-v*/children/subc.ID/children/data + + + + + +dup40_/lht_tree_doc/comm/attributes/children/attrib-key + + +attrib-key +string + + + + + +dup40_/lht_tree_doc/comm/attributes->dup40_/lht_tree_doc/comm/attributes/children/attrib-key + + + + + +dup40_/lht_tree_doc/comm/flags_subcircuit/children/found + + +found +flag + + + + + +dup40_/lht_tree_doc/comm/flags_subcircuit->dup40_/lht_tree_doc/comm/flags_subcircuit/children/found + + + + + +dup40_/lht_tree_doc/comm/flags_subcircuit/children/selected + + +selected +flag + + + + + +dup40_/lht_tree_doc/comm/flags_subcircuit->dup40_/lht_tree_doc/comm/flags_subcircuit/children/selected + + + + + +dup40_/lht_tree_doc/comm/flags_subcircuit/children/drc + + +drc +flag + + + + + +dup40_/lht_tree_doc/comm/flags_subcircuit->dup40_/lht_tree_doc/comm/flags_subcircuit/children/drc + + + + + +dup40_/lht_tree_doc/comm/flags_subcircuit/children/lock + + +lock +flag + + + + + +dup40_/lht_tree_doc/comm/flags_subcircuit->dup40_/lht_tree_doc/comm/flags_subcircuit/children/lock + + + + + +dup40_/lht_tree_doc/comm/flags_subcircuit/children/nonetlist + + +nonetlist +flag + + + + + +dup40_/lht_tree_doc/comm/flags_subcircuit->dup40_/lht_tree_doc/comm/flags_subcircuit/children/nonetlist + + + + + +dup40_/lht_tree_doc/comm/flags_subcircuit/children/termname + + +termname +flag + + + + + +dup40_/lht_tree_doc/comm/flags_subcircuit->dup40_/lht_tree_doc/comm/flags_subcircuit/children/termname + + + + + +dup40_/lht_tree_doc/comm/flags_subcircuit/children/floater + + +floater +flag + + + + + +dup40_/lht_tree_doc/comm/flags_subcircuit->dup40_/lht_tree_doc/comm/flags_subcircuit/children/floater + + + + + + + + + + + +/lht_tree_doc/comm/data/children/element.ID/children/x + + +x +coord + + + + + +/lht_tree_doc/comm/data/children/element.ID->/lht_tree_doc/comm/data/children/element.ID/children/x + + + + + +/lht_tree_doc/comm/data/children/element.ID/children/y + + +y +coord + + + + + +/lht_tree_doc/comm/data/children/element.ID->/lht_tree_doc/comm/data/children/element.ID/children/y + + + + + +dup41_/lht_tree_doc/comm/attributes + + +ha:attributes + + + + + +/lht_tree_doc/comm/data/children/element.ID->dup41_/lht_tree_doc/comm/attributes + + + + + +dup42_/lht_tree_doc/comm/flags_element + + +ha:flags_element + + + + + +/lht_tree_doc/comm/data/children/element.ID->dup42_/lht_tree_doc/comm/flags_element + + + + + +/lht_tree_doc/comm/data/children/element.ID/children/objects + + +li:objects + + + + + +/lht_tree_doc/comm/data/children/element.ID->/lht_tree_doc/comm/data/children/element.ID/children/objects + + + + + +dup41_/lht_tree_doc/comm/attributes/children/attrib-key + + +attrib-key +string + + + + + +dup41_/lht_tree_doc/comm/attributes->dup41_/lht_tree_doc/comm/attributes/children/attrib-key + + + + + +dup42_/lht_tree_doc/comm/flags_element/children/found + + +found +flag + + + + + +dup42_/lht_tree_doc/comm/flags_element->dup42_/lht_tree_doc/comm/flags_element/children/found + + + + + +dup42_/lht_tree_doc/comm/flags_element/children/selected + + +selected +flag + + + + + +dup42_/lht_tree_doc/comm/flags_element->dup42_/lht_tree_doc/comm/flags_element/children/selected + + + + + +dup42_/lht_tree_doc/comm/flags_element/children/auto + + +auto +flag + + + + + +dup42_/lht_tree_doc/comm/flags_element->dup42_/lht_tree_doc/comm/flags_element/children/auto + + + + + +dup42_/lht_tree_doc/comm/flags_element/children/drc + + +drc +flag + + + + + +dup42_/lht_tree_doc/comm/flags_element->dup42_/lht_tree_doc/comm/flags_element/children/drc + + + + + +dup42_/lht_tree_doc/comm/flags_element/children/lock + + +lock +flag + + + + + +dup42_/lht_tree_doc/comm/flags_element->dup42_/lht_tree_doc/comm/flags_element/children/lock + + + + + +dup42_/lht_tree_doc/comm/flags_element/children/nonetlist + + +nonetlist +flag + + + + + +dup42_/lht_tree_doc/comm/flags_element->dup42_/lht_tree_doc/comm/flags_element/children/nonetlist + + + + + +dup42_/lht_tree_doc/comm/flags_element/children/termname + + +termname +flag + + + + + +dup42_/lht_tree_doc/comm/flags_element->dup42_/lht_tree_doc/comm/flags_element/children/termname + + + + + +dup42_/lht_tree_doc/comm/flags_element/children/floater + + +floater +flag + + + + + +dup42_/lht_tree_doc/comm/flags_element->dup42_/lht_tree_doc/comm/flags_element/children/floater + + + + + +dup42_/lht_tree_doc/comm/flags_element/children/onsolder + + +onsolder +flag + + + + + +dup42_/lht_tree_doc/comm/flags_element->dup42_/lht_tree_doc/comm/flags_element/children/onsolder + + + + + + + + + + + + + +dup43_/lht_tree_doc/comm/data/children/element.ID/children/objects/children/line.ID + +line.ID -> + + + + + +/lht_tree_doc/comm/data/children/element.ID/children/objects->dup43_/lht_tree_doc/comm/data/children/element.ID/children/objects/children/line.ID + + + + + +dup44_/lht_tree_doc/comm/data/children/element.ID/children/objects/children/arc.ID + +arc.ID -> + + + + + +/lht_tree_doc/comm/data/children/element.ID/children/objects->dup44_/lht_tree_doc/comm/data/children/element.ID/children/objects/children/arc.ID + + + + + +dup45_/lht_tree_doc/comm/data/children/element.ID/children/objects/children/text.ID + +text.ID -> + + + + + +/lht_tree_doc/comm/data/children/element.ID/children/objects->dup45_/lht_tree_doc/comm/data/children/element.ID/children/objects/children/text.ID + + + + + +/lht_tree_doc/comm/data/children/element.ID/children/objects/children/pad.ID + + +ha:pad.ID + + + + + +/lht_tree_doc/comm/data/children/element.ID/children/objects->/lht_tree_doc/comm/data/children/element.ID/children/objects/children/pad.ID + + + + + +/lht_tree_doc/comm/data/children/element.ID/children/objects/children/pin.ID + + +ha:pin.ID + + + + + +/lht_tree_doc/comm/data/children/element.ID/children/objects->/lht_tree_doc/comm/data/children/element.ID/children/objects/children/pin.ID + + + + + +/lht_tree_doc/comm/data/children/element.ID/children/objects/children/pad.ID/children/x1 + + +x1 +coord + + + + + +/lht_tree_doc/comm/data/children/element.ID/children/objects/children/pad.ID->/lht_tree_doc/comm/data/children/element.ID/children/objects/children/pad.ID/children/x1 + + + + + +/lht_tree_doc/comm/data/children/element.ID/children/objects/children/pad.ID/children/y1 + + +y1 +coord + + + + + +/lht_tree_doc/comm/data/children/element.ID/children/objects/children/pad.ID->/lht_tree_doc/comm/data/children/element.ID/children/objects/children/pad.ID/children/y1 + + + + + +/lht_tree_doc/comm/data/children/element.ID/children/objects/children/pad.ID/children/x2 + + +x2 +coord + + + + + +/lht_tree_doc/comm/data/children/element.ID/children/objects/children/pad.ID->/lht_tree_doc/comm/data/children/element.ID/children/objects/children/pad.ID/children/x2 + + + + + +/lht_tree_doc/comm/data/children/element.ID/children/objects/children/pad.ID/children/y2 + + +y2 +coord + + + + + +/lht_tree_doc/comm/data/children/element.ID/children/objects/children/pad.ID->/lht_tree_doc/comm/data/children/element.ID/children/objects/children/pad.ID/children/y2 + + + + + +/lht_tree_doc/comm/data/children/element.ID/children/objects/children/pad.ID/children/thickness + + +thickness +coord + + + + + +/lht_tree_doc/comm/data/children/element.ID/children/objects/children/pad.ID->/lht_tree_doc/comm/data/children/element.ID/children/objects/children/pad.ID/children/thickness + + + + + +/lht_tree_doc/comm/data/children/element.ID/children/objects/children/pad.ID/children/clearance + + +clearance +coord + + + + + +/lht_tree_doc/comm/data/children/element.ID/children/objects/children/pad.ID->/lht_tree_doc/comm/data/children/element.ID/children/objects/children/pad.ID/children/clearance + + + + + +/lht_tree_doc/comm/data/children/element.ID/children/objects/children/pad.ID/children/mask + + +mask +coord + + + + + +/lht_tree_doc/comm/data/children/element.ID/children/objects/children/pad.ID->/lht_tree_doc/comm/data/children/element.ID/children/objects/children/pad.ID/children/mask + + + + + +/lht_tree_doc/comm/data/children/element.ID/children/objects/children/pad.ID/children/name + + +name +string + + + + + +/lht_tree_doc/comm/data/children/element.ID/children/objects/children/pad.ID->/lht_tree_doc/comm/data/children/element.ID/children/objects/children/pad.ID/children/name + + + + + +/lht_tree_doc/comm/data/children/element.ID/children/objects/children/pad.ID/children/number + + +number +string + + + + + +/lht_tree_doc/comm/data/children/element.ID/children/objects/children/pad.ID->/lht_tree_doc/comm/data/children/element.ID/children/objects/children/pad.ID/children/number + + + + + +dup46_/lht_tree_doc/comm/attributes + + +ha:attributes + + + + + +/lht_tree_doc/comm/data/children/element.ID/children/objects/children/pad.ID->dup46_/lht_tree_doc/comm/attributes + + + + + +dup47_/lht_tree_doc/comm/flags_pad + + +ha:flags_pad + + + + + +/lht_tree_doc/comm/data/children/element.ID/children/objects/children/pad.ID->dup47_/lht_tree_doc/comm/flags_pad + + + + + +dup46_/lht_tree_doc/comm/attributes/children/attrib-key + + +attrib-key +string + + + + + +dup46_/lht_tree_doc/comm/attributes->dup46_/lht_tree_doc/comm/attributes/children/attrib-key + + + + + +dup47_/lht_tree_doc/comm/flags_pad/children/found + + +found +flag + + + + + +dup47_/lht_tree_doc/comm/flags_pad->dup47_/lht_tree_doc/comm/flags_pad/children/found + + + + + +dup47_/lht_tree_doc/comm/flags_pad/children/hole + + +hole +flag + + + + + +dup47_/lht_tree_doc/comm/flags_pad->dup47_/lht_tree_doc/comm/flags_pad/children/hole + + + + + +dup47_/lht_tree_doc/comm/flags_pad/children/clearline + + +clearline +flag + + + + + +dup47_/lht_tree_doc/comm/flags_pad->dup47_/lht_tree_doc/comm/flags_pad/children/clearline + + + + + +dup47_/lht_tree_doc/comm/flags_pad/children/selected + + +selected +flag + + + + + +dup47_/lht_tree_doc/comm/flags_pad->dup47_/lht_tree_doc/comm/flags_pad/children/selected + + + + + +dup47_/lht_tree_doc/comm/flags_pad/children/auto + + +auto +flag + + + + + +dup47_/lht_tree_doc/comm/flags_pad->dup47_/lht_tree_doc/comm/flags_pad/children/auto + + + + + +dup47_/lht_tree_doc/comm/flags_pad/children/warn + + +warn +flag + + + + + +dup47_/lht_tree_doc/comm/flags_pad->dup47_/lht_tree_doc/comm/flags_pad/children/warn + + + + + +dup47_/lht_tree_doc/comm/flags_pad/children/usetherm + + +usetherm +flag + + + + + +dup47_/lht_tree_doc/comm/flags_pad->dup47_/lht_tree_doc/comm/flags_pad/children/usetherm + + + + + +dup47_/lht_tree_doc/comm/flags_pad/children/drc + + +drc +flag + + + + + +dup47_/lht_tree_doc/comm/flags_pad->dup47_/lht_tree_doc/comm/flags_pad/children/drc + + + + + +dup47_/lht_tree_doc/comm/flags_pad/children/lock + + +lock +flag + + + + + +dup47_/lht_tree_doc/comm/flags_pad->dup47_/lht_tree_doc/comm/flags_pad/children/lock + + + + + +dup47_/lht_tree_doc/comm/flags_pad/children/nonetlist + + +nonetlist +flag + + + + + +dup47_/lht_tree_doc/comm/flags_pad->dup47_/lht_tree_doc/comm/flags_pad/children/nonetlist + + + + + +dup47_/lht_tree_doc/comm/flags_pad/children/termname + + +termname +flag + + + + + +dup47_/lht_tree_doc/comm/flags_pad->dup47_/lht_tree_doc/comm/flags_pad/children/termname + + + + + +dup47_/lht_tree_doc/comm/flags_pad/children/floater + + +floater +flag + + + + + +dup47_/lht_tree_doc/comm/flags_pad->dup47_/lht_tree_doc/comm/flags_pad/children/floater + + + + + +dup47_/lht_tree_doc/comm/flags_pad/children/pin + + +pin +flag + + + + + +dup47_/lht_tree_doc/comm/flags_pad->dup47_/lht_tree_doc/comm/flags_pad/children/pin + + + + + +dup47_/lht_tree_doc/comm/flags_pad/children/via + + +via +flag + + + + + +dup47_/lht_tree_doc/comm/flags_pad->dup47_/lht_tree_doc/comm/flags_pad/children/via + + + + + + + + + + + + + + + + + + +dup48_/lht_tree_doc/comm/data/children/objects/children/via.ID/children/x + + +x +coord + + + + + +/lht_tree_doc/comm/data/children/element.ID/children/objects/children/pin.ID->dup48_/lht_tree_doc/comm/data/children/objects/children/via.ID/children/x + + + + + +dup48_/lht_tree_doc/comm/data/children/objects/children/via.ID/children/y + + +y +coord + + + + + +/lht_tree_doc/comm/data/children/element.ID/children/objects/children/pin.ID->dup48_/lht_tree_doc/comm/data/children/objects/children/via.ID/children/y + + + + + +dup48_/lht_tree_doc/comm/data/children/objects/children/via.ID/children/thickness + + +thickness +coord + + + + + +/lht_tree_doc/comm/data/children/element.ID/children/objects/children/pin.ID->dup48_/lht_tree_doc/comm/data/children/objects/children/via.ID/children/thickness + + + + + +dup48_/lht_tree_doc/comm/data/children/objects/children/via.ID/children/clearance + + +clearance +coord + + + + + +/lht_tree_doc/comm/data/children/element.ID/children/objects/children/pin.ID->dup48_/lht_tree_doc/comm/data/children/objects/children/via.ID/children/clearance + + + + + +dup48_/lht_tree_doc/comm/data/children/objects/children/via.ID/children/mask + + +mask +coord + + + + + +/lht_tree_doc/comm/data/children/element.ID/children/objects/children/pin.ID->dup48_/lht_tree_doc/comm/data/children/objects/children/via.ID/children/mask + + + + + +dup48_/lht_tree_doc/comm/data/children/objects/children/via.ID/children/hole + + +hole +coord + + + + + +/lht_tree_doc/comm/data/children/element.ID/children/objects/children/pin.ID->dup48_/lht_tree_doc/comm/data/children/objects/children/via.ID/children/hole + + + + + +dup48_/lht_tree_doc/comm/data/children/objects/children/via.ID/children/name + + +name +string + + + + + +/lht_tree_doc/comm/data/children/element.ID/children/objects/children/pin.ID->dup48_/lht_tree_doc/comm/data/children/objects/children/via.ID/children/name + + + + + +dup48_/lht_tree_doc/comm/data/children/objects/children/via.ID/children/number + + +number +string + + + + + +/lht_tree_doc/comm/data/children/element.ID/children/objects/children/pin.ID->dup48_/lht_tree_doc/comm/data/children/objects/children/via.ID/children/number + + + + + +dup48_/lht_tree_doc/comm/attributes + + +ha:attributes + + + + + +/lht_tree_doc/comm/data/children/element.ID/children/objects/children/pin.ID->dup48_/lht_tree_doc/comm/attributes + + + + + +dup48_/lht_tree_doc/comm/flags_pinvia + + +ha:flags_pinvia + + + + + +/lht_tree_doc/comm/data/children/element.ID/children/objects/children/pin.ID->dup48_/lht_tree_doc/comm/flags_pinvia + + + + + +dup48_/lht_tree_doc/comm/attributes/children/attrib-key + + +attrib-key +string + + + + + +dup48_/lht_tree_doc/comm/attributes->dup48_/lht_tree_doc/comm/attributes/children/attrib-key + + + + + +dup48_/lht_tree_doc/comm/flags_pinvia/children/found + + +found +flag + + + + + +dup48_/lht_tree_doc/comm/flags_pinvia->dup48_/lht_tree_doc/comm/flags_pinvia/children/found + + + + + +dup48_/lht_tree_doc/comm/flags_pinvia/children/hole + + +hole +flag + + + + + +dup48_/lht_tree_doc/comm/flags_pinvia->dup48_/lht_tree_doc/comm/flags_pinvia/children/hole + + + + + +dup48_/lht_tree_doc/comm/flags_pinvia/children/clearline + + +clearline +flag + + + + + +dup48_/lht_tree_doc/comm/flags_pinvia->dup48_/lht_tree_doc/comm/flags_pinvia/children/clearline + + + + + +dup48_/lht_tree_doc/comm/flags_pinvia/children/selected + + +selected +flag + + + + + +dup48_/lht_tree_doc/comm/flags_pinvia->dup48_/lht_tree_doc/comm/flags_pinvia/children/selected + + + + + +dup48_/lht_tree_doc/comm/flags_pinvia/children/auto + + +auto +flag + + + + + +dup48_/lht_tree_doc/comm/flags_pinvia->dup48_/lht_tree_doc/comm/flags_pinvia/children/auto + + + + + +dup48_/lht_tree_doc/comm/flags_pinvia/children/warn + + +warn +flag + + + + + +dup48_/lht_tree_doc/comm/flags_pinvia->dup48_/lht_tree_doc/comm/flags_pinvia/children/warn + + + + + +dup48_/lht_tree_doc/comm/flags_pinvia/children/usetherm + + +usetherm +flag + + + + + +dup48_/lht_tree_doc/comm/flags_pinvia->dup48_/lht_tree_doc/comm/flags_pinvia/children/usetherm + + + + + +dup48_/lht_tree_doc/comm/flags_pinvia/children/drc + + +drc +flag + + + + + +dup48_/lht_tree_doc/comm/flags_pinvia->dup48_/lht_tree_doc/comm/flags_pinvia/children/drc + + + + + +dup48_/lht_tree_doc/comm/flags_pinvia/children/lock + + +lock +flag + + + + + +dup48_/lht_tree_doc/comm/flags_pinvia->dup48_/lht_tree_doc/comm/flags_pinvia/children/lock + + + + + +dup48_/lht_tree_doc/comm/flags_pinvia/children/nonetlist + + +nonetlist +flag + + + + + +dup48_/lht_tree_doc/comm/flags_pinvia->dup48_/lht_tree_doc/comm/flags_pinvia/children/nonetlist + + + + + +dup48_/lht_tree_doc/comm/flags_pinvia/children/termname + + +termname +flag + + + + + +dup48_/lht_tree_doc/comm/flags_pinvia->dup48_/lht_tree_doc/comm/flags_pinvia/children/termname + + + + + +dup48_/lht_tree_doc/comm/flags_pinvia/children/floater + + +floater +flag + + + + + +dup48_/lht_tree_doc/comm/flags_pinvia->dup48_/lht_tree_doc/comm/flags_pinvia/children/floater + + + + + +dup48_/lht_tree_doc/comm/flags_pinvia/children/pin + + +pin +flag + + + + + +dup48_/lht_tree_doc/comm/flags_pinvia->dup48_/lht_tree_doc/comm/flags_pinvia/children/pin + + + + + +dup48_/lht_tree_doc/comm/flags_pinvia/children/via + + +via +flag + + + + + +dup48_/lht_tree_doc/comm/flags_pinvia->dup48_/lht_tree_doc/comm/flags_pinvia/children/via + + + + + + + + + + + + + + + + + + +/lht_tree_doc/comm/data/children/rat.ID/children/x1 + + +x1 +coord + + + + + +/lht_tree_doc/comm/data/children/rat.ID->/lht_tree_doc/comm/data/children/rat.ID/children/x1 + + + + + +/lht_tree_doc/comm/data/children/rat.ID/children/y1 + + +y1 +coord + + + + + +/lht_tree_doc/comm/data/children/rat.ID->/lht_tree_doc/comm/data/children/rat.ID/children/y1 + + + + + +/lht_tree_doc/comm/data/children/rat.ID/children/x2 + + +x2 +coord + + + + + +/lht_tree_doc/comm/data/children/rat.ID->/lht_tree_doc/comm/data/children/rat.ID/children/x2 + + + + + +/lht_tree_doc/comm/data/children/rat.ID/children/y2 + + +y2 +coord + + + + + +/lht_tree_doc/comm/data/children/rat.ID->/lht_tree_doc/comm/data/children/rat.ID/children/y2 + + + + + +/lht_tree_doc/comm/data/children/rat.ID/children/lgrp1 + + +lgrp1 +integer + + + + + +/lht_tree_doc/comm/data/children/rat.ID->/lht_tree_doc/comm/data/children/rat.ID/children/lgrp1 + + + + + +/lht_tree_doc/comm/data/children/rat.ID/children/lgrp2 + + +lgrp2 +integer + + + + + +/lht_tree_doc/comm/data/children/rat.ID->/lht_tree_doc/comm/data/children/rat.ID/children/lgrp2 + + + + + +dup49_/lht_tree_doc/comm/attributes + + +ha:attributes + + + + + +/lht_tree_doc/comm/data/children/rat.ID->dup49_/lht_tree_doc/comm/attributes + + + + + +dup50_/lht_tree_doc/comm/flags_line + + +ha:flags + + + + + +/lht_tree_doc/comm/data/children/rat.ID->dup50_/lht_tree_doc/comm/flags_line + + + + + +dup49_/lht_tree_doc/comm/attributes/children/attrib-key + + +attrib-key +string + + + + + +dup49_/lht_tree_doc/comm/attributes->dup49_/lht_tree_doc/comm/attributes/children/attrib-key + + + + + +dup50_/lht_tree_doc/comm/flags_line/children/found + + +found +flag + + + + + +dup50_/lht_tree_doc/comm/flags_line->dup50_/lht_tree_doc/comm/flags_line/children/found + + + + + +dup50_/lht_tree_doc/comm/flags_line/children/clearline + + +clearline +flag + + + + + +dup50_/lht_tree_doc/comm/flags_line->dup50_/lht_tree_doc/comm/flags_line/children/clearline + + + + + +dup50_/lht_tree_doc/comm/flags_line/children/selected + + +selected +flag + + + + + +dup50_/lht_tree_doc/comm/flags_line->dup50_/lht_tree_doc/comm/flags_line/children/selected + + + + + +dup50_/lht_tree_doc/comm/flags_line/children/auto + + +auto +flag + + + + + +dup50_/lht_tree_doc/comm/flags_line->dup50_/lht_tree_doc/comm/flags_line/children/auto + + + + + +dup50_/lht_tree_doc/comm/flags_line/children/rubberend + + +rubberend +flag + + + + + +dup50_/lht_tree_doc/comm/flags_line->dup50_/lht_tree_doc/comm/flags_line/children/rubberend + + + + + +dup50_/lht_tree_doc/comm/flags_line/children/drc + + +drc +flag + + + + + +dup50_/lht_tree_doc/comm/flags_line->dup50_/lht_tree_doc/comm/flags_line/children/drc + + + + + +dup50_/lht_tree_doc/comm/flags_line/children/lock + + +lock +flag + + + + + +dup50_/lht_tree_doc/comm/flags_line->dup50_/lht_tree_doc/comm/flags_line/children/lock + + + + + +dup50_/lht_tree_doc/comm/flags_line/children/termname + + +termname +flag + + + + + +dup50_/lht_tree_doc/comm/flags_line->dup50_/lht_tree_doc/comm/flags_line/children/termname + + + + + +dup50_/lht_tree_doc/comm/flags_line/children/floater + + +floater +flag + + + + + +dup50_/lht_tree_doc/comm/flags_line->dup50_/lht_tree_doc/comm/flags_line/children/floater + + + + + + + + + + + + + Index: tags/2.1.2/doc/developer/lihata_format/examples/board.lht =================================================================== --- tags/2.1.2/doc/developer/lihata_format/examples/board.lht (nonexistent) +++ tags/2.1.2/doc/developer/lihata_format/examples/board.lht (revision 24813) @@ -0,0 +1,284 @@ +ha:pcb-rnd-board-v5 { + + ha:attributes { + {PCB::grid::unit}=mil + } + + li:styles { + ha:Signal { + diameter = 2.0mm + thickness = 10.0mil + hole = 31.5mil + clearance = 20.0mil + } + ha:Power { + diameter = 2.2mm + thickness = 20.0mil + hole = 1.0mm + clearance = 20.0mil + } + } + + ha:meta { + ha:size { + thermal_scale = 0.500000 + x = 500.0mil + y = 150.0mil + } + ha:grid { + spacing = 25.0mil + offs_x = 0.0 + offs_y = 0.0 + } + } + + ha:data { + li:padstack_prototypes { + } + + li:objects { + } + li:layers { + + ha:top-sig { + lid=0 + group=3 + ha:combining { } + visible=1 + + li:objects { + ha:line.8 { + x1=50.0mil; y1=75.0mil; x2=450.0mil; y2=75.0mil; thickness=10.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + } + color = {#8b2323} + } + + ha:bottom-sig { + lid=1 + group=10 + ha:combining { } + visible=1 + + li:objects { + } + color = {#3a5fcd} + } + + ha:top-gnd { + lid=2 + group=3 + ha:combining { } + visible=1 + + li:objects { + } + color = {#104e8b} + } + + ha:bottom-gnd { + lid=3 + group=10 + ha:combining { } + visible=1 + + li:objects { + } + color = {#cd3700} + } + + ha:int-sig2 { + lid=4 + group=7 + ha:combining { } + visible=1 + + li:objects { + } + color = {#548b54} + } + + ha:int-sig1 { + lid=5 + group=5 + ha:combining { } + visible=1 + + li:objects { + } + color = {#8b7355} + } + + ha:outline { + lid=6 + group=9 + ha:combining { } + visible=1 + + li:objects { + } + color = {#00868b} + } + + ha:bottom-silk { + lid=7 + group=12 + ha:combining { auto=1; } + visible=1 + + li:objects { + } + color = {#cccccc} + } + + ha:top-silk { + lid=8 + group=1 + ha:combining { auto=1; } + visible=1 + + li:objects { + } + color = {#000000} + } + + ha:top-paste { + lid=9 + group=0 + ha:combining { auto=1; } + visible=0 + + li:objects { + } + color = {#3a5fcd} + } + + ha:top-mask { + lid=10 + group=2 + ha:combining { sub=1; auto=1; } + visible=0 + + li:objects { + } + color = {#104e8b} + } + + ha:bottom-mask { + lid=11 + group=11 + ha:combining { sub=1; auto=1; } + visible=0 + + li:objects { + } + color = {#cd3700} + } + + ha:bottom-paste { + lid=12 + group=13 + ha:combining { auto=1; } + visible=0 + + li:objects { + } + color = {#548b54} + } + } + } + + ha:layer_stack { + li:groups { + ha:0 { + name = top_paste + ha:type { top=1; paste=1; } + li:layers { 9; } + } + ha:1 { + name = top_silk + ha:type { silk=1; top=1; } + li:layers { 8; } + } + ha:2 { + name = top_mask + ha:type { top=1; mask=1; } + li:layers { 10; } + } + ha:3 { + name = top_copper + ha:type { copper=1; top=1; } + li:layers { 0; 2; } + } + ha:4 { + name = grp_4 + ha:type { substrate=1; intern=1; } + li:layers { } + } + ha:5 { + name = Intern + ha:type { copper=1; intern=1; } + li:layers { 5; } + } + ha:6 { + name = grp_6 + ha:type { substrate=1; intern=1; } + li:layers { } + } + ha:7 { + name = Intern + ha:type { copper=1; intern=1; } + li:layers { 4; } + } + ha:8 { + name = grp_8 + ha:type { substrate=1; intern=1; } + li:layers { } + } + ha:9 { + name = global_outline + ha:type { outline=1; } + li:layers { 6; } + } + ha:10 { + name = bottom_copper + ha:type { bottom=1; copper=1; } + li:layers { 1; 3; } + } + ha:11 { + name = bottom_mask + ha:type { bottom=1; mask=1; } + li:layers { 11; } + } + ha:12 { + name = bottom_silk + ha:type { silk=1; bottom=1; } + li:layers { 7; } + } + ha:13 { + name = bottom_paste + ha:type { bottom=1; paste=1; } + li:layers { 12; } + } + } + } + li:pcb-rnd-conf-v1 { + ha:overwrite { + ha:design { + line_thickness = 10.00 mil + via_thickness = 2.0000 mm + via_drilling_hole = 31.50 mil + poly_isle_area = 200000000.0 + clearance = 20.00 mil + } + ha:editor { + grids_idx = 4 + grid = 25.00 mil + grid_unit = mil + } + } + } +} Index: tags/2.1.2/doc/developer/lihata_format/examples/conf.lht =================================================================== --- tags/2.1.2/doc/developer/lihata_format/examples/conf.lht (nonexistent) +++ tags/2.1.2/doc/developer/lihata_format/examples/conf.lht (revision 24813) @@ -0,0 +1,26 @@ +li:pcb-rnd-conf-v1 { + ha:overwrite { + ha:plugins { + ha:hid_gtk { + ha:window_geometry { + library_x = 1342 + library_y = 316 + library_width = 580 + library_height = 448 + } + } + } + ha:editor { + auto_place = { 1 } + save_in_tmp = { 0 } + } + ha:rc { + li:library_search_paths { + ?../pcblib + ?~/pcblib/ + $(rc.path.share)/pcblib + } + backup_interval = { 60 } + } + } +} Index: tags/2.1.2/doc/developer/lihata_format/examples/subc.lht =================================================================== --- tags/2.1.2/doc/developer/lihata_format/examples/subc.lht (nonexistent) +++ tags/2.1.2/doc/developer/lihata_format/examples/subc.lht (revision 24813) @@ -0,0 +1,236 @@ +li:pcb-rnd-subcircuit-v4 { + ha:subc.4 { + ha:attributes { + value = 1206 + footprint = Standard SMT resistor, capacitor etc + } + ha:data { + li:padstack_prototypes { + ha:ps_proto_v4.0 { + htop = 0 + hdia = 0.0 + li:shape { + ha:ps_shape_v4 { + clearance = 0.0 + li:ps_poly { + 0.649986mm + -0.94996mm + -0.649986mm + -0.94996mm + -0.649986mm + 0.94996mm + 0.649986mm + 0.94996mm + } + ha:layer_mask { + copper = 1 + top = 1 + } + ha:combining { + } + } + ha:ps_shape_v4 { + clearance = 0.0 + li:ps_poly { + 0.726186mm + -1.02616mm + -0.726186mm + -1.02616mm + -0.726186mm + 1.02616mm + 0.726186mm + 1.02616mm + } + ha:layer_mask { + top = 1 + mask = 1 + } + ha:combining { + sub = 1 + auto = 1 + } + } + ha:ps_shape_v4 { + clearance = 0.0 + li:ps_poly { + 0.649986mm + -0.94996mm + -0.649986mm + -0.94996mm + -0.649986mm + 0.94996mm + 0.649986mm + 0.94996mm + } + ha:layer_mask { + top = 1 + paste = 1 + } + ha:combining { + auto = 1 + } + } + } + hbottom = 0 + hplated = 0 + } + } + li:objects { + ha:padstack_ref.6 { + smirror = 0 + ha:attributes { + term = 1 + name = 1 + } + proto = 0 + xmirror = 0 + x = -1.49987mm + rot = 0.000000 + y = 0.0 + li:thermal { + } + ha:flags { + clearline = 1 + } + clearance = 10.0mil + } + ha:padstack_ref.7 { + smirror = 0 + ha:attributes { + term = 2 + name = 2 + } + proto = 0 + xmirror = 0 + x = 1.49987mm + rot = 0.000000 + y = 0.0 + li:thermal { + } + ha:flags { + clearline = 1 + } + clearance = 10.0mil + } + } + li:layers { + ha:top-silk { + lid = 0 + ha:type { + silk = 1 + top = 1 + } + li:objects { + ha:line.8 { + clearance = 0.0 + y2 = -0.94996mm + thickness = 8.0mil + ha:attributes { + } + x1 = -23.62mil + x2 = 23.62mil + ha:flags { + } + y1 = -0.94996mm + } + ha:line.11 { + clearance = 0.0 + y2 = 0.94996mm + thickness = 8.0mil + ha:attributes { + } + x1 = -23.62mil + x2 = 23.62mil + ha:flags { + } + y1 = 0.94996mm + } + ha:text.5 { + scale = 100 + ha:attributes { + } + direction = 0 + x = -31.5mil + y = -31.5mil + string = %a.parent.refdes% + fid = 0 + ha:flags { + dyntext = 1 + floater = 1 + } + } + } + ha:combining { + } + } + ha:subc-aux { + lid = 1 + ha:type { + top = 1 + misc = 1 + virtual = 1 + } + li:objects { + ha:line.14 { + clearance = 0.0 + y2 = 0.0 + thickness = 0.1mm + ha:attributes { + subc-role = pnp-origin + } + x1 = 0.0 + x2 = 0.0 + ha:flags { + } + y1 = 0.0 + } + ha:line.17 { + clearance = 0.0 + y2 = 0.0 + thickness = 0.1mm + ha:attributes { + subc-role = origin + } + x1 = 0.0 + x2 = 0.0 + ha:flags { + } + y1 = 0.0 + } + ha:line.20 { + clearance = 0.0 + y2 = 0.0 + thickness = 0.1mm + ha:attributes { + subc-role = x + } + x1 = 0.0 + x2 = 1.0mm + ha:flags { + } + y1 = 0.0 + } + ha:line.23 { + clearance = 0.0 + y2 = 1.0mm + thickness = 0.1mm + ha:attributes { + subc-role = y + } + x1 = 0.0 + x2 = 0.0 + ha:flags { + } + y1 = 0.0 + } + } + ha:combining { + } + } + } + } + uid = kazsgcWF3uqvvuDCYMsAAAAB + ha:flags { + } + } +} Index: tags/2.1.2/doc/developer/lihata_format/geda-project-v1.svg =================================================================== --- tags/2.1.2/doc/developer/lihata_format/geda-project-v1.svg (nonexistent) +++ tags/2.1.2/doc/developer/lihata_format/geda-project-v1.svg (revision 24813) @@ -0,0 +1,303 @@ + + + + + + +ha:geda-project-v1 + + + +/lht_tree_doc/roots/geda-project-v1 + + +ha:geda-project-v1 + + + + + +/lht_tree_doc/roots/geda-project-v1/children/common + + +ha:common + + + + + +/lht_tree_doc/roots/geda-project-v1->/lht_tree_doc/roots/geda-project-v1/children/common + + + + + +dup16_/lht_tree_doc/roots/geda-project-v1/children/pcb-rnd-conf-v1 + +pcb-rnd-conf-v1 -> + + + + + +/lht_tree_doc/roots/geda-project-v1->dup16_/lht_tree_doc/roots/geda-project-v1/children/pcb-rnd-conf-v1 + + + + + +/lht_tree_doc/roots/geda-project-v1/children/common/children/name + + +name +string + + + + + +/lht_tree_doc/roots/geda-project-v1/children/common->/lht_tree_doc/roots/geda-project-v1/children/common/children/name + + + + + +/lht_tree_doc/roots/geda-project-v1/children/common/children/desc + + +desc +string + + + + + +/lht_tree_doc/roots/geda-project-v1/children/common->/lht_tree_doc/roots/geda-project-v1/children/common/children/desc + + + + + +/lht_tree_doc/roots/geda-project-v1/children/common/children/url + + +url +string + + + + + +/lht_tree_doc/roots/geda-project-v1/children/common->/lht_tree_doc/roots/geda-project-v1/children/common/children/url + + + + + +/lht_tree_doc/roots/geda-project-v1/children/common/children/vcs + + +vcs +string + + + + + +/lht_tree_doc/roots/geda-project-v1/children/common->/lht_tree_doc/roots/geda-project-v1/children/common/children/vcs + + + + + +/lht_tree_doc/roots/geda-project-v1/children/common/children/contact + + +contact +string + + + + + +/lht_tree_doc/roots/geda-project-v1/children/common->/lht_tree_doc/roots/geda-project-v1/children/common/children/contact + + + + + +/lht_tree_doc/roots/geda-project-v1/children/common/children/files + + +li:files + + + + + +/lht_tree_doc/roots/geda-project-v1/children/common->/lht_tree_doc/roots/geda-project-v1/children/common/children/files + + + + + +/lht_tree_doc/roots/geda-project-v1/children/common/children/libs + + +li:libs + + + + + +/lht_tree_doc/roots/geda-project-v1/children/common->/lht_tree_doc/roots/geda-project-v1/children/common/children/libs + + + + + +/lht_tree_doc/roots/geda-project-v1/children/common/children/files/children/NAME + + +ha:NAME + + + + + +/lht_tree_doc/roots/geda-project-v1/children/common/children/files->/lht_tree_doc/roots/geda-project-v1/children/common/children/files/children/NAME + + + + + +/lht_tree_doc/roots/geda-project-v1/children/common/children/files/children/NAME/children/path + + +path +string + + + + + +/lht_tree_doc/roots/geda-project-v1/children/common/children/files/children/NAME->/lht_tree_doc/roots/geda-project-v1/children/common/children/files/children/NAME/children/path + + + + + +/lht_tree_doc/roots/geda-project-v1/children/common/children/files/children/NAME/children/desc + + +desc +string + + + + + +/lht_tree_doc/roots/geda-project-v1/children/common/children/files/children/NAME->/lht_tree_doc/roots/geda-project-v1/children/common/children/files/children/NAME/children/desc + + + + + +/lht_tree_doc/roots/geda-project-v1/children/common/children/files/children/NAME/children/type + + +type +string + + + + + +/lht_tree_doc/roots/geda-project-v1/children/common/children/files/children/NAME->/lht_tree_doc/roots/geda-project-v1/children/common/children/files/children/NAME/children/type + + + + + +/lht_tree_doc/roots/geda-project-v1/children/common/children/libs/children/NAME + + +ha:NAME + + + + + +/lht_tree_doc/roots/geda-project-v1/children/common/children/libs->/lht_tree_doc/roots/geda-project-v1/children/common/children/libs/children/NAME + + + + + +/lht_tree_doc/roots/geda-project-v1/children/common/children/libs/children/NAME/children/path + + +path +string + + + + + +/lht_tree_doc/roots/geda-project-v1/children/common/children/libs/children/NAME->/lht_tree_doc/roots/geda-project-v1/children/common/children/libs/children/NAME/children/path + + + + + +/lht_tree_doc/roots/geda-project-v1/children/common/children/libs/children/NAME/children/url + + +url +string + + + + + +/lht_tree_doc/roots/geda-project-v1/children/common/children/libs/children/NAME->/lht_tree_doc/roots/geda-project-v1/children/common/children/libs/children/NAME/children/url + + + + + +/lht_tree_doc/roots/geda-project-v1/children/common/children/libs/children/NAME/children/desc + + +desc +string + + + + + +/lht_tree_doc/roots/geda-project-v1/children/common/children/libs/children/NAME->/lht_tree_doc/roots/geda-project-v1/children/common/children/libs/children/NAME/children/desc + + + + + +/lht_tree_doc/roots/geda-project-v1/children/common/children/libs/children/NAME/children/type + + +type +string + + + + + +/lht_tree_doc/roots/geda-project-v1/children/common/children/libs/children/NAME->/lht_tree_doc/roots/geda-project-v1/children/common/children/libs/children/NAME/children/type + + + + + Index: tags/2.1.2/doc/developer/lihata_format/index.html =================================================================== --- tags/2.1.2/doc/developer/lihata_format/index.html (nonexistent) +++ tags/2.1.2/doc/developer/lihata_format/index.html (revision 24813) @@ -0,0 +1,65 @@ + + + + pcb-rnd developer manual - lihata file formats + + + +

pcb-rnd native file formats

+

+The native file format of pcb-rnd is +lihata based. Lihata is a generic markup language that describes how +a tree can be serialized into a file format. What the tree contains and +what each node means is up to the user (pcb-rnd in this case). This document +describes how the lihata trees are interpreted by pcb-rnd. +

+This document is halfway in between the low level lihata document and the +high level data model +specification. It is assumed that the reader is familiar with both: the +lihata interface plugin doesn't do anything on its own, it only takes +the data model from the memory and the lihata document on disk and +converts the syntax between the two. +

+The following table is a summary of the native file formats the core +handles. Various plugins will handle their own file formats, often also +lihata based - those are each documented at the corresponding. Note: +pcb-rnd does not try to recognize the purpose of the file by the file name, +but by the root node name - files can be named anything, there's no +"extension"; there are some files that are found by name (typically config +files) - these are marked with bold. +

+ + +
typical filename root node + purpose (and documentation) + +
foo.lht ha:pcb-rnd-board-v* + Printed circuit board, self-contained +
(struct drawing) +
(sample file) + +
bar.lht, bar.fp li:pcb-rnd-subcircuit-v* + A subcircuit, self-contained, most often used as a footprint +
(struct drawing) +
(sample file) + +
times.lht li:pcb-rnd-font-v1 + Vector font +
(struct drawing) + +
pcb-conf.lht li:pcb-rnd-conf-v1 + A configuration subtree: system config (e.g. /usr/share/pcb-rnd/pcb-conf.lht) or user config (~/.pcb-rnd/pcb-conf.lht) +
(struct drawing) +
(sample file) + +
project.lht ha:geda-project-v1 + A project file that describes configuration and source file names for various software +
(struct drawing) + +
pcb-menu-default.lht ha: + The main menu system, including popup menus, all key and mouse bindings + +
+ + + Index: tags/2.1.2/doc/developer/lihata_format/pcb-rnd-board-v.svg =================================================================== --- tags/2.1.2/doc/developer/lihata_format/pcb-rnd-board-v.svg (nonexistent) +++ tags/2.1.2/doc/developer/lihata_format/pcb-rnd-board-v.svg (revision 24813) @@ -0,0 +1,1067 @@ + + + + + + +ha:pcb-rnd-board-v* + + + +/lht_tree_doc/roots/pcb-rnd-board-v* + + +ha:pcb-rnd-board-v* + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/meta + + +ha:meta + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*->/lht_tree_doc/roots/pcb-rnd-board-v*/children/meta + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/layer_stack + + +ha:layer_stack + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*->/lht_tree_doc/roots/pcb-rnd-board-v*/children/layer_stack + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/font + + +ha:font + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*->/lht_tree_doc/roots/pcb-rnd-board-v*/children/font + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/styles + + +ha:styles + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*->/lht_tree_doc/roots/pcb-rnd-board-v*/children/styles + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/netlists + + +ha:netlists + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*->/lht_tree_doc/roots/pcb-rnd-board-v*/children/netlists + + + + + +dup4_/lht_tree_doc/roots/pcb-rnd-board-v*/children/conf + +conf -> + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*->dup4_/lht_tree_doc/roots/pcb-rnd-board-v*/children/conf + + + + + +dup5_/lht_tree_doc/roots/pcb-rnd-board-v*/children/data + +data -> + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*->dup5_/lht_tree_doc/roots/pcb-rnd-board-v*/children/data + + + + + +dup6_/lht_tree_doc/comm/attributes + + +ha:attributes + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*->dup6_/lht_tree_doc/comm/attributes + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/meta/children/board_name + + +board_name +string + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/meta->/lht_tree_doc/roots/pcb-rnd-board-v*/children/meta/children/board_name + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/meta/children/grid + + +ha:grid + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/meta->/lht_tree_doc/roots/pcb-rnd-board-v*/children/meta/children/grid + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/meta/children/size + + +ha:size + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/meta->/lht_tree_doc/roots/pcb-rnd-board-v*/children/meta/children/size + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/meta/children/drc + + +ha:drc +<5 + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/meta->/lht_tree_doc/roots/pcb-rnd-board-v*/children/meta/children/drc + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/meta/children/cursor + + +ha:cursor + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/meta->/lht_tree_doc/roots/pcb-rnd-board-v*/children/meta/children/cursor + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/meta/children/grid/children/offs_x + + +offs_x +coord + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/meta/children/grid->/lht_tree_doc/roots/pcb-rnd-board-v*/children/meta/children/grid/children/offs_x + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/meta/children/grid/children/offs_y + + +offs_y +coord + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/meta/children/grid->/lht_tree_doc/roots/pcb-rnd-board-v*/children/meta/children/grid/children/offs_y + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/meta/children/grid/children/spacing + + +spacing +coord + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/meta/children/grid->/lht_tree_doc/roots/pcb-rnd-board-v*/children/meta/children/grid/children/spacing + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/meta/children/size/children/x + + +x +coord + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/meta/children/size->/lht_tree_doc/roots/pcb-rnd-board-v*/children/meta/children/size/children/x + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/meta/children/size/children/y + + +y +coord + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/meta/children/size->/lht_tree_doc/roots/pcb-rnd-board-v*/children/meta/children/size/children/y + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/meta/children/size/children/isle_area_nm2 + + +isle_area_nm2 +double + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/meta/children/size->/lht_tree_doc/roots/pcb-rnd-board-v*/children/meta/children/size/children/isle_area_nm2 + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/meta/children/size/children/thermal_scale + + +thermal_scale +double + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/meta/children/size->/lht_tree_doc/roots/pcb-rnd-board-v*/children/meta/children/size/children/thermal_scale + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/meta/children/drc/children/bloat + + +bloat +coord + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/meta/children/drc->/lht_tree_doc/roots/pcb-rnd-board-v*/children/meta/children/drc/children/bloat + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/meta/children/drc/children/shrink + + +shrink +coord + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/meta/children/drc->/lht_tree_doc/roots/pcb-rnd-board-v*/children/meta/children/drc/children/shrink + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/meta/children/drc/children/min_width + + +min_width +coord + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/meta/children/drc->/lht_tree_doc/roots/pcb-rnd-board-v*/children/meta/children/drc/children/min_width + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/meta/children/drc/children/min_silk + + +min_silk +coord + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/meta/children/drc->/lht_tree_doc/roots/pcb-rnd-board-v*/children/meta/children/drc/children/min_silk + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/meta/children/drc/children/min_drill + + +min_drill +coord + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/meta/children/drc->/lht_tree_doc/roots/pcb-rnd-board-v*/children/meta/children/drc/children/min_drill + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/meta/children/drc/children/min_ring + + +min_ring +coord + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/meta/children/drc->/lht_tree_doc/roots/pcb-rnd-board-v*/children/meta/children/drc/children/min_ring + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/meta/children/cursor/children/x + + +x +coord + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/meta/children/cursor->/lht_tree_doc/roots/pcb-rnd-board-v*/children/meta/children/cursor/children/x + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/meta/children/cursor/children/y + + +y +coord + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/meta/children/cursor->/lht_tree_doc/roots/pcb-rnd-board-v*/children/meta/children/cursor/children/y + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/meta/children/cursor/children/zoom + + +zoom +double + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/meta/children/cursor->/lht_tree_doc/roots/pcb-rnd-board-v*/children/meta/children/cursor/children/zoom + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/layer_stack/children/groups + + +li:groups + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/layer_stack->/lht_tree_doc/roots/pcb-rnd-board-v*/children/layer_stack/children/groups + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/layer_stack/children/groups/children/INTEGER + + +ha:INTEGER + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/layer_stack/children/groups->/lht_tree_doc/roots/pcb-rnd-board-v*/children/layer_stack/children/groups/children/INTEGER + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/layer_stack/children/groups/children/INTEGER/children/name + + +name +string +>=6 + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/layer_stack/children/groups/children/INTEGER->/lht_tree_doc/roots/pcb-rnd-board-v*/children/layer_stack/children/groups/children/INTEGER/children/name + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/layer_stack/children/groups/children/INTEGER->/lht_tree_doc/roots/pcb-rnd-board-v*/children/layer_stack/children/groups/children/INTEGER/children/name + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/layer_stack/children/groups/children/INTEGER/children/type + + +ha:type + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/layer_stack/children/groups/children/INTEGER->/lht_tree_doc/roots/pcb-rnd-board-v*/children/layer_stack/children/groups/children/INTEGER/children/type + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/layer_stack/children/groups/children/INTEGER/children/layers + + +li:layers + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/layer_stack/children/groups/children/INTEGER->/lht_tree_doc/roots/pcb-rnd-board-v*/children/layer_stack/children/groups/children/INTEGER/children/layers + + + + + +dup1_/lht_tree_doc/comm/layer_mask/children/top + + +top +flag + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/layer_stack/children/groups/children/INTEGER/children/type->dup1_/lht_tree_doc/comm/layer_mask/children/top + + + + + +dup1_/lht_tree_doc/comm/layer_mask/children/bottom + + +bottom +flag + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/layer_stack/children/groups/children/INTEGER/children/type->dup1_/lht_tree_doc/comm/layer_mask/children/bottom + + + + + +dup1_/lht_tree_doc/comm/layer_mask/children/intern + + +intern +flag + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/layer_stack/children/groups/children/INTEGER/children/type->dup1_/lht_tree_doc/comm/layer_mask/children/intern + + + + + +dup1_/lht_tree_doc/comm/layer_mask/children/logical + + +logical +flag + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/layer_stack/children/groups/children/INTEGER/children/type->dup1_/lht_tree_doc/comm/layer_mask/children/logical + + + + + +dup1_/lht_tree_doc/comm/layer_mask/children/copper + + +copper +flag + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/layer_stack/children/groups/children/INTEGER/children/type->dup1_/lht_tree_doc/comm/layer_mask/children/copper + + + + + +dup1_/lht_tree_doc/comm/layer_mask/children/silk + + +silk +flag + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/layer_stack/children/groups/children/INTEGER/children/type->dup1_/lht_tree_doc/comm/layer_mask/children/silk + + + + + +dup1_/lht_tree_doc/comm/layer_mask/children/mask + + +mask +flag + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/layer_stack/children/groups/children/INTEGER/children/type->dup1_/lht_tree_doc/comm/layer_mask/children/mask + + + + + +dup1_/lht_tree_doc/comm/layer_mask/children/paste + + +paste +flag + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/layer_stack/children/groups/children/INTEGER/children/type->dup1_/lht_tree_doc/comm/layer_mask/children/paste + + + + + +dup1_/lht_tree_doc/comm/layer_mask/children/outline + + +outline +flag + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/layer_stack/children/groups/children/INTEGER/children/type->dup1_/lht_tree_doc/comm/layer_mask/children/outline + + + + + +dup1_/lht_tree_doc/comm/layer_mask/children/substrate + + +substrate +flag + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/layer_stack/children/groups/children/INTEGER/children/type->dup1_/lht_tree_doc/comm/layer_mask/children/substrate + + + + + + + + + + + + + + +dup2_/lht_tree_doc/roots/pcb-rnd-board-v*/children/font/children/FONT-ID + +FONT-ID -> + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/font->dup2_/lht_tree_doc/roots/pcb-rnd-board-v*/children/font/children/FONT-ID + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/netlists/children/netlist + + +li:netlist + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/netlists->/lht_tree_doc/roots/pcb-rnd-board-v*/children/netlists/children/netlist + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/netlists/children/netlist_patch + + +li:netlist_patch + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/netlists->/lht_tree_doc/roots/pcb-rnd-board-v*/children/netlists/children/netlist_patch + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/netlists/children/netlist/children/NETNAME + + +ha:NETNAME + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/netlists/children/netlist->/lht_tree_doc/roots/pcb-rnd-board-v*/children/netlists/children/netlist/children/NETNAME + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/netlists/children/netlist/children/NETNAME/children/conn + + +li:conn + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/netlists/children/netlist/children/NETNAME->/lht_tree_doc/roots/pcb-rnd-board-v*/children/netlists/children/netlist/children/NETNAME/children/conn + + + + + +dup3_/lht_tree_doc/comm/attributes_v5p + + +ha:attributes +>=5 + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/netlists/children/netlist/children/NETNAME->dup3_/lht_tree_doc/comm/attributes_v5p + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/netlists/children/netlist/children/NETNAME/children/conn/children/diameter + + +diameter +string + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/netlists/children/netlist/children/NETNAME/children/conn->/lht_tree_doc/roots/pcb-rnd-board-v*/children/netlists/children/netlist/children/NETNAME/children/conn/children/diameter + + + + + +dup3_/lht_tree_doc/comm/attributes_v5p/children/attrib-key + + +attrib-key +string + + + + + +dup3_/lht_tree_doc/comm/attributes_v5p->dup3_/lht_tree_doc/comm/attributes_v5p/children/attrib-key + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/netlists/children/netlist_patch/children/net_info + + +li:net_info + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/netlists/children/netlist_patch->/lht_tree_doc/roots/pcb-rnd-board-v*/children/netlists/children/netlist_patch/children/net_info + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/netlists/children/netlist_patch/children/add_conn + + +ha:add_conn + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/netlists/children/netlist_patch->/lht_tree_doc/roots/pcb-rnd-board-v*/children/netlists/children/netlist_patch/children/add_conn + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/netlists/children/netlist_patch/children/del_conn + + +ha:del_conn + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/netlists/children/netlist_patch->/lht_tree_doc/roots/pcb-rnd-board-v*/children/netlists/children/netlist_patch/children/del_conn + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/netlists/children/netlist_patch/children/change_attrib + + +ha:change_attrib + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/netlists/children/netlist_patch->/lht_tree_doc/roots/pcb-rnd-board-v*/children/netlists/children/netlist_patch/children/change_attrib + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/netlists/children/netlist_patch/children/net_info/children/net + + +net +string + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/netlists/children/netlist_patch/children/net_info->/lht_tree_doc/roots/pcb-rnd-board-v*/children/netlists/children/netlist_patch/children/net_info/children/net + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/netlists/children/netlist_patch/children/net_info/children/term + + +term +string + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/netlists/children/netlist_patch/children/net_info->/lht_tree_doc/roots/pcb-rnd-board-v*/children/netlists/children/netlist_patch/children/net_info/children/term + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/netlists/children/netlist_patch/children/add_conn/children/net + + +net +string + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/netlists/children/netlist_patch/children/add_conn->/lht_tree_doc/roots/pcb-rnd-board-v*/children/netlists/children/netlist_patch/children/add_conn/children/net + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/netlists/children/netlist_patch/children/add_conn/children/term + + +term +string + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/netlists/children/netlist_patch/children/add_conn->/lht_tree_doc/roots/pcb-rnd-board-v*/children/netlists/children/netlist_patch/children/add_conn/children/term + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/netlists/children/netlist_patch/children/del_conn/children/net + + +net +string + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/netlists/children/netlist_patch/children/del_conn->/lht_tree_doc/roots/pcb-rnd-board-v*/children/netlists/children/netlist_patch/children/del_conn/children/net + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/netlists/children/netlist_patch/children/del_conn/children/term + + +term +string + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/netlists/children/netlist_patch/children/del_conn->/lht_tree_doc/roots/pcb-rnd-board-v*/children/netlists/children/netlist_patch/children/del_conn/children/term + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/netlists/children/netlist_patch/children/change_attrib/children/net + + +net +string + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/netlists/children/netlist_patch/children/change_attrib->/lht_tree_doc/roots/pcb-rnd-board-v*/children/netlists/children/netlist_patch/children/change_attrib/children/net + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/netlists/children/netlist_patch/children/change_attrib/children/key + + +key +string + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/netlists/children/netlist_patch/children/change_attrib->/lht_tree_doc/roots/pcb-rnd-board-v*/children/netlists/children/netlist_patch/children/change_attrib/children/key + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/netlists/children/netlist_patch/children/change_attrib/children/val + + +val +string + + + + + +/lht_tree_doc/roots/pcb-rnd-board-v*/children/netlists/children/netlist_patch/children/change_attrib->/lht_tree_doc/roots/pcb-rnd-board-v*/children/netlists/children/netlist_patch/children/change_attrib/children/val + + + + + +dup6_/lht_tree_doc/comm/attributes/children/attrib-key + + +attrib-key +string + + + + + +dup6_/lht_tree_doc/comm/attributes->dup6_/lht_tree_doc/comm/attributes/children/attrib-key + + + + + Index: tags/2.1.2/doc/developer/lihata_format/pcb-rnd-conf-v1.svg =================================================================== --- tags/2.1.2/doc/developer/lihata_format/pcb-rnd-conf-v1.svg (nonexistent) +++ tags/2.1.2/doc/developer/lihata_format/pcb-rnd-conf-v1.svg (revision 24813) @@ -0,0 +1,67 @@ + + + + + + +li:pcb-rnd-conf-v1 + + + +/lht_tree_doc/roots/pcb-rnd-conf-v1 + + +li:pcb-rnd-conf-v1 + + + + + +/lht_tree_doc/roots/pcb-rnd-conf-v1/children/overwrite + + +ha:overwrite + + + + + +/lht_tree_doc/roots/pcb-rnd-conf-v1->/lht_tree_doc/roots/pcb-rnd-conf-v1/children/overwrite + + + + + +/lht_tree_doc/roots/pcb-rnd-conf-v1/children/prepend + + +ha:prepend + + + + + +/lht_tree_doc/roots/pcb-rnd-conf-v1->/lht_tree_doc/roots/pcb-rnd-conf-v1/children/prepend + + + + + +/lht_tree_doc/roots/pcb-rnd-conf-v1/children/append + + +ha:append + + + + + +/lht_tree_doc/roots/pcb-rnd-conf-v1->/lht_tree_doc/roots/pcb-rnd-conf-v1/children/append + + + + + Index: tags/2.1.2/doc/developer/lihata_format/pcb-rnd-font-v1.svg =================================================================== --- tags/2.1.2/doc/developer/lihata_format/pcb-rnd-font-v1.svg (nonexistent) +++ tags/2.1.2/doc/developer/lihata_format/pcb-rnd-font-v1.svg (revision 24813) @@ -0,0 +1,415 @@ + + + + + + +li:pcb-rnd-font-v1 + + + +/lht_tree_doc/roots/pcb-rnd-font-v1 + + +li:pcb-rnd-font-v1 + + + + + +/lht_tree_doc/roots/pcb-rnd-font-v1/children/FONT-ID + + +ha:FONT-ID + + + + + +/lht_tree_doc/roots/pcb-rnd-font-v1->/lht_tree_doc/roots/pcb-rnd-font-v1/children/FONT-ID + + + + + +/lht_tree_doc/roots/pcb-rnd-font-v1/children/FONT-ID/children/cell_height + + +cell_height +coord + + + + + +/lht_tree_doc/roots/pcb-rnd-font-v1/children/FONT-ID->/lht_tree_doc/roots/pcb-rnd-font-v1/children/FONT-ID/children/cell_height + + + + + +/lht_tree_doc/roots/pcb-rnd-font-v1/children/FONT-ID/children/cell_width + + +cell_width +coord + + + + + +/lht_tree_doc/roots/pcb-rnd-font-v1/children/FONT-ID->/lht_tree_doc/roots/pcb-rnd-font-v1/children/FONT-ID/children/cell_width + + + + + +/lht_tree_doc/roots/pcb-rnd-font-v1/children/FONT-ID/children/id + + +id +integer + + + + + +/lht_tree_doc/roots/pcb-rnd-font-v1/children/FONT-ID->/lht_tree_doc/roots/pcb-rnd-font-v1/children/FONT-ID/children/id + + + + + +/lht_tree_doc/roots/pcb-rnd-font-v1/children/FONT-ID/children/name + + +name +string + + + + + +/lht_tree_doc/roots/pcb-rnd-font-v1/children/FONT-ID->/lht_tree_doc/roots/pcb-rnd-font-v1/children/FONT-ID/children/name + + + + + +/lht_tree_doc/roots/pcb-rnd-font-v1/children/FONT-ID/children/symbols + + +ha:symbols + + + + + +/lht_tree_doc/roots/pcb-rnd-font-v1/children/FONT-ID->/lht_tree_doc/roots/pcb-rnd-font-v1/children/FONT-ID/children/symbols + + + + + +/lht_tree_doc/roots/pcb-rnd-font-v1/children/FONT-ID/children/symbols/children/CHARACTER + + +ha:CHARACTER + + + + + +/lht_tree_doc/roots/pcb-rnd-font-v1/children/FONT-ID/children/symbols->/lht_tree_doc/roots/pcb-rnd-font-v1/children/FONT-ID/children/symbols/children/CHARACTER + + + + + +/lht_tree_doc/roots/pcb-rnd-font-v1/children/FONT-ID/children/symbols/children/CHARACTER/children/height + + +height +coord + + + + + +/lht_tree_doc/roots/pcb-rnd-font-v1/children/FONT-ID/children/symbols/children/CHARACTER->/lht_tree_doc/roots/pcb-rnd-font-v1/children/FONT-ID/children/symbols/children/CHARACTER/children/height + + + + + +/lht_tree_doc/roots/pcb-rnd-font-v1/children/FONT-ID/children/symbols/children/CHARACTER/children/width + + +width +coord + + + + + +/lht_tree_doc/roots/pcb-rnd-font-v1/children/FONT-ID/children/symbols/children/CHARACTER->/lht_tree_doc/roots/pcb-rnd-font-v1/children/FONT-ID/children/symbols/children/CHARACTER/children/width + + + + + +/lht_tree_doc/roots/pcb-rnd-font-v1/children/FONT-ID/children/symbols/children/CHARACTER/children/delta + + +delta +coord + + + + + +/lht_tree_doc/roots/pcb-rnd-font-v1/children/FONT-ID/children/symbols/children/CHARACTER->/lht_tree_doc/roots/pcb-rnd-font-v1/children/FONT-ID/children/symbols/children/CHARACTER/children/delta + + + + + +/lht_tree_doc/roots/pcb-rnd-font-v1/children/FONT-ID/children/symbols/children/CHARACTER/children/objects + + +li:objects + + + + + +/lht_tree_doc/roots/pcb-rnd-font-v1/children/FONT-ID/children/symbols/children/CHARACTER->/lht_tree_doc/roots/pcb-rnd-font-v1/children/FONT-ID/children/symbols/children/CHARACTER/children/objects + + + + + +/lht_tree_doc/roots/pcb-rnd-font-v1/children/FONT-ID/children/symbols/children/CHARACTER/children/objects/children/line.ID + + +ha:line.ID + + + + + +/lht_tree_doc/roots/pcb-rnd-font-v1/children/FONT-ID/children/symbols/children/CHARACTER/children/objects->/lht_tree_doc/roots/pcb-rnd-font-v1/children/FONT-ID/children/symbols/children/CHARACTER/children/objects/children/line.ID + + + + + +/lht_tree_doc/roots/pcb-rnd-font-v1/children/FONT-ID/children/symbols/children/CHARACTER/children/objects/children/simplearc.ID + + +ha:simplearc.ID + + + + + +/lht_tree_doc/roots/pcb-rnd-font-v1/children/FONT-ID/children/symbols/children/CHARACTER/children/objects->/lht_tree_doc/roots/pcb-rnd-font-v1/children/FONT-ID/children/symbols/children/CHARACTER/children/objects/children/simplearc.ID + + + + + +/lht_tree_doc/roots/pcb-rnd-font-v1/children/FONT-ID/children/symbols/children/CHARACTER/children/objects/children/simplepoly.ID + + +li:simplepoly.ID + + + + + +/lht_tree_doc/roots/pcb-rnd-font-v1/children/FONT-ID/children/symbols/children/CHARACTER/children/objects->/lht_tree_doc/roots/pcb-rnd-font-v1/children/FONT-ID/children/symbols/children/CHARACTER/children/objects/children/simplepoly.ID + + + + + +/lht_tree_doc/roots/pcb-rnd-font-v1/children/FONT-ID/children/symbols/children/CHARACTER/children/objects/children/line.ID/children/x1 + + +x1 +coord + + + + + +/lht_tree_doc/roots/pcb-rnd-font-v1/children/FONT-ID/children/symbols/children/CHARACTER/children/objects/children/line.ID->/lht_tree_doc/roots/pcb-rnd-font-v1/children/FONT-ID/children/symbols/children/CHARACTER/children/objects/children/line.ID/children/x1 + + + + + +/lht_tree_doc/roots/pcb-rnd-font-v1/children/FONT-ID/children/symbols/children/CHARACTER/children/objects/children/line.ID/children/y1 + + +y1 +coord + + + + + +/lht_tree_doc/roots/pcb-rnd-font-v1/children/FONT-ID/children/symbols/children/CHARACTER/children/objects/children/line.ID->/lht_tree_doc/roots/pcb-rnd-font-v1/children/FONT-ID/children/symbols/children/CHARACTER/children/objects/children/line.ID/children/y1 + + + + + +/lht_tree_doc/roots/pcb-rnd-font-v1/children/FONT-ID/children/symbols/children/CHARACTER/children/objects/children/line.ID/children/x2 + + +x2 +coord + + + + + +/lht_tree_doc/roots/pcb-rnd-font-v1/children/FONT-ID/children/symbols/children/CHARACTER/children/objects/children/line.ID->/lht_tree_doc/roots/pcb-rnd-font-v1/children/FONT-ID/children/symbols/children/CHARACTER/children/objects/children/line.ID/children/x2 + + + + + +/lht_tree_doc/roots/pcb-rnd-font-v1/children/FONT-ID/children/symbols/children/CHARACTER/children/objects/children/line.ID/children/y2 + + +y2 +coord + + + + + +/lht_tree_doc/roots/pcb-rnd-font-v1/children/FONT-ID/children/symbols/children/CHARACTER/children/objects/children/line.ID->/lht_tree_doc/roots/pcb-rnd-font-v1/children/FONT-ID/children/symbols/children/CHARACTER/children/objects/children/line.ID/children/y2 + + + + + +/lht_tree_doc/roots/pcb-rnd-font-v1/children/FONT-ID/children/symbols/children/CHARACTER/children/objects/children/line.ID/children/thickness + + +thickness +coord + + + + + +/lht_tree_doc/roots/pcb-rnd-font-v1/children/FONT-ID/children/symbols/children/CHARACTER/children/objects/children/line.ID->/lht_tree_doc/roots/pcb-rnd-font-v1/children/FONT-ID/children/symbols/children/CHARACTER/children/objects/children/line.ID/children/thickness + + + + + +/lht_tree_doc/roots/pcb-rnd-font-v1/children/FONT-ID/children/symbols/children/CHARACTER/children/objects/children/simplearc.ID/children/x + + +x +coord + + + + + +/lht_tree_doc/roots/pcb-rnd-font-v1/children/FONT-ID/children/symbols/children/CHARACTER/children/objects/children/simplearc.ID->/lht_tree_doc/roots/pcb-rnd-font-v1/children/FONT-ID/children/symbols/children/CHARACTER/children/objects/children/simplearc.ID/children/x + + + + + +/lht_tree_doc/roots/pcb-rnd-font-v1/children/FONT-ID/children/symbols/children/CHARACTER/children/objects/children/simplearc.ID/children/y + + +y +coord + + + + + +/lht_tree_doc/roots/pcb-rnd-font-v1/children/FONT-ID/children/symbols/children/CHARACTER/children/objects/children/simplearc.ID->/lht_tree_doc/roots/pcb-rnd-font-v1/children/FONT-ID/children/symbols/children/CHARACTER/children/objects/children/simplearc.ID/children/y + + + + + +/lht_tree_doc/roots/pcb-rnd-font-v1/children/FONT-ID/children/symbols/children/CHARACTER/children/objects/children/simplearc.ID/children/r + + +r +coord + + + + + +/lht_tree_doc/roots/pcb-rnd-font-v1/children/FONT-ID/children/symbols/children/CHARACTER/children/objects/children/simplearc.ID->/lht_tree_doc/roots/pcb-rnd-font-v1/children/FONT-ID/children/symbols/children/CHARACTER/children/objects/children/simplearc.ID/children/r + + + + + +/lht_tree_doc/roots/pcb-rnd-font-v1/children/FONT-ID/children/symbols/children/CHARACTER/children/objects/children/simplearc.ID/children/thickness + + +thickness +coord + + + + + +/lht_tree_doc/roots/pcb-rnd-font-v1/children/FONT-ID/children/symbols/children/CHARACTER/children/objects/children/simplearc.ID->/lht_tree_doc/roots/pcb-rnd-font-v1/children/FONT-ID/children/symbols/children/CHARACTER/children/objects/children/simplearc.ID/children/thickness + + + + + +/lht_tree_doc/roots/pcb-rnd-font-v1/children/FONT-ID/children/symbols/children/CHARACTER/children/objects/children/simplearc.ID/children/astart + + +astart +angle + + + + + +/lht_tree_doc/roots/pcb-rnd-font-v1/children/FONT-ID/children/symbols/children/CHARACTER/children/objects/children/simplearc.ID->/lht_tree_doc/roots/pcb-rnd-font-v1/children/FONT-ID/children/symbols/children/CHARACTER/children/objects/children/simplearc.ID/children/astart + + + + + +/lht_tree_doc/roots/pcb-rnd-font-v1/children/FONT-ID/children/symbols/children/CHARACTER/children/objects/children/simplearc.ID/children/adelta + + +adelta +angle + + + + + +/lht_tree_doc/roots/pcb-rnd-font-v1/children/FONT-ID/children/symbols/children/CHARACTER/children/objects/children/simplearc.ID->/lht_tree_doc/roots/pcb-rnd-font-v1/children/FONT-ID/children/symbols/children/CHARACTER/children/objects/children/simplearc.ID/children/adelta + + + + + Index: tags/2.1.2/doc/developer/lihata_format/pcb-rnd-log-v.svg =================================================================== --- tags/2.1.2/doc/developer/lihata_format/pcb-rnd-log-v.svg (nonexistent) +++ tags/2.1.2/doc/developer/lihata_format/pcb-rnd-log-v.svg (revision 24813) @@ -0,0 +1,116 @@ + + + + + + +ha:pcb-rnd-log-v* + + + +/lht_tree_doc/roots/pcb-rnd-log-v* + + +ha:pcb-rnd-log-v* + + + + + +/lht_tree_doc/roots/pcb-rnd-log-v*/children/entries + + +li:entries + + + + + +/lht_tree_doc/roots/pcb-rnd-log-v*->/lht_tree_doc/roots/pcb-rnd-log-v*/children/entries + + + + + +/lht_tree_doc/roots/pcb-rnd-log-v*/children/entries/children/ID + + +ha:ID + + + + + +/lht_tree_doc/roots/pcb-rnd-log-v*/children/entries->/lht_tree_doc/roots/pcb-rnd-log-v*/children/entries/children/ID + + + + + +/lht_tree_doc/roots/pcb-rnd-log-v*/children/entries/children/ID/children/stamp + + +stamp +string + + + + + +/lht_tree_doc/roots/pcb-rnd-log-v*/children/entries/children/ID->/lht_tree_doc/roots/pcb-rnd-log-v*/children/entries/children/ID/children/stamp + + + + + +/lht_tree_doc/roots/pcb-rnd-log-v*/children/entries/children/ID/children/level + + +level +integer + + + + + +/lht_tree_doc/roots/pcb-rnd-log-v*/children/entries/children/ID->/lht_tree_doc/roots/pcb-rnd-log-v*/children/entries/children/ID/children/level + + + + + +/lht_tree_doc/roots/pcb-rnd-log-v*/children/entries/children/ID/children/seen + + +seen +integer + + + + + +/lht_tree_doc/roots/pcb-rnd-log-v*/children/entries/children/ID->/lht_tree_doc/roots/pcb-rnd-log-v*/children/entries/children/ID/children/seen + + + + + +/lht_tree_doc/roots/pcb-rnd-log-v*/children/entries/children/ID/children/str + + +str +string + + + + + +/lht_tree_doc/roots/pcb-rnd-log-v*/children/entries/children/ID->/lht_tree_doc/roots/pcb-rnd-log-v*/children/entries/children/ID/children/str + + + + + Index: tags/2.1.2/doc/developer/lihata_format/pcb-rnd-subcircuit-v.svg =================================================================== --- tags/2.1.2/doc/developer/lihata_format/pcb-rnd-subcircuit-v.svg (nonexistent) +++ tags/2.1.2/doc/developer/lihata_format/pcb-rnd-subcircuit-v.svg (revision 24813) @@ -0,0 +1,232 @@ + + + + + + +li:pcb-rnd-subcircuit-v* + + + +/lht_tree_doc/roots/pcb-rnd-subcircuit-v* + + +li:pcb-rnd-subcircuit-v* + + + + + +/lht_tree_doc/roots/pcb-rnd-subcircuit-v*/children/subc.ID + + +ha:subc.ID +>=3 + + + + + +/lht_tree_doc/roots/pcb-rnd-subcircuit-v*->/lht_tree_doc/roots/pcb-rnd-subcircuit-v*/children/subc.ID + + + + + +/lht_tree_doc/roots/pcb-rnd-subcircuit-v*/children/subc.ID/children/uid + + +uid +minuid + + + + + +/lht_tree_doc/roots/pcb-rnd-subcircuit-v*/children/subc.ID->/lht_tree_doc/roots/pcb-rnd-subcircuit-v*/children/subc.ID/children/uid + + + + + +dup17_/lht_tree_doc/comm/attributes + + +ha:attributes + + + + + +/lht_tree_doc/roots/pcb-rnd-subcircuit-v*/children/subc.ID->dup17_/lht_tree_doc/comm/attributes + + + + + +dup18_/lht_tree_doc/comm/flags_subcircuit + + +ha:flags + + + + + +/lht_tree_doc/roots/pcb-rnd-subcircuit-v*/children/subc.ID->dup18_/lht_tree_doc/comm/flags_subcircuit + + + + + +dup19_/lht_tree_doc/roots/pcb-rnd-subcircuit-v*/children/subc.ID/children/data + +data -> + + + + + +/lht_tree_doc/roots/pcb-rnd-subcircuit-v*/children/subc.ID->dup19_/lht_tree_doc/roots/pcb-rnd-subcircuit-v*/children/subc.ID/children/data + + + + + +dup17_/lht_tree_doc/comm/attributes/children/attrib-key + + +attrib-key +string + + + + + +dup17_/lht_tree_doc/comm/attributes->dup17_/lht_tree_doc/comm/attributes/children/attrib-key + + + + + +dup18_/lht_tree_doc/comm/flags_subcircuit/children/found + + +found +flag + + + + + +dup18_/lht_tree_doc/comm/flags_subcircuit->dup18_/lht_tree_doc/comm/flags_subcircuit/children/found + + + + + +dup18_/lht_tree_doc/comm/flags_subcircuit/children/selected + + +selected +flag + + + + + +dup18_/lht_tree_doc/comm/flags_subcircuit->dup18_/lht_tree_doc/comm/flags_subcircuit/children/selected + + + + + +dup18_/lht_tree_doc/comm/flags_subcircuit/children/drc + + +drc +flag + + + + + +dup18_/lht_tree_doc/comm/flags_subcircuit->dup18_/lht_tree_doc/comm/flags_subcircuit/children/drc + + + + + +dup18_/lht_tree_doc/comm/flags_subcircuit/children/lock + + +lock +flag + + + + + +dup18_/lht_tree_doc/comm/flags_subcircuit->dup18_/lht_tree_doc/comm/flags_subcircuit/children/lock + + + + + +dup18_/lht_tree_doc/comm/flags_subcircuit/children/nonetlist + + +nonetlist +flag + + + + + +dup18_/lht_tree_doc/comm/flags_subcircuit->dup18_/lht_tree_doc/comm/flags_subcircuit/children/nonetlist + + + + + +dup18_/lht_tree_doc/comm/flags_subcircuit/children/termname + + +termname +flag + + + + + +dup18_/lht_tree_doc/comm/flags_subcircuit->dup18_/lht_tree_doc/comm/flags_subcircuit/children/termname + + + + + +dup18_/lht_tree_doc/comm/flags_subcircuit/children/floater + + +floater +flag + + + + + +dup18_/lht_tree_doc/comm/flags_subcircuit->dup18_/lht_tree_doc/comm/flags_subcircuit/children/floater + + + + + + + + + + + Index: tags/2.1.2/doc/developer/lihata_format/render/common.awk =================================================================== --- tags/2.1.2/doc/developer/lihata_format/render/common.awk (nonexistent) +++ tags/2.1.2/doc/developer/lihata_format/render/common.awk (revision 24813) @@ -0,0 +1,69 @@ +function get_name(node, ty, level) +{ + if (node "/name" in DATA) + nm = DATA[node "/name"] + else + nm = qstrip(NAME[node]) + if (ty != "") + nm = ty ":" nm + while(level > 0) { + nm = " " nm + level-- + } + return nm +} + +function dup_begin(DUPSAV) +{ + DUPSAV[1] = dupd_prefix + if (DUPSAV[1] == "") + dupd_prefix = "dup" ++uniq_node_name "_" +} + +function dup_end(DUPSAV) +{ + dupd_prefix = DUPSAV[1] +} + +function gen_sub(root, level, parent, v, n, N, node, dst_children, DUPSAV) +{ + if (!(root in NAME)) { + print "Error: path not found: " root > "/dev/stderr" + return + } + if (parent == "") + parent = root + v = children(N, root "/children") + for(n = 1; n <= v; n++) { + node = N[n] + if (TYPE[node] == "symlink") { + # normal node symlink: generate a link +# print "SY:" node " " DATA[node] "^^^" sy_is_recursive(node) > "/dev/stderr" + dup_begin(DUPSAV) + if (NAME[node] ~ "@dup") { + tbl_entry(DATA[node], level, parent) + gen_sub(DATA[node], level+1) + } + else + tbl_entry_link(node, DATA[node], level, parent) + dup_end(DUPSAV) + } + else if ((node "/children") in NAME) { + tbl_entry(node, level, parent) + if (TYPE[node "/children"] == "symlink") { + dup_begin(DUPSAV) + dst_children = DATA[node "/children"] + sub("/children$", "", dst_children) + gen_sub(dst_children, level+1, node) + dup_end(DUPSAV) + } + else { + gen_sub(node, level+1) + } + } + else if (TYPE[node] == "hash") + tbl_entry(node, level, parent) + else + print "Unhandled child (unknown type): " node > "/dev/stderr" + } +} Index: tags/2.1.2/doc/developer/lihata_format/render/dot.awk =================================================================== --- tags/2.1.2/doc/developer/lihata_format/render/dot.awk (nonexistent) +++ tags/2.1.2/doc/developer/lihata_format/render/dot.awk (revision 24813) @@ -0,0 +1,99 @@ +BEGIN { + nl = "\\n" +} + +function tbl_entry(node, level, nparent ,nm,vt,dsc,ty,vr, url, tip,duppar,grp,grp_parent) +{ + ty = DATA[node "/type"] + nm = get_name(node, ty, 0) + vt = DATA[node "/valtype"] + vr = DATA[node "/ver"] + grp_parent = parent(parent(node)) + grp = DATA[grp_parent "/dot_group"] + dsc = qstrip(DATA[node "/desc"]) + gsub("\"", "\\\"", dsc) + tip=" tooltip=" q dsc q + url=" URL=" q "tree.html#" node q + + if (dupd_prefix != "") { + node = dupd_prefix node + DUPD[node] ++ + + if (nparent != "") { + duppar = dupd_prefix nparent + if (duppar in DUPD) + nparent = duppar + } + } + + print " " q node q " [label=" q nm nl vt nl vr q url tip "]" >fn + if (nparent != "") + print " " q nparent q " -> " q node q > fn + if (grp != "") { + if (LAST_GRP_SIBL[nparent] != "") { + print " " q LAST_GRP_SIBL[nparent] q " -> " q node q "[style=invis]" > fn + } + LAST_GRP_SIBL[nparent] = node + } +} + +function tbl_entry_link(node, dst, level, parent ,nm,vt,dsc,ty,vr,contid,url,tip,dr) +{ + ty = DATA[node "/type"] + nm = get_name(node, ty, 0) + vt = DATA[node "/valtype"] + vr = DATA[node "/ver"] + dsc = qstrip(DATA[node "/desc"]) + gsub("\"", "\\\"", dsc) + dr = dst + sub("^.*/", "", dr) + url=" URL=" q dr ".svg" q + tip=" tooltip=" q dsc q + + + if (dupd_prefix != "") { + node = dupd_prefix node + DUPD[node] ++ + + if (parent != "") { + duppar = dupd_prefix parent + if (duppar in DUPD) + parent = duppar + } + } + + + print " " q node q " [label=" q nm " ->" nl vt nl vr nl q url tip " shape=plaintext]" >fn + if (parent != "") + print " " q parent q " -> " q node q > fn +} + +function gen_graph(rpath, v, n, N, name) +{ + name = get_name(rpath, DATA[rpath "/type"]) + fn=name + sub(".*[:/]", "", fn) + gsub("[*]", "", fn) + fn = "../" fn ".dot" + + print "digraph " q name q " {" > fn + tbl_entry(rpath, 0) + gen_sub(rpath, 1) + print "}" > fn + close(fn) +} + +function gen_graphs(rpath, v, n, N, name) +{ + v = children(N, rpath) + for(n = 1; n <= v; n++) { + if (N[n] "/hide" in NAME) + continue + gen_graph(N[n]) + } +} + +END { + gen_graphs("/lht_tree_doc/roots") + gen_graphs("/lht_tree_doc/comm") +} Index: tags/2.1.2/doc/developer/lihata_format/render/gen_flags.sh =================================================================== --- tags/2.1.2/doc/developer/lihata_format/render/gen_flags.sh (nonexistent) +++ tags/2.1.2/doc/developer/lihata_format/render/gen_flags.sh (revision 24813) @@ -0,0 +1,40 @@ +../../../../src/pcb-rnd --dump-oflags | awk ' +BEGIN { + print "ha:lht_tree_doc { ha:comm {" +} + +function close_last() +{ + if (is_open) { + print " }" + print " }" + } + is_open = 0; +} + +/^[^\t]/ { + close_last() + print " ha:flags_" $1 " {" + print " hide=1" + print " name=flags" + print " dot_group=1" + print " desc={flag bits of a " $1 "}" + print " type=ha" + print " li:children {" + is_open=1 +} + +/^[\t]/ { + bit=$1 + name=$2 + help=$0 + sub("^[\t ]*" $1 "[\t ]*" $2 "[\t ]*", "", help) + print " ha:" name " { valtype=flag; desc={" help "}}" +} + +END { + close_last() + print "} }" +} + +' Property changes on: tags/2.1.2/doc/developer/lihata_format/render/gen_flags.sh ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/2.1.2/doc/developer/lihata_format/render/html.awk =================================================================== --- tags/2.1.2/doc/developer/lihata_format/render/html.awk (nonexistent) +++ tags/2.1.2/doc/developer/lihata_format/render/html.awk (revision 24813) @@ -0,0 +1,117 @@ +BEGIN { + print "" + print "" + print "" + print " pcb-rnd developer manual - lihata file formats" + print "" + print "" + print "" +} + +function tbl_hdr(node, level) +{ + print " type:name value ver description" +} + +function get_valtype(node, vt) +{ + vt = DATA[node "/valtype"] + if (vt != "") + vt = "" vt "" + else + vt = " " + return vt +} + +function tbl_entry(node, level, parent ,nm,vt,dsc,ty,vr) +{ + if (!(node in NAME)) { + print "Error: path not found: " node > "/dev/stderr" + return + } + ty = DATA[node "/type"] + nm = get_name(node, ty, level) + vt = get_valtype(node) + vr = DATA[node "/ver"] + if (vr == "") vr = " " + dsc = qstrip(DATA[node "/desc"]) + print " " nm " " vt " " vr " " dsc +} + +function tbl_entry_link(node, dst, level, parent ,nm,vt,dsc,ty,vr) +{ + if (!(node in NAME)) { + print "Error: path not found: " node > "/dev/stderr" + return + } + if (!(dst in NAME)) { + print "Error: path not found: " dst > "/dev/stderr" + return + } + + ty = DATA[dst "/type"] + nm = get_name(node, ty, level) + vt = get_valtype(dst) + vr = DATA[dst "/ver"] + if (vr == "") vr = " " + dsc = qstrip(DATA[dst "/desc"]) + print " " nm " " vt " " vr " " dsc " -> " +} + +function gen_main(path, v, n, N) +{ + print "

" DATA[path "/type"] ":" NAME[path] "

" +# print "

" +# print qstrip(DATA[path "/desc"]) + print "

" + print "" + tbl_hdr() + tbl_entry(path, 0) + gen_sub(path, 1) + print "
" +} + +function gen_roots(rpath, v, n, N) +{ + v = children(N, rpath) + for(n = 1; n <= v; n++) { + if (N[n] "/hide" in NAME) + continue + gen_main(N[n]) + } +} + +function gen_types(path, v, n, N, node) +{ + print "" + print "" + print "
type description" + + v = children(N, path) + for(n = 1; n <= v; n++) { + node = N[n] + print "
" NAME[node] + print " " qstripnl(DATA[node]) + } + print "
" +} + + +END { + print "

File format root nodes

" + print "

Each table below describes the full tree of one of the pcb-rnd file formats, from the root." + gen_roots("/lht_tree_doc/roots") + + print "

Common subtrees

" + print "

Each table below describes a subtree that usually does not specify a whole tree (thus they are usually not a valid file on their own). These subtrees are described in a separate table because they are used from multiple other trees." + gen_roots("/lht_tree_doc/comm") + + print "

Types

" + print "

" + gen_types("/lht_tree_doc/types") + + print "

Comments

" + print "

ver column: Format version range the subtree may appear in." + print "" + print "" +} Index: tags/2.1.2/doc/developer/lihata_format/render/lht.awk =================================================================== --- tags/2.1.2/doc/developer/lihata_format/render/lht.awk (nonexistent) +++ tags/2.1.2/doc/developer/lihata_format/render/lht.awk (revision 24813) @@ -0,0 +1,62 @@ +BEGIN { + q="\"" +} + +function parent(path) +{ + sub("/[^/]*$", "", path) + return path +} + +function children(DST, path) +{ + return split(CHILDREN[path], DST, "[|]") +} + +function sy_is_recursive(path, dp) +{ + dp = DATA[path] + gsub("/[0-9]::", "/", path) + if (path ~ dp) + rturn 1 + return 0 +} + +function sy_href(path) +{ + return "#" path +} + +(($1 == "open") || ($1 == "data")) { + path=$3 + gsub("[0-9]+::", "", path) + TYPE[path] = $2 + p = parent(path) + if (CHILDREN[p] == "") + CHILDREN[p] = path + else + CHILDREN[p] = CHILDREN[p] "|" path + data=$4 + gsub("\\\\057", "/", data) + DATA[path] = data + + name=$3 + sub("^.*/", "", name) + sub(".*::", "", name) + NAME[path] = name +} + +function qstrip(s) +{ + gsub("[\\\\]+164", " ", s) + gsub("[\\\\]n", " ", s) + return s +} + +function qstripnl(s) +{ + gsub("[\\\\]+164", " ", s) + gsub("[\\\\]n", "\n", s) + return s +} + Index: tags/2.1.2/doc/developer/lihata_format/render/render.sh =================================================================== --- tags/2.1.2/doc/developer/lihata_format/render/render.sh (nonexistent) +++ tags/2.1.2/doc/developer/lihata_format/render/render.sh (revision 24813) @@ -0,0 +1,6 @@ +#!/bin/sh + +for n in ../*.lht +do + lhtflat < $n +done | tee Flat | awk -F "[\t]" -f lht.awk -f common.awk -f $1.awk Property changes on: tags/2.1.2/doc/developer/lihata_format/render/render.sh ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/2.1.2/doc/developer/lihata_format/root_board.lht =================================================================== --- tags/2.1.2/doc/developer/lihata_format/root_board.lht (nonexistent) +++ tags/2.1.2/doc/developer/lihata_format/root_board.lht (revision 24813) @@ -0,0 +1,185 @@ +ha:lht_tree_doc { ha:roots { + + ha:pcb-rnd-board-v* { + type=ha + desc { + The full, self-contained description of a printed circuit board. + This is the root of a board .lht file. The * after the v in the name + is an integer which is the format version. + } + li:children { + ha:meta { + type=ha + desc { Any meta-data that won't directly turn into physical material (e.g. copper). } + li:children { + ha:board_name { valtype=string; desc={User assigned name of the board}} + ha:grid { + type=ha + desc { User interface last grid settings } + li:children { + ha:offs_x { valtype=coord; desc={grid origin: X offset from 0;0}} + ha:offs_y { valtype=coord; desc={grid origin: Y offset from 0;0}} + ha:spacing { valtype=coord; desc={distance between two grid points both in X and Y directions }} + } + } + ha:size { + type=ha + desc { object size related settings } + li:children { + ha:x { valtype=coord; desc={drawing area size X (width)}} + ha:y { valtype=coord; desc={drawing area size Y (height)}} + ha:isle_area_nm2 { valtype=double; desc={remove polygon islands smaller than this value, specified in nm2}} + ha:thermal_scale { valtype=double; desc={scale all thermals on the board by this factor}} + } + } + ha:drc { + type=ha + desc { design rule checker settings for the old DRC } + ver {<5} + li:children { + ha:bloat { valtype=coord; desc={Minimum copper spacing}} + ha:shrink { valtype=coord; desc={Minimum overlap between validly touching copper objects}} + ha:min_width { valtype=coord; desc={Minimum copper width}} + ha:min_silk { valtype=coord; desc={Minimum silk width}} + ha:min_drill { valtype=coord; desc={Minimum drill diameter}} + ha:min_ring { valtype=coord; desc={Minimum annular ring width}} + } + } + ha:cursor { + type=ha + desc { obsolete cursor/view state } + li:children { + ha:x { valtype=coord; obs=1; desc={last position, X (horizontal)}} + ha:y { valtype=coord; obs=1; desc={last position, Y (horizontal)}} + ha:zoom { valtype=double; obs=1; desc={last view zoom factor}} + } + } + } + } + ha:layer_stack { + type=ha + desc { physical layer stack information: geometry and properties of physical layers } + li:children { + ha:groups { + type=li + desc { ordered list of physical layers from top to bottom } + li:children { + ha:INTEGER { + li:name_patterns={p={[0-9]+}} + type=ha + desc { a layer group (a physical layer of the board); the ID of the layer group is the integer in the name of the node } + li:children { + ha:name { valtype=string; desc={user assigned name of the layer group, e.g. "top copper"}} + ha:type { + type=ha + desc { a flag-list of layer type flag bits } + sy:children = {/lht_tree_doc/comm/layer_mask/children} + } + ha:name { valtype=string; ver={>=6} desc={purpose of layer groups (useful with mechanical/documentation groups}} + ha:layers { + type=li + desc { ordered list of logical layer IDs hosted by this layer group } + } + } + } + } + } + } + } + ha:font { + type=ha + desc { font kit: all fonts used on the board (if no font specified, default font will be used) } + li:children { + sy:FONT-ID {/lht_tree_doc/roots/pcb-rnd-font-v1/children/FONT-ID} + } + } + ha:styles { + type=ha + desc { routing styles hash: collection of all available routing syles } + ha:ROUTE-STYLE-NAME { + type=ha + desc { routing style: a collection of pen settings } + li:children { + ha:thickness { valtype=coord; desc={default trace thickness (affects lines and arcs)}} + ha:text_thick { valtype=coord; ver={>=6} desc={default text stroke thickness (0 means pick thickness automatically using the original algorithm)}} + ha:text_scale { valtype=coord; ver={>=6} desc={default text scaling (0 means 100%, for backward compatibility)}} + ha:clearance { valtype=coord; desc={default clearance (affects lines, arcs and polygons)}} + ha:diameter { valtype=coord; ver={<=5} desc={old round via outer diameter; removed in favor of padstack prototype based vias, see via_proto}} + ha:hole { valtype=coord; ver={<=5} desc={old round via hole diameter; removed in favor of padstack prototype based vias, see via_proto}} + ha:via_proto { valtype=integer; ver={>5} desc={padstack prototype ID used for placing new vias}} + sy:attr@dup {/lht_tree_doc/comm/attributes} + } + } + } + ha:netlists { + type=ha + desc { all available netlists } + li:children { + ha:netlist { + type=li + desc { the input netlist (as seen in the last netlist import, a.k.a. forward annotation) } + li:children { + ha:NETNAME { + type=ha + desc { a network } + li:children { + ha:conn { + type=li + desc { list of terminals connected to the network } + li:children { + ha:diameter { valtype=string; desc={refdes-terminal}} + } + } + sy:attr@dup = {/lht_tree_doc/comm/attributes_v5p} + } + } + } + } + ha:netlist_patch { + type=li + desc { a list of intentional deviations from the input netlist, a.k.a. material for back annotation } + li:children { + ha:net_info { + type=li + desc { describe the current state of a net, as seen on the input } + li:children { + ha:net { valtype=string; desc={net name; first item on the list, only once}} + ha:term { valtype=string; desc={terminal name; zero or more items starting from the second item}} + } + } + ha:add_conn { + type=ha + desc { the 'as built' network requires a new connection to be created during the back annotation } + li:children { + ha:net { valtype=string; desc={net name the terminal should be added to}} + ha:term { valtype=string; desc={terminal name}} + } + } + ha:del_conn { + type=ha + desc { the 'as built' network requires an existing connection to be removed during the back annotation } + li:children { + ha:net { valtype=string; desc={net name the terminal should be removed from}} + ha:term { valtype=string; desc={terminal name}} + } + } + ha:change_attrib { + type=ha + desc { the 'as built' network requires an attribute to be set or changed } + li:children { + ha:net { valtype=string; desc={net name whose attribute needs to be changed }} + ha:key { valtype=string; desc={key (name) of the attribute}} + ha:val { valtype=string; desc={new value of the attribute}} + } + } + } + } + } + } + sy:conf = {/lht_tree_doc/roots/pcb-rnd-conf-v1} + sy:data = {/lht_tree_doc/comm/data} + sy:attributes@dup = {/lht_tree_doc/comm/attributes} + } + } + +}} Index: tags/2.1.2/doc/developer/lihata_format/root_conf.lht =================================================================== --- tags/2.1.2/doc/developer/lihata_format/root_conf.lht (nonexistent) +++ tags/2.1.2/doc/developer/lihata_format/root_conf.lht (revision 24813) @@ -0,0 +1,22 @@ +ha:lht_tree_doc { ha:roots { + + ha:pcb-rnd-conf-v1 { + type=li + desc=complete pcb-rnd configuration tree + li:children { + ha:overwrite { + type=ha + desc={overwrite values while merging; children: a full or partial config tree} + } + ha:prepend { + type=ha + desc={prepend values while merging; children: a full or partial config tree} + } + ha:append { + type=ha + desc={append values while merging; children: a full or partial config tree} + } + } + } + +}} Index: tags/2.1.2/doc/developer/lihata_format/root_font.lht =================================================================== --- tags/2.1.2/doc/developer/lihata_format/root_font.lht (nonexistent) +++ tags/2.1.2/doc/developer/lihata_format/root_font.lht (revision 24813) @@ -0,0 +1,69 @@ +ha:lht_tree_doc { ha:roots { + + ha:pcb-rnd-font-v1 { + type=li + desc={font description} + li:children { + ha:FONT-ID { + type=ha + li:name_patterns={p={geda_pcb}; p={[0-9]+}} + desc { the full description of a font; the node name is the integer font id or "geda_pcb" for font 0 (for historical reasons); the name is used only to make each node unique, the ID is also a field below } + li:children { + ha:cell_height { valtype=coord; desc={height of the tallest glyph}} + ha:cell_width { valtype=coord; desc={width of the widest glyph}} + ha:id { valtype=integer; desc={unique font ID within the fontkit; fonts are referenced by ID}} + ha:name { valtype=string; desc={user specified, user readable font name}} + ha:symbols { + type=ha + desc { a collections of glyphs availbale in the font } + li:children { + ha:CHARACTER { + type=ha + li:name_patterns={p={.}} + desc { Description of a glyph (symbol). Node name is a signel ASCII character or is of format &xx where xx is a hex digit of the ASCII code of the character. Characters that must use the hex version are: codes below 33 or over 126, &, #, {, \}, /, :, ;, =, \\, :} + li:children { + ha:height { valtype=coord; desc={height of the glyph}} + ha:width { valtype=coord; desc={width of the glyph}} + ha:delta { valtype=coord; desc={extra space always inserted after the current symbol, before the next character}} + ha:objects { + type=li + desc={objects that make up the symbol; IDs are per symbol local IDs counted from 0} + li:children { + ha:line.ID { + type=ha + desc={round cap line, simplified} + li:children { + ha:x1 = { valtype=coord; desc={line first endpoint, horizontal offset }} + ha:y1 = { valtype=coord; desc={line first endpoint, vertical offset }} + ha:x2 = { valtype=coord; desc={line second endpoint, horizontal offset }} + ha:y2 = { valtype=coord; desc={line second endpoint, vertical offset }} + ha:thickness = { valtype=coord; desc={width of the line }} + } + } + ha:simplearc.ID { + type=ha + desc={round cap arc, simplified } + li:children { + ha:x = { valtype=coord; desc={center, X coord}} + ha:y = { valtype=coord; desc={center, Y coord}} + ha:r = { valtype=coord; desc={radius (of the centerline of the arc) }} + ha:thickness = { valtype=coord; desc={width of the pen the arc is drawn with }} + ha:astart = { valtype=angle; desc={ start angle}} + ha:adelta = { valtype=angle; desc={ delta angle}} + } + } + ha:simplepoly.ID { + type=li + desc={round cap arc, simplified; contains a flat list of coords; each coord pair is an x;y corner of the outline of the polygon (odd indices are x coords, even indices are y coords) } + } + } + } + } + } + } + } + } + } + } + } +}} \ No newline at end of file Index: tags/2.1.2/doc/developer/lihata_format/root_log.lht =================================================================== --- tags/2.1.2/doc/developer/lihata_format/root_log.lht (nonexistent) +++ tags/2.1.2/doc/developer/lihata_format/root_log.lht (revision 24813) @@ -0,0 +1,26 @@ +ha:lht_tree_doc { ha:roots { + + ha:pcb-rnd-log-v* { + type=ha + desc={pcb-rnd message log dump} + li:children { + ha:entries { + type=li + desc={list of message log entries} + li:children { + ha:ID { + type=ha + desc={each entry is identified by an unique unsigned long int ID} + li:children { + ha:stamp { valtype=string; desc={UNIX time stamp of entry creation} } + ha:level { valtype=integer; desc={log level enum value (see error.h)} } + ha:seen { valtype=integer; desc={1 if the message got displayed} } + ha:str { valtype=string; desc={log message} } + } + } + } + } + } + } + +}} Index: tags/2.1.2/doc/developer/lihata_format/root_menu.lht =================================================================== --- tags/2.1.2/doc/developer/lihata_format/root_menu.lht (nonexistent) +++ tags/2.1.2/doc/developer/lihata_format/root_menu.lht (revision 24813) @@ -0,0 +1,151 @@ +ha:lht_tree_doc { + +ha:roots { + ha:menu { + type=ha + name={} + desc={Menu file} + li:children { + ha:mouse { + type=li + desc={mouse bindings} + li:children { + ha:left { + type=li + desc={actions to execute on left button click} + sy:children = {/lht_tree_doc/comm/mouse_actions/children} + } + ha:middle { + type=li + desc={actions to execute on middle button click} + sy:children = {/lht_tree_doc/comm/mouse_actions/children} + } + ha:right { + type=li + desc={actions to execute on right button click} + sy:children = {/lht_tree_doc/comm/mouse_actions/children} + } + ha:scroll-up { + type=li + desc={actions to execute on scroll wheel scolling up event} + sy:children = {/lht_tree_doc/comm/mouse_actions_scroll/children} + } + ha:scroll-down { + type=li + desc={actions to execute on scroll wheel scolling down event} + sy:children = {/lht_tree_doc/comm/mouse_actions_scroll/children} + } + } + } + ha:main_menu { + type=li + desc={root of the main pull-down menu system; ordered list of main menus} + li:children { + ha:MENUNAME { + type=ha + desc={main menu name, e.g. "File"} + li:children { + sy:m@dup = {/lht_tree_doc/comm/submenu/children/m} + sy:submenu = {/lht_tree_doc/comm/submenu} + } + } + } + } + ha:popups { + type=li + desc={collection of popup menus} + li:children { + ha:POPUPNAME { + type=ha + desc={popup menu name, e.g. "layer" for layer context menu} + li:children { + sy:m@dup = {/lht_tree_doc/comm/submenu/children/m} + sy:submenu = {/lht_tree_doc/comm/submenu} + } + } + } + } + } + } +} + +ha:comm { + ha:mouse_actions { + hide=1 + li:children { + ha:press { type=li; desc={actions to execute on mouse button press when no modifier is pressed} } + ha:press-shift { type=li; desc={actions to execute on mouse button press when shift is pressed} } + ha:press-ctrl { type=li; desc={actions to execute on mouse button press when control is pressed} } + ha:release { type=li; desc={actions to execute on mouse button release when no modifier is pressed} } + ha:release-shift { type=li; desc={actions to execute on mouse button release when shift is pressed} } + ha:release-ctrl { type=li; desc={actions to execute on mouse button release when control is pressed} } + } + } + ha:mouse_actions_scroll { + hide=1 + li:children { + ha:press { type=li; desc={actions to execute on mouse button press when no modifier is pressed} } + ha:press-shift { type=li; desc={actions to execute on mouse button press when shift is pressed} } + ha:press-ctrl { type=li; desc={actions to execute on mouse button press when control is pressed} } + } + } + + ha:submenu { + type=li + desc={ordered list of menu items for a submenu} + li:children { + ha:m = {valtype=string; desc={mnemonic: single character that should be underlined and used as a hot key in the menu name}} + ha:- = {valtype=none; desc={horizontal separator}} + ha:@ANCHOR = {valtype=none; desc={an anchor is an invisible placeholder where a dynamically generated set of menu items should be inserted runtime}} + ha:SUBSUBMENUNAME = { + type=ha + desc={sub-submenu item: opens a new level of submenu when clicked} + li:children { + sy:m@dup = {/lht_tree_doc/comm/submenu/children/m} + sy:submenu = {/lht_tree_doc/comm/submenu} + } + } + ha:LEAFSUBMENUNAME = { + type=ha + desc={leaf submenu item: executes an action when clicked} + li:children { + sy:m@dup = {/lht_tree_doc/comm/submenu/children/m} + ha:a1 { + type=li + name=a + desc={list of alternative hotkey sequences to activate the menu} + } + ha:a2 { + valtype=string + name=a + desc={a single hotkey sequences to activate the menu} + } + ha:action1 { + type=li + name=action + desc={list of actions to execute when the menu is activated} + } + ha:action2 { + valtype=string + name=action + desc={a single action to execute when the menu is activated} + } + ha:tip { + valtype=string + desc={tooltip text} + } + ha:checked { + valtype=string + desc={the menu item has a checkbox; value is the action to execute to determine whether the menu item's checkbox is checked or not} + } + ha:update_on { + valtype=string + desc={path of a conf node that triggers re-evaluation of the checkbox state} + } + } + } + } + } +} +} + Index: tags/2.1.2/doc/developer/lihata_format/root_project.lht =================================================================== --- tags/2.1.2/doc/developer/lihata_format/root_project.lht (nonexistent) +++ tags/2.1.2/doc/developer/lihata_format/root_project.lht (revision 24813) @@ -0,0 +1,54 @@ +ha:lht_tree_doc { ha:roots { + + ha:coraleda-project-v1 { + type=ha + desc={Project file root. Except for "common", each software package should create a single subtree under the root; the subtree shall be named after the software package } + li:children { + ha:common { + type=ha + desc={project settings that should be common to all software packages} + li:children { + ha:name { valtype=string; desc={long name of the project }} + ha:desc { valtype=string; desc={description of the project }} + ha:url { valtype=string; desc={homepage of the project }} + ha:vcs { valtype=string; desc={main vcs url for the project }} + ha:contact { valtype=string; desc={author/maintainer contact info }} + ha:files { + type=li + desc={ordered list of source files being used by the project} + li:children { + ha:NAME { + type=ha + desc={a project member file} + li:children { + ha:path { valtype=string; desc={path to the file, relative to the project file }} + ha:desc { valtype=string; desc={description of the file }} + ha:type { valtype=string; desc={optional: type of the file; one of: "pcb", "schematic", "doc" }} + } + } + } + } + ha:libs { + type=li + desc={ordered list of libraries the project depends on} + li:children { + ha:NAME { + type=ha + desc={a library} + li:children { + ha:path { valtype=string; desc={path to the library, relative to the project file; all files and subdirectories under the root, recursively, are considered part of the library (must not be used together with url) }} + ha:url { valtype=string; desc={url to the library (must not be used together with path) }} + ha:desc { valtype=string; desc={description of the library }} + ha:type { valtype=string; desc={optional: type of the library; one of: "footprint" (for pcb design), "symbol" (for schematic), "sim" (models and subcircuits for e.g. spice simulation) }} + } + } + } + } + } + } + sy:pcb-rnd-conf-v1 = {/lht_tree_doc/roots/pcb-rnd-conf-v1} + } + } + +}} + Index: tags/2.1.2/doc/developer/lihata_format/root_subc.lht =================================================================== --- tags/2.1.2/doc/developer/lihata_format/root_subc.lht (nonexistent) +++ tags/2.1.2/doc/developer/lihata_format/root_subc.lht (revision 24813) @@ -0,0 +1,20 @@ +ha:lht_tree_doc { ha:roots { + + ha:pcb-rnd-subcircuit-v* { + type=li + desc={footprint file containing a single subcircuit} + li:children { + ha:subc.ID { + type=ha + desc={an instance (full copy) of a subcircuit} + ver = {>=3} + li:children { + ha:uid = { valtype=minuid; desc={UID assigned by the user to track subc history }} + sy:attr@dup = {/lht_tree_doc/comm/attributes} + sy:flags@dup = {/lht_tree_doc/comm/flags_subcircuit} + sy:data = {/lht_tree_doc/comm/data} + } + } + } + } +}} \ No newline at end of file Index: tags/2.1.2/doc/developer/lihata_format/root_view.lht =================================================================== --- tags/2.1.2/doc/developer/lihata_format/root_view.lht (nonexistent) +++ tags/2.1.2/doc/developer/lihata_format/root_view.lht (revision 24813) @@ -0,0 +1,31 @@ +ha:lht_tree_doc { ha:roots { + + ha:view-list-v* { + type=li + desc={a list of view items (locations and objects to highlight on the board, e.g. for DRC violations)} + li:children { + ha:view.ID { + type=ha + desc={a view item; ID is a 32 bit signed integer, unique within the view list} + li:children { + ha:type { valtype=string; desc={free form short text for type of the entry; the GUI may group items by type} } + ha:title { valtype=string; desc={free form short text for the title of the entry; the GUI typically uses this in brief listings} } + ha:description { valtype=string; desc={free form long text for the detailed description of the entry } } + ha:bbox { type=li; valtype=coord; desc={optional: 4 coordinates in x1;y1;x2;y2 order that describes the bounding box of the view in board space coordinates; when available, the preview or go-to will use this for view box} } + ha:xy { type=li; valtype=coord; desc={optional: 2 coordinates in x;y order that describes a specific board location} } + ha:objs.ID { + type=li + desc={a group of related objects; there should be at most two groups with ID 0 and 1. These objects are often highlighted in red and blue.} + li:children { + ha:id { + type=li + desc={objects are specified as a list of object IDs (32 bit integers)} + } + } + } + } + } + } + } + +}} Index: tags/2.1.2/doc/developer/lihata_format/submenu.svg =================================================================== --- tags/2.1.2/doc/developer/lihata_format/submenu.svg (nonexistent) +++ tags/2.1.2/doc/developer/lihata_format/submenu.svg (revision 24813) @@ -0,0 +1,256 @@ + + + + + + +li:submenu + + + +/lht_tree_doc/comm/submenu + + +li:submenu + + + + + +/lht_tree_doc/comm/submenu/children/m + + +m +string + + + + + +/lht_tree_doc/comm/submenu->/lht_tree_doc/comm/submenu/children/m + + + + + +/lht_tree_doc/comm/submenu/children/- + + +- +none + + + + + +/lht_tree_doc/comm/submenu->/lht_tree_doc/comm/submenu/children/- + + + + + +/lht_tree_doc/comm/submenu/children/@ANCHOR + + +@ANCHOR +none + + + + + +/lht_tree_doc/comm/submenu->/lht_tree_doc/comm/submenu/children/@ANCHOR + + + + + +/lht_tree_doc/comm/submenu/children/SUBSUBMENUNAME + + +ha:SUBSUBMENUNAME + + + + + +/lht_tree_doc/comm/submenu->/lht_tree_doc/comm/submenu/children/SUBSUBMENUNAME + + + + + +/lht_tree_doc/comm/submenu/children/LEAFSUBMENUNAME + + +ha:LEAFSUBMENUNAME + + + + + +/lht_tree_doc/comm/submenu->/lht_tree_doc/comm/submenu/children/LEAFSUBMENUNAME + + + + + +dup51_/lht_tree_doc/comm/submenu/children/m + + +m +string + + + + + +/lht_tree_doc/comm/submenu/children/SUBSUBMENUNAME->dup51_/lht_tree_doc/comm/submenu/children/m + + + + + +dup52_/lht_tree_doc/comm/submenu/children/SUBSUBMENUNAME/children/submenu + +submenu -> + + + + + +/lht_tree_doc/comm/submenu/children/SUBSUBMENUNAME->dup52_/lht_tree_doc/comm/submenu/children/SUBSUBMENUNAME/children/submenu + + + + + +dup53_/lht_tree_doc/comm/submenu/children/m + + +m +string + + + + + +/lht_tree_doc/comm/submenu/children/LEAFSUBMENUNAME->dup53_/lht_tree_doc/comm/submenu/children/m + + + + + +/lht_tree_doc/comm/submenu/children/LEAFSUBMENUNAME/children/a1 + + +li:a + + + + + +/lht_tree_doc/comm/submenu/children/LEAFSUBMENUNAME->/lht_tree_doc/comm/submenu/children/LEAFSUBMENUNAME/children/a1 + + + + + +/lht_tree_doc/comm/submenu/children/LEAFSUBMENUNAME/children/a2 + + +a +string + + + + + +/lht_tree_doc/comm/submenu/children/LEAFSUBMENUNAME->/lht_tree_doc/comm/submenu/children/LEAFSUBMENUNAME/children/a2 + + + + + +/lht_tree_doc/comm/submenu/children/LEAFSUBMENUNAME/children/action1 + + +li:action + + + + + +/lht_tree_doc/comm/submenu/children/LEAFSUBMENUNAME->/lht_tree_doc/comm/submenu/children/LEAFSUBMENUNAME/children/action1 + + + + + +/lht_tree_doc/comm/submenu/children/LEAFSUBMENUNAME/children/action2 + + +action +string + + + + + +/lht_tree_doc/comm/submenu/children/LEAFSUBMENUNAME->/lht_tree_doc/comm/submenu/children/LEAFSUBMENUNAME/children/action2 + + + + + +/lht_tree_doc/comm/submenu/children/LEAFSUBMENUNAME/children/tip + + +tip +string + + + + + +/lht_tree_doc/comm/submenu/children/LEAFSUBMENUNAME->/lht_tree_doc/comm/submenu/children/LEAFSUBMENUNAME/children/tip + + + + + +/lht_tree_doc/comm/submenu/children/LEAFSUBMENUNAME/children/checked + + +checked +string + + + + + +/lht_tree_doc/comm/submenu/children/LEAFSUBMENUNAME->/lht_tree_doc/comm/submenu/children/LEAFSUBMENUNAME/children/checked + + + + + +/lht_tree_doc/comm/submenu/children/LEAFSUBMENUNAME/children/update_on + + +update_on +string + + + + + +/lht_tree_doc/comm/submenu/children/LEAFSUBMENUNAME->/lht_tree_doc/comm/submenu/children/LEAFSUBMENUNAME/children/update_on + + + + + Index: tags/2.1.2/doc/developer/lihata_format/tree.html =================================================================== --- tags/2.1.2/doc/developer/lihata_format/tree.html (nonexistent) +++ tags/2.1.2/doc/developer/lihata_format/tree.html (revision 24813) @@ -0,0 +1,663 @@ + + + + pcb-rnd developer manual - lihata file formats + + + +

File format root nodes

+

Each table below describes the full tree of one of the pcb-rnd file formats, from the root. +

ha:pcb-rnd-board-v*

+

+ +
type:name value ver description +
ha:pcb-rnd-board-v*     The full, self-contained description of a printed circuit board. This is the root of a board .lht file. The * after the v in the name is an integer which is the format version. +
 ha:meta     Any meta-data that won't directly turn into physical material (e.g. copper). +
  board_name string   User assigned name of the board +
  ha:grid     User interface last grid settings +
   offs_x coord   grid origin: X offset from 0;0 +
   offs_y coord   grid origin: Y offset from 0;0 +
   spacing coord   distance between two grid points both in X and Y directions +
  ha:size     object size related settings +
   x coord   drawing area size X (width) +
   y coord   drawing area size Y (height) +
   isle_area_nm2 double   remove polygon islands smaller than this value, specified in nm2 +
   thermal_scale double   scale all thermals on the board by this factor +
  ha:drc   <5 design rule checker settings for the old DRC +
   bloat coord   Minimum copper spacing +
   shrink coord   Minimum overlap between validly touching copper objects +
   min_width coord   Minimum copper width +
   min_silk coord   Minimum silk width +
   min_drill coord   Minimum drill diameter +
   min_ring coord   Minimum annular ring width +
  ha:cursor     obsolete cursor/view state +
   x coord   last position, X (horizontal) +
   y coord   last position, Y (horizontal) +
   zoom double   last view zoom factor +
 ha:layer_stack     physical layer stack information: geometry and properties of physical layers +
  li:groups     ordered list of physical layers from top to bottom +
   ha:INTEGER     a layer group (a physical layer of the board); the ID of the layer group is the integer in the name of the node +
    name string >=6 purpose of layer groups (useful with mechanical/documentation groups +
    ha:type     a flag-list of layer type flag bits +
     top flag   location: top side +
     bottom flag   location: bottom side +
     intern flag   location: internal +
     logical flag   location: logical (not in the actual stackup) +
     copper flag   material: copper +
     silk flag   material: silk +
     mask flag   material: mask +
     paste flag   material: paste +
     outline flag   "material": router path (board outline, slots, cutouts) +
     substrate flag   material: substrate or insulator +
    name string >=6 purpose of layer groups (useful with mechanical/documentation groups +
    li:layers     ordered list of logical layer IDs hosted by this layer group +
 ha:font     font kit: all fonts used on the board (if no font specified, default font will be used) +
  ha:FONT-ID     the full description of a font; the node name is the integer font id or "geda_pcb" for font 0 (for historical reasons); the name is used only to make each node unique, the ID is also a field below -> +
 ha:styles     routing styles hash: collection of all available routing syles +
 ha:netlists     all available netlists +
  li:netlist     the input netlist (as seen in the last netlist import, a.k.a. forward annotation) +
   ha:NETNAME     a network +
    li:conn     list of terminals connected to the network +
     diameter string   refdes-terminal +
    ha:attributes   >=5 a hash of attribute key=value pairs +
     attrib-key string   attribute value +
  li:netlist_patch     a list of intentional deviations from the input netlist, a.k.a. material for back annotation +
   li:net_info     describe the current state of a net, as seen on the input +
    net string   net name; first item on the list, only once +
    term string   terminal name; zero or more items starting from the second item +
   ha:add_conn     the 'as built' network requires a new connection to be created during the back annotation +
    net string   net name the terminal should be added to +
    term string   terminal name +
   ha:del_conn     the 'as built' network requires an existing connection to be removed during the back annotation +
    net string   net name the terminal should be removed from +
    term string   terminal name +
   ha:change_attrib     the 'as built' network requires an attribute to be set or changed +
    net string   net name whose attribute needs to be changed +
    key string   key (name) of the attribute +
    val string   new value of the attribute +
 li:conf     complete pcb-rnd configuration tree -> +
 ha:data     Layers and global objects of the board -> +
 ha:attributes     a hash of attribute key=value pairs +
  attrib-key string   attribute value +
+

li:pcb-rnd-conf-v1

+

+ +
type:name value ver description +
li:pcb-rnd-conf-v1     complete pcb-rnd configuration tree +
 ha:overwrite     overwrite values while merging; children: a full or partial config tree +
 ha:prepend     prepend values while merging; children: a full or partial config tree +
 ha:append     append values while merging; children: a full or partial config tree +
+

li:pcb-rnd-font-v1

+

+ +
type:name value ver description +
li:pcb-rnd-font-v1     font description +
 ha:FONT-ID     the full description of a font; the node name is the integer font id or "geda_pcb" for font 0 (for historical reasons); the name is used only to make each node unique, the ID is also a field below +
  cell_height coord   height of the tallest glyph +
  cell_width coord   width of the widest glyph +
  id integer   unique font ID within the fontkit; fonts are referenced by ID +
  name string   user specified, user readable font name +
  ha:symbols     a collections of glyphs availbale in the font +
   ha:CHARACTER     Description of a glyph (symbol). Node name is a signel ASCII character or is of format &xx where xx is a hex digit of the ASCII code of the character. Characters that must use the hex version are: codes below 33 or over 126, &, #, {, }, /, :, ;, =, \, : +
    height coord   height of the glyph +
    width coord   width of the glyph +
    delta coord   extra space always inserted after the current symbol, before the next character +
    li:objects     objects that make up the symbol; IDs are per symbol local IDs counted from 0 +
     ha:line.ID     round cap line, simplified +
      x1 coord   line first endpoint, horizontal offset +
      y1 coord   line first endpoint, vertical offset +
      x2 coord   line second endpoint, horizontal offset +
      y2 coord   line second endpoint, vertical offset +
      thickness coord   width of the line +
     ha:simplearc.ID     round cap arc, simplified +
      x coord   center, X coord +
      y coord   center, Y coord +
      r coord   radius (of the centerline of the arc) +
      thickness coord   width of the pen the arc is drawn with +
      astart angle   start angle +
      adelta angle   delta angle +
     li:simplepoly.ID     round cap arc, simplified; contains a flat list of coords; each coord pair is an x;y corner of the outline of the polygon (odd indices are x coords, even indices are y coords) +
+

ha:pcb-rnd-log-v*

+

+ +
type:name value ver description +
ha:pcb-rnd-log-v*     pcb-rnd message log dump +
 li:entries     list of message log entries +
  ha:ID     each entry is identified by an unique unsigned long int ID +
   stamp string   UNIX time stamp of entry creation +
   level integer   log level enum value (see error.h) +
   seen integer   1 if the message got displayed +
   str string   log message +
+

ha:menu

+

+ +
type:name value ver description +
ha:     Menu file +
 li:mouse     mouse bindings +
  li:left     actions to execute on left button click +
   li:press     actions to execute on mouse button press when no modifier is pressed +
   li:press-shift     actions to execute on mouse button press when shift is pressed +
   li:press-ctrl     actions to execute on mouse button press when control is pressed +
   li:release     actions to execute on mouse button release when no modifier is pressed +
   li:release-shift     actions to execute on mouse button release when shift is pressed +
   li:release-ctrl     actions to execute on mouse button release when control is pressed +
  li:middle     actions to execute on middle button click +
   li:press     actions to execute on mouse button press when no modifier is pressed +
   li:press-shift     actions to execute on mouse button press when shift is pressed +
   li:press-ctrl     actions to execute on mouse button press when control is pressed +
   li:release     actions to execute on mouse button release when no modifier is pressed +
   li:release-shift     actions to execute on mouse button release when shift is pressed +
   li:release-ctrl     actions to execute on mouse button release when control is pressed +
  li:right     actions to execute on right button click +
   li:press     actions to execute on mouse button press when no modifier is pressed +
   li:press-shift     actions to execute on mouse button press when shift is pressed +
   li:press-ctrl     actions to execute on mouse button press when control is pressed +
   li:release     actions to execute on mouse button release when no modifier is pressed +
   li:release-shift     actions to execute on mouse button release when shift is pressed +
   li:release-ctrl     actions to execute on mouse button release when control is pressed +
  li:scroll-up     actions to execute on scroll wheel scolling up event +
   li:press     actions to execute on mouse button press when no modifier is pressed +
   li:press-shift     actions to execute on mouse button press when shift is pressed +
   li:press-ctrl     actions to execute on mouse button press when control is pressed +
  li:scroll-down     actions to execute on scroll wheel scolling down event +
   li:press     actions to execute on mouse button press when no modifier is pressed +
   li:press-shift     actions to execute on mouse button press when shift is pressed +
   li:press-ctrl     actions to execute on mouse button press when control is pressed +
 li:main_menu     root of the main pull-down menu system; ordered list of main menus +
  ha:MENUNAME     main menu name, e.g. "File" +
   m string   mnemonic: single character that should be underlined and used as a hot key in the menu name +
   li:submenu     ordered list of menu items for a submenu -> +
 li:popups     collection of popup menus +
  ha:POPUPNAME     popup menu name, e.g. "layer" for layer context menu +
   m string   mnemonic: single character that should be underlined and used as a hot key in the menu name +
   li:submenu     ordered list of menu items for a submenu -> +
+

ha:coraleda-project-v1

+

+ +
type:name value ver description +
ha:coraleda-project-v1     Project file root. Except for "common", each software package should create a single subtree under the root; the subtree shall be named after the software package +
 ha:common     project settings that should be common to all software packages +
  name string   long name of the project +
  desc string   description of the project +
  url string   homepage of the project +
  vcs string   main vcs url for the project +
  contact string   author/maintainer contact info +
  li:files     ordered list of source files being used by the project +
   ha:NAME     a project member file +
    path string   path to the file, relative to the project file +
    desc string   description of the file +
    type string   optional: type of the file; one of: "pcb", "schematic", "doc" +
  li:libs     ordered list of libraries the project depends on +
   ha:NAME     a library +
    path string   path to the library, relative to the project file; all files and subdirectories under the root, recursively, are considered part of the library (must not be used together with url) +
    url string   url to the library (must not be used together with path) +
    desc string   description of the library +
    type string   optional: type of the library; one of: "footprint" (for pcb design), "symbol" (for schematic), "sim" (models and subcircuits for e.g. spice simulation) +
 li:pcb-rnd-conf-v1     complete pcb-rnd configuration tree -> +
+

li:pcb-rnd-subcircuit-v*

+

+ +
type:name value ver description +
li:pcb-rnd-subcircuit-v*     footprint file containing a single subcircuit +
 ha:subc.ID   >=3 an instance (full copy) of a subcircuit +
  uid minuid   UID assigned by the user to track subc history +
  ha:attributes     a hash of attribute key=value pairs +
   attrib-key string   attribute value +
  ha:flags     flag bits of a subcircuit +
   found flag   If set, this object has been found by FindConnection() +
   selected flag   Set when the object is selected. +
   drc flag   Set for objects that fail DRC: flag like FOUND flag for DRC checking. +
   lock flag   Set for locked objects. +
   nonetlist flag   subcircuit is not on the netlist and should not interfere with the netlist +
   termname flag   when set the names of pins are shown. +
   floater flag   subc part can be moved after subc placing +
  ha:data     Layers and global objects of the board -> +
+

li:view-list-v*

+

+ +
type:name value ver description +
li:view-list-v*     a list of view items (locations and objects to highlight on the board, e.g. for DRC violations) +
 ha:view.ID     a view item; ID is a 32 bit signed integer, unique within the view list +
  type string   free form short text for type of the entry; the GUI may group items by type +
  title string   free form short text for the title of the entry; the GUI typically uses this in brief listings +
  description string   free form long text for the detailed description of the entry +
  li:bbox coord   optional: 4 coordinates in x1;y1;x2;y2 order that describes the bounding box of the view in board space coordinates; when available, the preview or go-to will use this for view box +
  li:xy coord   optional: 2 coordinates in x;y order that describes a specific board location +
  li:objs.ID     a group of related objects; there should be at most two groups with ID 0 and 1. These objects are often highlighted in red and blue. +
   li:id     objects are specified as a list of object IDs (32 bit integers) +
+

Common subtrees

+

Each table below describes a subtree that usually does not specify a whole tree (thus they are usually not a valid file on their own). These subtrees are described in a separate table because they are used from multiple other trees. +

ha:data

+

+ +
type:name value ver description +
ha:data     Layers and global objects of the board +
 li:objects     List of global (non-layer/multi-layer) objects +
  ha:padstack_ref.ID   >=4 a padstack reference (instance) placed on the board (e.g. used as a via) +
   proto integer   padstack prototype ID to use, from the parent data's proto list +
   x coord   place padstack with origin at this horizontal coordinate +
   y coord   place padstack with origin at this vertical coordinate +
   clearance coord   global clearance; if non-zero, overrides local (per shape) clearance +
   rot angle   rotation angle in degrees +
   xmirror integer   0 or 1; if 1, mirror all shapes over the x (horizontal) axis (so that y coords are flipped) +
   smirror integer   0 or 1; if 1, mirror the layer stackup: bottom becomes top, top becomes bottom (a.k.a. "place on the other side") +
   ha:attributes     a hash of attribute key=value pairs +
    attrib-key string   attribute value +
   ha:flags     flag bits of a padstack +
    found flag   If set, this object has been found by FindConnection() +
    hole flag   For pins and vias, this flag means that the pin or via is a hole without a copper annulus. +
    clearline flag   For lines and arcs, the line/arc will clear polygons instead of connecting to them. +
    selected flag   Set when the object is selected. +
    auto flag   For lines and vias, indicates that these were created by the autorouter. +
    warn flag   For pins, vias, and pads, set to indicate a warning. +
    drc flag   Set for objects that fail DRC: flag like FOUND flag for DRC checking. +
    lock flag   Set for locked objects. +
    termname flag   when set the names of pins are shown. +
    floater flag   subc part can be moved after subc placing +
   li:thermal     list of thermal shapes, per layer +
    li:LAYERID     integer layer ID the thermal affects; each word is a boolean flag that is either present on the list or is missing; only one shape may be present +
     on none   thermal is present on this layer; if not present, all other thermal flags are ignored on this layer +
     diag none   thermal graphics is not axis aligned but diagonal (rotated by 45 degrees) +
     round none   shape: rounded edge fingers +
     sharp none   shape: sharp edge fingers +
     solid none   shape: no thermal relief, solid connection without clearance +
     noshape none >=6 shape: special: omit copper shape of the padstack on this layer +
  ha:via.ID   <=4 an old via object (loaded as padstack in the new model) +
   x coord   place padstack with origin at this horizontal coordinate +
   y coord   place padstack with origin at this vertical coordinate +
   thickness coord   copper shape dimension (diameter) +
   clearance coord   copper clearance around the copper shape +
   mask coord   mask cutout shape dimension (diameter) +
   hole coord   drill/hole diameter +
   name string   optional name attribute +
   number string   for a pin (or to-be-pin) this is the terminal ID +
   ha:attributes     a hash of attribute key=value pairs +
    attrib-key string   attribute value +
   ha:flags_pinvia     flag bits of a pin or via +
    found flag   If set, this object has been found by FindConnection() +
    hole flag   For pins and vias, this flag means that the pin or via is a hole without a copper annulus. +
    clearline flag   For lines and arcs, the line/arc will clear polygons instead of connecting to them. +
    selected flag   Set when the object is selected. +
    auto flag   For lines and vias, indicates that these were created by the autorouter. +
    warn flag   For pins, vias, and pads, set to indicate a warning. +
    usetherm flag   Obsolete, indicates that pins/vias should be drawn with thermal fingers. +
    drc flag   Set for objects that fail DRC: flag like FOUND flag for DRC checking. +
    lock flag   Set for locked objects. +
    nonetlist flag   subcircuit is not on the netlist and should not interfere with the netlist +
    termname flag   when set the names of pins are shown. +
    floater flag   subc part can be moved after subc placing +
    pin flag   object is a pin (in an element) +
    via flag   object is a via +
 li:layers     ordered list of layers; v1 required the order to be top-bottom physically; v1 also required silk layers to be at the end (same resrtictions as in the old .pcb format; only real (non-bound) layers have attributes) +
  ha:NAME     a logical layer +
   lid integer >=2 layer ID +
   visible integer <6 only in real (non-boud) layers: 1 if the layer is visible, 0 if not (UI setting) +
   group integer   only in real (non-boud) layers: "parent" layer group ID +
   color string >=5 layer color on UI, in #rrggbb format +
   stack_offs integer   only in bound layers: match offset e.g. for internal copper layers +
   ha:type     only for bound layers: try to bind to this type of layer on the host board +
    top flag   location: top side +
    bottom flag   location: bottom side +
    intern flag   location: internal +
    logical flag   location: logical (not in the actual stackup) +
    copper flag   material: copper +
    silk flag   material: silk +
    mask flag   material: mask +
    paste flag   material: paste +
    outline flag   "material": router path (board outline, slots, cutouts) +
    substrate flag   material: substrate or insulator +
   purpose integer >=6 only in bound layers: match layer group purpose +
   combining   >=2 layer combination (compositing) flags +
    sub flag   draw in negative +
    auto flag   padstacks draw their paste, mask and silk objects on the first layer (of matching type) that features the auto flag +
   ha:attributes     a hash of attribute key=value pairs +
    attrib-key string   attribute value +
   li:objects     list of drawing primitives put on this layer +
    ha:line.ID     round cap line +
     x1 coord   line first endpoint, horizontal offset +
     y1 coord   line first endpoint, vertical offset +
     x2 coord   line second endpoint, horizontal offset +
     y2 coord   line second endpoint, vertical offset +
     thickness coord   width of the line +
     clearance coord   copper clearance around the object +
     ha:attributes     a hash of attribute key=value pairs +
      attrib-key string   attribute value +
     ha:flags     flag bits of a line +
      found flag   If set, this object has been found by FindConnection() +
      clearline flag   For lines and arcs, the line/arc will clear polygons instead of connecting to them. +
      selected flag   Set when the object is selected. +
      auto flag   For lines and vias, indicates that these were created by the autorouter. +
      rubberend flag   For lines, used internally for rubber band moves: indicates one end already rubber banding. +
      drc flag   Set for objects that fail DRC: flag like FOUND flag for DRC checking. +
      lock flag   Set for locked objects. +
      termname flag   when set the names of pins are shown. +
      floater flag   subc part can be moved after subc placing +
     li:thermal     list of thermal flags for heavy terminals, on the single layer the object is on +
      on none   draw any thermal only if this string is present; else normal clearance is applied +
      diag none   if present, the thermal is diagonal (45 degree rotated) +
      round none   if present, thermal shape is rounded +
      sharp none   if present, thermal shape is sharp +
      solid none   if present, there is no thermal but a solid connection ("join") +
    ha:arc.ID     round cap elliptic arc (only width==height is fully supported at the moment) +
     x coord   center, X coord +
     y coord   center, Y coord +
     width coord   radius (of the centerline of the arc) in X direction +
     height coord   radius (of the centerline of the arc) in Y direction +
     thickness coord   width of the pen the arc is drawn with +
     clearance coord   copper clearance around the object +
     astart angle   start angle +
     adelta angle   delta angle +
     ha:attributes     a hash of attribute key=value pairs +
      attrib-key string   attribute value +
     ha:flags     flag bits of a arc +
      found flag   If set, this object has been found by FindConnection() +
      clearline flag   For lines and arcs, the line/arc will clear polygons instead of connecting to them. +
      selected flag   Set when the object is selected. +
      auto flag   For lines and vias, indicates that these were created by the autorouter. +
      rubberend flag   For lines, used internally for rubber band moves: indicates one end already rubber banding. +
      drc flag   Set for objects that fail DRC: flag like FOUND flag for DRC checking. +
      lock flag   Set for locked objects. +
      termname flag   when set the names of pins are shown. +
      floater flag   subc part can be moved after subc placing +
     li:thermal     list of thermal flags for heavy terminals, on the single layer the object is on +
      on none   draw any thermal only if this string is present; else normal clearance is applied +
      diag none   if present, the thermal is diagonal (45 degree rotated) +
      round none   if present, thermal shape is rounded +
      sharp none   if present, thermal shape is sharp +
      solid none   if present, there is no thermal but a solid connection ("join") +
    ha:polygon.ID     polygon, as drawn (unclipped) +
     clearance coord >=3 copper clearance around the object +
     ha:attributes     a hash of attribute key=value pairs +
      attrib-key string   attribute value +
     ha:flags     flag bits of a polygon +
      found flag   If set, this object has been found by FindConnection() +
      clearpoly flag   For polygons, this flag means that pins and vias will normally clear these polygons (thus, thermals are required for electrical connection). When clear, polygons will solidly connect to pins and vias. +
      fullpoly flag   For polygons, the full polygon is drawn (i.e. all parts instead of only the biggest one). +
      selected flag   Set when the object is selected. +
      drc flag   Set for objects that fail DRC: flag like FOUND flag for DRC checking. +
      lock flag   Set for locked objects. +
      termname flag   when set the names of pins are shown. +
      clearpolypoly flag   For polygons, apply clearance to nearby polygons +
      floater flag   subc part can be moved after subc placing +
     li:thermal     list of thermal flags for heavy terminals, on the single layer the object is on +
      on none   draw any thermal only if this string is present; else normal clearance is applied +
      diag none   if present, the thermal is diagonal (45 degree rotated) +
      round none   if present, thermal shape is rounded +
      sharp none   if present, thermal shape is sharp +
      solid none   if present, there is no thermal but a solid connection ("join") +
     li:geometry     first item is the outer contour, subsequent, optional items are holes +
      contour coordtbl   2 column table of x;y coords for the outer contour +
      hole coordtbl   2 column table of x;y coords for a hole +
    ha:text.ID     single line text object +
     x coord   placement: X coord +
     y coord   placement: Y coord +
     role string   when part of an old element, determines which of the three hardwired text object role is used (footprint, refdes or value) +
     string string   text string (payload) +
     fid integer   font ID +
     scale integer   text size scale in % +
     direction integer <=5 rotation in 90 degree steps (0 is horizontal); between -3 and +3, inclusive. Starting from v6, the rot field shall be used instead of direction +
     rot angle >=6 rotation angle in degrees, [0..360), CCW +
     thickness coord >=6 if zero, use the default width algorithm; if non-zero use this value as rotation angle in degrees +
     ha:attributes     a hash of attribute key=value pairs +
      attrib-key string   attribute value +
     ha:flags     flag bits of a text +
      found flag   If set, this object has been found by FindConnection() +
      clearline flag   For lines and arcs, the line/arc will clear polygons instead of connecting to them. +
      selected flag   Set when the object is selected. +
      onsolder flag   For text, indicates that it is on the solder side. +
      drc flag   Set for objects that fail DRC: flag like FOUND flag for DRC checking. +
      lock flag   Set for locked objects. +
      termname flag   when set the names of pins are shown. +
      dyntext flag   For text: dynamic string (substitute %patterns%) +
      floater flag   subc part can be moved after subc placing +
 li:padstack_prototypes   >=4 +
  unused none   placeholder for markign uunsed slot to keep slot indices for early lihata v4 +
  ha:ps_proto_v4.PID     padstack prototype specification, as introduced in lihata board v4 +
   hdia coord   hole diameter; 0 means no hole +
   htop integer   hole start: copper layer index from the top (positive) or bottom (negative) copper layer (0 means top copper layer) +
   hbottom integer   hole start: copper layer index from the bottom (positive) or top (negative) copper layer (0 means bottom copper layer) +
   plated integer   0=unplated hole; 1=plated hole +
   name string >=5 optional user assigned prototype name +
   li:shape     shape per layer type definition +
    ha:ps_shape_v4     shape on a specific layer type (specified by layer_mask and combining), as specifie in lihata board v4; shape is either ps_poly, ps_line or ps_circ (only one of these will present per layer type); shape coords are relative to padstack origin; layer mask shall contain one material and at most one location bit +
     ha:layer_mask     layer type and location +
      top flag   location: top side +
      bottom flag   location: bottom side +
      intern flag   location: internal +
      logical flag   location: logical (not in the actual stackup) +
      copper flag   material: copper +
      silk flag   material: silk +
      mask flag   material: mask +
      paste flag   material: paste +
      outline flag   "material": router path (board outline, slots, cutouts) +
      substrate flag   material: substrate or insulator +
     combining     layer compositing match +
      sub flag   draw in negative +
      auto flag   padstacks draw their paste, mask and silk objects on the first layer (of matching type) that features the auto flag +
     clearance coord   local, per-layer-type clearance; applied if global padstack clearance is 0 +
     li:ps_poly     arbitrary convex polygon shape; contains a list of x;y coordinates +
     ha:ps_line     straight line shape, round or square cap +
      x1 coord   line first endpoint, horizontal offset +
      y1 coord   line first endpoint, vertical offset +
      x2 coord   line second endpoint, horizontal offset +
      y2 coord   line second endpoint, vertical offset +
      thickness coord   width of the line +
      square integer   0=round cap; 1=square cap +
     ha:ps_circ     filled circle shape +
      x coord   center, horizontal offset +
      y coord   center, vertical offset +
      dia coord   circle diameter +
     te:ps_hshadow   >=6 hole/slot shadow +
 ha:subc.ID   >=3 an instance (full copy) of a subcircuit +
  uid minuid   UID assigned by the user to track subc history +
  ha:attributes     a hash of attribute key=value pairs +
   attrib-key string   attribute value +
  ha:flags     flag bits of a subcircuit +
   found flag   If set, this object has been found by FindConnection() +
   selected flag   Set when the object is selected. +
   drc flag   Set for objects that fail DRC: flag like FOUND flag for DRC checking. +
   lock flag   Set for locked objects. +
   nonetlist flag   subcircuit is not on the netlist and should not interfere with the netlist +
   termname flag   when set the names of pins are shown. +
   floater flag   subc part can be moved after subc placing +
  ha:data     Layers and global objects of the board -> +
 ha:element.ID   <3 an instance (full copy) of an obsolete element footprint +
  x coord   element origin (diamond), horizontal offset +
  y coord   element origin (diamond), vertical offset +
  ha:attributes     a hash of attribute key=value pairs +
   attrib-key string   attribute value +
  ha:flags_element     flag bits of an element +
   found flag   If set, this object has been found by FindConnection() +
   selected flag   Set when the object is selected. +
   auto flag   For lines and vias, indicates that these were created by the autorouter. +
   drc flag   Set for objects that fail DRC: flag like FOUND flag for DRC checking. +
   lock flag   Set for locked objects. +
   nonetlist flag   subcircuit is not on the netlist and should not interfere with the netlist +
   termname flag   when set the names of pins are shown. +
   floater flag   subc part can be moved after subc placing +
   onsolder flag   element is placed on the solder side +
  li:objects     list of special objects that make up the element; lines and arcs are always on a silk layer +
   ha:line.ID     round cap line -> +
   ha:arc.ID     round cap elliptic arc (only width==height is fully supported at the moment) -> +
   ha:text.ID     single line text object -> +
   ha:pad.ID     SMD pad emulated using a line object; becomes a rectangle (but watch out for the cap-extended length!) when the square flag is set +
    x1 coord   line first endpoint, horizontal offset +
    y1 coord   line first endpoint, vertical offset +
    x2 coord   line second endpoint, horizontal offset +
    y2 coord   line second endpoint, vertical offset +
    thickness coord   width of the line +
    clearance coord   clearance around the line +
    mask coord   size of the mask cutout, as interpreted by gEDA/PCB +
    name string   symbolic name of the pad +
    number string   "pin number" for the netlist +
    ha:attributes     a hash of attribute key=value pairs +
     attrib-key string   attribute value +
    ha:flags_pad     flag bits of a pad +
     found flag   If set, this object has been found by FindConnection() +
     hole flag   For pins and vias, this flag means that the pin or via is a hole without a copper annulus. +
     clearline flag   For lines and arcs, the line/arc will clear polygons instead of connecting to them. +
     selected flag   Set when the object is selected. +
     auto flag   For lines and vias, indicates that these were created by the autorouter. +
     warn flag   For pins, vias, and pads, set to indicate a warning. +
     usetherm flag   Obsolete, indicates that pins/vias should be drawn with thermal fingers. +
     drc flag   Set for objects that fail DRC: flag like FOUND flag for DRC checking. +
     lock flag   Set for locked objects. +
     nonetlist flag   subcircuit is not on the netlist and should not interfere with the netlist +
     termname flag   when set the names of pins are shown. +
     floater flag   subc part can be moved after subc placing +
     pin flag   object is a pin (in an element) +
     via flag   object is a via +
   ha:pin.ID     thru-hole pin; emulated as an old-style via +
    x coord   place padstack with origin at this horizontal coordinate +
    y coord   place padstack with origin at this vertical coordinate +
    thickness coord   copper shape dimension (diameter) +
    clearance coord   copper clearance around the copper shape +
    mask coord   mask cutout shape dimension (diameter) +
    hole coord   drill/hole diameter +
    name string   optional name attribute +
    number string   for a pin (or to-be-pin) this is the terminal ID +
    ha:attributes     a hash of attribute key=value pairs +
     attrib-key string   attribute value +
    ha:flags_pinvia     flag bits of a pin or via +
     found flag   If set, this object has been found by FindConnection() +
     hole flag   For pins and vias, this flag means that the pin or via is a hole without a copper annulus. +
     clearline flag   For lines and arcs, the line/arc will clear polygons instead of connecting to them. +
     selected flag   Set when the object is selected. +
     auto flag   For lines and vias, indicates that these were created by the autorouter. +
     warn flag   For pins, vias, and pads, set to indicate a warning. +
     usetherm flag   Obsolete, indicates that pins/vias should be drawn with thermal fingers. +
     drc flag   Set for objects that fail DRC: flag like FOUND flag for DRC checking. +
     lock flag   Set for locked objects. +
     nonetlist flag   subcircuit is not on the netlist and should not interfere with the netlist +
     termname flag   when set the names of pins are shown. +
     floater flag   subc part can be moved after subc placing +
     pin flag   object is a pin (in an element) +
     via flag   object is a via +
 ha:rat.ID     global rat line +
  x1 coord   line first endpoint, horizontal offset +
  y1 coord   line first endpoint, vertical offset +
  x2 coord   line second endpoint, horizontal offset +
  y2 coord   line second endpoint, vertical offset +
  lgrp1 integer   first endpoint's layer group ID +
  lgrp2 integer   second endpoint's layer group ID +
  ha:attributes     a hash of attribute key=value pairs +
   attrib-key string   attribute value +
  ha:flags     flag bits of a line +
   found flag   If set, this object has been found by FindConnection() +
   clearline flag   For lines and arcs, the line/arc will clear polygons instead of connecting to them. +
   selected flag   Set when the object is selected. +
   auto flag   For lines and vias, indicates that these were created by the autorouter. +
   rubberend flag   For lines, used internally for rubber band moves: indicates one end already rubber banding. +
   drc flag   Set for objects that fail DRC: flag like FOUND flag for DRC checking. +
   lock flag   Set for locked objects. +
   termname flag   when set the names of pins are shown. +
   floater flag   subc part can be moved after subc placing +
+

li:submenu

+

+ +
type:name value ver description +
li:submenu     ordered list of menu items for a submenu +
 m string   mnemonic: single character that should be underlined and used as a hot key in the menu name +
 - none   horizontal separator +
 @ANCHOR none   an anchor is an invisible placeholder where a dynamically generated set of menu items should be inserted runtime +
 ha:SUBSUBMENUNAME     sub-submenu item: opens a new level of submenu when clicked +
  m string   mnemonic: single character that should be underlined and used as a hot key in the menu name +
  li:submenu     ordered list of menu items for a submenu -> +
 ha:LEAFSUBMENUNAME     leaf submenu item: executes an action when clicked +
  m string   mnemonic: single character that should be underlined and used as a hot key in the menu name +
  li:a     list of alternative hotkey sequences to activate the menu +
  a string   a single hotkey sequences to activate the menu +
  li:action     list of actions to execute when the menu is activated +
  action string   a single action to execute when the menu is activated +
  tip string   tooltip text +
  checked string   the menu item has a checkbox; value is the action to execute to determine whether the menu item's checkbox is checked or not +
  update_on string   path of a conf node that triggers re-evaluation of the checkbox state +
+

Types

+

+ + + + + + + + + + +
type description +
angle + + A decimal number without unit, representing an angle in degree. Can + be positive or negative. + +
coord + + A decimal number with a unit suffix. If the unit suffix is missing, + the coordinate is loaded in the internal units (which is nanometer as of 2018, + but could change in the future, thus files shall not depend on it). Depending + on the context, coordinates may have a sign (positive or negative). +

+ Examples: +

+x=10mil;
+y=1.5mm;
+dia=12cm;
+
+ +
coordtbl + + A two-column table of coords. First column are X, second column are Y + coordinates. +

+ Examples: +

+ta:contour {
+ 1mm;   2.1mm;
+ 5mm;   5.2mm;
+ 3.7mm; 12mil;
+}
+ta:foo = { 1mm; 2.1mm;  5mm;   5.2mm;  3.7mm; 12mil; }
+
+ +
double + + Unitless numeric value in decimal format. Depending on context it is + sometimes signed. + +
flag + + If the flag is set, the value is "1", if the flag is not set, the + whole key=value pair is omitted. + +
integer + + Unitless integer value in decimal format. Depending on context it is + sometimes signed. + +
minuid + + An unique ID as generated by libminuid (24 ASCII characters). + +
none + + No value. + +
string + + Free form text data + +
+

Comments

+

ver column: Format version range the subtree may appear in. + + Index: tags/2.1.2/doc/developer/lihata_format/tree.txt =================================================================== --- tags/2.1.2/doc/developer/lihata_format/tree.txt (nonexistent) +++ tags/2.1.2/doc/developer/lihata_format/tree.txt (revision 24813) @@ -0,0 +1,626 @@ +File format root nodes + +Each table below describes the full tree of one of the pcb-rnd file formats, from the root. + +ha:pcb-rnd-board-v* + +type:name value ver description +ha:pcb-rnd-board-v* The full, self-contained description of a printed circuit board. This is the root of a board .lht file. The * after the v in the name is an integer which is the format version. + ha:meta Any meta-data that won't directly turn into physical material (e.g. copper). + board_name string User assigned name of the board + ha:grid User interface last grid settings + offs_x coord grid origin: X offset from 0;0 + offs_y coord grid origin: Y offset from 0;0 + spacing coord distance between two grid points both in X and Y directions + ha:size object size related settings + x coord drawing area size X (width) + y coord drawing area size Y (height) + isle_area_nm2 double remove polygon islands smaller than this value, specified in nm^2 + thermal_scale double scale all thermals on the board by this factor + ha:drc <5 design rule checker settings for the old DRC + bloat coord Minimum copper spacing + shrink coord Minimum overlap between validly touching copper objects + min_width coord Minimum copper width + min_silk coord Minimum silk width + min_drill coord Minimum drill diameter + min_ring coord Minimum annular ring width + ha:cursor obsolete cursor/view state + x coord last position, X (horizontal) + y coord last position, Y (horizontal) + zoom double last view zoom factor + ha:layer_stack physical layer stack information: geometry and properties of physical layers + li:groups ordered list of physical layers from top to bottom + ha:INTEGER a layer group (a physical layer of the board); the ID of the layer group is the integer in the name of the node + name string >=6 purpose of layer groups (useful with mechanical/documentation groups + ha:type a flag-list of layer type flag bits + top flag location: top side + bottom flag location: bottom side + intern flag location: internal + logical flag location: logical (not in the actual stackup) + copper flag material: copper + silk flag material: silk + mask flag material: mask + paste flag material: paste + outline flag "material": router path (board outline, slots, cutouts) + substrate flag material: substrate or insulator + name string >=6 purpose of layer groups (useful with mechanical/documentation groups + li:layers ordered list of logical layer IDs hosted by this layer group + ha:font font kit: all fonts used on the board (if no font specified, default font will be used) + ha:FONT-ID the full description of a font; the node name is the integer font id or "geda_pcb" for font 0 (for historical reasons); the name is used only to make each node unique, the ID is also a field below -> + ha:styles routing styles hash: collection of all available routing syles + ha:netlists all available netlists + li:netlist the input netlist (as seen in the last netlist import, a.k.a. forward annotation) + ha:NETNAME a network + li:conn list of terminals connected to the network + diameter string refdes-terminal + ha:attributes >=5 a hash of attribute key=value pairs + attrib-key string attribute value + li:netlist_patch a list of intentional deviations from the input netlist, a.k.a. material for back annotation + li:net_info describe the current state of a net, as seen on the input + net string net name; first item on the list, only once + term string terminal name; zero or more items starting from the second item + ha:add_conn the 'as built' network requires a new connection to be created during the back annotation + net string net name the terminal should be added to + term string terminal name + ha:del_conn the 'as built' network requires an existing connection to be removed during the back annotation + net string net name the terminal should be removed from + term string terminal name + ha:change_attrib the 'as built' network requires an attribute to be set or changed + net string net name whose attribute needs to be changed + key string key (name) of the attribute + val string new value of the attribute + li:conf complete pcb-rnd configuration tree -> + ha:data Layers and global objects of the board -> + ha:attributes a hash of attribute key=value pairs + attrib-key string attribute value + +li:pcb-rnd-conf-v1 + +type:name value ver description +li:pcb-rnd-conf-v1 complete pcb-rnd configuration tree + ha:overwrite overwrite values while merging; children: a full or partial config tree + ha:prepend prepend values while merging; children: a full or partial config tree + ha:append append values while merging; children: a full or partial config tree + +li:pcb-rnd-font-v1 + +type:name value ver description +li:pcb-rnd-font-v1 font description + ha:FONT-ID the full description of a font; the node name is the integer font id or "geda_pcb" for font 0 (for historical reasons); the name is used only to make each node unique, the ID is also a field below + cell_height coord height of the tallest glyph + cell_width coord width of the widest glyph + id integer unique font ID within the fontkit; fonts are referenced by ID + name string user specified, user readable font name + ha:symbols a collections of glyphs availbale in the font + ha:CHARACTER Description of a glyph (symbol). Node name is a signel ASCII character or is of format &xx where xx is a hex digit of the ASCII code of the character. Characters that must use the hex version are: codes below 33 or over + 126, &, #, {, }, /, :, ;, =, \, : + height coord height of the glyph + width coord width of the glyph + delta coord extra space always inserted after the current symbol, before the next character + li:objects objects that make up the symbol; IDs are per symbol local IDs counted from 0 + ha:line.ID round cap line, simplified + x1 coord line first endpoint, horizontal offset + y1 coord line first endpoint, vertical offset + x2 coord line second endpoint, horizontal offset + y2 coord line second endpoint, vertical offset + thickness coord width of the line + ha:simplearc.ID round cap arc, simplified + x coord center, X coord + y coord center, Y coord + r coord radius (of the centerline of the arc) + thickness coord width of the pen the arc is drawn with + astart angle start angle + adelta angle delta angle + li:simplepoly.ID round cap arc, simplified; contains a flat list of coords; each coord pair is an x;y corner of the outline of the polygon (odd indices are x coords, even indices are y coords) + +ha:pcb-rnd-log-v* + +type:name value ver description +ha:pcb-rnd-log-v* pcb-rnd message log dump + li:entries list of message log entries + ha:ID each entry is identified by an unique unsigned long int ID + stamp string UNIX time stamp of entry creation + level integer log level enum value (see error.h) + seen integer 1 if the message got displayed + str string log message + +ha:menu + +type:name value ver description +ha: Menu file + li:mouse mouse bindings + li:left actions to execute on left button click + li:press actions to execute on mouse button press when no modifier is pressed + li:press-shift actions to execute on mouse button press when shift is pressed + li:press-ctrl actions to execute on mouse button press when control is pressed + li:release actions to execute on mouse button release when no modifier is pressed + li:release-shift actions to execute on mouse button release when shift is pressed + li:release-ctrl actions to execute on mouse button release when control is pressed + li:middle actions to execute on middle button click + li:press actions to execute on mouse button press when no modifier is pressed + li:press-shift actions to execute on mouse button press when shift is pressed + li:press-ctrl actions to execute on mouse button press when control is pressed + li:release actions to execute on mouse button release when no modifier is pressed + li:release-shift actions to execute on mouse button release when shift is pressed + li:release-ctrl actions to execute on mouse button release when control is pressed + li:right actions to execute on right button click + li:press actions to execute on mouse button press when no modifier is pressed + li:press-shift actions to execute on mouse button press when shift is pressed + li:press-ctrl actions to execute on mouse button press when control is pressed + li:release actions to execute on mouse button release when no modifier is pressed + li:release-shift actions to execute on mouse button release when shift is pressed + li:release-ctrl actions to execute on mouse button release when control is pressed + li:scroll-up actions to execute on scroll wheel scolling up event + li:press actions to execute on mouse button press when no modifier is pressed + li:press-shift actions to execute on mouse button press when shift is pressed + li:press-ctrl actions to execute on mouse button press when control is pressed + li:scroll-down actions to execute on scroll wheel scolling down event + li:press actions to execute on mouse button press when no modifier is pressed + li:press-shift actions to execute on mouse button press when shift is pressed + li:press-ctrl actions to execute on mouse button press when control is pressed + li:main_menu root of the main pull-down menu system; ordered list of main menus + ha:MENUNAME main menu name, e.g. "File" + m string mnemonic: single character that should be underlined and used as a hot key in the menu name + li:submenu ordered list of menu items for a submenu -> + li:popups collection of popup menus + ha:POPUPNAME popup menu name, e.g. "layer" for layer context menu + m string mnemonic: single character that should be underlined and used as a hot key in the menu name + li:submenu ordered list of menu items for a submenu -> + +ha:coraleda-project-v1 + +type:name value ver description +ha:coraleda-project-v1 Project file root. Except for "common", each software package should create a single subtree under the root; the subtree shall be named after the software package + ha:common project settings that should be common to all software packages + name string long name of the project + desc string description of the project + url string homepage of the project + vcs string main vcs url for the project + contact string author/maintainer contact info + li:files ordered list of source files being used by the project + ha:NAME a project member file + path string path to the file, relative to the project file + desc string description of the file + type string optional: type of the file; one of: "pcb", "schematic", "doc" + li:libs ordered list of libraries the project depends on + ha:NAME a library + path string path to the library, relative to the project file; all files and subdirectories under the root, recursively, are considered part of the library (must not be used together with url) + url string url to the library (must not be used together with path) + desc string description of the library + type string optional: type of the library; one of: "footprint" (for pcb design), "symbol" (for schematic), "sim" (models and subcircuits for e.g. spice simulation) + li:pcb-rnd-conf-v1 complete pcb-rnd configuration tree -> + +li:pcb-rnd-subcircuit-v* + +type:name value ver description +li:pcb-rnd-subcircuit-v* footprint file containing a single subcircuit + ha:subc.ID >=3 an instance (full copy) of a subcircuit + uid minuid UID assigned by the user to track subc history + ha:attributes a hash of attribute key=value pairs + attrib-key string attribute value + ha:flags flag bits of a subcircuit + found flag If set, this object has been found by FindConnection() + selected flag Set when the object is selected. + drc flag Set for objects that fail DRC: flag like FOUND flag for DRC checking. + lock flag Set for locked objects. + nonetlist flag subcircuit is not on the netlist and should not interfere with the netlist + termname flag when set the names of pins are shown. + floater flag subc part can be moved after subc placing + ha:data Layers and global objects of the board -> + +li:view-list-v* + +type:name value ver description +li:view-list-v* a list of view items (locations and objects to highlight on the board, e.g. for DRC violations) + ha:view.ID a view item; ID is a 32 bit signed integer, unique within the view list + type string free form short text for type of the entry; the GUI may group items by type + title string free form short text for the title of the entry; the GUI typically uses this in brief listings + description string free form long text for the detailed description of the entry + li:bbox coord optional: 4 coordinates in x1;y1;x2;y2 order that describes the bounding box of the view in board space coordinates; when available, the preview or go-to will use this for view box + li:xy coord optional: 2 coordinates in x;y order that describes a specific board location + li:objs.ID a group of related objects; there should be at most two groups with ID 0 and 1. These objects are often highlighted in red and blue. + li:id objects are specified as a list of object IDs (32 bit integers) + +Common subtrees + +Each table below describes a subtree that usually does not specify a whole tree (thus they are usually not a valid file on their own). These subtrees are described in a separate table because they are used from multiple other trees. + +ha:data + +type:name value ver description +ha:data Layers and global objects of the board + li:objects List of global (non-layer/multi-layer) objects + ha:padstack_ref.ID >=4 a padstack reference (instance) placed on the board (e.g. used as a via) + proto integer padstack prototype ID to use, from the parent data's proto list + x coord place padstack with origin at this horizontal coordinate + y coord place padstack with origin at this vertical coordinate + clearance coord global clearance; if non-zero, overrides local (per shape) clearance + rot angle rotation angle in degrees + xmirror integer 0 or 1; if 1, mirror all shapes over the x (horizontal) axis (so that y coords are flipped) + smirror integer 0 or 1; if 1, mirror the layer stackup: bottom becomes top, top becomes bottom (a.k.a. "place on the other side") + ha:attributes a hash of attribute key=value pairs + attrib-key string attribute value + ha:flags flag bits of a padstack + found flag If set, this object has been found by FindConnection() + hole flag For pins and vias, this flag means that the pin or via is a hole without a copper annulus. + clearline flag For lines and arcs, the line/arc will clear polygons instead of connecting to them. + selected flag Set when the object is selected. + auto flag For lines and vias, indicates that these were created by the autorouter. + warn flag For pins, vias, and pads, set to indicate a warning. + drc flag Set for objects that fail DRC: flag like FOUND flag for DRC checking. + lock flag Set for locked objects. + termname flag when set the names of pins are shown. + floater flag subc part can be moved after subc placing + li:thermal list of thermal shapes, per layer + li:LAYERID integer layer ID the thermal affects; each word is a boolean flag that is either present on the list or is missing; only one shape may be present + on none thermal is present on this layer; if not present, all other thermal flags are ignored on this layer + diag none thermal graphics is not axis aligned but diagonal (rotated by 45 degrees) + round none shape: rounded edge fingers + sharp none shape: sharp edge fingers + solid none shape: no thermal relief, solid connection without clearance + noshape none >=6 shape: special: omit copper shape of the padstack on this layer + ha:via.ID <=4 an old via object (loaded as padstack in the new model) + x coord place padstack with origin at this horizontal coordinate + y coord place padstack with origin at this vertical coordinate + thickness coord copper shape dimension (diameter) + clearance coord copper clearance around the copper shape + mask coord mask cutout shape dimension (diameter) + hole coord drill/hole diameter + name string optional name attribute + number string for a pin (or to-be-pin) this is the terminal ID + ha:attributes a hash of attribute key=value pairs + attrib-key string attribute value + ha:flags_pinvia flag bits of a pin or via + found flag If set, this object has been found by FindConnection() + hole flag For pins and vias, this flag means that the pin or via is a hole without a copper annulus. + clearline flag For lines and arcs, the line/arc will clear polygons instead of connecting to them. + selected flag Set when the object is selected. + auto flag For lines and vias, indicates that these were created by the autorouter. + warn flag For pins, vias, and pads, set to indicate a warning. + usetherm flag Obsolete, indicates that pins/vias should be drawn with thermal fingers. + drc flag Set for objects that fail DRC: flag like FOUND flag for DRC checking. + lock flag Set for locked objects. + nonetlist flag subcircuit is not on the netlist and should not interfere with the netlist + termname flag when set the names of pins are shown. + floater flag subc part can be moved after subc placing + pin flag object is a pin (in an element) + via flag object is a via + li:layers ordered list of layers; v1 required the order to be top-bottom physically; v1 also required silk layers to be at the end (same resrtictions as in the old .pcb format; only real (non-bound) layers have attributes) + ha:NAME a logical layer + lid integer >=2 layer ID + visible integer <6 only in real (non-boud) layers: 1 if the layer is visible, 0 if not (UI setting) + group integer only in real (non-boud) layers: "parent" layer group ID + color string >=5 layer color on UI, in #rrggbb format + stack_offs integer only in bound layers: match offset e.g. for internal copper layers + ha:type only for bound layers: try to bind to this type of layer on the host board + top flag location: top side + bottom flag location: bottom side + intern flag location: internal + logical flag location: logical (not in the actual stackup) + copper flag material: copper + silk flag material: silk + mask flag material: mask + paste flag material: paste + outline flag "material": router path (board outline, slots, cutouts) + substrate flag material: substrate or insulator + purpose integer >=6 only in bound layers: match layer group purpose + combining >=2 layer combination (compositing) flags + sub flag draw in negative + auto flag padstacks draw their paste, mask and silk objects on the first layer (of matching type) that features the auto flag + ha:attributes a hash of attribute key=value pairs + attrib-key string attribute value + li:objects list of drawing primitives put on this layer + ha:line.ID round cap line + x1 coord line first endpoint, horizontal offset + y1 coord line first endpoint, vertical offset + x2 coord line second endpoint, horizontal offset + y2 coord line second endpoint, vertical offset + thickness coord width of the line + clearance coord copper clearance around the object + ha:attributes a hash of attribute key=value pairs + attrib-key string attribute value + ha:flags flag bits of a line + found flag If set, this object has been found by FindConnection() + clearline flag For lines and arcs, the line/arc will clear polygons instead of connecting to them. + selected flag Set when the object is selected. + auto flag For lines and vias, indicates that these were created by the autorouter. + rubberend flag For lines, used internally for rubber band moves: indicates one end already rubber banding. + drc flag Set for objects that fail DRC: flag like FOUND flag for DRC checking. + lock flag Set for locked objects. + termname flag when set the names of pins are shown. + floater flag subc part can be moved after subc placing + li:thermal list of thermal flags for heavy terminals, on the single layer the object is on + on none draw any thermal only if this string is present; else normal clearance is applied + diag none if present, the thermal is diagonal (45 degree rotated) + round none if present, thermal shape is rounded + sharp none if present, thermal shape is sharp + solid none if present, there is no thermal but a solid connection ("join") + ha:arc.ID round cap elliptic arc (only width==height is fully supported at the moment) + x coord center, X coord + y coord center, Y coord + width coord radius (of the centerline of the arc) in X direction + height coord radius (of the centerline of the arc) in Y direction + thickness coord width of the pen the arc is drawn with + clearance coord copper clearance around the object + astart angle start angle + adelta angle delta angle + ha:attributes a hash of attribute key=value pairs + attrib-key string attribute value + ha:flags flag bits of a arc + found flag If set, this object has been found by FindConnection() + clearline flag For lines and arcs, the line/arc will clear polygons instead of connecting to them. + selected flag Set when the object is selected. + auto flag For lines and vias, indicates that these were created by the autorouter. + rubberend flag For lines, used internally for rubber band moves: indicates one end already rubber banding. + drc flag Set for objects that fail DRC: flag like FOUND flag for DRC checking. + lock flag Set for locked objects. + termname flag when set the names of pins are shown. + floater flag subc part can be moved after subc placing + li:thermal list of thermal flags for heavy terminals, on the single layer the object is on + on none draw any thermal only if this string is present; else normal clearance is applied + diag none if present, the thermal is diagonal (45 degree rotated) + round none if present, thermal shape is rounded + sharp none if present, thermal shape is sharp + solid none if present, there is no thermal but a solid connection ("join") + ha:polygon.ID polygon, as drawn (unclipped) + clearance coord >=3 copper clearance around the object + ha:attributes a hash of attribute key=value pairs + attrib-key string attribute value + ha:flags flag bits of a polygon + found flag If set, this object has been found by FindConnection() + clearpoly flag For polygons, this flag means that pins and vias will normally clear these polygons (thus, thermals are required for electrical connection). When clear, polygons will solidly connect to pins and vias. + fullpoly flag For polygons, the full polygon is drawn (i.e. all parts instead of only the biggest one). + selected flag Set when the object is selected. + drc flag Set for objects that fail DRC: flag like FOUND flag for DRC checking. + lock flag Set for locked objects. + termname flag when set the names of pins are shown. + clearpolypoly flag For polygons, apply clearance to nearby polygons + floater flag subc part can be moved after subc placing + li:thermal list of thermal flags for heavy terminals, on the single layer the object is on + on none draw any thermal only if this string is present; else normal clearance is applied + diag none if present, the thermal is diagonal (45 degree rotated) + round none if present, thermal shape is rounded + sharp none if present, thermal shape is sharp + solid none if present, there is no thermal but a solid connection ("join") + li:geometry first item is the outer contour, subsequent, optional items are holes + contour coordtbl 2 column table of x;y coords for the outer contour + hole coordtbl 2 column table of x;y coords for a hole + ha:text.ID single line text object + x coord placement: X coord + y coord placement: Y coord + role string when part of an old element, determines which of the three hardwired text object role is used (footprint, refdes or value) + string string text string (payload) + fid integer font ID + scale integer text size scale in % + direction integer <=5 rotation in 90 degree steps (0 is horizontal); between -3 and +3, inclusive. Starting from v6, the rot field shall be used instead of direction + rot angle >=6 rotation angle in degrees, [0..360), CCW + thickness coord >=6 if zero, use the default width algorithm; if non-zero use this value as rotation angle in degrees + ha:attributes a hash of attribute key=value pairs + attrib-key string attribute value + ha:flags flag bits of a text + found flag If set, this object has been found by FindConnection() + clearline flag For lines and arcs, the line/arc will clear polygons instead of connecting to them. + selected flag Set when the object is selected. + onsolder flag For text, indicates that it is on the solder side. + drc flag Set for objects that fail DRC: flag like FOUND flag for DRC checking. + lock flag Set for locked objects. + termname flag when set the names of pins are shown. + dyntext flag For text: dynamic string (substitute %patterns%) + floater flag subc part can be moved after subc placing + li:padstack_prototypes >=4 + unused none placeholder for markign uunsed slot to keep slot indices for early lihata v4 + ha:ps_proto_v4.PID padstack prototype specification, as introduced in lihata board v4 + hdia coord hole diameter; 0 means no hole + htop integer hole start: copper layer index from the top (positive) or bottom (negative) copper layer (0 means top copper layer) + hbottom integer hole start: copper layer index from the bottom (positive) or top (negative) copper layer (0 means bottom copper layer) + plated integer 0=unplated hole; 1=plated hole + name string >=5 optional user assigned prototype name + li:shape shape per layer type definition + ha:ps_shape_v4 shape on a specific layer type (specified by layer_mask and combining), as specifie in lihata board v4; shape is either ps_poly, ps_line or ps_circ (only one of these will present per layer type); shape coords are + relative to padstack origin; layer mask shall contain one material and at most one location bit + ha:layer_mask layer type and location + top flag location: top side + bottom flag location: bottom side + intern flag location: internal + logical flag location: logical (not in the actual stackup) + copper flag material: copper + silk flag material: silk + mask flag material: mask + paste flag material: paste + outline flag "material": router path (board outline, slots, cutouts) + substrate flag material: substrate or insulator + combining layer compositing match + sub flag draw in negative + auto flag padstacks draw their paste, mask and silk objects on the first layer (of matching type) that features the auto flag + clearance coord local, per-layer-type clearance; applied if global padstack clearance is 0 + li:ps_poly arbitrary convex polygon shape; contains a list of x;y coordinates + ha:ps_line straight line shape, round or square cap + x1 coord line first endpoint, horizontal offset + y1 coord line first endpoint, vertical offset + x2 coord line second endpoint, horizontal offset + y2 coord line second endpoint, vertical offset + thickness coord width of the line + square integer 0=round cap; 1=square cap + ha:ps_circ filled circle shape + x coord center, horizontal offset + y coord center, vertical offset + dia coord circle diameter + te:ps_hshadow >=6 hole/slot shadow + ha:subc.ID >=3 an instance (full copy) of a subcircuit + uid minuid UID assigned by the user to track subc history + ha:attributes a hash of attribute key=value pairs + attrib-key string attribute value + ha:flags flag bits of a subcircuit + found flag If set, this object has been found by FindConnection() + selected flag Set when the object is selected. + drc flag Set for objects that fail DRC: flag like FOUND flag for DRC checking. + lock flag Set for locked objects. + nonetlist flag subcircuit is not on the netlist and should not interfere with the netlist + termname flag when set the names of pins are shown. + floater flag subc part can be moved after subc placing + ha:data Layers and global objects of the board -> + ha:element.ID <3 an instance (full copy) of an obsolete element footprint + x coord element origin (diamond), horizontal offset + y coord element origin (diamond), vertical offset + ha:attributes a hash of attribute key=value pairs + attrib-key string attribute value + ha:flags_element flag bits of an element + found flag If set, this object has been found by FindConnection() + selected flag Set when the object is selected. + auto flag For lines and vias, indicates that these were created by the autorouter. + drc flag Set for objects that fail DRC: flag like FOUND flag for DRC checking. + lock flag Set for locked objects. + nonetlist flag subcircuit is not on the netlist and should not interfere with the netlist + termname flag when set the names of pins are shown. + floater flag subc part can be moved after subc placing + onsolder flag element is placed on the solder side + li:objects list of special objects that make up the element; lines and arcs are always on a silk layer + ha:line.ID round cap line -> + ha:arc.ID round cap elliptic arc (only width==height is fully supported at the moment) -> + ha:text.ID single line text object -> + ha:pad.ID SMD pad emulated using a line object; becomes a rectangle (but watch out for the cap-extended length!) when the square flag is set + x1 coord line first endpoint, horizontal offset + y1 coord line first endpoint, vertical offset + x2 coord line second endpoint, horizontal offset + y2 coord line second endpoint, vertical offset + thickness coord width of the line + clearance coord clearance around the line + mask coord size of the mask cutout, as interpreted by gEDA/PCB + name string symbolic name of the pad + number string "pin number" for the netlist + ha:attributes a hash of attribute key=value pairs + attrib-key string attribute value + ha:flags_pad flag bits of a pad + found flag If set, this object has been found by FindConnection() + hole flag For pins and vias, this flag means that the pin or via is a hole without a copper annulus. + clearline flag For lines and arcs, the line/arc will clear polygons instead of connecting to them. + selected flag Set when the object is selected. + auto flag For lines and vias, indicates that these were created by the autorouter. + warn flag For pins, vias, and pads, set to indicate a warning. + usetherm flag Obsolete, indicates that pins/vias should be drawn with thermal fingers. + drc flag Set for objects that fail DRC: flag like FOUND flag for DRC checking. + lock flag Set for locked objects. + nonetlist flag subcircuit is not on the netlist and should not interfere with the netlist + termname flag when set the names of pins are shown. + floater flag subc part can be moved after subc placing + pin flag object is a pin (in an element) + via flag object is a via + ha:pin.ID thru-hole pin; emulated as an old-style via + x coord place padstack with origin at this horizontal coordinate + y coord place padstack with origin at this vertical coordinate + thickness coord copper shape dimension (diameter) + clearance coord copper clearance around the copper shape + mask coord mask cutout shape dimension (diameter) + hole coord drill/hole diameter + name string optional name attribute + number string for a pin (or to-be-pin) this is the terminal ID + ha:attributes a hash of attribute key=value pairs + attrib-key string attribute value + ha:flags_pinvia flag bits of a pin or via + found flag If set, this object has been found by FindConnection() + hole flag For pins and vias, this flag means that the pin or via is a hole without a copper annulus. + clearline flag For lines and arcs, the line/arc will clear polygons instead of connecting to them. + selected flag Set when the object is selected. + auto flag For lines and vias, indicates that these were created by the autorouter. + warn flag For pins, vias, and pads, set to indicate a warning. + usetherm flag Obsolete, indicates that pins/vias should be drawn with thermal fingers. + drc flag Set for objects that fail DRC: flag like FOUND flag for DRC checking. + lock flag Set for locked objects. + nonetlist flag subcircuit is not on the netlist and should not interfere with the netlist + termname flag when set the names of pins are shown. + floater flag subc part can be moved after subc placing + pin flag object is a pin (in an element) + via flag object is a via + ha:rat.ID global rat line + x1 coord line first endpoint, horizontal offset + y1 coord line first endpoint, vertical offset + x2 coord line second endpoint, horizontal offset + y2 coord line second endpoint, vertical offset + lgrp1 integer first endpoint's layer group ID + lgrp2 integer second endpoint's layer group ID + ha:attributes a hash of attribute key=value pairs + attrib-key string attribute value + ha:flags flag bits of a line + found flag If set, this object has been found by FindConnection() + clearline flag For lines and arcs, the line/arc will clear polygons instead of connecting to them. + selected flag Set when the object is selected. + auto flag For lines and vias, indicates that these were created by the autorouter. + rubberend flag For lines, used internally for rubber band moves: indicates one end already rubber banding. + drc flag Set for objects that fail DRC: flag like FOUND flag for DRC checking. + lock flag Set for locked objects. + termname flag when set the names of pins are shown. + floater flag subc part can be moved after subc placing + +li:submenu + +type:name value ver description +li:submenu ordered list of menu items for a submenu + m string mnemonic: single character that should be underlined and used as a hot key in the menu name + - none horizontal separator + @ANCHOR none an anchor is an invisible placeholder where a dynamically generated set of menu items should be inserted runtime + ha:SUBSUBMENUNAME sub-submenu item: opens a new level of submenu when clicked + m string mnemonic: single character that should be underlined and used as a hot key in the menu name + li:submenu ordered list of menu items for a submenu -> + ha:LEAFSUBMENUNAME leaf submenu item: executes an action when clicked + m string mnemonic: single character that should be underlined and used as a hot key in the menu name + li:a list of alternative hotkey sequences to activate the menu + a string a single hotkey sequences to activate the menu + li:action list of actions to execute when the menu is activated + action string a single action to execute when the menu is activated + tip string tooltip text + checked string the menu item has a checkbox; value is the action to execute to determine whether the menu item's checkbox is checked or not + update_on string path of a conf node that triggers re-evaluation of the checkbox state + +Types + ++---------------------------------------------------------------+ +| type | description | +|--------+------------------------------------------------------| +|angle |A decimal number without unit, representing an angle | +| |in degree. Can be positive or negative. | +|--------+------------------------------------------------------| +| |A decimal number with a unit suffix. If the unit | +| |suffix is missing, the coordinate is loaded in the | +| |internal units (which is nanometer as of 2018, but | +| |could change in the future, thus files shall not | +| |depend on it). Depending on the context, coordinates | +|coord |may have a sign (positive or negative). | +| | | +| |Examples: | +| | | +| |x=10mil; | +| |y=1.5mm; | +| |dia=12cm; | +|--------+------------------------------------------------------| +| |A two-column table of coords. First column are X, | +| |second column are Y coordinates. | +| | | +| |Examples: | +| | | +|coordtbl|ta:contour { | +| | 1mm; 2.1mm; | +| | 5mm; 5.2mm; | +| | 3.7mm; 12mil; | +| |} | +| |ta:foo = { 1mm; 2.1mm; 5mm; 5.2mm; 3.7mm; 12mil; }| +|--------+------------------------------------------------------| +|double |Unitless numeric value in decimal format. Depending on| +| |context it is sometimes signed. | +|--------+------------------------------------------------------| +|flag |If the flag is set, the value is "1", if the flag is | +| |not set, the whole key=value pair is omitted. | +|--------+------------------------------------------------------| +|integer |Unitless integer value in decimal format. Depending on| +| |context it is sometimes signed. | +|--------+------------------------------------------------------| +|minuid |An unique ID as generated by libminuid (24 ASCII | +| |characters). | +|--------+------------------------------------------------------| +|none |No value. | +|--------+------------------------------------------------------| +|string |Free form text data | ++---------------------------------------------------------------+ + +Comments + +ver column: Format version range the subtree may appear in. Index: tags/2.1.2/doc/developer/lihata_format/types.lht =================================================================== --- tags/2.1.2/doc/developer/lihata_format/types.lht (nonexistent) +++ tags/2.1.2/doc/developer/lihata_format/types.lht (revision 24813) @@ -0,0 +1,65 @@ +ha:lht_tree_doc { ha:types { + +angle { + A decimal number without unit, representing an angle in degree. Can + be positive or negative. +} + +coord { + A decimal number with a unit suffix. If the unit suffix is missing, + the coordinate is loaded in the internal units (which is nanometer as of 2018, + but could change in the future, thus files shall not depend on it). Depending + on the context, coordinates may have a sign (positive or negative). +

+ Examples: +

+x=10mil;
+y=1.5mm;
+dia=12cm;
+
+} + +coordtbl { + A two-column table of coords. First column are X, second column are Y + coordinates. +

+ Examples: +

+ta:contour {
+	1mm;   2.1mm;
+	5mm;   5.2mm;
+	3.7mm; 12mil;
+\}
+ta:foo = { 1mm; 2.1mm;  5mm;   5.2mm;  3.7mm; 12mil; \}
+
+} + +double { + Unitless numeric value in decimal format. Depending on context it is + sometimes signed. +} + +flag { + If the flag is set, the value is "1", if the flag is not set, the + whole key=value pair is omitted. +} + +integer { + Unitless integer value in decimal format. Depending on context it is + sometimes signed. +} + +minuid { + An unique ID as generated by libminuid (24 ASCII characters). +} + +none { + No value. +} + +string { + Free form text data +} + +}} + Index: tags/2.1.2/doc/developer/lihata_format/view-list-v.svg =================================================================== --- tags/2.1.2/doc/developer/lihata_format/view-list-v.svg (nonexistent) +++ tags/2.1.2/doc/developer/lihata_format/view-list-v.svg (revision 24813) @@ -0,0 +1,147 @@ + + + + + + +li:view-list-v* + + + +/lht_tree_doc/roots/view-list-v* + + +li:view-list-v* + + + + + +/lht_tree_doc/roots/view-list-v*/children/view.ID + + +ha:view.ID + + + + + +/lht_tree_doc/roots/view-list-v*->/lht_tree_doc/roots/view-list-v*/children/view.ID + + + + + +/lht_tree_doc/roots/view-list-v*/children/view.ID/children/type + + +type +string + + + + + +/lht_tree_doc/roots/view-list-v*/children/view.ID->/lht_tree_doc/roots/view-list-v*/children/view.ID/children/type + + + + + +/lht_tree_doc/roots/view-list-v*/children/view.ID/children/title + + +title +string + + + + + +/lht_tree_doc/roots/view-list-v*/children/view.ID->/lht_tree_doc/roots/view-list-v*/children/view.ID/children/title + + + + + +/lht_tree_doc/roots/view-list-v*/children/view.ID/children/description + + +description +string + + + + + +/lht_tree_doc/roots/view-list-v*/children/view.ID->/lht_tree_doc/roots/view-list-v*/children/view.ID/children/description + + + + + +/lht_tree_doc/roots/view-list-v*/children/view.ID/children/bbox + + +li:bbox +coord + + + + + +/lht_tree_doc/roots/view-list-v*/children/view.ID->/lht_tree_doc/roots/view-list-v*/children/view.ID/children/bbox + + + + + +/lht_tree_doc/roots/view-list-v*/children/view.ID/children/xy + + +li:xy +coord + + + + + +/lht_tree_doc/roots/view-list-v*/children/view.ID->/lht_tree_doc/roots/view-list-v*/children/view.ID/children/xy + + + + + +/lht_tree_doc/roots/view-list-v*/children/view.ID/children/objs.ID + + +li:objs.ID + + + + + +/lht_tree_doc/roots/view-list-v*/children/view.ID->/lht_tree_doc/roots/view-list-v*/children/view.ID/children/objs.ID + + + + + +/lht_tree_doc/roots/view-list-v*/children/view.ID/children/objs.ID/children/id + + +li:id + + + + + +/lht_tree_doc/roots/view-list-v*/children/view.ID/children/objs.ID->/lht_tree_doc/roots/view-list-v*/children/view.ID/children/objs.ID/children/id + + + + + Index: tags/2.1.2/doc/developer/lihata_format/view-list-v1.dot =================================================================== --- tags/2.1.2/doc/developer/lihata_format/view-list-v1.dot (nonexistent) +++ tags/2.1.2/doc/developer/lihata_format/view-list-v1.dot (revision 24813) @@ -0,0 +1,19 @@ +digraph "li:view-list-v1" { + "/lht_tree_doc/roots/view-list-v1" [label="li:view-list-v1\n\n" URL="tree.html#/lht_tree_doc/roots/view-list-v1" tooltip="a list of view items (locations and objects to highlight on the board, e.g. for DRC violations)"] + "/lht_tree_doc/roots/view-list-v1/children/view.ID" [label="ha:view.ID\n\n" URL="tree.html#/lht_tree_doc/roots/view-list-v1/children/view.ID" tooltip="a view item; ID is a 32 bit signed integer, unique within the view list"] + "/lht_tree_doc/roots/view-list-v1" -> "/lht_tree_doc/roots/view-list-v1/children/view.ID" + "/lht_tree_doc/roots/view-list-v1/children/view.ID/children/type" [label="type\nstring\n" URL="tree.html#/lht_tree_doc/roots/view-list-v1/children/view.ID/children/type" tooltip="free form short text for type of the entry; the GUI may group items by type"] + "/lht_tree_doc/roots/view-list-v1/children/view.ID" -> "/lht_tree_doc/roots/view-list-v1/children/view.ID/children/type" + "/lht_tree_doc/roots/view-list-v1/children/view.ID/children/title" [label="title\nstring\n" URL="tree.html#/lht_tree_doc/roots/view-list-v1/children/view.ID/children/title" tooltip="free form short text for the title of the entry; the GUI typically uses this in brief listings"] + "/lht_tree_doc/roots/view-list-v1/children/view.ID" -> "/lht_tree_doc/roots/view-list-v1/children/view.ID/children/title" + "/lht_tree_doc/roots/view-list-v1/children/view.ID/children/description" [label="description\nstring\n" URL="tree.html#/lht_tree_doc/roots/view-list-v1/children/view.ID/children/description" tooltip="free form long text for the detailed description of the entry "] + "/lht_tree_doc/roots/view-list-v1/children/view.ID" -> "/lht_tree_doc/roots/view-list-v1/children/view.ID/children/description" + "/lht_tree_doc/roots/view-list-v1/children/view.ID/children/bbox" [label="li:bbox\ncoord\n" URL="tree.html#/lht_tree_doc/roots/view-list-v1/children/view.ID/children/bbox" tooltip="optional: 4 coordinates in x1;y1;x2;y2 order that describes the bounding box of the view in board space coordinates; when available, the preview or go-to will use this for view box"] + "/lht_tree_doc/roots/view-list-v1/children/view.ID" -> "/lht_tree_doc/roots/view-list-v1/children/view.ID/children/bbox" + "/lht_tree_doc/roots/view-list-v1/children/view.ID/children/xy" [label="li:xy\ncoord\n" URL="tree.html#/lht_tree_doc/roots/view-list-v1/children/view.ID/children/xy" tooltip="optional: 2 coordinates in x;y order that describes a specific board location"] + "/lht_tree_doc/roots/view-list-v1/children/view.ID" -> "/lht_tree_doc/roots/view-list-v1/children/view.ID/children/xy" + "/lht_tree_doc/roots/view-list-v1/children/view.ID/children/objs.ID" [label="li:objs.ID\n\n" URL="tree.html#/lht_tree_doc/roots/view-list-v1/children/view.ID/children/objs.ID" tooltip="a group of related objects; there should be at most two groups with ID 0 and 1. These objects are often highlighted in red and blue."] + "/lht_tree_doc/roots/view-list-v1/children/view.ID" -> "/lht_tree_doc/roots/view-list-v1/children/view.ID/children/objs.ID" + "/lht_tree_doc/roots/view-list-v1/children/view.ID/children/objs.ID/children/id" [label="li:id\n\n" URL="tree.html#/lht_tree_doc/roots/view-list-v1/children/view.ID/children/objs.ID/children/id" tooltip="objects are specified as a list of object IDs (32 bit integers)"] + "/lht_tree_doc/roots/view-list-v1/children/view.ID/children/objs.ID" -> "/lht_tree_doc/roots/view-list-v1/children/view.ID/children/objs.ID/children/id" +} Index: tags/2.1.2/doc/developer/lihata_format/view-list-v1.svg =================================================================== --- tags/2.1.2/doc/developer/lihata_format/view-list-v1.svg (nonexistent) +++ tags/2.1.2/doc/developer/lihata_format/view-list-v1.svg (revision 24813) @@ -0,0 +1,147 @@ + + + + + + +li:view-list-v1 + + + +/lht_tree_doc/roots/view-list-v1 + + +li:view-list-v1 + + + + + +/lht_tree_doc/roots/view-list-v1/children/view.ID + + +ha:view.ID + + + + + +/lht_tree_doc/roots/view-list-v1->/lht_tree_doc/roots/view-list-v1/children/view.ID + + + + + +/lht_tree_doc/roots/view-list-v1/children/view.ID/children/type + + +type +string + + + + + +/lht_tree_doc/roots/view-list-v1/children/view.ID->/lht_tree_doc/roots/view-list-v1/children/view.ID/children/type + + + + + +/lht_tree_doc/roots/view-list-v1/children/view.ID/children/title + + +title +string + + + + + +/lht_tree_doc/roots/view-list-v1/children/view.ID->/lht_tree_doc/roots/view-list-v1/children/view.ID/children/title + + + + + +/lht_tree_doc/roots/view-list-v1/children/view.ID/children/description + + +description +string + + + + + +/lht_tree_doc/roots/view-list-v1/children/view.ID->/lht_tree_doc/roots/view-list-v1/children/view.ID/children/description + + + + + +/lht_tree_doc/roots/view-list-v1/children/view.ID/children/bbox + + +li:bbox +coord + + + + + +/lht_tree_doc/roots/view-list-v1/children/view.ID->/lht_tree_doc/roots/view-list-v1/children/view.ID/children/bbox + + + + + +/lht_tree_doc/roots/view-list-v1/children/view.ID/children/xy + + +li:xy +coord + + + + + +/lht_tree_doc/roots/view-list-v1/children/view.ID->/lht_tree_doc/roots/view-list-v1/children/view.ID/children/xy + + + + + +/lht_tree_doc/roots/view-list-v1/children/view.ID/children/objs.ID + + +li:objs.ID + + + + + +/lht_tree_doc/roots/view-list-v1/children/view.ID->/lht_tree_doc/roots/view-list-v1/children/view.ID/children/objs.ID + + + + + +/lht_tree_doc/roots/view-list-v1/children/view.ID/children/objs.ID/children/id + + +li:id + + + + + +/lht_tree_doc/roots/view-list-v1/children/view.ID/children/objs.ID->/lht_tree_doc/roots/view-list-v1/children/view.ID/children/objs.ID/children/id + + + + + Index: tags/2.1.2/doc/developer/mods3/README =================================================================== --- tags/2.1.2/doc/developer/mods3/README (nonexistent) +++ tags/2.1.2/doc/developer/mods3/README (revision 24813) @@ -0,0 +1,10 @@ +Run ./gne.sh to regenerate index.html. + +It depends on the following tools to be installed: + +- shell, awk +- sloccount +- netpbm +- animator (svn://repo.hu/animator/trunk) +- animpie - needs to be symlinked or copied to path from animator/test (sorry) + Index: tags/2.1.2/doc/developer/mods3/after.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/developer/mods3/after.png =================================================================== --- tags/2.1.2/doc/developer/mods3/after.png (nonexistent) +++ tags/2.1.2/doc/developer/mods3/after.png (revision 24813) Property changes on: tags/2.1.2/doc/developer/mods3/after.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/developer/mods3/before.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/developer/mods3/before.png =================================================================== --- tags/2.1.2/doc/developer/mods3/before.png (nonexistent) +++ tags/2.1.2/doc/developer/mods3/before.png (revision 24813) Property changes on: tags/2.1.2/doc/developer/mods3/before.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/developer/mods3/deps.svg =================================================================== --- tags/2.1.2/doc/developer/mods3/deps.svg (nonexistent) +++ tags/2.1.2/doc/developer/mods3/deps.svg (revision 24813) @@ -0,0 +1,1233 @@ + + + + + + +plugin_deps + + +user + +user + + +acompnet + +acompnet + + +user->acompnet + + + + +act_draw + +act_draw + + +user->act_draw + + + + +ar_cpcb + +ar_cpcb + + +user->ar_cpcb + + + + +asm + +asm + + +user->asm + + + + +autocrop + +autocrop + + +user->autocrop + + + + +autoplace + +autoplace + + +user->autoplace + + + + +autoroute + +autoroute + + +user->autoroute + + + + +cam + +cam + + +user->cam + + + + +ddraft + +ddraft + + +user->ddraft + + + + +diag + +diag + + +user->diag + + + + +dialogs + +dialogs + + +user->dialogs + + + + +distalign + +distalign + + +user->distalign + + + + +distaligntext + +distaligntext + + +user->distaligntext + + + + +djopt + +djopt + + +user->djopt + + + + +draw_fab + +draw_fab + + +user->draw_fab + + + + +report + +report + + +user->report + + + + +drc_orig + +drc_orig + + +user->drc_orig + + + + +expfeat + +expfeat + + +user->expfeat + + + + +export_bboard + +export_bboard + + +user->export_bboard + + + + +export_bom + +export_bom + + +user->export_bom + + + + +export_dsn + +export_dsn + + +user->export_dsn + + + + +export_dxf + +export_dxf + + +user->export_dxf + + + + +export_fidocadj + +export_fidocadj + + +user->export_fidocadj + + + + +export_gcode + +export_gcode + + +user->export_gcode + + + + +export_gerber + +export_gerber + + +user->export_gerber + + + + +export_ipcd356 + +export_ipcd356 + + +user->export_ipcd356 + + + + +export_lpr + +export_lpr + + +user->export_lpr + + + + +export_ps + +export_ps + + +user->export_ps + + + + +export_oldconn + +export_oldconn + + +user->export_oldconn + + + + +export_openems + +export_openems + + +user->export_openems + + + + +export_openscad + +export_openscad + + +user->export_openscad + + + + +export_png + +export_png + + +user->export_png + + + + +export_stat + +export_stat + + +user->export_stat + + + + +export_svg + +export_svg + + +user->export_svg + + + + +export_test + +export_test + + +user->export_test + + + + +export_xy + +export_xy + + +user->export_xy + + + + +extedit + +extedit + + +user->extedit + + + + +io_lihata + +io_lihata + + +user->io_lihata + + + + +fontmode + +fontmode + + +user->fontmode + + + + +fp_board + +fp_board + + +user->fp_board + + + + +fp_fs + +fp_fs + + +user->fp_fs + + + + +fp_wget + +fp_wget + + +user->fp_wget + + + + +hid_batch + +hid_batch + + +user->hid_batch + + + + +hid_gtk2_gdk + +hid_gtk2_gdk + + +user->hid_gtk2_gdk + + + + +hid_gtk2_gl + +hid_gtk2_gl + + +user->hid_gtk2_gl + + + + +hid_gtk3_cairo + +hid_gtk3_cairo + + +user->hid_gtk3_cairo + + + + +hid_gtk3_gl + +hid_gtk3_gl + + +user->hid_gtk3_gl + + + + +hid_lesstif + +hid_lesstif + + +user->hid_lesstif + + + + +hid_remote + +hid_remote + + +user->hid_remote + + + + +import_calay + +import_calay + + +user->import_calay + + + + +import_dsn + +import_dsn + + +user->import_dsn + + + + +import_edif + +import_edif + + +user->import_edif + + + + +import_fpcb_nl + +import_fpcb_nl + + +user->import_fpcb_nl + + + + +import_hpgl + +import_hpgl + + +user->import_hpgl + + + + +import_ipcd356 + +import_ipcd356 + + +user->import_ipcd356 + + + + +import_ltspice + +import_ltspice + + +user->import_ltspice + + + + +import_mentor_sch + +import_mentor_sch + + +user->import_mentor_sch + + + + +import_mucs + +import_mucs + + +user->import_mucs + + + + +import_netlist + +import_netlist + + +user->import_netlist + + + + +import_sch + +import_sch + + +user->import_sch + + + + +import_tinycad + +import_tinycad + + +user->import_tinycad + + + + +import_ttf + +import_ttf + + +user->import_ttf + + + + +io_autotrax + +io_autotrax + + +user->io_autotrax + + + + +io_dsn + +io_dsn + + +user->io_dsn + + + + +io_eagle + +io_eagle + + +user->io_eagle + + + + +io_hyp + +io_hyp + + +user->io_hyp + + + + +io_kicad + +io_kicad + + +user->io_kicad + + + + +io_kicad_legacy + +io_kicad_legacy + + +user->io_kicad_legacy + + + + +io_mentor_cell + +io_mentor_cell + + +user->io_mentor_cell + + + + +io_pcb + +io_pcb + + +user->io_pcb + + + + +io_tedax + +io_tedax + + +user->io_tedax + + + + +jostle + +jostle + + +user->jostle + + + + +loghid + +loghid + + +user->loghid + + + + +millpath + +millpath + + +user->millpath + + + + +mincut + +mincut + + +user->mincut + + + + +oldactions + +oldactions + + +user->oldactions + + + + +polycombine + +polycombine + + +user->polycombine + + + + +polystitch + +polystitch + + +user->polystitch + + + + +propedit + +propedit + + +user->propedit + + + + +puller + +puller + + +user->puller + + + + +query + +query + + +user->query + + + + +renumber + +renumber + + +user->renumber + + + + +rubberband_orig + +rubberband_orig + + +user->rubberband_orig + + + + +script + +script + + +user->script + + + + +serpentine + +serpentine + + +user->serpentine + + + + +shand_cmd + +shand_cmd + + +user->shand_cmd + + + + +shape + +shape + + +user->shape + + + + +sketch_route + +sketch_route + + +user->sketch_route + + + + +smartdisperse + +smartdisperse + + +user->smartdisperse + + + + +stroke + +stroke + + +user->stroke + + + + +teardrops + +teardrops + + +user->teardrops + + + + +vendordrill + +vendordrill + + +user->vendordrill + + + + +lib_gensexpr + +lib_gensexpr + + +ar_cpcb->lib_gensexpr + + + + +lib_compat_help + +lib_compat_help + + +ar_cpcb->lib_compat_help + + + + +lib_netmap + +lib_netmap + + +ar_cpcb->lib_netmap + + + + +autoroute->lib_compat_help + + + + +draw_fontsel + +draw_fontsel + + +dialogs->draw_fontsel + + + + +draw_csect + +draw_csect + + +draw_fab->report + + + + +export_fidocadj->lib_compat_help + + + + +export_ipcd356->lib_compat_help + + + + +export_lpr->export_ps + + + + +lib_polyhelp + +lib_polyhelp + + +export_openems->lib_polyhelp + + + + +export_openscad->lib_polyhelp + + + + +export_xy->export_bom + + + + +extedit->io_lihata + + + + +io_lihata->lib_compat_help + + + + +fp_wget->fp_fs + + + + +hid_gtk2_gdk->draw_csect + + + + +lib_gtk_common + +lib_gtk_common + + +hid_gtk2_gdk->lib_gtk_common + + + + +lib_gtk_hid + +lib_gtk_hid + + +hid_gtk2_gdk->lib_gtk_hid + + + + +lib_gtk_common->dialogs + + + + +lib_gtk_hid->dialogs + + + + +lib_hid_common + +lib_hid_common + + +lib_gtk_hid->lib_hid_common + + + + +hid_gtk2_gl->draw_csect + + + + +hid_gtk2_gl->lib_gtk_common + + + + +hid_gtk2_gl->lib_gtk_hid + + + + +lib_hid_gl + +lib_hid_gl + + +hid_gtk2_gl->lib_hid_gl + + + + +hid_gtk3_cairo->draw_csect + + + + +hid_gtk3_cairo->lib_gtk_common + + + + +hid_gtk3_cairo->lib_gtk_hid + + + + +hid_gtk3_gl->draw_csect + + + + +hid_gtk3_gl->lib_gtk_common + + + + +hid_gtk3_gl->lib_gtk_hid + + + + +hid_gtk3_gl->lib_hid_gl + + + + +hid_lesstif->dialogs + + + + +hid_lesstif->draw_csect + + + + +hid_lesstif->lib_hid_common + + + + +import_dsn->lib_compat_help + + + + +import_ipcd356->lib_compat_help + + + + +import_mentor_sch->lib_gensexpr + + + + +import_mucs->lib_compat_help + + + + +io_autotrax->lib_polyhelp + + + + +io_dsn->lib_gensexpr + + + + +io_hyp->lib_netmap + + + + +io_kicad->lib_gensexpr + + + + +io_kicad_legacy->io_kicad + + + + +io_pcb->lib_compat_help + + + + +io_tedax->lib_compat_help + + + + +io_tedax->lib_netmap + + + + +lib_legacy_func + +lib_legacy_func + + +millpath->lib_polyhelp + + + + + Index: tags/2.1.2/doc/developer/mods3/export.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/developer/mods3/export.png =================================================================== --- tags/2.1.2/doc/developer/mods3/export.png (nonexistent) +++ tags/2.1.2/doc/developer/mods3/export.png (revision 24813) Property changes on: tags/2.1.2/doc/developer/mods3/export.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/developer/mods3/feature.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/developer/mods3/feature.png =================================================================== --- tags/2.1.2/doc/developer/mods3/feature.png (nonexistent) +++ tags/2.1.2/doc/developer/mods3/feature.png (revision 24813) Property changes on: tags/2.1.2/doc/developer/mods3/feature.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/developer/mods3/fp.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/developer/mods3/fp.png =================================================================== --- tags/2.1.2/doc/developer/mods3/fp.png (nonexistent) +++ tags/2.1.2/doc/developer/mods3/fp.png (revision 24813) Property changes on: tags/2.1.2/doc/developer/mods3/fp.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/developer/mods3/gen.sh =================================================================== --- tags/2.1.2/doc/developer/mods3/gen.sh (nonexistent) +++ tags/2.1.2/doc/developer/mods3/gen.sh (revision 24813) @@ -0,0 +1,188 @@ +#!/bin/sh + +path=../../../src_plugins + +sloc() +{ + (cd "$1" && sloccount .) | awk '/^Total Phys/ { size=$9; sub(",", "", size); print size }' +} + +gen_pie() +{ + local bn=$1 code_size=$2 color=$3 + echo "" + echo "@slice" + echo "$code_size" + echo "@label" + echo "$bn ($code_size)" + if test ! -z "$color" + then + echo "@color" + echo "$color" + fi +} + +rm -f *.pie *.lines + +echo "#autogenerated by gen.sh" > mods.pie +echo "#autogenerated by gen.sh" > after.pie + +echo Core >&2 +tmp=/tmp/pcb-mods-stat +mkdir $tmp +cp -r ../../../src/*.c ../../../src/*.h ../../../src/Makefile* $tmp +code_size=`sloc $tmp` +gen_pie "core" $code_size "#00ff88" >> after.pie + +#echo 3rd >&2 +#code_size=`sloc ../../src_3rd` +#gen_pie "3rd" $code_size >> after.pie + +echo "" > classes +echo ' +digraph plugin_deps { +overlap=scale +'> deps.dot + +( +cat pre.html +for n in $path/* +do + if test -d "$n" + then + echo $n >&2 + bn=`basename $n` + code_size=`sloc $n` + total=$(($total + $code_size)) + class=`cat $n/*.pup | sed ' + /^$class/ { + s/$class *// + s/[()]//g + p + } + { d } + ' ` + echo "$class" >> classes + + echo "$code_size" >> $class.lines + gen_pie $bn $code_size >> $class.pie + +# case $bn in +# gpmi) echo "@pull" >> mods.pie; echo "0.1" >> mods.pie;; +# esac + + echo "$bn$code_size" + cat $n/*.pup | awk -v "plugin=$n" ' + BEGIN { + q = "\"" + dep="/dev/fd/3" + sub(".*/", "", plugin) + } + /^[$]/ { + key=$1 + sub("[$]", "", key) + $1="" + DB[key]=$0 + next + } + + /^dep/ { + print q plugin q "->" q $2 q >> dep + } + + /^[A-Za-z]/ { + key=$1 + $1="" + DB[key]=$0 + next + } + + function strip(s) { + sub("^[ \t]*", "", s) + sub("[ \t]*$", "", s) + return s + } + + END { + st = DB["state"] + if (st ~ "partial") + clr = "bgcolor=\"yellow\"" + else if (st ~ "works") + clr = "bgcolor=\"lightgreen\"" + else if ((st ~ "fail") || (st ~ "disable")) + clr = "bgcolor=\"red\"" + else + clr="" + + clr2 = clr + if (clr2 != "") { + sub("bgcolor=\"", "", clr2) + sub("\"", "", clr2) + print "@color" >> "mods.pie" + print clr2 >> "mods.pie" + } + + print "" st + if (DB["lstate"] != "") + print "
(" strip(DB["lstate"]) ")" + + dfl = DB["default"] + if (dfl ~ "buildin") + clr = "bgcolor=\"lightgreen\"" + else if (dfl ~ "plugin") + clr = "bgcolor=\"yellow\"" + else if ((dfl ~ "disable-all") || (dfl ~ "disable")) + clr = "bgcolor=\"red\"" + else + clr="" + + print "" dfl + if (DB["ldefault"] != "") + print "
(" strip(DB["ldefault"]) ")" + print "" DB["class"] + print "" DB["long"] + if (int(DB["autoload"])) + print q "user" q "->" q plugin q " [color=\"#a0a0a0\"]" >> dep + + class = DB["class"] + if (class ~ "io") + clr = "fillcolor=\"#ffa0a0\"" + else if (class ~ "import") + clr = "fillcolor=\"#a0ffff\"" + else if (class ~ "export") + clr = "fillcolor=\"#a0ffff\"" + else if (class ~ "lib") + clr = "fillcolor=\"#a0a0a0\"" + else if (class ~ "hid") + clr = "fillcolor=\"#a0a0ff\"" + print q plugin q " [style=filled " clr "]" >> dep + } + ' + fi +done +cat post.html +gen_pie "plugins" "$total" "#0088ff" >> after.pie +) > index.html 3>>deps.dot +echo "}" >>deps.dot + +twopi -Tsvg deps.dot > deps.svg + +for n in *.lines +do + lines=`awk '{ sum += $1 } END { print sum }' < $n` + bn=${n%%.lines} + gen_pie $bn $lines >> mods.pie +done + + +classes=`sort < classes | uniq` + +for n in $classes after mods +do + animpie < $n.pie | animator -H -d $n + pngtopnm ${n}0000.png | pnmcrop | pnmtopng > $n.png + rm ${n}0000.png +done + + +rm classes Property changes on: tags/2.1.2/doc/developer/mods3/gen.sh ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/2.1.2/doc/developer/mods3/hid.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/developer/mods3/hid.png =================================================================== --- tags/2.1.2/doc/developer/mods3/hid.png (nonexistent) +++ tags/2.1.2/doc/developer/mods3/hid.png (revision 24813) Property changes on: tags/2.1.2/doc/developer/mods3/hid.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/developer/mods3/import.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/developer/mods3/import.png =================================================================== --- tags/2.1.2/doc/developer/mods3/import.png (nonexistent) +++ tags/2.1.2/doc/developer/mods3/import.png (revision 24813) Property changes on: tags/2.1.2/doc/developer/mods3/import.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/developer/mods3/index.html =================================================================== --- tags/2.1.2/doc/developer/mods3/index.html (nonexistent) +++ tags/2.1.2/doc/developer/mods3/index.html (revision 24813) @@ -0,0 +1,636 @@ + + + pcb-rnd modularization + + +

pcb-rnd modularization

+

Why bother...

+I believe good software should be modular. This is especially important in +the context of large software, such as CAD applications. There should be +a thin core that can model the world and provide the basic operations defined +on it but anything else should go in separate modules. +

+Fortunately PCB already had a strong infrastructure supporting this idea. +It has dynamic loadable plugins and the GUI and exporters are in separate +HID modules. While working on pcb-gpmi and later pcb-rnd, I added the +gpmi module as a separate plugin. +

+In version 1.0.8 to 1.1.0 a considerable chunk of core code has been moved into +core plugins. A core plugin is just a plugin that is +maintained together with the core, in the same repository, still the code is +somewhat detached from the core. More importantly, the user can choose, for +each plugin, separately: +

    +
  • to compile it as a buildin (static-link it into the pcb executable) +
  • to compile it as a plugin (dynamic-link it runtime, if the .so is installed in the plugins/ directory) +
  • to disable the plugin, so it is not compiled at all +
+

+I believe such modularization has benefits on multiple levels: +

    +
  • it is possible to compile smaller, potentially faster executables by omitting features the specific user would never use anyway +
  • in a distribution dynamic-link plugins can be distributed as separate packages providing the user with the option to decide what features to install +
  • such plugins have to have some sort of APIs if they want to reference each other or if the code needs to reference them; such an API may not (and often did not) exist when the code is part of the core +
+ +

Progress in charts

+

Before-after

+All numbers are in SLOC +and are acquired running sloccount on the given directory. While lines of +code alone is not a true measure of complexity, it's a good estimation. The +slices of pie charts are the major components of the pcb-rnd executable. +
+ +
        +
Before modularization: pcb-rnd version 1.0.7 +
Note: gpmi was already a plugin +
+ After modularization: current pcb-rnd +
Note: gpmi is part of the "plugins" slice +
+
+

Zooming on to the plugins

+

+ + + +
total size per class
+
IO plugins
+
+ + + + +
feature plugins
+
export plugins
+
+ + + +
HID plugins
+
import plugins
+
+ + + +
library plugins
+
footprint plugins
+
+ +

+(Red means the plugin doesn't really work). + +

Progress in numbers

+Below is a table with the summary of core plugins. + +
module size [sloc] status configure
default
class description + + +
acompnet306 + WIP + disable + feature + Auto-complete the current network. A very limited autorouter/assistant. +
act_draw355 + works + buildin + feature + Expose drawing related API as actions +
ar_cpcb320 + WIP + buildin + feature + Autoroute using external tool c-pcb +
asm491 + WIP + buildin + feature + hand assembly assistant GUI +
autocrop53 + works + buildin + feature + Reduce the board dimensions to just enclose the objects on the board. +
autoplace720 + works + buildin + feature + Automatically place subcircuits. +
autoroute4448 + works + buildin + feature + Automatically route selected or all rats. This is the original autorouter. +
cam215 + WIP + buildin + export + Configurable output job based batch exporting +
ddraft2018 + WIP + buildin + export + Actions and a command interpreter for supporting advanced/precise 2 dimensional drafting +
diag722 + works + disable + feature + Actions for pcb-rnd core diagnostics, intended for developers. These are not in core because end users normally don't need these. As a plugin, due to dynamic loading, it can be dropped on an existing pcb-rnd installation with minimal risk of scaring away a reproducible bug. +
dialogs7071 + works + disable + feature + Interactive core functionality: HID-independent GUI dialogs (enabled by GUI HIDs) +
distalign441 + works + buildin + feature + Introducing Align() and Distribute(), which work much like the similarly named functions in Visio. Given that PCB does not have the concept of "first selected object" to draw on, the reference points can be selected by arguments. +
distaligntext477 + works + buildin + feature + Same as distalign, operates on text objects. +
djopt2253 + works + buildin + feature + Various board optimization algorithms. +
draw_csect785 + works + disable + feature + Draw cross section and layer map. +
draw_fab288 + works + buildin + feature + Draw the fab layer (for various exporters). +
draw_fontsel143 + works + disable + feature + Draw the font selector GUI +
drc_orig353 + + buildin + feature + A few simple, hardwired Design Rule Checks. +
expfeat33 + works + disable + feature + Staging plugin for experimenting with new actions and dialogs before getting them into core or other plugins +
export_bboard447 + WIP + disable-all + export + Export breadboard +
export_bom234 + works + buildin + export + Export bom (Bill of Materials) +
export_dsn451 + works + buildin + export + Export specctra .dsn files +
export_dxf610 + works + buildin + export + Export dxf +
export_fidocadj279 + WIP + buildin + export + Export to FidoCadJ format (.fcd) +
export_gcode2474 + works + buildin + export + Export to gcode +
export_gerber1260 + works + buildin + export + Export to gerber +
export_ipcd356384 + works + buildin + export + IPC-D-356 Netlist export. +
export_lpr104 + works + buildin + export + Export to lpr (using export_ps to generate postscript) +
export_oldconn224 + works + buildin + export + Export subc/terminal connection map in an old, custom file format +
export_openems1749 + WIP + disable + export + Export copper to OpenEMS simulation +
export_openscad725 + WIP + buildin + export + Export openscad +
export_png1403 + works + buildin + export + Export to png, gif and jpeg +
export_ps1612 + works + buildin + export + Export postscript or embedded postscript. +
export_stat316 + works + buildin + export + Export various board statistics in lihata format +
export_svg671 + works + buildin + export + Scalable Vector Graphics (SVG) exporter +
export_test92 + WIP + disable + export + A thin layer of code to dump exporter calls for testing the HID exporter API. +
export_xy721 + works + buildin + export + Template based export of XY centroid subcircuit data e.g. for pick & place. +
extedit315 + works + buildin + feature + invoke external program to edit parts of the current board +
fontmode259 + works + buildin + feature + Font editing actions. +
fp_board120 + WIP + buildin + fp + Footprint: load a board and expose all the unique subcircuits on that board as a footprint library +
fp_fs428 + works + buildin + fp + Footprint: file system based implementation. Used to be called Newlib: load footprints from directories. Run external processes for the parametric footprints. +
fp_wget637 + works + buildin + fp + Footprint: get static (file) footprints from the web, e.g. from http://gedasymbols.org +
hid_batch294 + works + buildin + hid + HID without GUI: read actions from stdin. +
hid_gtk2_gdk1335 + works + buildin + hid + GUI: GTK2 HID with GDK software rendering. +
hid_gtk2_gl916 + works + buildin + hid + GUI: GTK2 with opengl rendering +
hid_gtk3_cairo1122 + WIP + disable-all + hid + GUI: the GTK3 HID, using cairo for rendering +
hid_gtk3_gl51 + WIP + disable-all + hid + GUI: the GTK3 HID, using gl for rendering +
hid_lesstif9133 + works + buildin + hid + GUI: the lesstif HID. +
hid_remote1148 + WIP + disable-all + hid + Remote access HID: implement a protocol and use it to relay between a core and a remote HID implementation. +
import_calay177 + works + buildin + import + Import the netlist and footprints from a calay netlist. +
import_dsn270 + works + buildin + import + Import specctra .dsn files +
import_edif3626 + works + buildin + import + Import plugin for netlists in the EDIF format. +
import_fpcb_nl153 + works + buildin + import + Import the netlist and footprints from freepcb format (exported by e.g. easyeda) +
import_hpgl133 + works + buildin + import + Emulate a plotter and import the plot as lines, arcs and polygons. +
import_ipcd356383 + works + buildin + import + IPC-D-356 Netlist and pad centroid import +
import_ltspice244 + works + buildin + import + Import the netlist and footprints from an ltspice .asc and .net pair of files +
import_mentor_sch495 + works + buildin + import + Import Mentor Graphics Design Capture from flattened .edf netlist, using a parts conversion table. +
import_mucs124 + works + buildin + import + Import lines and vias from MUCS unixplot .pl files +
import_netlist141 + works + buildin + import + Import plugin for netlists in the classic pcb netlist format. +
import_sch335 + works + buildin + import + Imports footprints and netlist data from the schematics (or some other source). +
import_tinycad151 + works + buildin + import + Import the netlist and footprints from a tinycad netlist. +
import_ttf165 + WIP + buildin + import + Import outline ttf glyphs into the current font, either as polygons or lines +
io_autotrax1584 + works + buildin + io + Import and export autotrax layouts and footprints. +
io_dsn1676 + works + disable + io + Load and save specctra DSN files +
io_eagle4027 + works + buildin + io + Load the design from eagle's xml and binary formats. +
io_hyp4087 + works + buildin + io + Import plugin for hyperlynx geometry (no polygons yet). +
io_kicad3508 + works + buildin + io + Load and save the design and footprints in Kicad's s-expression format - this is the new, currently preferred format in Kicad. +
io_kicad_legacy936 + works + buildin + io + Export the design and footprints in Kicad's legacy format. +
io_lihata4160 + works + buildin + io + Load and save the design and footprints in the lihata board format. +
io_mentor_cell401 + WIP + disable + io + Load Mentor Graphics cell footprint library and make footprints available (e.g. for fp_board) +
io_pcb2859 + works + buildin + io + Load and save the design and footprints in the original gEDA/PCB text format. +
io_tedax2281 + works + buildin + io + Import and export tEDAx netlists and footprints. +
jostle423 + works + buildin + feature + Pushes lines out of the way. +
lib_compat_help1167 + works + buildin + lib + a library of functions providing a simplified API compatibility layer, mainly for I/O plugins +
lib_gensexpr13 + works + disable-all + lib + S-expression parser lib +
lib_gtk_common10463 + works + disable-all + lib + hid_gtk* common code (regardless of gtk version or drawing mechanism: for both gtk2 and gtk3 and for both sw rendering and gl) +
lib_gtk_hid1313 + works + disable-all + lib + Generic gtk HID implementation, independent of GTK version (2 vs. 3) and rendering engine. Mostly a dispatcher that fills in all the glue to connect the parts. An actual gtk HID implementation may use this lib or replace parts of it or the whole with local implementation. +
lib_hid_common715 + works + disable-all + lib + hid_* common helper functions +
lib_hid_gl1106 + works + disable-all + lib + generic openGL renderer shared among GUI HIDs +
lib_legacy_func90 + works + buildin + lib + Random collection of old/obsolete (legacy) functions. 3rd party plugins may depend on them. This module implements C functions and variables and does not register actions or flags. +
lib_netmap216 + works + disable-all + lib + create disposable cross-reference maps between all objects and all nets +
lib_polyhelp708 + works + buildin + lib + functions to help plugins processing polygons and PolyHatch() action +
loghid307 + WIP + disable + feature + Sits between a HID (or exporter) and the core and logs all core->plugin calls made through the HID structure. +
millpath246 + WIP + disable + feature + Calculate and simulate toolpath for milling away opper +
mincut948 + works + buildin + feature + Use the minimal cut algorithm to indicate shorts: instead of highlighting two random pins/pads, try to highlight the least number of objects that connect the two networks. +
oldactions270 + works + disable + feature + Random collection of old/obsolete actions. Bell(): audible feedback, DumpLibrary(): print footprint library on stdout, a set of debug actions useful for writing pcb scripts: Debug(), DebugXY(), Return(). Old plugin actions to toggle or set settings that are now accessible via the unified config system (vendordrill, djopt) +
polycombine209 + works + buildin + feature + The selected polygons are combined together according to the ordering of their points. +
polystitch98 + works + buildin + feature + The polygon under the cursor (based on closest-corner) is stitched together with the polygon surrounding it on the same layer. Use with pstoedit conversions where there's a "hole" in the shape - select the hole. +
propedit1540 + works + buildin + feature + List and edit properties of a group of objects. +
puller1749 + works + buildin + feature + Pull traces to minimize their length. +
query1986 + works + buildin + feature + pcb-rnd query language: execute expressions on objects and rules for the programmed drc. +
renumber332 + works + buildin + feature + Renumber subcircuits (renaming them) and generate a text file for back annotation. +
report899 + works + buildin + feature + Report() and ReportObject() actions - print a report about design objects. +
rubberband_orig1252 + works + buildin + feature + The original rubberband code. +
script812 + works + buildin + feature + Load and execute scripts written in any language supported by fungw +
serpentine371 + WIP + disable-all + feature + Create serpentines on existing lines. +
shand_cmd167 + works + buildin + feature + vi-like command shorthands (1..3 character long commands) +
shape829 + works + buildin + feature + Generate objects of regular shape (regular polygons, circle, round rect) +
sketch_route2677 + WIP + disable + feature + TODO +
smartdisperse276 + works + buildin + feature + Improve the initial dispersion of subcircuits by choosing an order based on the netlist, rather than the arbitrary subcircuit order. This isn't the same as a global autoplace, it's more of a linear autoplace. It might make some useful local groupings. For example, you should not have to chase all over the board to find the resistor that goes with a given LED. +
stroke133 + works + buildin + feature + Configurable gesture recognition with libstroke. +
teardrops217 + works + buildin + feature + Draw teardrops on pins. +
vendordrill517 + works + buildin + feature + Vendor drill mapping. +
+ +

Classes

+

+Each plugin implements a class (rarely a set of classes). Classes are: + +
name description +
feature random features directly accessible for the user, usually actions +
lib support code library for other plugins (core doesn't depend on these); functionality not directly accessible for the user but other plugins may depend on it +
hid Human Interface Device: interactive user interface, usually GUI +
import load alien formats into the design space +
export save (parts of) the design space in alien formats +
fp footprint (element) library implementation +
io native file format (save & load) implementation +
+ +

Status

+

+Common status column values mean: + +
name description +
works production quality code - configures, compiles, tested +
WIP work in progress: the plugin may be avaialble for testing but is not yet production quality +
abandoned unmaintained plugin; may be in working condition but there is no developer supporting it +
deprecated legacy plugin scheduled for removal; may still work but will soon be removed; if your workflow depends on it, please report ASAP +
+ +

Plugin dependency map

+

+pcb-rnd plugin dependency graph + + + Index: tags/2.1.2/doc/developer/mods3/io.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/developer/mods3/io.png =================================================================== --- tags/2.1.2/doc/developer/mods3/io.png (nonexistent) +++ tags/2.1.2/doc/developer/mods3/io.png (revision 24813) Property changes on: tags/2.1.2/doc/developer/mods3/io.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/developer/mods3/lib.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/developer/mods3/lib.png =================================================================== --- tags/2.1.2/doc/developer/mods3/lib.png (nonexistent) +++ tags/2.1.2/doc/developer/mods3/lib.png (revision 24813) Property changes on: tags/2.1.2/doc/developer/mods3/lib.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/developer/mods3/mods.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/developer/mods3/mods.png =================================================================== --- tags/2.1.2/doc/developer/mods3/mods.png (nonexistent) +++ tags/2.1.2/doc/developer/mods3/mods.png (revision 24813) Property changes on: tags/2.1.2/doc/developer/mods3/mods.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/developer/mods3/post.html =================================================================== --- tags/2.1.2/doc/developer/mods3/post.html (nonexistent) +++ tags/2.1.2/doc/developer/mods3/post.html (revision 24813) @@ -0,0 +1,33 @@ + + +

Classes

+

+Each plugin implements a class (rarely a set of classes). Classes are: + +
name description +
feature random features directly accessible for the user, usually actions +
lib support code library for other plugins (core doesn't depend on these); functionality not directly accessible for the user but other plugins may depend on it +
hid Human Interface Device: interactive user interface, usually GUI +
import load alien formats into the design space +
export save (parts of) the design space in alien formats +
fp footprint (element) library implementation +
io native file format (save & load) implementation +
+ +

Status

+

+Common status column values mean: + +
name description +
works production quality code - configures, compiles, tested +
WIP work in progress: the plugin may be avaialble for testing but is not yet production quality +
abandoned unmaintained plugin; may be in working condition but there is no developer supporting it +
deprecated legacy plugin scheduled for removal; may still work but will soon be removed; if your workflow depends on it, please report ASAP +
+ +

Plugin dependency map

+

+pcb-rnd plugin dependency graph + + + Index: tags/2.1.2/doc/developer/mods3/pre.html =================================================================== --- tags/2.1.2/doc/developer/mods3/pre.html (nonexistent) +++ tags/2.1.2/doc/developer/mods3/pre.html (revision 24813) @@ -0,0 +1,88 @@ + + + pcb-rnd modularization + + +

pcb-rnd modularization

+

Why bother...

+I believe good software should be modular. This is especially important in +the context of large software, such as CAD applications. There should be +a thin core that can model the world and provide the basic operations defined +on it but anything else should go in separate modules. +

+Fortunately PCB already had a strong infrastructure supporting this idea. +It has dynamic loadable plugins and the GUI and exporters are in separate +HID modules. While working on pcb-gpmi and later pcb-rnd, I added the +gpmi module as a separate plugin. +

+In version 1.0.8 to 1.1.0 a considerable chunk of core code has been moved into +core plugins. A core plugin is just a plugin that is +maintained together with the core, in the same repository, still the code is +somewhat detached from the core. More importantly, the user can choose, for +each plugin, separately: +

    +
  • to compile it as a buildin (static-link it into the pcb executable) +
  • to compile it as a plugin (dynamic-link it runtime, if the .so is installed in the plugins/ directory) +
  • to disable the plugin, so it is not compiled at all +
+

+I believe such modularization has benefits on multiple levels: +

    +
  • it is possible to compile smaller, potentially faster executables by omitting features the specific user would never use anyway +
  • in a distribution dynamic-link plugins can be distributed as separate packages providing the user with the option to decide what features to install +
  • such plugins have to have some sort of APIs if they want to reference each other or if the code needs to reference them; such an API may not (and often did not) exist when the code is part of the core +
+ +

Progress in charts

+

Before-after

+All numbers are in SLOC +and are acquired running sloccount on the given directory. While lines of +code alone is not a true measure of complexity, it's a good estimation. The +slices of pie charts are the major components of the pcb-rnd executable. +
+ +
        +
Before modularization: pcb-rnd version 1.0.7 +
Note: gpmi was already a plugin +
+ After modularization: current pcb-rnd +
Note: gpmi is part of the "plugins" slice +
+
+

Zooming on to the plugins

+

+ + + +
total size per class
+
IO plugins
+
+ + + + +
feature plugins
+
export plugins
+
+ + + +
HID plugins
+
import plugins
+
+ + + +
library plugins
+
footprint plugins
+
+ +

+(Red means the plugin doesn't really work). + +

Progress in numbers

+Below is a table with the summary of core plugins. + +
module size [sloc] status configure
default
class description + + Index: tags/2.1.2/doc/developer/new_model_progress/Makefile =================================================================== --- tags/2.1.2/doc/developer/new_model_progress/Makefile (nonexistent) +++ tags/2.1.2/doc/developer/new_model_progress/Makefile (revision 24813) @@ -0,0 +1,2 @@ +roadmap.svg: roadmap.dot + dot -Tsvg < roadmap.dot > roadmap.svg Index: tags/2.1.2/doc/developer/new_model_progress/remove_stats.txt =================================================================== --- tags/2.1.2/doc/developer/new_model_progress/remove_stats.txt (nonexistent) +++ tags/2.1.2/doc/developer/new_model_progress/remove_stats.txt (revision 24813) @@ -0,0 +1,8 @@ +with old model: 1.2.8 +SLOC=200842 +#warnings: 326 +c and h files in src/ and src_plugins/: 817 + +after removal: +SLOC=189893 (removed 10949 sloc, 5.4515% of the code in 1.2.8) + Index: tags/2.1.2/doc/developer/new_model_progress/roadmap.dot =================================================================== --- tags/2.1.2/doc/developer/new_model_progress/roadmap.dot (nonexistent) +++ tags/2.1.2/doc/developer/new_model_progress/roadmap.dot (revision 24813) @@ -0,0 +1,72 @@ +digraph roadmap { + "2016_4" [label="2016\n4th\nquarter" shape=plaintext] + "2017_1" [label="2017\n1st\nquarter" shape=plaintext] + "2017_2" [label="2017\n2nd\nquarter" shape=plaintext] + "2017_3" [label="2017\n3rd\nquarter" shape=plaintext] + "2017_3b" [label="" shape=plaintext] + "2017_4" [label="2017\n4th\nquarter" shape=plaintext] + "2018_1" [label="2018\n1st\nquarter" shape=plaintext] + "2018_2" [label="2018\n2nd\nquarter" shape=plaintext] + + "2016_4" -> "2017_1" [style=invisible arrowhead=none] + "2017_1" -> "2017_2" [style=invisible arrowhead=none] + "2017_2" -> "2017_3" [style=invisible arrowhead=none] + "2017_3" -> "2017_3b" [style=invisible arrowhead=none] + "2017_3b" -> "2017_4" [style=invisible arrowhead=none] + "2017_4" -> "2018_1" [style=invisible arrowhead=none] + "2018_1" -> "2018_2" [style=invisible arrowhead=none] + + lihata [color=green label="Lihata:\nNew native file format\nso we can make our changes\nwithout breaking compatibilty\nor having to wait for mainline"] + layer [color=green label="layer rewrite:\nmuch more detailed model of\nphysical and logical layers"] + subcircuit [color=green label="subcircuit:\nfootprints without special objects"] + binding [color=green label="layer binding:\nabstract layer recipes\nthat are board-independent\nand can be applied on a\ngiven board's stackup"] + compositing [color=green label="layer compositing:\npositive/nagative drawn layers within a group\nallows drawing paste, mask, inverse silk, etc."] + term [color=green label="subcircuit terminals:\ngeneralized pin/pad idea\nthat allows any drawing primitive\nto be a pin or pad"] + elem_replace [color=green label="element replacement:\nreplace the old element model\nwith subcircuits\nmake sure subcircuits can do\nanything an element could do"] + elem_remove [color=red label="element removal:\nremove elements, element-lines, element-arcs\npins, pads and the old circular-only vias\nin favor of subcircuits and pad stacks"] + padstacks [color=green label="pad stacks:\na via (or pin or pad)\nthat can have different,\narbitrary copper shape\non different layer groups"] + bbvia [color=green label="blind/buried via:\na pad stack has per layer info on\ncopper shape, it can\nalso have such info about the drill ends"] + + fp_nolimit [color=green shape=box label="goal:\nfootprints without limitations"] + clean [color=red shape=box label="goal:\nclean, tree based data structure"] + + recur [color=red label="subcircuit in subcircuit"] + hier [color=red label="hierarchical netlists"] + + { rank=same; "2016_4" lihata} + { rank=same; "2017_1" layer} + { rank=same; "2017_2" compositing} + { rank=same; "2017_3" subcircuit} + { rank=same; "2017_3b" binding term} + { rank=same; "2017_4" padstacks} + { rank=same; "2018_1" elem_replace} + { rank=same; "2018_2" elem_remove} + + lihata -> layer + layer -> subcircuit + layer -> binding + layer -> compositing + subcircuit -> binding + subcircuit -> term + subcircuit -> elem_replace + padstacks -> elem_replace + padstacks -> bbvia + binding -> elem_replace + elem_replace -> elem_remove + elem_remove -> clean + + + compositing -> fp_nolimit + binding -> fp_nolimit + term -> fp_nolimit + + compositing -> clean + binding -> clean + term -> clean + + clean -> recur + recur -> hier + + + +} Index: tags/2.1.2/doc/developer/new_model_progress/roadmap.svg =================================================================== --- tags/2.1.2/doc/developer/new_model_progress/roadmap.svg (nonexistent) +++ tags/2.1.2/doc/developer/new_model_progress/roadmap.svg (revision 24813) @@ -0,0 +1,281 @@ + + + + + + +roadmap + + +2016_4 +2016 +4th +quarter + + +2017_1 +2017 +1st +quarter + + +2016_4->2017_1 + + +2017_2 +2017 +2nd +quarter + + +2017_1->2017_2 + + +2017_3 +2017 +3rd +quarter + + +2017_2->2017_3 + + +2017_3b + + +2017_3->2017_3b + + +2017_4 +2017 +4th +quarter + + +2017_3b->2017_4 + + +2018_1 +2018 +1st +quarter + + +2017_4->2018_1 + + +2018_2 +2018 +2nd +quarter + + +2018_1->2018_2 + + +lihata + +Lihata: +New native file format +so we can make our changes +without breaking compatibilty +or having to wait for mainline + + +layer + +layer rewrite: +much more detailed model of +physical and logical layers + + +lihata->layer + + + + +subcircuit + +subcircuit: +footprints without special objects + + +layer->subcircuit + + + + +binding + +layer binding: +abstract layer recipes +that are board-independent +and can be applied on a +given board's stackup + + +layer->binding + + + + +compositing + +layer compositing: +positive/nagative drawn layers within a group +allows drawing paste, mask, inverse silk, etc. + + +layer->compositing + + + + +subcircuit->binding + + + + +term + +subcircuit terminals: +generalized pin/pad idea +that allows any drawing primitive +to be a pin or pad + + +subcircuit->term + + + + +elem_replace + +element replacement: +replace the old element model +with subcircuits +make sure subcircuits can do +anything an element could do + + +subcircuit->elem_replace + + + + +binding->elem_replace + + + + +fp_nolimit + +goal: +footprints without limitations + + +binding->fp_nolimit + + + + +clean + +goal: +clean, tree based data structure + + +binding->clean + + + + +compositing->fp_nolimit + + + + +compositing->clean + + + + +term->fp_nolimit + + + + +term->clean + + + + +elem_remove + +element removal: +remove elements, element-lines, element-arcs +pins, pads and the old circular-only vias +in favor of subcircuits and pad stacks + + +elem_replace->elem_remove + + + + +elem_remove->clean + + + + +padstacks + +pad stacks: +a via (or pin or pad) +that can have different, +arbitrary copper shape +on different layer groups + + +padstacks->elem_replace + + + + +bbvia + +blind/buried via: +a pad stack has per layer info on +copper shape, it can +also have such info about the drill ends + + +padstacks->bbvia + + + + +recur + +subcircuit in subcircuit + + +clean->recur + + + + +hier + +hierarchical netlists + + +recur->hier + + + + + Index: tags/2.1.2/doc/developer/obj_func_naming.txt =================================================================== --- tags/2.1.2/doc/developer/obj_func_naming.txt (nonexistent) +++ tags/2.1.2/doc/developer/obj_func_naming.txt (revision 24813) @@ -0,0 +1,98 @@ +obj_* function naming conventions + + +High level (new/destroy): + + This is the recommended way of creating new objects. + + pcb_*_new(): + Calls pcb_*_alloc(), fills in fields from parameters and calls the post + processing (pcb_add_*_on_layer()) function as needed. Makes sanity checks + on the parameters and may fail upon that. + + pcb_*_new_*(): + Same as pcb_*_new(), but may do clever things so the object created may + not be 1:1 what was requested or may not even be a new object (e.g. + overlapping line merging) + + pcb_*_destroy() + free all fields of an object and properly remove it from the parent + (including rtree removal) + +Low level (alloc/free): + + Use this in some special cases (like loading a file) when the extra checks + of a _new may interfere. + + pcb_*_alloc(): + allocate a new objects within a parent (as of now: layer). Allocates + the struct of a new objects with all fields clean and links the object + in the parent list. Returns a pointer to the object. NOTE: some post + processing may be needed after filling in the fields + (see also: pcb_add_*_on_layer()). Calls pcb_*_reg() automatically. + + pcb_*_alloc_id(): + same as pcb_*_alloc(), but instead of automatically pick the next id, + uses the user supplied ID + + pcb_*_free(): + free the struct memory (but not the fields!) of an object and remove + it from the parent list. Calls pcb_*_unreg() automatically. + + pcb_*_reg(): + register an object in data; this includes adding the object in the right + object list and in the id hash, but does not include any rtree operation + (so coords/sizes may change later). Also sets the object's parent. + + pcb_*_unreg(): + unregister an object from its data; this includes removing the object from + the right object list and from the id hash, but does not include any + rtree operation. Also clears the object's parent. + + pcb_add_*_on_layer(): + Postprocessing: call this after a new object is allocated and fields are + filled in. It mainly updates the rtree. + + pcb_*_copy(): + copy fields of a complex obj to a pre-allocated target obj + + pcb_*_pre() and pcb_*_post(): + when an object needs to be moved/changed within its own context (e.g. layer + object moved within layer, global object moved within data), it first needs + to be removed from the rtree and uncleared from any sorrunding polygon. + After the changes are done, the object should be put back in the rtree and + the affected polygons should be cleared. These two steps are done by + pcb_*_pre() and pcb_*_post(). Call pre() before the operation, call post() + after the operation. + +Accessors: + pcb_*_get_*(): + Return data that are not directly accessible as object struct fields but + require some sort of calculation + + pcb_*_set_*(): + Set object fields that require postprocessing because of side effects. + Use these instead of direct writes to the fields to get side effects + properly executed. + + pcb_*_change_*(): + Similar to pcb_*_set_*(), but instead of setting a field to a value + specified as a parameter, change the field to comply with some global + state, e.g. "change side" would move the object to the currently viewed + side. + +Transformations: + pcb_*_move(): + move the object within its parent (x;y); it's often implemented as a + macro + + pcb_*_mirror(): + mirror the object within its parent (x;y) + + +Misc: + pcb_*_bbox(): + calculate and update the bounding box of an object + + pcb_*_rotate90() + Rotate the object by n*90 degrees Index: tags/2.1.2/doc/developer/old_netlist.txt =================================================================== --- tags/2.1.2/doc/developer/old_netlist.txt (nonexistent) +++ tags/2.1.2/doc/developer/old_netlist.txt (revision 24813) @@ -0,0 +1,38 @@ +This file describes the old netlist model. The old model seems to be +deisgned from a GUI perspective, probably from the Xaw times. This old +model will eventually be replaced by a more proper tree structure that +will be able to represent hierarchic netlists. + +Moved from the gtk sources: + + -------- The netlist nodes (pcb_lib_entry_t) data model ---------- + Each time a net is selected in the left treeview, this node model + is recreated containing all the nodes (pins/pads) that are connected + to the net. Loading the new model will update the right treeview with + all the new node names (C100-1, R100-1, etc). + + The terminology is a bit confusing because the PCB netlist data + structures are generic structures used for library elements, netlist + data, and possibly other things also. The mapping is that + the layout netlist data structure is a pcb_lib_t which + contains an allocated array of pcb_lib_menu_t structs. Each of these + structs represents a net in the netlist and contains an array + of pcb_lib_entry_t structs which represent the nodes connecting to + the net. So we have: + + | Nets Nodes + | pcb_lib_t pcb_lib_menu_t pcb_lib_entry_t + | ------------------------------------------------------- + | PCB->NetlistLib------Menu[0]-----------Entry[0] + | | Entry[1] + | | ... + | | + | --Menu[1]-----------Entry[0] + | | Entry[1] + | | ... + | | + | -- ... + | + | Where for example Menu[] names would be nets GND, Vcc, etc and Entry[] + | names would be nodes C101-1, R101-2, etc + Index: tags/2.1.2/doc/developer/openems.txt =================================================================== --- tags/2.1.2/doc/developer/openems.txt (nonexistent) +++ tags/2.1.2/doc/developer/openems.txt (revision 24813) @@ -0,0 +1,15 @@ +Temporary doc draft for openems usage. + +For ports, place padstacks with either top or bottom copper shape and _no_ +hole. Then set the attribute openems::vport on the padstack. The value +should be the name of the port as to be seen in openems. + +List of openems-related attributes: + +openems::vport - mandatory: port name +openems::resistance - optional: overrides default port resistance +openems::active - optional: either true or false; default=true +openems::vport-reverse - optional: when present, swap start/end + + + Index: tags/2.1.2/doc/developer/packaging/Changelog =================================================================== --- tags/2.1.2/doc/developer/packaging/Changelog (nonexistent) +++ tags/2.1.2/doc/developer/packaging/Changelog (revision 24813) @@ -0,0 +1,100 @@ +How to get a release candidate tarball in /tmp: + + ver=2.1.2 + cd /tmp + svn export svn://repo.hu/pcb-rnd/trunk pcb-rnd-$ver + tar -cf pcb-rnd-$ver.tar pcb-rnd-$ver + + +Packaging changes between 2.1.1 and 2.1.2 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +A. changes that probably don't need action + +1. Fixed typo in the packages.html: pcb-rnd-hid-gtk2-dl -> pcb-rnd-hid-gtk2-gl + +B. changes that probably DO need action + +1. Fixed wording in the description of package pcb-rnd-io-alien: + "PCB board" -> "PCB layout" (to avoid redundancy with the acrynom) + Please adjust the description of your package. + + +Packaging changes between 2.1.0 and 2.1.1 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +A. changes that probably don't need action + +1. new plugins in already existing packages (new files in existing packages, ./configure line change): + - import_calay plugin in pcb-rnd-import-net + - drc_orig plugin in pcb-rnd-core (old DRC code moved from core code to plugin code) + - export_oldconn plugin in pcb-rnd-export-extra (old connection export moved out from core to plugin) + +2. plugins removed (but parent packages are kept, ./configure line change): + - boardflip plugin (was in pcb-rnd-core) + - lib_gtk_config (was in pcb-rnd-lib-gtk) - old gtk-only preferences dialog removed in favor of the new + +3. bugs that got fixed in packages.html + - cam.conf was not listed as installed file for pcb-rnd-export + +B. changes that probably DO need action + +1. minor changes in package deps: + - pcb-rnd-hid-gtk2-gl doesn't directly depend on pcb-rnd-lib-gui + - pcb-rnd-hid-gtk2-gdk doesn't directly depend on pcb-rnd-lib-gui + - pcb-rnd-io-standard started to depend on pcb-rnd-lib-io + +2. new files introduced by already existing plugins + - $C/dialogs.conf in pcb-rnd-lib-gui + +3. please update your ./configure line because it has changed for + plugin removals and new plugins. You can obtain a diff by looking + at the bottom of: svn diff -c 22941 packages.html + + + +Packaging changes between 2.0.1 and 2.1.0 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +A. changes that probably don't need action + +1. FYI, the html now contains a more complete installed file listing: not +just the .so and .pup files but also the per plugin .conf files. +Installed files got a path prefix $P/ or $C/ depending on where they end +up (plugin dir or conf dir) after the installation. + +2. New plugin: ar_cpcb (in pcb-rnd-auto); this is our new interface for +external autorouter c-pcb. c-pcb doesn't seem to have standard installation +yet, so packaging it would be hard. If there's interest, in packaging +c-pcb, I can try to push for a make install. + +3. Scripting and fungw: by now fungw scripting is at least as capable +as gpmi scripting is. I will remove gpmi in December. However, for +packaged pcb-rnd scripting is not yet available because fungw is not +yet packaged. If you plan to make pcb-rnd scriptable in your distro, +you will need to package libmawk and fungw first - please contact me. +(Packaging those don't need to be in sync with pcb-rnd releases, can +happen any time). For more details see: +http://repo.hu/cgi-bin/pool.cgi?cmd=show&node=script_pkg + +4. New io plugin: io_dsn, in pcb-rnd-io-alien; it can load a full board +from dsn, which is a de-facto industrial standard for autorouting. + +5. New mini-plugin: act_draw in pcb-rnd-core; it implements actions to +low level drawing (exposes pcb-rnd's native drawing functions) + +6. New GUI plugin asm in pcb-rnd-auto; it's a feature that helps manually +building a board by preseting the BoM in a grouped, sorted list, keeping +track on what's put on the board already and highlighting what needs to be +put on next. It has a high eye-candy factor, may look good in the screenshots. + + +B. changes that probably DO need action + +7. We have removed our nelma support; please make sure you remove them +from any documentation/metadata/material. + +8. New, preliminary plugin in pcb-rnd-import-geo: ttf import; this makes +pcb-rnd-import-geo depend on libfreetype6 + +9. Package pcb-rnd-auto started to depend on package pcb-rnd-io +(because of external autorouters like ar_cpcb) Index: tags/2.1.2/doc/developer/packaging/desc =================================================================== --- tags/2.1.2/doc/developer/packaging/desc (nonexistent) +++ tags/2.1.2/doc/developer/packaging/desc (revision 24813) @@ -0,0 +1,105 @@ +@pcb-rnd + Standard installation of pcb-rnd + + Install pcb-rnd core and the most commonly used plugins. + +@pcb-rnd-doc + Documentation for pcb-rnd + + User manual (html) and manual pages. + +@pcb-rnd-core + pcb-rnd executable with the core functionality + + Includes the data model, the most common action commands, the native file + format and the CLI (batch HID). Does not contain GUI. Can be used in + headless mode or batch/scripted mode for automated processing. + +@pcb-rnd-auto + Autoroute and autoplace. + + Feature plugins for automated component placing and track routing + +@pcb-rnd-cloud + Networking plugins. + + 'Cloud' footprint access plugin that integrates edakrill and gedasymbols.org. + +@pcb-rnd-debug + Debug and diagnostics. + + Extra action commands to help debugging and diagnostize problems and bugs. + +@pcb-rnd-export-extra + Export formats: special/extra + + Less commonly used export formats: fidocadj, ipc-356-d, direct printing with lpr. + +@pcb-rnd-export-sim + Export plugins to simulators + + Export the board in formats that can be used for simulation: openems. + +@pcb-rnd-export + Common export plugins. + + Export the board in vector graphics (svg, ps, eps), raster graphics + (png, jpeg, etc.), gerber, 3d model in openscad, xy for pick and place, + BoM, etc. + +@pcb-rnd-extra + Extra action commands and optional functionality. + + Align objects in grid, optimize tracks, font editor, combine polygons, + renumber subcircuits, apply vendor drill mapping. + +@pcb-rnd-hid-gtk2-gdk + GUI: gtk2, software render + + Software rendering on gtk2, using the gdk API. + +@pcb-rnd-hid-gtk2-gl + GUI: gtk2, opengl + + Hardware accelerated (opengl) rendering on gtk2. + +@pcb-rnd-hid-lesstif + GUI: motif/lesstif, software render + + Lightweight GUI and software rendering using the motif (lesstif) toolkit. + +@pcb-rnd-import-geo + Geometry import plugins. + + Import geometry from HPGL plots. HPGL can be produced (plotted) with + most mechanical cads. + +@pcb-rnd-import-net + Netlist/schematics import plugins. + + Import netlist and footprint information from edif, ltspice, mentor graphics, + gschem and tinycad. + +@pcb-rnd-io-alien + File format compatibility with other PCB layout designers. + + Load and/or save boards in file formats supported by other + EDA tools, such as KiCAD, Eagle, protel/autotrax, etc. + +@pcb-rnd-io-standard + Commonly used non-native board and footprint file formats + + Plugins for tEDAx footprint format and the gEDA/PCB file formats + (footprint and board). + +@pcb-rnd-lib-gl + Support library for rendering with opengl. + +@pcb-rnd-lib-gtk + Support library for building the GUI with gtk. + +@pcb-rnd-lib-gui + Support library for building the GUI. + +@pcb-rnd-lib-io + Support library for alien file formats. Index: tags/2.1.2/doc/developer/packaging/description.txt =================================================================== --- tags/2.1.2/doc/developer/packaging/description.txt (nonexistent) +++ tags/2.1.2/doc/developer/packaging/description.txt (revision 24813) @@ -0,0 +1,54 @@ +Description-en: Modular Printed Circuit Board layout tool + pcb-rnd is a highly modular PCB (Printed Circuit Board) layout tool + with a rich set of plugins for communicating with various external + design tools and other EDA/CAD packages. + . + Feature highlights: + - subcircuits, pad stacks + - flexible footprint model; unrestricted pad shapes + - arbitrary copper, silk, paste and soldermask objects + - sophisticated, flexible layer model + - flexible/universal polygon model + - any object, even polygons, can have a clearance within a polygon + - advanced mil and mm grid, with support for mixed unit design + - strong CLI support + - static footprints and parametric (generated) footprints + - query language for advanced search & select + - layout optimizers such as teardrops and a trace puller + - footprint library from local file systems, HTTP and board files + - netlist management: imported and as-built; back annotation + - design rule checker + . + File formats and compatibility: + - text based, tree structured native file format + - gerber (export) + - KiCad, s-expr format boards (read, write) + - KiCad, s-expr format elements (write) + - KiCad, legacy text format boards (write) + - KiCad, eeschema netlist+footprint info (import) + - tEDAx footprints (read, write) + - tEDAx netlist (read) + - Autotrax (protel) pcb boards (read, write) + - Eagle XML format boards and libraries (read) + - Eagle binary format boards and libraries (read) + - Eagle DRU files (read) + - Mentor Graphics Hyperlynx (read/write) + - gEDA/PCB (read, write) + - Specctra DSN (partial import/export, for freerouting.net) + - flat EDIF netlist (import) + - HPGL plot files (import) + - openSCAD colored 3d model script (export) + - ltspice netlist+footprint info (import) + - Mentor Graphics Design Capture netlist+footprint info (import) + - MUCS unixplot (partial import: lines, vias) + - gEDA/gschem netlist+footprint info (import) + - TinyCAD netlist+footprint info (import) + - breadboard assembly drawing png (export) + - BoM (Bill of Materials; export) + - dxf, 2d drawings (export) + - fidocadj board (export) + - gcode (export) + - PNG, JPEG, GIF (export with photo-realistic render option) + - postscript: ps, eps (export) + - svg (export) + - xy: template based, multi-format footprint/coord list (export) Index: tags/2.1.2/doc/developer/packaging/lib64.txt =================================================================== --- tags/2.1.2/doc/developer/packaging/lib64.txt (nonexistent) +++ tags/2.1.2/doc/developer/packaging/lib64.txt (revision 24813) @@ -0,0 +1,23 @@ +Why pcb-rnd plusings are in /usr/lib/ and not /usr/lib64/ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +On a 64 bit system where both 32 bit and 64 bit software needs to be run +a separate set of 32 and 64 bit libraries are kept for two reasons: + +1. You may want to install both the 32 and the 64 bit version of the +same lib (e.g. libc) without interference. + +2. You want the dynamic linker to find the right one for your app; so +when linking a 32 bit app, you want to look only for 32 bit libs and +when linking a 64 bit app, you want to look only for 64 bit libs. +Linking means the dynamic linker's automatic run when a dynamic linked +executable is started up. + +What we do in our plugin dir is neither of those. We never want to have +both 32 and 64 bit pcb-rnds live side by side on a 64 bit system. And +these .so files are never read by the dynamic linker on executable +startup. The only one way they are loaded is by explicit path, using +dlopen, from within pcb-rnd. Because they are plugins, not general +purpose shared libs. So it is safe to put them in a common lib/, we do +not need to install them in different libdirs per system. + Index: tags/2.1.2/doc/developer/packaging/packages.html =================================================================== --- tags/2.1.2/doc/developer/packaging/packages.html (nonexistent) +++ tags/2.1.2/doc/developer/packaging/packages.html (revision 24813) @@ -0,0 +1,152 @@ + + + + +

Package summary and dependencies

+ +
package depends on (packages) consists of (plugins) +
pcb-rnd-debug pcb-rnd-core diag +
pcb-rnd-export pcb-rnd-core cam export_bom export_dxf export_gcode export_gerber export_openscad export_png export_ps export_stat export_svg export_xy +
pcb-rnd-doc  +
pcb-rnd-export-sim pcb-rnd-core export_openems +
pcb-rnd-lib-gl pcb-rnd-core lib_hid_gl +
pcb-rnd-import-geo pcb-rnd-core import_hpgl import_ttf +
pcb-rnd-hid-gtk2-gl pcb-rnd-core pcb-rnd-lib-gtk pcb-rnd-lib-gl hid_gtk2_gl +
pcb-rnd-import-net pcb-rnd-core pcb-rnd-lib-io import_calay import_edif import_fpcb_nl import_ipcd356 import_ltspice import_mentor_sch import_netlist import_sch import_tinycad +
pcb-rndpcb-rnd-core pcb-rnd-io-standard pcb-rnd-io-alien pcb-rnd-hid-gtk2-gl pcb-rnd-hid-gtk2-gdk pcb-rnd-export pcb-rnd-export-sim pcb-rnd-export-extra pcb-rnd-auto pcb-rnd-extra pcb-rnd-cloud pcb-rnd-doc<metapackage> +
pcb-rnd-auto pcb-rnd-core pcb-rnd-lib-io ar_cpcb asm autoplace autoroute export_dsn import_dsn import_mucs smartdisperse +
pcb-rnd-lib-io pcb-rnd-core lib_gensexpr lib_netmap +
pcb-rnd-io-standard pcb-rnd-core pcb-rnd-lib-io io_pcb io_tedax +
pcb-rnd-lib-gui pcb-rnd-core dialogs draw_fontsel lib_hid_common +
pcb-rnd-core act_draw autocrop ddraft draw_csect draw_fab drc_orig extedit fp_board fp_fs hid_batch io_lihata lib_compat_help lib_polyhelp mincut propedit query report rubberband_orig script shape +
pcb-rnd-lib-gtk pcb-rnd-core pcb-rnd-lib-gui lib_gtk_common lib_gtk_hid +
pcb-rnd-hid-lesstif pcb-rnd-core pcb-rnd-lib-gui hid_lesstif +
pcb-rnd-io-alien pcb-rnd-core pcb-rnd-lib-io io_autotrax io_dsn io_eagle io_hyp io_kicad io_kicad_legacy +
pcb-rnd-cloud pcb-rnd-core fp_wget +
pcb-rnd-export-extra pcb-rnd-core pcb-rnd-export export_fidocadj export_ipcd356 export_lpr export_oldconn +
pcb-rnd-hid-gtk2-gdk pcb-rnd-core pcb-rnd-lib-gtk hid_gtk2_gdk +
pcb-rnd-extra pcb-rnd-core distalign distaligntext djopt fontmode jostle polycombine polystitch puller renumber shand_cmd teardrops vendordrill +
+

Package description and files

+ +
package files short long +
pcb-rnd-debug $P/diag.pup $P/diag.so Debug and diagnostics. Extra action commands to help debugging and diagnostize problems and bugs. +
pcb-rnd-export $P/cam.pup $P/cam.so $P/export_bom.pup $P/export_bom.so $P/export_dxf.pup $P/export_dxf.so $P/export_gcode.pup $P/export_gcode.so $P/export_gerber.pup $P/export_gerber.so $P/export_openscad.pup $P/export_openscad.so $P/export_png.pup $P/export_png.so $P/export_ps.pup $P/export_ps.so $P/export_stat.pup $P/export_stat.so $P/export_svg.pup $P/export_svg.so $P/export_xy.pup $P/export_xy.so $C/cam.conf $C/export_xy.conf Common export plugins. Export the board in vector graphics (svg, ps, eps), raster graphics (png, jpeg, etc.), gerber, 3d model in openscad, xy for pick and place, BoM, etc. +
pcb-rnd-doc/usr/share/doc/* Documentation for pcb-rnd User manual (html) and manual pages. +
pcb-rnd-export-sim $P/export_openems.pup $P/export_openems.so Export plugins to simulators Export the board in formats that can be used for simulation: openems. +
pcb-rnd-lib-gl $P/lib_hid_gl.pup $P/lib_hid_gl.so Support library for rendering with opengl. +
pcb-rnd-import-geo $P/import_hpgl.pup $P/import_hpgl.so $P/import_ttf.pup $P/import_ttf.so Geometry import plugins. Import geometry from HPGL plots. HPGL can be produced (plotted) with most mechanical cads. +
pcb-rnd-hid-gtk2-gl $P/hid_gtk2_gl.pup $P/hid_gtk2_gl.so GUI: gtk2, opengl Hardware accelerated (opengl) rendering on gtk2. +
pcb-rnd-import-net $P/import_calay.pup $P/import_calay.so $P/import_edif.pup $P/import_edif.so $P/import_fpcb_nl.pup $P/import_fpcb_nl.so $P/import_ipcd356.pup $P/import_ipcd356.so $P/import_ltspice.pup $P/import_ltspice.so $P/import_mentor_sch.pup $P/import_mentor_sch.so $P/import_netlist.pup $P/import_netlist.so $P/import_sch.pup $P/import_sch.so $P/import_tinycad.pup $P/import_tinycad.so Netlist/schematics import plugins. Import netlist and footprint information from edif, ltspice, mentor graphics, gschem and tinycad. +
pcb-rnd Standard installation of pcb-rnd Install pcb-rnd core and the most commonly used plugins. +
pcb-rnd-auto $P/ar_cpcb.pup $P/ar_cpcb.so $P/asm.pup $P/asm.so $P/autoplace.pup $P/autoplace.so $P/autoroute.pup $P/autoroute.so $P/export_dsn.pup $P/export_dsn.so $P/import_dsn.pup $P/import_dsn.so $P/import_mucs.pup $P/import_mucs.so $P/smartdisperse.pup $P/smartdisperse.so $C/asm.conf Autoroute and autoplace. Feature plugins for automated component placing and track routing +
pcb-rnd-lib-io $P/lib_gensexpr.pup $P/lib_gensexpr.so $P/lib_netmap.pup $P/lib_netmap.so Support library for alien file formats.  +
pcb-rnd-io-standard $P/io_pcb.pup $P/io_pcb.so $P/io_tedax.pup $P/io_tedax.so Commonly used non-native board and footprint file formats Plugins for tEDAx footprint format and the gEDA/PCB file formats (footprint and board). +
pcb-rnd-lib-gui $P/dialogs.pup $P/dialogs.so $P/draw_fontsel.pup $P/draw_fontsel.so $P/lib_hid_common.pup $P/lib_hid_common.so $C/dialogs.conf Support library for building the GUI. +
pcb-rnd-core $P/act_draw.pup $P/act_draw.so $P/autocrop.pup $P/autocrop.so $P/ddraft.pup $P/ddraft.so $P/draw_csect.pup $P/draw_csect.so $P/draw_fab.pup $P/draw_fab.so $P/drc_orig.pup $P/drc_orig.so $P/extedit.pup $P/extedit.so $P/fp_board.pup $P/fp_board.so $P/fp_fs.pup $P/fp_fs.so $P/hid_batch.pup $P/hid_batch.so $P/io_lihata.pup $P/io_lihata.so $P/lib_compat_help.pup $P/lib_compat_help.so $P/lib_polyhelp.pup $P/lib_polyhelp.so $P/mincut.pup $P/mincut.so $P/propedit.pup $P/propedit.so $P/query.pup $P/query.so $P/report.pup $P/report.so $P/rubberband_orig.pup $P/rubberband_orig.so $P/script.pup $P/script.so $P/shape.pup $P/shape.so pcb-rnd executable with the core functionality Includes the data model, the most common action commands, the native file format and the CLI (batch HID). Does not contain GUI. Can be used in headless mode or batch/scripted mode for automated processing. +
pcb-rnd-lib-gtk $P/lib_gtk_common.pup $P/lib_gtk_common.so $P/lib_gtk_hid.pup $P/lib_gtk_hid.so Support library for building the GUI with gtk. +
pcb-rnd-hid-lesstif $P/hid_lesstif.pup $P/hid_lesstif.so GUI: motif/lesstif, software render Lightweight GUI and software rendering using the motif (lesstif) toolkit. +
pcb-rnd-io-alien $P/io_autotrax.pup $P/io_autotrax.so $P/io_dsn.pup $P/io_dsn.so $P/io_eagle.pup $P/io_eagle.so $P/io_hyp.pup $P/io_hyp.so $P/io_kicad.pup $P/io_kicad.so $P/io_kicad_legacy.pup $P/io_kicad_legacy.so File format compatibility with other PCB layout designers. Load and/or save boards in file formats supported by other EDA tools, such as KiCAD, Eagle, protel/autotrax, etc. +
pcb-rnd-cloud $P/fp_wget.pup $P/fp_wget.so $C/fp_wget.conf Networking plugins. 'Cloud' footprint access plugin that integrates edakrill and gedasymbols.org. +
pcb-rnd-export-extra $P/export_fidocadj.pup $P/export_fidocadj.so $P/export_ipcd356.pup $P/export_ipcd356.so $P/export_lpr.pup $P/export_lpr.so $P/export_oldconn.pup $P/export_oldconn.so Export formats: special/extra Less commonly used export formats: fidocadj, ipc-356-d, direct printing with lpr. +
pcb-rnd-hid-gtk2-gdk $P/hid_gtk2_gdk.pup $P/hid_gtk2_gdk.so GUI: gtk2, software render Software rendering on gtk2, using the gdk API. +
pcb-rnd-extra $P/distalign.pup $P/distalign.so $P/distaligntext.pup $P/distaligntext.so $P/djopt.pup $P/djopt.so $P/fontmode.pup $P/fontmode.so $P/jostle.pup $P/jostle.so $P/polycombine.pup $P/polycombine.so $P/polystitch.pup $P/polystitch.so $P/puller.pup $P/puller.so $P/renumber.pup $P/renumber.so $P/shand_cmd.pup $P/shand_cmd.so $P/teardrops.pup $P/teardrops.so $P/vendordrill.pup $P/vendordrill.so Extra action commands and optional functionality. Align objects in grid, optimize tracks, font editor, combine polygons, renumber subcircuits, apply vendor drill mapping. +
+

File prefixes:

    +
  • $P: plugin install dir (e.g. /usr/lib/pcb-rnd/) +
  • $C: conf dir (e.g. /usr/share/pcb-rnd/) +
+

./configure arguments

+--all=disable +--buildin-script +--buildin-fp_fs +--buildin-draw_fab +--buildin-mincut +--buildin-report +--buildin-rubberband_orig +--buildin-fp_board +--buildin-propedit +--buildin-io_lihata +--buildin-autocrop +--buildin-lib_polyhelp +--buildin-draw_csect +--buildin-ddraft +--buildin-hid_batch +--buildin-act_draw +--buildin-query +--buildin-lib_compat_help +--buildin-drc_orig +--buildin-shape +--buildin-extedit +--plugin-export_fidocadj +--plugin-export_lpr +--plugin-export_oldconn +--plugin-export_stat +--plugin-io_kicad_legacy +--plugin-io_eagle +--plugin-io_tedax +--plugin-io_kicad +--plugin-import_mucs +--plugin-renumber +--plugin-import_calay +--plugin-smartdisperse +--plugin-draw_fontsel +--plugin-polycombine +--plugin-export_gcode +--plugin-export_bom +--plugin-ar_cpcb +--plugin-import_sch +--plugin-teardrops +--plugin-shand_cmd +--plugin-import_tinycad +--plugin-export_openems +--plugin-import_ltspice +--plugin-export_dxf +--plugin-lib_gtk_common +--plugin-export_ipcd356 +--plugin-import_ttf +--plugin-import_mentor_sch +--plugin-import_dsn +--plugin-export_ps +--plugin-hid_gtk2_gdk +--plugin-djopt +--plugin-hid_gtk2_gl +--plugin-import_edif +--plugin-hid_lesstif +--plugin-lib_gtk_hid +--plugin-lib_gensexpr +--plugin-diag +--plugin-lib_hid_gl +--plugin-autoplace +--plugin-export_svg +--plugin-fp_wget +--plugin-fontmode +--plugin-import_netlist +--plugin-polystitch +--plugin-dialogs +--plugin-io_dsn +--plugin-export_xy +--plugin-export_png +--plugin-import_hpgl +--plugin-import_ipcd356 +--plugin-distaligntext +--plugin-export_dsn +--plugin-lib_netmap +--plugin-lib_hid_common +--plugin-io_hyp +--plugin-cam +--plugin-puller +--plugin-import_fpcb_nl +--plugin-io_pcb +--plugin-distalign +--plugin-asm +--plugin-export_openscad +--plugin-jostle +--plugin-autoroute +--plugin-io_autotrax +--plugin-vendordrill +--plugin-export_gerber + + + + Index: tags/2.1.2/doc/developer/packaging/packages.sh =================================================================== --- tags/2.1.2/doc/developer/packaging/packages.sh (nonexistent) +++ tags/2.1.2/doc/developer/packaging/packages.sh (revision 24813) @@ -0,0 +1,173 @@ +#!/bin/sh +proot=../../../src_plugins + +meta_deps="core io-standard io-alien hid-gtk2-gl hid-gtk2-gdk export export-sim export-extra auto extra cloud doc" + +(echo ' + + +' + +( +for n in $proot/*/*.pup +do + pkg=`basename $n` + sed "s/^/$pkg /" < $n +done + +for n in $proot/*/*.tmpasm +do + sed "s@^@$n @" < $n +done + +)| awk -v "meta_deps=$meta_deps" ' + BEGIN { + gsub(" ", " pcb-rnd-", meta_deps) + sub("^", "pcb-rnd-", meta_deps) + while((getline < "desc") == 1) { + if ($0 ~ "^@") { + pkg=$0 + sub("^@", "", pkg) + getline SHORT[pkg] < "desc" + continue + } + LONG[pkg] = LONG[pkg] $0 " " + } + } + + ($1 ~ "[.]pup$") { + pkg = $1; + sub("[.]pup$", "", pkg) + if (pkg == "(core)") pkg="core" + } + + ($1 ~ "[.]tmpasm$") { + pkg = $1; + sub("/Plug.tmpasm$", "", pkg) + sub(".*/", "", pkg) + if (pkg == "(core)") pkg="core" + } + + ($1 ~ "[.]pup$") { + val=$3 + if (val == "(core)") val="core" + cfg = pkg + val = "pcb-rnd-" val + } + + { + pkg = "pcb-rnd-" pkg + } + + ($1 ~ "[.]pup$") && ($2 == "$package") { + PKG[val] = PKG[val] " " cfg; + PLUGIN[pkg] = val; + IFILES[val] = IFILES[val] " $P/" cfg ".pup $P/" cfg ".so" + if (val == "pcb-rnd-core") CFG_BUILDIN[cfg]++ + else CFG_PLUGIN[cfg]++ + } + + ($1 ~ "[.]pup$") && ($2 == "dep") { PLUGIN_DEP[pkg] = PLUGIN_DEP[pkg] " " val } + + ($1 ~ "[.]tmpasm$") && ($3 == "/local/pcb/mod/CONFFILE") { + fn=$4 + sub("[{][ \t]*", "", fn) + sub("[ \t]*[}]", "", fn) + if (CONFFILE[PLUGIN[pkg]] == "") + CONFFILE[PLUGIN[pkg]] = "$C/" fn + else + CONFFILE[PLUGIN[pkg]] = CONFFILE[PLUGIN[pkg]] " $C/" fn + } + + function add_dep(pkg, depson, ds) + { + if (pkg != depson) { + ds = pkg "::" depson + if (!(ds in DEP_SEEN)) { + DEP_SEEN[ds] = 1 + PKG_DEP[pkg] = PKG_DEP[pkg] " " depson + } + } + } + + function strip(s) { + sub("^[ \t]*", "", s) + sub("[ \t]*$", "", s) + return s + } + + END { + + # everything depends on core + for(pkg in PKG) + add_dep(pkg, "pcb-rnd-core") + + # calculate dependencies + for(plg in PLUGIN_DEP) { + v = split(PLUGIN_DEP[plg], A, " ") + pkg = PLUGIN[plg] + if (pkg == "") continue + for(n = 1; n <= v; n++) { + if (A[n] == "") continue + depson = PLUGIN[A[n]] + if (depson == "") + depson = "!!!" A[n] + add_dep(pkg, depson) + } + } + + PKG_DEP["core"] = "" + PKG_DEP["doc"] = "" + PKG_DEP["pcb-rnd"] = meta_deps + PKG["pcb-rnd"] = "<metapackage>" + PKG["pcb-rnd-doc"] = " " + IFILES["pcb-rnd-doc"] = "/usr/share/doc/*" + + print "

Package summary and dependencies

" + print "" + print "
package depends on (packages) consists of (plugins)" + + for(pkg in PKG) { + print "
" pkg "" PKG_DEP[pkg] "" PKG[pkg] + print strip(PKG_DEP[pkg]) > "auto/" pkg ".deps" + print pkg > "auto/List" + } + print "
" + + print "

Package description and files

" + print "" + print "
package files short long" + for(pkg in PKG) { + if (SHORT[pkg] == "") SHORT[pkg] = " " + if (LONG[pkg] == "") LONG[pkg] = " " + print "
" pkg "" IFILES[pkg] " " CONFFILE[pkg] "" "" SHORT[pkg] "" LONG[pkg] + print strip(IFILES[pkg] " " CONFFILE[pkg]) > "auto/" pkg ".files" + print strip(SHORT[pkg]) > "auto/" pkg ".short" + print strip(LONG[pkg]) > "auto/" pkg ".long" + } + print "
" + print "

File prefixes:

    " + print "
  • $P: plugin install dir (e.g. /usr/lib/pcb-rnd/)" + print "
  • $C: conf dir (e.g. /usr/share/pcb-rnd/)" + print "
" + + print "

./configure arguments

" + print "--all=disable" + print "--all=disable" > "auto/Configure.args" + + for(p in CFG_BUILDIN) { + print "--buildin-" p + print "--buildin-" p > "auto/Configure.args" + } + for(p in CFG_PLUGIN) { + print "--plugin-" p + print "--plugin-" p > "auto/Configure.args" + } + } +' + +echo ' + + +') > packages.html + Property changes on: tags/2.1.2/doc/developer/packaging/packages.sh ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/2.1.2/doc/developer/packaging.txt =================================================================== --- tags/2.1.2/doc/developer/packaging.txt (nonexistent) +++ tags/2.1.2/doc/developer/packaging.txt (revision 24813) @@ -0,0 +1,95 @@ +Packaging pcb-rnd for a distribution +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +1. program, libs, desktop integration + +Pcb-rnd is an interactive printed circuit board editor program. A typical +user is an electric engineer. This sort of programs are often called EDA, +Electronics Design Automation. + +Pcb-rnd has different frontends: graphical and stdio/text based batch +processing. There are different graphical frontends - pcb-rnd does not +depend on gtk or motif, the specific frontend modules may depend on them. + +Pcb-rnd is scriptable if system installed libfungw is available. Since +libfungw is not a mainstream library, it is most probably not already +present in your distro and it should also be packaged too. + +Pcb-rnd is intended for UNIX-fans. It is heavily keyboard-oriented and it +doesn't assume its users don't want to understand or learn how it works. +Many typical user workflows include Makefiles and it's a common thing to +start pcb-rnd from a shell. Thus desktop integration is not in focus +at the moment. If you fixed things for this while packaging, please let +us know, we may merge your patches (see below). + +2. options, plugins, dependencies + +Pcb-rnd is a modular software with a lot of options. Majority of these options +are selected by the state of a module. A module has three states: + - disable: (not compiled at all) + - buildin: enabled and static linked + - plugin: enabled and dynamic loaded (from a .so) + +The configure script takes --disable-*, --building-* and --plugin-* +arguments with * substituted with the name of the module. The configure +script also determines the dependencies according to the selection. Special +arguments --all=plugin and --all=buildin are provided in configure to select +all working modules to be plugins or buildins. + +For binary distributions it's strongly recommended to have most of the +modules compiled as plugins and have them in separate packages. This +would let the user to install a core pcb-rnd package and then the GTK +or the lesstif plugin (or both) from separate packages. This also reduces +package dependencies. + +The preferred package splitup is documented in packaging/, +please follow that as closely as possible so different systems can +deliver similar pcb-rnd packages. + +This is less relevant for source distributions, if the user has full control +over the configuration. + +If non-critical dependencies are not met, modules are automatically disabled +by ./configure. + +3. typical ./configure options - scconfig vs. auto* + +./configure --prefix works as expected. DESTDIR works as expected. + +Typical commands for configuring pcb-rnd for packaging would be: + + ./configure --all=plugin --prefix=/usr + make all + DESTDIR=/tmp/pkg_tmp make install + +We are happy with scconfig. Please don't write about how much better +autoconf or cmake would be, we won't switch. + +4. release cycles, tarballs, svn trunk - what to package + +Development happens in svn trunk/, there are usually no branches. While +we try to keep trunk/ compilable any time, it's not guaranteed that it +would work out-of-the-box between releases. It is not recommended to +package trunk/ - please package stable releases instead. + +We follow the "release early, release often" rule. Source release tarballs +are always considered stable. Beside the project web page, releases are +also accessible as svn tags: svn://repo.hu/pcb-rnd/tags . + +Sometimes we have minor releases with 1..2 month period, sometimes a +longer period passes between releases. + +There's no automated release notification at the moment; if you want to +get notified about new releases, please contact me +(http://repo.hu/projects/pcb-rnd/contact.html) + +5. bug reporting and fixes for packaging + +There's no special method for reporting packaging related bugs and +feature requests, please follow the normal bug report instructions or just +drop me a mail. Please mention that the issue is related to packaging, this +usually gives it a higher priority. + +We are willing to make minor changes to make packaging easier - if you bump +into something you'd need to work around while packaging, please let us know, +we may just fix it "upstream". + Index: tags/2.1.2/doc/developer/plugin/actions.html =================================================================== --- tags/2.1.2/doc/developer/plugin/actions.html (nonexistent) +++ tags/2.1.2/doc/developer/plugin/actions.html (revision 24813) @@ -0,0 +1,105 @@ + + +

pcb-rnd - plugin development - creating actions

+

+Actions are fungw functions typically implemented in C or in a script language. +Actions are used by pcb-rnd to act upon any user request - there's always +an action behind any GUI, CLI or automated operation. pcb-rnd plugins are +written in C, thus they are registering actions written in C. + +

Includes and other requirements

+

+The plugin must #include "actions.h" to be able to register actions. +

+Registering actions require the standard plugin cookie. + +

action implementation

+

+The following example shows how an action is implemented: +

+static const char pcb_acts_ActionName[] = "ActionName(arg1, arg2, [arg3]...)";
+static const char pcb_acth_ActionName[] = "Help text: short description of what the action does.";
+static fgw_error_t pcb_act_ActionName(fgw_arg_t *res, int argc, fgw_arg_t *argv)
+{
+	/* process arguments */
+	/* implement the action */
+	/* return on no-error: */
+	PCB_ACT_IRES(0);
+	return 0;
+}
+
+

+More on how arguments are and return value are handled can be found in the +fungw action documentation. +

+Because of historical reasons action names are in CamelCase. This is the +only context where pcb-rnd tolerates CamelCase. +

+A plugin is free to register any amount of actions. Action names are globally +unique within pcb-rnd. For core plugins, the maintainer of the plugin is +responsible to avoid action name collision. For external plugins, the action +name must be prefixed with the plugin's name. + +

action table

+

+For convenience, actions are most often registered from data tables. The table +shall contain all actions provided by the plugin: +

+static const pcb_action_t pluginname_action_list[] = {
+	{"Action1", pcb_act_Action1, pcb_acth_Action1, pcb_acts_Action1},
+	{"Action2", pcb_act_Action2, pcb_acth_Action2, pcb_acts_Action2}
+};
+PCB_REGISTER_ACTIONS(pluginname_action_list, pluginname_cookie)
+
+

+The action name in the first column must be unique. If an action has +alternative names (e.g. shorthands), multiple lines may contain the +same pcb_act* fields with only the name differing. If multiple actions +are implemented in the same function (that e.g. looks at argv[0] to +decide which one was invoked), multiple lines may contain the same +pcb_act_ function, with different name and help/syntax text. +In the very unlikely case multiple action functions have the same +syntax or help, the same pcb_acth_ and/or pcb_acts_ can be used in multiple +rows of the table. +

+The table should be placed after the last action to avoid action +function/help/syntax forward declarations. Most often the table is placed +right above the check_ver callback. +

+The PCB_REGISTER_ACTIONS() macro invocation is right after the table; it +requires the standard plugin cookie. + +

action registration on init

+

+Place #include "dolists.h" right above the plugins standard init +callback function. This include will change some global states so +that PCB_REGISTER_ACTIONS will work differently, so its place is significant. +

+Invoke macro +PCB_REGISTER_ACTIONS(pluginname_action_list, pluginname_cookie) +again, from the init callback. +

+In practice, the plugin init will look like this: +

+#include "dolists.h"
+
+int pplg_init_expfeat(void)
+{
+	PCB_API_CHK_VER;
+	PCB_REGISTER_ACTIONS(pluginname_action_list, pluginname_cookie)
+	return 0;
+}
+
+ +

action removal on uninit

+

+When the plugin is uninitialized, all actions must be removed (to avoid +dangling function pointers after a dynamic plugin unload). This is normally +done by calling +

+	pcb_remove_actions_by_cookie(pluginname_cookie);
+
+from the plugin's uninit callback. + + + Index: tags/2.1.2/doc/developer/plugin/api.html =================================================================== --- tags/2.1.2/doc/developer/plugin/api.html (nonexistent) +++ tags/2.1.2/doc/developer/plugin/api.html (revision 24813) @@ -0,0 +1,101 @@ + + +

pcb-rnd - plugin development - API and initialization

+

+Since plugins are managed by puplug, the minimal API a plugin must +provide is as defined by the +puplug project. This +document describes that API with any pcb-rnd aspects included. +

+A minimalistic example of a plugin's main source file implementation +can be found in the plugin template. + +

copyright banner

+

+For core plugins the copyright banner is standard and shall not be +changed (except for the year and name in the copyright line). All +manually written .c files and any non-trivial .h file must have the +banner. License: core plugins must be GPL2+. +

+External plugins can choose a different license banner, but since +pcb-rnd is licensed under the GPL, they shall choose a license that is +compatible with the GPL for run-time dynamic linking. + +

headers and watchdogs

+

+If the plugin consists of multiple source files compiled as separate +compilation units (multiple .o files), there will be header (.h) files. +The header watchdog #defines shall be PCB_PLUGINNAME_H, unless +PLUGINNAME is short and generic and/or conflicts with already +existing core or core plugin watchdogs. In that case use +PCB_CPLUG_PLUGINNAME_H +

+For external plugins, always use PCB_EPLUG_PLUGINNAME_H. + +

#includes

+

+The first include in any .c file must be "config.h", to ensure +configuration time detected libc feature macros are. The .h files +shall not include "config.h". +

+The plugin shall #include pcb-rnd core's "plugins.h" for the mandatory +PCB_API_CHK_VER call. This also requires <stdio.h>. + +

int pplg_check_ver_pluginname(int ver_needed)

+

+This function is called by puplug before the plugin is initialized. The +code that triggered the load may have specified a required API version +number in ver_needed and the plugin needs to decide if it can serve +all functionality of that version - if so, it should return 0 and +initializing the plugin will proceed. How the version number is interpreted +is up to the plugin: can be a serially incremented number, a bitfield, a +date encoded. +

+Most pcb-rnd plugins will not need this and can safely return 0 without +even checking ver_needed. For pcb-rnd plugins the only situation when +using this API makes sense is for external (non-core) lib plugins that +other external plugins are likely to depend on. + + +

void pplg_uninit_pluginname(void)

+

+Called before unloading the plugin. This often happens before quitting pcb-rnd, +even for builtin (static linked) plugins, but for a dynamically loaded +plugin it can happen any time while pcb-rnd is running. +

+The plugin needs to free all memory allocated and unregister from all central +pcb-rnd infrastructure. The plugin must assume pcb-rnd will not exit +after plugin uninitialization. +

+The rule of thumb is: anything registered in the init() callback must have +an unregister call in this uninit() callback. + +

int pplg_init_pluginname(void)

+

+Called after the plugin is loaded and version is checked, +before any other plugin function or variable is accessed. +

+The plugin should set up its own infrastructure and register actions, callbacks, +hooks, tools, etc. in central infrastructure. +

+Each plugin is loaded and initialized only once at a time (there are no +multiple parallel instances of the same plugin), but it is possible to +load-unload the same plugin multiple times during a single pcb-rnd session. +

+Before the init does anything else, it must issue a PCB_API_CHK_VER. This macro +checks for ABI compatibility between the plugin and the core and returns +failure on incompatibility (useful in the dynamic plugin load setup). +

+The init call shall return 0 on success and anything else on failure. After +a failure, the plugin is unloaded - without a call to uninit. Thus on failure +the init function needs to clean up any effect of partial initialization +or registration before returning. + +

conventions

+

+These functions are implemented in the main c file of the plugin, which is +called pluginname.c. These functions are normally the last ones on +the bottom of the file. They are never exposed in header files. + + + Index: tags/2.1.2/doc/developer/plugin/conf.h =================================================================== --- tags/2.1.2/doc/developer/plugin/conf.h (nonexistent) +++ tags/2.1.2/doc/developer/plugin/conf.h (revision 24813) @@ -0,0 +1,17 @@ +!!! replace FOOBAR and foobar with your plugin name !!! + +#ifndef PCB_FOOBAR_CONF_H +#define PCB_FOOBAR_CONF_H + +#include "conf.h" + +typedef struct { + const struct plugins { + const struct foobar { + CFT_BOOLEAN enable; /* Enable the plugin */ + CFT_INTEGER snow; /* intensity of snowing, 0..100 */ + } foobar; + } plugins; +} conf_foobar_t; + +#endif Index: tags/2.1.2/doc/developer/plugin/conf.html =================================================================== --- tags/2.1.2/doc/developer/plugin/conf.html (nonexistent) +++ tags/2.1.2/doc/developer/plugin/conf.html (revision 24813) @@ -0,0 +1,84 @@ + + +

pcb-rnd - plugin development - per plugin config subtree

+

+Each plugin can maintain its own configuration subtree within the central +conf tree. For this, the plugin needs to create the subtree under its own +name under the plugins/. From then on, the config values are loaded and +handled by the central system and are accessible through a global +struct variable declared within the plugin. + +

the config header

+

+The source of all information on what nodes consists the plugin's own +subtree is the file pluginname_conf.h in the plugin dir. It can +be created by copying and renaming this template. +

+The structure must reproduce the plugin sub-struct and the pluginname +sub-struct nested in it, in order to keep the C struct field reference path +the same as the textual conf path. +

+Create an empty file called pluginname_conf_fields.h for placeholder. +Do not add it to the svn repo. + +

tmpasm

+

+The conf file must be registered in the tmpasm file. Add these lines in +Plug.tmpasm to set the file name: +

+put /local/pcb/mod/CONFFILE {pluginname.conf}
+put /local/pcb/mod/CONF {$(PLUGDIR)/pluginname/pluginname_conf.h}
+
+ +

Create the conf variable

+

+The conf access variable should be a global variable in the main plugin c file: +

+#include "pluginname_conf.h"
+
+const conf_pluginname_t conf_pluginname;
+
+

+From now on, the example fields can be accessed like: +

+conf_pluginname.plugins.pluginname.snow
+
+

+Note: these variables are strictly read-only. Use conf_set*() from src/conf.h +to change the value. + + +

plugin init

+

+Copy these lines in the plugin init callback: +

+#define conf_reg(field,isarray,type_name,cpath,cname,desc,flags) \
+	conf_reg_field(conf_pluginname, field,isarray,type_name,cpath,cname,desc,flags);
+#include "pluginname_conf_fields.h"
+
+ +

plugin uninit

+

+On uninit all local config nodes need to be removed from the config system. +This is easy, since all our nodes are under a single subtree. Copy this line +in the plugin uninit callback: +

+	conf_unreg_fields("plugins/pluginname/");
+
+ +

make dep

+

+After committing all these, you will need to run make dep in src/. Before committing +that, double check svn diff: it must not have any unrelated change, only files +related to your plugin. +

+When done, the build system knows how to generate pluginname_conf_fields.h - +remove the dummy empty file and run make to get it generated. + +

default values

+

+For setting default values, a local +default config file needs to be set up. + + + Index: tags/2.1.2/doc/developer/plugin/conf_chg.html =================================================================== --- tags/2.1.2/doc/developer/plugin/conf_chg.html (nonexistent) +++ tags/2.1.2/doc/developer/plugin/conf_chg.html (revision 24813) @@ -0,0 +1,83 @@ + + +

pcb-rnd - plugin development - config change notification

+

+All settings are stored in one central conf tree. +Any part of the code can register function callbacks that are activated when +a specific (or any) conf node changes. +

+Multiple callback functions can be bound to the same config node and +the same callback function can be bound to multiple config nodes. It is +also possible to bind the callback function to global change, which +means it would be called on any config change. +

+Config change notification is also called 'watch'. + +

how to declare a callback function

+
+void bar_confchg(conf_native_t *cfg, int arr_idx)
+{
+}
+
+ +

local: how to bind the callback function to a node

+

+This typically happens in the plugin init callback: +

+	conf_native_t *cn;
+	conf_hid_id_t confid;
+	static const conf_hid_callbacks_t foo_cbs = { NULL, bar_confchg, NULL, NULL };
+
+	confid = conf_hid_reg(pluginname_cookie, NULL);
+
+	cn = conf_get_field("editor/all_direction_lines");
+	if (cn != NULL)
+		conf_hid_set_cb(cn, confid, &foo_cbs);
+	else
+		/* handle the error */
+
+

+The callbacks struct needs to be static because it is not copied, but the pointer +is stored after registration. The fields of this structure are callback function +pointers for different event types, e.g. "call before the change", "call after +the change" or "call when a new item is created in the conf database"; refer +to src/conf_hid.h for more info. +

+For registering config watches, a confid needs to be registered using conf_hid_reg(). +The registration is done by the plugins standard cookie. +The second argument to this call is for global conf change watches (see below). +

+The next step is to resolve the conf node's conf_native_t pointer, using +conf_get_field(), which takes the plain text config node path as argument. +

+If that worked, conf_hid_set_cb() binds the callback structure to the +config node. There can be only one such binding per conf node per confid, +but the plugin may request multiple confid's with different cookies. + +

global: how to bind the callback function to any change

+

+Sometimes a plugin needs to run on any conf change or needs to react on +new conf nodes being created. For these, use the global callback +argument of conf_hid_reg(): load it with a pointer to a static +conf_hid_callbacks_t struct. +

+Do not do this if you are watching a finite set of conf nodes with +known names - just do a per conf node local binding, even if it means +10 bindings. + +

how to unbind the callback function to a node

+

+When the watch is no longer needed, conf_hid_unreg(), +typically from the uninit callback of the plugin. This will unregister +all watches (local and global) and confid. If only one watch need to be +removed, conf_hid_set_cb() should be called with a callback struct that +has NULL for the given function pointer. (Note: this doesn't replace the +function pointer, but the callback struct pointer in the central registry). +

+For example, place this line in the plugin uninit callback: +

+	conf_hid_unreg(pluginname_cookie);
+
+ + + Index: tags/2.1.2/doc/developer/plugin/conf_file.conf =================================================================== --- tags/2.1.2/doc/developer/plugin/conf_file.conf (nonexistent) +++ tags/2.1.2/doc/developer/plugin/conf_file.conf (revision 24813) @@ -0,0 +1,10 @@ +li:pcb-rnd-conf-v1 { + ha:append { + ha:plugins { + ha:pluginname { + enabled=1 + snow=42 + } + } + } +} Index: tags/2.1.2/doc/developer/plugin/conf_file.html =================================================================== --- tags/2.1.2/doc/developer/plugin/conf_file.html (nonexistent) +++ tags/2.1.2/doc/developer/plugin/conf_file.html (revision 24813) @@ -0,0 +1,64 @@ + + +

pcb-rnd - plugin development - local default conf file

+

+Each plugin can have a config file, pluginname.conf, stored +locally and also installed. When this file is available, it specifies +the default value for the plugin-local config nodes. +It also allows users to create user config under ~/.pcb-rnd/ using the +same file name, modularizing the config. + +

create the config file

+

+Copy the template and rename it to +pluginname.conf, replace pluginname and the config nodes +to match the plugin's conf.h. +

+Create an empty file called conf_internal.c (but do not commit it). + +

include the internal version of the config file

+

+Insert the following lines in the main plugin c source: +

+#include "../src_plugins/pluginname/conf_internal.c"
+
+ +

Register the custom conf file

+

+Define the file name (will be used twice) somewhere around the top of +the main source file, then in plugin init callback issue a conf_reg_file(): +

+#define PLUGINNAME_CONF_FN "pluginname.conf"
+
+int pplg_init_pluginname(void)
+{
+	PCB_API_CHK_VER;
+	conf_reg_file(PLUGINNAME_CONF_FN, pluginname_conf_internal);
+	...
+
+

+The conf_reg_file() call should be before the conf fields initialization. + + + +

Unregister the custom conf file

+

+In the uninit callback of the plugin, insert the following line: +

+	conf_unreg_file(PLUGINNAME_CONF_FN, pluginname_conf_internal);
+
+ +

make dep

+

+After finishing all these, before the commit, you will need to run make +dep in src/. Before committing that, double check svn diff: it must not +have any unrelated change, only files related to your plugin. +

+When done, the build system knows how to generate conf_internal.c - +remove the dummy empty file and run make to get it generated. +

+The file will contain one large character array, holding the internal +version of pluginname.conf + + + Index: tags/2.1.2/doc/developer/plugin/cookie.html =================================================================== --- tags/2.1.2/doc/developer/plugin/cookie.html (nonexistent) +++ tags/2.1.2/doc/developer/plugin/cookie.html (revision 24813) @@ -0,0 +1,37 @@ + + +

pcb-rnd - plugin development - plugin cookie

+

+Many of the pcb-rnd infrastructure API requires a cookie for +registering new objects. This cookie is typically a const char *, which +is used only in pointer comparison. It is also useful for debugging: +when objects are not unregistered properly, the code can print the value +(string) of the cookie in the error message, which can be a hint on the +source of the registration. +

+The cookie should be a static const char string, normally on top +of the main c file of the plugin: +

+static const char *pluginname_cookie = "pluginname + a 2..3 word description";
+
+ +

multiple cookies

+

+The plugin may use multiple cookies, e.g. different cookie for registering +different set of objects, if that potentially helps debugging. This is especially +useful if the plugin is consists of largely independent subsystems - each +subsystem can have its own cookie. + +

multiple source files vs. cookies

+

+If the plugin contains multiple compilation units (object files), these files +may need to use the same cookie. In that case pluginname_cookie +should not be static and shall be exposed in a plugin header file using +extern. +

+Since cookies are used by pointer, it is important not to copy the +string into multiple objects - those copies will not match. This can happen +accidentally on some systems if the header is missing extern. + + + Index: tags/2.1.2/doc/developer/plugin/core_simple.html =================================================================== --- tags/2.1.2/doc/developer/plugin/core_simple.html (nonexistent) +++ tags/2.1.2/doc/developer/plugin/core_simple.html (revision 24813) @@ -0,0 +1,30 @@ + + +

pcb-rnd hacking - simple core plugins

+ +

Introduction

+ +

Setting up a new core plugin

+
    +
  • 1. make up a name for the plugin. There are a few conventions. This document will refer to the name as plg, always replace it with your chosen name. +
  • 2. cd src_plugins; svn mkdir plg +
  • 3. copy all files from the plugin template +
  • 4. edit Makefile: replace "foobar" to plg +
  • 5. edit plg.pup; there should be short summary about the purpose of the plugin then "#key: value" pairs for statistics. Please refer to the pup syntax +
  • 6. edit Plug.tmpasm: replace "foobar" with plg, list all local objects you plan to have +
  • 7. rename and edit foobar.c: replace "foobar" with plg +
  • 8. create your C sources and headers in src_plugins/plg/ +
  • 9. run "make map_plugins" in src/ to get your new plugin on the plugin list +
  • 10. run ./configure --buildin-plg +
  • 11. run make to see if it compiles and test +
  • (12. while developing, you can run make from src_plugins/plg - if + your plugin is a builtin, it will recompile pcb-rnd. For some of us it's convenient + to run make in the same directory where all the source files are.) +
+ +Congratulations, you now have a compilable core plugin that does not do +anything yet, with the basic API skeleton in place. + + + + Index: tags/2.1.2/doc/developer/plugin/events.html =================================================================== --- tags/2.1.2/doc/developer/plugin/events.html (nonexistent) +++ tags/2.1.2/doc/developer/plugin/events.html (revision 24813) @@ -0,0 +1,58 @@ + + +

pcb-rnd - plugin development - binding to events

+

+The pcb-rnd event system is a very simple callback system: a list +of function pointers registered by different parts of the code (e.g. plugins), +to be called back on certain events. Different events have different number +and type of arguments, which are passed as an argc/argv pair. An event may +be bound to any number of functions. +

+Upon the occurrence of the event, all event handler functions bound to it +are called, in no particular order. +

+An event handler function can be bound to one or more events, and it can +be bound and unbound runtime. +

+For more details, please read the API in src/event.h. + +

Creating the event handler

+

+Create an event handler function of type pcb_event_handler_t. +

+static void ev_my_event_handler_name(void *user_data, int argc, pcb_event_arg_t argv[])
+{
+
+}
+
+ +

Binding the event

+

+Call pcb_event_bind(), typically in the init callback of the plugin: +

+	pcb_event_bind(PCB_EVENT_BOARD_CHANGED, ev_my_event_handler_name, NULL, pluginname_cookie);
+
+

+The registration requires a standard plugin cookie. +

+The 3rd argument is an arbitrary user data pointer that will get passed to +each call of the event handler. It can be used to communicate between the +code that registers the event and the event handler code. The event system +only stores and passes it on, never dereferences, allocates or frees it. +Should be NULL if not used. + +

Unbinding events

+

+Events are normally unbound in the plugin's uninit callback, using +pcb_event_unbind_cookie(), which unregisters all events registered +with the same cookie. The typical call is: +

+	pcb_event_unbind_allcookie(pluginname_cookie);
+
+

+Events can be unbound one by one, on an event_id/callback_function basis, +using pcb_event_unbind(). This is useful if an event needs to be installed +and uninstalled temporarily. + + + Index: tags/2.1.2/doc/developer/plugin/ext_dont.html =================================================================== --- tags/2.1.2/doc/developer/plugin/ext_dont.html (nonexistent) +++ tags/2.1.2/doc/developer/plugin/ext_dont.html (revision 24813) @@ -0,0 +1,73 @@ + + +

pcb-rnd - plugin development - why not to create external plugins

+

+Short answer: join us and create a core plugin instead. Or write a script in +one of the many scripting languages pcb-rnd supports. +

+Pcb-rnd has a fast paced, centralized development strategy, heavily building +on coordinated team work. There is no "API stability": we do not promise +that core APIs wouldn't change. But we do guarantee that any change to the +core will be immediately tracked in all core plugins. +

+The core team, by definition, will not consider or upgrade any +external plugin while changing core APIs. Scripts are much less affected +as they are using actions only and we try not to break action backward +compatibility. +

+Because of the high amount of development time goes into pcb-rnd these days, +if you start maintaining your own external plugin, you will need to spend +a portion of the time we spend on pcb-rnd on just keeping your plugin +from bit-rotting. Example in geda/PCB, with much slower core development, showed +that it does not pay back long term. There are usually four outcomes: +

    +
  • You manage to keep up with core changes - but then you spend (waste) a + lot of time on just keeping your project up-to-date. You also have to + sync your release cycles to pcb-rnd's: users will have to pick the + corresponding plugin version for each pcb-rnd release else the plugin + won't work. That work could better be spent on developing the plugin + if it was a core plugin. +
  • You support only one specific pcb-rnd version; this will get your plugin + unaccessible for most users as they will go on upgrading pcb-rnd. + Rationale: we probably spend more accumulated time on developing + pcb-rnd than you spend on developing your plugin, which means more + features and more bugfixes. Most users will sooner or later will choose + more activity over less. Also, users using pcb-rnd from packages + will be "forced" to upgrade by their distribution. So effectively + this leads to the 3rd possibility: +
  • You maintain a plugin that practically will not be usable for + anybody else. Which sometimes leads to the 4th possibility: +
  • Sometimes we import external plugins and start to maintain them as + core plugins. We had such a mass-import back in 2016, for bit-rotten + pcb plugins floating on the web. However, this could happen only with + abandoned plugins, as we are not going to keep merging forth and back. + Also, this method proven to be extremely inefficient: we already had + to rewrite 1/3 of the imported plugins, had to remove a few and + scheduled a full rewrite on another 1/3. This taught us that it's + often cheaper to write something from scratch than insisting on reuse. + We will especially refuse importing plugins that were started as external + plugin in order to overcome pcb-rnd conventions (e.g. svn or C89). So + if you can't accept our ways and can't join to do a core plugin, it + is not worth starting an external plugin effort and hope it will get + merged because there's high chance it will just bit-rot instead. +
+

+That said, there are some legitimate cases when you could consider maintaining +an external plugin. For example if the goal of the plugin is so extremely +far away from pcb-rnd's that we do not accept the idea at all. But +if you start maintaining your plugin, and do not want to end up spending a lot +of time just to have something bit-rotting, you should really consider how much +time keeping things up to date will require, before you start. +

+Please also note that beause we really prefer our team work model, and we +most likely consider an external plugin effort just waste of time, we will +probably not endorse or promote your plugin in any way. +

+Please do not write an external plugin (or core plugin) off-svn and +then contact us to ask for inclusion as a core plugin. The only way a core +plugin can happen is that you contact the project lead, agree on some details, +get an svn write access and do it in pcb-rnd's repo. We will refuse to import +plugins developed differently. + + + Index: tags/2.1.2/doc/developer/plugin/ext_fungw.html =================================================================== --- tags/2.1.2/doc/developer/plugin/ext_fungw.html (nonexistent) +++ tags/2.1.2/doc/developer/plugin/ext_fungw.html (revision 24813) @@ -0,0 +1,41 @@ + + +

pcb-rnd - plugin development - external fungw plugin

+

+First of all: you should write a core plugin, not +an external plugin. +

+If you absolutely can't avoid writing an external plugin, you have two choices: +a native puplug plugin or a fungw engine plugin. This page is about the fungw plugin +method. Pros: simpler code, less boilerplate. Cons: loaded like a script, +shouldn't access pcb-rnd APIs other than actions, +requires system installed (full featured) fungw. +

+Note: this method is equivalent to using a script language and writing +an user script - except that it's written in C, needs to be compiled, and +if crashes, will bring down the whole process with it. +

+Please refer to the example/template plugin. +After make, the resulting .so can be loaded from pcb-rnd using the script() +action: +

+LoadScript(foo, ./ext_bar.so, c)
+
+

+The stderr message from init should appear. The ExtBar action should be +available. +

+To start your external plugin, copy it to new directory and rename +ext_bar both in file names and file content. Please preserve the ext_ prefix. + +

how to develop the plugin

+

+Some naming conventions differ from core plugin development. It is not +possible to register action help and syntax at the moment. + +

Other considerations

+

+As documented for puplug plugins. + + + Index: tags/2.1.2/doc/developer/plugin/ext_pup.html =================================================================== --- tags/2.1.2/doc/developer/plugin/ext_pup.html (nonexistent) +++ tags/2.1.2/doc/developer/plugin/ext_pup.html (revision 24813) @@ -0,0 +1,69 @@ + + +

pcb-rnd - plugin development - external pupplug plugin + FAQ

+

+First of all: you should write a core plugin, not +an external plugin. +

+If you absolutely can't avoid writing an external plugin, you have two choices: +a native puplug plugin or a fungw engine plugin. This page is about the puplug plugin +method. Pro: have full access to all APIs. Con: more boilerplate code. +

+Please refer to the example/template plugin. +After make and make install, starting pcb-rnd should auto-load the plugin. +The stderr message from init should appear. The ExtFoo action should +be available. +

+To start your external plugin, copy it to new directory and rename +ext_foo both in file names and file content. Make sure to fill in the +fields in the pup file. Please preserve the ext_ prefix. + +

how to develop the plugin

+

+Other than some naming conventions and the #includes, which are +either "src/*.h" or you need an extra -I for src/, everything is +as documented for core plugins. + +

how to access pcb-rnd's CC, CFLAGS, LDFLAGS, etc.

+

+For that you need to use scconfig +to configure your external plugin. Once you do that, you can use the +--import=$(TRUNK)/scconfig/config.cache argument, which will get scconfig +to read everything cached during pcb-rnd's configuration. This will save +running some detections that are already done for pcb-rnd and will also +import the exact results of CC, CFLAGS, LDFLAGS, etc. +

+After that, you should get your hooks.c to generate a conf file you can +include from your Makefile. +

+Note: we generally do not support having external plugins, so please do +not make requests for pcb-rnd's Makefile.conf to contain whatever nodes +your external plugin may need. + +

How to use autotools, cmake, qmake, ...

+

+No idea, at pcb-rnd we don't use those - we don't provide support for those +tools. + +

Suddenly pcb-rnd core API changed and my external plugin broke!

+

+We told you so. Please consider restarting +your plugin from scratch as a core plugin. If you can't, you will have to +live with frequent API changes. pcb-rnd is not a lib, but an application, +we do not promote developing external plugins, so we don't feel obliged +to keep internal API backward compatibility. + +

The API changes too often. Can you stop doing that please?

+

+No. + +

The API changes too often. Could you please maintain my external plugin?

+

+No. + +

The API changes too often. Could you please include my external plugin as core plugin?

+

+No. + + + Index: tags/2.1.2/doc/developer/plugin/index.html =================================================================== --- tags/2.1.2/doc/developer/plugin/index.html (nonexistent) +++ tags/2.1.2/doc/developer/plugin/index.html (revision 24813) @@ -0,0 +1,35 @@ + + +

pcb-rnd - plugin development

+ +

basics

+ + +

advanced topics

+ + +

external plugins

+ + + + Index: tags/2.1.2/doc/developer/plugin/io.html =================================================================== --- tags/2.1.2/doc/developer/plugin/io.html (nonexistent) +++ tags/2.1.2/doc/developer/plugin/io.html (revision 24813) @@ -0,0 +1,82 @@ + + +

pcb-rnd - plugin development - registering I/O

+

+A plugin can serve as an I/O interface. Note the difference between plain +import/export and a full I/O - do not implement an I/O for a simple +import or export task but do not implement a pair of import/export +plugins for an I/O task either. +

+A plugin can register multiple I/O interfaces. This is typical for +formats with multiple versions, or for format families with alternative +sub-formats for the same purpose. But the most common setup is that an +io plugin registers one I/O interface. +

+Each I/O interface has a name and priorities. The name is displayed to +the user and priorities determine in what order different options are +presented - this helps ordering common file formats first, exotic options +last. +

+Each I/O interface also has hooks for testing whether it will be able +to load an input file, before doing the real parse. When a file needs to +be loaded, the plugins that will attempt to load are not selected by the +file name, but by file content. +

+For more details on the I/O interface fields, callback functions and +mechanism, refer to src/plug_io.h. + +

Registering an I/O interface

+

+Declare a static variable of pcb_plug_io_t and fill it in from the plugin +init callback: +

+static pcb_plug_io_t io_pluginname;
+
+...
+
+int pplg_init_io_pluginname(void)
+{
+	PCB_API_CHK_VER;
+
+	memset(&io_pluginname, 0, sizeof(io_pluginname));
+
+	/* these are mandatory: */
+	io_pluginname.default_fmt = "shortname";
+	io_pluginname.description = "longname";
+	io_pluginname.save_preference_prio = 89;
+	io_pluginname.default_extension = ".foo";
+	io_pluginname.fp_extension = ".bar";
+	io_pluginname.mime_type = "application/x-pcb-layout";
+	io_pluginname.fmt_support_prio = io_pluginname_fmt;
+	io_pluginname.test_parse = io_pluginname_test_parse;
+
+	/* these are optional (leave NULL if not supported): */
+	io_pluginname.plugin_data = &ctx;
+	io_pluginname.parse_pcb = io_pluginname_parse_pcb;
+	io_pluginname.parse_footprint = io_pluginname_parse_footprint;
+	io_pluginname.parse_font = io_pluginname_parse_font;
+	io_pluginname.write_buffer = io_pluginname_write_buffer;
+	io_pluginname.write_footprint = io_pluginname_write_footprint;
+	io_pluginname.write_pcb = io_pluginname_write_pcb;
+
+	/* the actual registration */
+	PCB_HOOK_REGISTER(pcb_plug_io_t, pcb_plug_io_chain, &io_pluginname);
+
+

+The memset is required in case the core struct is extended with new fields. +The convention is that NULL or 0 is the default/unused value. With the +memset extending the core struct won't force us to update all plugins. + + +

Unregistering an I/O interface

+

+On plugin uninit any I/O interface registered by the plugin must be +removed. This is done using the PCB_HOOK_UNREGISTER() macro: +

+	PCB_HOOK_UNREGISTER(pcb_plug_io_t, pcb_plug_io_chain, &io_pluginname);
+
+ + + + Index: tags/2.1.2/doc/developer/plugin/naming.html =================================================================== --- tags/2.1.2/doc/developer/plugin/naming.html (nonexistent) +++ tags/2.1.2/doc/developer/plugin/naming.html (revision 24813) @@ -0,0 +1,16 @@ + + +

pcb-rnd hacking - plugin naming conventions

+
    +
  • export_: export plugins start with export_; these render to a non-native format that can not be then loaded +
  • import_: import plugins start with import_; these perform partial data load from alien formats (typically: netlist/schematics) +
  • io_: full board save/load prefixed with io_; even if your plugin can now only load or save, if it's possible to do a load-save-load round-trip without data loss, it's an io_ +
  • hid_: interactive, often GUI, frontends are prefixed with hid_ +
  • fp_: footprint access plugins start with fp_ +
  • lib_ plugins are libraries used by other plugins; they are disabled by default and are enabled through the plugin dependency system +
  • act_ plugins are stateless wrappers to expose existing C functions (moslty core functionality) over the action API (for scripts and users) +
  • ar_ plugins are related to external autorouting: they are reponsible for calling the external process and coordinate the routing but sometimes also implement export/import pair for the format +
  • anything else is considered a feature plugin and has no specific prefix. +
+ + Index: tags/2.1.2/doc/developer/plugin/new_plugin.html =================================================================== --- tags/2.1.2/doc/developer/plugin/new_plugin.html (nonexistent) +++ tags/2.1.2/doc/developer/plugin/new_plugin.html (revision 24813) @@ -0,0 +1,38 @@ + + +

pcb-rnd - plugin development - when to create a new plugin

+

+The generic structure of the pcb-rnd source code is: +

    +
  • core (always linked into the pcb-rnd executable) +
  • core plugins (disabled, linked into the executable or installed as runtime dynamic loadable plugins) +
  • utilities (never linked to the pcb-rnd executable, as they are stand-alone programs) +
+

+Core is mainly providing startup and basic infrastructure, including basic +objects, basic operations on those objects, event and action systems, configuration +system, etc. Anything else, including any file format, GUI, and majority of the +user features are implemented in core plugins. Thus most of the code of +pcb-rnd are in the core plugins. +

+When a new feature is to be introduced, it should go into a plugin by +default. Adding it in core should be considered only if it's a basic, central +infrastructure multiple other plugins will depend on. +

+Whether the new feature should go in an existing core plugin or should get +a new core plugin depends on how far it is from existing plugin functionality. +We generally prefer to have more, smaller plugins instead of few large ones. +However we also prefer to avoid code duplications. +

+Before creating a new plugin or adding the feature in an existing plugin, +please consult the project leader. We are liberal and welcoming about new +plugins; however, any new plugin must meet a few requirements: +

    +
  • Programming language: C89. In a few special cases C99 (project leader permission required). Plugins can not be written in C11, C++, etc. +
  • External dependencies should be reasonable: reuse only when it pays off. Shall not depend on glib, apr and other large solves-everything megalib. +
  • Core plugins are in our central svn repository. It is not possible to maintain core plugins in git, hg, fossil, etc. Consult the project leader, you will get svn write access from day 0. +
  • If you start writing a plugin, we expect you to be able to allocate enough time to at least finish the initial version, but it's even better if you can maintain it afterward. If you implement the first 10% then lose interest and stop working on it, the code will eventually get removed from the project. +
+ + + Index: tags/2.1.2/doc/developer/plugin/pup.html =================================================================== --- tags/2.1.2/doc/developer/plugin/pup.html (nonexistent) +++ tags/2.1.2/doc/developer/plugin/pup.html (revision 24813) @@ -0,0 +1,38 @@ + + +

pcb-rnd hacking - plugin .pup fields

+

+The pup file holds all metadata for a plugin that is required for +./configure and for puplug to load the plugin run-time. Fields starting +with $ are pcb-rnd-specific fields, the rest are common puplug fields that +will behave the same in other puplug modularized projects as well. +

+Each field is a single-line and can not contain semicolon (';'). +

+The fields in use for pcb-rnd plugins: +

+

    +
  • $class the same as the plugin name prefix (see conventions. ) or (feature) for feature plugins; it's redundant but is kept for supporting external plugins - see mods3 for a short list of all classes +
  • $short short description - should be less than 32 characters; this shows up in the configure summary +
  • $long long description - used for documentation; no length limitation, but must be a single line +
  • $state works, WIP, abandoned or deprecated - see mods3 for explanation +
  • $lstate [optional] a chance to explain why the value of default is what it is; e.g. why a plugin is disabled +
  • $package when pcb-rnd is packaged for a distribution or OS, which package this plugin should end up in (see also: packaging howto) +
  • $fmt-native only for io_ plugins: whether this format is considered native (see also: io_lihata's pup) +
  • $fmt-feature-r only for io_ plugins: a read/load feature supported by the plugin (multiple entries of this should be added; see also: io_lihata's pup) +
  • $fmt-feature-w only for io_ plugins: a write/save feature supported by the plugin (multiple entries of this should be added; see also: io_lihata's pup) +
  • default disable-all or disable or buildin or plugin; see below +
  • dep [optional] a single plugin name on which plg depends; multiple dep lines can be added +
  • conflict [optional] a single plugin name on which plg conflicts with; multiple dep lines can be added +
  • autoload [optional] when 1, the plugin is automatically loaded and initialized (when not disabled); do not set this on libs and other code that are accessible only as a dependency of other plugins; set this 1 on HID, io, import, export, feature plugins +
+

Values of default: +

    +
  • buildin - unless the user requests otherwise, your plugin is linked into the executable +
  • plugin - unless the user requests otherwise, your plugin is dynamically linked; not recommended: the policy is to let users explicitly request dynamic linking +
  • disable - unless the user requests otherwise, your plugin is not compiled (recommended until the plugin gets some user testing) +
  • disable-all - the plugin stays disabled even with ./configure --all=* and the only way to enable it is to explicitly name it +
+ + + Index: tags/2.1.2/doc/developer/plugin/template/Makefile =================================================================== --- tags/2.1.2/doc/developer/plugin/template/Makefile (nonexistent) +++ tags/2.1.2/doc/developer/plugin/template/Makefile (revision 24813) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_foobar + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/2.1.2/doc/developer/plugin/template/Plug.tmpasm =================================================================== --- tags/2.1.2/doc/developer/plugin/template/Plug.tmpasm (nonexistent) +++ tags/2.1.2/doc/developer/plugin/template/Plug.tmpasm (revision 24813) @@ -0,0 +1,10 @@ +put /local/pcb/mod {foobar} +put /local/pcb/mod/OBJS [@ + $(PLUGDIR)/foobar/foobar.o +@] + +switch /local/pcb/foobar/controls + case {buildin} include /local/pcb/tmpasm/buildin; end; + case {plugin} include /local/pcb/tmpasm/plugin; end; + case {disable} include /local/pcb/tmpasm/disable; end; +end Index: tags/2.1.2/doc/developer/plugin/template/foobar.c =================================================================== --- tags/2.1.2/doc/developer/plugin/template/foobar.c (nonexistent) +++ tags/2.1.2/doc/developer/plugin/template/foobar.c (revision 24813) @@ -0,0 +1,43 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2018 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "config.h" + +#include + +#include "plugins.h" + +int pplg_check_ver_foobar(int ver_needed) { return 0; } + +void pplg_uninit_foobar(void) +{ +} + +int pplg_init_foobar(void) +{ + PCB_API_CHK_VER; + return 0; +} Index: tags/2.1.2/doc/developer/plugin/template/foobar.pup =================================================================== --- tags/2.1.2/doc/developer/plugin/template/foobar.pup (nonexistent) +++ tags/2.1.2/doc/developer/plugin/template/foobar.pup (revision 24813) @@ -0,0 +1,6 @@ +$class ***FILL THIS IN*** +$short ***FILL THIS IN*** +$long ***FILL THIS IN*** +$state WIP +default disable +autoload 1 Index: tags/2.1.2/doc/developer/plugin/template_fungw/Makefile =================================================================== --- tags/2.1.2/doc/developer/plugin/template_fungw/Makefile (nonexistent) +++ tags/2.1.2/doc/developer/plugin/template_fungw/Makefile (revision 24813) @@ -0,0 +1,20 @@ +### config part ### + +# You may want to use some configuration system for these; below is +# a simple "edited by the user" concept to keep the example small and clear +CFLAGS = -Wall -g -fPIC +LDFLAGS = +SOFLAGS = -rdynamic -shared + + +### rules ### + +all: ext_bar.so + +ext_bar.so: ext_bar.o + $(CC) -o ext_bar.so $(LDFLAGS) $(SOFLAGS) ext_bar.o + +ext_bar.o: ext_bar.c + +clean: + rm -f ext_bar.o ext_bar.so Index: tags/2.1.2/doc/developer/plugin/template_fungw/ext_bar.c =================================================================== --- tags/2.1.2/doc/developer/plugin/template_fungw/ext_bar.c (nonexistent) +++ tags/2.1.2/doc/developer/plugin/template_fungw/ext_bar.c (revision 24813) @@ -0,0 +1,63 @@ +/* + * COPYRIGHT + * + * bar - an external fungw plugin for pcb-rnd (example/template plugin) + * Copyright (C) 2018 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: TODO: FILL THIS IN + */ + +#include +#include + +/* Action ExtBar() */ +static fgw_error_t extbar(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + fgw_ctx_t *ctx = argv[0].val.func->obj->parent; + fgw_arg_t call_res; + int retval; + + /* pcb-rnd API shall be accessed through fungw calls */ + retval = fgw_vcall(ctx, &call_res, "message", FGW_STR, "PLEASE CONSIDER DEVELOPING A CORE PLUGIN INSTEAD!\n", 0); + + /* need to check and free the return value - any action call may fail */ + if (retval != 0) + fprintf(stderr, "ERROR: failed to call message() (fungw level)\n"); + else if ((call_res.type != FGW_INT) || (call_res.val.nat_int != 0)) + fprintf(stderr, "ERROR: failed to call message() (action level)\n"); + fgw_arg_free(ctx, &call_res); + + /* Set the return value of this action */ + res->val.nat_int = 0; + res->type = FGW_INT; + return 0; +} + +/* Called once before the plugin is unloaded */ +void pcb_rnd_uninit(fgw_obj_t *obj) +{ + fprintf(stderr, "EXT BAR uninit\n"); +} + +/* Called once when the plugin is loaded; returns 0 on success */ +int pcb_rnd_init(fgw_obj_t *obj, const char *opts) +{ + fgw_func_reg(obj, "extbar", extbar); /* need to register with lowercase name */ + + fprintf(stderr, "EXT BAR init with '%s'\n", opts); + return 0; +} Index: tags/2.1.2/doc/developer/plugin/template_pup/Makefile =================================================================== --- tags/2.1.2/doc/developer/plugin/template_pup/Makefile (nonexistent) +++ tags/2.1.2/doc/developer/plugin/template_pup/Makefile (revision 24813) @@ -0,0 +1,36 @@ +### config part ### + +# edit this to point to pcb-rnd svn checkout's trunk/ (or the release +# tarball's root). Assumes the pcb-rnd source is configured. +TRUNK=../../../.. + +# You may want to use some configuration system for these; below is +# a simple "edited by the user" concept to keep the example small and clear +CFLAGS = -Wall -g -fPIC -I$(TRUNK) -I$(TRUNK)/src_3rd +LDFLAGS = +SOFLAGS = -rdynamic -shared +PLUGDIR = $(LIBDIR)/plugins + + +### rules ### + +all: ext_foo.so + +include $(TRUNK)/Makefile.conf + +ext_foo.so: ext_foo.o + $(CC) -o ext_foo.so $(LDFLAGS) $(SOFLAGS) ext_foo.o + +ext_foo.o: ext_foo.c + +clean: + rm -f ext_foo.o ext_foo.so + +install: + mkdir -p $(PLUGDIR) + cp ext_foo.so $(PLUGDIR)/ext_foo.so + cp ext_foo.pup $(PLUGDIR)/ext_foo.pup + +uninstall: + rm -f $(PLUGDIR)/ext_foo.so $(PLUGDIR)/ext_foo.pup + Index: tags/2.1.2/doc/developer/plugin/template_pup/ext_foo.c =================================================================== --- tags/2.1.2/doc/developer/plugin/template_pup/ext_foo.c (nonexistent) +++ tags/2.1.2/doc/developer/plugin/template_pup/ext_foo.c (revision 24813) @@ -0,0 +1,68 @@ +/* + * COPYRIGHT + * + * foo - an external plugin for pcb-rnd (example/template plugin) + * Copyright (C) 2018 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: TODO: FILL THIS IN + */ + +/* This is pcb-rnd's config.h from trunk: */ +#include "config.h" + +#include + +/* These are pcb-rnd's headers from trunk: */ +#include "src/actions.h" +#include "src/plugins.h" + +static const char *ext_foo_cookie = "ext foo (external plugin example/template)"; + +static const char pcb_acts_ExtFoo[] = "ExtFoo(arg1, arg2, [arg3]...)"; +static const char pcb_acth_ExtFoo[] = "Help text: short description of what the action does."; +static fgw_error_t pcb_act_ExtFoo(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + pcb_message(PCB_MSG_ERROR, "PLEASE CONSIDER DEVELOPING A CORE PLUGIN INSTEAD!\n"); + PCB_ACT_IRES(0); + return 0; +} + +static const pcb_action_t ext_foo_action_list[] = { + {"ExtFoo", pcb_act_ExtFoo, pcb_acth_ExtFoo, pcb_acts_ExtFoo} +}; +PCB_REGISTER_ACTIONS(ext_foo_action_list, ext_foo_cookie) + + +int pplg_check_ver_ext_foo(int ver_needed) { return 0; } + +void pplg_uninit_ext_foo(void) +{ + fprintf(stderr, "EXT FOO uninit\n"); + pcb_remove_actions_by_cookie(ext_foo_cookie); +} + +#include "src/dolists.h" + +int pplg_init_ext_foo(void) +{ + PCB_API_CHK_VER; /* for external plugins this is CRITICAL */ + + PCB_REGISTER_ACTIONS(ext_foo_action_list, ext_foo_cookie); + + fprintf(stderr, "EXT FOO init\n"); + return 0; +} Index: tags/2.1.2/doc/developer/plugin/template_pup/ext_foo.pup =================================================================== --- tags/2.1.2/doc/developer/plugin/template_pup/ext_foo.pup (nonexistent) +++ tags/2.1.2/doc/developer/plugin/template_pup/ext_foo.pup (revision 24813) @@ -0,0 +1,5 @@ +$class ***FILL THIS IN*** +$short ***FILL THIS IN*** +$long ***FILL THIS IN*** +$state WIP +autoload 1 Index: tags/2.1.2/doc/developer/plugin/terms.html =================================================================== --- tags/2.1.2/doc/developer/plugin/terms.html (nonexistent) +++ tags/2.1.2/doc/developer/plugin/terms.html (revision 24813) @@ -0,0 +1,23 @@ + + +

pcb-rnd - plugin development - terminology

+

+The core is pcb-rnd's core source code that lives in pcb-rnd svn, in +trunk/src. Maintained by the pcb-rnd team. +

+A plugin is a small portion of the code. +

+Core plugins are those plugins that are in pcb-rnd svn, +in trunk/src_plugins. Maintained by the pcb-rnd team. +

+External plugins are those plugins that are written, maintained +and hosted by developers not part of the pcb-rnd team. External plugins +are not hosted in the pcb-rnd svn and are not supported by the pcb-rnd team. +

+A core plugin can be disabled (not compiled at all), +static linked (builtin), or dynamically linked (plugin). This is +selected during pcb-rnd ./configure time. An external plugin is always dynamically +linked. + + + Index: tags/2.1.2/doc/developer/plugin/tmpasm_vars.html =================================================================== --- tags/2.1.2/doc/developer/plugin/tmpasm_vars.html (nonexistent) +++ tags/2.1.2/doc/developer/plugin/tmpasm_vars.html (revision 24813) @@ -0,0 +1,70 @@ + + +

pcb-rnd hacking - plugin Plug.tmpasm variables

+

+Plug.tmpasm is used for coordinating the build of the plugin. It is +written in tmpasm +and is processed by scconfig while generating the Makefile. For core (src/) +and core plugins (src_plugins/) there is a single central Makefile generated +in src/Makefile. The plugin's own Makefile is just a call to the central +Makefile for convenience. +

+Plug.tmpasm is a generic template, its output directly ends up in src/Makefile. +This provides the plugin developer some flexibility, but using this feature +needs deep understanding of the build system. +

+For the features that are most commonly needed, the system offers +prewritten, turn key solutions. It is strongly recommended to use these +features only. These features are accessible through setting /local/pcb/mod/* +tmpasm variables (typically with the put and append instructions). The +rest of this document lists and explains these variables. + + + + + + + + + + + + + +
variable description +
/local/pcb/mod + the name of the plugin +
/local/pcb/mod/OBJS + a whitespace separated list of local object files to compile, + e.g. foo.o +
/local/pcb/mod/OBJS_C99 + same as OBJS, but for sources that can be compiled only with a C99 + compiler; plugins must not use this variable unless the source + depends on 3rd party library which comes with a header that absolutely + can not compiled with C89 +
/local/pcb/mod/CFLAGS + +
/local/pcb/mod/LDFLAGS + +
/local/pcb/mod/CONF + optional: the name of the conf struct + header - if the plugin doesn't have runtime configuration + settings, remove this line +
/local/pcb/mod/CONFFILE + optional: conf file's internal version: the file name of the conf + file (without path) that should be encoded in conf_internal.c +
/local/pcb/mod/CONFVAR + optional: conf file's internal version: the variable name to use + in conf_internal.c +
/local/pcb/mod/YACC + optional: if you have files for yacc-processing, list them without + the .y suffix here (whitespace separated list) +
/local/pcb/mod/LEX + optional: if you have files for lex-processing, list them without + the .l suffix here (whitespace separated list) +
/local/pcb/mod/SPHASH + optional: if the plugin uses an sphash (compile time perfect hash), + the sphash source file name should be specified in this field + + + Index: tags/2.1.2/doc/developer/polygon.html =================================================================== --- tags/2.1.2/doc/developer/polygon.html (nonexistent) +++ tags/2.1.2/doc/developer/polygon.html (revision 24813) @@ -0,0 +1,160 @@ +

different faces of a polygon

+

+In pcb-rnd polygons have three possible appearance: +

    +
  • points: the as-drawn version +
  • clipped: the as-shown version, with holes +
  • no-holes: the as-shown version, without holes +
+ +

The as-drawn version

+

+The as-drawn version is a list of points (corners), as drawn +by the user. The points are stored in an array of x;y coordinates. +There is a single, continous, dynamically allocated array for all points, +including the outer contour and the holes. +

+The points are stored in the Points[] field. The HoleIndex[] +field lists the starting index of each hole. For example a +rectangular polygon with 2 triangle holes is stored as: +

+ +
index 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. +
Points[] value c1 c2 c3 c4 h1.1 h1.2 h1.3 h2.1 h2.2 h2.3 +
part of outer contour hole 1 hole 2 +
+

+The array length of Points[] is 10, the length of the correspoding HoleIndex[] is 2. +The values of HoleIndex[] is {4, 7}, indicating that the corners of first hole +starts at 4 while the corners of the second hole starts at 7. +

+If HoldeIndex[] is NULL, there are no holes and all points are part of the +outer contour. The Outer contour must contain at least 3 points. +

+The as-drawn version always contains the contour of a single island +and 0 or more holes - none of them can intersect or touch any contour or +hole of the same polygon. This also means a contour or hole can not be +self-intersecting. +

+The as-drawn version is stored to make editing possible. It is +not affected by other objects (e.g. clearances) or flags of the polygon. +The as-drawn points exist and are stored even if they are not visible +(clipped). The UI maniulates the as-drawn version. + + +

The clipped version

+

+The polygon is clipped by an object if both the polygon and the object have +the correspoding 'clear' flag set. A clipped polygon typically has a much +more complex shape than the as-drawn polygon, due to the clearance cutouts +(not to be confused with user drawn holes). The clipped polygon is the actual +"in-copper" shape of the polygon. +

+In some cases the clearance cutouts slice the polygon in multiple components +or in other word islands. If the polygon is full (set by +a polygon flag), all islands are kept, else only the largest island is kept. +(Note: the find code handles all islands of a full polygon as one polygon: it +indicates connection between them even if there is no connection, which makes +full polygons dangerous on copper layers.) +

+The clipped polygon is stored in the polyarea field Clipped. It is a doubly +linked circular list (link fields are .f for forward and .b for backward). Each +item on the list is an island of the polygon. If Clipped is NULL, the +polygon clipping is not yet compiled for the given polygon; call pcb_poly_init_clip(). +

+Each island is a polyarea, which consists of an outer contour and 0 or more +holes - all correspoding to the actual cutouts created by user-drawn polygon +holes and/or clearance cutouts. These contours are stored in a singly linked +list of plines. The first element of the list is the pline for the outer +contour and always exists. The next 0 or more plines, using the .next field +of the pline, are the contours of the cutouts (holes). +

+A pline consists of a circular, doubly linked list of points; traversing using +the .next field, the points are ordered in counter-clockwise. +

+The clipped polygon shall be updated by any code that changes: +

    +
  • the as-drawn points of the polygon +
  • geomerty of any object that may overlap with the polygon (so that clearance changes are applied) +
+

+When some code forgets to update clippig, the clipped polygon doesn't match +the clearances dictated by other objects; a reload of the board "fixes" the +problem by forcing the clip. (Native save files contain the as-drawn poly only, +not the (outdated) clipped poly). + +

The no-holes version

+

+Some export plugins (and/or export formats) don't support holes in polygons. +The no-hole version of the polygon is stored in the .NoHoles filed and is +a list of islands, each specified with an outer countour that are crafted +to include the holes. This is done by slicing an island at each hole. +TODO: check how it looks, include image + +

Further comments by Ben Jackson

+As extracted from the original code comments: +
+The first pcb_polyarea_t in pcb_polygon_t.Clipped is what is used for the vast
+majority of Polygon related tests.  The basic logic for an
+intersection is "is the target shape inside pcb_polyarea_t.contours and NOT
+fully enclosed in any of pcb_polyarea_t.contours.next... (the holes)".
+
+The polygon dicer (NoHolesPolygonDicer and r_NoHolesPolygonDicer)
+emits a series of "simple" pcb_pline_t shapes.  That is, the pcb_pline_t isn't
+linked to any other "holes" outlines).  That's the meaning of the first
+test in r_NoHolesPolygonDicer.  It is testing to see if the pcb_pline_t
+contour (the first, making it a solid outline) has a valid next
+pointer (which would point to one or more holes).  The dicer works by
+recursively chopping the polygon in half through the first hole it
+sees (which is guaranteed to eliminate at least that one hole).  The
+dicer output is used for HIDs which cannot render things with holes
+(which would require erasure).
+
+ +

How to code with polygons

+ +

Iterators: looping on clipped polygon geometry

+ +The following code prints all contours and holes of a polygon, using loops +iterators. The same iterator holds all states, so that it points to: +
    +
  • one polygon +
  • one of the islands of that polygon +
  • either the outer contour or one of the holes in that polygon (cntr) +
  • one of the points in cntr +
+ +
+void print_poly(pcb_polygon_t *polygon)
+{
+	pcb_poly_it_t it;
+	pcb_polyarea_t *pa;
+
+	/* first, iterate over all islands of a polygon */
+	for(pa = pcb_poly_island_first(polygon, &it); pa != NULL; pa = pcb_poly_island_next(&it)) {
+		pcb_coord_t x, y;
+		pcb_pline_t *pl;
+		int go;
+
+		printf(" island\n");
+		/* check if we have a contour for the given island */
+		pl = pcb_poly_contour(&it);
+		if (pl != NULL) {
+			printf("  contour:\n");
+			/* iterate over the vectors of the contour */
+			for(go = pcb_poly_vect_first(&it, &x, &y); go; go = pcb_poly_vect_next(&it, &x, &y)) {
+				pcb_printf("   %mm %mm\n", x, y);
+			}
+			
+			/* iterate over all holes within this island */
+			for(pl = pcb_poly_hole_first(&it); pl != NULL; pl = pcb_poly_hole_next(&it)) {
+				printf("  hole:\n");
+				/* iterate over the vectors of the given hole */
+				for(go = pcb_poly_vect_first(&it, &x, &y); go; go = pcb_poly_vect_next(&it, &x, &y)) {
+					pcb_printf("   %mm %mm\n", x, y);
+				}
+			}
+		}
+	}
+}
+
Index: tags/2.1.2/doc/developer/releasing.txt =================================================================== --- tags/2.1.2/doc/developer/releasing.txt (nonexistent) +++ tags/2.1.2/doc/developer/releasing.txt (revision 24813) @@ -0,0 +1,11 @@ +release check list + +0. test compile and test run a clean checkout on a clean system + configure with --debug --all=buildin, then without +1. check next version number and previous revision in tags/ +2. update the changelog +3. rewrite the release notes +4. modify version number in scconfig +5. commit trunk +6. svn tag using URLs +7. update the timeline, events and doc/news.html Index: tags/2.1.2/doc/developer/renames =================================================================== --- tags/2.1.2/doc/developer/renames (nonexistent) +++ tags/2.1.2/doc/developer/renames (revision 24813) @@ -0,0 +1,1781 @@ +Name differences between mainline -> pcb_rnd +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +#types: + +PCBTypePtr -> pcb_board_t * +PCBType -> pcb_board_t +DataTypePtr -> pcb_data_t * +DataType -> pcb_data_t +LayerGroupTypePtr -> pcb_layer_group_t * +LayerGroupType -> pcb_layer_group_t +LayerTypePtr -> pcb_layer_t * +LayerType -> pcb_layer_t +BufferTypePtr -> pcb_buffer_t * +BufferType -> pcb_buffer_t +NetTypePtr -> pcb_net_t * +NetType -> pcb_net_t +ConnectionTypePtr -> pcb_connection_t * +ConnectionType -> pcb_connection_t +BoxTypePtr -> pcb_box_t * +BoxType -> pcb_box_t +BoxListTypePtr -> pcb_box_list_t * +BoxListType -> pcb_box_list_t +FontTypePtr -> pcb_font_t * +FontType -> pcb_font_t +LineTypePtr -> pcb_line_t * +LineType -> pcb_line_t +AttachedObjectTypePtr -> pcb_attached_obj_t * +AttachedObjectType -> pcb_attached_obj_t +AttachedLineTypePtr -> pcb_attached_line_t * +AttachedLineType -> pcb_attached_line_t +CrosshairTypePtr -> pcb_crosshair_t * +CrosshairType -> pcb_crosshair_t +MarkTypePtr -> pcb_mark_t * +MarkType -> pcb_mark_t +ArcTypePtr -> pcb_arc_t * +ArcType -> pcb_arc_t +PointTypePtr -> pcb_point_t * +PointType -> pcb_point_t +RatTypePtr -> pcb_rat_t * +RatType -> pcb_rat_t +PolygonTypePtr -> pcb_polygon_t * +PolygonType -> pcb_polygon_t +PadTypePtr -> pcb_pad_t * +PadType -> pcb_pad_t +PinTypeType -> pcb_pin_t * +PinType -> pcb_pin_t +ElementTypeHandle -> pcb_element_t ** +ElementTypePtr -> pcb_element_t * +ElementType -> pcb_element_t +TextTypePtr -> pcb_text_t * +TextType -> pcb_text_t +AttributeListTypePtr -> pcb_attribute_list_t * +AttributeListType -> pcb_attribute_list_t +AttributeTypePtr -> pcb_attribute_t * +AttributeType -> pcb_attribute_t +OutputTypePtr -> pcb_output_t * +OutputType -> pcb_output_t +DrcViolationTypePtr -> pcb_drc_violation_t * +DrcViolationType -> pcb_drc_violation_t +FlagBitsTypePtr -> pcb_flag_bits_t * +FlagBitsType -> pcb_flag_bits_t +FlagTypePtr -> pcb_flag_t * +FlagType -> pcb_flag_t +SymbolTypePtr -> pcb_symbol_t * +SymbolType -> pcb_symbol_t +FunctionID -> pcb_function_id_t +EndCapStyle -> pcb_cap_style_t +hidval -> pcb_hidval_t +HID_Action -> pcb_hid_action_t +PCBWatchFlags -> pcb_watch_flags_t +HID_DRC_GUI -> pcb_hid_drc_gui_t +HID -> pcb_hid_t +hid_gc_struct -> hid_gc_s +hidGC -> pcb_hid_gc_t +HID_Attr_Val -> pcb_hid_attr_val_t +HID_Attribute -> pcb_hid_attribute_t +HID_AttrNode -> pcb_hid_attr_node_t +LibraryEntryTypePtr -> pcb_lib_entry_t * +LibraryEntryType -> pcb_lib_entry_t +LibraryMenuTypePtr -> pcb_lib_menu_t * +LibraryMenuType -> pcb_lib_menu_t +LibraryTypePtr -> pcb_lib_t * +LibraryType -> pcb_lib_t +UnitList -> pcb_unit_list_t +unitflags -> pcb_unit_flags_e +UnitList -> pcb_unit_list_t +NetListTypePtr -> pcb_netlist_t * +NetListType -> pcb_netlist_t +NetListListTypePtr -> pcb_netlist_list_t * +NetListListType -> pcb_netlist_list_t +AnyObjectTypePtr -> pcb_any_obj_t * +AnyObjectType -> pcb_any_obj_t +AnyLineObjectTypePtr -> pcb_any_line_t * +AnyLineObjectType -> pcb_any_line_t +AttachedLineTypePtr -> pcb_attached_line_t +AttachedLineType -> pcb_attached_line_t * +Vector -> pcb_vector_t +vertex -> pcb_vertex_t +CVCList -> pcb_cvc_list_t +VNODE -> pcb_vnode_t +PLINE -> pcb_pline_t +POLYAREA -> pcb_polyarea_t +PolygonBooleanOperation -> pcb_poly_bool_op_e +RubberbandType -> pcb_rubberband_t +Unit -> pcb_unit_t +Increments -> pcb_increments_t +Angle -> pcb_angle_t +Coord -> pcb_coord_t +RouteStyleTypePtr -> pcb_route_style_t * +RouteStyleType -> pcb_route_style_t +heap_t -> pcb_heap_t +cost_t -> pcb_cost_t + +# functions: +EventMoveCrosshair -> pcb_event_move_crosshair +AdjustAttachedObjects -> pcb_adjust_attached_objects + +warpNoWhere -> pcb_warp_nowhere +get_style_size -> pcb_get_style_size +NotifyLine -> pcb_notify_line +NotifyBlock -> pcb_notify_block +NotifyMode -> pcb_notify_mode +ClearWarnings -> pcb_clear_warnings +ReleaseMode -> pcb_release_mode +AFAIL -> PCB_AFAIL +ACTION_ARG -> PCB_ACTION_ARG +AttributeGetFromList -> pcb_attribute_get +AttributePutToList -> pcb_attribute_put +AttributeRemoveFromList -> pcb_attribute_remove +FreeAttributeListMemory -> pcb_attribute_free +AttributeGet -> pcb_attrib_get +AttributePut -> pcb_attrib_put +AttributeRemove -> pcb_attrib_remove +FreePCBMemory -> pcb_board_free +CreateNewPCB_ -> pcb_board_new_ +CreateNewPCB -> pcb_board_new +CreateNewPCBPost -> pcb_board_new_postproc +CountHoles -> pcb_board_count_holes +SWAP_X -> PCB_SWAP_X +SWAP_Y -> PCB_SWAP_Y +ROTATEBOX_CW -> PCB_BOX_ROTATE_CW +ROTATEBOX_TO_NORTH -> PCB_BOX_ROTATE_TO_NORTH +ROTATEBOX_FROM_NORTH -> PCB_BOX_ROTATE_FROM_NORTH +CENTER_X -> PCB_BOX_CENTER_X +CENTER_Y -> PCB_BOX_CENTER_Y +MOVE_BOX_LOWLEVEL -> PCB_BOX_MOVE_LOWLEVEL +point_in_box -> pcb_point_in_box +point_in_closed_box -> pcb_point_in_closed_box +box_is_good -> pcb_box_is_good +box_intersect -> pcb_box_intersect +closest_pcb_point_in_box -> pcb_closest_pcb_point_in_box +box_in_box -> pcb_box_in_box +clip_box -> pcb_clip_box +shrink_box -> pcb_shrink_box +bloat_box -> pcb_bloat_box +box_center -> pcb_box_center +box_corner -> pcb_box_corner +point_box -> pcb_point_box +close_box -> pcb_close_box +dist2_to_box -> pcb_dist2_to_box +GetBoxMemory -> pcb_box_new +FreeBoxListMemory -> pcb_box_free +SetPointBoundingBox -> pcb_set_point_bounding_box +SwapBuffer -> pcb_swap_buffer +SetBufferBoundingBox -> pcb_set_buffer_bbox +ClearBuffer -> pcb_buffer_clear +pcb_swap_buffer -> pcb_buffer_swap +pcb_buffer_set_bbox -> +AddSelectedToBuffer -> pcb_buffer_add_selected +LoadLayoutToBuffer -> pcb_buffer_load_layout +RotateBuffer -> pcb_buffer_rotate +SelectPasteBuffer -> pcb_buffer_select_paste +MirrorBuffer -> pcb_buffer_mirror +InitBuffers -> pcb_init_buffers +UninitBuffers -> pcb_uninit_buffers +MoveObjectToBuffer -> pcb_move_obj_to_buffer +CopyObjectToBuffer -> pcb_copy_obj_to_buffer +LoadFootprint -> pcb_load_footprint +CreateNewBuffer -> pcb_buffer_new +PASTEBUFFER -> PCB_PASTEBUFFER +QuitApplication -> pcb_quit_app +GetInfoString -> pcb_get_infostr +ChangeLayoutName -> pcb_board_change_name +ChangeLayerName -> pcb_layer_change_name +ChangeSelectedSize -> pcb_chg_selected_size +ChangeSelectedClearSize -> pcb_chg_selected_clear_size +ChangeSelected2ndSize -> pcb_chg_selected_2nd_size +ChangeSelectedMaskSize -> pcb_chg_selected_mask_size +ChangeSelectedJoin -> pcb_chg_selected_join +SetSelectedJoin -> pcb_set_selected_join +ClrSelectedJoin -> pcb_clr_selected_join +ChangeSelectedNonetlist -> pcb_chg_selected_nonetlist +ChangeSelectedSquare -> pcb_chg_selected_square +SetSelectedSquare -> pcb_set_selected_square +ClrSelectedSquare -> pcb_clr_selected_square +ChangeSelectedThermals -> pcb_chg_selected_thermals +ChangeSelectedHole -> pcb_chg_selected_hole +ChangeSelectedPaste -> pcb_chg_selected_paste +ChangeSelectedOctagon -> pcb_chg_selected_octagon +SetSelectedOctagon -> pcb_set_selected_octagon +ClrSelectedOctagon -> pcb_clr_selected_octagon +ChangeObjectSize -> pcb_chg_obj_size +ChangeObject1stSize -> pcb_chg_obj_1st_size +ChangeObjectThermal -> pcb_chg_obj_thermal +ChangeObjectClearSize -> pcb_chg_obj_clear_size +ChangeObject2ndSize -> pcb_chg_obj_2nd_size +ChangeObjectMaskSize -> pcb_chg_obj_mask_size +ChangeObjectJoin -> pcb_chg_obj_join +SetObjectJoin -> pcb_set_obj_join +ClrObjectJoin -> pcb_clr_obj_join +ChangeObjectNonetlist -> pcb_chg_obj_nonetlist +ChangeObjectSquare -> pcb_chg_obj_square +SetObjectSquare -> pcb_set_obj_square +ClrObjectSquare -> pcb_clr_obj_square +ChangeObjectOctagon -> pcb_chg_obj_octagon +SetObjectOctagon -> pcb_set_obj_octagon +ClrObjectOctagon -> pcb_clr_obj_octagon +ChangeObjectName -> pcb_chg_obj_name +QueryInputAndChangeObjectName -> pcb_chg_obj_name_query +ChangeObjectPinnum -> pcb_chg_obj_pinnum +ChangeObjectRadius -> pcb_chg_obj_radius +ChangeObjectAngle -> pcb_chg_obj_angle +ChangeSelectedAngle -> pcb_chg_selected_angle +ChangeSelectedRadius -> pcb_chg_selected_radius +QueryInputAndpcb_chg_obj_name -> pcb_chg_obj_name_query +ChangePCBSize -> pcb_board_resize +ClipLine -> pcb_line_clip +GetWorkingDirectory -> pcb_get_wd +tempfile_name_new -> pcb_tempfile_name_new +tempfile_unlink -> pcb_tempfile_unlink +lrealpath -> pcb_lrealpath +get_user_name -> pcb_get_user_name +CopyPastebufferToLayout -> pcb_buffer_copy_to_layout +CopyObject -> pcb_copy_obj +GridFit -> pcb_grid_fit +notify_crosshair_change -> pcb_notify_crosshair_change +notify_mark_change -> pcb_notify_mark_change +HideCrosshair -> pcb_crosshair_hide +RestoreCrosshair -> pcb_crosshair_restore +DrawAttached -> pcb_draw_attached +DrawMark -> pcb_draw_mark +MoveCrosshairRelative -> pcb_crosshair_move_relative +MoveCrosshairAbsolute -> pcb_crosshair_move_absolute +SetCrosshairRange -> pcb_crosshair_set_range +InitCrosshair -> pcb_crosshair_init +DestroyCrosshair -> pcb_crosshair_uninit +FitCrosshairIntoGrid -> pcb_crosshair_grid_fit +CenterDisplay -> pcb_center_display +FreeDataMemory -> pcb_data_free +IsDataEmpty -> pcb_data_is_empty +GetDataBoundingBox -> pcb_data_bbox +Draw -> pcb_draw +Redraw -> pcb_redraw +DrawObject -> pcb_draw_obj +DrawLayer -> pcb_draw_layer +EraseObject -> pcb_erase_obj +LightenColor -> pcb_lighten_color +Message -> pcb_message +OpenErrorpcb_messag -> pcb_open_error_message +PopenErrorpcb_message -> pcb_popen_error_message +OpendirErrorpcb_message -> pcb_opendir_error_message +ChdirErrorpcb_message -> ocb_chdir_error_message +OpenErrorpcb_message -> pcb_open_error_message +CatchSignal -> pcb_catch_signal +events_init -> pcb_events_init +events_uninit -> pcb_events_uninit +event_bind -> pcb_event_bind +event_unbind -> pcb_event_unbind +event_unbind_cookie -> pcb_event_unbind_cookie +event_unbind_allcookie -> pcb_event_unbind_allcookie +event -> pcb_event +LineLineIntersect -> pcb_intersect_line_line +LineArcIntersect -> pcb_intersect_line_arc +PinLineIntersect -> pcb_intersect_line_pin +LinePadIntersect -> pcb_intersect_line_pad +ArcPadIntersect -> pcb_intersect_arc_pad +IsPolygonInPolygon -> pcb_is_poly_in_poly +LookupElementConnections -> pcb_lookup_element_conns +LookupConnectionsToAllElements -> pcb_lookup_conns_to_all_elements +LookupConnection -> pcb_lookup_conn +LookupConnectionByPin -> pcb_lookup_conn_by_pin +LookupUnusedPins -> pcb_lookup_unused_pins +ResetFoundLinesAndPolygons -> pcb_reset_found_lines_polys +ResetFoundPinsViasAndPads -> pcb_reset_found_pins_vias_pads +ResetConnections -> pcb_reset_conns +InitConnectionLookup -> pcb_conn_lookup_init +InitComponentLookup -> pcb_component_lookup_init +InitLayoutLookup -> pcb_layout_lookup_init +FreeConnectionLookupMemory -> pcb_conn_lookup_uninit +FreeComponentLookupMemory -> pcb_component_lookup_uninit +FreeLayoutLookupMemory -> pcb_layout_lookup_uninit +RatFindHook -> pcb_rat_find_hook +SaveFindFlag -> pcb_save_find_flag +RestoreFindFlag -> pcb_restore_find_flag +DRCAll -> pcb_drc_all +IsLineInPolygon -> pcb_is_line_in_poly +IsArcInPolygon -> pcb_is_arc_in_poly +IsPadInPolygon -> pcb_is_pad_in_poly +ClearFlagOnPinsViasAndPads -> pcb_clear_flag_on_pins_vias_pads +ClearFlagOnLinesAndPolygons -> pcb_clear_flag_on_lines_polys +ClearFlagOnAllObjects -> pcb_clear_flag_on_all_objs +MakeFlags -> pcb_flag_make +OldFlags -> pcb_flag_old +AddFlags -> pcb_flag_add +MaskFlags -> pcb_flag_mask +EraseFlags -> pcb_flag_erase +NoFlags -> pcb_no_flags +mem_any_set -> pcb_mem_any_set +SET_FLAG -> PCB_FLAG_SET +CLEAR_FLAG -> PCB_FLAG_CLEAR +TEST_FLAG -> PCB_FLAG_TEST +TOGGLE_FLAG -> PCB_FLAG_TOGGLE +ASSIGN_FLAG -> PCB_FLAG_ASSIGN +TEST_FLAGS -> PCB_FLAGS_TEST +CHANGE_FLAG -> PCB_FLAG_CHANGE +FLAGS_EQUAL -> PCB_FLAG_EQ +THERMFLAG -> PCB_FLAG_THERM +TEST_THERM -> PCB_FLAG_THERM_TEST +GET_THERM -> PCB_FLAG_THERM_GET +CLEAR_THERM -> PCB_FLAG_THERM_CLEAR +ASSIGN_THERM -> PCB_FLAG_THERM_ASSIGN +GET_SQUARE -> PCB_FLAG_SQUARE_GET +CLEAR_SQUARE -> PCB_FLAG_SQUARE_CLEAR +ASSIGN_SQUARE -> PCB_FLAG_SQUARE_ASSIGN +GET_INTCONN -> PCB_FLAG_INTCONN_GET +TEST_ANY_THERMS -> PCB_FLAG_THERM_TEST_ANY +common_string_to_flags -> pcb_strflg_common_s2f +common_flags_to_string -> pcb_strflg_common_f2s +uninit_strflags_buf -> pcb_strflg_uninit_buf +uninit_strflags_layerlist -> pcb_strflg_uninit_layerlist +pcbflags_to_string -> pcb_strflg_board_f2s +string_to_pcbflags -> pcb_strflg_board_s2f +string_to_flags -> pcb_strflg_s2f +flags_to_string -> pcb_strflg_f2s +CreateDefaultFont -> pcb_font_create_default +SetFontInfo -> pcb_font_set_info +CreateNewLineInSymbol -> pcb_font_new_line_in_sym +leaky_init -> pcb_leaky_init +leaky_uninit -> pcb_leaky_uninit +leaky_malloc -> pcb_leaky_malloc +leaky_calloc -> pcb_leaky_calloc +leaky_realloc -> pcb_leaky_realloc +leaky_strdup -> pcb_leaky_strdup +funchash_get -> pcb_funchash_get +funchash_set -> pcb_funchash_set +funchash_set_table -> pcb_funchash_set_table +funchash_remove_cookie -> pcb_funchash_remove_cookie +funchash_init -> pcb_funchash_init +funchash_uninit -> pcb_funchash_uninit +heap_create -> pcb_heap_create +heap_destroy -> pcb_heap_destroy +heap_free -> pcb_heap_free +heap_insert -> pcb_heap_insert +heap_remove_smallest -> pcb_heap_remove_smallest +heap_replace -> pcb_heap_replace +heap_is_empty -> pcb_heap_is_empty +heap_size -> pcb_heap_size +hid_register_action -> pcb_hid_register_action +hid_register_actions -> pcb_hid_register_actions +REGISTER_ACTIONS -> PCB_REGISTER_ACTIONS +HIDCONCAT -> PCB_HIDCONCAT +hid_expose_callback -> pcb_hid_expose_callback +hid_actions_init -> pcb_hid_actions_init +hid_actions_uninit -> pcb_hid_actions_uninit +REGISTER_ATTRIBUTES -> PCB_REGISTER_ATTRIBUTES +print_actions -> pcb_print_actions +dump_actions -> pcb_dump_actions +hid_find_action -> pcb_hid_find_action +hid_remove_actions -> pcb_hid_remove_actions +hid_remove_action -> pcb_hid_remove_action +hid_remove_actions_by_cookie -> pcb_hid_remove_actions_by_cookie +hid_action -> pcb_hid_action +hid_actionl -> pcb_hid_actionl +hid_actionv -> pcb_hid_actionv +hid_actionv_ -> pcb_hid_actionv_ +hid_parse_command -> pcb_hid_parse_command +hid_parse_actions -> pcb_hid_parse_actions +hid_register_attributes -> pcb_hid_register_attributes +hid_remove_attributes_by_cookie -> pcb_hid_remove_attributes_by_cookie +hid_attributes_uninit -> pcb_hid_attributes_uninit +hid_usage -> pcb_hid_usage +hid_usage_option -> pcb_hid_usage_option +hid_cfg_create_menu -> pcb_hid_cfg_create_menu +hid_cfg_remove_menu -> pcb_hid_cfg_remove_menu +hid_cfg_load -> pcb_hid_cfg_load +hid_cfg_load_lht -> pcb_hid_cfg_load_lht +hid_cfg_load_str -> pcb_hid_cfg_load_str +hid_cfg_get_menu -> pcb_hid_cfg_get_menu +hid_cfg_get_menu_at -> pcb_hid_cfg_get_menu_at +hid_cfg_menu_field_path -> pcb_hid_cfg_menu_field_path +hid_cfg_menu_field_str -> pcb_hid_cfg_menu_field_str +hid_cfg_menu_field -> pcb_hid_cfg_menu_field +hid_cfg_has_submenus -> pcb_hid_cfg_has_submenus +hid_cfg_create_hash_node -> pcb_hid_cfg_create_hash_node +hid_cfg_extend_hash_nodev -> pcb_hid_cfg_extend_hash_nodev +hid_cfg_extend_hash_node -> pcb_hid_cfg_extend_hash_node +hid_cfg_dfs -> pcb_hid_cfg_dfs +hid_cfg_error -> pcb_hid_cfg_error +hid_cfg_action -> pcb_hid_cfg_action +hid_cfg_keys_init -> pcb_hid_cfg_keys_init +hid_cfg_keys_uninit -> pcb_hid_cfg_keys_uninit +hid_cfg_keys_add_under -> pcb_hid_cfg_keys_add_under +hid_cfg_keys_add_by_desc -> pcb_hid_cfg_keys_add_by_desc +hid_cfg_keys_add_by_strdesc -> pcb_hid_cfg_keys_add_by_strdesc +hid_cfg_keys_gen_accel -> pcb_hid_cfg_keys_gen_accel +hid_cfg_keys_input -> pcb_hid_cfg_keys_input +hid_cfg_keys_action -> pcb_hid_cfg_keys_action +hid_cache_color -> pcb_hid_cache_color +common_fill_pcb_polygon -> pcb_dhlp_fill_pcb_polygon +common_thindraw_pcb_polygon -> pcb_dhlp_thindraw_pcb_polygon +common_fill_pcb_pad -> pcb_dhlp_fill_pcb_pad +common_thindraw_pcb_pad -> pcb_dhlp_thindraw_pcb_pad +common_fill_pcb_pv -> pcb_dhlp_fill_pcb_pv +common_thindraw_pcb_pv -> pcb_dhlp_thindraw_pcb_pv +common_draw_helpers_init -> pcb_dhlp_draw_helpers_init +hid_get_extents -> pcb_hid_get_extents +hid_save_and_show_layer_ons -> pcb_hid_save_and_show_layer_ons +hid_restore_layer_ons -> pcb_hid_restore_layer_ons +hid_get_flag -> pcb_hid_get_flag +derive_default_filename -> pcb_derive_default_filename +layer_type_to_file_name -> pcb_layer_type_to_file_name +hid_init -> pcb_hid_init +hid_uninit -> pcb_hid_uninit +hid_find_gui -> pcb_hid_find_gui +hid_find_printer -> pcb_hid_find_printer +hid_find_exporter -> pcb_hid_find_exporter +hid_enumerate -> pcb_hid_enumerate +hid_parse_command_line -> pcb_hid_parse_command_line +hid_register_hid -> pcb_hid_register_hid +hid_remove_hid -> pcb_hid_remove_hid +common_nogui_init -> pcb_hid_nogui_init +hid_nogui_get_hid -> pcb_hid_nogui_get_hid +InsertPointIntoObject -> pcb_insert_point_in_object +AdjustInsertPoint -> pcb_adjust_insert_point +ComputeIntersectionArea -> pcb_intersect_box_box +ComputeUnionArea -> pcb_union_box_box +GetLibraryMenuMemory -> pcb_lib_menu_new +GetLibraryEntryMemory -> pcb_lib_entry_new +FreeLibraryMemory -> pcb_lib_free +DeleteLibraryMenuMemory -> pcb_lib_menu_free +CreateNewNet -> pcb_lib_net_new +CreateNewConnection -> pcb_lib_conn_new +ENTRIES -> PCB_ENTRIES +UNKNOWN -> PCB_UNKNOWN +NSTRCMP -> PCB_NSTRCMP +EMPTY -> PCB_EMPTY +EMPTY_STRING_P -> PCB_EMPTY_STRING_P +XOR -> PCB_XOR +SQUARE -> PCB_SQUARE +OBJECT_ID -> PCB_OBJECT_ID +FRONT -> PCB_FRONT +ON_SIDE -> PCB_ON_SIDE +TO_RADIANS -> PCB_TO_RADIANS +MAKEMIN -> PCB_MAKE_MIN +MAKEMAX -> PCB_MAKE_MAX +SGNZ -> PCB_SGNZ +SWAP_SIGN_X -> PCB_SWAP_SIGN_X +SWAP_SIGN_Y -> PCB_SWAP_SIGN_Y +Distance2 -> pcb_distance2 +Distance -> pcb_distance +GetValue -> pcb_get_value +GetValueEx -> pcb_get_value_ex +GetNum -> pcb_get_num +Concat -> pcb_concat +StripWhiteSpaceAndDup -> pcb_strdup_strip_wspace +MoveLayer -> pcb_layer_move +MOVE -> PCB_MOVE +MoveObject -> pcb_move_obj +MoveObjectToLayer -> pcb_move_obj_to_layer +MoveObjectAndRubberband -> pcb_move_obj_and_rubberband +MoveSelectedObjectsToLayer -> pcb_move_selected_objs_to_layer +GetNetMemory -> pcb_net_new +GetNetListMemory -> pcb_netlist_new +FreeNetListListMemory -> pcb_netlist_list_free +FreeNetListMemory -> pcb_netlist_free +FreeNetMemory -> pcb_net_free +NETLIST_LOOP -> PCB_NETLIST_LOOP +NET_LOOP -> PCB_NET_LOOP +GetArcMemory -> pcb_arc_new +GetElementArcMemory -> pcb_element_arc_new +RemoveFreeArc -> pcb_arc_free +GetElementMemory -> pcb_element_new +RemoveFreeElement -> pcb_element_free +FreeElementMemory -> pcb_element_free_fields +GetElementLineMemory -> pcb_element_line_new +GetLineMemory -> pcb_line_new +RemoveFreeLine -> pcb_line_free +CreateNewLineOnLayer -> pcb_line_new_on_layer +CreateDrawnLineOnLayer -> pcb_line_new_on_layer_merge +GetPadMemory -> pcb_pad_new +RemoveFreePad -> pcb_pad_free +CreateNewPad -> pcb_pad_new_in_element +SetPadBoundingBox -> pcb_pad_bbox +GetViaMemory -> pcb_via_new +RemoveFreeVia -> pcb_via_free +GetPinMemory -> pcb_pin_new +RemoveFreePin -> pcb_pin_free +CreateNewVia -> pcb_via_new_on_board +CreateNewPin -> pcb_pin_new_in_element +SetPinBoundingBox -> pcb_pin_bbox +GetPolygonMemory -> pcb_poly_alloc +RemoveFreePolygon -> pcb_poly_free +GetPointMemoryInPolygon -> pcb_poly_point_alloc +GetHoleIndexMemoryInPolygon -> pcb_poly_holeidx_new +FreePolygonMemory -> pcb_poly_free_fields +SetPolygonBoundingBox -> pcb_poly_bbox +CreateNewPolygonFromRectangle -> pcb_poly_new_from_rectangle +CreateNewPolygon -> pcb_poly_new +CreateNewPointInPolygon -> pcb_poly_point_new +CreateNewHoleInPolygon -> pcb_poly_hole_new +RemovePolygon -> pcb_poly_remove +GetRatMemory -> pcb_rat_alloc +RemoveFreeRat -> pcb_rat_free +CreateNewRat -> pcb_rat_new +DeleteRats -> pcb_rats_delete +GetTextMemory -> pcb_text_alloc +RemoveFreeText -> pcb_text_free +CreateNewText -> pcb_text_new +pcb_arc_new -> pcb_arc_alloc +CreateNewArcOnLayer -> pcb_arc_new +RemoveArc -> pcb_arc_destroy +pcb_element_arc_new -> pcb_element_arc_alloc +pcb_element_new -> pcb_element_alloc +pcb_element_free_fields -> pcb_element_destroy +pcb_line_new -> pcb_line_alloc +pcb_line_new_on_layer_merge -> pcb_line_new_merge +pcb_line_new_on_layer -> pcb_line_new +RemoveLine -> pcb_line_destroy +pcb_pad_new -> pcb_pad_alloc +pcb_pad_new_in_element -> pcb_element_pad_new +pcb_via_new -> pcb_via_alloc +pcb_pin_new -> pcb_pin_alloc +pcb_via_new_on_board -> pcb_via_new +pcb_pin_new_in_element -> pcb_element_pin_new +pcb_rats_delete -> pcb_rats_destroy +RemoveText -> pcb_text_destroy +SetArcBoundingBox -> pcb_arc_bbox +SetElementBoundingBox -> pcb_element_bbox +SetLineBoundingBox -> pcb_line_bbox +SetTextBoundingBox -> pcb_text_bbox +RotateArcLowLevel -> pcb_arc_rotate90 +RotateElementLowLevel -> pcb_element_rotate90 +RotateLineLowLevel -> pcb_line_rotate90 +RotatePolygonLowLevel -> pcb_poly_rotate90 +RotateTextLowLevel -> pcb_text_rotate90 +Freepcb_element_rotate90 -> pcb_element_rotate +Freepcb_element_rotate90 -> pcb_element_rotate +Freepcb_buffer_rotate -> pcb_buffer_free_rotate +GetArcEnds -> pcb_arc_get_ends +ChangeArcAngles -> pcb_arc_set_angles +ChangeArcRadii -> pcb_arc_set_radii +ChangeElementSide -> pcb_element_change_side +ChangeSelectedElementSide -> pcb_selected_element_change_side +ElementOrientation -> pcb_element_get_orientation +ChangePaste -> pcb_pad_change_paste +ChangeHole -> pcb_pin_change_hole +CreateNewElement -> pcb_element_new +CreateNewArcInElement -> pcb_element_arc_new +CreateNewLineInElement -> pcb_element_line_new +RemoveElement -> pcb_element_remove +MoveElementLowLevel -> pcb_element_move +MirrorElementCoordinates -> pcb_element_mirror +MovePolygonLowLevel -> pcb_poly_move +CopyPolygonLowLevel -> pcb_poly_copy +MOVE_TEXT_LOWLEVEL -> pcb_text_move +TEXT_IS_VISIBLE -> pcb_text_is_visible +MOVE_ARC_LOWLEVEL -> pcb_arc_move +MOVE_LINE_LOWLEVEL -> pcb_line_move +MOVE_PAD_LOWLEVEL -> pcb_pad_move +MOVE_PIN_LOWLEVEL -> pcb_pin_move +MOVE_VIA_LOWLEVEL -> pcb_via_move +ALLARC_LOOP -> PCB_ARC_ALL_LOOP +COPPERARC_LOOP -> PCB_ARC_COPPER_LOOP +SILKARC_LOOP -> PCB_ARC_SILK_LOOP +VISIBLEARC_LOOP -> PCB_ARC_VISIBLE_LOOP +ARC_LOOP -> PCB_ARC_LOOP +ELEMENTTEXT_LOOP -> PCB_ELEMENT_TEXT_LOOP +ELEMENTNAME_LOOP -> PCB_ELEMENT_NAME_LOOP +ELEMENTLINE_LOOP -> PCB_ELEMENT_LINE_LOOP +ELEMENTPCB_ARC_LOOP -> PCB_ELEMENT_ARC_LOOP +ELEMENT_LOOP -> PCB_ELEMENT_LOOP +ALLLINE_LOOP -> PCB_LINE_ALL_LOOP +COPPERLINE_LOOP -> PCB_LINE_COPPER_LOOP +SILKLINE_LOOP -> PCB_LINE_SILK_LOOP +VISIBLELINE_LOOP -> PCB_LINE_VISIBLE_LOOP +LINE_LOOP -> PCB_LINE_LOOP +ALLPAD_LOOP -> PCB_PAD_ALL_LOOP +PAD_LOOP -> PCB_PAD_LOOP +ALLPIN_LOOP -> PCB_PIN_ALL_LOOP +VIA_LOOP -> PCB_VIA_LOOP +PIN_LOOP -> PCB_PIN_LOOP +POLYGONPOINT_LOOP -> PCB_POLY_POINT_LOOP +ALLPOLYGON_LOOP -> PCB_POLY_ALL_LOOP +COPPERPOLYGON_LOOP -> PCB_POLY_COPPER_LOOP +SILKPOLYGON_LOOP -> PCB_POLY_SILK_LOOP +VISIBLEPOLYGON_LOOP -> PCB_POLY_VISIBLE_LOOP +POLYGON_LOOP -> PCB_POLY_LOOP +ALLTEXT_LOOP -> PCB_TEXT_ALL_LOOP +VISIBLETEXT_LOOP -> PCB_TEXT_VISIBLE_LOOP +TEXT_LOOP -> PCB_TEXT_LOOP +LoadElementToBuffer -> pcb_element_load_to_buffer +LoadFootprintByName -> pcb_element_load_footprint_by_name +SmashBufferElement -> pcb_element_smash_buffer +ConvertBufferToElement -> pcb_element_convert_from_buffer +CopyElementLowLevel -> pcb_element_copy +UniqueElementName -> pcb_element_uniq_name +AddTextToElement -> pcb_element_text_set +ChangeElementText -> pcb_element_text_change +resolve_path -> pcb_path_resolve +resolve_path_inplace -> pcb_path_resolve_inplace +resolve_paths -> pcb_paths_resolve +resolve_all_paths -> pcb_paths_resolve_all +fp_fopen -> pcb_fp_fopen +fp_fclose -> pcb_fp_fclose +fp_dupname -> pcb_fp_dupname +fp_tagname -> pcb_fp_tagname +fp_uninit -> pcb_fp_uninit +fp_tag -> pcb_fp_tag +fp_init -> pcb_fp_init +get_library_memory -> pcb_get_library_memory +fp_free_children -> pcb_fp_free_children +fp_sort_children -> pcb_fp_sort_children +fp_rmdir -> pcb_fp_rmdir +fp_mkdir_p -> pcb_fp_mkdir_p +fp_mkdir_len -> pcb_fp_mkdir_len +fp_lib_search -> pcb_fp_lib_search +fp_append_entry -> pcb_fp_append_entry +fp_read_lib_all -> pcb_fp_read_lib_all +fp_default_search_path -> pcb_fp_default_search_path +fp_host_uninit -> pcb_fp_host_uninit +fp_rehash -> pcb_fp_rehash +ImportNetlist -> pcb_import_netlist +ParsePCB -> pcb_parse_pcb +ParseElement -> pcb_parse_element +ParseFont -> pcb_parse_font +WriteBuffer -> pcb_write_buffer +WriteElementData -> pcb_write_element_data +CheckAndOpenFile -> pcb_check_and_open_file +OpenConnectionDataFile -> pcb_open_connection_file +SavePCB -> pcb_save_pcb +LoadPCB -> pcb_load_pcb +EnableAutosave -> pcb_enable_autosave +Backup -> pcb_backup +SaveInTMP -> pcb_save_in_tmp +EmergencySave -> pcb_emergency_save +DisableEmergencySave -> pcb_disable_emergency_save +RevertPCB -> pcb_revert_pcb +SaveBufferElements -> pcb_save_buffer_elements +PrintQuotedString -> pcb_print_quoted_string +sort_library -> pcb_library_sort +set_some_route_style -> pcb_set_some_route_style +WritePCBFile -> pcb_write_pcb_file +WritePipe -> pcb_write_pipe +SaveTMPData -> pcb_tmp_data_save +RemoveTMPData -> pcb_tmp_data_remove +plugins_init -> pcb_plugins_init +plugins_uninit -> pcb_plugins_uninit +plugin_register -> pcb_plugin_register +HOOK_CALL_DO -> PCB_HOOK_CALL_DO +HOOK_CALL_ALL -> PCB_HOOK_CALL_ALL +HOOK_UNREGISTER -> PCB_HOOK_UNREGISTER +HOOK_CALL -> PCB_HOOK_CALL +HOOK_REGISTER -> PCB_HOOK_REGISTER +poly_NewContour -> pcb_poly_contour_new +poly_IniContour -> pcb_poly_contour_init +poly_ClrContour -> pcb_poly_contour_clear +poly_DelContour -> pcb_poly_contour_del +poly_CopyContour -> pcb_poly_contour_copy +poly_PreContour -> pcb_poly_contour_pre +poly_InvContour -> pcb_poly_contour_inv +poly_CreateNode -> pcb_poly_node_create +poly_InclVertex -> pcb_poly_vertex_include +poly_ExclVertex -> pcb_poly_vertex_exclude +poly_M_Copy0 -> pcb_poly_m_copy0 +poly_M_Incl -> pcb_poly_m_include +poly_Copy0 -> pcb_poly_copy0 +poly_Copy1 -> pcb_poly_copy1 +poly_InclContour -> pcb_poly_contour_include +poly_ExclContour -> pcb_poly_contour_exclide +poly_ChkContour -> pcb_poly_contour_check +poly_CheckInside -> pcb_poly_contour_inside +Touching -> pcb_poly_touching +pcb_poly_m_copy0 -> pcb_polyarea_m_copy0 +pcb_poly_m_include -> pcb_polyarea_m_include +pcb_poly_copy0 -> pcb_polyarea_copy0 +pcb_poly_copy1 -> pcb_polyarea_copy1 +pcb_poly_contour_include -> pcb_polyarea_contour_include +pcb_poly_contour_exclide -> pcb_polyarea_contour_exclide +pcb_poly_contour_check -> pcb_polyarea_contour_check +pcb_poly_contour_inside -> pcb_polyarea_contour_inside +pcb_poly_touching -> pcb_polyarea_touching +poly_InsideContour -> pcb_poly_contour_inside +poly_ContourInContour -> pcb_poly_contour_in_contour +poly_Create -> pcb_polyarea_create +poly_Free -> pcb_polyarea_free +poly_Init -> pcb_polyarea_init +poly_FreeContours -> pcb_poly_contours_free +poly_Valid -> pcb_poly_valid +vect_dist2 -> pcb_vect_dist2 +vect_det2 -> pcb_vect_det2 +vect_len2 -> pcb_vect_len2 +vect_inters2 -> pcb_vect_inters2 +poly_Boolean -> pcb_polyarea_boolean +poly_Boolean_free -> pcb_polyarea_boolean_free +poly_AndSubtract_free -> pcb_polyarea_and_subtract_free +poly_bbox -> pcb_polyarea_bbox +Savepcb_polyarea_t -> pcb_polyarea_save +polygon_init -> pcb_polygon_init +polygon_point_idx -> pcb_poly_point_idx +polygon_point_contour -> pcb_poly_contour_point +prev_contour_point -> pcb_poly_contour_prev_point +next_contour_point -> pcb_poly_contour_next_point +GetLowestDistancePolygonPoint -> pcb_poly_get_lowest_distance_point +RemoveExcessPolygonPoints -> pcb_poly_remove_excess_points +GoToPreviousPoint -> pcb_polygon_go_to_prev_point +ClosePolygon -> pcb_polygon_close_poly +CopyAttachedPolygonToLayer -> pcb_polygon_copy_attached_to_layer +PolygonHoles -> pcb_poly_holes +PlowsPolygon -> pcb_poly_plows +ComputeNoHoles -> pcb_poly_compute_no_holes +ContourToPoly -> pcb_poly_from_contour +PolygonToPoly -> pcb_poly_from_poly +RectPoly -> pcb_poly_from_rect +CirclePoly -> pcb_poly_from_circle +OctagonPoly -> pcb_poly_from_octagon +LinePoly -> pcb_poly_from_line +ArcPoly -> pcb_poly_from_arc +PinPoly -> pcb_poly_from_pin +BoxPolyBloated -> pcb_poly_from_box_bloated +ContourToPoly -> pcb_poly_from_contour +PolygonToPoly -> pcb_poly_from_poly +RectPoly -> pcb_poly_from_rect +CirclePoly -> pcb_poly_from_circle +OctagonPoly -> pcb_poly_from_octagon +LinePoly -> pcb_poly_from_line +ArcPoly -> pcb_poly_from_arc +PinPoly -> pcb_poly_from_pin +BoxPolyBloated -> pcb_poly_from_box_bloated +frac_circle -> pcb_poly_frac_circle +InitClip -> pcb_poly_init_clip +RestoreToPolygon -> pcb_poly_restore_to_poly +ClearFromPolygon -> pcb_poly_clear_from_poly +IsPointInPolygon -> pcb_poly_is_point_in_p +IsPointInPolygonIgnoreHoles -> pcb_poly_is_point_in_p_ignore_holes +IsRectangleInPolygon -> pcb_poly_is_rect_in_p +isects -> pcb_poly_isects_poly +MorphPolygon -> pcb_poly_morph +NoHolesPolygonDicer -> pcb_poly_no_holes_dicer +PolyToPolygonsOnLayer -> pcb_poly_to_polygons_on_layer +square_pin_factors -> pcb_poly_square_pin_factors +AddNet -> pcb_rat_add_net +ConnectionName -> pcb_connection_name +AddAllRats -> pcb_rat_add_all +SeekPad -> pcb_rat_seek_pad +ProcNetlist -> pcb_rat_proc_netlist +CollectSubnets -> pcb_rat_collect_subnets +GetConnectionMemory -> pcb_rat_connection_alloc +CONNECTION_LOOP -> PCB_CONNECTION_LOOP +RAT_LOOP -> PCB_RAT_LOOP +rats_patch_append -> pcb_ratspatch_append +rats_patch_destroy -> pcb_ratspatch_destroy +rats_patch_append_optimize -> pcb_ratspatch_append_optimize +rats_patch_make_edited -> pcb_ratspatch_make_edited +rats_patch_apply -> pcb_ratspatch_apply +rats_patch_fexport -> pcb_ratspatch_fexport +RemovePCB -> pcb_board_remove +RemoveSelected -> pcb_remove_selected +RemoveObject -> pcb_remove_object +DestroyObject -> pcb_destroy_object +ROTATE -> PCB_ROTATE90 +PIN_ROTATE -> PCB_PIN_ROTATE_SHAPE +ROTATE_VIA_LOWLEVEL -> PCB_VIA_ROTATE90 +ROTATE_PIN_LOWLEVEL -> PCB_PIN_ROTATE90 +ROTATE_PAD_LOWLEVEL -> PCB_PAD_ROTATE90 +RotateBoxLowLevel -> pcb_box_rotate90 +RotateObject -> pcb_obj_rotate90 +RotateScreenObject -> pcb_screen_obj_rotate90 +RotatePointLowLevel -> pcb_point_rotate90 +free_rotate -> pcb_rotate +PCB_ROTATE90 -> PCB_COORD_ROTATE90 +ParseRoutingString1 -> pcb_route_string_parse1 +ParseRouteString -> pcb_route_string_parse +make_route_string -> pcb_route_string_make +r_create_tree -> pcb_r_create_tree +r_destroy_tree -> pcb_r_destroy_tree +r_delete_entry -> pcb_r_delete_entry +r_insert_entry -> pcb_r_insert_entry +r_search -> pcb_r_search +r_region_is_empty -> pcb_r_region_is_empty +__r_dump_tree -> pcb_r_dump_tree +LookupRubberbandLines -> pcb_rubber_band_lookup_lines +LookupRatLines -> pcb_rubber_band_lookup_rat_lines +GetRubberbandMemory -> pcb_rubber_band_alloc +CreateNewRubberbandEntry -> pcb_rubber_band_create +IsPointOnLine -> pcb_is_point_on_line +IsPointOnPin -> pcb_is_point_in_pin +IsPointOnArc -> pcb_is_point_on_arc +IsPointOnLineEnd -> pcb_is_point_on_line_end +IsLineInRectangle -> pcb_is_line_in_rectangle +IsLineInQuadrangle -> pcb_is_line_in_quadrangle +IsArcInRectangle -> pcb_is_arc_in_rectangle +IsPointInPad -> pcb_is_point_in_pad +IsPointInBox -> pcb_is_point_in_box +lines_intersect -> pcb_lines_intersect +POINT_IN_BOX -> PCB_POINT_IN_BOX +VIA_OR_PIN_IN_BOX -> PCB_VIA_OR_PIN_IN_BOX +LINE_IN_BOX -> PCB_LINE_IN_BOX +PAD_IN_BOX -> PCB_PAD_IN_BOX +BOX_IN_BOX -> PCB_BOX_IN_BOX +TEXT_IN_BOX -> PCB_TEXT_IN_BOX +POLYGON_IN_BOX -> PCB_POLYGON_IN_BOX +ELEMENT_IN_BOX -> PCB_ELEMENT_IN_BOX +ARC_IN_BOX -> PCB_ARC_IN_BOX +POINT_IN_CIRCLE -> PCB_POINT_IN_CIRCLE +CIRCLE_TOUCHES_BOX -> PCB_CIRCLE_TOUCHES_BOX +VIA_OR_PIN_TOUCHES_BOX -> PCB_VIA_OR_PIN_TOUCHES_BOX +LINE_TOUCHES_BOX -> PCB_LINE_TOUCHES_BOX +PAD_TOUCHES_BOX -> PCB_PAD_TOUCHES_BOX +BOX_TOUCHES_BOX -> PCB_BOX_TOUCHES_BOX +TEXT_TOUCHES_BOX -> PCB_TEXT_TOUCHES_BOX +POLYGON_TOUCHES_BOX -> PCB_POLYGON_TOUCHES_BOX +ELEMENT_TOUCHES_BOX -> PCB_ELEMENT_TOUCHES_BOX +ARC_TOUCHES_BOX -> PCB_ARC_TOUCHES_BOX +IS_BOX_NEGATIVE -> PCB_IS_BOX_NEGATIVE +BOX_NEAR_BOX -> PCB_BOX_NEAR_BOX +VIA_OR_PIN_NEAR_BOX -> PCB_VIA_OR_PIN_NEAR_BOX +LINE_NEAR_BOX -> PCB_LINE_NEAR_BOX +PAD_NEAR_BOX -> PCB_PAD_NEAR_BOX +TEXT_NEAR_BOX -> PCB_TEXT_NEAR_BOX +POLYGON_NEAR_BOX -> PCB_POLYGON_NEAR_BOX +ELEMENT_NEAR_BOX -> PCB_ELEMENT_NEAR_BOX +ARC_NEAR_BOX -> PCB_ARC_NEAR_BOX +SearchObjectByLocation -> pcb_search_obj_by_location +SearchScreen -> pcb_search_screen +SearchScreenGridSlop -> pcb_search_grid_slop +SearchObjectByID -> pcb_search_obj_by_id +SearchElementByName -> pcb_search_elem_by_name +SelectObject -> pcb_select_object +SelectBlock -> pcb_select_block +ListBlock -> pcb_list_block +ObjectOperation -> pcb_object_operation +SelectedOperation -> pcb_selected_operation +SelectConnection -> pcb_select_connection +SelectObjectByName -> pcb_select_object_by_name +SetTextScale -> pcb_text_set_scale +SetGrid -> pcb_board_set_grid +SetLineSize -> pcb_line_set_size +SetViaSize -> pcb_via_set_size +SetViaDrillingHole -> pcb_via_set_drilling_hole +SetClearanceWidth -> pcb_conf_set_clearance_width +SetChangedFlag -> pcb_board_set_changed_flag +SetBufferNumber -> pcb_buffer_set_number +SetMode -> pcb_crosshair_set_mode +SetCrosshairRangeToBuffer -> pcb_crosshair_range_to_buffer +SetLocalRef -> pcb_crosshair_set_local_ref +SaveMode -> pcb_crosshair_save_mode +RestoreMode -> pcb_crosshair_restore_mode +pcb_text_set_scale -> pcb_board_set_text_scale +pcb_line_set_size -> pcb_board_set_line_width +pcb_via_set_size -> pcb_board_set_via_size +pcb_via_set_drilling_hole -> pcb_board_set_via_drilling_hole +pcb_conf_set_clearance_width -> pcb_board_set_clearance +stub_DrawFab_overhang -> pcb_stub_draw_fab_overhang +stub_DrawFab -> pcb_stub_draw_fab +stub_rat_found_short -> pcb_stub_rat_found_short +stub_rat_proc_shorts -> pcb_stub_rat_proc_shorts +Undo -> pcb_undo +Redo -> pcb_redo +IncrementUndoSerialNumber -> pcb_undo_inc_serial +SaveUndoSerialNumber -> pcb_undo_save_serial +RestoreUndoSerialNumber -> pcb_undo_restore_serial +ClearUndoList -> pcb_undo_clear_list +LockUndo -> pcb_undo_lock +UnlockUndo -> pcb_undo_unlock +Undoing -> pcb_undoing +MoveObjectToRemoveUndoList -> pcb_undo_move_obj_to_remove +AddObjectToRemovePointUndoList -> pcb_undo_add_obj_to_remove_point +AddObjectToInsertPointUndoList -> pcb_undo_add_obj_to_insert_point +AddObjectToRemoveContourUndoList -> pcb_undo_add_obj_to_remove_contour +AddObjectToInsertContourUndoList -> pcb_undo_add_obj_to_insert_contour +AddObjectToMoveUndoList -> pcb_undo_add_obj_to_move +AddObjectToChangeNameUndoList -> pcb_undo_add_obj_to_change_name +AddObjectToChangePinnumUndoList -> pcb_undo_add_obj_to_change_pinnum +AddObjectToRotateUndoList -> pcb_undo_add_obj_to_rotate +AddObjectToCreateUndoList -> pcb_undo_add_obj_to_create +AddObjectToMirrorUndoList -> pcb_undo_add_obj_to_mirror +AddObjectToMoveToLayerUndoList -> pcb_undo_add_obj_to_move_to_layer +AddObjectToFlagUndoList -> pcb_undo_add_obj_to_flag +AddObjectToSizeUndoList -> pcb_undo_add_obj_to_size +AddObjectTo2ndSizeUndoList -> pcb_undo_add_obj_to_2nd_size +AddObjectToClearSizeUndoList -> pcb_undo_add_obj_to_clear_size +AddObjectToMaskSizeUndoList -> pcb_undo_add_obj_to_mask_size +AddObjectToChangeAnglesUndoList -> pcb_undo_add_obj_to_change_angles +AddObjectToChangeRadiiUndoList -> pcb_undo_add_obj_to_change_radii +AddObjectToClearPolyUndoList -> pcb_undo_add_obj_to_clear_poly +AddLayerChangeToUndoList -> pcb_undo_add_layer_change +AddNetlistLibToUndoList -> pcb_undo_add_netlist_lib +get_n_units -> pcb_get_n_units +coord_to_unit -> pcb_coord_to_unit +unit_to_factor -> pcb_unit_to_factor +unit_to_coord -> pcb_unit_to_coord +get_increments_struct -> pcb_get_increments_struct +NormalizeAngle -> pcb_normalize_angle +initialize_units -> pcb_units_init +UNDO_CHANGENAME -> PCB_UNDO_CHANGENAME +UNDO_MOVE -> PCB_UNDO_MOVE +UNDO_REMOVE -> PCB_UNDO_REMOVE +UNDO_REMOVE_POINT -> PCB_UNDO_REMOVE_POINT +UNDO_INSERT_POINT -> PCB_UNDO_INSERT_POINT +UNDO_REMOVE_CONTOUR -> PCB_UNDO_REMOVE_CONTOUR +UNDO_INSERT_CONTOUR -> PCB_UNDO_INSERT_CONTOUR +UNDO_ROTATE -> PCB_UNDO_ROTATE +UNDO_CREATE -> PCB_UNDO_CREATE +UNDO_MOVETOLAYER -> PCB_UNDO_MOVETOLAYER +UNDO_FLAG -> PCB_UNDO_FLAG +UNDO_CHANGESIZE -> PCB_UNDO_CHANGESIZE +UNDO_CHANGE2NDSIZE -> PCB_UNDO_CHANGE2NDSIZE +UNDO_MIRROR -> PCB_UNDO_MIRROR +UNDO_CHANGECLEARSIZE -> PCB_UNDO_CHANGECLEARSIZE +UNDO_CHANGEMASKSIZE -> PCB_UNDO_CHANGEMASKSIZE +UNDO_CHANGEANGLES -> PCB_UNDO_CHANGEANGLES +UNDO_LAYERCHANGE -> PCB_UNDO_LAYERCHANGE +UNDO_CLEAR -> PCB_UNDO_CLEAR +UNDO_NETLISTCHANGE -> PCB_UNDO_NETLISTCHANGE +UNDO_CHANGEPINNUM -> PCB_UNDO_CHANGEPINNUM +UNDO_CHANGERADII -> PCB_UNDO_CHANGERADII +ROTATE_TYPES -> PCB_ROTATE_TYPES +CHANGENAME_TYPES -> PCB_CHANGENAME_TYPES +CHANGESIZE_TYPES -> PCB_CHANGESIZE_TYPES +CHANGE2NDSIZE_TYPES -> PCB_CHANGE2NDSIZE_TYPES +CHANGECLEARSIZE_TYPES -> PCB_CHANGECLEARSIZE_TYPES +CHANGENONETLIST_TYPES -> PCB_CHANGENONETLIST_TYPES +CHANGESQUARE_TYPES -> PCB_CHANGESQUARE_TYPES +CHANGEOCTAGON_TYPES -> PCB_CHANGEOCTAGON_TYPES +CHANGEJOIN_TYPES -> PCB_CHANGEJOIN_TYPES +CHANGETHERMAL_TYPES -> PCB_CHANGETHERMAL_TYPES +CHANGEMASKSIZE_TYPES -> PCB_CHANGEMASKSIZE_TYPES +SELECT_TYPES -> PCB_SELECT_TYPES +MOVE_TYPES -> PCB_MOVE_TYPES +MOVETOLAYER_TYPES -> PCB_MOVETOLAYER_TYPES +INSERT_TYPES -> PCB_INSERT_TYPES +COPY_TYPES -> PCB_COPY_TYPES +REMOVE_TYPES -> PCB_REMOVE_TYPES +NETLIST_INPUT -> PCB_NETLIST_INPUT +NETLIST_EDITED -> PCB_NETLIST_EDITED +NUM_NETLISTS -> PCB_NUM_NETLISTS +ATTRIBUTE_UNUSED -> PCB_ATTRIBUTE_UNUSED +UNLIKELY -> PCB_UNLIKELY +LIKELY -> PCB_LIKELY +STATE_FIRST -> PCB_CH_STATE_FIRST +STATE_SECOND -> PCB_CH_STATE_SECOND +STATE_THIRD -> PCB_CH_STATE_THIRD +Basic_Crosshair_Shape -> pcb_ch_shape_basic +Union_Jack_Crosshair_Shape -> pcb_ch_shape_union_jack +Dozen_Crosshair_Shape -> pcb_ch_shape_dozen +Crosshair_Shapes_Number -> pcb_ch_shape_NUM +Crosshair -> pcb_crosshair +Marked -> pcb_marked +max_group -> pcb_max_group +max_copper_layer -> pcb_max_copper_layer +solder_silk_layer -> pcb_solder_silk_layer +component_silk_layer -> pcb_component_silk_layer +Buffers -> pcb_buffers +addedLines -> pcb_added_lines +LayerStack -> pcb_layer_stack +Bumped -> pcb_bumped +STATUS_OK -> 0 +STATUS_ERROR -> -1 +EVENT_GUI_INIT -> PCB_EVENT_GUI_INIT +EVENT_CLI_ENTER -> PCB_EVENT_CLI_ENTER +EVENT_SAVE_PRE -> PCB_EVENT_SAVE_PRE +EVENT_SAVE_POST -> PCB_EVENT_SAVE_POST +EVENT_LOAD_PRE -> PCB_EVENT_LOAD_PRE +EVENT_LOAD_POST -> PCB_EVENT_LOAD_POST +EVENT_last -> PCB_EVENT_last +ARG_INT -> PCB_EVARG_INT +ARG_DOUBLE -> PCB_EVARG_DOUBLE +ARG_STR -> PCB_EVARG_STR +LOOKUP_FIRST -> PCB_LOOKUP_FIRST +LOOKUP_MORE -> PCB_LOOKUP_MORE +SILK_TYPE -> PCB_SILK_TYPE +FCT_COPPER -> PCB_FCT_COPPER +FCT_INTERNAL -> PCB_FCT_INTERNAL +FCT_RAT -> PCB_FCT_RAT +FCT_ELEMENT -> PCB_FCT_ELEMENT +FCT_START -> PCB_FCT_START +find_callback_t -> pcb_find_callback_t +find_callback -> pcb_find_callback +SHOWNUMBERFLAG -> PCB_SHOWNUMBERFLAG +LOCALREFFLAG -> PCB_LOCALREFFLAG +CHECKPLANESFLAG -> PCB_CHECKPLANESFLAG +SHOWPCB_FLAG_DRC -> PCB_SHOWPCB_FLAG_DRC +RUBBERBANDFLAG -> PCB_RUBBERBANDFLAG +DESCRIPTIONFLAG -> PCB_DESCRIPTIONFLAG +NAMEONPCBFLAG -> PCB_NAMEONPCBFLAG +AUTOPCB_FLAG_DRC -> PCB_AUTOPCB_FLAG_DRC +ALLDIRECTIONFLAG -> PCB_ALLDIRECTIONFLAG +SWAPSTARTDIRFLAG -> PCB_SWAPSTARTDIRFLAG +UNIQUENAMEFLAG -> PCB_UNIQUENAMEFLAG +CLEARNEWFLAG -> PCB_CLEARNEWFLAG +SNAPPCB_FLAG_PIN -> PCB_SNAPPCB_FLAG_PIN +SHOWMASKFLAG -> PCB_SHOWMASKFLAG +THINDRAWFLAG -> PCB_THINDRAWFLAG +ORTHOMOVEFLAG -> PCB_ORTHOMOVEFLAG +LIVEROUTEFLAG -> PCB_LIVEROUTEFLAG +THINDRAWPOLYFLAG -> PCB_THINDRAWPOLYFLAG +LOCKNAMESFLAG -> PCB_LOCKNAMESFLAG +ONLYNAMESFLAG -> PCB_ONLYNAMESFLAG +NEWPCB_FLAG_FULLPOLY -> PCB_NEWPCB_FLAG_FULLPOLY +HIDENAMESFLAG -> PCB_HIDENAMESFLAG +ENABLEPCB_FLAG_MINCUT -> PCB_ENABLEPCB_FLAG_MINCUT +GROUNDPLANEFRAME -> PCB_GROUNDPLANEFRAME +MASKFRAME -> PCB_MASKFRAME +LARGE_VALUE -> PCB_LARGE_VALUE +MAX_LAYER -> PCB_MAX_LAYER +MIN_LINESIZE -> PCB_MIN_LINESIZE +MAX_LINESIZE -> PCB_MAX_LINESIZE +MIN_ARCSIZE -> PCB_MIN_ARCSIZE +MAX_ARCSIZE -> PCB_MAX_ARCSIZE +MIN_TEXTSCALE -> PCB_MIN_TEXTSCALE +MAX_TEXTSCALE -> PCB_MAX_TEXTSCALE +MIN_PINORVIASIZE -> PCB_MIN_PINORVIASIZE +MIN_PINORVIAHOLE -> PCB_MIN_PINORVIAHOLE +MAX_PINORVIASIZE -> PCB_MAX_PINORVIASIZE +MIN_PINORVIACOPPER -> PCB_MIN_PINORVIACOPPER +MIN_PADSIZE -> PCB_MIN_PADSIZE +MAX_PADSIZE -> PCB_MAX_PADSIZE +MIN_DRC_VALUE -> PCB_MIN_DRC_VALUE +MAX_DRC_VALUE -> PCB_MAX_DRC_VALUE +MIN_DRC_SILK -> PCB_MIN_DRC_SILK +MAX_DRC_SILK -> PCB_MAX_DRC_SILK +MIN_DRC_DRILL -> PCB_MIN_DRC_DRILL +MAX_DRC_DRILL -> PCB_MAX_DRC_DRILL +MIN_DRC_RING -> PCB_MIN_DRC_RING +MAX_DRC_RING -> PCB_MAX_DRC_RING +MIN_GRID -> PCB_MIN_GRID +MAX_GRID -> PCB_MAX_GRID +MAX_FONTPOSITION -> PCB_MAX_FONTPOSITION +MAX_COORD -> PCB_MAX_COORD +MIN_SIZE -> PCB_MIN_SIZE +MAX_SIZE -> PCB_MAX_SIZE +MAX_BUFFER -> PCB_MAX_BUFFER +DEFAULT_DRILLINGHOLE -> PCB_DEFAULT_DRILLINGHOLE +MAXPATHLEN -> PCB_PATH_MAX +MAX_LINE_POINT_DISTANCE -> PCB_MAX_LINE_POINT_DISTANCE +MAX_POLYGON_POINT_DISTANCE -> PCB_MAX_POLYGON_POINT_DISTANCE +MAX_ELEMENTNAMES -> PCB_MAX_ELEMENTNAMES +MAX_NETLIST_LINE_LENGTH -> PCB_MAX_NETLIST_LINE_LENGTH +MAX_MODESTACK_DEPTH -> PCB_MAX_MODESTACK_DEPTH +MIN_GRID_DISTANCE -> PCB_MIN_GRID_DISTANCE +EMARK_SIZE -> PCB_EMARK_SIZE +FONT_CAPHEIGHT -> PCB_FONT_CAPHEIGHT +DEFAULT_CELLSIZE -> PCB_DEFAULT_CELLSIZE +next_gui -> pcb_next_gui +current_action -> pcb_current_action +pixel_slop -> pcb_pixel_slop +MF_ACCELERATOR -> PCB_MF_ACCELERATOR +MF_MNEMONIC -> PCB_MF_MNEMONIC +MF_SUBMENU -> PCB_MF_SUBMENU +MF_CHECKED -> PCB_MF_CHECKED +MF_UPDATE_ON -> PCB_MF_UPDATE_ON +MF_SENSITIVE -> PCB_MF_SENSITIVE +MF_TIP -> PCB_MF_TIP +MF_ACTIVE -> PCB_MF_ACTIVE +MF_ACTION -> PCB_MF_ACTION +MF_FOREGROUND -> PCB_MF_FOREGROUND +MF_BACKGROUND -> PCB_MF_BACKGROUND +MF_FONT -> PCB_MF_FONT +M_Shift -> PCB_M_Shift +M_Ctrl -> PCB_M_Ctrl +M_Alt -> PCB_M_Alt +M_Mod1 -> PCB_M_Mod1 +M_Release -> PCB_M_Release +MB_LEFT -> PCB_MB_LEFT +MB_MIDDLE -> PCB_MB_MIDDLE +MB_RIGHT -> PCB_MB_RIGHT +MB_SCROLL_UP -> PCB_MB_SCROLL_UP +MB_SCROLL_DOWN -> PCB_MB_SCROLL_DOWN +MB_SCROLL_LEFT -> PCB_MB_SCROLL_LEFT +MB_SCROLL_RIGHT -> PCB_MB_SCROLL_RIGHT +MB_ANY -> PCB_MB_ANY +M_ANY -> PCB_M_ANY +hid_list -> pcb_hid_list +hid_num_hids -> pcb_hid_num_hids +MENU_LOOP -> PCB_MENU_LOOP +ENTRY_LOOP -> PCB_ENTRY_LOOP +SWAP_IDENT -> PCB_SWAP_IDENT +END_LOOP -> PCB_END_LOOP +ENDALL_LOOP -> PCB_ENDALL_LOOP +pcb_create_be_lenient -> pcb_create_being_lenient +CreateBeLenient -> pcb_create_be_lenient +CreateIDBump -> pcb_create_ID_bump +CreateIDReset -> pcb_create_ID_reset +CreateIDGet -> pcb_create_ID_get +DESCRIPTION_INDEX -> PCB_ELEMNAME_IDX_DESCRIPTION +NAMEONPCB_INDEX -> PCB_ELEMNAME_IDX_REFDES +VALUE_INDEX -> PCB_ELEMNAME_IDX_VALUE +NAME_INDEX -> PCB_ELEMNAME_IDX_VISIBLE +ELEMENT_NAME -> PCB_ELEM_NAME_VISIBLE +DESCRIPTION_NAME -> PCB_ELEM_NAME_DESCRIPTION +NAMEONPCB_NAME -> PCB_ELEM_NAME_REFDES +VALUE_NAME -> PCB_ELEM_NAME_VALUE +ELEMENT_TEXT -> PCB_ELEM_TEXT_VISIBLE +DESCRIPTION_TEXT -> PCB_ELEM_TEXT_DESCRIPTION +NAMEONPCB_TEXT -> PCB_ELEM_TEXT_REFDES +VALUE_TEXT -> PCB_ELEM_TEXT_VALUE +AdjustAttachedLine -> pcb_line_adjust_attached +AdjustTwoLine -> pcb_line_adjust_attached_2lines +FortyFiveLine -> pcb_line_45 +EnforceLineDRC -> pcb_line_enforce_drc +library -> pcb_library +gui -> pcb_gui +exporter -> pcb_exporter +plug_fp_chain -> pcb_plug_fp_chain +plug_import_chain -> pcb_plug_import_chain +plug_io_chain -> pcb_plug_io_chain +PLF_DIR -> PCB_PLF_DIR +PLF_INV -> PCB_PLF_INV +PLF_MARK -> PCB_PLF_MARK +VertexEqu -> pcb_vertex_equ +VertexCpy -> pcb_vertex_cpy +err_no_memory -> pcb_err_no_memory +err_bad_parm -> pcb_err_bad_parm +err_ok -> pcb_err_ok +PBO_UNITE -> PCB_PBO_UNITE +PBO_ISECT -> PCB_PBO_ISECT +PBO_SUB -> PCB_PBO_SUB +PBO_XOR -> PCB_PBO_XOR +POLY_CIRC_SEGS -> PCB_POLY_CIRC_SEGS +POLY_CIRC_SEGS_F -> PCB_POLY_CIRC_SEGS_F +POLY_CIRC_RADIUS_ADJ -> PCB_POLY_CIRC_RADIUS_ADJ +POLY_ARC_MAX_DEVIATION -> PCB_POLY_ARC_MAX_DEVIATION +R_DIR_NOT_FOUND -> PCB_R_DIR_NOT_FOUND +R_DIR_FOUND_CONTINUE -> PCB_R_DIR_FOUND_CONTINUE +R_DIR_CANCEL -> PCB_R_DIR_CANCEL +SLOP -> PCB_SLOP +SM_REGEX -> PCB_SM_REGEX +SM_LIST -> PCB_SM_LIST +SWAP_ANGLE -> PCB_SWAP_ANGLE +SWAP_DELTA -> PCB_SWAP_DELTA +METRIC -> PCB_UNIT_METRIC +IMPERIAL -> PCB_UNIT_IMPERIAL +NO_SUFFIX -> PCB_UNIT_NO_SUFFIX +SUFFIX -> PCB_UNIT_SUFFIX +FILE_MODE -> PCB_UNIT_FILE_MODE +NO_PRINT -> PCB_UNIT_NO_PRINT +ALLOW_NM -> PCB_UNIT_ALLOW_NM +ALLOW_UM -> PCB_UNIT_ALLOW_UM +ALLOW_MM -> PCB_UNIT_ALLOW_MM +ALLOW_CM -> PCB_UNIT_ALLOW_CM +ALLOW_M -> PCB_UNIT_ALLOW_M +ALLOW_KM -> PCB_UNIT_ALLOW_KM +ALLOW_CMIL -> PCB_UNIT_ALLOW_CMIL +ALLOW_MIL -> PCB_UNIT_ALLOW_MIL +ALLOW_IN -> PCB_UNIT_ALLOW_IN +ALLOW_DMIL -> PCB_UNIT_ALLOW_DMIL +ALLOW_METRIC -> PCB_UNIT_ALLOW_METRIC +ALLOW_IMPERIAL -> PCB_UNIT_ALLOW_IMPERIAL +ALLOW_READABLE -> PCB_UNIT_ALLOW_READABLE +ALLOW_NATURAL -> PCB_UNIT_ALLOW_NATURAL +ALLOW_ALL -> PCB_UNIT_ALLOW_ALL +ActionExecuteFile -> pcb_act_ExecuteFile +executefile_help -> pcb_acth_ExecuteFile +executefile_syntax -> pcb_acts_ExecuteFile +ActionChangeAngle -> pcb_act_ChangeAngle +changeangle_help -> pcb_acth_ChangeAngle +changeangle_syntax -> pcb_acts_ChangeAngle +ActionChangeClearSize -> pcb_act_ChangeClearSize +changeclearsize_help -> pcb_acth_ChangeClearSize +changeclearsize_syntax -> pcb_acts_ChangeClearSize +ActionChange2ndSize -> pcb_act_Change2ndSize +change2ndsize_help -> pcb_acth_Change2ndSize +change2ndsize_syntax -> pcb_acts_Change2ndSize +ActionChangeHole -> pcb_act_ChangeHole +changehole_help -> pcb_acth_ChangeHole +changehole_syntax -> pcb_acts_ChangeHole +ActionChangeJoin -> pcb_act_ChangeJoin +changejoin_help -> pcb_acth_ChangeJoin +changejoin_syntax -> pcb_acts_ChangeJoin +ActionChangeName -> pcb_act_ChangeName +changename_help -> pcb_acth_ChangeName +changename_syntax -> pcb_acts_ChangeName +ActionChangePaste -> pcb_act_ChangePaste +changepaste_help -> pcb_acth_ChangePaste +changepaste_syntax -> pcb_acts_ChangePaste +ActionChangePinName -> pcb_act_ChangePinName +changepinname_help -> pcb_acth_ChangePinName +changepinname_syntax -> pcb_acts_ChangePinName +ActionChangeRadius -> pcb_act_ChangeRadius +changeradius_help -> pcb_acth_ChangeRadius +changeradius_syntax -> pcb_acts_ChangeRadius +ActionChangeSize -> pcb_act_ChangeSize +changesize_help -> pcb_acth_ChangeSize +changesize_syntax -> pcb_acts_ChangeSize +ActionChangeSizes -> pcb_act_ChangeSizes +changesizes_help -> pcb_acth_ChangeSizes +changesizes_syntax -> pcb_acts_ChangeSizes +ActionChangeNonetlist -> pcb_act_ChangeNonetlist +changenonetlist_help -> pcb_acth_ChangeNonetlist +changenonetlist_syntax -> pcb_acts_ChangeNonetlist +ActionChangeSquare -> pcb_act_ChangeSquare +changesquare_help -> pcb_acth_ChangeSquare +changesquare_syntax -> pcb_acts_ChangeSquare +ActionChangeOctagon -> pcb_act_ChangeOctagon +changeoctagon_help -> pcb_acth_ChangeOctagon +changeoctagon_syntax -> pcb_acts_ChangeOctagon +ActionChangeFlag -> pcb_act_ChangeFlag +changeflag_help -> pcb_acth_ChangeFlag +changeflag_syntax -> pcb_acts_ChangeFlag +ActionClearSquare -> pcb_act_ClearSquare +clearsquare_help -> pcb_acth_ClearSquare +clearsquare_syntax -> pcb_acts_ClearSquare +ActionClearOctagon -> pcb_act_ClearOctagon +clearoctagon_help -> pcb_acth_ClearOctagon +clearoctagon_syntax -> pcb_acts_ClearOctagon +ActionSetSquare -> pcb_act_SetSquare +setsquare_help -> pcb_acth_SetSquare +setsquare_syntax -> pcb_acts_SetSquare +ActionSetOctagon -> pcb_act_SetOctagon +setoctagon_help -> pcb_acth_SetOctagon +setoctagon_syntax -> pcb_acts_SetOctagon +ActionSetThermal -> pcb_act_SetThermal +setthermal_help -> pcb_acth_SetThermal +setthermal_syntax -> pcb_acts_SetThermal +ActionSetValue -> pcb_act_SetValue +setvalue_help -> pcb_acth_SetValue +setvalue_syntax -> pcb_acts_SetValue +ActionSetFlag -> pcb_act_SetFlag +setflag_help -> pcb_acth_SetFlag +setflag_syntax -> pcb_acts_SetFlag +ActionClrFlag -> pcb_act_ClrFlag +clrflag_help -> pcb_acth_ClrFlag +clrflag_syntax -> pcb_acts_ClrFlag +ActionExecCommand -> pcb_act_ExecCommand +execcommand_help -> pcb_acth_ExecCommand +execcommand_syntax -> pcb_acts_ExecCommand +ActionLoadFrom -> pcb_act_LoadFrom +loadfrom_help -> pcb_acth_LoadFrom +loadfrom_syntax -> pcb_acts_LoadFrom +ActionNew -> pcb_act_New +new_help -> pcb_acth_New +new_syntax -> pcb_acts_New +ActionSaveTo -> pcb_act_SaveTo +saveto_help -> pcb_acth_SaveTo +saveto_syntax -> pcb_acts_SaveTo +ActionQuit -> pcb_act_Quit +quit_help -> pcb_acth_Quit +quit_syntax -> pcb_acts_Quit +ActionDRCheck -> pcb_act_DRCheck +drcheck_help -> pcb_acth_DRCheck +drcheck_syntax -> pcb_acts_DRCheck +ActionDisplay -> pcb_act_Display +display_help -> pcb_acth_Display +display_syntax -> pcb_acts_Display +ActionCycleDrag -> pcb_act_CycleDrag +cycledrag_help -> pcb_acth_CycleDrag +cycledrag_syntax -> pcb_acts_CycleDrag +FullScreen -> pcb_act_FullScreen +fullscreen_help -> pcb_acth_FullScreen +fullscreen_syntax -> pcb_acts_FullScreen +ActionMarkCrosshair -> pcb_act_MarkCrosshair +markcrosshair_help -> pcb_acth_MarkCrosshair +markcrosshair_syntax -> pcb_acts_MarkCrosshair +ActionMessage -> pcb_act_Message +message_help -> pcb_acth_Message +message_syntax -> pcb_acts_Message +ActionMode -> pcb_act_Mode +mode_help -> pcb_acth_Mode +mode_syntax -> pcb_acts_Mode +ActionToggleHideName -> pcb_act_ToggleHideName +togglehidename_help -> pcb_acth_ToggleHideName +togglehidename_syntax -> pcb_acts_ToggleHideName +ActionSetSame -> pcb_act_SetSame +setsame_help -> pcb_acth_SetSame +setsame_syntax -> pcb_acts_SetSame +ActionRouteStyle -> pcb_act_RouteStyle +routestyle_help -> pcb_acth_RouteStyle +routestyle_syntax -> pcb_acts_RouteStyle +ActionCreateMenu -> pcb_act_CreateMenu +createmenu_help -> pcb_acth_CreateMenu +createmenu_syntax -> pcb_acts_CreateMenu +ActionRemoveMenu -> pcb_act_RemoveMenu +removemenu_help -> pcb_acth_RemoveMenu +removemenu_syntax -> pcb_acts_RemoveMenu +ActionSwitchHID -> pcb_act_SwitchHID +switchhid_help -> pcb_acth_SwitchHID +switchhid_syntax -> pcb_acts_SwitchHID +ActionPrintActions -> pcb_act_PrintActions +printactions_help -> pcb_acth_PrintActions +printactions_syntax -> pcb_acts_PrintActions +ActionDumpActions -> pcb_act_DumpActions +dumpactions_help -> pcb_acth_DumpActions +dumpactions_syntax -> pcb_acts_DumpActions +ActionPrintUsage -> pcb_act_PrintUsage +printusage_help -> pcb_acth_PrintUsage +printusage_syntax -> pcb_acts_PrintUsage +ActionPrintVersion -> pcb_act_PrintVersion +printversion_help -> pcb_acth_PrintVersion +printversion_syntax -> pcb_acts_PrintVersion +ActionPrintCopyright -> pcb_act_PrintCopyright +printcopyright_help -> pcb_acth_PrintCopyright +printcopyright_syntax -> pcb_acts_PrintCopyright +ActionPrintPaths -> pcb_act_PrintPaths +printpaths_help -> pcb_acth_PrintPaths +printpaths_syntax -> pcb_acts_PrintPaths +ActionNetlist -> pcb_act_Netlist +netlist_help -> pcb_acth_Netlist +netlist_syntax -> pcb_acts_Netlist +ActionNetlist -> pcb_act_Netlist +netlist_help -> pcb_acth_Netlist +netlist_syntax -> pcb_acts_Netlist +ActionAttributes -> pcb_act_Attributes +attributes_help -> pcb_acth_Attributes +attributes_syntax -> pcb_acts_Attributes +ActionDisperseElements -> pcb_act_DisperseElements +disperseelements_help -> pcb_acth_DisperseElements +disperseelements_syntax -> pcb_acts_DisperseElements +ActionFlip -> pcb_act_Flip +flip_help -> pcb_acth_Flip +flip_syntax -> pcb_acts_Flip +ActionListRotations -> pcb_act_ListRotations +listrotations_help -> pcb_acth_ListRotations +listrotations_syntax -> pcb_acts_ListRotations +ActionMoveObject -> pcb_act_MoveObject +moveobject_help -> pcb_acth_MoveObject +moveobject_syntax -> pcb_acts_MoveObject +ActionMoveToCurrentLayer -> pcb_act_MoveToCurrentLayer +movetocurrentlayer_help -> pcb_acth_MoveToCurrentLayer +movetocurrentlayer_syntax -> pcb_acts_MoveToCurrentLayer +ActionElementList -> pcb_act_ElementList +elementlist_help -> pcb_acth_ElementList +elementlist_syntax -> pcb_acts_ElementList +ActionElementSetAttr -> pcb_act_ElementSetAttr +elementsetattr_help -> pcb_acth_ElementSetAttr +elementsetattr_syntax -> pcb_acts_ElementSetAttr +ActionRipUp -> pcb_act_RipUp +ripup_help -> pcb_acth_RipUp +ripup_syntax -> pcb_acts_RipUp +ActionMinMaskGap -> pcb_act_MinMaskGap +minmaskgap_help -> pcb_acth_MinMaskGap +minmaskgap_syntax -> pcb_acts_MinMaskGap +ActionMinClearGap -> pcb_act_MinClearGap +mincleargap_help -> pcb_acth_MinClearGap +mincleargap_syntax -> pcb_acts_MinClearGap +MoveLayerAction -> pcb_act_MoveLayerAction +movelayeraction_help -> pcb_acth_MoveLayerAction +movelayeraction_syntax -> pcb_acts_MoveLayerAction +Action_fp_rehash -> pcb_act__fp_rehash +_fp_rehash_help -> pcb_acth__fp_rehash +_fp_rehash_syntax -> pcb_acts__fp_rehash +ActionMorphPolygon -> pcb_act_MorphPolygon +morphpolygon_help -> pcb_acth_MorphPolygon +morphpolygon_syntax -> pcb_acts_MorphPolygon +ActionPolygon -> pcb_act_Polygon +polygon_help -> pcb_acth_Polygon +polygon_syntax -> pcb_acts_Polygon +ActionAddRats -> pcb_act_AddRats +addrats_help -> pcb_acth_AddRats +addrats_syntax -> pcb_acts_AddRats +ActionConnection -> pcb_act_Connection +connection_help -> pcb_acth_Connection +connection_syntax -> pcb_acts_Connection +ActionDeleteRats -> pcb_act_DeleteRats +deleterats_help -> pcb_acth_DeleteRats +deleterats_syntax -> pcb_acts_DeleteRats +ActionDelete -> pcb_act_Delete +delete_help -> pcb_acth_Delete +delete_syntax -> pcb_acts_Delete +ActionRemoveSelected -> pcb_act_RemoveSelected +removeselected_help -> pcb_acth_RemoveSelected +removeselected_syntax -> pcb_acts_RemoveSelected +ActionSelect -> pcb_act_Select +select_help -> pcb_acth_Select +select_syntax -> pcb_acts_Select +ActionUnselect -> pcb_act_Unselect +unselect_help -> pcb_acth_Unselect +unselect_syntax -> pcb_acts_Unselect +ActionAtomic -> pcb_act_Atomic +atomic_help -> pcb_acth_Atomic +atomic_syntax -> pcb_acts_Atomic +ActionUndo -> pcb_act_Undo +undo_help -> pcb_acth_Undo +undo_syntax -> pcb_acts_Undo +ActionRedo -> pcb_act_Redo +redo_help -> pcb_acth_Redo +redo_syntax -> pcb_acts_Redo +ActionReplaceFootprint -> pcb_act_ReplaceFootprint +replacefootprint_help -> pcb_acth_ReplaceFootprint +replacefootprint_syntax -> pcb_acts_ReplaceFootprint +ActionSavePatch -> pcb_act_SavePatch +savepatch_help -> pcb_acth_SavePatch +savepatch_syntax -> pcb_acts_SavePatch +ActionManagePlugins -> pcb_act_ManagePlugins +manageplugins_help -> pcb_acth_ManagePlugins +manageplugins_syntax -> pcb_acts_ManagePlugins +ActionConf -> pcb_act_Conf +conf_help -> pcb_acth_Conf +conf_syntax -> pcb_acts_Conf +ActionGetStyle -> pcb_act_GetStyle +getstyle_help -> pcb_acth_GetStyle +getstyle_syntax -> pcb_acts_GetStyle +ActionChkMode -> pcb_act_ChkMode +chkmode_help -> pcb_acth_ChkMode +chkmode_syntax -> pcb_acts_ChkMode +ActionChkGridSize -> pcb_act_ChkGridSize +chkgridsize_help -> pcb_acth_ChkGridSize +chkgridsize_syntax -> pcb_acts_ChkGridSize +ActionChkElementName -> pcb_act_ChkElementName +chkelementname_help -> pcb_acth_ChkElementName +chkelementname_syntax -> pcb_acts_ChkElementName +ActionChkGridUnits -> pcb_act_ChkGridUnits +chkgridunits_help -> pcb_acth_ChkGridUnits +chkgridunits_syntax -> pcb_acts_ChkGridUnits +ActionChkBuffer -> pcb_act_ChkBuffer +chkbuffer_help -> pcb_acth_ChkBuffer +chkbuffer_syntax -> pcb_acts_ChkBuffer +ActionFreeRotateBuffer -> pcb_act_FreeRotateBuffer +freerotatebuffer_help -> pcb_acth_FreeRotateBuffer +freerotatebuffer_syntax -> pcb_acts_FreeRotateBuffer +ActionPasteBuffer -> pcb_act_PasteBuffer +pastebuffer_help -> pcb_acth_PasteBuffer +pastebuffer_syntax -> pcb_acts_PasteBuffer +ActionDumpLibrary -> pcb_act_DumpLibrary +dumplibrary_help -> pcb_acth_DumpLibrary +dumplibrary_syntax -> pcb_acts_DumpLibrary +ActionBell -> pcb_act_Bell +bell_help -> pcb_acth_Bell +bell_syntax -> pcb_acts_Bell +ActionToggleVendor -> pcb_act_ToggleVendor +togglevendor_help -> pcb_acth_ToggleVendor +togglevendor_syntax -> pcb_acts_ToggleVendor +ActionEnableVendor -> pcb_act_EnableVendor +enablevendor_help -> pcb_acth_EnableVendor +enablevendor_syntax -> pcb_acts_EnableVendor +ActionDisableVendor -> pcb_act_DisableVendor +disablevendor_help -> pcb_acth_DisableVendor +disablevendor_syntax -> pcb_acts_DisableVendor +ActionImport -> pcb_act_Import +import_help -> pcb_acth_Import +import_syntax -> pcb_acts_Import +ActionLoadhypFrom -> pcb_act_LoadhypFrom +loadhypfrom_help -> pcb_acth_LoadhypFrom +loadhypfrom_syntax -> pcb_acts_LoadhypFrom +ActionRenumber -> pcb_act_Renumber +renumber_help -> pcb_acth_Renumber +renumber_syntax -> pcb_acts_Renumber +ActionRenumberBlock -> pcb_act_RenumberBlock +renumberblock_help -> pcb_acth_RenumberBlock +renumberblock_syntax -> pcb_acts_RenumberBlock +ActionRenumberBuffer -> pcb_act_RenumberBuffer +renumberbuffer_help -> pcb_acth_RenumberBuffer +renumberbuffer_syntax -> pcb_acts_RenumberBuffer +ActionLoadDsnFrom -> pcb_act_LoadDsnFrom +loaddsnfrom_help -> pcb_acth_LoadDsnFrom +loaddsnfrom_syntax -> pcb_acts_LoadDsnFrom +ActionDumpConf -> pcb_act_DumpConf +dumpconf_help -> pcb_acth_DumpConf +dumpconf_syntax -> pcb_acts_DumpConf +ActionDumpLayers -> pcb_act_DumpLayers +dumplayers_help -> pcb_acth_DumpLayers +dumplayers_syntax -> pcb_acts_DumpLayers +ActionEvalConf -> pcb_act_EvalConf +evalconf_help -> pcb_acth_EvalConf +evalconf_syntax -> pcb_acts_EvalConf +ActionPSCalib -> pcb_act_PSCalib +pscalib_help -> pcb_acth_PSCalib +pscalib_syntax -> pcb_acts_PSCalib +ActionApplyVendor -> pcb_act_ApplyVendor +applyvendor_help -> pcb_acth_ApplyVendor +applyvendor_syntax -> pcb_acts_ApplyVendor +ActionUnloadVendor -> pcb_act_UnloadVendor +unloadvendor_help -> pcb_acth_UnloadVendor +unloadvendor_syntax -> pcb_acts_UnloadVendor +ActionLoadVendorFrom -> pcb_act_LoadVendorFrom +loadvendorfrom_help -> pcb_acth_LoadVendorFrom +loadvendorfrom_syntax -> pcb_acts_LoadVendorFrom +ActionAutoRoute -> pcb_act_AutoRoute +autoroute_help -> pcb_acth_AutoRoute +autoroute_syntax -> pcb_acts_AutoRoute +GlobalPuller -> pcb_act_GlobalPuller +globalpuller_help -> pcb_acth_GlobalPuller +globalpuller_syntax -> pcb_acts_GlobalPuller +Puller -> pcb_act_Puller +puller_help -> pcb_acth_Puller +puller_syntax -> pcb_acts_Puller +ActionAutoPlaceSelected -> pcb_act_AutoPlaceSelected +autoplaceselected_help -> pcb_acth_AutoPlaceSelected +autoplaceselected_syntax -> pcb_acts_AutoPlaceSelected +ActionDJopt -> pcb_act_DJopt +djopt_help -> pcb_acth_DJopt +djopt_syntax -> pcb_acts_DJopt +h_str -> pcb_hash_str +h_coordox -> pcb_hash_element_ox +h_coordoy -> pcb_hash_element_oy +h_coord -> pcb_hash_coord +pcb_buffer_swap -> pcb_buffer_flip_side +pcb_swap_buffers -> pcb_buffers_flip_side +LAYER_IS_PCB_EMPTY -> PCB_LAYER_IS_EMPTY +LAYER_IS_PCB_EMPTY -> PCB_LAYER_IS_EMPTY +IsLayerEmpty -> pcb_layer_is_empty_ +IsLayerNumEmpty -> pcb_layer_is_empty +IsLayerGroupEmpty -> pcb_is_layergrp_empty +ParseGroupString -> pcb_layer_parse_group_string +GetLayerNumber -> pcb_layer_id +GetGroupOfLayer -> pcb_layer_get_group +GetLayerGroupNumberByPointer -> pcb_layer_get_group_ +GetLayerGroupNumberByNumber -> pcb_layer_get_group +IsPasteEmpty -> pcb_layer_is_paste_empty +SOLDER_LAYER -> PCB_SOLDER_SIDE +COMPONENT_LAYER -> PCB_COMPONENT_SIDE +LayerStringToLayerStack -> pcb_layervis_parse_string +ChangeGroupVisibility -> pcb_layervis_change_group_vis +ResetStackAndVisibility -> pcb_layervis_reset_stack +SaveStackAndVisibility -> pcb_layervis_save_stack +RestoreStackAndVisibility -> pcb_layervis_restore_stack +AddArcToBuffer -> pcb_arcop_add_to_buffer +MoveArcToBuffer -> pcb_arcop_move_to_buffer +ChangeArcSize -> pcb_arcop_change_size +ChangeArcClearSize -> pcb_arcop_change_clear_size +ChangeArcRadius -> pcb_arcop_change_radius +ChangeArcAngle -> pcb_arcop_change_angle +ChangeArcJoin -> pcb_arcop_change_join +SetArcJoin -> pcb_arcop_set_join +ClrArcJoin -> pcb_arcop_clear_join +CopyArc -> pcb_arcop_copy +MoveArc -> pcb_arcop_move +MoveArcToLayerLowLevel -> pcb_arcop_move_to_layer_low +MoveArcToLayer -> pcb_arcop_move_to_layer +DestroyArc -> pcb_arcop_destroy +RemoveArc_op -> pcb_arcop_remove +RemoveArcPoint_op -> pcb_arcop_remove_point +Rotate90Arc -> pcb_arcop_rotate90 +ChgFlagArc -> pcb_arcop_change_flag +AddLineToBuffer -> pcb_lineop_add_to_buffer +ChangeLineSize -> pcb_lineop_change_size +ChangeLineClearSize -> pcb_lineop_change_clear_size +ChangeLineName -> pcb_lineop_change_name +ChangeLineJoin -> pcb_lineop_change_join +SetLineJoin -> pcb_lineop_set_join +ClrLineJoin -> pcb_lineop_clear_join +InsertPointIntoLine -> pcb_lineop_insert_point +MoveLineToBuffer -> pcb_lineop_move_to_buffer +CopyLine -> pcb_lineop_copy +MoveLine -> pcb_lineop_move +MoveLinePoint -> pcb_lineop_move_point +MoveLinePointWithRoute -> pcb_lineop_move_point_with_route +MoveLineToLayerLowLevel -> pcb_lineop_move_to_layer_low +MoveLineToLayer -> pcb_lineop_move_to_layer +DestroyLine -> pcb_lineop_destroy +RemoveLinePoint -> pcb_lineop_remove_point +RemoveLine_op -> pcb_lineop_remove +Rotate90LinePoint -> pcb_lineop_rotate90_point +Rotate90Line -> pcb_lineop_rotate90 +ChgFlagLine -> pcb_lineop_change_flag +AddArcToBuffer -> pcb_arcop_add_to_buffer +MoveArcToBuffer -> pcb_arcop_move_to_buffer +ChangeArcSize -> pcb_arcop_change_size +ChangeArcClearSize -> pcb_arcop_change_clear_size +ChangeArcRadius -> pcb_arcop_change_radius +ChangeArcAngle -> pcb_arcop_change_angle +ChangeArcJoin -> pcb_arcop_change_join +SetArcJoin -> pcb_arcop_set_join +ClrArcJoin -> pcb_arcop_clear_join +CopyArc -> pcb_arcop_copy +MoveArc -> pcb_arcop_move +MoveArcToLayerLowLevel -> pcb_arcop_move_to_layer_low +MoveArcToLayer -> pcb_arcop_move_to_layer +DestroyArc -> pcb_arcop_destroy +RemoveArc_op -> pcb_arcop_remove +RemoveArcPoint_op -> pcb_arcop_remove_point +Rotate90Arc -> pcb_arcop_rotate90 +ChgFlagArc -> pcb_arcop_change_flag +AddElementToBuffer -> pcb_elemop_add_to_buffer +MoveElementToBuffer -> pcb_elemop_move_to_buffer +ClrElementOctagon -> pcb_elemop_clear_octagon +SetElementOctagon -> pcb_elemop_set_octagon +ChangeElementOctagon -> pcb_elemop_change_octagon +ClrElementSquare -> pcb_elemop_clear_square +SetElementSquare -> pcb_elemop_set_square +ChangeElementSquare -> pcb_elemop_change_square +ChangeElementNonetlist -> pcb_elemop_change_nonetlist +ChangeElementName -> pcb_elemop_change_name +ChangeElementNameSize -> pcb_elemop_change_name_size +ChangeElementSize -> pcb_elemop_change_size +ChangeElementClearSize -> pcb_elemop_change_clear_size +ChangeElement1stSize -> pcb_elemop_change_1st_size +ChangeElement2ndSize -> pcb_elemop_change_2nd_size +CopyElement -> pcb_elemop_copy +MoveElementName -> pcb_elemop_move_name +MoveElement -> pcb_elemop_move +DestroyElement -> pcb_elemop_destroy +RemoveElement_op -> pcb_elemop_remove +Rotate90Element -> pcb_elemop_rotate90 +Rotate90ElementName -> pcb_elemop_rotate90_name +ChangePadSize -> pcb_padop_change_size +ChangePadClearSize -> pcb_padop_change_clear_size +ChangePadName -> pcb_padop_change_name +ChangePadNum -> pcb_padop_change_num +ChangePadSquare -> pcb_padop_change_square +SetPadSquare -> pcb_padop_set_square +ClrPadSquare -> pcb_padop_clear_square +ChangePadMaskSize -> pcb_padop_change_mask_size +AddViaToBuffer -> pcb_viaop_add_to_buffer +MoveViaToBuffer -> pcb_viaop_move_to_buffer +ChangeViaThermal -> pcb_viaop_change_thermal +ChangePinThermal -> pcb_pinop_change_thermal +ChangeViaSize -> pcb_viaop_change_size +ChangeVia2ndSize -> pcb_viaop_change_2nd_size +ChangePin2ndSize -> pcb_pinop_change_2nd_size +ChangeViaClearSize -> pcb_viaop_change_clear_size +ChangePinSize -> pcb_pinop_change_size +ChangePinClearSize -> pcb_pinop_change_clear_size +ChangeViaName -> pcb_viaop_change_name +ChangePinName -> pcb_pinop_change_name +ChangePinNum -> pcb_pinop_change_num +ChangeViaSquare -> pcb_viaop_change_square +ChangePinSquare -> pcb_pinop_change_square +SetPinSquare -> pcb_pinop_set_square +ClrPinSquare -> pcb_pinop_clear_square +ChangeViaOctagon -> pcb_viaop_change_octagon +SetViaOctagon -> pcb_viaop_set_octagon +ClrViaOctagon -> pcb_viaop_clear_octagon +ChangePinOctagon -> pcb_pinop_change_octagon +SetPinOctagon -> pcb_pinop_set_octagon +ClrPinOctagon -> pcb_pinop_clear_octagon +ChangePinMaskSize -> pcb_pinop_change_mask_size +ChangeViaMaskSize -> pcb_viaop_change_mask_size +CopyVia -> pcb_viaop_copy +MoveVia -> pcb_viaop_move +DestroyVia -> pcb_viaop_destroy +RemoveVia -> pcb_viaop_remove +AddPolygonToBuffer -> pcb_polyop_add_to_buffer +MovePolygonToBuffer -> pcb_polyop_move_to_buffer +ChangePolygonClearSize -> pcb_polyop_change_clear_size +ChangePolyClear -> pcb_polyop_change_clear +InsertPointIntoPolygon -> pcb_polyop_insert_point +MovePolygon -> pcb_polyop_move +MovePolygonPoint -> pcb_polyop_move_point +MovePolygonToLayerLowLevel -> pcb_polyop_move_to_layer_low +MovePolygonToLayer -> pcb_polyop_move_to_layer +DestroyPolygon -> pcb_polyop_destroy +DestroyPolygonPoint -> pcb_polyop_destroy_point +RemovePolygon_op -> pcb_polyop_remove +RemovePolygonContour -> pcb_polyop_remove_counter +RemovePolygonPoint -> pcb_polyop_remove_point +CopyPolygon -> pcb_polyop_copy +Rotate90Polygon -> pcb_polyop_rotate90 +ChgFlagPolygon -> pcb_polyop_change_flag +AddRatToBuffer -> pcb_ratop_add_to_buffer +MoveRatToBuffer -> pcb_ratop_move_to_buffer +InsertPointIntoRat -> pcb_ratop_insert_point +MoveRatToLayer -> pcb_ratop_move_to_layer +DestroyRat -> pcb_ratop_destroy +RemoveRat -> pcb_ratop_remove +CopySubc -> pcb_subcop_copy +MoveSubc -> pcb_subcop_move +Rotate90Subc -> pcb_subcop_rotate90 +MoveSubcToBuffer -> pcb_subcop_move_to_buffer +AddSubcToBuffer -> pcb_subcop_add_to_buffer +ChangeSubcSize -> pcb_subcop_change_size +ChangeSubcClearSize -> pcb_subcop_change_clear_size +ChangeSubc1stSize -> pcb_subcop_change_1st_size +ChangeSubc2ndSize -> pcb_subcop_change_2nd_size +ChangeSubcNonetlist -> pcb_subcop_change_nonetlist +ChangeSubcName -> pcb_subcop_change_name +DestroySubc -> pcb_subcop_destroy +RemoveSubc_op -> pcb_subcop_remove +ClrSubcOctagon -> pcb_subcop_clear_octagon +SetSubcOctagon -> pcb_subcop_set_octagon +ChangeSubcOctagon -> pcb_subcop_change_octagon +ClrSubcSquare -> pcb_subcop_clear_square +SetSubcSquare -> pcb_subcop_set_square +ChangeSubcSquare -> pcb_subcop_change_square +ChgFlagSubc -> pcb_subcop_change_flag +AddTextToBuffer -> pcb_textop_add_to_buffer +MoveTextToBuffer -> pcb_textop_move_to_buffer +ChangeTextSize -> pcb_textop_change_size +ChangeTextName -> pcb_textop_change_name +ChangeTextJoin -> pcb_textop_change_join +SetTextJoin -> pcb_textop_set_join +ClrTextJoin -> pcb_textop_clear_join +CopyText -> pcb_textop_copy +MoveText -> pcb_textop_move +MoveTextToLayerLowLevel -> pcb_textop_move_to_layer_low +MoveTextToLayer -> pcb_textop_move_to_layer +DestroyText -> pcb_textop_destroy +RemoveText_op -> pcb_textop_remove +Rotate90Text -> pcb_textop_rotate90 +ChgFlagText -> pcb_textop_change_flag +EraseArc -> pcb_arc_invalidate_erase +DrawArc -> pcb_arc_invalidate_draw +_draw_arc -> pcb_arc_draw_ +draw_arc -> pcb_arc_draw +draw_line_callback -> pcb_line_draw_callback +_draw_line -> pcb_line_draw_ +draw_line -> pcb_line_draw +EraseLine -> pcb_line_invalidate_erase +DrawLine -> pcb_line_invalidate_draw +draw_poly_callback -> pcb_poly_draw_callback +ErasePolygon -> pcb_poly_invalidate_erase +DrawPolygon -> pcb_poly_invalidate_draw +draw_rat_callback -> pcb_rat_draw_callback +EraseRat -> pcb_rat_invalidate_erase +DrawRat -> pcb_rat_invalidate_draw +draw_text_callback -> pcb_text_draw_callback +XORDrawText -> pcb_text_draw_xor +DrawTextLowLevel -> pcb_text_draw +EraseText -> pcb_text_invalidate_erase +DrawText -> pcb_text_invalidate_draw +draw_arc_callback -> pcb_arc_draw_callback +draw_pad_name_callback -> pcb_pad_name_draw_callback +pcb_draw_paste_auto -> pcb_pad_paste_draw +ErasePadName -> pcb_pad_name_invalidate_erase +DrawPadName -> pcb_pad_name_invalidate_draw +draw_pad_callback -> pcb_pad_draw_callback +clear_pad_callback -> pcb_pad_clear_callback +draw_pad -> pcb_pad_draw +ErasePad -> pcb_pad_invalidate_erase +DrawPad -> pcb_pad_invalidate_draw +draw_pin_name_callback -> pcb_pin_name_draw_callback +EraseViaName -> pcb_via_name_invalidate_erase +ErasePinName -> pcb_pin_name_invalidate_erase +DrawViaName -> pcb_via_name_invalidate_draw +DrawPinName -> pcb_pin_name_invalidate_draw +draw_pin_callback -> pcb_pin_draw_callback +clear_pin_callback -> pcb_pin_clear_callback +draw_via_callback -> pcb_via_draw_callback +draw_hole_callback -> pcb_hole_draw_callback +draw_pin -> pcb_pin_draw +EraseVia -> pcb_via_invalidate_erase +ErasePin -> pcb_pin_invalidate_erase +DrawVia -> pcb_via_invalidate_draw +DrawPin -> pcb_pin_invalidate_draw +draw_element_name_callback -> pcb_elem_name_draw_callback +draw_element_mark_callback -> pcb_elem_mark_draw_callback +draw_element_callback -> pcb_elem_draw_callback +draw_element_pins_and_pads -> pcb_elem_pp_draw +draw_element_package -> pcb_elem_package_draw +draw_element_name -> pcb_elem_name_draw +draw_element -> pcb_elem_draw +EraseElementPinsAndPads -> pcb_elem_pp_invalidate_erase +EraseElementName -> pcb_elem_name_invalidate_erase +EraseElement -> pcb_elem_invalidate_erase +DrawElementPinsAndPads -> pcb_elem_pp_invalidate_draw +DrawElementPackage -> pcb_elem_package_invalidate_draw +DrawElementName -> pcb_elem_name_invalidate_draw +DrawElement -> pcb_elem_invalidate_draw +pcb_polygon_t -> pcb_poly_t +pcb_polygon_s -> pcb_poly_s +pcb_add_polygon_on_layer -> pcb_add_poly_on_layer +GetObjectBoundingBox -> pcb_obj_get_bbox +PCB_TYPE_ -> PCB_OBJ_ +PCB_OBJ_NONE -> PCB_OBJ_VOID +pcb_obj_tpye_t -> pcb_objtype_t +PCB_TYPEMASK_ALL -> PCB_OBJ_ANY +PCB_OBJ_RATLINE -> PCB_OBJ_RAT +PCB_OBJ_SUBC_FLOATER -> PCB_OBJ_FLOATER +PCB_TYPEMASK_ -> PCB_OBJ_CLASS_ +XORDrawAttachedLine -> pcb_xordraw_attached_line +XORPolygon -> pcb_xordraw_poly +XORPolygon_subc -> pcb_xordraw_poly_subc +XORDrawAttachedArc -> pcb_xordraw_attached_arc +XORDrawBuffer -> pcb_xordraw_buffer +XORDrawMoveOrCopy -> pcb_xordraw_movecopy +XORDrawInsertPointObject -> pcb_xordraw_insert_pt_obj +XORDrawSubc -> pcb_xordraw_subc +pcb_hid_find_action -> pcb_find_action +pcb_hid_remove_actions -> pcb_remove_actions +pcb_hid_remove_action -> pcb_remove_action +pcb_hid_remove_actions_by_cookie -> pcb_remove_actions_by_cookie +pcb_hid_action -> pcb_action +pcb_hid_actionl -> pcb_actionl +pcb_hid_actionv -> pcb_actionv +pcb_hid_actionv_ -> pcb_actionv_ +pcb_hid_parse_command -> pcb_parse_command +pcb_hid_parse_actions -> pcb_parse_actions +pcb_hid_register_action -> pcb_register_action +pcb_hid_register_actions -> pcb_register_actions +pcb_hid_actions_uninit -> pcb_actions_uninit +pcb_hid_actions_init -> pcb_actions_init Index: tags/2.1.2/doc/developer/src/Makefile =================================================================== --- tags/2.1.2/doc/developer/src/Makefile (nonexistent) +++ tags/2.1.2/doc/developer/src/Makefile (revision 24813) @@ -0,0 +1,2 @@ +../data1.svg: data1.dot + dot -Tsvg $^ > $@ Index: tags/2.1.2/doc/developer/src/data1.dot =================================================================== --- tags/2.1.2/doc/developer/src/data1.dot (nonexistent) +++ tags/2.1.2/doc/developer/src/data1.dot (revision 24813) @@ -0,0 +1,84 @@ +digraph pcb_data { + ranksep=1.3 + PCBType_misc [label="misc fields:\nID\nName\nFileName\ncolors\ndrc settings\ncursor coords\ngrid\nlayergroups\nroute styles\npadstack protos\n..."] + PCBType_flags [label="flags:\nChanged\nViaOn (vias drawn?)\n..."] + pcb_board_t -> PCBType_misc + pcb_board_t -> PCBType_flags + pcb_board_t -> pcb_data_t + pcb_board_t [shape=box] + + pcb_data_t2 [label="another level of\npcb_data_t\n..." shape=none] + + pcb_subc_t [shape=box style=filled color="#aaffaa"] + pcb_rat_line_t [shape=box style=filled color="#aaffaa"] + pcb_pstk_t [shape=box style=filled color="#aaffaa"] + pcb_padstack_proto_t [shape=box] + pcb_arc_t [shape=box style=filled color="#aaffaa"] + pcb_line_t [shape=box style=filled color="#aaffaa"] + pcb_text_t [shape=box style=filled color="#aaffaa"] + pcb_poly_t [shape=box style=filled color="#aaffaa"] + + PCB [label="extern pcb_board_t PCB\nglobal variable\nholding the current\nboard" shape=diamond] + PCB -> pcb_board_t + + Buffers [label="extern pcb_buffer_t Buffers[]\nglobal variable holding\nall paste buffers" shape=diamond] + Buffers -> pcb_buffer_t + + BufferType_misc [label="misc fields:\nbounding box\noffset"] + pcb_buffer_t -> BufferType_misc + pcb_buffer_t -> pcb_data_t + pcb_buffer_t [shape=box] + + DataType_listrt [label="layer-independent lists and rtrees"] + DataType_LayerN [label="LayerN: number of\nlayers in use"] + DataType_layers [label="an array of layers"] + DataType_misc [label="misc fields"] + + pcb_data_t -> DataType_misc [tailport=s] + pcb_data_t -> DataType_LayerN [tailport=s] + pcb_data_t -> DataType_layers [tailport=s] + pcb_data_t -> DataType_listrt [tailport=s] + pcb_data_t -> DataType_rtrees [tailport=s] + pcb_data_t [shape=box] + + DataType_layers -> pcb_layer_t + + DataType_listrt -> pcb_subc_t + DataType_listrt -> pcb_rat_line_t + DataType_listrt -> pcb_pstk_t + DataType_listrt -> pcb_padstack_proto_t + + pcb_subc_t -> pcb_data_t2 + pcb_pstk_t -> pcb_padstack_proto_t [constraint=no color=blue label="id\nref."] + + LayerType_lines [label="list and rtree of lines"] + LayerType_arcs [label="list and rtree of arcs"] + LayerType_texts [label="list and rtree of text objects"] + LayerType_polygons [label="list and rtree of polygons"] + LayerType_misc [label="misc fields:\nflags\ncolors"] + + LayerType_lines -> pcb_line_t + LayerType_arcs -> pcb_arc_t + LayerType_polygons -> pcb_poly_t + LayerType_texts -> pcb_text_t + + pcb_layer_t -> LayerType_misc + pcb_layer_t -> LayerType_lines + pcb_layer_t -> LayerType_arcs + pcb_layer_t -> LayerType_texts + pcb_layer_t -> LayerType_polygons + pcb_layer_t [shape=box] + + subgraph "cluster_1" { + label="LEGEND" + style=filled + bgcolor=grey + round [label="round:\nstruct field"] + struct [label="box:\nstruct" shape=box] + diamond [label="diamond:\nglobal variable" shape=diamond] + grn [label="green:\ndrawing primitive" shape=box style=filled color="#aaffaa"] + + } + + pcb_poly_t -> struct [style=invis] +} Index: tags/2.1.2/doc/doc.html =================================================================== --- tags/2.1.2/doc/doc.html (nonexistent) +++ tags/2.1.2/doc/doc.html (revision 24813) @@ -0,0 +1,38 @@ + + + + pcb-rnd - documentation + + + + + + + + + + +
Main + News + Doc & pool + Support + People + Events & timeline + pcb-rnd [pcb-rnd logo] +
+ + +
+ +

pcb-rnd documentation

+ + + + + Index: tags/2.1.2/doc/faq.html =================================================================== --- tags/2.1.2/doc/faq.html (nonexistent) +++ tags/2.1.2/doc/faq.html (revision 24813) @@ -0,0 +1,82 @@ + + + + pcb-rnd - FAQ + + + + + + + + + + +
Main + News + Doc & pool + Support + People + Events & timeline + pcb-rnd [pcb-rnd logo] +
+ + +
+ +

pcb-rnd FAQ

+ +

padstacks

+ +

Intern copper layer shape not rendering

+

+Does the padstack has a hole? Does the hole drill through any internal +copper layer (in non-thru-hole case)? +

+Internal copper layers are special: there are multiple of them. The padstack +will place the intern shape on any internal copper layer that the padstack's +hole reaches. If the padstack has no hole, no internal layer shape is +rendered, even if it is specified. + + +

slots (oval holes)

+ +

My slot doesn't show up on screen or in exports

+

+Make sure you have the right layer groups and layers set up: +

    +
  • a mech layer group with purpose uroute and another with purpose proute for unplated and plated slots +
  • make sure there is a layer in each group that has auto in the comb flags - padstack side effects will land only on auto layers; auto layers are indicated with white hatching in the layer selector's layer color +
+ +

DSN format

+

There are no holes in padstacks on import

+

+The DSN format was originally designed for autorouting; an autorouter doesn't +need to know the geometry of a hole, assuming copper annulus is always around +the hole. Thus old versions of the file format simply does not have a way +to describe holes. +

+Some software extended the format and use a hole directive that pcb-rnd +picks up - but if the file does not contain holes, pcb-rnd can't improvise them. +

+You can use query() to find offending padstacks and use propset() or +the padstack editor to install the holes. + +

There are no silk graphics on subcircuits after import

+

+The DSN format does not specify silk. There are outline and keepout objects +in the format and pcb-rnd loads them on special purpose documentation layers. +The use of these objects vary from tool to tool - some tools will draw the +bounding box of the part using lines on the outline layer, but other tools +may just draw a large, rectangular filled polygon. +

+Use the per subcircuit layer bindings to map them on a board silk layer. + +

Missing solder mask cutouts and solder paste patterns after import

+

+The DSN format does not specify solder mask or paste. Please use the padstack +editor on the affected padstacks. + + + Index: tags/2.1.2/doc/help.html =================================================================== --- tags/2.1.2/doc/help.html (nonexistent) +++ tags/2.1.2/doc/help.html (revision 24813) @@ -0,0 +1,72 @@ + + + + pcb-rnd - help wanted + + + + + + + + + + +
Main + News + Doc & pool + Support + People + Events & timeline + pcb-rnd [pcb-rnd logo] +
+ + +

pcb-rnd - help wanted

+The project is looking for volunteers for the features listed below. If +you want to contribute, you will need to have an svn client and an email +client. Furthermore an IRC client is strongly recommended. +

+You will become part of the team and get svn commit right immediately +when you start working. +

+Don't have much free time? Don't worry: the tasks below are split up in +very small (1..2 hours) chunks. Coordination is granted, the administrative +overhead is almost zero - you can focus on the task, and finish it whenever +you have a free hour. +

+Worrying about your contribution to go in /dev/null? Don't: pcb-rnd +has very short loops; you start contributing and get immediate feedback. Your +work is part of the official thing immediately and revised and accepted (or +rarely refused) within hours or at most days. +There are no bitrotting branches. +

+You are not confident enough with your skills? pcb-rnd is an optimal +project for learning. If you start contributing, you get support. There +are small and simple entry level tasks. Most of the tasks don't require +any programming skills. +

+Sign up by contacting the lead developer +If you want to work on a feature not listed below, feel free to drop me +a mail. +

+ +
ID skill required description +
validation user reference output valudation (gerber and other formats) +
tutorial user tutorial projects +
windows user generic testing on windows +
mtest user systematic manual testing +
actionvry user test and verify existing action documentation (very small chunks) +
actiondoc user, html write missing action documentation (very small chunks) +
doc user, html write sections of user documentation (generic) +
doc:act user, html write sections of user documentation: action testing and documentation +
icons designer icons, other graphical elements for the GTK HID +
atest C/beginner program automated test cases +
rosetta scripting port example scripts to your favorite language (more details) +
fungw_pkg packaging packaging fungw for your favorite distro (more details) +
script_pkg packaging packaging libmawk, funlisp, estutter for your favorite distro (more details) +
actionw C action wrapper programming (more details) + +
+ + Index: tags/2.1.2/doc/help_details.html =================================================================== --- tags/2.1.2/doc/help_details.html (nonexistent) +++ tags/2.1.2/doc/help_details.html (revision 24813) @@ -0,0 +1,78 @@ + + + + pcb-rnd - help wanted + + + + + + + + + + +
Main + News + Doc & pool + Support + People + Events & timeline + pcb-rnd [pcb-rnd logo] +
+ + +

pcb-rnd - help wanted - details

+ +

porting example scripts

+

+The rosetta scripts start with an awk script, because awk is my favorite +language. When the awk version is tested out and the documentation +finalized, the script needs to be ported to different languages. The +porting is line-by-line, becuase we want to have all scripts do the same +and look the same, that's how it's easy to compare them. +

+If you have a favorite language, you could join porting example scripts to +that language. +

+Requirements: knowing your scripting language, system-wide fungw +installation, pcb-rnd from svn. + +

packaging fungw for your favorite distro

+

+At the moment fungw has no packaging coverage. Because we use fungw as the +action infrastructure, we have a minimal (no-script) version embedded in +src_3rd/ and scconfig already has the logics for choosing a system +installed version over the local version when avaialble. +

+To make system installs more wide-spread, we need OS packages, preferrably +official packages in as many systems as possible. Fungw is small: the core +lib and all existing engines (~ script language bindings) take up 4k sloc +total). The only challange is that we need to have a modular packaging: a +core package and one package per script language binding, to avoid the +core package depending on 6..8 scripting engines. +

+Requirements: knowing your favorite distro's packaging model + + +

packaging libmawk, funlisp, estutter

+

+These three scripting language libs are relatively small (funlisp is even +tiny), and unlike many popular languages they come with a nice, generic +API. Unfortunately they are not widely known so we lack OS packages. They +are generally easy to package. +

+Requirements: knowing your favorite distro's packaging model + +

action wrapper programming

+

+Most of our API in pcb-rnd are good, old-fashioned, raw C APIs. Which +means they are currently unaccessible to scripts. To make them accessible, +we need to write action wrappers. Such an action wrapper is usually +simple, as 90% of the time we want to expose the very same API, +parameter-to-parameter, in a coordinated effort. +

+Requirements: intermediate C knowledge, willing to learn the fungw API, +willing to use svn and IRC + + Index: tags/2.1.2/doc/index.html =================================================================== --- tags/2.1.2/doc/index.html (nonexistent) +++ tags/2.1.2/doc/index.html (revision 24813) @@ -0,0 +1,132 @@ + + + + pcb-rnd - main + + + + + + + + + + +
Main + News + Doc & pool + Support + People + Events & timeline + pcb-rnd [pcb-rnd logo] +
+ + +
+ + +
+

Summary

+ +
+
[pcb-rnd logo]pcb-rnd
+
+ is a free/open source, flexible, modular Printed Circuit Board editor +

for design of professional and hobby boards. +

is feature-rich and compatible +

has a long history, fast paced development, and big plans. +

is part of the coralEDA ecosystem. + + + +

Version Control svn://repo.hu/pcb-rnd/trunk (mirrors) +
Download source releases +
Comments, feedback, patches live chat with the developer
or contact the lead developer
Mailing list: pcb-rnd list.repo.hu (send a mail with subject: subscribe) (archives) +
Contribution and support + How to join or contribute +
We are looking for help and sponsoration/donation. +
Do you have a feature request? + +
Key features + editor for multilayer Printed Circuit Boards +
scriptable in 10+ different scripting languages +
parametric footprint generation, web footprints +
modular code with a flexible plugin system +
fits well in a UNIXy workflow +
supports CLI and server applications +
active development, frequent releases +
friendly and efficient developer and user community +
predictable development cycles +
compatible with KiCad and gEDA/PCB, understands Eagle and Protel/Autotrax file formats + +
Supported platforms + +
+ Linux desktop (various distributions, from source) +
official packages in Debian, Ubuntu, Fedora and Mageia +
Arch Linux (user package) +
Mac OS X + +
IRIX 5.3 +
OpenBSD +
(Likely: any 90's UNIX system with motif) +
Screen resolution as small as 800x600 +
GUI options: motif/lesstif, gtk-gdk, gtk-gl +
+ + screenshot of pcb-rnd running on Debian GNU/Linux +
+
+ + +
+ + + +

What is -rnd?

+
+ + + +
RespoNsive Developers + Developers try to respond on user needs, adding features that are actually needed by current users. +
+ +

+ + +
+ Response Not Delayed + Bugreports, user requests and patches submitted are answered ASAP. There are no patches bitrotting for months. There are no forgotten bugreports. +
+ +

+ + + +
Research
&
Development
+
+
+ Rázós,
Nehéz
Döntések
(Brave, hard decisions) +
There is a constant experimentation with new features and directions. We are willing to try strange/unusual ideas without risking the stability of the daily workflow. +
+ +

+ + + +
Rants
Now
Dissipating
+
Instead of talking and ranting a lot about what could work better, we just sit down and make it work better. +
+ +

+ + + +
Rather
Nicely
Decentralized
+
Slim, generic core; most of the code organized in replacable plugins. Most plugins depend only on the core. +
+

+ + + Index: tags/2.1.2/doc/irc.html =================================================================== --- tags/2.1.2/doc/irc.html (nonexistent) +++ tags/2.1.2/doc/irc.html (revision 24813) @@ -0,0 +1,48 @@ + + + + pcb-rnd - IRC + + + + + + + + + + +
Main + News + Doc & pool + Support + People + Events & timeline + pcb-rnd [pcb-rnd logo] +
+ + +

Live support via IRC (chat)

+
Irc server: repo.hu       Port: 6667       Channel: #pcb-rnd +
  +

I'm normally online as Igor2 between 5:00 CET and 19:00 CET; on Sunday there's an AFK-window between 11:00 CET and 16:00 CET. If I don't answer in a few minutes I'm probably away doing something, please be patient; say hi before you type your long question so you see if I'm available. +


+

+Below is an iframe of +kiwiirc irc client configured with the above settings. If it doesn't +work, please visit their page and +try to manually configure it, it's just 4 fields. +

+Using the web client: you should change your nickname (or using the +/nick myname command if you are already connected); there's no password +or registration or channel key or ssl of any form. Your real IP won't be +shown on the IRC network (check kiwiirc's page about their privacy +policy). +

+Connecting with the web client may take some time, give it a minute. +


+ + + + + Index: tags/2.1.2/doc/keys.html =================================================================== --- tags/2.1.2/doc/keys.html (nonexistent) +++ tags/2.1.2/doc/keys.html (revision 24813) @@ -0,0 +1,869 @@ + + + + + + Key to action bindings + + + + + +

Key to action bindings

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
key pcb-menu-default.lht +
+ + Zoom In 20%
Zoom(-1.2) +
, + Cycle object being dragged
CycleDrag() +
- + Zoom Out 20%
Zoom(+1.2) +
. + 'All-direction' lines
conf(toggle, editor/all_direction_lines, design) +
0 + Select Layer 10
SelectLayer(10) +
0-alt + Select Layer 20
SelectLayer(20) +
0-alt-ctrl + Toggle Layer 20
ToggleView(20) +
0-ctrl + Toggle Layer 10
ToggleView(10) +
1 + Select Layer 1
SelectLayer(1) +
1-alt + Select Layer 11
SelectLayer(11) +
1-alt-ctrl + Toggle Layer 11
ToggleView(11) +
1-ctrl + Toggle Layer 1
ToggleView(1) +
2 + Select Layer 2
SelectLayer(2) +
2-alt + Select Layer 12
SelectLayer(12) +
2-alt-ctrl + Toggle Layer 12
ToggleView(12) +
2-ctrl + Toggle Layer 2
ToggleView(2) +
3 + Select Layer 3
SelectLayer(3) +
3-alt + Select Layer 13
SelectLayer(13) +
3-alt-ctrl + Toggle Layer 13
ToggleView(13) +
3-ctrl + Toggle Layer 3
ToggleView(3) +
4 + Select Layer 4
SelectLayer(4) +
4-alt + Select Layer 14
SelectLayer(14) +
4-alt-ctrl + Toggle Layer 14
ToggleView(14) +
4-ctrl + Toggle Layer 4
ToggleView(4) +
5 + Select Layer 5
SelectLayer(5) +
5-alt + Select Layer 15
SelectLayer(15) +
5-alt-ctrl + Toggle Layer 15
ToggleView(15) +
5-ctrl + Toggle Layer 5
ToggleView(5) +
6 + Select Layer 6
SelectLayer(6) +
6-alt + Select Layer 16
SelectLayer(16) +
6-alt-ctrl + Toggle Layer 16
ToggleView(16) +
6-ctrl + Toggle Layer 6
ToggleView(6) +
7 + Select Layer 7
SelectLayer(7) +
7-alt + Select Layer 17
SelectLayer(17) +
7-alt-ctrl + Toggle Layer 17
ToggleView(17) +
7-ctrl + Toggle Layer 7
ToggleView(7) +
8 + Select Layer 8
SelectLayer(8) +
8-alt + Select Layer 18
SelectLayer(18) +
8-alt-ctrl + Toggle Layer 18
ToggleView(18) +
8-ctrl + Toggle Layer 8
ToggleView(8) +
9 + Select Layer 9
SelectLayer(9) +
9-alt + Select Layer 19
SelectLayer(19) +
9-alt-ctrl + Toggle Layer 19
ToggleView(19) +
9-ctrl + Toggle Layer 9
ToggleView(9) +
: + Command Entry
Command() +
[ + Previous grid
Grid(down) +
\ + Full screen
fullscreen(toggle) +
/ + Cycle line clip/refraction
Display(CycleClip) +
] + Next grid
Grid(up) +
a
 a +
Start routing an arc
Mode(Save); Mode(Arc); Mode(Notify) +
a
 b
  f
    +
Replace footprint
ReplaceFootprint() +
a
 b
  s
    +
Swap nets on two selected pins
net(swap) +
a
 b
  x +
netlist patch for back annotation
SavePatch() +
a
 d
  a
    +
Disperse all subcircuits
DisperseElements(All) +
a
 d
  s
    +
Disperse selected subcircuits
DisperseElements(Selected) +
a
 l +
Start routing a line
Mode(Save); Mode(Line); Mode(Notify) +
a
 m +
Place mark
MarkCrosshair() +
a
 o
  a
    +
Auto-Optimize
djopt(auto) +
a
 o
  d
    +
Debumpify
djopt(debumpify) +
a
 o
  m
    +
Miter
djopt(miter) +
a
 o
  n
    +
Vianudge
djopt(vianudge) +
a
 o
  o
    +
Ortho pull
djopt(orthopull) +
a
 o
  p
    +
Puller
Puller() +
a
 o
  s
    +
Simple optimization
djopt(simple) +
a
 o
  t
    +
Viatrim
djopt(viatrim) +
a
 o
  u
    +
Unjaggy
djopt(unjaggy) +
a
 p
  s
    +
Auto-place selected subcircuits
AutoPlaceSelected() +
a
 r
  a
    +
Auto-route all rats
AutoRoute(AllRats) +
a
 r
  r
    +
Rip up all auto-routed tracks
RipUp(All) +
a
 r
  s
    +
Auto-route selected rats
AutoRoute(SelectedRats) +
a
 r
  t
    +
Rip up selected auto-routed tracks
RipUp(Selected) +
a
 v +
Place via
Mode(Save); Mode(Via); Mode(Notify); Mode(Restore) +
a
 w +
Place mark
MarkCrosshair() +
a
 x
   +
Design Rule Checker
DRC() +
b
 1
   +
Select Buffer #1
PasteBuffer(1) +
b
 2
   +
Select Buffer #2
PasteBuffer(2) +
b
 3
   +
Select Buffer #3
PasteBuffer(3) +
b
 4
   +
Select Buffer #4
PasteBuffer(4) +
b
 5
   +
Select scratchpad
PasteBuffer(5) +
b
 b
   +
Layer bindings...
LayerBinding(buffer) +
b
 c
  c
    +
Clear buffer
PasteBuffer(Clear) +
b
 c
  p +
Convert buffer to padstack
PadstackConvert(buffer); Mode(PasteBuffer) +
b
 c
  s +
Convert buffer to subcircuit
PasteBuffer(ConvertSubc) +
b
 m
  l +
Mirror buffer (left/right)
Mode(PasteBuffer); PasteBuffer(Rotate,1); PasteBuffer(Mirror); PasteBuffer(Rotate,3) +
b
 m
  u +
Mirror buffer (up/down)
Mode(PasteBuffer); PasteBuffer(Mirror) +
b
 n +
Normalize
Mode(PasteBuffer); PasteBuffer(Rotate,1); PasteBuffer(Normalize) +
b
 r
  a +
Arbitrarily Rotate Buffer
Mode(PasteBuffer); FreeRotateBuffer() +
b
 r
  l +
Rotate buffer 90 deg CCW (left)
Mode(PasteBuffer); PasteBuffer(Rotate,1) +
b
 r
  r +
Rotate buffer 90 deg CW (right)
Mode(PasteBuffer); PasteBuffer(Rotate,3) +
b
 s
  b +
Break buffer subcircuits to pieces
PasteBuffer(Restore) +
b
 s
  p +
Break buffer padstacks to pieces
PadstackBreakup(buffer) +
b
 s
  s +
Save buffer subcircuits to file
Save(PasteBuffer) +
c-ctrl
  +
Copy selection to buffer
GetXY(Click to set the snap point for this buffer); PasteBuffer(Clear); PasteBuffer(AddSelected); Unselect(All); Mode(PasteBuffer) +
c
 c
   +
Clear/reset lookup
Connection(Reset); Display(Redraw) +
c
 d
   +
Del/Remove Connected
Atomic(Save); Connection(Reset); Atomic(Restore); Unselect(All); Atomic(Restore); Connection(Find); Atomic(Restore); Select(Connection); Atomic(Restore); RemoveSelected(); Atomic(Restore); Connection(Reset); Atomic(Restore); Unselect(All); Atomic(Block) +
c
 e
   +
Erase rats nest
DeleteRats(AllRats) +
c
 f
   +
Find Connections
Connection(Reset); Connection(Find) +
c
 r
   +
Optimize rats nest
Atomic(Save); DeleteRats(AllRats); Atomic(Restore); AddRats(AllRats); Atomic(Block) +
c
 s
   +
Select shortest rat
AddRats(Close) +
delete + Remove object
Mode(Save); Mode(Remove); Mode(Notify); Mode(Restore) +
down + Step Down
Cursor(Warp,0,-1,grid) +
down-shift + Step +Down
Cursor(Pan,0,-50,view) +
e
 c +
Copy selection to buffer
GetXY(Click to set the snap point for this buffer); PasteBuffer(Clear); PasteBuffer(AddSelected); Unselect(All); Mode(PasteBuffer) +
e
 d +
Remove object
Mode(Save); Mode(Remove); Mode(Notify); Mode(Restore) +
e
 f +
Object flags...
FlagEdit() +
e
 g
  c +
Clearance +2 mil
ChangeClearSize(Object,+2,mil) +
e
 g
  c-shift +
Clearance -2 mil
ChangeClearSize(Object,-2,mil) +
e
 g
  d +
ChangeDrill +5 mil
ChangeDrillSize(Object,+5,mil) +
e
 g
  d-shift +
ChangeDrill -5 mil
ChangeDrillSize(Object,-5,mil) +
e
 g
  s +
ChangeSize +5 mil
ChangeSize(Object,+5,mil) +
e
 g
  s-shift +
ChangeSize -5 mil
ChangeSize(Object,-5,mil) +
e
 g
  y +
ChangeSizes to Route style
ChangeSizes(Object,style,mil) +
e
 i +
Flip Object
Flip(Object) +
e
 j +
ChangeJoin Object
ChangeJoin(Object) +
e
 l +
Move to current layer
MoveToCurrentLayer(Object) +
e
 o +
Change font...
FontSel(Object) +
e
 p +
Object Properties...
PropEdit(selection) +
e
 r +
Change refdes
ChangeName(Refdes) +
e
 s
  b +
Layer bindings...
LayerBinding() +
e
 s
  e +
External editor...
GetXY(Click on the subcircuit to edit); extedit(object) +
e
 s
  r +
Refdes
ChangeName(Subc) +
e
 s
  s +
Set Same Style
SetSame() +
e
 t +
Edit text...
ChangeName(Object) +
e
 v +
Paste buffer to layout
Mode(PasteBuffer) +
e
 x +
Cut selection to buffer
GetXY(Click to set the snap point for this buffer); PasteBuffer(Clear); PasteBuffer(AddSelected); RemoveSelected(); Unselect(All); Mode(PasteBuffer) +
e
 y
   +
Cycle object being dragged
CycleDrag() +
enter + Click
Mode(Notify); Mode(Release) +
escape + Cancel
Mode(Escape) +
f1 + Via
Mode(Via) +
f10 + Thermal
Mode(Thermal) +
f11 + Arrow
Mode(Arrow) +
f12 + Lock
Mode(Lock) +
f2 + Line
Mode(Line) +
f3 + Arc
Mode(Arc) +
f4 + Text
Mode(Text) +
f5 + Rectangle
Mode(Rectangle) +
f6 + Polygon
Mode(Polygon) +
f7 + Buffer
Mode(PasteBuffer) +
f7-shift + Rotate buffer 90 deg CCW (left)
Mode(PasteBuffer); PasteBuffer(Rotate,1) +
f8 + Del/Remove
Mode(Remove) +
f9 + Rotate
Mode(Rotate) +
f
 a +
Save Layout As...
Save(LayoutAs) +
f
 c +
Export with CAM job...
cam() +
f
 e +
Export layout...
ExportGUI() +
f
 l +
Load layout...
Load(Layout) +
f
 n +
Start New Layout
New() +
f
 o +
Load layout...
Load(Layout) +
f
 p +
Print layout...
Print() +
f
 q +
Quit Program
Quit() +
f
 r +
Revert
Load(Revert,none) +
f
 s +
Save Layout
Save(Layout) +
f
 x
  p +
netlist patch for back annotation
SavePatch() +
g
 b +
Previous grid
Grid(down) +
g
 d +
Grid *2
SetValue(Grid,*2) +
g
 f +
Next grid
Grid(up) +
g
 h +
Grid /2
SetValue(Grid,/2) +
g
 i +
mil
SetUnits(mil) +
g
 l +
Enable local grid
conf(toggle, plugins/hid_gtk/local_grid/enable, design) +
g
 m +
mm
SetUnits(mm) +
g
 r +
Realign grid
GetXY(Click to set the grid origin); Display(ToggleGrid) +
g
 v +
Enable visible grid
conf(toggle, editor/draw_grid, design) +
i
 a +
About...
About() +
i
 c
  c +
Calibrate Printer...
PrintCalibrate() +
i
 c
  i +
Data integrity check
Integrity() +
i
 c
  p +
Preferences...
preferences +
i
 c
  r +
Re-scan the footprint library
fp_rehash() +
i
 d +
Generate drill summary
Report(DrillReport) +
i
 f +
Report found padstacks
Report(FoundPins) +
i
 r +
Generate object report
ReportObject() +
insert + Insert Point
Mode(InsertPoint) +
left + Step Left
Cursor(Warp,-1,0,grid) +
left-shift + Step +Left
Cursor(Pan,-50,0,view) +
m
 c
  c +
Crosshair shows DRC clearance
conf(toggle, editor/show_drc, design) +
m
 c
  o +
Orthogonal moves
conf(toggle, editor/orthogonal_moves, design) +
m
 c
  p +
Crosshair snaps to padstacks
conf(toggle, editor/snap_pin, design) +
m
 c
  s +
Crosshair snaps to off-grid points on lines
conf(toggle, editor/snap_offgrid_line, design) +
m
 d
  a +
Show autorouter trials
conf(toggle, editor/live_routing, design) +
m
 d
  c +
Check polygons
conf(toggle, editor/check_planes, design) +
m
 d
  d +
poly as-drawn frame annotation
conf(toggle, editor/as_drawn_poly, design) +
m
 d
  h +
Highlighting on line, arc points
conf(toggle, editor/highlight_on_point, design) +
m
 d
  p +
Thin draw poly
conf(toggle, editor/thin_draw_poly, design) +
m
 d
  t +
Thin draw
conf(toggle, editor/thin_draw, design) +
m
 d
  w +
Wireframe draw
conf(toggle, editor/wireframe_draw, design) +
m
 f
  h +
Hide floaters
conf(toggle, editor/hide_names, design) +
m
 f
  l +
Lock floaters
conf(toggle, editor/lock_names, design) +
m
 f
  o +
Only floaters
conf(toggle, editor/only_names, design) +
m
 k
  s +
Loose subcircuits (no subc lock)
subc(loose, toggle) +
m
 l
  + +
Line Tool size +5 mil
SetValue(LineSize,+5,mil) +
m
 l
  - +
Line Tool size -5 mil
SetValue(LineSize,-5,mil) +
m
 l
  a +
'All-direction' lines
conf(toggle, editor/all_direction_lines, design) +
m
 l
  c +
New lines, arcs clear polygons
conf(toggle, editor/clear_line, design) +
m
 l
  d +
Auto enforce DRC clearance
conf(toggle, editor/auto_drc, design) +
m
 l
  f +
Cycle line clip/refraction
Display(CycleClip) +
m
 o
  b +
black current group
conf(toggle, appearance/black_current_group, design) +
m
 o
  i +
Invisible-color on other groups
conf(toggle, appearance/invis_other_groups, design) +
m
 p
  c +
New polygons clear polygons
conf(toggle, editor/clear_polypoly, design) +
m
 p
  f +
New polygons are full ones
conf(toggle, editor/full_poly, design) +
m
 p
  i +
Polygon clip inhibit (toggle)
ClipInhibit(toggle) +
m
 r
  m +
Rubber band keeps middle line dir
conf(toggle, editor/rubber_band_keep_midlinedir, design) +
m
 r
  r +
Rubber band mode
conf(toggle, editor/rubber_band_mode, design) +
m
 t
  + +
Text Tool scale +10 mil
SetValue(TextScale,+10,mil) +
m
 t
  - +
Text Tool scale -10 mil
SetValue(TextScale,-10,mil) +
n-ctrl + Start New Layout
New() +
n
 c
  f
    +
claim net on found
ClaimNet(found) +
n
 c
  o
    +
claim net by object
ClaimNet(object) +
n
 c
  s
    +
claim net on selected
ClaimNet(selected) +
p
 m
  p
    +
Manage plugins...
ManagePlugins() +
p
 m
  s
    +
Manage scripts...
BrowseScripts() +
q-ctrl + Quit Program
Quit() +
r
 r
  + +
Route radius +0.5
conf(delta, editor/route_radius, +0.5, design) +
r
 r
  - +
Route radius -0.5
conf(delta, editor/route_radius, -0.5, design) +
r
 r
  m +
Route radius -0.5
conf(delta, editor/route_radius, -0.5, design) +
r
 r
  p +
Route radius +0.5
conf(delta, editor/route_radius, +0.5, design) +
right + Step Right
Cursor(Warp,1,0,grid) +
right-shift + Step +Right
Cursor(Pan,50,0,view) +
s-ctrl + Save Layout
Save(Layout) +
s-ctrl-shift + Save Layout As...
Save(LayoutAs) +
s
 a
  a
    +
Select all visible objects
Select(All) +
s
 a
  c
    +
Select all connected objects
Select(Connection) +
s
 b
  p +
Break selection padstack to pieces
PadstackBreakup(selected) +
s
 b
  s +
Break selection subcircuits to pieces
PasteBuffer(Push); PasteBuffer(5); PasteBuffer(Clear); PasteBuffer(AddSelected); RemoveSelected(); PasteBuffer(Restore); PasteBuffer(ToLayout, crosshair); PasteBuffer(Clear); PasteBuffer(Pop) +
s
 c
  p
    +
Convert selection to padstack
PadstackConvert(selected); Mode(PasteBuffer) +
s
 c
  s
    +
Convert selection to subcircuit
Select(ConvertSubc) +
s
 f
   +
Move selected subcircuits to other side
Flip(SelectedElements) +
s
 i
   +
Invert selection
Select(Invert) +
s
 l
   +
Move selected objects to current layer
MoveToCurrentLayer(Selected) +
s
 r
   +
Remove selected objects
RemoveSelected() +
s
 s
   +
Advanced search and select
DoWindows(search) +
s
 u
  a
    +
Unselect all objects
Unselect(All) +
s
 u
  c
    +
unselect all connected objects
Unselect(Connection) +
space + Arrow
Mode(Arrow) +
t
 a +
Arc
Mode(Arc) +
t
 b +
Buffer
Mode(PasteBuffer) +
t
 c +
Copy
Mode(Copy) +
t
 d +
Del/Remove
Mode(Remove) +
t
 e +
Thermal
Mode(Thermal) +
t
 h +
Polygon Hole
Mode(PolygonHole) +
t
 i +
Insert Point
Mode(InsertPoint) +
t
 k +
Lock
Mode(Lock) +
t
 l +
Line
Mode(Line) +
t
 m +
Move
Mode(Move) +
t
 n +
Arrow
Mode(Arrow) +
t
 o +
Rotate
Mode(Rotate) +
t
 p +
Polygon
Mode(Polygon) +
t
 r +
Rectangle
Mode(Rectangle) +
t
 t +
Text
Mode(Text) +
t
 v +
Via
Mode(Via) +
tab + Flip up/down
SwapSides(V) +
tab-ctrl + Spin 180 degrees
SwapSides(R) +
tab-ctrl-shift + Swap Sides
SwapSides() +
tab-shift + Flip left/right
SwapSides(H) +
u
 c +
Clear undo-buffer
Undo(ClearList) +
u
 d
   +
Undo dialog (for debugging)
UndoDialog() +
u
 r +
Redo last undone operation
Redo() +
u
 u +
Undo last operation
Undo() +
up + Step Up
Cursor(Warp,0,1,grid) +
up-shift + Step +Up
Cursor(Pan,0,50,view) +
v
 c +
Center cursor
Center() +
v
 f +
Zoom Extents
Zoom() +
v
 n +
Show padstack numbers in a subc
Display(PinOrPadName) +
v
 s
  c +
user configured
Display(SubcID) +
v
 s
  f +
footprint
Display(SubcID,"%a.footprint%") +
v
 s
  r +
refdes
Display(SubcID, "%a.refdes%") +
v
 s
  s +
refdes+value
Display(SubcID,"%a.refdes%\\n%a.value%") +
v
 s
  v +
value
Display(SubcID,"%a.value%") +
v
 t
  c +
user configured
Display(TermID) +
v
 t
  n +
name
Display(TermID, "%a.name%") +
v
 t
  s +
term+name
Display(TermID, "%a.term%,%a.name%") +
v
 t
  t +
term
Display(TermID, "%a.term%") +
w
 a +
About...
About() +
w
 d +
DRC Check
DRC() +
w
 f +
Font selector
FontSel() +
w
 l +
Library
DoWindows(Library) +
w
 m +
Message Log
LogDialog() +
w
 n +
Netlist
DoWindows(Netlist) +
w
 p +
Pinout
Display(Pinout) +
y-ctrl + Redo last undone operation
Redo() +
z-ctrl + Undo last operation
Undo() +
z
 e
   +
Zoom Extents
Zoom() +
z
 f
   +
Zoom to found
ZoomTo(found) +
z
 s
   +
Zoom to selection
ZoomTo(selected) +
z
 x
   +
Zoom Out 20%
Zoom(+1.2) +
z
 z
   +
Zoom In 20%
Zoom(-1.2) +
| + Wireframe draw
conf(toggle, editor/wireframe_draw, design) +
+ + Index: tags/2.1.2/doc/license.html =================================================================== --- tags/2.1.2/doc/license.html (nonexistent) +++ tags/2.1.2/doc/license.html (revision 24813) @@ -0,0 +1,56 @@ + + + + pcb-rnd - license + + + + + + + + + + +
Main + News + Doc & pool + Support + People + Events & timeline + pcb-rnd [pcb-rnd logo] +
+ + +

pcb-rnd - license

+Pcb-rnd is a Free Software, Open source, under the terms of GPL version 2. +

+Pcb-rnd started as a fork of gEDA/PCB thus inherited its GPL2+ license. +See file +trunk/COPYING for more details on the license terms. Pcb-rnd +incorporates a few mini-libs with various, GPL-compatible licenses, mostly +BSD, MIT and public domain - the official Debian package has a great index of these. +

+For users: the resulting software is distributable under the GNU GPL version 2 +(or later versions), the usual GPL terms and conditions apply. +

+Contribution: by contributing, you agree to submit patches that are conforming +to the license terms (e.g. don't copy random code from other projects). We +are keeping track of copyright: each contributor holds the copyright for and +is responsible for their part. Contributors agree to license their contribution +under the same term as the subproject they are adding to, which is typically +GPL2+ for core and plugins and utilities. +

+Re-licensing under different conditions: pcb-rnd's GPL2+ allows the user +to upgrade to GPL3 or later versions of the GPL (as long as new versions +don't contradict with the license of the mini-libs). It is not possible to +change pcb-rnd's license to anything else unless all past developers agree +(but there's not even a index of all the names!). It is possible to request +relicensing of the files that are brand new in pcb-rnd (they are all marked +in the copyright banner on the top of the file) - this requires the agreement +of all copyright holders listed in the file, and wouldn't affect other files. +Same rules apply for mini-libs. + + + + Index: tags/2.1.2/doc/mac.txt =================================================================== --- tags/2.1.2/doc/mac.txt (nonexistent) +++ tags/2.1.2/doc/mac.txt (revision 24813) @@ -0,0 +1,30 @@ +State on MacOSX +~~~~~~~~~~~~~~~ + +Source releases starting from 1.1.0 should compile and run out-of-the-box. + +Requirements for GUI: x11 and gtk+ + - X11 server and client libraries for OS X are available from the XQuartz + download and install + - gtk+ is available from brew + * brew install dependencies (gtk+ and libgd) with the following commands + brew install libgd + brew install gtk+ + brew install pkg-config + * if you want to use gEDA with PCB-RND you may want to install it as well + via brew + brew install homebrew/science/geda-gaf + +Known issues: + - application window opens behind other windows; it seems to be a gtk bug + that can not be worked around from the application + - slow rendering and error messages about invalid numerics on the console + +Considerations listed in ../INSTALL apply. + +pcb-rnd is reported to work at least on the following versions: + +macOS xquartz +---------------------------- +10.14.3 majove 2.7.11 + Index: tags/2.1.2/doc/man/Makefile =================================================================== --- tags/2.1.2/doc/man/Makefile (nonexistent) +++ tags/2.1.2/doc/man/Makefile (revision 24813) @@ -0,0 +1,63 @@ +# This Makefile is a plain old hand written one; all configuration settings +# are included from $(ROOT)/Makefile.conf which is scconfig generated +ROOT=../.. + +IN=pcb-rnd.1.mml pcb-strip.1.mml pcb-prj2lht.1.mml fp2anim.1.mml fp2subc.1.mml +OUT_HTML = pcb-rnd.1.html pcb-strip.1.html pcb-prj2lht.1.html fp2anim.1.html fp2subc.1.html +OUT_MAN1 = pcb-rnd.1 pcb-strip.1 pcb-prj2lht.1 fp2anim.1 fp2subc.1 +OUT_LINT = pcb-rnd.1.lint pcb-strip.1.lint pcb-prj2lht.1.lint fp2anim.1.lint fp2subc.1.lint + +OUTPUT = $(OUT_HTML) $(OUT_MAN1) index.html +MML = /usr/bin/mml + +all: $(OUTPUT) + +lint: $(OUT_LINT) + +.SUFFIXES: .html .mml .lint + +.mml.html: .mml_linkmap + $(MML) -i copyright.mml -f html $< > $@ + +.mml: + $(MML) -i copyright.mml -f man $< > $@ + +.mml_linkmap: + $(MML) -i copyright.mml -f linkmap $(IN) > $@ + +index.html: $(IN) + @echo '' > $@ + @echo 'man page index - pcb-rnd

    ' >> $@ + $(MML) -i copyright.mml -f indexhtml $(IN) >> $@ + @echo "
" >> $@ + +clean: + +distclean: + +genclean: + rm $(OUTPUT) 2>/dev/null ; true + +.mml.lint: + $(MML) -i copyright.mml -f lint $< + +install_all: + $(SCCBOX) mkdir -p "$(MAN1DIR)" + $(SCCBOX) $(HOW) "pcb-rnd.1" "$(MAN1DIR)/pcb-rnd.1" + $(SCCBOX) $(HOW) "pcb-strip.1" "$(MAN1DIR)/pcb-strip.1" + $(SCCBOX) $(HOW) "pcb-prj2lht.1" "$(MAN1DIR)/pcb-prj2lht.1" + $(SCCBOX) $(HOW) "gsch2pcb-rnd.1" "$(MAN1DIR)/gsch2pcb-rnd.1" + $(SCCBOX) $(HOW) "fp2anim.1" "$(MAN1DIR)/fp2anim.1" + $(SCCBOX) $(HOW) "fp2subc.1" "$(MAN1DIR)/fp2subc.1" + +install: + $(MAKE) install_all HOW="install -f" + +linstall: + $(MAKE) install_all HOW="linstall -f" + +uninstall: + $(MAKE) install_all HOW="uninstall" + +include $(ROOT)/Makefile.conf + Index: tags/2.1.2/doc/man/README =================================================================== --- tags/2.1.2/doc/man/README (nonexistent) +++ tags/2.1.2/doc/man/README (revision 24813) @@ -0,0 +1,10 @@ +Manual pages are written in the manual markup format and are compiled into +manual and html using mml. Do not edit the generated manual or html pages. + +The generated files are commited in the repository so dependencies are not +required for casual users to build the project. + +The required tools and dependencies are: + svn://repo.hu/libmawk/trunk + svn://repo.hu/web3.0/trunk + svn://repo.hu/shscripts/trunk/manmarkup Index: tags/2.1.2/doc/man/copyright.mml =================================================================== --- tags/2.1.2/doc/man/copyright.mml (nonexistent) +++ tags/2.1.2/doc/man/copyright.mml (revision 24813) @@ -0,0 +1,21 @@ + +pcb-rnd - manual\n +Copyright (C) 2016 Tibor 'Igor2' Palinkas\n +\n +This program is free software; you can redistribute it and/or modify\n +it under the terms of the GNU General Public License as published by\n +the Free Software Foundation; either version 2 of the License, or\n +(at your option) any later version.\n +\n +This program is distributed in the hope that it will be useful,\n +but WITHOUT ANY WARRANTY; without even the implied warranty of\n +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n +GNU General Public License for more details.\n +\n +You should have received a copy of the GNU General Public License along\n +with this program; if not, write to the Free Software Foundation, Inc.,\n +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n +\n +Contact: pcb-rnd-man[removethis]@igor2.repo.hu + +pcb-rnd manual Index: tags/2.1.2/doc/man/fp2anim.1 =================================================================== --- tags/2.1.2/doc/man/fp2anim.1 (nonexistent) +++ tags/2.1.2/doc/man/fp2anim.1 (revision 24813) @@ -0,0 +1,67 @@ +.\" pcb-rnd - manual +.\" Copyright (C) 2016 Tibor 'Igor2' Palinkas +.\" +.\" This program is free software; you can redistribute it and/or modify +.\" it under the terms of the GNU General Public License as published by +.\" the Free Software Foundation; either version 2 of the License, or +.\" (at your option) any later version. +.\" +.\" This program is distributed in the hope that it will be useful, +.\" but WITHOUT ANY WARRANTY; without even the implied warranty of +.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +.\" GNU General Public License for more details. +.\" +.\" You should have received a copy of the GNU General Public License along +.\" with this program; if not, write to the Free Software Foundation, Inc., +.\" 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +.\" +.\" Contact: pcb-rnd-man[removethis]@igor2.repo.hu +.TH fp2anim 1 2016-12-27 "" "pcb-rnd manual" +.SH NAME +fp2anim - convert a gEDA/PCB footprint to animator script +.SH SYNPOSIS +.nf +.sp +\fBfp2anim [\fIoptions\fB] [\fIinputfile\fB] +.fi +.SH DECSRIPTION + +.BR fp2anim +converts a footprint to a script that can be run through animator(1). It's main use is to have a automated, light-weight footprint preview generator on hosts where installing pcb-rnd would be too expensive (e.g. on web servers). +.PP +If \fIinputfile\fR is not specified, +.BR fp2anim +reads its STDIN for the footprint. +.SH OPTIONS + + +.TP + +.B --photo +draw the footprint in "photo realistic mode" +.TP + +.B -p +same as --photo +.TP + +.B --grid unit +set grid unit e.g. to mm or mil +.TP + +.B -g unit +same as --grid +.TP + +.B --mm +use an mm grid instead of a mil grid; shorthand for -g mm +.TP + +.B --diamond +draw a small diamond to mark at footprint origin +.TP + +.B --annotation types +turn on annotation types; types is a string that may consist "pins" for pin numbers, "dimname" and "dimvalue" for dimension names and values and "background" for drawing a background under annotation text +.PP + Index: tags/2.1.2/doc/man/fp2anim.1.html =================================================================== --- tags/2.1.2/doc/man/fp2anim.1.html (nonexistent) +++ tags/2.1.2/doc/man/fp2anim.1.html (revision 24813) @@ -0,0 +1,102 @@ + + + +fp2anim - pcb-rnd manual + + + + +
fp2anim 1 + 2016-12-27 + pcb-rnd manual +
+ + + +

NAME

+
+fp2anim - convert a gEDA/PCB footprint to animator script +
+ +

SYNPOSIS

+
+

+fp2anim [options] [inputfile] + + + +

+ +

DESCRIPTION

+
+fp2anim converts a footprint to a script that can be run through animator(1). It's main use is to have a automated, light-weight footprint preview generator on hosts where installing pcb-rnd would be too expensive (e.g. on web servers). +

+If inputfile is not specified, fp2anim reads its STDIN for the footprint. + +

+ + +

OPTIONS

+
+ + + + + + + + + + + + + + + + + +
--photo + draw the footprint in "photo realistic mode" +
-p + same as --photo +
--grid unit + set grid unit e.g. to mm or mil +
-g unit + same as --grid +
--mm + use an mm grid instead of a mil grid; shorthand for -g mm +
--diamond + draw a small diamond to mark at footprint origin +
--annotation types + turn on annotation types; types is a string that may consist "pins" for pin numbers, "dimname" and "dimvalue" for dimension names and values and "background" for drawing a background under annotation text +
+
+

+ + +
fp2anim 1 + 2016-12-27 + pcb-rnd manual +
+ + + Index: tags/2.1.2/doc/man/fp2anim.1.mml =================================================================== --- tags/2.1.2/doc/man/fp2anim.1.mml (nonexistent) +++ tags/2.1.2/doc/man/fp2anim.1.mml (revision 24813) @@ -0,0 +1,58 @@ +fp2anim +1 +2016-12-27 + + fp2anim - convert a gEDA/PCB footprint to animator script + fp2anim [options] [inputfile] + + +fp2anim converts a footprint to a script that can be run through +animator(1). It's main use is to have a automated, light-weight footprint +preview generator on hosts where installing pcb-rnd would be too expensive +(e.g. on web servers). +

+If inputfile is not specified, fp2anim reads its +STDIN for the footprint. + + + + + + + --photo + draw the footprint in "photo realistic mode" + + + -p + same as --photo + + + + --grid unit + set grid unit e.g. to mm or mil + + + -g unit + same as --grid + + + + --mm + use an mm grid instead of a mil grid; shorthand for -g mm + + + + --diamond + draw a small diamond to mark at footprint origin + + + + --annotation types + turn on annotation types; types is a string that may consist + "pins" for pin numbers, "dimname" and "dimvalue" for dimension + names and values and "background" for drawing a background under + annotation text + + + + Index: tags/2.1.2/doc/man/fp2subc.1 =================================================================== --- tags/2.1.2/doc/man/fp2subc.1 (nonexistent) +++ tags/2.1.2/doc/man/fp2subc.1 (revision 24813) @@ -0,0 +1,65 @@ +.\" pcb-rnd - manual +.\" Copyright (C) 2016 Tibor 'Igor2' Palinkas +.\" +.\" This program is free software; you can redistribute it and/or modify +.\" it under the terms of the GNU General Public License as published by +.\" the Free Software Foundation; either version 2 of the License, or +.\" (at your option) any later version. +.\" +.\" This program is distributed in the hope that it will be useful, +.\" but WITHOUT ANY WARRANTY; without even the implied warranty of +.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +.\" GNU General Public License for more details. +.\" +.\" You should have received a copy of the GNU General Public License along +.\" with this program; if not, write to the Free Software Foundation, Inc., +.\" 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +.\" +.\" Contact: pcb-rnd-man[removethis]@igor2.repo.hu +.TH fp2subc 1 2018-04-08 "" "pcb-rnd manual" +.SH NAME +fp2subc - convert any footprint into a pcb-rnd subcircuit +.SH SYNPOSIS +.nf +.sp +\fBfp2subc [\fIoptions\fB] \fIinfile\fB [\fIoutfile\fB] +.fi +.SH DECSRIPTION + +.BR fp2subc +executes pcb-rnd in batch mode to load a footprint (typically specified in an alien format) and save it as a native pcb-rnd subcircuit. The script is useful for mass-converting old footprint libraries. +.PP +If \fIoutfile\fR is not specified, its name is guessed from \fIinfile\fR +.SH OPTIONS + + +.TP + +.B --lib +\fIinfile\fR is not a path but a footprint name that should be searched in the library +.TP + +.B -l +same as --lib +.TP + +.B --pcb-rnd exepath +run exepath for invoking pcb-rnd (default is "pcb-rnd", which depends on $PATH) +.TP + +.B -p exepath +same as --pcb-rnd +.TP + +.B --debugger exepath +insert exepath before pcb-rnd on the command line; useful for running the process e.g. in valgrind +.TP + +.B -d exepath +same as --debugger +.TP + +.B -c key=val +pass on a -c key=val CLI config setting to pcb-rnd; useful for setting up library paths +.PP + Index: tags/2.1.2/doc/man/fp2subc.1.html =================================================================== --- tags/2.1.2/doc/man/fp2subc.1.html (nonexistent) +++ tags/2.1.2/doc/man/fp2subc.1.html (revision 24813) @@ -0,0 +1,102 @@ + + + +fp2subc - pcb-rnd manual + + + + +
fp2subc 1 + 2018-04-08 + pcb-rnd manual +
+ + + +

NAME

+
+fp2subc - convert any footprint into a pcb-rnd subcircuit +
+ +

SYNPOSIS

+
+

+fp2subc [options] infile [outfile] + + + +

+ +

DESCRIPTION

+
+fp2subc executes pcb-rnd in batch mode to load a footprint (typically specified in an alien format) and save it as a native pcb-rnd subcircuit. The script is useful for mass-converting old footprint libraries. +

+If outfile is not specified, its name is guessed from infile + +

+ + +

OPTIONS

+
+ + + + + + + + + + + + + + + + + +
--lib + infile is not a path but a footprint name that should be searched in the library +
-l + same as --lib +
--pcb-rnd exepath + run exepath for invoking pcb-rnd (default is "pcb-rnd", which depends on $PATH) +
-p exepath + same as --pcb-rnd +
--debugger exepath + insert exepath before pcb-rnd on the command line; useful for running the process e.g. in valgrind +
-d exepath + same as --debugger +
-c key=val + pass on a -c key=val CLI config setting to pcb-rnd; useful for setting up library paths +
+
+

+ + +
fp2subc 1 + 2018-04-08 + pcb-rnd manual +
+ + + Index: tags/2.1.2/doc/man/fp2subc.1.mml =================================================================== --- tags/2.1.2/doc/man/fp2subc.1.mml (nonexistent) +++ tags/2.1.2/doc/man/fp2subc.1.mml (revision 24813) @@ -0,0 +1,58 @@ +fp2subc +1 +2018-04-08 + + fp2subc - convert any footprint into a pcb-rnd subcircuit + fp2subc [options] infile [outfile] + + +fp2subc executes pcb-rnd in batch mode to load a footprint +(typically specified in an alien format) and save it as a native pcb-rnd +subcircuit. The script is useful for mass-converting old footprint +libraries. +

+If outfile is not specified, its name is guessed from +infile + + + + + + + --lib + infile is not a path but a footprint name that + should be searched in the library + + + -l + same as --lib + + + + --pcb-rnd exepath + run exepath for invoking pcb-rnd (default is "pcb-rnd", which + depends on $PATH) + + + -p exepath + same as --pcb-rnd + + + + --debugger exepath + insert exepath before pcb-rnd on the command line; useful + for running the process e.g. in valgrind + + + -d exepath + same as --debugger + + + + -c key=val + pass on a -c key=val CLI config setting to pcb-rnd; useful for + setting up library paths + + + + Index: tags/2.1.2/doc/man/gsch2pcb-rnd.1 =================================================================== --- tags/2.1.2/doc/man/gsch2pcb-rnd.1 (nonexistent) +++ tags/2.1.2/doc/man/gsch2pcb-rnd.1 (revision 24813) @@ -0,0 +1,134 @@ +.TH gsch2pcb-rnd 1 "September 25th, 2013" "gEDA Project" 1.8.2.20130925 +.SH NAME +gsch2pcb-rnd - Update pcb-rnd layouts from gEDA/gaf schematics +.SH SYNOPSIS +\fBgsch2pcb-rnd\fR [\fIOPTION\fR ...] {\fIPROJECT\fR | \fIFILE\fR ...} +.SH DESCRIPTION +.PP +\fBgsch2pcb-rnd\fR is a frontend to \fBgnetlist\fR(1) which aids in +creating and updating \fBpcb-rnd\fR(1) printed circuit board layouts based +on a set of electronic schematics created with \fBgschem\fR(1). + +.PP +Instead of specifying all options and input gEDA schematic \fIFILE\fRs +on the command line, \fBgsch2pcb-rnd\fR can use a \fIPROJECT\fR file +instead. + +.PP +\fBgsch2pcb-rnd\fR first runs \fBgnetlist\fR(1) with the `PCB' backend to +create a `.net' file containing a \fBpcb-rnd\fR(1) formatted netlist for +the design. + +.PP +The second step is to run \fBgnetlist\fR(1) again with the `gsch2pcb-rnd' +backend to find any \fBM4\fR(1) elements required by the schematics. +Any missing elements are found by searching a set of file element +directories. If no `.pcb' file exists for the design yet, it is +created with the required elements; otherwise, any new elements +are output to a `.new.pcb' file. + +.PP +If a `.pcb' file exists, it is searched for elements with a +non-empty element name with no matching schematic symbol. These +elements are removed from the `.pcb' file, with a backup in a +`.pcb.bak' file. + +.PP +Finally, \fBgnetlist\fR(1) is run a third time with the `pcbpins' +backend to create a `.cmd' file. This can be loaded into +\fBpcb-rnd\fR(1) to rename all pin names in the PCB layout to match the +schematic. + +.SH OPTIONS +.TP 8 +\fB-o\fR, \fB--output-name\fR=\fIBASENAME\fR +Use output filenames `\fIBASENAME\fR.net', `\fIBASENAME\fR.pcb', and +`\fIBASENAME\fR.new.pcb'. By default, the basename of the first +schematic file in the list of input files is used. +.TP 8 +\fB-d\fR, \fB--elements-dir\fR=\fIDIRECTORY\fR +Add \fIDIRECTORY\fR to the list of directories to search for PCB file +elements. +.TP 8 +\fB-r\fR, \fB--remove-unfound\fR +Don't include references to unfound elements in the generated `.pcb' +files. Use if you want \fBpcb-rnd\fR(1) to be able to load the +(incomplete) `.pcb' file. This is enabled by default. +.TP 8 +\fB-k\fR, \fB--keep-unfound\fR +Keep include references to unfound elements in the generated `.pcb' +files. Use if you want to hand edit or otherwise preprocess the +generated `.pcb' file before running \fBpcb\fR(1). +.TP 8 +\fB-p\fR, \fB--preserve\fR +Preserve elements in PCB files which are not found in the schematics. +Since elements with an empty element name (schematic "refdes") are +never deleted, this option is rarely useful. +.TP 8 +\fB--gnetlist\fR \fIBACKEND\fR +In addition to the default backends, run \fBgnetlist\fR(1) with `\-g +\fIBACKEND\fR', with output to `.\fIBACKEND\fR'. +.TP 8 +\fB--gnetlist-arg\fR \fIARG\fR +Pass \fIARG\fR as an additional argument to \fBgnetlist\fR(1). +.TP 8 +\fB--empty-footprint\fR \fINAME\fR +If \fINAME\fR is not `none', \fBgsch2pcb-rnd\fR will not add elements for +components with that name to the PCB file. Note that if the omitted +components have net connections, they will still appear in the netlist +and \fBpcb-rnd\fR(1) will warn that they are missing. +.TP 8 +\fB--fix-elements\fR +If a schematic component's `footprint' attribute is not equal to the +`Description' of the corresponding PCB element, update the +`Description' instead of replacing the element. +.TP 8 +\fB-q\fR, \fB--quiet\fR +Don't output information on steps to take after running \fBgsch2pcb-rnd\fR. +.TP 8 +\fB-v\fR, \fB--verbose\fR +Output extra debugging information. This option can be specified +twice (`\-v \-v') to obtain additional debugging for file elements. +.TP 8 +\fB-h\fR, \fB--help\fR +Print a help message. +.TP 8 +\fB-V\fR, \fB--version\fR +Print \fBgsch2pcb-rnd\fR version information. + +.SH PROJECT FILES +.PP +A \fBgsch2pcb-rnd\fR project file is a file (not ending in `.sch') +containing a list of schematics to process and some options. Any +long-form command line option can appear in the project file with the +leading `\-\-' removed, with the exception of `\-\-gnetlist-arg', +`\-\-fix-elements', `\-\-verbose', and `\-\-version'. Schematics should be +listed on a line beginning with `schematics'. +.PP +An example project file might look like: + +.nf + schematics partA.sch partB.sch + output-name design +.ad b + +.SH ENVIRONMENT +.TP 8 +.B GNETLIST +specifies the \fBgnetlist\fR(1) program to run. The default is +`gnetlist'. + +.SH AUTHORS +See the `AUTHORS' file included with this program. + +.SH COPYRIGHT +.nf +Copyright \(co 1999-2011 gEDA Contributors. License GPLv2+: GNU GPL +version 2 or later. Please see the `COPYING' file included with this +program for full details. +.PP +This is free software: you are free to change and redistribute it. +There is NO WARRANTY, to the extent permitted by law. + +.SH SEE ALSO +\fBgschem\fR(1), \fBgnetlist\fR(1), \fBpcb-rnd\fR(1) Index: tags/2.1.2/doc/man/index.html =================================================================== --- tags/2.1.2/doc/man/index.html (nonexistent) +++ tags/2.1.2/doc/man/index.html (revision 24813) @@ -0,0 +1,8 @@ + +man page index - pcb-rnd

    +
  • pcb-rnd (1) -- pcb-rnd - Printed Circuit Board editor +
  • pcb-strip (1) -- pcb-strip - remove sections of a pcb file +
  • pcb-prj2lht (1) -- pcb-prj2lht - convert old gsch2pcb project file to pcb-rnd project +
  • fp2anim (1) -- fp2anim - convert a gEDA/PCB footprint to animator script +
  • fp2subc (1) -- fp2subc - convert any footprint into a pcb-rnd subcircuit +
Index: tags/2.1.2/doc/man/pcb-prj2lht.1 =================================================================== --- tags/2.1.2/doc/man/pcb-prj2lht.1 (nonexistent) +++ tags/2.1.2/doc/man/pcb-prj2lht.1 (revision 24813) @@ -0,0 +1,32 @@ +.\" pcb-rnd - manual +.\" Copyright (C) 2016 Tibor 'Igor2' Palinkas +.\" +.\" This program is free software; you can redistribute it and/or modify +.\" it under the terms of the GNU General Public License as published by +.\" the Free Software Foundation; either version 2 of the License, or +.\" (at your option) any later version. +.\" +.\" This program is distributed in the hope that it will be useful, +.\" but WITHOUT ANY WARRANTY; without even the implied warranty of +.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +.\" GNU General Public License for more details. +.\" +.\" You should have received a copy of the GNU General Public License along +.\" with this program; if not, write to the Free Software Foundation, Inc., +.\" 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +.\" +.\" Contact: pcb-rnd-man[removethis]@igor2.repo.hu +.TH pcb-prj2lht 1 2016-12-27 "" "pcb-rnd manual" +.SH NAME +pcb-prj2lht - convert old gsch2pcb project file to pcb-rnd project +.SH SYNPOSIS +.nf +.sp +\fBpcb-prj2lht [\fIinputfile\fB] +.fi +.SH DECSRIPTION + +.BR pcb-prj2lht +converts the old gsch2pcb project file to the new, lihata project file format that is usable with pcb-rnd and gsch2pcb-rnd. If \fIinputfile\fR is specified, the file is modified in-place, else +.BR pcb-prj2lht +reads from STDIN and writes the result to STDOUT. Index: tags/2.1.2/doc/man/pcb-prj2lht.1.html =================================================================== --- tags/2.1.2/doc/man/pcb-prj2lht.1.html (nonexistent) +++ tags/2.1.2/doc/man/pcb-prj2lht.1.html (revision 24813) @@ -0,0 +1,62 @@ + + + +pcb-prj2lht - pcb-rnd manual + + + + +
pcb-prj2lht 1 + 2016-12-27 + pcb-rnd manual +
+ + + +

NAME

+
+pcb-prj2lht - convert old gsch2pcb project file to pcb-rnd project +
+ +

SYNPOSIS

+
+

+pcb-prj2lht [inputfile] + + + +

+ +

DESCRIPTION

+
+pcb-prj2lht converts the old gsch2pcb project file to the new, lihata project file format that is usable with pcb-rnd and gsch2pcb-rnd. If inputfile is specified, the file is modified in-place, else pcb-prj2lht reads from STDIN and writes the result to STDOUT. +
+

+ + +
pcb-prj2lht 1 + 2016-12-27 + pcb-rnd manual +
+ + + Index: tags/2.1.2/doc/man/pcb-prj2lht.1.mml =================================================================== --- tags/2.1.2/doc/man/pcb-prj2lht.1.mml (nonexistent) +++ tags/2.1.2/doc/man/pcb-prj2lht.1.mml (revision 24813) @@ -0,0 +1,14 @@ +pcb-prj2lht +1 +2016-12-27 + + pcb-prj2lht - convert old gsch2pcb project file to pcb-rnd project + pcb-prj2lht [inputfile] + + +pcb-prj2lht converts the old gsch2pcb project file to the +new, lihata project file format that is usable with pcb-rnd and +gsch2pcb-rnd. If inputfile is specified, the file is modified +in-place, else pcb-prj2lht reads from STDIN and writes the +result to STDOUT. + Index: tags/2.1.2/doc/man/pcb-rnd.1 =================================================================== --- tags/2.1.2/doc/man/pcb-rnd.1 (nonexistent) +++ tags/2.1.2/doc/man/pcb-rnd.1 (revision 24813) @@ -0,0 +1,51 @@ +.\" pcb-rnd - manual +.\" Copyright (C) 2016 Tibor 'Igor2' Palinkas +.\" +.\" This program is free software; you can redistribute it and/or modify +.\" it under the terms of the GNU General Public License as published by +.\" the Free Software Foundation; either version 2 of the License, or +.\" (at your option) any later version. +.\" +.\" This program is distributed in the hope that it will be useful, +.\" but WITHOUT ANY WARRANTY; without even the implied warranty of +.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +.\" GNU General Public License for more details. +.\" +.\" You should have received a copy of the GNU General Public License along +.\" with this program; if not, write to the Free Software Foundation, Inc., +.\" 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +.\" +.\" Contact: pcb-rnd-man[removethis]@igor2.repo.hu +.TH pcb-rnd 1 2018-01-01 "" "pcb-rnd manual" +.SH NAME +pcb-rnd - Printed Circuit Board editor +.SH SYNPOSIS +.nf +.sp +\fBpcb-rnd [\fIoptions\fB] [\fIinputfile\fB] +.fi +.SH DECSRIPTION + +.BR pcb-rnd +is a modular PCB editor. The main use is interactive editing. If no \fI-x\fR is specified on the command line, the graphical editor mode is initiated. Automated, headless processing is also possible with \fI-x\fR or \fI--gui batch\fR. +.SH OPTIONS + + +.TP + +.B --help \fItopic\fR +Print help about \fItopic\fR and exit; if no topic is specified, print available topics. +.TP + +.B -x \fIexporter\fR [\fIexportflags] \fIinputfile\fR\fR +Instead of interactive editing, export the design (loaded from \fIinputfile\fR) to a file using the specified \fIexporter\fR plugin. A list of exporter-specific parameters may follow to control the details of the process. +.TP + +.B --gui \fIhid\fR +Use the \fIhid\fR plugin for the "gui" frontend. Common choices are "gtk" or "lesstif" for graphical user interfaces and "batch" for a headless command-line interface (or automated batch processing). +.TP + +.B -c \fIpath=val\fR +Set a config node in role CFR_CLI. The path of the node is \fIpath\fR (e.g. editor/grid) and the new value is \fIval\fR (e.g. 5mm). +.PP + Index: tags/2.1.2/doc/man/pcb-rnd.1.html =================================================================== --- tags/2.1.2/doc/man/pcb-rnd.1.html (nonexistent) +++ tags/2.1.2/doc/man/pcb-rnd.1.html (revision 24813) @@ -0,0 +1,87 @@ + + + +pcb-rnd - pcb-rnd manual + + + + +
pcb-rnd 1 + 2018-01-01 + pcb-rnd manual +
+ + + +

NAME

+
+pcb-rnd - Printed Circuit Board editor +
+ +

SYNPOSIS

+
+

+pcb-rnd [options] [inputfile] + + + +

+ +

DESCRIPTION

+
+pcb-rnd is a modular PCB editor. The main use is interactive editing. If no -x is specified on the command line, the graphical editor mode is initiated. Automated, headless processing is also possible with -x or --gui batch. +
+ + +

OPTIONS

+
+ + + + + + + + + + + +
--help topic + Print help about topic and exit; if no topic is specified, print available topics. +
-x exporter [exportflags] inputfile + Instead of interactive editing, export the design (loaded from inputfile) to a file using the specified exporter plugin. A list of exporter-specific parameters may follow to control the details of the process. +
--gui hid + Use the hid plugin for the "gui" frontend. Common choices are "gtk" or "lesstif" for graphical user interfaces and "batch" for a headless command-line interface (or automated batch processing). +
-c path=val + Set a config node in role CFR_CLI. The path of the node is path (e.g. editor/grid) and the new value is val (e.g. 5mm). +
+
+

+ + +
pcb-rnd 1 + 2018-01-01 + pcb-rnd manual +
+ + + Index: tags/2.1.2/doc/man/pcb-rnd.1.mml =================================================================== --- tags/2.1.2/doc/man/pcb-rnd.1.mml (nonexistent) +++ tags/2.1.2/doc/man/pcb-rnd.1.mml (revision 24813) @@ -0,0 +1,43 @@ +pcb-rnd +1 +2018-01-01 + + pcb-rnd - Printed Circuit Board editor + pcb-rnd [options] [inputfile] + + +pcb-rnd is a modular PCB editor. The main use is interactive +editing. If no -x is specified on the command line, the +graphical editor mode is initiated. Automated, headless processing +is also possible with -x or --gui batch. + + + + + + --help topic + Print help about topic and exit; if no topic is + specified, print available topics. + + + -x exporter [exportflags] inputfile + Instead of interactive editing, export the design (loaded from + inputfile) to a file using the specified + exporter plugin. A list of exporter-specific parameters + may follow to control the details of the process. + + + --gui hid + Use the hid plugin for the "gui" frontend. Common + choices are "gtk" or "lesstif" for graphical user interfaces + and "batch" for a headless command-line interface (or automated + batch processing). + + + -c path=val + Set a config node in role CFR_CLI. The path of the node is + path (e.g. editor/grid) and the new value is + val (e.g. 5mm). + + + Index: tags/2.1.2/doc/man/pcb-strip.1 =================================================================== --- tags/2.1.2/doc/man/pcb-strip.1 (nonexistent) +++ tags/2.1.2/doc/man/pcb-strip.1 (revision 24813) @@ -0,0 +1,45 @@ +.\" pcb-rnd - manual +.\" Copyright (C) 2016 Tibor 'Igor2' Palinkas +.\" +.\" This program is free software; you can redistribute it and/or modify +.\" it under the terms of the GNU General Public License as published by +.\" the Free Software Foundation; either version 2 of the License, or +.\" (at your option) any later version. +.\" +.\" This program is distributed in the hope that it will be useful, +.\" but WITHOUT ANY WARRANTY; without even the implied warranty of +.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +.\" GNU General Public License for more details. +.\" +.\" You should have received a copy of the GNU General Public License along +.\" with this program; if not, write to the Free Software Foundation, Inc., +.\" 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +.\" +.\" Contact: pcb-rnd-man[removethis]@igor2.repo.hu +.TH pcb-strip 1 2016-12-27 "" "pcb-rnd manual" +.SH NAME +pcb-strip - remove sections of a pcb file +.SH SYNPOSIS +.nf +.sp +\fBpcb-strip [\fIoptions\fB] [\fIinputfile\fB] +.fi +.SH DECSRIPTION + +.BR pcb-strip +removes sections of a pcb file. If \fIinputfile\fR is specified, the file is modified in-place, else +.BR pcb-strip +reads from STDIN and writes the result to STDOUT. +.SH OPTIONS + + +.TP + +.B -s +Remove symbols (the font). The pcb file stops being self-containing, pcb-rnd (or pcb) will load and apply the default font when the file is loaded. Useful for reducing the file size for test input and example files where font correctness is not required. +.TP + +.B -a +Remove board attributes. Useful for deleting local configuration +.PP + Index: tags/2.1.2/doc/man/pcb-strip.1.html =================================================================== --- tags/2.1.2/doc/man/pcb-strip.1.html (nonexistent) +++ tags/2.1.2/doc/man/pcb-strip.1.html (revision 24813) @@ -0,0 +1,79 @@ + + + +pcb-strip - pcb-rnd manual + + + + +
pcb-strip 1 + 2016-12-27 + pcb-rnd manual +
+ + + +

NAME

+
+pcb-strip - remove sections of a pcb file +
+ +

SYNPOSIS

+
+

+pcb-strip [options] [inputfile] + + + +

+ +

DESCRIPTION

+
+pcb-strip removes sections of a pcb file. If inputfile is specified, the file is modified in-place, else pcb-strip reads from STDIN and writes the result to STDOUT. +
+ + +

OPTIONS

+
+ + + + + + + +
-s + Remove symbols (the font). The pcb file stops being self-containing, pcb-rnd (or pcb) will load and apply the default font when the file is loaded. Useful for reducing the file size for test input and example files where font correctness is not required. +
-a + Remove board attributes. Useful for deleting local configuration +
+
+

+ + +
pcb-strip 1 + 2016-12-27 + pcb-rnd manual +
+ + + Index: tags/2.1.2/doc/man/pcb-strip.1.mml =================================================================== --- tags/2.1.2/doc/man/pcb-strip.1.mml (nonexistent) +++ tags/2.1.2/doc/man/pcb-strip.1.mml (revision 24813) @@ -0,0 +1,30 @@ +pcb-strip +1 +2016-12-27 + + pcb-strip - remove sections of a pcb file + pcb-strip [options] [inputfile] + + +pcb-strip removes sections of a pcb file. If inputfile +is specified, the file is modified in-place, else pcb-strip +reads from STDIN and writes the result to STDOUT. + + + + + + -s + Remove symbols (the font). The pcb file stops being self-containing, + pcb-rnd (or pcb) will load and apply the default font when the file + is loaded. Useful for reducing the file size for test input and + example files where font correctness is not required. + + + + -a + Remove board attributes. Useful for deleting local configuration + + + + Index: tags/2.1.2/doc/mirrors.html =================================================================== --- tags/2.1.2/doc/mirrors.html (nonexistent) +++ tags/2.1.2/doc/mirrors.html (revision 24813) @@ -0,0 +1,56 @@ + + + + pcb-rnd - main + + + + + + + + + + +
Main + News + Doc & pool + Support + People + Events & timeline + pcb-rnd [pcb-rnd logo] +
+ + +
+ +

read-only svn mirrors

+

+Master repository: svn://repo.hu/pcb-rnd +

+ +
url + update frequency location +
svn://timesausage.com/pcb-rnd + 10 minutes + U.S., west coast +
svn://igor3.repo.hu/pcb-rnd + manual/random (every few days) + Budapest, Hungary +
+

+Note: svn mirrors are always read-only and lag behind the master +repository. The latest commits are often accessible only in the master +repo, until mirrors sync, which may take anything between minutes and +days. You should almost always use the master repository. +There are situations when using a mirror may help, tho: +

    +
  • if you need to do a lot of checkouts of past revisions, e.g. for + bisecting an old bug, you should pick the mirror that is fastest + for you +
  • the master repositry is not accessible for some reason and your + svn access can not wait until it is restored +
+ + + Index: tags/2.1.2/doc/motivation.html =================================================================== --- tags/2.1.2/doc/motivation.html (nonexistent) +++ tags/2.1.2/doc/motivation.html (revision 24813) @@ -0,0 +1,134 @@ + + + + pcb-rnd - motivation + + + + + + + + + + +
Main + News + Doc & pool + Support + People + Events & timeline + pcb-rnd [pcb-rnd logo] +
+ + +

pcb-rnd motivation

+ +

Phase 5: new data model (2018)

+

+Mid 2018 the data model rewrite has mostly finished. The new model is +capable of handling complex layer stackups, subcircuits, padstacks, slots. We +are building a few long demanded features on top of the new infrastructure. + +

Phase 4: expansion, data model rewrite (2017)

+

+Late 2016 and during 2017 there was a major expansion in number of developers, +users and the amount of time spent on pcb-rnd. Our community is not tiny +any more, and is very active: there is a lot of on-topic discussion going +on on IRC every day, which result in bugs fixed and features implemented. +Newcomers are intergated fast. + +

+We started to rewrite the data model by slowly replacing elements with +more generic subcircuits. + + +

Phase 3: community requested features (2016)

+Overlapping phase 2 there was + feature poll . If there +are enough active users/testers for a feature, it gets implemented in +phase 3. +

+There is a small, active, constructive community forming around pcb-rnd. Future +directions will be mainly set by their need. + +

Phase 2: major cleanups (2015..2016)

+In the first phase I was mostly implementing a set of small features and fixes. +As I got more familiar with the code base, I decided to bite the bullet and +do some refactoring: +
    +
  • replaced the footprint mapping/loading code; instead of a hardwired m4 dependency, parametric (generated-on-the-fly) footprints can be written in any language +
  • replaced the default footprint library shipped with the software; the new library ships a small, well organized collection of essentials, omitting special/rarely used footprints +
  • got the code much more modular - a lot of core code got converted into plugins +
  • threw out the resource parser and file format (menu.res and friends) in favor of lihata; this removed a lot of code duplication and a strangely designed resource tree data structure I really hated; as a side effect the gtk hid has multi-stroke hotkeys +
  • replaced glib with a set of mini libs in core and most of the plugins; at the end only the gtk hid should depend on glib; this made the code easier to maintain and debug; a lot of checks are now compile-time (through the C type system) instead of runtime (glib lists) +
  • replaced the settings/rc/preferences system with a central, lihata based configuration system - long term hid attributes will be converted too +
+

+Plans for the future includes: +

    +
  • turning most of the core code into a library for external tools to reuse +
  • extending the core to provide an infrastructure for composite objects handled by plugins +
  • support for saving and loading pcb and footprint files in the lihata format +
  • plans for a set of smallish features that can be implemented in a weekend or two each. +
+ + +

Phase 1: At the beginning... (2013..2014)

+I use PCB a lot on various computers. I used to try to join the mainstream +development with small contribution (minor patches) and was active on +IRC and the mailing lists for a while. However, it didn't work out well, +and: +
    +
  • PCB already knew 95% of everything I'd ever need years ago +
  • the remaining 5% was not on the TODO list of developers and generally no one shown much interest in getting patches for those +
  • meanwhile a lot of new features have been added, from which most I find totally useless: +
      +
    • dbus +
    • gl - transparency makes even simple 2 sided boards unusable; slower than the classic version sw render on all my computers +
    • preparation for a C++ transition +
    • 3d support in core (I believe communication to 3d cad programs should be via exporter plugins) +
    +
  • the official Debian package enables (requires, depends on) both dbus and gl +
  • DVCS - it almost always results in chaos, and has no benefit for such a small group of developers; there are posts from time to time on the mailing list about how to handle the chaos; my choice is to stick with a simple, centralized version control system +
  • DVCS always results in increased administration, which I hate to spend my time on - I'd rather invest the time in bugfixing, documentation or implementing new features +
  • it's nearly impossible to get small patches applied^1: +
      +
    • often no one has the time to revise and commit them +
    • communication requires web2.0 (lp) +
    • there are too many cycles of "please fix this and change that first" +
    • with the chaos VCS, it's too likely that new feature patches would require ongoing maintenance while sitting in a "feature branch", to avoid that a large scale merge (or rebase, whatever) breaks it when it finally hits the official branch +
    • there are too much pondering and too less prototyping; there are features that are being considered for years (for example back annotation, internal connections) with multiple concurrent ideas, but no code. Instead, I'd like to implement some code from the early phase of the idea, test it, and deprecate it if it didn't work out well. +
    • I wouldn't even dream about getting larger patches in the official release +
    +
  • no stable release for years; maintaining a set of patches (like pcb-gpmi) and porting them to new releases is too much hassle +
+I was pondering a fork for years. The trigger was that one day I've upgraded +Debian on my lab computer and the new version of PCB came with gl enabled; this +made PCB absolutely unusable (had to wait like 10 seconds for a scroll) while +all the transparent polys over traces made the whole screen a mess. I should +have recompiled everything and built a new Debian package with gl disabled or +install from source (but I have too many computers for that). My decision +was to set up my own .deb but then build it from a fork (it's not much of +an extra effort), so I can add some of the features I miss in daily use. +My plans with this fork: +
    +
  • I stick with my fork and will use it on all my computers for all my designs +
  • Because of that, there's no emphasis on keeping the file formats compatible - breaking compatibility is not a goal either; as long as mainline doesn't change the format, pcb-rnd is about 98% compatible (the 2% is where pcb-rnd features are not supported by mainline) +
  • I won't actively seek ways to get my changes into the mainstream; I will keep on using my svn repo in a manner that (as a side effect) makes such merges easier, tho. If PCB developers decide to pick them up from svn and merge them in the official repo, it's fine (but I personally will keep using my fork anyway). +
  • Most probably I won't merge anything back from the mainstream to my fork - the past few years showed that it's unlikely there would be new features I'd need +
  • My plans for new features were: +
      +
    • pin shapes (a preliminary version was already implemented - as of 2017, it's obsolete because of padstacks) +
    • 1206 jumpers without having to add them on the schematics/netlist (done: [intconn] and [nonetlist] are the pcb-rnd-side features for this) +
    • merge pcb-gpmi; GPMI would be an optional addon, it'd probably stay a plugin, but there should not be a separate repo (done; meanwhile superseded by fungw scripting) +
    +
+

+Footnotes: +

    +
  • ^1: this may have changed lately and pcb developers are more open to newcomers; there seems to be a shortage of developers tho, which still makes it slow to get bigger patches through +
+ + + Index: tags/2.1.2/doc/myfeature.html =================================================================== --- tags/2.1.2/doc/myfeature.html (nonexistent) +++ tags/2.1.2/doc/myfeature.html (revision 24813) @@ -0,0 +1,55 @@ + + + + pcb-rnd - my feature + + + + + + + + + + +
Main + News + Doc & pool + Support + People + Events & timeline + pcb-rnd [pcb-rnd logo] +
+ + +

pcb-rnd - how to get my favorite feature implemented

+ +The list below is sorted: top items have higher priority, but you +are free to choose any. + +

1. If you are a programmer with free time to spend

+Read the contribution howto and join the project. +You are welcome to work only on the feature you are interested in. You get +all the support (e.g. for understanding the API, to get a blank plugin +set up so you need to fill in only the feature-specific parts, etc.). Success +rate should be near to 100%. + +

2. If you are not a programmer and have free time

+You can join and work on things you don't need that much, but others do. +This will build your reputation in the community which in turns encourages +others to implement your favorite feature even if they wouldn't do it for +themselves. The success rate is somewhat more random, obviously. + +

3. If you don't have free time

+Consider donation: buy someone else's time, e.g. + sponsor the +project with small donations. +

+You can also directly buy the development time for the feature you need; +contact me (see the contribution +howto page). Since you don't need to cover all costs and the hourly +rates are much lower on a pet project, and your feature may be simpler +than it looks, and someone who already knows the code also saves the +learning curve, it may all be cheaper than you think. The success rate +should be close to 100%. + Index: tags/2.1.2/doc/news.html =================================================================== --- tags/2.1.2/doc/news.html (nonexistent) +++ tags/2.1.2/doc/news.html (revision 24813) @@ -0,0 +1,219 @@ + + + + pcb-rnd - news + + + + + + + + + + +
Main + News + Doc & pool + Support + People + Events & timeline + pcb-rnd [pcb-rnd logo] +
+ + +
+ +

News

+ +
+ + + + + + + + + + + + + + + + + + + + + + + +
+ 2019-04-24 +
+ release: 2.1.2 +
+ Release 2.1.2 available: cleanup/bugfix release; netlist rewrite, CAM jobs, better KiCad4 support + +
+ 2019-02-13 +
+ release: 2.1.1 +
+ Release 2.1.1 available: cleanup/bugfix release; improved DRC GUI, find.c rewrite + +
+ 2018-11-25 +
+ release: 2.1.0 +
+ Release 2.1.0 available: doc/mech layers, slots, text rotation & thickness, asm plugin + +
+ 2018-09-19 +
+ CoralEDA +
+ pcb-rnd joins the CoralEDA ecosystem (umbrella project). + +
+ 2018-08-29 +
+ release: 2.0.1 +
+ Release 2.0.1 available: rendering speed optimization and various smallish features, including new scripting engine, CAM export, 2d drafting, new export dialog, easyEDA netlist import. + +
+ 2018-06-06 +
+ release: 2.0.0 +
+ Release 2.0.0 available: old data model fully removed; new default menu and key bindings. + +
+ 2018-03-21 +
+ release: 1.2.8 +
+ Release 1.2.8 available, with all parts of the code handling the new data model. + +
+ 2017-12-26 +
+ release: 1.2.7 +
+ Release 1.2.7 available, with padstacks. + +
+ 2017-10-11 +
+ release: 1.2.6 +
+ Release 1.2.6 available, with subcircuit terminals, dxf, hpgl, openscad and poly-clears-poly support. + +
+ 2017-09-15 +
+ release: 1.2.5b +
+ Release 1.2.5b is is an 1.2.5 with a security fix, please upgrade as soon as possible! + +
+ 2017-08-21 +
+ release: 1.2.5 +
+ Release 1.2.5 is available: it is an 1.2.4 with a few critical bugfixes + +
+ 2017-08-07 +
+ release: 1.2.4 +
+ Release 1.2.4 is available, with subcircuit, eagle binary and protel autotrax support. + +
+ 2017-05-30 +
+ release: 1.2.3 +
+ Release 1.2.3 is available, with a new plugin system and editable soldermask and paste layers. + +
+ 2017-04-10 +
+ release: 1.2.2 +
+ Release 1.2.2 is available. + +
+ 2017-03-12 +
+ opengl +
+ Opengl support available in svn HEAD. Thanks to Keith Packard. + +
+ 2017-02-17 +
+ EDA ecosystem, release: 1.2.1 +
+ Release 1.2.1 is available. +
+ We've strengthen our connections to other EDA tools, trying to + contribute more to the + EDA ecosystem, by implementing more import and export plugins. + +
+ 2016-12-28 +
+ release: 1.2.0 +
+ Release 1.2.0 is available. + +
+ 2016-12-20 +
+ Official Debian packaging +
+ Dima Kogan volunteered to do the packaging for Debian. We may get in + testing, or if we are lucky, in the next stable. To ease packaging + an unscheduled intermediate version 1.1.4 was released. Thank you Dima! + +
+ 2016-11-02 +
+ Release: 1.1.3 +
+ Available at the download page . +
+ Features kicad compatibility, advanced search and the + lihata board format. + +
+ 2016-09-04 +
+ Rebranding +
+ We have a new main page reflecting the transition how we regard pcb-rnd: + it is not much of just a fork of geda/pcb by now, but a separate PCB + editor with its own team and own course. File save/load compatibility is + maintained. + +
+ 2016-08-24 +
+ Release 1.1.1 +
+ Available at the download page . +
+ The next development cycle will focus on editable/searchable attributes + and a new native file format. + +
+
+ + + Index: tags/2.1.2/doc/plan.txt =================================================================== --- tags/2.1.2/doc/plan.txt (nonexistent) +++ tags/2.1.2/doc/plan.txt (revision 24813) @@ -0,0 +1,135 @@ +user manual + 1. intro: what is pcb-rnd; place in the generic workflow + 2. model of the world + intro + real boards (terminology) + pcb-rnd terminology + limitations + board, global properties + layer groups and layers + atomic objects + lines + arcs + vias + polygons + composite objects + elements + 3. where data is + board + paste buffers + footprint libraries + pcblib + static footprints + generated footprints + file formats + board + lihata + pcb + kicadl + kicad + footprint + import + export + 4. invocation + TODO + 5. user interface (hid plugins) + under the hood: actions + gtk + main window + menu + keys + misc dialogs + log window + cli + library dialog + propedit dialog + preferences dialog + batch + (lesstif: low prio) + (remote: not finished yet) + (sdl: not even started yet) + 6. feature plugins included,buildin name DocDraftComplete? + net auto-completion no [acompnet] y + crop board to fit objects yes, buildin [autocrop] y + auto place components yes, buildin [autoplace] + the original autorouter yes, buildin [autoroute] + flip board objects yes, buildin [boardflip] + diagnostic acts. for devs no [diag] + HID-independent GUI dialogs yes, buildin [dialogs] + distribute and align text yes, buildin [distaligntext] y + distribute and align objs yes, buildin [distalign] + djopt board optimization yes, buildin [djopt] y + draw cross-section (layers) yes, buildin [draw_csect] + fab layer in some exports yes, buildin [draw_fab] + font selection GUI yes, buildin [draw_fontsel] + font editor yes, buildin [fontmode] + push lines out of the way yes, buildin [jostle] + diagnostics: log HID calls no [loghid] + calculate toolpath for milling no [millpath] + minimal cut shorts yes, buildin [mincut] + old/obsolete actions no [oldactions] + combine selected polygons yes, buildin [polycombine] + stitch polygon at cursor no [polystitch] + object property editor yes, buildin [propedit] + puller yes, buildin [puller] + query language yes, buildin [query] y + renumber action yes, buildin [renumber] + report actions yes, buildin [report] + the original rubberband yes, buildin [rubberband_orig] + command shorthands yes, buildin [shand_cmd] + netlist based dispenser yes, buildin [smartdisperse] + libstroke gestures no [stroke] + draw teardrops on pins yes, buildin [teardrops] + vendor drill mapping yes, buildin [vendordrill] y + 7. io and import plugins + Comparison table (build from data like tests/RTT/RTT_kicad*) + intro: io_lihata extra attention to pcb-rnd's native format + IO & Import plugins sorted by capability: Boards, footprints, and netlists parens=(in development) + Boards: io plugins that deal with boards + lihata + pcb + kicadl + kicad + protel autotrax + (eagle) + Footprints: io plugins that deal with footprints + lihata + fp -- handled by pcb + kicadl + kicad + protel autotrax -- 'components' + (eagle) + (mentor-cell) + Netlists: there are import and io plugins dealing with netlists + lihata + specctra dsn + geda -- import_netlist plugin + tinycad + ltspice .net + .asc + kicadl + kicad + tinycad .net + protel autotrax + Mentor graphics schematic + Electronic Design Interchange Format (EDIF import plugin) + tEDAx + mucs routing + (eagle) + 8. utilities + 9. appendix + glossary + full index/catalog of actions (generated) + full index/catalog of all plugins + how to build + + +_styleguide notes:_ +urls all lowercased (eg. GTK becomes gtk) +pronouns: write to avoid pronouns, use user/developer, use she +organization: hierarchical with lots of links for people who have tunneled deep? +navigation: don't add navigation in page, rely on browser navs +html strict: use standard html 1.0 +css: use css for looks without content modification +assets: generate assets (use dot, etc), assume make and same system is able to build pcb-rnd +tables: use zebra styling for ease of reading +deps/requirements for pcb-rnd itself (we need an appendix table to live create the actions list) +naming sections: despite lowercasing urls, keep naming concise so links have names that lead to sections with same names Index: tags/2.1.2/doc/resources/at.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/resources/at.png =================================================================== --- tags/2.1.2/doc/resources/at.png (nonexistent) +++ tags/2.1.2/doc/resources/at.png (revision 24813) Property changes on: tags/2.1.2/doc/resources/at.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/resources/logo.pcb =================================================================== --- tags/2.1.2/doc/resources/logo.pcb (nonexistent) +++ tags/2.1.2/doc/resources/logo.pcb (revision 24813) @@ -0,0 +1,91 @@ +# release: pcb-rnd 1.1.0 + +# To read pcb files, the pcb version (or the git source date) must be >= the file version +FileVersion[20070407] + +PCB["" 15240000nm 15240000nm] + +Grid[635000nm 0 0 1] +Cursor[13335000nm 8890000nm 0.000000] +PolyArea[3100.006200] +Thermal[0.500000] +DRC[304800nm 228600nm 254000nm 177800nm 381000nm 254000nm] +Flags("nameonpcb,clearnew,snappin") +Groups("1,3,4,c:2,5,6,s:7:8") +Styles["Signal,254000nm,1999996nm,800100nm,508000nm:Power,508000nm,2199894nm,999998nm,508000nm:Fat,2032000nm,3500120nm,1199896nm,635000nm:Sig-tight,254000nm,1625600nm,800100nm,304800nm"] + +Symbol['r' 304800nm] +( + SymbolLine[127000nm 889000nm 127000nm 1270000nm 203200nm] + SymbolLine[127000nm 889000nm 254000nm 762000nm 203200nm] + SymbolLine[254000nm 762000nm 508000nm 762000nm 203200nm] + SymbolLine[0 762000nm 127000nm 889000nm 203200nm] +) +Symbol['n' 304800nm] +( + SymbolLine[127000nm 889000nm 127000nm 1270000nm 203200nm] + SymbolLine[127000nm 889000nm 254000nm 762000nm 203200nm] + SymbolLine[254000nm 762000nm 381000nm 762000nm 203200nm] + SymbolLine[381000nm 762000nm 508000nm 889000nm 203200nm] + SymbolLine[508000nm 889000nm 508000nm 1270000nm 203200nm] + SymbolLine[0 762000nm 127000nm 889000nm 203200nm] +) +Symbol['d' 304800nm] +( + SymbolLine[508000nm 254000nm 508000nm 1270000nm 203200nm] + SymbolLine[381000nm 1270000nm 508000nm 1143000nm 203200nm] + SymbolLine[127000nm 1270000nm 381000nm 1270000nm 203200nm] + SymbolLine[0 1143000nm 127000nm 1270000nm 203200nm] + SymbolLine[0 889000nm 0 1143000nm 203200nm] + SymbolLine[0 889000nm 127000nm 762000nm 203200nm] + SymbolLine[127000nm 762000nm 381000nm 762000nm 203200nm] + SymbolLine[381000nm 762000nm 508000nm 889000nm 203200nm] +) + + +Attribute("PCB::grid::unit" "mil") +Attribute("PCB::conf::editor/buffer_number" "0") +Attribute("PCB::conf::editor/draw_grid" "true") +Attribute("PCB::conf::editor/show_solder_side" "0") +Attribute("PCB::conf::editor/view/flip_x" "0") +Attribute("PCB::conf::editor/view/flip_y" "0") + +Element["" "dip(2)" "rnd" "2*300" 0 6985000nm 6350000nm 635000nm 0 115 ""] +( + Pin[7620000nm 0 2540000nm 1270000nm 2692400nm 999998nm "" "2" "thermal(0X,1X)"] + + ) +Layer(1 "component") +( + Polygon("clearpoly") + ( + [635000nm 635000nm] [14605000nm 635000nm] [14605000nm 14605000nm] [635000nm 14605000nm] + ) +) +Layer(2 "solder") +( +) +Layer(3 "comp-GND") +( +) +Layer(4 "comp-power") +( +) +Layer(5 "sold-GND") +( +) +Layer(6 "sold-power") +( +) +Layer(7 "signal3") +( +) +Layer(8 "outline") +( +) +Layer(9 "silk") +( +) +Layer(10 "silk") +( +) Index: tags/2.1.2/doc/resources/logo.svg =================================================================== --- tags/2.1.2/doc/resources/logo.svg (nonexistent) +++ tags/2.1.2/doc/resources/logo.svg (revision 24813) @@ -0,0 +1,105 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: tags/2.1.2/doc/resources/logo128.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/resources/logo128.png =================================================================== --- tags/2.1.2/doc/resources/logo128.png (nonexistent) +++ tags/2.1.2/doc/resources/logo128.png (revision 24813) Property changes on: tags/2.1.2/doc/resources/logo128.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/resources/logo16.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/resources/logo16.png =================================================================== --- tags/2.1.2/doc/resources/logo16.png (nonexistent) +++ tags/2.1.2/doc/resources/logo16.png (revision 24813) Property changes on: tags/2.1.2/doc/resources/logo16.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/resources/logo256.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/resources/logo256.png =================================================================== --- tags/2.1.2/doc/resources/logo256.png (nonexistent) +++ tags/2.1.2/doc/resources/logo256.png (revision 24813) Property changes on: tags/2.1.2/doc/resources/logo256.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/resources/logo32.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/resources/logo32.png =================================================================== --- tags/2.1.2/doc/resources/logo32.png (nonexistent) +++ tags/2.1.2/doc/resources/logo32.png (revision 24813) Property changes on: tags/2.1.2/doc/resources/logo32.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/resources/logo32.xpm =================================================================== --- tags/2.1.2/doc/resources/logo32.xpm (nonexistent) +++ tags/2.1.2/doc/resources/logo32.xpm (revision 24813) @@ -0,0 +1,295 @@ +/* XPM */ +static char *noname[] = { +/* width height ncolors chars_per_pixel */ +"32 32 256 2", +/* colors */ +" c #000000", +" . c #838D91", +" X c #365938", +" o c #5F6767", +" O c #E2E0E1", +" + c #799A7D", +" @ c #9FA9B3", +" # c #2F5331", +" $ c #B1C3B4", +" % c #2B552D", +" & c #2D512F", +" * c #6B6F76", +" = c #DBDADA", +" - c #2A532C", +" ; c #2B512D", +" : c #99A3AD", +" > c #AEBFB1", +" , c #2A4F2C", +" < c #729276", +" 1 c #294F2B", +" 2 c #859396", +" 3 c #284F2A", +" 4 c #709274", +" 5 c #6C9870", +" 6 c #274F29", +" 7 c #264F28", +" 8 c #254F27", +" 9 c #264D28", +" 0 c #254D27", +" q c #244D26", +" w c #234D25", +" e c #939DA7", +" r c #244B26", +" t c #6A8C6E", +" y c #8F99A3", +" u c #8F97A3", +" i c #6E737C", +" p c #8D97A1", +" a c #1B451D", +" s c #8B959F", +" d c #608C64", +" f c #9FAFA2", +" g c #89939D", +" h c #9DAFA0", +" j c #5D8861", +" k c #87919B", +" l c #708E77", +" z c #96AB99", +" x c #727B83", +" c c #113D13", +" v c #58785C", +" b c #547458", +" n c #537457", +" m c #57645B", +" M c #4B6C4F", +" N c #101112", +" B c #747C7E", +" V c #7D9D80", +" C c #73787D", +" Z c #7B9288", +" A c #B1C2B3", +" S c #879497", +" D c #55625C", +" F c #636A6D", +" G c #274828", +" H c #244C25", +" J c #9FB6A1", +" K c #A0B0A2", +" L c #9DAE9F", +" P c #709376", +" I c #87909A", +" U c #5B855E", +" Y c #858E98", +" T c #558558", +" R c #7E9987", +" E c #678B6D", +" W c #CAD3CB", +" Q c #4E7B51", +" ! c #49794C", +" ~ c #728D7B", +" ^ c #4C6D4F", +" / c #496F4C", +" ( c #B8C1B9", +" ) c #6E7577", +" _ c #465749", +" ` c #B3BBB4", +" ' c #37693A", +" ] c #3B5D3E", +" [ c #646D6D", +" { c #E7E6E7", +" } c #E2E4E2", +" | c #38513B", +". c #E1E2E1", +".. c #9099A2", +".X c #384D3B", +".o c #7D858C", +".O c #6C6F78", +".+ c #DBDCDB", +".@ c #729877", +".# c #2C512F", +".$ c #879399", +".% c #719476", +".& c #709475", +".* c #D8D8D8", +".= c #719276", +".- c #709275", +".; c #6F9274", +".: c #6E9073", +".> c #949FA9", +"., c #6D9072", +".< c #6D8E72", +".1 c #6A8E6F", +".2 c #6B8C70", +".3 c #67926C", +".4 c #303133", +".5 c #909BA5", +".6 c #678C6C", +".7 c #8E99A3", +".8 c #68886D", +".9 c #8D97A2", +".0 c #CDCECD", +".q c #517A53", +".w c #8EA18F", +".e c #9BB39F", +".r c #686F77", +".t c #517053", +".y c #2C2F32", +".u c #F3EDF2", +".i c #456047", +".p c #426444", +".a c #3C6A3E", +".s c #58645D", +".d c #161719", +".f c #39683B", +".g c #969EA7", +".h c #39543B", +".j c #7B9B7F", +".k c #2D562F", +".l c #B1C2B4", +".z c #2D522F", +".x c #6B7076", +".c c #677F68", +".v c #658166", +".b c #677B68", +".n c #89909A", +".m c #6F9773", +".M c #2E4830", +".N c #98A2AC", +".B c #565E5E", +".V c #265028", +".C c #274E29", +".Z c #6F9173", +".A c #264E28", +".S c #254E27", +".D c #6E8F72", +".F c #244E26", +".G c #254C27", +".H c #274829", +".J c #244C26", +".K c #234C25", +".L c #234A25", +".P c #214A23", +".I c #909AA4", +".U c #69896D", +".Y c #6F747D", +".T c #8E98A2", +".R c #577758", +".E c #68876C", +".W c #8C96A0", +".Q c #658769", +".! c #7B828C", +".~ c #5E8D62", +".^ c #9EB0A1", +"./ c #9DAEA0", +".( c #7F9789", +".) c #456746", +"._ c #C2CFC4", +".` c #859E88", +".' c #1D2022", +".] c #315732", +".[ c #426746", +".{ c #7C927F", +".} c #B1C1B3", +".| c #8B919B", +"X c #2E4D2F", +"X. c #2A512B", +"XX c #264F27", +"Xo c #224B23", +"XO c #7F878F", +"X+ c #8D97A0", +"X@ c #74947A", +"X# c #88919B", +"X$ c #6B9071", +"X% c #62696F", +"X& c #57845A", +"X* c #6B8C71", +"X= c #698E6F", +"X- c #678C6D", +"X; c #638A69", +"X: c #1A1B1B", +"X> c #697179", +"X, c #477A4A", +"X< c #5E7E64", +"X1 c #467649", +"X2 c #2F3336", +"X3 c #F6F1F6", +"X4 c #416A44", +"X5 c #6D7876", +"X6 c #436446", +"X7 c #8E949D", +"X8 c #060707", +"X9 c #415644", +"X0 c #385C3B", +"Xq c #3E5241", +"Xw c #355A38", +"Xe c #355838", +"Xr c #E2E3E2", +"Xt c #7B9B80", +"Xy c #7A997F", +"Xu c #8E9AA0", +"Xi c #E0DFE0", +"Xp c #DFDFDF", +"Xa c #315434", +"Xs c #DDDFDD", +"Xd c #739B78", +"Xf c #729577", +"Xg c #739378", +"Xh c #D9D9D9", +"Xj c #D8D9D8", +"Xk c #709375", +"Xl c #6F9374", +"Xz c #6F9174", +"Xx c #6E9173", +"Xc c #6B9570", +"Xv c #6D8F72", +"Xb c #919CA6", +"Xn c #698D6E", +"Xm c #909AA5", +"XM c #8F9AA4", +"XN c #69896E", +"XB c #8E98A3", +"XV c #8D96A2", +"XC c #8C96A1", +"XZ c #7C848E", +"XA c #8B96A0", +"XS c #65856A", +"XD c #CACDCA", +"XF c #5F7F64", +"XG c #879E88", +"XH c #899A8A", +"XJ c #889889", +"XK c #2B2E31", +"XL c #446546", +"XP c #EDE8EC", +"XI c #546359", +"XU c None", +/* pixels */ +"XxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXx", +"XxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXx", +"XxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXx", +"XxXxXxXxXxXxXxXxXxXxXxXxXxXkXf.<..n BX;XlXxXxXxXxXxXxXxXxXxXx", +"XxXxXxXxXxXxXv.8XvXx ~XC s s p s.W p pXA u.(.,.;XSXNXxXxXxXxXxXx", +"XxXxXxXxXx.2 #.KXw lXC p.W.W.W p.W.W p p pXV RX6 q 9.QXxXxXxXxXx", +"XxXxXxXx.; M 7 6Xo ..W.W p.W p y y p.W.W p.W IX. 6 6X4XzXxXxXxXx", +"XxXxXxXx PXa 6 6.M.g p.W.W.T xX2XKX> y p.W.WX#X9 7 6 7.@XxXxXxXx", +"XxXxXxXxX*.C 6 7.s y p.W p.r X%.W.W.WXM o.F 6 r.3XxXxXxXx", +"XxXxXxXx.E H 6XX ).W.W.W.5.d N e p p.T * - 6.G jXxXxXxXx", +"XxXxXxXxXF 0 6 8 C s p p pX8 @ p.W p.O.k 6 9X&.:XxXxXx", +"XxXxXxXxXN.K 6 7 [ p.W.W.I.y .4.I.W p p.x.V 6.G dXxXxXxXx", +"XxXxXxXxXv , 6 6 _Xm s.W p k.' X:...W.W p y D.S 6.L 5XxXxXxXx", +"XxXxXxXx.%Xe 6 6 G.| s.W.W.WXbXO.o.N.W p.W p Y.h 6 6 %XdXxXxXxXx", +"XxXxXxXxXx b.S 6.P Z p p.W.W p.W p.W.W p p.W S q 6.C !.:XxXxXxXx", +"XxXxXxXxXx.Z /.f T.,.$.W p.W.W p.W.W.W p.TX+.e.{.aX1.mXxXxXxXxXx", +"XxXxXxXxXxXxXz.-XxXx.: 2 sXB.W p.W.W.7 gXuX@.l h.-XzXxXxXxXxXxXx", +"XxXxXxXxXxXxXxXxXxXxXzXL |.B i.!XZ.Y FX9X0.D $./XxXxXxXxXxXxXxXx", +"XxXxXxXxXxXxXxXxXt.6.`.R.] w.p.i.b ;.V q.) V._ hXxXxXxXxXxXxXxXx", +"XxXxXxXxXxXxXxXn.+ W.0 `.c.t.*XsXDXH.K.vXp (Xi.^XxXxXxXxXxXxXxXx", +"XxXxXxXxXxXxXxXx.j =X$.[.F.J.wXJ aX3 cXr.qXc.} hXxXxXxXxXxXxXxXx", +"XxXxXxXxXxXxXxXx.jXj.1.;Xl U JXG '.uX, }XyX- A LXxXxXxXxXxXxXxXx", +"XxXxXxXxXxXxXxXx +XhX=XxXxXx > f EXP.6 z O. { KXxXxXxXxXxXxXxXx", +"XxXxXxXxXxXxXxXx.,.-XxXxXxXx.,.-XxXzXx.,.=Xg < 4XxXxXxXxXxXxXxXx", +"XxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXx", +"XxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXx", +"XxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXx" +}; Index: tags/2.1.2/doc/resources/logo64.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/resources/logo64.png =================================================================== --- tags/2.1.2/doc/resources/logo64.png (nonexistent) +++ tags/2.1.2/doc/resources/logo64.png (revision 24813) Property changes on: tags/2.1.2/doc/resources/logo64.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/resources/logo64.xpm =================================================================== --- tags/2.1.2/doc/resources/logo64.xpm (nonexistent) +++ tags/2.1.2/doc/resources/logo64.xpm (revision 24813) @@ -0,0 +1,618 @@ +/* XPM */ +static char *noname[] = { +/* width height ncolors chars_per_pixel */ +"64 64 547 2", +/* colors */ +" c #000000", +" . c #829C86", +" X c #3F4941", +" o c #365738", +" O c #75A879", +" + c #365538", +" @ c #B4C7B7", +" # c #7A987E", +" $ c #E0DEDF", +" % c #79987D", +" & c #305532", +" * c #E0DCDF", +" = c #77987B", +" - c #DEDCDD", +" ; c #729C76", +" : c #344736", +" > c #749478", +" , c #2B512D", +" < c #709674", +" 1 c #28512A", +" 2 c #294F2B", +" 3 c #275129", +" 4 c #274F29", +" 5 c #6F9273", +" 6 c #264F28", +" 7 c #607C61", +" 8 c #264D28", +" 9 c #6E9072", +" 0 c #669C6A", +" q c #254D27", +" w c #244D26", +" e c #D5D2D4", +" r c #244B26", +" t c #234B25", +" y c #224B24", +" u c #6B8C6F", +" i c #919BA5", +" p c #224924", +" a c #6A8C6E", +" s c #204922", +" d c #619665", +" f c #1F4921", +" g c #8F99A3", +" h c #7B9682", +" j c #8E97A2", +" k c #1D471F", +" l c #8D97A1", +" z c #799480", +" x c #1C471E", +" c c #8C95A0", +" v c #91969B", +" b c #1B451D", +" n c #8B959F", +" m c #8A959E", +" M c #8A939E", +" N c #89939D", +" B c #638267", +" V c #174119", +" C c #87919B", +" Z c #8B9095", +" A c #607C64", +" S c #646B72", +" D c #54595F", +" F c #5F7C63", +" G c #5E7A62", +" H c #989EA5", +" J c #CDDACF", +" K c #75767C", +" L c #697A70", +" P c #547058", +" I c #537057", +" U c #4F7453", +" Y c #516C55", +" T c #575C5B", +" R c #888E95", +" E c #777C81", +" W c #4C6A50", +" Q c #4B6A4F", +" ! c #4B684F", +" ~ c #BACCBC", +" ^ c #374C38", +" / c #446248", +" ( c #9CA6AF", +" ) c #415E45", +" _ c #2B542C", +" ` c #69A16C", +" ' c #285229", +" ] c #68A16B", +" [ c #2A482B", +" { c #264E27", +" } c #254E26", +" | c #959EA8", +". c #949EA7", +".. c #254C26", +".X c #A9B8AB", +".o c #939CA6", +".O c #828A92", +".+ c #629B65", +".@ c #639966", +".# c #A7B6A9", +".$ c #909AA3", +".% c #808890", +".& c #7D868D", +".* c #5D9360", +".= c #5C935F", +".- c #879D90", +".; c #686E75", +".: c #719377", +".> c #8D9196", +"., c #588F5B", +".< c #9AAE9C", +".1 c #869099", +".2 c #858E98", +".3 c #6D9173", +".4 c #848E97", +".5 c #838C96", +".6 c #828C95", +".7 c #727A82", +".8 c #707880", +".9 c #92A894", +".0 c #69896F", +".q c #7D8690", +".w c #4D8350", +".e c #474C51", +".r c #97A9A6", +".t c #575F5A", +".y c #FAF8FA", +".u c #58575B", +".i c #A7B1B9", +".p c #F9F6F9", +".a c #A6AFB8", +".s c #74797D", +".d c #1E2022", +".f c #0E0E0F", +".g c #525555", +".h c #A3ABB5", +".j c #4C5D4F", +".k c #515354", +".l c #416544", +".z c #4E4F51", +".x c #8A9B99", +".c c #435F46", +".v c #B6BDB7", +".b c #B5BDB6", +".n c #EDECED", +".m c #B1BFB2", +".M c #ECEAEC", +".N c #3F5D42", +".B c #56635C", +".V c #38673B", +".C c #585B5E", +".Z c #365F39", +".A c #E6E6E6", +".S c #54575A", +".D c #37593A", +".F c #38573B", +".G c #E4E4E4", +".H c #E5E2E5", +".J c #37573A", +".K c #535359", +".L c #525358", +".P c #E2E2E2", +".I c #E1E0E1", +".U c #335536", +".Y c #E0E0E0", +".T c #E0DEE0", +".R c #315534", +".E c #2F5332", +".W c #77967C", +".Q c #DDDCDD", +".! c #DCDCDC", +".~ c #719C76", +".^ c #2B552E", +"./ c #749679", +".( c #DBDADB", +".) c #709A75", +"._ c #DADADA", +".` c #DBD8DB", +".' c #719676", +".] c #59905B", +".[ c #719476", +".{ c #709475", +".} c #709275", +".| c #5D845F", +"X c #859197", +"X. c #6F9274", +"XX c #6E9273", +"Xo c #656B71", +"XO c #6E9073", +"X+ c #6B9470", +"X@ c #848D96", +"X# c #6D9072", +"X$ c #6E8E73", +"X% c #97AB98", +"X& c #6C9071", +"X* c #D1D8D1", +"X= c #939DA8", +"X- c #6C8E71", +"X; c #95A996", +"X: c #D2D2D2", +"X> c #6B8C70", +"X, c #94A995", +"X< c #698E6E", +"X1 c #909BA5", +"X2 c #93A794", +"X3 c #698A6E", +"X4 c #678C6C", +"X5 c #94A395", +"X6 c #7E8790", +"X7 c #68886D", +"X8 c #67886C", +"X9 c #4E8450", +"X0 c #658A6A", +"Xq c #7C858E", +"Xw c #82848A", +"Xe c #8C95A1", +"Xr c #8B95A0", +"Xt c #CBCCCB", +"Xy c #65846A", +"Xu c #8A959F", +"Xi c #4B7E4D", +"Xp c #FEFBFD", +"Xa c #777F89", +"Xs c #899F8A", +"Xd c #767F88", +"Xf c #666D75", +"Xg c #7C7E84", +"Xh c #555B61", +"Xj c #607E65", +"Xk c #585C5A", +"Xl c #5F7C64", +"Xz c #636B72", +"Xx c #F9F7F8", +"Xc c #555C57", +"Xv c #A7B0B8", +"Xb c #67666C", +"Xn c #437445", +"Xm c #A5AEB6", +"XM c #4F555B", +"XN c #2E3134", +"XB c #A3ACB4", +"XV c #3D4146", +"XC c #4C5C4E", +"XZ c #476449", +"XA c #57745C", +"XS c #3D703F", +"XD c #436645", +"XF c #465C48", +"XG c #416443", +"XH c #050505", +"XJ c #3F5E41", +"XK c #38663A", +"XL c #3C5E3E", +"XP c #575A5C", +"XI c #111314", +"XU c #375E39", +"XY c #809F84", +"XT c #365E38", +"XR c #336035", +"XE c #809B84", +"XW c #3B523D", +"XQ c #326034", +"X! c #7F9B83", +"X~ c #76A97A", +"X^ c #38543A", +"X/ c #708571", +"X( c #525257", +"X) c #75A579", +"X_ c #335835", +"X` c #3D423F", +"X' c #7A977E", +"X] c #4F5054", +"X[ c #315433", +"X{ c #3C423E", +"X} c #79977D", +"X| c #39463B", +"o c #6B816C", +"o. c #38463A", +"oX c #70A374", +"oo c #39443B", +"oO c #6FA373", +"o+ c #2D562F", +"o@ c #729D76", +"o# c #6DA571", +"o$ c #364638", +"o% c #374439", +"o& c #697F6A", +"o* c #709F74", +"o= c #2E5230", +"o- c #778A85", +"o; c #2D522F", +"o: c #6DA171", +"o> c #2B542D", +"o, c #2B522D", +"o< c #DBD9DA", +"o1 c #719775", +"o2 c #709774", +"o3 c #2A502C", +"o4 c #DAD7D9", +"o5 c #28522A", +"o6 c #98A2AC", +"o7 c #29502B", +"o8 c #28502A", +"o9 c #294E2B", +"o0 c #2C482E", +"oq c #275029", +"ow c #265028", +"oe c #2A482C", +"or c #264E28", +"ot c #55585D", +"oy c #254E27", +"ou c #235025", +"oi c #254C27", +"op c #54565C", +"oa c #244C26", +"os c #264828", +"od c #234C25", +"of c #244A26", +"og c #929CA6", +"oh c #234A25", +"oj c #808C91", +"ok c #61666C", +"ol c #214A23", +"oz c #224824", +"ox c #204A22", +"oc c #214823", +"ov c #629566", +"ob c #688B6C", +"on c #658F69", +"om c #8F98A3", +"oM c #204622", +"oN c #3E4043", +"oB c #8E98A2", +"oV c #1D481F", +"oC c #6D747B", +"oZ c #8D96A1", +"oA c #618F65", +"oS c #8C96A0", +"oD c #8B969F", +"oF c #8B949F", +"oG c #909E90", +"oH c #8A949E", +"oJ c #788089", +"oK c #628166", +"oL c #869D90", +"oP c #728F79", +"oI c #7B7D82", +"oU c #607D64", +"oY c #96AE99", +"oT c #133C15", +"oR c #56875A", +"oE c #707881", +"oW c #6B8972", +"oQ c #58755C", +"o! c #557959", +"o~ c #7F8589", +"o^ c #8BA28E", +"o/ c #536F57", +"o( c #415D42", +"o) c #637D6A", +"o_ c #88A08B", +"o` c #4D6B51", +"o' c #57595B", +"o] c #212426", +"o[ c #859A88", +"o{ c #385B39", +"o} c #959DA5", +"o| c #728672", +"O c #49674D", +"O. c #0B0C0D", +"OX c #46634A", +"Oo c #3F4140", +"OO c #B2C5B4", +"O+ c #B4BDB6", +"O@ c #EBEEEC", +"O# c #9BA5AE", +"O$ c #9AA3AD", +"O% c #274F28", +"O& c #679C6A", +"O* c #959FA8", +"O= c #7F9C85", +"O- c #659A68", +"O; c #929BA5", +"O: c #525359", +"O> c #224923", +"O, c #254126", +"O< c #629665", +"O1 c #8D97A0", +"O2 c #DBE2DC", +"O3 c #8B959E", +"O4 c #5B5F65", +"O5 c #D9E0DA", +"O6 c #9DB59F", +"O7 c #5A5D64", +"O8 c #59905C", +"O9 c #88919B", +"O0 c #87919A", +"Oq c #676D74", +"Ow c #868F99", +"Oe c #848D97", +"Or c #838D96", +"Ot c #6B9071", +"Oy c #95AB97", +"Ou c #828B95", +"Oi c #717981", +"Op c #698E6F", +"Oa c #6B8871", +"Os c #6F777F", +"Od c #C9D2CA", +"Of c #517C54", +"Og c #7B858E", +"Oh c #81848A", +"Oj c #8B9E97", +"Ok c #C7D0C8", +"Ol c #FDFBFD", +"Oz c #FAF9FA", +"Ox c #69686F", +"Oc c #F9F7F9", +"Ov c #212325", +"Ob c #A7AEB9", +"On c #F8F5F8", +"Om c #6E8477", +"OM c #F5F5F5", +"ON c #427245", +"OB c #A3ACB5", +"OV c #829184", +"OC c #0B0B0C", +"OZ c #F2F1F2", +"OA c #71747A", +"OS c #436246", +"OD c #3C6C3F", +"OF c #8D949C", +"OG c #415E44", +"OH c #405E43", +"OJ c #4B4C4E", +"OK c #3B663E", +"OL c #E9E7E9", +"OP c #E7E7E7", +"OI c #E6E5E6", +"OU c #39583C", +"OY c #E5E5E5", +"OT c #E4E3E4", +"OR c #365839", +"OE c #365639", +"OW c #808C8F", +"OQ c #525258", +"O! c #335636", +"O~ c #515057", +"O^ c #E0DFE0", +"O/ c #325435", +"O( c #DFDFDF", +"O) c #485A4E", +"O_ c #2E5231", +"O` c #DCDBDC", +"O' c #75957A", +"O] c #729977", +"O[ c #749579", +"O{ c #D8DDD8", +"O} c #DAD9DA", +"O| c #709775", +"+ c #719576", +"+. c #DAD7DA", +"+X c #29502C", +"+o c #588F5A", +"+O c #6F9574", +"++ c #709375", +"+@ c #849D8C", +"+# c #6F9374", +"+$ c #6F9174", +"+% c #D2DDD2", +"+& c #849096", +"+* c #6E9173", +"+= c #6D9172", +"+- c #D5D5D5", +"+; c #6E8F73", +"+: c #D6D3D6", +"+> c #646A70", +"+, c #D5D3D5", +"+< c #838C95", +"+1 c #6C8F71", +"+2 c #D5D1D5", +"+3 c #6B8F70", +"+4 c #818A93", +"+5 c #698D6E", +"+6 c #D1D1D1", +"+7 c #6A8B6F", +"+8 c #5B755D", +"+9 c #8F9AA4", +"+0 c #CED1CE", +"+q c #8F98A4", +"+w c #68896D", +"+e c #1E4821", +"+r c #668B6B", +"+t c #8E98A3", +"+y c #84858C", +"+u c #1D4820", +"+i c #67876C", +"+p c #65896A", +"+a c #8D96A2", +"+s c #82858A", +"+d c #8C96A1", +"+f c #66856B", +"+g c #929E93", +"+h c #7B848D", +"+j c #65856A", +"+k c #818389", +"+l c #4C814E", +"+z c #4D7F4F", +"+x c #909E91", +"+c c #4C7F4E", +"+v c #8A949F", +"+b c #CACBCA", +"+n c #19441C", +"+m c #89949E", +"+M c #697078", +"+N c #88929D", +"+B c #628167", +"+V c #778089", +"+C c #8A9E8B", +"+Z c #9CA3AA", +"+A c #617F66", +"+S c #607D65", +"+D c #728B7A", +"+F c #89988A", +"+G c #5E7D63", +"+H c #A9B1BA", +"+J c #F9F6F8", +"+K c #5C7B61", +"+L c #829883", +"+P c #466948", +"+I c #8FAA93", +"+U c #4D5D4F", +"+Y c #4C5D4E", +"+T c #58755D", +"+R c #4A5D4C", +"+E c #1B1C1E", +"+W c #EDECEC", +"+Q c #445746", +"+! c #788E79", +"+~ c #141617", +"+^ c #3D5F3F", +"+/ c #38673A", +"+( c #595D5E", +"+) c #84A288", +"+_ c #83A287", +"+` c #3A5D3C", +"+' c None", +/* pixels */ +"+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*", +"+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*", +"+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*", +"+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*", +"+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*", +"+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*", +"+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*", +"+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+#.{+ +iX7X7X7X-.{++X.+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*", +"+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*.{Xy GO OE.FX[O_O_o= o.J.N I+AX-X.+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*", +"+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+* 9Xl /.R wor 4 4 4 4 4 4 4 4 6oy+X.J PX8+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*", +"+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+* !o7or 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 }ORX.+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*", +"+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*X.XA 6 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4or U+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*", +"+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*++ /or 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4XRO]+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*", +"+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*.{OU 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4oMX~+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*", +"+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*X. Wor 4 4 4 4oqoyocoeo0o0o0or t 6 4 4 4 4 4.Vo@+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*", +"+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+Ao3 4 4oyosX|OoOxXgXw+sOhXb.k XX^ y 4 4oh.,+O+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*", +"+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*X.oK.ZO,X{ K v.iO$.$ n+moH | (OFOA.z ^ '.] <+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*", +"+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+7o-ObXmO*+d l noBoSoS loSoSoBXrO#.h.r./+=+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*", +"+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*X..0X XroB noS n l loSoSoS loS l l l loHoBom hX#+*+*+*+*+*X.X.+*+*+*+*+*+*+*+*+*+*+*+*+*", +"+*+*+*+*+*+*+*+*+*+*+*+*.{Xj+KoU+BX.+*+*Oa coDoB l loS noSoS noSoSoS loS l l l loSoBXeoLX&+*+*X- Fo/oQ+i+*+*+*+*+*+*+*+*+*+*+*+*", +"+*+*+*+*+*+*+*+*+*+*+*+* Y ,oy wo; B+* a.1oSoS l noSoS n loS loB noS n loSoSoSoB l n n+qO=X# u.N 4oy w.DX>+*+*+*+*+*+*+*+*+*+*+*", +"+*+*+*+*+*+*+*+*+*+*XX+T 6 4 4 4 4 2obojoHoB l noS noS loSoSoS l loS loS loB n l l loS lom = )oy 4 4 4O%.lX.+*+*+*+*+*+*+*+*+*+*", +"+*+*+*+*+*+*+*+*+*+*X-.J 4 4 4 4 4oro) joSoSoS l loSoS n l l n noS l l g loS loS l l loHoSOWo, 4 4 4 4 4O>.)+*+*+*+*+*+*+*+*+*+*", +"+*+*+*+*+*+*+*+*+*+* A+X 4 4 4 4 4of+k+voSoB n l l loS l loB+doB noBoH l n loSoSoSoSoS l lXao( 4 4 4 4 4 4OfXO+*+*+*+*+*+*+*+*+*", +"+*+*+*+*+*+*+*+*+*+#O or 4 4 4 4oq : ZoHoBoH noSoS loS noBoH+h DXhoEOe l loS l loS loB n lXd.tod 4 4 4 4 4XQ.[+*+*+*+*+*+*+*+*+*", +"+*+*+*+*+*+*+*+*+*+*.J 4 4 4 4 4odOJ.aoSoSoB loS noSoS g.7XN o]Xf+toS loSoH l noS lO0O:+^ 4 4 4 4 4 po*+*+*+*+*+*+*+*+*+*", +"+*+*+*+*+*+*+*+*+*X7o= 4 4 4 4 4 [ K.ooS loS n n loSoBOiO. Xz n l l l noS n n g+>+Roy 4 4 4 4oi dXO+*+*+*+*+*+*+*+*", +"+*+*+*+*+*+*+*+*+*+Ao3 4 4 4 4oq :.>+N l n l loS l l+4XI oBoHoS loS l noBoBXdXc w 4 4 4 4 8oRXO+*+*+*+*+*+*+*+*", +"+*+*+*+*+*+*+*+*+*Xloy 4 4 4 4oqo% H loSoHoSoSoS lX1XM .eoSoH l l noB n lOg T 1 4 4 4 4 4.w+;+*+*+*+*+*+*+*+*", +"+*+*+*+*+*+*+*+*X.+Toy 4 4 4 4owX`OB loS l l l NoSO9Ov .fo6 l loSoS l l l.5O~XU 4 4 4 4 4ON+#+*+*+*+*+*+*+*+*", +"+*+*+*+*+*+*+*+*X. Qor 4 4 4 4owX`OB noS l loH loS.2+~ +HoS l l n n l nX@OQXT 4 4 4 4 4XK ;+*+*+*+*+*+*+*+*", +"+*+*+*+*+*+*+*+*X.o`or 4 4 4 4owX`XBoBoSoSoS loS l.4+E Xv loSoS n loS lOrOQXT 4 4 4 4 4OD.~+*+*+*+*+*+*+*+*", +"+*+*+*+*+*+*+*+*+*+Soy 4 4 4 4oqooo} l noSoS loS l+9XV oN. oSoSoSoS loS lOuXPo+ 4 4 4 4 4X9X$+*+*+*+*+*+*+*+*", +"+*+*+*+*+*+*+*+*+*Xl w 4 4 4 4oqo$ R+doS noS loSoSoSX6XH +ZoSoS n l loSoS n+VXk w 4 4 4 4 4+l+;+*+*+*+*+*+*+*+*", +"+*+*+*+*+*+*+*+*+*+f.E 4 4 4 4 4o0oI+m l n noS l l lO3 S .sO;oSoB noS l l noBoCXC q 4 4 4 4oa.@XO+*+*+*+*+*+*+*+*", +"+*+*+*+*+*+*+*+*+*X3.U 4 4 4 4 4ol.uX=oBoSoSoSoS l loS lOs.d OCo~ ioBoS n noSoS noS lO7XJ 4 4 4 4 4 r 0XO+*+*+*+*+*+*+*+*", +"+*+*+*+*+*+*+*+*+*.{.N 6 4 4 4 4oqo..O n noSoH goSoSoSoSoSog.%.S.C E+HO1oSoSoBoSoS loBoS l.q+( 3 4 4 4 4 4 4 O+*+*+*+*+*+*+*+*+*", +"+*+*+*+*+*+*+*+*+*X. I } 4 4 4 4 4os+yoHoS noSoS noBoBoSoSoSoSoHoHXuoS l n loS l n n loS noJXFor 4 4 4 4 4XnO|+*+*+*+*+*+*+*+*+*", +"+*+*+*+*+*+*+*+*+*+*+j.R 4 4 4 4 4oq L n noBoS l loSoSoS loSoSoS l loSoS loH l noSoB noBoS.& _ 4 4 4 4 4oi.++;+*+*+*+*+*+*+*+*+*", +"+*+*+*+*+*+*+*+*+*+*.{OX { 4 4 4 4ozO- C loH l loSoS loSoS l loS loS l l l noSoSoSoSoSoB+a zO/ 4 4 4 4 4o>X)+*+*+*+*+*+*+*+*+*+*", +"+*+*+*+*+*+*+*+*+*+*+*+wO!oa 4 8 pO8O|oWoS l loBoS l n loSoS l loSoS l noSoS loS l noSoZ.-+_o[o9.. 4 q.^ ]+*+*+*+*+*+*+*+*+*+*+*", +"+*+*+*+*+*+*+*+*+*+*+*+*+$oA+c+oO&o2+*X.Om+qoS noS loS l loSoSoS loS n n n loS l l goF.xX4Oz+:+povXi.*oX+*+*+*+*+*+*+*+*+*+*+*+*", +"+*+*+*+*+*+*+*+*+*+*+*+*+*+*+;+;XO+*+*+*+#+D M m l l n noHoSoS loSoS loSoS l l noSoZOj 5X0+J+,X #+*+*+* > #+*+*+*+*O[X!X!X!XEX} #+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*", +"+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*", +"+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*", +"+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*", +"+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*", +"+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*", +"+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*", +"+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*" +}; Index: tags/2.1.2/doc/resources/logo_made_with.lht =================================================================== --- tags/2.1.2/doc/resources/logo_made_with.lht (nonexistent) +++ tags/2.1.2/doc/resources/logo_made_with.lht (revision 24813) @@ -0,0 +1,555 @@ +li:pcb-rnd-subcircuit-v4 { + ha:subc.438 { + ha:attributes { + refdes = U0 + } + ha:data { + li:padstack_prototypes { + } + li:objects { + } + li:layers { + ha:silk { + lid = 0 + ha:type { + silk = 1 + top = 1 + } + li:objects { + ha:line.338 { + clearance = 20.0mil + y2 = 1.97in + thickness = 10.0mil + ha:attributes { + } + x1 = 2.3in + x2 = 2.31in + ha:flags { + clearline = 1 + } + y1 = 1.96in + } + ha:line.341 { + clearance = 20.0mil + y2 = 1.93in + thickness = 10.0mil + ha:attributes { + } + x1 = 2.3in + x2 = 2.31in + ha:flags { + clearline = 1 + } + y1 = 1.94in + } + ha:line.344 { + clearance = 20.0mil + y2 = 1.93in + thickness = 10.0mil + ha:attributes { + } + x1 = 59.436mm + x2 = 2.31in + ha:flags { + clearline = 1 + } + y1 = 1.93in + } + ha:line.347 { + clearance = 20.0mil + y2 = 1.88in + thickness = 10.0mil + ha:attributes { + } + x1 = 59.436mm + x2 = 59.436mm + ha:flags { + clearline = 1 + } + y1 = 1.97in + } + ha:line.350 { + clearance = 20.0mil + y2 = 1.97in + thickness = 10.0mil + ha:attributes { + } + x1 = 2.31in + x2 = 59.436mm + ha:flags { + clearline = 1 + } + y1 = 1.97in + } + ha:line.353 { + clearance = 20.0mil + y2 = 1.96in + thickness = 10.0mil + ha:attributes { + } + x1 = 2.3in + x2 = 2.3in + ha:flags { + clearline = 1 + } + y1 = 1.94in + } + ha:line.356 { + clearance = 20.0mil + y2 = 1.93in + thickness = 10.0mil + ha:attributes { + } + x1 = 2.28in + x2 = 2.27in + ha:flags { + clearline = 1 + } + y1 = 1.94in + } + ha:line.359 { + clearance = 20.0mil + y2 = 1.97in + thickness = 10.0mil + ha:attributes { + } + x1 = 2.28in + x2 = 2.28in + ha:flags { + clearline = 1 + } + y1 = 1.94in + } + ha:line.362 { + clearance = 20.0mil + y2 = 1.93in + thickness = 10.0mil + ha:attributes { + } + x1 = 2.25in + x2 = 2.27in + ha:flags { + clearline = 1 + } + y1 = 1.93in + } + ha:line.365 { + clearance = 20.0mil + y2 = 1.93in + thickness = 10.0mil + ha:attributes { + } + x1 = 2.24in + x2 = 2.25in + ha:flags { + clearline = 1 + } + y1 = 1.94in + } + ha:line.368 { + clearance = 20.0mil + y2 = 1.97in + thickness = 10.0mil + ha:attributes { + } + x1 = 2.24in + x2 = 2.24in + ha:flags { + clearline = 1 + } + y1 = 1.93in + } + ha:line.371 { + clearance = 20.0mil + y2 = 1.96in + thickness = 10.0mil + ha:attributes { + } + x1 = 49.53mm + x2 = 1.96in + ha:flags { + clearline = 1 + } + y1 = 1.97in + } + ha:line.374 { + clearance = 20.0mil + y2 = 1.94in + thickness = 10.0mil + ha:attributes { + } + x1 = 49.53mm + x2 = 1.96in + ha:flags { + clearline = 1 + } + y1 = 1.93in + } + ha:line.377 { + clearance = 20.0mil + y2 = 1.97in + thickness = 10.0mil + ha:attributes { + } + x1 = 2.08in + x2 = 52.578mm + ha:flags { + clearline = 1 + } + y1 = 1.96in + } + ha:line.380 { + clearance = 20.0mil + y2 = 1.94in + thickness = 10.0mil + ha:attributes { + } + x1 = 52.578mm + x2 = 2.08in + ha:flags { + clearline = 1 + } + y1 = 1.93in + } + ha:line.383 { + clearance = 20.0mil + y2 = 1.97in + thickness = 10.0mil + ha:attributes { + } + x1 = 1.98in + x2 = 1.99in + ha:flags { + clearline = 1 + } + y1 = 1.96in + } + ha:line.386 { + clearance = 20.0mil + y2 = 1.93in + thickness = 10.0mil + ha:attributes { + } + x1 = 1.98in + x2 = 1.99in + ha:flags { + clearline = 1 + } + y1 = 1.94in + } + ha:line.389 { + clearance = 20.0mil + y2 = 2.01in + thickness = 10.0mil + ha:attributes { + } + x1 = 1.92in + x2 = 1.92in + ha:flags { + clearline = 1 + } + y1 = 1.93in + } + ha:line.392 { + clearance = 20.0mil + y2 = 1.93in + thickness = 10.0mil + ha:attributes { + } + x1 = 52.578mm + x2 = 2.04in + ha:flags { + clearline = 1 + } + y1 = 1.93in + } + ha:line.395 { + clearance = 20.0mil + y2 = 1.94in + thickness = 10.0mil + ha:attributes { + } + x1 = 2.08in + x2 = 2.08in + ha:flags { + clearline = 1 + } + y1 = 1.96in + } + ha:line.398 { + clearance = 20.0mil + y2 = 1.97in + thickness = 10.0mil + ha:attributes { + } + x1 = 2.04in + x2 = 52.578mm + ha:flags { + clearline = 1 + } + y1 = 1.97in + } + ha:line.401 { + clearance = 20.0mil + y2 = 1.97in + thickness = 10.0mil + ha:attributes { + } + x1 = 2.04in + x2 = 2.04in + ha:flags { + clearline = 1 + } + y1 = 1.88in + } + ha:line.404 { + clearance = 20.0mil + y2 = 1.97in + thickness = 10.0mil + ha:attributes { + } + x1 = 1.99in + x2 = 2.02in + ha:flags { + clearline = 1 + } + y1 = 1.97in + } + ha:line.407 { + clearance = 20.0mil + y2 = 1.96in + thickness = 10.0mil + ha:attributes { + } + x1 = 1.98in + x2 = 1.98in + ha:flags { + clearline = 1 + } + y1 = 1.94in + } + ha:line.410 { + clearance = 20.0mil + y2 = 1.93in + thickness = 10.0mil + ha:attributes { + } + x1 = 1.99in + x2 = 2.02in + ha:flags { + clearline = 1 + } + y1 = 1.93in + } + ha:line.413 { + clearance = 20.0mil + y2 = 1.96in + thickness = 10.0mil + ha:attributes { + } + x1 = 1.96in + x2 = 1.96in + ha:flags { + clearline = 1 + } + y1 = 1.94in + } + ha:line.416 { + clearance = 20.0mil + y2 = 1.97in + thickness = 10.0mil + ha:attributes { + } + x1 = 49.53mm + x2 = 1.92in + ha:flags { + clearline = 1 + } + y1 = 1.97in + } + ha:line.419 { + clearance = 20.0mil + y2 = 1.93in + thickness = 10.0mil + ha:attributes { + } + x1 = 1.92in + x2 = 49.53mm + ha:flags { + clearline = 1 + } + y1 = 1.93in + } + ha:line.422 { + clearance = 20.0mil + y2 = 1.93in + thickness = 10.0mil + ha:attributes { + } + x1 = 55.626mm + x2 = 2.22in + ha:flags { + clearline = 1 + } + y1 = 1.93in + } + ha:line.425 { + clearance = 20.0mil + y2 = 1.93in + thickness = 10.0mil + ha:attributes { + } + x1 = 2.18in + x2 = 55.626mm + ha:flags { + clearline = 1 + } + y1 = 1.94in + } + ha:line.428 { + clearance = 20.0mil + y2 = 1.97in + thickness = 10.0mil + ha:attributes { + } + x1 = 2.18in + x2 = 2.18in + ha:flags { + clearline = 1 + } + y1 = 1.93in + } + ha:line.431 { + clearance = 20.0mil + y2 = 49.53mm + thickness = 10.0mil + ha:attributes { + } + x1 = 53.594mm + x2 = 54.61mm + ha:flags { + clearline = 1 + } + y1 = 49.53mm + } + ha:arc.434 { + astart = 0 + thickness = 10.0mil + width = 10.0mil + height = 10.0mil + ha:attributes { + } + x = 59.436mm + y = 1.87in + adelta = 360 + ha:flags { + clearline = 1 + } + clearance = 20.0mil + } + ha:arc.435 { + astart = 0 + thickness = 10.0mil + width = 10.0mil + height = 10.0mil + ha:attributes { + } + x = 2.04in + y = 1.87in + adelta = 360 + ha:flags { + clearline = 1 + } + clearance = 20.0mil + } + ha:arc.436 { + astart = 0 + thickness = 10.0mil + width = 10.0mil + height = 10.0mil + ha:attributes { + } + x = 1.92in + y = 2.02in + adelta = 360 + ha:flags { + clearline = 1 + } + clearance = 20.0mil + } + ha:text.437 { + scale = 100 + ha:attributes { + } + direction = 0 + x = 2.06in + y = 1.86in + string = made with + fid = 0 + ha:flags { + clearline = 1 + } + } + } + ha:combining { + auto = 1 + } + } + ha:subc-aux { + lid = 1 + ha:type { + top = 1 + misc = 1 + virtual = 1 + } + li:objects { + ha:line.439 { + clearance = 0.0 + y2 = 1.93in + thickness = 0.1mm + ha:attributes { + subc-role = origin + } + x1 = 2.04in + x2 = 2.04in + ha:flags { + } + y1 = 1.93in + } + ha:line.442 { + clearance = 0.0 + y2 = 1.93in + thickness = 0.1mm + ha:attributes { + subc-role = x + } + x1 = 2.04in + x2 = 52.816mm + ha:flags { + } + y1 = 1.93in + } + ha:line.445 { + clearance = 0.0 + y2 = 50.022mm + thickness = 0.1mm + ha:attributes { + subc-role = y + } + x1 = 2.04in + x2 = 2.04in + ha:flags { + } + y1 = 1.93in + } + } + ha:combining { + } + } + } + } + uid = NhAIKQfa5EkLmJw7dscAAAAE + ha:flags { + } + } +} Index: tags/2.1.2/doc/resources/logo_made_with.pcb =================================================================== --- tags/2.1.2/doc/resources/logo_made_with.pcb (nonexistent) +++ tags/2.1.2/doc/resources/logo_made_with.pcb (revision 24813) @@ -0,0 +1,82 @@ +# release: pcb 20140316 + +# To read pcb files, the pcb version (or the git source date) must be >= the file version +FileVersion[20091103] + +PCB["" 6000.00mil 5000.00mil] + +Grid[1000.000000 0.0000 0.0000 0] +PolyArea[3100.006200] +Thermal[0.500000] +DRC[10.00mil 10.00mil 10.00mil 10.00mil 15.00mil 10.00mil] +Flags("nameonpcb,uniquename,clearnew,snappin") +Groups("1,c:2:3:4:5:6,s:7:8") +Styles["Signal,10.00mil,36.00mil,20.00mil,10.00mil:Power,25.00mil,60.00mil,35.00mil,10.00mil:Fat,40.00mil,60.00mil,35.00mil,10.00mil:Skinny,6.00mil,24.02mil,11.81mil,6.00mil"] + +Attribute("PCB::grid::unit" "mil") +Layer(1 "top") +( +) +Layer(2 "ground") +( +) +Layer(3 "signal2") +( +) +Layer(4 "signal3") +( +) +Layer(5 "power") +( +) +Layer(6 "bottom") +( +) +Layer(7 "outline") +( +) +Layer(8 "spare") +( +) +Layer(9 "silk") +( +) +Layer(10 "silk") +( + Line[2110.00mil 1950.00mil 2150.00mil 1950.00mil 10.00mil 20.00mil "clearline"] + Line[2180.00mil 1930.00mil 2180.00mil 1970.00mil 10.00mil 20.00mil "clearline"] + Line[2180.00mil 1940.00mil 2190.00mil 1930.00mil 10.00mil 20.00mil "clearline"] + Line[2190.00mil 1930.00mil 2220.00mil 1930.00mil 10.00mil 20.00mil "clearline"] + Line[1920.00mil 1930.00mil 1950.00mil 1930.00mil 10.00mil 20.00mil "clearline"] + Line[1950.00mil 1970.00mil 1920.00mil 1970.00mil 10.00mil 20.00mil "clearline"] + Line[1960.00mil 1940.00mil 1960.00mil 1960.00mil 10.00mil 20.00mil "clearline"] + Line[1990.00mil 1930.00mil 2020.00mil 1930.00mil 10.00mil 20.00mil "clearline"] + Line[1980.00mil 1940.00mil 1980.00mil 1960.00mil 10.00mil 20.00mil "clearline"] + Line[1990.00mil 1970.00mil 2020.00mil 1970.00mil 10.00mil 20.00mil "clearline"] + Line[2040.00mil 1880.00mil 2040.00mil 1970.00mil 10.00mil 20.00mil "clearline"] + Line[2040.00mil 1970.00mil 2070.00mil 1970.00mil 10.00mil 20.00mil "clearline"] + Line[2080.00mil 1960.00mil 2080.00mil 1940.00mil 10.00mil 20.00mil "clearline"] + Line[2070.00mil 1930.00mil 2040.00mil 1930.00mil 10.00mil 20.00mil "clearline"] + Line[1920.00mil 1930.00mil 1920.00mil 2010.00mil 10.00mil 20.00mil "clearline"] + Line[1980.00mil 1940.00mil 1990.00mil 1930.00mil 10.00mil 20.00mil "clearline"] + Line[1980.00mil 1960.00mil 1990.00mil 1970.00mil 10.00mil 20.00mil "clearline"] + Line[2070.00mil 1930.00mil 2080.00mil 1940.00mil 10.00mil 20.00mil "clearline"] + Line[2080.00mil 1960.00mil 2070.00mil 1970.00mil 10.00mil 20.00mil "clearline"] + Line[1950.00mil 1930.00mil 1960.00mil 1940.00mil 10.00mil 20.00mil "clearline"] + Line[1950.00mil 1970.00mil 1960.00mil 1960.00mil 10.00mil 20.00mil "clearline"] + Line[2240.00mil 1930.00mil 2240.00mil 1970.00mil 10.00mil 20.00mil "clearline"] + Line[2240.00mil 1940.00mil 2250.00mil 1930.00mil 10.00mil 20.00mil "clearline"] + Line[2250.00mil 1930.00mil 2270.00mil 1930.00mil 10.00mil 20.00mil "clearline"] + Line[2280.00mil 1940.00mil 2280.00mil 1970.00mil 10.00mil 20.00mil "clearline"] + Line[2280.00mil 1940.00mil 2270.00mil 1930.00mil 10.00mil 20.00mil "clearline"] + Line[2300.00mil 1940.00mil 2300.00mil 1960.00mil 10.00mil 20.00mil "clearline"] + Line[2310.00mil 1970.00mil 2340.00mil 1970.00mil 10.00mil 20.00mil "clearline"] + Line[2340.00mil 1970.00mil 2340.00mil 1880.00mil 10.00mil 20.00mil "clearline"] + Line[2340.00mil 1930.00mil 2310.00mil 1930.00mil 10.00mil 20.00mil "clearline"] + Line[2300.00mil 1940.00mil 2310.00mil 1930.00mil 10.00mil 20.00mil "clearline"] + Line[2300.00mil 1960.00mil 2310.00mil 1970.00mil 10.00mil 20.00mil "clearline"] + Arc[1920.00mil 2020.00mil 10.00mil 10.00mil 10.00mil 20.00mil 0 360 "clearline"] + Arc[2040.00mil 1870.00mil 10.00mil 10.00mil 10.00mil 20.00mil 0 360 "clearline"] + Arc[2340.00mil 1870.00mil 10.00mil 10.00mil 10.00mil 20.00mil 0 360 "clearline"] + Text[2060.00mil 1860.00mil 0 100 "made with" "clearline"] +) Index: tags/2.1.2/doc/resources/logo_svg.pcb =================================================================== --- tags/2.1.2/doc/resources/logo_svg.pcb (nonexistent) +++ tags/2.1.2/doc/resources/logo_svg.pcb (revision 24813) @@ -0,0 +1,105 @@ +# release: pcb-rnd 1.2.6 + +# To read pcb files, the pcb version (or the git source date) must be >= the file version +FileVersion[20070407] + +PCB["" 5080000nm 5080000nm] + +Grid[635000nm 0 0 1] +Cursor[4445000nm 3175000nm 0.000000] +PolyArea[3100.006200] +Thermal[0.500000] +DRC[304800nm 228600nm 254000nm 177800nm 381000nm 254000nm] +Flags("nameonpcb,clearnew,snappin") +Groups("9:11:1,3,4,c:7:8:2,5,6,s:12:10") +Styles["Signal,254000nm,1999996nm,800100nm,508000nm:Power,508000nm,2199894nm,999998nm,508000nm:Fat,2032000nm,3500120nm,1199896nm,635000nm:Sig-tight,254000nm,1625600nm,800100nm,304800nm"] + +Symbol['d' 304800nm] +( + SymbolLine[508000nm 0 508000nm 1016000nm 203200nm] + SymbolLine[381000nm 1016000nm 508000nm 889000nm 203200nm] + SymbolLine[127000nm 1016000nm 381000nm 1016000nm 203200nm] + SymbolLine[0 889000nm 127000nm 1016000nm 203200nm] + SymbolLine[0 635000nm 0 889000nm 203200nm] + SymbolLine[0 635000nm 127000nm 508000nm 203200nm] + SymbolLine[127000nm 508000nm 381000nm 508000nm 203200nm] + SymbolLine[381000nm 508000nm 508000nm 635000nm 203200nm] +) +Symbol['n' 304800nm] +( + SymbolLine[127000nm 635000nm 127000nm 1016000nm 203200nm] + SymbolLine[127000nm 635000nm 254000nm 508000nm 203200nm] + SymbolLine[254000nm 508000nm 381000nm 508000nm 203200nm] + SymbolLine[381000nm 508000nm 508000nm 635000nm 203200nm] + SymbolLine[508000nm 635000nm 508000nm 1016000nm 203200nm] + SymbolLine[0 508000nm 127000nm 635000nm 203200nm] +) +Symbol['r' 304800nm] +( + SymbolLine[127000nm 635000nm 127000nm 1016000nm 203200nm] + SymbolLine[127000nm 635000nm 254000nm 508000nm 203200nm] + SymbolLine[254000nm 508000nm 508000nm 508000nm 203200nm] + SymbolLine[0 508000nm 127000nm 635000nm 203200nm] +) +Attribute("PCB::grid::unit" "mil") +Attribute("PCB::conf::editor/buffer_number" "0") +Attribute("PCB::conf::editor/draw_grid" "true") +Attribute("PCB::conf::editor/show_solder_side" "0") +Attribute("PCB::conf::editor/view/flip_x" "0") +Attribute("PCB::conf::editor/view/flip_y" "0") +Attribute("PCB::loader" "geda/pcb - nanometer") + +Element["" "dip(2)" "rnd" "2*300" -5000000nm 2500000nm 6350000nm 635000nm 0 115 ""] +( + Attribute("footprint" "dip(2)") + Attribute("refdes" "rnd") + Attribute("value" "2*300") + Pin[7620000nm 0 2540000nm 1270000nm 2692400nm 999998nm "" "2" "thermal(0X,1X)"] + +) +Layer(1 "component") +( + Polygon("clearpoly") + ( + [0 0] [5080000nm 0] [5080000nm 5080000nm] [0 5080000nm] + ) +) +Layer(2 "solder") +( +) +Layer(3 "comp-GND") +( +) +Layer(4 "comp-power") +( +) +Layer(5 "sold-GND") +( +) +Layer(6 "sold-power") +( +) +Layer(7 "signal3") +( +) +Layer(8 "outline") +( +) +Layer(9 "top-paste") +( +) +Layer(10 "bottom-paste") +( +) +Layer(11 "top-mask") +( +) +Layer(12 "bottom-mask") +( +) +Layer(13 "silk") +( +) +Layer(14 "silk") +( +) Index: tags/2.1.2/doc/resources/screenshot.jpg =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/resources/screenshot.jpg =================================================================== --- tags/2.1.2/doc/resources/screenshot.jpg (nonexistent) +++ tags/2.1.2/doc/resources/screenshot.jpg (revision 24813) Property changes on: tags/2.1.2/doc/resources/screenshot.jpg ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/scripting.txt =================================================================== --- tags/2.1.2/doc/scripting.txt (nonexistent) +++ tags/2.1.2/doc/scripting.txt (revision 24813) @@ -0,0 +1,34 @@ +1. Action scripting +~~~~~~~~~~~~~~~~~~~ +Action scripting is the builtin, non-turing-complete way of giving pcb-rnd +commands. On the GUI it's usually the ':' key that pops up the command line. +Most HIDs support the --listen argument that makes pcb-rnd also read commands +on the stdin. + +The batch HID always reads commands on stdin (without --listen). Automated +pcb-rnd runs from shell is possible using a script like: + +echo ' + action1() + action2() + ... +' | pcb-rnd --gui batch + +From within pcb-rnd the ExecuteFile(filename) action can be used to +load and execute a pcb-rnd action script from a file. + +2. Embedded scripting +~~~~~~~~~~~~~~~~~~~~~ +pcb-rnd uses fungw for embedded scripting. This allows pcb-rnd to be +scripted in 10+ turing complete scripting languages, including awk, tcl, +python, perl, lua, some lisp dialects, etc. Embedded scripts run within +pcb-rnd (in the same process, same address space), having full access +to the action infrastructure: + - embedded scripts can declare new actions that are accessible from + menu, from the command line and from other embedded scripts + - embedded scripts can execute actions (defined by pcb-rnd or other + embedded scripts) + +For more info see user/06_feature/scripting/ + + Index: tags/2.1.2/doc/security/Makefile =================================================================== --- tags/2.1.2/doc/security/Makefile (nonexistent) +++ tags/2.1.2/doc/security/Makefile (revision 24813) @@ -0,0 +1,26 @@ +ROOT=../.. +SECDIR=$(DOCDIR)/security + + +all: + +install_all: + $(SCCBOX) mkdir -p $(SECDIR) + $(SCCBOX) $(HOW) *.html $(SECDIR)/ + $(SCCBOX) $(HOW) README $(SECDIR)/ + +install: + $(MAKE) install_all HOW="install -f -d" + +linstall: + $(MAKE) install_all HOW="install -f -l -d" + +uninstall: + $(MAKE) install_all HOW="install -u" + +clean: + +distclean: + + +include $(ROOT)/Makefile.conf Index: tags/2.1.2/doc/security/README =================================================================== --- tags/2.1.2/doc/security/README (nonexistent) +++ tags/2.1.2/doc/security/README (revision 24813) @@ -0,0 +1,2 @@ +This directory contains bugreports that are security sensitive. The +reports also describe mitigation and upgrade paths and safe versions. Index: tags/2.1.2/doc/security/bug1.html =================================================================== --- tags/2.1.2/doc/security/bug1.html (nonexistent) +++ tags/2.1.2/doc/security/bug1.html (revision 24813) @@ -0,0 +1,70 @@ + + + + pcb-rnd - news + + + + + +

pcb-rnd security related bug #1: execbug

+

+Users opening untrusted boards or projects may unintentionally execute +external programs. + +

1. Bug description

+

+pcb-rnd inherited 5 settings from gEDA/PCB that let pcb-rnd (and PCB) +execute external processes, wrapping certain file operations: +

    +
  • conf_core.rc.save_command +
  • conf_core.rc.rat_command +
  • conf_core.rc.library_shell +
  • conf_core.rc.file_command +
  • conf_core.rc.font_command +
+

+The old Settings system has been replaced in pcb-rnd; the new conf system +allows any configuration setting to be specified in a project file or a +board file. This includes the above 5 items as well. +

+Thus an attacker may produce a project or a single board file in .pcb or .lht format +that contains the above config settings, executing arbitrary shell command on the +user's computer when pcb-rnd opens or saves the file or loads fonts or +footprints or netlists. + +

2. How to prevent the attack

+ +

2.1. By using a version that is not affected

+

+

    +
  • from svn /trunk, any revision newer than r11597 +
  • any release starting from 1.2.6 +
  • old stable release 1.2.5, patched: 1.2.5b +
  • old stable release 1.1.4, patched: 1.1.4b +
+ +

2.2. By manually checking board and project files from untrusted source

+

+Before opening the file, grep for _command and _shell in it, remove +the offending lines. + + +

3. What did the patch/fix do

+

+The patch prevents these 5 settings to take effect when the source of +the setting is not from one of these: +

    +
  • internal (embedded in the executable, used as the ultimate fallback when no config is available) +
  • system installed config file (typically under /usr/) +
  • user config file (typically in ~/.pcb-rnd/) +
  • command line argument (-c) +
+

+This bans sources like the board file, the project file and environmental +variable. + + + + + Index: tags/2.1.2/doc/support.html =================================================================== --- tags/2.1.2/doc/support.html (nonexistent) +++ tags/2.1.2/doc/support.html (revision 24813) @@ -0,0 +1,69 @@ + + + + pcb-rnd - news + + + + + + + + + + +
Main + News + Doc & pool + Support + People + Events & timeline + pcb-rnd [pcb-rnd logo] +
+ + +
+ +

pcb-rnd support

+ +

Get support

+ +Option 1: subscribe to the mailing list: pcb-rnd list.repo.hu (send +a mail with subject: subscribe). We usually reply there within 24 hours. + (Archives) +

+Option 2: real-time chat with the developers and hard core users: IRC ; please pick a meaningful nickname, join, say +hi, state your question and be patient; someone will react in at most +3..4 hours. If nobody reacts but you see traffic, repeat your question. +Leaving there an idler client is okay. +

+The generic rule is that over whatever channel you can reach us, that's +also the right place to ask questions about pcb-rnd and we will answer there. +Currently these are the channels where we can be reached: +

+ +
type address +
public mailing list send subscribe to pcb-rnd list.repo.hu +
public IRC channel repo.hu:6667 #pcb-rnd +
private email Igor2's email address +
private IRC Igor2 on repo.hu or on ircnet +
+

+(We used to provide support on the gEDA mailing lists but we no longer do that.) + + +

Give support

+Option 1: if you are experienced with pcb-rnd or electronics: subscribe to +the mailing list, join IRC, try to provide help for +newbies. +

+Option 2: subscribe to the mailing list, offer your help; we are looking +for manpower with a lot of non-programming tasks as well! +

+Option 3: consider donating a small amount , +e.g. $5 or $10. Donations are transformed into developer hours put in the project. + + + + Index: tags/2.1.2/doc/tutorials/15_no_sch/index.html =================================================================== --- tags/2.1.2/doc/tutorials/15_no_sch/index.html (nonexistent) +++ tags/2.1.2/doc/tutorials/15_no_sch/index.html (revision 24813) @@ -0,0 +1,195 @@ +

step 1: place two capacitors

+

+Start pcb-rnd - it will start with an empty board (loaded from the +default board, as configured). +

+Pan: click with the scroll wheel of the mouse (or middle button) and move +the mouse; alternatively use the scroll bars at the bottom and right +of the editor area. Zoom: scroll wheel. +

+Press key w then key l (which will be written as {w l} in this tutorial). +This will open the library window ({w l} is for "window, library"). The +library window has a filter entry on the bottom left: enter +acy(200) there and the preview on the right side will show an +axial lead footprint with 200 mil pin distance. Although a typical +thru-hole ceramic capacitor is not axial lead, it will fit nicely in this +footprint: +

+step1: selecting acy(200) from the library window +

+The footprint is in the paste buffer and the buffer tool is selected +(which is visible on the overhead tool bar under the menu). Place +the buffer on the board by a left click. You can exit the buffer mode +by pressing the escape key or F11. +

+The placed footprint is called subcircuit or subc for short. The subc has +a refdes (the main ID of the subc) reading "R1". Grab this "R1" with a +left click and move it out from the middle of the subc and drop it near +the subc so it is readable. Rename the subc to "C1" by pressing {e r} +while hovering the mouse cursor over the subc body (not the refdes text); +{e r} is for "Edit Refdes". +

+Select the subcircuit by clicking it - any point where the subcircuit +has graphics would work, within the red dashed subc frame. The subc will +turn cyan. Note: the refdes text is selected separately from the subc. Make +sure to click on the silk screen graphics (black lines) or a pin to +make the whole subc cyan, not just the refdes text. +

+Once selected, press {e c} ("edit, copy") which will copy the modified subc +to the buffer and will select the buffer tool. Now place it next to the +original subc and modify its refdes to "C2". +

+step1: two capacitors + +

step 2: place the rest

+

+Place the rest of the subcircuits using the same method. It's best to keep +the library window open for all these placements: +

    +
  • a to220, rename it to U1 +
  • an rcy(200), rename it to C3 +
  • two connector(1,2), renamed to J1 and J2 +
+ +

+step2: all parts +

+ Board file for step2. + + +

step 3: create the gnd net by drawing rat lines

+

+To ease laying out the board, we create a net list by drawing rats. +Rat lines are logical connections between terminals. A terminal is +a pin or pad of a component, addressed as refdes-termid, where +refdes is the host subcircuit's refdes and termid is the unique terminal +ID within the subc. The drawing already has unique refdes assigned to +each subc and the stock footprints we worked from already have unique +terminal IDs. +

+Note: terminal IDs can be shown or hidden by hovering over the subc or +the terminal and pressing {v n} (for "view name"). The ID shows up printed +over the terminal (pin in our case) with tiny red letters - zoom in to see them. +A tooltip also shows the terminal ID after hovering the mouse cursor over the +terminal for a few seconds1. +

+Select the Rats layer on the left - it is part of the "Virtual" layer +group on the bottom. Select the line tool on the overhead toolbar +(second icon from the left). +

+Start drawing a line from J1's terminal 2 (the round one) by left-clicking it. +Left click C1's terminal 2. This is a new logical connection, a new net, so +a popup dialog will ask for the net name. Enter gnd and press enter. +

+The rat line drawing is still active from the last terminal, so go on connecting +C2's terminal 2, J2's terminal 2, U1's middle terminal and C3's negative +terminal. Since these connections are all extending the gnd network, no net name +is asked. When finished, press esc or F11. Don't mind what your rat lines +cross: only the two endpoint of a rat line matter. +

+step3: the gnd network +

+Press {w n} to open the network window: +

+step3: the network window +

+Note: you can zoom/pan the preview on the top right the same way as the main +drawing. If the network selection on the left changes, the right side is +updated. The preview highlights affected terminals. + +

step 4: create the rest of the networks using the same method

+

+

    +
  • network called in: J1-1, C3-1, U1-1, C1-1 +
  • network called out: J2-1, U1-3, C2-1 +
+

+ Board file for step3. +

+ +

step 5: draw the in and out nets

+

+Select the line tool (hotkey: F2). Select the 'Power' style from the +bottom left style selector - this will get the traces you'll be +drawing thicker. Select the bottom signal layer, called "bottom-sig" in +the layer selector on the left. This way the new traces will end up on +copper on the bottom side of the board. +

+Start drawing a line from J1-1 with left click. The line will bend in +45 degrees. You can press the shift key and move the mouse to invert +the refraction temporarily, or use the slash key to cycle through different +refraction (including the ortho mode, which allows 90 degree lines only). +With 2..3 clicks, connect J1-1 and C3's '+' pin. +

+Now that one of the logical connections is turned to copper, press {c r} +(for "connection, refresh rats") - this will recalculate all rats, considering +already established connections. +

+Draw the remaining segments of the in net, using {c r} to see the +progress. The number of remaining rat lines is also printed in the message +log, which can be opened using {w m}. +

+Do the same for the out network. At the end only the gnd network +should remain unrouted: +

+step4: in and out routed +

+ Board file for step4. + +

step 6: draw the gnd poly

+

+We could route the gnd net the same way, using thick traces. +However, it's more common to have a solid ground plane/pour, which is +a polygon in pcb-rnd. +

+Select the bottom-gnd layer. This layer is in the same layer group, +bottom copper, as the other layer we used, so at the end it will go +on the same physical copper layer. However, it has a different color +configured on screen, which would make it easier to see what's connected +to gnd. +

+Select the rect tool from the toolbar. This will draw a rectangular polygon. +Do a single click on the top left corner of your circuit. After releasing +the mouse button, the rectangle tool draws an overlay indication on how big +the polygon would be. Move the mouse cursor to the bottom right corner until the +box encloses the whole circuit and some margin and do another single click. +

+This will finish the operation and a large red rectangular polygon will appear. +However, {c r} shows that no gnd rat line got routed: the terminals of +the subcircuits won't automatically touch the polygon. The easiest way to +get them connected is using the thermal tool (labelled THRM in the toolbar). +Select the thermal tool and click on the J1-2. An X shaped connection will +appear to the polygon. +

+Note: it's important to still have the bottom-gnd +layer selected: the thermal tool connects the terminal to the polygon on the +currently selected layer, so the currently selected layer should be the one +we drew the ground plane polygon on. +

+Another click on the terminal would remove the thermal - it's a toggle operation. +When the thermal is there, a shift+click with the thermal tool will change +the thermal style, cycling through different available styles. +

+Use the thermal tool to connect all gnd terminals and press {c r}. +

+step6: board finished +

+ Board file for step6. + + +

Note on the view

+

+We've been drawing the board from looking at it from the top, with +'x-ray vision', seeing all copper on the bottom. Once the board is fabricated, +this is not how we'll see it. +

+It is possible to flip the board using the tab key, to get a bottom view. +There's also shift-tab an ctrl-tab to flip among different axes. Flipping +is a view-only feature, it does not modify any geometry or physical +property of the board. + +


+Footnotes: +
    +
  • 1: may not be available in the lesstif HID +
Index: tags/2.1.2/doc/tutorials/15_no_sch/step1a.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/tutorials/15_no_sch/step1a.png =================================================================== --- tags/2.1.2/doc/tutorials/15_no_sch/step1a.png (nonexistent) +++ tags/2.1.2/doc/tutorials/15_no_sch/step1a.png (revision 24813) Property changes on: tags/2.1.2/doc/tutorials/15_no_sch/step1a.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/tutorials/15_no_sch/step1b.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/tutorials/15_no_sch/step1b.png =================================================================== --- tags/2.1.2/doc/tutorials/15_no_sch/step1b.png (nonexistent) +++ tags/2.1.2/doc/tutorials/15_no_sch/step1b.png (revision 24813) Property changes on: tags/2.1.2/doc/tutorials/15_no_sch/step1b.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/tutorials/15_no_sch/step2.lht =================================================================== --- tags/2.1.2/doc/tutorials/15_no_sch/step2.lht (nonexistent) +++ tags/2.1.2/doc/tutorials/15_no_sch/step2.lht (revision 24813) @@ -0,0 +1,2107 @@ +ha:pcb-rnd-board-v6 { + + ha:attributes { + {PCB::grid::unit}=mil + } + + li:styles { + ha:Signal { + diameter = 2.0mm + text_scale = 0 + text_thick = 0.0 + thickness = 10.0mil + hole = 31.5mil + clearance = 20.0mil + } + ha:Power { + diameter = 2.2mm + text_scale = 0 + text_thick = 0.0 + thickness = 20.0mil + hole = 1.0mm + clearance = 20.0mil + } + ha:Fat { + diameter = 137.8mil + text_scale = 0 + text_thick = 0.0 + thickness = 80.0mil + hole = 47.24mil + clearance = 25.0mil + } + ha:Sig-tight { + diameter = 64.0mil + text_scale = 0 + text_thick = 0.0 + thickness = 10.0mil + hole = 31.5mil + clearance = 12.0mil + } + } + + ha:meta { + ha:size { + thermal_scale = 0.500000 + x = 127.0mm + y = 127.0mm + } + ha:grid { + spacing = 25.0mil + offs_x = 0.0 + offs_y = 0.0 + } + } + + ha:data { + li:padstack_prototypes { + } + + li:objects { + ha:subc.1158 { + ha:attributes { + value=TO220 + footprint=Transistor + refdes=U1 + } + ha:data { + li:padstack_prototypes { + + ha:ps_proto_v6.0 { + hdia=60.0mil; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + li:ps_poly { + -45.0mil + -45.0mil + 45.0mil + -45.0mil + 45.0mil + 45.0mil + -45.0mil + 45.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + li:ps_poly { + -45.0mil + -45.0mil + 45.0mil + -45.0mil + 45.0mil + 45.0mil + -45.0mil + 45.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + li:ps_poly { + -45.0mil + -45.0mil + 45.0mil + -45.0mil + 45.0mil + 45.0mil + -45.0mil + 45.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { sub=1; auto=1; } + ha:layer_mask { + top = 1 + mask = 1 + } + clearance=0.0 + li:ps_poly { + -48.0mil + -48.0mil + 48.0mil + -48.0mil + 48.0mil + 48.0mil + -48.0mil + 48.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { sub=1; auto=1; } + ha:layer_mask { + bottom = 1 + mask = 1 + } + clearance=0.0 + li:ps_poly { + -48.0mil + -48.0mil + 48.0mil + -48.0mil + 48.0mil + 48.0mil + -48.0mil + 48.0mil + } + } + } + } + + ha:ps_proto_v6.1 { + hdia=60.0mil; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=90.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=90.0mil; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=90.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=96.0mil; } + ha:combining { sub=1; auto=1; } + ha:layer_mask { + top = 1 + mask = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=96.0mil; } + ha:combining { sub=1; auto=1; } + ha:layer_mask { + bottom = 1 + mask = 1 + } + clearance=0.0 + } + } + } + + ha:ps_proto_v6.2 { + hdia=130.0mil; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=150.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=150.0mil; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=150.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=156.0mil; } + ha:combining { sub=1; auto=1; } + ha:layer_mask { + top = 1 + mask = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=156.0mil; } + ha:combining { sub=1; auto=1; } + ha:layer_mask { + bottom = 1 + mask = 1 + } + clearance=0.0 + } + } + } + } + + li:objects { + ha:padstack_ref.1229 { + proto=0; x=44.45mm; y=1.8in; rot=0.000000; xmirror=0; smirror=0; clearance=15.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + + ha:attributes { + term=1 + name=1 + } + } + ha:padstack_ref.1230 { + proto=1; x=46.99mm; y=1.8in; rot=0.000000; xmirror=0; smirror=0; clearance=15.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + + ha:attributes { + term=2 + name=2 + } + } + ha:padstack_ref.1231 { + proto=1; x=49.53mm; y=1.8in; rot=0.000000; xmirror=0; smirror=0; clearance=15.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + + ha:attributes { + term=3 + name=3 + } + } + ha:padstack_ref.1232 { + proto=2; x=46.99mm; y=1.13in; rot=0.000000; xmirror=0; smirror=0; clearance=15.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + + ha:attributes { + term=4 + name=4 + } + } + } + li:layers { + + ha:top-silk { + lid=0 + ha:combining { } + + li:objects { + ha:line.1159 { + x1=44.45mm; y1=1.8in; x2=44.45mm; y2=1.62in; thickness=30.0mil; clearance=0.0; + } + ha:line.1162 { + x1=46.99mm; y1=1.8in; x2=46.99mm; y2=1.62in; thickness=30.0mil; clearance=0.0; + } + ha:line.1165 { + x1=49.53mm; y1=1.8in; x2=49.53mm; y2=1.62in; thickness=30.0mil; clearance=0.0; + } + ha:line.1168 { + x1=1.65in; y1=1.62in; x2=52.07mm; y2=1.62in; thickness=20.0mil; clearance=0.0; + } + ha:line.1171 { + x1=52.07mm; y1=1.62in; x2=52.07mm; y2=31.623mm; thickness=20.0mil; clearance=0.0; + } + ha:line.1174 { + x1=52.07mm; y1=31.623mm; x2=1.65in; y2=31.623mm; thickness=20.0mil; clearance=0.0; + } + ha:line.1177 { + x1=1.65in; y1=31.623mm; x2=1.65in; y2=1.62in; thickness=20.0mil; clearance=0.0; + } + ha:line.1180 { + x1=1.65in; y1=31.623mm; x2=52.07mm; y2=31.623mm; thickness=20.0mil; clearance=0.0; + } + ha:line.1183 { + x1=52.07mm; y1=31.623mm; x2=52.07mm; y2=1.12in; thickness=20.0mil; clearance=0.0; + } + ha:line.1186 { + x1=52.07mm; y1=1.12in; x2=51.689mm; y2=1.12in; thickness=20.0mil; clearance=0.0; + } + ha:line.1189 { + x1=51.689mm; y1=1.12in; x2=51.689mm; y2=26.67mm; thickness=20.0mil; clearance=0.0; + } + ha:line.1192 { + x1=51.689mm; y1=26.67mm; x2=52.07mm; y2=26.67mm; thickness=20.0mil; clearance=0.0; + } + ha:line.1195 { + x1=52.07mm; y1=26.67mm; x2=52.07mm; y2=1.01in; thickness=20.0mil; clearance=0.0; + } + ha:line.1198 { + x1=52.07mm; y1=1.01in; x2=1.65in; y2=1.01in; thickness=20.0mil; clearance=0.0; + } + ha:line.1201 { + x1=1.65in; y1=1.01in; x2=1.65in; y2=26.67mm; thickness=20.0mil; clearance=0.0; + } + ha:line.1204 { + x1=1.65in; y1=26.67mm; x2=1.665in; y2=26.67mm; thickness=20.0mil; clearance=0.0; + } + ha:line.1207 { + x1=1.665in; y1=26.67mm; x2=1.665in; y2=1.12in; thickness=20.0mil; clearance=0.0; + } + ha:line.1210 { + x1=1.665in; y1=1.12in; x2=1.65in; y2=1.12in; thickness=20.0mil; clearance=0.0; + } + ha:line.1213 { + x1=1.65in; y1=1.12in; x2=1.65in; y2=31.623mm; thickness=20.0mil; clearance=0.0; + } + ha:text.1216 { + string=%a.parent.refdes%; x=40.005mm; y=27.813mm; scale=100; fid=0; + ha:flags { + dyntext=1 + floater=1 + } + rot = 90.000000 + } + } + ha:type { + silk = 1 + top = 1 + } + } + + ha:subc-aux { + lid=1 + ha:combining { } + + li:objects { + ha:line.1217 { + x1=46.99mm; y1=1.6325in; x2=46.99mm; y2=1.6325in; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=pnp-origin + } + } + ha:line.1220 { + x1=46.99mm; y1=1.8in; x2=46.99mm; y2=1.8in; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=origin + } + } + ha:line.1223 { + x1=46.99mm; y1=1.8in; x2=46.99mm; y2=46.72mm; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=x + } + } + ha:line.1226 { + x1=46.99mm; y1=1.8in; x2=47.99mm; y2=1.8in; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=y + } + } + } + ha:type { + top = 1 + misc = 1 + virtual = 1 + } + } + } + } + uid = 2YrIDHgdUiD93dfM91oAAAAJ + } + ha:subc.1234 { + ha:attributes { + value=acy200 + footprint=rcy(200) + refdes=C3 + } + ha:data { + li:padstack_prototypes { + + ha:ps_proto_v6.0 { + hdia=0.999998mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + li:ps_poly { + -40.0mil + -40.0mil + 40.0mil + -40.0mil + 40.0mil + 40.0mil + -40.0mil + 40.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + li:ps_poly { + -40.0mil + -40.0mil + 40.0mil + -40.0mil + 40.0mil + 40.0mil + -40.0mil + 40.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + li:ps_poly { + -40.0mil + -40.0mil + 40.0mil + -40.0mil + 40.0mil + 40.0mil + -40.0mil + 40.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { sub=1; auto=1; } + ha:layer_mask { + top = 1 + mask = 1 + } + clearance=0.0 + li:ps_poly { + -43.0mil + -43.0mil + 43.0mil + -43.0mil + 43.0mil + 43.0mil + -43.0mil + 43.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { sub=1; auto=1; } + ha:layer_mask { + bottom = 1 + mask = 1 + } + clearance=0.0 + li:ps_poly { + -43.0mil + -43.0mil + 43.0mil + -43.0mil + 43.0mil + 43.0mil + -43.0mil + 43.0mil + } + } + } + } + + ha:ps_proto_v6.1 { + hdia=0.999998mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=80.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=80.0mil; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=80.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=86.0mil; } + ha:combining { sub=1; auto=1; } + ha:layer_mask { + top = 1 + mask = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=86.0mil; } + ha:combining { sub=1; auto=1; } + ha:layer_mask { + bottom = 1 + mask = 1 + } + clearance=0.0 + } + } + } + } + + li:objects { + ha:padstack_ref.1258 { + proto=0; x=31.75mm; y=1.525in; rot=0.000000; xmirror=0; smirror=0; clearance=25.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + + ha:attributes { + term=1 + } + } + ha:padstack_ref.1259 { + proto=1; x=36.83mm; y=1.525in; rot=0.000000; xmirror=0; smirror=0; clearance=25.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + + ha:attributes { + term=2 + } + } + } + li:layers { + + ha:top-silk { + lid=0 + ha:combining { } + + li:objects { + ha:line.1235 { + x1=1.57in; y1=1.525in; x2=1.61in; y2=1.525in; thickness=10.0mil; clearance=0.0; + } + ha:line.1238 { + x1=1.09in; y1=1.525in; x2=1.13in; y2=1.525in; thickness=10.0mil; clearance=0.0; + } + ha:line.1241 { + x1=1.11in; y1=1.505in; x2=1.11in; y2=39.243mm; thickness=10.0mil; clearance=0.0; + } + ha:arc.1244 { + x=1.35in; y=1.525in; width=200.0mil; height=200.0mil; astart=0; adelta=360; thickness=10.0mil; clearance=0.0; + } + ha:text.1245 { + string=%a.parent.refdes%; x=1.31in; y=31.242mm; scale=100; fid=0; + ha:flags { + dyntext=1 + floater=1 + } + rot = 0.000000 + } + } + ha:type { + silk = 1 + top = 1 + } + } + + ha:subc-aux { + lid=1 + ha:combining { } + + li:objects { + ha:line.1246 { + x1=1.35in; y1=1.525in; x2=1.35in; y2=1.525in; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=pnp-origin + } + } + ha:line.1249 { + x1=31.75mm; y1=1.525in; x2=31.75mm; y2=1.525in; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=origin + } + } + ha:line.1252 { + x1=31.75mm; y1=1.525in; x2=32.75mm; y2=1.525in; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=x + } + } + ha:line.1255 { + x1=31.75mm; y1=1.525in; x2=31.75mm; y2=39.735mm; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=y + } + } + } + ha:type { + top = 1 + misc = 1 + virtual = 1 + } + } + } + } + uid = 2YrIDHgdUiD93dfM91oAAAAL + } + ha:subc.1261 { + ha:attributes { + value=1*2 + footprint=connector(1,2) + refdes=J1 + } + ha:data { + li:padstack_prototypes { + + ha:ps_proto_v6.0 { + hdia=0.999998mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + li:ps_poly { + -40.0mil + -40.0mil + 40.0mil + -40.0mil + 40.0mil + 40.0mil + -40.0mil + 40.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + li:ps_poly { + -40.0mil + -40.0mil + 40.0mil + -40.0mil + 40.0mil + 40.0mil + -40.0mil + 40.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + li:ps_poly { + -40.0mil + -40.0mil + 40.0mil + -40.0mil + 40.0mil + 40.0mil + -40.0mil + 40.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { sub=1; auto=1; } + ha:layer_mask { + top = 1 + mask = 1 + } + clearance=0.0 + li:ps_poly { + -43.0mil + -43.0mil + 43.0mil + -43.0mil + 43.0mil + 43.0mil + -43.0mil + 43.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { sub=1; auto=1; } + ha:layer_mask { + bottom = 1 + mask = 1 + } + clearance=0.0 + li:ps_poly { + -43.0mil + -43.0mil + 43.0mil + -43.0mil + 43.0mil + 43.0mil + -43.0mil + 43.0mil + } + } + } + } + + ha:ps_proto_v6.1 { + hdia=0.999998mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=80.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=80.0mil; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=80.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=86.0mil; } + ha:combining { sub=1; auto=1; } + ha:layer_mask { + top = 1 + mask = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=86.0mil; } + ha:combining { sub=1; auto=1; } + ha:layer_mask { + bottom = 1 + mask = 1 + } + clearance=0.0 + } + } + } + } + + li:objects { + ha:padstack_ref.1293 { + proto=0; x=975.0mil; y=46.355mm; rot=0.000000; xmirror=0; smirror=0; clearance=25.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + + ha:attributes { + term=1 + } + } + ha:padstack_ref.1294 { + proto=1; x=975.0mil; y=48.895mm; rot=0.000000; xmirror=0; smirror=0; clearance=25.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + + ha:attributes { + term=2 + } + } + } + li:layers { + + ha:top-silk { + lid=0 + ha:combining { } + + li:objects { + ha:line.1262 { + x1=925.0mil; y1=45.085mm; x2=925.0mil; y2=1.975in; thickness=10.0mil; clearance=0.0; + } + ha:line.1265 { + x1=925.0mil; y1=45.085mm; x2=26.035mm; y2=45.085mm; thickness=10.0mil; clearance=0.0; + } + ha:line.1268 { + x1=26.035mm; y1=1.975in; x2=925.0mil; y2=1.975in; thickness=10.0mil; clearance=0.0; + } + ha:line.1271 { + x1=26.035mm; y1=1.975in; x2=26.035mm; y2=45.085mm; thickness=10.0mil; clearance=0.0; + } + ha:line.1274 { + x1=925.0mil; y1=47.625mm; x2=26.035mm; y2=47.625mm; thickness=10.0mil; clearance=0.0; + } + ha:line.1277 { + x1=26.035mm; y1=45.085mm; x2=26.035mm; y2=47.625mm; thickness=10.0mil; clearance=0.0; + } + ha:text.1280 { + string=%a.parent.refdes%; x=950.0mil; y=42.545mm; scale=100; fid=0; + ha:flags { + dyntext=1 + floater=1 + } + rot = 0.000000 + } + } + ha:type { + silk = 1 + top = 1 + } + } + + ha:subc-aux { + lid=1 + ha:combining { } + + li:objects { + ha:line.1281 { + x1=975.0mil; y1=47.625mm; x2=975.0mil; y2=47.625mm; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=pnp-origin + } + } + ha:line.1284 { + x1=975.0mil; y1=46.355mm; x2=975.0mil; y2=46.355mm; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=origin + } + } + ha:line.1287 { + x1=975.0mil; y1=46.355mm; x2=975.0mil; y2=45.355mm; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=x + } + } + ha:line.1290 { + x1=975.0mil; y1=46.355mm; x2=23.765mm; y2=46.355mm; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=y + } + } + } + ha:type { + top = 1 + misc = 1 + virtual = 1 + } + } + } + } + uid = 2YrIDHgdUiD93dfM91oAAAAN + } + ha:subc.1296 { + ha:attributes { + value=1*2 + footprint=connector(1,2) + refdes=J2 + } + ha:data { + li:padstack_prototypes { + + ha:ps_proto_v6.0 { + hdia=0.999998mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + li:ps_poly { + -40.0mil + -40.0mil + 40.0mil + -40.0mil + 40.0mil + 40.0mil + -40.0mil + 40.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + li:ps_poly { + -40.0mil + -40.0mil + 40.0mil + -40.0mil + 40.0mil + 40.0mil + -40.0mil + 40.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + li:ps_poly { + -40.0mil + -40.0mil + 40.0mil + -40.0mil + 40.0mil + 40.0mil + -40.0mil + 40.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { sub=1; auto=1; } + ha:layer_mask { + top = 1 + mask = 1 + } + clearance=0.0 + li:ps_poly { + -43.0mil + -43.0mil + 43.0mil + -43.0mil + 43.0mil + 43.0mil + -43.0mil + 43.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { sub=1; auto=1; } + ha:layer_mask { + bottom = 1 + mask = 1 + } + clearance=0.0 + li:ps_poly { + -43.0mil + -43.0mil + 43.0mil + -43.0mil + 43.0mil + 43.0mil + -43.0mil + 43.0mil + } + } + } + } + + ha:ps_proto_v6.1 { + hdia=0.999998mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=80.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=80.0mil; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=80.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=86.0mil; } + ha:combining { sub=1; auto=1; } + ha:layer_mask { + top = 1 + mask = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=86.0mil; } + ha:combining { sub=1; auto=1; } + ha:layer_mask { + bottom = 1 + mask = 1 + } + clearance=0.0 + } + } + } + } + + li:objects { + ha:padstack_ref.1328 { + proto=0; x=60.96mm; y=46.99mm; rot=0.000000; xmirror=0; smirror=0; clearance=25.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + + ha:attributes { + term=1 + } + } + ha:padstack_ref.1329 { + proto=1; x=60.96mm; y=49.53mm; rot=0.000000; xmirror=0; smirror=0; clearance=25.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + + ha:attributes { + term=2 + } + } + } + li:layers { + + ha:top-silk { + lid=0 + ha:combining { } + + li:objects { + ha:line.1297 { + x1=2.35in; y1=1.8in; x2=2.35in; y2=2.0in; thickness=10.0mil; clearance=0.0; + } + ha:line.1300 { + x1=2.35in; y1=1.8in; x2=2.45in; y2=1.8in; thickness=10.0mil; clearance=0.0; + } + ha:line.1303 { + x1=2.45in; y1=2.0in; x2=2.35in; y2=2.0in; thickness=10.0mil; clearance=0.0; + } + ha:line.1306 { + x1=2.45in; y1=2.0in; x2=2.45in; y2=1.8in; thickness=10.0mil; clearance=0.0; + } + ha:line.1309 { + x1=2.35in; y1=1.9in; x2=2.45in; y2=1.9in; thickness=10.0mil; clearance=0.0; + } + ha:line.1312 { + x1=2.45in; y1=1.8in; x2=2.45in; y2=1.9in; thickness=10.0mil; clearance=0.0; + } + ha:text.1315 { + string=%a.parent.refdes%; x=60.325mm; y=43.18mm; scale=100; fid=0; + ha:flags { + dyntext=1 + floater=1 + } + rot = 0.000000 + } + } + ha:type { + silk = 1 + top = 1 + } + } + + ha:subc-aux { + lid=1 + ha:combining { } + + li:objects { + ha:line.1316 { + x1=60.96mm; y1=1.9in; x2=60.96mm; y2=1.9in; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=pnp-origin + } + } + ha:line.1319 { + x1=60.96mm; y1=46.99mm; x2=60.96mm; y2=46.99mm; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=origin + } + } + ha:line.1322 { + x1=60.96mm; y1=46.99mm; x2=60.96mm; y2=45.99mm; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=x + } + } + ha:line.1325 { + x1=60.96mm; y1=46.99mm; x2=59.96mm; y2=46.99mm; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=y + } + } + } + ha:type { + top = 1 + misc = 1 + virtual = 1 + } + } + } + } + uid = 2YrIDHgdUiD93dfM91oAAAAN + } + ha:subc.1331 { + ha:attributes { + value=acy200 + footprint=acy(200) + refdes=C1 + } + ha:data { + li:padstack_prototypes { + + ha:ps_proto_v6.0 { + hdia=0.999998mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + li:ps_poly { + -40.0mil + -40.0mil + 40.0mil + -40.0mil + 40.0mil + 40.0mil + -40.0mil + 40.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + li:ps_poly { + -40.0mil + -40.0mil + 40.0mil + -40.0mil + 40.0mil + 40.0mil + -40.0mil + 40.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + li:ps_poly { + -40.0mil + -40.0mil + 40.0mil + -40.0mil + 40.0mil + 40.0mil + -40.0mil + 40.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { sub=1; auto=1; } + ha:layer_mask { + top = 1 + mask = 1 + } + clearance=0.0 + li:ps_poly { + -43.0mil + -43.0mil + 43.0mil + -43.0mil + 43.0mil + 43.0mil + -43.0mil + 43.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { sub=1; auto=1; } + ha:layer_mask { + bottom = 1 + mask = 1 + } + clearance=0.0 + li:ps_poly { + -43.0mil + -43.0mil + 43.0mil + -43.0mil + 43.0mil + 43.0mil + -43.0mil + 43.0mil + } + } + } + } + + ha:ps_proto_v6.1 { + hdia=0.999998mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=80.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=80.0mil; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=80.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=86.0mil; } + ha:combining { sub=1; auto=1; } + ha:layer_mask { + top = 1 + mask = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=86.0mil; } + ha:combining { sub=1; auto=1; } + ha:layer_mask { + bottom = 1 + mask = 1 + } + clearance=0.0 + } + } + } + } + + li:objects { + ha:padstack_ref.1363 { + proto=0; x=38.1mm; y=53.975mm; rot=0.000000; xmirror=0; smirror=0; clearance=25.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + + ha:attributes { + term=1 + } + } + ha:padstack_ref.1364 { + proto=1; x=43.18mm; y=53.975mm; rot=0.000000; xmirror=0; smirror=0; clearance=25.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + + ha:attributes { + term=2 + } + } + } + li:layers { + + ha:top-silk { + lid=0 + ha:combining { } + + li:objects { + ha:line.1332 { + x1=38.1mm; y1=53.975mm; x2=1.55in; y2=53.975mm; thickness=10.0mil; clearance=0.0; + } + ha:line.1335 { + x1=1.65in; y1=53.975mm; x2=43.18mm; y2=53.975mm; thickness=10.0mil; clearance=0.0; + } + ha:line.1338 { + x1=1.55in; y1=2.10834in; x2=1.55in; y2=54.398164mm; thickness=10.0mil; clearance=0.0; + } + ha:line.1341 { + x1=1.55in; y1=2.10834in; x2=1.65in; y2=2.10834in; thickness=10.0mil; clearance=0.0; + } + ha:line.1344 { + x1=1.65in; y1=54.398164mm; x2=1.55in; y2=54.398164mm; thickness=10.0mil; clearance=0.0; + } + ha:line.1347 { + x1=1.65in; y1=54.398164mm; x2=1.65in; y2=2.10834in; thickness=10.0mil; clearance=0.0; + } + ha:text.1350 { + string=%a.parent.refdes%; x=1.56in; y=50.927mm; scale=100; fid=0; + ha:flags { + dyntext=1 + floater=1 + } + rot = 0.000000 + } + } + ha:type { + silk = 1 + top = 1 + } + } + + ha:subc-aux { + lid=1 + ha:combining { } + + li:objects { + ha:line.1351 { + x1=1.6in; y1=53.975mm; x2=1.6in; y2=53.975mm; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=pnp-origin + } + } + ha:line.1354 { + x1=38.1mm; y1=53.975mm; x2=38.1mm; y2=53.975mm; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=origin + } + } + ha:line.1357 { + x1=38.1mm; y1=53.975mm; x2=39.1mm; y2=53.975mm; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=x + } + } + ha:line.1360 { + x1=38.1mm; y1=53.975mm; x2=38.1mm; y2=54.975mm; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=y + } + } + } + ha:type { + top = 1 + misc = 1 + virtual = 1 + } + } + } + } + uid = 2YrIDHgdUiD93dfM91oAAAAB + } + ha:subc.1366 { + ha:attributes { + value=acy200 + footprint=acy(200) + refdes=C2 + } + ha:data { + li:padstack_prototypes { + + ha:ps_proto_v6.0 { + hdia=0.999998mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + li:ps_poly { + -40.0mil + -40.0mil + 40.0mil + -40.0mil + 40.0mil + 40.0mil + -40.0mil + 40.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + li:ps_poly { + -40.0mil + -40.0mil + 40.0mil + -40.0mil + 40.0mil + 40.0mil + -40.0mil + 40.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + li:ps_poly { + -40.0mil + -40.0mil + 40.0mil + -40.0mil + 40.0mil + 40.0mil + -40.0mil + 40.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { sub=1; auto=1; } + ha:layer_mask { + top = 1 + mask = 1 + } + clearance=0.0 + li:ps_poly { + -43.0mil + -43.0mil + 43.0mil + -43.0mil + 43.0mil + 43.0mil + -43.0mil + 43.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { sub=1; auto=1; } + ha:layer_mask { + bottom = 1 + mask = 1 + } + clearance=0.0 + li:ps_poly { + -43.0mil + -43.0mil + 43.0mil + -43.0mil + 43.0mil + 43.0mil + -43.0mil + 43.0mil + } + } + } + } + + ha:ps_proto_v6.1 { + hdia=0.999998mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=80.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=80.0mil; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=80.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=86.0mil; } + ha:combining { sub=1; auto=1; } + ha:layer_mask { + top = 1 + mask = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=86.0mil; } + ha:combining { sub=1; auto=1; } + ha:layer_mask { + bottom = 1 + mask = 1 + } + clearance=0.0 + } + } + } + } + + li:objects { + ha:padstack_ref.1398 { + proto=0; x=48.895mm; y=53.975mm; rot=0.000000; xmirror=0; smirror=0; clearance=25.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + + ha:attributes { + term=1 + } + } + ha:padstack_ref.1399 { + proto=1; x=53.975mm; y=53.975mm; rot=0.000000; xmirror=0; smirror=0; clearance=25.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + + ha:attributes { + term=2 + } + } + } + li:layers { + + ha:top-silk { + lid=0 + ha:combining { } + + li:objects { + ha:line.1367 { + x1=48.895mm; y1=53.975mm; x2=1.975in; y2=53.975mm; thickness=10.0mil; clearance=0.0; + } + ha:line.1370 { + x1=2.075in; y1=53.975mm; x2=53.975mm; y2=53.975mm; thickness=10.0mil; clearance=0.0; + } + ha:line.1373 { + x1=1.975in; y1=2.10834in; x2=1.975in; y2=54.398164mm; thickness=10.0mil; clearance=0.0; + } + ha:line.1376 { + x1=1.975in; y1=2.10834in; x2=2.075in; y2=2.10834in; thickness=10.0mil; clearance=0.0; + } + ha:line.1379 { + x1=2.075in; y1=54.398164mm; x2=1.975in; y2=54.398164mm; thickness=10.0mil; clearance=0.0; + } + ha:line.1382 { + x1=2.075in; y1=54.398164mm; x2=2.075in; y2=2.10834in; thickness=10.0mil; clearance=0.0; + } + ha:text.1385 { + string=%a.parent.refdes%; x=1.985in; y=50.927mm; scale=100; fid=0; + ha:flags { + dyntext=1 + floater=1 + } + rot = 0.000000 + } + } + ha:type { + silk = 1 + top = 1 + } + } + + ha:subc-aux { + lid=1 + ha:combining { } + + li:objects { + ha:line.1386 { + x1=51.435mm; y1=53.975mm; x2=51.435mm; y2=53.975mm; thickness=0.1mm; clearance=0.0; + ha:flags { + selected=1 + } + + ha:attributes { + subc-role=pnp-origin + } + } + ha:line.1389 { + x1=48.895mm; y1=53.975mm; x2=48.895mm; y2=53.975mm; thickness=0.1mm; clearance=0.0; + ha:flags { + selected=1 + } + + ha:attributes { + subc-role=origin + } + } + ha:line.1392 { + x1=48.895mm; y1=53.975mm; x2=49.895mm; y2=53.975mm; thickness=0.1mm; clearance=0.0; + ha:flags { + selected=1 + } + + ha:attributes { + subc-role=x + } + } + ha:line.1395 { + x1=48.895mm; y1=53.975mm; x2=48.895mm; y2=54.975mm; thickness=0.1mm; clearance=0.0; + ha:flags { + selected=1 + } + + ha:attributes { + subc-role=y + } + } + } + ha:type { + top = 1 + misc = 1 + virtual = 1 + } + } + } + } + uid = 2YrIDHgdUiD93dfM91oAAAAB + } + } + li:layers { + + ha:top-sig { + lid=0 + group=3 + ha:combining { } + + li:objects { + } + color = {#8b2323} + } + + ha:bottom-sig { + lid=1 + group=10 + ha:combining { } + + li:objects { + } + color = {#3a5fcd} + } + + ha:top-gnd { + lid=2 + group=3 + ha:combining { } + + li:objects { + } + color = {#104e8b} + } + + ha:bottom-gnd { + lid=3 + group=10 + ha:combining { } + + li:objects { + } + color = {#cd3700} + } + + ha:int-sig2 { + lid=4 + group=7 + ha:combining { } + + li:objects { + } + color = {#548b54} + } + + ha:int-sig1 { + lid=5 + group=5 + ha:combining { } + + li:objects { + } + color = {#8b7355} + } + + ha:outline { + lid=6 + group=9 + ha:combining { } + + li:objects { + } + color = {#00868b} + } + + ha:bottom-silk { + lid=7 + group=12 + ha:combining { auto=1; } + + li:objects { + } + color = {#000000} + } + + ha:top-silk { + lid=8 + group=1 + ha:combining { auto=1; } + + li:objects { + } + color = {#000000} + } + + ha:top-paste { + lid=9 + group=0 + ha:combining { auto=1; } + + li:objects { + } + color = {#cd00cd} + } + + ha:top-mask { + lid=10 + group=2 + ha:combining { sub=1; auto=1; } + + li:objects { + } + color = {#ff0000} + } + + ha:bottom-mask { + lid=11 + group=11 + ha:combining { sub=1; auto=1; } + + li:objects { + } + color = {#ff0000} + } + + ha:bottom-paste { + lid=12 + group=13 + ha:combining { auto=1; } + + li:objects { + } + color = {#cd00cd} + } + + ha:slot-plated { + lid=13 + group=14 + ha:combining { auto=1; } + + li:objects { + } + color = {#8b7355} + } + + ha:slot-unplated { + lid=14 + group=15 + ha:combining { auto=1; } + + li:objects { + } + color = {#00868b} + } + } + } + + ha:layer_stack { + li:groups { + ha:0 { + name = top_paste + ha:type { top=1; paste=1; } + li:layers { 9; } + } + ha:1 { + name = top_silk + ha:type { silk=1; top=1; } + li:layers { 8; } + } + ha:2 { + name = top_mask + ha:type { top=1; mask=1; } + li:layers { 10; } + } + ha:3 { + name = top_copper + ha:type { copper=1; top=1; } + li:layers { 0; 2; } + } + ha:4 { + name = grp_4 + ha:type { substrate=1; intern=1; } + li:layers { } + } + ha:5 { + name = Intern + ha:type { copper=1; intern=1; } + li:layers { 5; } + } + ha:6 { + name = grp_6 + ha:type { substrate=1; intern=1; } + li:layers { } + } + ha:7 { + name = Intern + ha:type { copper=1; intern=1; } + li:layers { 4; } + } + ha:8 { + name = grp_8 + ha:type { substrate=1; intern=1; } + li:layers { } + } + ha:9 { + name = global_outline + ha:type { boundary=1; } + li:layers { 6; } + purpose = uroute + } + ha:10 { + name = bottom_copper + ha:type { bottom=1; copper=1; } + li:layers { 1; 3; } + } + ha:11 { + name = bottom_mask + ha:type { bottom=1; mask=1; } + li:layers { 11; } + } + ha:12 { + name = bottom_silk + ha:type { silk=1; bottom=1; } + li:layers { 7; } + } + ha:13 { + name = bottom_paste + ha:type { bottom=1; paste=1; } + li:layers { 12; } + } + ha:14 { + name = pmech + ha:type { mech=1; } + li:layers { 13; } + purpose = proute + } + ha:15 { + name = umech + ha:type { mech=1; } + li:layers { 14; } + purpose = uroute + } + } + } + li:pcb-rnd-conf-v1 { + ha:overwrite { + ha:design { + text_font_id = 0 + text_scale = 100 + via_thickness = 2.0000 mm + via_drilling_hole = 31.50 mil + text_thickness = 0 + line_thickness = 10.00 mil + poly_isle_area = 200000000.0 + clearance = 20.00 mil + } + ha:editor { + buffer_number = 0 + draw_grid = false + grids_idx = 4 + grid = 25.00 mil + } + } + } +} Index: tags/2.1.2/doc/tutorials/15_no_sch/step2.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/tutorials/15_no_sch/step2.png =================================================================== --- tags/2.1.2/doc/tutorials/15_no_sch/step2.png (nonexistent) +++ tags/2.1.2/doc/tutorials/15_no_sch/step2.png (revision 24813) Property changes on: tags/2.1.2/doc/tutorials/15_no_sch/step2.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/tutorials/15_no_sch/step3.lht =================================================================== --- tags/2.1.2/doc/tutorials/15_no_sch/step3.lht (nonexistent) +++ tags/2.1.2/doc/tutorials/15_no_sch/step3.lht (revision 24813) @@ -0,0 +1,2154 @@ +ha:pcb-rnd-board-v6 { + + ha:attributes { + {PCB::grid::unit}=mil + } + + li:styles { + ha:Signal { + diameter = 2.0mm + text_scale = 0 + text_thick = 0.0 + thickness = 10.0mil + hole = 31.5mil + clearance = 20.0mil + } + ha:Power { + diameter = 2.2mm + text_scale = 0 + text_thick = 0.0 + thickness = 20.0mil + hole = 1.0mm + clearance = 20.0mil + } + ha:Fat { + diameter = 137.8mil + text_scale = 0 + text_thick = 0.0 + thickness = 80.0mil + hole = 47.24mil + clearance = 25.0mil + } + ha:Sig-tight { + diameter = 64.0mil + text_scale = 0 + text_thick = 0.0 + thickness = 10.0mil + hole = 31.5mil + clearance = 12.0mil + } + } + + ha:meta { + ha:size { + thermal_scale = 0.500000 + x = 127.0mm + y = 127.0mm + } + ha:grid { + spacing = 25.0mil + offs_x = 0.0 + offs_y = 0.0 + } + } + + ha:data { + li:padstack_prototypes { + } + + li:objects { + ha:subc.1158 { + ha:attributes { + value=TO220 + footprint=Transistor + refdes=U1 + } + ha:data { + li:padstack_prototypes { + + ha:ps_proto_v6.0 { + hdia=60.0mil; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + li:ps_poly { + -45.0mil + -45.0mil + 45.0mil + -45.0mil + 45.0mil + 45.0mil + -45.0mil + 45.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + li:ps_poly { + -45.0mil + -45.0mil + 45.0mil + -45.0mil + 45.0mil + 45.0mil + -45.0mil + 45.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + li:ps_poly { + -45.0mil + -45.0mil + 45.0mil + -45.0mil + 45.0mil + 45.0mil + -45.0mil + 45.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { sub=1; auto=1; } + ha:layer_mask { + top = 1 + mask = 1 + } + clearance=0.0 + li:ps_poly { + -48.0mil + -48.0mil + 48.0mil + -48.0mil + 48.0mil + 48.0mil + -48.0mil + 48.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { sub=1; auto=1; } + ha:layer_mask { + bottom = 1 + mask = 1 + } + clearance=0.0 + li:ps_poly { + -48.0mil + -48.0mil + 48.0mil + -48.0mil + 48.0mil + 48.0mil + -48.0mil + 48.0mil + } + } + } + } + + ha:ps_proto_v6.1 { + hdia=60.0mil; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=90.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=90.0mil; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=90.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=96.0mil; } + ha:combining { sub=1; auto=1; } + ha:layer_mask { + top = 1 + mask = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=96.0mil; } + ha:combining { sub=1; auto=1; } + ha:layer_mask { + bottom = 1 + mask = 1 + } + clearance=0.0 + } + } + } + + ha:ps_proto_v6.2 { + hdia=130.0mil; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=150.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=150.0mil; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=150.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=156.0mil; } + ha:combining { sub=1; auto=1; } + ha:layer_mask { + top = 1 + mask = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=156.0mil; } + ha:combining { sub=1; auto=1; } + ha:layer_mask { + bottom = 1 + mask = 1 + } + clearance=0.0 + } + } + } + } + + li:objects { + ha:padstack_ref.1229 { + proto=0; x=44.45mm; y=1.8in; rot=0.000000; xmirror=0; smirror=0; clearance=15.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + + ha:attributes { + term=1 + name=1 + } + } + ha:padstack_ref.1230 { + proto=1; x=46.99mm; y=1.8in; rot=0.000000; xmirror=0; smirror=0; clearance=15.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + + ha:attributes { + term=2 + name=2 + } + } + ha:padstack_ref.1231 { + proto=1; x=49.53mm; y=1.8in; rot=0.000000; xmirror=0; smirror=0; clearance=15.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + + ha:attributes { + term=3 + name=3 + } + } + ha:padstack_ref.1232 { + proto=2; x=46.99mm; y=1.13in; rot=0.000000; xmirror=0; smirror=0; clearance=15.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + + ha:attributes { + term=4 + name=4 + } + } + } + li:layers { + + ha:top-silk { + lid=0 + ha:combining { } + + li:objects { + ha:line.1159 { + x1=44.45mm; y1=1.8in; x2=44.45mm; y2=1.62in; thickness=30.0mil; clearance=0.0; + } + ha:line.1162 { + x1=46.99mm; y1=1.8in; x2=46.99mm; y2=1.62in; thickness=30.0mil; clearance=0.0; + } + ha:line.1165 { + x1=49.53mm; y1=1.8in; x2=49.53mm; y2=1.62in; thickness=30.0mil; clearance=0.0; + } + ha:line.1168 { + x1=1.65in; y1=1.62in; x2=52.07mm; y2=1.62in; thickness=20.0mil; clearance=0.0; + } + ha:line.1171 { + x1=52.07mm; y1=1.62in; x2=52.07mm; y2=31.623mm; thickness=20.0mil; clearance=0.0; + } + ha:line.1174 { + x1=52.07mm; y1=31.623mm; x2=1.65in; y2=31.623mm; thickness=20.0mil; clearance=0.0; + } + ha:line.1177 { + x1=1.65in; y1=31.623mm; x2=1.65in; y2=1.62in; thickness=20.0mil; clearance=0.0; + } + ha:line.1180 { + x1=1.65in; y1=31.623mm; x2=52.07mm; y2=31.623mm; thickness=20.0mil; clearance=0.0; + } + ha:line.1183 { + x1=52.07mm; y1=31.623mm; x2=52.07mm; y2=1.12in; thickness=20.0mil; clearance=0.0; + } + ha:line.1186 { + x1=52.07mm; y1=1.12in; x2=51.689mm; y2=1.12in; thickness=20.0mil; clearance=0.0; + } + ha:line.1189 { + x1=51.689mm; y1=1.12in; x2=51.689mm; y2=26.67mm; thickness=20.0mil; clearance=0.0; + } + ha:line.1192 { + x1=51.689mm; y1=26.67mm; x2=52.07mm; y2=26.67mm; thickness=20.0mil; clearance=0.0; + } + ha:line.1195 { + x1=52.07mm; y1=26.67mm; x2=52.07mm; y2=1.01in; thickness=20.0mil; clearance=0.0; + } + ha:line.1198 { + x1=52.07mm; y1=1.01in; x2=1.65in; y2=1.01in; thickness=20.0mil; clearance=0.0; + } + ha:line.1201 { + x1=1.65in; y1=1.01in; x2=1.65in; y2=26.67mm; thickness=20.0mil; clearance=0.0; + } + ha:line.1204 { + x1=1.65in; y1=26.67mm; x2=1.665in; y2=26.67mm; thickness=20.0mil; clearance=0.0; + } + ha:line.1207 { + x1=1.665in; y1=26.67mm; x2=1.665in; y2=1.12in; thickness=20.0mil; clearance=0.0; + } + ha:line.1210 { + x1=1.665in; y1=1.12in; x2=1.65in; y2=1.12in; thickness=20.0mil; clearance=0.0; + } + ha:line.1213 { + x1=1.65in; y1=1.12in; x2=1.65in; y2=31.623mm; thickness=20.0mil; clearance=0.0; + } + ha:text.1216 { + string=%a.parent.refdes%; x=40.005mm; y=27.813mm; scale=100; fid=0; + ha:flags { + dyntext=1 + floater=1 + } + rot = 90.000000 + } + } + ha:type { + silk = 1 + top = 1 + } + } + + ha:subc-aux { + lid=1 + ha:combining { } + + li:objects { + ha:line.1217 { + x1=46.99mm; y1=1.6325in; x2=46.99mm; y2=1.6325in; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=pnp-origin + } + } + ha:line.1220 { + x1=46.99mm; y1=1.8in; x2=46.99mm; y2=1.8in; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=origin + } + } + ha:line.1223 { + x1=46.99mm; y1=1.8in; x2=46.99mm; y2=46.72mm; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=x + } + } + ha:line.1226 { + x1=46.99mm; y1=1.8in; x2=47.99mm; y2=1.8in; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=y + } + } + } + ha:type { + top = 1 + misc = 1 + virtual = 1 + } + } + } + } + uid = 2YrIDHgdUiD93dfM91oAAAAJ + } + ha:subc.1234 { + ha:attributes { + value=acy200 + footprint=rcy(200) + refdes=C3 + } + ha:data { + li:padstack_prototypes { + + ha:ps_proto_v6.0 { + hdia=0.999998mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + li:ps_poly { + -40.0mil + -40.0mil + 40.0mil + -40.0mil + 40.0mil + 40.0mil + -40.0mil + 40.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + li:ps_poly { + -40.0mil + -40.0mil + 40.0mil + -40.0mil + 40.0mil + 40.0mil + -40.0mil + 40.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + li:ps_poly { + -40.0mil + -40.0mil + 40.0mil + -40.0mil + 40.0mil + 40.0mil + -40.0mil + 40.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { sub=1; auto=1; } + ha:layer_mask { + top = 1 + mask = 1 + } + clearance=0.0 + li:ps_poly { + -43.0mil + -43.0mil + 43.0mil + -43.0mil + 43.0mil + 43.0mil + -43.0mil + 43.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { sub=1; auto=1; } + ha:layer_mask { + bottom = 1 + mask = 1 + } + clearance=0.0 + li:ps_poly { + -43.0mil + -43.0mil + 43.0mil + -43.0mil + 43.0mil + 43.0mil + -43.0mil + 43.0mil + } + } + } + } + + ha:ps_proto_v6.1 { + hdia=0.999998mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=80.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=80.0mil; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=80.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=86.0mil; } + ha:combining { sub=1; auto=1; } + ha:layer_mask { + top = 1 + mask = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=86.0mil; } + ha:combining { sub=1; auto=1; } + ha:layer_mask { + bottom = 1 + mask = 1 + } + clearance=0.0 + } + } + } + } + + li:objects { + ha:padstack_ref.1258 { + proto=0; x=31.75mm; y=1.525in; rot=0.000000; xmirror=0; smirror=0; clearance=25.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + + ha:attributes { + term=1 + } + } + ha:padstack_ref.1259 { + proto=1; x=36.83mm; y=1.525in; rot=0.000000; xmirror=0; smirror=0; clearance=25.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + + ha:attributes { + term=2 + } + } + } + li:layers { + + ha:top-silk { + lid=0 + ha:combining { } + + li:objects { + ha:line.1235 { + x1=1.57in; y1=1.525in; x2=1.61in; y2=1.525in; thickness=10.0mil; clearance=0.0; + } + ha:line.1238 { + x1=1.09in; y1=1.525in; x2=1.13in; y2=1.525in; thickness=10.0mil; clearance=0.0; + } + ha:line.1241 { + x1=1.11in; y1=1.505in; x2=1.11in; y2=39.243mm; thickness=10.0mil; clearance=0.0; + } + ha:arc.1244 { + x=1.35in; y=1.525in; width=200.0mil; height=200.0mil; astart=0; adelta=360; thickness=10.0mil; clearance=0.0; + } + ha:text.1245 { + string=%a.parent.refdes%; x=1.31in; y=31.242mm; scale=100; fid=0; + ha:flags { + dyntext=1 + floater=1 + } + rot = 0.000000 + } + } + ha:type { + silk = 1 + top = 1 + } + } + + ha:subc-aux { + lid=1 + ha:combining { } + + li:objects { + ha:line.1246 { + x1=1.35in; y1=1.525in; x2=1.35in; y2=1.525in; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=pnp-origin + } + } + ha:line.1249 { + x1=31.75mm; y1=1.525in; x2=31.75mm; y2=1.525in; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=origin + } + } + ha:line.1252 { + x1=31.75mm; y1=1.525in; x2=32.75mm; y2=1.525in; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=x + } + } + ha:line.1255 { + x1=31.75mm; y1=1.525in; x2=31.75mm; y2=39.735mm; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=y + } + } + } + ha:type { + top = 1 + misc = 1 + virtual = 1 + } + } + } + } + uid = 2YrIDHgdUiD93dfM91oAAAAL + } + ha:subc.1261 { + ha:attributes { + value=1*2 + footprint=connector(1,2) + refdes=J1 + } + ha:data { + li:padstack_prototypes { + + ha:ps_proto_v6.0 { + hdia=0.999998mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + li:ps_poly { + -40.0mil + -40.0mil + 40.0mil + -40.0mil + 40.0mil + 40.0mil + -40.0mil + 40.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + li:ps_poly { + -40.0mil + -40.0mil + 40.0mil + -40.0mil + 40.0mil + 40.0mil + -40.0mil + 40.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + li:ps_poly { + -40.0mil + -40.0mil + 40.0mil + -40.0mil + 40.0mil + 40.0mil + -40.0mil + 40.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { sub=1; auto=1; } + ha:layer_mask { + top = 1 + mask = 1 + } + clearance=0.0 + li:ps_poly { + -43.0mil + -43.0mil + 43.0mil + -43.0mil + 43.0mil + 43.0mil + -43.0mil + 43.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { sub=1; auto=1; } + ha:layer_mask { + bottom = 1 + mask = 1 + } + clearance=0.0 + li:ps_poly { + -43.0mil + -43.0mil + 43.0mil + -43.0mil + 43.0mil + 43.0mil + -43.0mil + 43.0mil + } + } + } + } + + ha:ps_proto_v6.1 { + hdia=0.999998mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=80.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=80.0mil; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=80.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=86.0mil; } + ha:combining { sub=1; auto=1; } + ha:layer_mask { + top = 1 + mask = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=86.0mil; } + ha:combining { sub=1; auto=1; } + ha:layer_mask { + bottom = 1 + mask = 1 + } + clearance=0.0 + } + } + } + } + + li:objects { + ha:padstack_ref.1293 { + proto=0; x=975.0mil; y=46.355mm; rot=0.000000; xmirror=0; smirror=0; clearance=25.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + + ha:attributes { + term=1 + } + } + ha:padstack_ref.1294 { + proto=1; x=975.0mil; y=48.895mm; rot=0.000000; xmirror=0; smirror=0; clearance=25.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + + ha:attributes { + term=2 + } + } + } + li:layers { + + ha:top-silk { + lid=0 + ha:combining { } + + li:objects { + ha:line.1262 { + x1=925.0mil; y1=45.085mm; x2=925.0mil; y2=1.975in; thickness=10.0mil; clearance=0.0; + } + ha:line.1265 { + x1=925.0mil; y1=45.085mm; x2=26.035mm; y2=45.085mm; thickness=10.0mil; clearance=0.0; + } + ha:line.1268 { + x1=26.035mm; y1=1.975in; x2=925.0mil; y2=1.975in; thickness=10.0mil; clearance=0.0; + } + ha:line.1271 { + x1=26.035mm; y1=1.975in; x2=26.035mm; y2=45.085mm; thickness=10.0mil; clearance=0.0; + } + ha:line.1274 { + x1=925.0mil; y1=47.625mm; x2=26.035mm; y2=47.625mm; thickness=10.0mil; clearance=0.0; + } + ha:line.1277 { + x1=26.035mm; y1=45.085mm; x2=26.035mm; y2=47.625mm; thickness=10.0mil; clearance=0.0; + } + ha:text.1280 { + string=%a.parent.refdes%; x=950.0mil; y=42.545mm; scale=100; fid=0; + ha:flags { + dyntext=1 + floater=1 + } + rot = 0.000000 + } + } + ha:type { + silk = 1 + top = 1 + } + } + + ha:subc-aux { + lid=1 + ha:combining { } + + li:objects { + ha:line.1281 { + x1=975.0mil; y1=47.625mm; x2=975.0mil; y2=47.625mm; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=pnp-origin + } + } + ha:line.1284 { + x1=975.0mil; y1=46.355mm; x2=975.0mil; y2=46.355mm; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=origin + } + } + ha:line.1287 { + x1=975.0mil; y1=46.355mm; x2=975.0mil; y2=45.355mm; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=x + } + } + ha:line.1290 { + x1=975.0mil; y1=46.355mm; x2=23.765mm; y2=46.355mm; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=y + } + } + } + ha:type { + top = 1 + misc = 1 + virtual = 1 + } + } + } + } + uid = 2YrIDHgdUiD93dfM91oAAAAN + } + ha:subc.1296 { + ha:attributes { + value=1*2 + footprint=connector(1,2) + refdes=J2 + } + ha:data { + li:padstack_prototypes { + + ha:ps_proto_v6.0 { + hdia=0.999998mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + li:ps_poly { + -40.0mil + -40.0mil + 40.0mil + -40.0mil + 40.0mil + 40.0mil + -40.0mil + 40.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + li:ps_poly { + -40.0mil + -40.0mil + 40.0mil + -40.0mil + 40.0mil + 40.0mil + -40.0mil + 40.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + li:ps_poly { + -40.0mil + -40.0mil + 40.0mil + -40.0mil + 40.0mil + 40.0mil + -40.0mil + 40.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { sub=1; auto=1; } + ha:layer_mask { + top = 1 + mask = 1 + } + clearance=0.0 + li:ps_poly { + -43.0mil + -43.0mil + 43.0mil + -43.0mil + 43.0mil + 43.0mil + -43.0mil + 43.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { sub=1; auto=1; } + ha:layer_mask { + bottom = 1 + mask = 1 + } + clearance=0.0 + li:ps_poly { + -43.0mil + -43.0mil + 43.0mil + -43.0mil + 43.0mil + 43.0mil + -43.0mil + 43.0mil + } + } + } + } + + ha:ps_proto_v6.1 { + hdia=0.999998mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=80.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=80.0mil; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=80.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=86.0mil; } + ha:combining { sub=1; auto=1; } + ha:layer_mask { + top = 1 + mask = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=86.0mil; } + ha:combining { sub=1; auto=1; } + ha:layer_mask { + bottom = 1 + mask = 1 + } + clearance=0.0 + } + } + } + } + + li:objects { + ha:padstack_ref.1328 { + proto=0; x=60.96mm; y=46.99mm; rot=0.000000; xmirror=0; smirror=0; clearance=25.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + + ha:attributes { + term=1 + } + } + ha:padstack_ref.1329 { + proto=1; x=60.96mm; y=49.53mm; rot=0.000000; xmirror=0; smirror=0; clearance=25.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + + ha:attributes { + term=2 + } + } + } + li:layers { + + ha:top-silk { + lid=0 + ha:combining { } + + li:objects { + ha:line.1297 { + x1=2.35in; y1=1.8in; x2=2.35in; y2=2.0in; thickness=10.0mil; clearance=0.0; + } + ha:line.1300 { + x1=2.35in; y1=1.8in; x2=2.45in; y2=1.8in; thickness=10.0mil; clearance=0.0; + } + ha:line.1303 { + x1=2.45in; y1=2.0in; x2=2.35in; y2=2.0in; thickness=10.0mil; clearance=0.0; + } + ha:line.1306 { + x1=2.45in; y1=2.0in; x2=2.45in; y2=1.8in; thickness=10.0mil; clearance=0.0; + } + ha:line.1309 { + x1=2.35in; y1=1.9in; x2=2.45in; y2=1.9in; thickness=10.0mil; clearance=0.0; + } + ha:line.1312 { + x1=2.45in; y1=1.8in; x2=2.45in; y2=1.9in; thickness=10.0mil; clearance=0.0; + } + ha:text.1315 { + string=%a.parent.refdes%; x=60.325mm; y=43.18mm; scale=100; fid=0; + ha:flags { + dyntext=1 + floater=1 + } + rot = 0.000000 + } + } + ha:type { + silk = 1 + top = 1 + } + } + + ha:subc-aux { + lid=1 + ha:combining { } + + li:objects { + ha:line.1316 { + x1=60.96mm; y1=1.9in; x2=60.96mm; y2=1.9in; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=pnp-origin + } + } + ha:line.1319 { + x1=60.96mm; y1=46.99mm; x2=60.96mm; y2=46.99mm; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=origin + } + } + ha:line.1322 { + x1=60.96mm; y1=46.99mm; x2=60.96mm; y2=45.99mm; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=x + } + } + ha:line.1325 { + x1=60.96mm; y1=46.99mm; x2=59.96mm; y2=46.99mm; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=y + } + } + } + ha:type { + top = 1 + misc = 1 + virtual = 1 + } + } + } + } + uid = 2YrIDHgdUiD93dfM91oAAAAN + } + ha:subc.1331 { + ha:attributes { + value=acy200 + footprint=acy(200) + refdes=C1 + } + ha:data { + li:padstack_prototypes { + + ha:ps_proto_v6.0 { + hdia=0.999998mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + li:ps_poly { + -40.0mil + -40.0mil + 40.0mil + -40.0mil + 40.0mil + 40.0mil + -40.0mil + 40.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + li:ps_poly { + -40.0mil + -40.0mil + 40.0mil + -40.0mil + 40.0mil + 40.0mil + -40.0mil + 40.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + li:ps_poly { + -40.0mil + -40.0mil + 40.0mil + -40.0mil + 40.0mil + 40.0mil + -40.0mil + 40.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { sub=1; auto=1; } + ha:layer_mask { + top = 1 + mask = 1 + } + clearance=0.0 + li:ps_poly { + -43.0mil + -43.0mil + 43.0mil + -43.0mil + 43.0mil + 43.0mil + -43.0mil + 43.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { sub=1; auto=1; } + ha:layer_mask { + bottom = 1 + mask = 1 + } + clearance=0.0 + li:ps_poly { + -43.0mil + -43.0mil + 43.0mil + -43.0mil + 43.0mil + 43.0mil + -43.0mil + 43.0mil + } + } + } + } + + ha:ps_proto_v6.1 { + hdia=0.999998mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=80.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=80.0mil; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=80.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=86.0mil; } + ha:combining { sub=1; auto=1; } + ha:layer_mask { + top = 1 + mask = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=86.0mil; } + ha:combining { sub=1; auto=1; } + ha:layer_mask { + bottom = 1 + mask = 1 + } + clearance=0.0 + } + } + } + } + + li:objects { + ha:padstack_ref.1363 { + proto=0; x=38.1mm; y=53.975mm; rot=0.000000; xmirror=0; smirror=0; clearance=25.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + + ha:attributes { + term=1 + } + } + ha:padstack_ref.1364 { + proto=1; x=43.18mm; y=53.975mm; rot=0.000000; xmirror=0; smirror=0; clearance=25.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + + ha:attributes { + term=2 + } + } + } + li:layers { + + ha:top-silk { + lid=0 + ha:combining { } + + li:objects { + ha:line.1332 { + x1=38.1mm; y1=53.975mm; x2=1.55in; y2=53.975mm; thickness=10.0mil; clearance=0.0; + } + ha:line.1335 { + x1=1.65in; y1=53.975mm; x2=43.18mm; y2=53.975mm; thickness=10.0mil; clearance=0.0; + } + ha:line.1338 { + x1=1.55in; y1=2.10834in; x2=1.55in; y2=54.398164mm; thickness=10.0mil; clearance=0.0; + } + ha:line.1341 { + x1=1.55in; y1=2.10834in; x2=1.65in; y2=2.10834in; thickness=10.0mil; clearance=0.0; + } + ha:line.1344 { + x1=1.65in; y1=54.398164mm; x2=1.55in; y2=54.398164mm; thickness=10.0mil; clearance=0.0; + } + ha:line.1347 { + x1=1.65in; y1=54.398164mm; x2=1.65in; y2=2.10834in; thickness=10.0mil; clearance=0.0; + } + ha:text.1350 { + string=%a.parent.refdes%; x=1.56in; y=50.927mm; scale=100; fid=0; + ha:flags { + dyntext=1 + floater=1 + } + rot = 0.000000 + } + } + ha:type { + silk = 1 + top = 1 + } + } + + ha:subc-aux { + lid=1 + ha:combining { } + + li:objects { + ha:line.1351 { + x1=1.6in; y1=53.975mm; x2=1.6in; y2=53.975mm; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=pnp-origin + } + } + ha:line.1354 { + x1=38.1mm; y1=53.975mm; x2=38.1mm; y2=53.975mm; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=origin + } + } + ha:line.1357 { + x1=38.1mm; y1=53.975mm; x2=39.1mm; y2=53.975mm; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=x + } + } + ha:line.1360 { + x1=38.1mm; y1=53.975mm; x2=38.1mm; y2=54.975mm; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=y + } + } + } + ha:type { + top = 1 + misc = 1 + virtual = 1 + } + } + } + } + uid = 2YrIDHgdUiD93dfM91oAAAAB + } + ha:subc.1366 { + ha:attributes { + value=acy200 + footprint=acy(200) + refdes=C2 + } + ha:data { + li:padstack_prototypes { + + ha:ps_proto_v6.0 { + hdia=0.999998mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + li:ps_poly { + -40.0mil + -40.0mil + 40.0mil + -40.0mil + 40.0mil + 40.0mil + -40.0mil + 40.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + li:ps_poly { + -40.0mil + -40.0mil + 40.0mil + -40.0mil + 40.0mil + 40.0mil + -40.0mil + 40.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + li:ps_poly { + -40.0mil + -40.0mil + 40.0mil + -40.0mil + 40.0mil + 40.0mil + -40.0mil + 40.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { sub=1; auto=1; } + ha:layer_mask { + top = 1 + mask = 1 + } + clearance=0.0 + li:ps_poly { + -43.0mil + -43.0mil + 43.0mil + -43.0mil + 43.0mil + 43.0mil + -43.0mil + 43.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { sub=1; auto=1; } + ha:layer_mask { + bottom = 1 + mask = 1 + } + clearance=0.0 + li:ps_poly { + -43.0mil + -43.0mil + 43.0mil + -43.0mil + 43.0mil + 43.0mil + -43.0mil + 43.0mil + } + } + } + } + + ha:ps_proto_v6.1 { + hdia=0.999998mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=80.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=80.0mil; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=80.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=86.0mil; } + ha:combining { sub=1; auto=1; } + ha:layer_mask { + top = 1 + mask = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=86.0mil; } + ha:combining { sub=1; auto=1; } + ha:layer_mask { + bottom = 1 + mask = 1 + } + clearance=0.0 + } + } + } + } + + li:objects { + ha:padstack_ref.1398 { + proto=0; x=48.895mm; y=53.975mm; rot=0.000000; xmirror=0; smirror=0; clearance=25.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + + ha:attributes { + term=1 + } + } + ha:padstack_ref.1399 { + proto=1; x=53.975mm; y=53.975mm; rot=0.000000; xmirror=0; smirror=0; clearance=25.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + + ha:attributes { + term=2 + } + } + } + li:layers { + + ha:top-silk { + lid=0 + ha:combining { } + + li:objects { + ha:line.1367 { + x1=48.895mm; y1=53.975mm; x2=1.975in; y2=53.975mm; thickness=10.0mil; clearance=0.0; + } + ha:line.1370 { + x1=2.075in; y1=53.975mm; x2=53.975mm; y2=53.975mm; thickness=10.0mil; clearance=0.0; + } + ha:line.1373 { + x1=1.975in; y1=2.10834in; x2=1.975in; y2=54.398164mm; thickness=10.0mil; clearance=0.0; + } + ha:line.1376 { + x1=1.975in; y1=2.10834in; x2=2.075in; y2=2.10834in; thickness=10.0mil; clearance=0.0; + } + ha:line.1379 { + x1=2.075in; y1=54.398164mm; x2=1.975in; y2=54.398164mm; thickness=10.0mil; clearance=0.0; + } + ha:line.1382 { + x1=2.075in; y1=54.398164mm; x2=2.075in; y2=2.10834in; thickness=10.0mil; clearance=0.0; + } + ha:text.1385 { + string=%a.parent.refdes%; x=1.985in; y=50.927mm; scale=100; fid=0; + ha:flags { + dyntext=1 + floater=1 + } + rot = 0.000000 + } + } + ha:type { + silk = 1 + top = 1 + } + } + + ha:subc-aux { + lid=1 + ha:combining { } + + li:objects { + ha:line.1386 { + x1=51.435mm; y1=53.975mm; x2=51.435mm; y2=53.975mm; thickness=0.1mm; clearance=0.0; + ha:flags { + selected=1 + } + + ha:attributes { + subc-role=pnp-origin + } + } + ha:line.1389 { + x1=48.895mm; y1=53.975mm; x2=48.895mm; y2=53.975mm; thickness=0.1mm; clearance=0.0; + ha:flags { + selected=1 + } + + ha:attributes { + subc-role=origin + } + } + ha:line.1392 { + x1=48.895mm; y1=53.975mm; x2=49.895mm; y2=53.975mm; thickness=0.1mm; clearance=0.0; + ha:flags { + selected=1 + } + + ha:attributes { + subc-role=x + } + } + ha:line.1395 { + x1=48.895mm; y1=53.975mm; x2=48.895mm; y2=54.975mm; thickness=0.1mm; clearance=0.0; + ha:flags { + selected=1 + } + + ha:attributes { + subc-role=y + } + } + } + ha:type { + top = 1 + misc = 1 + virtual = 1 + } + } + } + } + uid = 2YrIDHgdUiD93dfM91oAAAAB + } + ha:rat.1400 { + x1=975.0mil; y1=48.895mm; lgrp1=3; x2=43.18mm; y2=53.975mm; lgrp2=3; + } + ha:rat.1403 { + x1=43.18mm; y1=53.975mm; lgrp1=3; x2=53.975mm; y2=53.975mm; lgrp2=3; + } + ha:rat.1406 { + x1=53.975mm; y1=53.975mm; lgrp1=3; x2=60.96mm; y2=49.53mm; lgrp2=3; + } + ha:rat.1409 { + x1=60.96mm; y1=49.53mm; lgrp1=3; x2=46.99mm; y2=1.8in; lgrp2=3; + } + ha:rat.1412 { + x1=46.99mm; y1=1.8in; lgrp1=3; x2=36.83mm; y2=1.525in; lgrp2=3; + } + ha:rat.1415 { + x1=975.0mil; y1=46.355mm; lgrp1=3; x2=31.75mm; y2=1.525in; lgrp2=3; + } + ha:rat.1418 { + x1=31.75mm; y1=1.525in; lgrp1=3; x2=44.45mm; y2=1.8in; lgrp2=3; + } + ha:rat.1421 { + x1=44.45mm; y1=1.8in; lgrp1=3; x2=38.1mm; y2=53.975mm; lgrp2=3; + } + ha:rat.1424 { + x1=60.96mm; y1=46.99mm; lgrp1=3; x2=49.53mm; y2=1.8in; lgrp2=3; + } + ha:rat.1427 { + x1=49.53mm; y1=1.8in; lgrp1=3; x2=48.895mm; y2=53.975mm; lgrp2=3; + } + } + li:layers { + + ha:top-sig { + lid=0 + group=3 + ha:combining { } + + li:objects { + } + color = {#8b2323} + } + + ha:bottom-sig { + lid=1 + group=10 + ha:combining { } + + li:objects { + } + color = {#3a5fcd} + } + + ha:top-gnd { + lid=2 + group=3 + ha:combining { } + + li:objects { + } + color = {#104e8b} + } + + ha:bottom-gnd { + lid=3 + group=10 + ha:combining { } + + li:objects { + } + color = {#cd3700} + } + + ha:int-sig2 { + lid=4 + group=7 + ha:combining { } + + li:objects { + } + color = {#548b54} + } + + ha:int-sig1 { + lid=5 + group=5 + ha:combining { } + + li:objects { + } + color = {#8b7355} + } + + ha:outline { + lid=6 + group=9 + ha:combining { } + + li:objects { + } + color = {#00868b} + } + + ha:bottom-silk { + lid=7 + group=12 + ha:combining { auto=1; } + + li:objects { + } + color = {#000000} + } + + ha:top-silk { + lid=8 + group=1 + ha:combining { auto=1; } + + li:objects { + } + color = {#000000} + } + + ha:top-paste { + lid=9 + group=0 + ha:combining { auto=1; } + + li:objects { + } + color = {#cd00cd} + } + + ha:top-mask { + lid=10 + group=2 + ha:combining { sub=1; auto=1; } + + li:objects { + } + color = {#ff0000} + } + + ha:bottom-mask { + lid=11 + group=11 + ha:combining { sub=1; auto=1; } + + li:objects { + } + color = {#ff0000} + } + + ha:bottom-paste { + lid=12 + group=13 + ha:combining { auto=1; } + + li:objects { + } + color = {#cd00cd} + } + + ha:slot-plated { + lid=13 + group=14 + ha:combining { auto=1; } + + li:objects { + } + color = {#8b7355} + } + + ha:slot-unplated { + lid=14 + group=15 + ha:combining { auto=1; } + + li:objects { + } + color = {#00868b} + } + } + } + + ha:netlists { + li:netlist_patch { + ha:add_conn { net=gnd; term=J1-2; } + ha:add_conn { net=gnd; term=C1-2; } + ha:add_conn { net=gnd; term=C2-2; } + ha:add_conn { net=gnd; term=J2-2; } + ha:add_conn { net=gnd; term=U1-2; } + ha:add_conn { net=gnd; term=C3-2; } + ha:add_conn { net=in; term=J1-1; } + ha:add_conn { net=in; term=C3-1; } + ha:add_conn { net=in; term=U1-1; } + ha:add_conn { net=in; term=C1-1; } + ha:add_conn { net=out; term=J2-1; } + ha:add_conn { net=out; term=U1-3; } + ha:add_conn { net=out; term=C2-1; } + } + } + ha:layer_stack { + li:groups { + ha:0 { + name = top_paste + ha:type { top=1; paste=1; } + li:layers { 9; } + } + ha:1 { + name = top_silk + ha:type { silk=1; top=1; } + li:layers { 8; } + } + ha:2 { + name = top_mask + ha:type { top=1; mask=1; } + li:layers { 10; } + } + ha:3 { + name = top_copper + ha:type { copper=1; top=1; } + li:layers { 0; 2; } + } + ha:4 { + name = grp_4 + ha:type { substrate=1; intern=1; } + li:layers { } + } + ha:5 { + name = Intern + ha:type { copper=1; intern=1; } + li:layers { 5; } + } + ha:6 { + name = grp_6 + ha:type { substrate=1; intern=1; } + li:layers { } + } + ha:7 { + name = Intern + ha:type { copper=1; intern=1; } + li:layers { 4; } + } + ha:8 { + name = grp_8 + ha:type { substrate=1; intern=1; } + li:layers { } + } + ha:9 { + name = global_outline + ha:type { boundary=1; } + li:layers { 6; } + purpose = uroute + } + ha:10 { + name = bottom_copper + ha:type { bottom=1; copper=1; } + li:layers { 1; 3; } + } + ha:11 { + name = bottom_mask + ha:type { bottom=1; mask=1; } + li:layers { 11; } + } + ha:12 { + name = bottom_silk + ha:type { silk=1; bottom=1; } + li:layers { 7; } + } + ha:13 { + name = bottom_paste + ha:type { bottom=1; paste=1; } + li:layers { 12; } + } + ha:14 { + name = pmech + ha:type { mech=1; } + li:layers { 13; } + purpose = proute + } + ha:15 { + name = umech + ha:type { mech=1; } + li:layers { 14; } + purpose = uroute + } + } + } + li:pcb-rnd-conf-v1 { + ha:overwrite { + ha:design { + text_font_id = 0 + text_scale = 100 + via_thickness = 2.0000 mm + via_drilling_hole = 31.50 mil + text_thickness = 0 + line_thickness = 10.00 mil + poly_isle_area = 200000000.0 + clearance = 20.00 mil + } + ha:editor { + buffer_number = 0 + draw_grid = false + grids_idx = 4 + grid = 25.00 mil + } + } + } +} Index: tags/2.1.2/doc/tutorials/15_no_sch/step3a.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/tutorials/15_no_sch/step3a.png =================================================================== --- tags/2.1.2/doc/tutorials/15_no_sch/step3a.png (nonexistent) +++ tags/2.1.2/doc/tutorials/15_no_sch/step3a.png (revision 24813) Property changes on: tags/2.1.2/doc/tutorials/15_no_sch/step3a.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/tutorials/15_no_sch/step3b.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/tutorials/15_no_sch/step3b.png =================================================================== --- tags/2.1.2/doc/tutorials/15_no_sch/step3b.png (nonexistent) +++ tags/2.1.2/doc/tutorials/15_no_sch/step3b.png (revision 24813) Property changes on: tags/2.1.2/doc/tutorials/15_no_sch/step3b.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/tutorials/15_no_sch/step4.lht =================================================================== --- tags/2.1.2/doc/tutorials/15_no_sch/step4.lht (nonexistent) +++ tags/2.1.2/doc/tutorials/15_no_sch/step4.lht (revision 24813) @@ -0,0 +1,2235 @@ +ha:pcb-rnd-board-v6 { + + ha:attributes { + {PCB::grid::unit}=mil + } + + li:styles { + ha:Signal { + diameter = 2.0mm + text_scale = 0 + text_thick = 0.0 + thickness = 10.0mil + hole = 31.5mil + clearance = 20.0mil + } + ha:Power { + diameter = 2.2mm + text_scale = 0 + text_thick = 0.0 + thickness = 20.0mil + hole = 1.0mm + clearance = 20.0mil + } + ha:Fat { + diameter = 137.8mil + text_scale = 0 + text_thick = 0.0 + thickness = 80.0mil + hole = 47.24mil + clearance = 25.0mil + } + ha:Sig-tight { + diameter = 64.0mil + text_scale = 0 + text_thick = 0.0 + thickness = 10.0mil + hole = 31.5mil + clearance = 12.0mil + } + } + + ha:meta { + ha:size { + thermal_scale = 0.500000 + x = 127.0mm + y = 127.0mm + } + ha:grid { + spacing = 25.0mil + offs_x = 0.0 + offs_y = 0.0 + } + } + + ha:data { + li:padstack_prototypes { + } + + li:objects { + ha:subc.1158 { + ha:attributes { + value=TO220 + footprint=Transistor + refdes=U1 + } + ha:data { + li:padstack_prototypes { + + ha:ps_proto_v6.0 { + hdia=60.0mil; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + li:ps_poly { + -45.0mil + -45.0mil + 45.0mil + -45.0mil + 45.0mil + 45.0mil + -45.0mil + 45.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + li:ps_poly { + -45.0mil + -45.0mil + 45.0mil + -45.0mil + 45.0mil + 45.0mil + -45.0mil + 45.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + li:ps_poly { + -45.0mil + -45.0mil + 45.0mil + -45.0mil + 45.0mil + 45.0mil + -45.0mil + 45.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { sub=1; auto=1; } + ha:layer_mask { + top = 1 + mask = 1 + } + clearance=0.0 + li:ps_poly { + -48.0mil + -48.0mil + 48.0mil + -48.0mil + 48.0mil + 48.0mil + -48.0mil + 48.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { sub=1; auto=1; } + ha:layer_mask { + bottom = 1 + mask = 1 + } + clearance=0.0 + li:ps_poly { + -48.0mil + -48.0mil + 48.0mil + -48.0mil + 48.0mil + 48.0mil + -48.0mil + 48.0mil + } + } + } + } + + ha:ps_proto_v6.1 { + hdia=60.0mil; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=90.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=90.0mil; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=90.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=96.0mil; } + ha:combining { sub=1; auto=1; } + ha:layer_mask { + top = 1 + mask = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=96.0mil; } + ha:combining { sub=1; auto=1; } + ha:layer_mask { + bottom = 1 + mask = 1 + } + clearance=0.0 + } + } + } + + ha:ps_proto_v6.2 { + hdia=130.0mil; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=150.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=150.0mil; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=150.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=156.0mil; } + ha:combining { sub=1; auto=1; } + ha:layer_mask { + top = 1 + mask = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=156.0mil; } + ha:combining { sub=1; auto=1; } + ha:layer_mask { + bottom = 1 + mask = 1 + } + clearance=0.0 + } + } + } + } + + li:objects { + ha:padstack_ref.1229 { + proto=0; x=44.45mm; y=1.8in; rot=0.000000; xmirror=0; smirror=0; clearance=15.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + + ha:attributes { + term=1 + name=1 + } + } + ha:padstack_ref.1230 { + proto=1; x=46.99mm; y=1.8in; rot=0.000000; xmirror=0; smirror=0; clearance=15.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + li:3 { + on + diag + round + noshape + } + } + + ha:attributes { + term=2 + name=2 + } + } + ha:padstack_ref.1231 { + proto=1; x=49.53mm; y=1.8in; rot=0.000000; xmirror=0; smirror=0; clearance=15.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + + ha:attributes { + term=3 + name=3 + } + } + ha:padstack_ref.1232 { + proto=2; x=46.99mm; y=1.13in; rot=0.000000; xmirror=0; smirror=0; clearance=15.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + + ha:attributes { + term=4 + name=4 + } + } + } + li:layers { + + ha:top-silk { + lid=0 + ha:combining { } + + li:objects { + ha:line.1159 { + x1=44.45mm; y1=1.8in; x2=44.45mm; y2=1.62in; thickness=30.0mil; clearance=0.0; + } + ha:line.1162 { + x1=46.99mm; y1=1.8in; x2=46.99mm; y2=1.62in; thickness=30.0mil; clearance=0.0; + } + ha:line.1165 { + x1=49.53mm; y1=1.8in; x2=49.53mm; y2=1.62in; thickness=30.0mil; clearance=0.0; + } + ha:line.1168 { + x1=1.65in; y1=1.62in; x2=52.07mm; y2=1.62in; thickness=20.0mil; clearance=0.0; + } + ha:line.1171 { + x1=52.07mm; y1=1.62in; x2=52.07mm; y2=31.623mm; thickness=20.0mil; clearance=0.0; + } + ha:line.1174 { + x1=52.07mm; y1=31.623mm; x2=1.65in; y2=31.623mm; thickness=20.0mil; clearance=0.0; + } + ha:line.1177 { + x1=1.65in; y1=31.623mm; x2=1.65in; y2=1.62in; thickness=20.0mil; clearance=0.0; + } + ha:line.1180 { + x1=1.65in; y1=31.623mm; x2=52.07mm; y2=31.623mm; thickness=20.0mil; clearance=0.0; + } + ha:line.1183 { + x1=52.07mm; y1=31.623mm; x2=52.07mm; y2=1.12in; thickness=20.0mil; clearance=0.0; + } + ha:line.1186 { + x1=52.07mm; y1=1.12in; x2=51.689mm; y2=1.12in; thickness=20.0mil; clearance=0.0; + } + ha:line.1189 { + x1=51.689mm; y1=1.12in; x2=51.689mm; y2=26.67mm; thickness=20.0mil; clearance=0.0; + } + ha:line.1192 { + x1=51.689mm; y1=26.67mm; x2=52.07mm; y2=26.67mm; thickness=20.0mil; clearance=0.0; + } + ha:line.1195 { + x1=52.07mm; y1=26.67mm; x2=52.07mm; y2=1.01in; thickness=20.0mil; clearance=0.0; + } + ha:line.1198 { + x1=52.07mm; y1=1.01in; x2=1.65in; y2=1.01in; thickness=20.0mil; clearance=0.0; + } + ha:line.1201 { + x1=1.65in; y1=1.01in; x2=1.65in; y2=26.67mm; thickness=20.0mil; clearance=0.0; + } + ha:line.1204 { + x1=1.65in; y1=26.67mm; x2=1.665in; y2=26.67mm; thickness=20.0mil; clearance=0.0; + } + ha:line.1207 { + x1=1.665in; y1=26.67mm; x2=1.665in; y2=1.12in; thickness=20.0mil; clearance=0.0; + } + ha:line.1210 { + x1=1.665in; y1=1.12in; x2=1.65in; y2=1.12in; thickness=20.0mil; clearance=0.0; + } + ha:line.1213 { + x1=1.65in; y1=1.12in; x2=1.65in; y2=31.623mm; thickness=20.0mil; clearance=0.0; + } + ha:text.1216 { + string=%a.parent.refdes%; x=40.005mm; y=27.813mm; scale=100; fid=0; + ha:flags { + dyntext=1 + floater=1 + } + rot = 90.000000 + } + } + ha:type { + silk = 1 + top = 1 + } + } + + ha:subc-aux { + lid=1 + ha:combining { } + + li:objects { + ha:line.1217 { + x1=46.99mm; y1=1.6325in; x2=46.99mm; y2=1.6325in; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=pnp-origin + } + } + ha:line.1220 { + x1=46.99mm; y1=1.8in; x2=46.99mm; y2=1.8in; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=origin + } + } + ha:line.1223 { + x1=46.99mm; y1=1.8in; x2=46.99mm; y2=46.72mm; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=x + } + } + ha:line.1226 { + x1=46.99mm; y1=1.8in; x2=47.99mm; y2=1.8in; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=y + } + } + } + ha:type { + top = 1 + misc = 1 + virtual = 1 + } + } + } + } + uid = 2YrIDHgdUiD93dfM91oAAAAJ + } + ha:subc.1234 { + ha:attributes { + value=acy200 + footprint=rcy(200) + refdes=C3 + } + ha:data { + li:padstack_prototypes { + + ha:ps_proto_v6.0 { + hdia=0.999998mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + li:ps_poly { + -40.0mil + -40.0mil + 40.0mil + -40.0mil + 40.0mil + 40.0mil + -40.0mil + 40.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + li:ps_poly { + -40.0mil + -40.0mil + 40.0mil + -40.0mil + 40.0mil + 40.0mil + -40.0mil + 40.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + li:ps_poly { + -40.0mil + -40.0mil + 40.0mil + -40.0mil + 40.0mil + 40.0mil + -40.0mil + 40.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { sub=1; auto=1; } + ha:layer_mask { + top = 1 + mask = 1 + } + clearance=0.0 + li:ps_poly { + -43.0mil + -43.0mil + 43.0mil + -43.0mil + 43.0mil + 43.0mil + -43.0mil + 43.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { sub=1; auto=1; } + ha:layer_mask { + bottom = 1 + mask = 1 + } + clearance=0.0 + li:ps_poly { + -43.0mil + -43.0mil + 43.0mil + -43.0mil + 43.0mil + 43.0mil + -43.0mil + 43.0mil + } + } + } + } + + ha:ps_proto_v6.1 { + hdia=0.999998mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=80.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=80.0mil; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=80.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=86.0mil; } + ha:combining { sub=1; auto=1; } + ha:layer_mask { + top = 1 + mask = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=86.0mil; } + ha:combining { sub=1; auto=1; } + ha:layer_mask { + bottom = 1 + mask = 1 + } + clearance=0.0 + } + } + } + } + + li:objects { + ha:padstack_ref.1258 { + proto=0; x=31.75mm; y=1.525in; rot=0.000000; xmirror=0; smirror=0; clearance=25.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + + ha:attributes { + term=1 + } + } + ha:padstack_ref.1259 { + proto=1; x=36.83mm; y=1.525in; rot=0.000000; xmirror=0; smirror=0; clearance=25.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + li:3 { + on + diag + round + noshape + } + } + + ha:attributes { + term=2 + } + } + } + li:layers { + + ha:top-silk { + lid=0 + ha:combining { } + + li:objects { + ha:line.1235 { + x1=1.57in; y1=1.525in; x2=1.61in; y2=1.525in; thickness=10.0mil; clearance=0.0; + } + ha:line.1238 { + x1=1.09in; y1=1.525in; x2=1.13in; y2=1.525in; thickness=10.0mil; clearance=0.0; + } + ha:line.1241 { + x1=1.11in; y1=1.505in; x2=1.11in; y2=39.243mm; thickness=10.0mil; clearance=0.0; + } + ha:arc.1244 { + x=1.35in; y=1.525in; width=200.0mil; height=200.0mil; astart=0; adelta=360; thickness=10.0mil; clearance=0.0; + } + ha:text.1245 { + string=%a.parent.refdes%; x=1.31in; y=31.242mm; scale=100; fid=0; + ha:flags { + dyntext=1 + floater=1 + } + rot = 0.000000 + } + } + ha:type { + silk = 1 + top = 1 + } + } + + ha:subc-aux { + lid=1 + ha:combining { } + + li:objects { + ha:line.1246 { + x1=1.35in; y1=1.525in; x2=1.35in; y2=1.525in; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=pnp-origin + } + } + ha:line.1249 { + x1=31.75mm; y1=1.525in; x2=31.75mm; y2=1.525in; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=origin + } + } + ha:line.1252 { + x1=31.75mm; y1=1.525in; x2=32.75mm; y2=1.525in; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=x + } + } + ha:line.1255 { + x1=31.75mm; y1=1.525in; x2=31.75mm; y2=39.735mm; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=y + } + } + } + ha:type { + top = 1 + misc = 1 + virtual = 1 + } + } + } + } + uid = 2YrIDHgdUiD93dfM91oAAAAL + } + ha:subc.1261 { + ha:attributes { + value=1*2 + footprint=connector(1,2) + refdes=J1 + } + ha:data { + li:padstack_prototypes { + + ha:ps_proto_v6.0 { + hdia=0.999998mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + li:ps_poly { + -40.0mil + -40.0mil + 40.0mil + -40.0mil + 40.0mil + 40.0mil + -40.0mil + 40.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + li:ps_poly { + -40.0mil + -40.0mil + 40.0mil + -40.0mil + 40.0mil + 40.0mil + -40.0mil + 40.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + li:ps_poly { + -40.0mil + -40.0mil + 40.0mil + -40.0mil + 40.0mil + 40.0mil + -40.0mil + 40.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { sub=1; auto=1; } + ha:layer_mask { + top = 1 + mask = 1 + } + clearance=0.0 + li:ps_poly { + -43.0mil + -43.0mil + 43.0mil + -43.0mil + 43.0mil + 43.0mil + -43.0mil + 43.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { sub=1; auto=1; } + ha:layer_mask { + bottom = 1 + mask = 1 + } + clearance=0.0 + li:ps_poly { + -43.0mil + -43.0mil + 43.0mil + -43.0mil + 43.0mil + 43.0mil + -43.0mil + 43.0mil + } + } + } + } + + ha:ps_proto_v6.1 { + hdia=0.999998mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=80.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=80.0mil; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=80.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=86.0mil; } + ha:combining { sub=1; auto=1; } + ha:layer_mask { + top = 1 + mask = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=86.0mil; } + ha:combining { sub=1; auto=1; } + ha:layer_mask { + bottom = 1 + mask = 1 + } + clearance=0.0 + } + } + } + } + + li:objects { + ha:padstack_ref.1293 { + proto=0; x=975.0mil; y=46.355mm; rot=0.000000; xmirror=0; smirror=0; clearance=25.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + + ha:attributes { + term=1 + } + } + ha:padstack_ref.1294 { + proto=1; x=975.0mil; y=48.895mm; rot=0.000000; xmirror=0; smirror=0; clearance=25.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + li:3 { + on + round + noshape + } + } + + ha:attributes { + term=2 + } + } + } + li:layers { + + ha:top-silk { + lid=0 + ha:combining { } + + li:objects { + ha:line.1262 { + x1=925.0mil; y1=45.085mm; x2=925.0mil; y2=1.975in; thickness=10.0mil; clearance=0.0; + } + ha:line.1265 { + x1=925.0mil; y1=45.085mm; x2=26.035mm; y2=45.085mm; thickness=10.0mil; clearance=0.0; + } + ha:line.1268 { + x1=26.035mm; y1=1.975in; x2=925.0mil; y2=1.975in; thickness=10.0mil; clearance=0.0; + } + ha:line.1271 { + x1=26.035mm; y1=1.975in; x2=26.035mm; y2=45.085mm; thickness=10.0mil; clearance=0.0; + } + ha:line.1274 { + x1=925.0mil; y1=47.625mm; x2=26.035mm; y2=47.625mm; thickness=10.0mil; clearance=0.0; + } + ha:line.1277 { + x1=26.035mm; y1=45.085mm; x2=26.035mm; y2=47.625mm; thickness=10.0mil; clearance=0.0; + } + ha:text.1280 { + string=%a.parent.refdes%; x=950.0mil; y=42.545mm; scale=100; fid=0; + ha:flags { + dyntext=1 + floater=1 + } + rot = 0.000000 + } + } + ha:type { + silk = 1 + top = 1 + } + } + + ha:subc-aux { + lid=1 + ha:combining { } + + li:objects { + ha:line.1281 { + x1=975.0mil; y1=47.625mm; x2=975.0mil; y2=47.625mm; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=pnp-origin + } + } + ha:line.1284 { + x1=975.0mil; y1=46.355mm; x2=975.0mil; y2=46.355mm; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=origin + } + } + ha:line.1287 { + x1=975.0mil; y1=46.355mm; x2=975.0mil; y2=45.355mm; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=x + } + } + ha:line.1290 { + x1=975.0mil; y1=46.355mm; x2=23.765mm; y2=46.355mm; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=y + } + } + } + ha:type { + top = 1 + misc = 1 + virtual = 1 + } + } + } + } + uid = 2YrIDHgdUiD93dfM91oAAAAN + } + ha:subc.1296 { + ha:attributes { + value=1*2 + footprint=connector(1,2) + refdes=J2 + } + ha:data { + li:padstack_prototypes { + + ha:ps_proto_v6.0 { + hdia=0.999998mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + li:ps_poly { + -40.0mil + -40.0mil + 40.0mil + -40.0mil + 40.0mil + 40.0mil + -40.0mil + 40.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + li:ps_poly { + -40.0mil + -40.0mil + 40.0mil + -40.0mil + 40.0mil + 40.0mil + -40.0mil + 40.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + li:ps_poly { + -40.0mil + -40.0mil + 40.0mil + -40.0mil + 40.0mil + 40.0mil + -40.0mil + 40.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { sub=1; auto=1; } + ha:layer_mask { + top = 1 + mask = 1 + } + clearance=0.0 + li:ps_poly { + -43.0mil + -43.0mil + 43.0mil + -43.0mil + 43.0mil + 43.0mil + -43.0mil + 43.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { sub=1; auto=1; } + ha:layer_mask { + bottom = 1 + mask = 1 + } + clearance=0.0 + li:ps_poly { + -43.0mil + -43.0mil + 43.0mil + -43.0mil + 43.0mil + 43.0mil + -43.0mil + 43.0mil + } + } + } + } + + ha:ps_proto_v6.1 { + hdia=0.999998mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=80.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=80.0mil; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=80.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=86.0mil; } + ha:combining { sub=1; auto=1; } + ha:layer_mask { + top = 1 + mask = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=86.0mil; } + ha:combining { sub=1; auto=1; } + ha:layer_mask { + bottom = 1 + mask = 1 + } + clearance=0.0 + } + } + } + } + + li:objects { + ha:padstack_ref.1328 { + proto=0; x=60.96mm; y=46.99mm; rot=0.000000; xmirror=0; smirror=0; clearance=25.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + + ha:attributes { + term=1 + } + } + ha:padstack_ref.1329 { + proto=1; x=60.96mm; y=49.53mm; rot=0.000000; xmirror=0; smirror=0; clearance=25.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + li:3 { + on + diag + round + noshape + } + } + + ha:attributes { + term=2 + } + } + } + li:layers { + + ha:top-silk { + lid=0 + ha:combining { } + + li:objects { + ha:line.1297 { + x1=2.35in; y1=1.8in; x2=2.35in; y2=2.0in; thickness=10.0mil; clearance=0.0; + } + ha:line.1300 { + x1=2.35in; y1=1.8in; x2=2.45in; y2=1.8in; thickness=10.0mil; clearance=0.0; + } + ha:line.1303 { + x1=2.45in; y1=2.0in; x2=2.35in; y2=2.0in; thickness=10.0mil; clearance=0.0; + } + ha:line.1306 { + x1=2.45in; y1=2.0in; x2=2.45in; y2=1.8in; thickness=10.0mil; clearance=0.0; + } + ha:line.1309 { + x1=2.35in; y1=1.9in; x2=2.45in; y2=1.9in; thickness=10.0mil; clearance=0.0; + } + ha:line.1312 { + x1=2.45in; y1=1.8in; x2=2.45in; y2=1.9in; thickness=10.0mil; clearance=0.0; + } + ha:text.1315 { + string=%a.parent.refdes%; x=60.325mm; y=43.18mm; scale=100; fid=0; + ha:flags { + dyntext=1 + floater=1 + } + rot = 0.000000 + } + } + ha:type { + silk = 1 + top = 1 + } + } + + ha:subc-aux { + lid=1 + ha:combining { } + + li:objects { + ha:line.1316 { + x1=60.96mm; y1=1.9in; x2=60.96mm; y2=1.9in; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=pnp-origin + } + } + ha:line.1319 { + x1=60.96mm; y1=46.99mm; x2=60.96mm; y2=46.99mm; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=origin + } + } + ha:line.1322 { + x1=60.96mm; y1=46.99mm; x2=60.96mm; y2=45.99mm; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=x + } + } + ha:line.1325 { + x1=60.96mm; y1=46.99mm; x2=59.96mm; y2=46.99mm; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=y + } + } + } + ha:type { + top = 1 + misc = 1 + virtual = 1 + } + } + } + } + uid = 2YrIDHgdUiD93dfM91oAAAAN + } + ha:subc.1331 { + ha:attributes { + value=acy200 + footprint=acy(200) + refdes=C1 + } + ha:data { + li:padstack_prototypes { + + ha:ps_proto_v6.0 { + hdia=0.999998mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + li:ps_poly { + -40.0mil + -40.0mil + 40.0mil + -40.0mil + 40.0mil + 40.0mil + -40.0mil + 40.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + li:ps_poly { + -40.0mil + -40.0mil + 40.0mil + -40.0mil + 40.0mil + 40.0mil + -40.0mil + 40.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + li:ps_poly { + -40.0mil + -40.0mil + 40.0mil + -40.0mil + 40.0mil + 40.0mil + -40.0mil + 40.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { sub=1; auto=1; } + ha:layer_mask { + top = 1 + mask = 1 + } + clearance=0.0 + li:ps_poly { + -43.0mil + -43.0mil + 43.0mil + -43.0mil + 43.0mil + 43.0mil + -43.0mil + 43.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { sub=1; auto=1; } + ha:layer_mask { + bottom = 1 + mask = 1 + } + clearance=0.0 + li:ps_poly { + -43.0mil + -43.0mil + 43.0mil + -43.0mil + 43.0mil + 43.0mil + -43.0mil + 43.0mil + } + } + } + } + + ha:ps_proto_v6.1 { + hdia=0.999998mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=80.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=80.0mil; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=80.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=86.0mil; } + ha:combining { sub=1; auto=1; } + ha:layer_mask { + top = 1 + mask = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=86.0mil; } + ha:combining { sub=1; auto=1; } + ha:layer_mask { + bottom = 1 + mask = 1 + } + clearance=0.0 + } + } + } + } + + li:objects { + ha:padstack_ref.1363 { + proto=0; x=38.1mm; y=53.975mm; rot=0.000000; xmirror=0; smirror=0; clearance=25.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + + ha:attributes { + term=1 + } + } + ha:padstack_ref.1364 { + proto=1; x=43.18mm; y=53.975mm; rot=0.000000; xmirror=0; smirror=0; clearance=25.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + li:3 { + on + diag + round + noshape + } + } + + ha:attributes { + term=2 + } + } + } + li:layers { + + ha:top-silk { + lid=0 + ha:combining { } + + li:objects { + ha:line.1332 { + x1=38.1mm; y1=53.975mm; x2=1.55in; y2=53.975mm; thickness=10.0mil; clearance=0.0; + } + ha:line.1335 { + x1=1.65in; y1=53.975mm; x2=43.18mm; y2=53.975mm; thickness=10.0mil; clearance=0.0; + } + ha:line.1338 { + x1=1.55in; y1=2.10834in; x2=1.55in; y2=54.398164mm; thickness=10.0mil; clearance=0.0; + } + ha:line.1341 { + x1=1.55in; y1=2.10834in; x2=1.65in; y2=2.10834in; thickness=10.0mil; clearance=0.0; + } + ha:line.1344 { + x1=1.65in; y1=54.398164mm; x2=1.55in; y2=54.398164mm; thickness=10.0mil; clearance=0.0; + } + ha:line.1347 { + x1=1.65in; y1=54.398164mm; x2=1.65in; y2=2.10834in; thickness=10.0mil; clearance=0.0; + } + ha:text.1350 { + string=%a.parent.refdes%; x=1.56in; y=50.927mm; scale=100; fid=0; + ha:flags { + dyntext=1 + floater=1 + } + rot = 0.000000 + } + } + ha:type { + silk = 1 + top = 1 + } + } + + ha:subc-aux { + lid=1 + ha:combining { } + + li:objects { + ha:line.1351 { + x1=1.6in; y1=53.975mm; x2=1.6in; y2=53.975mm; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=pnp-origin + } + } + ha:line.1354 { + x1=38.1mm; y1=53.975mm; x2=38.1mm; y2=53.975mm; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=origin + } + } + ha:line.1357 { + x1=38.1mm; y1=53.975mm; x2=39.1mm; y2=53.975mm; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=x + } + } + ha:line.1360 { + x1=38.1mm; y1=53.975mm; x2=38.1mm; y2=54.975mm; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=y + } + } + } + ha:type { + top = 1 + misc = 1 + virtual = 1 + } + } + } + } + uid = 2YrIDHgdUiD93dfM91oAAAAB + } + ha:subc.1366 { + ha:attributes { + value=acy200 + footprint=acy(200) + refdes=C2 + } + ha:data { + li:padstack_prototypes { + + ha:ps_proto_v6.0 { + hdia=0.999998mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + li:ps_poly { + -40.0mil + -40.0mil + 40.0mil + -40.0mil + 40.0mil + 40.0mil + -40.0mil + 40.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + li:ps_poly { + -40.0mil + -40.0mil + 40.0mil + -40.0mil + 40.0mil + 40.0mil + -40.0mil + 40.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + li:ps_poly { + -40.0mil + -40.0mil + 40.0mil + -40.0mil + 40.0mil + 40.0mil + -40.0mil + 40.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { sub=1; auto=1; } + ha:layer_mask { + top = 1 + mask = 1 + } + clearance=0.0 + li:ps_poly { + -43.0mil + -43.0mil + 43.0mil + -43.0mil + 43.0mil + 43.0mil + -43.0mil + 43.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { sub=1; auto=1; } + ha:layer_mask { + bottom = 1 + mask = 1 + } + clearance=0.0 + li:ps_poly { + -43.0mil + -43.0mil + 43.0mil + -43.0mil + 43.0mil + 43.0mil + -43.0mil + 43.0mil + } + } + } + } + + ha:ps_proto_v6.1 { + hdia=0.999998mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=80.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=80.0mil; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=80.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=86.0mil; } + ha:combining { sub=1; auto=1; } + ha:layer_mask { + top = 1 + mask = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=86.0mil; } + ha:combining { sub=1; auto=1; } + ha:layer_mask { + bottom = 1 + mask = 1 + } + clearance=0.0 + } + } + } + } + + li:objects { + ha:padstack_ref.1398 { + proto=0; x=48.895mm; y=53.975mm; rot=0.000000; xmirror=0; smirror=0; clearance=25.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + + ha:attributes { + term=1 + } + } + ha:padstack_ref.1399 { + proto=1; x=53.975mm; y=53.975mm; rot=0.000000; xmirror=0; smirror=0; clearance=25.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + li:3 { + on + diag + round + noshape + } + } + + ha:attributes { + term=2 + } + } + } + li:layers { + + ha:top-silk { + lid=0 + ha:combining { } + + li:objects { + ha:line.1367 { + x1=48.895mm; y1=53.975mm; x2=1.975in; y2=53.975mm; thickness=10.0mil; clearance=0.0; + } + ha:line.1370 { + x1=2.075in; y1=53.975mm; x2=53.975mm; y2=53.975mm; thickness=10.0mil; clearance=0.0; + } + ha:line.1373 { + x1=1.975in; y1=2.10834in; x2=1.975in; y2=54.398164mm; thickness=10.0mil; clearance=0.0; + } + ha:line.1376 { + x1=1.975in; y1=2.10834in; x2=2.075in; y2=2.10834in; thickness=10.0mil; clearance=0.0; + } + ha:line.1379 { + x1=2.075in; y1=54.398164mm; x2=1.975in; y2=54.398164mm; thickness=10.0mil; clearance=0.0; + } + ha:line.1382 { + x1=2.075in; y1=54.398164mm; x2=2.075in; y2=2.10834in; thickness=10.0mil; clearance=0.0; + } + ha:text.1385 { + string=%a.parent.refdes%; x=1.985in; y=50.927mm; scale=100; fid=0; + ha:flags { + dyntext=1 + floater=1 + } + rot = 0.000000 + } + } + ha:type { + silk = 1 + top = 1 + } + } + + ha:subc-aux { + lid=1 + ha:combining { } + + li:objects { + ha:line.1386 { + x1=51.435mm; y1=53.975mm; x2=51.435mm; y2=53.975mm; thickness=0.1mm; clearance=0.0; + ha:flags { + selected=1 + } + + ha:attributes { + subc-role=pnp-origin + } + } + ha:line.1389 { + x1=48.895mm; y1=53.975mm; x2=48.895mm; y2=53.975mm; thickness=0.1mm; clearance=0.0; + ha:flags { + selected=1 + } + + ha:attributes { + subc-role=origin + } + } + ha:line.1392 { + x1=48.895mm; y1=53.975mm; x2=49.895mm; y2=53.975mm; thickness=0.1mm; clearance=0.0; + ha:flags { + selected=1 + } + + ha:attributes { + subc-role=x + } + } + ha:line.1395 { + x1=48.895mm; y1=53.975mm; x2=48.895mm; y2=54.975mm; thickness=0.1mm; clearance=0.0; + ha:flags { + selected=1 + } + + ha:attributes { + subc-role=y + } + } + } + ha:type { + top = 1 + misc = 1 + virtual = 1 + } + } + } + } + uid = 2YrIDHgdUiD93dfM91oAAAAB + } + ha:rat.1529 { + x1=53.975mm; y1=53.975mm; lgrp1=3; x2=60.96mm; y2=49.53mm; lgrp2=3; + } + ha:rat.1526 { + x1=43.18mm; y1=53.975mm; lgrp1=3; x2=53.975mm; y2=53.975mm; lgrp2=3; + } + ha:rat.1523 { + x1=43.18mm; y1=53.975mm; lgrp1=3; x2=46.99mm; y2=1.8in; lgrp2=3; + } + ha:rat.1520 { + x1=46.99mm; y1=1.8in; lgrp1=3; x2=36.83mm; y2=1.525in; lgrp2=3; + } + ha:rat.1517 { + x1=975.0mil; y1=48.895mm; lgrp1=3; x2=36.83mm; y2=1.525in; lgrp2=3; + } + } + li:layers { + + ha:top-sig { + lid=0 + group=3 + ha:combining { } + + li:objects { + } + color = {#8b2323} + } + + ha:bottom-sig { + lid=1 + group=10 + ha:combining { } + + li:objects { + ha:line.1433 { + x1=1.175in; y1=46.355mm; x2=31.75mm; y2=44.45mm; thickness=20.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1436 { + x1=31.75mm; y1=44.45mm; x2=31.75mm; y2=1.525in; thickness=20.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1472 { + x1=1.375in; y1=46.355mm; x2=38.1mm; y2=49.53mm; thickness=20.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1475 { + x1=38.1mm; y1=49.53mm; x2=38.1mm; y2=53.975mm; thickness=20.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1478 { + x1=975.0mil; y1=46.355mm; x2=1.725in; y2=46.355mm; thickness=20.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1481 { + x1=1.725in; y1=46.355mm; x2=44.45mm; y2=1.8in; thickness=20.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1505 { + x1=49.53mm; y1=1.8in; x2=2.35in; y2=1.8in; thickness=20.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1508 { + x1=2.35in; y1=1.8in; x2=60.96mm; y2=46.99mm; thickness=20.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1511 { + x1=49.53mm; y1=1.8in; x2=48.895mm; y2=46.355mm; thickness=20.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1514 { + x1=48.895mm; y1=46.355mm; x2=48.895mm; y2=53.975mm; thickness=20.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + } + color = {#3a5fcd} + } + + ha:top-gnd { + lid=2 + group=3 + ha:combining { } + + li:objects { + } + color = {#104e8b} + } + + ha:bottom-gnd { + lid=3 + group=10 + ha:combining { } + + li:objects { + } + color = {#cd3700} + } + + ha:int-sig2 { + lid=4 + group=7 + ha:combining { } + + li:objects { + } + color = {#548b54} + } + + ha:int-sig1 { + lid=5 + group=5 + ha:combining { } + + li:objects { + } + color = {#8b7355} + } + + ha:outline { + lid=6 + group=9 + ha:combining { } + + li:objects { + } + color = {#00868b} + } + + ha:bottom-silk { + lid=7 + group=12 + ha:combining { auto=1; } + + li:objects { + } + color = {#000000} + } + + ha:top-silk { + lid=8 + group=1 + ha:combining { auto=1; } + + li:objects { + } + color = {#000000} + } + + ha:top-paste { + lid=9 + group=0 + ha:combining { auto=1; } + + li:objects { + } + color = {#cd00cd} + } + + ha:top-mask { + lid=10 + group=2 + ha:combining { sub=1; auto=1; } + + li:objects { + } + color = {#ff0000} + } + + ha:bottom-mask { + lid=11 + group=11 + ha:combining { sub=1; auto=1; } + + li:objects { + } + color = {#ff0000} + } + + ha:bottom-paste { + lid=12 + group=13 + ha:combining { auto=1; } + + li:objects { + } + color = {#cd00cd} + } + + ha:slot-plated { + lid=13 + group=14 + ha:combining { auto=1; } + + li:objects { + } + color = {#8b7355} + } + + ha:slot-unplated { + lid=14 + group=15 + ha:combining { auto=1; } + + li:objects { + } + color = {#00868b} + } + } + } + + ha:netlists { + li:netlist_patch { + ha:add_conn { net=gnd; term=J1-2; } + ha:add_conn { net=gnd; term=C1-2; } + ha:add_conn { net=gnd; term=C2-2; } + ha:add_conn { net=gnd; term=J2-2; } + ha:add_conn { net=gnd; term=U1-2; } + ha:add_conn { net=gnd; term=C3-2; } + ha:add_conn { net=in; term=J1-1; } + ha:add_conn { net=in; term=C3-1; } + ha:add_conn { net=in; term=U1-1; } + ha:add_conn { net=in; term=C1-1; } + ha:add_conn { net=out; term=J2-1; } + ha:add_conn { net=out; term=U1-3; } + ha:add_conn { net=out; term=C2-1; } + } + } + ha:layer_stack { + li:groups { + ha:0 { + name = top_paste + ha:type { top=1; paste=1; } + li:layers { 9; } + } + ha:1 { + name = top_silk + ha:type { silk=1; top=1; } + li:layers { 8; } + } + ha:2 { + name = top_mask + ha:type { top=1; mask=1; } + li:layers { 10; } + } + ha:3 { + name = top_copper + ha:type { copper=1; top=1; } + li:layers { 0; 2; } + } + ha:4 { + name = grp_4 + ha:type { substrate=1; intern=1; } + li:layers { } + } + ha:5 { + name = Intern + ha:type { copper=1; intern=1; } + li:layers { 5; } + } + ha:6 { + name = grp_6 + ha:type { substrate=1; intern=1; } + li:layers { } + } + ha:7 { + name = Intern + ha:type { copper=1; intern=1; } + li:layers { 4; } + } + ha:8 { + name = grp_8 + ha:type { substrate=1; intern=1; } + li:layers { } + } + ha:9 { + name = global_outline + ha:type { boundary=1; } + li:layers { 6; } + purpose = uroute + } + ha:10 { + name = bottom_copper + ha:type { bottom=1; copper=1; } + li:layers { 1; 3; } + } + ha:11 { + name = bottom_mask + ha:type { bottom=1; mask=1; } + li:layers { 11; } + } + ha:12 { + name = bottom_silk + ha:type { silk=1; bottom=1; } + li:layers { 7; } + } + ha:13 { + name = bottom_paste + ha:type { bottom=1; paste=1; } + li:layers { 12; } + } + ha:14 { + name = pmech + ha:type { mech=1; } + li:layers { 13; } + purpose = proute + } + ha:15 { + name = umech + ha:type { mech=1; } + li:layers { 14; } + purpose = uroute + } + } + } + li:pcb-rnd-conf-v1 { + ha:overwrite { + ha:design { + text_font_id = 0 + text_scale = 100 + via_thickness = 2.2000 mm + via_drilling_hole = 1000.00 um + text_thickness = 0 + line_thickness = 20.00 mil + poly_isle_area = 200000000.0 + clearance = 20.00 mil + } + ha:editor { + line_refraction = 1 + buffer_number = 0 + draw_grid = false + grids_idx = 4 + grid = 25.00 mil + } + } + } +} Index: tags/2.1.2/doc/tutorials/15_no_sch/step5.lht =================================================================== --- tags/2.1.2/doc/tutorials/15_no_sch/step5.lht (nonexistent) +++ tags/2.1.2/doc/tutorials/15_no_sch/step5.lht (revision 24813) @@ -0,0 +1,2201 @@ +ha:pcb-rnd-board-v6 { + + ha:attributes { + {PCB::grid::unit}=mil + } + + li:styles { + ha:Signal { + diameter = 2.0mm + text_scale = 0 + text_thick = 0.0 + thickness = 10.0mil + hole = 31.5mil + clearance = 20.0mil + } + ha:Power { + diameter = 2.2mm + text_scale = 0 + text_thick = 0.0 + thickness = 20.0mil + hole = 1.0mm + clearance = 20.0mil + } + ha:Fat { + diameter = 137.8mil + text_scale = 0 + text_thick = 0.0 + thickness = 80.0mil + hole = 47.24mil + clearance = 25.0mil + } + ha:Sig-tight { + diameter = 64.0mil + text_scale = 0 + text_thick = 0.0 + thickness = 10.0mil + hole = 31.5mil + clearance = 12.0mil + } + } + + ha:meta { + ha:size { + thermal_scale = 0.500000 + x = 127.0mm + y = 127.0mm + } + ha:grid { + spacing = 25.0mil + offs_x = 0.0 + offs_y = 0.0 + } + } + + ha:data { + li:padstack_prototypes { + } + + li:objects { + ha:subc.1158 { + ha:attributes { + value=TO220 + footprint=Transistor + refdes=U1 + } + ha:data { + li:padstack_prototypes { + + ha:ps_proto_v6.0 { + hdia=60.0mil; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + li:ps_poly { + -45.0mil + -45.0mil + 45.0mil + -45.0mil + 45.0mil + 45.0mil + -45.0mil + 45.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + li:ps_poly { + -45.0mil + -45.0mil + 45.0mil + -45.0mil + 45.0mil + 45.0mil + -45.0mil + 45.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + li:ps_poly { + -45.0mil + -45.0mil + 45.0mil + -45.0mil + 45.0mil + 45.0mil + -45.0mil + 45.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { sub=1; auto=1; } + ha:layer_mask { + top = 1 + mask = 1 + } + clearance=0.0 + li:ps_poly { + -48.0mil + -48.0mil + 48.0mil + -48.0mil + 48.0mil + 48.0mil + -48.0mil + 48.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { sub=1; auto=1; } + ha:layer_mask { + bottom = 1 + mask = 1 + } + clearance=0.0 + li:ps_poly { + -48.0mil + -48.0mil + 48.0mil + -48.0mil + 48.0mil + 48.0mil + -48.0mil + 48.0mil + } + } + } + } + + ha:ps_proto_v6.1 { + hdia=60.0mil; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=90.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=90.0mil; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=90.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=96.0mil; } + ha:combining { sub=1; auto=1; } + ha:layer_mask { + top = 1 + mask = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=96.0mil; } + ha:combining { sub=1; auto=1; } + ha:layer_mask { + bottom = 1 + mask = 1 + } + clearance=0.0 + } + } + } + + ha:ps_proto_v6.2 { + hdia=130.0mil; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=150.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=150.0mil; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=150.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=156.0mil; } + ha:combining { sub=1; auto=1; } + ha:layer_mask { + top = 1 + mask = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=156.0mil; } + ha:combining { sub=1; auto=1; } + ha:layer_mask { + bottom = 1 + mask = 1 + } + clearance=0.0 + } + } + } + } + + li:objects { + ha:padstack_ref.1229 { + proto=0; x=44.45mm; y=1.8in; rot=0.000000; xmirror=0; smirror=0; clearance=15.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + + ha:attributes { + term=1 + name=1 + } + } + ha:padstack_ref.1230 { + proto=1; x=46.99mm; y=1.8in; rot=0.000000; xmirror=0; smirror=0; clearance=15.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + + ha:attributes { + term=2 + name=2 + } + } + ha:padstack_ref.1231 { + proto=1; x=49.53mm; y=1.8in; rot=0.000000; xmirror=0; smirror=0; clearance=15.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + + ha:attributes { + term=3 + name=3 + } + } + ha:padstack_ref.1232 { + proto=2; x=46.99mm; y=1.13in; rot=0.000000; xmirror=0; smirror=0; clearance=15.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + + ha:attributes { + term=4 + name=4 + } + } + } + li:layers { + + ha:top-silk { + lid=0 + ha:combining { } + + li:objects { + ha:line.1159 { + x1=44.45mm; y1=1.8in; x2=44.45mm; y2=1.62in; thickness=30.0mil; clearance=0.0; + } + ha:line.1162 { + x1=46.99mm; y1=1.8in; x2=46.99mm; y2=1.62in; thickness=30.0mil; clearance=0.0; + } + ha:line.1165 { + x1=49.53mm; y1=1.8in; x2=49.53mm; y2=1.62in; thickness=30.0mil; clearance=0.0; + } + ha:line.1168 { + x1=1.65in; y1=1.62in; x2=52.07mm; y2=1.62in; thickness=20.0mil; clearance=0.0; + } + ha:line.1171 { + x1=52.07mm; y1=1.62in; x2=52.07mm; y2=31.623mm; thickness=20.0mil; clearance=0.0; + } + ha:line.1174 { + x1=52.07mm; y1=31.623mm; x2=1.65in; y2=31.623mm; thickness=20.0mil; clearance=0.0; + } + ha:line.1177 { + x1=1.65in; y1=31.623mm; x2=1.65in; y2=1.62in; thickness=20.0mil; clearance=0.0; + } + ha:line.1180 { + x1=1.65in; y1=31.623mm; x2=52.07mm; y2=31.623mm; thickness=20.0mil; clearance=0.0; + } + ha:line.1183 { + x1=52.07mm; y1=31.623mm; x2=52.07mm; y2=1.12in; thickness=20.0mil; clearance=0.0; + } + ha:line.1186 { + x1=52.07mm; y1=1.12in; x2=51.689mm; y2=1.12in; thickness=20.0mil; clearance=0.0; + } + ha:line.1189 { + x1=51.689mm; y1=1.12in; x2=51.689mm; y2=26.67mm; thickness=20.0mil; clearance=0.0; + } + ha:line.1192 { + x1=51.689mm; y1=26.67mm; x2=52.07mm; y2=26.67mm; thickness=20.0mil; clearance=0.0; + } + ha:line.1195 { + x1=52.07mm; y1=26.67mm; x2=52.07mm; y2=1.01in; thickness=20.0mil; clearance=0.0; + } + ha:line.1198 { + x1=52.07mm; y1=1.01in; x2=1.65in; y2=1.01in; thickness=20.0mil; clearance=0.0; + } + ha:line.1201 { + x1=1.65in; y1=1.01in; x2=1.65in; y2=26.67mm; thickness=20.0mil; clearance=0.0; + } + ha:line.1204 { + x1=1.65in; y1=26.67mm; x2=1.665in; y2=26.67mm; thickness=20.0mil; clearance=0.0; + } + ha:line.1207 { + x1=1.665in; y1=26.67mm; x2=1.665in; y2=1.12in; thickness=20.0mil; clearance=0.0; + } + ha:line.1210 { + x1=1.665in; y1=1.12in; x2=1.65in; y2=1.12in; thickness=20.0mil; clearance=0.0; + } + ha:line.1213 { + x1=1.65in; y1=1.12in; x2=1.65in; y2=31.623mm; thickness=20.0mil; clearance=0.0; + } + ha:text.1216 { + string=%a.parent.refdes%; x=40.005mm; y=27.813mm; scale=100; fid=0; + ha:flags { + dyntext=1 + floater=1 + } + rot = 90.000000 + } + } + ha:type { + silk = 1 + top = 1 + } + } + + ha:subc-aux { + lid=1 + ha:combining { } + + li:objects { + ha:line.1217 { + x1=46.99mm; y1=1.6325in; x2=46.99mm; y2=1.6325in; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=pnp-origin + } + } + ha:line.1220 { + x1=46.99mm; y1=1.8in; x2=46.99mm; y2=1.8in; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=origin + } + } + ha:line.1223 { + x1=46.99mm; y1=1.8in; x2=46.99mm; y2=46.72mm; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=x + } + } + ha:line.1226 { + x1=46.99mm; y1=1.8in; x2=47.99mm; y2=1.8in; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=y + } + } + } + ha:type { + top = 1 + misc = 1 + virtual = 1 + } + } + } + } + uid = 2YrIDHgdUiD93dfM91oAAAAJ + } + ha:subc.1234 { + ha:attributes { + value=acy200 + footprint=rcy(200) + refdes=C3 + } + ha:data { + li:padstack_prototypes { + + ha:ps_proto_v6.0 { + hdia=0.999998mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + li:ps_poly { + -40.0mil + -40.0mil + 40.0mil + -40.0mil + 40.0mil + 40.0mil + -40.0mil + 40.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + li:ps_poly { + -40.0mil + -40.0mil + 40.0mil + -40.0mil + 40.0mil + 40.0mil + -40.0mil + 40.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + li:ps_poly { + -40.0mil + -40.0mil + 40.0mil + -40.0mil + 40.0mil + 40.0mil + -40.0mil + 40.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { sub=1; auto=1; } + ha:layer_mask { + top = 1 + mask = 1 + } + clearance=0.0 + li:ps_poly { + -43.0mil + -43.0mil + 43.0mil + -43.0mil + 43.0mil + 43.0mil + -43.0mil + 43.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { sub=1; auto=1; } + ha:layer_mask { + bottom = 1 + mask = 1 + } + clearance=0.0 + li:ps_poly { + -43.0mil + -43.0mil + 43.0mil + -43.0mil + 43.0mil + 43.0mil + -43.0mil + 43.0mil + } + } + } + } + + ha:ps_proto_v6.1 { + hdia=0.999998mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=80.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=80.0mil; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=80.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=86.0mil; } + ha:combining { sub=1; auto=1; } + ha:layer_mask { + top = 1 + mask = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=86.0mil; } + ha:combining { sub=1; auto=1; } + ha:layer_mask { + bottom = 1 + mask = 1 + } + clearance=0.0 + } + } + } + } + + li:objects { + ha:padstack_ref.1258 { + proto=0; x=31.75mm; y=1.525in; rot=0.000000; xmirror=0; smirror=0; clearance=25.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + + ha:attributes { + term=1 + } + } + ha:padstack_ref.1259 { + proto=1; x=36.83mm; y=1.525in; rot=0.000000; xmirror=0; smirror=0; clearance=25.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + + ha:attributes { + term=2 + } + } + } + li:layers { + + ha:top-silk { + lid=0 + ha:combining { } + + li:objects { + ha:line.1235 { + x1=1.57in; y1=1.525in; x2=1.61in; y2=1.525in; thickness=10.0mil; clearance=0.0; + } + ha:line.1238 { + x1=1.09in; y1=1.525in; x2=1.13in; y2=1.525in; thickness=10.0mil; clearance=0.0; + } + ha:line.1241 { + x1=1.11in; y1=1.505in; x2=1.11in; y2=39.243mm; thickness=10.0mil; clearance=0.0; + } + ha:arc.1244 { + x=1.35in; y=1.525in; width=200.0mil; height=200.0mil; astart=0; adelta=360; thickness=10.0mil; clearance=0.0; + } + ha:text.1245 { + string=%a.parent.refdes%; x=1.31in; y=31.242mm; scale=100; fid=0; + ha:flags { + dyntext=1 + floater=1 + } + rot = 0.000000 + } + } + ha:type { + silk = 1 + top = 1 + } + } + + ha:subc-aux { + lid=1 + ha:combining { } + + li:objects { + ha:line.1246 { + x1=1.35in; y1=1.525in; x2=1.35in; y2=1.525in; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=pnp-origin + } + } + ha:line.1249 { + x1=31.75mm; y1=1.525in; x2=31.75mm; y2=1.525in; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=origin + } + } + ha:line.1252 { + x1=31.75mm; y1=1.525in; x2=32.75mm; y2=1.525in; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=x + } + } + ha:line.1255 { + x1=31.75mm; y1=1.525in; x2=31.75mm; y2=39.735mm; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=y + } + } + } + ha:type { + top = 1 + misc = 1 + virtual = 1 + } + } + } + } + uid = 2YrIDHgdUiD93dfM91oAAAAL + } + ha:subc.1261 { + ha:attributes { + value=1*2 + footprint=connector(1,2) + refdes=J1 + } + ha:data { + li:padstack_prototypes { + + ha:ps_proto_v6.0 { + hdia=0.999998mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + li:ps_poly { + -40.0mil + -40.0mil + 40.0mil + -40.0mil + 40.0mil + 40.0mil + -40.0mil + 40.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + li:ps_poly { + -40.0mil + -40.0mil + 40.0mil + -40.0mil + 40.0mil + 40.0mil + -40.0mil + 40.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + li:ps_poly { + -40.0mil + -40.0mil + 40.0mil + -40.0mil + 40.0mil + 40.0mil + -40.0mil + 40.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { sub=1; auto=1; } + ha:layer_mask { + top = 1 + mask = 1 + } + clearance=0.0 + li:ps_poly { + -43.0mil + -43.0mil + 43.0mil + -43.0mil + 43.0mil + 43.0mil + -43.0mil + 43.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { sub=1; auto=1; } + ha:layer_mask { + bottom = 1 + mask = 1 + } + clearance=0.0 + li:ps_poly { + -43.0mil + -43.0mil + 43.0mil + -43.0mil + 43.0mil + 43.0mil + -43.0mil + 43.0mil + } + } + } + } + + ha:ps_proto_v6.1 { + hdia=0.999998mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=80.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=80.0mil; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=80.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=86.0mil; } + ha:combining { sub=1; auto=1; } + ha:layer_mask { + top = 1 + mask = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=86.0mil; } + ha:combining { sub=1; auto=1; } + ha:layer_mask { + bottom = 1 + mask = 1 + } + clearance=0.0 + } + } + } + } + + li:objects { + ha:padstack_ref.1293 { + proto=0; x=975.0mil; y=46.355mm; rot=0.000000; xmirror=0; smirror=0; clearance=25.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + + ha:attributes { + term=1 + } + } + ha:padstack_ref.1294 { + proto=1; x=975.0mil; y=48.895mm; rot=0.000000; xmirror=0; smirror=0; clearance=25.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + + ha:attributes { + term=2 + } + } + } + li:layers { + + ha:top-silk { + lid=0 + ha:combining { } + + li:objects { + ha:line.1262 { + x1=925.0mil; y1=45.085mm; x2=925.0mil; y2=1.975in; thickness=10.0mil; clearance=0.0; + } + ha:line.1265 { + x1=925.0mil; y1=45.085mm; x2=26.035mm; y2=45.085mm; thickness=10.0mil; clearance=0.0; + } + ha:line.1268 { + x1=26.035mm; y1=1.975in; x2=925.0mil; y2=1.975in; thickness=10.0mil; clearance=0.0; + } + ha:line.1271 { + x1=26.035mm; y1=1.975in; x2=26.035mm; y2=45.085mm; thickness=10.0mil; clearance=0.0; + } + ha:line.1274 { + x1=925.0mil; y1=47.625mm; x2=26.035mm; y2=47.625mm; thickness=10.0mil; clearance=0.0; + } + ha:line.1277 { + x1=26.035mm; y1=45.085mm; x2=26.035mm; y2=47.625mm; thickness=10.0mil; clearance=0.0; + } + ha:text.1280 { + string=%a.parent.refdes%; x=950.0mil; y=42.545mm; scale=100; fid=0; + ha:flags { + dyntext=1 + floater=1 + } + rot = 0.000000 + } + } + ha:type { + silk = 1 + top = 1 + } + } + + ha:subc-aux { + lid=1 + ha:combining { } + + li:objects { + ha:line.1281 { + x1=975.0mil; y1=47.625mm; x2=975.0mil; y2=47.625mm; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=pnp-origin + } + } + ha:line.1284 { + x1=975.0mil; y1=46.355mm; x2=975.0mil; y2=46.355mm; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=origin + } + } + ha:line.1287 { + x1=975.0mil; y1=46.355mm; x2=975.0mil; y2=45.355mm; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=x + } + } + ha:line.1290 { + x1=975.0mil; y1=46.355mm; x2=23.765mm; y2=46.355mm; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=y + } + } + } + ha:type { + top = 1 + misc = 1 + virtual = 1 + } + } + } + } + uid = 2YrIDHgdUiD93dfM91oAAAAN + } + ha:subc.1296 { + ha:attributes { + value=1*2 + footprint=connector(1,2) + refdes=J2 + } + ha:data { + li:padstack_prototypes { + + ha:ps_proto_v6.0 { + hdia=0.999998mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + li:ps_poly { + -40.0mil + -40.0mil + 40.0mil + -40.0mil + 40.0mil + 40.0mil + -40.0mil + 40.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + li:ps_poly { + -40.0mil + -40.0mil + 40.0mil + -40.0mil + 40.0mil + 40.0mil + -40.0mil + 40.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + li:ps_poly { + -40.0mil + -40.0mil + 40.0mil + -40.0mil + 40.0mil + 40.0mil + -40.0mil + 40.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { sub=1; auto=1; } + ha:layer_mask { + top = 1 + mask = 1 + } + clearance=0.0 + li:ps_poly { + -43.0mil + -43.0mil + 43.0mil + -43.0mil + 43.0mil + 43.0mil + -43.0mil + 43.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { sub=1; auto=1; } + ha:layer_mask { + bottom = 1 + mask = 1 + } + clearance=0.0 + li:ps_poly { + -43.0mil + -43.0mil + 43.0mil + -43.0mil + 43.0mil + 43.0mil + -43.0mil + 43.0mil + } + } + } + } + + ha:ps_proto_v6.1 { + hdia=0.999998mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=80.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=80.0mil; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=80.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=86.0mil; } + ha:combining { sub=1; auto=1; } + ha:layer_mask { + top = 1 + mask = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=86.0mil; } + ha:combining { sub=1; auto=1; } + ha:layer_mask { + bottom = 1 + mask = 1 + } + clearance=0.0 + } + } + } + } + + li:objects { + ha:padstack_ref.1328 { + proto=0; x=60.96mm; y=46.99mm; rot=0.000000; xmirror=0; smirror=0; clearance=25.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + + ha:attributes { + term=1 + } + } + ha:padstack_ref.1329 { + proto=1; x=60.96mm; y=49.53mm; rot=0.000000; xmirror=0; smirror=0; clearance=25.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + + ha:attributes { + term=2 + } + } + } + li:layers { + + ha:top-silk { + lid=0 + ha:combining { } + + li:objects { + ha:line.1297 { + x1=2.35in; y1=1.8in; x2=2.35in; y2=2.0in; thickness=10.0mil; clearance=0.0; + } + ha:line.1300 { + x1=2.35in; y1=1.8in; x2=2.45in; y2=1.8in; thickness=10.0mil; clearance=0.0; + } + ha:line.1303 { + x1=2.45in; y1=2.0in; x2=2.35in; y2=2.0in; thickness=10.0mil; clearance=0.0; + } + ha:line.1306 { + x1=2.45in; y1=2.0in; x2=2.45in; y2=1.8in; thickness=10.0mil; clearance=0.0; + } + ha:line.1309 { + x1=2.35in; y1=1.9in; x2=2.45in; y2=1.9in; thickness=10.0mil; clearance=0.0; + } + ha:line.1312 { + x1=2.45in; y1=1.8in; x2=2.45in; y2=1.9in; thickness=10.0mil; clearance=0.0; + } + ha:text.1315 { + string=%a.parent.refdes%; x=60.325mm; y=43.18mm; scale=100; fid=0; + ha:flags { + dyntext=1 + floater=1 + } + rot = 0.000000 + } + } + ha:type { + silk = 1 + top = 1 + } + } + + ha:subc-aux { + lid=1 + ha:combining { } + + li:objects { + ha:line.1316 { + x1=60.96mm; y1=1.9in; x2=60.96mm; y2=1.9in; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=pnp-origin + } + } + ha:line.1319 { + x1=60.96mm; y1=46.99mm; x2=60.96mm; y2=46.99mm; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=origin + } + } + ha:line.1322 { + x1=60.96mm; y1=46.99mm; x2=60.96mm; y2=45.99mm; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=x + } + } + ha:line.1325 { + x1=60.96mm; y1=46.99mm; x2=59.96mm; y2=46.99mm; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=y + } + } + } + ha:type { + top = 1 + misc = 1 + virtual = 1 + } + } + } + } + uid = 2YrIDHgdUiD93dfM91oAAAAN + } + ha:subc.1331 { + ha:attributes { + value=acy200 + footprint=acy(200) + refdes=C1 + } + ha:data { + li:padstack_prototypes { + + ha:ps_proto_v6.0 { + hdia=0.999998mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + li:ps_poly { + -40.0mil + -40.0mil + 40.0mil + -40.0mil + 40.0mil + 40.0mil + -40.0mil + 40.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + li:ps_poly { + -40.0mil + -40.0mil + 40.0mil + -40.0mil + 40.0mil + 40.0mil + -40.0mil + 40.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + li:ps_poly { + -40.0mil + -40.0mil + 40.0mil + -40.0mil + 40.0mil + 40.0mil + -40.0mil + 40.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { sub=1; auto=1; } + ha:layer_mask { + top = 1 + mask = 1 + } + clearance=0.0 + li:ps_poly { + -43.0mil + -43.0mil + 43.0mil + -43.0mil + 43.0mil + 43.0mil + -43.0mil + 43.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { sub=1; auto=1; } + ha:layer_mask { + bottom = 1 + mask = 1 + } + clearance=0.0 + li:ps_poly { + -43.0mil + -43.0mil + 43.0mil + -43.0mil + 43.0mil + 43.0mil + -43.0mil + 43.0mil + } + } + } + } + + ha:ps_proto_v6.1 { + hdia=0.999998mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=80.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=80.0mil; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=80.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=86.0mil; } + ha:combining { sub=1; auto=1; } + ha:layer_mask { + top = 1 + mask = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=86.0mil; } + ha:combining { sub=1; auto=1; } + ha:layer_mask { + bottom = 1 + mask = 1 + } + clearance=0.0 + } + } + } + } + + li:objects { + ha:padstack_ref.1363 { + proto=0; x=38.1mm; y=53.975mm; rot=0.000000; xmirror=0; smirror=0; clearance=25.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + + ha:attributes { + term=1 + } + } + ha:padstack_ref.1364 { + proto=1; x=43.18mm; y=53.975mm; rot=0.000000; xmirror=0; smirror=0; clearance=25.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + + ha:attributes { + term=2 + } + } + } + li:layers { + + ha:top-silk { + lid=0 + ha:combining { } + + li:objects { + ha:line.1332 { + x1=38.1mm; y1=53.975mm; x2=1.55in; y2=53.975mm; thickness=10.0mil; clearance=0.0; + } + ha:line.1335 { + x1=1.65in; y1=53.975mm; x2=43.18mm; y2=53.975mm; thickness=10.0mil; clearance=0.0; + } + ha:line.1338 { + x1=1.55in; y1=2.10834in; x2=1.55in; y2=54.398164mm; thickness=10.0mil; clearance=0.0; + } + ha:line.1341 { + x1=1.55in; y1=2.10834in; x2=1.65in; y2=2.10834in; thickness=10.0mil; clearance=0.0; + } + ha:line.1344 { + x1=1.65in; y1=54.398164mm; x2=1.55in; y2=54.398164mm; thickness=10.0mil; clearance=0.0; + } + ha:line.1347 { + x1=1.65in; y1=54.398164mm; x2=1.65in; y2=2.10834in; thickness=10.0mil; clearance=0.0; + } + ha:text.1350 { + string=%a.parent.refdes%; x=1.56in; y=50.927mm; scale=100; fid=0; + ha:flags { + dyntext=1 + floater=1 + } + rot = 0.000000 + } + } + ha:type { + silk = 1 + top = 1 + } + } + + ha:subc-aux { + lid=1 + ha:combining { } + + li:objects { + ha:line.1351 { + x1=1.6in; y1=53.975mm; x2=1.6in; y2=53.975mm; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=pnp-origin + } + } + ha:line.1354 { + x1=38.1mm; y1=53.975mm; x2=38.1mm; y2=53.975mm; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=origin + } + } + ha:line.1357 { + x1=38.1mm; y1=53.975mm; x2=39.1mm; y2=53.975mm; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=x + } + } + ha:line.1360 { + x1=38.1mm; y1=53.975mm; x2=38.1mm; y2=54.975mm; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=y + } + } + } + ha:type { + top = 1 + misc = 1 + virtual = 1 + } + } + } + } + uid = 2YrIDHgdUiD93dfM91oAAAAB + } + ha:subc.1366 { + ha:attributes { + value=acy200 + footprint=acy(200) + refdes=C2 + } + ha:data { + li:padstack_prototypes { + + ha:ps_proto_v6.0 { + hdia=0.999998mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + li:ps_poly { + -40.0mil + -40.0mil + 40.0mil + -40.0mil + 40.0mil + 40.0mil + -40.0mil + 40.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + li:ps_poly { + -40.0mil + -40.0mil + 40.0mil + -40.0mil + 40.0mil + 40.0mil + -40.0mil + 40.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + li:ps_poly { + -40.0mil + -40.0mil + 40.0mil + -40.0mil + 40.0mil + 40.0mil + -40.0mil + 40.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { sub=1; auto=1; } + ha:layer_mask { + top = 1 + mask = 1 + } + clearance=0.0 + li:ps_poly { + -43.0mil + -43.0mil + 43.0mil + -43.0mil + 43.0mil + 43.0mil + -43.0mil + 43.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { sub=1; auto=1; } + ha:layer_mask { + bottom = 1 + mask = 1 + } + clearance=0.0 + li:ps_poly { + -43.0mil + -43.0mil + 43.0mil + -43.0mil + 43.0mil + 43.0mil + -43.0mil + 43.0mil + } + } + } + } + + ha:ps_proto_v6.1 { + hdia=0.999998mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=80.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=80.0mil; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=80.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=86.0mil; } + ha:combining { sub=1; auto=1; } + ha:layer_mask { + top = 1 + mask = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=86.0mil; } + ha:combining { sub=1; auto=1; } + ha:layer_mask { + bottom = 1 + mask = 1 + } + clearance=0.0 + } + } + } + } + + li:objects { + ha:padstack_ref.1398 { + proto=0; x=48.895mm; y=53.975mm; rot=0.000000; xmirror=0; smirror=0; clearance=25.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + + ha:attributes { + term=1 + } + } + ha:padstack_ref.1399 { + proto=1; x=53.975mm; y=53.975mm; rot=0.000000; xmirror=0; smirror=0; clearance=25.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + + ha:attributes { + term=2 + } + } + } + li:layers { + + ha:top-silk { + lid=0 + ha:combining { } + + li:objects { + ha:line.1367 { + x1=48.895mm; y1=53.975mm; x2=1.975in; y2=53.975mm; thickness=10.0mil; clearance=0.0; + } + ha:line.1370 { + x1=2.075in; y1=53.975mm; x2=53.975mm; y2=53.975mm; thickness=10.0mil; clearance=0.0; + } + ha:line.1373 { + x1=1.975in; y1=2.10834in; x2=1.975in; y2=54.398164mm; thickness=10.0mil; clearance=0.0; + } + ha:line.1376 { + x1=1.975in; y1=2.10834in; x2=2.075in; y2=2.10834in; thickness=10.0mil; clearance=0.0; + } + ha:line.1379 { + x1=2.075in; y1=54.398164mm; x2=1.975in; y2=54.398164mm; thickness=10.0mil; clearance=0.0; + } + ha:line.1382 { + x1=2.075in; y1=54.398164mm; x2=2.075in; y2=2.10834in; thickness=10.0mil; clearance=0.0; + } + ha:text.1385 { + string=%a.parent.refdes%; x=1.985in; y=50.927mm; scale=100; fid=0; + ha:flags { + dyntext=1 + floater=1 + } + rot = 0.000000 + } + } + ha:type { + silk = 1 + top = 1 + } + } + + ha:subc-aux { + lid=1 + ha:combining { } + + li:objects { + ha:line.1386 { + x1=51.435mm; y1=53.975mm; x2=51.435mm; y2=53.975mm; thickness=0.1mm; clearance=0.0; + ha:flags { + selected=1 + } + + ha:attributes { + subc-role=pnp-origin + } + } + ha:line.1389 { + x1=48.895mm; y1=53.975mm; x2=48.895mm; y2=53.975mm; thickness=0.1mm; clearance=0.0; + ha:flags { + selected=1 + } + + ha:attributes { + subc-role=origin + } + } + ha:line.1392 { + x1=48.895mm; y1=53.975mm; x2=49.895mm; y2=53.975mm; thickness=0.1mm; clearance=0.0; + ha:flags { + selected=1 + } + + ha:attributes { + subc-role=x + } + } + ha:line.1395 { + x1=48.895mm; y1=53.975mm; x2=48.895mm; y2=54.975mm; thickness=0.1mm; clearance=0.0; + ha:flags { + selected=1 + } + + ha:attributes { + subc-role=y + } + } + } + ha:type { + top = 1 + misc = 1 + virtual = 1 + } + } + } + } + uid = 2YrIDHgdUiD93dfM91oAAAAB + } + ha:rat.1517 { + x1=975.0mil; y1=48.895mm; lgrp1=3; x2=36.83mm; y2=1.525in; lgrp2=3; + } + ha:rat.1520 { + x1=46.99mm; y1=1.8in; lgrp1=3; x2=36.83mm; y2=1.525in; lgrp2=3; + } + ha:rat.1523 { + x1=43.18mm; y1=53.975mm; lgrp1=3; x2=46.99mm; y2=1.8in; lgrp2=3; + } + ha:rat.1526 { + x1=43.18mm; y1=53.975mm; lgrp1=3; x2=53.975mm; y2=53.975mm; lgrp2=3; + } + ha:rat.1529 { + x1=53.975mm; y1=53.975mm; lgrp1=3; x2=60.96mm; y2=49.53mm; lgrp2=3; + } + } + li:layers { + + ha:top-sig { + lid=0 + group=3 + ha:combining { } + + li:objects { + } + color = {#8b2323} + } + + ha:bottom-sig { + lid=1 + group=10 + ha:combining { } + + li:objects { + ha:line.1433 { + x1=1.175in; y1=46.355mm; x2=31.75mm; y2=44.45mm; thickness=20.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1436 { + x1=31.75mm; y1=44.45mm; x2=31.75mm; y2=1.525in; thickness=20.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1472 { + x1=1.375in; y1=46.355mm; x2=38.1mm; y2=49.53mm; thickness=20.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1475 { + x1=38.1mm; y1=49.53mm; x2=38.1mm; y2=53.975mm; thickness=20.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1478 { + x1=975.0mil; y1=46.355mm; x2=1.725in; y2=46.355mm; thickness=20.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1481 { + x1=1.725in; y1=46.355mm; x2=44.45mm; y2=1.8in; thickness=20.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1505 { + x1=49.53mm; y1=1.8in; x2=2.35in; y2=1.8in; thickness=20.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1508 { + x1=2.35in; y1=1.8in; x2=60.96mm; y2=46.99mm; thickness=20.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1511 { + x1=49.53mm; y1=1.8in; x2=48.895mm; y2=46.355mm; thickness=20.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1514 { + x1=48.895mm; y1=46.355mm; x2=48.895mm; y2=53.975mm; thickness=20.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + } + color = {#3a5fcd} + } + + ha:top-gnd { + lid=2 + group=3 + ha:combining { } + + li:objects { + } + color = {#104e8b} + } + + ha:bottom-gnd { + lid=3 + group=10 + ha:combining { } + + li:objects { + } + color = {#cd3700} + } + + ha:int-sig2 { + lid=4 + group=7 + ha:combining { } + + li:objects { + } + color = {#548b54} + } + + ha:int-sig1 { + lid=5 + group=5 + ha:combining { } + + li:objects { + } + color = {#8b7355} + } + + ha:outline { + lid=6 + group=9 + ha:combining { } + + li:objects { + } + color = {#00868b} + } + + ha:bottom-silk { + lid=7 + group=12 + ha:combining { auto=1; } + + li:objects { + } + color = {#000000} + } + + ha:top-silk { + lid=8 + group=1 + ha:combining { auto=1; } + + li:objects { + } + color = {#000000} + } + + ha:top-paste { + lid=9 + group=0 + ha:combining { auto=1; } + + li:objects { + } + color = {#cd00cd} + } + + ha:top-mask { + lid=10 + group=2 + ha:combining { sub=1; auto=1; } + + li:objects { + } + color = {#ff0000} + } + + ha:bottom-mask { + lid=11 + group=11 + ha:combining { sub=1; auto=1; } + + li:objects { + } + color = {#ff0000} + } + + ha:bottom-paste { + lid=12 + group=13 + ha:combining { auto=1; } + + li:objects { + } + color = {#cd00cd} + } + + ha:slot-plated { + lid=13 + group=14 + ha:combining { auto=1; } + + li:objects { + } + color = {#8b7355} + } + + ha:slot-unplated { + lid=14 + group=15 + ha:combining { auto=1; } + + li:objects { + } + color = {#00868b} + } + } + } + + + ha:netlists { + li:netlist_patch { + ha:add_conn { net=gnd; term=J1-2; } + ha:add_conn { net=gnd; term=C1-2; } + ha:add_conn { net=gnd; term=C2-2; } + ha:add_conn { net=gnd; term=J2-2; } + ha:add_conn { net=gnd; term=U1-2; } + ha:add_conn { net=gnd; term=C3-2; } + ha:add_conn { net=in; term=J1-1; } + ha:add_conn { net=in; term=C3-1; } + ha:add_conn { net=in; term=U1-1; } + ha:add_conn { net=in; term=C1-1; } + ha:add_conn { net=out; term=J2-1; } + ha:add_conn { net=out; term=U1-3; } + ha:add_conn { net=out; term=C2-1; } + } + } + ha:layer_stack { + li:groups { + ha:0 { + name = top_paste + ha:type { top=1; paste=1; } + li:layers { 9; } + } + ha:1 { + name = top_silk + ha:type { silk=1; top=1; } + li:layers { 8; } + } + ha:2 { + name = top_mask + ha:type { top=1; mask=1; } + li:layers { 10; } + } + ha:3 { + name = top_copper + ha:type { copper=1; top=1; } + li:layers { 0; 2; } + } + ha:4 { + name = grp_4 + ha:type { substrate=1; intern=1; } + li:layers { } + } + ha:5 { + name = Intern + ha:type { copper=1; intern=1; } + li:layers { 5; } + } + ha:6 { + name = grp_6 + ha:type { substrate=1; intern=1; } + li:layers { } + } + ha:7 { + name = Intern + ha:type { copper=1; intern=1; } + li:layers { 4; } + } + ha:8 { + name = grp_8 + ha:type { substrate=1; intern=1; } + li:layers { } + } + ha:9 { + name = global_outline + ha:type { boundary=1; } + li:layers { 6; } + purpose = uroute + } + ha:10 { + name = bottom_copper + ha:type { bottom=1; copper=1; } + li:layers { 1; 3; } + } + ha:11 { + name = bottom_mask + ha:type { bottom=1; mask=1; } + li:layers { 11; } + } + ha:12 { + name = bottom_silk + ha:type { silk=1; bottom=1; } + li:layers { 7; } + } + ha:13 { + name = bottom_paste + ha:type { bottom=1; paste=1; } + li:layers { 12; } + } + ha:14 { + name = pmech + ha:type { mech=1; } + li:layers { 13; } + purpose = proute + } + ha:15 { + name = umech + ha:type { mech=1; } + li:layers { 14; } + purpose = uroute + } + } + } + li:pcb-rnd-conf-v1 { + ha:overwrite { + ha:design { + text_font_id = 0 + text_scale = 100 + via_thickness = 2.2000 mm + via_drilling_hole = 1000.00 um + text_thickness = 0 + line_thickness = 20.00 mil + poly_isle_area = 200000000.0 + clearance = 20.00 mil + } + ha:editor { + line_refraction = 1 + buffer_number = 0 + draw_grid = false + grids_idx = 4 + grid = 25.00 mil + } + } + } +} Index: tags/2.1.2/doc/tutorials/15_no_sch/step5.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/tutorials/15_no_sch/step5.png =================================================================== --- tags/2.1.2/doc/tutorials/15_no_sch/step5.png (nonexistent) +++ tags/2.1.2/doc/tutorials/15_no_sch/step5.png (revision 24813) Property changes on: tags/2.1.2/doc/tutorials/15_no_sch/step5.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/tutorials/15_no_sch/step6.lht =================================================================== --- tags/2.1.2/doc/tutorials/15_no_sch/step6.lht (nonexistent) +++ tags/2.1.2/doc/tutorials/15_no_sch/step6.lht (revision 24813) @@ -0,0 +1,2234 @@ +ha:pcb-rnd-board-v6 { + + ha:attributes { + {PCB::grid::unit}=mil + } + + li:styles { + ha:Signal { + diameter = 2.0mm + text_scale = 0 + text_thick = 0.0 + thickness = 10.0mil + hole = 31.5mil + clearance = 20.0mil + } + ha:Power { + diameter = 2.2mm + text_scale = 0 + text_thick = 0.0 + thickness = 20.0mil + hole = 1.0mm + clearance = 20.0mil + } + ha:Fat { + diameter = 137.8mil + text_scale = 0 + text_thick = 0.0 + thickness = 80.0mil + hole = 47.24mil + clearance = 25.0mil + } + ha:Sig-tight { + diameter = 64.0mil + text_scale = 0 + text_thick = 0.0 + thickness = 10.0mil + hole = 31.5mil + clearance = 12.0mil + } + } + + ha:meta { + ha:size { + thermal_scale = 0.500000 + x = 127.0mm + y = 127.0mm + } + ha:grid { + spacing = 25.0mil + offs_x = 0.0 + offs_y = 0.0 + } + } + + ha:data { + li:padstack_prototypes { + } + + li:objects { + ha:subc.1158 { + ha:attributes { + value=TO220 + footprint=Transistor + refdes=U1 + } + ha:data { + li:padstack_prototypes { + + ha:ps_proto_v6.0 { + hdia=60.0mil; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + li:ps_poly { + -45.0mil + -45.0mil + 45.0mil + -45.0mil + 45.0mil + 45.0mil + -45.0mil + 45.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + li:ps_poly { + -45.0mil + -45.0mil + 45.0mil + -45.0mil + 45.0mil + 45.0mil + -45.0mil + 45.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + li:ps_poly { + -45.0mil + -45.0mil + 45.0mil + -45.0mil + 45.0mil + 45.0mil + -45.0mil + 45.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { sub=1; auto=1; } + ha:layer_mask { + top = 1 + mask = 1 + } + clearance=0.0 + li:ps_poly { + -48.0mil + -48.0mil + 48.0mil + -48.0mil + 48.0mil + 48.0mil + -48.0mil + 48.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { sub=1; auto=1; } + ha:layer_mask { + bottom = 1 + mask = 1 + } + clearance=0.0 + li:ps_poly { + -48.0mil + -48.0mil + 48.0mil + -48.0mil + 48.0mil + 48.0mil + -48.0mil + 48.0mil + } + } + } + } + + ha:ps_proto_v6.1 { + hdia=60.0mil; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=90.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=90.0mil; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=90.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=96.0mil; } + ha:combining { sub=1; auto=1; } + ha:layer_mask { + top = 1 + mask = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=96.0mil; } + ha:combining { sub=1; auto=1; } + ha:layer_mask { + bottom = 1 + mask = 1 + } + clearance=0.0 + } + } + } + + ha:ps_proto_v6.2 { + hdia=130.0mil; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=150.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=150.0mil; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=150.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=156.0mil; } + ha:combining { sub=1; auto=1; } + ha:layer_mask { + top = 1 + mask = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=156.0mil; } + ha:combining { sub=1; auto=1; } + ha:layer_mask { + bottom = 1 + mask = 1 + } + clearance=0.0 + } + } + } + } + + li:objects { + ha:padstack_ref.1229 { + proto=0; x=44.45mm; y=1.8in; rot=0.000000; xmirror=0; smirror=0; clearance=15.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + + ha:attributes { + term=1 + name=1 + } + } + ha:padstack_ref.1230 { + proto=1; x=46.99mm; y=1.8in; rot=0.000000; xmirror=0; smirror=0; clearance=15.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + li:3 { + on + diag + round + noshape + } + } + + ha:attributes { + term=2 + name=2 + } + } + ha:padstack_ref.1231 { + proto=1; x=49.53mm; y=1.8in; rot=0.000000; xmirror=0; smirror=0; clearance=15.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + + ha:attributes { + term=3 + name=3 + } + } + ha:padstack_ref.1232 { + proto=2; x=46.99mm; y=1.13in; rot=0.000000; xmirror=0; smirror=0; clearance=15.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + + ha:attributes { + term=4 + name=4 + } + } + } + li:layers { + + ha:top-silk { + lid=0 + ha:combining { } + + li:objects { + ha:line.1159 { + x1=44.45mm; y1=1.8in; x2=44.45mm; y2=1.62in; thickness=30.0mil; clearance=0.0; + } + ha:line.1162 { + x1=46.99mm; y1=1.8in; x2=46.99mm; y2=1.62in; thickness=30.0mil; clearance=0.0; + } + ha:line.1165 { + x1=49.53mm; y1=1.8in; x2=49.53mm; y2=1.62in; thickness=30.0mil; clearance=0.0; + } + ha:line.1168 { + x1=1.65in; y1=1.62in; x2=52.07mm; y2=1.62in; thickness=20.0mil; clearance=0.0; + } + ha:line.1171 { + x1=52.07mm; y1=1.62in; x2=52.07mm; y2=31.623mm; thickness=20.0mil; clearance=0.0; + } + ha:line.1174 { + x1=52.07mm; y1=31.623mm; x2=1.65in; y2=31.623mm; thickness=20.0mil; clearance=0.0; + } + ha:line.1177 { + x1=1.65in; y1=31.623mm; x2=1.65in; y2=1.62in; thickness=20.0mil; clearance=0.0; + } + ha:line.1180 { + x1=1.65in; y1=31.623mm; x2=52.07mm; y2=31.623mm; thickness=20.0mil; clearance=0.0; + } + ha:line.1183 { + x1=52.07mm; y1=31.623mm; x2=52.07mm; y2=1.12in; thickness=20.0mil; clearance=0.0; + } + ha:line.1186 { + x1=52.07mm; y1=1.12in; x2=51.689mm; y2=1.12in; thickness=20.0mil; clearance=0.0; + } + ha:line.1189 { + x1=51.689mm; y1=1.12in; x2=51.689mm; y2=26.67mm; thickness=20.0mil; clearance=0.0; + } + ha:line.1192 { + x1=51.689mm; y1=26.67mm; x2=52.07mm; y2=26.67mm; thickness=20.0mil; clearance=0.0; + } + ha:line.1195 { + x1=52.07mm; y1=26.67mm; x2=52.07mm; y2=1.01in; thickness=20.0mil; clearance=0.0; + } + ha:line.1198 { + x1=52.07mm; y1=1.01in; x2=1.65in; y2=1.01in; thickness=20.0mil; clearance=0.0; + } + ha:line.1201 { + x1=1.65in; y1=1.01in; x2=1.65in; y2=26.67mm; thickness=20.0mil; clearance=0.0; + } + ha:line.1204 { + x1=1.65in; y1=26.67mm; x2=1.665in; y2=26.67mm; thickness=20.0mil; clearance=0.0; + } + ha:line.1207 { + x1=1.665in; y1=26.67mm; x2=1.665in; y2=1.12in; thickness=20.0mil; clearance=0.0; + } + ha:line.1210 { + x1=1.665in; y1=1.12in; x2=1.65in; y2=1.12in; thickness=20.0mil; clearance=0.0; + } + ha:line.1213 { + x1=1.65in; y1=1.12in; x2=1.65in; y2=31.623mm; thickness=20.0mil; clearance=0.0; + } + ha:text.1216 { + string=%a.parent.refdes%; x=40.005mm; y=27.813mm; scale=100; fid=0; + ha:flags { + dyntext=1 + floater=1 + } + rot = 90.000000 + } + } + ha:type { + silk = 1 + top = 1 + } + } + + ha:subc-aux { + lid=1 + ha:combining { } + + li:objects { + ha:line.1217 { + x1=46.99mm; y1=1.6325in; x2=46.99mm; y2=1.6325in; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=pnp-origin + } + } + ha:line.1220 { + x1=46.99mm; y1=1.8in; x2=46.99mm; y2=1.8in; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=origin + } + } + ha:line.1223 { + x1=46.99mm; y1=1.8in; x2=46.99mm; y2=46.72mm; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=x + } + } + ha:line.1226 { + x1=46.99mm; y1=1.8in; x2=47.99mm; y2=1.8in; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=y + } + } + } + ha:type { + top = 1 + misc = 1 + virtual = 1 + } + } + } + } + uid = 2YrIDHgdUiD93dfM91oAAAAJ + } + ha:subc.1234 { + ha:attributes { + value=acy200 + footprint=rcy(200) + refdes=C3 + } + ha:data { + li:padstack_prototypes { + + ha:ps_proto_v6.0 { + hdia=0.999998mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + li:ps_poly { + -40.0mil + -40.0mil + 40.0mil + -40.0mil + 40.0mil + 40.0mil + -40.0mil + 40.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + li:ps_poly { + -40.0mil + -40.0mil + 40.0mil + -40.0mil + 40.0mil + 40.0mil + -40.0mil + 40.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + li:ps_poly { + -40.0mil + -40.0mil + 40.0mil + -40.0mil + 40.0mil + 40.0mil + -40.0mil + 40.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { sub=1; auto=1; } + ha:layer_mask { + top = 1 + mask = 1 + } + clearance=0.0 + li:ps_poly { + -43.0mil + -43.0mil + 43.0mil + -43.0mil + 43.0mil + 43.0mil + -43.0mil + 43.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { sub=1; auto=1; } + ha:layer_mask { + bottom = 1 + mask = 1 + } + clearance=0.0 + li:ps_poly { + -43.0mil + -43.0mil + 43.0mil + -43.0mil + 43.0mil + 43.0mil + -43.0mil + 43.0mil + } + } + } + } + + ha:ps_proto_v6.1 { + hdia=0.999998mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=80.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=80.0mil; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=80.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=86.0mil; } + ha:combining { sub=1; auto=1; } + ha:layer_mask { + top = 1 + mask = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=86.0mil; } + ha:combining { sub=1; auto=1; } + ha:layer_mask { + bottom = 1 + mask = 1 + } + clearance=0.0 + } + } + } + } + + li:objects { + ha:padstack_ref.1258 { + proto=0; x=31.75mm; y=1.525in; rot=0.000000; xmirror=0; smirror=0; clearance=25.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + + ha:attributes { + term=1 + } + } + ha:padstack_ref.1259 { + proto=1; x=36.83mm; y=1.525in; rot=0.000000; xmirror=0; smirror=0; clearance=25.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + li:3 { + on + diag + round + noshape + } + } + + ha:attributes { + term=2 + } + } + } + li:layers { + + ha:top-silk { + lid=0 + ha:combining { } + + li:objects { + ha:line.1235 { + x1=1.57in; y1=1.525in; x2=1.61in; y2=1.525in; thickness=10.0mil; clearance=0.0; + } + ha:line.1238 { + x1=1.09in; y1=1.525in; x2=1.13in; y2=1.525in; thickness=10.0mil; clearance=0.0; + } + ha:line.1241 { + x1=1.11in; y1=1.505in; x2=1.11in; y2=39.243mm; thickness=10.0mil; clearance=0.0; + } + ha:arc.1244 { + x=1.35in; y=1.525in; width=200.0mil; height=200.0mil; astart=0; adelta=360; thickness=10.0mil; clearance=0.0; + } + ha:text.1245 { + string=%a.parent.refdes%; x=1.31in; y=31.242mm; scale=100; fid=0; + ha:flags { + dyntext=1 + floater=1 + } + rot = 0.000000 + } + } + ha:type { + silk = 1 + top = 1 + } + } + + ha:subc-aux { + lid=1 + ha:combining { } + + li:objects { + ha:line.1246 { + x1=1.35in; y1=1.525in; x2=1.35in; y2=1.525in; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=pnp-origin + } + } + ha:line.1249 { + x1=31.75mm; y1=1.525in; x2=31.75mm; y2=1.525in; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=origin + } + } + ha:line.1252 { + x1=31.75mm; y1=1.525in; x2=32.75mm; y2=1.525in; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=x + } + } + ha:line.1255 { + x1=31.75mm; y1=1.525in; x2=31.75mm; y2=39.735mm; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=y + } + } + } + ha:type { + top = 1 + misc = 1 + virtual = 1 + } + } + } + } + uid = 2YrIDHgdUiD93dfM91oAAAAL + } + ha:subc.1261 { + ha:attributes { + value=1*2 + footprint=connector(1,2) + refdes=J1 + } + ha:data { + li:padstack_prototypes { + + ha:ps_proto_v6.0 { + hdia=0.999998mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + li:ps_poly { + -40.0mil + -40.0mil + 40.0mil + -40.0mil + 40.0mil + 40.0mil + -40.0mil + 40.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + li:ps_poly { + -40.0mil + -40.0mil + 40.0mil + -40.0mil + 40.0mil + 40.0mil + -40.0mil + 40.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + li:ps_poly { + -40.0mil + -40.0mil + 40.0mil + -40.0mil + 40.0mil + 40.0mil + -40.0mil + 40.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { sub=1; auto=1; } + ha:layer_mask { + top = 1 + mask = 1 + } + clearance=0.0 + li:ps_poly { + -43.0mil + -43.0mil + 43.0mil + -43.0mil + 43.0mil + 43.0mil + -43.0mil + 43.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { sub=1; auto=1; } + ha:layer_mask { + bottom = 1 + mask = 1 + } + clearance=0.0 + li:ps_poly { + -43.0mil + -43.0mil + 43.0mil + -43.0mil + 43.0mil + 43.0mil + -43.0mil + 43.0mil + } + } + } + } + + ha:ps_proto_v6.1 { + hdia=0.999998mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=80.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=80.0mil; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=80.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=86.0mil; } + ha:combining { sub=1; auto=1; } + ha:layer_mask { + top = 1 + mask = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=86.0mil; } + ha:combining { sub=1; auto=1; } + ha:layer_mask { + bottom = 1 + mask = 1 + } + clearance=0.0 + } + } + } + } + + li:objects { + ha:padstack_ref.1293 { + proto=0; x=975.0mil; y=46.355mm; rot=0.000000; xmirror=0; smirror=0; clearance=25.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + + ha:attributes { + term=1 + } + } + ha:padstack_ref.1294 { + proto=1; x=975.0mil; y=48.895mm; rot=0.000000; xmirror=0; smirror=0; clearance=25.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + li:3 { + on + round + noshape + } + } + + ha:attributes { + term=2 + } + } + } + li:layers { + + ha:top-silk { + lid=0 + ha:combining { } + + li:objects { + ha:line.1262 { + x1=925.0mil; y1=45.085mm; x2=925.0mil; y2=1.975in; thickness=10.0mil; clearance=0.0; + } + ha:line.1265 { + x1=925.0mil; y1=45.085mm; x2=26.035mm; y2=45.085mm; thickness=10.0mil; clearance=0.0; + } + ha:line.1268 { + x1=26.035mm; y1=1.975in; x2=925.0mil; y2=1.975in; thickness=10.0mil; clearance=0.0; + } + ha:line.1271 { + x1=26.035mm; y1=1.975in; x2=26.035mm; y2=45.085mm; thickness=10.0mil; clearance=0.0; + } + ha:line.1274 { + x1=925.0mil; y1=47.625mm; x2=26.035mm; y2=47.625mm; thickness=10.0mil; clearance=0.0; + } + ha:line.1277 { + x1=26.035mm; y1=45.085mm; x2=26.035mm; y2=47.625mm; thickness=10.0mil; clearance=0.0; + } + ha:text.1280 { + string=%a.parent.refdes%; x=950.0mil; y=42.545mm; scale=100; fid=0; + ha:flags { + dyntext=1 + floater=1 + } + rot = 0.000000 + } + } + ha:type { + silk = 1 + top = 1 + } + } + + ha:subc-aux { + lid=1 + ha:combining { } + + li:objects { + ha:line.1281 { + x1=975.0mil; y1=47.625mm; x2=975.0mil; y2=47.625mm; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=pnp-origin + } + } + ha:line.1284 { + x1=975.0mil; y1=46.355mm; x2=975.0mil; y2=46.355mm; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=origin + } + } + ha:line.1287 { + x1=975.0mil; y1=46.355mm; x2=975.0mil; y2=45.355mm; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=x + } + } + ha:line.1290 { + x1=975.0mil; y1=46.355mm; x2=23.765mm; y2=46.355mm; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=y + } + } + } + ha:type { + top = 1 + misc = 1 + virtual = 1 + } + } + } + } + uid = 2YrIDHgdUiD93dfM91oAAAAN + } + ha:subc.1296 { + ha:attributes { + value=1*2 + footprint=connector(1,2) + refdes=J2 + } + ha:data { + li:padstack_prototypes { + + ha:ps_proto_v6.0 { + hdia=0.999998mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + li:ps_poly { + -40.0mil + -40.0mil + 40.0mil + -40.0mil + 40.0mil + 40.0mil + -40.0mil + 40.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + li:ps_poly { + -40.0mil + -40.0mil + 40.0mil + -40.0mil + 40.0mil + 40.0mil + -40.0mil + 40.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + li:ps_poly { + -40.0mil + -40.0mil + 40.0mil + -40.0mil + 40.0mil + 40.0mil + -40.0mil + 40.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { sub=1; auto=1; } + ha:layer_mask { + top = 1 + mask = 1 + } + clearance=0.0 + li:ps_poly { + -43.0mil + -43.0mil + 43.0mil + -43.0mil + 43.0mil + 43.0mil + -43.0mil + 43.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { sub=1; auto=1; } + ha:layer_mask { + bottom = 1 + mask = 1 + } + clearance=0.0 + li:ps_poly { + -43.0mil + -43.0mil + 43.0mil + -43.0mil + 43.0mil + 43.0mil + -43.0mil + 43.0mil + } + } + } + } + + ha:ps_proto_v6.1 { + hdia=0.999998mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=80.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=80.0mil; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=80.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=86.0mil; } + ha:combining { sub=1; auto=1; } + ha:layer_mask { + top = 1 + mask = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=86.0mil; } + ha:combining { sub=1; auto=1; } + ha:layer_mask { + bottom = 1 + mask = 1 + } + clearance=0.0 + } + } + } + } + + li:objects { + ha:padstack_ref.1328 { + proto=0; x=60.96mm; y=46.99mm; rot=0.000000; xmirror=0; smirror=0; clearance=25.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + + ha:attributes { + term=1 + } + } + ha:padstack_ref.1329 { + proto=1; x=60.96mm; y=49.53mm; rot=0.000000; xmirror=0; smirror=0; clearance=25.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + li:3 { + on + diag + round + noshape + } + } + + ha:attributes { + term=2 + } + } + } + li:layers { + + ha:top-silk { + lid=0 + ha:combining { } + + li:objects { + ha:line.1297 { + x1=2.35in; y1=1.8in; x2=2.35in; y2=2.0in; thickness=10.0mil; clearance=0.0; + } + ha:line.1300 { + x1=2.35in; y1=1.8in; x2=2.45in; y2=1.8in; thickness=10.0mil; clearance=0.0; + } + ha:line.1303 { + x1=2.45in; y1=2.0in; x2=2.35in; y2=2.0in; thickness=10.0mil; clearance=0.0; + } + ha:line.1306 { + x1=2.45in; y1=2.0in; x2=2.45in; y2=1.8in; thickness=10.0mil; clearance=0.0; + } + ha:line.1309 { + x1=2.35in; y1=1.9in; x2=2.45in; y2=1.9in; thickness=10.0mil; clearance=0.0; + } + ha:line.1312 { + x1=2.45in; y1=1.8in; x2=2.45in; y2=1.9in; thickness=10.0mil; clearance=0.0; + } + ha:text.1315 { + string=%a.parent.refdes%; x=60.325mm; y=43.18mm; scale=100; fid=0; + ha:flags { + dyntext=1 + floater=1 + } + rot = 0.000000 + } + } + ha:type { + silk = 1 + top = 1 + } + } + + ha:subc-aux { + lid=1 + ha:combining { } + + li:objects { + ha:line.1316 { + x1=60.96mm; y1=1.9in; x2=60.96mm; y2=1.9in; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=pnp-origin + } + } + ha:line.1319 { + x1=60.96mm; y1=46.99mm; x2=60.96mm; y2=46.99mm; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=origin + } + } + ha:line.1322 { + x1=60.96mm; y1=46.99mm; x2=60.96mm; y2=45.99mm; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=x + } + } + ha:line.1325 { + x1=60.96mm; y1=46.99mm; x2=59.96mm; y2=46.99mm; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=y + } + } + } + ha:type { + top = 1 + misc = 1 + virtual = 1 + } + } + } + } + uid = 2YrIDHgdUiD93dfM91oAAAAN + } + ha:subc.1331 { + ha:attributes { + value=acy200 + footprint=acy(200) + refdes=C1 + } + ha:data { + li:padstack_prototypes { + + ha:ps_proto_v6.0 { + hdia=0.999998mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + li:ps_poly { + -40.0mil + -40.0mil + 40.0mil + -40.0mil + 40.0mil + 40.0mil + -40.0mil + 40.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + li:ps_poly { + -40.0mil + -40.0mil + 40.0mil + -40.0mil + 40.0mil + 40.0mil + -40.0mil + 40.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + li:ps_poly { + -40.0mil + -40.0mil + 40.0mil + -40.0mil + 40.0mil + 40.0mil + -40.0mil + 40.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { sub=1; auto=1; } + ha:layer_mask { + top = 1 + mask = 1 + } + clearance=0.0 + li:ps_poly { + -43.0mil + -43.0mil + 43.0mil + -43.0mil + 43.0mil + 43.0mil + -43.0mil + 43.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { sub=1; auto=1; } + ha:layer_mask { + bottom = 1 + mask = 1 + } + clearance=0.0 + li:ps_poly { + -43.0mil + -43.0mil + 43.0mil + -43.0mil + 43.0mil + 43.0mil + -43.0mil + 43.0mil + } + } + } + } + + ha:ps_proto_v6.1 { + hdia=0.999998mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=80.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=80.0mil; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=80.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=86.0mil; } + ha:combining { sub=1; auto=1; } + ha:layer_mask { + top = 1 + mask = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=86.0mil; } + ha:combining { sub=1; auto=1; } + ha:layer_mask { + bottom = 1 + mask = 1 + } + clearance=0.0 + } + } + } + } + + li:objects { + ha:padstack_ref.1363 { + proto=0; x=38.1mm; y=53.975mm; rot=0.000000; xmirror=0; smirror=0; clearance=25.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + + ha:attributes { + term=1 + } + } + ha:padstack_ref.1364 { + proto=1; x=43.18mm; y=53.975mm; rot=0.000000; xmirror=0; smirror=0; clearance=25.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + li:3 { + on + diag + round + noshape + } + } + + ha:attributes { + term=2 + } + } + } + li:layers { + + ha:top-silk { + lid=0 + ha:combining { } + + li:objects { + ha:line.1332 { + x1=38.1mm; y1=53.975mm; x2=1.55in; y2=53.975mm; thickness=10.0mil; clearance=0.0; + } + ha:line.1335 { + x1=1.65in; y1=53.975mm; x2=43.18mm; y2=53.975mm; thickness=10.0mil; clearance=0.0; + } + ha:line.1338 { + x1=1.55in; y1=2.10834in; x2=1.55in; y2=54.398164mm; thickness=10.0mil; clearance=0.0; + } + ha:line.1341 { + x1=1.55in; y1=2.10834in; x2=1.65in; y2=2.10834in; thickness=10.0mil; clearance=0.0; + } + ha:line.1344 { + x1=1.65in; y1=54.398164mm; x2=1.55in; y2=54.398164mm; thickness=10.0mil; clearance=0.0; + } + ha:line.1347 { + x1=1.65in; y1=54.398164mm; x2=1.65in; y2=2.10834in; thickness=10.0mil; clearance=0.0; + } + ha:text.1350 { + string=%a.parent.refdes%; x=1.56in; y=50.927mm; scale=100; fid=0; + ha:flags { + dyntext=1 + floater=1 + } + rot = 0.000000 + } + } + ha:type { + silk = 1 + top = 1 + } + } + + ha:subc-aux { + lid=1 + ha:combining { } + + li:objects { + ha:line.1351 { + x1=1.6in; y1=53.975mm; x2=1.6in; y2=53.975mm; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=pnp-origin + } + } + ha:line.1354 { + x1=38.1mm; y1=53.975mm; x2=38.1mm; y2=53.975mm; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=origin + } + } + ha:line.1357 { + x1=38.1mm; y1=53.975mm; x2=39.1mm; y2=53.975mm; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=x + } + } + ha:line.1360 { + x1=38.1mm; y1=53.975mm; x2=38.1mm; y2=54.975mm; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=y + } + } + } + ha:type { + top = 1 + misc = 1 + virtual = 1 + } + } + } + } + uid = 2YrIDHgdUiD93dfM91oAAAAB + } + ha:subc.1366 { + ha:attributes { + value=acy200 + footprint=acy(200) + refdes=C2 + } + ha:data { + li:padstack_prototypes { + + ha:ps_proto_v6.0 { + hdia=0.999998mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + li:ps_poly { + -40.0mil + -40.0mil + 40.0mil + -40.0mil + 40.0mil + 40.0mil + -40.0mil + 40.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + li:ps_poly { + -40.0mil + -40.0mil + 40.0mil + -40.0mil + 40.0mil + 40.0mil + -40.0mil + 40.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + li:ps_poly { + -40.0mil + -40.0mil + 40.0mil + -40.0mil + 40.0mil + 40.0mil + -40.0mil + 40.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { sub=1; auto=1; } + ha:layer_mask { + top = 1 + mask = 1 + } + clearance=0.0 + li:ps_poly { + -43.0mil + -43.0mil + 43.0mil + -43.0mil + 43.0mil + 43.0mil + -43.0mil + 43.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { sub=1; auto=1; } + ha:layer_mask { + bottom = 1 + mask = 1 + } + clearance=0.0 + li:ps_poly { + -43.0mil + -43.0mil + 43.0mil + -43.0mil + 43.0mil + 43.0mil + -43.0mil + 43.0mil + } + } + } + } + + ha:ps_proto_v6.1 { + hdia=0.999998mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=80.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=80.0mil; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=80.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=86.0mil; } + ha:combining { sub=1; auto=1; } + ha:layer_mask { + top = 1 + mask = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=86.0mil; } + ha:combining { sub=1; auto=1; } + ha:layer_mask { + bottom = 1 + mask = 1 + } + clearance=0.0 + } + } + } + } + + li:objects { + ha:padstack_ref.1398 { + proto=0; x=48.895mm; y=53.975mm; rot=0.000000; xmirror=0; smirror=0; clearance=25.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + + ha:attributes { + term=1 + } + } + ha:padstack_ref.1399 { + proto=1; x=53.975mm; y=53.975mm; rot=0.000000; xmirror=0; smirror=0; clearance=25.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + li:3 { + on + diag + round + noshape + } + } + + ha:attributes { + term=2 + } + } + } + li:layers { + + ha:top-silk { + lid=0 + ha:combining { } + + li:objects { + ha:line.1367 { + x1=48.895mm; y1=53.975mm; x2=1.975in; y2=53.975mm; thickness=10.0mil; clearance=0.0; + } + ha:line.1370 { + x1=2.075in; y1=53.975mm; x2=53.975mm; y2=53.975mm; thickness=10.0mil; clearance=0.0; + } + ha:line.1373 { + x1=1.975in; y1=2.10834in; x2=1.975in; y2=54.398164mm; thickness=10.0mil; clearance=0.0; + } + ha:line.1376 { + x1=1.975in; y1=2.10834in; x2=2.075in; y2=2.10834in; thickness=10.0mil; clearance=0.0; + } + ha:line.1379 { + x1=2.075in; y1=54.398164mm; x2=1.975in; y2=54.398164mm; thickness=10.0mil; clearance=0.0; + } + ha:line.1382 { + x1=2.075in; y1=54.398164mm; x2=2.075in; y2=2.10834in; thickness=10.0mil; clearance=0.0; + } + ha:text.1385 { + string=%a.parent.refdes%; x=1.985in; y=50.927mm; scale=100; fid=0; + ha:flags { + dyntext=1 + floater=1 + } + rot = 0.000000 + } + } + ha:type { + silk = 1 + top = 1 + } + } + + ha:subc-aux { + lid=1 + ha:combining { } + + li:objects { + ha:line.1386 { + x1=51.435mm; y1=53.975mm; x2=51.435mm; y2=53.975mm; thickness=0.1mm; clearance=0.0; + ha:flags { + selected=1 + } + + ha:attributes { + subc-role=pnp-origin + } + } + ha:line.1389 { + x1=48.895mm; y1=53.975mm; x2=48.895mm; y2=53.975mm; thickness=0.1mm; clearance=0.0; + ha:flags { + selected=1 + } + + ha:attributes { + subc-role=origin + } + } + ha:line.1392 { + x1=48.895mm; y1=53.975mm; x2=49.895mm; y2=53.975mm; thickness=0.1mm; clearance=0.0; + ha:flags { + selected=1 + } + + ha:attributes { + subc-role=x + } + } + ha:line.1395 { + x1=48.895mm; y1=53.975mm; x2=48.895mm; y2=54.975mm; thickness=0.1mm; clearance=0.0; + ha:flags { + selected=1 + } + + ha:attributes { + subc-role=y + } + } + } + ha:type { + top = 1 + misc = 1 + virtual = 1 + } + } + } + } + uid = 2YrIDHgdUiD93dfM91oAAAAB + } + } + li:layers { + + ha:top-sig { + lid=0 + group=3 + ha:combining { } + + li:objects { + } + color = {#8b2323} + } + + ha:bottom-sig { + lid=1 + group=10 + ha:combining { } + + li:objects { + ha:line.1433 { + x1=1.175in; y1=46.355mm; x2=31.75mm; y2=44.45mm; thickness=20.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1436 { + x1=31.75mm; y1=44.45mm; x2=31.75mm; y2=1.525in; thickness=20.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1472 { + x1=1.375in; y1=46.355mm; x2=38.1mm; y2=49.53mm; thickness=20.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1475 { + x1=38.1mm; y1=49.53mm; x2=38.1mm; y2=53.975mm; thickness=20.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1478 { + x1=975.0mil; y1=46.355mm; x2=1.725in; y2=46.355mm; thickness=20.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1481 { + x1=1.725in; y1=46.355mm; x2=44.45mm; y2=1.8in; thickness=20.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1505 { + x1=49.53mm; y1=1.8in; x2=2.35in; y2=1.8in; thickness=20.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1508 { + x1=2.35in; y1=1.8in; x2=60.96mm; y2=46.99mm; thickness=20.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1511 { + x1=49.53mm; y1=1.8in; x2=48.895mm; y2=46.355mm; thickness=20.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.1514 { + x1=48.895mm; y1=46.355mm; x2=48.895mm; y2=53.975mm; thickness=20.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + } + color = {#3a5fcd} + } + + ha:top-gnd { + lid=2 + group=3 + ha:combining { } + + li:objects { + } + color = {#104e8b} + } + + ha:bottom-gnd { + lid=3 + group=10 + ha:combining { } + + li:objects { + ha:polygon.1537 { clearance=40.0mil; + li:geometry { + ta:contour { + { 850.0mil; 975.0mil } + { 64.135mm; 975.0mil } + { 64.135mm; 2.25in } + { 850.0mil; 2.25in } + } + } + + ha:flags { + clearpoly=1 + } + } + } + color = {#cd3700} + } + + ha:int-sig2 { + lid=4 + group=7 + ha:combining { } + + li:objects { + } + color = {#548b54} + } + + ha:int-sig1 { + lid=5 + group=5 + ha:combining { } + + li:objects { + } + color = {#8b7355} + } + + ha:outline { + lid=6 + group=9 + ha:combining { } + + li:objects { + } + color = {#00868b} + } + + ha:bottom-silk { + lid=7 + group=12 + ha:combining { auto=1; } + + li:objects { + } + color = {#000000} + } + + ha:top-silk { + lid=8 + group=1 + ha:combining { auto=1; } + + li:objects { + } + color = {#000000} + } + + ha:top-paste { + lid=9 + group=0 + ha:combining { auto=1; } + + li:objects { + } + color = {#cd00cd} + } + + ha:top-mask { + lid=10 + group=2 + ha:combining { sub=1; auto=1; } + + li:objects { + } + color = {#ff0000} + } + + ha:bottom-mask { + lid=11 + group=11 + ha:combining { sub=1; auto=1; } + + li:objects { + } + color = {#ff0000} + } + + ha:bottom-paste { + lid=12 + group=13 + ha:combining { auto=1; } + + li:objects { + } + color = {#cd00cd} + } + + ha:slot-plated { + lid=13 + group=14 + ha:combining { auto=1; } + + li:objects { + } + color = {#8b7355} + } + + ha:slot-unplated { + lid=14 + group=15 + ha:combining { auto=1; } + + li:objects { + } + color = {#00868b} + } + } + } + + ha:netlists { + li:netlist_patch { + ha:add_conn { net=gnd; term=J1-2; } + ha:add_conn { net=gnd; term=C1-2; } + ha:add_conn { net=gnd; term=C2-2; } + ha:add_conn { net=gnd; term=J2-2; } + ha:add_conn { net=gnd; term=U1-2; } + ha:add_conn { net=gnd; term=C3-2; } + ha:add_conn { net=in; term=J1-1; } + ha:add_conn { net=in; term=C3-1; } + ha:add_conn { net=in; term=U1-1; } + ha:add_conn { net=in; term=C1-1; } + ha:add_conn { net=out; term=J2-1; } + ha:add_conn { net=out; term=U1-3; } + ha:add_conn { net=out; term=C2-1; } + } + } + ha:layer_stack { + li:groups { + ha:0 { + name = top_paste + ha:type { top=1; paste=1; } + li:layers { 9; } + } + ha:1 { + name = top_silk + ha:type { silk=1; top=1; } + li:layers { 8; } + } + ha:2 { + name = top_mask + ha:type { top=1; mask=1; } + li:layers { 10; } + } + ha:3 { + name = top_copper + ha:type { copper=1; top=1; } + li:layers { 0; 2; } + } + ha:4 { + name = grp_4 + ha:type { substrate=1; intern=1; } + li:layers { } + } + ha:5 { + name = Intern + ha:type { copper=1; intern=1; } + li:layers { 5; } + } + ha:6 { + name = grp_6 + ha:type { substrate=1; intern=1; } + li:layers { } + } + ha:7 { + name = Intern + ha:type { copper=1; intern=1; } + li:layers { 4; } + } + ha:8 { + name = grp_8 + ha:type { substrate=1; intern=1; } + li:layers { } + } + ha:9 { + name = global_outline + ha:type { boundary=1; } + li:layers { 6; } + purpose = uroute + } + ha:10 { + name = bottom_copper + ha:type { bottom=1; copper=1; } + li:layers { 1; 3; } + } + ha:11 { + name = bottom_mask + ha:type { bottom=1; mask=1; } + li:layers { 11; } + } + ha:12 { + name = bottom_silk + ha:type { silk=1; bottom=1; } + li:layers { 7; } + } + ha:13 { + name = bottom_paste + ha:type { bottom=1; paste=1; } + li:layers { 12; } + } + ha:14 { + name = pmech + ha:type { mech=1; } + li:layers { 13; } + purpose = proute + } + ha:15 { + name = umech + ha:type { mech=1; } + li:layers { 14; } + purpose = uroute + } + } + } + li:pcb-rnd-conf-v1 { + ha:overwrite { + ha:design { + text_font_id = 0 + text_scale = 100 + via_thickness = 2.2000 mm + via_drilling_hole = 1000.00 um + text_thickness = 0 + line_thickness = 20.00 mil + poly_isle_area = 200000000.0 + clearance = 20.00 mil + } + ha:editor { + line_refraction = 1 + buffer_number = 0 + draw_grid = false + grids_idx = 4 + grid = 25.00 mil + } + } + } +} Index: tags/2.1.2/doc/tutorials/15_no_sch/step6.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/tutorials/15_no_sch/step6.png =================================================================== --- tags/2.1.2/doc/tutorials/15_no_sch/step6.png (nonexistent) +++ tags/2.1.2/doc/tutorials/15_no_sch/step6.png (revision 24813) Property changes on: tags/2.1.2/doc/tutorials/15_no_sch/step6.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/tutorials/16_tdx_netlist/7805.tdx =================================================================== --- tags/2.1.2/doc/tutorials/16_tdx_netlist/7805.tdx (nonexistent) +++ tags/2.1.2/doc/tutorials/16_tdx_netlist/7805.tdx (revision 24813) @@ -0,0 +1,29 @@ +tEDAx v1 +begin netlist v1 linear_stab + conn gnd U1 2 + conn gnd J1 2 + conn gnd J2 2 + conn in U1 1 + conn in J1 1 + conn out U1 3 + conn out J2 1 + conn gnd C1 2 + conn in C1 1 + conn gnd C2 2 + conn out C2 1 + conn gnd C3 2 + conn out C3 1 + footprint J1 connector(1,2) + footprint J2 connector(1,2) + footprint U1 TO220 + footprint C1 acy(200) + footprint C2 acy(200) + footprint C3 rcy(200) + value C1 100 nf + value C2 100 nf + value C3 100 uf + device C1 ceramic\ capacitor + device C2 ceramic\ capacitor + device C3 electrolithic\ capacitor + device U1 7805 +end netlist Index: tags/2.1.2/doc/tutorials/16_tdx_netlist/index.html =================================================================== --- tags/2.1.2/doc/tutorials/16_tdx_netlist/index.html (nonexistent) +++ tags/2.1.2/doc/tutorials/16_tdx_netlist/index.html (revision 24813) @@ -0,0 +1,38 @@ +

Step 1: import the schematics

+

+Our schematics is coming from a tEDAx netlist, which is a bit more than +just a list of networks: it also contains information about footprints and +device attributes. +

+Start with an empty board and import the schematics information from +7805.tdx using the File menu, Import submenu, Import tEDAx schematics submenu. +

+All subcircuits and networks should be loaded. + +

Step 2: disperse

+

+However, the subcircuits are placed randomly. There are many different +strategies to resolve this: +

    +
  • manual placement: drag&drop move the subcircuits around; you may + want to temporarily enable the "floater lock" in the Mode menu, + Drawing submenu, "lock floaters" item (or using {m f l}). Since + refdes text is normally a floater, this will lock it down to + its parent subc so it will be easier to grab the subc to move, not + the refdes. +
  • disperse: Connects menu, Subcircuit placement submenu, disperse all + subcircuits. This will place the subcircuits in a grid in random order + so that there will be no overlap +
  • in the same submenu there is an auto-place selected subcircuits item; + select all subcircuits (drag-and-drop selection box enclosing them all) + then execute this menu. It's a smarter algorithm that is trying to + place subcircuits to minimize resulting rat line length. It will + try to use both sides of the board. +
+ +

Step 3 on: lay out the board

+

+Once subcircuits are placed, press {c r} and the nets are shown with rat lines. +From this point, please follow +the no-sch tutorial from step 5. + Index: tags/2.1.2/doc/tutorials/20_dbl_sided/7805.lht =================================================================== --- tags/2.1.2/doc/tutorials/20_dbl_sided/7805.lht (nonexistent) +++ tags/2.1.2/doc/tutorials/20_dbl_sided/7805.lht (revision 24813) @@ -0,0 +1,2100 @@ +ha:pcb-rnd-board-v6 { + + ha:attributes { + {PCB::grid::unit}=mil + } + + li:styles { + ha:Signal { + diameter = 1.999996mm + text_scale = 0 + text_thick = 0.0 + thickness = 10.0mil + hole = 31.5mil + clearance = 20.0mil + } + ha:Power { + diameter = 2.199894mm + text_scale = 0 + text_thick = 0.0 + thickness = 20.0mil + hole = 0.999998mm + clearance = 20.0mil + } + ha:Fat { + diameter = 137.8mil + text_scale = 0 + text_thick = 0.0 + thickness = 80.0mil + hole = 47.24mil + clearance = 25.0mil + } + ha:Sig-tight { + diameter = 64.0mil + text_scale = 0 + text_thick = 0.0 + thickness = 10.0mil + hole = 31.5mil + clearance = 12.0mil + } + } + + ha:meta { + ha:size { + thermal_scale = 0.500000 + x = 30.48mm + y = 30.48mm + } + ha:grid { + spacing = 25.0mil + offs_x = 0.0 + offs_y = 0.0 + } + } + + ha:data { + li:padstack_prototypes { + } + + li:objects { + ha:subc.5 { + ha:attributes { + footprint=0805 + refdes=C3 + manufacturer=unknown + vendor_part_number=unknown + manufacturer_part_number=unknown + value=100nF + vendor=unknown + device=CAPACITOR + } + ha:data { + li:padstack_prototypes { + + ha:ps_proto_v6.0 { + hdia=0.0; hplated=0; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + li:ps_poly { + 0.649986mm + -0.749808mm + -0.649986mm + -0.749808mm + -0.649986mm + 0.749808mm + 0.649986mm + 0.749808mm + } + } + + ha:ps_shape_v4 { + ha:combining { sub=1; auto=1; } + ha:layer_mask { + top = 1 + mask = 1 + } + clearance=0.0 + li:ps_poly { + 0.726186mm + -32.52mil + -0.726186mm + -32.52mil + -0.726186mm + 32.52mil + 0.726186mm + 32.52mil + } + } + + ha:ps_shape_v4 { + ha:combining { auto=1; } + ha:layer_mask { + top = 1 + paste = 1 + } + clearance=0.0 + li:ps_poly { + 0.649986mm + -0.749808mm + -0.649986mm + -0.749808mm + -0.649986mm + 0.749808mm + 0.649986mm + 0.749808mm + } + } + } + } + } + + li:objects { + ha:padstack_ref.7 { + proto=0; x=1.03543in; y=800.0mil; rot=0.000000; xmirror=0; smirror=1; clearance=10.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + + ha:attributes { + term=1 + name=1 + } + } + ha:padstack_ref.8 { + proto=0; x=964.57mil; y=800.0mil; rot=0.000000; xmirror=0; smirror=1; clearance=10.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + + ha:attributes { + term=2 + name=2 + } + } + } + li:layers { + + ha:top-silk { + lid=0 + ha:combining { } + + li:objects { + ha:line.9 { + x1=996.07mil; y1=772.45mil; x2=25.499822mm; y2=772.45mil; thickness=8.0mil; clearance=0.0; + } + ha:line.12 { + x1=996.07mil; y1=21.01977mm; x2=25.499822mm; y2=21.01977mm; thickness=8.0mil; clearance=0.0; + } + ha:text.6 { + string=%a.parent.refdes%; x=1.0315in; y=768.5mil; scale=100; fid=0; + ha:flags { + dyntext=1 + floater=1 + onsolder=1 + } + rot = 180.000000 + } + } + ha:type { + silk = 1 + bottom = 1 + } + } + + ha:subc-aux { + lid=1 + ha:combining { } + + li:objects { + ha:line.15 { + x1=1000.0mil; y1=800.0mil; x2=1000.0mil; y2=800.0mil; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=pnp-origin + } + } + ha:line.18 { + x1=1000.0mil; y1=800.0mil; x2=1000.0mil; y2=800.0mil; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=origin + } + } + ha:line.21 { + x1=1000.0mil; y1=800.0mil; x2=26.4mm; y2=800.0mil; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=x + } + } + ha:line.24 { + x1=1000.0mil; y1=800.0mil; x2=1000.0mil; y2=21.32mm; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=y + } + } + } + ha:type { + bottom = 1 + virtual = 1 + misc = 1 + } + } + } + } + uid = quxFXVYZGTxSjZpBCmYAAAAB + } + ha:subc.27 { + ha:attributes { + footprint=0805 + refdes=C2 + manufacturer=unknown + vendor_part_number=unknown + manufacturer_part_number=unknown + value=100nF + vendor=unknown + device=CAPACITOR + } + ha:data { + li:padstack_prototypes { + + ha:ps_proto_v6.0 { + hdia=0.0; hplated=0; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + li:ps_poly { + 0.649986mm + -0.749808mm + -0.649986mm + -0.749808mm + -0.649986mm + 0.749808mm + 0.649986mm + 0.749808mm + } + } + + ha:ps_shape_v4 { + ha:combining { sub=1; auto=1; } + ha:layer_mask { + top = 1 + mask = 1 + } + clearance=0.0 + li:ps_poly { + 0.726186mm + -32.52mil + -0.726186mm + -32.52mil + -0.726186mm + 32.52mil + 0.726186mm + 32.52mil + } + } + + ha:ps_shape_v4 { + ha:combining { auto=1; } + ha:layer_mask { + top = 1 + paste = 1 + } + clearance=0.0 + li:ps_poly { + 0.649986mm + -0.749808mm + -0.649986mm + -0.749808mm + -0.649986mm + 0.749808mm + 0.649986mm + 0.749808mm + } + } + } + } + } + + li:objects { + ha:padstack_ref.29 { + proto=0; x=764.57mil; y=800.0mil; rot=0.000000; xmirror=0; smirror=1; clearance=10.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + + ha:attributes { + term=1 + name=1 + } + } + ha:padstack_ref.30 { + proto=0; x=21.219922mm; y=800.0mil; rot=0.000000; xmirror=0; smirror=1; clearance=10.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + + ha:attributes { + term=2 + name=2 + } + } + } + li:layers { + + ha:top-silk { + lid=0 + ha:combining { } + + li:objects { + ha:line.31 { + x1=796.07mil; y1=21.01977mm; x2=20.419822mm; y2=21.01977mm; thickness=8.0mil; clearance=0.0; + } + ha:line.34 { + x1=796.07mil; y1=772.45mil; x2=20.419822mm; y2=772.45mil; thickness=8.0mil; clearance=0.0; + } + ha:text.28 { + string=%a.parent.refdes%; x=768.5mil; y=831.5mil; scale=100; fid=0; + ha:flags { + dyntext=1 + floater=1 + onsolder=1 + } + rot = 0.000000 + } + } + ha:type { + silk = 1 + bottom = 1 + } + } + + ha:subc-aux { + lid=1 + ha:combining { } + + li:objects { + ha:line.37 { + x1=800.0mil; y1=800.0mil; x2=800.0mil; y2=800.0mil; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=pnp-origin + } + } + ha:line.40 { + x1=800.0mil; y1=800.0mil; x2=800.0mil; y2=800.0mil; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=origin + } + } + ha:line.43 { + x1=800.0mil; y1=800.0mil; x2=19.32mm; y2=800.0mil; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=x + } + } + ha:line.46 { + x1=800.0mil; y1=800.0mil; x2=800.0mil; y2=19.32mm; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=y + } + } + } + ha:type { + bottom = 1 + virtual = 1 + misc = 1 + } + } + } + } + uid = quxFXVYZGTxSjZpBCmYAAAAC + } + ha:subc.49 { + ha:attributes { + footprint=rcy(200) + refdes=C1 + manufacturer=unknown + vendor_part_number=unknown + manufacturer_part_number=unknown + value=47uF + vendor=unknown + device=POLARIZED_CAPACITOR + } + ha:data { + li:padstack_prototypes { + + ha:ps_proto_v6.0 { + hdia=0.999998mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + li:ps_poly { + -40.0mil + -40.0mil + 40.0mil + -40.0mil + 40.0mil + 40.0mil + -40.0mil + 40.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + li:ps_poly { + -40.0mil + -40.0mil + 40.0mil + -40.0mil + 40.0mil + 40.0mil + -40.0mil + 40.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + li:ps_poly { + -40.0mil + -40.0mil + 40.0mil + -40.0mil + 40.0mil + 40.0mil + -40.0mil + 40.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { sub=1; auto=1; } + ha:layer_mask { + top = 1 + mask = 1 + } + clearance=0.0 + li:ps_poly { + -43.0mil + -43.0mil + 43.0mil + -43.0mil + 43.0mil + 43.0mil + -43.0mil + 43.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { sub=1; auto=1; } + ha:layer_mask { + bottom = 1 + mask = 1 + } + clearance=0.0 + li:ps_poly { + -43.0mil + -43.0mil + 43.0mil + -43.0mil + 43.0mil + 43.0mil + -43.0mil + 43.0mil + } + } + } + } + + ha:ps_proto_v6.1 { + hdia=0.999998mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=80.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=80.0mil; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=80.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=86.0mil; } + ha:combining { sub=1; auto=1; } + ha:layer_mask { + top = 1 + mask = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=86.0mil; } + ha:combining { sub=1; auto=1; } + ha:layer_mask { + bottom = 1 + mask = 1 + } + clearance=0.0 + } + } + } + } + + li:objects { + ha:padstack_ref.51 { + proto=0; x=500.0mil; y=400.0mil; rot=0.000000; xmirror=0; smirror=0; clearance=25.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + + ha:attributes { + term=1 + name=+ + } + } + ha:padstack_ref.52 { + proto=1; x=300.0mil; y=400.0mil; rot=0.000000; xmirror=0; smirror=0; clearance=25.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + li:4 { + on + diag + round + noshape + } + } + + ha:attributes { + term=2 + name=- + } + } + } + li:layers { + + ha:top-silk { + lid=0 + ha:combining { } + + li:objects { + ha:line.53 { + x1=140.0mil; y1=400.0mil; x2=180.0mil; y2=400.0mil; thickness=10.0mil; clearance=0.0; + } + ha:line.56 { + x1=620.0mil; y1=400.0mil; x2=660.0mil; y2=400.0mil; thickness=10.0mil; clearance=0.0; + } + ha:line.59 { + x1=640.0mil; y1=380.0mil; x2=640.0mil; y2=420.0mil; thickness=10.0mil; clearance=0.0; + } + ha:arc.62 { + x=400.0mil; y=400.0mil; width=200.0mil; height=200.0mil; astart=180; adelta=360; thickness=10.0mil; clearance=0.0; + } + ha:text.50 { + string=%a.parent.refdes%; x=460.0mil; y=605.0mil; scale=100; fid=0; + ha:flags { + dyntext=1 + floater=1 + } + rot = 0.000000 + } + } + ha:type { + silk = 1 + top = 1 + } + } + + ha:subc-aux { + lid=1 + ha:combining { } + + li:objects { + ha:line.63 { + x1=400.0mil; y1=400.0mil; x2=400.0mil; y2=400.0mil; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=pnp-origin + } + } + ha:line.66 { + x1=500.0mil; y1=400.0mil; x2=500.0mil; y2=400.0mil; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=origin + } + } + ha:line.69 { + x1=500.0mil; y1=400.0mil; x2=11.7mm; y2=400.0mil; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=x + } + } + ha:line.72 { + x1=500.0mil; y1=400.0mil; x2=500.0mil; y2=9.16mm; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=y + } + } + } + ha:type { + top = 1 + misc = 1 + virtual = 1 + } + } + } + } + uid = quxFXVYZGTxSjZpBCmYAAAAD + } + ha:subc.75 { + ha:attributes { + footprint=connector(2,1) + refdes=CONN2 + manufacturer=unknown + vendor_part_number=unknown + manufacturer_part_number=unknown + value=unknown + vendor=unknown + device=CONNECTOR_2 + } + ha:data { + li:padstack_prototypes { + + ha:ps_proto_v6.0 { + hdia=0.999998mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + li:ps_poly { + -40.0mil + -40.0mil + 40.0mil + -40.0mil + 40.0mil + 40.0mil + -40.0mil + 40.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + li:ps_poly { + -40.0mil + -40.0mil + 40.0mil + -40.0mil + 40.0mil + 40.0mil + -40.0mil + 40.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + li:ps_poly { + -40.0mil + -40.0mil + 40.0mil + -40.0mil + 40.0mil + 40.0mil + -40.0mil + 40.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { sub=1; auto=1; } + ha:layer_mask { + top = 1 + mask = 1 + } + clearance=0.0 + li:ps_poly { + -43.0mil + -43.0mil + 43.0mil + -43.0mil + 43.0mil + 43.0mil + -43.0mil + 43.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { sub=1; auto=1; } + ha:layer_mask { + bottom = 1 + mask = 1 + } + clearance=0.0 + li:ps_poly { + -43.0mil + -43.0mil + 43.0mil + -43.0mil + 43.0mil + 43.0mil + -43.0mil + 43.0mil + } + } + } + } + + ha:ps_proto_v6.1 { + hdia=0.999998mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=80.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=80.0mil; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=80.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=86.0mil; } + ha:combining { sub=1; auto=1; } + ha:layer_mask { + top = 1 + mask = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=86.0mil; } + ha:combining { sub=1; auto=1; } + ha:layer_mask { + bottom = 1 + mask = 1 + } + clearance=0.0 + } + } + } + } + + li:objects { + ha:padstack_ref.77 { + proto=0; x=250.0mil; y=800.0mil; rot=0.000000; xmirror=0; smirror=0; clearance=25.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + + ha:attributes { + term=1 + name=1 + } + } + ha:padstack_ref.78 { + proto=1; x=250.0mil; y=700.0mil; rot=0.000000; xmirror=0; smirror=0; clearance=25.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + li:4 { + on + diag + round + noshape + } + } + + ha:attributes { + term=2 + name=2 + } + } + } + li:layers { + + ha:top-silk { + lid=0 + ha:combining { } + + li:objects { + ha:line.79 { + x1=200.0mil; y1=850.0mil; x2=300.0mil; y2=850.0mil; thickness=10.0mil; clearance=0.0; + } + ha:line.82 { + x1=200.0mil; y1=650.0mil; x2=200.0mil; y2=850.0mil; thickness=10.0mil; clearance=0.0; + } + ha:line.85 { + x1=300.0mil; y1=650.0mil; x2=300.0mil; y2=850.0mil; thickness=10.0mil; clearance=0.0; + } + ha:line.88 { + x1=200.0mil; y1=650.0mil; x2=300.0mil; y2=650.0mil; thickness=10.0mil; clearance=0.0; + } + ha:line.91 { + x1=300.0mil; y1=750.0mil; x2=300.0mil; y2=850.0mil; thickness=10.0mil; clearance=0.0; + } + ha:line.94 { + x1=200.0mil; y1=750.0mil; x2=300.0mil; y2=750.0mil; thickness=10.0mil; clearance=0.0; + } + ha:text.76 { + string=%a.parent.refdes%; x=125.0mil; y=825.0mil; scale=100; fid=0; + ha:flags { + dyntext=1 + floater=1 + } + rot = 90.000000 + } + } + ha:type { + silk = 1 + top = 1 + } + } + + ha:subc-aux { + lid=1 + ha:combining { } + + li:objects { + ha:line.97 { + x1=250.0mil; y1=750.0mil; x2=250.0mil; y2=750.0mil; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=pnp-origin + } + } + ha:line.100 { + x1=250.0mil; y1=800.0mil; x2=250.0mil; y2=800.0mil; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=origin + } + } + ha:line.103 { + x1=250.0mil; y1=800.0mil; x2=250.0mil; y2=21.32mm; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=x + } + } + ha:line.106 { + x1=250.0mil; y1=800.0mil; x2=7.35mm; y2=800.0mil; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=y + } + } + } + ha:type { + top = 1 + misc = 1 + virtual = 1 + } + } + } + } + uid = quxFXVYZGTxSjZpBCmYAAAAE + } + ha:subc.109 { + ha:attributes { + footprint=connector(3,1) + refdes=CONN1 + manufacturer=unknown + vendor_part_number=unknown + manufacturer_part_number=unknown + value=unknown + vendor=unknown + device=CONNECTOR_3 + } + ha:data { + li:padstack_prototypes { + + ha:ps_proto_v6.0 { + hdia=0.999998mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + li:ps_poly { + -40.0mil + -40.0mil + 40.0mil + -40.0mil + 40.0mil + 40.0mil + -40.0mil + 40.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + li:ps_poly { + -40.0mil + -40.0mil + 40.0mil + -40.0mil + 40.0mil + 40.0mil + -40.0mil + 40.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + li:ps_poly { + -40.0mil + -40.0mil + 40.0mil + -40.0mil + 40.0mil + 40.0mil + -40.0mil + 40.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { sub=1; auto=1; } + ha:layer_mask { + top = 1 + mask = 1 + } + clearance=0.0 + li:ps_poly { + -43.0mil + -43.0mil + 43.0mil + -43.0mil + 43.0mil + 43.0mil + -43.0mil + 43.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { sub=1; auto=1; } + ha:layer_mask { + bottom = 1 + mask = 1 + } + clearance=0.0 + li:ps_poly { + -43.0mil + -43.0mil + 43.0mil + -43.0mil + 43.0mil + 43.0mil + -43.0mil + 43.0mil + } + } + } + } + + ha:ps_proto_v6.1 { + hdia=0.999998mm; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=80.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=80.0mil; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=80.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=86.0mil; } + ha:combining { sub=1; auto=1; } + ha:layer_mask { + top = 1 + mask = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=86.0mil; } + ha:combining { sub=1; auto=1; } + ha:layer_mask { + bottom = 1 + mask = 1 + } + clearance=0.0 + } + } + } + } + + li:objects { + ha:padstack_ref.111 { + proto=0; x=575.0mil; y=925.0mil; rot=0.000000; xmirror=0; smirror=0; clearance=25.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + + ha:attributes { + term=1 + name=1 + } + } + ha:padstack_ref.112 { + proto=1; x=475.0mil; y=925.0mil; rot=0.000000; xmirror=0; smirror=0; clearance=25.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + li:4 { + on + diag + round + noshape + } + } + + ha:attributes { + term=2 + name=2 + } + } + ha:padstack_ref.113 { + proto=1; x=375.0mil; y=925.0mil; rot=0.000000; xmirror=0; smirror=0; clearance=25.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + + ha:attributes { + term=3 + name=3 + } + } + } + li:layers { + + ha:top-silk { + lid=0 + ha:combining { } + + li:objects { + ha:line.114 { + x1=625.0mil; y1=875.0mil; x2=625.0mil; y2=975.0mil; thickness=10.0mil; clearance=0.0; + } + ha:line.117 { + x1=325.0mil; y1=975.0mil; x2=625.0mil; y2=975.0mil; thickness=10.0mil; clearance=0.0; + } + ha:line.120 { + x1=325.0mil; y1=875.0mil; x2=625.0mil; y2=875.0mil; thickness=10.0mil; clearance=0.0; + } + ha:line.123 { + x1=325.0mil; y1=875.0mil; x2=325.0mil; y2=975.0mil; thickness=10.0mil; clearance=0.0; + } + ha:line.126 { + x1=525.0mil; y1=875.0mil; x2=625.0mil; y2=875.0mil; thickness=10.0mil; clearance=0.0; + } + ha:line.129 { + x1=525.0mil; y1=875.0mil; x2=525.0mil; y2=975.0mil; thickness=10.0mil; clearance=0.0; + } + ha:text.110 { + string=%a.parent.refdes%; x=425.0mil; y=975.0mil; scale=100; fid=0; + ha:flags { + dyntext=1 + floater=1 + } + rot = 0.000000 + } + } + ha:type { + silk = 1 + top = 1 + } + } + + ha:subc-aux { + lid=1 + ha:combining { } + + li:objects { + ha:line.132 { + x1=475.0mil; y1=925.0mil; x2=475.0mil; y2=925.0mil; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=pnp-origin + } + } + ha:line.135 { + x1=575.0mil; y1=925.0mil; x2=575.0mil; y2=925.0mil; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=origin + } + } + ha:line.138 { + x1=575.0mil; y1=925.0mil; x2=575.0mil; y2=22.495mm; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=x + } + } + ha:line.141 { + x1=575.0mil; y1=925.0mil; x2=13.605mm; y2=925.0mil; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=y + } + } + } + ha:type { + top = 1 + misc = 1 + virtual = 1 + } + } + } + } + uid = quxFXVYZGTxSjZpBCmYAAAAF + } + ha:subc.144 { + ha:attributes { + footprint=TO220 + refdes=U1 + manufacturer=unknown + vendor_part_number=unknown + manufacturer_part_number=unknown + value=unknown + vendor=unknown + device=7805 + } + ha:data { + li:padstack_prototypes { + + ha:ps_proto_v6.0 { + hdia=60.0mil; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + li:ps_poly { + -45.0mil + -45.0mil + 45.0mil + -45.0mil + 45.0mil + 45.0mil + -45.0mil + 45.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + li:ps_poly { + -45.0mil + -45.0mil + 45.0mil + -45.0mil + 45.0mil + 45.0mil + -45.0mil + 45.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + li:ps_poly { + -45.0mil + -45.0mil + 45.0mil + -45.0mil + 45.0mil + 45.0mil + -45.0mil + 45.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { sub=1; auto=1; } + ha:layer_mask { + top = 1 + mask = 1 + } + clearance=0.0 + li:ps_poly { + -48.0mil + -48.0mil + 48.0mil + -48.0mil + 48.0mil + 48.0mil + -48.0mil + 48.0mil + } + } + + ha:ps_shape_v4 { + ha:combining { sub=1; auto=1; } + ha:layer_mask { + bottom = 1 + mask = 1 + } + clearance=0.0 + li:ps_poly { + -48.0mil + -48.0mil + 48.0mil + -48.0mil + 48.0mil + 48.0mil + -48.0mil + 48.0mil + } + } + } + } + + ha:ps_proto_v6.1 { + hdia=60.0mil; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=90.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=90.0mil; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=90.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=96.0mil; } + ha:combining { sub=1; auto=1; } + ha:layer_mask { + top = 1 + mask = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=96.0mil; } + ha:combining { sub=1; auto=1; } + ha:layer_mask { + bottom = 1 + mask = 1 + } + clearance=0.0 + } + } + } + + ha:ps_proto_v6.2 { + hdia=130.0mil; hplated=1; htop=0; hbottom=0; + li:shape { + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=150.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + top = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=150.0mil; } + ha:combining { } + ha:layer_mask { + bottom = 1 + copper = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=150.0mil; } + ha:combining { } + ha:layer_mask { + copper = 1 + intern = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=156.0mil; } + ha:combining { sub=1; auto=1; } + ha:layer_mask { + top = 1 + mask = 1 + } + clearance=0.0 + } + + ha:ps_shape_v4 { + ha:ps_circ { x=0.0; y=0.0; dia=156.0mil; } + ha:combining { sub=1; auto=1; } + ha:layer_mask { + bottom = 1 + mask = 1 + } + clearance=0.0 + } + } + } + } + + li:objects { + ha:padstack_ref.146 { + proto=0; x=800.0mil; y=925.0mil; rot=0.000000; xmirror=0; smirror=0; clearance=15.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + + ha:attributes { + term=1 + name=1 + } + } + ha:padstack_ref.147 { + proto=1; x=900.0mil; y=925.0mil; rot=0.000000; xmirror=0; smirror=0; clearance=15.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + li:4 { + on + diag + round + noshape + } + } + + ha:attributes { + term=2 + name=2 + } + } + ha:padstack_ref.148 { + proto=1; x=1000.0mil; y=925.0mil; rot=0.000000; xmirror=0; smirror=0; clearance=15.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + + ha:attributes { + term=3 + name=3 + } + } + ha:padstack_ref.149 { + proto=2; x=900.0mil; y=255.0mil; rot=0.000000; xmirror=0; smirror=0; clearance=15.0mil; + ha:flags { + clearline=1 + } + + li:thermal { + } + + ha:attributes { + term=4 + name=4 + } + } + } + li:layers { + + ha:top-silk { + lid=0 + ha:combining { } + + li:objects { + ha:line.150 { + x1=800.0mil; y1=925.0mil; x2=800.0mil; y2=745.0mil; thickness=30.0mil; clearance=0.0; + } + ha:line.153 { + x1=900.0mil; y1=925.0mil; x2=900.0mil; y2=745.0mil; thickness=30.0mil; clearance=0.0; + } + ha:line.156 { + x1=1000.0mil; y1=925.0mil; x2=1000.0mil; y2=745.0mil; thickness=30.0mil; clearance=0.0; + } + ha:line.159 { + x1=700.0mil; y1=745.0mil; x2=1.1in; y2=745.0mil; thickness=20.0mil; clearance=0.0; + } + ha:line.162 { + x1=1.1in; y1=745.0mil; x2=1.1in; y2=370.0mil; thickness=20.0mil; clearance=0.0; + } + ha:line.165 { + x1=1.1in; y1=370.0mil; x2=700.0mil; y2=370.0mil; thickness=20.0mil; clearance=0.0; + } + ha:line.168 { + x1=700.0mil; y1=370.0mil; x2=700.0mil; y2=745.0mil; thickness=20.0mil; clearance=0.0; + } + ha:line.171 { + x1=700.0mil; y1=370.0mil; x2=1.1in; y2=370.0mil; thickness=20.0mil; clearance=0.0; + } + ha:line.174 { + x1=1.1in; y1=370.0mil; x2=1.1in; y2=245.0mil; thickness=20.0mil; clearance=0.0; + } + ha:line.177 { + x1=1.1in; y1=245.0mil; x2=27.559mm; y2=245.0mil; thickness=20.0mil; clearance=0.0; + } + ha:line.180 { + x1=27.559mm; y1=245.0mil; x2=27.559mm; y2=175.0mil; thickness=20.0mil; clearance=0.0; + } + ha:line.183 { + x1=27.559mm; y1=175.0mil; x2=1.1in; y2=175.0mil; thickness=20.0mil; clearance=0.0; + } + ha:line.186 { + x1=1.1in; y1=175.0mil; x2=1.1in; y2=135.0mil; thickness=20.0mil; clearance=0.0; + } + ha:line.189 { + x1=1.1in; y1=135.0mil; x2=700.0mil; y2=135.0mil; thickness=20.0mil; clearance=0.0; + } + ha:line.192 { + x1=700.0mil; y1=135.0mil; x2=700.0mil; y2=175.0mil; thickness=20.0mil; clearance=0.0; + } + ha:line.195 { + x1=700.0mil; y1=175.0mil; x2=715.0mil; y2=175.0mil; thickness=20.0mil; clearance=0.0; + } + ha:line.198 { + x1=715.0mil; y1=175.0mil; x2=715.0mil; y2=245.0mil; thickness=20.0mil; clearance=0.0; + } + ha:line.201 { + x1=715.0mil; y1=245.0mil; x2=700.0mil; y2=245.0mil; thickness=20.0mil; clearance=0.0; + } + ha:line.204 { + x1=700.0mil; y1=245.0mil; x2=700.0mil; y2=370.0mil; thickness=20.0mil; clearance=0.0; + } + ha:text.145 { + string=%a.parent.refdes%; x=625.0mil; y=170.0mil; scale=100; fid=0; + ha:flags { + dyntext=1 + floater=1 + } + rot = 90.000000 + } + } + ha:type { + silk = 1 + top = 1 + } + } + + ha:subc-aux { + lid=1 + ha:combining { } + + li:objects { + ha:line.207 { + x1=900.0mil; y1=757.5mil; x2=900.0mil; y2=757.5mil; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=pnp-origin + } + } + ha:line.210 { + x1=900.0mil; y1=925.0mil; x2=900.0mil; y2=925.0mil; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=origin + } + } + ha:line.213 { + x1=900.0mil; y1=925.0mil; x2=900.0mil; y2=24.495mm; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=x + } + } + ha:line.216 { + x1=900.0mil; y1=925.0mil; x2=23.86mm; y2=925.0mil; thickness=0.1mm; clearance=0.0; + ha:attributes { + subc-role=y + } + } + } + ha:type { + top = 1 + misc = 1 + virtual = 1 + } + } + } + } + uid = quxFXVYZGTxSjZpBCmYAAAAG + } + } + li:layers { + + ha:component { + lid=0 + group=3 + ha:combining { } + + li:objects { + } + color = {#8b2323} + } + + ha:solder { + lid=1 + group=8 + ha:combining { } + + li:objects { + ha:line.219 { + x1=250.0mil; y1=800.0mil; x2=175.0mil; y2=800.0mil; thickness=80.0mil; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.222 { + x1=250.0mil; y1=800.0mil; x2=150.0mil; y2=800.0mil; thickness=80.0mil; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.225 { + x1=150.0mil; y1=800.0mil; x2=150.0mil; y2=150.0mil; thickness=80.0mil; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.228 { + x1=27.305mm; y1=150.0mil; x2=27.305mm; y2=925.0mil; thickness=80.0mil; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.231 { + x1=27.305mm; y1=925.0mil; x2=1000.0mil; y2=925.0mil; thickness=80.0mil; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.234 { + x1=150.0mil; y1=150.0mil; x2=800.0mil; y2=150.0mil; thickness=80.0mil; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.237 { + x1=27.305mm; y1=150.0mil; x2=1000.0mil; y2=150.0mil; thickness=80.0mil; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.240 { + x1=800.0mil; y1=150.0mil; x2=1000.0mil; y2=150.0mil; thickness=30.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.243 { + x1=800.0mil; y1=125.0mil; x2=26.035mm; y2=125.0mil; thickness=25.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.246 { + x1=500.0mil; y1=400.0mil; x2=600.0mil; y2=400.0mil; thickness=80.0mil; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.249 { + x1=600.0mil; y1=400.0mil; x2=675.0mil; y2=475.0mil; thickness=80.0mil; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.252 { + x1=675.0mil; y1=475.0mil; x2=675.0mil; y2=925.0mil; thickness=80.0mil; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.255 { + x1=800.0mil; y1=925.0mil; x2=575.0mil; y2=925.0mil; thickness=80.0mil; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.258 { + x1=764.57mil; y1=800.0mil; x2=675.0mil; y2=800.0mil; thickness=20.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + } + color = {#3a5fcd} + } + + ha:comp-GND { + lid=2 + group=3 + ha:combining { } + + li:objects { + } + color = {#104e8b} + } + + ha:comp-power { + lid=3 + group=3 + ha:combining { } + + li:objects { + } + color = {#cd3700} + } + + ha:sold-GND { + lid=4 + group=8 + ha:combining { } + + li:objects { + ha:line.261 { + x1=21.219922mm; y1=800.0mil; x2=964.57mil; y2=800.0mil; thickness=20.0mil; clearance=40.0mil; + } + ha:polygon.264 { + li:geometry { + ta:contour { + { 100.0mil; 26.035mm } + { 1.125in; 26.035mm } + { 1.125in; 100.0mil } + { 100.0mil; 100.0mil } + } + } + + ha:flags { + clearpoly=1 + } + } + } + color = {#548b54} + } + + ha:sold-power { + lid=5 + group=8 + ha:combining { } + + li:objects { + } + color = {#8b7355} + } + + ha:signal3 { + lid=6 + group=5 + ha:combining { } + + li:objects { + } + color = {#00868b} + } + + ha:outline { + lid=7 + group=7 + ha:combining { auto=1; } + + li:objects { + ha:line.269 { + x1=100.0mil; y1=100.0mil; x2=100.0mil; y2=26.035mm; thickness=10.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.272 { + x1=100.0mil; y1=100.0mil; x2=1.125in; y2=100.0mil; thickness=10.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.275 { + x1=100.0mil; y1=26.035mm; x2=1.125in; y2=26.035mm; thickness=10.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.278 { + x1=1.125in; y1=26.035mm; x2=1.125in; y2=100.0mil; thickness=10.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + } + color = {#228b22} + } + + ha:silk { + lid=8 + group=10 + ha:combining { auto=1; } + + li:objects { + } + color = {#000000} + } + + ha:silk { + lid=9 + group=1 + ha:combining { auto=1; } + + li:objects { + ha:text.281 { + string=-; x=325.0mil; y=625.0mil; scale=195; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.282 { + string=+; x=325.0mil; y=725.0mil; scale=195; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.283 { + string=+; x=550.0mil; y=775.0mil; scale=195; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.284 { + string=-; x=450.0mil; y=775.0mil; scale=195; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.285 { + string=in; x=275.0mil; y=900.0mil; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + ha:text.286 { + string={out: +5V}; x=115.0mil; y=585.0mil; scale=100; fid=0; + ha:flags { + clearline=1 + } + rot = 0.000000 + } + } + color = {#000000} + } + + ha:top-mask { + lid=10 + group=2 + ha:combining { sub=1; auto=1; } + + li:objects { + } + color = {#ff0000} + } + + ha:bottom-mask { + lid=11 + group=9 + ha:combining { sub=1; auto=1; } + + li:objects { + } + color = {#ff0000} + } + + ha:top-paste { + lid=12 + group=0 + ha:combining { auto=1; } + + li:objects { + } + color = {#cd00cd} + } + + ha:bottom-paste { + lid=13 + group=11 + ha:combining { auto=1; } + + li:objects { + } + color = {#cd00cd} + } + } + } + + + ha:netlists { + li:input { + ha:unnamed_net1 { + ha:attributes { + style=(unknown) + } + li:conn { C1-1; C2-1; CONN1-1; U1-1; } + style = (unknown) + } + ha:unnamed_net2 { + ha:attributes { + style=(unknown) + } + li:conn { C3-1; CONN2-1; U1-3; } + style = (unknown) + } + ha:GND { + ha:attributes { + style=(unknown) + } + li:conn { C1-2; C2-2; C3-2; CONN1-2; CONN2-2; U1-2; } + style = (unknown) + } + } + } + ha:layer_stack { + li:groups { + ha:0 { + name = top_paste + ha:type { top=1; paste=1; } + li:layers { 12; } + } + ha:1 { + name = top_silk + ha:type { silk=1; top=1; } + li:layers { 9; } + } + ha:2 { + name = top_mask + ha:type { top=1; mask=1; } + li:layers { 10; } + } + ha:3 { + name = top_copper + ha:type { copper=1; top=1; } + li:layers { 0; 2; 3; } + } + ha:4 { + name = implicit_subst + ha:type { substrate=1; intern=1; } + li:layers { } + } + ha:5 { + name = Intern + ha:type { copper=1; intern=1; } + li:layers { 6; } + } + ha:6 { + name = implicit_subst + ha:type { substrate=1; intern=1; } + li:layers { } + } + ha:7 { + name = global_outline + ha:type { boundary=1; } + li:layers { 7; } + purpose = uroute + } + ha:8 { + name = bottom_copper + ha:type { bottom=1; copper=1; } + li:layers { 1; 4; 5; } + } + ha:9 { + name = bottom_mask + ha:type { bottom=1; mask=1; } + li:layers { 11; } + } + ha:10 { + name = bottom_silk + ha:type { silk=1; bottom=1; } + li:layers { 8; } + } + ha:11 { + name = bottom_paste + ha:type { bottom=1; paste=1; } + li:layers { 13; } + } + } + } +} Index: tags/2.1.2/doc/tutorials/7805/7805.pcb =================================================================== --- tags/2.1.2/doc/tutorials/7805/7805.pcb (nonexistent) +++ tags/2.1.2/doc/tutorials/7805/7805.pcb (revision 24813) @@ -0,0 +1,222 @@ +# release: pcb-rnd 1.1.3 + +# To read pcb files, the pcb version (or the git source date) must be >= the file version +FileVersion[20070407] + +PCB["" 30480000nm 30480000nm] + +Grid[2540000nm 0 0 1] +Cursor[0 0 0.000000] +PolyArea[3100.006200] +Thermal[0.500000] +DRC[304800nm 228600nm 254000nm 177800nm 381000nm 254000nm] +Flags("nameonpcb,clearnew,snappin") +Groups("1,3,4,c:2,5,6,s:7:8") +Styles["Signal,254000nm,1999996nm,800100nm,508000nm:Power,508000nm,2199894nm,999998nm,508000nm:Fat,2032000nm,3500120nm,1199896nm,635000nm:Sig-tight,254000nm,1625600nm,800100nm,304800nm"] + +Attribute("PCB::grid::unit" "mil") +Attribute("PCB::loader" "geda/pcb - nanometer") +Attribute("PCB::conf::editor/grid" "100.00 mil") +Attribute("PCB::conf::editor/view/flip_x" "0") +Attribute("PCB::conf::editor/view/flip_y" "0") +Attribute("PCB::conf::editor/show_solder_side" "0") +Attribute("PCB::conf::editor/draw_grid" "true") +Attribute("PCB::conf::editor/buffer_number" "0") + +Element["onsolder" "0805" "C3" "100nF" 25400000nm 20320000nm 800100nm -800100nm 2 100 "auto"] +( + Attribute("vendor_part_number" "unknown") + Attribute("vendor" "unknown") + Attribute("manufacturer_part_number" "unknown") + Attribute("device" "CAPACITOR") + Attribute("manufacturer" "unknown") + Pad[899922nm -99822nm 899922nm 99822nm 1299972nm 508000nm 1452372nm "1" "1" "onsolder,square"] + Pad[-899922nm -99822nm -899922nm 99822nm 1299972nm 508000nm 1452372nm "2" "2" "onsolder,square"] + ElementLine [-99822nm -699770nm 99822nm -699770nm 203200nm] + ElementLine [-99822nm 699770nm 99822nm 699770nm 203200nm] + + ) + +Element["onsolder" "0805" "C2" "100nF" 20320000nm 20320000nm -800100nm 800100nm 0 100 "auto"] +( + Attribute("vendor_part_number" "unknown") + Attribute("vendor" "unknown") + Attribute("manufacturer_part_number" "unknown") + Attribute("device" "CAPACITOR") + Attribute("manufacturer" "unknown") + Pad[-899922nm -99822nm -899922nm 99822nm 1299972nm 508000nm 1452372nm "1" "1" "onsolder,square"] + Pad[899922nm -99822nm 899922nm 99822nm 1299972nm 508000nm 1452372nm "2" "2" "onsolder,square"] + ElementLine [-99822nm 699770nm 99822nm 699770nm 203200nm] + ElementLine [-99822nm -699770nm 99822nm -699770nm 203200nm] + + ) + +Element["" "rcy(200)" "C1" "47uF" 12700000nm 10160000nm -1016000nm 5207000nm 0 100 ""] +( + Attribute("vendor_part_number" "unknown") + Attribute("vendor" "unknown") + Attribute("manufacturer_part_number" "unknown") + Attribute("device" "POLARIZED_CAPACITOR") + Attribute("manufacturer" "unknown") + Pin[0 0 2032000nm 1270000nm 2184400nm 999998nm "+" "1" "square,edge2"] + Pin[-5080000nm 0 2032000nm 1270000nm 2184400nm 999998nm "-" "2" "edge2,thermal(4X)"] + ElementLine [-9144000nm 0 -8128000nm 0 254000nm] + ElementLine [3048000nm 0 4064000nm 0 254000nm] + ElementLine [3556000nm -508000nm 3556000nm 508000nm 254000nm] + ElementArc [-2540000nm 0 5080000nm 5080000nm 180 360 254000nm] + + ) + +Element["" "connector(2,1)" "CONN2" "unknown" 6350000nm 20320000nm -3175000nm 635000nm 1 100 ""] +( + Attribute("vendor_part_number" "unknown") + Attribute("vendor" "unknown") + Attribute("manufacturer_part_number" "unknown") + Attribute("device" "CONNECTOR_2") + Attribute("manufacturer" "unknown") + Pin[0 0 2032000nm 1270000nm 2184400nm 999998nm "1" "1" "square"] + Pin[0 -2540000nm 2032000nm 1270000nm 2184400nm 999998nm "2" "2" "thermal(4X)"] + ElementLine [-1270000nm 1270000nm 1270000nm 1270000nm 254000nm] + ElementLine [-1270000nm -3810000nm -1270000nm 1270000nm 254000nm] + ElementLine [1270000nm -3810000nm 1270000nm 1270000nm 254000nm] + ElementLine [-1270000nm -3810000nm 1270000nm -3810000nm 254000nm] + ElementLine [1270000nm -1270000nm 1270000nm 1270000nm 254000nm] + ElementLine [-1270000nm -1270000nm 1270000nm -1270000nm 254000nm] + + ) + +Element["" "connector(3,1)" "CONN1" "unknown" 14605000nm 23495000nm -3810000nm 1270000nm 0 100 ""] +( + Attribute("vendor_part_number" "unknown") + Attribute("vendor" "unknown") + Attribute("manufacturer_part_number" "unknown") + Attribute("device" "CONNECTOR_3") + Attribute("manufacturer" "unknown") + Pin[0 0 2032000nm 1270000nm 2184400nm 999998nm "1" "1" "square,edge2"] + Pin[-2540000nm 0 2032000nm 1270000nm 2184400nm 999998nm "2" "2" "edge2,thermal(4X)"] + Pin[-5080000nm 0 2032000nm 1270000nm 2184400nm 999998nm "3" "3" "edge2"] + ElementLine [1270000nm -1270000nm 1270000nm 1270000nm 254000nm] + ElementLine [-6350000nm 1270000nm 1270000nm 1270000nm 254000nm] + ElementLine [-6350000nm -1270000nm 1270000nm -1270000nm 254000nm] + ElementLine [-6350000nm -1270000nm -6350000nm 1270000nm 254000nm] + ElementLine [-1270000nm -1270000nm 1270000nm -1270000nm 254000nm] + ElementLine [-1270000nm -1270000nm -1270000nm 1270000nm 254000nm] + + ) + +Element["" "TO220" "U1" "unknown" 22860000nm 23495000nm -6985000nm -19177000nm 1 100 ""] +( + Attribute("vendor_part_number" "unknown") + Attribute("vendor" "unknown") + Attribute("manufacturer_part_number" "unknown") + Attribute("device" "7805") + Attribute("manufacturer" "unknown") + Pin[-2540000nm 0 2286000nm 762000nm 2438400nm 1524000nm "1" "1" "square"] + Pin[0 0 2286000nm 762000nm 2438400nm 1524000nm "2" "2" "thermal(4X)"] + Pin[2540000nm 0 2286000nm 762000nm 2438400nm 1524000nm "3" "3" ""] + Pin[0 -17018000nm 3810000nm 762000nm 3962400nm 3302000nm "4" "4" ""] + ElementLine [-2540000nm 0 -2540000nm -4572000nm 762000nm] + ElementLine [0 0 0 -4572000nm 762000nm] + ElementLine [2540000nm 0 2540000nm -4572000nm 762000nm] + ElementLine [-5080000nm -4572000nm 5080000nm -4572000nm 508000nm] + ElementLine [5080000nm -4572000nm 5080000nm -14097000nm 508000nm] + ElementLine [5080000nm -14097000nm -5080000nm -14097000nm 508000nm] + ElementLine [-5080000nm -14097000nm -5080000nm -4572000nm 508000nm] + ElementLine [-5080000nm -14097000nm 5080000nm -14097000nm 508000nm] + ElementLine [5080000nm -14097000nm 5080000nm -17272000nm 508000nm] + ElementLine [5080000nm -17272000nm 4699000nm -17272000nm 508000nm] + ElementLine [4699000nm -17272000nm 4699000nm -19050000nm 508000nm] + ElementLine [4699000nm -19050000nm 5080000nm -19050000nm 508000nm] + ElementLine [5080000nm -19050000nm 5080000nm -20066000nm 508000nm] + ElementLine [5080000nm -20066000nm -5080000nm -20066000nm 508000nm] + ElementLine [-5080000nm -20066000nm -5080000nm -19050000nm 508000nm] + ElementLine [-5080000nm -19050000nm -4699000nm -19050000nm 508000nm] + ElementLine [-4699000nm -19050000nm -4699000nm -17272000nm 508000nm] + ElementLine [-4699000nm -17272000nm -5080000nm -17272000nm 508000nm] + ElementLine [-5080000nm -17272000nm -5080000nm -14097000nm 508000nm] + + ) +Layer(1 "component") +( +) +Layer(2 "solder") +( + Line[6350000nm 20320000nm 4445000nm 20320000nm 2032000nm 1270000nm "clearline"] + Line[6350000nm 20320000nm 3810000nm 20320000nm 2032000nm 1270000nm "clearline"] + Line[3810000nm 20320000nm 3810000nm 3810000nm 2032000nm 1270000nm "clearline"] + Line[27305000nm 3810000nm 27305000nm 23495000nm 2032000nm 1270000nm "clearline"] + Line[27305000nm 23495000nm 25400000nm 23495000nm 2032000nm 1270000nm "clearline"] + Line[3810000nm 3810000nm 20320000nm 3810000nm 2032000nm 1270000nm "clearline"] + Line[27305000nm 3810000nm 25400000nm 3810000nm 2032000nm 1270000nm "clearline"] + Line[20320000nm 3810000nm 25400000nm 3810000nm 762000nm 1016000nm "clearline"] + Line[20320000nm 3175000nm 26035000nm 3175000nm 635000nm 1016000nm "clearline"] + Line[12700000nm 10160000nm 15240000nm 10160000nm 2032000nm 1270000nm "clearline"] + Line[15240000nm 10160000nm 17145000nm 12065000nm 2032000nm 1270000nm "clearline"] + Line[17145000nm 12065000nm 17145000nm 23495000nm 2032000nm 1270000nm "clearline"] + Line[20320000nm 23495000nm 14605000nm 23495000nm 2032000nm 1270000nm "clearline"] + Line[19420078nm 20320000nm 17145000nm 20320000nm 508000nm 1016000nm "clearline"] +) +Layer(3 "comp-GND") +( +) +Layer(4 "comp-power") +( +) +Layer(5 "sold-GND") +( + Line[21219922nm 20320000nm 24500078nm 20320000nm 508000nm 1016000nm ""] + Polygon("clearpoly") + ( + [2540000nm 26035000nm] [28575000nm 26035000nm] [28575000nm 2540000nm] [2540000nm 2540000nm] + ) +) +Layer(6 "sold-power") +( +) +Layer(7 "signal3") +( +) +Layer(8 "outline") +( + Line[2540000nm 2540000nm 2540000nm 26035000nm 254000nm 1016000nm "clearline"] + Line[2540000nm 2540000nm 28575000nm 2540000nm 254000nm 1016000nm "clearline"] + Line[2540000nm 26035000nm 28575000nm 26035000nm 254000nm 1016000nm "clearline"] + Line[28575000nm 26035000nm 28575000nm 2540000nm 254000nm 1016000nm "clearline"] +) +Layer(9 "silk") +( +) +Layer(10 "silk") +( + Text[8255000nm 15875000nm 0 195 "-" "clearline"] + Text[8255000nm 18415000nm 0 195 "+" "clearline"] + Text[13970000nm 19685000nm 0 195 "+" "clearline"] + Text[11430000nm 19685000nm 0 195 "-" "clearline"] + Text[6985000nm 22860000nm 0 100 "in" "clearline"] + Text[2921000nm 14859000nm 0 100 "out: +5V" "clearline"] +) +NetList() +( + Net("GND" "(unknown)") + ( + Connect("C1-2") + Connect("C2-2") + Connect("C3-2") + Connect("CONN1-2") + Connect("CONN2-2") + Connect("U1-2") + ) + Net("unnamed_net1" "(unknown)") + ( + Connect("C1-1") + Connect("C2-1") + Connect("CONN1-1") + Connect("U1-1") + ) + Net("unnamed_net2" "(unknown)") + ( + Connect("C3-1") + Connect("CONN2-1") + Connect("U1-3") + ) +) Index: tags/2.1.2/doc/tutorials/7805/7805.sch =================================================================== --- tags/2.1.2/doc/tutorials/7805/7805.sch (nonexistent) +++ tags/2.1.2/doc/tutorials/7805/7805.sch (revision 24813) @@ -0,0 +1,86 @@ +v 20130925 2 +C 23100 57800 1 0 0 lm7805-1.sym +{ +T 24700 59100 5 10 0 0 0 0 1 +device=7805 +T 24500 58800 5 10 1 1 0 6 1 +refdes=U1 +T 23400 58800 5 10 1 1 0 0 1 +footprint=TO220 +} +N 21100 58400 23100 58400 4 +N 21100 58000 21700 58000 4 +N 21700 58000 21700 56700 4 +C 21600 56400 1 0 0 gnd-1.sym +C 23800 56400 1 0 0 gnd-1.sym +N 23900 56700 23900 57800 4 +C 25900 57600 1 0 0 connector2-2.sym +{ +T 26600 58900 5 10 1 1 0 6 1 +refdes=J2 +T 26200 58850 5 10 0 0 0 0 1 +device=CONNECTOR_2 +T 26200 59050 5 10 0 0 0 0 1 +footprint=connector(1,2) +} +N 25900 58400 24700 58400 4 +N 25700 58000 25700 56700 4 +C 25600 56400 1 0 0 gnd-1.sym +N 25900 58000 25700 58000 4 +C 22000 58000 1 270 0 capacitor-2.sym +{ +T 22700 57800 5 10 0 0 270 0 1 +device=POLARIZED_CAPACITOR +T 22000 57400 5 10 1 1 270 0 1 +refdes=C3 +T 22900 57800 5 10 0 0 270 0 1 +symversion=0.1 +T 22000 58000 5 10 0 0 270 0 1 +footprint=rcy(200) +T 22000 58100 5 10 1 1 270 0 1 +value=100uF +} +C 22100 56400 1 0 0 gnd-1.sym +N 22200 57100 22200 56700 4 +N 22200 58000 22200 58400 4 +C 22700 58000 1 270 0 capacitor-1.sym +{ +T 23400 57800 5 10 0 0 270 0 1 +device=CAPACITOR +T 23200 57800 5 10 1 1 270 0 1 +refdes=C1 +T 23600 57800 5 10 0 0 270 0 1 +symversion=0.1 +T 22700 58200 5 10 1 1 270 0 1 +value=100nF +T 22700 58000 5 10 0 0 0 0 1 +footprint=acy(200) +} +N 22900 58000 22900 58400 4 +C 22800 56400 1 0 0 gnd-1.sym +N 22900 56700 22900 57100 4 +C 24800 58000 1 270 0 capacitor-1.sym +{ +T 25500 57800 5 10 0 0 270 0 1 +device=CAPACITOR +T 25300 57800 5 10 1 1 270 0 1 +refdes=C2 +T 25700 57800 5 10 0 0 270 0 1 +symversion=0.1 +T 24800 58200 5 10 1 1 270 0 1 +value=100nF +T 24800 58000 5 10 0 0 0 0 1 +footprint=acy(200) +} +N 25000 58000 25000 58400 4 +C 24900 56400 1 0 0 gnd-1.sym +N 25000 56700 25000 57100 4 +C 21100 57600 1 0 1 connector2-2.sym +{ +T 20400 58900 5 10 1 1 0 0 1 +refdes=J1 +T 20800 58850 5 10 0 0 0 6 1 +device=CONNECTOR_2 +T 20800 59050 5 10 0 0 0 6 1 +footprint=connector(1,2) +} Index: tags/2.1.2/doc/tutorials/7805/Makefile.inst =================================================================== --- tags/2.1.2/doc/tutorials/7805/Makefile.inst (nonexistent) +++ tags/2.1.2/doc/tutorials/7805/Makefile.inst (revision 24813) @@ -0,0 +1,23 @@ +ROOT=../../.. +TUTDIR=$(DOCDIR)/tutorial/7805 + + +all: + +install_all: + $(SCCBOX) mkdir -p $(TUTDIR) + $(SCCBOX) $(HOW) 7805.pcb $(TUTDIR)/7805.pcb + $(SCCBOX) $(HOW) 7805.sch $(TUTDIR)/7805.sch + $(SCCBOX) $(HOW) sch.png $(TUTDIR)/sch.png + $(SCCBOX) $(HOW) index.html $(TUTDIR)/index.html + +install: + $(MAKE) -f Makefile.inst install_all HOW="install -f" + +linstall: + $(MAKE) -f Makefile.inst install_all HOW="install -f -l --absolute " + +uninstall: + $(MAKE) -f Makefile.inst install_all HOW="install -u" + +include $(ROOT)/Makefile.conf Index: tags/2.1.2/doc/tutorials/7805/index.html =================================================================== --- tags/2.1.2/doc/tutorials/7805/index.html (nonexistent) +++ tags/2.1.2/doc/tutorials/7805/index.html (revision 24813) @@ -0,0 +1,47 @@ +

Step 1: schematics

+

+ The schematics is usually the single source of all logical information: + footprints, refdes and values and connections (networks or nets). + A project is just a directory that holds at least the schematics, but + usually also the pcb layout file and scripts. +

+ Start the new project by creating an empty directory. Draw + the schematics with any schematics editor supported by pcb-rnd and + save it in this new directory. On the schematics + place the following symbols and edit/add these attributes: +

    +
  • 7805, footprint=TO220, refdes=U1 +
  • 2 pin connector, footprint=connector(1,2), refdes=J1 +
  • 2 pin connector, footprint=connector(1,2), refdes=J2 +
  • polarized capacitor, fooptrint=rcy(200), value=100uF, refdes=C3 +
  • capacitor, fooptrint=acy(200), value=100nF, refdes=C1 +
  • capacitor, fooptrint=acy(200), value=100nF, refdes=C2 +
  • gnd +
+

+ Arrange and connect the pins as shown below. +

+ schematics +

+ +

Step 2: export the netlist as needed

+

+Depending on the schematics capture software you choose, you may need to +export a netlist that can be imported in pcb-rnd. +

+TODO: create a pool node on this + +

Step 3: lay out the board

+ + +

Step 4: updates: forward annotation

+

+If you need to change the schematics later, re-export it from the schematics +editor and re-import it from pcb-rnd. If the format included importing +footprints, all new footprints will be imported. The netlist will be updated. +press {c r} after the import and update the board to reflect schematics changes. + Index: tags/2.1.2/doc/tutorials/7805/sch.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/tutorials/7805/sch.png =================================================================== --- tags/2.1.2/doc/tutorials/7805/sch.png (nonexistent) +++ tags/2.1.2/doc/tutorials/7805/sch.png (revision 24813) Property changes on: tags/2.1.2/doc/tutorials/7805/sch.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/tutorials/Makefile =================================================================== --- tags/2.1.2/doc/tutorials/Makefile (nonexistent) +++ tags/2.1.2/doc/tutorials/Makefile (revision 24813) @@ -0,0 +1,18 @@ +all: + $(MAKE) all_ CMD=all + +all_: + cd 7805 && $(MAKE) -f Makefile.inst $(CMD) + +install: + $(MAKE) all_ CMD=install + +linstall: + $(MAKE) all_ CMD=linstall + +uninstall: + $(MAKE) all_ CMD=uninstall + +clean: + +distclean: Index: tags/2.1.2/doc/tutorials/README =================================================================== --- tags/2.1.2/doc/tutorials/README (nonexistent) +++ tags/2.1.2/doc/tutorials/README (revision 24813) @@ -0,0 +1,6 @@ +Policy: + - a small, modular tutorial + - reference back wherever possible to save redundant board files and screenshots + - the goal is to provide the smallest starter kit here + - but the few tutorials we have here should describe full workflows + - any tutorial on detals shall go in the pool Index: tags/2.1.2/doc/tutorials/pnp-origin/index.html =================================================================== --- tags/2.1.2/doc/tutorials/pnp-origin/index.html (nonexistent) +++ tags/2.1.2/doc/tutorials/pnp-origin/index.html (revision 24813) @@ -0,0 +1,153 @@ + + + + pcb-rnd - license + + + +

pick and place - origin

+ +

A. simplest case: rectangular board, implicit outline, implicit P&P origin

+

+Assume a board of 775*725 mils needs to be +created. The P&P fab says coord 0;0 is the lower left corner. The board +fab says they need the centerline of tool-path on the outline layer for +milling. +

+By far the simplest way to handle this board is to rely on builtin defaults: +

    +
  • board size (width and height) specifies the outline of a rectangular board +
  • if the outline layer exists but is empty, an implicit rectangular outline is drawn, matching board sizes +
  • implicit P&P origin is the lower left corner +
+

+Setting it up: +

    +
  • 1. start pcb-rnd with no board - this gets the default board template +
  • 2. change board width & height (gtk: file/preferences/user PoV/sizes) +
  • 3. do the layout +
  • 4. when exporting Gerber, enable the 'all layers' option to get the implicit outline layer +
  • 5. export the xy +
+

+ + + +
ProsCons +
    +
  • easy to set up +
  • no need to draw the outline +
+
    +
  • limited drawing area - unsuitable for editing small boards +
  • supports rectangular shapes only +
+
+ +

B. rectangular board, explicit outline, explicit P&P origin

+

+Assume another board of 775*725 mils needs to +be created. The P&P fab says coord 0;0 is the lower left corner. The +board fab says they need the centerline of tool-path on the outline layer +for milling. +

+This time the virtual board (canvas, drawing area) will be larger and the +board outline of a 775*725 will be manually drawn. Since pcb-rnd won't make +a guess of where the lower-left corner is, an explicit origin mark +needs to be added for the pick&place process. +Setting it up, assuming the GTK HID: +

    +
  • 1. start pcb-rnd with no board - this gets the default board template +
  • 2. draw the 775*725 mils box on the outline layer anywhere in the drawing area +
  • 3. do the layout within this box +
  • 4. draw a short line on a random layer - this will be the P&P mark +
  • 5. drag&drop move the endpoint of the unselected mark line to its other endpoint - this will result in a 0 long line, which looks like a filled circle; with 's' increase the size so that it's easily visible +
  • 6. select the mark, drag&drop move it to the lower left corner of the outline box +
  • 7. the mark still selected, press ctrl+e and click on the "add attribute" button in the property editor +
  • 8. type in "pnp-origin" in the "Attribute key" and "yes" in the "Attribute value" field; click ok and close the property editor +
  • 9. export the Gerber and xy files +
+

+There is a video tutorial available on steps 4..8. +

+Note 1: the mark is not explicitly visible in the XY file. It is not explicitly +passed to the P&P fab. Instead, all subcircuit coordinates are calculated considering +the mark's center as 0;0. +

+Note 2: still, the mark is not hidden or suppressed by pcb-rnd from any +of the output. It must be a line, but it can be on any of the layers. +Thus the mark potentially would show up on the board. There are multiple +options to make the mark disappear: +

    +
  • make the mark diameter smaller that the router mill bit diameter and place + the mark on a copper layer; the board fab will have the copper dot, but it + will be milled away. +
  • same trick should work with silk as well +
  • or even on the solder mask layer where this object would be a small cutout over void +
  • make a new (copper) layer, place the mark there and don't send this layer's Gerber export + (later on pcb-rnd will support documentation layers which are more dedicated for this sort of use) +
+

+ + +
ProsCons +
    +
  • drawing area (canvas) is bigger than the board: easier to edit +
  • can handle slots, cut-outs on the outline layer +
  • if the pick and place fab requires a slight offset on the placement, it is easy to move the mark +
+
    +
  • requires more steps to set up +
+
+ +

C. round board, explicit outline, explicit P&P origin

+

+Assume a third board shaped as a 700 mil +diameter circle. The P&P fab says coord 0;0 is the lower left corner of +the bounding box of the circle. The board fab says they need the +centerline of tool-path on the outline layer for milling. +

+The process is the same as in example B. The only extra consideration +is how to find the coords of the P&P origin mark; for this the P&P fab +house needs to be consulted. +

+There is a video tutorial available on using temporary +lines to aid placing the mark for a round lower-left corner. + +

D. different P&P origin for different fabs

+

+If the same board is populated by two different fabs who want different +origins, as long as they are also using different file formats, it is possible +to use two marks. The mechanism for finding the relevant mark is this: +

    +
  • look for a line that has attribute pnp-origin-FORMAT where FORMAT is the name of the format, e.g. gxyrs or Macrofab +
  • if that's not found, look for a line that has attribute pnp-origin +
  • if that's not found, use the bottom-left corner of the drawing area +
+

+This means the origin can be a different mark per format and/or a fallback +mark can be also added. + +

E. mark shapes

+

+In the above examples we used a zero-length line for the mark, which looked +like a filled circle. The code will find the first line with the right attribute +and use the center point of that line. For a zero-length line the center point +is the same as the two endpoints or the center of the filled circle it produces +on the screen. +

+It is possible to use non-zero-length lines for the mark. For example two lines +arranged in a + or x shape, either or both lines having the pnp-origin +attribute. If the mark is symmetrical, the crossing point happens to be the +middle of the line, which is what the code is after. +

+Of course it's also possible to use a single, non-zer-length line as mark, +but then it's harder to see the middle point as an user. It may still work +in some simple cases, e.g. a 45 degree short line segment symmetrically placed +on the corner of a 90 degree outline corner. + + + + + Index: tags/2.1.2/doc/tutorials/pnp-origin/orig_impl.lht =================================================================== --- tags/2.1.2/doc/tutorials/pnp-origin/orig_impl.lht (nonexistent) +++ tags/2.1.2/doc/tutorials/pnp-origin/orig_impl.lht (revision 24813) @@ -0,0 +1,411 @@ +ha:pcb-rnd-board-v2 { + + ha:attributes { + {PCB::grid::unit}=mil + } + + li:styles { + ha:Signal { + diameter = 1.999996mm + thickness = 10.0mil + hole = 31.5mil + clearance = 20.0mil + } + ha:Power { + diameter = 2.199894mm + thickness = 20.0mil + hole = 0.999998mm + clearance = 20.0mil + } + ha:Fat { + diameter = 137.8mil + thickness = 80.0mil + hole = 47.24mil + clearance = 25.0mil + } + ha:Sig-tight { + diameter = 64.0mil + thickness = 10.0mil + hole = 31.5mil + clearance = 12.0mil + } + } + + ha:meta { + ha:size { + thermal_scale = 0.500000 + x = 775.0mil + y = 725.0mil + isle_area_nm2 = 199999999.999200 + } + ha:cursor { + zoom = 0.000000 + x = 25.0mil + y = 625.0mil + } + ha:drc { + min_drill = 15.0mil + min_ring = 10.0mil + bloat = 12.0mil + shrink = 9.0mil + min_width = 10.0mil + min_silk = 7.0mil + } + ha:grid { + spacing = 25.0mil + offs_x = 0.0 + offs_y = 0.0 + } + } + + ha:data { + + li:objects { + ha:element.777 { + x=225.0mil; y=200.0mil; + li:objects { + ha:text.774 { + string=Standard SMT resistor, capacitor etc; x=193.5mil; y=93.5mil; scale=100; fid=0; direction=0; role=desc; + } + ha:text.775 { + string=R1; x=193.5mil; y=93.5mil; scale=100; fid=0; direction=0; role=name; + } + ha:text.776 { + string=1206; x=193.5mil; y=93.5mil; scale=100; fid=0; direction=0; role=value; + } + ha:line.778 { + x1=-599.948um; y1=-37.4mil; x2=23.62mil; y2=-37.4mil; thickness=8.0mil; clearance=0.0; + } + ha:line.779 { + x1=-599.948um; y1=0.94996mm; x2=23.62mil; y2=0.94996mm; thickness=8.0mil; clearance=0.0; + } + ha:pad.780 { + name=1; number=1; x1=-59.05mil; y1=-299.974um; x2=-59.05mil; y2=11.81mil; mask=1.452372mm; thickness=1.299972mm; clearance=20.0mil; + ha:flags { + square=1 + } + } + ha:pad.781 { + name=2; number=2; x1=1.49987mm; y1=-299.974um; x2=1.49987mm; y2=11.81mil; mask=1.452372mm; thickness=1.299972mm; clearance=20.0mil; + ha:flags { + square=1 + } + } + } + } + ha:element.785 { + x=550.0mil; y=200.0mil; + li:objects { + ha:text.782 { + string=Standard SMT resistor, capacitor etc; x=518.5mil; y=93.5mil; scale=100; fid=0; direction=0; role=desc; + } + ha:text.783 { + string=R2; x=518.5mil; y=93.5mil; scale=100; fid=0; direction=0; role=name; + } + ha:text.784 { + string=1206; x=518.5mil; y=93.5mil; scale=100; fid=0; direction=0; role=value; + } + ha:line.786 { + x1=-599.948um; y1=-37.4mil; x2=23.62mil; y2=-37.4mil; thickness=8.0mil; clearance=0.0; + } + ha:line.787 { + x1=-599.948um; y1=0.94996mm; x2=23.62mil; y2=0.94996mm; thickness=8.0mil; clearance=0.0; + } + ha:pad.788 { + name=1; number=1; x1=-59.05mil; y1=-299.974um; x2=-59.05mil; y2=11.81mil; mask=1.452372mm; thickness=1.299972mm; clearance=20.0mil; + ha:flags { + square=1 + } + } + ha:pad.789 { + name=2; number=2; x1=1.49987mm; y1=-299.974um; x2=1.49987mm; y2=11.81mil; mask=1.452372mm; thickness=1.299972mm; clearance=20.0mil; + ha:flags { + square=1 + } + } + } + } + ha:element.793 { + x=225.0mil; y=450.0mil; + li:objects { + ha:text.790 { + string=Standard SMT resistor, capacitor etc; x=193.5mil; y=343.5mil; scale=100; fid=0; direction=0; role=desc; + } + ha:text.791 { + string=R3; x=193.5mil; y=343.5mil; scale=100; fid=0; direction=0; role=name; + } + ha:text.792 { + string=1206; x=193.5mil; y=343.5mil; scale=100; fid=0; direction=0; role=value; + } + ha:line.794 { + x1=-599.948um; y1=-37.4mil; x2=23.62mil; y2=-37.4mil; thickness=8.0mil; clearance=0.0; + } + ha:line.795 { + x1=-599.948um; y1=0.94996mm; x2=23.62mil; y2=0.94996mm; thickness=8.0mil; clearance=0.0; + } + ha:pad.796 { + name=1; number=1; x1=-59.05mil; y1=-299.974um; x2=-59.05mil; y2=11.81mil; mask=1.452372mm; thickness=1.299972mm; clearance=20.0mil; + ha:flags { + square=1 + } + } + ha:pad.797 { + name=2; number=2; x1=1.49987mm; y1=-299.974um; x2=1.49987mm; y2=11.81mil; mask=1.452372mm; thickness=1.299972mm; clearance=20.0mil; + ha:flags { + square=1 + } + } + } + } + ha:element.801 { + x=550.0mil; y=450.0mil; + li:objects { + ha:text.798 { + string=Standard SMT resistor, capacitor etc; x=443.5mil; y=481.5mil; scale=100; fid=0; direction=1; role=desc; + } + ha:text.799 { + string=R4; x=443.5mil; y=481.5mil; scale=100; fid=0; direction=1; role=name; + } + ha:text.800 { + string=1206; x=443.5mil; y=481.5mil; scale=100; fid=0; direction=1; role=value; + } + ha:line.802 { + x1=-37.4mil; y1=-599.948um; x2=-37.4mil; y2=23.62mil; thickness=8.0mil; clearance=0.0; + } + ha:line.803 { + x1=0.94996mm; y1=-599.948um; x2=0.94996mm; y2=23.62mil; thickness=8.0mil; clearance=0.0; + } + ha:pad.804 { + name=1; number=1; x1=-299.974um; y1=1.49987mm; x2=11.81mil; y2=1.49987mm; mask=1.452372mm; thickness=1.299972mm; clearance=20.0mil; + ha:flags { + square=1 + } + } + ha:pad.805 { + name=2; number=2; x1=-299.974um; y1=-59.05mil; x2=11.81mil; y2=-59.05mil; mask=1.452372mm; thickness=1.299972mm; clearance=20.0mil; + ha:flags { + square=1 + } + } + } + } + } + li:layers { + + ha:component { + lid=0 + group=3 + ha:combining { } + visible=1 + + li:objects { + ha:line.750 { + x1=284.05mil; y1=200.0mil; x2=12.47013mm; y2=200.0mil; thickness=10.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.753 { + x1=4.21513mm; y1=200.0mil; x2=4.21513mm; y2=450.0mil; thickness=10.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.756 { + x1=284.05mil; y1=450.0mil; x2=325.0mil; y2=450.0mil; thickness=10.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.759 { + x1=325.0mil; y1=450.0mil; x2=400.0mil; y2=525.0mil; thickness=10.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.762 { + x1=400.0mil; y1=525.0mil; x2=525.0mil; y2=525.0mil; thickness=10.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.765 { + x1=550.0mil; y1=9.93013mm; x2=550.0mil; y2=375.0mil; thickness=10.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.768 { + x1=550.0mil; y1=375.0mil; x2=625.0mil; y2=300.0mil; thickness=10.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.771 { + x1=625.0mil; y1=300.0mil; x2=625.0mil; y2=200.0mil; thickness=10.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + } + } + + ha:solder { + lid=1 + group=8 + ha:combining { } + visible=1 + } + + ha:comp-GND { + lid=2 + group=3 + ha:combining { } + visible=1 + } + + ha:comp-power { + lid=3 + group=3 + ha:combining { } + visible=1 + } + + ha:sold-GND { + lid=4 + group=8 + ha:combining { } + visible=1 + } + + ha:sold-power { + lid=5 + group=8 + ha:combining { } + visible=1 + } + + ha:signal3 { + lid=6 + group=5 + ha:combining { } + visible=1 + + } + + ha:outline { + lid=7 + group=7 + ha:combining { } + visible=1 + + } + + ha:silk { + lid=8 + group=10 + ha:combining { auto=1; } + visible=1 + } + + ha:silk { + lid=9 + group=1 + ha:combining { auto=1; } + visible=1 + } + } + } + + ha:netlists { + li:input { + } + } + ha:layer_stack { + li:groups { + ha:0 { + name = top paste + ha:type { top=1; paste=1; } + li:layers { } + } + ha:1 { + name = top silk + ha:type { silk=1; top=1; } + li:layers { 9; } + } + ha:2 { + name = top mask + ha:type { top=1; mask=1; } + li:layers { } + } + ha:3 { + name = top copper + ha:type { copper=1; top=1; } + li:layers { 0; 2; 3; } + } + ha:4 { + ha:type { substrate=1; intern=1; } + li:layers { } + name = grp_4 + } + ha:5 { + name = Intern + ha:type { copper=1; intern=1; } + li:layers { 6; } + } + ha:6 { + ha:type { substrate=1; intern=1; } + li:layers { } + name = grp_6 + } + ha:7 { + name = global outline + ha:type { outline=1; intern=1; } + li:layers { 7; } + } + ha:8 { + name = bottom copper + ha:type { bottom=1; copper=1; } + li:layers { 1; 4; 5; } + } + ha:9 { + name = bottom mask + ha:type { bottom=1; mask=1; } + li:layers { } + } + ha:10 { + name = bottom silk + ha:type { silk=1; bottom=1; } + li:layers { 8; } + } + ha:11 { + name = bottom paste + ha:type { bottom=1; paste=1; } + li:layers { } + } + } + } + li:pcb-rnd-conf-v1 { + ha:overwrite { + ha:design { + min_ring = 10.00 mil + clearance = 20.00 mil + via_thickness = 2000.00 um + via_drilling_hole = 31.50 mil + min_slk = 7.00 mil + max_height = 725.00 mil + line_thickness = 10.00 mil + shrink = 9.00 mil + poly_isle_area = 199999999.999200 + max_width = 775.00 mil + min_wid = 10.00 mil + bloat = 12.00 mil + min_drill = 15.00 mil + } + ha:editor { + buffer_number = 0 + grid_unit = mil + } + } + } +} Index: tags/2.1.2/doc/tutorials/pnp-origin/orig_round.lht =================================================================== --- tags/2.1.2/doc/tutorials/pnp-origin/orig_round.lht (nonexistent) +++ tags/2.1.2/doc/tutorials/pnp-origin/orig_round.lht (revision 24813) @@ -0,0 +1,449 @@ +ha:pcb-rnd-board-v2 { + + ha:attributes { + {PCB::grid::unit}=mil + } + + li:styles { + ha:Signal { + diameter = 1.999996mm + thickness = 10.0mil + hole = 31.5mil + clearance = 20.0mil + } + ha:Power { + diameter = 2.199894mm + thickness = 20.0mil + hole = 0.999998mm + clearance = 20.0mil + } + ha:Fat { + diameter = 137.8mil + thickness = 80.0mil + hole = 47.24mil + clearance = 25.0mil + } + ha:Sig-tight { + diameter = 64.0mil + thickness = 10.0mil + hole = 31.5mil + clearance = 12.0mil + } + } + + ha:meta { + ha:size { + thermal_scale = 0.500000 + x = 1000.0mil + y = 1000.0mil + isle_area_nm2 = 199999999.999200 + } + ha:cursor { + zoom = 0.000000 + x = 25.0mil + y = 625.0mil + } + ha:drc { + min_drill = 15.0mil + min_ring = 10.0mil + bloat = 12.0mil + shrink = 9.0mil + min_width = 10.0mil + min_silk = 7.0mil + } + ha:grid { + spacing = 25.0mil + offs_x = 0.0 + offs_y = 0.0 + } + } + + ha:data { + + li:objects { + ha:element.45 { + x=375.0mil; y=350.0mil; + li:objects { + ha:text.42 { + string=Standard SMT resistor, capacitor etc; x=343.5mil; y=243.5mil; scale=100; fid=0; direction=0; role=desc; + } + ha:text.43 { + string=R1; x=343.5mil; y=243.5mil; scale=100; fid=0; direction=0; role=name; + } + ha:text.44 { + string=1206; x=343.5mil; y=243.5mil; scale=100; fid=0; direction=0; role=value; + } + ha:line.46 { + x1=-599.948um; y1=-37.4mil; x2=23.62mil; y2=-37.4mil; thickness=8.0mil; clearance=0.0; + } + ha:line.47 { + x1=-599.948um; y1=0.94996mm; x2=23.62mil; y2=0.94996mm; thickness=8.0mil; clearance=0.0; + } + ha:pad.48 { + name=1; number=1; x1=-59.05mil; y1=-299.974um; x2=-59.05mil; y2=11.81mil; mask=1.452372mm; thickness=1.299972mm; clearance=20.0mil; + ha:flags { + square=1 + } + } + ha:pad.49 { + name=2; number=2; x1=1.49987mm; y1=-299.974um; x2=1.49987mm; y2=11.81mil; mask=1.452372mm; thickness=1.299972mm; clearance=20.0mil; + ha:flags { + square=1 + } + } + } + } + ha:element.73 { + x=700.0mil; y=350.0mil; + li:objects { + ha:text.70 { + string=Standard SMT resistor, capacitor etc; x=668.5mil; y=243.5mil; scale=100; fid=0; direction=0; role=desc; + } + ha:text.71 { + string=R2; x=668.5mil; y=243.5mil; scale=100; fid=0; direction=0; role=name; + } + ha:text.72 { + string=1206; x=668.5mil; y=243.5mil; scale=100; fid=0; direction=0; role=value; + } + ha:line.74 { + x1=-599.948um; y1=-37.4mil; x2=23.62mil; y2=-37.4mil; thickness=8.0mil; clearance=0.0; + } + ha:line.75 { + x1=-599.948um; y1=0.94996mm; x2=23.62mil; y2=0.94996mm; thickness=8.0mil; clearance=0.0; + } + ha:pad.76 { + name=1; number=1; x1=-59.05mil; y1=-299.974um; x2=-59.05mil; y2=11.81mil; mask=1.452372mm; thickness=1.299972mm; clearance=20.0mil; + ha:flags { + square=1 + } + } + ha:pad.77 { + name=2; number=2; x1=1.49987mm; y1=-299.974um; x2=1.49987mm; y2=11.81mil; mask=1.452372mm; thickness=1.299972mm; clearance=20.0mil; + ha:flags { + square=1 + } + } + } + } + ha:element.81 { + x=375.0mil; y=600.0mil; + li:objects { + ha:text.78 { + string=Standard SMT resistor, capacitor etc; x=343.5mil; y=493.5mil; scale=100; fid=0; direction=0; role=desc; + } + ha:text.79 { + string=R3; x=343.5mil; y=493.5mil; scale=100; fid=0; direction=0; role=name; + } + ha:text.80 { + string=1206; x=343.5mil; y=493.5mil; scale=100; fid=0; direction=0; role=value; + } + ha:line.82 { + x1=-599.948um; y1=-37.4mil; x2=23.62mil; y2=-37.4mil; thickness=8.0mil; clearance=0.0; + } + ha:line.83 { + x1=-599.948um; y1=0.94996mm; x2=23.62mil; y2=0.94996mm; thickness=8.0mil; clearance=0.0; + } + ha:pad.84 { + name=1; number=1; x1=-59.05mil; y1=-299.974um; x2=-59.05mil; y2=11.81mil; mask=1.452372mm; thickness=1.299972mm; clearance=20.0mil; + ha:flags { + square=1 + } + } + ha:pad.85 { + name=2; number=2; x1=1.49987mm; y1=-299.974um; x2=1.49987mm; y2=11.81mil; mask=1.452372mm; thickness=1.299972mm; clearance=20.0mil; + ha:flags { + square=1 + } + } + } + } + ha:element.89 { + x=700.0mil; y=600.0mil; + li:objects { + ha:text.86 { + string=Standard SMT resistor, capacitor etc; x=593.5mil; y=631.5mil; scale=100; fid=0; direction=1; role=desc; + } + ha:text.87 { + string=R4; x=593.5mil; y=631.5mil; scale=100; fid=0; direction=1; role=name; + } + ha:text.88 { + string=1206; x=593.5mil; y=631.5mil; scale=100; fid=0; direction=1; role=value; + } + ha:line.90 { + x1=-37.4mil; y1=-599.948um; x2=-37.4mil; y2=23.62mil; thickness=8.0mil; clearance=0.0; + } + ha:line.91 { + x1=0.94996mm; y1=-599.948um; x2=0.94996mm; y2=23.62mil; thickness=8.0mil; clearance=0.0; + } + ha:pad.92 { + name=1; number=1; x1=-299.974um; y1=1.49987mm; x2=11.81mil; y2=1.49987mm; mask=1.452372mm; thickness=1.299972mm; clearance=20.0mil; + ha:flags { + square=1 + } + } + ha:pad.93 { + name=2; number=2; x1=-299.974um; y1=-59.05mil; x2=11.81mil; y2=-59.05mil; mask=1.452372mm; thickness=1.299972mm; clearance=20.0mil; + ha:flags { + square=1 + } + } + } + } + } + li:layers { + + ha:component { + lid=0 + group=3 + ha:combining { } + visible=1 + + li:objects { + ha:line.94 { + x1=434.05mil; y1=350.0mil; x2=640.95mil; y2=350.0mil; thickness=10.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.97 { + x1=8.02513mm; y1=350.0mil; x2=8.02513mm; y2=600.0mil; thickness=10.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.100 { + x1=434.05mil; y1=600.0mil; x2=475.0mil; y2=600.0mil; thickness=10.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.103 { + x1=475.0mil; y1=600.0mil; x2=550.0mil; y2=675.0mil; thickness=10.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.112 { + x1=550.0mil; y1=675.0mil; x2=675.0mil; y2=675.0mil; thickness=10.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.115 { + x1=700.0mil; y1=540.95mil; x2=700.0mil; y2=525.0mil; thickness=10.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.118 { + x1=700.0mil; y1=525.0mil; x2=775.0mil; y2=450.0mil; thickness=10.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.127 { + x1=775.0mil; y1=450.0mil; x2=775.0mil; y2=350.0mil; thickness=10.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + } + } + + ha:solder { + lid=1 + group=8 + ha:combining { } + visible=1 + } + + ha:comp-GND { + lid=2 + group=3 + ha:combining { } + visible=1 + } + + ha:comp-power { + lid=3 + group=3 + ha:combining { } + visible=1 + } + + ha:sold-GND { + lid=4 + group=8 + ha:combining { } + visible=1 + } + + ha:sold-power { + lid=5 + group=8 + ha:combining { } + visible=1 + } + + ha:signal3 { + lid=6 + group=5 + ha:combining { } + visible=1 + + li:objects { + ha:line.209 { + x1=150.0mil; y1=825.0mil; x2=150.0mil; y2=825.0mil; thickness=50.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + selected=1 + } + ha:attributes { + pnp-origin=yes + } + } + } + } + + ha:outline { + lid=7 + group=7 + ha:combining { } + visible=1 + + li:objects { + ha:arc.195 { + x=500.0mil; y=475.0mil; width=350.0mil; height=350.0mil; astart=0; adelta=-90; thickness=10.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.197 { + x=500.0mil; y=475.0mil; width=350.0mil; height=350.0mil; astart=90; adelta=-90; thickness=10.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.198 { + x=500.0mil; y=475.0mil; width=350.0mil; height=350.0mil; astart=180; adelta=-90; thickness=10.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.199 { + x=500.0mil; y=475.0mil; width=350.0mil; height=350.0mil; astart=270; adelta=-90; thickness=10.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + } + } + + ha:silk { + lid=8 + group=10 + ha:combining { auto=1; } + visible=1 + } + + ha:silk { + lid=9 + group=1 + ha:combining { auto=1; } + visible=1 + } + } + } + + ha:netlists { + li:input { + } + } + ha:layer_stack { + li:groups { + ha:0 { + name = top paste + ha:type { top=1; paste=1; } + li:layers { } + } + ha:1 { + name = top silk + ha:type { silk=1; top=1; } + li:layers { 9; } + } + ha:2 { + name = top mask + ha:type { top=1; mask=1; } + li:layers { } + } + ha:3 { + name = top copper + ha:type { copper=1; top=1; } + li:layers { 0; 2; 3; } + } + ha:4 { + ha:type { substrate=1; intern=1; } + li:layers { } + name = grp_4 + } + ha:5 { + name = Intern + ha:type { copper=1; intern=1; } + li:layers { 6; } + } + ha:6 { + ha:type { substrate=1; intern=1; } + li:layers { } + name = grp_6 + } + ha:7 { + name = global outline + ha:type { outline=1; intern=1; } + li:layers { 7; } + } + ha:8 { + name = bottom copper + ha:type { bottom=1; copper=1; } + li:layers { 1; 4; 5; } + } + ha:9 { + name = bottom mask + ha:type { bottom=1; mask=1; } + li:layers { } + } + ha:10 { + name = bottom silk + ha:type { silk=1; bottom=1; } + li:layers { 8; } + } + ha:11 { + name = bottom paste + ha:type { bottom=1; paste=1; } + li:layers { } + } + } + } + li:pcb-rnd-conf-v1 { + ha:overwrite { + ha:design { + min_ring = 10.00 mil + clearance = 20.00 mil + via_thickness = 2000.00 um + via_drilling_hole = 31.50 mil + min_slk = 7.00 mil + max_height = 1000.00 mil + line_thickness = 10.00 mil + shrink = 9.00 mil + poly_isle_area = 199999999.999200 + max_width = 1000.00 mil + min_wid = 10.00 mil + bloat = 12.00 mil + min_drill = 15.00 mil + } + ha:editor { + buffer_number = 0 + grid_unit = mil + } + } + } +} Index: tags/2.1.2/doc/tutorials/pnp-origin/orig_sq.lht =================================================================== --- tags/2.1.2/doc/tutorials/pnp-origin/orig_sq.lht (nonexistent) +++ tags/2.1.2/doc/tutorials/pnp-origin/orig_sq.lht (revision 24813) @@ -0,0 +1,445 @@ +ha:pcb-rnd-board-v2 { + + ha:attributes { + {PCB::grid::unit}=mil + } + + li:styles { + ha:Signal { + diameter = 1.999996mm + thickness = 10.0mil + hole = 31.5mil + clearance = 20.0mil + } + ha:Power { + diameter = 2.199894mm + thickness = 20.0mil + hole = 0.999998mm + clearance = 20.0mil + } + ha:Fat { + diameter = 137.8mil + thickness = 80.0mil + hole = 47.24mil + clearance = 25.0mil + } + ha:Sig-tight { + diameter = 64.0mil + thickness = 10.0mil + hole = 31.5mil + clearance = 12.0mil + } + } + + ha:meta { + ha:size { + thermal_scale = 0.500000 + x = 1000.0mil + y = 1000.0mil + isle_area_nm2 = 199999999.999200 + } + ha:cursor { + zoom = 0.000000 + x = 25.0mil + y = 625.0mil + } + ha:drc { + min_drill = 15.0mil + min_ring = 10.0mil + bloat = 12.0mil + shrink = 9.0mil + min_width = 10.0mil + min_silk = 7.0mil + } + ha:grid { + spacing = 25.0mil + offs_x = 0.0 + offs_y = 0.0 + } + } + + ha:data { + + li:objects { + ha:element.45 { + x=375.0mil; y=350.0mil; + li:objects { + ha:text.42 { + string=Standard SMT resistor, capacitor etc; x=343.5mil; y=243.5mil; scale=100; fid=0; direction=0; role=desc; + } + ha:text.43 { + string=R1; x=343.5mil; y=243.5mil; scale=100; fid=0; direction=0; role=name; + } + ha:text.44 { + string=1206; x=343.5mil; y=243.5mil; scale=100; fid=0; direction=0; role=value; + } + ha:line.46 { + x1=-599.948um; y1=-37.4mil; x2=23.62mil; y2=-37.4mil; thickness=8.0mil; clearance=0.0; + } + ha:line.47 { + x1=-599.948um; y1=0.94996mm; x2=23.62mil; y2=0.94996mm; thickness=8.0mil; clearance=0.0; + } + ha:pad.48 { + name=1; number=1; x1=-59.05mil; y1=-299.974um; x2=-59.05mil; y2=11.81mil; mask=1.452372mm; thickness=1.299972mm; clearance=20.0mil; + ha:flags { + square=1 + } + } + ha:pad.49 { + name=2; number=2; x1=1.49987mm; y1=-299.974um; x2=1.49987mm; y2=11.81mil; mask=1.452372mm; thickness=1.299972mm; clearance=20.0mil; + ha:flags { + square=1 + } + } + } + } + ha:element.73 { + x=700.0mil; y=350.0mil; + li:objects { + ha:text.70 { + string=Standard SMT resistor, capacitor etc; x=668.5mil; y=243.5mil; scale=100; fid=0; direction=0; role=desc; + } + ha:text.71 { + string=R2; x=668.5mil; y=243.5mil; scale=100; fid=0; direction=0; role=name; + } + ha:text.72 { + string=1206; x=668.5mil; y=243.5mil; scale=100; fid=0; direction=0; role=value; + } + ha:line.74 { + x1=-599.948um; y1=-37.4mil; x2=23.62mil; y2=-37.4mil; thickness=8.0mil; clearance=0.0; + } + ha:line.75 { + x1=-599.948um; y1=0.94996mm; x2=23.62mil; y2=0.94996mm; thickness=8.0mil; clearance=0.0; + } + ha:pad.76 { + name=1; number=1; x1=-59.05mil; y1=-299.974um; x2=-59.05mil; y2=11.81mil; mask=1.452372mm; thickness=1.299972mm; clearance=20.0mil; + ha:flags { + square=1 + } + } + ha:pad.77 { + name=2; number=2; x1=1.49987mm; y1=-299.974um; x2=1.49987mm; y2=11.81mil; mask=1.452372mm; thickness=1.299972mm; clearance=20.0mil; + ha:flags { + square=1 + } + } + } + } + ha:element.81 { + x=375.0mil; y=600.0mil; + li:objects { + ha:text.78 { + string=Standard SMT resistor, capacitor etc; x=343.5mil; y=493.5mil; scale=100; fid=0; direction=0; role=desc; + } + ha:text.79 { + string=R3; x=343.5mil; y=493.5mil; scale=100; fid=0; direction=0; role=name; + } + ha:text.80 { + string=1206; x=343.5mil; y=493.5mil; scale=100; fid=0; direction=0; role=value; + } + ha:line.82 { + x1=-599.948um; y1=-37.4mil; x2=23.62mil; y2=-37.4mil; thickness=8.0mil; clearance=0.0; + } + ha:line.83 { + x1=-599.948um; y1=0.94996mm; x2=23.62mil; y2=0.94996mm; thickness=8.0mil; clearance=0.0; + } + ha:pad.84 { + name=1; number=1; x1=-59.05mil; y1=-299.974um; x2=-59.05mil; y2=11.81mil; mask=1.452372mm; thickness=1.299972mm; clearance=20.0mil; + ha:flags { + square=1 + } + } + ha:pad.85 { + name=2; number=2; x1=1.49987mm; y1=-299.974um; x2=1.49987mm; y2=11.81mil; mask=1.452372mm; thickness=1.299972mm; clearance=20.0mil; + ha:flags { + square=1 + } + } + } + } + ha:element.89 { + x=700.0mil; y=600.0mil; + li:objects { + ha:text.86 { + string=Standard SMT resistor, capacitor etc; x=593.5mil; y=631.5mil; scale=100; fid=0; direction=1; role=desc; + } + ha:text.87 { + string=R4; x=593.5mil; y=631.5mil; scale=100; fid=0; direction=1; role=name; + } + ha:text.88 { + string=1206; x=593.5mil; y=631.5mil; scale=100; fid=0; direction=1; role=value; + } + ha:line.90 { + x1=-37.4mil; y1=-599.948um; x2=-37.4mil; y2=23.62mil; thickness=8.0mil; clearance=0.0; + } + ha:line.91 { + x1=0.94996mm; y1=-599.948um; x2=0.94996mm; y2=23.62mil; thickness=8.0mil; clearance=0.0; + } + ha:pad.92 { + name=1; number=1; x1=-299.974um; y1=1.49987mm; x2=11.81mil; y2=1.49987mm; mask=1.452372mm; thickness=1.299972mm; clearance=20.0mil; + ha:flags { + square=1 + } + } + ha:pad.93 { + name=2; number=2; x1=-299.974um; y1=-59.05mil; x2=11.81mil; y2=-59.05mil; mask=1.452372mm; thickness=1.299972mm; clearance=20.0mil; + ha:flags { + square=1 + } + } + } + } + } + li:layers { + + ha:component { + lid=0 + group=3 + ha:combining { } + visible=1 + + li:objects { + ha:line.94 { + x1=434.05mil; y1=350.0mil; x2=640.95mil; y2=350.0mil; thickness=10.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.97 { + x1=8.02513mm; y1=350.0mil; x2=8.02513mm; y2=600.0mil; thickness=10.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.100 { + x1=434.05mil; y1=600.0mil; x2=475.0mil; y2=600.0mil; thickness=10.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.103 { + x1=475.0mil; y1=600.0mil; x2=550.0mil; y2=675.0mil; thickness=10.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.112 { + x1=550.0mil; y1=675.0mil; x2=675.0mil; y2=675.0mil; thickness=10.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.115 { + x1=700.0mil; y1=540.95mil; x2=700.0mil; y2=525.0mil; thickness=10.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.118 { + x1=700.0mil; y1=525.0mil; x2=775.0mil; y2=450.0mil; thickness=10.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.127 { + x1=775.0mil; y1=450.0mil; x2=775.0mil; y2=350.0mil; thickness=10.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + } + } + + ha:solder { + lid=1 + group=8 + ha:combining { } + visible=1 + } + + ha:comp-GND { + lid=2 + group=3 + ha:combining { } + visible=1 + } + + ha:comp-power { + lid=3 + group=3 + ha:combining { } + visible=1 + } + + ha:sold-GND { + lid=4 + group=8 + ha:combining { } + visible=1 + } + + ha:sold-power { + lid=5 + group=8 + ha:combining { } + visible=1 + } + + ha:signal3 { + lid=6 + group=5 + ha:combining { } + visible=1 + + li:objects { + ha:line.136 { + x1=150.0mil; y1=875.0mil; x2=150.0mil; y2=875.0mil; thickness=50.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + ha:attributes { + pnp-origin=yes + } + } + } + } + + ha:outline { + lid=7 + group=7 + ha:combining { } + visible=1 + + li:objects { + ha:line.50 { + x1=150.0mil; y1=150.0mil; x2=150.0mil; y2=875.0mil; thickness=10.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.53 { + x1=150.0mil; y1=875.0mil; x2=925.0mil; y2=875.0mil; thickness=10.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.56 { + x1=925.0mil; y1=875.0mil; x2=925.0mil; y2=150.0mil; thickness=10.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.59 { + x1=925.0mil; y1=150.0mil; x2=150.0mil; y2=150.0mil; thickness=10.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + } + } + + ha:silk { + lid=8 + group=10 + ha:combining { auto=1; } + visible=1 + } + + ha:silk { + lid=9 + group=1 + ha:combining { auto=1; } + visible=1 + } + } + } + + ha:netlists { + li:input { + } + } + ha:layer_stack { + li:groups { + ha:0 { + name = top paste + ha:type { top=1; paste=1; } + li:layers { } + } + ha:1 { + name = top silk + ha:type { silk=1; top=1; } + li:layers { 9; } + } + ha:2 { + name = top mask + ha:type { top=1; mask=1; } + li:layers { } + } + ha:3 { + name = top copper + ha:type { copper=1; top=1; } + li:layers { 0; 2; 3; } + } + ha:4 { + ha:type { substrate=1; intern=1; } + li:layers { } + } + ha:5 { + name = Intern + ha:type { copper=1; intern=1; } + li:layers { 6; } + } + ha:6 { + ha:type { substrate=1; intern=1; } + li:layers { } + } + ha:7 { + name = global outline + ha:type { outline=1; intern=1; } + li:layers { 7; } + } + ha:8 { + name = bottom copper + ha:type { bottom=1; copper=1; } + li:layers { 1; 4; 5; } + } + ha:9 { + name = bottom mask + ha:type { bottom=1; mask=1; } + li:layers { } + } + ha:10 { + name = bottom silk + ha:type { silk=1; bottom=1; } + li:layers { 8; } + } + ha:11 { + name = bottom paste + ha:type { bottom=1; paste=1; } + li:layers { } + } + } + } + li:pcb-rnd-conf-v1 { + ha:overwrite { + ha:design { + min_ring = 10.00 mil + clearance = 20.00 mil + via_thickness = 2000.00 um + via_drilling_hole = 31.50 mil + min_slk = 7.00 mil + max_height = 1000.00 mil + line_thickness = 10.00 mil + shrink = 9.00 mil + poly_isle_area = 199999999.999200 + max_width = 1000.00 mil + min_wid = 10.00 mil + bloat = 12.00 mil + min_drill = 15.00 mil + } + ha:editor { + buffer_number = 0 + } + } + } +} Index: tags/2.1.2/doc/user/01_intro/Makefile =================================================================== --- tags/2.1.2/doc/user/01_intro/Makefile (nonexistent) +++ tags/2.1.2/doc/user/01_intro/Makefile (revision 24813) @@ -0,0 +1,2 @@ +flow.svg: src/flow.dot + dot -Tsvg src/flow.dot > flow.svg Index: tags/2.1.2/doc/user/01_intro/flow.svg =================================================================== --- tags/2.1.2/doc/user/01_intro/flow.svg (nonexistent) +++ tags/2.1.2/doc/user/01_intro/flow.svg (revision 24813) @@ -0,0 +1,135 @@ + + + + + + +flow + + +sch + +schematics editor +e.g. gschem + + +pcb + +pcb-rnd + + +sch->pcb + + +fwd annotation + + +pcb->sch + + +back annotation + + +fab + +fab house + + +pcb->fab + + +e.g. gerber, bom, xy + + +tt + +etching at home: +toner transfer + + +pcb->tt + + +e.g. ps or png + + +web + +web page + + +pcb->web + + +e.g. svg + + +doc + +printed +documentation + + +pcb->doc + + +e.g. ps, eps, png, jpg + + +kicad + +collaboration with +someone using kicad + + +pcb->kicad + + + +kicad's +native format + + +gpcb + +collaboration with +someone using gEDA/PCB + + +pcb->gpcb + + + +gEDA +native format + + +lib + +local footprint +library + + +lib->pcb + + + +.fp + + +wlib + +remote footprint +library (e.g. on the web) + + +wlib->pcb + + +import footprint + + + Index: tags/2.1.2/doc/user/01_intro/history.html =================================================================== --- tags/2.1.2/doc/user/01_intro/history.html (nonexistent) +++ tags/2.1.2/doc/user/01_intro/history.html (revision 24813) @@ -0,0 +1,45 @@ + + + + pcb-rnd user manual + + + + +

pcb-rnd History

+

pcb-rnd is a rapid moving independent project started in 2013, but roots +tracing back to the early 90s, to PCB. + +

+From the pcb.html documentation: +


+	Pcb was first written by Thomas Nau for an
+	Atari ST in 1990 and ported to UNIX and X11 in
+	1994.  It was not intended as a professional layout system, but as a tool
+	which supports people who do some home-developing of hardware.
+
+ +

In Fall 2013, Tibor 'Igor2' Palinkas started an +unofficial fork of PCB to make and +share random changes and improvements (hence the name "-rnd"). Over +the following years the fork was officially announced, adopted additional +users, and reached various milestones, including modularization of the code +base, a better configuration system. +

+In 2015, the project switched pace: lot of hours invested and many new developers +and contributors joined, pcb-rnd started to grow rapidly. Most of the code base +has been extended, cleaned up or rewritten. +

+In 2016 and 2017 pcb-rnd went on growig in number of developers, contributors +and users. The number of long standing bugs and misfeatures fixed and missing +features implemented grew a lot too. This affected major components +as the plugin system, the I/O (file format support) subsystem and even the +data model pcb-rnd operates on. +

+At the moment, pcb-rnd is not part of any EDA suite. +

+A more complete history can be found in the +pcb-history project. + + + Index: tags/2.1.2/doc/user/01_intro/index.html =================================================================== --- tags/2.1.2/doc/user/01_intro/index.html (nonexistent) +++ tags/2.1.2/doc/user/01_intro/index.html (revision 24813) @@ -0,0 +1,70 @@ + + + + pcb-rnd user manual + + + + +

pcb-rnd - user manual

+ +

1. Introduction

+

+pcb-rnd is a highly modular, interactive Printed Circuit Board editor +with a very long history . + + +

1.1. Place in the workflow

+

+The main purpose of pcb-rnd is to edit the geometry of the board. This +includes board shape, copper shape, layer stackup, holes drilled, slots +routed. +

+The input of the layout process is usually a netlist derived from +schematics, and occasionally layouts drawn from scratch or created from +schematic without importable netlist. Pcb-rnd can read different netlist +formats and it can help the user to realize the given netlist in copper or to +change the netlist and back annotate the changes. Pcb-rnd, however, does not +display or edit schematics directly. +

+The output of pcb-rnd is most often a vector format (e.g. gerber +RS274D), that is sent to a pcb fab house for manufacturing or is utilized for +auto-fabrication. Pcb-rnd supports a variety of vector and raster output +formats making it easy to print boards, publish them on web pages, and include +them in documentation. +

+The typical workflows are: +

+[workflow diagram showing pcb-rnd interacting with schematics editor, fabrication, and others] +

+Black flows are the most commonly used; grey flows are possible, fully +supported but less often used in practice. + +

1.2. What pcb-rnd is and is not

+

+Pcb-rnd is a versatile tool for PCB layout design. It is geared to be +a tool for users with the UNIX mind set: +

    +
  • it is small, easy to compile and run, has low resource footprint +
  • it is modular - most features are in plugins, the user can chose which plugins to use +
  • it is portable - also runs on systems that are not hyped today +
  • it works well from both CLI (automation, e.g. called from a Makefile or even using with an interactive action command shell) and GUI +
  • it is designed to communicate with other software: +
      +
    • it is easy to remote control +
    • it speaks many file formats +
    +
  • it doesn't outsmart the user, it doesn't block the user from doing unusual things; it has support for checking the result and generate warnings +
+

+There are a few things that are out of scope for pcb-rnd: +

    +
  • 3d editing: pcb-rnd is 2.5d, that means it's basically 2d and understands the 3rd dimension partially; it does load, handle and export 3d data (e.g. subcircuit part models for an openscad export) but it does not edit 3d data +
  • embedded <whatever-non-pcb-editing>: as a UNIX tool, pcb-rnd focuses on one thing, pcb edition, and relies on (and maintains close cooperation with) other tools for: +
      +
    • circuit schematics edition +
    • 3d rendering +
    • simulation +
    +
  • autorouting - there's a basic built-in autorouter, but it's recommended to use external autorouters (various file formats are supported) +
Index: tags/2.1.2/doc/user/01_intro/src/flow.dot =================================================================== --- tags/2.1.2/doc/user/01_intro/src/flow.dot (nonexistent) +++ tags/2.1.2/doc/user/01_intro/src/flow.dot (revision 24813) @@ -0,0 +1,45 @@ +digraph flow { + rankdir=LR + + subgraph in { + rank=same + sch [label="schematics editor\ne.g. gschem"] + } + + subgraph edit { + rank=same + pcb [label="pcb-rnd" shape=octagon width=2 height=2] + lib [label="local footprint\nlibrary"] + wlib [label="remote footprint\nlibrary (e.g. on the web)" color=grey fontcolor=grey] + } + + + subgraph out { + rank=same + fab [label="fab house"] + tt [label="etching at home:\ntoner transfer"] + web [label="web page"] + doc [label="printed\ndocumentation"] + } + + subgraph edit { + rank=same + kicad [label="collaboration with\nsomeone using kicad" color=grey fontcolor=grey] + gpcb [label="collaboration with\nsomeone using gEDA/PCB" color=grey fontcolor=grey] + } + + + sch -> pcb [label="fwd annotation"] + pcb -> sch [label="back annotation" color=grey fontcolor=grey] + pcb -> fab [label="e.g. gerber, bom, xy"] + pcb -> tt [label="e.g. ps or png"] + pcb -> web [label="e.g. svg"] + pcb -> doc [label="e.g. ps, eps, png, jpg"] + + lib -> pcb [label=".fp" dir=both weight=1000] + + wlib -> pcb [label="import footprint" dir=back color=grey fontcolor=grey] + + pcb -> kicad [label="kicad's\nnative format" dir=both color=grey fontcolor=grey] + pcb -> gpcb [label="gEDA\nnative format" dir=both color=grey fontcolor=grey] +} Index: tags/2.1.2/doc/user/02_model/index.html =================================================================== --- tags/2.1.2/doc/user/02_model/index.html (nonexistent) +++ tags/2.1.2/doc/user/02_model/index.html (revision 24813) @@ -0,0 +1,615 @@ + + + + pcb-rnd user manual + + + + +

pcb-rnd - user manual

+ +

2. Model of the world

+

+Pcb-rnd is designed to handle the geometric data of a PCB. This section describes +how pcb-rnd represents reality (e.g. copper shapes) in memory. + +

2.1. Board

+

+Each design pcb-rnd handles is a board. The board has global properties and hosts +layers. Most drawing primitives (objects) are on layers. This section describes +the most important global properties. +

+Board size is given as a width and a height. For rectangular boards +this can be the real board size, but more commonly it is used to simply +determine the on-screen drawing area and the final board dimensions are +specified using boundary layer groups. If the board is not rectangular, the +contour must be specified on boundary layers and the board size must be +large enough that the outline fits in it. +

+Netlist is the list of logical connections to be realized in copper. +A netlist is a list of named nets. Each net consists of a list of +terminals (pins or pads) to connect. A terminal is given as +refdes-pinname, e.g. U4-7 means "pin number 7 in subcircuit called U4". +

+Fonts are always embedded in the design file in order to guarantee +that the file can be ported and will look the same on different hosts. +

+Misc editor settings, such as grid size and offset. + +

2.2. Layers

+

+The main use of pcb-rnd is to aide the user in the process of producing real +pcbs composed of real physical layers. pcb-rnd also refers to layers to +conceptualize this process, but pcb-rnd layers are different than the +physical layers. +

+Unlike a physical layer, a pcb-rnd layer has no thickness. Any pcb-rnd +layer is always part of a layer group. It is a 2 dimensional logical +canvas, similar to layers in image manipulation software like GIMP. In pcb-rnd +there are explicit, virtual or implicit layers. An +explicit layer contains drawing primitives (objects) +placed by the user. The user has full control over an explicit layer: objects +can be added or removed or changed any time. A virtual or implicit layer has no +such flexibility: pcb-rnd computes its content from explicit layers and there's +no way for the user to change the result directly. +

+Pcb-rnd currently maintains some layers types as virtual layers for +compatibility with the PCB package. In a pcb-rnd board design started from +default configuration options, the mask, silk, and paste layers currently start +out as virtual layers. The content for these layers is computed by pcb-rnd as +for a virtual or explicit layer, until the user decides to use features that +require user control over one or more of the layers in the group. At that +point, the virtual layer is replaced with an explicit layer group. +

+For example, in pcb-rnd when using one of the gtk GUIs, if the user right +clicks on a solder mask ('mask') layer and choose an option to 'insert new +layer before this one', pcb-rnd replaces the virtual mask layer with an explicit +mask layer group. The mask layer group can contain one to many pcb-rnd layers +each with individual settings to control implicit generation, and additive or +subtractive behavior when adding objects to the layers. + +

2.3. Layer Groups

+

+One or more explicit layers form a layer group. All pcb-rnd layers +of a layer group will end up on the same physical layer. The visibility of +layers in a layer group are toggled together. Having more than one layer +in a group may be useful to: +

    +
  • exploit that layers have different + drawing color on screen: + e.g. there can be a signal and a gnd layers with different color in + the same layer group, on the same physical layer. +
  • on composite-groups (mask, paste, silk), layers are combined using + their properties: some layers may draw, others may clear; some layers + may contain auto-generated objects. The order of layers does matter + in draw-clear combinations. +
+

+Since layer groups donate the physical layers, a board stack-up +is built of layer groups. Substrates are layer groups without drawable +layers in them. The mask, paste, silk layer groups behave the same and +can host zero or more logical layers. +

+Each layer group has a main type. Main types are: +

    +
  • copper for signal layers +
  • silk for silkscreen layers +
  • mask for solder masks +
  • paste for solder paste + +
  • boundary for the contour of the board +
  • mech mechanical information (e.g. cutouts, slots, adhesive; sent to the board fab) +
  • doc documentation and metadata (not sent to the board fab) +
+

+Each layer group has a location. Locations are: +

    +
  • top (used to be the "component side" in the age of thru-hole components) +
  • bottom (used to be the "solder side" in the age of thru-hole components) +
  • intern (sandwiched between other layers) +
  • global (affects all physical layers, thus has no specific location) +
+

+Not all combination of type and location are supported: e.g. for a boundary +layer group the location is always global. The table below lists whether a +combination is supported or not. +

+ +
Layer Combination Support +
  top bottom intern global composite +
copper yes yes yes no no +
silk yes yes no no yes +
mask yes yes no no yes +
paste yes yes no no yes +
boundary no no no yes no +
mech yes yes yes yes maybe +
doc yes yes yes yes maybe +
+

+Note: for some layer types whether compositing is allowed depends on the +subtype (purpose). +

+Each layer group has a purpose field, which functions as a +subtype. The value is a free form text for user defined groups, but pcb-rnd +recognizes (and handles specially) the following combinations: +

+ +
Layer purpose combination recongized +
main type purpose special meaning +
boundary uroute unplated, routed bounary: routed outline of the board +
boundary proute plated, routed bounary: routed outline of the board with copper plating +
mech uroute unplated, routed inner cutout: unplated slots and small inner cutouts, done with drilling or routing or punch-through +
mech proute plated, routed inner cutout: plated slots and small inner cutouts, done with drilling or routing or punch-through (typical for oval/rectanglar pins) +
+ +

2.4. Basic Drawing Objects

+

+Pcb-rnd supports a small number of basic drawing objects, from which complex +objects can be build. The following figure demonstrates all basic objects: +

+ +[Arc, Line, Polygon, Pin, Via] +

+Objects have flags that control their behavior. The following flags are common +to all objects: +

+ +
Object Flags +
name description +
selected selected by the user ("cyan") +
found found as a galvanic connection in the last connection lookup ("green") +
warn offending object e.g. in a short circuit ("orange") +
lock locked by the user: can't be selected, moved or changed using the basic mouse/keyboard actions (still can be copied, selected by query() and edited by propedit()) +
+ + +

2.4.1. Line Objects

+

+Lines are round ended straight line segments with a width and +a clearance. The above image shows 3 lines connected. Lines are mainly +used to construct traces. A line is always on a specific layer. The user +interface allows drawing lines aligned to 90 or 45 degree axes or +lines with random angle. +

+A line is specified by its two endpoints, width and clearance: +

+[Line interacting with a polygon] +

+A clearance is the gap between a line and the surrounding polygon +in the same layer group. The gap is made only if the surrounding polygon has +the "clearpoly" flag set and the line has the "clearline" flag set. If either +of these flags is not set, no gap is made - or in pcb-rnd terminology, +the line is joined to the polygon. +

+ +
Line Object Flags +
name description +
clearline clears polygons with the "clearpoly" flag in the same layer group +
+ +

2.4.2. Arc Objects

+

+Arcs are round ended circular arcs with trace width and clearance. They +behave like lines in all respects. +

+[Arc interacting with a polygon] +

+Although the arc is described with its center, radius, start and end +angles, the user interface may offer drawing arcs by endpoints. +

+ +
Arc Object Flags +
name description +
clearline clears polygons with the "clearpoly" flag in the same layer group +
+ +

2.4.3. Polygon Objects

+

+Polygons are solid, filled copper areas with optional holes in them. Polygon +contour consists of lines - when they look curvy, its really high resolution +line approximation. There are two type of holes in a polygon: explicit, +user drawn holes and clearance cutouts. User drawn holes are "negative" +polygons drawn manually. To keep polygons simple, if an user drawn hole +touches the contour of a polygon, the hole is removed and the contour is +modified; if two holes touch, they are merged into one hole. +

+If the polygon has the "clearpoly" flag set (default), clearance cutouts are +automatically inserted around objects on the same layer group: +

    +
  • lines and arcs, if they have the "clearline" flag set (default) +
  • padstacks, if they are not connected to the polygon by thermals +
+

+Overlapping or touching polygons are not automatically merged. An object +with the "clearline" flag set will clear all "clearpolys" it is over - +if there are multiple such polygons overlapping under the objects (on +the same layer group), all such polygons get the clearance cutout. +

+If a polygon has the "clearpolypoly" flag set, it clears any other polygon +that does not have the "clearpolypoly" flag set but has the +"clearpoly" set. In other words, a "clearpolypoly" polygon behaves the same +as a line/arc that has the "clearline" flag. +

+If a polygon is cut into multiple islands, the behavior depends on the +"fullpoly" flag of the polygon. If it is not set (default), only the largest +island is kept, else all islands are kept. In the "fullpoly" mode islands +will have no galvanic connection (unless the user adds vias and connect them +on another layer), still the program will handle all islands as a single +polygon. This is risky: the program will indicate connection between polygon +islands that are not really connected, only because they are part of the same +polygon! +

+

+ +
Polygon Object Flags +
name description +
clearpoly should have clearance around objects, if the objects have the appropriate flags too +
fullpoly keep all islands, not only the largest +
+ +

2.4.4. Text Objects

+

+A text object is string and a series of symbols (pcb-rnd's terminology for +glyph). Symbols are built of lines and are stored in the font. Each board +can have its own font, but there can be only one font per board. When +the string of the text is edited, the object is rendered again so that the +new string appears. +

+Text objects can be placed on copper and silk layers. Text can be rotated +only in 90 degree steps. Each text object has a scale parameter that +determines its size in percentage. A scale of 100% means symbols are +rendered in 1:1 size. +

+The clearance around text is rendered as a round corner rectangular cutout. +Bug: copper text can not participate in short circuits, the galvanic connection +checker code skips texts. + +

2.4.5. Subcircuits

+

+A subc (subcircuit) is a group of objects with its own, local layer +information. All layers of a subc are bound layers, that is, the user +is free to choose on which actual board layer it is placed on. +There is no limitation on what layers or objects a subc can contain. +

+The main uses of subc are: +

    +
  • footprint +
  • copy&paste anonymous repetitive section of a circuit +
+ +
2.4.5.1 Subcircuits as footprints
+ +

+A subcircuit may be an instance (copy) of a footprint. The subcircuit is +placed on the board or loaded into a paste buffer (the footprint lives in +the footprint library). + +

+In the footprint form the construct is small and flexible. It describes +all the physical parts, like pins, pads, silk lines. In the same time a +footprint leaves many details blank, e.g. it doesn't specify exact layers, +it doesn't have font and the refdes is random. + +

+When the footprint is loaded, it becomes an subcircuit. The subcircuit inherits all +the physical properties and the blank details are filled in with the data taken +from the current board: the layer binding is done, all parts of the subcircuit +lands on a specific board layer; the refdes is rendered using the font in +the current board. + +

+The footprint -> subcircuit instantiation is also a copy. Once the subcircuit +is created from a footprint, the subcircuit is a self-containing object and +does not have any direct reference to the footprint it was once derived from. +Changes to the original footprint will not affect the subcircuits. + +

+In other words, a footprint is an abstract recipe, part of a +library, while an subcircuit is a land pattern already embedded in a +specific design and describes actual copper and silk. + +

+Currently a subcircuit or footprint can contain any object on any layer +that a board can contain. The only notable limitation (that applies to boards too) +is that there is no good way to represent plated slotting. +

+Commonly used subcircuit attributes: +

+ +
Element Properties +
subcircuit attribute description +
name: refdes unique identifier, e.g. "C42" - pcb-rnd code will use this when present +
name: value informal value, e.g. "15 pF" +
name: footprint informal footprint description, e.g. "1206" +
+

+If the nonetlist flag is set, the subcircuit is not intended to be +part of the netlist + +

+When a subcircuit is a footprint, it normally has the refdes attribute set. +Refdes is the name that identifies the part on the netlist. Some objects +of a footprint will have the term attribute to turn those object into +terminals (representing pins or pads). If multiple objects have the same +term attribute value, they are all contributing to the same terminal. +

+When the terminal object is a single padstack, it is called a +light terminal. When the terminal is built using multiple objects, +it is called a heavy terminal. +

+A connection on the netlist is identified as refdes-term, e.g. +U5-3 means "the object(s) whose term attribute is 3 within the subcircuit +whose refdes attribute is 'U5'". + +

2.4.5.2 Subcircuits as repetitive modules
+

+If the repetitive module is specified as a refdes-named device on +the schematics, it is really just a footprint. Else it is a non-footprint +subcircuit. +

+Compared to subcircuits as footprint, a non-footprint subcircuit will not have +a refdes attribute and will not have terminals. It will also have the +nonetlist flag set. + +

2.4.6. Pad stacks

+

+A pad stack is a generic pin/pad/via object that may contain any combination +of: +

    +
  • a hole (plated or unplated, thru-hole or blind/buried) +
  • a pad shape that can be different on each layer group type +
  • thermal relief info on a per layer basis +
+

+Pad stacks are flexible enough to cover the majority of the simple pin/pad/via +cases. In a subcircuit, marked as a terminal, a pad stack is called a +light terminal. This concept exist in parallel to the heavy terminal +concept: a heavy terminal consists of multiple objects (e.g. polygons, lines, +arcs, pad stacks), all tagged to the same terminal. When the pad stack model +is not capable to describe a complicated pin or pad, the user should chose the +heavy terminal model. A typical example is the center pad of a QFN footprint +with vias for heat transfer and a specific pattern of paste. The strength +of a pad stack is it's relative simplicity and that all objects on the vertical +stack are bundled together; the strength of the heavy model is its flexibility: +anything that can be drawn on board can be turned into a heavy terminal. +

+The optional hole of the pad stack is useful if the pad stack is to be used +as a mounting hole, via or pin. The span of the hole is described by two +integers: how far the hole starts and ends from the top or bottom copper +layer group, counted in copper layer groups. +

+A simple all-way-thru hole's span is 0;0, which means it starts at the +top copper group and ends on the bottom copper group. Or precisely, +"starts 0 groups down from top copper group and spans until 0 groups up +from the bottom group". That is, when hol span values are positive, +the top of the hole is counted from the top copper group down and the +bottom of the hole is counted from the bottom group up. If a span value +is negative, it is counted from the other side, e.g. a 0;-3 means: +"hole top is 0 groups down from top copper group, hole bottom is 3 groups +down from the top copper group". Or in other words, the topmost four copper +layer groups are connected by the via. +

+The plating of the hole is a boolean and is independent of any +other parameter. +

+For each layer group type, the user may specify zero or one pad shape. + +
Pad stack layer group types +
name remarks +
top silk   +
top paste   +
top mask the first negative layer is used +
top copper   +
intern copper the same pad will be used on all internal copper groups +
bottom copper   +
bottom mask the first negative layer is used +
bottom paste   +
bottom silk   +
+

+ +
Pad shapes +
name description +
fillcircle x;y offset of the center, diameter +
line round or square cap, from x1;y1 to x2;y2 with the specified thickness +
simple-polygon a simple polygon has a single outer contour and no holes +
hshadow n/a +
+

+Pad shape hshadow is a special construct: when drawing a clearance around +the shape, it pretends to be a copy of the hole or slot shape, but it never +has any visible (positive) effect on the target layer. Typical use is inner +layer clearance around a via that should not have a copper ring on that layer. +

+The pad stack has an origin, a 0;0 point where it is grabbed. If the pad stack +features a hole, the origin is the center point of the hole. Pad shapes are +all defined in a way that they do not have to be concentric with the hole or +the origin. This allows asymmetric pads. +

+In case of blind/buried vias, the internal copper layer pads are applied +only on layers with hole span. However, this does not apply to top/bottom +shapes, those are always explicit. This means it is possible to use a pad stack +as a pad-pair of an board edge connector, having a copper pad on the top +layer and one on the bottom layer, even without having a (plated) hole in between. +The code will assume connection between the pads only if the pad stack has a +plated hole. +

+If the global clearance is set, it overrides the per layer type +clearance and the padstack will have the same global clearance on all +layer groups on which it has copper objects. +

+ +
Typical pad stack examples +
name description +
rectangular smd pad no hole; square cap line or polygon on top copper, top mask and top paste +
simple pin or via plated hole and the same filled circle on all copper layers; if pin, a slightly bigger circle on the mask layers +
octagon pin or via plated hole and the same simple polygon (octagon shaped) on all copper layers; if pin, a slightly bigger polygon on the mask layers +
'oblong' pin plated hole, a short round cap line segment on the bottom copper and mask layers, filled circle on all other copper layers and on the top mask layer +
blind via plated hole and the same filled circle on internal and top copper layers - nothing on the bottom copper layer +
power jack with slot n/a - can not be done with pad stack as the plated slots for the pins can not be represented as plated round holes - use heavy terminals instead +
+

+Pad stack prototypes (templates) are stored only once per pcb_data_t (only once per +board for vias or per each subcircuit for terminals). The actual pad stacks +placed on the board (or in subcircuit) are called pad stack references. +A pad stack reference has its own x;y coordinate (within the board or +subcircuit), a rotation angle and a mirror flag. This means if a TQFP chip +has 48 pads along 4 sides, in the simplest setup there will be onlt one pad +stack prototype and 48 pad stack references using the same prototype with +different coordinates and rotations. +

+Each padstack reference has an optional global clearance; if it is +non-zero, this value is used as clearance on all layers for this instance. +When it is zero, the prototype's per shape clearance applies, which makes it +possible to have different clearance for internal layers, for example. +

+Each padstack reference has a per board layer list of thermal relief types. +

+A thermal relief property is added to the copper rings of a via when it is +connected to the surrounding polygon of any individual layer. Physical designs +may use thermal reliefs to enable easy hand soldering, or reduce occurrence of +tombstoning in automated production. +

+The following thermal relief options are available: + +
Pad/Pin/Via Thermal Relief +
Thermal Relief Appearance +
no connection unconnected via +
solid solid thermal +
round x 90 Thermal relief arc style +
round x 45 Thermal relief arc style, 45deg +
crossbar x 90 Thermal relief crossbar style, 90deg +
crossbar x 45 Thermal relief crossbar style, 45deg +
+ + +

2.4.7. Rat line Objects

+

+A rat line represents a logical connection that is not yet realized in copper. +It requires a loaded netlist for generation, and relies on calculations for any +existing copper layers that connect terminals on the pcb-rnd board. Rat +connections are straight line connections between the terminals of any two +drawing primitives that aren't yet connected + +

2.4.8 Netlists

+

+A netlist is a list of named logical networks. Each network is a list of +netlist terminals that should be connected. A netlist terminal is a pair +of subcircuit-refdes and pin-number (or pad-number). Thus a typical netlist +looks like the following: +

    +
  • net: GND +
      +
    • U1-2 +
    • U2-7 +
    • U3-7 +
    • C1-1 +
    +
  • net: Vcc +
      +
    • U1-3 +
    • U2-14 +
    • U3-14 +
    • C1-2 +
    +
  • net: strobe +
      +
    • U2-2 +
    • U3-5 +
    +
+

+The netlist assumes subcircuit refdes are unique. If a subcircuit has multiple +instances of the same terminal number, the engine picks one randomly and +assumes there's an invisible, internal connection within the subcircuit. +

+Rat lines can be regenerated from the current netlist for missing connections. +Connections that are realized in copper but not present on the netlist, pcb-rnd +gives a "short circuit" warning. Both happens when the net is "optimized" +(upon user request). +

+The netlist is typically derived from a schematics by external tools +(such as gnetlist). The netlist can be imported (updated) any time. This +process is called "forward annotation". +

+It is also possible to make changes to the netlist from within pcb-rnd: +terminals can be swapped, subcircuit footprint replaced using back annotation +actions. Such actions will keep a list of intended netlist and subcircuit +changes, called the netlist patch. Pcb-rnd will keep these changes even +if a new version of the netlist is imported. It is possible to export the +netlist patch that can be imported in the schematics editor to change the +schematics - this process is called "back annotation". A new forward +annotation from the schematics editor to pcb-rnd will then cancel +the netlist/subcircuit changes as the new netlist import netlist matches +the intended (changed) netlist. + +

2.5. Non-objects

+

+The following objects are commonly used in the industry, but have no +special implementation in pcb-rnd but are created by using the above +objects. + +

Vias

+

+A via is an electrically connected hole that connects copper rings to multiple +layers. In pcb-rnd, a via is always implemented using a +padstack. + +

Holes

+

+A hole is a special case of a padstack: it has +an unplated hole and typically does not have copper pad shapes but should +have mask cutout shape. + +

Test points, test pads

+

+A test point or test pad is a padstack that has +copper shape only on one of the outer copper layer and a mask cutout shape +over that layer. + +

Fiducials

+

+A fiducial mark is a special case of a padstack +very similar to the test point/pad. + +

Targets/marks

+A mark or target (e.g. for layer alignment) is usually realized as a + subcircuit it has more complex graphics that +doesn't fit in a padstack. + +

Using subcircuit instead of raw padstack

+

+Holes, test points/pads and fiducials are often realized within a + subcircuit , especially if they have a refdes +and present on the schematics. However, the only way to implement a hole +is using a padstack, so the resulting subcircuit for holes and test pins +will always have at least one padstack. + +

2.6. Comparison of Physical world and pcb-rnd world terminology

+

+ +
Pcb-rnd Terminology +
Physical board pcb-rnd Description +
Layer Layer Group enables the user to design complex physical constructions +
Copper layer Layer group with copper layers designed with one to many pcb-rnd layers +
Component/Top copper layer Layer group with copper layers any group of copper layers defined as the 'top' of a board +
Solder/bottom copper layer Layer group with copper layers any group of copper layers defined as the 'bottom' of a board +
Substrate Layer group marked as substrate, hosting no logical layers pcb-rnd does not yet handle properties of physical substrate information +
Contour of the board Outline layer designed using standard pcb-rnd objects +
Outline routing path Outline layer designed using standard pcb-rnd objects +
Polygon pour Polygon an object available for design in any layer group +
Plane Polygon see above +
Mask (solder mask) Layer group with implicit and potential explicit content design layers available: automatic, additive, subtractive +
Silk Layer group with implicit and potential explicit content design layers available: automatic, additive, subtractive +
Paste (paste stencil) Layer group with implicit and potential explicit content design layers available: automatic, additive, subtractive +
N/A, or poss. net/circuit Rats assistive layer automatically generated with netlist and copper layer group connection data +
Via Padstack a vertical construction that features a plated hole and copper pads around the hole +
Pin Padstack a special via that is going to host a pin of a through-hole component soldered on the board +
Pad Padstack a copper feature that is going to host a lead of an surface mount component +
Hole, mounting hole Padstack special case of vias, with no plating or copper pads +
Fiducial mark, test pad Padstack special case of pad +
Element, module, part (on board) Subcircuit a placed instance of a library footprint +
Footprint, land pattern Footprint reusable patterns stored in the footprint library +
+ Index: tags/2.1.2/doc/user/02_model/obj_arc.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/user/02_model/obj_arc.png =================================================================== --- tags/2.1.2/doc/user/02_model/obj_arc.png (nonexistent) +++ tags/2.1.2/doc/user/02_model/obj_arc.png (revision 24813) Property changes on: tags/2.1.2/doc/user/02_model/obj_arc.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/user/02_model/obj_line.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/user/02_model/obj_line.png =================================================================== --- tags/2.1.2/doc/user/02_model/obj_line.png (nonexistent) +++ tags/2.1.2/doc/user/02_model/obj_line.png (revision 24813) Property changes on: tags/2.1.2/doc/user/02_model/obj_line.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/user/02_model/objects_basic.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/user/02_model/objects_basic.png =================================================================== --- tags/2.1.2/doc/user/02_model/objects_basic.png (nonexistent) +++ tags/2.1.2/doc/user/02_model/objects_basic.png (revision 24813) Property changes on: tags/2.1.2/doc/user/02_model/objects_basic.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/user/02_model/objects_complex.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/user/02_model/objects_complex.png =================================================================== --- tags/2.1.2/doc/user/02_model/objects_complex.png (nonexistent) +++ tags/2.1.2/doc/user/02_model/objects_complex.png (revision 24813) Property changes on: tags/2.1.2/doc/user/02_model/objects_complex.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/user/02_model/src/Makefile =================================================================== --- tags/2.1.2/doc/user/02_model/src/Makefile (nonexistent) +++ tags/2.1.2/doc/user/02_model/src/Makefile (revision 24813) @@ -0,0 +1,68 @@ +PCBRND=pcb-rnd +CLEANFILES= ../*.png + +all: ../objects_basic.png ../objects_complex.png ../obj_line.png \ + ../obj_arc.png ../via_therm_noconn.png ../via_therm_solid.png \ + ../via_therm_round_x90.png ../via_therm_round_x45.png \ + ../via_therm_sharp_x90.png ../via_therm_sharp_x45.png + +../objects_basic.png: objects_basic.lht + $(PCBRND) -x png --dpi 450 objects_basic.lht + mv objects_basic.png ../objects_basic.png + +../objects_complex.png: objects_complex.lht + $(PCBRND) -x png --dpi 450 objects_complex.lht + mv objects_complex.png ../objects_complex.png + +../obj_line.png: obj_line.lht + $(PCBRND) -x png --dpi 450 obj_line.lht + mv obj_line.png ../obj_line.png + +../obj_arc.png: obj_arc.lht + $(PCBRND) -x png --dpi 450 obj_arc.lht + mv obj_arc.png ../obj_arc.png + +../via_therm_noconn.png: via_therm_noconn.lht + $(PCBRND) -x png --dpi 450 via_therm_noconn.lht + mv via_therm_noconn.png ../ + +# make thermal style images +../via_therm_solid.png: via_therm_solid.lht + $(PCBRND) -x png --dpi 450 via_therm_solid.lht + mv via_therm_solid.png ../ + +../via_therm_round_x90.png: via_therm_round_x90.lht + $(PCBRND) -x png --dpi 450 via_therm_round_x90.lht + mv via_therm_round_x90.png ../ + +../via_therm_round_x45.png: via_therm_round_x45.lht + $(PCBRND) -x png --dpi 450 via_therm_round_x45.lht + mv via_therm_round_x45.png ../ + +../via_therm_sharp_x90.png: via_therm_sharp_x90.lht + $(PCBRND) -x png --dpi 450 via_therm_sharp_x90.lht + mv via_therm_sharp_x90.png ../ + +../via_therm_sharp_x45.png: via_therm_sharp_x45.lht + $(PCBRND) -x png --dpi 450 via_therm_sharp_x45.lht + mv via_therm_sharp_x45.png ../ + +#make shapes for shape table +via_ring_shape.png: via_ring_shape.lht + $(PCBRND) -x png --dpi 450 via_ring_shape.lht + mv via_ring_shape.png ../ + +via_square_shape.png: via_square_shape.lht + $(PCBRND) -x png --dpi 450 via_square_shape.lht + mv via_square_shape.png ../ + +via_octagon_shape.png: via_octagon_shape.lht + $(PCBRND) -x png --dpi 450 via_octagon_shape.lht + mv via_octagon_shape.png ../ + +via_asym_shape.png: via_asym_shape.lht + $(PCBRND) -x png --dpi 450 via_asym_shape.lht + mv via_asym_shape.png ../ + +clean: $(CLEANRULES) + -rm $(CLEANFILES) Index: tags/2.1.2/doc/user/02_model/src/obj_arc.lht =================================================================== --- tags/2.1.2/doc/user/02_model/src/obj_arc.lht (nonexistent) +++ tags/2.1.2/doc/user/02_model/src/obj_arc.lht (revision 24813) @@ -0,0 +1,384 @@ +ha:pcb-rnd-board-v1 { + + ha:attributes { + {PCB::loader}=geda/pcb - nanometer + {PCB::grid::unit}=mil + {PCB::conf::editor/grid}=25.00 mil + {PCB::conf::editor/draw_grid}=true + {PCB::conf::editor/buffer_number}=0 + } + + li:styles { + ha:Signal { + diameter = 1.999996mm + thickness = 10.0mil + hole = 31.5mil + clearance = 20.0mil + } + ha:Power { + diameter = 2.199894mm + thickness = 20.0mil + hole = 0.999998mm + clearance = 20.0mil + } + ha:Fat { + diameter = 137.8mil + thickness = 80.0mil + hole = 47.24mil + clearance = 25.0mil + } + ha:Sig-tight { + diameter = 64.0mil + thickness = 10.0mil + hole = 31.5mil + clearance = 12.0mil + } + } + + ha:meta { + ha:size { + thermal_scale = 0.500000 + x = 1.4in + y = 31.75mm + isle_area_nm2 = 199999999.999200 + } + ha:cursor { + zoom = 0.000000 + x = 0.0 + y = 0.0 + } + ha:drc { + min_drill = 15.0mil + min_ring = 10.0mil + bloat = 12.0mil + shrink = 9.0mil + min_width = 10.0mil + min_silk = 7.0mil + } + ha:grid { + spacing = 25.0mil + offs_x = 0.0 + offs_y = 0.0 + } + } + + ha:data { + li:objects { + } + li:layers { + + ha:component { + visible=1 + group=0 + + li:objects { + ha:arc.3 { + x=26.67mm; y=27.305mm; width=400.0mil; height=400.0mil; astart=-90; adelta=90; thickness=75.0mil; clearance=48.0mil; + ha:flags { + clearline=1 + } + } + ha:polygon.4 { + li:geometry { + ta:contour { + { 725.0mil; 550.0mil } + { 31.75mm; 550.0mil } + { 31.75mm; 900.0mil } + { 725.0mil; 900.0mil } + } + } + + ha:flags { + clearpoly=1 + } + } + } + } + + ha:solder { + visible=1 + group=1 + } + + ha:comp-GND { + visible=1 + group=0 + } + + ha:comp-power { + visible=1 + group=0 + } + + ha:sold-GND { + visible=1 + group=1 + } + + ha:sold-power { + visible=1 + group=1 + } + + ha:signal3 { + visible=1 + group=2 + } + + ha:outline { + visible=1 + group=3 + } + + ha:silk { + visible=1 + group=1 + } + + ha:silk { + visible=1 + group=0 + + li:objects { + ha:line.9 { + x1=26.67mm; y1=26.67mm; x2=26.67mm; y2=1.1in; thickness=10.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.12 { + x1=26.035mm; y1=27.305mm; x2=27.305mm; y2=27.305mm; thickness=10.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.15 { + x1=29.21mm; y1=1.175in; x2=26.67mm; y2=27.305mm; thickness=10.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.18 { + x1=1.35in; y1=1.175in; x2=29.21mm; y2=1.175in; thickness=10.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.21 { + x1=26.67mm; y1=27.305mm; x2=675.0mil; y2=950.0mil; thickness=10.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.24 { + x1=625.0mil; y1=750.0mil; x2=800.0mil; y2=925.0mil; thickness=10.0mil; clearance=24.0mil; + ha:flags { + clearline=1 + } + } + ha:line.27 { + x1=625.0mil; y1=750.0mil; x2=350.0mil; y2=750.0mil; thickness=10.0mil; clearance=24.0mil; + ha:flags { + clearline=1 + } + } + ha:line.30 { + x1=875.0mil; y1=825.0mil; x2=650.0mil; y2=600.0mil; thickness=10.0mil; clearance=24.0mil; + ha:flags { + clearline=1 + } + } + ha:line.33 { + x1=650.0mil; y1=600.0mil; x2=325.0mil; y2=600.0mil; thickness=10.0mil; clearance=24.0mil; + ha:flags { + clearline=1 + } + } + ha:line.36 { + x1=675.0mil; y1=27.305mm; x2=0.0; y2=27.305mm; thickness=10.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.39 { + x1=26.67mm; y1=700.0mil; x2=26.67mm; y2=25.0mil; thickness=10.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.42 { + x1=150.0mil; y1=27.305mm; x2=150.0mil; y2=1.225in; thickness=10.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.45 { + x1=650.0mil; y1=26.67mm; x2=650.0mil; y2=1.1in; thickness=10.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.48 { + x1=26.035mm; y1=675.0mil; x2=27.305mm; y2=675.0mil; thickness=10.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.51 { + x=26.67mm; y=27.305mm; width=1000.0mil; height=1000.0mil; astart=-90; adelta=90; thickness=10.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:polygon.58 { + li:geometry { + ta:contour { + { 17.594013mm; 20.769012mm } + { 657.3223622mil; 18.972961mm } + { 15.797962mm; 19.870987mm } + } + } + + ha:flags { + clearpoly=1 + } + } + ha:polygon.62 { + li:geometry { + ta:contour { + { 18.600987mm; 21.775988mm } + { 19.499012mm; 23.572039mm } + { 20.397038mm; 22.674013mm } + } + } + + ha:flags { + clearpoly=1 + } + } + ha:polygon.66 { + li:geometry { + ta:contour { + { 19.753013mm; 18.483012mm } + { 742.3223622mil; 16.686961mm } + { 17.956962mm; 17.584987mm } + } + } + + ha:flags { + clearpoly=1 + } + } + ha:polygon.70 { + li:geometry { + ta:contour { + { 19.870987mm; 18.600988mm } + { 20.769012mm; 20.397039mm } + { 21.667038mm; 19.499013mm } + } + } + + ha:flags { + clearpoly=1 + } + } + ha:polygon.74 { + li:geometry { + ta:contour { + { 690.0mil; 955.0mil } + { 19.109758mm; 25.491476mm } + { 19.533695mm; 24.29432mm } + } + } + + ha:flags { + clearpoly=1 + } + } + ha:polygon.78 { + li:geometry { + ta:contour { + { 3.809999mm; 27.178001mm } + { 3.174999mm; 1.145in } + { 4.444999mm; 1.145in } + } + } + + ha:flags { + clearpoly=1 + } + } + ha:polygon.82 { + li:geometry { + ta:contour { + { 26.796999mm; 1.904999mm } + { 980.0mil; 1.269999mm } + { 980.0mil; 2.539999mm } + } + } + + ha:flags { + clearpoly=1 + } + } + ha:polygon.86 { + li:geometry { + ta:contour { + { 1.270001mm; 27.431999mm } + { 1.905001mm; 25.527mm } + { 0.635001mm; 25.527mm } + } + } + + ha:flags { + clearpoly=1 + } + } + ha:text.52 { + string=center; x=1.175in; y=1.1in; scale=100; direction=0; + ha:flags { + clearline=1 + } + } + ha:text.53 { + string=width; x=375.0mil; y=675.0mil; scale=100; direction=0; + ha:flags { + clearline=1 + } + } + ha:text.54 { + string=R; x=850.0mil; y=950.0mil; scale=100; direction=0; + ha:flags { + clearline=1 + } + } + ha:text.55 { + string=clearance; x=350.0mil; y=525.0mil; scale=100; direction=0; + ha:flags { + clearline=1 + } + } + ha:text.56 { + string=delta angle; x=625.0mil; y=0.0; scale=100; direction=0; + ha:flags { + clearline=1 + } + } + ha:text.57 { + string=start angle; x=175.0mil; y=29.21mm; scale=100; direction=0; + ha:flags { + clearline=1 + } + } + } + } + } + } + + +ha:netlists { + + li:input { + } +} +} Index: tags/2.1.2/doc/user/02_model/src/obj_line.lht =================================================================== --- tags/2.1.2/doc/user/02_model/src/obj_line.lht (nonexistent) +++ tags/2.1.2/doc/user/02_model/src/obj_line.lht (revision 24813) @@ -0,0 +1,302 @@ +ha:pcb-rnd-board-v1 { + + ha:attributes { + {PCB::loader}=geda/pcb - nanometer + {PCB::grid::unit}=mil + {PCB::conf::editor/grid}=25.00 mil + {PCB::conf::editor/draw_grid}=true + {PCB::conf::editor/buffer_number}=0 + } + + li:styles { + ha:Signal { + diameter = 1.999996mm + thickness = 10.0mil + hole = 31.5mil + clearance = 20.0mil + } + ha:Power { + diameter = 2.199894mm + thickness = 20.0mil + hole = 0.999998mm + clearance = 20.0mil + } + ha:Fat { + diameter = 137.8mil + thickness = 80.0mil + hole = 47.24mil + clearance = 25.0mil + } + ha:Sig-tight { + diameter = 64.0mil + thickness = 10.0mil + hole = 31.5mil + clearance = 12.0mil + } + } + + ha:meta { + ha:size { + thermal_scale = 0.500000 + x = 30.48mm + y = 850.0mil + isle_area_nm2 = 199999999.999200 + } + ha:cursor { + zoom = 0.000000 + x = 25.0mil + y = 275.0mil + } + ha:drc { + min_drill = 15.0mil + min_ring = 10.0mil + bloat = 12.0mil + shrink = 9.0mil + min_width = 10.0mil + min_silk = 7.0mil + } + ha:grid { + spacing = 25.0mil + offs_x = 0.0 + offs_y = 0.0 + } + } + + ha:data { + li:objects { + } + li:layers { + + ha:component { + visible=1 + group=0 + + li:objects { + ha:line.5 { + x1=475.0mil; y1=675.0mil; x2=800.0mil; y2=350.0mil; thickness=110.0mil; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:polygon.8 { + li:geometry { + ta:contour { + { 600.0mil; 175.0mil } + { 1.125in; 175.0mil } + { 1.125in; 525.0mil } + { 600.0mil; 525.0mil } + } + } + + ha:flags { + clearpoly=1 + } + } + } + } + + ha:solder { + visible=1 + group=1 + } + + ha:comp-GND { + visible=1 + group=0 + } + + ha:comp-power { + visible=1 + group=0 + } + + ha:sold-GND { + visible=1 + group=1 + } + + ha:sold-power { + visible=1 + group=1 + } + + ha:signal3 { + visible=1 + group=2 + } + + ha:outline { + visible=1 + group=3 + } + + ha:silk { + visible=1 + group=1 + } + + ha:silk { + visible=1 + group=0 + + li:objects { + ha:line.13 { + x1=525.0mil; y1=425.0mil; x2=750.0mil; y2=650.0mil; thickness=10.0mil; clearance=24.0mil; + ha:flags { + clearline=1 + } + } + ha:line.16 { + x1=525.0mil; y1=425.0mil; x2=250.0mil; y2=425.0mil; thickness=10.0mil; clearance=24.0mil; + ha:flags { + clearline=1 + } + } + ha:line.19 { + x1=575.0mil; y1=225.0mil; x2=250.0mil; y2=225.0mil; thickness=10.0mil; clearance=24.0mil; + ha:flags { + clearline=1 + } + } + ha:line.22 { + x1=800.0mil; y1=450.0mil; x2=575.0mil; y2=225.0mil; thickness=10.0mil; clearance=24.0mil; + ha:flags { + clearline=1 + } + } + ha:line.25 { + x1=475.0mil; y1=650.0mil; x2=475.0mil; y2=700.0mil; thickness=10.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.28 { + x1=450.0mil; y1=675.0mil; x2=500.0mil; y2=675.0mil; thickness=10.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.31 { + x1=800.0mil; y1=325.0mil; x2=800.0mil; y2=375.0mil; thickness=10.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.34 { + x1=775.0mil; y1=350.0mil; x2=825.0mil; y2=350.0mil; thickness=10.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.37 { + x1=475.0mil; y1=675.0mil; x2=375.0mil; y2=575.0mil; thickness=10.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.40 { + x1=375.0mil; y1=575.0mil; x2=25.0mil; y2=575.0mil; thickness=10.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.43 { + x1=800.0mil; y1=350.0mil; x2=550.0mil; y2=100.0mil; thickness=10.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.46 { + x1=550.0mil; y1=100.0mil; x2=200.0mil; y2=100.0mil; thickness=10.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:polygon.53 { + li:geometry { + ta:contour { + { 17.965987mm; 9.075988mm } + { 18.864012mm; 10.872039mm } + { 19.762038mm; 9.974013mm } + } + } + + ha:flags { + clearpoly=1 + } + } + ha:polygon.57 { + li:geometry { + ta:contour { + { 16.695987mm; 14.155988mm } + { 17.594012mm; 15.952039mm } + { 18.492038mm; 15.054013mm } + } + } + + ha:flags { + clearpoly=1 + } + } + ha:polygon.61 { + li:geometry { + ta:contour { + { 15.054013mm; 12.514012mm } + { 14.155988mm; 10.717961mm } + { 13.257962mm; 11.615987mm } + } + } + + ha:flags { + clearpoly=1 + } + } + ha:polygon.65 { + li:geometry { + ta:contour { + { 17.848013mm; 8.958012mm } + { 16.949988mm; 281.9669685mil } + { 16.051962mm; 8.059987mm } + } + } + + ha:flags { + clearpoly=1 + } + } + ha:text.49 { + string=width; x=275.0mil; y=350.0mil; scale=100; direction=0; + ha:flags { + clearline=1 + } + } + ha:text.50 { + string=clearance; x=275.0mil; y=150.0mil; scale=100; direction=0; + ha:flags { + clearline=1 + } + } + ha:text.51 { + string=1st endpoint; x=25.0mil; y=500.0mil; scale=100; direction=0; + ha:flags { + clearline=1 + } + } + ha:text.52 { + string=2nd endpoint; x=200.0mil; y=25.0mil; scale=100; direction=0; + ha:flags { + clearline=1 + } + } + } + } + } + } + + +ha:netlists { + + li:input { + } +} +} Index: tags/2.1.2/doc/user/02_model/src/objects_basic.lht =================================================================== --- tags/2.1.2/doc/user/02_model/src/objects_basic.lht (nonexistent) +++ tags/2.1.2/doc/user/02_model/src/objects_basic.lht (revision 24813) @@ -0,0 +1,242 @@ +ha:pcb-rnd-board-v1 { + + ha:attributes { + {PCB::loader}=geda/pcb - nanometer + {PCB::grid::unit}=mil + {PCB::conf::editor/buffer_number}=0 + {PCB::conf::editor/draw_grid}=true + } + + li:styles { + ha:Signal { + diameter = 1.999996mm + thickness = 10.0mil + hole = 31.5mil + clearance = 20.0mil + } + ha:Power { + diameter = 2.199894mm + thickness = 20.0mil + hole = 0.999998mm + clearance = 20.0mil + } + ha:Fat { + diameter = 137.8mil + thickness = 80.0mil + hole = 47.24mil + clearance = 25.0mil + } + ha:Sig-tight { + diameter = 64.0mil + thickness = 10.0mil + hole = 31.5mil + clearance = 12.0mil + } + } + + ha:meta { + ha:size { + thermal_scale = 0.500000 + x = 2.075in + y = 500.0mil + isle_area_nm2 = 199999999.999200 + } + ha:cursor { + zoom = 0.000000 + x = 225.0mil + y = 0.0 + } + ha:drc { + min_drill = 15.0mil + min_ring = 10.0mil + bloat = 12.0mil + shrink = 9.0mil + min_width = 10.0mil + min_silk = 7.0mil + } + ha:grid { + spacing = 25.0mil + offs_x = 0.0 + offs_y = 0.0 + } + } + + ha:data { + li:objects { + ha:via.3 { + x=1.6in; y=125.0mil; hole=47.24mil; mask=0.0; thickness=137.8mil; clearance=50.0mil; + ha:flags { + via=1 + } + } + ha:via.4 { + x=1.6in; y=350.0mil; hole=47.24mil; mask=0.0; thickness=137.8mil; clearance=50.0mil; + ha:flags { + via=1 + square=1 + shape=1 + } + } + ha:via.5 { + x=49.53mm; y=250.0mil; hole=47.24mil; mask=0.0; thickness=137.8mil; clearance=50.0mil; + ha:flags { + via=1 + square=1 + shape=17 + } + } + ha:via.6 { + x=45.085mm; y=125.0mil; hole=47.24mil; mask=0.0; thickness=137.8mil; clearance=50.0mil; + ha:flags { + via=1 + square=1 + shape=2 + } + } + ha:via.7 { + x=1.8in; y=350.0mil; hole=47.24mil; mask=0.0; thickness=137.8mil; clearance=50.0mil; + ha:flags { + via=1 + square=1 + shape=9 + } + } + } + li:layers { + + ha:component { + visible=1 + group=0 + + li:objects { + ha:line.16 { + x1=575.0mil; y1=75.0mil; x2=825.0mil; y2=75.0mil; thickness=80.0mil; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.19 { + x1=825.0mil; y1=75.0mil; x2=925.0mil; y2=175.0mil; thickness=80.0mil; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:line.22 { + x1=925.0mil; y1=175.0mil; x2=925.0mil; y2=400.0mil; thickness=80.0mil; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.25 { + x=425.0mil; y=425.0mil; width=350.0mil; height=350.0mil; astart=0; adelta=-90; thickness=80.0mil; clearance=50.0mil; + ha:flags { + clearline=1 + } + } + ha:polygon.42 { + li:geometry { + ta:contour { + { 26.67mm; 50.0mil } + { 31.75mm; 50.0mil } + { 1.375in; 175.0mil } + { 1.375in; 425.0mil } + { 26.67mm; 425.0mil } + } + ta:hole { + { 29.21mm; 225.0mil } + { 29.21mm; 300.0mil } + { 31.75mm; 300.0mil } + { 31.75mm; 175.0mil } + { 1.175in; 175.0mil } + { 29.21mm; 200.0mil } + } + } + + ha:flags { + clearpoly=1 + } + } + } + } + + ha:solder { + visible=1 + group=1 + } + + ha:comp-GND { + visible=1 + group=0 + } + + ha:comp-power { + visible=1 + group=0 + } + + ha:sold-GND { + visible=1 + group=1 + } + + ha:sold-power { + visible=1 + group=1 + } + + ha:signal3 { + visible=1 + group=2 + } + + ha:outline { + visible=1 + group=3 + } + + ha:silk { + visible=1 + group=1 + } + + ha:silk { + visible=1 + group=0 + + li:objects { + ha:text.44 { + string=Arc; x=275.0mil; y=425.0mil; scale=100; direction=0; + ha:flags { + clearline=1 + } + } + ha:text.45 { + string=Line; x=700.0mil; y=425.0mil; scale=100; direction=0; + ha:flags { + clearline=1 + } + } + ha:text.46 { + string=Polygon; x=1.125in; y=425.0mil; scale=100; direction=0; + ha:flags { + clearline=1 + } + } + ha:text.47 { + string=Pin, Via; x=1.65in; y=425.0mil; scale=100; direction=0; + ha:flags { + clearline=1 + } + } + } + } + } + } + + +ha:netlists { + + li:input { + } +} +} Index: tags/2.1.2/doc/user/02_model/src/objects_complex.lht =================================================================== --- tags/2.1.2/doc/user/02_model/src/objects_complex.lht (nonexistent) +++ tags/2.1.2/doc/user/02_model/src/objects_complex.lht (revision 24813) @@ -0,0 +1,182 @@ +ha:pcb-rnd-board-v1 { + + ha:attributes { + {PCB::loader}=geda/pcb - nanometer + {PCB::grid::unit}=mil + {PCB::conf::editor/buffer_number}=0 + {PCB::conf::editor/draw_grid}=true + } + + li:styles { + ha:Signal { + diameter = 1.999996mm + thickness = 10.0mil + hole = 31.5mil + clearance = 20.0mil + } + ha:Power { + diameter = 2.199894mm + thickness = 20.0mil + hole = 0.999998mm + clearance = 20.0mil + } + ha:Fat { + diameter = 137.8mil + thickness = 80.0mil + hole = 47.24mil + clearance = 25.0mil + } + ha:Sig-tight { + diameter = 64.0mil + thickness = 10.0mil + hole = 31.5mil + clearance = 12.0mil + } + } + + ha:meta { + ha:size { + thermal_scale = 0.500000 + x = 850.0mil + y = 500.0mil + isle_area_nm2 = 199999999.999200 + } + ha:cursor { + zoom = 0.000000 + x = 225.0mil + y = 0.0 + } + ha:drc { + min_drill = 15.0mil + min_ring = 10.0mil + bloat = 12.0mil + shrink = 9.0mil + min_width = 10.0mil + min_silk = 7.0mil + } + ha:grid { + spacing = 25.0mil + offs_x = 0.0 + offs_y = 0.0 + } + } + + ha:data { + li:objects { + ha:element.81 { + x=600.0mil; y=250.0mil; + li:objects { + ha:text.78 { + string=Standard SMT resistor, capacitor etc; x=568.5mil; y=143.5mil; scale=100; direction=0; role=desc; + } + ha:text.79 { + string=R1; x=568.5mil; y=143.5mil; scale=100; direction=0; role=name; + } + ha:text.80 { + string=1206; x=568.5mil; y=143.5mil; scale=100; direction=0; role=value; + } + ha:line.82 { + x1=-599.948um; y1=-37.4mil; x2=23.62mil; y2=-37.4mil; thickness=8.0mil; clearance=0.0; + } + ha:line.83 { + x1=-599.948um; y1=0.94996mm; x2=23.62mil; y2=0.94996mm; thickness=8.0mil; clearance=0.0; + } + ha:pad.84 { + name=1; number=1; x1=-59.05mil; y1=-299.974um; x2=-59.05mil; y2=11.81mil; mask=1.452372mm; thickness=1.299972mm; clearance=20.0mil; + ha:flags { + square=1 + } + } + ha:pad.85 { + name=2; number=2; x1=1.49987mm; y1=-299.974um; x2=1.49987mm; y2=11.81mil; mask=1.452372mm; thickness=1.299972mm; clearance=20.0mil; + ha:flags { + square=1 + } + } + } + } + } + li:layers { + + ha:component { + visible=1 + group=0 + + li:objects { + ha:text.75 { + string=Hello; x=25.0mil; y=150.0mil; scale=245; direction=0; + ha:flags { + clearline=1 + } + } + } + } + + ha:solder { + visible=1 + group=1 + } + + ha:comp-GND { + visible=1 + group=0 + } + + ha:comp-power { + visible=1 + group=0 + } + + ha:sold-GND { + visible=1 + group=1 + } + + ha:sold-power { + visible=1 + group=1 + } + + ha:signal3 { + visible=1 + group=2 + } + + ha:outline { + visible=1 + group=3 + } + + ha:silk { + visible=1 + group=1 + } + + ha:silk { + visible=1 + group=0 + + li:objects { + ha:text.76 { + string=Text; x=100.0mil; y=425.0mil; scale=100; direction=0; + ha:flags { + clearline=1 + } + } + ha:text.77 { + string=Element, Pad; x=425.0mil; y=425.0mil; scale=100; direction=0; + ha:flags { + clearline=1 + } + } + } + } + } + } + +ha:netlists { + + li:input { + } +} +} Index: tags/2.1.2/doc/user/02_model/src/via_therm_noconn.lht =================================================================== --- tags/2.1.2/doc/user/02_model/src/via_therm_noconn.lht (nonexistent) +++ tags/2.1.2/doc/user/02_model/src/via_therm_noconn.lht (revision 24813) @@ -0,0 +1,267 @@ +ha:pcb-rnd-board-v2 { + + ha:attributes { + {PCB::grid::unit}=mil + {PCB::conf::editor/draw_grid}=true + {PCB::conf::editor/grid}=181.00 um + } + + li:styles { + ha:Signal { + diameter = 1.999996mm + thickness = 10.0mil + hole = 31.5mil + clearance = 20.0mil + } + ha:Power { + diameter = 2.199894mm + thickness = 20.0mil + hole = 0.999998mm + clearance = 20.0mil + } + ha:Fat { + diameter = 137.8mil + thickness = 80.0mil + hole = 47.24mil + clearance = 25.0mil + } + ha:Sig-tight { + diameter = 64.0mil + thickness = 10.0mil + hole = 31.5mil + clearance = 12.0mil + } + } + + ha:meta { + ha:size { + thermal_scale = 0.500000 + x = 300.0mil + y = 300.0mil + isle_area_nm2 = 199999999.999200 + } + ha:cursor { + zoom = 0.000000 + x = 225.0mil + y = 0.0 + } + ha:drc { + min_drill = 15.0mil + min_ring = 10.0mil + bloat = 12.0mil + shrink = 9.0mil + min_width = 10.0mil + min_silk = 7.0mil + } + ha:grid { + spacing = 10.0mil + offs_x = 0.245mm + offs_y = 0.064mm + } + } + + ha:data { + + li:objects { + ha:via.107 { + x=150mil; y=150mil; hole=47.24mil; mask=0.0; thickness=3.11912mm; clearance=50.0mil; + ha:flags { + via=1 + } + } + } + li:layers { + + ha:component { + lid=0 + group=3 + ha:combining { } + visible=1 + + li:objects { + ha:polygon.110 { + li:geometry { + ta:contour { + { 25.0mil; 25.0mil } + { 275.0mil; 25.0mil } + { 275.0mil; 275.0mil } + { 25.0mil; 275.0mil } + } + } + + ha:flags { + clearpoly=1 + } + } + } + } + + ha:solder { + lid=1 + group=8 + ha:combining { } + visible=1 + } + + ha:comp-GND { + lid=2 + group=3 + ha:combining { } + visible=1 + } + + ha:comp-power { + lid=3 + group=3 + ha:combining { } + visible=1 + } + + ha:sold-GND { + lid=4 + group=8 + ha:combining { } + visible=1 + } + + ha:sold-power { + lid=5 + group=8 + ha:combining { } + visible=1 + } + + ha:signal3 { + lid=6 + group=5 + ha:combining { } + visible=1 + } + + ha:outline { + lid=7 + group=7 + ha:combining { } + visible=1 + } + + ha:silk { + lid=8 + group=10 + ha:combining { auto=1; } + visible=1 + } + + ha:silk { + lid=9 + group=1 + ha:combining { auto=1; } + visible=1 + + li:objects { + ha:text.114 { + string=no conn.; x=1.994mm; y=5.877mm; scale=70; fid=0; direction=0; + ha:flags { + clearline=1 + } + } + } + } + } + } + + ha:netlists { + li:input { + } + } + ha:layer_stack { + li:groups { + ha:0 { + name = top paste + ha:type { top=1; paste=1; } + li:layers { } + } + ha:1 { + name = top silk + ha:type { silk=1; top=1; } + li:layers { 9; } + } + ha:2 { + name = top mask + ha:type { top=1; mask=1; } + li:layers { } + } + ha:3 { + name = top copper + ha:type { copper=1; top=1; } + li:layers { 0; 2; 3; } + } + ha:4 { + ha:type { substrate=1; intern=1; } + li:layers { } + name = grp_4 + } + ha:5 { + name = Intern + ha:type { copper=1; intern=1; } + li:layers { 6; } + } + ha:6 { + ha:type { substrate=1; intern=1; } + li:layers { } + name = grp_6 + } + ha:7 { + name = global outline + ha:type { outline=1; intern=1; } + li:layers { 7; } + } + ha:8 { + name = bottom copper + ha:type { bottom=1; copper=1; } + li:layers { 1; 4; 5; } + } + ha:9 { + name = bottom mask + ha:type { bottom=1; mask=1; } + li:layers { } + } + ha:10 { + name = bottom silk + ha:type { silk=1; bottom=1; } + li:layers { 8; } + } + ha:11 { + name = bottom paste + ha:type { bottom=1; paste=1; } + li:layers { } + } + } + } + li:pcb-rnd-conf-v1 { + ha:overwrite { + ha:design { + min_ring = 10.00 mil + clearance = 20.00 mil + text_font_id = 1 + text_scale = 5744 + via_thickness = 2000.00 um + via_drilling_hole = 31.50 mil + min_slk = 7.00 mil + max_height = 300.00 mil + line_thickness = 10.00 mil + shrink = 9.00 mil + poly_isle_area = 199999999.999200 + max_width = 300.00 mil + min_wid = 10.00 mil + bloat = 12.00 mil + min_drill = 15.00 mil + } + ha:editor { + grid_unit = mil + buffer_number = 0 + grid = 10.00 mil + } + } + } +} Index: tags/2.1.2/doc/user/02_model/src/via_therm_round_x45.lht =================================================================== --- tags/2.1.2/doc/user/02_model/src/via_therm_round_x45.lht (nonexistent) +++ tags/2.1.2/doc/user/02_model/src/via_therm_round_x45.lht (revision 24813) @@ -0,0 +1,287 @@ +ha:pcb-rnd-board-v2 { + + ha:attributes { + {PCB::conf::editor/grid}=181.00 um + {PCB::conf::editor/draw_grid}=true + {PCB::grid::unit}=mil + } + + li:styles { + ha:Signal { + diameter = 1.999996mm + thickness = 10.0mil + hole = 31.5mil + clearance = 20.0mil + } + ha:Power { + diameter = 2.199894mm + thickness = 20.0mil + hole = 0.999998mm + clearance = 20.0mil + } + ha:Fat { + diameter = 137.8mil + thickness = 80.0mil + hole = 47.24mil + clearance = 25.0mil + } + ha:Sig-tight { + diameter = 64.0mil + thickness = 10.0mil + hole = 31.5mil + clearance = 12.0mil + } + } + + ha:meta { + ha:size { + thermal_scale = 0.500000 + x = 300.0mil + y = 300.0mil + isle_area_nm2 = 199999999.999200 + } + ha:cursor { + zoom = 0.000000 + x = 225.0mil + y = 0.0 + } + ha:drc { + min_drill = 15.0mil + min_ring = 10.0mil + bloat = 12.0mil + shrink = 9.0mil + min_width = 10.0mil + min_silk = 7.0mil + } + ha:grid { + spacing = 0.181mm + offs_x = 0.0 + offs_y = 0.0 + } + } + + ha:data { + + li:objects { + ha:via.118 { + x=150mil; y=150mil; hole=47.24mil; mask=0.0; thickness=3.11912mm; clearance=50.0mil; + ha:flags { + ha:thermal { silk=diagonal-round; component=diagonal-round; } + via=1 + } + } + } + li:layers { + + ha:component { + lid=0 + group=3 + ha:combining { } + visible=1 + + li:objects { + ha:polygon.110 { + li:geometry { + ta:contour { + { 25.0mil; 25.0mil } + { 275.0mil; 25.0mil } + { 275.0mil; 275.0mil } + { 25.0mil; 275.0mil } + } + } + + ha:flags { + clearpoly=1 + } + } + } + } + + ha:solder { + lid=1 + group=8 + ha:combining { } + visible=1 + } + + ha:comp-GND { + lid=2 + group=3 + ha:combining { } + visible=1 + + } + + ha:comp-power { + lid=3 + group=3 + ha:combining { } + visible=1 + } + + ha:sold-GND { + lid=4 + group=8 + ha:combining { } + visible=1 + } + + ha:sold-power { + lid=5 + group=8 + ha:combining { } + visible=1 + } + + ha:signal3 { + lid=6 + group=5 + ha:combining { } + visible=1 + } + + ha:outline { + lid=7 + group=7 + ha:combining { } + visible=1 + } + + ha:silk { + lid=8 + group=10 + ha:combining { auto=1; } + visible=1 + } + + ha:silk { + lid=9 + group=1 + ha:combining { auto=1; } + visible=1 + + li:objects { + ha:text.126 { + string=Arc Thermal; x=0.873886mm; y=5.34154mm; scale=70; fid=0; direction=0; + ha:flags { + clearline=1 + } + } + ha:text.131 { + string=45; x=2.896mm; y=7.24mm; scale=5744; fid=0; direction=0; + ha:flags { + clearline=1 + } + } + ha:text.137 { + string=45; x=3.258mm; y=6.335mm; scale=65; fid=0; direction=0; + ha:flags { + clearline=1 + } + } + } + } + } + } + + + ha:netlists { + li:input { + } + } + ha:layer_stack { + li:groups { + ha:0 { + name = top paste + ha:type { top=1; paste=1; } + li:layers { } + } + ha:1 { + name = top silk + ha:type { silk=1; top=1; } + li:layers { 9; } + } + ha:2 { + name = top mask + ha:type { top=1; mask=1; } + li:layers { } + } + ha:3 { + name = top copper + ha:type { copper=1; top=1; } + li:layers { 0; 2; 3; } + } + ha:4 { + ha:type { substrate=1; intern=1; } + li:layers { } + name = grp_4 + } + ha:5 { + name = Intern + ha:type { copper=1; intern=1; } + li:layers { 6; } + } + ha:6 { + ha:type { substrate=1; intern=1; } + li:layers { } + name = grp_6 + } + ha:7 { + name = global outline + ha:type { outline=1; intern=1; } + li:layers { 7; } + } + ha:8 { + name = bottom copper + ha:type { bottom=1; copper=1; } + li:layers { 1; 4; 5; } + } + ha:9 { + name = bottom mask + ha:type { bottom=1; mask=1; } + li:layers { } + } + ha:10 { + name = bottom silk + ha:type { silk=1; bottom=1; } + li:layers { 8; } + } + ha:11 { + name = bottom paste + ha:type { bottom=1; paste=1; } + li:layers { } + } + } + } + li:pcb-rnd-conf-v1 { + ha:overwrite { + ha:design { + min_ring = 10.00 mil + clearance = 20.00 mil + text_font_id = 0 + text_scale = 100 + via_thickness = 2000.00 um + via_drilling_hole = 31.50 mil + min_slk = 7.00 mil + max_height = 300.00 mil + line_thickness = 10.00 mil + shrink = 9.00 mil + poly_isle_area = 199999999.999200 + max_width = 300.00 mil + min_wid = 10.00 mil + bloat = 12.00 mil + min_drill = 15.00 mil + } + ha:editor { + ha:view { + flip_x = 0 + flip_y = 0 + } + grid_unit = mil + buffer_number = 0 + show_solder_side = 0 + grid = 181.00 um + } + } + } +} Index: tags/2.1.2/doc/user/02_model/src/via_therm_round_x90.lht =================================================================== --- tags/2.1.2/doc/user/02_model/src/via_therm_round_x90.lht (nonexistent) +++ tags/2.1.2/doc/user/02_model/src/via_therm_round_x90.lht (revision 24813) @@ -0,0 +1,275 @@ +ha:pcb-rnd-board-v2 { + + ha:attributes { + {PCB::conf::editor/grid}=181.00 um + {PCB::conf::editor/draw_grid}=true + {PCB::grid::unit}=mil + } + + li:styles { + ha:Signal { + diameter = 1.999996mm + thickness = 10.0mil + hole = 31.5mil + clearance = 20.0mil + } + ha:Power { + diameter = 2.199894mm + thickness = 20.0mil + hole = 0.999998mm + clearance = 20.0mil + } + ha:Fat { + diameter = 137.8mil + thickness = 80.0mil + hole = 47.24mil + clearance = 25.0mil + } + ha:Sig-tight { + diameter = 64.0mil + thickness = 10.0mil + hole = 31.5mil + clearance = 12.0mil + } + } + + ha:meta { + ha:size { + thermal_scale = 0.500000 + x = 300.0mil + y = 300.0mil + isle_area_nm2 = 199999999.999200 + } + ha:cursor { + zoom = 0.000000 + x = 225.0mil + y = 0.0 + } + ha:drc { + min_drill = 15.0mil + min_ring = 10.0mil + bloat = 12.0mil + shrink = 9.0mil + min_width = 10.0mil + min_silk = 7.0mil + } + ha:grid { + spacing = 0.181mm + offs_x = 0.0 + offs_y = 0.0 + } + } + + ha:data { + + li:objects { + ha:via.118 { + x=150mil; y=150mil; hole=47.24mil; mask=0.0; thickness=3.11912mm; clearance=50.0mil; + ha:flags { + ha:thermal { component=horver-round; silk=diagonal-round; } + via=1 + } + } + } + li:layers { + + ha:component { + lid=0 + group=3 + ha:combining { } + visible=1 + + li:objects { + ha:polygon.149 { + li:geometry { + ta:contour { + { 25.0mil; 25.0mil } + { 275.0mil; 25.0mil } + { 275.0mil; 275.0mil } + { 25.0mil; 275.0mil } + } + } + + ha:flags { + clearpoly=1 + } + } + } + } + + ha:solder { + lid=1 + group=8 + ha:combining { } + visible=1 + } + + ha:comp-GND { + lid=2 + group=3 + ha:combining { } + visible=1 + + } + + ha:comp-power { + lid=3 + group=3 + ha:combining { } + visible=1 + } + + ha:sold-GND { + lid=4 + group=8 + ha:combining { } + visible=1 + } + + ha:sold-power { + lid=5 + group=8 + ha:combining { } + visible=1 + } + + ha:signal3 { + lid=6 + group=5 + ha:combining { } + visible=1 + } + + ha:outline { + lid=7 + group=7 + ha:combining { } + visible=1 + } + + ha:silk { + lid=8 + group=10 + ha:combining { auto=1; } + visible=1 + } + + ha:silk { + lid=9 + group=1 + ha:combining { auto=1; } + visible=1 + + li:objects { + ha:text.144 { + string=Arc Thermal; x=0.692886mm; y=5.70354mm; scale=75; fid=0; direction=0; + ha:flags { + clearline=1 + } + } + } + } + } + } + + + ha:netlists { + li:input { + } + } + ha:layer_stack { + li:groups { + ha:0 { + name = top paste + ha:type { top=1; paste=1; } + li:layers { } + } + ha:1 { + name = top silk + ha:type { silk=1; top=1; } + li:layers { 9; } + } + ha:2 { + name = top mask + ha:type { top=1; mask=1; } + li:layers { } + } + ha:3 { + name = top copper + ha:type { copper=1; top=1; } + li:layers { 0; 2; 3; } + } + ha:4 { + ha:type { substrate=1; intern=1; } + li:layers { } + name = grp_4 + } + ha:5 { + name = Intern + ha:type { copper=1; intern=1; } + li:layers { 6; } + } + ha:6 { + ha:type { substrate=1; intern=1; } + li:layers { } + name = grp_6 + } + ha:7 { + name = global outline + ha:type { outline=1; intern=1; } + li:layers { 7; } + } + ha:8 { + name = bottom copper + ha:type { bottom=1; copper=1; } + li:layers { 1; 4; 5; } + } + ha:9 { + name = bottom mask + ha:type { bottom=1; mask=1; } + li:layers { } + } + ha:10 { + name = bottom silk + ha:type { silk=1; bottom=1; } + li:layers { 8; } + } + ha:11 { + name = bottom paste + ha:type { bottom=1; paste=1; } + li:layers { } + } + } + } + li:pcb-rnd-conf-v1 { + ha:overwrite { + ha:design { + min_ring = 10.00 mil + clearance = 20.00 mil + text_font_id = 1 + text_scale = 5744 + via_thickness = 2000.00 um + via_drilling_hole = 31.50 mil + min_slk = 7.00 mil + max_height = 300.00 mil + line_thickness = 10.00 mil + shrink = 9.00 mil + poly_isle_area = 199999999.999200 + max_width = 300.00 mil + min_wid = 10.00 mil + bloat = 12.00 mil + min_drill = 15.00 mil + } + ha:editor { + ha:view { + flip_x = 0 + flip_y = 0 + } + grid_unit = mil + buffer_number = 0 + show_solder_side = 0 + grid = 181.00 um + } + } + } +} Index: tags/2.1.2/doc/user/02_model/src/via_therm_sharp_x45.lht =================================================================== --- tags/2.1.2/doc/user/02_model/src/via_therm_sharp_x45.lht (nonexistent) +++ tags/2.1.2/doc/user/02_model/src/via_therm_sharp_x45.lht (revision 24813) @@ -0,0 +1,280 @@ +ha:pcb-rnd-board-v2 { + + ha:attributes { + {PCB::conf::editor/grid}=181.00 um + {PCB::conf::editor/draw_grid}=true + {PCB::grid::unit}=mil + {PCB::conf::editor/buffer_number}=0 + {PCB::conf::editor/show_solder_side}=0 + {PCB::loader}=geda/pcb - nanometer + {PCB::conf::editor/view/flip_x}=0 + {PCB::conf::editor/view/flip_y}=0 + } + + li:styles { + ha:Signal { + diameter = 1.999996mm + thickness = 10.0mil + hole = 31.5mil + clearance = 20.0mil + } + ha:Power { + diameter = 2.199894mm + thickness = 20.0mil + hole = 0.999998mm + clearance = 20.0mil + } + ha:Fat { + diameter = 137.8mil + thickness = 80.0mil + hole = 47.24mil + clearance = 25.0mil + } + ha:Sig-tight { + diameter = 64.0mil + thickness = 10.0mil + hole = 31.5mil + clearance = 12.0mil + } + } + + ha:meta { + ha:size { + thermal_scale = 0.500000 + x = 300.0mil + y = 300.0mil + isle_area_nm2 = 199999999.999200 + } + ha:cursor { + zoom = 0.000000 + x = 225.0mil + y = 0.0 + } + ha:drc { + min_drill = 15.0mil + min_ring = 10.0mil + bloat = 12.0mil + shrink = 9.0mil + min_width = 10.0mil + min_silk = 7.0mil + } + ha:grid { + spacing = 0.181mm + offs_x = 0.0 + offs_y = 0.0 + } + } + + ha:data { + + li:objects { + ha:via.118 { + x=150mil; y=150mil; hole=47.24mil; mask=0.0; thickness=3.11912mm; clearance=50.0mil; + ha:flags { + ha:thermal { silk=diagonal-round; component=diagonal-sharp; } + via=1 + } + } + } + li:layers { + + ha:component { + lid=0 + group=3 + ha:combining { } + visible=1 + + li:objects { + ha:polygon.130 { + li:geometry { + ta:contour { + { 25.0mil; 25.0mil } + { 275.0mil; 25.0mil } + { 275.0mil; 275.0mil } + { 25.0mil; 275.0mil } + } + } + + ha:flags { + clearpoly=1 + } + } + } + } + + ha:solder { + lid=1 + group=8 + ha:combining { } + visible=1 + } + + ha:comp-GND { + lid=2 + group=3 + ha:combining { } + visible=1 + + } + + ha:comp-power { + lid=3 + group=3 + ha:combining { } + visible=1 + } + + ha:sold-GND { + lid=4 + group=8 + ha:combining { } + visible=1 + } + + ha:sold-power { + lid=5 + group=8 + ha:combining { } + visible=1 + } + + ha:signal3 { + lid=6 + group=5 + ha:combining { } + visible=1 + } + + ha:outline { + lid=7 + group=7 + ha:combining { } + visible=1 + } + + ha:silk { + lid=8 + group=10 + ha:combining { auto=1; } + visible=1 + } + + ha:silk { + lid=9 + group=1 + ha:combining { auto=1; } + visible=1 + + li:objects { + ha:text.131 { + string=Sharp, 45; x=1.054886mm; y=5.70354mm; scale=75; fid=0; direction=0; + ha:flags { + clearline=1 + } + } + } + } + } + } + + + ha:netlists { + li:input { + } + } + ha:layer_stack { + li:groups { + ha:0 { + name = top paste + ha:type { top=1; paste=1; } + li:layers { } + } + ha:1 { + name = top silk + ha:type { silk=1; top=1; } + li:layers { 9; } + } + ha:2 { + name = top mask + ha:type { top=1; mask=1; } + li:layers { } + } + ha:3 { + name = top copper + ha:type { copper=1; top=1; } + li:layers { 0; 2; 3; } + } + ha:4 { + ha:type { substrate=1; intern=1; } + li:layers { } + name = grp_4 + } + ha:5 { + name = Intern + ha:type { copper=1; intern=1; } + li:layers { 6; } + } + ha:6 { + ha:type { substrate=1; intern=1; } + li:layers { } + name = grp_6 + } + ha:7 { + name = global outline + ha:type { outline=1; intern=1; } + li:layers { 7; } + } + ha:8 { + name = bottom copper + ha:type { bottom=1; copper=1; } + li:layers { 1; 4; 5; } + } + ha:9 { + name = bottom mask + ha:type { bottom=1; mask=1; } + li:layers { } + } + ha:10 { + name = bottom silk + ha:type { silk=1; bottom=1; } + li:layers { 8; } + } + ha:11 { + name = bottom paste + ha:type { bottom=1; paste=1; } + li:layers { } + } + } + } + li:pcb-rnd-conf-v1 { + ha:overwrite { + ha:design { + min_ring = 10.00 mil + clearance = 20.00 mil + text_font_id = 0 + text_scale = 5744 + via_thickness = 2000.00 um + via_drilling_hole = 31.50 mil + min_slk = 7.00 mil + max_height = 300.00 mil + line_thickness = 10.00 mil + shrink = 9.00 mil + poly_isle_area = 199999999.999200 + max_width = 300.00 mil + min_wid = 10.00 mil + bloat = 12.00 mil + min_drill = 15.00 mil + } + ha:editor { + ha:view { + flip_x = 0 + flip_y = 0 + } + grid_unit = mil + buffer_number = 0 + show_solder_side = 0 + grid = 181.00 um + } + } + } +} Index: tags/2.1.2/doc/user/02_model/src/via_therm_sharp_x90.lht =================================================================== --- tags/2.1.2/doc/user/02_model/src/via_therm_sharp_x90.lht (nonexistent) +++ tags/2.1.2/doc/user/02_model/src/via_therm_sharp_x90.lht (revision 24813) @@ -0,0 +1,275 @@ +ha:pcb-rnd-board-v2 { + + ha:attributes { + {PCB::conf::editor/grid}=181.00 um + {PCB::conf::editor/draw_grid}=true + {PCB::grid::unit}=mil + } + + li:styles { + ha:Signal { + diameter = 1.999996mm + thickness = 10.0mil + hole = 31.5mil + clearance = 20.0mil + } + ha:Power { + diameter = 2.199894mm + thickness = 20.0mil + hole = 0.999998mm + clearance = 20.0mil + } + ha:Fat { + diameter = 137.8mil + thickness = 80.0mil + hole = 47.24mil + clearance = 25.0mil + } + ha:Sig-tight { + diameter = 64.0mil + thickness = 10.0mil + hole = 31.5mil + clearance = 12.0mil + } + } + + ha:meta { + ha:size { + thermal_scale = 0.500000 + x = 300.0mil + y = 300.0mil + isle_area_nm2 = 199999999.999200 + } + ha:cursor { + zoom = 0.000000 + x = 225.0mil + y = 0.0 + } + ha:drc { + min_drill = 15.0mil + min_ring = 10.0mil + bloat = 12.0mil + shrink = 9.0mil + min_width = 10.0mil + min_silk = 7.0mil + } + ha:grid { + spacing = 0.181mm + offs_x = 0.0 + offs_y = 0.0 + } + } + + ha:data { + + li:objects { + ha:via.118 { + x=150mil; y=150mil; hole=47.24mil; mask=0.0; thickness=3.11912mm; clearance=50.0mil; + ha:flags { + ha:thermal { silk=diagonal-round; component=horver-sharp; } + via=1 + } + } + } + li:layers { + + ha:component { + lid=0 + group=3 + ha:combining { } + visible=1 + + li:objects { + ha:polygon.136 { + li:geometry { + ta:contour { + { 25.0mil; 25.0mil } + { 275.0mil; 25.0mil } + { 275.0mil; 275.0mil } + { 25.0mil; 275.0mil } + } + } + + ha:flags { + clearpoly=1 + } + } + } + } + + ha:solder { + lid=1 + group=8 + ha:combining { } + visible=1 + } + + ha:comp-GND { + lid=2 + group=3 + ha:combining { } + visible=1 + + } + + ha:comp-power { + lid=3 + group=3 + ha:combining { } + visible=1 + } + + ha:sold-GND { + lid=4 + group=8 + ha:combining { } + visible=1 + } + + ha:sold-power { + lid=5 + group=8 + ha:combining { } + visible=1 + } + + ha:signal3 { + lid=6 + group=5 + ha:combining { } + visible=1 + } + + ha:outline { + lid=7 + group=7 + ha:combining { } + visible=1 + } + + ha:silk { + lid=8 + group=10 + ha:combining { auto=1; } + visible=1 + } + + ha:silk { + lid=9 + group=1 + ha:combining { auto=1; } + visible=1 + + li:objects { + ha:text.137 { + string=Sharp; x=2.140886mm; y=5.70354mm; scale=75; fid=0; direction=0; + ha:flags { + clearline=1 + } + } + } + } + } + } + + + ha:netlists { + li:input { + } + } + ha:layer_stack { + li:groups { + ha:0 { + name = top paste + ha:type { top=1; paste=1; } + li:layers { } + } + ha:1 { + name = top silk + ha:type { silk=1; top=1; } + li:layers { 9; } + } + ha:2 { + name = top mask + ha:type { top=1; mask=1; } + li:layers { } + } + ha:3 { + name = top copper + ha:type { copper=1; top=1; } + li:layers { 0; 2; 3; } + } + ha:4 { + ha:type { substrate=1; intern=1; } + li:layers { } + name = grp_4 + } + ha:5 { + name = Intern + ha:type { copper=1; intern=1; } + li:layers { 6; } + } + ha:6 { + ha:type { substrate=1; intern=1; } + li:layers { } + name = grp_6 + } + ha:7 { + name = global outline + ha:type { outline=1; intern=1; } + li:layers { 7; } + } + ha:8 { + name = bottom copper + ha:type { bottom=1; copper=1; } + li:layers { 1; 4; 5; } + } + ha:9 { + name = bottom mask + ha:type { bottom=1; mask=1; } + li:layers { } + } + ha:10 { + name = bottom silk + ha:type { silk=1; bottom=1; } + li:layers { 8; } + } + ha:11 { + name = bottom paste + ha:type { bottom=1; paste=1; } + li:layers { } + } + } + } + li:pcb-rnd-conf-v1 { + ha:overwrite { + ha:design { + min_ring = 10.00 mil + clearance = 20.00 mil + text_font_id = 0 + text_scale = 5744 + via_thickness = 2000.00 um + via_drilling_hole = 31.50 mil + min_slk = 7.00 mil + max_height = 300.00 mil + line_thickness = 10.00 mil + shrink = 9.00 mil + poly_isle_area = 199999999.999200 + max_width = 300.00 mil + min_wid = 10.00 mil + bloat = 12.00 mil + min_drill = 15.00 mil + } + ha:editor { + ha:view { + flip_x = 0 + flip_y = 0 + } + grid_unit = mil + buffer_number = 0 + show_solder_side = 0 + grid = 181.00 um + } + } + } +} Index: tags/2.1.2/doc/user/02_model/src/via_therm_solid.lht =================================================================== --- tags/2.1.2/doc/user/02_model/src/via_therm_solid.lht (nonexistent) +++ tags/2.1.2/doc/user/02_model/src/via_therm_solid.lht (revision 24813) @@ -0,0 +1,269 @@ +ha:pcb-rnd-board-v2 { + + ha:attributes { + {PCB::grid::unit}=mil + {PCB::conf::editor/draw_grid}=true + {PCB::conf::editor/grid}=181.00 um + } + + li:styles { + ha:Signal { + diameter = 1.999996mm + thickness = 10.0mil + hole = 31.5mil + clearance = 20.0mil + } + ha:Power { + diameter = 2.199894mm + thickness = 20.0mil + hole = 0.999998mm + clearance = 20.0mil + } + ha:Fat { + diameter = 137.8mil + thickness = 80.0mil + hole = 47.24mil + clearance = 25.0mil + } + ha:Sig-tight { + diameter = 64.0mil + thickness = 10.0mil + hole = 31.5mil + clearance = 12.0mil + } + } + + ha:meta { + ha:size { + thermal_scale = 0.500000 + x = 300.0mil + y = 300.0mil + isle_area_nm2 = 199999999.999200 + } + ha:cursor { + zoom = 0.000000 + x = 225.0mil + y = 0.0 + } + ha:drc { + min_drill = 15.0mil + min_ring = 10.0mil + bloat = 12.0mil + shrink = 9.0mil + min_width = 10.0mil + min_silk = 7.0mil + } + ha:grid { + spacing = 0.181mm + offs_x = 0.0 + offs_y = 0.0 + } + } + + ha:data { + + li:objects { + ha:via.107 { + x=150mil; y=150mil; hole=47.24mil; mask=0.0; thickness=3.11912mm; clearance=50.0mil; + ha:flags { + via=1 + ha:thermal { + component=solid; } + } + } + } + li:layers { + + ha:component { + lid=0 + group=3 + ha:combining { } + visible=1 + + li:objects { + ha:polygon.110 { + li:geometry { + ta:contour { + { 25.0mil; 25.0mil } + { 275.0mil; 25.0mil } + { 275.0mil; 275.0mil } + { 25.0mil; 275.0mil } + } + } + + ha:flags { + clearpoly=1 + } + } + } + } + + ha:solder { + lid=1 + group=8 + ha:combining { } + visible=1 + } + + ha:comp-GND { + lid=2 + group=3 + ha:combining { } + visible=1 + } + + ha:comp-power { + lid=3 + group=3 + ha:combining { } + visible=1 + } + + ha:sold-GND { + lid=4 + group=8 + ha:combining { } + visible=1 + } + + ha:sold-power { + lid=5 + group=8 + ha:combining { } + visible=1 + } + + ha:signal3 { + lid=6 + group=5 + ha:combining { } + visible=1 + } + + ha:outline { + lid=7 + group=7 + ha:combining { } + visible=1 + } + + ha:silk { + lid=8 + group=10 + ha:combining { auto=1; } + visible=1 + } + + ha:silk { + lid=9 + group=1 + ha:combining { auto=1; } + visible=1 + + li:objects { + ha:text.113 { + string=Solid via; x=1.813mm; y=5.442mm; scale=70; fid=0; direction=0; + ha:flags { + clearline=1 + } + } + } + } + } + } + + ha:netlists { + li:input { + } + } + ha:layer_stack { + li:groups { + ha:0 { + name = top paste + ha:type { top=1; paste=1; } + li:layers { } + } + ha:1 { + name = top silk + ha:type { silk=1; top=1; } + li:layers { 9; } + } + ha:2 { + name = top mask + ha:type { top=1; mask=1; } + li:layers { } + } + ha:3 { + name = top copper + ha:type { copper=1; top=1; } + li:layers { 0; 2; 3; } + } + ha:4 { + ha:type { substrate=1; intern=1; } + li:layers { } + name = grp_4 + } + ha:5 { + name = Intern + ha:type { copper=1; intern=1; } + li:layers { 6; } + } + ha:6 { + ha:type { substrate=1; intern=1; } + li:layers { } + name = grp_6 + } + ha:7 { + name = global outline + ha:type { outline=1; intern=1; } + li:layers { 7; } + } + ha:8 { + name = bottom copper + ha:type { bottom=1; copper=1; } + li:layers { 1; 4; 5; } + } + ha:9 { + name = bottom mask + ha:type { bottom=1; mask=1; } + li:layers { } + } + ha:10 { + name = bottom silk + ha:type { silk=1; bottom=1; } + li:layers { 8; } + } + ha:11 { + name = bottom paste + ha:type { bottom=1; paste=1; } + li:layers { } + } + } + } + li:pcb-rnd-conf-v1 { + ha:overwrite { + ha:design { + min_ring = 10.00 mil + clearance = 20.00 mil + text_font_id = 0 + text_scale = 5744 + via_thickness = 2000.00 um + via_drilling_hole = 31.50 mil + min_slk = 7.00 mil + max_height = 300.00 mil + line_thickness = 10.00 mil + shrink = 9.00 mil + poly_isle_area = 199999999.999200 + max_width = 300.00 mil + min_wid = 10.00 mil + bloat = 12.00 mil + min_drill = 15.00 mil + } + ha:editor { + grid_unit = mil + buffer_number = 0 + grid = 181.00 um + } + } + } +} Index: tags/2.1.2/doc/user/02_model/via_therm_noconn.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/user/02_model/via_therm_noconn.png =================================================================== --- tags/2.1.2/doc/user/02_model/via_therm_noconn.png (nonexistent) +++ tags/2.1.2/doc/user/02_model/via_therm_noconn.png (revision 24813) Property changes on: tags/2.1.2/doc/user/02_model/via_therm_noconn.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/user/02_model/via_therm_round_x45.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/user/02_model/via_therm_round_x45.png =================================================================== --- tags/2.1.2/doc/user/02_model/via_therm_round_x45.png (nonexistent) +++ tags/2.1.2/doc/user/02_model/via_therm_round_x45.png (revision 24813) Property changes on: tags/2.1.2/doc/user/02_model/via_therm_round_x45.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/user/02_model/via_therm_round_x90.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/user/02_model/via_therm_round_x90.png =================================================================== --- tags/2.1.2/doc/user/02_model/via_therm_round_x90.png (nonexistent) +++ tags/2.1.2/doc/user/02_model/via_therm_round_x90.png (revision 24813) Property changes on: tags/2.1.2/doc/user/02_model/via_therm_round_x90.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/user/02_model/via_therm_sharp_x45.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/user/02_model/via_therm_sharp_x45.png =================================================================== --- tags/2.1.2/doc/user/02_model/via_therm_sharp_x45.png (nonexistent) +++ tags/2.1.2/doc/user/02_model/via_therm_sharp_x45.png (revision 24813) Property changes on: tags/2.1.2/doc/user/02_model/via_therm_sharp_x45.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/user/02_model/via_therm_sharp_x90.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/user/02_model/via_therm_sharp_x90.png =================================================================== --- tags/2.1.2/doc/user/02_model/via_therm_sharp_x90.png (nonexistent) +++ tags/2.1.2/doc/user/02_model/via_therm_sharp_x90.png (revision 24813) Property changes on: tags/2.1.2/doc/user/02_model/via_therm_sharp_x90.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/user/02_model/via_therm_solid.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/user/02_model/via_therm_solid.png =================================================================== --- tags/2.1.2/doc/user/02_model/via_therm_solid.png (nonexistent) +++ tags/2.1.2/doc/user/02_model/via_therm_solid.png (revision 24813) Property changes on: tags/2.1.2/doc/user/02_model/via_therm_solid.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/user/03_data/index.html =================================================================== --- tags/2.1.2/doc/user/03_data/index.html (nonexistent) +++ tags/2.1.2/doc/user/03_data/index.html (revision 24813) @@ -0,0 +1,179 @@ + + + + pcb-rnd user manual + + + + +

pcb-rnd - user manual

+ +

3. Where Data Is Stored

+

+Pcb-rnd enables the user to design complex original boards in a standard EDA +flow with netlists and other data inputs that aide in design. pcb-rnd also +acts as a multiuse layout design CAD, opening board designs saved in a variety +of legacy and contemporary software. +

+The user can import a variety of non-layout data sources commonly used in EDA +flow. Schematics from gschem or kicad, netlists, reference images, tinyCAD, +and more are available to the user. + +

3.1. Board

+

+pcb-rnd can edit a single board at a time. To edit multiple boards, open +multiple instances of pcb-rnd. + +

3.2. Paste Buffer

+There are multiple paste buffers available in pcb-rnd. The user can select +one of them to be active - most buffer operations will work with the active +buffer. +

+Buffers are board-independent: they have their own dynamic size and their +own virtual layer stack. These enable buffers to act as a proxy between +different boards with different properties. +

+The following operations can be done with buffers: +

    +
  • clear: the content of the buffer is discarded +
  • copy from layout: copy objects from the layout to the buffer +
  • paste to layout: copy objects from the buffer to the layout +
  • load: load buffer from file (including footprints/subcircuits from the library) +
  • save subcircuit: save elements/subcircuits from buffer to file +
  • build a subcircuit in a buffer, from the objects stored in the buffer +
  • build a padstack in a buffer, from the objects stored in the buffer +
  • break up a subcircuit in a buffer + +
  • rotate +
  • mirror +
+ +

3.3. Footprint Libraries

+

3.3.1. Library handling

+

+A footprint library is a collection of subcircuit files, optionally +equipped with metadata. A footprint library is stored and accessed by +footprint plugins (whose names are conventionally prefixed with fp_). +Where the actual data is stored, how and when it is retrieved depends +on the fp_ plugin. +

+There is a configuration node called rc/library_search_paths which +is a list of footprint library search paths. How each path is interpreted +also depends on the fp_ plugins. +

+Currently pcb-rnd offers the following fp_ plugins: + +
plugin description library_search_paths example +
fp_fs + list and load files from directories on the host file system + ~/my_lib
/usr/lib/company_lib
$(rc.path.share)/pcblib +
fp_board + extract all footprints from an existing board file (given in + any board format pcb-rnd can load) and use these footprints as + a library + board@/home/joe/ee/control/cpu.lht +
fp_wget + download a digested map of a footprint library from a web server, + using wget; make all footprints and metadata available in the + library but do not immediately download footprint files; keep + a local (host file system) cache of footprints accessed. Currently + supports edakrill + and gedasymbols. + wget@edakrill
wget@gedasymbols +
+ +

3.3.2. footprint types

+

+There are two types of footprints: +

    +
  • static (file) footprints; and +
  • parametric (generated) footprints. +
+

+A static footprint is a data file that is loaded and parsed by one of +the io_ plugins. pcb-rnd supports multiple file formats: the native lihata +subcircuit format, kicad, eagle, gEDA footprints. +

+A parametric footprint is an external program or script that is executed +by pcb-rnd. The external program shall write a valid footprint file to its +standard output, which is then parsed and used the same way as in case of +static footprints. The external program gets a list of parameters +extracted from the footprint name by pcb-rnd. +

+The basic syntax for a parametric footprint is name(arg1, arg2, ... +argN). Any footprint name that contains a '(' is treated as parametric. +The list of arguments is separated by commas. How arguments are interpreted, +e.g. whether the are positional or named or both, is up to the external +parametric footprint program. +

+The footprint programs are stored in the library tree, and are accessed +using the fp_ plugins. There is no limitation on how the program is implemented +other than the host operating system on which pcb-rnd runs has to be able to +execute it. + + +

3.4. file formats

+

+pcb-rnd operates on an in-memory data tree of the board while it is being edited. +The in-memory data tree can not be dumped in a file without conversion: loading +any file means converting the given file format to the in-memory representation +and saving from memory to any file format is just another conversion. + +

+Lossless save/load round trips for all pcb-rnd features are guaranteed +only when using the latest version of the native formats. The reason is +that the native formats are always upgraded to support all features of +the in-memory data model. It is possible (but not recommended) to use +older versions of the native formats to retrain compatibility with older +versions of pcb-rnd. + +

+The native file formats of pcb-rnd are: +

    +
  • lihata board for PCBs +
  • lihata subcircuit for footprints +
  • lihata based pcb-rnd-conf for configuration data +
+ +

+Non-native file formats are called alien formats. pcb-rnd supports +a large variety of alien formats, but lossless save/load round trips are +not guaranteed when alien formats are used. The code will always do its best +to get good results, but different alien formats have different features, +and most of them can not fully capture all features pcb-rnd offers. + +

+Some alien formats are implemented as io_ plugins and are accessible +as normal board (and footprint) file formats directly from the load/save +infrastructure and footprint library. These formats are trying to capture +all details of the board (or footprint) and are usually close to +producing lossless save/load round trips. + +

+Other alien formats are supported through import_ or export_ plugins. +These formats do not capture enough aspects of a board (or footprint) to +be used as a full load or save, round trip of any sort is impossible. + +

+Typical export example is render outputs: png, ps, gerber are all +export_ plugins: they export one aspect (geometry and sometimes layering) +of the board, but do not export other aspects such as connections, +subcircuits or padstack structure. Lacking that information, the exported +board can never be loaded as a board from png, ps or gerber. + +

+Typical import example is netlist (or schematics): it deals with one aspect +of the project, connection info, and lacks any physical information such +as geometry or layers. It is possible to import one aspect of the design from +a netlist (or schematics), but it is not possible to reconstruct a full board +using only the netlist information. + +

+a map of pcb-rnd format support + +

+For a detailed list of formats, please refer to + the list of supported file formats +in the appendix. + + Index: tags/2.1.2/doc/user/04_invoc/index.html =================================================================== --- tags/2.1.2/doc/user/04_invoc/index.html (nonexistent) +++ tags/2.1.2/doc/user/04_invoc/index.html (revision 24813) @@ -0,0 +1,70 @@ + + + + pcb-rnd user manual + + + + +

pcb-rnd - user manual

+ +

4. User Invocation (running pcb-rnd)

+

+pcb-rnd is typically run by invoking it from the shell after installation +

+ +pcb-rnd [options] + +or + +pcb-rnd [options] path + +

+When a path is provided, it is either a board file or a subcircuit which +will be automatically opened for editing. When invoked with a path referring +to a non-existing file, pcb-rnd assumes a new board is to be created and +saved using the file name provided as path. This makes it very easy to +make new boards from the command line. + +

+The list of available options can be acquired by running +

+ +pcb-rnd --help + +

+The most commonly used option is to export a file: + +pcb-rnd -x format [format_options] path + +

+For example a photo-realistic png export pwr.png from the board saved +in pwr.lht can be exported as: + +pcb-rnd --export png --dpi 600 --photo-mode pwr.lht + +

+Listing exporter-specific options is possible running pcb-rnd --help +exporter, e.g.: + +pcb-rnd --help png + +

+Another typical application of options is to select the user interface to +start pcb-rnd with (as pcb-rnd normally comes with multiple UIs compiled in): +

+
+pcb-rnd --gui=batch
+pcb-rnd --gui=gtk2_gdk
+pcb-rnd --gui=gtk2_gl
+pcb-rnd --gui=lesstif
+
+
+

+The most notable UI is the batch UI: it reads the standard input for +action commands, executes them and quits on EOF. This allows pcb-rnd to be +run as a UNIX filter (just like a sed, awk or perl), loading, manipulating +and saving boards, without starting a GUI. + + + Index: tags/2.1.2/doc/user/05_ui/01_gtk/base_window_highlight_coordsreadout.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/user/05_ui/01_gtk/base_window_highlight_coordsreadout.png =================================================================== --- tags/2.1.2/doc/user/05_ui/01_gtk/base_window_highlight_coordsreadout.png (nonexistent) +++ tags/2.1.2/doc/user/05_ui/01_gtk/base_window_highlight_coordsreadout.png (revision 24813) Property changes on: tags/2.1.2/doc/user/05_ui/01_gtk/base_window_highlight_coordsreadout.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/user/05_ui/01_gtk/base_window_highlight_layerops.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/user/05_ui/01_gtk/base_window_highlight_layerops.png =================================================================== --- tags/2.1.2/doc/user/05_ui/01_gtk/base_window_highlight_layerops.png (nonexistent) +++ tags/2.1.2/doc/user/05_ui/01_gtk/base_window_highlight_layerops.png (revision 24813) Property changes on: tags/2.1.2/doc/user/05_ui/01_gtk/base_window_highlight_layerops.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/user/05_ui/01_gtk/base_window_highlight_main.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/user/05_ui/01_gtk/base_window_highlight_main.png =================================================================== --- tags/2.1.2/doc/user/05_ui/01_gtk/base_window_highlight_main.png (nonexistent) +++ tags/2.1.2/doc/user/05_ui/01_gtk/base_window_highlight_main.png (revision 24813) Property changes on: tags/2.1.2/doc/user/05_ui/01_gtk/base_window_highlight_main.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/user/05_ui/01_gtk/base_window_highlight_menus.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/user/05_ui/01_gtk/base_window_highlight_menus.png =================================================================== --- tags/2.1.2/doc/user/05_ui/01_gtk/base_window_highlight_menus.png (nonexistent) +++ tags/2.1.2/doc/user/05_ui/01_gtk/base_window_highlight_menus.png (revision 24813) Property changes on: tags/2.1.2/doc/user/05_ui/01_gtk/base_window_highlight_menus.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/user/05_ui/01_gtk/base_window_highlight_opsreadout.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/user/05_ui/01_gtk/base_window_highlight_opsreadout.png =================================================================== --- tags/2.1.2/doc/user/05_ui/01_gtk/base_window_highlight_opsreadout.png (nonexistent) +++ tags/2.1.2/doc/user/05_ui/01_gtk/base_window_highlight_opsreadout.png (revision 24813) Property changes on: tags/2.1.2/doc/user/05_ui/01_gtk/base_window_highlight_opsreadout.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/user/05_ui/01_gtk/base_window_highlight_routestyle.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/user/05_ui/01_gtk/base_window_highlight_routestyle.png =================================================================== --- tags/2.1.2/doc/user/05_ui/01_gtk/base_window_highlight_routestyle.png (nonexistent) +++ tags/2.1.2/doc/user/05_ui/01_gtk/base_window_highlight_routestyle.png (revision 24813) Property changes on: tags/2.1.2/doc/user/05_ui/01_gtk/base_window_highlight_routestyle.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/user/05_ui/01_gtk/base_window_highlight_workops.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/user/05_ui/01_gtk/base_window_highlight_workops.png =================================================================== --- tags/2.1.2/doc/user/05_ui/01_gtk/base_window_highlight_workops.png (nonexistent) +++ tags/2.1.2/doc/user/05_ui/01_gtk/base_window_highlight_workops.png (revision 24813) Property changes on: tags/2.1.2/doc/user/05_ui/01_gtk/base_window_highlight_workops.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/user/05_ui/01_gtk/index.html =================================================================== --- tags/2.1.2/doc/user/05_ui/01_gtk/index.html (nonexistent) +++ tags/2.1.2/doc/user/05_ui/01_gtk/index.html (revision 24813) @@ -0,0 +1,95 @@ + + + + pcb-rnd user manual + + + + +

pcb-rnd - user manual

+ +

5.1 GTK+

+

+pcb-rnd comes with a default graphical hid using GTK+ + +

5.1.1 Using GTK+

+ +
    +
  1. Main Window +
  2. Menus +
  3. Operations Toolbar +
  4. Layer Controller +
  5. Coordinates Readout +
  6. Route Styles +
  7. Ops Readout +
  8. Key Commands +
  9. Gui Command Line Interface +
  10. Dialog Windows + +
+

+ +

Main Window

+
+Main layout window highlighted +

+The main window in pcb-rnd is a drawing area for your layout. +

Menus

+
+Menus highlighted +

+Menus perform standard file operations commands as well as pcb-rnd layout specific operations +menus: +

    +
  • File - Standard file operations -pcb-rnd import/export, and access to the pcb-rnd preferences +
  • Edit - Undos, buffer ops, selection, edit name and route styles +
  • View - Main view grid control and attribute visibility +
  • Settings - Direct control of main window settings that mostly affect drawing +
  • Select - Selection and edit selection control +
  • Buffer - edit, select, place, transform buffer contents +
  • Connects - connection operations and DRC +
  • Plugins - Manage plugins +
  • Info - Generate reports and get keybindings +
  • Window - open a auxiliary window (dialog) +
+

Operations Toolbar

+
+Operations toolbar highlighted +

+Add to and edit your layout +

Layer Controller

+
+Layer controls highlighted +

+Change layer visibility +

Coordinates Readout

+
+Coordinate readout highlighted +

+Readouts give live info for the user: +Obtain absolute and relative coordinate information +

Route Styles

+
+Route styles area highlighted +

+Access route style dialog and alter existing route style +

Ops Readout

+
+Operations readout highlighted +

+Readouts provide live info for the user +Obtain view grid line drawing style reporter, via size, clearance value, text +size, buffer number +

Key Commands

+pcb-rnd key command standard... +Quick Keys +

Gui Command Line Interface

+Enter the command line interface by typing : + + Index: tags/2.1.2/doc/user/05_ui/02_cli/index.html =================================================================== --- tags/2.1.2/doc/user/05_ui/02_cli/index.html (nonexistent) +++ tags/2.1.2/doc/user/05_ui/02_cli/index.html (revision 24813) @@ -0,0 +1,29 @@ + + + + pcb-rnd user manual + + + + +

pcb-rnd - user manual

+ +

5.2 Actions and Command Line Interface

+

+pcb-rnd actions can be listed + +

+ +./pcb-rnd --show-actions + + +

+Uses for CLI: +

    +
  • format translation (with additional plugins active) +
  • export (with additional plugins) +
  • agnostic version control (use with git/mercurial/svn) +
+

+ + Index: tags/2.1.2/doc/user/05_ui/05_batch/index.html =================================================================== --- tags/2.1.2/doc/user/05_ui/05_batch/index.html (nonexistent) +++ tags/2.1.2/doc/user/05_ui/05_batch/index.html (revision 24813) @@ -0,0 +1,37 @@ + + + + pcb-rnd user manual + + + + +

pcb-rnd - user manual

+ +

5.5 Batch User Interface

+ +

+Pcb-rnd comes with a interpreter which is known as the batch UI. This batch UI +is a default buildin and can be summond at any time when running pcb-rnd (see +code below). Batch mode will compile and run as the default user interface when pcb-rnd is +compiled on systems without any GUI libs installed. + +

+The batch UI is useful for automation, test, and debugging: it is reading +action commands on the standard input and prints results on the standard +output. It does not run a GUI and does not require X. Typical invocation: +

+ +./pcb-rnd --gui batch [path] + + +

+Uses and examples for Batch mode (TODO): +

    +
  • automation +
  • export footprint (with additional plugins) +
  • possible hook processing (ensuring consistent layout state for a dvcs) +
+

+ + Index: tags/2.1.2/doc/user/05_ui/06_common/grid_menu.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/user/05_ui/06_common/grid_menu.png =================================================================== --- tags/2.1.2/doc/user/05_ui/06_common/grid_menu.png (nonexistent) +++ tags/2.1.2/doc/user/05_ui/06_common/grid_menu.png (revision 24813) Property changes on: tags/2.1.2/doc/user/05_ui/06_common/grid_menu.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/user/05_ui/06_common/index.html =================================================================== --- tags/2.1.2/doc/user/05_ui/06_common/index.html (nonexistent) +++ tags/2.1.2/doc/user/05_ui/06_common/index.html (revision 24813) @@ -0,0 +1,109 @@ + + + + pcb-rnd user manual + + + + +

pcb-rnd - user manual

+ +

6.1. keyboard bindings

+

+The same default menu file is used in all GUI HIDs. It comes with multi-stroke +key bindings, plus only a very few, alternative keys that use modifiers +(mostly ctrl). A multi-stroke key binding requires the user to type in a +sequence of keys, e.g. pressing 't' and 'l' (written as {t l} in this document) +will make pcb-rnd switch to the line tool. There are two major advanatges of +using multi-stroke instead of modifiers: +

    +
  • It is often easier to remember them, e.g. the above {t l} can be + memorized as 'tool, line', and it is similar to {t a} for 'tool, arc' + and {t, p} for 'tool, polygon'. The old menu file had these as F2, F3 + and F6. They could be also ctrl+l, ctrl+a, ctrl+p, but then if another + group of functionality required similar letters, like l for list or + p for print, they would ned to use a different modifier, e.g. alt+l + and alt+p. At the end there would be a random set of alt, ctrl, shift + combinations that are real hard to remember - this is exactly how + the old (pre-2.0.0) default menu file was. +
  • Since pcb-rnd is a graphical CAD, the mouse is an inportant user input + device. Most users will have one hand constantly on the mouse. It is much + faster to type a sequence of 2 or rarely 3 plain keys with one hand than + doing the acrobatics for something like ctrl+t or even alt+shif+u. +
+

+Most multi-stroke keys, especially the commonly used ones, use two strokes. +Some rarely used feature will require three. The system can be regarded +as a tree: e.g. in a 3-key sequence, starting from the root +(nothing is pressed) the first key select a chapter, the second +key narrows it down to a subchapter and the third key (leaf) selects the actual +action within the subchapter. The current key tree is +accessible in a large svg drawing or in a script-digestable +flat list. + +

6.2. Grid

+

+The grid is an imaginary set of points over the drawing. The crosshair +can snap to the grid, helping the user to keep coordinates of objects +distributed evenly. +

+The only grid geometr pcb-rnd supports is a regular, rectangular grid, that +is: grid points spaced evenly in x and y directions, aligned into horizontal +and vertical rows. The grid also has an optional offset in x and y directions +(which is usually set to 0;0). +

+The grid spacing (distance between grid points) is user configurable. There +are two methods managing the grid. + +

6.2.1. Preset grid

+ +

+The configuration system has a node called editor/grids, which is an ordered +list of preset grid settings. This list should contain the grid settings +preferred by the user, or preferred for the given design. Since this is a +configuration item, the usual conf rules apply (e.g. local grid config +can be saved in the project's config or even in the board file). +

+While drawing, the user can use the {g b} and {g f} hotkeys, or the shorter +[ and ] keys to step the current grid, selecting the previous or next item +from the list. The grid sizes menu will always have the currently selected +item checked. +

+ +

+If the user changes grid properties directly, the new grid setup will most +likely not match any of the presets and the check mark is gone from the menu. +However, pcb-rnd remember the last used preset menu and upon the next +stepping it will move from the last selected preset grid. + +

+The format for the grid configuration is a simple text that lists an +optional grid name, the mandatory grid size, the optional offset and +optionally instructs pcb-rnd to also switch units when the grid is activated. +The full syntax, optional parts written in [] is: +

+[name:]size[@offs][!unit]
+
+

+(The optional name has no functionality other than being displayed, helping +the user to remember the purpose of the grid.) + +

+Examples: +

+ +
grid spec description +
10 mil
anonymous 10 mil grid with no offset +
1.5 mm
anonymous 1.5 mm grid with no offset +
20 mil@1mil;-3mil
20 mil grid with a horizontal offset of +1 mil and vertical offset of -3 mil +
1.5 mm!mm
1.5 mm grid; when activated, switch untis to mm +
placing dips:100 mil
named grid +
leds:1mm@0.5mm;-0.1mm!mm
all the above features, combined +
+ +

6.2.2. Custom grid

+

+The current grid is stored as grid distance and x;y offset. Regardless of +the configured presets, these properties of the current grid can be changed +any time, using the SetValue() action or using the menu. + Index: tags/2.1.2/doc/user/05_ui/06_common/keytree.svg =================================================================== --- tags/2.1.2/doc/user/05_ui/06_common/keytree.svg (nonexistent) +++ tags/2.1.2/doc/user/05_ui/06_common/keytree.svg (revision 24813) @@ -0,0 +1,3035 @@ + + + + + + +keytree + + + +a + +{a} + auto or add + + + +a_b + +{a b} + back annotation + + + +a->a_b + + + + + +a_p + +{a p} + auto-place + + + +a->a_p + + + + + +a_d + +{a d} + auto-disperse + + + +a->a_d + + + + + +a_r + +{a r} + auto-route + + + +a->a_r + + + + + +a_o + +{a o} + optimize (djopt) + + + +a->a_o + + + + + +a_a + +{a a} +Start routing an arc + + + +a->a_a + + + + + +a_l + +{a l} +Start routing a line + + + +a->a_l + + + + + +a_m + +{a m} +Place mark + + + +a->a_m + + + + + +a_v + +{a v} +Place via + + + +a->a_v + + + + + +a_w + +{a w} +Place mark + + + +a->a_w + + + + + +a_x + +{a x} +Design Rule Checker + + + +a->a_x + + + + + +a_b_f + +{a b f} +Replace footprint + + + +a_b->a_b_f + + + + + +a_b_s + +{a b s} +Swap nets on two selected pins + + + +a_b->a_b_s + + + + + +a_b_x + +{a b x} +netlist patch for back annotation + + + +a_b->a_b_x + + + + + +a_p_s + +{a p s} +Auto-place selected subcircuits + + + +a_p->a_p_s + + + + + +a_d_a + +{a d a} +Disperse all subcircuits + + + +a_d->a_d_a + + + + + +a_d_s + +{a d s} +Disperse selected subcircuits + + + +a_d->a_d_s + + + + + +a_r_a + +{a r a} +Auto-route all rats + + + +a_r->a_r_a + + + + + +a_r_r + +{a r r} +Rip up all auto-routed tracks + + + +a_r->a_r_r + + + + + +a_r_s + +{a r s} +Auto-route selected rats + + + +a_r->a_r_s + + + + + +a_r_t + +{a r t} +Rip up selected auto-routed tracks + + + +a_r->a_r_t + + + + + +a_o_a + +{a o a} +Auto-Optimize + + + +a_o->a_o_a + + + + + +a_o_d + +{a o d} +Debumpify + + + +a_o->a_o_d + + + + + +a_o_m + +{a o m} +Miter + + + +a_o->a_o_m + + + + + +a_o_n + +{a o n} +Vianudge + + + +a_o->a_o_n + + + + + +a_o_o + +{a o o} +Ortho pull + + + +a_o->a_o_o + + + + + +a_o_p + +{a o p} +Puller + + + +a_o->a_o_p + + + + + +a_o_s + +{a o s} +Simple optimization + + + +a_o->a_o_s + + + + + +a_o_t + +{a o t} +Viatrim + + + +a_o->a_o_t + + + + + +a_o_u + +{a o u} +Unjaggy + + + +a_o->a_o_u + + + + + +b + +{b} + buffer + + + +b_c + +{b c} + convert & clear + + + +b->b_c + + + + + +b_m + +{b m} + mirror + + + +b->b_m + + + + + +b_r + +{b r} + rotate + + + +b->b_r + + + + + +b_s + +{b s} + subcircuit + + + +b->b_s + + + + + +b_b + +{b b} +Layer bindings... + + + +b->b_b + + + + + +b_n + +{b n} +Normalize + + + +b->b_n + + + + + +b_c_c + +{b c c} +Clear buffer + + + +b_c->b_c_c + + + + + +b_c_p + +{b c p} +Convert buffer to padstack + + + +b_c->b_c_p + + + + + +b_c_s + +{b c s} +Convert buffer to subcircuit + + + +b_c->b_c_s + + + + + +b_m_l + +{b m l} +Mirror buffer (left/right) + + + +b_m->b_m_l + + + + + +b_m_u + +{b m u} +Mirror buffer (up/down) + + + +b_m->b_m_u + + + + + +b_r_a + +{b r a} +Arbitrarily Rotate Buffer + + + +b_r->b_r_a + + + + + +b_r_l + +{b r l} +Rotate buffer 90 deg CCW (left) + + + +b_r->b_r_l + + + + + +b_r_r + +{b r r} +Rotate buffer 90 deg CW (right) + + + +b_r->b_r_r + + + + + +b_s_b + +{b s b} +Break buffer subcircuits to pieces + + + +b_s->b_s_b + + + + + +b_s_p + +{b s p} +Break buffer padstacks to pieces + + + +b_s->b_s_p + + + + + +b_s_s + +{b s s} +Save buffer subcircuits to file + + + +b_s->b_s_s + + + + + +c + +{c} + connections & rats + + + +c_c + +{c c} +Clear/reset lookup + + + +c->c_c + + + + + +c_d + +{c d} +Del/Remove Connected + + + +c->c_d + + + + + +c_e + +{c e} +Erase rats nest + + + +c->c_e + + + + + +c_f + +{c f} +Find Connections + + + +c->c_f + + + + + +c_r + +{c r} +Optimize rats nest + + + +c->c_r + + + + + +c_s + +{c s} +Select shortest rat + + + +c->c_s + + + + + +e + +{e} + edit + + + +e_m + +{e m} + move + + + +e->e_m + + + + + +e_s + +{e s} + subcircuit or style + + + +e->e_s + + + + + +e_g + +{e g} + geometry + + + +e->e_g + + + + + +e_c + +{e c} +Copy selection to buffer + + + +e->e_c + + + + + +e_d + +{e d} +Remove object + + + +e->e_d + + + + + +e_f + +{e f} +Object flags... + + + +e->e_f + + + + + +e_i + +{e i} +Flip Object + + + +e->e_i + + + + + +e_j + +{e j} +ChangeJoin Object + + + +e->e_j + + + + + +e_l + +{e l} +Move to current layer + + + +e->e_l + + + + + +e_o + +{e o} +Change font... + + + +e->e_o + + + + + +e_p + +{e p} +Object Properties... + + + +e->e_p + + + + + +e_r + +{e r} +Change refdes + + + +e->e_r + + + + + +e_t + +{e t} +Edit text... + + + +e->e_t + + + + + +e_v + +{e v} +Paste buffer to layout + + + +e->e_v + + + + + +e_x + +{e x} +Cut selection to buffer + + + +e->e_x + + + + + +e_y + +{e y} +Cycle object being dragged + + + +e->e_y + + + + + +e_s_b + +{e s b} +Layer bindings... + + + +e_s->e_s_b + + + + + +e_s_e + +{e s e} +External editor... + + + +e_s->e_s_e + + + + + +e_s_r + +{e s r} +Refdes + + + +e_s->e_s_r + + + + + +e_s_s + +{e s s} +Set Same Style + + + +e_s->e_s_s + + + + + +e_g_c + +{e g c} +Clearance +2 mil + + + +e_g->e_g_c + + + + + +e_g_c-shift + +{e g c-shift} +Clearance -2 mil + + + +e_g->e_g_c-shift + + + + + +e_g_d + +{e g d} +ChangeDrill +5 mil + + + +e_g->e_g_d + + + + + +e_g_d-shift + +{e g d-shift} +ChangeDrill -5 mil + + + +e_g->e_g_d-shift + + + + + +e_g_s + +{e g s} +ChangeSize +5 mil + + + +e_g->e_g_s + + + + + +e_g_s-shift + +{e g s-shift} +ChangeSize -5 mil + + + +e_g->e_g_s-shift + + + + + +e_g_y + +{e g y} +ChangeSizes to Route style + + + +e_g->e_g_y + + + + + +g + +{g} + grid + + + +g_b + +{g b} +Previous grid + + + +g->g_b + + + + + +g_d + +{g d} +Grid *2 + + + +g->g_d + + + + + +g_f + +{g f} +Next grid + + + +g->g_f + + + + + +g_h + +{g h} +Grid /2 + + + +g->g_h + + + + + +g_i + +{g i} +mil + + + +g->g_i + + + + + +g_l + +{g l} +Enable local grid + + + +g->g_l + + + + + +g_m + +{g m} +mm + + + +g->g_m + + + + + +g_r + +{g r} +Realign grid + + + +g->g_r + + + + + +g_v + +{g v} +Enable visible grid + + + +g->g_v + + + + + +f + +{f} + file + + + +f_x + +{f x} + export to + + + +f->f_x + + + + + +f_c + +{f c} +Export with CAM job... + + + +f->f_c + + + + + +f_a + +{f a} +Save Layout As... + + + +f->f_a + + + + + +f_e + +{f e} +Export layout... + + + +f->f_e + + + + + +f_l + +{f l} +Load layout... + + + +f->f_l + + + + + +f_n + +{f n} +Start New Layout + + + +f->f_n + + + + + +f_o + +{f o} +Load layout... + + + +f->f_o + + + + + +f_p + +{f p} +Print layout... + + + +f->f_p + + + + + +f_q + +{f q} +Quit Program + + + +f->f_q + + + + + +f_r + +{f r} +Revert + + + +f->f_r + + + + + +f_s + +{f s} +Save Layout + + + +f->f_s + + + + + +f_x_p + +{f x p} +netlist patch for back annotation + + + +f_x->f_x_p + + + + + +i + +{i} + info + + + +i_c + +{i c} + configuration + + + +i->i_c + + + + + +i_a + +{i a} +About... + + + +i->i_a + + + + + +i_d + +{i d} +Generate drill summary + + + +i->i_d + + + + + +i_f + +{i f} +Report found padstacks + + + +i->i_f + + + + + +i_r + +{i r} +Generate object report + + + +i->i_r + + + + + +i_c_c + +{i c c} +Calibrate Printer... + + + +i_c->i_c_c + + + + + +i_c_i + +{i c i} +Data integrity check + + + +i_c->i_c_i + + + + + +i_c_p + +{i c p} +Preferences... + + + +i_c->i_c_p + + + + + +i_c_r + +{i c r} +Re-scan the footprint library + + + +i_c->i_c_r + + + + + +m + +{m} + mode + + + +m_c + +{m c} + cursor/crosshair mode + + + +m->m_c + + + + + +m_d + +{m d} + drawing (render) mode + + + +m->m_d + + + + + +m_f + +{m f} + floater mode + + + +m->m_f + + + + + +m_l + +{m l} + line drawing (routing) settings + + + +m->m_l + + + + + +m_t + +{m t} + text drawing (routing) settings + + + +m->m_t + + + + + +m_p + +{m p} + polygon drawing mode + + + +m->m_p + + + + + +m_r + +{m r} + rubber band mode + + + +m->m_r + + + + + +m_k + +m_k + + + +m->m_k + + + + + +m_o + +m_o + + + +m->m_o + + + + + +m_c_c + +{m c c} +Crosshair shows DRC clearance + + + +m_c->m_c_c + + + + + +m_c_o + +{m c o} +Orthogonal moves + + + +m_c->m_c_o + + + + + +m_c_p + +{m c p} +Crosshair snaps to padstacks + + + +m_c->m_c_p + + + + + +m_c_s + +{m c s} +Crosshair snaps to off-grid points on lines + + + +m_c->m_c_s + + + + + +m_d_a + +{m d a} +Show autorouter trials + + + +m_d->m_d_a + + + + + +m_d_c + +{m d c} +Check polygons + + + +m_d->m_d_c + + + + + +m_d_d + +{m d d} +poly as-drawn frame annotation + + + +m_d->m_d_d + + + + + +m_d_h + +{m d h} +Highlighting on line, arc points + + + +m_d->m_d_h + + + + + +m_d_p + +{m d p} +Thin draw poly + + + +m_d->m_d_p + + + + + +m_d_t + +{m d t} +Thin draw + + + +m_d->m_d_t + + + + + +m_d_w + +{m d w} +Wireframe draw + + + +m_d->m_d_w + + + + + +m_f_h + +{m f h} +Hide floaters + + + +m_f->m_f_h + + + + + +m_f_l + +{m f l} +Lock floaters + + + +m_f->m_f_l + + + + + +m_f_o + +{m f o} +Only floaters + + + +m_f->m_f_o + + + + + +m_l_+ + +{m l +} +Line Tool size +5 mil + + + +m_l->m_l_+ + + + + + +m_l_- + +{m l -} +Line Tool size -5 mil + + + +m_l->m_l_- + + + + + +m_l_a + +{m l a} +'All-direction' lines + + + +m_l->m_l_a + + + + + +m_l_c + +{m l c} +New lines, arcs clear polygons + + + +m_l->m_l_c + + + + + +m_l_d + +{m l d} +Auto enforce DRC clearance + + + +m_l->m_l_d + + + + + +m_l_f + +{m l f} +Cycle line clip/refraction + + + +m_l->m_l_f + + + + + +m_t_+ + +{m t +} +Text Tool scale +10 mil + + + +m_t->m_t_+ + + + + + +m_t_- + +{m t -} +Text Tool scale -10 mil + + + +m_t->m_t_- + + + + + +m_p_c + +{m p c} +New polygons clear polygons + + + +m_p->m_p_c + + + + + +m_p_f + +{m p f} +New polygons are full ones + + + +m_p->m_p_f + + + + + +m_p_i + +{m p i} +Polygon clip inhibit (toggle) + + + +m_p->m_p_i + + + + + +m_r_m + +{m r m} +Rubber band keeps middle line dir + + + +m_r->m_r_m + + + + + +m_r_r + +{m r r} +Rubber band mode + + + +m_r->m_r_r + + + + + +s + +{s} + select + + + +s_a + +{s a} + select all... + + + +s->s_a + + + + + +s_u + +{s u} + unselect all... + + + +s->s_u + + + + + +s_c + +{s c} + convert selected + + + +s->s_c + + + + + +s_b + +s_b + + + +s->s_b + + + + + +s_f + +{s f} +Move selected subcircuits to other side + + + +s->s_f + + + + + +s_i + +{s i} +Invert selection + + + +s->s_i + + + + + +s_l + +{s l} +Move selected objects to current layer + + + +s->s_l + + + + + +s_r + +{s r} +Remove selected objects + + + +s->s_r + + + + + +s_s + +{s s} +Advanced search and select + + + +s->s_s + + + + + +s_a_a + +{s a a} +Select all visible objects + + + +s_a->s_a_a + + + + + +s_a_c + +{s a c} +Select all connected objects + + + +s_a->s_a_c + + + + + +s_u_a + +{s u a} +Unselect all objects + + + +s_u->s_u_a + + + + + +s_u_c + +{s u c} +unselect all connected objects + + + +s_u->s_u_c + + + + + +s_c_p + +{s c p} +Convert selection to padstack + + + +s_c->s_c_p + + + + + +s_c_s + +{s c s} +Convert selection to subcircuit + + + +s_c->s_c_s + + + + + +r + +{r} + routing helper + + + +r_r + +{r r} + routing radius + + + +r->r_r + + + + + +r_r_+ + +{r r +} +Route radius +0.5 + + + +r_r->r_r_+ + + + + + +r_r_- + +{r r -} +Route radius -0.5 + + + +r_r->r_r_- + + + + + +r_r_m + +{r r m} +Route radius -0.5 + + + +r_r->r_r_m + + + + + +r_r_p + +{r r p} +Route radius +0.5 + + + +r_r->r_r_p + + + + + +t + +{t} + tool + + + +t_a + +{t a} +Arc + + + +t->t_a + + + + + +t_b + +{t b} +Buffer + + + +t->t_b + + + + + +t_c + +{t c} +Copy + + + +t->t_c + + + + + +t_d + +{t d} +Del/Remove + + + +t->t_d + + + + + +t_e + +{t e} +Thermal + + + +t->t_e + + + + + +t_h + +{t h} +Polygon Hole + + + +t->t_h + + + + + +t_i + +{t i} +Insert Point + + + +t->t_i + + + + + +t_k + +{t k} +Lock + + + +t->t_k + + + + + +t_l + +{t l} +Line + + + +t->t_l + + + + + +t_m + +{t m} +Move + + + +t->t_m + + + + + +t_n + +{t n} +Arrow + + + +t->t_n + + + + + +t_o + +{t o} +Rotate + + + +t->t_o + + + + + +t_p + +{t p} +Polygon + + + +t->t_p + + + + + +t_r + +{t r} +Rectangle + + + +t->t_r + + + + + +t_t + +{t t} +Text + + + +t->t_t + + + + + +t_v + +{t v} +Via + + + +t->t_v + + + + + +u + +{u} + undo + + + +u_c + +{u c} +Clear undo-buffer + + + +u->u_c + + + + + +u_d + +{u d} +Undo dialog (for debugging) + + + +u->u_d + + + + + +u_r + +{u r} +Redo last undone operation + + + +u->u_r + + + + + +u_u + +{u u} +Undo last operation + + + +u->u_u + + + + + +v + +{v} + view + + + +v_s + +{v s} + set view + + + +v->v_s + + + + + +v_c + +{v c} +Center cursor + + + +v->v_c + + + + + +v_f + +{v f} +Zoom Extents + + + +v->v_f + + + + + +v_n + +{v n} +Show padstack numbers in a subc + + + +v->v_n + + + + + +v_t + +v_t + + + +v->v_t + + + + + +v_s_c + +{v s c} +user configured + + + +v_s->v_s_c + + + + + +v_s_f + +{v s f} +footprint + + + +v_s->v_s_f + + + + + +v_s_r + +{v s r} +refdes + + + +v_s->v_s_r + + + + + +v_s_s + +{v s s} +refdes+value + + + +v_s->v_s_s + + + + + +v_s_v + +{v s v} +value + + + +v_s->v_s_v + + + + + +w + +{w} + window + + + +w_a + +{w a} +About... + + + +w->w_a + + + + + +w_d + +{w d} +DRC Check + + + +w->w_d + + + + + +w_f + +{w f} +Font selector + + + +w->w_f + + + + + +w_l + +{w l} +Library + + + +w->w_l + + + + + +w_m + +{w m} +Message Log + + + +w->w_m + + + + + +w_n + +{w n} +Netlist + + + +w->w_n + + + + + +w_p + +{w p} +Pinout + + + +w->w_p + + + + + +m_k_s + +{m k s} +Loose subcircuits (no subc lock) + + + +m_k->m_k_s + + + + + +m_o_b + +{m o b} +black current group + + + +m_o->m_o_b + + + + + +m_o_i + +{m o i} +Invisible-color on other groups + + + +m_o->m_o_i + + + + + +n_c_f + +{n c f} +claim net on found + + + +n + +n + + + +n_c + +n_c + + + +n->n_c + + + + + +n_c->n_c_f + + + + + +n_c_o + +{n c o} +claim net by object + + + +n_c->n_c_o + + + + + +n_c_s + +{n c s} +claim net on selected + + + +n_c->n_c_s + + + + + +p_m_p + +{p m p} +Manage plugins... + + + +p + +p + + + +p_m + +p_m + + + +p->p_m + + + + + +p_m->p_m_p + + + + + +p_m_s + +{p m s} +Manage scripts... + + + +p_m->p_m_s + + + + + +s_b_p + +{s b p} +Break selection padstack to pieces + + + +s_b->s_b_p + + + + + +s_b_s + +{s b s} +Break selection subcircuits to pieces + + + +s_b->s_b_s + + + + + +v_t_c + +{v t c} +user configured + + + +v_t->v_t_c + + + + + +v_t_n + +{v t n} +name + + + +v_t->v_t_n + + + + + +v_t_s + +{v t s} +term+name + + + +v_t->v_t_s + + + + + +v_t_t + +{v t t} +term + + + +v_t->v_t_t + + + + + +z_e + +{z e} +Zoom Extents + + + +z + +z + + + +z->z_e + + + + + +z_f + +{z f} +Zoom to found + + + +z->z_f + + + + + +z_s + +{z s} +Zoom to selection + + + +z->z_s + + + + + +z_x + +{z x} +Zoom Out 20% + + + +z->z_x + + + + + +z_z + +{z z} +Zoom In 20% + + + +z->z_z + + + + + Index: tags/2.1.2/doc/user/05_ui/06_common/keytree.txt =================================================================== --- tags/2.1.2/doc/user/05_ui/06_common/keytree.txt (nonexistent) +++ tags/2.1.2/doc/user/05_ui/06_common/keytree.txt (revision 24813) @@ -0,0 +1,284 @@ ++ pcb-menu-default.lht Zoom(-1.2) Zoom In 20% +, pcb-menu-default.lht CycleDrag() Cycle object being dragged +- pcb-menu-default.lht Zoom(+1.2) Zoom Out 20% +. pcb-menu-default.lht conf(toggle, editor\057all_direction_lines, design) 'All-direction' lines +0 pcb-menu-default.lht SelectLayer(10) Select Layer 10 +0-alt pcb-menu-default.lht SelectLayer(20) Select Layer 20 +0-alt-ctrl pcb-menu-default.lht ToggleView(20) Toggle Layer 20 +0-ctrl pcb-menu-default.lht ToggleView(10) Toggle Layer 10 +1 pcb-menu-default.lht SelectLayer(1) Select Layer 1 +1-alt pcb-menu-default.lht SelectLayer(11) Select Layer 11 +1-alt-ctrl pcb-menu-default.lht ToggleView(11) Toggle Layer 11 +1-ctrl pcb-menu-default.lht ToggleView(1) Toggle Layer 1 +2 pcb-menu-default.lht SelectLayer(2) Select Layer 2 +2-alt pcb-menu-default.lht SelectLayer(12) Select Layer 12 +2-alt-ctrl pcb-menu-default.lht ToggleView(12) Toggle Layer 12 +2-ctrl pcb-menu-default.lht ToggleView(2) Toggle Layer 2 +3 pcb-menu-default.lht SelectLayer(3) Select Layer 3 +3-alt pcb-menu-default.lht SelectLayer(13) Select Layer 13 +3-alt-ctrl pcb-menu-default.lht ToggleView(13) Toggle Layer 13 +3-ctrl pcb-menu-default.lht ToggleView(3) Toggle Layer 3 +4 pcb-menu-default.lht SelectLayer(4) Select Layer 4 +4-alt pcb-menu-default.lht SelectLayer(14) Select Layer 14 +4-alt-ctrl pcb-menu-default.lht ToggleView(14) Toggle Layer 14 +4-ctrl pcb-menu-default.lht ToggleView(4) Toggle Layer 4 +5 pcb-menu-default.lht SelectLayer(5) Select Layer 5 +5-alt pcb-menu-default.lht SelectLayer(15) Select Layer 15 +5-alt-ctrl pcb-menu-default.lht ToggleView(15) Toggle Layer 15 +5-ctrl pcb-menu-default.lht ToggleView(5) Toggle Layer 5 +6 pcb-menu-default.lht SelectLayer(6) Select Layer 6 +6-alt pcb-menu-default.lht SelectLayer(16) Select Layer 16 +6-alt-ctrl pcb-menu-default.lht ToggleView(16) Toggle Layer 16 +6-ctrl pcb-menu-default.lht ToggleView(6) Toggle Layer 6 +7 pcb-menu-default.lht SelectLayer(7) Select Layer 7 +7-alt pcb-menu-default.lht SelectLayer(17) Select Layer 17 +7-alt-ctrl pcb-menu-default.lht ToggleView(17) Toggle Layer 17 +7-ctrl pcb-menu-default.lht ToggleView(7) Toggle Layer 7 +8 pcb-menu-default.lht SelectLayer(8) Select Layer 8 +8-alt pcb-menu-default.lht SelectLayer(18) Select Layer 18 +8-alt-ctrl pcb-menu-default.lht ToggleView(18) Toggle Layer 18 +8-ctrl pcb-menu-default.lht ToggleView(8) Toggle Layer 8 +9 pcb-menu-default.lht SelectLayer(9) Select Layer 9 +9-alt pcb-menu-default.lht SelectLayer(19) Select Layer 19 +9-alt-ctrl pcb-menu-default.lht ToggleView(19) Toggle Layer 19 +9-ctrl pcb-menu-default.lht ToggleView(9) Toggle Layer 9 +: pcb-menu-default.lht Command() Command Entry +[ pcb-menu-default.lht Grid(down) Previous grid +\ pcb-menu-default.lht fullscreen(toggle) Full screen +\057 pcb-menu-default.lht Display(CycleClip) Cycle line clip\057refraction +] pcb-menu-default.lht Grid(up) Next grid +a;a pcb-menu-default.lht Mode(Save);Mode(Arc);Mode(Notify) Start routing an arc +a;b;f; pcb-menu-default.lht ReplaceFootprint() Replace footprint +a;b;s; pcb-menu-default.lht net(swap) Swap nets on two selected pins +a;b;x pcb-menu-default.lht SavePatch() netlist patch for back annotation +a;d;a; pcb-menu-default.lht DisperseElements(All) Disperse all subcircuits +a;d;s; pcb-menu-default.lht DisperseElements(Selected) Disperse selected subcircuits +a;l pcb-menu-default.lht Mode(Save);Mode(Line);Mode(Notify) Start routing a line +a;m pcb-menu-default.lht MarkCrosshair() Place mark +a;o;a; pcb-menu-default.lht djopt(auto) Auto-Optimize +a;o;d; pcb-menu-default.lht djopt(debumpify) Debumpify +a;o;m; pcb-menu-default.lht djopt(miter) Miter +a;o;n; pcb-menu-default.lht djopt(vianudge) Vianudge +a;o;o; pcb-menu-default.lht djopt(orthopull) Ortho pull +a;o;p; pcb-menu-default.lht Puller() Puller +a;o;s; pcb-menu-default.lht djopt(simple) Simple optimization +a;o;t; pcb-menu-default.lht djopt(viatrim) Viatrim +a;o;u; pcb-menu-default.lht djopt(unjaggy) Unjaggy +a;p;s; pcb-menu-default.lht AutoPlaceSelected() Auto-place selected subcircuits +a;r;a; pcb-menu-default.lht AutoRoute(AllRats) Auto-route all rats +a;r;r; pcb-menu-default.lht RipUp(All) Rip up all auto-routed tracks +a;r;s; pcb-menu-default.lht AutoRoute(SelectedRats) Auto-route selected rats +a;r;t; pcb-menu-default.lht RipUp(Selected) Rip up selected auto-routed tracks +a;v pcb-menu-default.lht Mode(Save);Mode(Via);Mode(Notify);Mode(Restore) Place via +a;w pcb-menu-default.lht MarkCrosshair() Place mark +a;x; pcb-menu-default.lht DRC() Design Rule Checker +b;1; pcb-menu-default.lht PasteBuffer(1) Select Buffer #1 +b;2; pcb-menu-default.lht PasteBuffer(2) Select Buffer #2 +b;3; pcb-menu-default.lht PasteBuffer(3) Select Buffer #3 +b;4; pcb-menu-default.lht PasteBuffer(4) Select Buffer #4 +b;5; pcb-menu-default.lht PasteBuffer(5) Select scratchpad +b;b; pcb-menu-default.lht LayerBinding(buffer) Layer bindings... +b;c;c; pcb-menu-default.lht PasteBuffer(Clear) Clear buffer +b;c;p pcb-menu-default.lht PadstackConvert(buffer);Mode(PasteBuffer) Convert buffer to padstack +b;c;s pcb-menu-default.lht PasteBuffer(ConvertSubc) Convert buffer to subcircuit +b;m;l pcb-menu-default.lht Mode(PasteBuffer);PasteBuffer(Rotate,1);PasteBuffer(Mirror);PasteBuffer(Rotate,3) Mirror buffer (left\057right) +b;m;u pcb-menu-default.lht Mode(PasteBuffer);PasteBuffer(Mirror) Mirror buffer (up\057down) +b;n pcb-menu-default.lht Mode(PasteBuffer);PasteBuffer(Rotate,1);PasteBuffer(Normalize) Normalize +b;r;a pcb-menu-default.lht Mode(PasteBuffer);FreeRotateBuffer() Arbitrarily Rotate Buffer +b;r;l pcb-menu-default.lht Mode(PasteBuffer);PasteBuffer(Rotate,1) Rotate buffer 90 deg CCW (left) +b;r;r pcb-menu-default.lht Mode(PasteBuffer);PasteBuffer(Rotate,3) Rotate buffer 90 deg CW (right) +b;s;b pcb-menu-default.lht PasteBuffer(Restore) Break buffer subcircuits to pieces +b;s;p pcb-menu-default.lht PadstackBreakup(buffer) Break buffer padstacks to pieces +b;s;s pcb-menu-default.lht Save(PasteBuffer) Save buffer subcircuits to file +c-ctrl; pcb-menu-default.lht GetXY(Click to set the snap point for this buffer);PasteBuffer(Clear);PasteBuffer(AddSelected);Unselect(All);Mode(PasteBuffer) Copy selection to buffer +c;c; pcb-menu-default.lht Connection(Reset);Display(Redraw) Clear\057reset lookup +c;d; pcb-menu-default.lht Atomic(Save);Connection(Reset);Atomic(Restore);Unselect(All);Atomic(Restore);Connection(Find);Atomic(Restore);Select(Connection);Atomic(Restore);RemoveSelected();Atomic(Restore);Connection(Reset);Atomic(Restore);Unselect(All);Atomic(Block) Del\057Remove Connected +c;e; pcb-menu-default.lht DeleteRats(AllRats) Erase rats nest +c;f; pcb-menu-default.lht Connection(Reset);Connection(Find) Find Connections +c;r; pcb-menu-default.lht Atomic(Save);DeleteRats(AllRats);Atomic(Restore);AddRats(AllRats);Atomic(Block) Optimize rats nest +c;s; pcb-menu-default.lht AddRats(Close) Select shortest rat +delete pcb-menu-default.lht Mode(Save);Mode(Remove);Mode(Notify);Mode(Restore) Remove object +down pcb-menu-default.lht Cursor(Warp,0,-1,grid) Step Down +down-shift pcb-menu-default.lht Cursor(Pan,0,-50,view) Step +Down +e;c pcb-menu-default.lht GetXY(Click to set the snap point for this buffer);PasteBuffer(Clear);PasteBuffer(AddSelected);Unselect(All);Mode(PasteBuffer) Copy selection to buffer +e;d pcb-menu-default.lht Mode(Save);Mode(Remove);Mode(Notify);Mode(Restore) Remove object +e;f pcb-menu-default.lht FlagEdit() Object flags... +e;g;c pcb-menu-default.lht ChangeClearSize(Object,+2,mil) Clearance +2 mil +e;g;c-shift pcb-menu-default.lht ChangeClearSize(Object,-2,mil) Clearance -2 mil +e;g;d pcb-menu-default.lht ChangeDrillSize(Object,+5,mil) ChangeDrill +5 mil +e;g;d-shift pcb-menu-default.lht ChangeDrillSize(Object,-5,mil) ChangeDrill -5 mil +e;g;s pcb-menu-default.lht ChangeSize(Object,+5,mil) ChangeSize +5 mil +e;g;s-shift pcb-menu-default.lht ChangeSize(Object,-5,mil) ChangeSize -5 mil +e;g;y pcb-menu-default.lht ChangeSizes(Object,style,mil) ChangeSizes to Route style +e;i pcb-menu-default.lht Flip(Object) Flip Object +e;j pcb-menu-default.lht ChangeJoin(Object) ChangeJoin Object +e;l pcb-menu-default.lht MoveToCurrentLayer(Object) Move to current layer +e;o pcb-menu-default.lht FontSel(Object) Change font... +e;p pcb-menu-default.lht PropEdit(selection) Object Properties... +e;r pcb-menu-default.lht ChangeName(Refdes) Change refdes +e;s;b pcb-menu-default.lht LayerBinding() Layer bindings... +e;s;e pcb-menu-default.lht GetXY(Click on the subcircuit to edit);extedit(object) External editor... +e;s;r pcb-menu-default.lht ChangeName(Subc) Refdes +e;s;s pcb-menu-default.lht SetSame() Set Same Style +e;t pcb-menu-default.lht ChangeName(Object) Edit text... +e;v pcb-menu-default.lht Mode(PasteBuffer) Paste buffer to layout +e;x pcb-menu-default.lht GetXY(Click to set the snap point for this buffer);PasteBuffer(Clear);PasteBuffer(AddSelected);RemoveSelected();Unselect(All);Mode(PasteBuffer) Cut selection to buffer +e;y; pcb-menu-default.lht CycleDrag() Cycle object being dragged +enter pcb-menu-default.lht Mode(Notify);Mode(Release) Click +escape pcb-menu-default.lht Mode(Escape) Cancel +f1 pcb-menu-default.lht Mode(Via) Via +f10 pcb-menu-default.lht Mode(Thermal) Thermal +f11 pcb-menu-default.lht Mode(Arrow) Arrow +f12 pcb-menu-default.lht Mode(Lock) Lock +f2 pcb-menu-default.lht Mode(Line) Line +f3 pcb-menu-default.lht Mode(Arc) Arc +f4 pcb-menu-default.lht Mode(Text) Text +f5 pcb-menu-default.lht Mode(Rectangle) Rectangle +f6 pcb-menu-default.lht Mode(Polygon) Polygon +f7 pcb-menu-default.lht Mode(PasteBuffer) Buffer +f7-shift pcb-menu-default.lht Mode(PasteBuffer);PasteBuffer(Rotate,1) Rotate buffer 90 deg CCW (left) +f8 pcb-menu-default.lht Mode(Remove) Del\057Remove +f9 pcb-menu-default.lht Mode(Rotate) Rotate +f;a pcb-menu-default.lht Save(LayoutAs) Save Layout As... +f;c pcb-menu-default.lht cam() Export with CAM job... +f;e pcb-menu-default.lht ExportGUI() Export layout... +f;l pcb-menu-default.lht Load(Layout) Load layout... +f;n pcb-menu-default.lht New() Start New Layout +f;o pcb-menu-default.lht Load(Layout) Load layout... +f;p pcb-menu-default.lht Print() Print layout... +f;q pcb-menu-default.lht Quit() Quit Program +f;r pcb-menu-default.lht Load(Revert,none) Revert +f;s pcb-menu-default.lht Save(Layout) Save Layout +f;x;p pcb-menu-default.lht SavePatch() netlist patch for back annotation +g;b pcb-menu-default.lht Grid(down) Previous grid +g;d pcb-menu-default.lht SetValue(Grid,*2) Grid *2 +g;f pcb-menu-default.lht Grid(up) Next grid +g;h pcb-menu-default.lht SetValue(Grid,\0572) Grid \0572 +g;i pcb-menu-default.lht SetUnits(mil) mil +g;l pcb-menu-default.lht conf(toggle, plugins\057hid_gtk\057local_grid\057enable, design) Enable local grid +g;m pcb-menu-default.lht SetUnits(mm) mm +g;r pcb-menu-default.lht GetXY(Click to set the grid origin); Display(ToggleGrid) Realign grid +g;v pcb-menu-default.lht conf(toggle, editor\057draw_grid, design) Enable visible grid +i;a pcb-menu-default.lht About() About... +i;c;c pcb-menu-default.lht PrintCalibrate() Calibrate Printer... +i;c;i pcb-menu-default.lht Integrity() Data integrity check +i;c;p pcb-menu-default.lht preferences Preferences... +i;c;r pcb-menu-default.lht fp_rehash() Re-scan the footprint library +i;d pcb-menu-default.lht Report(DrillReport) Generate drill summary +i;f pcb-menu-default.lht Report(FoundPins) Report found padstacks +i;r pcb-menu-default.lht ReportObject() Generate object report +insert pcb-menu-default.lht Mode(InsertPoint) Insert Point +left pcb-menu-default.lht Cursor(Warp,-1,0,grid) Step Left +left-shift pcb-menu-default.lht Cursor(Pan,-50,0,view) Step +Left +m;c;c pcb-menu-default.lht conf(toggle, editor\057show_drc, design) Crosshair shows DRC clearance +m;c;o pcb-menu-default.lht conf(toggle, editor\057orthogonal_moves, design) Orthogonal moves +m;c;p pcb-menu-default.lht conf(toggle, editor\057snap_pin, design) Crosshair snaps to padstacks +m;c;s pcb-menu-default.lht conf(toggle, editor\057snap_offgrid_line, design) Crosshair snaps to off-grid points on lines +m;d;a pcb-menu-default.lht conf(toggle, editor\057live_routing, design) Show autorouter trials +m;d;c pcb-menu-default.lht conf(toggle, editor\057check_planes, design) Check polygons +m;d;d pcb-menu-default.lht conf(toggle, editor\057as_drawn_poly, design) poly as-drawn frame annotation +m;d;h pcb-menu-default.lht conf(toggle, editor\057highlight_on_point, design) Highlighting on line, arc points +m;d;p pcb-menu-default.lht conf(toggle, editor\057thin_draw_poly, design) Thin draw poly +m;d;t pcb-menu-default.lht conf(toggle, editor\057thin_draw, design) Thin draw +m;d;w pcb-menu-default.lht conf(toggle, editor\057wireframe_draw, design) Wireframe draw +m;f;h pcb-menu-default.lht conf(toggle, editor\057hide_names, design) Hide floaters +m;f;l pcb-menu-default.lht conf(toggle, editor\057lock_names, design) Lock floaters +m;f;o pcb-menu-default.lht conf(toggle, editor\057only_names, design) Only floaters +m;k;s pcb-menu-default.lht subc(loose, toggle) Loose subcircuits (no subc lock) +m;l;+ pcb-menu-default.lht SetValue(LineSize,+5,mil) Line Tool size +5 mil +m;l;- pcb-menu-default.lht SetValue(LineSize,-5,mil) Line Tool size -5 mil +m;l;a pcb-menu-default.lht conf(toggle, editor\057all_direction_lines, design) 'All-direction' lines +m;l;c pcb-menu-default.lht conf(toggle, editor\057clear_line, design) New lines, arcs clear polygons +m;l;d pcb-menu-default.lht conf(toggle, editor\057auto_drc, design) Auto enforce DRC clearance +m;l;f pcb-menu-default.lht Display(CycleClip) Cycle line clip\057refraction +m;o;b pcb-menu-default.lht conf(toggle, appearance\057black_current_group, design) black current group +m;o;i pcb-menu-default.lht conf(toggle, appearance\057invis_other_groups, design) Invisible-color on other groups +m;p;c pcb-menu-default.lht conf(toggle, editor\057clear_polypoly, design) New polygons clear polygons +m;p;f pcb-menu-default.lht conf(toggle, editor\057full_poly, design) New polygons are full ones +m;p;i pcb-menu-default.lht ClipInhibit(toggle) Polygon clip inhibit (toggle) +m;r;m pcb-menu-default.lht conf(toggle, editor\057rubber_band_keep_midlinedir, design) Rubber band keeps middle line dir +m;r;r pcb-menu-default.lht conf(toggle, editor\057rubber_band_mode, design) Rubber band mode +m;t;+ pcb-menu-default.lht SetValue(TextScale,+10,mil) Text Tool scale +10 mil +m;t;- pcb-menu-default.lht SetValue(TextScale,-10,mil) Text Tool scale -10 mil +n-ctrl pcb-menu-default.lht New() Start New Layout +n;c;f; pcb-menu-default.lht ClaimNet(found) claim net on found +n;c;o; pcb-menu-default.lht ClaimNet(object) claim net by object +n;c;s; pcb-menu-default.lht ClaimNet(selected) claim net on selected +p;m;p; pcb-menu-default.lht ManagePlugins() Manage plugins... +p;m;s; pcb-menu-default.lht BrowseScripts() Manage scripts... +q-ctrl pcb-menu-default.lht Quit() Quit Program +r;r;+ pcb-menu-default.lht conf(delta, editor\057route_radius, +0.5, design) Route radius +0.5 +r;r;- pcb-menu-default.lht conf(delta, editor\057route_radius, -0.5, design) Route radius -0.5 +r;r;m pcb-menu-default.lht conf(delta, editor\057route_radius, -0.5, design) Route radius -0.5 +r;r;p pcb-menu-default.lht conf(delta, editor\057route_radius, +0.5, design) Route radius +0.5 +right pcb-menu-default.lht Cursor(Warp,1,0,grid) Step Right +right-shift pcb-menu-default.lht Cursor(Pan,50,0,view) Step +Right +s-ctrl pcb-menu-default.lht Save(Layout) Save Layout +s-ctrl-shift pcb-menu-default.lht Save(LayoutAs) Save Layout As... +s;a;a; pcb-menu-default.lht Select(All) Select all visible objects +s;a;c; pcb-menu-default.lht Select(Connection) Select all connected objects +s;b;p pcb-menu-default.lht PadstackBreakup(selected) Break selection padstack to pieces +s;b;s pcb-menu-default.lht PasteBuffer(Push);PasteBuffer(5);PasteBuffer(Clear);PasteBuffer(AddSelected);RemoveSelected();PasteBuffer(Restore);PasteBuffer(ToLayout, crosshair);PasteBuffer(Clear);PasteBuffer(Pop) Break selection subcircuits to pieces +s;c;p; pcb-menu-default.lht PadstackConvert(selected);Mode(PasteBuffer) Convert selection to padstack +s;c;s; pcb-menu-default.lht Select(ConvertSubc) Convert selection to subcircuit +s;f; pcb-menu-default.lht Flip(SelectedElements) Move selected subcircuits to other side +s;i; pcb-menu-default.lht Select(Invert) Invert selection +s;l; pcb-menu-default.lht MoveToCurrentLayer(Selected) Move selected objects to current layer +s;r; pcb-menu-default.lht RemoveSelected() Remove selected objects +s;s; pcb-menu-default.lht DoWindows(search) Advanced search and select +s;u;a; pcb-menu-default.lht Unselect(All) Unselect all objects +s;u;c; pcb-menu-default.lht Unselect(Connection) unselect all connected objects +space pcb-menu-default.lht Mode(Arrow) Arrow +t;a pcb-menu-default.lht Mode(Arc) Arc +t;b pcb-menu-default.lht Mode(PasteBuffer) Buffer +t;c pcb-menu-default.lht Mode(Copy) Copy +t;d pcb-menu-default.lht Mode(Remove) Del\057Remove +t;e pcb-menu-default.lht Mode(Thermal) Thermal +t;h pcb-menu-default.lht Mode(PolygonHole) Polygon Hole +t;i pcb-menu-default.lht Mode(InsertPoint) Insert Point +t;k pcb-menu-default.lht Mode(Lock) Lock +t;l pcb-menu-default.lht Mode(Line) Line +t;m pcb-menu-default.lht Mode(Move) Move +t;n pcb-menu-default.lht Mode(Arrow) Arrow +t;o pcb-menu-default.lht Mode(Rotate) Rotate +t;p pcb-menu-default.lht Mode(Polygon) Polygon +t;r pcb-menu-default.lht Mode(Rectangle) Rectangle +t;t pcb-menu-default.lht Mode(Text) Text +t;v pcb-menu-default.lht Mode(Via) Via +tab pcb-menu-default.lht SwapSides(V) Flip up\057down +tab-ctrl pcb-menu-default.lht SwapSides(R) Spin 180 degrees +tab-ctrl-shift pcb-menu-default.lht SwapSides() Swap Sides +tab-shift pcb-menu-default.lht SwapSides(H) Flip left\057right +u;c pcb-menu-default.lht Undo(ClearList) Clear undo-buffer +u;d; pcb-menu-default.lht UndoDialog() Undo dialog (for debugging) +u;r pcb-menu-default.lht Redo() Redo last undone operation +u;u pcb-menu-default.lht Undo() Undo last operation +up pcb-menu-default.lht Cursor(Warp,0,1,grid) Step Up +up-shift pcb-menu-default.lht Cursor(Pan,0,50,view) Step +Up +v;c pcb-menu-default.lht Center() Center cursor +v;f pcb-menu-default.lht Zoom() Zoom Extents +v;n pcb-menu-default.lht Display(PinOrPadName) Show padstack numbers in a subc +v;s;c pcb-menu-default.lht Display(SubcID) user configured +v;s;f pcb-menu-default.lht Display(SubcID,"%a.footprint%") footprint +v;s;r pcb-menu-default.lht Display(SubcID, "%a.refdes%") refdes +v;s;s pcb-menu-default.lht Display(SubcID,"%a.refdes%\\n%a.value%") refdes+value +v;s;v pcb-menu-default.lht Display(SubcID,"%a.value%") value +v;t;c pcb-menu-default.lht Display(TermID) user configured +v;t;n pcb-menu-default.lht Display(TermID, "%a.name%") name +v;t;s pcb-menu-default.lht Display(TermID, "%a.term%,%a.name%") term+name +v;t;t pcb-menu-default.lht Display(TermID, "%a.term%") term +w;a pcb-menu-default.lht About() About... +w;d pcb-menu-default.lht DRC() DRC Check +w;f pcb-menu-default.lht FontSel() Font selector +w;l pcb-menu-default.lht DoWindows(Library) Library +w;m pcb-menu-default.lht LogDialog() Message Log +w;n pcb-menu-default.lht DoWindows(Netlist) Netlist +w;p pcb-menu-default.lht Display(Pinout) Pinout +y-ctrl pcb-menu-default.lht Redo() Redo last undone operation +z-ctrl pcb-menu-default.lht Undo() Undo last operation +z;e; pcb-menu-default.lht Zoom() Zoom Extents +z;f; pcb-menu-default.lht ZoomTo(found) Zoom to found +z;s; pcb-menu-default.lht ZoomTo(selected) Zoom to selection +z;x; pcb-menu-default.lht Zoom(+1.2) Zoom Out 20% +z;z; pcb-menu-default.lht Zoom(-1.2) Zoom In 20% +| pcb-menu-default.lht conf(toggle, editor\057wireframe_draw, design) Wireframe draw Index: tags/2.1.2/doc/user/05_ui/06_common/src/node_names.txt =================================================================== --- tags/2.1.2/doc/user/05_ui/06_common/src/node_names.txt (nonexistent) +++ tags/2.1.2/doc/user/05_ui/06_common/src/node_names.txt (revision 24813) @@ -0,0 +1,41 @@ +/a auto or add +/a/b back annotation +/a/p auto-place +/a/d auto-disperse +/a/r auto-route +/a/o optimize (djopt) +/b buffer +/b/c convert & clear +/b/m mirror +/b/r rotate +/b/s subcircuit +/c connections & rats +/e edit +/e/m move +/e/s subcircuit or style +/e/g geometry +/g grid +/f file +/f/x export to +/f/c configuration +/i info +/i/c configuration +/m mode +/m/c cursor/crosshair mode +/m/d drawing (render) mode +/m/f floater mode +/m/l line drawing (routing) settings +/m/t text drawing (routing) settings +/m/p polygon drawing mode +/m/r rubber band mode +/s select +/s/a select all... +/s/u unselect all... +/s/c convert selected +/r routing helper +/r/r routing radius +/t tool +/u undo +/v view +/v/s set view +/w window Index: tags/2.1.2/doc/user/05_ui/index.html =================================================================== --- tags/2.1.2/doc/user/05_ui/index.html (nonexistent) +++ tags/2.1.2/doc/user/05_ui/index.html (revision 24813) @@ -0,0 +1,29 @@ + + + + pcb-rnd user manual + + + + +

pcb-rnd - user manual

+ +

5. User Interface (UI)

+

+pcb-rnd offers various user interface plugins. The plugins connect different +input methods to the pcb-rnd core, offering functionality to match a variety of +user tools, experience, or desired workflows. +

+The following sections describe all the existing pcb-rnd UI plugins. We start +with the section on GTK+ because it is the most commonly used HID +

+

+ + Index: tags/2.1.2/doc/user/06_feature/acompnet/index.html =================================================================== --- tags/2.1.2/doc/user/06_feature/acompnet/index.html (nonexistent) +++ tags/2.1.2/doc/user/06_feature/acompnet/index.html (revision 24813) @@ -0,0 +1,16 @@ + + + + pcb-rnd user manual + + + + +

Acompnet plugin

+

+Acompnet was originally conceived as a limited autorouter and layout assistant. +

+Issues: Acompnet is a work in progress, incomplete, and as such it is currently disabled by default in the +pcb-rnd builds. + + Index: tags/2.1.2/doc/user/06_feature/asm/index.html =================================================================== --- tags/2.1.2/doc/user/06_feature/asm/index.html (nonexistent) +++ tags/2.1.2/doc/user/06_feature/asm/index.html (revision 24813) @@ -0,0 +1,89 @@ + + + + pcb-rnd user manual + + + + +

asm - manual assembly helper

+

+The asm plugin provides an action called asm which pops up a dialog +box that assists manual assembly of the current board. The plugin is useful only +with a GUI HID. +

+The plugin lists, groups and sorts all subcircuits (parts) that are placed +on the current board. The asm dialog presents all subcircuits in a tree of two +levels. the first level is all part groups. In each part group, the second level +is all parts that have the same grouping template. The list of groups is +sorted by group properties and the lists of parts within each groups are +sorted by the sorting template. While the assembly dialog is open, clicking a +part or a group of parts will highlight (select) the parts in the main window. + +

Intended use: rapid full board building

+

+The intended use is configuring the plugin to group parts by assembly steps. +Each group should contain parts that are "coming from the same bin". Within +each group parts should be sorted by board side and location. +

+The user should click the first part in the first group, check the highlight, +solder on the part and click the 'part done' button. This will skip to the +next part, while the focus stays on the same button. From now on, simply +pressing enter indicates the currently highlighted part is done, soldered +on the board. +

+In this setup the grouping template should contain a height hint attribute +of the subcircuits so that taller parts are built last. + +

Intended use: build by functionality

+

+It is also possible to configure the grouping/sorting templates to support +a per functionality build, which is more useful in building and testing the +first prototype. +

+In this scenario subcircuits shall have a dedicated attribute defining +which functionality each part belongs to - preferably this attribute +should be coming from the schematics. The group template shall contain this +attribute as the first field, so groups are created and sorted by functionality. + +

Templates

+

+There are two configured templates under /plugins/asm1: +

    +
  • group_template: for rendering the group string for each part +
  • sort_template: for rendering the sort string for each part +
+

+The group string is used for grouping parts and as the sorting function +for the groups. If two parts have the same group string, they will end up +in the same group. The sort string is used for sorting parts within +their group. +

+A template is comma separated list of directives. A directive is one of +the following: +

+ +
directive substituted with... +
side either "0/top" or "1/bottom" depending on which side the subcircuit is placed on +
x subcircuit origin X coordinate in mm, without unit +
y subcircuit origin X coordinate in mm, without unit +
a.keywith the value of the subcircuit's attribute with matching key +
+

+For example the group template +

+a.footprint, a.value, a.asm::group
+
+

+will be executed by pasting the footprint attribute, a comma, the value +attribute, a comma and the asm::group attribute. This will typically result +in something like "1206,100nF,". The resulting group string is then used for +grouping and sorting the groups alphabetically. + + + + + + + + Index: tags/2.1.2/doc/user/06_feature/autocrop/index.html =================================================================== --- tags/2.1.2/doc/user/06_feature/autocrop/index.html (nonexistent) +++ tags/2.1.2/doc/user/06_feature/autocrop/index.html (revision 24813) @@ -0,0 +1,32 @@ + + + + pcb-rnd user manual + + + + +

Autocrop plugin

+

+Use the autocrop action to resize your pcb-board to extants +

Description

+

+Autocrop finds the extents of your existing layout and resizes the board +dimensions to contain only your parts plus a margin along the edge. +

+Syntax: +
+autocrop(); +

+Use: +
+Bind autocrop to a key in the appropriate pcb-menu-*.lht for your preferred pcb-rnd gui. +

+Issues: +
Autocrop will move the objects to crop the layout, and as a consequence autocrop() plugin will take time to calculate for complex layouts. +
Autocrop is not undoable. +
Edge clearance is fixed at 5*line spacing + + + + Index: tags/2.1.2/doc/user/06_feature/autoplace/index.html =================================================================== --- tags/2.1.2/doc/user/06_feature/autoplace/index.html (nonexistent) +++ tags/2.1.2/doc/user/06_feature/autoplace/index.html (revision 24813) @@ -0,0 +1,22 @@ + + + + pcb-rnd user manual + + + + +

Autoplace plugin

+

+The autoplace plugin looks at the netlist and tries to place subcircuits +in a way to get routing easier. The algorithms follow those described in +sections 4.1 of "Placement and Routing of Electronic Modules" edited by +Michael Pecht Marcel Dekker, Inc. 1993. ISBN: 0-8247-8916-4 TK7868.P7.P57 +1993. +

+The plugin declares action AutoPlaceSelected which operates on +the selected subcircuits. A netlist shall be loaded and subcircuits +available on the board before the action is invoked. + + + Index: tags/2.1.2/doc/user/06_feature/autoroute/index.html =================================================================== --- tags/2.1.2/doc/user/06_feature/autoroute/index.html (nonexistent) +++ tags/2.1.2/doc/user/06_feature/autoroute/index.html (revision 24813) @@ -0,0 +1,46 @@ + + + + pcb-rnd user manual + + + + +

Autoroute plugin

+

+Tha autoroute plugin attempts to route traces according to the netlist, +after subcircuit placement is done by the user. There are two modes of +operation: +

    +
  • route all rat lines +
  • route only the selected rat lines +
+

+Limiting the operation to selected rat lines only gives some control +to the user; typical use is to route critical nets first, while the board +is sparse and leave less important nets to the end (getting them longer and +have more vias). +

+The autorouter uses only the currently visible copper layers and places +vias and jumps layers where necessary. +

+Before the autorouter is ran, a netlist should be imported, subcircuits +should be loaded and placed. Other plugins, such as the + autoplace or smartdisperse can help with +the placement. After the autorouting, djopt +actions can be used to purify the routed tracks. +

+The plugin implements a rectangle-expansion router, based on +"A Method for Gridless Routing of Printed Circuit Boards" by +A. C. Finch, K. J. Mackenzie, G. J. Balsdon, and G. Symonds in the +1985 Proceedings of the 22nd ACM/IEEE Design Automation Conference. +This reference is available from the ACM Digital Library at +http://www.acm.org/dl for those with institutional or personal +access to it. +

+Note: the built-in autorouter is not very smart. There are 3rd party, external +autorouters that can do better job on some boards, and pcb-rnd supports +export/import to communicate with them. + + + Index: tags/2.1.2/doc/user/06_feature/cam/index.html =================================================================== --- tags/2.1.2/doc/user/06_feature/cam/index.html (nonexistent) +++ tags/2.1.2/doc/user/06_feature/cam/index.html (revision 24813) @@ -0,0 +1,170 @@ + + + + pcb-rnd user manual + + + + +

CAM support

+

+The purpose of the CAM support is to provide an unified interface to export a +a board in different file formats using different exporter plugins. The +interface consists of a CLI layer (each export plugin's "cam" option) and +an optional GUI (the CAM plugin). + +

CAM export support in other plugins

+

+Each CAM-plugin-compatible exporter plugin offers an option called "cam". +The syntax and capabilities are the same for all exporter's cam option. +

+The syntax is: +

+outfile=layergrp[,layergrp,...]
+
+

+where: +

    +
  • outfile is the output file name template that substitutes %%: +
      +
    • %name% is substituted with the layer group name +
    • %base% is substituted with the base name of the output file path (the file name without directories) +
    • %top_offs% is substituted with the layer group offset from the top (top layer group being 0); only layer groups with the same material considered +
    • %bot_offs% is substituted with the layer group offset from the bottom (bottom layer group being 0); only layer groups with the same material considered +
    +
  • layergrp: one or more layer group definitions separated by comma (see below) +
  • optionally a list of exporter options in the same format as on direct command line (e.g. --verbose); when there's overlap on any state/definition between opts and CAM operation, the effect of the opt is ignored +
+Syntax of the layer group definition: +
    +
  • @layername (e.g. "@top_copper" if the group's name is top_copper) +
  • location-material (e.g. "top-copper" for any layer group that is copper and is on the top side) +
  • type[-type...] (more generally: a list of layer type flags) +
  • type:offs (e.g. "copper:+2" means the second copper layer group from the top, "copper:-3" means the third copper layer group from the bottom; offs is counted from 1, +1 meaning top outer layer, -1 meaning bottom outer layer) +
  • plus an optional list of supplements in paranthesis +
+

+When supplements are specified, it's a comma separated list of key=value pairs. +Available supplements are: +

    +
  • purpose: specify matching layer group purpose field +
  • bloat: bloat or shrink objects by the specified value (e.g. 1mm) +
  • (TODO: supplement for inversion) +
+

+Examples: + +
directive + explanation +
bot.gbr=@bottom_copper,@bottom_silk + export layer groups called bottom_copper and bottom_silk (by group name) +
asm=top-assy + export the top assembly group, by type +
fabrication.ps=fab + export any fab layer group, by type +
gnd=copper:2 + export the second copper layer group from the top (the first internal copper layer group under the top copper layer group, if it is a multilayer board; for 2 layer boards this will be the bottom copper layer group) +
gnd=intern-copper:1 + similar to the above, but addresses the first internal copper layer group explicitly so it can not end up being the bottom copper layer group +
pwr=copper:-2 + export the second copper layer group from the bottom (the first internal copper layer group above the bottom copper layer group, if it is a multilayer board; for 2 layer boards this will be the top copper layer group) +
gnd=intern-copper:-1 + similar to the above, but addresses the last internal copper layer group explicitly so it can not end up being the top copper layer group +
pst.gbr=top-paste(bloat=0.1mm),bottom-paste(bloat=0.1mm) + export the top and bottom paste groups in the same file with all objects bloated up by 0.1mm +
plated_drills.cnc=virtual(purpose=pdrill) + export plated drilled holes (padstack side effects, but no slots) +
unplated_drills.cnc=virtual(purpose=udrill) + export unplated drilled holes (padstack side effects, but no slots) +
+

+If multiple layer groups match a layergrp specification, all matching +layer groups are exported. If the file name is a static string, they are +all merged. If the file name is templated, it is possible to export the +layer groups in multiple files. For example: + +
directive + explanation +
copper.gbr=copper + export all copper layers to copper.gbr +
copper-%top_offs%.gbr=copper + export all copper layers to numbered copper-N.gbr files where N is the offset from the top side, starting from 0 (for top copper) +
copper-%name%.gbr=copper + export all copper layers to numbered copper-N.gbr files where N is the full name of the group being exported +
+ +

CAM plugin

+

+The CAM plugin is a way to manage output "jobs": collections of cam export +settings for reproducing export packages in various formats. +

+... +

+A job is a script that contains zero or more export directives, separated +by semicolons or newlines. An export directive is one of these: +

+desc text
+plugin name [--option value] [--option value] ...
+write outfile=layergrp[,layergrp,...]
+
+

+desc is a free form one-liner that describes what the job is for. Multiple +desc directives may be present (to bypass the limitation that the text can +not contain newlines). +

+The plugin directive selects a plugin and sets plugin specific options. +The plugin and options are active until the next plugin directive or the +end of the script. The first outfile directive must be preceeded by a +plugin directive. +

+The write directive argument has the same syntax as the cam argument for each +cam-capable exporter, see above. Each write is a call +to an exporter the same way as if pcb-rnd was called with --cam and -x +with the exporter and options taken from the last plugin directive. +

+For example, the following config tree defines a job called doc_png +that generates two 600 DPI images from the sides of the board, copper and +silk combined, all in the doc/ dir (that is created if necessary): +

+li:pcb-rnd-conf-v1 {
+	ha:overwrite {
+		ha:plugins {
+			ha:cam {
+				li:jobs {
+					doc_png {
+						desc export top and bottom copper and silk in 600 DPI pngs
+						plugin png --dpi 600
+						write top.png=top-copper,top-silk
+						write bottom.png=bottom-copper,bottom-silk
+					}
+				}
+			}
+		}
+	}
+}
+
+

+Once the above subtree is loaded in the config, the following action triggers +the export: +

+cam(call, doc_png)
+
+ + +

Tips for using with various exporters

+

+When exporting to ps, consider using the --no-show-toc. It is +possible to combine multiple layers (e.g. top silk and top copper, which +may be useful for a single-layer board) using the --single-page option. +

+The plugin field has the same values command line -x has. +The list of currently available exporter names can be acquired by running +

+pcb-rnd -x
+
+Note: this list contains all exporter plugins currently available +(depends on your configure time options and plugin availability). Some export +plugins can not do per layer exporting and those will not support CAM exporting +either. + + Index: tags/2.1.2/doc/user/06_feature/ddraft/coord_seq.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/user/06_feature/ddraft/coord_seq.png =================================================================== --- tags/2.1.2/doc/user/06_feature/ddraft/coord_seq.png (nonexistent) +++ tags/2.1.2/doc/user/06_feature/ddraft/coord_seq.png (revision 24813) Property changes on: tags/2.1.2/doc/user/06_feature/ddraft/coord_seq.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/user/06_feature/ddraft/coord_sys.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/user/06_feature/ddraft/coord_sys.png =================================================================== --- tags/2.1.2/doc/user/06_feature/ddraft/coord_sys.png (nonexistent) +++ tags/2.1.2/doc/user/06_feature/ddraft/coord_sys.png (revision 24813) Property changes on: tags/2.1.2/doc/user/06_feature/ddraft/coord_sys.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/user/06_feature/ddraft/index.html =================================================================== --- tags/2.1.2/doc/user/06_feature/ddraft/index.html (nonexistent) +++ tags/2.1.2/doc/user/06_feature/ddraft/index.html (revision 24813) @@ -0,0 +1,194 @@ + + + + pcb-rnd user manual + + + + +

ddraft - 2 dimensional drafting aid

+

+The purpose of ddraft is to provide actions and GUI tools to help users +drawing precise 2d drafts. Many of the features in ddraft are very similar +to those found in standard 2d CAD packages. +

+Ddraft uses the following coordinate system (when looked from the top +of the board): +

+ddraft coordinate system: upper left corner is 0;0, x+ is tot he right, y+ is down, 0 deg is at 3 o'clock and increases clockwise + +

constraints

+

+Coordinate and/or angle constraints can be applied on line drawing (when +all-direction lines turned on) and move operation. Executing the +constraint() action without arguments opens a dialog box with the +settings. The same settings are accessible from the command line, using +the constraint() action with arguments: +

+ +
Constraint arguments: explicitly set +
action syntax description +
constraint(line_angle, ang1, ang2, ...) permit drawing lines only at specific angles +
constraint(line_angle_mod, ang) permit drawing lines only at angles which are integer multiplies of ang +
constraint(line_length, len1, len2, ...) draw lines with length matching any length on the list +
constraint(line_length_mod, len) draw lines with length matching any integer multiply of the len +
constraint(move_angle, ang1, ang2, ...) permit moving objects only at specific angles +
constraint(move_angle_mod, ang) permit moving objects only at angles which are integer multiplies of ang +
constraint(move_length, len1, len2, ...) move objects at a distance matching any length on the list +
constraint(move_length_mod, len) move objects at a distance matching an integer multiply of the len +
constraint(reset) reset all constraints +
+

+Length can include unit (on the GUI: without space). Multiple constraints +can be set in the same time. Constraints are reset upon explicit user +request or pcb-rnd restart. +

+For line drawing, it is possible to get the angle constraints calculated using +the line start point and an existing object: +

+ +
Constraint arguments: calculated +
action syntax description +
perp() click on a line; set line_angle perpendicular to that line +
paral() click on a line; set line_angle parallel to that line +
tang() click on an arc; set line_angle tangential to the circle of the arc +
+ +

Cutting edges

+

+For already existing, intersecting objects (lines and arcs), the user may +define cutting edges that can manipulate target objects they intersect. There +are two actions for cutting edges: trim() and split(). The first argument of +these actions is: +

    +
  • object (selecting a single cutting edge) +
  • selected (to use any selected object as cutting edge) +
  • found (to use any found (green highlight) object as cutting edge) +
+

+The objects participating may be on different layers. All calculation use +the centerline of the objects. +

+In a trim operation the target objects are cut at the intersection point, +excess parts (at the click) removed. If there are multiple cutting edges, +the shortest possible section is removed. The below examples are generated +with trim(selected), clicking on the horizontal line at the small +triangle mark. +

+[Effect of trim on a few examples] +

+In a split operation target objects are split into multiple section wherever +they cross a cutting edge. A split means a single line object becomes multiple +line objects or a single arc object becomes multiple arc objects. + +

Command line drafting

+

+The above features are pcb-rnd actions designed to fit in the action framework, +to work together with the original pcb-rnd drawing tools, like the line tool. +An alternative to that is using the new, ddraft command line interpreter, which +offers a different syntax, optimized for drafting. +

+There are two ways to use the ddraft command line interpreter: +

    +
  • a command wrapped in the ddraft() action, e.g. ddraft(line from 1,3 to 4,2) +
  • switching the command entry to ddraft CLI mode, by issuing the ddraft() action; + to exit from the ddraft CLI mode, type /exit +
+

+When used as a CLI mode, mouse clicks on the drawing will also edit the +command line at the cursor. The generic rule is that a click will replace +an already entered numerical value or inserts a missing numerical value, but +all instruction keywords are typed on the keyboard. Instructions can +be abbreviated; the shortest form accepted is the shortest prefix that +is unique among the instruction keywords. For example "li" means "line" +and "rel" or even "re" works for "relative". +

+The first instruction is the drawing command, which is one of the following. +

+ +
ddraft drawing commands +
command syntax summary purpose +
line + line [from] coord to coord + draw line segments on the current layer, using the current routing style +
+

+Parts enclosed in [] are optional. A coord description is a sequence +of absolute and relative coordinates: +

+ +
ddraft drawing commands +
keyword next instruction (argument) example purpose +
absolute + xcoord,ycoord + abs 1mm,15mm + an absolute coordinate; units are optional; must not contain space +
* + *1mm,15mm +
  + 1mm,15mm + +
relative + xcoord,ycoord + rel 1mm,15mm + a relative coordinate measured from the absolute coord specified so far; units are optional; must not contain space +
@ + @1mm,15mm + +
angle + degree + ang 15 + an absolute angle in degrees; always measured from the X axis; should be used together with length +
< + <15 + +
relative angle + degree + rel ang 15 + a relative angle in degrees; always measured from the X axis; should be used together with length +
@< + @<15 + + + +
length + coord + len 3.1mm + length or distance to move from the previous coordinate; always relative; used together with an angle +
~ + ~3.1mm + +
+

+For example the sequence +5mm,100mil relative 1mm,1mm relative angle 30 length 2mm +means: +

    +
  • step 1: start from absolute coords at 5mm, 100mil; after this the current coordinate is: 5.0000mm,2.5400mm +
  • step 2: move relative (to the right and down) 1 and 1 mm; after this the current coordinate is: 6.0000mm,3.5400mm +
  • step 3: the last move was a 45 degree move; relative to this 45 degrees, start moving at 30 degrees (that is, in absolute 75 degrees), and... +
  • step 4: ... move 2mm in that direction +
  • step 5: the sequence ends here, the coordinate it points to is: 6.5176mm,5.4719mm +
+

+Below the same steps are demonstrated; dark red lines demonstrate the moves, +thin black lines show how they are calculated. The result is a single coordinate +marked with a thin black cross at step 5. The sequence itself does not draw +anything, the drawing merely demonstrates how the steps are executed in +memory. +

+the coord sequence annotated with auxiliary lines and step numbers +

+Equivalent alternative forms for the same sequence: +

+5mm,100mil rel 1mm,1mm rel ang 30 len 2mm
+5mm,100mil @1mm,1mm @<30~2mm
+5,100mil @1,1 @<30~2
+
+

+The last one assumes unit is set to mm. + + + + + Index: tags/2.1.2/doc/user/06_feature/ddraft/src/Makefile =================================================================== --- tags/2.1.2/doc/user/06_feature/ddraft/src/Makefile (nonexistent) +++ tags/2.1.2/doc/user/06_feature/ddraft/src/Makefile (revision 24813) @@ -0,0 +1,19 @@ +PCBRND=pcb-rnd +CLEANFILES= ../*.png + +all: ../coord_sys.png ../coord_seq.png ../trim.png + +../coord_sys.png: coord_sys.lht + $(PCBRND) -x png --dpi 450 coord_sys.lht + mv coord_sys.png ../coord_sys.png + +../coord_seq.png: coord_seq.lht + $(PCBRND) -x png --dpi 450 coord_seq.lht + mv coord_seq.png ../coord_seq.png + +../trim.png: trim.lht + $(PCBRND) -x png --dpi 450 trim.lht + mv trim.png ../trim.png + +clean: $(CLEANRULES) + -rm $(CLEANFILES) Index: tags/2.1.2/doc/user/06_feature/ddraft/src/coord_seq.lht =================================================================== --- tags/2.1.2/doc/user/06_feature/ddraft/src/coord_seq.lht (nonexistent) +++ tags/2.1.2/doc/user/06_feature/ddraft/src/coord_seq.lht (revision 24813) @@ -0,0 +1,472 @@ +ha:pcb-rnd-board-v5 { + ha:netlists { + li:input { + } + } + ha:meta { + ha:size { + thermal_scale = 0.500000 + x = 390.0mil + y = 310.0mil + } + ha:grid { + spacing = 5.0mil + offs_x = 0.0 + offs_y = 0.0 + } + } + ha:layer_stack { + li:groups { + ha:0 { + ha:type { + top = 1 + paste = 1 + } + li:layers { + 8 + } + name = top_paste + } + ha:1 { + ha:type { + silk = 1 + top = 1 + } + li:layers { + 7 + } + name = top_silk + } + ha:2 { + ha:type { + top = 1 + mask = 1 + } + li:layers { + 9 + } + name = top_mask + } + ha:3 { + ha:type { + copper = 1 + top = 1 + } + li:layers { + 0 + 2 + } + name = top_copper + } + ha:4 { + ha:type { + substrate = 1 + intern = 1 + } + li:layers { + } + name = grp_4 + } + ha:5 { + ha:type { + copper = 1 + intern = 1 + } + li:layers { + 5 + } + name = Intern + } + ha:6 { + ha:type { + substrate = 1 + intern = 1 + } + li:layers { + } + name = grp_6 + } + ha:7 { + ha:type { + copper = 1 + intern = 1 + } + li:layers { + 4 + } + name = Intern + } + ha:8 { + ha:type { + substrate = 1 + intern = 1 + } + li:layers { + } + name = grp_8 + } + ha:9 { + ha:type { + outline = 1 + } + li:layers { + } + name = global_outline + } + ha:10 { + ha:type { + bottom = 1 + copper = 1 + } + li:layers { + 1 + 3 + } + name = bottom_copper + } + ha:11 { + ha:type { + bottom = 1 + mask = 1 + } + li:layers { + 10 + } + name = bottom_mask + } + ha:12 { + ha:type { + silk = 1 + bottom = 1 + } + li:layers { + 6 + } + name = bottom_silk + } + ha:13 { + ha:type { + bottom = 1 + paste = 1 + } + li:layers { + 11 + } + name = bottom_paste + } + } + } + + li:styles { + ha:Signal { + diameter = 2.0mm + thickness = 0.1mil + hole = 31.5mil + clearance = 20.0mil + } + ha:Power { + diameter = 2.2mm + thickness = 20.0mil + hole = 1.0mm + clearance = 20.0mil + } + ha:Fat { + diameter = 137.8mil + thickness = 80.0mil + hole = 47.24mil + clearance = 25.0mil + } + ha:Sig-tight { + diameter = 64.0mil + thickness = 10.0mil + hole = 31.5mil + clearance = 12.0mil + } + } + + ha:data { + li:padstack_prototypes { + } + li:objects { + } + li:layers { + ha:top-sig { + visible = 1 + lid = 0 + li:objects { + ha:line.4 { + clearance = 40.0mil + y2 = 130.0mil + thickness = 10.0mil + x1 = 30.0mil + x2 = 226.8503937mil + ha:flags { + clearline = 1 + } + y1 = 30.0mil + } + ha:line.7 { + clearance = 40.0mil + y2 = 4.302mm + thickness = 10.0mil + x1 = 226.8503937mil + x2 = 6.762mm + ha:flags { + clearline = 1 + } + y1 = 130.0mil + } + ha:line.10 { + clearance = 40.0mil + y2 = 6.2339mm + thickness = 10.0mil + x1 = 6.762mm + x2 = 7.2796mm + ha:flags { + clearline = 1 + } + y1 = 4.302mm + } + } + color = {#8b2323} + group = 3 + ha:combining { + } + } + ha:bottom-sig { + visible = 1 + lid = 1 + li:objects { + } + color = {#3a5fcd} + group = 10 + ha:combining { + } + } + ha:top-gnd { + visible = 1 + lid = 2 + li:objects { + } + color = {#104e8b} + group = 3 + ha:combining { + } + } + ha:bottom-gnd { + visible = 1 + lid = 3 + li:objects { + } + color = {#cd3700} + group = 10 + ha:combining { + } + } + ha:int-sig2 { + visible = 1 + lid = 4 + li:objects { + } + color = {#548b54} + group = 7 + ha:combining { + } + } + ha:int-sig1 { + visible = 1 + lid = 5 + li:objects { + } + color = {#8b7355} + group = 5 + ha:combining { + } + } + ha:bottom-silk { + visible = 1 + lid = 6 + li:objects { + } + color = {#000000} + group = 12 + ha:combining { + auto = 1 + } + } + ha:top-silk { + visible = 1 + lid = 7 + li:objects { + ha:line.13 { + clearance = 40.0mil + y2 = 30.0mil + thickness = 0.1mil + x1 = 226.8503937mil + x2 = 226.8503937mil + ha:flags { + clearline = 1 + } + y1 = 130.0mil + } + ha:line.17 { + clearance = 40.0mil + y2 = 130.0mil + thickness = 0.1mil + x1 = 226.8503937mil + x2 = 6.762mm + ha:flags { + clearline = 1 + } + y1 = 130.0mil + } + ha:line.20 { + clearance = 40.0mil + y2 = 130.0mil + thickness = 0.1mil + x1 = 6.762mm + x2 = 6.762mm + ha:flags { + clearline = 1 + } + y1 = 4.302mm + } + ha:line.23 { + clearance = 40.0mil + y2 = 260.0mil + thickness = 0.1mil + x1 = 6.762mm + x2 = 9.064mm + ha:flags { + clearline = 1 + } + y1 = 4.302mm + } + ha:line.56 { + x1=7.2796mm; y1=6.2339mm; x2=4.834137mm; y2=6.889159mm; thickness=0.1mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.65 { + x1=6.762mm; y1=4.302mm; x2=4.316537mm; y2=4.957259mm; thickness=0.1mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.68 { + x1=180.0mil; y1=4.888807mm; x2=5.093772mm; y2=6.836086mm; thickness=0.1mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.104 { + x1=7.2796mm; y1=234.09972441mil; x2=7.2796mm; y2=255.0mil; thickness=0.1mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.113 { + x1=300.0mil; y1=6.2339mm; x2=275.0mil; y2=6.2339mm; thickness=0.1mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.38 { + x=260.0mil; y=190.0mil; width=50.0mil; height=50.0mil; astart=118; adelta=39; thickness=0.1mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:text.83 { + string=1; x=210.0mil; y=50.0mil; scale=50; fid=0; direction=0; + ha:flags { + clearline=1 + } + } + ha:text.85 { + string=2; x=270.0mil; y=100.0mil; scale=50; fid=0; direction=0; + ha:flags { + clearline=1 + } + } + ha:text.87 { + string=3; x=310.0mil; y=180.0mil; scale=50; fid=0; direction=0; + ha:flags { + clearline=1 + } + } + ha:text.89 { + string=4; x=170.0mil; y=220.0mil; scale=50; fid=0; direction=0; + ha:flags { + clearline=1 + } + } + ha:text.91 { + string=5; x=300.0mil; y=250.0mil; scale=50; fid=0; direction=0; + ha:flags { + clearline=1 + } + } + ha:text.117 { + string=0; x=10.0mil; y=0.0; scale=50; fid=0; direction=0; + ha:flags { + clearline=1 + } + } + } + color = {#000000} + group = 1 + ha:combining { + auto = 1 + } + } + ha:top-paste { + visible = 0 + lid = 8 + li:objects { + } + color = {#cd00cd} + group = 0 + ha:combining { + auto = 1 + } + } + ha:top-mask { + visible = 0 + lid = 9 + li:objects { + } + color = {#ff0000} + group = 2 + ha:combining { + sub = 1 + auto = 1 + } + } + ha:bottom-mask { + visible = 0 + lid = 10 + li:objects { + } + color = {#ff0000} + group = 11 + ha:combining { + sub = 1 + auto = 1 + } + } + ha:bottom-paste { + visible = 0 + lid = 11 + li:objects { + } + color = {#cd00cd} + group = 13 + ha:combining { + auto = 1 + } + } + } + } +} Index: tags/2.1.2/doc/user/06_feature/ddraft/src/coord_sys.lht =================================================================== --- tags/2.1.2/doc/user/06_feature/ddraft/src/coord_sys.lht (nonexistent) +++ tags/2.1.2/doc/user/06_feature/ddraft/src/coord_sys.lht (revision 24813) @@ -0,0 +1,362 @@ +ha:pcb-rnd-board-v5 { + + ha:attributes { + {PCB::grid::unit}=mil + } + + li:styles { + ha:Signal { + diameter = 2.0mm + thickness = 10.0mil + hole = 31.5mil + clearance = 20.0mil + } + ha:Power { + diameter = 2.2mm + thickness = 20.0mil + hole = 1.0mm + clearance = 20.0mil + } + ha:Fat { + diameter = 137.8mil + thickness = 80.0mil + hole = 47.24mil + clearance = 25.0mil + } + ha:Sig-tight { + diameter = 64.0mil + thickness = 10.0mil + hole = 31.5mil + clearance = 12.0mil + } + } + + ha:meta { + ha:size { + thermal_scale = 0.500000 + x = 950.0mil + y = 925.0mil + } + ha:grid { + spacing = 25.0mil + offs_x = 0.0 + offs_y = 0.0 + } + } + + ha:data { + li:padstack_prototypes { + } + + li:objects { + } + li:layers { + + ha:top-sig { + lid=0 + group=3 + ha:combining { } + visible=1 + + li:objects { + } + color = {#8b2323} + } + + ha:bottom-sig { + lid=1 + group=10 + ha:combining { } + visible=1 + + li:objects { + } + color = {#3a5fcd} + } + + ha:top-gnd { + lid=2 + group=3 + ha:combining { } + visible=1 + + li:objects { + } + color = {#104e8b} + } + + ha:bottom-gnd { + lid=3 + group=10 + ha:combining { } + visible=1 + + li:objects { + } + color = {#cd3700} + } + + ha:int-sig2 { + lid=4 + group=7 + ha:combining { } + visible=1 + + li:objects { + } + color = {#548b54} + } + + ha:int-sig1 { + lid=5 + group=5 + ha:combining { } + visible=1 + + li:objects { + } + color = {#8b7355} + } + + ha:outline { + lid=6 + group=9 + ha:combining { } + visible=1 + + li:objects { + } + color = {#00868b} + } + + ha:bottom-silk { + lid=7 + group=12 + ha:combining { auto=1; } + visible=1 + + li:objects { + } + color = {#000000} + } + + ha:top-silk { + lid=8 + group=1 + ha:combining { auto=1; } + visible=1 + + li:objects { + ha:line.5 { + x1=75.0mil; y1=175.0mil; x2=850.0mil; y2=175.0mil; thickness=10.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.19 { + x1=200.0mil; y1=50.0mil; x2=200.0mil; y2=825.0mil; thickness=10.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.32 { + x=325.0mil; y=175.0mil; width=400.0mil; height=400.0mil; astart=142; adelta=38; thickness=10.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:polygon.11 { clearance=40.0mil; + li:geometry { + ta:contour { + { 900.0mil; 175.0mil } + { 775.0mil; 150.0mil } + { 775.0mil; 200.0mil } + } + } + + ha:flags { + clearpoly=1 + } + } + ha:polygon.22 { clearance=40.0mil; + li:geometry { + ta:contour { + { 200.0mil; 875.0mil } + { 225.0mil; 750.0mil } + { 175.0mil; 750.0mil } + } + } + + ha:flags { + clearpoly=1 + } + } + ha:polygon.45 { clearance=40.0mil; + li:geometry { + ta:contour { + { 14.851175mm; 12.720308mm } + { 17.192442mm; 10.483721mm } + { 16.15212mm; 9.755279mm } + } + } + + ha:flags { + clearpoly=1 + } + } + ha:text.26 { + string=0; x=150.0mil; y=100.0mil; scale=100; fid=0; direction=0; + ha:flags { + clearline=1 + } + } + ha:text.27 { + string=+x; x=825.0mil; y=100.0mil; scale=100; fid=0; direction=0; + ha:flags { + clearline=1 + } + } + ha:text.28 { + string=+y; x=125.0mil; y=775.0mil; scale=100; fid=0; direction=0; + ha:flags { + clearline=1 + } + } + ha:text.49 { + string=+angle; x=700.0mil; y=425.0mil; scale=100; fid=0; direction=0; + ha:flags { + clearline=1 + } + } + ha:text.51 { + string=0 deg; x=625.0mil; y=100.0mil; scale=100; fid=0; direction=0; + ha:flags { + clearline=1 + } + } + } + color = {#000000} + } + + ha:top-paste { + lid=9 + group=0 + ha:combining { auto=1; } + visible=0 + + li:objects { + } + color = {#cd00cd} + } + + ha:top-mask { + lid=10 + group=2 + ha:combining { sub=1; auto=1; } + visible=0 + + li:objects { + } + color = {#ff0000} + } + + ha:bottom-mask { + lid=11 + group=11 + ha:combining { sub=1; auto=1; } + visible=0 + + li:objects { + } + color = {#ff0000} + } + + ha:bottom-paste { + lid=12 + group=13 + ha:combining { auto=1; } + visible=0 + + li:objects { + } + color = {#cd00cd} + } + } + } + + + ha:layer_stack { + li:groups { + ha:0 { + name = top_paste + ha:type { top=1; paste=1; } + li:layers { 9; } + } + ha:1 { + name = top_silk + ha:type { silk=1; top=1; } + li:layers { 8; } + } + ha:2 { + name = top_mask + ha:type { top=1; mask=1; } + li:layers { 10; } + } + ha:3 { + name = top_copper + ha:type { copper=1; top=1; } + li:layers { 0; 2; } + } + ha:4 { + name = grp_4 + ha:type { substrate=1; intern=1; } + li:layers { } + } + ha:5 { + name = Intern + ha:type { copper=1; intern=1; } + li:layers { 5; } + } + ha:6 { + name = grp_6 + ha:type { substrate=1; intern=1; } + li:layers { } + } + ha:7 { + name = Intern + ha:type { copper=1; intern=1; } + li:layers { 4; } + } + ha:8 { + name = grp_8 + ha:type { substrate=1; intern=1; } + li:layers { } + } + ha:9 { + name = global_outline + ha:type { outline=1; } + li:layers { 6; } + } + ha:10 { + name = bottom_copper + ha:type { bottom=1; copper=1; } + li:layers { 1; 3; } + } + ha:11 { + name = bottom_mask + ha:type { bottom=1; mask=1; } + li:layers { 11; } + } + ha:12 { + name = bottom_silk + ha:type { silk=1; bottom=1; } + li:layers { 7; } + } + ha:13 { + name = bottom_paste + ha:type { bottom=1; paste=1; } + li:layers { 12; } + } + } + } +} Index: tags/2.1.2/doc/user/06_feature/ddraft/src/trim.lht =================================================================== --- tags/2.1.2/doc/user/06_feature/ddraft/src/trim.lht (nonexistent) +++ tags/2.1.2/doc/user/06_feature/ddraft/src/trim.lht (revision 24813) @@ -0,0 +1,474 @@ +ha:pcb-rnd-board-v5 { + + ha:attributes { + {PCB::grid::unit}=mil + } + + li:styles { + ha:Signal { + diameter = 2.0mm + thickness = 10.0mil + hole = 31.5mil + clearance = 20.0mil + } + ha:Power { + diameter = 2.2mm + thickness = 20.0mil + hole = 1.0mm + clearance = 20.0mil + } + ha:Fat { + diameter = 137.8mil + thickness = 80.0mil + hole = 47.24mil + clearance = 25.0mil + } + ha:Sig-tight { + diameter = 64.0mil + thickness = 10.0mil + hole = 31.5mil + clearance = 12.0mil + } + } + + ha:meta { + ha:size { + thermal_scale = 0.500000 + x = 800.0mil + y = 27.305mm + } + ha:grid { + spacing = 25.0mil + offs_x = 0.0 + offs_y = 0.0 + } + } + + ha:data { + li:padstack_prototypes { + } + + li:objects { + } + li:layers { + + ha:top-sig { + lid=0 + group=3 + ha:combining { } + visible=1 + + li:objects { + ha:line.14 { + x1=75.0mil; y1=325.0mil; x2=275.0mil; y2=325.0mil; thickness=10.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.17 { + x1=150.0mil; y1=225.0mil; x2=150.0mil; y2=425.0mil; thickness=10.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + selected=1 + } + } + ha:line.63 { + x1=75.0mil; y1=600.0mil; x2=275.0mil; y2=600.0mil; thickness=10.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.66 { + x1=150.0mil; y1=500.0mil; x2=150.0mil; y2=700.0mil; thickness=10.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + selected=1 + } + } + ha:line.69 { + x1=75.0mil; y1=900.0mil; x2=275.0mil; y2=900.0mil; thickness=10.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.72 { + x1=150.0mil; y1=800.0mil; x2=150.0mil; y2=1000.0mil; thickness=10.0mil; clearance=40.0mil; + ha:flags { + selected=1 + } + } + ha:line.203 { + x1=475.0mil; y1=325.0mil; x2=550.0mil; y2=325.0mil; thickness=10.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.206 { + x1=550.0mil; y1=225.0mil; x2=550.0mil; y2=425.0mil; thickness=10.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + selected=1 + } + } + ha:line.209 { + x1=475.0mil; y1=600.0mil; x2=15.575194mm; y2=600.0mil; thickness=10.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.212 { + x1=550.0mil; y1=500.0mil; x2=550.0mil; y2=700.0mil; thickness=10.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + selected=1 + } + } + ha:line.215 { + x1=15.575194mm; y1=900.0mil; x2=675.0mil; y2=900.0mil; thickness=10.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.218 { + x1=550.0mil; y1=800.0mil; x2=550.0mil; y2=1000.0mil; thickness=10.0mil; clearance=40.0mil; + ha:flags { + selected=1 + } + } + ha:line.221 { + x1=475.0mil; y1=900.0mil; x2=550.0mil; y2=900.0mil; thickness=10.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:arc.75 { + x=325.0mil; y=700.0mil; width=150.0mil; height=150.0mil; astart=-90; adelta=90; thickness=10.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + selected=1 + } + } + ha:arc.76 { + x=325.0mil; y=1000.0mil; width=150.0mil; height=150.0mil; astart=-90; adelta=90; thickness=10.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + selected=1 + } + } + ha:arc.224 { + x=725.0mil; y=700.0mil; width=150.0mil; height=150.0mil; astart=-90; adelta=90; thickness=10.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + selected=1 + } + } + ha:arc.225 { + x=725.0mil; y=1000.0mil; width=150.0mil; height=150.0mil; astart=-90; adelta=90; thickness=10.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + selected=1 + } + } + ha:polygon.89 { clearance=40.0mil; + li:geometry { + ta:contour { + { 260.0mil; 400.0mil } + { 250.0mil; 350.0mil } + { 240.0mil; 400.0mil } + } + } + + ha:flags { + clearpoly=1 + } + } + ha:polygon.93 { clearance=40.0mil; + li:geometry { + ta:contour { + { 260.0mil; 675.0mil } + { 250.0mil; 625.0mil } + { 240.0mil; 675.0mil } + } + } + + ha:flags { + clearpoly=1 + } + } + ha:polygon.97 { clearance=40.0mil; + li:geometry { + ta:contour { + { 165.0mil; 825.0mil } + { 175.0mil; 875.0mil } + { 185.0mil; 825.0mil } + } + } + + ha:flags { + clearpoly=1 + } + } + } + color = {#8b2323} + } + + ha:bottom-sig { + lid=1 + group=10 + ha:combining { } + visible=1 + + li:objects { + } + color = {#3a5fcd} + } + + ha:top-gnd { + lid=2 + group=3 + ha:combining { } + visible=1 + + li:objects { + } + color = {#104e8b} + } + + ha:bottom-gnd { + lid=3 + group=10 + ha:combining { } + visible=1 + + li:objects { + } + color = {#cd3700} + } + + ha:int-sig2 { + lid=4 + group=7 + ha:combining { } + visible=1 + + li:objects { + } + color = {#548b54} + } + + ha:int-sig1 { + lid=5 + group=5 + ha:combining { } + visible=1 + + li:objects { + } + color = {#8b7355} + } + + ha:bottom-silk { + lid=6 + group=12 + ha:combining { auto=1; } + visible=1 + + li:objects { + } + color = {#000000} + } + + ha:top-silk { + lid=7 + group=1 + ha:combining { auto=1; } + visible=1 + + li:objects { + ha:line.238 { + x1=400.0mil; y1=25.0mil; x2=400.0mil; y2=26.67mm; thickness=10.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.253 { + x1=25.0mil; y1=150.0mil; x2=775.0mil; y2=150.0mil; thickness=10.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.259 { + x1=25.0mil; y1=475.0mil; x2=775.0mil; y2=475.0mil; thickness=10.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.262 { + x1=25.0mil; y1=750.0mil; x2=775.0mil; y2=750.0mil; thickness=10.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.265 { + x1=25.0mil; y1=26.67mm; x2=775.0mil; y2=26.67mm; thickness=10.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.268 { + x1=25.0mil; y1=25.0mil; x2=775.0mil; y2=25.0mil; thickness=10.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.271 { + x1=25.0mil; y1=25.0mil; x2=25.0mil; y2=26.67mm; thickness=10.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:line.274 { + x1=775.0mil; y1=25.0mil; x2=775.0mil; y2=26.67mm; thickness=10.0mil; clearance=40.0mil; + ha:flags { + clearline=1 + } + } + ha:text.20 { + string=Before; x=100.0mil; y=50.0mil; scale=100; fid=0; direction=0; + ha:flags { + clearline=1 + } + } + ha:text.21 { + string=After; x=525.0mil; y=50.0mil; scale=100; fid=0; direction=0; + ha:flags { + clearline=1 + } + } + } + color = {#000000} + } + + ha:top-paste { + lid=8 + group=0 + ha:combining { auto=1; } + visible=0 + + li:objects { + } + color = {#cd00cd} + } + + ha:top-mask { + lid=9 + group=2 + ha:combining { sub=1; auto=1; } + visible=0 + + li:objects { + } + color = {#ff0000} + } + + ha:bottom-mask { + lid=10 + group=11 + ha:combining { sub=1; auto=1; } + visible=0 + + li:objects { + } + color = {#ff0000} + } + + ha:bottom-paste { + lid=11 + group=13 + ha:combining { auto=1; } + visible=0 + + li:objects { + } + color = {#cd00cd} + } + } + } + + + + ha:layer_stack { + li:groups { + ha:0 { + name = top_paste + ha:type { top=1; paste=1; } + li:layers { 8; } + } + ha:1 { + name = top_silk + ha:type { silk=1; top=1; } + li:layers { 7; } + } + ha:2 { + name = top_mask + ha:type { top=1; mask=1; } + li:layers { 9; } + } + ha:3 { + name = top_copper + ha:type { copper=1; top=1; } + li:layers { 0; 2; } + } + ha:4 { + name = grp_4 + ha:type { substrate=1; intern=1; } + li:layers { } + } + ha:5 { + name = Intern + ha:type { copper=1; intern=1; } + li:layers { 5; } + } + ha:6 { + name = grp_6 + ha:type { substrate=1; intern=1; } + li:layers { } + } + ha:7 { + name = Intern + ha:type { copper=1; intern=1; } + li:layers { 4; } + } + ha:8 { + name = grp_8 + ha:type { substrate=1; intern=1; } + li:layers { } + } + ha:9 { + name = global_outline + ha:type { outline=1; } + li:layers { } + } + ha:10 { + name = bottom_copper + ha:type { bottom=1; copper=1; } + li:layers { 1; 3; } + } + ha:11 { + name = bottom_mask + ha:type { bottom=1; mask=1; } + li:layers { 10; } + } + ha:12 { + name = bottom_silk + ha:type { silk=1; bottom=1; } + li:layers { 6; } + } + ha:13 { + name = bottom_paste + ha:type { bottom=1; paste=1; } + li:layers { 11; } + } + } + } +} Index: tags/2.1.2/doc/user/06_feature/ddraft/trim.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/user/06_feature/ddraft/trim.png =================================================================== --- tags/2.1.2/doc/user/06_feature/ddraft/trim.png (nonexistent) +++ tags/2.1.2/doc/user/06_feature/ddraft/trim.png (revision 24813) Property changes on: tags/2.1.2/doc/user/06_feature/ddraft/trim.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/user/06_feature/diag/index.html =================================================================== --- tags/2.1.2/doc/user/06_feature/diag/index.html (nonexistent) +++ tags/2.1.2/doc/user/06_feature/diag/index.html (revision 24813) @@ -0,0 +1,18 @@ + + + + pcb-rnd user manual + + + + +

Diag plugin

+

+Diag is a config POV setting, you can enable or disable it any time, +from gui, from cli, from config files, from actions. It's called +plugins/diag/auto_integrity - by default it's 0 (off); it runs when it's set to +1. +

+The diagnostic plugin provides a dumpconf action to pcb-rnd. + + Index: tags/2.1.2/doc/user/06_feature/distalign/align_mixed_parts_x.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/user/06_feature/distalign/align_mixed_parts_x.png =================================================================== --- tags/2.1.2/doc/user/06_feature/distalign/align_mixed_parts_x.png (nonexistent) +++ tags/2.1.2/doc/user/06_feature/distalign/align_mixed_parts_x.png (revision 24813) Property changes on: tags/2.1.2/doc/user/06_feature/distalign/align_mixed_parts_x.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/user/06_feature/distalign/align_parts_y.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/user/06_feature/distalign/align_parts_y.png =================================================================== --- tags/2.1.2/doc/user/06_feature/distalign/align_parts_y.png (nonexistent) +++ tags/2.1.2/doc/user/06_feature/distalign/align_parts_y.png (revision 24813) Property changes on: tags/2.1.2/doc/user/06_feature/distalign/align_parts_y.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/user/06_feature/distalign/distalign.txt =================================================================== --- tags/2.1.2/doc/user/06_feature/distalign/distalign.txt (nonexistent) +++ tags/2.1.2/doc/user/06_feature/distalign/distalign.txt (revision 24813) @@ -0,0 +1,79 @@ +From: Ben Jackson +To: geda-user@moria.seul.org +Date: Sat, 24 Feb 2007 22:13:51 -0800 +Subject: The amazing Align/Distribute plugin + +Ok, having "finished" the smartdisperse plugin, I moved on to phase 2 +of my "I'm sick of moving LEDs by hand" master plan. + +Introducing Align() and Distribute(), which work much like the +similarly named functions in Visio. +Given that PCB does not have the concept of "first selected object" +to draw on, the reference points can be selected by arguments. + +Both functions always work on all selected elements[*]. + +Some examples: + +:Align(X) + +Objects are moved left/right to align their Marks with the Mark of +the topmost selected object. All objects remain on or move to the +current grid. + +:Align(Y,Centers) + +Now objects are aligned up/down to their geometric centers rather +than their marks. The reference point is the center of the leftmost +object. + +:Align(Y,Tops,Average,Gridless) + +Feeling bold, you align the tops all selected objects to the average +of their top edges and let them wander off the grid to exactly the +average of their tops. + +:Align(X,Marks,pcb_crosshair) + +None of the objects are where you want them, so you move the +crosshair to a likely spot and cause them all to move their X +coordinates to your new X location. + +:Align(X,Marks,Last) + +As above, but instead of the crosshair you just override the default +"First" to "Last" so the reference object is bottommost instead of +topmost. + + +Now you have them in a neat line, but they're all clumped! + +:Distribute(Y) + +Objects are spread out evenly from the first (uppermost) to last +using their marks as the reference point. + +:Distribute(X,Lefts,pcb_crosshair,Last) + +You move your crosshair to the left edge of the target area, which +will be the leftmost edge of the leftmost object. The objects are +spread between your crosshair and the original location of the Last +(rightmost) object. + +:Distribute(Y,Gaps) + +You have chosen to select many oddly sized objects, and instead of +their centers being spread out evenly, you want the space (or "gaps") +to be even. + +You get tricky and bind `Align(X,Marks,pcb_crosshair)' to a key. +Now you can select an object and hit your key and the object will +warp to the same X coordinate as your cursor. + +[*] If it has any flaws, it is that you can't operate non-element +objects, though some melding of autocrop (which knows how to do such +things) and distalign could produce such a capability. + +Ben Jackson AD7GD + +http://www.ben.com/ Index: tags/2.1.2/doc/user/06_feature/distalign/distribute_parts_x.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/user/06_feature/distalign/distribute_parts_x.png =================================================================== --- tags/2.1.2/doc/user/06_feature/distalign/distribute_parts_x.png (nonexistent) +++ tags/2.1.2/doc/user/06_feature/distalign/distribute_parts_x.png (revision 24813) Property changes on: tags/2.1.2/doc/user/06_feature/distalign/distribute_parts_x.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/user/06_feature/distalign/distribute_y_gaps.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/user/06_feature/distalign/distribute_y_gaps.png =================================================================== --- tags/2.1.2/doc/user/06_feature/distalign/distribute_y_gaps.png (nonexistent) +++ tags/2.1.2/doc/user/06_feature/distalign/distribute_y_gaps.png (revision 24813) Property changes on: tags/2.1.2/doc/user/06_feature/distalign/distribute_y_gaps.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/user/06_feature/distalign/import_parts.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/user/06_feature/distalign/import_parts.png =================================================================== --- tags/2.1.2/doc/user/06_feature/distalign/import_parts.png (nonexistent) +++ tags/2.1.2/doc/user/06_feature/distalign/import_parts.png (revision 24813) Property changes on: tags/2.1.2/doc/user/06_feature/distalign/import_parts.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/user/06_feature/distalign/index.html =================================================================== --- tags/2.1.2/doc/user/06_feature/distalign/index.html (nonexistent) +++ tags/2.1.2/doc/user/06_feature/distalign/index.html (revision 24813) @@ -0,0 +1,73 @@ + + + + pcb-rnd user manual + + + + +

Distalign plugin

+
+Two actions for aligning and distributing subcircuits in pcb-rnd +

Action Syntax

+

+

+Align(X/Y, [Lefts/Rights/Tops/Bottoms/Centers/Marks, [First/Last/pcb_crosshair/Average[, Gridless]]]) +

+

+Distribute(Y, [Lefts/Rights/Tops/Bottoms/Centers/Marks/Gaps, [First/Last/pcb_crosshair, First/Last/pcb_crosshair[, Gridless]]]) +

Description

+

+

+align() aligns selected subcircuits along the X or Y axis, relative to user selected reference points (like specific subcircuit edges, their centers, or marks) +

+

+distribute() distributes selected subcircuits evenly between the first or last subcircuit or to the pcb crosshairs + +

Examples

+

+

Build a linear array of tactile switch parts

+

+ +
Command descriptionimage + +
import +
Import an array of 8 TACT_6x6_4p footprints needed for a 1x8 grid.
Place the first part at the exact X,Y coord to start the array
Place the last part at the X position where the array will end +
+ +
align(y) +
The user aligns the TACT_6x6_4p footprints along a Y axis
The center of the first part is the default reference point +
+ +
distribute(x,centers,first,last) +
Note user places last part in position
Parts are distributed between the first and last along the X axis +
+
+ +

Align & distribute a mix of parts

+ +
Command descriptionimage + +
import +
A small set of nonhomogenous parts are imported +
+ +
align(x,centers,last) +
The parts are aligned to each other along an x axis with resepect to their centers
The chosen x axis is determined from the 'last' part location +
+ +
distribute(y,gaps) +
The parts are evenly distibuted by the gaps between them +
+ +
copy, align(), distribute() +
The parts in the first step are copied to create an array
The align and distribute commands are used for each row of the array in turn +
+
+ +

+See also: the original email that describes the plugin, +the dist/align action argument gallery (illustration). + + + Index: tags/2.1.2/doc/user/06_feature/distalign/result.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/user/06_feature/distalign/result.png =================================================================== --- tags/2.1.2/doc/user/06_feature/distalign/result.png (nonexistent) +++ tags/2.1.2/doc/user/06_feature/distalign/result.png (revision 24813) Property changes on: tags/2.1.2/doc/user/06_feature/distalign/result.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/user/06_feature/distaligntext/distaligntext_1.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/user/06_feature/distaligntext/distaligntext_1.png =================================================================== --- tags/2.1.2/doc/user/06_feature/distaligntext/distaligntext_1.png (nonexistent) +++ tags/2.1.2/doc/user/06_feature/distaligntext/distaligntext_1.png (revision 24813) Property changes on: tags/2.1.2/doc/user/06_feature/distaligntext/distaligntext_1.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/user/06_feature/distaligntext/distaligntext_2.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/user/06_feature/distaligntext/distaligntext_2.png =================================================================== --- tags/2.1.2/doc/user/06_feature/distaligntext/distaligntext_2.png (nonexistent) +++ tags/2.1.2/doc/user/06_feature/distaligntext/distaligntext_2.png (revision 24813) Property changes on: tags/2.1.2/doc/user/06_feature/distaligntext/distaligntext_2.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/user/06_feature/distaligntext/distaligntext_3.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/user/06_feature/distaligntext/distaligntext_3.png =================================================================== --- tags/2.1.2/doc/user/06_feature/distaligntext/distaligntext_3.png (nonexistent) +++ tags/2.1.2/doc/user/06_feature/distaligntext/distaligntext_3.png (revision 24813) Property changes on: tags/2.1.2/doc/user/06_feature/distaligntext/distaligntext_3.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/user/06_feature/distaligntext/index.html =================================================================== --- tags/2.1.2/doc/user/06_feature/distaligntext/index.html (nonexistent) +++ tags/2.1.2/doc/user/06_feature/distaligntext/index.html (revision 24813) @@ -0,0 +1,34 @@ + + + + pcb-rnd user manual + + + + +

Distaligntext

+ +Two actions to align and distribute text objects in pcb-rnd + +

Action Syntx

+

+

+AlignText(X/Y, [Lefts/Rights/Tops/Bottoms/Centers, [First/Last/pcb_crosshair/Average[, Gridless]]]) +

+

+DistributeText(Y, [Lefts/Rights/Tops/Bottoms/Centers/Gaps, [First/Last/pcb_crosshair, First/Last/pcb_crosshair[, Gridless]]]) + +

Examples

+

+ +
Command descriptionimage + +
import and text toolsText for a TI 14 pin jtag connector is generated + +
aligntext(x,rights)The text is aligned along the right side to +justify up with the 14 pin connector part +
The last part is positioned alongside pin 7 to delimit the last position
+ +
distributetext(y,gaps,first,last)The text is repositioned at even spacing between the first and last element + + Index: tags/2.1.2/doc/user/06_feature/djopt/Makefile =================================================================== --- tags/2.1.2/doc/user/06_feature/djopt/Makefile (nonexistent) +++ tags/2.1.2/doc/user/06_feature/djopt/Makefile (revision 24813) @@ -0,0 +1,50 @@ +PCB=../../src/pcb-rnd +HTML=index.html +CASES = \ + debumpify.$(TARGET) \ + miter.$(TARGET) \ + orthopull.$(TARGET) \ + unjaggy.$(TARGET) \ + vianudge.$(TARGET) \ + viatrim.$(TARGET) + +all: + $(MAKE) conv TARGET=out.png + $(MAKE) conv TARGET=png + $(MAKE) index + +index: + $(MAKE) index.html TARGET=txt + +index.html: Pre.html Post.html $(CASES) Makefile + cat Pre.html > $(HTML) + $(MAKE) conv TARGET=tbl + cat Post.html >>$(HTML) + +conv: $(CASES) + +.SUFFIXES: .pcb .out.pcb .png .out.png .tbl +.PRECIOUS: %.pcb %.out.pcb %.png %.out.png + +.pcb.out.pcb: + echo "OptAutoOnly(); djopt($*); SaveTo(LayoutAs, $*.out.pcb.tmp);"| $(PCB) --gui batch $*.pcb + awk '/Symbol.. . 1800./,/^Attribute/ { next } { print $$0 }' < $*.out.pcb.tmp > $*.out.pcb + rm $*.out.pcb.tmp + +.pcb.tbl: + echo '
$*'>>$(HTML) + cat $*.txt >>$(HTML) + echo ' '>>$(HTML) + +.pcb.png: + $(PCB) -x png --dpi 300 $*.pcb + +out.pcb.out.png: + $(PCB) -x png --dpi 300 $*.out.pcb + +clean: + rm *.out.pcb *.png index.html 2>/dev/null; true + + + + Index: tags/2.1.2/doc/user/06_feature/djopt/Post.html =================================================================== --- tags/2.1.2/doc/user/06_feature/djopt/Post.html (nonexistent) +++ tags/2.1.2/doc/user/06_feature/djopt/Post.html (revision 24813) @@ -0,0 +1,4 @@ +
autorun all the above except miter; run them multiple times until there's no more change possible     +
+ + Index: tags/2.1.2/doc/user/06_feature/djopt/Pre.html =================================================================== --- tags/2.1.2/doc/user/06_feature/djopt/Pre.html (nonexistent) +++ tags/2.1.2/doc/user/06_feature/djopt/Pre.html (revision 24813) @@ -0,0 +1,14 @@ + + +

Action djopt()

+ +The different types of optimizations change your board in order to +reduce the total trace length and via count. Each optimization is accessible +using an argument, e.g. djopt(miter). The basic actions have to be run multiple +times as each iteration will change the design making new changes possible for +subsequent iterations with the same or other actions. +

+Click on the images to download the example .pcb design. + + +
argument name description example in example out after 1st iteration Index: tags/2.1.2/doc/user/06_feature/djopt/debumpify.out.pcb =================================================================== --- tags/2.1.2/doc/user/06_feature/djopt/debumpify.out.pcb (nonexistent) +++ tags/2.1.2/doc/user/06_feature/djopt/debumpify.out.pcb (revision 24813) @@ -0,0 +1,88 @@ +# release: pcb-rnd 1.0.7 + +# To read pcb files, the pcb version (or the git source date) must be >= the file version +FileVersion[20070407] + +PCB["" 140000 67500] + +Grid[2500.0 0 0 1] +Cursor[0 5000 0.000000] +PolyArea[3100.006200] +Thermal[0.500000] +DRC[1200 900 1000 700 1500 1000] +Flags("nameonpcb,clearnew,snappin") +Groups("1,3,4,c:2,5,6,s:7:8") +Styles["Signal,1000,7874,3150,2000:Power,2000,8661,3937,2000:Fat,8000,13780,4724,2500:Sig-tight,1000,6400,3150,1200"] + + +Element["" "Standard SMT resistor, capacitor etc" "R101" "1206" 17500 32500 -5650 4350 0 100 ""] +( + Pad[5905 -1181 5905 1181 5118 2000 5718 "1" "1" "square"] + Pad[-5905 -1181 -5905 1181 5118 2000 5718 "2" "2" "square"] + ElementLine [-2362 3740 2362 3740 800] + ElementLine [-2362 -3740 2362 -3740 800] + + ) + +Element["" "Standard SMT resistor, capacitor etc" "R102" "1206" 117500 32500 -5650 4350 0 100 ""] +( + Pad[5905 -1181 5905 1181 5118 2000 5718 "1" "1" "square"] + Pad[-5905 -1181 -5905 1181 5118 2000 5718 "2" "2" "square"] + ElementLine [-2362 3740 2362 3740 800] + ElementLine [-2362 -3740 2362 -3740 800] + + ) +Layer(1 "component") +( + Line[23405 32500 30000 32500 1000 4000 "clearline"] + Line[92500 32500 111595 32500 1000 4000 "clearline"] + Line[30000 32500 30000 32500 1000 4000 "clearline"] + Line[30000 32500 37500 32500 1000 4000 "clearline"] + Line[37500 32500 37500 32500 1000 4000 "clearline"] + Line[37500 32500 47500 32500 1000 4000 "clearline"] + Line[47500 32500 57500 22500 1000 4000 "clearline"] + Line[57500 22500 67500 22500 1000 4000 "clearline"] + Line[67500 22500 77500 32500 1000 4000 "clearline"] + Line[77500 32500 82500 32500 1000 4000 "clearline"] + Line[82500 32500 85000 22500 1000 4000 "clearline"] + Line[90000 22500 92500 32500 1000 4000 "clearline"] + Line[85000 22500 90000 22500 1000 4000 "clearline"] +) +Layer(2 "solder") +( +) +Layer(3 "comp-GND") +( +) +Layer(4 "comp-power") +( +) +Layer(5 "sold-GND") +( +) +Layer(6 "sold-power") +( +) +Layer(7 "signal3") +( +) +Layer(8 "outline") +( +) +Layer(9 "silk") +( +) +Layer(10 "silk") +( + Text[30000 5000 0 105 "90" "clearline"] + Text[60000 5000 0 105 "45" "clearline"] + Text[82500 5000 0 105 "rand" "clearline"] +) +NetList() +( + Net("GND" "(unknown)") + ( + Connect("R101-1") + Connect("R102-2") + ) +) Index: tags/2.1.2/doc/user/06_feature/djopt/debumpify.out.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/user/06_feature/djopt/debumpify.out.png =================================================================== --- tags/2.1.2/doc/user/06_feature/djopt/debumpify.out.png (nonexistent) +++ tags/2.1.2/doc/user/06_feature/djopt/debumpify.out.png (revision 24813) Property changes on: tags/2.1.2/doc/user/06_feature/djopt/debumpify.out.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/user/06_feature/djopt/debumpify.pcb =================================================================== --- tags/2.1.2/doc/user/06_feature/djopt/debumpify.pcb (nonexistent) +++ tags/2.1.2/doc/user/06_feature/djopt/debumpify.pcb (revision 24813) @@ -0,0 +1,89 @@ +# release: pcb-rnd 1.0.7 + +# To read pcb files, the pcb version (or the git source date) must be >= the file version +FileVersion[20070407] + +PCB["" 140000 67500] + +Grid[2500.0 0 0 1] +Cursor[0 5000 0.000000] +PolyArea[3100.006200] +Thermal[0.500000] +DRC[1200 900 1000 700 1500 1000] +Flags("nameonpcb,clearnew,snappin") +Groups("1,3,4,c:2,5,6,s:7:8") +Styles["Signal,1000,7874,3150,2000:Power,2000,8661,3937,2000:Fat,8000,13780,4724,2500:Sig-tight,1000,6400,3150,1200"] + +Attribute("PCB::grid::unit" "mm") + +Element["" "Standard SMT resistor, capacitor etc" "R101" "1206" 17500 32500 -5650 4350 0 100 ""] +( + Pad[5905 -1181 5905 1181 5118 2000 5718 "1" "1" "square"] + Pad[-5905 -1181 -5905 1181 5118 2000 5718 "2" "2" "square"] + ElementLine [-2362 3740 2362 3740 800] + ElementLine [-2362 -3740 2362 -3740 800] + + ) + +Element["" "Standard SMT resistor, capacitor etc" "R102" "1206" 117500 32500 -5650 4350 0 100 ""] +( + Pad[5905 -1181 5905 1181 5118 2000 5718 "1" "1" "square"] + Pad[-5905 -1181 -5905 1181 5118 2000 5718 "2" "2" "square"] + ElementLine [-2362 3740 2362 3740 800] + ElementLine [-2362 -3740 2362 -3740 800] + + ) +Layer(1 "component") +( + Line[23405 32500 30000 32500 1000 4000 "clearline"] + Line[92500 32500 111595 32500 1000 4000 "clearline"] + Line[30000 32500 30000 22500 1000 4000 "clearline"] + Line[30000 22500 37500 22500 1000 4000 "clearline"] + Line[37500 22500 37500 32500 1000 4000 "clearline"] + Line[37500 32500 47500 32500 1000 4000 "clearline"] + Line[47500 32500 57500 22500 1000 4000 "clearline"] + Line[57500 22500 67500 22500 1000 4000 "clearline"] + Line[67500 22500 77500 32500 1000 4000 "clearline"] + Line[77500 32500 82500 32500 1000 4000 "clearline"] + Line[82500 32500 85000 22500 1000 4000 "clearline"] + Line[90000 22500 92500 32500 1000 4000 "clearline"] + Line[85000 22500 90000 22500 1000 4000 "clearline"] +) +Layer(2 "solder") +( +) +Layer(3 "comp-GND") +( +) +Layer(4 "comp-power") +( +) +Layer(5 "sold-GND") +( +) +Layer(6 "sold-power") +( +) +Layer(7 "signal3") +( +) +Layer(8 "outline") +( +) +Layer(9 "silk") +( +) +Layer(10 "silk") +( + Text[30000 5000 0 105 "90" "clearline"] + Text[60000 5000 0 105 "45" "clearline"] + Text[82500 5000 0 105 "rand" "clearline"] +) +NetList() +( + Net("GND" "(unknown)") + ( + Connect("R101-1") + Connect("R102-2") + ) +) Index: tags/2.1.2/doc/user/06_feature/djopt/debumpify.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/user/06_feature/djopt/debumpify.png =================================================================== --- tags/2.1.2/doc/user/06_feature/djopt/debumpify.png (nonexistent) +++ tags/2.1.2/doc/user/06_feature/djopt/debumpify.png (revision 24813) Property changes on: tags/2.1.2/doc/user/06_feature/djopt/debumpify.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/user/06_feature/djopt/debumpify.txt =================================================================== --- tags/2.1.2/doc/user/06_feature/djopt/debumpify.txt (nonexistent) +++ tags/2.1.2/doc/user/06_feature/djopt/debumpify.txt (revision 24813) @@ -0,0 +1,2 @@ +Looks for U-shaped traces (with 90 degree corners) that can be shortened +or eliminated. Index: tags/2.1.2/doc/user/06_feature/djopt/index.html =================================================================== --- tags/2.1.2/doc/user/06_feature/djopt/index.html (nonexistent) +++ tags/2.1.2/doc/user/06_feature/djopt/index.html (revision 24813) @@ -0,0 +1,45 @@ + + +

Action djopt()

+ +The different types of optimizations change your board in order to +reduce the total trace length and via count. Each optimization is accessible +using an argument, e.g. djopt(miter). The basic actions have to be run multiple +times as each iteration will change the design making new changes possible for +subsequent iterations with the same or other actions. +

+Click on the images to download the example .pcb design. + + +
argument name description example in example out after 1st iteration +
debumpify +Looks for U-shaped traces (with 90 degree corners) that can be shortened +or eliminated. + +
miter +Replaces 90 degree corners with a pair of 45 degree corners, to reduce +RF losses and trace length. + +
orthopull +Looks for chains of traces all going in one direction, with more +traces orthogonal on one side than on the other. Moves the chain in +that direction, causing a net reduction in trace length, possibly +eliminating traces and/or corners. + +
unjaggy +Looks for corners which could be flipped to eliminate one or more +corners (i.e. jaggy lines become simpler). + +
vianudge +Looks for vias where all traces leave in the same direction. Tries to +move via in that direction to eliminate one of the traces (and thus a +corner). + +
viatrim +Looks for traces that go from via to via, where moving that trace to a +different layer eliminates one or both vias. + +
autorun all the above except miter; run them multiple times until there's no more change possible     +
+ + Index: tags/2.1.2/doc/user/06_feature/djopt/miter.out.pcb =================================================================== --- tags/2.1.2/doc/user/06_feature/djopt/miter.out.pcb (nonexistent) +++ tags/2.1.2/doc/user/06_feature/djopt/miter.out.pcb (revision 24813) @@ -0,0 +1,75 @@ +# release: pcb-rnd 1.0.7 + +# To read pcb files, the pcb version (or the git source date) must be >= the file version +FileVersion[20070407] + +PCB["" 140000 67500] + +Grid[500.0 0 0 1] +Cursor[500 0 0.000000] +PolyArea[3100.006200] +Thermal[0.500000] +DRC[1200 900 1000 700 1500 1000] +Flags("nameonpcb,clearnew,snappin") +Groups("1,3,4,c:2,5,6,s:7:8") +Styles["Signal,1000,7874,3150,2000:Power,2000,8661,3937,2000:Fat,8000,13780,4724,2500:Sig-tight,1000,6400,3150,1200"] + + +Element["" "Standard SMT resistor, capacitor etc" "R101" "1206" 45000 15000 -5650 4350 0 100 ""] +( + Pad[5905 -1181 5905 1181 5118 2000 5718 "1" "1" "square"] + Pad[-5905 -1181 -5905 1181 5118 2000 5718 "2" "2" "square"] + ElementLine [-2362 3740 2362 3740 800] + ElementLine [-2362 -3740 2362 -3740 800] + + ) + +Element["" "Standard SMT resistor, capacitor etc" "R102" "1206" 80000 47500 -4350 -5650 3 100 ""] +( + Pad[-1181 5905 1181 5905 5118 2000 5718 "1" "1" "square"] + Pad[-1181 -5905 1181 -5905 5118 2000 5718 "2" "2" "square"] + ElementLine [-3740 -2362 -3740 2362 800] + ElementLine [3740 -2362 3740 2362 800] + + ) +Layer(1 "component") +( + Line[50905 15000 53405 15000 1000 4000 "clearline"] + Line[80000 41595 80000 41595 1000 4000 "clearline"] + Line[53405 15000 80000 41595 1000 4000 "clearline"] +) +Layer(2 "solder") +( +) +Layer(3 "comp-GND") +( +) +Layer(4 "comp-power") +( +) +Layer(5 "sold-GND") +( +) +Layer(6 "sold-power") +( +) +Layer(7 "signal3") +( +) +Layer(8 "outline") +( +) +Layer(9 "silk") +( +) +Layer(10 "silk") +( +) +NetList() +( + Net("GND" "(unknown)") + ( + Connect("R101-1") + Connect("R102-2") + ) +) Index: tags/2.1.2/doc/user/06_feature/djopt/miter.out.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/user/06_feature/djopt/miter.out.png =================================================================== --- tags/2.1.2/doc/user/06_feature/djopt/miter.out.png (nonexistent) +++ tags/2.1.2/doc/user/06_feature/djopt/miter.out.png (revision 24813) Property changes on: tags/2.1.2/doc/user/06_feature/djopt/miter.out.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/user/06_feature/djopt/miter.pcb =================================================================== --- tags/2.1.2/doc/user/06_feature/djopt/miter.pcb (nonexistent) +++ tags/2.1.2/doc/user/06_feature/djopt/miter.pcb (revision 24813) @@ -0,0 +1,80 @@ +# release: pcb-rnd 1.0.7 + +# To read pcb files, the pcb version (or the git source date) must be >= the file version +FileVersion[20070407] + +PCB["" 140000 67500] + +Grid[500.0 0 0 1] +Cursor[500 0 0.000000] +PolyArea[3100.006200] +Thermal[0.500000] +DRC[1200 900 1000 700 1500 1000] +Flags("nameonpcb,clearnew,snappin") +Groups("1,3,4,c:2,5,6,s:7:8") +Styles["Signal,1000,7874,3150,2000:Power,2000,8661,3937,2000:Fat,8000,13780,4724,2500:Sig-tight,1000,6400,3150,1200"] + + +Attribute("PCB::grid::unit" "mil") + +Element["" "Standard SMT resistor, capacitor etc" "R101" "1206" 45000 15000 -5650 4350 0 100 ""] +( + Pad[5905 -1181 5905 1181 5118 2000 5718 "1" "1" "square"] + Pad[-5905 -1181 -5905 1181 5118 2000 5718 "2" "2" "square"] + ElementLine [-2362 3740 2362 3740 800] + ElementLine [-2362 -3740 2362 -3740 800] + + ) + +Element["" "Standard SMT resistor, capacitor etc" "R102" "1206" 80000 47500 -4350 -5650 3 100 ""] +( + Pad[-1181 5905 1181 5905 5118 2000 5718 "1" "1" "square"] + Pad[-1181 -5905 1181 -5905 5118 2000 5718 "2" "2" "square"] + ElementLine [-3740 -2362 -3740 2362 800] + ElementLine [3740 -2362 3740 2362 800] + + ) +Layer(1 "component") +( + Line[50905 15000 80000 15000 1000 4000 "clearline"] + Line[80000 15000 80000 41595 1000 4000 "clearline"] + Line[81181 41595 80000 41595 1000 4000 "clearline"] + Line[80000 41595 78819 41595 1000 4000 "clearline"] + Line[50905 16181 50905 15000 1000 4000 "clearline"] + Line[50905 15000 50905 13819 1000 4000 "clearline"] +) +Layer(2 "solder") +( +) +Layer(3 "comp-GND") +( +) +Layer(4 "comp-power") +( +) +Layer(5 "sold-GND") +( +) +Layer(6 "sold-power") +( +) +Layer(7 "signal3") +( +) +Layer(8 "outline") +( +) +Layer(9 "silk") +( +) +Layer(10 "silk") +( +) +NetList() +( + Net("GND" "(unknown)") + ( + Connect("R101-1") + Connect("R102-2") + ) +) Index: tags/2.1.2/doc/user/06_feature/djopt/miter.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/user/06_feature/djopt/miter.png =================================================================== --- tags/2.1.2/doc/user/06_feature/djopt/miter.png (nonexistent) +++ tags/2.1.2/doc/user/06_feature/djopt/miter.png (revision 24813) Property changes on: tags/2.1.2/doc/user/06_feature/djopt/miter.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/user/06_feature/djopt/miter.txt =================================================================== --- tags/2.1.2/doc/user/06_feature/djopt/miter.txt (nonexistent) +++ tags/2.1.2/doc/user/06_feature/djopt/miter.txt (revision 24813) @@ -0,0 +1,2 @@ +Replaces 90 degree corners with a pair of 45 degree corners, to reduce +RF losses and trace length. Index: tags/2.1.2/doc/user/06_feature/djopt/orthopull.out.pcb =================================================================== --- tags/2.1.2/doc/user/06_feature/djopt/orthopull.out.pcb (nonexistent) +++ tags/2.1.2/doc/user/06_feature/djopt/orthopull.out.pcb (revision 24813) @@ -0,0 +1,99 @@ +# release: pcb-rnd 1.0.7 + +# To read pcb files, the pcb version (or the git source date) must be >= the file version +FileVersion[20070407] + +PCB["" 140000 67500] + +Grid[2500.0 0 0 1] +Cursor[47500 32500 0.000000] +PolyArea[3100.006200] +Thermal[0.500000] +DRC[1200 900 1000 700 1500 1000] +Flags("nameonpcb,clearnew,snappin") +Groups("1,3,4,c:2,5,6,s:7:8") +Styles["Signal,1000,7874,3150,2000:Power,2000,8661,3937,2000:Fat,8000,13780,4724,2500:Sig-tight,1000,6400,3150,1200"] + + +Element["" "Standard SMT resistor, capacitor etc" "R102" "1206" 52500 10000 4350 5650 1 100 ""] +( + Pad[-1181 -5905 1181 -5905 5118 2000 5718 "1" "1" "square"] + Pad[-1181 5905 1181 5905 5118 2000 5718 "2" "2" "square"] + ElementLine [3740 -2362 3740 2362 800] + ElementLine [-3740 -2362 -3740 2362 800] + + ) + +Element["" "Standard SMT resistor, capacitor etc" "R103" "1206" 72500 10000 4350 5650 1 100 ""] +( + Pad[-1181 -5905 1181 -5905 5118 2000 5718 "1" "1" "square"] + Pad[-1181 5905 1181 5905 5118 2000 5718 "2" "2" "square"] + ElementLine [3740 -2362 3740 2362 800] + ElementLine [-3740 -2362 -3740 2362 800] + + ) + +Element["" "Standard SMT resistor, capacitor etc" "R104" "1206" 62500 52500 -4350 -5650 3 100 ""] +( + Pad[-1181 5905 1181 5905 5118 2000 5718 "1" "1" "square"] + Pad[-1181 -5905 1181 -5905 5118 2000 5718 "2" "2" "square"] + ElementLine [-3740 -2362 -3740 2362 800] + ElementLine [3740 -2362 3740 2362 800] + + ) + +Element["" "Standard SMT resistor, capacitor etc" "R101" "1206" 35000 10000 -4350 -5650 3 100 ""] +( + Pad[-1181 5905 1181 5905 5118 2000 5718 "1" "1" "square"] + Pad[-1181 -5905 1181 -5905 5118 2000 5718 "2" "2" "square"] + ElementLine [-3740 -2362 -3740 2362 800] + ElementLine [3740 -2362 3740 2362 800] + + ) +Layer(1 "component") +( + Line[52500 15905 52500 22500 1000 4000 "clearline"] + Line[72500 15905 72500 22500 1000 4000 "clearline"] + Line[62500 46595 62500 22500 1000 4000 "clearline"] + Line[35000 22500 52500 22500 1000 4000 "clearline"] + Line[35000 22500 35000 15905 1000 4000 "clearline"] + Line[62500 22500 72500 22500 1000 4000 "clearline"] + Line[52500 22500 62500 22500 1000 4000 "clearline"] +) +Layer(2 "solder") +( +) +Layer(3 "comp-GND") +( +) +Layer(4 "comp-power") +( +) +Layer(5 "sold-GND") +( +) +Layer(6 "sold-power") +( +) +Layer(7 "signal3") +( +) +Layer(8 "outline") +( +) +Layer(9 "silk") +( +) +Layer(10 "silk") +( +) +NetList() +( + Net("GND" "(unknown)") + ( + Connect("R101-1") + Connect("R102-2") + Connect("R103-2") + Connect("R104-2") + ) +) Index: tags/2.1.2/doc/user/06_feature/djopt/orthopull.out.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/user/06_feature/djopt/orthopull.out.png =================================================================== --- tags/2.1.2/doc/user/06_feature/djopt/orthopull.out.png (nonexistent) +++ tags/2.1.2/doc/user/06_feature/djopt/orthopull.out.png (revision 24813) Property changes on: tags/2.1.2/doc/user/06_feature/djopt/orthopull.out.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/user/06_feature/djopt/orthopull.pcb =================================================================== --- tags/2.1.2/doc/user/06_feature/djopt/orthopull.pcb (nonexistent) +++ tags/2.1.2/doc/user/06_feature/djopt/orthopull.pcb (revision 24813) @@ -0,0 +1,98 @@ +# release: pcb-rnd 1.0.7 + +# To read pcb files, the pcb version (or the git source date) must be >= the file version +FileVersion[20070407] + +PCB["" 140000 67500] + +Grid[2500.0 0 0 1] +Cursor[47500 32500 0.000000] +PolyArea[3100.006200] +Thermal[0.500000] +DRC[1200 900 1000 700 1500 1000] +Flags("nameonpcb,clearnew,snappin") +Groups("1,3,4,c:2,5,6,s:7:8") +Styles["Signal,1000,7874,3150,2000:Power,2000,8661,3937,2000:Fat,8000,13780,4724,2500:Sig-tight,1000,6400,3150,1200"] + +Attribute("PCB::grid::unit" "mm") + +Element["" "Standard SMT resistor, capacitor etc" "R102" "1206" 52500 10000 4350 5650 1 100 ""] +( + Pad[-1181 -5905 1181 -5905 5118 2000 5718 "1" "1" "square"] + Pad[-1181 5905 1181 5905 5118 2000 5718 "2" "2" "square"] + ElementLine [3740 -2362 3740 2362 800] + ElementLine [-3740 -2362 -3740 2362 800] + + ) + +Element["" "Standard SMT resistor, capacitor etc" "R103" "1206" 72500 10000 4350 5650 1 100 ""] +( + Pad[-1181 -5905 1181 -5905 5118 2000 5718 "1" "1" "square"] + Pad[-1181 5905 1181 5905 5118 2000 5718 "2" "2" "square"] + ElementLine [3740 -2362 3740 2362 800] + ElementLine [-3740 -2362 -3740 2362 800] + + ) + +Element["" "Standard SMT resistor, capacitor etc" "R104" "1206" 62500 52500 -4350 -5650 3 100 ""] +( + Pad[-1181 5905 1181 5905 5118 2000 5718 "1" "1" "square"] + Pad[-1181 -5905 1181 -5905 5118 2000 5718 "2" "2" "square"] + ElementLine [-3740 -2362 -3740 2362 800] + ElementLine [3740 -2362 3740 2362 800] + + ) + +Element["" "Standard SMT resistor, capacitor etc" "R101" "1206" 35000 10000 -4350 -5650 3 100 ""] +( + Pad[-1181 5905 1181 5905 5118 2000 5718 "1" "1" "square"] + Pad[-1181 -5905 1181 -5905 5118 2000 5718 "2" "2" "square"] + ElementLine [-3740 -2362 -3740 2362 800] + ElementLine [3740 -2362 3740 2362 800] + + ) +Layer(1 "component") +( + Line[52500 15905 52500 37500 1000 4000 "clearline"] + Line[72500 15905 72500 37500 1000 4000 "clearline"] + Line[62500 46595 62500 37500 1000 4000 "clearline"] + Line[35000 37500 72500 37500 1000 4000 "clearline"] + Line[35000 37500 35000 15905 1000 4000 "clearline"] +) +Layer(2 "solder") +( +) +Layer(3 "comp-GND") +( +) +Layer(4 "comp-power") +( +) +Layer(5 "sold-GND") +( +) +Layer(6 "sold-power") +( +) +Layer(7 "signal3") +( +) +Layer(8 "outline") +( +) +Layer(9 "silk") +( +) +Layer(10 "silk") +( +) +NetList() +( + Net("GND" "(unknown)") + ( + Connect("R101-1") + Connect("R102-2") + Connect("R103-2") + Connect("R104-2") + ) +) Index: tags/2.1.2/doc/user/06_feature/djopt/orthopull.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/user/06_feature/djopt/orthopull.png =================================================================== --- tags/2.1.2/doc/user/06_feature/djopt/orthopull.png (nonexistent) +++ tags/2.1.2/doc/user/06_feature/djopt/orthopull.png (revision 24813) Property changes on: tags/2.1.2/doc/user/06_feature/djopt/orthopull.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/user/06_feature/djopt/orthopull.txt =================================================================== --- tags/2.1.2/doc/user/06_feature/djopt/orthopull.txt (nonexistent) +++ tags/2.1.2/doc/user/06_feature/djopt/orthopull.txt (revision 24813) @@ -0,0 +1,4 @@ +Looks for chains of traces all going in one direction, with more +traces orthogonal on one side than on the other. Moves the chain in +that direction, causing a net reduction in trace length, possibly +eliminating traces and/or corners. Index: tags/2.1.2/doc/user/06_feature/djopt/unjaggy.out.pcb =================================================================== --- tags/2.1.2/doc/user/06_feature/djopt/unjaggy.out.pcb (nonexistent) +++ tags/2.1.2/doc/user/06_feature/djopt/unjaggy.out.pcb (revision 24813) @@ -0,0 +1,79 @@ +# release: pcb-rnd 1.0.7 + +# To read pcb files, the pcb version (or the git source date) must be >= the file version +FileVersion[20070407] + +PCB["" 140000 67500] + +Grid[2500.0 0 0 1] +Cursor[12500 10000 0.000000] +PolyArea[3100.006200] +Thermal[0.500000] +DRC[1200 900 1000 700 1500 1000] +Flags("nameonpcb,clearnew,snappin") +Groups("1,3,4,c:2,5,6,s:7:8") +Styles["Signal,1000,7874,3150,2000:Power,2000,8661,3937,2000:Fat,8000,13780,4724,2500:Sig-tight,1000,6400,3150,1200"] + + +Element["" "Standard SMT resistor, capacitor etc" "R101" "1206" 17500 32500 -5650 4350 0 100 ""] +( + Pad[5905 -1181 5905 1181 5118 2000 5718 "1" "1" "square"] + Pad[-5905 -1181 -5905 1181 5118 2000 5718 "2" "2" "square"] + ElementLine [-2362 3740 2362 3740 800] + ElementLine [-2362 -3740 2362 -3740 800] + + ) + +Element["" "Standard SMT resistor, capacitor etc" "R102" "1206" 65000 12500 -5650 4350 0 100 ""] +( + Pad[5905 -1181 5905 1181 5118 2000 5718 "1" "1" "square"] + Pad[-5905 -1181 -5905 1181 5118 2000 5718 "2" "2" "square"] + ElementLine [-2362 3740 2362 3740 800] + ElementLine [-2362 -3740 2362 -3740 800] + + ) +Layer(1 "component") +( + Line[23405 32500 37500 32500 1000 4000 "clearline"] + Line[37500 32500 37500 15000 1000 4000 "clearline"] + Line[37500 15000 37500 15000 1000 4000 "clearline"] + Line[37500 32500 37500 32500 1000 4000 "clearline"] + Line[37500 15000 45000 15000 1000 4000 "clearline"] + Line[45000 15000 45000 10000 1000 4000 "clearline"] + Line[45000 10000 59095 10000 1000 4000 "clearline"] +) +Layer(2 "solder") +( +) +Layer(3 "comp-GND") +( +) +Layer(4 "comp-power") +( +) +Layer(5 "sold-GND") +( +) +Layer(6 "sold-power") +( +) +Layer(7 "signal3") +( +) +Layer(8 "outline") +( +) +Layer(9 "silk") +( +) +Layer(10 "silk") +( +) +NetList() +( + Net("GND" "(unknown)") + ( + Connect("R101-1") + Connect("R102-2") + ) +) Index: tags/2.1.2/doc/user/06_feature/djopt/unjaggy.out.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/user/06_feature/djopt/unjaggy.out.png =================================================================== --- tags/2.1.2/doc/user/06_feature/djopt/unjaggy.out.png (nonexistent) +++ tags/2.1.2/doc/user/06_feature/djopt/unjaggy.out.png (revision 24813) Property changes on: tags/2.1.2/doc/user/06_feature/djopt/unjaggy.out.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/user/06_feature/djopt/unjaggy.pcb =================================================================== --- tags/2.1.2/doc/user/06_feature/djopt/unjaggy.pcb (nonexistent) +++ tags/2.1.2/doc/user/06_feature/djopt/unjaggy.pcb (revision 24813) @@ -0,0 +1,81 @@ +# release: pcb-rnd 1.0.7 + +# To read pcb files, the pcb version (or the git source date) must be >= the file version +FileVersion[20070407] + +PCB["" 140000 67500] + +Grid[2500.0 0 0 1] +Cursor[12500 10000 0.000000] +PolyArea[3100.006200] +Thermal[0.500000] +DRC[1200 900 1000 700 1500 1000] +Flags("nameonpcb,clearnew,snappin") +Groups("1,3,4,c:2,5,6,s:7:8") +Styles["Signal,1000,7874,3150,2000:Power,2000,8661,3937,2000:Fat,8000,13780,4724,2500:Sig-tight,1000,6400,3150,1200"] + + +Attribute("PCB::grid::unit" "mm") + +Element["" "Standard SMT resistor, capacitor etc" "R101" "1206" 17500 32500 -5650 4350 0 100 ""] +( + Pad[5905 -1181 5905 1181 5118 2000 5718 "1" "1" "square"] + Pad[-5905 -1181 -5905 1181 5118 2000 5718 "2" "2" "square"] + ElementLine [-2362 3740 2362 3740 800] + ElementLine [-2362 -3740 2362 -3740 800] + + ) + +Element["" "Standard SMT resistor, capacitor etc" "R102" "1206" 65000 12500 -5650 4350 0 100 ""] +( + Pad[5905 -1181 5905 1181 5118 2000 5718 "1" "1" "square"] + Pad[-5905 -1181 -5905 1181 5118 2000 5718 "2" "2" "square"] + ElementLine [-2362 3740 2362 3740 800] + ElementLine [-2362 -3740 2362 -3740 800] + + ) +Layer(1 "component") +( + Line[23405 32500 30000 32500 1000 4000 "clearline"] + Line[30000 22500 37500 22500 1000 4000 "clearline"] + Line[37500 22500 37500 15000 1000 4000 "clearline"] + Line[30000 32500 30000 22500 1000 4000 "clearline"] + Line[37500 15000 45000 15000 1000 4000 "clearline"] + Line[45000 15000 45000 10000 1000 4000 "clearline"] + Line[45000 10000 56595 10000 1000 4000 "clearline"] +) +Layer(2 "solder") +( +) +Layer(3 "comp-GND") +( +) +Layer(4 "comp-power") +( +) +Layer(5 "sold-GND") +( +) +Layer(6 "sold-power") +( +) +Layer(7 "signal3") +( +) +Layer(8 "outline") +( +) +Layer(9 "silk") +( +) +Layer(10 "silk") +( +) +NetList() +( + Net("GND" "(unknown)") + ( + Connect("R101-1") + Connect("R102-2") + ) +) Index: tags/2.1.2/doc/user/06_feature/djopt/unjaggy.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/user/06_feature/djopt/unjaggy.png =================================================================== --- tags/2.1.2/doc/user/06_feature/djopt/unjaggy.png (nonexistent) +++ tags/2.1.2/doc/user/06_feature/djopt/unjaggy.png (revision 24813) Property changes on: tags/2.1.2/doc/user/06_feature/djopt/unjaggy.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/user/06_feature/djopt/unjaggy.txt =================================================================== --- tags/2.1.2/doc/user/06_feature/djopt/unjaggy.txt (nonexistent) +++ tags/2.1.2/doc/user/06_feature/djopt/unjaggy.txt (revision 24813) @@ -0,0 +1,2 @@ +Looks for corners which could be flipped to eliminate one or more +corners (i.e. jaggy lines become simpler). Index: tags/2.1.2/doc/user/06_feature/djopt/vianudge.out.pcb =================================================================== --- tags/2.1.2/doc/user/06_feature/djopt/vianudge.out.pcb (nonexistent) +++ tags/2.1.2/doc/user/06_feature/djopt/vianudge.out.pcb (revision 24813) @@ -0,0 +1,79 @@ +# release: pcb-rnd 1.0.7 + +# To read pcb files, the pcb version (or the git source date) must be >= the file version +FileVersion[20070407] + +PCB["" 140000 67500] + +Grid[2500.0 0 0 1] +Cursor[17500 22500 0.000000] +PolyArea[3100.006200] +Thermal[0.500000] +DRC[1200 900 1000 700 1500 1000] +Flags("nameonpcb,clearnew,snappin") +Groups("1,3,4,c:2,5,6,s:7:8") +Styles["Signal,1000,7874,3150,2000:Power,2000,8661,3937,2000:Fat,8000,13780,4724,2500:Sig-tight,1000,6400,3150,1200"] + +Via[85000 27500 8661 4000 0 3937 "" ""] + +Element["" "Standard SMT resistor, capacitor etc" "R101" "1206" 57500 10000 -5650 4350 0 100 ""] +( + Pad[5905 -1181 5905 1181 5118 2000 5718 "1" "1" "square"] + Pad[-5905 -1181 -5905 1181 5118 2000 5718 "2" "2" "square"] + ElementLine [-2362 3740 2362 3740 800] + ElementLine [-2362 -3740 2362 -3740 800] + + ) + +Element["onsolder" "Standard SMT resistor, capacitor etc" "R102" "1206" 10000 10000 5650 4350 2 100 "auto"] +( + Pad[-5905 -1181 -5905 1181 5118 2000 5718 "1" "1" "onsolder,square"] + Pad[5905 -1181 5905 1181 5118 2000 5718 "2" "2" "onsolder,square"] + ElementLine [-2362 3740 2362 3740 800] + ElementLine [-2362 -3740 2362 -3740 800] + + ) +Layer(1 "component") +( + Line[63405 10000 85000 10000 1000 4000 "clearline"] + Line[85000 10000 85000 27500 1000 4000 "clearline"] +) +Layer(2 "solder") +( + Line[15905 10000 30000 10000 2000 4000 "clearline"] + Line[30000 10000 30000 27500 2000 4000 "clearline"] + Line[30000 27500 85000 27500 2000 4000 "clearline"] + Line[85000 27500 85000 27500 2000 4000 "clearline"] +) +Layer(3 "comp-GND") +( +) +Layer(4 "comp-power") +( +) +Layer(5 "sold-GND") +( +) +Layer(6 "sold-power") +( +) +Layer(7 "signal3") +( +) +Layer(8 "outline") +( +) +Layer(9 "silk") +( +) +Layer(10 "silk") +( +) +NetList() +( + Net("GND" "(unknown)") + ( + Connect("R101-1") + Connect("R102-2") + ) +) Index: tags/2.1.2/doc/user/06_feature/djopt/vianudge.out.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/user/06_feature/djopt/vianudge.out.png =================================================================== --- tags/2.1.2/doc/user/06_feature/djopt/vianudge.out.png (nonexistent) +++ tags/2.1.2/doc/user/06_feature/djopt/vianudge.out.png (revision 24813) Property changes on: tags/2.1.2/doc/user/06_feature/djopt/vianudge.out.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/user/06_feature/djopt/vianudge.pcb =================================================================== --- tags/2.1.2/doc/user/06_feature/djopt/vianudge.pcb (nonexistent) +++ tags/2.1.2/doc/user/06_feature/djopt/vianudge.pcb (revision 24813) @@ -0,0 +1,81 @@ +# release: pcb-rnd 1.0.7 + +# To read pcb files, the pcb version (or the git source date) must be >= the file version +FileVersion[20070407] + +PCB["" 140000 67500] + +Grid[2500.0 0 0 1] +Cursor[17500 22500 0.000000] +PolyArea[3100.006200] +Thermal[0.500000] +DRC[1200 900 1000 700 1500 1000] +Flags("nameonpcb,clearnew,snappin") +Groups("1,3,4,c:2,5,6,s:7:8") +Styles["Signal,1000,7874,3150,2000:Power,2000,8661,3937,2000:Fat,8000,13780,4724,2500:Sig-tight,1000,6400,3150,1200"] + + +Attribute("PCB::grid::unit" "mm") +Via[85000 50000 8661 4000 0 3937 "" ""] + +Element["" "Standard SMT resistor, capacitor etc" "R101" "1206" 57500 10000 -5650 4350 0 100 ""] +( + Pad[5905 -1181 5905 1181 5118 2000 5718 "1" "1" "square"] + Pad[-5905 -1181 -5905 1181 5118 2000 5718 "2" "2" "square"] + ElementLine [-2362 3740 2362 3740 800] + ElementLine [-2362 -3740 2362 -3740 800] + + ) + +Element["onsolder" "Standard SMT resistor, capacitor etc" "R102" "1206" 10000 10000 5650 4350 2 100 "auto"] +( + Pad[-5905 -1181 -5905 1181 5118 2000 5718 "1" "1" "onsolder,square"] + Pad[5905 -1181 5905 1181 5118 2000 5718 "2" "2" "onsolder,square"] + ElementLine [-2362 3740 2362 3740 800] + ElementLine [-2362 -3740 2362 -3740 800] + + ) +Layer(1 "component") +( + Line[63405 10000 85000 10000 1000 4000 "clearline"] + Line[85000 10000 85000 50000 1000 4000 "clearline"] +) +Layer(2 "solder") +( + Line[15905 10000 30000 10000 2000 4000 "clearline"] + Line[30000 10000 30000 27500 2000 4000 "clearline"] + Line[30000 27500 85000 27500 2000 4000 "clearline"] + Line[85000 50000 85000 27500 2000 4000 "clearline"] +) +Layer(3 "comp-GND") +( +) +Layer(4 "comp-power") +( +) +Layer(5 "sold-GND") +( +) +Layer(6 "sold-power") +( +) +Layer(7 "signal3") +( +) +Layer(8 "outline") +( +) +Layer(9 "silk") +( +) +Layer(10 "silk") +( +) +NetList() +( + Net("GND" "(unknown)") + ( + Connect("R101-1") + Connect("R102-2") + ) +) Index: tags/2.1.2/doc/user/06_feature/djopt/vianudge.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/user/06_feature/djopt/vianudge.png =================================================================== --- tags/2.1.2/doc/user/06_feature/djopt/vianudge.png (nonexistent) +++ tags/2.1.2/doc/user/06_feature/djopt/vianudge.png (revision 24813) Property changes on: tags/2.1.2/doc/user/06_feature/djopt/vianudge.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/user/06_feature/djopt/vianudge.txt =================================================================== --- tags/2.1.2/doc/user/06_feature/djopt/vianudge.txt (nonexistent) +++ tags/2.1.2/doc/user/06_feature/djopt/vianudge.txt (revision 24813) @@ -0,0 +1,3 @@ +Looks for vias where all traces leave in the same direction. Tries to +move via in that direction to eliminate one of the traces (and thus a +corner). Index: tags/2.1.2/doc/user/06_feature/djopt/viatrim.out.pcb =================================================================== --- tags/2.1.2/doc/user/06_feature/djopt/viatrim.out.pcb (nonexistent) +++ tags/2.1.2/doc/user/06_feature/djopt/viatrim.out.pcb (revision 24813) @@ -0,0 +1,80 @@ +# release: pcb-rnd 1.0.7 + +# To read pcb files, the pcb version (or the git source date) must be >= the file version +FileVersion[20070407] + +PCB["" 140000 67500] + +Grid[2500.0 0 0 1] +Cursor[37500 10000 0.000000] +PolyArea[3100.006200] +Thermal[0.500000] +DRC[1200 900 1000 700 1500 1000] +Flags("nameonpcb,clearnew,snappin") +Groups("1,3,4,c:2,5,6,s:7:8") +Styles["Signal,1000,7874,3150,2000:Power,2000,8661,3937,2000:Fat,8000,13780,4724,2500:Sig-tight,1000,6400,3150,1200"] + +Via[60000 32500 7874 4000 0 3150 "" ""] +Via[92500 32500 7874 4000 0 3150 "" ""] +Via[75000 32500 7874 4000 0 3150 "" ""] + +Element["" "Standard SMT resistor, capacitor etc" "R101" "1206" 17500 32500 -5650 4350 0 100 ""] +( + Pad[5905 -1181 5905 1181 5118 2000 5718 "1" "1" "square"] + Pad[-5905 -1181 -5905 1181 5118 2000 5718 "2" "2" "square"] + ElementLine [-2362 3740 2362 3740 800] + ElementLine [-2362 -3740 2362 -3740 800] + + ) + +Element["" "Standard SMT resistor, capacitor etc" "R102" "1206" 117500 32500 -5650 4350 0 100 ""] +( + Pad[5905 -1181 5905 1181 5118 2000 5718 "1" "1" "square"] + Pad[-5905 -1181 -5905 1181 5118 2000 5718 "2" "2" "square"] + ElementLine [-2362 3740 2362 3740 800] + ElementLine [-2362 -3740 2362 -3740 800] + + ) +Layer(1 "component") +( + Line[23405 32500 60000 32500 1000 4000 "clearline"] + Line[92500 32500 111595 32500 1000 4000 "clearline"] + Line[60000 32500 60000 32500 1000 4000 "clearline"] + Line[60000 32500 75000 32500 1000 4000 "clearline"] +) +Layer(2 "solder") +( + Line[75000 32500 92500 32500 1000 4000 "clearline"] +) +Layer(3 "comp-GND") +( +) +Layer(4 "comp-power") +( +) +Layer(5 "sold-GND") +( +) +Layer(6 "sold-power") +( +) +Layer(7 "signal3") +( +) +Layer(8 "outline") +( +) +Layer(9 "silk") +( +) +Layer(10 "silk") +( +) +NetList() +( + Net("GND" "(unknown)") + ( + Connect("R101-1") + Connect("R102-2") + ) +) Index: tags/2.1.2/doc/user/06_feature/djopt/viatrim.out.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/user/06_feature/djopt/viatrim.out.png =================================================================== --- tags/2.1.2/doc/user/06_feature/djopt/viatrim.out.png (nonexistent) +++ tags/2.1.2/doc/user/06_feature/djopt/viatrim.out.png (revision 24813) Property changes on: tags/2.1.2/doc/user/06_feature/djopt/viatrim.out.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/user/06_feature/djopt/viatrim.pcb =================================================================== --- tags/2.1.2/doc/user/06_feature/djopt/viatrim.pcb (nonexistent) +++ tags/2.1.2/doc/user/06_feature/djopt/viatrim.pcb (revision 24813) @@ -0,0 +1,87 @@ +# release: pcb-rnd 1.0.7 + +# To read pcb files, the pcb version (or the git source date) must be >= the file version +FileVersion[20070407] + +PCB["" 140000 67500] + +Grid[2500.0 0 0 1] +Cursor[37500 10000 0.000000] +PolyArea[3100.006200] +Thermal[0.500000] +DRC[1200 900 1000 700 1500 1000] +Flags("nameonpcb,clearnew,snappin") +Groups("1,3,4,c:2,5,6,s:7:8") +Styles["Signal,1000,7874,3150,2000:Power,2000,8661,3937,2000:Fat,8000,13780,4724,2500:Sig-tight,1000,6400,3150,1200"] + + +Attribute("PCB::grid::unit" "mm") +Via[60000 32500 7874 4000 0 3150 "" ""] +Via[92500 32500 7874 4000 0 3150 "" ""] +Via[75000 32500 7874 4000 0 3150 "" ""] +Via[40000 32500 7874 4000 0 3150 "" ""] + +Element["" "Standard SMT resistor, capacitor etc" "R101" "1206" 17500 32500 -5650 4350 0 100 ""] +( + Pad[5905 -1181 5905 1181 5118 2000 5718 "1" "1" "square"] + Pad[-5905 -1181 -5905 1181 5118 2000 5718 "2" "2" "square"] + ElementLine [-2362 3740 2362 3740 800] + ElementLine [-2362 -3740 2362 -3740 800] + + ) + +Element["" "Standard SMT resistor, capacitor etc" "R102" "1206" 117500 32500 -5650 4350 0 100 ""] +( + Pad[5905 -1181 5905 1181 5118 2000 5718 "1" "1" "square"] + Pad[-5905 -1181 -5905 1181 5118 2000 5718 "2" "2" "square"] + ElementLine [-2362 3740 2362 3740 800] + ElementLine [-2362 -3740 2362 -3740 800] + + ) +Layer(1 "component") +( + Line[23405 32500 40000 32500 1000 4000 "clearline"] + Line[92500 32500 111595 32500 1000 4000 "clearline"] + Line[111595 33681 111595 32500 1000 4000 "clearline"] + Line[111595 32500 111595 31319 1000 4000 "clearline"] + Line[23405 33681 23405 32500 1000 4000 "clearline"] + Line[23405 32500 23405 31319 1000 4000 "clearline"] + Line[40000 32500 60000 32500 1000 4000 "clearline"] +) +Layer(2 "solder") +( + Line[60000 32500 75000 32500 1000 4000 "clearline"] + Line[75000 32500 92500 32500 1000 4000 "clearline"] +) +Layer(3 "comp-GND") +( +) +Layer(4 "comp-power") +( +) +Layer(5 "sold-GND") +( +) +Layer(6 "sold-power") +( +) +Layer(7 "signal3") +( +) +Layer(8 "outline") +( +) +Layer(9 "silk") +( +) +Layer(10 "silk") +( +) +NetList() +( + Net("GND" "(unknown)") + ( + Connect("R101-1") + Connect("R102-2") + ) +) Index: tags/2.1.2/doc/user/06_feature/djopt/viatrim.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/user/06_feature/djopt/viatrim.png =================================================================== --- tags/2.1.2/doc/user/06_feature/djopt/viatrim.png (nonexistent) +++ tags/2.1.2/doc/user/06_feature/djopt/viatrim.png (revision 24813) Property changes on: tags/2.1.2/doc/user/06_feature/djopt/viatrim.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/user/06_feature/djopt/viatrim.txt =================================================================== --- tags/2.1.2/doc/user/06_feature/djopt/viatrim.txt (nonexistent) +++ tags/2.1.2/doc/user/06_feature/djopt/viatrim.txt (revision 24813) @@ -0,0 +1,2 @@ +Looks for traces that go from via to via, where moving that trace to a +different layer eliminates one or both vias. Index: tags/2.1.2/doc/user/06_feature/index.html =================================================================== --- tags/2.1.2/doc/user/06_feature/index.html (nonexistent) +++ tags/2.1.2/doc/user/06_feature/index.html (revision 24813) @@ -0,0 +1,60 @@ + + + + pcb-rnd user manual + + + + + +

Feature Plugins

+These plugins have a wide variety of origins and offer a likewise wide variety +of actions to the pcb-rnd user. + + Index: tags/2.1.2/doc/user/06_feature/polystitch/index.html =================================================================== --- tags/2.1.2/doc/user/06_feature/polystitch/index.html (nonexistent) +++ tags/2.1.2/doc/user/06_feature/polystitch/index.html (revision 24813) @@ -0,0 +1,25 @@ + + + + pcb-rnd user manual + + + + +

Polystitch plugin

+

+This plugin is intended as a workaround for a bug in pstoedit. Pstodeit +generates polygons instead of polygon holes. This plugin creates a polystitch +action that can fix up that case. The polystitch action shall be ran while +the crosshair is over the inner polygon of two overlapping polygons. The action +takes the inner polygon and converts it into a hole within the outer polygon +then removes the inner polygon. +

+The plugin assumes that there are only two polygons under the crosshair and +the inner polygon is fully within the outer polygon. +

+The thindraw or wireframe view mode may be of help in searching such +overlapping polygons. + + + Index: tags/2.1.2/doc/user/06_feature/query/tutor_cli.html =================================================================== --- tags/2.1.2/doc/user/06_feature/query/tutor_cli.html (nonexistent) +++ tags/2.1.2/doc/user/06_feature/query/tutor_cli.html (revision 24813) @@ -0,0 +1,168 @@ + + + +

advanced search, command line tutorial: query language

+ +

scope

+ +pcb-rnd from version 1.1.3 features a flexible advanced search that helps +the user selecting/unselecting objects that match a given logical expression. +The core of the feature is the pcb-rnd query language. The same language +is used in the programmable DRC (see also: +a more formal description of the language). +

+The current document is a walk through of the practical aspects of the +language. It starts with the simplest examples while working towards more +complex cases. +

+A limited version of the functionality is accessible through a GUI +wizard when using the GTK HID. A separate +tutorial is dealing with that feature. + +

Actions

+The query(act, expr) action creates the list called "@", which contains all +objects of the design. Then it iterates over this list (if needed) and +evaluates the query expression on each object. For each evaluation "act" +is performed; "act" is one of: +
    +
  • select - add the matching object to the selections if expr evaluated to true +
  • unselect - remove the matching object from the selections if expr evaluated to true +
  • eval - print the result of the expression to stdout +
  • dump - this inhibits evaluating; it compiles the expression and dumps the parse tree (useful for debugging) +
+

+The symbol @ in the query represents the iterator, or in other words, +the current object we are checking. The engine iterates over all +copper objects, silk objects, pins, holes, layers and nets. A simple query +that selects all objects looks like this: +

+query(select, '@')
+
+The actual query expression was a single @ in this case. This made +the iteration happen, got the expression evaluated one each object. The +result of each evaluation was the given object. Since these objects +were all existing, valid objects, they were taken as logical value TRUE, +thus for each the add-to-selection was performed. +

+Note: it's usually a good idea to write the expression in single quotes, because +it may contain commas, double quotes and parenthesis that pcb-rnd's action parser may +take as action syntax. +

+The same expression can ran with eval would print the result of each +evaluation: +

+query(eval, '@')
+
+This is visible on the terminal pcb-rnd was started from - on X, it's a good +idea to start a terminal and run pcb-rnd from that instead from a menu or +icon. The rest of this tutorial will use the eval query because it's easier +to include the result of an eval than of a selection. Most examples will +specify the query expression only, without quotes - the reader should +add the query(eval, ' ') part. + +

iteration vs. evaluate once

+If an expression does not reference the @ object, no iteration is performed +and the expression is ran only once: +
+query(eval, '1')
+
+This will calculate the value of 1 and prints it to the standard output. Since +there's no iteration, this can not result in changes in selection. However, +it makes it easy to demonstrate some basic concepts of the query language. +

+Note: if @ is present multiple times in the expression, it's still only +one loop over all objects. When evaluating the expression for a given object, +all instances of @ are substituted with the same object in that iteration. + + +

grammar: arithmetics and logics

+For example the integer and floating point numbers and the usual +arithmetic and logical operators work as expected: + + +
expression result explanation +
42 42 the integer value 42 +
3.14 3.14 the floating point value 3.14 +
10 mil 254000 a number with a unit suffix is converted to pcb-rnd's internal coordinate unit (nanometers) +
1+2 3 sum of 1 and 2 +
2*4 8 multiplication +
47/4 11 integer division (because both operands were integers) +
47/4.0 11.75 floating point division (because at least one of the operands was a float) +
(1+2)*5 15 parenthesis works as usual +
1 && 0 0 logical AND - the result is 1 if both operands were TRUE, 0 else +
1 || 0 1 logical OR - the result is 1 if either operand was TRUE, 0 else +
!2 0 logical NOT - 2 is non-zero, so it is TRUE, negate this to get the result (FALSE, which is 0) +
4 > 2 1 because four is greater than two; all the usual relational operators work: == is equal, != is not-equal, <, <=, > and >=. +
+ +

grammar: object properties

+Object have named properties, e.g. the thickness of a line (or arc, or +trace in general) is called ".thickness", so the thickness of +the current object is: +
+	@.thickness
+
+

+Next, we can already select all traces thicker than 10 mil: +

+	query(select, '@.thickness > 10 mil')
+
+

+Because logical expressions are available, it's easy to select all medium-thick +lines: +

+	(@.thickness >= 10 mil) && (@.thickness <= 30 mil)
+
+

+or any trace that's too thin or too thick: +

+	(@.thickness < 10 mil) || (@.thickness > 30 mil)
+
+

+or traces that don't match our preferred 8, 10 and 15 mil thickness values: +

+	(@.thickness != 8 mil) && (@.thickness != 10 mil) && (@.thickness != 15 mil)
+
+ +

grammar: invalid value

+But how comes an expression like '@.thickness > 10 mil' works while +@ iterates over non-trace objects, like layers, nets or subcircuits that +clearly have no thickness? +

+The answer is the invalid value, which is neither true nor false. If +a property does not exist in a given object, the result is the invalid value +or invalid for short. The invalid is treated specially: +

    +
  • in arithmetic operations it propagates: if either operand is invalid, the result is invalid, e.g. 1+invalid = invalid; this affects +, -, *, / and all the relational operators +
  • in binary logic operations (&& and ||), it is ignored: it is assumed to be true in a && and false in a || so the outcome depends on the other operand +
  • in logical NOT (!), TODO +
+When @ refers to a non-trace object, @.thickness is invalid and +'@.thickness > 10 mil' is evaluated t invalid. If the result is not TRUE, +the requested action is not performed. +

+The invalid value is generated only when the expression is valid but the +actual object doesn't have the feature needed. If the expression is wrong, +an error is generated and the expression stops evaluating immediately. + +

grammar: more properties

+Some properties are a single numeric value, like thickness, or the +.name of a layer (which is a string) but others are objects. For +example the .layer property of a line or arc refers to the layer +object the given line or arc is drawn on. These in turn can be combined, +and the "name of the layer the current object is on": +
+	@.layer.name
+
+

+Referencing non-existing properties yields an error, e.g. @.thickness.layer +is an error - in contrast with @.layer, which may evaluate to the +invalid value (e.g. for vias or nets, because they don't have layers). +The difference is that thickness can not have a layer ever (thus is an error) +while @.layer is either applicable or not, but potentially could work, this +when it doesn't, it's only an invalid value. +

+Further useful property combinations: +TODO +

+There is a full list of all properties. Index: tags/2.1.2/doc/user/06_feature/scripting/index.html =================================================================== --- tags/2.1.2/doc/user/06_feature/scripting/index.html (nonexistent) +++ tags/2.1.2/doc/user/06_feature/scripting/index.html (revision 24813) @@ -0,0 +1,23 @@ + + + + pcb-rnd user manual + + + +

pcb-rnd fungw scripting - TOC

+ +

Installation, configuration

+ + + +

High level docs

+ + + + Index: tags/2.1.2/doc/user/06_feature/scripting/install.txt =================================================================== --- tags/2.1.2/doc/user/06_feature/scripting/install.txt (nonexistent) +++ tags/2.1.2/doc/user/06_feature/scripting/install.txt (revision 24813) @@ -0,0 +1,14 @@ +Requirements: + 1. download and install genht - svn://repo.hu/genht/trunk + Some Linux distributions already have this packaged, please check your + repositries (and install the development version) + NOTE: version 1.0.1 is too old, please get a newer one (e.g. svn version) + 2. download and install fungw - svn://repo.hu/fungw/trunk + 3. at the moment fungw must be installed as root, into /usr/local/ or /usr (TODO) + during configuration, make sure all relevant scripting languages are found + 4. (re)configure and (re)compile pcb-rnd so that it uses the system-installed + version of fungw instead of the local, no-script version; make sure the + "script" plugin is compiled (as builtin or plugin) + 5. later on if a new scripting language is required, reconfigure, + recompile and reinstall fungw - no pcb-rnd recompilation is needed as + long as the system-installed fungw version is not upgraded Index: tags/2.1.2/doc/user/06_feature/scripting/intro.html =================================================================== --- tags/2.1.2/doc/user/06_feature/scripting/intro.html (nonexistent) +++ tags/2.1.2/doc/user/06_feature/scripting/intro.html (revision 24813) @@ -0,0 +1,153 @@ + + + + pcb-rnd user manual + + + + +

Scripting - User Intro

+This document is an introduction to fungw for pcb-rnd users. It focuses on +scripting pcb-rnd and doesn't discuss fungw deeper than the minimum necessary. +Fungw is more generic than shown here. + +

1.1. Stored scripts

+

+Stored scripts are typically larger piece of works that register actions, +may create menus, GUI dialog boxes. Their role is to introduce new +functionality to pcb-rnd - functionality written and shared by users, +using their favorite script language. +

+Loading a script using the CLI: run action +

+	LoadScript(id, filename, language)
+
+

+where id is an arbitrary text ID. The ID is used for referencing the script +once it is loaded. The filename should be a full path (CWD is pcb-rnd's +CWD). Language must be one of the languages configured in fungw. +

+Once the script is loaded, it is accessible by calling the actions it +registered using the standard fgw_func_reg() mechanism. +

+Scripts can be unloaded using the action +

+	UnloadScript(id)
+
+

+These operations can also be done using the script browser dialog box, which +is invoked from the menu system or by running action +

+	BrowseScripts()
+
+ +

1.2. Oneliners

+

+Note: examples in this section assume pcb-rnd is configured and compiled +with system installed fungw, and libmawk is also installed +and the libmawk binding is compiled in fungw. +

+pcb-rnd also offers script one-liners. A one-liner is a short script +intended to do one thing at the moment of execution. It is typically not +saved in a file and is not recalled later. One-liners are invoked by +the Oneliner action: +

+	OneLiner(awk, 'message("hello")')
+
+

+Alternatively the language-specific shorthand action can be used; the +following example is equivalent to the above example: +

+	awk('message("hello")')
+
+

+A third approach, most convenient for experimenting, is switching the +command line interpreter to the given script lagnuage temporarily. For this +the shorthand action (e.g. "awk", "python", "perl") should be exected without +arguments. The promp of the cli changes to reflect the language that will +interpret all the following command lines entered. To leave the script mode, +type "/exit". +

+For example: +

    +
  • open the command line (pressing ':' with the default menu config) +
  • enter awk and press enter - this will switch to awk mode +
  • enter for(y=1; y < 10; y += 3) { createtext("#1", 0, "1 mm", y " mm", 0, 100, "foo:" y) } +
  • either enter more awk one-liners or leave the awk mode by typing /exit +
+

+The one-liner mode can be used to get a better command interpreter. After +all, any pcb-rnd action is accessible from any scripting language. For +example the user may choose to switch to awk mode and issue normal +pcb-rnd actions using the awk syntax. The default mode can even be +configured through the conf system, by setting rc/cli_backend to the +language name. However, the CPU and memory footprint of executing a full +script interpreter for each command entered should be noted. +

+Limitations: each command line is a separate script context, there are no +script states (e.g. variables) preserved between lines entered. Actions +defined in one-liners are also discarded after the one-liner finished. For +such use cases, stored script shall be written. + + +

Scripting - Developer Intro

+

+ +

2.1. The big picture

+

+The main interface between pcb-rnd internals and the outside world +(e.g. user interface, scripts) is called actions. An action is typically +a function with a few arguments that executes a smallish task. The +actions implemented by pcb-rnd are all functions written in C; some of +the actions are part of core pcb-rnd, others are implemented in plugins. +

+GUI operations, menu items, clicking on buttons all call these +actions. The advantage of this system is that the actions are accessible +in an user-interface-independent way: the same operations can be done +with and without GUI, initiated by an user with a mouse or by a script. +

+Thus the two main aspects of pcb-rnd scripting are: +

    +
  • defining new actions in script; actions that then can be called from + the user interface or from other scripts +
  • calling pcb-rnd actions from within the script to execute the actual + task +
+ +

2.2. Defining actions

+

+With fungw, every action is just a native function - the syntax varies +from scripting language to scripting language (see + the rosetta hello world example). The +arguments of the function are the arguments of the action. The return value +of the function is the return value of the action. +

+For the arguments, new actions should try to follow the conventions that +can be found in already existing + core actions +for similar purpose. +

+The return value depends on the purpose of the action. If the +action is used to calculate something, typically not changing any global +state (e.g. the board), it should return the value calculated, in whatever +scalar native data type the scripting language supports. If the action +is not called to get a value but to perform some changes, the return +value should be an integer: 0 means success, anything else means error. + +

2.3. Calling actions

+

+The script may call any action available at a given time, independently +of whether the action is defined in pcb-rnd core, in plugins or in other +scripts. In most scripting languages the action call looks like a simple +function call: function arguments are the action's arguments, the return +value of the function is the return value generated by the action. The calls +are all single threaded, blocking calls. The script may use any scalar native +data type for action arguments without conversion, fungw will take care of +the conversions automatically. + +

2.4. Action names

+

+All action names are registered in lowercase version. The script shall +register lower case function names and action (function) calls should be +spelled lowercase too. + Index: tags/2.1.2/doc/user/06_feature/scripting/rosetta/10_hello/ID.desc =================================================================== --- tags/2.1.2/doc/user/06_feature/scripting/rosetta/10_hello/ID.desc (nonexistent) +++ tags/2.1.2/doc/user/06_feature/scripting/rosetta/10_hello/ID.desc (revision 24813) @@ -0,0 +1,2 @@ +Create a new action hello() that prints "Hello world!" in the message log. + Index: tags/2.1.2/doc/user/06_feature/scripting/rosetta/10_hello/ID.name =================================================================== --- tags/2.1.2/doc/user/06_feature/scripting/rosetta/10_hello/ID.name (nonexistent) +++ tags/2.1.2/doc/user/06_feature/scripting/rosetta/10_hello/ID.name (revision 24813) @@ -0,0 +1 @@ +hello world (text, log) Index: tags/2.1.2/doc/user/06_feature/scripting/rosetta/10_hello/ex.awk =================================================================== --- tags/2.1.2/doc/user/06_feature/scripting/rosetta/10_hello/ex.awk (nonexistent) +++ tags/2.1.2/doc/user/06_feature/scripting/rosetta/10_hello/ex.awk (revision 24813) @@ -0,0 +1,12 @@ +# An action without arguments that prints hello world in the log window +# Returns 0 for success. +function hello() +{ + message("Hello world!\n"); + return 0 +} + +# Register the action - action name matches the function name +BEGIN { + fgw_func_reg("hello") +} Index: tags/2.1.2/doc/user/06_feature/scripting/rosetta/10_hello/ex.fl =================================================================== --- tags/2.1.2/doc/user/06_feature/scripting/rosetta/10_hello/ex.fl (nonexistent) +++ tags/2.1.2/doc/user/06_feature/scripting/rosetta/10_hello/ex.fl (revision 24813) @@ -0,0 +1,15 @@ +;; An action without arguments that prints hello world in the log window +;; Returns 0 for success. +(define hello + (lambda () + (message "Hello world!\n") + 0 + ) +) + +;; Register the action - action name matches the function name +(define main + (lambda (args) + (fgw_func_reg "hello") + ) +) Index: tags/2.1.2/doc/user/06_feature/scripting/rosetta/10_hello/ex.html =================================================================== --- tags/2.1.2/doc/user/06_feature/scripting/rosetta/10_hello/ex.html (nonexistent) +++ tags/2.1.2/doc/user/06_feature/scripting/rosetta/10_hello/ex.html (revision 24813) @@ -0,0 +1,7 @@ +Create a function hello that will be registered as an action. +The name of the action and the function is always the same. Action names +shall be lowercase. +

+When the action is called, use message to append a log message. +

+In the "main" section of the script, register the action using fgw_func_reg(). Index: tags/2.1.2/doc/user/06_feature/scripting/rosetta/10_hello/ex.js =================================================================== --- tags/2.1.2/doc/user/06_feature/scripting/rosetta/10_hello/ex.js (nonexistent) +++ tags/2.1.2/doc/user/06_feature/scripting/rosetta/10_hello/ex.js (revision 24813) @@ -0,0 +1,10 @@ +// An action without arguments that prints hello world in the log window +// Returns 0 for success. +function hello() +{ + message("Hello world!\n"); + return 0 +} + +// Register the action - action name matches the function name +fgw_func_reg("hello") Index: tags/2.1.2/doc/user/06_feature/scripting/rosetta/10_hello/ex.lua =================================================================== --- tags/2.1.2/doc/user/06_feature/scripting/rosetta/10_hello/ex.lua (nonexistent) +++ tags/2.1.2/doc/user/06_feature/scripting/rosetta/10_hello/ex.lua (revision 24813) @@ -0,0 +1,9 @@ +-- An action without arguments that prints hello world in the log window +-- Returns 0 for success. +function hello() + message("Hello world!") + return 0 +end + +-- register hello() action +fgw_func_reg("hello") Index: tags/2.1.2/doc/user/06_feature/scripting/rosetta/10_hello/ex.pl =================================================================== --- tags/2.1.2/doc/user/06_feature/scripting/rosetta/10_hello/ex.pl (nonexistent) +++ tags/2.1.2/doc/user/06_feature/scripting/rosetta/10_hello/ex.pl (revision 24813) @@ -0,0 +1,11 @@ +# An action without arguments that prints hello world in the log window +# Returns 0 for success. +sub hello { + message("Hello world!\n"); + return 0; +} + +# Register the action - action name matches the function name +fgw_func_reg("hello"); + + Index: tags/2.1.2/doc/user/06_feature/scripting/rosetta/10_hello/ex.py =================================================================== --- tags/2.1.2/doc/user/06_feature/scripting/rosetta/10_hello/ex.py (nonexistent) +++ tags/2.1.2/doc/user/06_feature/scripting/rosetta/10_hello/ex.py (revision 24813) @@ -0,0 +1,8 @@ +# An action without arguments that prints hello world in the log window +# Returns 0 for success. +def hello(): + message("Hello world!"); + return 0 + +# register hello() action +fgw_func_reg("hello") Index: tags/2.1.2/doc/user/06_feature/scripting/rosetta/10_hello/ex.rb =================================================================== --- tags/2.1.2/doc/user/06_feature/scripting/rosetta/10_hello/ex.rb (nonexistent) +++ tags/2.1.2/doc/user/06_feature/scripting/rosetta/10_hello/ex.rb (revision 24813) @@ -0,0 +1,9 @@ +# An action without arguments that prints hello world in the log window +# Returns 0 for success. +def hello() + message("Hello world!\n") + return 0 +end + +# Register the action - action name matches the function name +fgw_func_reg("hello") Index: tags/2.1.2/doc/user/06_feature/scripting/rosetta/10_hello/ex.sh =================================================================== --- tags/2.1.2/doc/user/06_feature/scripting/rosetta/10_hello/ex.sh (nonexistent) +++ tags/2.1.2/doc/user/06_feature/scripting/rosetta/10_hello/ex.sh (revision 24813) @@ -0,0 +1,13 @@ +#!/bin/sh + +# An action without arguments that prints hello world in the log window +# Returns 0 for success. +hello() +{ + fgw message "Hello world!" + return 0 +} + +# Register the action - action name matches the function name +fgw_func_reg "hello" + Index: tags/2.1.2/doc/user/06_feature/scripting/rosetta/10_hello/ex.stt =================================================================== --- tags/2.1.2/doc/user/06_feature/scripting/rosetta/10_hello/ex.stt (nonexistent) +++ tags/2.1.2/doc/user/06_feature/scripting/rosetta/10_hello/ex.stt (revision 24813) @@ -0,0 +1,10 @@ +;; An action without arguments that prints hello world in the log window +;; Returns 0 for success. +(defun hello () + (message "Hello world!\n") + 0 +) + +;; Register the action - action name matches the function name +(fgw_func_reg "hello") + Index: tags/2.1.2/doc/user/06_feature/scripting/rosetta/10_hello/ex.tcl =================================================================== --- tags/2.1.2/doc/user/06_feature/scripting/rosetta/10_hello/ex.tcl (nonexistent) +++ tags/2.1.2/doc/user/06_feature/scripting/rosetta/10_hello/ex.tcl (revision 24813) @@ -0,0 +1,9 @@ +# An action without arguments that prints hello world in the log window +# Returns 0 for success. +proc hello {} { + message "Hello world!" + return 0 +} + +# register hello() action +fgw_func_reg "hello" Index: tags/2.1.2/doc/user/06_feature/scripting/rosetta/10_hello/index.html =================================================================== --- tags/2.1.2/doc/user/06_feature/scripting/rosetta/10_hello/index.html (nonexistent) +++ tags/2.1.2/doc/user/06_feature/scripting/rosetta/10_hello/index.html (revision 24813) @@ -0,0 +1,41 @@ + + + + pcb-rnd rosetta hello world (text, log) + + + + +<-- back to the index of Rosetta examples +

hello world (text, log)

+Create a new action hello() that prints "Hello world!" in the message log. +

Example implementations

+awk + | +fl + | +js + | +lua + | +pl + | +py + | +rb + | +sh + | +stt + | +tcl +

Explanation, step by step

+Create a function +hello + that will be registered as an action. The name of the action and the function is always the same. Action names shall be lowercase. +

When the action is called, use +message + to append a log message. +

In the "main" section of the script, register the action using fgw_func_reg(). + + Index: tags/2.1.2/doc/user/06_feature/scripting/rosetta/11_hello_menu/ID.desc =================================================================== --- tags/2.1.2/doc/user/06_feature/scripting/rosetta/11_hello_menu/ID.desc (nonexistent) +++ tags/2.1.2/doc/user/06_feature/scripting/rosetta/11_hello_menu/ID.desc (revision 24813) @@ -0,0 +1,2 @@ +Create a new menu + action hello() that prints "Hello world!" in the message log. + Index: tags/2.1.2/doc/user/06_feature/scripting/rosetta/11_hello_menu/ID.name =================================================================== --- tags/2.1.2/doc/user/06_feature/scripting/rosetta/11_hello_menu/ID.name (nonexistent) +++ tags/2.1.2/doc/user/06_feature/scripting/rosetta/11_hello_menu/ID.name (revision 24813) @@ -0,0 +1 @@ +hello world (menu, log) Index: tags/2.1.2/doc/user/06_feature/scripting/rosetta/11_hello_menu/ex.awk =================================================================== --- tags/2.1.2/doc/user/06_feature/scripting/rosetta/11_hello_menu/ex.awk (nonexistent) +++ tags/2.1.2/doc/user/06_feature/scripting/rosetta/11_hello_menu/ex.awk (revision 24813) @@ -0,0 +1,10 @@ +function hello() +{ + message("hello!\n") +} + +BEGIN { + fgw_func_reg("hello") + cookie = scriptcookie() + createmenu("/main_menu/Plugins/script/hello", "hello()", "Prints hello! in the log", cookie) +} Index: tags/2.1.2/doc/user/06_feature/scripting/rosetta/11_hello_menu/ex.html =================================================================== --- tags/2.1.2/doc/user/06_feature/scripting/rosetta/11_hello_menu/ex.html (nonexistent) +++ tags/2.1.2/doc/user/06_feature/scripting/rosetta/11_hello_menu/ex.html (revision 24813) @@ -0,0 +1,14 @@ +Create a function hello that will be registered as an action. +The name of the action and the function is always the same. Action names +shall be lowercase. +

+When the action is called, use message to append a log message. +

+In the "main" section of the script, register the action using fgw_func_reg(). +Then save the script cookie and register a new submenu using it. Registering +the submenu with this cookie makes pcb-rnd auto-remove the menu when the script +is unloaded. +

+The menu path starts with /main_menu, because it is also possible to +insert menu entries in popups. + Index: tags/2.1.2/doc/user/06_feature/scripting/rosetta/11_hello_menu/ex.lua =================================================================== --- tags/2.1.2/doc/user/06_feature/scripting/rosetta/11_hello_menu/ex.lua (nonexistent) +++ tags/2.1.2/doc/user/06_feature/scripting/rosetta/11_hello_menu/ex.lua (revision 24813) @@ -0,0 +1,8 @@ +function hello() + message("Hello world!") + return 0 +end + +fgw_func_reg("hello") +cookie = scriptcookie() +createmenu("/main_menu/Plugins/script/hello", "hello()", "Prints hello! in the log", cookie) Index: tags/2.1.2/doc/user/06_feature/scripting/rosetta/11_hello_menu/ex.py =================================================================== --- tags/2.1.2/doc/user/06_feature/scripting/rosetta/11_hello_menu/ex.py (nonexistent) +++ tags/2.1.2/doc/user/06_feature/scripting/rosetta/11_hello_menu/ex.py (revision 24813) @@ -0,0 +1,7 @@ +def hello(): + message("Hello world!"); + return 0 + +fgw_func_reg("hello") +cookie = scriptcookie() +createmenu("/main_menu/Plugins/script/hello", "hello()", "Prints hello! in the log", cookie) Index: tags/2.1.2/doc/user/06_feature/scripting/rosetta/11_hello_menu/ex.tcl =================================================================== --- tags/2.1.2/doc/user/06_feature/scripting/rosetta/11_hello_menu/ex.tcl (nonexistent) +++ tags/2.1.2/doc/user/06_feature/scripting/rosetta/11_hello_menu/ex.tcl (revision 24813) @@ -0,0 +1,8 @@ +proc hello {} { + message "Hello world!" + return 0 +} + +fgw_func_reg "hello" +set cookie [scriptcookie] +createmenu "/main_menu/Plugins/script/hello" "hello()" "Prints hello! in the log" $cookie Index: tags/2.1.2/doc/user/06_feature/scripting/rosetta/11_hello_menu/index.html =================================================================== --- tags/2.1.2/doc/user/06_feature/scripting/rosetta/11_hello_menu/index.html (nonexistent) +++ tags/2.1.2/doc/user/06_feature/scripting/rosetta/11_hello_menu/index.html (revision 24813) @@ -0,0 +1,30 @@ + + + + pcb-rnd rosetta hello world (menu, log) + + + + +<-- back to the index of Rosetta examples +

hello world (menu, log)

+Create a new menu + action hello() that prints "Hello world!" in the message log. +

Example implementations

+awk + | +lua + | +py + | +tcl +

Explanation, step by step

+Create a function +hello + that will be registered as an action. The name of the action and the function is always the same. Action names shall be lowercase. +

When the action is called, use +message + to append a log message. +

In the "main" section of the script, register the action using fgw_func_reg(). Then save the script cookie and register a new submenu using it. Registering the submenu with this cookie makes pcb-rnd auto-remove the menu when the script is unloaded. +

The menu path starts with /main_menu, because it is also possible to insert menu entries in popups. + + Index: tags/2.1.2/doc/user/06_feature/scripting/rosetta/12_hello_dad/ID.desc =================================================================== --- tags/2.1.2/doc/user/06_feature/scripting/rosetta/12_hello_dad/ID.desc (nonexistent) +++ tags/2.1.2/doc/user/06_feature/scripting/rosetta/12_hello_dad/ID.desc (revision 24813) @@ -0,0 +1 @@ +Create a new action hello() that prints "Hello world!" in a modal dialog box using DAD. Index: tags/2.1.2/doc/user/06_feature/scripting/rosetta/12_hello_dad/ID.name =================================================================== --- tags/2.1.2/doc/user/06_feature/scripting/rosetta/12_hello_dad/ID.name (nonexistent) +++ tags/2.1.2/doc/user/06_feature/scripting/rosetta/12_hello_dad/ID.name (revision 24813) @@ -0,0 +1 @@ +hello world (GUI) Index: tags/2.1.2/doc/user/06_feature/scripting/rosetta/12_hello_dad/ex.awk =================================================================== --- tags/2.1.2/doc/user/06_feature/scripting/rosetta/12_hello_dad/ex.awk (nonexistent) +++ tags/2.1.2/doc/user/06_feature/scripting/rosetta/12_hello_dad/ex.awk (revision 24813) @@ -0,0 +1,12 @@ +function hello() +{ + dad("heldi", "new") + dad("heldi", "label", "Hello world!") + dad("heldi", "button_closes", "close", 0) + dad("heldi", "run_modal", "hello-world", "Hello world dialog") +} + +BEGIN { + fgw_func_reg("hello") +} + Index: tags/2.1.2/doc/user/06_feature/scripting/rosetta/12_hello_dad/ex.html =================================================================== --- tags/2.1.2/doc/user/06_feature/scripting/rosetta/12_hello_dad/ex.html (nonexistent) +++ tags/2.1.2/doc/user/06_feature/scripting/rosetta/12_hello_dad/ex.html (revision 24813) @@ -0,0 +1,15 @@ +Create a function hello that will be registered as an action. +

+When the action is called, build a dad dialog called "heldi", with a single +label containing "Hello world!" and a close button that makes the dialog +return 0 when clicked. When the dialog is ran in modal mode, +it will be open and block other pcb-rnd windows until the user closes it. +

+Note: the window title (4th parameter of the 3rd dad() call) is displayed +because the root node of the DAD is not a box. For a more complex version, +see 13_hello_dad. +

+In the "main" section of the script, register the action using fgw_func_reg(). +

+More details on DAD: +DAD developer's doc Index: tags/2.1.2/doc/user/06_feature/scripting/rosetta/12_hello_dad/ex.lua =================================================================== --- tags/2.1.2/doc/user/06_feature/scripting/rosetta/12_hello_dad/ex.lua (nonexistent) +++ tags/2.1.2/doc/user/06_feature/scripting/rosetta/12_hello_dad/ex.lua (revision 24813) @@ -0,0 +1,9 @@ +function hello() + dad("heldi", "new") + dad("heldi", "label", "Hello world!") + dad("heldi", "button_closes", "close", 0) + dad("heldi", "run_modal", "hello-world", "Hello world dialog") + return 0 +end + +fgw_func_reg("hello") Index: tags/2.1.2/doc/user/06_feature/scripting/rosetta/12_hello_dad/ex.pl =================================================================== --- tags/2.1.2/doc/user/06_feature/scripting/rosetta/12_hello_dad/ex.pl (nonexistent) +++ tags/2.1.2/doc/user/06_feature/scripting/rosetta/12_hello_dad/ex.pl (revision 24813) @@ -0,0 +1,9 @@ +sub hello +{ + dad('heldi', 'new'); + dad('heldi', 'label', 'Hello world!'); + dad('heldi', 'button_closes', "close", 0); + dad('heldi', 'run_modal', 'hello-world', 'Hello world dialog'); +} + +fgw_func_reg('hello'); Index: tags/2.1.2/doc/user/06_feature/scripting/rosetta/12_hello_dad/ex.py =================================================================== --- tags/2.1.2/doc/user/06_feature/scripting/rosetta/12_hello_dad/ex.py (nonexistent) +++ tags/2.1.2/doc/user/06_feature/scripting/rosetta/12_hello_dad/ex.py (revision 24813) @@ -0,0 +1,8 @@ +def hello(): + dad("heldi", "new") + dad("heldi", "label", "Hello world!") + dad("heldi", "button_closes", "close", 0) + dad("heldi", "run_modal", "hello-world", "Hello world dialog") + return 0 + +fgw_func_reg("hello") Index: tags/2.1.2/doc/user/06_feature/scripting/rosetta/12_hello_dad/ex.tcl =================================================================== --- tags/2.1.2/doc/user/06_feature/scripting/rosetta/12_hello_dad/ex.tcl (nonexistent) +++ tags/2.1.2/doc/user/06_feature/scripting/rosetta/12_hello_dad/ex.tcl (revision 24813) @@ -0,0 +1,9 @@ +proc hello {} { + dad "heldi" "new" + dad "heldi" "label" "Hello world!" + dad "heldi" "button_closes" "close" 0 + dad "heldi" "run_modal" "hello-world" "Hello world dialog" + return 0 +} + +fgw_func_reg "hello" Index: tags/2.1.2/doc/user/06_feature/scripting/rosetta/12_hello_dad/index.html =================================================================== --- tags/2.1.2/doc/user/06_feature/scripting/rosetta/12_hello_dad/index.html (nonexistent) +++ tags/2.1.2/doc/user/06_feature/scripting/rosetta/12_hello_dad/index.html (revision 24813) @@ -0,0 +1,33 @@ + + + + pcb-rnd rosetta hello world (GUI) + + + + +<-- back to the index of Rosetta examples +

hello world (GUI)

+Create a new action hello() that prints "Hello world!" in a modal dialog box using DAD. +

Example implementations

+awk + | +lua + | +pl + | +py + | +tcl +

Explanation, step by step

+Create a function +hello + that will be registered as an action. +

When the action is called, build a dad dialog called "heldi", with a single label containing "Hello world!" and a close button that makes the dialog return 0 when clicked. When the dialog is ran in modal mode, it will be open and block other pcb-rnd windows until the user closes it. +

Note: the window title (4th parameter of the 3rd dad() call) is displayed because the root node of the DAD is not a box. For a more complex version, see 13_hello_dad. +

In the "main" section of the script, register the action using fgw_func_reg(). +

More details on DAD: +DAD developer's doc + + + Index: tags/2.1.2/doc/user/06_feature/scripting/rosetta/13_hello_dad/ID.desc =================================================================== --- tags/2.1.2/doc/user/06_feature/scripting/rosetta/13_hello_dad/ID.desc (nonexistent) +++ tags/2.1.2/doc/user/06_feature/scripting/rosetta/13_hello_dad/ID.desc (revision 24813) @@ -0,0 +1 @@ +Create a new action hello() that prints "Hello world!" in vertical layout in a dialog box. Index: tags/2.1.2/doc/user/06_feature/scripting/rosetta/13_hello_dad/ID.name =================================================================== --- tags/2.1.2/doc/user/06_feature/scripting/rosetta/13_hello_dad/ID.name (nonexistent) +++ tags/2.1.2/doc/user/06_feature/scripting/rosetta/13_hello_dad/ID.name (revision 24813) @@ -0,0 +1 @@ +hello world (GUI, with vbox) Index: tags/2.1.2/doc/user/06_feature/scripting/rosetta/13_hello_dad/ex.awk =================================================================== --- tags/2.1.2/doc/user/06_feature/scripting/rosetta/13_hello_dad/ex.awk (nonexistent) +++ tags/2.1.2/doc/user/06_feature/scripting/rosetta/13_hello_dad/ex.awk (revision 24813) @@ -0,0 +1,15 @@ +function hello() +{ + dad("heldi", "new") + dad("heldi", "begin_vbox") + dad("heldi", "label", "Hello") + dad("heldi", "label", "world!") + dad("heldi", "button_closes", "cancel", -1, "ok", 0) + dad("heldi", "end") + dad("heldi", "run_modal", "hello-world", "") +} + +BEGIN { + fgw_func_reg("hello") +} + Index: tags/2.1.2/doc/user/06_feature/scripting/rosetta/13_hello_dad/ex.html =================================================================== --- tags/2.1.2/doc/user/06_feature/scripting/rosetta/13_hello_dad/ex.html (nonexistent) +++ tags/2.1.2/doc/user/06_feature/scripting/rosetta/13_hello_dad/ex.html (revision 24813) @@ -0,0 +1,17 @@ +Create a function hello that will be registered as an action. +

+When the action is called, build a dad dialog called "heldi", with a +vertical box that contains two labels "Hello" and "world!" and standard +dialog box close buttons. When the cancel button is clicked, the dialog +box will return -1; clicking the ok button will return 0. The vbox is +closed by a "end" call to dad(). When the dialog is ran in modal mode, it +will be open and block other pcb-rnd windows until the user closes it. +

+Tip #1: change "begin_vbox" to "begin_hbox" to get a horizontal layout. +

+Tip #2: boxes can be nested (but each box must have a corresponding "end"). +

+In the "main" section of the script, register the action using fgw_func_reg(). +

+More details on DAD: +DAD developer's doc Index: tags/2.1.2/doc/user/06_feature/scripting/rosetta/13_hello_dad/ex.lua =================================================================== --- tags/2.1.2/doc/user/06_feature/scripting/rosetta/13_hello_dad/ex.lua (nonexistent) +++ tags/2.1.2/doc/user/06_feature/scripting/rosetta/13_hello_dad/ex.lua (revision 24813) @@ -0,0 +1,12 @@ +function hello() + dad("heldi", "new") + dad("heldi", "begin_vbox") + dad("heldi", "label", "Hello") + dad("heldi", "label", "world!") + dad("heldi", "button_closes", "cancel", -1, "ok", 0) + dad("heldi", "end") + dad("heldi", "run_modal", "hello-world", "") + return 0 +end + +fgw_func_reg("hello") Index: tags/2.1.2/doc/user/06_feature/scripting/rosetta/13_hello_dad/ex.pl =================================================================== --- tags/2.1.2/doc/user/06_feature/scripting/rosetta/13_hello_dad/ex.pl (nonexistent) +++ tags/2.1.2/doc/user/06_feature/scripting/rosetta/13_hello_dad/ex.pl (revision 24813) @@ -0,0 +1,12 @@ +sub hello +{ + dad('heldi', 'new'); + dad('heldi', 'begin_vbox'); + dad('heldi', 'label', 'Hello'); + dad('heldi', 'label', 'world!'); + dad('heldi', 'button_closes', "cancel", -1, "ok", 0); + dad('heldi', 'end'); + dad('heldi', 'run_modal', 'hello-world', ''); +} + +fgw_func_reg('hello'); Index: tags/2.1.2/doc/user/06_feature/scripting/rosetta/13_hello_dad/ex.py =================================================================== --- tags/2.1.2/doc/user/06_feature/scripting/rosetta/13_hello_dad/ex.py (nonexistent) +++ tags/2.1.2/doc/user/06_feature/scripting/rosetta/13_hello_dad/ex.py (revision 24813) @@ -0,0 +1,11 @@ +def hello(): + dad("heldi", "new") + dad("heldi", "begin_vbox") + dad("heldi", "label", "Hello") + dad("heldi", "label", "world!") + dad("heldi", "button_closes", "cancel", -1, "ok", 0) + dad("heldi", "end") + dad("heldi", "run_modal", "hello-world", "") + return 0 + +fgw_func_reg("hello") Index: tags/2.1.2/doc/user/06_feature/scripting/rosetta/13_hello_dad/ex.tcl =================================================================== --- tags/2.1.2/doc/user/06_feature/scripting/rosetta/13_hello_dad/ex.tcl (nonexistent) +++ tags/2.1.2/doc/user/06_feature/scripting/rosetta/13_hello_dad/ex.tcl (revision 24813) @@ -0,0 +1,12 @@ +proc hello {} { + dad "heldi" "new" + dad "heldi" "begin_vbox" + dad "heldi" "label" "Hello" + dad "heldi" "label" "world!" + dad "heldi" "button_closes" "cancel" -1 "ok" 0 + dad "heldi" "end" + dad "heldi" "run_modal" "hello-world" "" + return 0 +} + +fgw_func_reg "hello" Index: tags/2.1.2/doc/user/06_feature/scripting/rosetta/13_hello_dad/index.html =================================================================== --- tags/2.1.2/doc/user/06_feature/scripting/rosetta/13_hello_dad/index.html (nonexistent) +++ tags/2.1.2/doc/user/06_feature/scripting/rosetta/13_hello_dad/index.html (revision 24813) @@ -0,0 +1,36 @@ + + + + pcb-rnd rosetta hello world (GUI, with vbox) + + + + +<-- back to the index of Rosetta examples +

hello world (GUI, with vbox)

+Create a new action hello() that prints "Hello world!" in vertical layout in a dialog box. +

Example implementations

+awk + | +lua + | +pl + | +py + | +tcl +

Explanation, step by step

+Create a function +hello + that will be registered as an action. +

When the action is called, build a dad dialog called "heldi", with a vertical box that contains two labels "Hello" and "world!" and standard dialog box +close buttons +. When the cancel button is clicked, the dialog box will return -1; clicking the ok button will return 0. The vbox is closed by a "end" call to dad(). When the dialog is ran in modal mode, it will be open and block other pcb-rnd windows until the user closes it. +

Tip #1: change "begin_vbox" to "begin_hbox" to get a horizontal layout. +

Tip #2: boxes can be nested (but each box must have a corresponding "end"). +

In the "main" section of the script, register the action using fgw_func_reg(). +

More details on DAD: +DAD developer's doc + + + Index: tags/2.1.2/doc/user/06_feature/scripting/rosetta/21_timer/ID.desc =================================================================== --- tags/2.1.2/doc/user/06_feature/scripting/rosetta/21_timer/ID.desc (nonexistent) +++ tags/2.1.2/doc/user/06_feature/scripting/rosetta/21_timer/ID.desc (revision 24813) @@ -0,0 +1 @@ +Create timers that are going to call back an action in the background. Index: tags/2.1.2/doc/user/06_feature/scripting/rosetta/21_timer/ID.name =================================================================== --- tags/2.1.2/doc/user/06_feature/scripting/rosetta/21_timer/ID.name (nonexistent) +++ tags/2.1.2/doc/user/06_feature/scripting/rosetta/21_timer/ID.name (revision 24813) @@ -0,0 +1 @@ +timers Index: tags/2.1.2/doc/user/06_feature/scripting/rosetta/21_timer/ex.awk =================================================================== --- tags/2.1.2/doc/user/06_feature/scripting/rosetta/21_timer/ex.awk (nonexistent) +++ tags/2.1.2/doc/user/06_feature/scripting/rosetta/21_timer/ex.awk (revision 24813) @@ -0,0 +1,15 @@ +function timer_cb(now, remain, ud) +{ + message("timer_cb: " now " " remain " " ud "\n") + return 0 +} + +BEGIN { + fgw_func_reg("timer_cb") + + addtimer("timer_cb", 0, 1, "single, async"); + addtimer("timer_cb", 1.2, 1, "single, delayed"); + addtimer("timer_cb", 0.5, 3, "multi"); + + message("Script init finished!\n"); +} Index: tags/2.1.2/doc/user/06_feature/scripting/rosetta/21_timer/ex.html =================================================================== --- tags/2.1.2/doc/user/06_feature/scripting/rosetta/21_timer/ex.html (nonexistent) +++ tags/2.1.2/doc/user/06_feature/scripting/rosetta/21_timer/ex.html (revision 24813) @@ -0,0 +1,16 @@ +Create a function timer_cb that will be registered as an action. +This is what the timer will execute. It only prints its arguments in +the message log so it is easy to trace how it is called. +

+Different combination of timer initialization arguments for period and count +(2nd and 3rd argument of addtimer()): +

+ +
period count effect +
0 1 call timer_cb once, but only after the script finished initialization (async); 0 means "0 seconds after the current script call returns" - but in practice this is a shortest non-zero time the timer system can do +
1.2 1 call timer_cb once, in 1.2 sec from now +
0.5 3 call timer_cb three times, with 0.5 sec in between +
+

+All timers start counting after a short period of time after the +script's initialization finished. The three timers are kept track on separately. Index: tags/2.1.2/doc/user/06_feature/scripting/rosetta/21_timer/ex.lua =================================================================== --- tags/2.1.2/doc/user/06_feature/scripting/rosetta/21_timer/ex.lua (nonexistent) +++ tags/2.1.2/doc/user/06_feature/scripting/rosetta/21_timer/ex.lua (revision 24813) @@ -0,0 +1,13 @@ +function timer_cb(now, remain, ud) + message("timer_cb: " .. now .. " " .. remain .. " " .. ud .. "\n") + return 0 +end + +fgw_func_reg("timer_cb") + +addtimer("timer_cb", 0, 1, "single, async") +addtimer("timer_cb", 1.2, 1, "single, delayed") +addtimer("timer_cb", 0.5, 3, "multi") + +message("Script init finished!\n") + Index: tags/2.1.2/doc/user/06_feature/scripting/rosetta/21_timer/ex.pl =================================================================== --- tags/2.1.2/doc/user/06_feature/scripting/rosetta/21_timer/ex.pl (nonexistent) +++ tags/2.1.2/doc/user/06_feature/scripting/rosetta/21_timer/ex.pl (revision 24813) @@ -0,0 +1,13 @@ +sub timer_cb { + my ($now,$remain,$ud)=@_; + message("timer_cb: $now $remain $ud\n"); + return 0; +} + +fgw_func_reg('timer_cb'); + +addtimer('timer_cb', 0, 1, 'single, async'); +addtimer('timer_cb', 1.2, 1, 'single, delayed'); +addtimer('timer_cb', 0.5, 3, 'multi'); + +message("Script init finished!\n"); Index: tags/2.1.2/doc/user/06_feature/scripting/rosetta/21_timer/ex.py =================================================================== --- tags/2.1.2/doc/user/06_feature/scripting/rosetta/21_timer/ex.py (nonexistent) +++ tags/2.1.2/doc/user/06_feature/scripting/rosetta/21_timer/ex.py (revision 24813) @@ -0,0 +1,11 @@ +def timer_cb(now, remain, ud): + message("timer_cb: " + str(now) + " " + str(remain) + " " + str(ud) + "\n") + return 0 + +fgw_func_reg('timer_cb') + +addtimer('timer_cb', 0, 1, 'single, async') +addtimer('timer_cb', 1.2, 1, 'single, delayed') +addtimer('timer_cb', 0.5, 3, 'multi') + +message("Script init finished!\n") Index: tags/2.1.2/doc/user/06_feature/scripting/rosetta/21_timer/ex.tcl =================================================================== --- tags/2.1.2/doc/user/06_feature/scripting/rosetta/21_timer/ex.tcl (nonexistent) +++ tags/2.1.2/doc/user/06_feature/scripting/rosetta/21_timer/ex.tcl (revision 24813) @@ -0,0 +1,12 @@ +proc timer_cb {now remain ud} { + message "timer_cb: $now $remain $ud\n" + return 0 +} + +fgw_func_reg "timer_cb" + +addtimer "timer_cb" 0 1 "single, async" +addtimer "timer_cb" 1.2 1 "single, delayed" +addtimer "timer_cb" 0.5 3 "multi" + +message "Script init finished!\n" Index: tags/2.1.2/doc/user/06_feature/scripting/rosetta/21_timer/index.html =================================================================== --- tags/2.1.2/doc/user/06_feature/scripting/rosetta/21_timer/index.html (nonexistent) +++ tags/2.1.2/doc/user/06_feature/scripting/rosetta/21_timer/index.html (revision 24813) @@ -0,0 +1,50 @@ + + + + pcb-rnd rosetta timers + + + + +<-- back to the index of Rosetta examples +

timers

+Create timers that are going to call back an action in the background. +

Example implementations

+awk + | +lua + | +pl + | +py + | +tcl +

Explanation, step by step

+Create a function +timer_cb + that will be registered as an action. This is what the timer will execute. It only prints its arguments in the message log so it is easy to trace how it is called. +

Different combination of timer initialization arguments for period and count (2nd and 3rd argument of addtimer()): +

+ + + + + +
period + count + effect +
0 + 1 + call timer_cb once, but only after the script finished initialization (async); 0 means "0 seconds after the current script call returns" - but in practice this is a shortest non-zero time the timer system can do +
1.2 + 1 + call timer_cb once, in 1.2 sec from now +
0.5 + 3 + call timer_cb three times, with 0.5 sec in between
+ +

All timers start counting after a short period of time +after + the script's initialization finished. The three timers are kept track on separately. + + Index: tags/2.1.2/doc/user/06_feature/scripting/rosetta/72_dad_unitconv/ID.desc =================================================================== --- tags/2.1.2/doc/user/06_feature/scripting/rosetta/72_dad_unitconv/ID.desc (nonexistent) +++ tags/2.1.2/doc/user/06_feature/scripting/rosetta/72_dad_unitconv/ID.desc (revision 24813) @@ -0,0 +1 @@ +Interactive unit converter in a dialog, created via dad(). Index: tags/2.1.2/doc/user/06_feature/scripting/rosetta/72_dad_unitconv/ID.name =================================================================== --- tags/2.1.2/doc/user/06_feature/scripting/rosetta/72_dad_unitconv/ID.name (nonexistent) +++ tags/2.1.2/doc/user/06_feature/scripting/rosetta/72_dad_unitconv/ID.name (revision 24813) @@ -0,0 +1 @@ +unit converter (GUI, interactive) Index: tags/2.1.2/doc/user/06_feature/scripting/rosetta/72_dad_unitconv/ex.awk =================================================================== --- tags/2.1.2/doc/user/06_feature/scripting/rosetta/72_dad_unitconv/ex.awk (nonexistent) +++ tags/2.1.2/doc/user/06_feature/scripting/rosetta/72_dad_unitconv/ex.awk (revision 24813) @@ -0,0 +1,34 @@ +function uconv() +{ + if (dad("uconv", "exists")) + return; + + dad("uconv", "new") + dad("uconv", "begin_vbox") + dad("uconv", "begin_hbox") + inp = dad("uconv", "coord", 0, "100m") + dad("uconv", "onchange", "uconv_update") + dad("uconv", "begin_vbox") + res1 = dad("uconv", "label", "-") + res2 = dad("uconv", "label", "-") + res3 = dad("uconv", "label", "-") + dad("uconv", "end") + dad("uconv", "end") + dad("uconv", "button_closes", "close", 0) + dad("uconv", "end") + + dad("uconv", "run", "Unit converter", "") +} + +function uconv_update() +{ + dad("uconv", "set", res1, dad("uconv", "get", inp, "mm") " mm") + dad("uconv", "set", res2, dad("uconv", "get", inp, "mil") " mil") + dad("uconv", "set", res3, dad("uconv", "get", inp, "inch") " inch") +} + +BEGIN { + fgw_func_reg("uconv") + fgw_func_reg("uconv_update") +} + Index: tags/2.1.2/doc/user/06_feature/scripting/rosetta/72_dad_unitconv/ex.html =================================================================== --- tags/2.1.2/doc/user/06_feature/scripting/rosetta/72_dad_unitconv/ex.html (nonexistent) +++ tags/2.1.2/doc/user/06_feature/scripting/rosetta/72_dad_unitconv/ex.html (revision 24813) @@ -0,0 +1,23 @@ +Create a function uconv that will be registered as an action. +

+When the action is called, build a dad dialog called "uconv". Make sure +there's only one instance of the dialog is created by checking if a dialog +by this name already exists. +

+The dialog is built as a horizontal box to split it to left and right. On +the left side there is only a coordinate input box. On the right side there's +a vertical box hosting 3 labels where the results will be displayed. +

+uconv dialog box as rendered by gtk2 +

+The widget IDs of the input and the three result labels are saved in global +variables inp, res1, res2 and res3. +

+Any change on the input will call action "uconv_update", which is also +registered by the script. The update code reads the input field with +the unit set to "mm", then sets the value of the first label (res1) +to this text with a "mm" suffix appended. This is repeated two more times +for two other unit types. +

+More details on DAD: +DAD developer's doc Index: tags/2.1.2/doc/user/06_feature/scripting/rosetta/72_dad_unitconv/ex.lua =================================================================== --- tags/2.1.2/doc/user/06_feature/scripting/rosetta/72_dad_unitconv/ex.lua (nonexistent) +++ tags/2.1.2/doc/user/06_feature/scripting/rosetta/72_dad_unitconv/ex.lua (revision 24813) @@ -0,0 +1,30 @@ +function uconv() + if dad("uconv", "exists") ~= 0 then + return + end + + dad("uconv", "new") + dad("uconv", "begin_vbox") + dad("uconv", "begin_hbox") + inp = dad("uconv", "coord", 0, "100m") + dad("uconv", "onchange", "uconv_update") + dad("uconv", "begin_vbox") + res1 = dad("uconv", "label", "-") + res2 = dad("uconv", "label", "-") + res3 = dad("uconv", "label", "-") + dad("uconv", "end") + dad("uconv", "end") + dad("uconv", "button_closes", "close", 0) + dad("uconv", "end") + dad("uconv", "run", "Unit converter", "") +end + +function uconv_update() + dad("uconv", "set", res1, dad("uconv", "get", inp, "mm") .. " mm") + dad("uconv", "set", res2, dad("uconv", "get", inp, "mil") .. " mil") + dad("uconv", "set", res3, dad("uconv", "get", inp, "inch") .. " inch") +end + +fgw_func_reg("uconv") +fgw_func_reg("uconv_update") + Index: tags/2.1.2/doc/user/06_feature/scripting/rosetta/72_dad_unitconv/ex.tcl =================================================================== --- tags/2.1.2/doc/user/06_feature/scripting/rosetta/72_dad_unitconv/ex.tcl (nonexistent) +++ tags/2.1.2/doc/user/06_feature/scripting/rosetta/72_dad_unitconv/ex.tcl (revision 24813) @@ -0,0 +1,31 @@ +proc uconv {} { + global inp res1 res2 res3 + + if {[dad "uconv" "exists"] == 0} { + dad "uconv" "new" + dad "uconv" "begin_vbox" + dad "uconv" "begin_hbox" + set inp [dad "uconv" "coord" 0 "100m"] + dad "uconv" "onchange" "uconv_update" + dad "uconv" "begin_vbox" + set res1 [dad "uconv" "label" "-"] + set res2 [dad "uconv" "label" "-"] + set res3 [dad "uconv" "label" "-"] + dad "uconv" "end" + dad "uconv" "end" + dad "uconv" "button_closes" "close" 0 + dad "uconv" "end" + dad "uconv" "run" "Unit converter" "" + } +} + +proc uconv_update {} { + global inp res1 res2 res3 + + dad "uconv" "set" $res1 "[dad uconv get $inp mm] mm" + dad "uconv" "set" $res2 "[dad uconv get $inp mil] mil" + dad "uconv" "set" $res3 "[dad uconv get $inp inch] inch" +} + +fgw_func_reg "uconv" +fgw_func_reg "uconv_update" Index: tags/2.1.2/doc/user/06_feature/scripting/rosetta/72_dad_unitconv/index.html =================================================================== --- tags/2.1.2/doc/user/06_feature/scripting/rosetta/72_dad_unitconv/index.html (nonexistent) +++ tags/2.1.2/doc/user/06_feature/scripting/rosetta/72_dad_unitconv/index.html (revision 24813) @@ -0,0 +1,38 @@ + + + + pcb-rnd rosetta unit converter (GUI, interactive) + + + + +<-- back to the index of Rosetta examples +

unit converter (GUI, interactive)

+Interactive unit converter in a dialog, created via dad(). +

Example implementations

+awk + | +lua + | +tcl +

Explanation, step by step

+Create a function +uconv + that will be registered as an action. +

When the action is called, build a dad dialog called "uconv". Make sure there's only one instance of the dialog is created by checking if a dialog by this name already exists. +

The dialog is built as a horizontal box to split it to left and right. On the left side there is only a coordinate input box. On the right side there's a vertical box hosting 3 labels where the results will be displayed. +

+uconv dialog box as rendered by gtk2 +

The widget IDs of the input and the three result labels are saved in global variables +inp, res1, res2 + and +res3 +. +

Any change on the input will call action "uconv_update", which is also registered by the script. The update code reads the input field with the unit set to "mm", then sets the value of the first label ( +res1 +) to this text with a "mm" suffix appended. This is repeated two more times for two other unit types. +

More details on DAD: +DAD developer's doc + + + Index: tags/2.1.2/doc/user/06_feature/scripting/rosetta/72_dad_unitconv/uconv.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/2.1.2/doc/user/06_feature/scripting/rosetta/72_dad_unitconv/uconv.png =================================================================== --- tags/2.1.2/doc/user/06_feature/scripting/rosetta/72_dad_unitconv/uconv.png (nonexistent) +++ tags/2.1.2/doc/user/06_feature/scripting/rosetta/72_dad_unitconv/uconv.png (revision 24813) Property changes on: tags/2.1.2/doc/user/06_feature/scripting/rosetta/72_dad_unitconv/uconv.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/2.1.2/doc/user/06_feature/scripting/rosetta/81_persistency/ID.desc =================================================================== --- tags/2.1.2/doc/user/06_feature/scripting/rosetta/81_persistency/ID.desc (nonexistent) +++ tags/2.1.2/doc/user/06_feature/scripting/rosetta/81_persistency/ID.desc (revision 24813) @@ -0,0 +1,2 @@ +Counts how many times the script was loaded, in a persistent on-disk counter. + Index: tags/2.1.2/doc/user/06_feature/scripting/rosetta/81_persistency/ID.name =================================================================== --- tags/2.1.2/doc/user/06_feature/scripting/rosetta/81_persistency/ID.name (nonexistent) +++ tags/2.1.2/doc/user/06_feature/scripting/rosetta/81_persistency/ID.name (revision 24813) @@ -0,0 +1 @@ +script state persistency (load/unload/reload) Index: tags/2.1.2/doc/user/06_feature/scripting/rosetta/81_persistency/ex.awk =================================================================== --- tags/2.1.2/doc/user/06_feature/scripting/rosetta/81_persistency/ex.awk (nonexistent) +++ tags/2.1.2/doc/user/06_feature/scripting/rosetta/81_persistency/ex.awk (revision 24813) @@ -0,0 +1,16 @@ +function preunload(why) +{ + message("preunload for " why "; counter will be " ctr "\n") + return ctr +} + +BEGIN { + ctr = scriptpersistency("read"); + if (ctr == -1) + ctr = 0; + ctr++ + message("pers reload: the script has been loaded " ctr " times so far.\n") +# scriptpersistency("remove") + + fgw_func_reg("preunload") +} Index: tags/2.1.2/doc/user/06_feature/scripting/rosetta/81_persistency/ex.html =================================================================== --- tags/2.1.2/doc/user/06_feature/scripting/rosetta/81_persistency/ex.html (nonexistent) +++ tags/2.1.2/doc/user/06_feature/scripting/rosetta/81_persistency/ex.html (revision 24813) @@ -0,0 +1,34 @@ +Create a function preunload that will be registered as an action. +This function will be called automatically right before the script is unloaded. +The return value of this function, automatically converted to string, will +be saved on disk (by pcb-rnd). +

+On init, scriptpersistency("read") reads back the last saved string. If +it returns -1, that means there was no saved data, reset the counter to 0. +

+When scriptpersistency("remove") is called, it removes the file from disk. +This matters if pcb-rnd exits abruptly (e.g. crashes), not calling script +unload to overwrite it or if multiple pcb-rnd processes would be running in +parallel and only one should load the data into the script. Keeping it +on disk means the script would still load the last known-to-be-good data +after a pcb-rnd crash. +

+Note #1: the script can save and reload multiple items, as data is an opaque +string to pcb-rnd. However, serialization (packing and unpacking of the items +into a single string) needs to be done by the script. +

+Note #2: persistency data is stored by script ID. Script ID is assigned +run-time by the user. That means the ID can be reused by a different script +next time and persistency data saved by one script may need to be passed to +another. This simplified example does not deal with that. A real script should +either do sanity checks or even better store a signature in the data. +

+Note #3: however, this also means compatible scripts can share data written +in a common format. The example scripts in this directory can be all loaded +under the same ID and will continue the counting. In a case like this, a safer +approach is to store a format-specific signature. +

+Note #4: ReloadScript() really does an unload and a load, but the reason +passed to preunload() will be "reload". The script may decide to save +persistency differently knowing that the reload will be immediate. + Index: tags/2.1.2/doc/user/06_feature/scripting/rosetta/81_persistency/ex.lua =================================================================== --- tags/2.1.2/doc/user/06_feature/scripting/rosetta/81_persistency/ex.lua (nonexistent) +++ tags/2.1.2/doc/user/06_feature/scripting/rosetta/81_persistency/ex.lua (revision 24813) @@ -0,0 +1,16 @@ +function preunload(why) + message("preunload for " .. why .. "; counter will be " .. ctr .. "\n") + return ctr +end + +ctr = scriptpersistency("read"); +if ctr == -1 then + ctr = 0; +end +ctr = ctr + 1 + +message("pers reload: the script has been loaded " .. ctr .. " times so far.\n") +-- scriptpersistency("remove") + +fgw_func_reg("preunload") + Index: tags/2.1.2/doc/user/06_feature/scripting/rosetta/81_persistency/index.html =================================================================== --- tags/2.1.2/doc/user/06_feature/scripting/rosetta/81_persistency/index.html (nonexistent) +++ tags/2.1.2/doc/user/06_feature/scripting/rosetta/81_persistency/index.html (revision 24813) @@ -0,0 +1,27 @@ + + + + pcb-rnd rosetta script state persistency (load/unload/reload) + + + + +<-- back to the index of Rosetta examples +

script state persistency (load/unload/reload)

+Counts how many times the script was loaded, in a persistent on-disk counter. +

Example implementations

+awk + | +lua +

Explanation, step by step

+Create a function +preunload + that will be registered as an action. This function will be called automatically right before the script is unloaded. The return value of this function, automatically converted to string, will be saved on disk (by pcb-rnd). +

On init, scriptpersistency("read") reads back the last saved string. If it returns -1, that means there was no saved data, reset the counter to 0. +

When scriptpersistency("remove") is called, it removes the file from disk. This matters if pcb-rnd exits abruptly (e.g. crashes), not calling script unload to overwrite it or if multiple pcb-rnd processes would be running in parallel and only one should load the data into the script. Keeping it on disk means the script would still load the last known-to-be-good data after a pcb-rnd crash. +

Note #1: the script can save and reload multiple items, as data is an opaque string to pcb-rnd. However, serialization (packing and unpacking of the items into a single string) needs to be done by the script. +

Note #2: persistency data is stored by script ID. Script ID is assigned run-time by the user. That means the ID can be reused by a different script next time and persistency data saved by one script may need to be passed to another. This simplified example does not deal with that. A real script should either do sanity checks or even better store a signature in the data. +

Note #3: however, this also means compatible scripts can share data written in a common format. The example scripts in this directory can be all loaded under the same ID and will continue the counting. In a case like this, a safer approach is to store a format-specific signature. +

Note #4: ReloadScript() really does an unload and a load, but the reason passed to preunload() will be "reload". The script may decide to save persistency differently knowing that the reload will be immediate. + + Index: tags/2.1.2/doc/user/06_feature/scripting/rosetta/Makefile =================================================================== --- tags/2.1.2/doc/user/06_feature/scripting/rosetta/Makefile (nonexistent) +++ tags/2.1.2/doc/user/06_feature/scripting/rosetta/Makefile (revision 24813) @@ -0,0 +1,4 @@ +all: FORCE + cd ../util && ./rosetta_genpages.sh + +FORCE: Index: tags/2.1.2/doc/user/06_feature/scripting/rosetta/index.html =================================================================== --- tags/2.1.2/doc/user/06_feature/scripting/rosetta/index.html (nonexistent) +++ tags/2.1.2/doc/user/06_feature/scripting/rosetta/index.html (revision 24813) @@ -0,0 +1,73 @@ + + + + pcb-rnd rosetta + + + + +

pcb-rnd scripting - Rosetta

+The Rosetta Stone +of pcb-rnd scripting is a collection of example scripts implemented in +various scripting languages. Rosetta has multiple purposes: +
    +
  • to provide examples of using the pcb-rnd API; +
  • to not scare away newcomers by showing the first examples in an unfamiliar language; +
  • to help the user to decide which language to use for a specific task; +
  • to provide examples on how to convert idioms of pcb-rnd scripts from one language to another. +
+

+Each example comes with an explanation, written in plain English about what the +scripts do, step by step. Instead of trying to exploit powerful features +of the language, example implementations try to be simple. +

+The list below is ordered from the least complex to the most complex examples. +Column lvl is the complexity score. The less the score is, the simpler +the example is. + + +

Index of examples

+ + + + + + + + + + +
lvlexample languages description +
10 + hello world (text, log) + awk fl js lua perl python ruby sh stutter tcl + Create a new action hello() that prints "Hello world!" in the message log. +
11 + hello world (menu, log) + awk lua python tcl + Create a new menu + action hello() that prints "Hello world!" in the message log. +
12 + hello world (GUI) + awk lua perl python tcl + Create a new action hello() that prints "Hello world!" in a modal dialog box using DAD. +
13 + hello world (GUI, with vbox) + awk lua perl python tcl + Create a new action hello() that prints "Hello world!" in vertical layout in a dialog box. +
21 + timers + awk lua perl python tcl + Create timers that are going to call back an action in the background. +
72 + unit converter (GUI, interactive) + awk lua tcl + Interactive unit converter in a dialog, created via dad(). +
81 + script state persistency (load/unload/reload) + awk lua + Counts how many times the script was loaded, in a persistent on-disk counter. +
+ + + + Index: tags/2.1.2/doc/user/06_feature/scripting/rosetta/index.templ.html =================================================================== --- tags/2.1.2/doc/user/06_feature/scripting/rosetta/index.templ.html (nonexistent) +++ tags/2.1.2/doc/user/06_feature/scripting/rosetta/index.templ.html (revision 24813) @@ -0,0 +1,34 @@ + + + + pcb-rnd rosetta + + + + +

pcb-rnd scripting - Rosetta

+The Rosetta Stone +of pcb-rnd scripting is a collection of example scripts implemented in +various scripting languages. Rosetta has multiple purposes: +
    +
  • to provide examples of using the pcb-rnd API; +
  • to not scare away newcomers by showing the first examples in an unfamiliar language; +
  • to help the user to decide which language to use for a specific task; +
  • to provide examples on how to convert idioms of pcb-rnd scripts from one language to another. +
+

+Each example comes with an explanation, written in plain English about what the +scripts do, step by step. Instead of trying to exploit powerful features +of the language, example implementations try to be simple. +

+The list below is ordered from the least complex to the most complex examples. +Column lvl is the complexity score. The less the score is, the simpler +the example is. + + +

Index of examples

+ + + + + Index: tags/2.1.2/doc/user/06_feature/scripting/util/Makefile =================================================================== --- tags/2.1.2/doc/user/06_feature/scripting/util/Makefile (nonexistent) +++ tags/2.1.2/doc/user/06_feature/scripting/util/Makefile (revision 24813) @@ -0,0 +1 @@ +all: Index: tags/2.1.2/doc/user/06_feature/scripting/util/rosetta_genpages.sh =================================================================== --- tags/2.1.2/doc/user/06_feature/scripting/util/rosetta_genpages.sh (nonexistent) +++ tags/2.1.2/doc/user/06_feature/scripting/util/rosetta_genpages.sh (revision 24813) @@ -0,0 +1,182 @@ +#!/bin/sh + +clean_id() +{ + tr "\r\n" "~" | sed ' +s/~*$//; +s/|/\&pipe;/g; +s/&/\&/g; +s//\>/g; +s/"/\"/g; +s/'\''/\'/g; +s/~\+/
/g; +' + echo "" +} + +genpage() +{ + local dir scripts name desc + + dir="$1" + scripts="$2" + + name=`cat $dir/ID.name` + desc=`cat $dir/ID.desc` + ./tags < "$dir/ex.html" | awk -v "fn_ref=../packages/XREF" -v "scripts=$scripts" -v "name=$name" -v "desc=$desc" ' + BEGIN { + while((getline < fn_ref) > 0) { + REF[$2] = $3 + } + print "" + print "" + print "" + print " pcb-rnd rosetta", name, "" + print " " + print "" + print "" + print "" + print "<-- back to the index of Rosetta examples" + print "

" name "

" + print desc + + print "

Example implementations

" + v = split(scripts, S, "[\r\n]+") + for(n = 1; n <= v; n++) { + lang=S[n] + sub("^ex[.]", "", lang) + if (n != 1) + print " | " + print "" lang "" + } + + print "

Explanation, step by step

" + } + /^/ { + gsub("", "", $0) + name=$0 + gsub("[ \t]*", "", name) + if (name in REF) { + link_begin="" + link_end = "" + } + else { + link_begin="" + link_end="" + } + print "" link_begin $0 link_end "" + next + } + + { print $0 } + + END { + print "" + print "" + } + + ' > "$dir/index.html" +} + +gen_index() +{ + + awk -v "template=$1" ' + BEGIN { + FS="[|]" + q = "\"" + LANGS["rb"] = "ruby" + LANGS["pl"] = "perl" + LANGS["py"] = "python" + LANGS["stt"] = "stutter" + LANGS["scm"] = "scheme" + } + + ($1 == "scripts") { + s = $3 + gsub("ex[.]", "", s) + v = split(s, S, " ") + s = "" + for(n = 1; n <= v; n++) { + if (S[n] in LANGS) + s = s " " LANGS[S[n]] + else + s = s " " S[n] + } + DATA[$2, $1] = s + next + } + + ($1 == "name") { + if (names == "") + names = $2 + else + names = names "|" $2 + } + + + { + # DATA[script, name] = "hello world" + DATA[$2, $1] = $3 + } + + function generate(cmd ,N,n,v,name,level) { + if (cmd == "index") { + print "" + print "" + print "
lvlexample languages description" + v = split(names, N, "[|]") + for(n = 1; n <= v; n++) { + name = N[n] + level = name + sub("_.*", "", level) + if (level ~ "[^0-9]") + level = "n/a" + print "
" level + print " " DATA[name, "name"] "" + print " " DATA[name, "scripts"] + print " " DATA[name, "desc"] + } + print "
" + } + else + print "Do not know how to generate " cmd > "/dev/stderr" + } + + END { + FS="" + while((getline < template) > 0) { + if (match($0, "]*>")) { + print substr($0, 1, RSTART-1) + cmd=substr($0, RSTART+8, RLENGTH-9) + sub("^[ \t]*", "", cmd) + generate(cmd) + print substr($0, RSTART+RLENGTH) + } + else + print $0 + } + } + ' + +} + + +for n in ../rosetta/* +do + if test -d "$n" + then + bn=`basename $n` + scripts=`cd $n && ls ex.* | grep -v ".pyc$\|.html$" ` + genpage "$n" "$scripts" + echo -n "desc|$bn|" + clean_id < $n/ID.desc + echo -n "name|$bn|" + clean_id < $n/ID.name + echo -n "scripts|$bn|" + echo $scripts + fi +done | gen_index ../rosetta/index.templ.html > ../rosetta/index.html + + Property changes on: tags/2.1.2/doc/user/06_feature/scripting/util/rosetta_genpages.sh ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/2.1.2/doc/user/06_feature/scripting/util/tags =================================================================== --- tags/2.1.2/doc/user/06_feature/scripting/util/tags (nonexistent) +++ tags/2.1.2/doc/user/06_feature/scripting/util/tags (revision 24813) @@ -0,0 +1,4 @@ +#!/bin/sh + +tr "\n" " " | sed "s@\(<[^/]\)@\n\1@g;s@\(]*>\)@\1\n@g" + Property changes on: tags/2.1.2/doc/user/06_feature/scripting/util/tags ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/2.1.2/doc/user/06_feature/stroke/arrow.svg =================================================================== --- tags/2.1.2/doc/user/06_feature/stroke/arrow.svg (nonexistent) +++ tags/2.1.2/doc/user/06_feature/stroke/arrow.svg (revision 24813) @@ -0,0 +1,115 @@ + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + Index: tags/2.1.2/doc/user/06_feature/stroke/index.html =================================================================== --- tags/2.1.2/doc/user/06_feature/stroke/index.html (nonexistent) +++ tags/2.1.2/doc/user/06_feature/stroke/index.html (revision 24813) @@ -0,0 +1,51 @@ + + + + pcb-rnd user manual + + + + +

Stroke plugin

+ +

Gestures

+

+The stroke plugin uses libstroke to recognize mouse gestures. By the +default menu config gestures are recognized while the right mouse button +is pressed and the mouse is moved. If no movement happened between press +and release or the gesture is not recognized, the context menu is open. +

+What gestures are recognized and what actions are executed for them are +all configured in stroke.conf. The default configuration coming with the +plugin defines the gestures listed in the table below. Please note: it is +important to start the gesture at the specific point relative to the +subsequent coordinates of the gesture; for example the rotation gestures +always need to start at the bottom. +

+ +
gesture drawing action taken +
switch to line drawing mode +
switch to arrow mode +
stop drawing a line, polygon contour or polygon hole +
switch to via placing mode +
rotate the object under the cursor 90 degrees clock-wise +
rotate the object under the cursor 90 degrees counter-clock-wise +
undo an operation +
redo an operation +
zoom to extent (all-board view) +
zoom in to the area between the endpoints of the gesture +
+ +

Configuration

+

+The stroke plugin is compiled only if (the development package of) +libstroke is installed. Any gesture recognition takes place only if +editor/enable_stroke is set to true (e.g. "1"). +

+The gestures are configured as an ordered list of +dial-pad-sequence={pcb-rnd-actions} under plugins/stroke/gestures. +Only the first match is executed; this allows the user to override default +gestures from user or project or design config. + + + Index: tags/2.1.2/doc/user/06_feature/stroke/line.svg =================================================================== --- tags/2.1.2/doc/user/06_feature/stroke/line.svg (nonexistent) +++ tags/2.1.2/doc/user/06_feature/stroke/line.svg (revision 24813) @@ -0,0 +1,115 @@ + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + Index: tags/2.1.2/doc/user/06_feature/stroke/redo.svg =================================================================== --- tags/2.1.2/doc/user/06_feature/stroke/redo.svg (nonexistent) +++ tags/2.1.2/doc/user/06_feature/stroke/redo.svg (revision 24813) @@ -0,0 +1,121 @@ + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + Index: tags/2.1.2/doc/user/06_feature/stroke/rotccw.svg =================================================================== --- tags/2.1.2/doc/user/06_feature/stroke/rotccw.svg (nonexistent) +++ tags/2.1.2/doc/user/06_feature/stroke/rotccw.svg (revision 24813) @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + Index: tags/2.1.2/doc/user/06_feature/stroke/rotcw.svg =================================================================== --- tags/2.1.2/doc/user/06_feature/stroke/rotcw.svg (nonexistent) +++ tags/2.1.2/doc/user/06_feature/stroke/rotcw.svg (revision 24813) @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + Index: tags/2.1.2/doc/user/06_feature/stroke/stopline.svg =================================================================== --- tags/2.1.2/doc/user/06_feature/stroke/stopline.svg (nonexistent) +++ tags/2.1.2/doc/user/06_feature/stroke/stopline.svg (revision 24813) @@ -0,0 +1,115 @@ + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + Index: tags/2.1.2/doc/user/06_feature/stroke/undo.svg =================================================================== --- tags/2.1.2/doc/user/06_feature/stroke/undo.svg (nonexistent) +++ tags/2.1.2/doc/user/06_feature/stroke/undo.svg (revision 24813) @@ -0,0 +1,103 @@ + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + Index: tags/2.1.2/doc/user/06_feature/stroke/via.svg =================================================================== --- tags/2.1.2/doc/user/06_feature/stroke/via.svg (nonexistent) +++ tags/2.1.2/doc/user/06_feature/stroke/via.svg (revision 24813) @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + Index: tags/2.1.2/doc/user/06_feature/stroke/zoom_ext.svg =================================================================== --- tags/2.1.2/doc/user/06_feature/stroke/zoom_ext.svg (nonexistent) +++ tags/2.1.2/doc/user/06_feature/stroke/zoom_ext.svg (revision 24813) @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + Index: tags/2.1.2/doc/user/06_feature/stroke/zoom_in.svg =================================================================== --- tags/2.1.2/doc/user/06_feature/stroke/zoom_in.svg (nonexistent) +++ tags/2.1.2/doc/user/06_feature/stroke/zoom_in.svg (revision 24813) @@ -0,0 +1,102 @@ + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + Index: tags/2.1.2/doc/user/06_feature/vendordrill/index.html =================================================================== --- tags/2.1.2/doc/user/06_feature/vendordrill/index.html (nonexistent) +++ tags/2.1.2/doc/user/06_feature/vendordrill/index.html (revision 24813) @@ -0,0 +1,101 @@ + + + + pcb-rnd user manual + + + + +

The vendordrill plugin - Apply Vendor Drills and DRC

+

+Load and Apply vendor file to the current design. + +

Description

+

+Footprint holes are predefined within each footprint and layer +characteristics are predefined in the layout file. Consequentially, hole +sizes may vary among footprints or not match a vendor's available drill +availability unless manually adjusted. Likewise, predefined layout layer +characteristics may mismatch a vendor's specific requirements. For +example one type of Through-Hole resistor footprint may have 40mil holes +while another may have 43.5 mil holes. + +

+Some PCB fabricators have a finite set of drill sizes available. In this +case loading a vendor file will automatically adjust the layout's hole +sizes to agree with the vendor's drill availability. + +

+Many current PCB fabricators offer any drill size within a tolerance with +just a minimum and maximum. In this case the layout's holes do not need +to match specific drill sizes but it may be desirable to normalize the +hole sizes. While the user may want all holes consistent for aesthetic +reasons there may be a fabrication cost saving if hole sizes are +consistent. Likewise, design rules, such as trace width and minimum +separation, can impact fabrication cost. In this situation the drills +listed in the vendor files would not be specific drill availability but +rather normalization values. + +

+The LoadVendorFrom() Action enables a file of vendor specific fabrication +requirements to be loaded to the current design. When the vendor file is +applied, holes will be automatically adjusted to conform to the drill +sizes listed in the vendor file and layer characteristics will be used in +any subsequent Design Rule Checks (DRC). Some critical parts where you +may not want to change the drill size can be identified to be left alone +- "skipped". + +

Vendor File Requirements

+
    + +
  • The vendor file is a text file in lihata format. It expects a + drillmap section and supports two other sections - + drc and skips. Skips + defines subcircuits to be skipped , hence the name. Skips' + regex patterns may only be defined for "refdes", "value" and + "descr" attributes. + +
  • The file name can be any existing, readable filename. The file name + may be entered in two ways - explicitly or using the standard file load + dialog box of the currently active HID. +
      +
    • LoadVendorFile(your_vendor_filename) +
    • LoadVendorFile() +
    + +
  • Defaults if no entry provided +
      +
    • vendor file = vendor.lht (allowed entries: + any readable filename in lihata vendor file format) +
    • units = mil (allowed entries: mil|mils|inch|inches|mm) +
    • round = up (allowed entries up|nearest) +
    +
+ +

+ Example Minimal Vendor File +

+
    ha:vendor_drill_map {
+  vendor = oshpark  # Optional and can be omitted
+  units = mil      # mil|mils|inch|inches|mm - mil is default
+  round = nearest  # up is default
+  li:drillmap = {
+      20
+      25
+      30
+  }
+  li:skips = {
+      refdes = {^J3$}       # Skip J3.
+      refdes = {^U[1-3]$}   # Skip U1, U2, U3
+  }
+  ha:drc = {
+      copper_space = 7
+      copper_width = 7
+      copper_overlap = 4
+      min_ring = 6
+      silk_width = 10
+      min_drill = 20
+  }
+
+ + Index: tags/2.1.2/doc/user/07_io/export_openscad/1206.scad =================================================================== --- tags/2.1.2/doc/user/07_io/export_openscad/1206.scad (nonexistent) +++ tags/2.1.2/doc/user/07_io/export_openscad/1206.scad (revision 24813) @@ -0,0 +1,15 @@ +module part_1206() +{ + translate([0,0,0.3]) { + // body + color([0.1,0.1,0.1]) + cube([3.2-2*0.2,1.6,0.6], center=true); + // terminals + color([0.8,0.8,0.8]) { + translate([+1.5, 0, 0]) + cube([0.2, 1.6, 0.6], center=true); + translate([-1.5, 0, 0]) + cube([0.2, 1.6, 0.6], center=true); + } + } +} Index: tags/2.1.2/doc/user/07_io/export_openscad/preliminary.txt =================================================================== --- tags/2.1.2/doc/user/07_io/export_openscad/preliminary.txt (nonexistent) +++ tags/2.1.2/doc/user/07_io/export_openscad/preliminary.txt (revision 24813) @@ -0,0 +1,48 @@ +The openscad exporter generates the 3D model of the board in form of +an openscad script. + +The main entry point of the script is pcb_board(). All coordinates are in +mm. The in x and y directions the 0;0 point of the board is the 0;0 point on +screen in pcb-rnd, to make it easy to wrap the board in a translate() after +measuring the coords of a point in pcb-rnd. The vertical origin is the middle +of the board's FR4. + +Supported features: + - arbitrary shaped outline + - top/bottom copper (optional) + - top/bottom mask (optional) + - top/bottom silk (optional) + - holes (optional) + - element models (optional) + +Element models are loaded from external files referenced from the element +in the pcb-rnd board file. Model files are searched recursively under the +footprint library search path. + +The element (footprint instance) can have the following openscad related +attributes, all optional: + + - openscad=filename file name of the .scad script (3d element model) + - openscad-transformation=script apply the specified transformation on the model instance + - openscad-param=p1,p2,p3... parameters to pass on to the model + +If the openscad attribute is not present, no 3d model is inserted. + +If openscad-transformation is specified, it is inserted before the model +call; it typically contains a transform() and/or a rotate() to modify the +placement of the model. The 0;0;0 point of the placement is the origin of +the element in pcb-rnd, on the surface of the board. + +If openscad-param is specified, the module is called with this parameter +list, else the model is called with empty parameter list. + +A model file shall contain a single module, with "module" and the arbitrary +module name in the same line, { in the following line. One instance of +each model is copied into the output file so that the resulting openscad +script has no external reference and is self-contained. + + +Known bugs: + - with pcb elements it's impossible to tell the rotation; this will + be fully solved only with the subcircuit transition. Until that you + will need to manually specify an openscd-transformation for each element Index: tags/2.1.2/doc/user/07_io/export_xy/index.html =================================================================== --- tags/2.1.2/doc/user/07_io/export_xy/index.html (nonexistent) +++ tags/2.1.2/doc/user/07_io/export_xy/index.html (revision 24813) @@ -0,0 +1,89 @@ + + + + pcb-rnd user manual + + + + +

pcb-rnd - user manual

+ +

7.x export_xy

+

+Export_xy is a configurable template based export plugin that prints +text files. The output contains an optional header, then an optional block +for each subcircuit and after each such subcircuit block an optional block +for each terminal in that subcircuit. In pseudo-code: +

+print header_template
+foreach subc in subcircuits {
+	print subc_template
+	foreach term in s.terminals {
+		print term_template
+	}
+}
+
+

+Templates can reference to the current term, the current +subc and global properties (such as board properties). + +

7.x.1. Template configuration

+

+Each xy export format has an user assigned ID (which is the short name of the format). +There is a list of strings in the config tree under plugins/export_xy/templates; +each item is named as ID.something where something is: +

    +
  • ID.name: the long name of the format (as shown on the UI); mandatory +
  • ID.hdr: header template, printed once when the output file is opened; optional +
  • ID.subc: subcircuit template, printed once when a subcircuit is entered; optional +
  • ID.term: terminal template, printed once for each terminal within each subcircuit; optional +
+

+Templates are text strings; they are printed as is, keeping all newlines and +whitespace. Portions in between % signs are substituted, depending on the +context. + +

Substitution keywords

+

+ +
keyword description +
%UTC% current date and time in UTC +
%author% board author +
%title% board title +
%suffix% coordinate unit (mm or mil) +
%boardw% boward width (unit suffixed coord) +
%boardh% boward height (unit suffixed coord) +
%subc.a.KEY% paste the current subcircuit's attribute value of the attribute whose name matches KEY; print "n/a" for non-existing attributes +
%subc.a.KEY|unk% same as %subc.a.KEY% but print "unknown" instead of "n/a" +
%subc.a.KEY?yes% same as %subc.a.KEY% but print "yes" if attribute value represents true, "n/a" otherwise +
%subc.a.KEY?yes:nope% same as %subc.a.KEY% but print "yes" if attribute value represents true, "nope" otherwise +
%subc.refdes% print the refdes of the current subcircuit +
%subc.refdes_% print the cleaned refdes of the current subcircuit +
%subc.footprint% print the footprint name of the current subcircuit +
%subc.footprint_% print the cleaned footprint name of the current subcircuit +
%subc.value% print the value of the current subcircuit +
%subc.value_% print the cleaned value of the current subcircuit +
%subc.x% print the X coordinate of the origin of the subcircuit (coord with unit suffix) +
%subc.y% print the Y coordinate of the origin of the subcircuit (coord with unit suffix) +
%subc.padx% print the X coordinate calculated from padstacks of the subcircuit (coord with unit suffix) +
%subc.pady% print the Y coordinate calculated from padstacks of the subcircuit (coord with unit suffix) +
%subc.pad_width% print the total width calculated from padstacks of the subcircuit (coord with unit suffix) +
%subc.pad_height% print the total height calculated from padstacks of the subcircuit (coord with unit suffix) +
%subc.pad_width_prerot% print the total width calculated from padstacks of the subcircuit, before applying rotation (coord with unit suffix) +
%subc.pad_height_prerot% print the total height calculated from padstacks of the subcircuit, before applying rotation (coord with unit suffix) +
%subc.rot% print the subc rotation value in degrees +
%subc.siderot% print the subc rotation value in degrees, always looking from the top side, "x-ray mode" (relative to side) +
%subc.270-rot% print the subc rotation value in degrees, subtracted from 270 +
%subc.side270-rot% print the subc rotation value in degrees, always looking from the top side, "x-ray mode", subtracted from 270 (relative to side) +
%subc.side% "top" or "bottom" (determined by subc placement, the subc aux layer) +
%subc.num-side% "1" for top or "2" for bottom (determined by subc placement, the subc aux layer) +
%subc.count% integer value, incremented by one before processing each subcircuit +
%subc.smdvsthru% "SMD" if contains padstacks but no padstack with hole; "PTH" if contains padstack with hole; "0" if neither +
%subc.smdvsthrunum% "2" if contains padstacks but no padstack with hole; "1" if contains padstack with hole; "0" if neither +
%subc.pincout% "pin" or "pad" count. Do not use. +
%term.netname% name of the net the current terminal should be connected to according to the netlist; "NC" for no connection +
+ +

+Cleaned means any character that is non-alphanumeric, not "." and not "-" +and not "+" is replaced with "_". Index: tags/2.1.2/doc/user/08_util/01_gsch2pcb-rnd.htm =================================================================== --- tags/2.1.2/doc/user/08_util/01_gsch2pcb-rnd.htm (nonexistent) +++ tags/2.1.2/doc/user/08_util/01_gsch2pcb-rnd.htm (revision 24813) @@ -0,0 +1,50 @@ + + + + pcb-rnd user manual + + + + +

pcb-rnd - user manual

+ +

2. Utilities

+

+

2.1. gsch2pcb-rnd

+

+Gsch2pcb-rnd is a standalone utility that can extract netlists and +element data from a schematics produced by gschem. Thus it is a glue +between gschem and pcb-rnd, doing forward annotation. It is ideal +for automating the design process as it can be easily called from +Makefiles, shell scripts or other programs/scripts, whereas the +"import schematics" feautre (import_sch plugin) is more geared for the +GUI user. +

+Multiple methods of operation are offered - the user can select +one of these by name, using the -m command line argument (e.g. +gsch2pcb-rnd -m importsep foo.sch): + + + + + +
method name + description +
import + Runs the same gnetlist backend as the import_sch plugin. A single + action command file generated with .cmd suffix. When executed + (using action ExcuteFile(foo.cmd)), it syncs (replaces/creates) + every element and sets up all nets. Pro: single-command import. + Con: can't load netlist only or elements only. +
importsep + Similar to import, but produces two files: a .cmd file with element + updates only (can be appled the same way as import's) and a + separate .net netlist file that can be imported the same way as the + .net of the pcb method. Pro: the user can update elements-only or + nets-only. Con: requires two user actions to get a full impoty. +
pcb + The classic approach that tried to edit the .pcb file. + No longer supported. +
+ + Index: tags/2.1.2/doc/user/08_util/install_cgi.html =================================================================== --- tags/2.1.2/doc/user/08_util/install_cgi.html (nonexistent) +++ tags/2.1.2/doc/user/08_util/install_cgi.html (revision 24813) @@ -0,0 +1,50 @@ + + + + pcb-rnd user manual + + + +

Installation of the footprint CGIs

+

system requirements, 3rd party software

+ The following software needs to be installed on the system + that will host the scripts: +
    +
  • /bin/bash (did not test with POSIX shell) +
  • awk (tested with gawk, may work with other modern implementation) +
  • common binutils, e.g. ls, find +
  • animator, the svn HEAD version; NOTE: it is possible to manually compile animator into a static executable (useful on dedicated web servers) +
  • a web server that can execute plain old CGI scripts +
  • a full checkout of pcb-rnd/trunk from svn://repo.hu/pcb-rnd/trunk +
+ +

Installation

+Since the CGIs are just demo scripts for repo.hu and are not really installed +anywhere else normally, there is no install script but a manual installation +process. For both the parametric and the static footprint CGI: +
    +
  1. check out pcb-rnd/trunk in a directory readable (but not writable) by www-data (or whatever user the CGI will run with) +
  2. copy the config file pcblib.cgi.conf from pcb-rnd/trunk/util to /etc +
  3. edit the config file; ignore setting sdir for now +
  4. hardlink, copy, or wrap the cgi files from under pcb-rnd/trunk/util into the web server's CGI directory +
+

+For the static footprint CGI (set up the map cache): +

    +
  1. cd to trunk/util/pcblib-map in the checkout and run make - NOTE: some awk scripts have hardwired CGI paths yet (TODO) +
  2. copy this directory to a web-accessible directory +
  3. set sdir to the absolute path of the web-accessible copy in /etc/pcblib.cgi.conf +
+ +

Tips and tricks

+

cgi wrapping

+Making the checkout directly into the cgi-bin dir is not a good idea. Using +a hard link on each CGI between the checkout and the cgi-bin dir is better, +but an svn up will silently break the link leaving the old version live. +The most stable solution is placing a wrapper script in the cgi-bin dir: +
+#!/bin/bash
+. /full/path/to/the/checkout/util/pcblib-param.cgi
+
+ + Index: tags/2.1.2/doc/user/09_appendix/action_details.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_details.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_details.html (revision 24813) @@ -0,0 +1,3949 @@ + + + + + pcb-rnd user manual - action details + + + + +

pcb-rnd actions (details)

+ + + +

AddRats

+
+

+ +
Syntax summary: +AddRats(AllRats|SelectedRats|Close) +
Help text: +Add one or more rat lines to the board. +
Registered by:n/a +
+

+Arguments: +

+ + + + + + + + + +
+ AllRats + + Create rat lines for all loaded nets that aren't already connected on with copper. +
+ SelectedRats + + Similarly, but only add rat lines for nets connected to selected pins and pads. +
+@item Close + + Selects the shortest unselected rat on the board. +
+ +

+ +

AddTimer

+
+

+ +
Syntax summary: +AddTimer(action, period, [repeat], [userdata]) +
Help text: +Add a new timer +
Registered by: +script plugin +
+

+This action is intended for scripts to create async timers. + +Note: + + timers do not work with the batch HID (no callback issued ever). +

+ Creates a timer that executes an +action + (by name) periodically. +Period + is a real number specified in seconds. Internal timer resolution is in the order of 0.1 second. +

+ If +repeat + is not specified or is less than 1, the timer is repeated indefinitely. If the optional +userdata + string is specified, it is also passed to the action. +

+ The +action + is specified only by a name, call arguments are always the following: +

    + +
  • + now: the current UNIX time in a floating point number +
  • + integer: count back remaining number of calls, including the current call; 1 means this was the last call; 0 means infinite number of calls will follow +
  • + +userdata + or empty string +
+ +

+ +Action + shall return integer 0 on success. If the action does not exist or returns anything else, the timer is uninstalled. +

+ There can be any number of timers in parallel. +

+ +

adjuststyle

+
+

+ +
Syntax summary:n/a +
Help text:n/a +
Registered by:n/a +
+

+Opens the window which allows editing of the route styles. +

+ +

align

+
+

+ +
Syntax summary: +Align(X/Y, [Lefts/Rights/Tops/Bottoms/Centers/Marks, [First/Last/pcb_crosshair/Average[, Gridless]]]) +
Help text: +Align subcircuits +
Registered by: +distalign plugin +
+

+ +Example: Align(X, [Lefts/Rights/Centers/Marks, [First/Last/pcb_crosshair/Average[, Gridless]]])
+ +

+ +Example: Align(Y, [Tops/Bottoms/Centers/Marks, [First/Last/pcb_crosshair/Average[, Gridless]]])
+ +

+ Arguments: +

+ + + + + + + + + + + +
+ X or Y + +Select which axis will move, other is untouched. +
+ Lefts, Rights, Tops, Bottoms, Centers, Marks + + Pick alignment point within each subcircuit +
+ First, Last, pcb_crosshair, Average + + Alignment reference, First=Topmost/Leftmost, Last=Bottommost/Rightmost, Average or pcb_crosshair point +
+ Gridless + + Do not force results to align to prevailing grid. +
+ +

+ Defaults are Marks, First. +

+ +

aligntext

+
+

+ +
Syntax summary: +AlignText(X/Y, [Lefts/Rights/Tops/Bottoms/Centers, [First/Last/pcb_crosshair/Average[, Gridless]]]) +
Help text: +Align Text Elements +
Registered by: +distaligntext plugin +
+

+ +

+ +Example: AlignText(X, [Lefts/Rights/Centers, [First/Last/pcb_crosshair/Average[, Gridless]]])
+ +

+ +Example: AlignText(Y, [Tops/Bottoms/Centers, [First/Last/pcb_crosshair/Average[, Gridless]]])
+ +

+ Arguments: +

+ + + + + + + + + + + +
+ X or Y + + Select which axis will move, other is untouched. +
+Lefts, Rights, Tops, Bottoms, Centers + + Pick alignment point within each element. +
+ NB: text objects have no Mark. +
+ First, Last, pcb_crosshair, Average + + Alignment reference, First=Topmost/Leftmost, Last=Bottommost/Rightmost, Average or pcb_crosshair point \n +
+ Gridless + + Do not force results to align to prevailing grid. \n +
+ +

+ Defaults are Lefts/Tops, First +

+ +

ApplyVendor

+
+

+ +
Syntax summary: +ApplyVendor() +
Help text: +Applies the currently loaded vendor drill table to the current design. +
Registered by: +vendor drill mapping +
+

+This will modify all of your drill holes to match the list of allowed sizes for your vendor. +

+ +

Atomic

+
+

+ +
Syntax summary: +Atomic(Save|Restore|Close|Block) +
Help text: +Save or restore the undo serial number. +
Registered by:n/a +
+

+This action allows making multiple-action bindings into an atomic operation that will be undone by a single Undo command. For example, to optimize rat lines, you'd delete the rats and re-add them. To group these into a single undo, you'd want the deletions and the additions to have the same undo serial number. So, you +Save +, delete the rats, +Restore +, add the rats - using the same serial number as the deletes, then +Block +, which checks to see if the deletions or additions actually did anything. If not, the serial number is set to the saved number, as there's nothing to undo. If something did happen, the serial number is incremented so that these actions are counted as a single undo step. +

+ Arguments: +

+ + + + + + + + + + + +
+ Save + + Saves the undo serial number. +
+ Restore + + Returns it to the last saved number. +
+ Close + + Sets it to 1 greater than the last save. +
+ Block + + Does a Restore if there was nothing to undo, else does a Close. +
+ +

+ +

Attributes

+
+

+ +
Syntax summary: +Attributes(Layout|Layer|Element|Subc) +Attributes(Layer,layername) +
Help text: +Let the user edit the attributes of the layout, current or given +layer, or selected subcircuit. +
Registered by:n/a +
+

+Pops up a dialog letting the user edit the attributes of the pcb, a subcircuit, or a layer. +

+ +

AutoPlaceSelected

+
+

+ +
Syntax summary: +AutoPlaceSelected() +
Help text: +Auto-place selected components. +
Registered by: +autoplace plugin +
+

+Attempts to re-arrange the selected components such that the nets connecting them are minimized. Note that you cannot undo this. +

+ +

AutoRoute

+
+

+ +
Syntax summary: +AutoRoute(AllRats|SelectedRats) +
Help text: +Auto-route some or all rat lines. +
Registered by: +autoroute plugin +
+

+Before autorouting, it's important to set up a few things. First, make sure any layers you aren't using are disabled, else the autorouter may use them. Next, make sure the current routing styles are set accordingly. Last, make sure "new lines clear polygons" is set, in case you eventually want to add a copper pour. +

+ Autorouting takes a while. During this time, the program may not be responsive. +

+ Arguments: +

+ + + + + + + +
+ AllRats + + Attempt to autoroute all rats. +
+ SelectedRats + + Attempt to autoroute the selected rats. +
+ +

+ +

Benchmark

+
+

+ +
Syntax summary: +Benchmark() +
Help text: +Benchmark the GUI speed. +
Registered by:n/a +
+

+This action is used to speed-test the GUI rendering. It redraws the current screen as many times as possible in ten seconds. It reports the amount of time needed to draw the screen once, in average. +

+ +

BoardFlip

+
+

+ +
Syntax summary: +BoardFlip([sides]) +
Help text: +Mirror the board over the x axis, optionally mirroring sides as well. +
Registered by:n/a +
+

+All objects on the board are up-down flipped (mirrored over the x axis). +

+ Command line board flipping: +

+ echo " BoardFlip() SaveTo(LayoutAs,$OUTFILE) Quit() " | pcb $INFILE 
+
+ +

+ To flip the board physically, use BoardFlip(sides) +

+ +

center

+
+

+ +
Syntax summary:n/a +
Help text:n/a +
Registered by:n/a +
+

+Move the pointer to the center of the window, but only if it's currently within the window already. +

+ +

ChangeClearSize

+
+

+ +
Syntax summary: +ChangeClearSize(Object, delta|style) +ChangeClearSize(SelectedPins|SelectedPads|SelectedVias, delta|style) +ChangeClearSize(SelectedLines|SelectedArcs, delta|style) +ChangeClearSize(Selected|SelectedObjects, delta|style) +
Help text: +Changes the clearance size of objects. +
Registered by:n/a +
+

+If the solder mask is currently showing, this action changes the solder mask cutout size. If the mask is not showing, this action changes the polygon clearance. +

+ +

ChangeFlag

+
+

+ +
Syntax summary: +ChangeFlag(Object|Selected|SelectedObjects, flag, value) +ChangeFlag(SelectedLines|SelectedPins|SelectedVias, flag, value) +ChangeFlag(SelectedPads|SelectedTexts|SelectedNames, flag, value) +ChangeFlag(SelectedElements, flag, value) +flag = thermal | join +value = 0 | 1 +
Help text: +Sets or clears flags on objects. +
Registered by:n/a +
+

+Toggles the given flag on the indicated object(s). The flag may be one of the flags listed above (thermal, join). The value may be the number 0 or 1. If the value is 0, the flag is cleared. If the value is 1, the flag is set. +

+ +

ChangeJoin

+
+

+ +
Syntax summary: +ChangeJoin(ToggleObject|SelectedLines|SelectedArcs|Selected) +
Help text: +Changes the join (clearance through polygons) of objects. +
Registered by:n/a +
+

+The join flag determines whether a line or arc, drawn to intersect a polygon, electrically connects to the polygon or not. When joined, the line/arc is simply drawn over the polygon, making an electrical connection. When not joined, a gap is drawn between the line and the polygon, insulating them from each other. +

+ +

ChangeName

+
+

+ +
Syntax summary: +ChangeName(Object) +ChangeName(Refdes) +ChangeName(Layout|Layer) +
Help text: +Sets the name, text string, terminal ID or refdes of objects. +
Registered by:n/a +
+

+Arguments: +

+ + + + + + + + + + + +
+ Object + + Changes the "name" of the object under the cursor. For a text object this is the text string. For a terminal, this is the terminal ID. For a subcircuit this is the refdes. For a subc text object that has only the refdes template in it, it offers changing the text object (template) or the parent subcircuit's refdes attribute. +
+ Refdes + + Changes the refdes attribute of a subcircuit under the cursor. +
+ Layout + + Changes the name of the layout. This is printed on the fab drawings. +
+ Layer + + Changes the name of the currently active layer. +
+ +

+ +

ChangePinName

+
+

+ +
Syntax summary: +ChangePinName(Refdes,PinNumber,PinName) +
Help text: +Sets the name of a specific pin on a specific subcircuit. +
Registered by:n/a +
+

+This can be especially useful for annotating pin names from a schematic to the layout without requiring knowledge of the pcb file format. +

+ +Example: ChangePinName(U3, 7, VCC)
+ +

+ +

ChangeSize

+
+

+ +
Syntax summary: +ChangeSize(Object, delta|style) +ChangeSize(SelectedObjects|Selected, delta|style) +ChangeSize(SelectedLines|SelectedPins|SelectedVias, delta|style) +ChangeSize(SelectedPads|SelectedTexts|SelectedNames, delta|style) +ChangeSize(SelectedElements, delta|style) +
Help text: +Changes the size of objects. +
Registered by:n/a +
+

+For lines and arcs, this changes the width. For padstacks, this changes the shape size (but does not touch the hole diameter). For texts, this changes the scaling factor. For subcircuits, this changes the width of the silk layer lines and arcs for this subcircuit (TODO: is this still true?). +

+ +

ChangeSizes

+
+

+ +
Syntax summary: +ChangeSizes(Object, delta|style) +ChangeSizes(SelectedObjects|Selected, delta|style) +ChangeSizes(SelectedLines|SelectedPins|SelectedVias, delta|style) +ChangeSizes(SelectedPads|SelectedTexts|SelectedNames, delta|style) +ChangeSizes(SelectedElements, delta|style) +
Help text: +Changes all sizes of objects. +
Registered by:n/a +
+

+Call ChangeSize, ChangeDrillSize and ChangeClearSize with the same arguments. If any of them did not fail, return success. +

+ +

ChkLayer

+
+

+ +
Syntax summary: +ChkLayer(layerid) +
Help text: +Returns 1 if the specified layer is the active layer +
Registered by:n/a +
+

+Returns 1 if the specified layer is the active layer. +

+ +

ChkRst

+
+

+ +
Syntax summary: +ChkRst(route_style_id) +
Help text: +Return 1 if route_style_id matches pen. +
Registered by:n/a +
+

+Return 1 if route_style_id matches pen. +

+ +

ChkView

+
+

+ +
Syntax summary: +ChkView(layerid) +
Help text: +Return 1 if layerid is visible. +
Registered by:n/a +
+

+Return 1 if layerid is visible. Intended for menu item 'checked' fields. +

+ +

claimnet

+
+

+ +
Syntax summary: +ClaimNet(object|selected|found,[netname]) +
Help text: +Claim existing connections and create a new net +
Registered by:n/a +
+

+The ClaimNet() action can be used to construct network metadata (netlist entry) converting existing physical (galvanic, copper) connections or object lists. +

+ When galvanic connections are mapped, the first argument shall be +object +; in this case the object under the mouse cursor is the starting point and anything galvanically connected (at the moment) is considered part of the new network. This mode of operation is useful for capturing existing nets. +

+ When the first argument is +selected + or +found +, the list of (selected or found) terminals are converted to a new net, regardless of galvanic connections. This mode is useful for designing a PCB by a netlist but without a schematics - in this setup the netlist is "drawn" in pcb-rnd as well. +

+ If +netname + is specified, the user is prompted for a name. +

+ +

ClrFlag

+
+

+ +
Syntax summary: +ClrFlag(Object|Selected|SelectedObjects, flag) +ClrFlag(SelectedLines|SelectedPins|SelectedVias, flag) +ClrFlag(SelectedPads|SelectedTexts|SelectedNames, flag) +ClrFlag(SelectedElements, flag) +flag = thermal | join +
Help text: +Clears flags on objects. +
Registered by:n/a +
+

+Turns the given flag off, regardless of its previous setting. See +changeflag +. +

+ +Example: ClrFlag(SelectedLines,join)
+ +

+ +

command

+
+

+ +
Syntax summary:n/a +
Help text:n/a +
Registered by:n/a +
+

+The command window allows the user to manually enter actions to be executed. +

+ There are two ways to finish with the command window. If you press the + +Enter + + key, the command is invoked, the entry normally goes away, and the next time you bring up the command window it's empty. If you press the + +Esc + + key, the window goes away without invoking anything, and the next time you bring up the command window it's empty. +

+ Use the + +up + + and + +down + + arrow keys to access command history. +

+ +

Connection

+
+

+ +
Syntax summary: +Connection(Find|ResetLinesAndPolygons|ResetPinsAndVias|Reset) +
Help text: +Searches connections of the object at the cursor position. +
Registered by:n/a +
+

+Connections found with this action will be highlighted in the "connected-color" color and will have the "found" flag set. +

+ Arguments: +

+ + + + + + + + + + + + + + + +
+ Find + + The net under the cursor is "found". +
+ ResetLayerObjects + + Any "found" layer objects (lines, arcs, polygons and texts) are marked "not found". +
+ ResetPadstacks + + Any "found" padstack are marked "not found". WARNING: does not touch non-padstack heavy terminals! +
+ Reset + + All "found" objects are marked "not found". +
+ ResetLinesAndPolygons + + Obsolate, misleading name for ResetLayerObjects. Do not use. +
+ ResetPinsAndVias + + Obsolate, misleading name for ResetPadstacks. Do not use. +
+ +

+ +

Cursor

+
+

+ +
Syntax summary: +Cursor(Type,DeltaUp,DeltaRight,Units) +
Help text: +Move the cursor. +
Registered by:n/a +
+

+This action moves the mouse cursor. Unlike other actions which take coordinates, this action's coordinates are always relative to the user's view of the board. Thus, a positive +DeltaUp + may move the cursor away from the board origin if the board is inverted (flipped, looked from the bottom). +

+ +Type + is one of + +Pan + + or + +Warp + +. + +Pan + + causes the viewport to move such that the crosshair is under the mouse cursor. + +Warp + + causes the mouse cursor to move to be above the crosshair. +

+ +Units + can be one of the following: +

+ + + + + + + + + + + +
+mil +
+mm +
+The cursor is moved by that amount, in board units. +
+grid + +The cursor is moved by that many grid points. +
+view + +The values are percentages of the viewport's view. Thus, a pan of + +100 + + would scroll the viewport by exactly the width of the current view. +
+board + + The values are percentages of the board size. Thus, a move of + +50,50 + + moves you halfway across the board. +
+ +

+ +

CycleDrag

+
+

+ +
Syntax summary: +CycleDrag() +
Help text: +Cycle through which object is being dragged +
Registered by:n/a +
+

+When multiple overlapping objects are accessible by clicking on a pixel on the screen, drag&drop operations may become harder to do: pcb-rnd will often "pick the wrong object" on click. +

+ Cycledraw provides a way to get pcb-rnd to jump to selecting another object of the avaialble ones on the original site, while the user is still in drag mode. This obviously works only through the key binding, as selecting the menu would require the drag operation to finish first. +

+ +

DisperseElements

+
+

+ +
Syntax summary: +DisperseElements(All|Selected) +
Help text: +Disperses subcircuits. +
Registered by:n/a +
+

+Normally this is used when starting a board, by selecting all subcircuits and then dispersing them. This scatters the subcircuits around the board so that you can pick individual ones, rather than have all the subcircuits at the same 0,0 coordinate and thus impossible to choose from. +

+ +

Display

+
+

+ +
Syntax summary: +Display(SubcID, template) +Display(Grid|Redraw|Pinout|PinOrPadName) +Display(CycleClip|CycleCrosshair|ToggleAllDirections|ToggleStartDirection) +Display(ToggleGrid|ToggleRubberBandMode|ToggleUniqueNames) +Display(ToggleName|ToggleClearLine|ToggleFullPoly|ToggleSnapPin) +Display(ToggleSnapOffGridLine|ToggleHighlightOnPoint|ToggleCheckPlanes) +Display(ToggleThindraw|ToggleThindrawPoly|ToggleOrthoMove|ToggleLocalRef) +Display(ToggleLiveRoute|ToggleShowDRC|ToggleAutoDRC|LockNames|OnlyNames) +
Help text: +Several display-related actions. +
Registered by:n/a +
+

+Changes random display related global states. +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ SubcID +
+ Description +
+ Value +
+Specify the subcircuit ID template to be printed on the subcircuit layer +
+ Redraw + +Redraw the whole board. +
+ ToggleAllDirections + +When clear, lines can be drawn at any angle. When set, lines are restricted to multiples of 45 degrees and requested lines may be broken up according to the clip setting. +
+ CycleClip + +Changes the way lines are restricted to 45 degree increments. The various settings are: straight only, orthogonal then angled, and angled then orthogonal. If AllDirections is set, this action disables it. +
+ CycleCrosshair + +Changes crosshair drawing. Crosshair may accept form of 4-ray, 8-ray and 12-ray cross. +
+ ToggleRubberBandMode + +If set, moving an object moves all the lines attached to it too. +
+ ToggleStartDirection + +If set, each time you set a point in a line, the Clip toggles between orth-angle and angle-ortho. +
+ ToggleUniqueNames + +If set, you will not be permitted to change the name of an element to match that of another element. +
+ ToggleSnapPin + +If set, pin centers and pad end points are treated as additional grid points that the cursor can snap to. +
+ ToggleSnapOffGridLine + +If set, snap at some sensible point along a line. +
+ ToggleHighlightOnPoint + +If set, highlights lines and arcs when the crosshair is on one of their two (end) points. +
+ ToggleLocalRef + +If set, the mark is automatically set to the beginning of any move, so you can see the relative distance you've moved. +
+ ToggleThindraw + +If set, objects on the screen are drawn as outlines (lines are drawn as center-lines). This lets you see line endpoints hidden under pins, for example. +
+ ToggleThindrawPoly + +If set, polygons on the screen are drawn as outlines. +
+ ToggleShowDRC + +If set, pending objects (i.e. lines you're in the process of drawing) will be drawn with an outline showing how far away from other copper you need to be. +
+ ToggleLiveRoute + +If set, the progress of the autorouter will be visible on the screen. +
+ ToggleAutoDRC + +If set, you will not be permitted to make connections which violate the current DRC and netlist settings. +
+ ToggleCheckPlanes + +If set, lines and arcs aren't drawn, which usually leaves just the polygons. If you also disable all but the layer you're interested in, this allows you to check for isolated regions. +
+ ToggleOrthoMove + +If set, the crosshair is only allowed to move orthogonally from its previous position. I.e. you can move a subcircuit or line up, down, left, or right, but not up+left or down+right. +
+ ToggleName + +Selects whether the pinouts show the pin names or the pin numbers. +
+ ToggleLockNames + +If set, text will ignore left mouse clicks and actions that work on objects under the mouse. You can still select text with a lasso (left mouse drag) and perform actions on the selection. +
+ ToggleOnlyNames + +If set, only text will be sensitive for mouse clicks and actions that work on objects under the mouse. You can still select other objects with a lasso (left mouse drag) and perform actions on the selection. +
+ ToggleClearLine + +When set, the clear-line flag causes new lines and arcs to have their "clear polygons" flag set, so they won't be electrically connected to any polygons they overlap. +
+ ToggleFullPoly + +When set, the full-poly flag causes new polygons to have their "full polygon" flag set, so all parts of them will be displayed instead of only the biggest one. +
+ ToggleGrid + +Resets the origin of the current grid to be wherever the crosshair is. If you provide two numbers after this, the origin is set to that coordinate. +
+ Grid + +Toggles whether the grid is displayed or not. +
+ Pinout + +Causes the pinout of the subcircuit indicated by the cursor to be displayed, usually in a separate window. +
+ PinOrPadName + +Toggles whether the names of terminals will be displayed. If the cursor is over an subcircuit, all of its terminals are affected. +
+ +

+ +

distribute

+
+

+ +
Syntax summary: +Distribute(X/Y, [Lefts/Rights/Tops/Bottoms/Centers/Marks/Gaps, [First/Last/pcb_crosshair, First/Last/pcb_crosshair[, Gridless]]]) +
Help text: +Distribute subcircuits +
Registered by: +distalign plugin +
+

+ +Example: Distribute(X, [Lefts/Rights/Centers/Marks/Gaps, [First/Last/pcb_crosshair, First/Last/pcb_crosshair[, Gridless]]])
+ +

+ +Example: Distribute(Y, [Tops/Bottoms/Centers/Marks/Gaps, [First/Last/pcb_crosshair, First/Last/pcb_crosshair[, Gridless]]])
+ +

+ As with +align +, plus: +

+ Arguments: +

+ + + + + + + +
+ Gaps + + Make gaps even rather than spreading points evenly. +
+ First, Last, pcb_crosshair + + Two arguments specifying both ends of the distribution, they can't both be the same. +
+ +

+ Defaults are Marks, First, Last +

+ Distributed subcircuits always retain the same relative order they had before they were distributed. +

+ +

distributetext

+
+

+ +
Syntax summary: +DistributeText(Y, [Lefts/Rights/Tops/Bottoms/Centers/Gaps, [First/Last/pcb_crosshair, First/Last/pcb_crosshair[, Gridless]]]) +
Help text: +Distribute Text Elements +
Registered by: +distaligntext plugin +
+

+ +

+ +Example: DistributeText(X, [Lefts/Rights/Centers/Gaps, [First/Last/pcb_crosshair, First/Last/pcb_crosshair[, Gridless]]])
+ +

+ +Example: DistributeText(Y, [Tops/Bottoms/Centers/Gaps, [First/Last/pcb_crosshair, First/Last/pcb_crosshair[, Gridless]]])
+ +

+ As with align, plus: +

+ + + + + + + +
+ Gaps + + Make gaps even rather than spreading points evenly. +
+ First, Last, pcb_crosshair + + Two arguments specifying both ends of the distribution, they can't both be the same. +
+ +

+ Defaults are Lefts/Tops, First, Last +

+ Distributed texts always retain the same relative order they had before they were distributed. +

+ +

djopt

+
+

+ +
Syntax summary: +djopt(debumpify|unjaggy|simple|vianudge|viatrim|orthopull) +djopt(auto) - all of the above +djopt(miter) +
Help text: +Perform various optimizations on the current board. +
Registered by: +djopt +
+

+The different types of optimizations change your board in order to reduce the total trace length and via count. +

+ Arguments: +

+ + + + + + + + + + + + + + + + + + + + + +
+ debumpify + + Looks for U-shaped traces that can be shortened or eliminated. +
+ unjaggy + + Looks for corners which could be flipped to eliminate one or more corners (i.e. jaggy lines become simpler). +
+ simple + + Removing uneeded vias, replacing two or more trace segments in a row with a single segment. This is usually performed automatically after other optimizations. +
+ vianudge + + Looks for vias where all traces leave in the same direction. Tries to move via in that direction to eliminate one of the traces (and thus a corner). +
+ viatrim + + Looks for traces that go from via to via, where moving that trace to a different layer eliminates one or both vias. +
+ orthopull + + Looks for chains of traces all going in one direction, with more traces orthogonal on one side than on the other. Moves the chain in that direction, causing a net reduction in trace length, possibly eliminating traces and/or corners. +
+ splitlines + + Looks for lines that pass through vias, pins, or pads, and splits them into separate lines so they can be managed separately. +
+ auto + + Performs the above options, repeating until no further optimizations can be made. +
+ miter + + Replaces 90 degree corners with a pair of 45 degree corners, to reduce RF losses and trace length. +
+ +

+ +

dowindows

+
+

+ +
Syntax summary:n/a +
Help text:n/a +
Registered by:n/a +
+

+Argument: +

+ + + + + + + + + + + + + + + + + +
+ 1 +
+ Layout +
+ Open the layout window. Since the layout window is always shown anyway, this has no effect. +
+ 2 +
+ Library +
+ Open the library window. +
+ 3 +
+ Log +
+ Open the log window. +
+ 4 +
+ Netlist +
+ Open the netlist window. +
+ 5 +
+ Preferences +
+ Open the preferences window. +
+ 6 +
+ DRC +
+ Open the DRC violations window. +
+ 7 +
+ Search +
+ Open the advanced search window. +
+ +

+ +

DRC

+
+

+ +
Syntax summary: +DRC([list|simple|print|log|dump]) +
Help text: +Invoke the DRC check. Results are presented as the argument requests. +
Registered by:n/a +
+

+Output styles available: + + + + + + + + + + + + + + +
+ name + + description +
+ list + + display a full list of all violations, with preview of the current item (large dialog) +
+ simple + + a small & simple dialog that navigates the user through the violations one by one, sequentially +
+ print + + print the list to stdout in human readable form +
+ log + + print the list as INFO lines in the log in human readable form +
+ dump + + print the list to stdout in script readable form +
+ +

+ Note that the design rule check uses the current board rule settings, not the current style settings. +

+ +

ElementList

+
+

+ +
Syntax summary: +ElementList(Start|Done|Need,,,) +
Help text: +Adds the given element if it doesn't already exist. +
Registered by:n/a +
+

+Arguments: +

+ + + + + + + + + +
+ Start + + Indicates the start of an subcircuit list; call this before any +Need + actions. +
+ Need + + Searches the board for an subcircuit with a matching refdes. +
+ If found, the value and footprint are updated. +
+ If not found, a new subcircuit is created with the given footprint and value. +
+ Done + + Compares the list of subcircuits needed since the most recent +Start + with the list of subcircuits actually on the board. Any subcircuits that weren't listed are selected, so that the user may delete them. +
+ +

+ +

ElementSetAttr

+
+

+ +
Syntax summary: +ElementSetAttr(refdes,name[,value]) +
Help text: +Sets or clears an element-specific attribute. +
Registered by:n/a +
+

+If a value is specified, the named attribute is added (if not already present) or changed (if it is) to the given value. If the value is not specified, the given attribute is removed if present. +

+ +

ExecuteFile

+
+

+ +
Syntax summary: +ExecuteFile(filename) +
Help text: +Run actions from the given file. +
Registered by:n/a +
+

+Lines starting with + +# + + are ignored. +

+ +

ExportOldConn

+
+

+ +
Syntax summary: +ExportOldConn(AllConnections|AllUnusedPins|ElementConnections,filename) +
Help text: +Export galvanic connection data in an old, custom file format. +
Registered by: +export_oldconn HID +
+

+Arguments: +

+ + + + + + + + + +
+ AllConnections + + Save all connections to a file. +
+ AllUnusedPins + + List all unconnected terminals to a file. +
+ ElementConnections + + Save connections to the subcircuit at the cursor to a file. +
+ +

+ +

Flip

+
+

+ +
Syntax summary: +Flip(Object|Selected) +
Help text: +Flip a subcircuit to the opposite side of the board. +
Registered by:n/a +
+

+Note that the location of the subcircuit will be symmetric about the cursor location; i.e. if the part you are pointing at will still be at the same spot once the subcircuit is on the other side. When flipping multiple subcircuits, this retains their positions relative to each other, not their absolute positions on the board. +

+ +

FreeRotateBuffer

+
+

+ +
Syntax summary: +FreeRotateBuffer([Angle]) +
Help text: +Rotates the current paste buffer contents by the specified angle. The +angle is given in degrees. If no angle is given, the user is prompted +for one. +
Registered by:n/a +
+

+Rotates the contents of the pastebuffer by an arbitrary angle. If no angle is given, the user is prompted for one. +

+ +

GetXY

+
+

+ +
Syntax summary: +GetXY() +
Help text: +Get a coordinate. +
Registered by:n/a +
+

+Prompts the user for a coordinate, if one is not already selected. +

+ +

Import

+
+

+ +
Syntax summary: +Import() +Import([gnetlist|make[,source,source,...]]) +Import(setnewpoint[,(mark|center|X,Y)]) +Import(setdisperse,D,units) +
Help text: +Import schematics. +
Registered by: +import_sch plugin +
+

+Imports subcircuits and netlist data from the schematics (or some other source). The first parameter, which is optional, is the mode. If not specified, the + +import::mode + + attribute in the board is used. Possible values: + +gnetlist + + means gnetlist is used to obtain the information from the schematics; + +make + + invokes make, assuming the user has a Makefile in the current directory. The Makefile will be invoked with the following variables set: +

+ + + + + + + + + +
+PCB + + The name of the .pcb file +
+ SRCLIST + + A space-separated list of source files +
+ OUT + + The name of the file in which to put the command script, which may contain any @pcb{} actions. By default, this is a temporary file selected by @pcb{}, but if you specify an + +import::outfile + + attribute, that file name is used instead (and not automatically deleted afterwards). +
+ +

+ The target specified to be built is the first of these that apply: +

    + +
  • +The target specified by an + +import::target + + attribute. +
  • +The output file specified by an + +import::outfile + + attribute. +
  • +If nothing else is specified, the target is + +pcb_import + +. +
+ +

+ If you specify an + +import::makefile + + attribute, then "-f + +that file + +" will be added to the command line. +

+ If you specify the mode, you may also specify the source files (schematics). If you do not specify any, the list of schematics is obtained by reading the + +import::srcN + + attributes (like + +import::src0 + +, + +import::src1 + +, etc). +

+ For compatibility with future extensions to the import file format, the generated file + +must not + + start with the two characters #%. +

+ If a temporary file is needed the + +TMPDIR + + environment variable is used to select its location. +

+ Note that the programs + +gnetlist + + and + +make + + must be configured. +

+ If pcb-rnd cannot determine which schematic(s) to import from, the GUI is called to let user choose (see +importgui() +). +

+ Note that +import() + doesn't delete anything - after an Import, subcircuits which shouldn't be on the board are selected and may be removed once it's determined that the deletion is appropriate. TODO: is this still true? +

+ If +import() + is called with +setnewpoint +, then the location of new components can be specified. This is where parts show up when they're added to the board. The default is the center of the board. Argument combinations: +

+ + + + + + + + + + + +
+ Import(setnewpoint) + + Prompts the user to click on the board somewhere, uses that point. If called by a hotkey, uses the current location of the crosshair. +
+ Import(setnewpoint,mark) + + Uses the location of the mark. If no mark is present, the point is not changed. +
+ Import(setnewpoint,center) + + Resets the point to the center of the board. +
+ Import(setnewpoint,X,Y,units) + + Sets the point to the specific coordinates given. +
+ + +Import(setnewpoint,50,25,mm) + + +
+ +

+ Note that the +X + and +Y + locations are stored in attributes named + +import::newX + + and + +import::newY} + + so you could change them manually if you wished. +

+ Calling + +Import(setdisperse,D,units) + + sets how much the newly placed subcircuits are dispersed relative to the set point. For example, + +Import(setdisperse,10,mm) + + will offset each part randomly up to 10mm away from the point. The default dispersion is 1/10th of the smallest board dimension. Dispersion is saved in the + +import::disperse + + attribute. +

+ +

ImportGUI

+
+

+ +
Syntax summary: +ImportGUI() +
Help text: +Asks user which schematics to import into PCB. +
Registered by: +dialogs plugin +
+

+Displays a dialog that lets the user select the schematic(s) to import from, then saves that information in the layout's attributes for future imports. +

+ +

l

+
+

+ +
Syntax summary: +l [name] [format] +
Help text: +Loads layout data. +
Registered by: +shand_cmd plugin +
+

+Loads a new datafile (layout) and, if confirmed, overwrites any existing unsaved data. If no filename is specified a file select box will popup. +

+ +

le

+
+

+ +
Syntax summary: +le [name] +
Help text: +Loads an element (subcircuit, footprint) into the current buffer. +
Registered by: +shand_cmd plugin +
+

+The +filename + is passed to the footprint loader. If no filename is specified a file select box will popup. +

+ +

ListScripts

+
+

+ +
Syntax summary: +ListScripts([pat]) +
Help text: +List fungw scripts, optionally filtered wiht regex pat. +
Registered by: +script plugin +
+

+Print one line in the log for each currently loaded script. If +pat + is specified, filter the list using +pat + as a case sensitive regex on script ID, file name and language (list only scripts that match with any of these fields). +

+ +

LiveScript

+
+

+ +
Syntax summary: +LiveScript([new], [name]) +LiveScript(load|save, name, [filame]) +LiveScript(run|stop|rerun|undo, name) +
Help text: +Manage a live script +
Registered by: +script plugin +
+

+The first argument determines what operation the action performs and how subsequent arguments are interpreted: +

+ + + + + + + + + + + + + + + + + +
+ new, [name] + + Create a new live script and open a new live script dialog. + +name + + is an unique live script name that identifies the window. If not specified, "default" is used" +
+ load, name, [filename] + + Replace the script source in the LiveScript window identified by + +name + + with the content loaded from a file. If + +filename + + is not specified, open a file selector dialog. +
+ save, name, [filename] + + Save the script source in the LiveScript window identified by + +name + + to a file. If + +filename + + is not specified, open a file selector dialog. +
+ run, name + + Run the script in the LiveScript window identified by + +name + +. +
+ stop, name + + Stop the script in the LiveScript window identified by + +name + +, if ti is running in persistent mode. +
+ undo, name + + Undo the "init changes" of the script in the LiveScript window identified by + +name + +. Init changes are those board changes the script has done while running its initialization section. Live script undo is possible only if there was no user edit after the script finished. +
+ rerun, name + + Stop, undo and run the script in the LiveScript window identified by + +name + +. +
+ +

+ +

Load

+
+

+ +
Syntax summary: +Load() +Load(Layout|LayoutToBuffer|ElementToBuffer|Netlist|Revert) +
Help text: +Load layout data from a user-selected file. +
Registered by: +dialogs plugin +
+

+This action is a GUI front-end to the core's +loadfrom + action. If you happen to pass a filename, +loadfrom + is called directly. Else, the user is prompted for a filename to load, and then +loadfrom + is called with that filename. +

+ +

LoadFootprint

+
+

+ +
Syntax summary: +pcb_load_footprint(filename[,refdes,value]) +
Help text: +Loads a single footprint by name. +
Registered by:n/a +
+

+Loads a single footprint by name, rather than by reference or through the library. If a refdes and value are specified, those are inserted into the footprint as well. The footprint remains in the paste buffer. +

+ +

LoadFrom

+
+

+ +
Syntax summary: +LoadFrom(Layout|LayoutToBuffer|SubcToBuffer|Netlist|Revert,filename[,format]) +
Help text: +Load layout data from a file. +
Registered by:n/a +
+

+This action assumes you know what the filename is. The various GUIs should have a similar +load + action where the filename is optional, and will provide their own file selection mechanism to let you choose the file name. +

+ Arguments: +

+ + + + + + + + + + + + + +
+ Layout + + Loads an entire PCB layout, replacing the current one. +
+ LayoutToBuffer + + Loads an entire PCB layout to the paste buffer. +
+ ElementToBuffer + + Loads the given footprint file into the paste buffer. Footprint files contain only a single subcircuit definition in one of the various supported file formats. +
+ Netlist + + Loads a new netlist, replacing any current netlist. +
+ Revert + + Re-loads the current layout from its disk file, reverting any changes you may have made. +
+ +

+ +

LoadScript

+
+

+ +
Syntax summary: +LoadScript(id, filename, [language]) +
Help text: +Load a fungw script +
Registered by: +script plugin +
+

+ +id + is an arbitrary string assigned by the user. +id + must be unique per pcb-rnd session per script and may contain alphanumeric characters and undescrore. +

+ +fn + is the file name of the script, which is a path. Pcb-rnd does not do any search, it only opens the path as specified. +

+ +lang + is the scripting language, as in + +fungw plugin name + +. When not specified, the code makes a guess (based on the file name). +

+ +

LoadVendorFrom

+
+

+ +
Syntax summary: +LoadVendorFrom(filename) +
Help text: +Loads the specified vendor lihata file. +
Registered by: +vendor drill mapping +
+

+Arguments: +

+ + + + + +
+filename + + Name of the vendor lihata file. If not specified, the user will be prompted to enter one. +
+ +

+ +

m

+
+

+ +
Syntax summary: +m [name] +
Help text: +Loads a layout into the current buffer. +
Registered by: +shand_cmd plugin +
+

+If no filename is specified a file select box will popup. +

+ +

MarkCrosshair

+
+

+ +
Syntax summary: +MarkCrosshair() +MarkCrosshair(Center) +
Help text: +Set/Reset the pcb_crosshair mark. +
Registered by:n/a +
+

+The "mark" is a small X-shaped target on the display which is treated like a second origin (the normal origin is the upper let corner of the board). The GUI will display a second set of coordinates for this mark, which tells you how far you are from it. +

+ If no argument is given, the mark is toggled - disabled if it was enabled, or enabled at the current cursor position of disabled. If the +Center + argument is given, the mark is moved to the current cursor location. +

+ +

Message

+
+

+ +
Syntax summary: +message(message) +
Help text: +Writes a message to the log window. +
Registered by:n/a +
+

+This action displays a message to the log window. This action is primarily provided for use by scripts and external programs which may interface with pcb-rnd. If multiple arguments are given, each one is sent to the log window followed by a newline. +

+ +

MinClearGap

+
+

+ +
Syntax summary: +MinClearGap(delta) +MinClearGap(Selected, delta) +
Help text: +Ensures that polygons are a minimum distance from objects. +
Registered by:n/a +
+

+Checks all specified objects, and increases the polygon clearance if needed to ensure a minimum distance between their edges and the polygon edges. +

+ +

Mode

+
+

+ +
Syntax summary: +Mode(Arc|Arrow|Copy|InsertPoint|Line|Lock|Move|None|PasteBuffer) +Mode(Polygon|Rectangle|Remove|Rotate|Text|Thermal|Via) +Mode(Notify|Release|Cancel|Stroke) +Mode(Save|Restore) +
Help text: +Change or use the tool mode. +
Registered by:n/a +
+

+Selects the tool or changes tool related global states. +

+ + + + + + + + + + + + + + + + + + + +
+ Arc +
+ Arrow +
+ Copy +
+ InsertPoint +
+ Line +
+ Lock +
+ Move +
+ None +
+ PasteBuffer +
+ Polygon +
+ Rectangle +
+ Remove +
+ Rotate +
+ Text +
+ Thermal +
+ Via +
+ ... +
+ Select the indicated tool. +
+ Notify + + Called when you press the mouse button, or move the mouse. +
+ Release + + Called when you release the mouse button. +
+ Cancel + + Cancels any pending tool activity, allowing you to restart elsewhere. For example, this allows you to start a new line rather than attach a line to the previous line. +
+ Escape + + Similar to Cancel but calling this action a second time will return to the Arrow tool. +
+ Stroke + + If pcb-rnd was built with libstroke, this invokes the stroke input method. If not, this will restart a drawing mode if you were drawing, else it will select objects. +
+ Save + + Remembers the current tool. +
+ Restore + + Restores the tool to the last saved tool. +
+ +

+ +

MorphPolygon

+
+

+ +
Syntax summary: +pcb_poly_morph(Object|Selected) +
Help text: +Converts dead polygon islands into separate polygons. +
Registered by:n/a +
+

+If a polygon is divided into unconnected "islands", you can use this command to convert the otherwise disappeared islands into separate polygons. Be sure the cursor is over a portion of the polygon that remains visible. Very small islands that may flake off are automatically deleted. +

+ +

MoveLayer

+
+

+ +
Syntax summary: +MoveLayer(old,new) +MoveLayer(lid,group,gid) +
Help text: +Moves/Creates/Deletes Layers. +
Registered by:n/a +
+

+Moves a layer, creates a new layer, or deletes a layer. +

+ Arguments: +

+ + + + + + + +
+ old + + The is the layer number to act upon. Allowed values are: +
    + +
  • + c = Currently selected layer. +
  • + -1 = Create a new layer. +
  • + + +number + + = An existing layer number. +
+ +
+ new + + Specifies where to move the layer to. Allowed values are: +
    + +
  • + -1 = Deletes the layer. +
  • + up = Moves the layer up (TODO: is this supported?) +
  • + down = Moves the layer down (TODO: is this supported?) +
  • + step+ = Moves the layer towards the end of its group's list. +
  • + step- = Moves the layer towards the beginning of its group's list. +
  • + c = Creates a new layer. +
  • + grp + +gid + + = move layer into group; target group ID is the 3rd argument +
+ +
+ +

+ +

MoveObject

+
+

+ +
Syntax summary: +pcb_move_obj(X,Y,[units]) +
Help text: +Moves the object under the crosshair. +
Registered by:n/a +
+

+The +code + and +Y + are treated like + +delta + + if they are prefixed by + or -, otherwise, they are absolute. Units can be + +mil + + or + +mm + + and is used when +X + and +Y + have no unit specified. If no unit unspecified in coords or units, nanometer is assumed. +

+ +

MoveToCurrentLayer

+
+

+ +
Syntax summary: +MoveToCurrentLayer(Object|SelectedObjects) +
Help text: +Moves objects to the current layer. +
Registered by:n/a +
+

+Note that moving an subcircuit from a component layer to a solder layer, or from solder to component, won't automatically flip it. Use the +flip + action to do that. +

+ +

netlist

+
+

+ +
Syntax summary: +Net(find|select|rats|norats||ripup|addrats|clear[,net[,pin]]) +Net(freeze|thaw|forcethaw) +Net(swap) +Net(add,net,pin)Net([rename|merge],srcnet,dstnet) +
Help text: +Perform various actions on netlists. +
Registered by:n/a +
+

+Each of these actions apply to a specified set of nets. +net + and +pin + are patterns which match one or more nets or pins; these patterns may be full names or regular expressions. If an exact match is found, it is the only match; if no exact match is found, + +then + + the pattern is tried as a regular expression. +

+ If neither +net + nor +pin + are specified, all nets apply. If +net + is specified but not +pin +, all nets matching +net + apply. If both are specified, nets which match +net + and contain a pin matching +pin + apply. +

+ +freeze +, +thaw + and +forcethaw + temporarily prevents changes to the netlist from being reflected in the GUI. For example, if you need to make multiple changes, you +freeze + the netlist, make the changes, then +thaw + it. Note that freeze/thaw requests may nest, with the netlist being fully thawed only when all pending freezes are thawed. You can bypass the nesting by using +forcethaw +, which resets the freeze count and immediately updates the GUI. +

+ Argument summary: +

+ +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ find + + Nets which apply are marked @emph{found} and are drawn in the + +connected-color + + color. +
+ select + + Nets which apply are selected (added to existing selections). +
+ unselect + + Nets which apply are unselected (removed from existing selections). +
+ rats + + Nets which apply are marked as available for the rats nest. +
+ norats + + Nets which apply are marked as not available for the rats nest. +
+ clear + + Clears the netlist. +
+ ripup + + Remove all non-subcircuit-part copper object that is connected to a net. +
+ add + + Add the given pin to the given netlist, creating either if needed. +
+ AddRats + + Calculate and add all rats required for finishing the named network. +
+ swap + + Swap the connections one end of two selected rats and pins. +
+ sort + + Called after a list of add's, this sorts the netlist. +
+ freeze +
+ thaw +
+ forcethaw +
+ Temporarily prevents changes to the netlist from being reflected in the GUI. +
+ rename + + Change the name of a network (with back annotation) +
+ merge + + Move all terminal connections from the source network (first arg) to the destination network (with back annotation) +
+ +

+ +

New

+
+

+ +
Syntax summary: +New([name]) +
Help text: +Starts a new layout. +
Registered by:n/a +
+

+If a name is not given, one is prompted for. +

+ +

onliner

+
+

+ +
Syntax summary:n/a +
Help text:n/a +
Registered by:n/a +
+

+The +oneliner + action is designed for quick execution of short, trivial scripts, such as a for loop for repeating an action. It supports any scripting language currently availabel through fungw. Each oneliner is an independent script context - variables, functions and other global states do not persist. +

+ This group of actions offers three forms: +

    + +
  • + +oneliner +( +lang +, +script +) - execute the script in the language specified +
  • + lang(script) - shorthand for the above +
  • + lang - switch the command line interpreter to execute one-liners in the given language, until /exit +
+ +

+ For example, a simple calculation using awk can be done in three ways: +

    + +
  • + + +oneliner(awk, 'print 42*3') + + +
  • + + +awk('print 42*3') + + +
  • + + +awk + +, then + +print 42*3 + +, then + +/exit + + +
+ +
+ +

OpenemsExcitation

+
+

+ +
Syntax summary: +OpenemsExcitation([interactive]) +OpenemsExcitation(select, excitationname) +OpenemsExcitation(set, [excitationnme], paramname, paramval) +OpenemsExcitation(get, [excitationnme], paramname) +
Help text: +Select which openEMS excitation method should be exported and manipulate the associated parameters. When invoked without arguments a dialog box with the same functionality is presented. +
Registered by: +openems HID +
+

+When invoked without argument or with +interactive + a dialog box is presented, allowing the user to do the same operations as with the action. +

+ If the first argument +select +, further OpenEMS exports will use the excitation named in the +excitationname + argument (in short: the excitation is selected). +

+ Arguments +set + and +get + is used to read or change an excitation parameter named in +paramname +. When +excitationname + is not set, they operate on the currently selected excitation. For +set + the +paramval + argument is mandatory. +

+ Note: the code remembers all settings for all excitements, not only the excitement that is currently selected. The selection and all parameters are saved as board attributes. +

+ +

pan

+
+

+ +
Syntax summary:n/a +
Help text:n/a +
Registered by:n/a +
+

+Start or stop panning. To start call with Mode = 1, to stop call with Mode = 0. +

+ +

PasteBuffer

+
+

+ +
Syntax summary: +PasteBuffer(AddSelected|Clear|1..PCB_MAX_BUFFER) +PasteBuffer(Rotate, 1..3) +PasteBuffer(Convert|Restore|Mirror) +PasteBuffer(ToLayout, X, Y, units) +PasteBuffer(ToLayout, crosshair) +PasteBuffer(Save, Filename, [format], [force]) +PasteBuffer(Push) +PasteBuffer(Pop) +
Help text: +Various operations on the paste buffer. +
Registered by:n/a +
+

+There are a number of paste buffers; the actual limit is a compile-time constant + +PCB_MAX_BUFFER + +. It is normally + +5 + +. One of these is the "current" paste buffer, often referred to as "the" paste buffer. Arguments: +

+ + + + + + + + + + + + + + + + + + + + + + + +
+ AddSelected + + Copies the selected objects to the current paste buffer. +
+ Clear + + Remove all objects from the current paste buffer. +
+ Convert + + Convert the current paste buffer to an subcircuit. +
+ Restore + + Convert any subcircuit in the paste buffer back to plain objects. +
+ Mirror + + Flip all objects in the paste buffer vertically (up/down flip). To mirror horizontally, combine this with rotations. +
+ Rotate + + Rotates the current buffer. The number to pass is 1..3, where 1 means 90 degrees counter clockwise, 2 means 180 degrees, and 3 means 90 degrees clockwise (270 CCW). +
+ Normalize + + Set the buffer origin to the center of the paste buffer bounding box. This is useful especially if an import plugin loaded objects in the buffer with a large offset. +
+ Save + + Saves any elements in the current buffer to the indicated file. If format is specified, try to use that file format, else use the default. If force is specified, overwrite target, don't ask. +
+ ToLayout + + Pastes objects in the current buffer to the indicated X, Y coordinates in the layout. The +X + and +Y + are treated like +delta + is for many other objects. For each, if it's prefixed by + or -, then that amount is relative to the last location. Otherwise, it's absolute. If units is unspecified, units are PCB's internal units, currently nanometer. If "crosshair" is used instead of coordinates, the paste happens at the current crosshair coords. +
+ 1..PCB_MAX_BUFFER + + Selects the given buffer to be the current paste buffer. +
+ +

+ +

PolyCombine

+
+

+ +
Syntax summary:n/a +
Help text:n/a +
Registered by: +polycombine plugin +
+

+The selected polygons are combined together according to the ordering of their points. +

+ +

Polygon

+
+

+ +
Syntax summary: +Polygon(Close|CloseHole|PreviousPoint) +
Help text: +Some polygon related stuff. +
Registered by:n/a +
+

+Argument: +

+ + + + + + + + + +
+ Close + + Creates the final segment of the polygon. This may fail if clipping to 45 degree lines is switched on, in which case a warning is issued. +
+ CloseHole + + Creates the final segment of the polygon hole. This may fail if clipping to 45 degree lines is switched on, in which case a warning is issued. +
+ PreviousPoint + + Resets the newly entered corner to the previous one. The Undo action will call Polygon(PreviousPoint) when appropriate to do so. +
+ +

+ +

PolyStitch

+
+

+ +
Syntax summary:n/a +
Help text:n/a +
Registered by: +polystitch plugin +
+

+The polygon under the cursor (based on closest-corner) is stitched together with the polygon surrounding it on the same layer. +

+ Use with pstoedit conversions where there's a "hole" in the shape - select the hole. +

+ + +
+

+ +
Syntax summary:n/a +
Help text:n/a +
Registered by:n/a +
+

+This just pops up the specified menu. The menu must have been defined in the popups subtree in the menu lht file. +

+ +

preunload

+
+

+ +
Syntax summary:n/a +
Help text:n/a +
Registered by:n/a +
+

+ +preunload + is an optional action scripts may provide. When present, it is called by pcb-rnd as the last call to the script before the script is unloaded. It has two purposes: +

    + +
  • + give scripts a chance to clean up, uninit and unregister +
  • + give scripts a chance to perist their state +
+ +

+ State persisting is achieved through returning a string from this action. That string is then saved by pcb-rnd under the scripts' load ID (as specified by the user). In a later script load, the script with the same ID may read the persistent data frolm disk using the +scriptpersistency +(read) action and can remove the save using the +scriptpersistency +(remove) action. +

+ + +It should never be called by the user or other code or other actions. + + +

+ +

Print

+
+

+ +
Syntax summary: +Print() +
Help text: +Present the print export dialog for printing the layout from the GUI. +
Registered by:n/a +
+

+Open an export dialog listing all printing plugins, prompt the user for their options, and print the layout. +

+ Available only with GUI HIDs: it's merely a graphical shorthand that in turn calls the export plugin for printing. +

+ +

PrintCalibrate

+
+

+ +
Syntax summary: +PrintCalibrate() +
Help text: +Calibrate the printer. +
Registered by: +dialogs plugin +
+

+This will print a calibration page, which you would measure and type the measurements in, so that future printouts will be more precise. +

+ +

PromptFor

+
+

+ +
Syntax summary: +PromptFor([message[,default[,title]]]) +
Help text: +Prompt for a string. Returns the string (or NULL on cancel) +
Registered by:n/a +
+

+UI-independent way of asking the user for a string. When GUI is available, it is a dialog box, else it's console input. Return value, unlike with other actions, is a string. The return value is NULL on cancel. +

+ +

Puller

+
+

+ +
Syntax summary: +pcb_act_Puller() +
Help text: +Pull an arc-line junction tight. +
Registered by: +puller plugin +
+

+The +puller + action is a special-purpose optimization. When invoked while the crosshair is over the junction of an arc and a line, it will adjust the arc's angle and the connecting line's endpoint such that the line intersects the arc at a tangent. +

+ +

q

+
+

+ +
Syntax summary: +q +
Help text: +Quits the application after confirming. +
Registered by: +shand_cmd plugin +
+

+If you have unsaved changes, you will be prompted to confirm (or save) before quitting, unless the action name included a !. +

+ +

Quit

+
+

+ +
Syntax summary: +Quit() +
Help text: +Quits the application after confirming. +
Registered by:n/a +
+

+If you have unsaved changes, you will be prompted to confirm (or save) before quitting. +

+ +

Redo

+
+

+ +
Syntax summary: +redo() +
Help text: +Redo recent "undo" operations. +
Registered by:n/a +
+

+The +redo + action allows you to recover from the last undo command. You might want to do this if you thought that undo was going to revert something other than what it actually did (in case you are confused about which operations are un-doable), or if you have been backing up through a long undo list and over-shoot your stopping point. Any change that is made since the undo in question will trim the redo list. For example if you add ten lines, then undo three of them you could use redo to put them back, but if you move a line on the board before performing the redo, you will lose the ability to "redo" the three "undone" lines. +

+ +

ReloadScript

+
+

+ +
Syntax summary: +ReloadScript(id) +
Help text: +Reload a fungw script +
Registered by: +script plugin +
+

+ +id + is the same that was specified for +loadscript +. If loading the new verison of the script fails, +id + is released (can be reused for a new LoadScript). +

+ +

RenumberBlock

+
+

+ +
Syntax summary: +RenumberBlock(old_base,new_base) +
Help text: +TODO +
Registered by: +renumber plugin +
+

+ +Example: RenumberBlock(oldnum,newnum)
+ +

+ All selected elements are renumbered by adding (newnum-oldnum) to the existing number. +

+ +Example: RenumberBlock(100,200)
+ will change R213 to R313. +

+ +

RenumberBuffer

+
+

+ +
Syntax summary: +RenumberBlock(old_base,new_base) +
Help text: +TODO +
Registered by: +renumber plugin +
+

+ +Example: RenumberBuffer(oldnum,newnum)
+ +

+ Same as +renumberblock +, but the paste buffer is renumbered. +

+ +

ReplaceFootprint

+
+

+ +
Syntax summary: +ReplaceFootprint([Selected|Object], [footprint], [dumb]) +
Help text: +Replace the footprint of the selected components with the footprint specified. +
Registered by:n/a +
+

+Replace footprint(s) from the library or buffer, in-place (preserving the original subcircuit's location, rotation and metadata) and append the replacement to the back annotation changeset. +

+ If first argument is + +selected + +, replace all selected subcircuits with the new footprint; if it is + +object + +, replace only one subcircuit, under the cursor. +

+ If the second argument is a footprint name, load it from the library. If it is + +@buffer + +, use the subcircuit in the current buffer (there must be exactly 1 subcircuit in the buffer). If it is empty or not specified, the user is asked for a footprint. +

+ If the third argument is + +dumb + + the location and rotation of the original subcircuit is not preserved (but all metadata and board side are preserved). A dumb replacement also omits creating back annotation. +

+ +

Report

+
+

+ +
Syntax summary: +Report(Object|DrillReport|FoundPins|NetLength|NetLengthTo|AllNetLengths|[,name]) +
Help text: +Produce various report. +
Registered by: +report plugin +
+

+Arguments: +

+ + + + + + + + + + + + + +
+ Object + + The object under the crosshair will be reported, describing various aspects of the object. +
+ DrillReport + + A report summarizing the number of drill sizes used, and how many of each, will be produced. +
+ FoundPins + + A report listing all pins and pads which are marked as "found" will be produced. +
+ NetLength + + The name and length of the net under the crosshair will be reported to the message log. +
+ AllNetLengths + + The name and length of the net under the crosshair will be reported to the message log. An optional parameter specifies mm, mil, pcb, or in units +
+ +

+ +

reportdialog

+
+

+ +
Syntax summary:n/a +
Help text:n/a +
Registered by:n/a +
+

+This is a shortcut for +report +( +Object +). +

+ +

RipUp

+
+

+ +
Syntax summary: +RipUp(All|Selected|Element) +
Help text: +Ripup auto-routed tracks +
Registered by:n/a +
+

+Arguments: +

+ + + + + + + +
+ All + + Removes all lines and vias which were created by the autorouter. +
+ Selected + + Removes all selected lines and vias which were created by the autorouter. +
+ +

+ +

rn

+
+

+ +
Syntax summary: +rn [name] +
Help text: +Reads netlist. +
Registered by: +shand_cmd plugin +
+

+If no filename is given a file select box will pop up. +

+ +

Rotate90

+
+

+ +
Syntax summary: +pcb_move_obj(steps) +
Help text: +Rotates the object under the crosshair by 90 degree steps. +
Registered by:n/a +
+

+Rotates the object under the mouse pointer by 90 degree +steps +. +steps + must be an integer between -3 and +3. +

+ +

s

+
+

+ +
Syntax summary: +s [name] +w [name] +
Help text: +Saves layout data. +
Registered by: +shand_cmd plugin +
+

+If no filename is entered, either the last one is used again or, if it is not available, a file select box will pop up. +

+ +

Save

+
+

+ +
Syntax summary: +Save() +Save(Layout|LayoutAs) +Save(AllConnections|AllUnusedPins|ElementConnections) +Save(PasteBuffer) +
Help text: +Save layout data to a user-selected file. +
Registered by: +dialogs plugin +
+

+This action is a GUI front-end to the core's +saveto + action. If you happen to pass a filename then +saveto + is called directly. Else, the user is prompted for a filename to save, and then +saveto + is called with that filename. +

+ +

SaveTo

+
+

+ +
Syntax summary: +SaveTo(Layout|LayoutAs,filename,[fmt]) +SaveTo(PasteBuffer,filename,[fmt]) +
Help text: +Saves data to a file. +
Registered by:n/a +
+

+Arguments: +

+ + + + + + + + + + + +
+ Layout + + Saves the current layout. +
+ LayoutAs + + Saves the current layout, and remembers the filename used. +
+ PasteBuffer + + Save the content of the active Buffer to a file. This is the graphical way to create a footprint. +
+ AllConnections, AllUnusedPins, ElementConnections + + obsolete arguments, kept for compatibility; please use +exportoldconn + instead. +
+ +

+ +

ScriptCookie

+
+

+ +
Syntax summary: +ScriptCookie() +
Help text: +Return a cookie specific to the current script instance during script initialization +
Registered by: +script plugin +
+

+The script: +

    + +
  • + may call ScriptCookie() + +during script initialization + + and save the resulting cookie string +
  • + may use the cookie string to register to core pcb-rnd infrastructure that requires cookie, such as +createmenu + +
  • + can depend on pcb-rnd to call any unregistering associated with this specific cookie atomatically after script unload ( +preunload +). +
+ +

+ The function can not be called outside of script initialization. The cookie string can be used any time between script load and script unload. +

+ +

ScriptPersistency

+
+

+ +
Syntax summary: +ScriptPersistency(read|remove) +
Help text: +Read or remove script persistency data savd on preunload +
Registered by: +script plugin +
+

+When a script is unloaded, its action +preunload + is called. The return value is saved as script persistent data. When the script is loaded again later, it can use +scriptpersistency +( +read +) to read the data saved. +

+ +scriptpersistency +( +remove +) deletes the data from disk. +

+ Note: the data is per script id, not per script file name. +

+ +

scroll

+
+

+ +
Syntax summary:n/a +
Help text:n/a +
Registered by:n/a +
+

+Arguments: +

+ + + + + + + +
+ up|down|left|right + + Specifies the direction to scroll +
+ div + + Optional. Specifies how much to scroll by. The viewport is scrolled by 1/div of what is visible, so div = 1 scrolls a whole page. If not default is given, div=40. +
+ +

+ + +WARNING: + + available in the GTK HID only. +

+ +

Select

+
+

+ +
Syntax summary: +Select(Object|ToggleObject) +Select(All|Block|Connection|Invert) +Select(Convert) +
Help text: +Toggles or sets the selection. +
Registered by:n/a +
+

+Arguments: +

+ + + + + + + + + + + + + + + +
+ Object +
+ ToggleObject +
+ Selects the object under the cursor. +
+ Block + + Selects all objects in a rectangle indicated by the cursor. +
+ All + + Selects all objects on the board. +
+ Connection + + Selects all connections with the ``found'' flag set. +
+ Convert + + Converts the selected objects to a subcircuit. This uses the highest numbered paste buffer. +
+ Invert + + Invert selection: anything that was not selected becomes selected, everything that was selected becomes unselected. Locked objects are not affected. +
+ +

+ +

SelectLayer

+
+

+ +
Syntax summary: +SelectLayer(1..MAXLAYER|Silk|Rats) +
Help text: +Select which layer is the current layer. +
Registered by:n/a +
+

+The specified layer becomes the currently active layer. It is made visible if it is not already visible +

+ +

SetFlag

+
+

+ +
Syntax summary: +SetFlag(Object|Selected|SelectedObjects, flag) +SetFlag(SelectedLines|SelectedPins|SelectedVias, flag) +SetFlag(SelectedPads|SelectedTexts|SelectedNames, flag) +SetFlag(SelectedElements, flag) +flag = thermal | join +
Help text: +Sets flags on objects. +
Registered by:n/a +
+

+Turns the given flag on, regardless of its previous setting. See +changeflag +. +

+ +Example: SetFlag(SelectedPins,thermal)
+ +

+ +

SetSame

+
+

+ +
Syntax summary: +SetSame() +
Help text: +Sets current layer and sizes to match indicated item. +
Registered by:n/a +
+

+When invoked over any line, arc, polygon, or via, this changes the current layer to be the layer that item is on, and changes the current sizes (thickness, clearance, etc) according to that item. +

+ +

SetThermal

+
+

+ +
Syntax summary: +SetThermal(Object|SelectedPins|SelectedVias|Selected, Style) +
Help text: +Set the thermal (on the current layer) of padstacks to the given style. +Style = 0 means no thermal. +Style = 1 has diagonal fingers with sharp edges. +Style = 2 has horizontal and vertical fingers with sharp edges. +Style = 3 is a solid connection to the plane. +Style = 4 has diagonal fingers with rounded edges. +Style = 5 has horizontal and vertical fingers with rounded edges. +
Registered by:n/a +
+

+This changes how/whether padstacks connect to any rectangle or polygon on the current layer. The first argument can specify one object, or all selected padstacks. The second argument specifies the style of connection. +

+ Thermal styles: +

+ + + + + + + + + + + + + + + +
+0 + + no connection, +
+1 + + 45 degree fingers with sharp edges, +
+2 + + horizontal & vertical fingers with sharp edges, +
+3 + + solid connection, +
+4 + + 45 degree fingers with rounded corners, +
+5 + + horizontal & vertical fingers with rounded corners. +
+ +

+ Padstacks may have thermals whether or not there is a polygon available to connect with. However, they will have no visible effect until a polygon is drawn around the padstack. +

+ +

SetUnits

+
+

+ +
Syntax summary: +SetUnits(mm|mil) +
Help text: +Set the default measurement units. +
Registered by:n/a +
+

+ + + + + + + +
+ mil + + Sets the display units to mils (1/1000 inch). +
+ mm + + Sets the display units to millimeters. +
+ +

+ +

SetValue

+
+

+ +
Syntax summary: +SetValue(Grid|Line|LineSize|Text|TextScale, delta) +
Help text: +Change various board-wide values and sizes. +
Registered by:n/a +
+

+Arguments: +

+ + + + + + + + + +
+ Grid + + Sets the grid spacing. +
+ Line +
+ LineSize +
+ Changes the thickness of new lines. +
+ Text +
+ TextScale +
+ Changes the size of new text. +
+ +

+ +

smartdisperse

+
+

+ +
Syntax summary: +SmartDisperse([All|Selected]) +
Help text: +Disperse subcircuits into clusters, by netlist connections +
Registered by: +smartdisperse plugin +
+

+Improve the initial dispersion of subcircuits by choosing an order based on the netlist, rather than the arbitrary subcircuit order. This isn't the same as a global autoplace, it's more of a linear autoplace. It might make some useful local groupings. For example, you should not have to chase all over the board to find the resistor that goes with a given LED. +

+ +

swapsides

+
+

+ +
Syntax summary:n/a +
Help text:n/a +
Registered by:n/a +
+

+This action changes the way you view the board (flipping the board). +

+ Arguments: +

+ + + + + + + + + +
+ v + + Flips the board over vertically (up/down). +
+ h + + Flips the board over horizontally (left/right), like flipping pages in a book. +
+ r + + Rotates the board 180 degrees without changing sides. +
+ +

+ If no argument is given, the board isn't moved but the opposite side is shown. +

+ Normally, this action changes which pads and silk layer are drawn as pcb_true silk, and which are drawn as the "invisible" layer. It also determines which solder mask you see. +

+ If +S + is specified as a second argument, if the layer group for the side you're looking at is visible and currently active, and the layer group for the opposite is not visible (i.e. disabled), then this action will also swap which layer group is visible and active, effectively swapping the "working side" of the board. +

+ +

ToggleView

+
+

+ +
Syntax summary: +ToggleView(1..MAXLAYER) +ToggleView(layername) +ToggleView(Silk|Rats|Pins|Vias|BackSide) +ToggleView(All, Open|Vis, Set|Clear|Toggle) +
Help text: +Toggle the visibility of the specified layer or layer group. +
Registered by:n/a +
+

+If you pass an integer, that layer is specified by index (the first layer is + +1 + +, etc). If you pass a layer name, that layer is specified by name. When a layer is specified, the visibility of the layer group containing that layer is toggled. +

+ If you pass a special layer name, the visibility of those components (silk, rats, etc) is toggled. Note that if you have a layer named the same as a special layer, the layer is chosen over the special layer. +

+ +

Undo

+
+

+ +
Syntax summary: +undo() +undo(ClearList) +
Help text: +Undo recent changes. +
Registered by:n/a +
+

+The unlimited undo feature of pcb-rnd allows you to recover from most operations that materially affect you work. Calling +pcb_undo + without any parameter recovers from the last (non-undo) operation. +ClearList + is used to release the allocated memory. +ClearList + is called whenever a new layout is started or loaded. See also +redo +. +

+ Note that undo groups operations by serial number; changes with the same serial number will be undone (or redone) as a group. See +atomic +. +

+ +

UnloadScript

+
+

+ +
Syntax summary: +UnloadScript(id) +
Help text: +Unload a fungw script +
Registered by: +script plugin +
+

+ +id + is the same that was specified for +loadscript +. After the call +id + is released (can be reused for a new LoadScript). +

+ +

Unselect

+
+

+ +
Syntax summary: +Unselect(All|Block|Connection) +
Help text: +Unselects the object at the pointer location or the specified objects. +
Registered by:n/a +
+

+Arguments: +

+ + + + + + + + + +
+ All + + Unselect all objects. +
+ Block + + Unselect all objects in a rectangle given by the cursor. +
+ Connection + + Unselect all connections with the "found" flag set. +
+ +

+ +

w

+
+

+ +
Syntax summary: +s [name] +w [name] +
Help text: +Saves layout data. +
Registered by: +shand_cmd plugin +
+

+This commands has been added for the convenience of + +vi + + users and has the same functionality as +s +. +

+ +

wq

+
+

+ +
Syntax summary: +wq +
Help text: +Saves the layout data and quits. +
Registered by: +shand_cmd plugin +
+

+This command has been added for the convenience of + +vi + + users and has the same functionality as +s + combined with +q +. +

+ +

zoom

+
+

+ +
Syntax summary:n/a +
Help text:n/a +
Registered by:n/a +
+

+Changes the zoom (magnification) of the view of the board. If no arguments are passed, the view is scaled such that the board just fits inside the visible window (i.e. "view all"). Otherwise, +factor + specifies a change in zoom factor. It may be prefixed by + ++ + +, + +- + +, + += + + to change how the zoom factor is modified (relative or absolute). The +factor + is a floating point number, such as + +1.5 + + or + +0.75 + +. +

+ Alternatively a box can be specified with 4 coordinates and +zoom + will set the zoom level (and modifies pan) so that the given box of the design is visible and as large as possible in the current window. +

+ Arguments: +

+ + + + + + + + + + + + + + + + + + + +
+ +factor + + Values greater than 1.0 cause the board to be drawn smaller; more of the board will be visible. Values between 0.0 and 1.0 cause the board to be drawn bigger; less of the board will be visible. +
+ -factor + + Values greater than 1.0 cause the board to be drawn bigger; less of the board will be visible. Values between 0.0 and 1.0 cause the board to be drawn smaller; more of the board will be visible. +
+ =factor + + The @var{factor} is an absolute zoom factor; the unit for this value is "PCB units per screen pixel". Since PCB units are nanometer, a +factor + of 1000 means 1 micrometer per pixel (TODO: test this). +
+ x1, y1, x2, y2 + + Zoom to the specified portion of the design, described as a rectangle (using board space coordinates) +
+ selected + + Zoom and pan so that all + +selected + + objects are on the screen. +
+ found + + Zoom and pan so that all + +found + + objects are on the screen. +
+ ? + + Print the current zoom level in the message log (as an info line). +
+ get + + Return the zoom level as an FGW_DOUBLE (useful for scripts). +
+ +

+ Note that zoom factors of zero are silently ignored. +

+ + + + Index: tags/2.1.2/doc/user/09_appendix/action_reference.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_reference.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_reference.html (revision 24813) @@ -0,0 +1,324 @@ + + + + pcb-rnd user manual + + + + +

+

pcb-rnd User Manual: Appendix

+

+

Action Reference

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
\n +This is pcb-rnd 2.1.1 (svn r23108) an interactive printed circuit board editor , Revision: 24770 + +
Action Description Syntax Plugin +
AboutPresent the about boxAbout()dialogs plugin
AddRatsAdd one or more rat lines to the board.AddRats(AllRats|SelectedRats|Close)
AddTimerAdd a new timerAddTimer(action, period, [repeat], [userdata])script plugin
ApplyVendorApplies the currently loaded vendor drill table to the current design.ApplyVendor()vendor drill mapping
ArcNewCreate a pcb arc segment on a layer. For now data must be "pcb". Returns the ID of the new object or 0 on error.ArcNew([noundo,] data, layer, centx, centy, radiusx, radiusy, start_ang, delta_ang, thickness, clearance, flags)act_draw
AtomicSave or restore the undo serial number.Atomic(Save|Restore|Close|Block)
AttributesLet the user edit the attributes of the layout, current or given
layer, or selected subcircuit.
Attributes(Layout|Layer|Element|Subc)
Attributes(Layer,layername)
AutoPlaceSelectedAuto-place selected components.AutoPlaceSelected()autoplace plugin
AutoRouteAuto-route some or all rat lines.AutoRoute(AllRats|SelectedRats)autoroute plugin
BackupBackup the current layout - save using the same method that the timed backup function usesBackup()
BellAttempt to produce audible notification (e.g. beep the speaker).Bell()oldactions plugin
BenchmarkBenchmark the GUI speed.Benchmark()
BoardFlipMirror the board over the x axis, optionally mirroring sides as well.BoardFlip([sides])
BraveChanges brave settings.Brave()
Brave(setting, on|off)
BrowseScriptsPresent a dialog box for browsing scriptsBrowseScripts()script plugin
ChangeAngleChanges the start angle, delta angle or both angles of an arc.ChangeAngle(Object, start|delta|both, delta)
ChangeAngle(SelectedObjects|Selected, start|delta|both, delta)
ChangeAngle(SelectedArcs, start|delta|both, delta)
ChangeClearSizeChanges the clearance size of objects.ChangeClearSize(Object, delta|style)
ChangeClearSize(SelectedPins|SelectedPads|SelectedVias, delta|style)
ChangeClearSize(SelectedLines|SelectedArcs, delta|style)
ChangeClearSize(Selected|SelectedObjects, delta|style)
ChangeDrillSizeChanges the drilling hole size of objects.ChangeDrillSize(Object, delta|style)
ChangeDrillSize(SelectedPins|SelectedVias|Selected|SelectedObjects, delta|style)
ChangeFlagSets or clears flags on objects.ChangeFlag(Object|Selected|SelectedObjects, flag, value)
ChangeFlag(SelectedLines|SelectedPins|SelectedVias, flag, value)
ChangeFlag(SelectedPads|SelectedTexts|SelectedNames, flag, value)
ChangeFlag(SelectedElements, flag, value)
flag = thermal | join
value = 0 | 1
ChangeHoleoldactions plugin
ChangeJoinChanges the join (clearance through polygons) of objects.ChangeJoin(ToggleObject|SelectedLines|SelectedArcs|Selected)
ChangeNameSets the name, text string, terminal ID or refdes of objects.ChangeName(Object)
ChangeName(Refdes)
ChangeName(Layout|Layer)
ChangeNonetlistChanges the nonetlist flag of subcircuits.ChangeNonetlist(ToggleObject)
ChangeNonetlist(SelectedElements)
ChangeNonetlist(Selected|SelectedObjects)
ChangeOctagonoldactions plugin
ChangePasteoldactions plugin
ChangePinNameSets the name of a specific pin on a specific subcircuit.ChangePinName(Refdes,PinNumber,PinName)
ChangeRadiusChanges the width or height (radius) of an arc.ChangeRadius(Object, width|x|height|y|both, delta)
ChangeRadius(SelectedObjects|Selected, width|x|height|y|both, delta)
ChangeRadius(SelectedArcs, width|x|height|y|both, delta)
ChangeSizeChanges the size of objects.ChangeSize(Object, delta|style)
ChangeSize(SelectedObjects|Selected, delta|style)
ChangeSize(SelectedLines|SelectedPins|SelectedVias, delta|style)
ChangeSize(SelectedPads|SelectedTexts|SelectedNames, delta|style)
ChangeSize(SelectedElements, delta|style)
ChangeSizesChanges all sizes of objects.ChangeSizes(Object, delta|style)
ChangeSizes(SelectedObjects|Selected, delta|style)
ChangeSizes(SelectedLines|SelectedPins|SelectedVias, delta|style)
ChangeSizes(SelectedPads|SelectedTexts|SelectedNames, delta|style)
ChangeSizes(SelectedElements, delta|style)
ChangeSquareoldactions plugin
ChkBufferReturn 1 if currently selected buffer's index matches idxChkBuffer(idx)
ChkGridSizeReturn 1 if the currently selected grid matches the expected_size. If argument is "none" return 1 if there is no grid.ChkGridSize(expected_size)
ChkGridSize(none)
ChkGridUnitsReturn 1 if currently selected grid unit matches the expected (normally mm or mil)ChkGridUnits(expected)
ChkLayerReturns 1 if the specified layer is the active layerChkLayer(layerid)
ChkModeReturn 1 if the currently selected mode is the expected_modeChkMode(expected_mode)
ChkRstReturn 1 if route_style_id matches pen.ChkRst(route_style_id)
ChkSubcIDReturn 1 if currently shown subc ID matches the requested patternChkSubcID(pattern)
ChkTermIDReturn 1 if currently shown term ID matches the requested patternChkTermID(pattern)
ChkViewReturn 1 if layerid is visible.ChkView(layerid)
ClearOctagonoldactions plugin
ClearSquareoldactions plugin
ClipInhibitClipInhibit Feature Template.ClipInhibit([on|off|check])
ClrFlagClears flags on objects.ClrFlag(Object|Selected|SelectedObjects, flag)
ClrFlag(SelectedLines|SelectedPins|SelectedVias, flag)
ClrFlag(SelectedPads|SelectedTexts|SelectedNames, flag)
ClrFlag(SelectedElements, flag)
flag = thermal | join
ConnectionSearches connections of the object at the cursor position.Connection(Find|ResetLinesAndPolygons|ResetPinsAndVias|Reset)
CreateMenuCreates a new menu, popup (only path specified) or submenu (at least path and action are specified)CreateMenu(path)
CreateMenu(path, action, tooltip, cookie)
CreateTextCreate a new text objectCreateText(layer, fontID, X, Y, direction, scale, text)
CursorMove the cursor.Cursor(Type,DeltaUp,DeltaRight,Units)
CycleDragCycle through which object is being draggedCycleDrag()
DRCInvoke the DRC check. Results are presented as the argument requests.DRC([list|simple|print|log|dump])
DebugDebug action.Debug(...)oldactions plugin
DebugXYDebug action, with coordinatesDebugXY(...)oldactions plugin
DelGroupRemove a layer group; if the first argument is not specified, the current group is removedDelGroup([@group])
DeleteDelete stuff.Delete(Object|Selected)
Delete(AllRats|SelectedRats)
DeleteRatsDelete rat lines.DeleteRats(AllRats|Selected|SelectedRats)
DisableVendorDisables automatic drill size mapping.DisableVendor()oldactions plugin
DisperseElementsDisperses subcircuits.DisperseElements(All|Selected)
DisplaySeveral display-related actions.Display(SubcID, template)
Display(Grid|Redraw|Pinout|PinOrPadName)
Display(CycleClip|CycleCrosshair|ToggleAllDirections|ToggleStartDirection)
Display(ToggleGrid|ToggleRubberBandMode|ToggleUniqueNames)
Display(ToggleName|ToggleClearLine|ToggleFullPoly|ToggleSnapPin)
Display(ToggleSnapOffGridLine|ToggleHighlightOnPoint|ToggleCheckPlanes)
Display(ToggleThindraw|ToggleThindrawPoly|ToggleOrthoMove|ToggleLocalRef)
Display(ToggleLiveRoute|ToggleShowDRC|ToggleAutoDRC|LockNames|OnlyNames)
DrcDialogExecute drc checks and invoke a view list dialog box for presenting the resultsDrcDialog([list|simple])dialogs plugin
DumpActionsDump all actions available.DumpActions()
DumpCsectPrint the cross-section of the board (layer stack)DumpCsect()draw_csect
DumpLibraryDisplay the entire contents of the libraries.DumpLibrary()oldactions plugin
DumpObjFlagsPrint a script processable digest of all flags, per object typeDumpObjFlags()
DumpPluginDirsPrint plugins directories in a format digestable by scripts.DumpPluginDirs()
DumpPluginsPrint plugins loaded in a format digestable by scripts.DumpPlugins()
DumpVersionDump version in script readable format.DumpVersion()
DupGroupDuplicate a layer group; if the first argument is not specified, the current group is duplicatedDupGroup([@group])
EditGroupChange a property or attribute of a layer group. If the first argument starts with @, it is taken as the group name to manipulate, else the action uses the current layer's group. Without arguments or if only a layer name is specified, interactive runs editing.Editgroup([@group], [name=text|type=+bit|type=-bit])]
Editlayer([@layer], attrib, key=value)
EditLayerChange a property or attribute of a layer. If the first argument starts with @, it is taken as the layer name to manipulate, else the action uses the current layer. Without arguments or if only a layer name is specified, interactive runs editing.Editlayer([@layer], [name=text|auto=[0|1]|sub=[0|1])]
Editlayer([@layer], attrib, key=value)
ElementListAdds the given element if it doesn't already exist.ElementList(Start|Done|Need,,,)
ElementSetAttrSets or clears an element-specific attribute.ElementSetAttr(refdes,name[,value])
EnableVendorEnables automatic drill size mapping.EnableVendor()oldactions plugin
EvalConfPerform various operations on the configuration tree.EvalConf(path) - evaluate a config path in different config sources to figure how it ended up in the native databasediag plugin
ExecCommandRun shell commandSystem(shell_cmd)
ExecuteFileRun actions from the given file.ExecuteFile(filename)
ExpFeatTmpExperimental Feature Template.ExpFeatTmp(...)experimental features plugin
ExportExport the current layout, e.g. Export(png, --dpi, 600)Export(exporter, [exporter-args])
ExportGUIOpen the export dialog.ExportGUI()dialogs plugin
ExportOldConnExport galvanic connection data in an old, custom file format.ExportOldConn(AllConnections|AllUnusedPins|ElementConnections,filename)export_oldconn HID
ExportScadPolyexports all selected polygons to an openscad script; only the outmost contour of each poly is exportedScadExportPoly(filename)openscad HID
ExportcpcbToDumps the current board in c-pcb format.ExportcpcbTo(filename)cpcb plugin
FlagEditChange the layer binding.FlagEdit(object)dialogs plugin
FlipFlip a subcircuit to the opposite side of the board.Flip(Object|Selected)
FontEditConvert the current font to a PCB for editing.FontEdit()fontmode plugin
FontSaveConvert the current PCB back to a font.FontSave()fontmode plugin
FontselOpen the font selection dialogFontsel()dialogs plugin
FreeRotateBufferRotates the current paste buffer contents by the specified angle. The
angle is given in degrees. If no angle is given, the user is prompted
for one.
FreeRotateBuffer([Angle])
FullScreenHide widgets to get edit area full screenFullScreen(on|off|toggle)
GetStyleReturn integer index (>=0) of the currently active style or -1 if no style is selected (== custom style)GetStyle()
GetValueConvert a coordinate value. Returns an unitless double or FGW_ERR_ARG_CONV. The 3rd parameter controls whether to require relative coordinates (+- prefix). Wraps pcb_get_value_ex().GetValue(input, units, relative, default_unit)act_draw
GetXYGet a coordinate.GetXY()
GlobalPullerPull all traces tight.pcb_act_GlobalPuller([Found|Selected])puller plugin
GridSet the grid.grid(set, [name:]size[@offs][!unit])
grid(+|up)
grid(-|down)
grid(#N)
grid(idx, N)
GroupPropGuiChange group flags and propertiesGroupPropGui(groupid)dialogs plugin
IOIncompatListPresent the format incompatibilities of the last save to file operation.IOIncompatList([list|simple])
IOIncompatListDialogPresent the format incompatibilities of the last save to file operation in a GUI dialog.IOIncompatListDialog([list|simple])dialogs plugin
ImportImport schematics.Import()
Import([gnetlist|make[,source,source,...]])
Import(setnewpoint[,(mark|center|X,Y)])
Import(setdisperse,D,units)
import_sch plugin
ImportGUIAsks user which schematics to import into PCB.ImportGUI()dialogs plugin
ImportcpcbFromLoads the auto-routed tracks from the specified c-pcb output.ImportcpcbFrom(filename)cpcb plugin
LayerBindingChange the layer binding.LayerBinding(object)
LayerBinding(selected)
LayerBinding(buffer)
dialogs plugin
LayerPropGuiChange layer flags and propertiesLayerPropGui(layerid)dialogs plugin
LibraryChangedTells the GUI that the libraries have changed.LibraryChanged()oldactions plugin
LineNewCreate a pcb line segment on a layer. For now data must be "pcb". Returns the ID of the new object or 0 on error.LineNew([noundo,] data, layer, X1, Y1, X2, Y2, Thickness, Clearance, Flags)act_draw
ListRotationsoldactions plugin
ListScriptsList fungw scripts, optionally filtered wiht regex pat.ListScripts([pat])script plugin
LiveScriptManage a live scriptLiveScript([new], [name])
LiveScript(load|save, name, [filame])
LiveScript(run|stop|rerun|undo, name)
script plugin
LoadLoad layout data from a user-selected file.Load()
Load(Layout|LayoutToBuffer|ElementToBuffer|Netlist|Revert)
dialogs plugin
LoadCalayFromLoads the specified calay netlist/component file pair.LoadCalayFrom(filename)calay importer
LoadDsnFromLoads the specified routed dsn file.LoadDsnFrom(filename)dsn importer
LoadEeschemaFromLoads the specified eeschema .net file - the netlist must be an s-expression.LoadEeschemaFrom(filename)kicad plugin
LoadFontFromLoad PCB font from a fileLoadFontFrom([file, id])
LoadFootprintLoads a single footprint by name.pcb_load_footprint(filename[,refdes,value])
LoadFpcbnlFromLoads the specified freepcb netlist.LoadFpcbnlFrom(filename)fpcb_nl importer
LoadFromLoad layout data from a file.LoadFrom(Layout|LayoutToBuffer|SubcToBuffer|Netlist|Revert,filename[,format])
LoadHpglFromLoads the specified hpgl plot file to the current bufferLoadHpglFrom(filename)hpgl importer
LoadIpc356FromLoads the specified IPC356-D netlistLoadIpc356From(filename, [nonet], [nopad], [nosubc])ipcd356 importer
LoadLtspiceFromLoads the specified ltspice .net and .asc file - the netlist must be mentor netlist.LoadLtspiceFrom(filename)ltspice importer
LoadMentorFromLoads the specified Mentor Graphics Design Capture schematics flat .edf file.LoadMentorFrom(filename)mentor_sch importer
LoadMucsFromLoads the specified mucs routing file.LoadMucsFrom(filename)mucs importer
LoadScriptLoad a fungw scriptLoadScript(id, filename, [language])script plugin
LoadTedaxFromLoads the specified block from a tedax file.LoadTedaxFrom(netlist|board|footprint|stackup|layer, filename, [block_id, [silent]])tEDAx IO
LoadTinycadFromLoads the specified tinycad .net file - the netlist must be tinycad netlist output.LoadTinycadFrom(filename)tinycad importer
LoadTtfGlyphsLoads glyphs from an outline ttf in the specified source range, optionally remapping them to dstchars range in the pcb-rnd fontLoadTtfGlyphs(filename, srcglyps, [dstchars])ttf importer
LoadVendorFromLoads the specified vendor lihata file.LoadVendorFrom(filename)vendor drill mapping
LoadhypFromLoads the specified Hyperlynx file.LoadhypFrom(filename[, "debug"]...)hyp importer
LogManages the central, in-memory log.Log(clear, [fromID, [toID])
Log(export, [filename, [text|lihata])
LogDialogOpen the log dialog.LogDialog()dialogs plugin
ManagePluginsManage plugins dialog.ManagePlugins()dialogs plugin
MarkCrosshairSet/Reset the pcb_crosshair mark.MarkCrosshair()
MarkCrosshair(Center)
MessageWrites a message to the log window.message(message)
MessageBoxOpen a modal message dialog box with title and label. If icon string is not empty, display the named icon on the left. Present one or more window close buttons with different text and return value.MessageBox(icon, title, label, button_txt, button_retval, ...)
MinClearGapEnsures that polygons are a minimum distance from objects.MinClearGap(delta)
MinClearGap(Selected, delta)
MinMaskGapoldactions plugin
ModeChange or use the tool mode.Mode(Arc|Arrow|Copy|InsertPoint|Line|Lock|Move|None|PasteBuffer)
Mode(Polygon|Rectangle|Remove|Rotate|Text|Thermal|Via)
Mode(Notify|Release|Cancel|Stroke)
Mode(Save|Restore)
MorphPolygonConverts dead polygon islands into separate polygons.pcb_poly_morph(Object|Selected)
MoveLayerMoves/Creates/Deletes Layers.MoveLayer(old,new)
MoveLayer(lid,group,gid)
MoveObjectMoves the object under the crosshair.pcb_move_obj(X,Y,[units])
MoveToCurrentLayerMoves objects to the current layer.MoveToCurrentLayer(Object|SelectedObjects)
NetlistChangedTells the GUI that the netlist has changed.NetlistChanged()oldactions plugin
NetlistDialogOpen the netlist dialog.NetlistDialog()dialogs plugin
NewStarts a new layout.New([name])
NewGroupCreate a new layer group with a single, positive drawn layer in itNewGroup(type [,location [, purpose[, auto|sub]]])
NormalizeMove all objects within the drawing area, align the drawing to 0;0Normalize()
OnelinerExecute a script one-liner using a specific languageOneliner(lang, script)script plugin
OpenemsExcitationSelect which openEMS excitation method should be exported and manipulate the associated parameters. When invoked without arguments a dialog box with the same functionality is presented.OpenemsExcitation([interactive])
OpenemsExcitation(select, excitationname)
OpenemsExcitation(set, [excitationnme], paramname, paramval)
OpenemsExcitation(get, [excitationnme], paramname)
openems HID
OptAutoOnlyToggles the optimize-only-autorouted flag.OptAutoOnly()oldactions plugin
PCBChangedTells the GUI that the whole PCB has changed. The optional "revert"parameter can be used as a hint to the GUI that the same design is beingreloaded, and that it might keep some viewport settingsPCBChanged([revert])oldactions plugin
PadstackBreakupBreak up a padstack into one non-padstack object per layer type (the hole is ignored)PadstackBreakup(buffer|selected|objet)
PadstackConvertConvert selection or current buffer to padstackPadstackConvert(buffer|selected, [originx, originy])
PadstackEditinteractive pad stack editorPadstackEdit(object, [tab])dialogs plugin
PadstackPlacePlace a pad stack (either proto_id, or if not specified, the default for style)PadstackPlace([proto_id|default], [x, y])
PasteBufferVarious operations on the paste buffer.PasteBuffer(AddSelected|Clear|1..PCB_MAX_BUFFER)
PasteBuffer(Rotate, 1..3)
PasteBuffer(Convert|Restore|Mirror)
PasteBuffer(ToLayout, X, Y, units)
PasteBuffer(ToLayout, crosshair)
PasteBuffer(Save, Filename, [format], [force])
PasteBuffer(Push)
PasteBuffer(Pop)
PinoutPresent the subcircuit pinout boxPinout()dialogs plugin
PolyCombinepolycombine plugin
PolyHatchhatch the selected polygon(s) with lines of the current style; lines are drawn on the current layer; flags are h:horizontal, v:vertical, c:contour, p:polyPolyHatch([spacing], [hvcp])
PolyHatch(interactive)
lib_polyhelp
PolyNewCreate an empty polygon. For now data must be "pcb". Use PolyNewPoint to add points. Returns a polygon pointer valid until PolyNewEnd() is called.PolyNew([noundo,] data, layer, ptlist, clearance, flags)act_draw
PolyNewEndClose and place a polygon started by PolyNew. Returns the ID of the new object or 0 on error.PolyNewEnd([noundo,] data, layer, poly)act_draw
PolyNewFromPointsCreate a polygon. For now data must be "pcb". ptlist is a comma separated list of coordinates (untiless coordinates are treated as mm). Returns the ID of the new object or 0 on error.PolyNewFromRectangle([noundo,] data, layer, ptlist, clearance, flags)act_draw
PolyNewFromRectangleCreate a rectangular polygon. For now data must be "pcb". Returns the ID of the new object or 0 on error.PolyNewFromRectangle([noundo,] data, layer, x1, y1, x2, y2, clearance, flags)act_draw
PolyNewPointsAdd a list of points to a polygon created by PolyNew. Returns 0 on success.PolyNewPoints([noundo,] poly, ptlist)act_draw
PolyOffsreplicate the outer contour of the selected polygon(s) with growing or shrinking them by offset; the new polygon is drawn on the current layerPolyOffs(offset)lib_polyhelp
PolyStitchpolystitch plugin
PolygonSome polygon related stuff.Polygon(Close|CloseHole|PreviousPoint)
PreferencesPresent the preferences dialog, optionally opening the tab requested.Preferences([tabname])dialogs plugin
PrintPresent the print export dialog for printing the layout from the GUI.Print()
PrintActionsPrint all actions available.PrintActions()
PrintCalibrateCalibrate the printer.PrintCalibrate()dialogs plugin
PrintCopyrightPrint copyright notice.PrintCopyright()
PrintFilesPrint files currently loaded.PrintFiles()
PrintGUIOpen the print dialog.PrintGUI()dialogs plugin
PrintPathsPrint full paths and search paths.PrintPaths()
PrintUsagePrint command line arguments of pcb-rnd or a plugin loaded.PrintUsage()
PrintUsage(plugin)
PrintVersionPrint version.PrintVersion()
PromptForPrompt for a string. Returns the string (or NULL on cancel)PromptFor([message[,default[,title]]])
PstkNewCreate a padstack. For now data must be "pcb". glob_clearance=0 turns off global clearance. Returns the ID of the new object or 0 on error.PstkNew([noundo,] data, protoID, x, y, glob_clearance, flags)act_draw
PullerPull an arc-line junction tight.pcb_act_Puller()puller plugin
QuitQuits the application after confirming.Quit()
RedoRedo recent "undo" operations.redo()
ReloadScriptReload a fungw scriptReloadScript(id)script plugin
RemoveMenuRecursively removes a new menu, popup (only path specified) or submenu. RemoveMenu(path|cookie)
RemoveSelectedRemoves any selected objects.pcb_remove_selected()
RenumberRenumber all subcircuits. The changes will be recorded to filename
for use in backannotating these changes to the schematic.
Renumber()
Renumber(filename)
renumber plugin
RenumberBlockTODORenumberBlock(old_base,new_base)renumber plugin
RenumberBufferTODORenumberBlock(old_base,new_base)renumber plugin
ReplaceFootprintReplace the footprint of the selected components with the footprint specified.ReplaceFootprint([Selected|Object], [footprint], [dumb])
ReportProduce various report.Report(Object|DrillReport|FoundPins|NetLength|NetLengthTo|AllNetLengths|[,name])report plugin
ReportObjectReport on the object under the crosshairReportObject()report plugin
RipUpRipup auto-routed tracksRipUp(All|Selected|Element)
Rotate90Rotates the object under the crosshair by 90 degree steps.pcb_move_obj(steps)
RouteStyleCopies the indicated routing style into the current pen.RouteStyle(style_id|style_name)
RouteStylesChangedTells the GUI that the routing styles have changed.RouteStylesChanged()oldactions plugin
SaveSave layout data to a user-selected file.Save()
Save(Layout|LayoutAs)
Save(AllConnections|AllUnusedPins|ElementConnections)
Save(PasteBuffer)
dialogs plugin
SaveFontToSave PCB font to a fileSaveFontTo([file, id])
SavePatchSave netlist patch for back annotation.SavePatch(filename)
SaveTedaxSaves the specific type of data in a tEDAx file.SaveTedax(netlist|board-footprints|stackup|layer|board|drc, filename)tEDAx IO
SaveToSaves data to a file.SaveTo(Layout|LayoutAs,filename,[fmt])
SaveTo(PasteBuffer,filename,[fmt])
ScaleBufferScales the buffer by multiplying all coordinates by a floating point number.
If only x is given, it is also used for y and thickness too. If subc is not
empty, subcircuits are also scaled
ScaleBuffer(x [,y [,thickness [,subc]]])
ScriptCookieReturn a cookie specific to the current script instance during script initializationScriptCookie()script plugin
ScriptPersistencyRead or remove script persistency data savd on preunloadScriptPersistency(read|remove)script plugin
SelectToggles or sets the selection.Select(Object|ToggleObject)
Select(All|Block|Connection|Invert)
Select(Convert)
SelectLayerSelect which layer is the current layer.SelectLayer(1..MAXLAYER|Silk|Rats)
SetFlagSets flags on objects.SetFlag(Object|Selected|SelectedObjects, flag)
SetFlag(SelectedLines|SelectedPins|SelectedVias, flag)
SetFlag(SelectedPads|SelectedTexts|SelectedNames, flag)
SetFlag(SelectedElements, flag)
flag = thermal | join
SetOctagonoldactions plugin
SetSameSets current layer and sizes to match indicated item.SetSame()
SetSquareoldactions plugin
SetThermalSet the thermal (on the current layer) of padstacks to the given style.
Style = 0 means no thermal.
Style = 1 has diagonal fingers with sharp edges.
Style = 2 has horizontal and vertical fingers with sharp edges.
Style = 3 is a solid connection to the plane.
Style = 4 has diagonal fingers with rounded edges.
Style = 5 has horizontal and vertical fingers with rounded edges.
SetThermal(Object|SelectedPins|SelectedVias|Selected, Style)
SetUnitsSet the default measurement units.SetUnits(mm|mil)
SetValueChange various board-wide values and sizes.SetValue(Grid|Line|LineSize|Text|TextScale, delta)
SwitchHIDSwitch to another HID.SwitchHID(lesstif|gtk|batch)
SystemRun shell commandSystem(shell_cmd)
Teardropsteardrops plugin
TextNewCreate a pcb text on a layer. For now data must be "pcb". Font id 0 is the default font. Thickness 0 means default, calculated thickness. Scale=100 is the original font size. Returns the ID of the new object or 0 on error.TextNew([noundo,] data, layer, fontID, x, y, rot, scale, thickness, test_string, flags)act_draw
ToPolyconvert a closed loop of lines and arcs into a polygonToPoly()
ToPoly(outline)
lib_polyhelp
ToggleHideNameoldactions plugin
ToggleVendorToggles the state of automatic drill size mapping.ToggleVendor()oldactions plugin
ToggleViewToggle the visibility of the specified layer or layer group.ToggleView(1..MAXLAYER)
ToggleView(layername)
ToggleView(Silk|Rats|Pins|Vias|BackSide)
ToggleView(All, Open|Vis, Set|Clear|Toggle)
UndoUndo recent changes.undo()
undo(ClearList)
UndoDialogOpen the undo dialog.UndoDialog()dialogs plugin
UnloadScriptUnload a fungw scriptUnloadScript(id)script plugin
UnloadVendorUnloads the current vendor drill mapping table.UnloadVendor()vendor drill mapping
UnselectUnselects the object at the pointer location or the specified objects.Unselect(All|Block|Connection)
ViewListPresent a new empty view listviewlist([name, [winid]])dialogs plugin
acompnetAttempt to auto-complete the current networkacompnet()acompnet plugin
alignAlign subcircuitsAlign(X/Y, [Lefts/Rights/Tops/Bottoms/Centers/Marks, [First/Last/pcb_crosshair/Average[, Gridless]]])distalign plugin
aligntextAlign Text ElementsAlignText(X/Y, [Lefts/Rights/Tops/Bottoms/Centers, [First/Last/pcb_crosshair/Average[, Gridless]]])distaligntext plugin
asmInteractive assembly assistantasm()asm plugin
autocropAutocrops the board dimensions to (extants + a margin of 1 grid), keeping the move and board size grid alignedautocrop()autocrop plugin
awkExecute a script one-liner using a specific languageOneliner(lang, script)script plugin
camExport jobs for feeding cam processescam(exec, script, [options])
cam(call, jobname, [options])
cam([gui])
cam exporter
circleGenerate a filled circle (zero length round cap line)circle([where,] diameter)shape plugin
claimnetClaim existing connections and create a new netClaimNet(object|selected|found,[netname])
cli_MessageBoxIntenal: CLI frontend action. Do not use directly.
cli_PromptForIntenal: CLI frontend action. Do not use directly.
confPerform various operations on the configuration tree.conf(set, path, value, [role], [policy]) - change a config setting to an absolute value
conf(delta, path, value, [role], [policy]) - change a config setting by a delta value (numerics-only)
conf(toggle, path, [role]) - invert boolean value of a flag; if no role given, overwrite the highest prio config
conf(reset, role) - reset the in-memory lihata of a role
conf(iseq, path, value) - returns whether the value of a conf item matches value (for menu checked's)
constraintConfigure or remove a drawing constraintconstraint(type, off)
constraint(type, value, [value...])
ddraft plugin
cpcbExecuted external autorouter cpcb to route the board or parts of the boardcpcb(board|selected, [command])cpcb plugin
d1debug action for developmentd1()diag plugin
dadManipulate Dynamic Attribute Dialogsdad(dlgname, new) - create new dialog
dad(dlgname, label, text) - append a label widget
dad(dlgname, button, text) - append a button widget
dad(dlgname, button_closes, label, retval, ...) - standard close buttons
dad(dlgname, enum, choices) - append an enum (combo box) widget; choices is a tab separated list
dad(dlgname, bool, [label]) - append an checkbox widget (default off)
dad(dlgname, integer|real|coord, min, max, [label]) - append an input field
dad(dlgname, string) - append a single line text input field
dad(dlgname, progress) - append a progress bar (set to 0)
dad(dlgname, tree, cols, istree, [header]) - append tree-table widget; header is like enum values
dad(dlgname, tree_append, row, cells) - append after row (0 means last item of the root); cells is like enum values; returns a row pointer
dad(dlgname, tree_append_under, row, cells) - append at the end of the list under row (0 means last item of the root); cells is like enum values; returns a row pointer
dad(dlgname, tree_insert, row, cells) - insert before row (0 means first item of the root); cells is like enum values; returns a row pointer
dad(dlgname, begin_hbox) - begin horizontal box
dad(dlgname, begin_vbox) - begin vertical box
dad(dlgname, begin_hpane) - begin horizontal paned box
dad(dlgname, begin_vpane) - begin vertical paned box
dad(dlgname, begin_table, cols) - begin table layout box
dad(dlgname, begin_tabbed, tabnames) - begin a view with tabs; tabnames are like choices in an enum; must have as many children widgets as many names it has
dad(dlgname, end) - end the last begin
dad(dlgname, flags, flg1, flg2, ...) - change the flags of the last created widget
dad(dlgname, onchange, action) - set the action to be called on widget change
dad(dlgname, run, title) - present dlgname as a non-modal dialog
dad(dlgname, run_modal, title) - present dlgname as a modal dialog
dad(dlgname, exists) - returns wheter the named dialog exists (0 or 1)
dad(dlgname, set, widgetID, val) - changes the value of a widget in a running dialog
dad(dlgname, get, widgetID, [unit]) - return the current value of a widget
dialogs plugin
ddraftEnter 2d drafting CLI mode or execute commandddraft([command])ddraft plugin
distributeDistribute subcircuitsDistribute(X/Y, [Lefts/Rights/Tops/Bottoms/Centers/Marks/Gaps, [First/Last/pcb_crosshair, First/Last/pcb_crosshair[, Gridless]]])distalign plugin
distributetextDistribute Text ElementsDistributeText(Y, [Lefts/Rights/Tops/Bottoms/Centers/Gaps, [First/Last/pcb_crosshair, First/Last/pcb_crosshair[, Gridless]]])distaligntext plugin
djoptPerform various optimizations on the current board.djopt(debumpify|unjaggy|simple|vianudge|viatrim|orthopull)
djopt(auto) - all of the above
djopt(miter)
djopt
dlg_testtest the attribute dialogdlg_test()dialogs plugin
dumpconfPerform various operations on the configuration tree.dumpconf(native, [verbose], [prefix]) - dump the native (binary) config tree to stdout
dumpconf(lihata, role, [prefix]) - dump in-memory lihata representation of a config tree
diag plugin
dumpdataDump an aspect of the datadumpdata()diag plugin
dumpflagsdump flags, optionally using the format string provided by the userdumpflags([fmt])diag plugin
dumpfontsPrint info about fontsdumpfonts()diag plugin
dumpidsDump the ID hashDumpIDs()diag plugin
dumplayersPrint info about each layerdumplayers([all])diag plugin
dumpundoPrint info about fontsdumpfonts()diag plugin
estutterExecute a script one-liner using a specific languageOneliner(lang, script)script plugin
exteditextedit(object|selected|buffer, [interactive|method])Invoke an external program to edit a specific part of the current board.extedit plugin
find2perfMeasure the peformance of find2.cfind2perf()diag plugin
forcecolorchange selected objects' color to #RRGGBB, reset if does not start with '#'forcecolor(#RRGGBB)diag plugin
fp_rehashFlush the library index; rescan all library search paths and rebuild the library index. Useful if there are changes in the library during a pcb-rnd session.fp_rehash()
gui_FallbackColorPickIntenal: GUI frontend action. Do not use directly.dialogs plugin
gui_MessageBoxIntenal: GUI frontend action. Do not use directly.dialogs plugin
gui_PromptForIntenal: GUI frontend action. Do not use directly.dialogs plugin
hPrint a help message for commands.hshand_cmd plugin
integrityperform integrirty check on the current board and generate errors if neededintegrity()diag plugin
javascriptExecute a script one-liner using a specific languageOneliner(lang, script)script plugin
jostleMake room by moving wires away.Jostle(diameter)jostle plugin
jsExecute a script one-liner using a specific languageOneliner(lang, script)script plugin
lLoads layout data.l [name] [format]shand_cmd plugin
leLoads an element (subcircuit, footprint) into the current buffer.le [name]shand_cmd plugin
luaExecute a script one-liner using a specific languageOneliner(lang, script)script plugin
mLoads a layout into the current buffer.m [name]shand_cmd plugin
mawkExecute a script one-liner using a specific languageOneliner(lang, script)script plugin
meshgenerate a mesh for simulationmesh()openems HID
millCalculate toolpath for milling away coppermill()millpath plugin
mrubyExecute a script one-liner using a specific languageOneliner(lang, script)script plugin
netPerform various actions on netlists.Net(find|select|rats|norats||ripup|addrats|clear[,net[,pin]])
Net(freeze|thaw|forcethaw)
Net(swap)
Net(add,net,pin)Net([rename|merge],srcnet,dstnet)
netlistPerform various actions on netlists.Net(find|select|rats|norats||ripup|addrats|clear[,net[,pin]])
Net(freeze|thaw|forcethaw)
Net(swap)
Net(add,net,pin)Net([rename|merge],srcnet,dstnet)
paralDraw a line perpendicular to another lineperp()ddraft plugin
perlExecute a script one-liner using a specific languageOneliner(lang, script)script plugin
perpDraw a line perpendicular to another lineperp()ddraft plugin
propeditpropedit(object[:id]|layer[:id]|layergrp[:id]|pcb|selection|selected)propedit
propprintPrint a property map of objects matching the scope. Scope is documented at PropEdit().PropPrint([scope])propedit
propsetChange the named property of all selected objects to/by value. Scope is documented at PropEdit().propset([scope], name, value)propedit
pscalibps HID
pstklibPresent the padstack library dialog on board padstacks or the padstacks of a subcircuitpstklib([board|subcid|object])dialogs plugin
pyExecute a script one-liner using a specific languageOneliner(lang, script)script plugin
pythonExecute a script one-liner using a specific languageOneliner(lang, script)script plugin
q!Quits the application without confirming.q!shand_cmd plugin
qQuits the application after confirming.qshand_cmd plugin
queryPerform various queries on PCB data.query(dump, expr) - dry run: compile and dump an expression
regpolyGenerate regular polygon. Where is x;y and radius is either r or rx;ry. Rotation is in degrees.regpoly([where,] corners, radius [,rotation])shape plugin
rnReads netlist.rn [name]shand_cmd plugin
roundrectGenerate a rectangle with round cornersroundrect([where,] width[;height] [,rx[;ry] [,rotation [,cornstyle [,roundness]]]])shape plugin
rubyExecute a script one-liner using a specific languageOneliner(lang, script)script plugin
sSaves layout data.s [name]
w [name]
shand_cmd plugin
shapeInteractive shape generator.shape()shape plugin
sklineTool for drawing sketch linesskline()sketch_route plugin
skretriangulateReconstruct CDT on all layer groupsskretriangulate()sketch_route plugin
sktransformTransform sketch to geometrical wiringsktransform(rect|oct|alldir)sketch_route plugin
smartdisperseDisperse subcircuits into clusters, by netlist connectionsSmartDisperse([All|Selected])smartdisperse plugin
splitUse one or more objects as cutting edge and trim or split other objects. First argument is the cutting edgetrim([selected|found|object], [selected|found|object])
split([selected|found|object], [selected|found|object])
ddraft plugin
strokeVarious gesture recognition related functionsstroke(gesture, seq)stroke plugin
sttExecute a script one-liner using a specific languageOneliner(lang, script)script plugin
subcVarious operations on subcsubc(hash, [board|selected])
subc(loose, on|off|toggle|check)
tangDraw a line to be tangential to a circletang()ddraft plugin
tclExecute a script one-liner using a specific languageOneliner(lang, script)script plugin
trimUse one or more objects as cutting edge and trim or split other objects. First argument is the cutting edgetrim([selected|found|object], [selected|found|object])
split([selected|found|object], [selected|found|object])
ddraft plugin
wSaves layout data.s [name]
w [name]
shand_cmd plugin
wqSaves the layout data and quits.wqshand_cmd plugin
+ + Index: tags/2.1.2/doc/user/09_appendix/action_src/addrats.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/addrats.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/addrats.html (revision 24813) @@ -0,0 +1,15 @@ +Arguments: +

+ +
AllRats + Create rat lines for all loaded nets that aren't already connected on + with copper. + +
SelectedRats + Similarly, but only add rat lines for nets connected to selected pins + and pads. + +
@item Close + Selects the shortest unselected rat on the board. +
+ Index: tags/2.1.2/doc/user/09_appendix/action_src/addtimer.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/addtimer.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/addtimer.html (revision 24813) @@ -0,0 +1,24 @@ +This action is intended for scripts to create async timers. Note: +timers do not work with the batch HID (no callback issued ever). +

+Creates a timer that executes an action (by name) periodically. +Period is a real number specified in seconds. Internal timer +resolution is in the order of 0.1 second. +

+If repeat is not specified or is less than 1, the timer is repeated +indefinitely. If the optional userdata string is specified, it is +also passed to the action. +

+The action is specified only by a name, call arguments are always +the following: +

    +
  • now: the current UNIX time in a floating point number +
  • integer: count back remaining number of calls, including the current call; 1 means this was the last call; 0 means infinite number of calls will follow +
  • userdata or empty string +
+

+Action shall return integer 0 on success. +If the action does not exist or returns anything else, the timer is +uninstalled. +

+There can be any number of timers in parallel. Index: tags/2.1.2/doc/user/09_appendix/action_src/adjuststyle.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/adjuststyle.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/adjuststyle.html (revision 24813) @@ -0,0 +1 @@ +Opens the window which allows editing of the route styles. Index: tags/2.1.2/doc/user/09_appendix/action_src/align.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/align.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/align.html (revision 24813) @@ -0,0 +1,23 @@ +Align(X, [Lefts/Rights/Centers/Marks, [First/Last/pcb_crosshair/Average[, Gridless]]]) +

+Align(Y, [Tops/Bottoms/Centers/Marks, [First/Last/pcb_crosshair/Average[, Gridless]]]) +

+Arguments: +

+ +
X or Y + Select which axis will move, other is untouched. + +
Lefts, Rights, Tops, Bottoms, Centers, Marks + Pick alignment point within each subcircuit + +
First, Last, pcb_crosshair, Average + Alignment reference, First=Topmost/Leftmost, Last=Bottommost/Rightmost, Average or pcb_crosshair point + +
Gridless + Do not force results to align to prevailing grid. + +
+

+Defaults are Marks, First. + Index: tags/2.1.2/doc/user/09_appendix/action_src/aligntext.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/aligntext.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/aligntext.html (revision 24813) @@ -0,0 +1,22 @@ +

+AlignText(X, [Lefts/Rights/Centers, [First/Last/pcb_crosshair/Average[, Gridless]]]) +

+AlignText(Y, [Tops/Bottoms/Centers, [First/Last/pcb_crosshair/Average[, Gridless]]]) +

+Arguments: +

+ +
X or Y + Select which axis will move, other is untouched. + +
Lefts, Rights, Tops, Bottoms, Centers + Pick alignment point within each element.
NB: text objects have no Mark. + +
First, Last, pcb_crosshair, Average + Alignment reference, First=Topmost/Leftmost, Last=Bottommost/Rightmost, Average or pcb_crosshair point \n + +
Gridless + Do not force results to align to prevailing grid. \n +
+

+Defaults are Lefts/Tops, First Index: tags/2.1.2/doc/user/09_appendix/action_src/applyvendor.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/applyvendor.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/applyvendor.html (revision 24813) @@ -0,0 +1,2 @@ +This will modify all of your drill holes to match the list of allowed +sizes for your vendor. Index: tags/2.1.2/doc/user/09_appendix/action_src/atomic.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/atomic.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/atomic.html (revision 24813) @@ -0,0 +1,27 @@ +This action allows making multiple-action bindings into an atomic +operation that will be undone by a single Undo command. For example, +to optimize rat lines, you'd delete the rats and re-add them. To +group these into a single undo, you'd want the deletions and the +additions to have the same undo serial number. So, you Save, +delete the rats, Restore, add the rats - using the same serial +number as the deletes, then Block, which checks to see if the +deletions or additions actually did anything. If not, the serial +number is set to the saved number, as there's nothing to undo. If +something did happen, the serial number is incremented so that these +actions are counted as a single undo step. +

+Arguments: +

+ +
Save + Saves the undo serial number. + +
Restore + Returns it to the last saved number. + +
Close + Sets it to 1 greater than the last save. + +
Block + Does a Restore if there was nothing to undo, else does a Close. +
Index: tags/2.1.2/doc/user/09_appendix/action_src/attributes.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/attributes.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/attributes.html (revision 24813) @@ -0,0 +1,3 @@ +Pops up a dialog letting the user edit the attributes of the +pcb, a subcircuit, or a layer. + Index: tags/2.1.2/doc/user/09_appendix/action_src/autoplaceselected.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/autoplaceselected.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/autoplaceselected.html (revision 24813) @@ -0,0 +1,2 @@ +Attempts to re-arrange the selected components such that the nets +connecting them are minimized. Note that you cannot undo this. Index: tags/2.1.2/doc/user/09_appendix/action_src/autoroute.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/autoroute.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/autoroute.html (revision 24813) @@ -0,0 +1,18 @@ +Before autorouting, it's important to set up a few things. First, +make sure any layers you aren't using are disabled, else the +autorouter may use them. Next, make sure the current routing +styles are set accordingly. Last, make sure "new lines clear +polygons" is set, in case you eventually want to add a copper pour. +

+Autorouting takes a while. During this time, the program may not be +responsive. +

+Arguments: +

+ +
AllRats + Attempt to autoroute all rats. + +
SelectedRats + Attempt to autoroute the selected rats. +
Index: tags/2.1.2/doc/user/09_appendix/action_src/benchmark.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/benchmark.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/benchmark.html (revision 24813) @@ -0,0 +1,3 @@ +This action is used to speed-test the GUI rendering. It +redraws the current screen as many times as possible in ten seconds. +It reports the amount of time needed to draw the screen once, in average. Index: tags/2.1.2/doc/user/09_appendix/action_src/boardflip.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/boardflip.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/boardflip.html (revision 24813) @@ -0,0 +1,12 @@ +All objects on the board are up-down flipped (mirrored over the x axis). +

+Command line board flipping: +

+echo "
+BoardFlip()
+SaveTo(LayoutAs,$OUTFILE)
+Quit()
+" | pcb $INFILE
+
+

+To flip the board physically, use BoardFlip(sides) Index: tags/2.1.2/doc/user/09_appendix/action_src/center.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/center.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/center.html (revision 24813) @@ -0,0 +1,2 @@ +Move the pointer to the center of the window, but only if it's +currently within the window already. Index: tags/2.1.2/doc/user/09_appendix/action_src/changeclearsize.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/changeclearsize.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/changeclearsize.html (revision 24813) @@ -0,0 +1,3 @@ +If the solder mask is currently showing, this action changes the +solder mask cutout size. If the mask is not showing, this action +changes the polygon clearance. Index: tags/2.1.2/doc/user/09_appendix/action_src/changeflag.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/changeflag.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/changeflag.html (revision 24813) @@ -0,0 +1,4 @@ +Toggles the given flag on the indicated object(s). The flag may be +one of the flags listed above (thermal, join). The +value may be the number 0 or 1. If the value is 0, the flag is +cleared. If the value is 1, the flag is set. Index: tags/2.1.2/doc/user/09_appendix/action_src/changejoin.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/changejoin.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/changejoin.html (revision 24813) @@ -0,0 +1,5 @@ +The join flag determines whether a line or arc, drawn to intersect a +polygon, electrically connects to the polygon or not. When joined, +the line/arc is simply drawn over the polygon, making an electrical +connection. When not joined, a gap is drawn between the line and the +polygon, insulating them from each other. Index: tags/2.1.2/doc/user/09_appendix/action_src/changename.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/changename.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/changename.html (revision 24813) @@ -0,0 +1,22 @@ +Arguments: +

+ + +
Object + Changes the "name" of the object under the cursor. For a text object + this is the text string. For a terminal, this is the terminal ID. + For a subcircuit this is the refdes. For a subc text object that has + only the refdes template in it, it offers changing the text object + (template) or the parent subcircuit's refdes attribute. + +
Refdes + Changes the refdes attribute of a subcircuit under the cursor. + +
Layout + Changes the name of the layout. This is printed on the fab drawings. + +
Layer + Changes the name of the currently active layer. + +
+ Index: tags/2.1.2/doc/user/09_appendix/action_src/changepinname.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/changepinname.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/changepinname.html (revision 24813) @@ -0,0 +1,5 @@ +This can be especially useful for annotating pin names from a +schematic to the layout without requiring knowledge of the pcb file +format. +

+ChangePinName(U3, 7, VCC) Index: tags/2.1.2/doc/user/09_appendix/action_src/changesize.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/changesize.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/changesize.html (revision 24813) @@ -0,0 +1,6 @@ +For lines and arcs, this changes the width. For padstacks, this +changes the shape size (but does not touch the hole diameter). For +texts, this changes the scaling factor. For subcircuits, this +changes the width of the silk layer lines and arcs for this subcircuit +(TODO: is this still true?). + Index: tags/2.1.2/doc/user/09_appendix/action_src/changesizes.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/changesizes.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/changesizes.html (revision 24813) @@ -0,0 +1,2 @@ +Call ChangeSize, ChangeDrillSize and ChangeClearSize +with the same arguments. If any of them did not fail, return success. Index: tags/2.1.2/doc/user/09_appendix/action_src/chklayer.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/chklayer.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/chklayer.html (revision 24813) @@ -0,0 +1 @@ +Returns 1 if the specified layer is the active layer. Index: tags/2.1.2/doc/user/09_appendix/action_src/chkrst.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/chkrst.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/chkrst.html (revision 24813) @@ -0,0 +1 @@ +Return 1 if route_style_id matches pen. Index: tags/2.1.2/doc/user/09_appendix/action_src/chkview.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/chkview.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/chkview.html (revision 24813) @@ -0,0 +1 @@ +Return 1 if layerid is visible. Intended for menu item 'checked' fields. Index: tags/2.1.2/doc/user/09_appendix/action_src/claimnet.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/claimnet.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/claimnet.html (revision 24813) @@ -0,0 +1,16 @@ +The ClaimNet() action can be used to construct network metadata +(netlist entry) converting existing physical (galvanic, copper) connections +or object lists. +

+When galvanic connections are mapped, the first argument shall be object; +in this case the object under the mouse cursor is the starting point and +anything galvanically connected (at the moment) is considered part of the new +network. This mode of operation is useful for capturing existing nets. +

+When the first argument is selected or found, the +list of (selected or found) terminals are converted to a new net, regardless +of galvanic connections. This mode is useful for designing a PCB by a netlist +but without a schematics - in this setup the netlist is "drawn" in pcb-rnd as +well. +

+If netname is specified, the user is prompted for a name. Index: tags/2.1.2/doc/user/09_appendix/action_src/clrflag.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/clrflag.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/clrflag.html (revision 24813) @@ -0,0 +1,4 @@ +Turns the given flag off, regardless of its previous setting. See +ChangeFlag. +

+ClrFlag(SelectedLines,join) Index: tags/2.1.2/doc/user/09_appendix/action_src/command.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/command.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/command.html (revision 24813) @@ -0,0 +1,12 @@ +The command window allows the user to manually enter actions to be +executed. +

+There are two ways to finish with the command window. If you press +the Enter key, the command is invoked, the entry normally goes away, +and the next time you bring up the command window it's empty. If you +press the Esc key, the window goes away without invoking +anything, and the next time you bring up the command window it's +empty. +

+Use the up and down arrow keys to access command history. + Index: tags/2.1.2/doc/user/09_appendix/action_src/connection.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/connection.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/connection.html (revision 24813) @@ -0,0 +1,28 @@ +Connections found with this action will be highlighted in the +"connected-color" color and will have the "found" flag set. +

+Arguments: +

+ +
Find + The net under the cursor is "found". + +
ResetLayerObjects + Any "found" layer objects (lines, arcs, polygons and texts) are + marked "not found". + +
ResetPadstacks + Any "found" padstack are marked "not found". WARNING: does not + touch non-padstack heavy terminals! + +
Reset + All "found" objects are marked "not found". + +
ResetLinesAndPolygons + Obsolate, misleading name for ResetLayerObjects. Do not use. + +
ResetPinsAndVias + Obsolate, misleading name for ResetPadstacks. Do not use. + +
+ Index: tags/2.1.2/doc/user/09_appendix/action_src/cursor.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/cursor.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/cursor.html (revision 24813) @@ -0,0 +1,29 @@ +This action moves the mouse cursor. Unlike other actions which take +coordinates, this action's coordinates are always relative to the +user's view of the board. Thus, a positive DeltaUp may move the +cursor away from the board origin if the board is inverted (flipped, +looked from the bottom). +

+Type is one of Pan or Warp. Pan causes the +viewport to move such that the crosshair is under the mouse cursor. +Warp causes the mouse cursor to move to be above the crosshair. +

+Units can be one of the following: +

+ +
mil
mm +
The cursor is moved by that amount, in board units. + +
grid + The cursor is moved by that many grid points. + +
view + The values are percentages of the viewport's view. Thus, a pan of + 100 would scroll the viewport by exactly the width of the current view. + + +
board + The values are percentages of the board size. Thus, a move of + 50,50 moves you halfway across the board. + +
Index: tags/2.1.2/doc/user/09_appendix/action_src/cycledrag.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/cycledrag.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/cycledrag.html (revision 24813) @@ -0,0 +1,8 @@ +When multiple overlapping objects are accessible by clicking on a pixel +on the screen, drag&drop operations may become harder to do: pcb-rnd will +often "pick the wrong object" on click. +

+Cycledraw provides a way to get pcb-rnd to jump to selecting another object +of the avaialble ones on the original site, while the user is still in drag +mode. This obviously works only through the key binding, as selecting the +menu would require the drag operation to finish first. Index: tags/2.1.2/doc/user/09_appendix/action_src/disperseelements.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/disperseelements.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/disperseelements.html (revision 24813) @@ -0,0 +1,5 @@ +Normally this is used when starting a board, by selecting all subcircuits +and then dispersing them. This scatters the subcircuits around the board +so that you can pick individual ones, rather than have all the +subcircuits at the same 0,0 coordinate and thus impossible to choose +from. Index: tags/2.1.2/doc/user/09_appendix/action_src/display.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/display.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/display.html (revision 24813) @@ -0,0 +1,121 @@ +Changes random display related global states. +

+ +
SubcID
Description
Value +
Specify the subcircuit ID template to be printed on the subcircuit layer + +
Redraw + Redraw the whole board. + +
ToggleAllDirections + When clear, lines can be drawn at any angle. When set, lines are + restricted to multiples of 45 degrees and requested lines may be + broken up according to the clip setting. + +
CycleClip + Changes the way lines are restricted to 45 degree increments. The + various settings are: straight only, orthogonal then angled, and angled + then orthogonal. If AllDirections is set, this action disables it. + +
CycleCrosshair + Changes crosshair drawing. Crosshair may accept form of 4-ray, + 8-ray and 12-ray cross. + +
ToggleRubberBandMode + If set, moving an object moves all the lines attached to it too. + +
ToggleStartDirection + If set, each time you set a point in a line, the Clip toggles between + orth-angle and angle-ortho. + +
ToggleUniqueNames + If set, you will not be permitted to change the name of an element to + match that of another element. + +
ToggleSnapPin + If set, pin centers and pad end points are treated as additional grid + points that the cursor can snap to. + +
ToggleSnapOffGridLine + If set, snap at some sensible point along a line. + +
ToggleHighlightOnPoint + If set, highlights lines and arcs when the crosshair is on one of their + two (end) points. + +
ToggleLocalRef + If set, the mark is automatically set to the beginning of any move, so + you can see the relative distance you've moved. + +
ToggleThindraw + If set, objects on the screen are drawn as outlines (lines are drawn + as center-lines). This lets you see line endpoints hidden under pins, + for example. + +
ToggleThindrawPoly + If set, polygons on the screen are drawn as outlines. + +
ToggleShowDRC + If set, pending objects (i.e. lines you're in the process of drawing) + will be drawn with an outline showing how far away from other copper + you need to be. + +
ToggleLiveRoute + If set, the progress of the autorouter will be visible on the screen. + +
ToggleAutoDRC + If set, you will not be permitted to make connections which violate + the current DRC and netlist settings. + +
ToggleCheckPlanes + If set, lines and arcs aren't drawn, which usually leaves just the + polygons. If you also disable all but the layer you're interested in, + this allows you to check for isolated regions. + +
ToggleOrthoMove + If set, the crosshair is only allowed to move orthogonally from its + previous position. I.e. you can move a subcircuit or line up, down, + left, or right, but not up+left or down+right. + +
ToggleName + Selects whether the pinouts show the pin names or the pin numbers. + +
ToggleLockNames + If set, text will ignore left mouse clicks and actions that work on + objects under the mouse. You can still select text with a lasso (left + mouse drag) and perform actions on the selection. + +
ToggleOnlyNames + If set, only text will be sensitive for mouse clicks and actions that + work on objects under the mouse. You can still select other objects + with a lasso (left mouse drag) and perform actions on the selection. + +
ToggleClearLine + When set, the clear-line flag causes new lines and arcs to have their + "clear polygons" flag set, so they won't be electrically connected + to any polygons they overlap. + +
ToggleFullPoly + When set, the full-poly flag causes new polygons to have their + "full polygon" flag set, so all parts of them will be displayed + instead of only the biggest one. + +
ToggleGrid + Resets the origin of the current grid to be wherever the crosshair is. + If you provide two numbers after this, the origin is set to that + coordinate. + +
Grid + Toggles whether the grid is displayed or not. + +
Pinout + Causes the pinout of the subcircuit indicated by the cursor to be + displayed, usually in a separate window. + +
PinOrPadName + Toggles whether the names of terminals will be + displayed. If the cursor is over an subcircuit, all of its terminals + are affected. + +
+ Index: tags/2.1.2/doc/user/09_appendix/action_src/distribute.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/distribute.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/distribute.html (revision 24813) @@ -0,0 +1,20 @@ +Distribute(X, [Lefts/Rights/Centers/Marks/Gaps, [First/Last/pcb_crosshair, First/Last/pcb_crosshair[, Gridless]]]) +

+Distribute(Y, [Tops/Bottoms/Centers/Marks/Gaps, [First/Last/pcb_crosshair, First/Last/pcb_crosshair[, Gridless]]]) +

+As with align, plus: +

+Arguments: +

+ +
Gaps + Make gaps even rather than spreading points evenly. + +
First, Last, pcb_crosshair + Two arguments specifying both ends of the distribution, they can't both be the same. +
+

+Defaults are Marks, First, Last +

+Distributed subcircuits always retain the same relative order they had +before they were distributed. Index: tags/2.1.2/doc/user/09_appendix/action_src/distributetext.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/distributetext.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/distributetext.html (revision 24813) @@ -0,0 +1,20 @@ +

+DistributeText(X, [Lefts/Rights/Centers/Gaps, [First/Last/pcb_crosshair, First/Last/pcb_crosshair[, Gridless]]]) +

+DistributeText(Y, [Tops/Bottoms/Centers/Gaps, [First/Last/pcb_crosshair, First/Last/pcb_crosshair[, Gridless]]]) +

+As with align, plus: +

+ +
Gaps + Make gaps even rather than spreading points evenly. + +
First, Last, pcb_crosshair + Two arguments specifying both ends of the distribution, they can't both be the same. + +
+

+Defaults are Lefts/Tops, First, Last +

+Distributed texts always retain the same relative order they had +before they were distributed. Index: tags/2.1.2/doc/user/09_appendix/action_src/djopt.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/djopt.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/djopt.html (revision 24813) @@ -0,0 +1,47 @@ +The different types of optimizations change your board in order to +reduce the total trace length and via count. +

+Arguments: +

+ + +
debumpify + Looks for U-shaped traces that can be shortened or eliminated. + +
unjaggy + Looks for corners which could be flipped to eliminate one or more + corners (i.e. jaggy lines become simpler). + +
simple + Removing uneeded vias, replacing two or more trace segments in a row + with a single segment. This is usually performed automatically after + other optimizations. + +
vianudge + Looks for vias where all traces leave in the same direction. Tries to + move via in that direction to eliminate one of the traces (and thus a + corner). + +
viatrim + Looks for traces that go from via to via, where moving that trace to a + different layer eliminates one or both vias. + +
orthopull + Looks for chains of traces all going in one direction, with more + traces orthogonal on one side than on the other. Moves the chain in + that direction, causing a net reduction in trace length, possibly + eliminating traces and/or corners. + +
splitlines + Looks for lines that pass through vias, pins, or pads, and splits them + into separate lines so they can be managed separately. + +
auto + Performs the above options, repeating until no further optimizations + can be made. + +
miter + Replaces 90 degree corners with a pair of 45 degree corners, to reduce + RF losses and trace length. + +
Index: tags/2.1.2/doc/user/09_appendix/action_src/dowindows.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/dowindows.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/dowindows.html (revision 24813) @@ -0,0 +1,27 @@ +Argument: +

+ +
1
Layout +
Open the layout window. Since the layout window is always shown anyway, this has no effect. + +
2
Library +
Open the library window. + +
3
Log +
Open the log window. + +
4
Netlist +
Open the netlist window. + +
5
Preferences +
Open the preferences window. + +
6
DRC +
Open the DRC violations window. + +
7
Search +
Open the advanced search window. + +
+ + Index: tags/2.1.2/doc/user/09_appendix/action_src/drc.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/drc.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/drc.html (revision 24813) @@ -0,0 +1,12 @@ +Output styles available: + +
name description +
list display a full list of all violations, with preview of the current item (large dialog) +
simple a small & simple dialog that navigates the user through the violations one by one, sequentially +
print print the list to stdout in human readable form +
log print the list as INFO lines in the log in human readable form +
dump print the list to stdout in script readable form +
+

+Note that the design rule check uses the current board rule settings, +not the current style settings. Index: tags/2.1.2/doc/user/09_appendix/action_src/elementlist.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/elementlist.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/elementlist.html (revision 24813) @@ -0,0 +1,22 @@ +Arguments: +

+ +
Start + Indicates the start of an subcircuit list; call this before any + Need actions. + +
Need + Searches the board for an subcircuit with a matching refdes.
+ If found, the value and footprint are updated.
+ If not found, a new subcircuit is created with the given + footprint and value. + +
Done + Compares the list of subcircuits needed since the most recent + Start with the list of subcircuits actually on the + board. Any subcircuits that weren't listed are selected, so + that the user may delete them. + +
+ + Index: tags/2.1.2/doc/user/09_appendix/action_src/elementsetattr.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/elementsetattr.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/elementsetattr.html (revision 24813) @@ -0,0 +1,4 @@ +If a value is specified, the named attribute is added (if not already +present) or changed (if it is) to the given value. If the value is +not specified, the given attribute is removed if present. + Index: tags/2.1.2/doc/user/09_appendix/action_src/executefile.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/executefile.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/executefile.html (revision 24813) @@ -0,0 +1,2 @@ +Lines starting with # are ignored. + Index: tags/2.1.2/doc/user/09_appendix/action_src/exportoldconn.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/exportoldconn.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/exportoldconn.html (revision 24813) @@ -0,0 +1,14 @@ +Arguments: +

+ + +
AllConnections + Save all connections to a file. + +
AllUnusedPins + List all unconnected terminals to a file. + +
ElementConnections + Save connections to the subcircuit at the cursor to a file. + +
Index: tags/2.1.2/doc/user/09_appendix/action_src/flip.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/flip.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/flip.html (revision 24813) @@ -0,0 +1,6 @@ +Note that the location of the subcircuit will be symmetric about the +cursor location; i.e. if the part you are pointing at will still be at +the same spot once the subcircuit is on the other side. When flipping +multiple subcircuits, this retains their positions relative to each +other, not their absolute positions on the board. + Index: tags/2.1.2/doc/user/09_appendix/action_src/freerotatebuffer.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/freerotatebuffer.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/freerotatebuffer.html (revision 24813) @@ -0,0 +1,2 @@ +Rotates the contents of the pastebuffer by an arbitrary angle. If no +angle is given, the user is prompted for one. Index: tags/2.1.2/doc/user/09_appendix/action_src/getxy.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/getxy.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/getxy.html (revision 24813) @@ -0,0 +1 @@ +Prompts the user for a coordinate, if one is not already selected. Index: tags/2.1.2/doc/user/09_appendix/action_src/import.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/import.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/import.html (revision 24813) @@ -0,0 +1,94 @@ +Imports subcircuits and netlist data from the schematics (or some other +source). The first parameter, which is optional, is the mode. If not +specified, the import::mode attribute in the board is used. +Possible values: +gnetlist means gnetlist is used to obtain the information from +the schematics; make invokes make, assuming the user +has a Makefile in the current directory. The Makefile +will be invoked with the following variables set: +

+ + +
PCB + The name of the .pcb file + +
SRCLIST + A space-separated list of source files + +
OUT + The name of the file in which to put the command script, which may + contain any @pcb{} actions. By default, this is a temporary file + selected by @pcb{}, but if you specify an import::outfile + attribute, that file name is used instead (and not automatically + deleted afterwards). +
+

+The target specified to be built is the first of these that apply: + +

    +
  • The target specified by an import::target attribute. +
  • The output file specified by an import::outfile attribute. +
  • If nothing else is specified, the target is pcb_import. +
+ +

+If you specify an import::makefile attribute, then "-f that +file" will be added to the command line. +

+If you specify the mode, you may also specify the source files +(schematics). If you do not specify any, the list of schematics is +obtained by reading the import::srcN attributes (like +import::src0, import::src1, etc). +

+For compatibility with future extensions to the import file format, +the generated file must not start with the two characters +#%. +

+If a temporary file is needed the TMPDIR environment variable +is used to select its location. +

+Note that the programs gnetlist and make must be +configured. +

+If pcb-rnd cannot determine which schematic(s) to import from, the GUI +is called to let user choose (see ImportGUI()). +

+Note that Import() doesn't delete anything - after an Import, subcircuits +which shouldn't be on the board are selected and may be removed once +it's determined that the deletion is appropriate. TODO: is this still true? +

+If Import() is called with setnewpoint, then the location +of new components can be specified. This is where parts show up when +they're added to the board. The default is the center of the board. + +Argument combinations: +

+ +
Import(setnewpoint) + Prompts the user to click on the board somewhere, uses that point. If + called by a hotkey, uses the current location of the crosshair. + +
Import(setnewpoint,mark) + Uses the location of the mark. If no mark is present, the point is + not changed. + +
Import(setnewpoint,center) + Resets the point to the center of the board. + +
Import(setnewpoint,X,Y,units) + Sets the point to the specific coordinates given.
+ Import(setnewpoint,50,25,mm) + +
+ +

+Note that the X and Y locations are stored in attributes named +import::newX and import::newY} so you could change them +manually if you wished. +

+Calling Import(setdisperse,D,units) sets how much the newly +placed subcircuits are dispersed relative to the set point. For example, +Import(setdisperse,10,mm) will offset each part randomly up to +10mm away from the point. The default dispersion is 1/10th of the +smallest board dimension. Dispersion is saved in the +import::disperse attribute. Index: tags/2.1.2/doc/user/09_appendix/action_src/importgui.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/importgui.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/importgui.html (revision 24813) @@ -0,0 +1,3 @@ +Displays a dialog that lets the user select the schematic(s) to import +from, then saves that information in the layout's attributes for +future imports. Index: tags/2.1.2/doc/user/09_appendix/action_src/l.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/l.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/l.html (revision 24813) @@ -0,0 +1,4 @@ +Loads a new datafile (layout) and, if confirmed, overwrites any +existing unsaved data. If no filename is specified a file select box +will popup. + Index: tags/2.1.2/doc/user/09_appendix/action_src/le.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/le.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/le.html (revision 24813) @@ -0,0 +1,2 @@ +The filename is passed to the +footprint loader. If no filename is specified a file select box will popup. Index: tags/2.1.2/doc/user/09_appendix/action_src/listscripts.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/listscripts.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/listscripts.html (revision 24813) @@ -0,0 +1,5 @@ +Print one line in the log for each currently loaded script. If pat +is specified, filter the list using pat as a case sensitive regex +on script ID, file name and language (list only scripts that match with +any of these fields). + Index: tags/2.1.2/doc/user/09_appendix/action_src/livescript.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/livescript.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/livescript.html (revision 24813) @@ -0,0 +1,40 @@ +The first argument determines what operation the action performs and +how subsequent arguments are interpreted: +

+ +
new, [name] + Create a new live script and open a new live script dialog. name + is an unique live script name that identifies the window. If not + specified, "default" is used" + +
load, name, [filename] + Replace the script source in the LiveScript window identified by + name with the content loaded from a file. If filename + is not specified, open a file selector dialog. + +
save, name, [filename] + Save the script source in the LiveScript window identified by + name to a file. If filename is not specified, open a + file selector dialog. + +
run, name + Run the script in the LiveScript window identified by + name. + +
stop, name + Stop the script in the LiveScript window identified by + name, if ti is running in persistent mode. + +
undo, name + Undo the "init changes" of the script in the LiveScript window + identified by name. Init changes are those board changes + the script has done while running its initialization section. + Live script undo is possible only if there was no user edit after + the script finished. + +
rerun, name + Stop, undo and run the script in the LiveScript window identified by + name. + +
+ Index: tags/2.1.2/doc/user/09_appendix/action_src/load.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/load.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/load.html (revision 24813) @@ -0,0 +1,5 @@ +This action is a GUI front-end to the core's LoadFrom action. +If you happen to pass a filename, LoadFrom is called directly. +Else, the user is prompted for a filename to load, and then LoadFrom +is called with that filename. + Index: tags/2.1.2/doc/user/09_appendix/action_src/loadfootprint.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/loadfootprint.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/loadfootprint.html (revision 24813) @@ -0,0 +1,4 @@ +Loads a single footprint by name, rather than by reference or through +the library. If a refdes and value are specified, those are inserted +into the footprint as well. The footprint remains in the paste buffer. + Index: tags/2.1.2/doc/user/09_appendix/action_src/loadfrom.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/loadfrom.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/loadfrom.html (revision 24813) @@ -0,0 +1,28 @@ +This action assumes you know what the filename is. The various GUIs +should have a similar Load action where the filename is +optional, and will provide their own file selection mechanism to let +you choose the file name. +

+Arguments: +

+ +
Layout + Loads an entire PCB layout, replacing the current one. + +
LayoutToBuffer + Loads an entire PCB layout to the paste buffer. + +
ElementToBuffer + Loads the given footprint file into the paste buffer. Footprint files + contain only a single subcircuit definition in one of the various + supported file formats. + +
Netlist + Loads a new netlist, replacing any current netlist. + +
Revert + Re-loads the current layout from its disk file, reverting any changes + you may have made. + +
+ Index: tags/2.1.2/doc/user/09_appendix/action_src/loadscript.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/loadscript.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/loadscript.html (revision 24813) @@ -0,0 +1,10 @@ +id is an arbitrary string assigned by the user. id +must be unique per pcb-rnd session per script and may contain alphanumeric characters +and undescrore. +

+fn is the file name of the script, which is a path. Pcb-rnd does not +do any search, it only opens the path as specified. +

+lang is the scripting language, as in +fungw plugin name. +When not specified, the code makes a guess (based on the file name). Index: tags/2.1.2/doc/user/09_appendix/action_src/loadvendorfrom.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/loadvendorfrom.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/loadvendorfrom.html (revision 24813) @@ -0,0 +1,7 @@ +Arguments: +

+ +
filename + Name of the vendor lihata file. If not specified, the user will + be prompted to enter one. +
Index: tags/2.1.2/doc/user/09_appendix/action_src/m.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/m.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/m.html (revision 24813) @@ -0,0 +1 @@ +If no filename is specified a file select box will popup. Index: tags/2.1.2/doc/user/09_appendix/action_src/markcrosshair.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/markcrosshair.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/markcrosshair.html (revision 24813) @@ -0,0 +1,9 @@ +The "mark" is a small X-shaped target on the display which is +treated like a second origin (the normal origin is the upper let +corner of the board). The GUI will display a second set of +coordinates for this mark, which tells you how far you are from it. +

+If no argument is given, the mark is toggled - disabled if it was +enabled, or enabled at the current cursor position of disabled. If +the Center argument is given, the mark is moved to the current +cursor location. Index: tags/2.1.2/doc/user/09_appendix/action_src/message.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/message.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/message.html (revision 24813) @@ -0,0 +1,4 @@ +This action displays a message to the log window. This action is primarily +provided for use by scripts and external programs which may interface with +pcb-rnd. If multiple arguments are given, each one is sent to the log window +followed by a newline. Index: tags/2.1.2/doc/user/09_appendix/action_src/mincleargap.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/mincleargap.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/mincleargap.html (revision 24813) @@ -0,0 +1,4 @@ +Checks all specified objects, and increases the polygon clearance if +needed to ensure a minimum distance between their edges and the +polygon edges. + Index: tags/2.1.2/doc/user/09_appendix/action_src/mode.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/mode.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/mode.html (revision 24813) @@ -0,0 +1,35 @@ +Selects the tool or changes tool related global states. +

+ +
Arc
Arrow
Copy
InsertPoint
Line
Lock +
Move
None
PasteBuffer
Polygon
Rectangle +
Remove
Rotate
Text
Thermal
Via
... +
Select the indicated tool. + +
Notify + Called when you press the mouse button, or move the mouse. + +
Release + Called when you release the mouse button. + +
Cancel + Cancels any pending tool activity, allowing you to restart elsewhere. + For example, this allows you to start a new line rather than attach a + line to the previous line. + +
Escape + Similar to Cancel but calling this action a second time will return + to the Arrow tool. + +
Stroke + If pcb-rnd was built with libstroke, this invokes the stroke + input method. If not, this will restart a drawing mode if you were + drawing, else it will select objects. + +
Save + Remembers the current tool. + +
Restore + Restores the tool to the last saved tool. + +
Index: tags/2.1.2/doc/user/09_appendix/action_src/morphpolygon.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/morphpolygon.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/morphpolygon.html (revision 24813) @@ -0,0 +1,5 @@ +If a polygon is divided into unconnected "islands", you can use +this command to convert the otherwise disappeared islands into +separate polygons. Be sure the cursor is over a portion of the +polygon that remains visible. Very small islands that may flake +off are automatically deleted. Index: tags/2.1.2/doc/user/09_appendix/action_src/movelayer.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/movelayer.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/movelayer.html (revision 24813) @@ -0,0 +1,25 @@ +Moves a layer, creates a new layer, or deletes a layer. +

+Arguments: +

+ +
old + The is the layer number to act upon. Allowed values are: +
    +
  • c = Currently selected layer. +
  • -1 = Create a new layer. +
  • number = An existing layer number. +
+
new + Specifies where to move the layer to. Allowed values are: +
    +
  • -1 = Deletes the layer. +
  • up = Moves the layer up (TODO: is this supported?) +
  • down = Moves the layer down (TODO: is this supported?) +
  • step+ = Moves the layer towards the end of its group's list. +
  • step- = Moves the layer towards the beginning of its group's list. +
  • c = Creates a new layer. +
  • grp gid = move layer into group; target group ID is the 3rd argument +
+ +
Index: tags/2.1.2/doc/user/09_appendix/action_src/moveobject.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/moveobject.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/moveobject.html (revision 24813) @@ -0,0 +1,5 @@ +The code and Y are treated like delta +if they are prefixed by + or -, otherwise, they are absolute. Units can be +mil or mm and is used when X and Y +have no unit specified. If no unit unspecified in coords or units, +nanometer is assumed. Index: tags/2.1.2/doc/user/09_appendix/action_src/movetocurrentlayer.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/movetocurrentlayer.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/movetocurrentlayer.html (revision 24813) @@ -0,0 +1,4 @@ +Note that moving an subcircuit from a component layer to a solder layer, +or from solder to component, won't automatically flip it. Use the +Flip action to do that. + Index: tags/2.1.2/doc/user/09_appendix/action_src/netlist.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/netlist.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/netlist.html (revision 24813) @@ -0,0 +1,69 @@ +Each of these actions apply to a specified set of nets. net and +pin are patterns which match one or more nets or pins; these +patterns may be full names or regular expressions. If an exact match +is found, it is the only match; if no exact match is found, +then the pattern is tried as a regular expression. +

+If neither net nor pin are specified, all nets apply. +If net is specified but not pin, all nets matching +net apply. If both are specified, nets which match net +and contain a pin matching pin apply. +

+freeze, thaw and forcethaw +temporarily prevents changes to the netlist from being reflected in +the GUI. For example, if you need to make multiple changes, you +freeze the netlist, make the changes, then thaw it. +Note that freeze/thaw requests may nest, with the netlist being fully thawed +only when all pending freezes are thawed. You can bypass the nesting +by using forcethaw, which resets the freeze count and immediately +updates the GUI. +

+Argument summary: +

+

+ +
find + Nets which apply are marked @emph{found} and are drawn in the + connected-color color. + +
select + Nets which apply are selected (added to existing selections). + +
unselect + Nets which apply are unselected (removed from existing selections). + +
rats + Nets which apply are marked as available for the rats nest. + +
norats + Nets which apply are marked as not available for the rats nest. + +
clear + Clears the netlist. + +
ripup + Remove all non-subcircuit-part copper object that is connected to a net. + +
add + Add the given pin to the given netlist, creating either if needed. + +
AddRats + Calculate and add all rats required for finishing the named network. + +
swap + Swap the connections one end of two selected rats and pins. + +
sort + Called after a list of add's, this sorts the netlist. + +
freeze
thaw
forcethaw +
Temporarily prevents changes to the netlist from being reflected in the GUI. + +
rename + Change the name of a network (with back annotation) + +
merge + Move all terminal connections from the source network (first arg) + to the destination network (with back annotation) + +
Index: tags/2.1.2/doc/user/09_appendix/action_src/new.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/new.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/new.html (revision 24813) @@ -0,0 +1 @@ +If a name is not given, one is prompted for. Index: tags/2.1.2/doc/user/09_appendix/action_src/onliner.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/onliner.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/onliner.html (revision 24813) @@ -0,0 +1,19 @@ +The oneliner action is designed for quick execution of short, +trivial scripts, such as a for loop for repeating an action. It supports +any scripting language currently availabel through fungw. Each oneliner is +an independent script context - variables, functions and other global states +do not persist. +

+This group of actions offers three forms: +

    +
  • oneliner(lang, script) - execute the script in the language specified +
  • lang(script) - shorthand for the above +
  • lang - switch the command line interpreter to execute one-liners in the given language, until /exit +
+

+For example, a simple calculation using awk can be done in three ways: +

    +
  • oneliner(awk, 'print 42*3') +
  • awk('print 42*3') +
  • awk, then print 42*3, then /exit +
Index: tags/2.1.2/doc/user/09_appendix/action_src/openemsexcitation.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/openemsexcitation.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/openemsexcitation.html (revision 24813) @@ -0,0 +1,16 @@ +When invoked without argument or with interactive a dialog box +is presented, allowing the user to do the same operations as with the +action. +

+If the first argument select, further OpenEMS exports will use +the excitation named in the excitationname argument (in short: +the excitation is selected). +

+Arguments set and get is used to read or change an +excitation parameter named in paramname. When excitationname +is not set, they operate on the currently selected excitation. For set +the paramval argument is mandatory. +

+Note: the code remembers all settings for all excitements, not only the +excitement that is currently selected. The selection and all parameters are +saved as board attributes. \ No newline at end of file Index: tags/2.1.2/doc/user/09_appendix/action_src/pan.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/pan.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/pan.html (revision 24813) @@ -0,0 +1,3 @@ +Start or stop panning. To start call with Mode = 1, to stop call with +Mode = 0. + Index: tags/2.1.2/doc/user/09_appendix/action_src/pastebuffer.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/pastebuffer.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/pastebuffer.html (revision 24813) @@ -0,0 +1,53 @@ +There are a number of paste buffers; the actual limit is a +compile-time constant PCB_MAX_BUFFER. It +is normally 5. One of these is the "current" paste buffer, +often referred to as "the" paste buffer. + +Arguments: +

+ + +
AddSelected + Copies the selected objects to the current paste buffer. + +
Clear + Remove all objects from the current paste buffer. + +
Convert + Convert the current paste buffer to an subcircuit. + +
Restore + Convert any subcircuit in the paste buffer back to plain objects. + +
Mirror + Flip all objects in the paste buffer vertically (up/down flip). To mirror + horizontally, combine this with rotations. + +
Rotate + Rotates the current buffer. The number to pass is 1..3, where 1 means + 90 degrees counter clockwise, 2 means 180 degrees, and 3 means 90 + degrees clockwise (270 CCW). + +
Normalize + Set the buffer origin to the center of the paste buffer bounding box. + This is useful especially if an import plugin loaded objects in the buffer + with a large offset. + +
Save + Saves any elements in the current buffer to the indicated file. If + format is specified, try to use that file format, else use the default. + If force is specified, overwrite target, don't ask. + +
ToLayout + Pastes objects in the current buffer to the indicated X, Y + coordinates in the layout. The X and Y are treated like + delta is for many other objects. For each, if it's prefixed by + + or -, then that amount is relative to the last + location. Otherwise, it's absolute. If units is unspecified, units are PCB's internal + units, currently nanometer. If "crosshair" is used instead of coordinates, + the paste happens at the current crosshair coords. + +
1..PCB_MAX_BUFFER + Selects the given buffer to be the current paste buffer. + +
Index: tags/2.1.2/doc/user/09_appendix/action_src/polycombine.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/polycombine.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/polycombine.html (revision 24813) @@ -0,0 +1,2 @@ +The selected polygons are combined together according to the ordering +of their points. Index: tags/2.1.2/doc/user/09_appendix/action_src/polygon.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/polygon.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/polygon.html (revision 24813) @@ -0,0 +1,17 @@ +Argument: +

+ +
Close + Creates the final segment of the polygon. This may fail if clipping + to 45 degree lines is switched on, in which case a warning is issued. + +
CloseHole + Creates the final segment of the polygon hole. This may fail if clipping + to 45 degree lines is switched on, in which case a warning is issued. + +
PreviousPoint + Resets the newly entered corner to the previous one. The Undo action + will call Polygon(PreviousPoint) when appropriate to do so. + +
+ Index: tags/2.1.2/doc/user/09_appendix/action_src/polystitch.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/polystitch.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/polystitch.html (revision 24813) @@ -0,0 +1,5 @@ +The polygon under the cursor (based on closest-corner) is stitched +together with the polygon surrounding it on the same layer. +

+Use with pstoedit conversions where there's a "hole" in the shape - +select the hole. Index: tags/2.1.2/doc/user/09_appendix/action_src/popup.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/popup.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/popup.html (revision 24813) @@ -0,0 +1,3 @@ +This just pops up the specified menu. The menu must have been defined +in the popups subtree in the menu lht file. + Index: tags/2.1.2/doc/user/09_appendix/action_src/preunload.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/preunload.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/preunload.html (revision 24813) @@ -0,0 +1,15 @@ +preunload is an optional action scripts may provide. When present, +it is called by pcb-rnd as the last call to the script before the script is +unloaded. It has two purposes: +

    +
  • give scripts a chance to clean up, uninit and unregister +
  • give scripts a chance to perist their state +
+

+State persisting is achieved through returning a string from this action. That +string is then saved by pcb-rnd under the scripts' load ID (as specified by +the user). In a later script load, the script with the same ID may read the +persistent data frolm disk using the ScriptPersistency(read) action +and can remove the save using the ScriptPersistency(remove) action. +

+It should never be called by the user or other code or other actions. Index: tags/2.1.2/doc/user/09_appendix/action_src/print.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/print.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/print.html (revision 24813) @@ -0,0 +1,8 @@ +Open an export dialog listing all printing plugins, prompt the user for their +options, and print the layout. +

+Available only with GUI HIDs: it's merely a graphical shorthand that in turn +calls the export plugin for printing. + + + Index: tags/2.1.2/doc/user/09_appendix/action_src/printcalibrate.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/printcalibrate.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/printcalibrate.html (revision 24813) @@ -0,0 +1,2 @@ +This will print a calibration page, which you would measure and type +the measurements in, so that future printouts will be more precise. Index: tags/2.1.2/doc/user/09_appendix/action_src/promptfor.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/promptfor.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/promptfor.html (revision 24813) @@ -0,0 +1,5 @@ +UI-independent way of asking the user for a string. When GUI is available, +it is a dialog box, else it's console input. Return value, unlike with other +actions, is a string. The return value is NULL on cancel. + + Index: tags/2.1.2/doc/user/09_appendix/action_src/puller.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/puller.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/puller.html (revision 24813) @@ -0,0 +1,4 @@ +The Puller action is a special-purpose optimization. When +invoked while the crosshair is over the junction of an arc and a line, +it will adjust the arc's angle and the connecting line's endpoint such +that the line intersects the arc at a tangent. Index: tags/2.1.2/doc/user/09_appendix/action_src/q.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/q.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/q.html (revision 24813) @@ -0,0 +1,2 @@ +If you have unsaved changes, you will be prompted to confirm (or +save) before quitting, unless the action name included a !. Index: tags/2.1.2/doc/user/09_appendix/action_src/quit.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/quit.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/quit.html (revision 24813) @@ -0,0 +1,2 @@ +If you have unsaved changes, you will be prompted to confirm (or save) +before quitting. Index: tags/2.1.2/doc/user/09_appendix/action_src/redo.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/redo.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/redo.html (revision 24813) @@ -0,0 +1,10 @@ +The Redo action allows you to recover from the last undo command. +You might want to do this if you thought that undo was going to revert +something other than what it actually did (in case you are confused +about which operations are un-doable), or if you have been backing up +through a long undo list and over-shoot your stopping point. Any +change that is made since the undo in question will trim the redo +list. For example if you add ten lines, then undo three of them you +could use redo to put them back, but if you move a line on the board +before performing the redo, you will lose the ability to "redo" the +three "undone" lines. Index: tags/2.1.2/doc/user/09_appendix/action_src/reloadscript.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/reloadscript.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/reloadscript.html (revision 24813) @@ -0,0 +1,4 @@ +id is the same that was specified for LoadScript. +If loading the new verison of the script fails, id is released +(can be reused for a new LoadScript). + Index: tags/2.1.2/doc/user/09_appendix/action_src/renumberblock.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/renumberblock.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/renumberblock.html (revision 24813) @@ -0,0 +1,7 @@ +RenumberBlock(oldnum,newnum) +

+All selected elements are renumbered by adding (newnum-oldnum) to +the existing number. +

+RenumberBlock(100,200) will change R213 +to R313. Index: tags/2.1.2/doc/user/09_appendix/action_src/renumberbuffer.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/renumberbuffer.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/renumberbuffer.html (revision 24813) @@ -0,0 +1,3 @@ +RenumberBuffer(oldnum,newnum) +

+Same as RenumberBlock, but the paste buffer is renumbered. Index: tags/2.1.2/doc/user/09_appendix/action_src/replacefootprint.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/replacefootprint.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/replacefootprint.html (revision 24813) @@ -0,0 +1,16 @@ +Replace footprint(s) from the library or buffer, in-place (preserving +the original subcircuit's location, rotation and metadata) and append +the replacement to the back annotation changeset. +

+If first argument is selected, replace all selected subcircuits +with the new footprint; if it is object, replace only one +subcircuit, under the cursor. +

+If the second argument is a footprint name, load it from the library. +If it is @buffer, use the subcircuit in the current buffer (there +must be exactly 1 subcircuit in the buffer). If it is empty or not specified, +the user is asked for a footprint. +

+If the third argument is dumb the location and rotation of the +original subcircuit is not preserved (but all metadata and board side are +preserved). A dumb replacement also omits creating back annotation. Index: tags/2.1.2/doc/user/09_appendix/action_src/report.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/report.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/report.html (revision 24813) @@ -0,0 +1,26 @@ +Arguments: +

+ +
Object + The object under the crosshair will be reported, describing various + aspects of the object. + +
DrillReport + A report summarizing the number of drill sizes used, and how many of + each, will be produced. + +
FoundPins + A report listing all pins and pads which are marked as "found" will + be produced. + +
NetLength + The name and length of the net under the crosshair will be reported to + the message log. + +
AllNetLengths + The name and length of the net under the crosshair will be reported to + the message log. An optional parameter specifies mm, mil, pcb, or in + units + +
+ Index: tags/2.1.2/doc/user/09_appendix/action_src/reportdialog.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/reportdialog.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/reportdialog.html (revision 24813) @@ -0,0 +1,2 @@ +This is a shortcut for Report(Object). + Index: tags/2.1.2/doc/user/09_appendix/action_src/ripup.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/ripup.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/ripup.html (revision 24813) @@ -0,0 +1,10 @@ +Arguments: +

+ +
All + Removes all lines and vias which were created by the autorouter. + +
Selected + Removes all selected lines and vias which were created by the + autorouter. +
Index: tags/2.1.2/doc/user/09_appendix/action_src/rn.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/rn.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/rn.html (revision 24813) @@ -0,0 +1 @@ +If no filename is given a file select box will pop up. Index: tags/2.1.2/doc/user/09_appendix/action_src/rotate90.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/rotate90.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/rotate90.html (revision 24813) @@ -0,0 +1,4 @@ +Rotates the object under the mouse pointer by 90 degree steps. +steps must be an integer between -3 and +3. + + Index: tags/2.1.2/doc/user/09_appendix/action_src/s.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/s.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/s.html (revision 24813) @@ -0,0 +1,2 @@ +If no filename is entered, either the last one is used +again or, if it is not available, a file select box will pop up. Index: tags/2.1.2/doc/user/09_appendix/action_src/save.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/save.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/save.html (revision 24813) @@ -0,0 +1,4 @@ +This action is a GUI front-end to the core's SaveTo action. +If you happen to pass a filename then SaveTo is called directly. +Else, the user is prompted for a filename to save, and then SaveTo +is called with that filename. Index: tags/2.1.2/doc/user/09_appendix/action_src/saveto.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/saveto.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/saveto.html (revision 24813) @@ -0,0 +1,17 @@ +Arguments: +

+ +
Layout + Saves the current layout. + +
LayoutAs + Saves the current layout, and remembers the filename used. + +
PasteBuffer + Save the content of the active Buffer to a file. This is + the graphical way to create a footprint. + +
AllConnections, AllUnusedPins, ElementConnections + obsolete arguments, kept for compatibility; please use + ExportOldConn instead. +
Index: tags/2.1.2/doc/user/09_appendix/action_src/scriptcookie.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/scriptcookie.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/scriptcookie.html (revision 24813) @@ -0,0 +1,9 @@ +The script: +

    +
  • may call ScriptCookie() during script initialization and save the resulting cookie string +
  • may use the cookie string to register to core pcb-rnd infrastructure that requires cookie, such as CreateMenu +
  • can depend on pcb-rnd to call any unregistering associated with this specific cookie atomatically after script unload (preunload). +
+

+The function can not be called outside of script initialization. The cookie +string can be used any time between script load and script unload. Index: tags/2.1.2/doc/user/09_appendix/action_src/scriptpersistency.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/scriptpersistency.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/scriptpersistency.html (revision 24813) @@ -0,0 +1,8 @@ +When a script is unloaded, its action preunload is called. The +return value is saved as script persistent data. When the script is loaded +again later, it can use ScriptPersistency(read) to +read the data saved. +

+ScriptPersistency(remove) deletes the data from disk. +

+Note: the data is per script id, not per script file name. Index: tags/2.1.2/doc/user/09_appendix/action_src/scroll.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/scroll.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/scroll.html (revision 24813) @@ -0,0 +1,15 @@ +Arguments: +

+ + +
up|down|left|right + Specifies the direction to scroll + +
div + Optional. Specifies how much to scroll by. The viewport is scrolled + by 1/div of what is visible, so div = 1 scrolls a whole page. If not + default is given, div=40. + +
+

+WARNING: available in the GTK HID only. Index: tags/2.1.2/doc/user/09_appendix/action_src/select.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/select.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/select.html (revision 24813) @@ -0,0 +1,24 @@ +Arguments: +

+ +
Object
ToggleObject +
Selects the object under the cursor. + +
Block + Selects all objects in a rectangle indicated by the cursor. + +
All + Selects all objects on the board. + +
Connection + Selects all connections with the ``found'' flag set. + +
Convert + Converts the selected objects to a subcircuit. This uses the highest + numbered paste buffer. + +
Invert + Invert selection: anything that was not selected becomes selected, + everything that was selected becomes unselected. Locked objects + are not affected. +
Index: tags/2.1.2/doc/user/09_appendix/action_src/selectlayer.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/selectlayer.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/selectlayer.html (revision 24813) @@ -0,0 +1,2 @@ +The specified layer becomes the currently active layer. It is made +visible if it is not already visible Index: tags/2.1.2/doc/user/09_appendix/action_src/setflag.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/setflag.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/setflag.html (revision 24813) @@ -0,0 +1,7 @@ +Turns the given flag on, regardless of its previous setting. See +ChangeFlag. +

+SetFlag(SelectedPins,thermal) + + + Index: tags/2.1.2/doc/user/09_appendix/action_src/setsame.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/setsame.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/setsame.html (revision 24813) @@ -0,0 +1,3 @@ +When invoked over any line, arc, polygon, or via, this changes the +current layer to be the layer that item is on, and changes the current +sizes (thickness, clearance, etc) according to that item. Index: tags/2.1.2/doc/user/09_appendix/action_src/setthermal.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/setthermal.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/setthermal.html (revision 24813) @@ -0,0 +1,31 @@ +This changes how/whether padstacks connect to any rectangle or polygon +on the current layer. The first argument can specify one object, or all +selected padstacks. +The second argument specifies the style of connection. +

+Thermal styles: +

+ +
0 + no connection, + +
1 + 45 degree fingers with sharp edges, + +
2 + horizontal & vertical fingers with sharp edges, + +
3 + solid connection, + +
4 + 45 degree fingers with rounded corners, + +
5 + horizontal & vertical fingers with rounded corners. +
+

+Padstacks may have thermals whether or not there is a polygon available +to connect with. However, they will have no visible effect until a polygon +is drawn around the padstack. + Index: tags/2.1.2/doc/user/09_appendix/action_src/setunits.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/setunits.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/setunits.html (revision 24813) @@ -0,0 +1,7 @@ + +
mil + Sets the display units to mils (1/1000 inch). + +
mm + Sets the display units to millimeters. +
Index: tags/2.1.2/doc/user/09_appendix/action_src/setvalue.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/setvalue.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/setvalue.html (revision 24813) @@ -0,0 +1,14 @@ +Arguments: +

+ +
Grid + Sets the grid spacing. + +
Line
LineSize +
Changes the thickness of new lines. + +
Text
TextScale +
Changes the size of new text. + +
+ Index: tags/2.1.2/doc/user/09_appendix/action_src/smartdisperse.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/smartdisperse.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/smartdisperse.html (revision 24813) @@ -0,0 +1,6 @@ +Improve the initial dispersion of subcircuits by choosing an order based +on the netlist, rather than the arbitrary subcircuit order. This isn't +the same as a global autoplace, it's more of a linear autoplace. It +might make some useful local groupings. For example, you should not +have to chase all over the board to find the resistor that goes with +a given LED. Index: tags/2.1.2/doc/user/09_appendix/action_src/swapsides.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/swapsides.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/swapsides.html (revision 24813) @@ -0,0 +1,30 @@ +This action changes the way you view the board (flipping the board). +

+Arguments: +

+ + +
v + Flips the board over vertically (up/down). + +
h + Flips the board over horizontally (left/right), like flipping pages in + a book. + +
r + Rotates the board 180 degrees without changing sides. +
+

+If no argument is given, the board isn't moved but the opposite side +is shown. +

+Normally, this action changes which pads and silk layer are drawn as +pcb_true silk, and which are drawn as the "invisible" layer. It also +determines which solder mask you see. +

+If S is specified as a second argument, +if the layer group for the side you're looking at +is visible and currently active, and the layer group for the opposite +is not visible (i.e. disabled), then this action will also swap which +layer group is visible and active, effectively swapping the "working +side" of the board. Index: tags/2.1.2/doc/user/09_appendix/action_src/toggleview.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/toggleview.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/toggleview.html (revision 24813) @@ -0,0 +1,8 @@ +If you pass an integer, that layer is specified by index (the first +layer is 1, etc). If you pass a layer name, that layer is +specified by name. When a layer is specified, the visibility of the +layer group containing that layer is toggled. +

+If you pass a special layer name, the visibility of those components +(silk, rats, etc) is toggled. Note that if you have a layer named +the same as a special layer, the layer is chosen over the special layer. Index: tags/2.1.2/doc/user/09_appendix/action_src/undo.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/undo.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/undo.html (revision 24813) @@ -0,0 +1,11 @@ +The unlimited undo feature of pcb-rnd allows you to recover from +most operations that materially affect you work. Calling +pcb_undo without any parameter recovers from the last (non-undo) +operation. ClearList is used to release the allocated +memory. ClearList is called whenever a new layout is started or +loaded. See also Redo. +

+Note that undo groups operations by serial number; changes with the +same serial number will be undone (or redone) as a group. See +Atomic. + Index: tags/2.1.2/doc/user/09_appendix/action_src/unloadscript.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/unloadscript.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/unloadscript.html (revision 24813) @@ -0,0 +1,2 @@ +id is the same that was specified for LoadScript. +After the call id is released (can be reused for a new LoadScript). Index: tags/2.1.2/doc/user/09_appendix/action_src/unselect.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/unselect.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/unselect.html (revision 24813) @@ -0,0 +1,14 @@ +Arguments: +

+ +
All + Unselect all objects. + +
Block + Unselect all objects in a rectangle given by the cursor. + +
Connection + Unselect all connections with the "found" flag set. +
+ + Index: tags/2.1.2/doc/user/09_appendix/action_src/w.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/w.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/w.html (revision 24813) @@ -0,0 +1,2 @@ +This commands has been added for the convenience of vi users +and has the same functionality as s. Index: tags/2.1.2/doc/user/09_appendix/action_src/wq.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/wq.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/wq.html (revision 24813) @@ -0,0 +1,2 @@ +This command has been added for the convenience of vi users and +has the same functionality as s combined with q. Index: tags/2.1.2/doc/user/09_appendix/action_src/zoom.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/action_src/zoom.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/action_src/zoom.html (revision 24813) @@ -0,0 +1,51 @@ +Changes the zoom (magnification) of the view of the board. If no +arguments are passed, the view is scaled such that the board just fits +inside the visible window (i.e. "view all"). Otherwise, +factor specifies a change in zoom factor. +It may be prefixed by +, -, = to change how the zoom +factor is modified (relative or absolute). The factor is a +floating point number, such as 1.5 or 0.75. +

+Alternatively a box can be specified with 4 coordinates and zoom +will set the zoom level (and modifies pan) so that the given box of the +design is visible and as large as possible in the current window. +

+Arguments: +

+ + +
+factor + Values greater than 1.0 cause the board to be drawn smaller; more of + the board will be visible. Values between 0.0 and 1.0 cause the board + to be drawn bigger; less of the board will be visible. + +
-factor + Values greater than 1.0 cause the board to be drawn bigger; less of + the board will be visible. Values between 0.0 and 1.0 cause the board + to be drawn smaller; more of the board will be visible. + +
=factor + The @var{factor} is an absolute zoom factor; the unit for this value + is "PCB units per screen pixel". Since PCB units are nanometer, a + factor of 1000 means 1 micrometer per pixel (TODO: test this). + +
x1, y1, x2, y2 + Zoom to the specified portion of the design, described as a rectangle + (using board space coordinates) + +
selected + Zoom and pan so that all selected objects are on the screen. + +
found + Zoom and pan so that all found objects are on the screen. + +
? + Print the current zoom level in the message log (as an info line). + +
get + Return the zoom level as an FGW_DOUBLE (useful for scripts). + +
+

+Note that zoom factors of zero are silently ignored. + Index: tags/2.1.2/doc/user/09_appendix/bridges.svg =================================================================== --- tags/2.1.2/doc/user/09_appendix/bridges.svg (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/bridges.svg (revision 24813) @@ -0,0 +1,221 @@ + + + + + + + + + + + + + + + + pcb-rnd + + output-only + + input-output + + HID (GUI) + + input-only + + kicadpcbnew + + gtkgdk or gl render + + web client(javascript) + + batchCLI/automation + + lesstif(motif) + + gEDApcb + + remote(network) + + freerouting.netautorouter + + c-pcb(autorouting) + + (any)IPC-D-356 + + (any)EDIF + + TinyCAD + + Calay + + mucs PCBautorouter + + XSCHEM + + LTSpice + + leptonEDA + + EasyEDA(web2.0) + + kicadeeschema + + (any)netlist + + Mentorhyperlynx + + gEDAgschem + + Eagle(board) + + FidoCadJ(board) + + ProtelAutotrax + + HPGL(2D CAD) + + gerber + + svg + + lpr(print) + + ipcd356e-tester + + dxf(2D CAD) + + XYtemplated + + openscad(3D CAD) + + pngjpg, bmp + + breadboard + + pspostscript + + BOM + + statstatistics + + importschematics + + + + IPC356D + + + + + + svg + + + + lihata + + + + ps + + + + importschematics + + + + + postscript + + + importschematics + + + importschematics + + importnetlist + + + TCP/IP + + + importnetlist + + importschematics + + importschematics + + netlistpads/subcs + + importschematics + + + .png + + + importschematics + + + board + + + + board + + + importlines/arcs + + + text + + + + footprint + + + + schematics + + + + footprints-expr + + + + .xy + + + + boards-expr + + + + board + + + + board + + + + .grb, .cnc + + + + boardlegacy + + + + board + + + + board + + + + board + + + Index: tags/2.1.2/doc/user/09_appendix/combined_glossary.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/combined_glossary.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/combined_glossary.html (revision 24813) @@ -0,0 +1,281 @@ + + + + pcb-rnd user manual + + + + +

pcb-rnd User Manual: Appendix

+ +

9.6 Glossary

+ +

Useful terminology for a common vernacular

+This glossary is under construction. It currently combines terms that focus +pertain to any of the following facet subjects. +
    +
  1. pcb-rnd specific terminology
  2. +
  3. pcb manufacturer terminology
  4. +
  5. pcb CAD layout and design terminology
  6. +
  7. CAD/graphics common design terminology
  8. +
+We will fill in definitions, continue to add terms, and determine an +appropriatly faceted method to index the terms. +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Combined Glossary Table +
termdescriptionfacets +
5/5 5mil minimum traces & 5mil minimum spacing
6/5 6mil minimum traces & 5mil minimum spacing
AMC aluminum metal core
ACY
additive
Adhesive
Altium
Annular Ring
Annulus
AOI automatic optical inspection
Aperture
Arc
Array
assembly
AutoCAD
autorouter
Autotrax
Autotrax
AXI automated x-ray inspection
Axial
Bakelite
BGA
Blind Via
bloat
board house
Board Thickness
Breadboard
buffer
Buried Via
bus
C4 Controlled collapse chip connection
CAD
CAM files
CAM
Capture
Card Edge connector
Castellations
CEM-1
CEM-3
Centroid
centroid
Chip Scale Package
clad
Clearance
Coating (Spin, Roll, Film)
COB
Component Side
Component
Computer Aided Design
Computer Aided Machining
Conformal Coating
Conformal coating
connect
Copper Foil
Copper weight
Copper
copper
courtyard
cte coefficient of thermal expansion (see tce)
Curve, open
delamination
DFSM Dry film soldermask
Dialectric
Diameter
Dielectric
differential pair
DIP
Discrete Component
double-sided
DRC design rule check
Drill file
Eagle
EDF
EDI Electronic Data Interchange
Endpoint
ENIG Electroless Nickel Immersion Gold
epoxy resin
ESD Electrostatic Discharge
Etching
Excellon
explicit layer
fabrication fab
Feedthrough Via
fidocad
Fiducial
Finger
Finite Element Filter
Fixture
flags
Flex
Flip chip
flood fill
Flux
Flying probe
Foil
font
Footprint
FR-1
FR-2
FR-3
FR-4
Gcode
gEDA
Gerber
grid snap
grid-pitch
grid
Hard Gold pcb surface finish (slip rings, fingers, etc)
HASL Hot Air surface levelling
High Density Interconnect(HDI)
Hole
Immersion Silver
Immersion Tin
implicit layer
Integrated Circuit
IPC (circa 1957)
JIT
Kapton
KiCAD
Knife
Laminate
Land
Laser
Layer Group
Layer Sequence
Layers (Physical)
Layers (Virtual)
Library
Lihata
mask
Masonite
Mentor
Mil
Milling
milling
Mirroring
Mouse bites
Multilayer
neckdown
negative process
Negative transfer
NEMA
Net
Netlist
ODB++
OrCAD
OSP Organic Solderability preservative
outline
Package
Pad
padstack
Panel Service
panel
Panelization
paste stencil
paste
Path
pcb-rnd
PCB
PDIP
phenolic resin
Photoengraving
Photoresist
pick and place pnp
Pin
pinout
pitch
PLCC plastic lead chip carrier
plotter
Polygon hole
Polygon, complex
Polygon, concave
Polygon, convex
Polygon, irregular
Polygon, regular
Polygon, simple
Polygon
polygon
positive process
Positive transfer
Protel
PTH
Pyralux AP
Pyralux FR
Pyralux LF
QFP
Radial Lead
Raster
rat
Ratsnest
refdes Reference Designator, https://en.wikipedia.org/wiki/Reference_designator
reflow
Registration
resin
resist
RF
Rigid-Flex
Route and Retain
routing style
Routing
routing
RS-274D
RS-274X
Rubylithe
Scoring
Short
Silk Screen
Silk
silk
single-sided
SIP
slot
SMD
SMOBC soldermask over bare copper
prevent unintended flow of tin/lead during reflow
SMT
Snap
SOIC
Solder Side
Solder
STEP
Subcircuit
Substrate
Subtractive
Symbol
Tape out
TCE thermal coefficient of expansion
tEDAx
Tented(Via)
terminal
TG Glass transition temp
Thermal Via Thermal relief
Thou
Tin Whisker
Tin
TinyCAD
Tolerance
tombstone
tooling
toolpath generator
toolpath
toporouter
Trace
TT toner transfer
V-Cut
aka v-scoring
V-score
Vcc
Vdd
Vector
Via stitching
Via
Wave Solder
Wire bonding
XY
Index: tags/2.1.2/doc/user/09_appendix/dialogs.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/dialogs.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/dialogs.html (revision 24813) @@ -0,0 +1,60 @@ + + + + + pcb-rnd - list of file formats + + + + + +

pcb-rnd User Manual: Appendix

+

+

List of GUI dialog boxes

+ + +
ID + dialog box name + action + source + comments + +
braveBrave featuresbrave()src/brave.c  +
progresspcb-rnd progressn/asrc/hid_dlg.cno action API yet (but it is planned) +
asmHand assembly with pcb-rndasm()src_plugins/asm/asm.c  +
camCAM exportcam()src_plugins/cam/cam_gui.cdoes not yet work in lesstif +
constraintDrawing constraintsconstraint()src_plugins/ddraft/constraint_gui.c  +
aboutAbout pcb-rndabout()src_plugins/dialogs/dlg_about.clesstif: needs to be resized to at least 600 pixels high +
prompt_forn/an/asrc_plugins/dialogs/dlg_comm_m.cnot for use from actions (for internal HID use) +
fallback_color_pickChange colorn/asrc_plugins/dialogs/dlg_comm_m.cnot for use from actions (for internal HID use) +
exportn/an/asrc_plugins/dialogs/dlg_export.c  +
flagsEdit flagsFlagEdit()src_plugins/dialogs/dlg_flag_edit.c  +
fontselFont selectionFontSel()src_plugins/dialogs/dlg_fontsel.c  +
layer_bindingLayer bindingsLayerBinding()src_plugins/dialogs/dlg_layer_binding.c  +
pstk_libn/aPstkLib()src_plugins/dialogs/dlg_lib_pstk.cdoes not yet work in lesstif +
logpcb-rnd message loglog()src_plugins/dialogs/dlg_log.c  +
netlistpcb-rnd netlistNetlistDialog()src_plugins/dialogs/dlg_netlist.c  +
padstack_shapeEdit padstack shapen/asrc_plugins/dialogs/dlg_padstack.copen from within the padstack dialog +
padstackEdit padstackPadstackEdit()src_plugins/dialogs/dlg_padstack.c  +
pinoutn/apinout()src_plugins/dialogs/dlg_pinout.c  +
pluginsManage pluginsManagePlugins()src_plugins/dialogs/dlg_plugins.cread-only list at the moment +
preferencespcb-rnd preferencespreferences()src_plugins/dialogs/dlg_pref.clesstif: some tabs are unusable +
pref_confeditpcb-rnd conf itemn/asrc_plugins/dialogs/dlg_pref_confedit.c  +
pref_lib_pathEdit library pathn/asrc_plugins/dialogs/dlg_pref_lib.copen from within the preferences dialog +
pref_lib_path_helppcb-rnd preferences: library helpn/asrc_plugins/dialogs/dlg_pref_lib.copen from within the preferences dialog +
undopcb-rnd undo listUndoDialog()src_plugins/dialogs/dlg_undo.c  +
openems_excitationopenems: excitationOpenEMSExcitation()src_plugins/export_openems/excitation.c  +
meshmeshermesh()src_plugins/export_openems/mesh.c  +
exteditExternal editorextedit()src_plugins/extedit/extedit_dad.c  +
poly_hatchPolygon hatchhatch(interactive)src_plugins/lib_polyhelp/polyhelp.c  +
propeditProperty editorpropedit()src_plugins/propedit/propdlg.c  +
reportn/areport()src_plugins/report/report.c  +
live_scriptn/aLiveScript()src_plugins/script/live_script.c  +
scriptspcb-rnd ScriptsBrowseScript()src_plugins/script/script_act.c  +
shapedlg_shapeshape()src_plugins/shape/shape_dialog.c  +
view*view*n/asrc_plugins/dialogs/dlg_view.c  + +
+ + + Index: tags/2.1.2/doc/user/09_appendix/external_resources.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/external_resources.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/external_resources.html (revision 24813) @@ -0,0 +1,43 @@ + + + + pcb-rnd user manual + + + + +

+

pcb-rnd User Manual: Appendix

+ +

External Resources

+

9.2.1 pcb-rnd community Resources

+
    +
  1. repo.hu is the pcb-rnd +maintainer's SVN based project hosting site +
  2. Contributer erichVK5's blog, +(including many posts directly and indirectly relevant to pcb-rnd) +
  3. Contributer erichVK5's github repository +
+ +

9.2.2 resources on building and contributing to pcb-rnd

+
    +
  1. contribution guidelines for pcb-rnd +
  2. live chat with the pcb-rnd user community +
  3. StackOverflow discussion on using svn +
+ +

9.2.3 Printed Circuit Board fabrication Resources

+
    +
  1. PCB Reference for pth and smt pcb footprint definitions pdf +warning! +
  2. AN4005 example industry appnote of layout considerations (many abound) +
+ +

9.2.4 EDA Resource Links

+
    +
  1. KiCAD: http://kicad-pcb.org +
  2. Eagle: https://www.autodesk.com/products/eagle/overview +
  3. gEDA: http://www.geda-project.org +
+ + Index: tags/2.1.2/doc/user/09_appendix/formats.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/formats.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/formats.html (revision 24813) @@ -0,0 +1,372 @@ + + + + + pcb-rnd - list of file formats + + + + + +

pcb-rnd User Manual: Appendix

+

+

File format support

+ + + +
plugin native state reads formats writes formats + +
io_lihata +yes +works + + lihata pcb-rnd board (any version) +
+ lihata pcb-rnd footprint (any version) +
+ lihata pcb-rnd font (any version) +
+ lihata pcb-rnd board (any version) +
+ lihata pcb-rnd footprint (any version) +
+ lihata pcb-rnd font (any version) +
io_autotrax +no +works + + autotrax PCB, version 4 +
+ autotrax PCB, version 5 +
+ autotrax PCB, version 4 +
io_dsn +no +works + + dsn board + + dsn board +
io_eagle +no +works + + eagle xml board version 6, 7 and 8 +
+ eagle xml library +
+ eagle binary board version 3, 4 and 5 +
+ eagle binary library +
+ eagle DRU (design rules) +
+n/a +
io_hyp +no +works + + hyperlynx board, version 2 and above + + hyperlynx board, version 2.0 +
io_kicad +no +works + + kicad board, version 3, 4 and 5 (s-expr) +
+ eeschema netlist and footprint info +
+ kicad board, version 3 (s-expr) +
+ kicad module (s-expr, according to version 3) +
io_kicad_legacy +no +works + +n/a + + kicad pcbnew-board, version 1 (legacy plain text format) +
+ kicad pcbnew-module (legacy plain text format) +
io_mentor_cell +no +WIP + + Mentor Graphics cell footprints + +n/a +
io_pcb +no +works + + gEDA/PCB .pcb board (any version up to 2017) +
+ gEDA/PCB .fp footprints +
+ gEDA/PCB font +
+ gEDA/PCB .pcb board (various version up to 2017 ) +
+ gEDA/PCB .fp footprints +
io_tedax +no +works + + tEDAx netlist (any version) +
+ tEDAx footprint (any version) +
+ tEDAx footprint (any version) +
import_calay +no +works + + import netlist and footprint info from calay netlists + +n/a +
import_dsn +no +works + + import wires and vias from specctra .dsn + +n/a +
import_edif +no +works + + flat netlist from EDIF + +n/a +
import_fpcb_nl +no +works + + import netlist and footprint names from freepcb netlist + +n/a +
import_hpgl +no +works + + import lines, arcs and polygons from HPGL plot files + +n/a +
import_ipcd356 +no +works + +n/a + + import IPC-D-356 Netlist (from automated testing) +
import_ltspice +no +works + + import netlist and footprint names from ltspice .net and .asc file pairs + +n/a +
import_mentor_sch +no +works + + import netlist and footprint names from a flat .edf produced by Mentor Graphics Design Capture + +n/a +
import_mucs +no +works + + import lines and vias from MUCS unixplot .pl files + +n/a +
import_netlist +no +works + + import plain text gEDA netlist files + +n/a +
import_sch +no +works + + import netlist and footprint info from gEDA schematics using gnetlist +
+ import netlist and footprint produced by an external command +
+n/a +
import_tinycad +no +works + + import netlist and footprint info from tinycad .net netlists + +n/a +
import_ttf +no +WIP + + ttf font + +n/a +
export_bboard +no +WIP + +n/a + + export breadboard assembly drawing in png +
export_bom +no +works + +n/a + + export bom (Bill of Materials) in plain text +
export_dsn +no +works + +n/a + + export specctra .dsn files with padstacks and subcircuits (usable for freerouting) +
export_dxf +no +works + +n/a + + export to 2D .dxf (for mech CADs) +
export_fidocadj +no +WIP + +n/a + + partial export in fidocad .fcd format +
export_gcode +no +works + +n/a + + export gcode (for milling) +
export_gerber +no +works + +n/a + + export gerber for PCB fabbing, multiple files (configurable) +
export_ipcd356 +no +works + +n/a + + export IPC-D-356 Netlist (for automated testing) +
export_lpr +no +works + +n/a + + use export_ps and lpr to print a board directly +
export_oldconn +no +works + +n/a + + export a list of terminal connections in an old, custom file format +
export_openems +no +WIP + +n/a + + export a matlab file suitable for OpenEMS simulation +
export_openscad +no +WIP + +n/a + + export a colored 3D model as an openscad script +
export_png +no +works + +n/a + + render the on-screen version or emulated photo mode version in .png +
+ render the on-screen version or emulated photo mode version in .gif +
+ render the on-screen version or emulated photo mode version in .jpeg +
export_ps +no +works + +n/a + + render black&white postscript (single or multiple files) +
+ render black&white or color embedded postscript (single file) +
export_stat +no +works + +n/a + + export a lihata file with anonimized statistics of the board +
export_svg +no +works + +n/a + + write an svg (Scalable Vector Graphics) +
export_test + +WIP + +n/a + +n/a +
export_vfs_fuse + +WIP + +n/a + +n/a +
export_vfs_mc + +WIP + +n/a + +n/a +
export_xy +no +works + +n/a + + geda/PCB xy +
+ gxyrs +
+ Macrofab's pick&place +
+ pick&place file for the TM220/TM240 device +
+ KiCad .pos file + +
+ + + Index: tags/2.1.2/doc/user/09_appendix/index.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/index.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/index.html (revision 24813) @@ -0,0 +1,25 @@ + + + + pcb-rnd user manual + + + + +

pcb-rnd User Manual: Appendix

+

+

9.0 Action reference

+
  • pcb-rnd action reference +

    9.1 List of formats

    +
  • File format support in pcb-rnd +

    9.2 External resources

    +
  • Useful resources for designing with +pcb-rnd +

    9.4 Layer colors

    +
  • Layer color mechanism +

    9.5 Dialog boxes

    +
  • List of GUI dialog boxes +

    9.6 Glossary of terminology

    +
  • Useful terminology for a common vernacular + + Index: tags/2.1.2/doc/user/09_appendix/layer_colors.html =================================================================== --- tags/2.1.2/doc/user/09_appendix/layer_colors.html (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/layer_colors.html (revision 24813) @@ -0,0 +1,48 @@ + + + + pcb-rnd user manual + + + + +

    pcb-rnd User Manual: Appendix

    +

    +

    9.4 Layer colors

    +

    +Each layer has its own layer color. Starting with lihata board v5, the +layer color is saved to and loaded from board files. Layers retain their +color even when they are moved within or between layer groups. +

    +In parallel to this mechanism, there is a set of default colors +defined in the conf subsystem: a set of default copper layer colors and +specific default colors for paste, mask and silk layers. +

    +There are only two cases when the default colors from the config subsystem +are used: +

      +
    • +When a new layer is created or a layer without color specified is loaded +from a file or when a layer is loaded from a file format that does not +support per layer color, a default color is assigned from the config, +depending on the layer type. + +
    • +When an object needs to be displayed out of the board, e.g. in the footprint +preview window of the library dialog +
    +

    +Composite rendering: positive layers are always rendered using their own +layer color (e.g. it is possible to define two silk layers in the top silk +group with two different colors, and the silk drawing on screen will have +two colors). A negative layer's color is normally invisible, thus does not +matter, because objects of a negative layer are removing pixels, not drawing +them. +

    +When a composite layer group is rendered with the first layer being negative +(typical for mask), the rendering code needs to apply a fill that covers +the whole board, so the negative layer objects can cut out from that fill. The +color of this fill is the color of the first layer. + + + Index: tags/2.1.2/doc/user/09_appendix/src/Makefile =================================================================== --- tags/2.1.2/doc/user/09_appendix/src/Makefile (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/src/Makefile (revision 24813) @@ -0,0 +1,24 @@ +# NOTE: aagraph is at svn://repo.hu/projects/aagraph/trunk + +PCBRND = ../../../../src/pcb-rnd +CLEANFILES=../action_details.html ../action_reference.html ../formats.html ../bridges.svg ../dialogs.html + +all: $(CLEANFILES) + +../action_details.html: ./action_compiler.sh ../action_src/*.html + ./action_compiler.sh ../action_src/*.html > ../action_details.html + +../action_reference.html : ./dump_actions_to_html.sh $(PCBRND) ../action_details.html + ./dump_actions_to_html.sh > ../action_reference.html + +../bridges.svg: bridges.txt + aagraph -Tsvg bridges.txt > ../bridges.svg + +../formats.html: gen_formats.sh ../../../../src_plugins/io_*/*.pup ../../../../src_plugins/import_*/*.pup ../../../../src_plugins/export_*/*.pup + ./gen_formats.sh > ../formats.html + +../dialogs.html: $(PCBRND) ./gen_dialogs.sh ./dialog_extra.awk + ./gen_dialogs.sh > ../dialogs.html + +clean: + rm $(CLEANFILES) Index: tags/2.1.2/doc/user/09_appendix/src/action_compiler.sh =================================================================== --- tags/2.1.2/doc/user/09_appendix/src/action_compiler.sh (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/src/action_compiler.sh (revision 24813) @@ -0,0 +1,162 @@ +#!/bin/sh + +SEP="<@@@@>" + +compile() +{ + awk -v "SEP=$SEP" ' + BEGIN { + q="\"" + SEP="^" SEP + } + + function strip(s) { + sub("^[ \t]*", "", s) + sub("[ \t]*$", "", s) + return s + } + + function read_tag(tag, tmp1,tmp2) { + getline tmp1 + getline tmp2 + if (tmp2 ~ " "/dev/stderr" + exit(1) + } + + function notav(s) { + if (s == "") return "n/a" + return s + } + + function end_act() + { + if (current != "") + print "" + currrent = "" + } + + ($0 ~ SEP) { + end_act() + action = "" + $1="" + current=tolower(strip($0)) + sub("^.*/", "", current) + sub(".html$", "", current) + + if (current in ANAME) + aname = ANAME[current] + else + aname = current + + print "" + print "

    " aname "

    " + print "
    " + print "

    " + print "" + print "
    Syntax summary:" notav(SYNTAX[current]) + print "
    Help text:" notav(HELP[current]) + print "
    Registered by:" notav(COOKIE[current]) + print "
    " + print "

    " + next + } + + (current == "") && (/^A/) { + # reading the action list: new action + action=strip($0) + sub("^A", "", action) + aname= action + action = tolower(action) +# avoid saving duplicates at the main action node + if (action in SEEN) + action = action "_dup" + else + ANAME[action] = aname + SEEN[action] = 1 + next + } + + + (current == "") && (/^D/) { + # reading the action list: help line + tmp = $0 + sub("^D", "", tmp) + HELP[action]=HELP[action] "\n" tmp + next + } + + (current == "") && (/^S/) { + # reading the action list: syntax line + tmp = $0 + sub("^S", "", tmp) + SYNTAX[action]=SYNTAX[action] "\n" tmp + next + } + + (current == "") && (/^C/) { + # reading the action list: cookie line + tmp = $0 + sub("^C", "", tmp) + COOKIE[action]=COOKIE[action] "\n" tmp + next + } + + /^/ { + arg = read_tag("arg") + print "" arg "" + next + } + + /^/ { + ex = read_tag("example") + print "Example:", ex, "
    " + next + } + + /^/ { + act = tolower(read_tag("act")) + print "" act "" + next + } + + { + print + } + + END { + end_act() + } + ' +} + +echo ' + + + + pcb-rnd user manual - action details + + + + +

    pcb-rnd actions (details)

    +' + +( + ( + cd ../../../../src + ./pcb-rnd --dump-actions 2>/dev/null + ) + for fn in "$@" + do + echo "" + echo "$SEP $fn" + tr "\n\r\t" " " < $fn | sed "s@<@\n<@g;s@>@>\n@g;" + done +) | compile + +echo ' + + +' Property changes on: tags/2.1.2/doc/user/09_appendix/src/action_compiler.sh ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/2.1.2/doc/user/09_appendix/src/bridges.txt =================================================================== --- tags/2.1.2/doc/user/09_appendix/src/bridges.txt (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/src/bridges.txt (revision 24813) @@ -0,0 +1,309 @@ + *io----------------------------------------------------------------+ + | [kica ] [gpcb ] [hyp_] [gsch] [c_pcb] | + | [ frt_ ] [fido] [prtl] [eagl] | + +------------------------------------------------------------------+ +*inp---+ *hid--------+ +|[eesc]| *pcbrnd----------------------------------------------------------+ |[batch ] | +|[mucs]| | | | | +|[lept]| | | |[gtk ] | +|[ltsp]| | | | | +|[tcad]| | | |[lesstif] | +|[edif]| | | | | +|[netl]| | | |[remote] | +|[ipcd]| | | | | +|[easy]| | | | | +|[xsch]| | | | | +|[caly]| | | | | +|[hpgl]| +----------------------------------------------------------------+ +-----------+ ++------+ + *out-----------------------------------------------------------------+ + | [bbrd] [bom_] [xy__] [gerb] [opcd] [lpr_] [scad] | [web ] + | [stat] [ps__] [svg_] [png_] [dxf_] | + +--------------------------------------------------------------------+ +%% + +[] + shape box + + +[inp] + linecolor #cccccc + bgcolor #cccccc + textcolor #884433 + label input-only + valign top + +[io] + linecolor #cccccc + bgcolor #cccccc + textcolor #884433 + label input-output + valign top + +[out] + linecolor #cccccc + bgcolor #cccccc + textcolor #884433 + label output-only + valign bottom + +[hid] + linecolor #cccccc + bgcolor #cccccc + textcolor #884433 + label HID (GUI) + valign top + + +[pcbrnd] + label pcb-rnd + bgcolor #00ffff + + +[eesc] + label kicad\neeschema + +[mucs] + label mucs PCB\nautorouter + +[lept] + label lepton\nEDA + +[ltsp] + label LTSpice + +[tcad] + label TinyCAD + +[edif] + label (any)\nEDIF + +[netl] + label (any)\nnetlist + +[ipcd] + label (any)\nIPC-D-356 + +[hpgl] + label HPGL\n(2D CAD) + +[easy] + label EasyEDA\n(web2.0) + +[xsch] + label XSCHEM\n + +[caly] + label Calay\n + +[bbrd] + label breadboard + + +[hyp_] + label Mentor\nhyperlynx + +[gsch] + label gEDA\ngschem + +[kica] + label kicad\npcbnew + +[gpcb] + label gEDA\npcb + +[frt_] + label freerouting.net\nautorouter + +[fido] + label FidoCadJ\n(board) + +[prtl] + label Protel\nAutotrax + +[eagl] + label Eagle\n(board) + +[c_pcb] + label c-pcb\n(autorouting) + + + +[bbrd] + label breadboard + +[bom_] + label BOM + +[xy__] + label XY\ntemplated + +[gerb] + label gerber + +[opcd] + label ipcd356\ne-tester + +[lpr_] + label lpr\n(print) + +[dxf_] + label dxf\n(2D CAD) + +[scad] + label openscad\n(3D CAD) + +[stat] + label stat\nstatistics + +[ps__] + label ps\npostscript + +[svg_] + label svg + +[png_] + label png\njpg, bmp + + + + + +[batch] + label batch\nCLI/automation + +[gtk] + label gtk\ngdk or gl render + +[lesstif] + label lesstif\n(motif) + +[remote] + label remote\n(network) + +[web] + label web client\n(javascript) + linecolor #aaaaaa + textcolor #aaaaaa + + +-> pcbrnd bbrd.n + label .png + +-> pcbrnd bom_.n + label text + +-> pcbrnd xy__.n + label .xy + +-> pcbrnd gerb.n + label .grb, .cnc + +-> eesc.e pcbrnd + label import\nschematics + +-> pcbrnd opcd.n + label IPC356D + +-> pcbrnd lpr_.n + label ps + +-> pcbrnd dxf_.n + +-> pcbrnd scad.n + +-> pcbrnd stat.n + label lihata + +-> pcbrnd ps__.n + label postscript + +-> pcbrnd svg_.n + label svg + +-> pcbrnd png_.n + + + +-> mucs.e pcbrnd + label import\nnetlist + +-> lept.e pcbrnd + label import\nschematics + +-> ltsp.e pcbrnd + label import\nschematics + +-> tcad.e pcbrnd + label import\nschematics + +-> edif.e pcbrnd + label import\nschematics + +-> netl.e pcbrnd + label import\nnetlist + +-> ipcd.e pcbrnd + label netlist\npads/subcs + +-> easy.e pcbrnd + label import\nschematics + +-> xsch.e pcbrnd + label import\nschematics + +-> caly.e pcbrnd + label import\nschematics + +-> hpgl.e pcbrnd + label import\nlines/arcs + + + + +<-> hyp_.s pcbrnd + label board + +<-> gsch.s pcbrnd + label schematics + +<-> gpcb.s-0.3 pcbrnd + label board + +<-> gpcb.s+0.3 pcbrnd + label footprint + +<-> kica.s-0.4 pcbrnd + label board\ns-expr + +<- kica.s pcbrnd + label board\nlegacy + +<-> kica.s+0.4 pcbrnd + label footprint\ns-expr + +<-> frt_.s pcbrnd + label board + +<-> fido.s pcbrnd + label board + +<-> prtl.s pcbrnd + label board + +<-> eagl.s pcbrnd + label board + +<-> c_pcb.s pcbrnd + label board + +<-> pcbrnd batch.w + +<-> pcbrnd gtk.w + +<-> pcbrnd lesstif.w + +<-> pcbrnd remote.w + +<-> remote.s web + label TCP/IP Index: tags/2.1.2/doc/user/09_appendix/src/dialog_extra.awk =================================================================== --- tags/2.1.2/doc/user/09_appendix/src/dialog_extra.awk (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/src/dialog_extra.awk (revision 24813) @@ -0,0 +1,35 @@ +# extra information about dialog boxes; anything that can not be extracte +# automatically from the code. Arrays indexed by id or source. +BEGIN { + ACTION["brave"] = "brave()" + ACTION["progress"] = "n/a"; COMMENT["progress"] = "no action API yet (but it is planned)" + ACTION["asm"] = "asm()" + ACTION["cam"] = "cam()"; COMMENT["cam"] = "does not yet work in lesstif" + ACTION["constraint"] = "constraint()" + ACTION["about"] = "about()"; COMMENT["about"] = "lesstif: needs to be resized to at least 600 pixels high" + ACTION["prompt_for"] = "n/a"; COMMENT["prompt_for"] = "not for use from actions (for internal HID use)" + ACTION["fallback_color_pick"] = "n/a"; COMMENT["fallback_color_pick"] = "not for use from actions (for internal HID use)" + ACTION["flags"] = "FlagEdit()" + ACTION["fontsel"] = "FontSel()" + ACTION["layer_binding"] = "LayerBinding()" + ACTION["pstk_lib"] = "PstkLib()"; COMMENT["pstk_lib"] = "does not yet work in lesstif" + ACTION["log"] = "log()" + ACTION["netlist"] = "NetlistDialog()"; COMMENT["NetlistDialog"] = "does not yet work in lesstif" + ACTION["padstack_shape"] = "n/a"; COMMENT["padstack_shape"] = "open from within the padstack dialog" + ACTION["padstack"] = "PadstackEdit()" + ACTION["pinout"] = "pinout()" + ACTION["plugins"] = "ManagePlugins()"; COMMENT["plugins"] = "read-only list at the moment" + ACTION["preferences"] = "preferences()"; COMMENT["preferences"] = "lesstif: some tabs are unusable" + ACTION["pref_lib_path"] = "n/a"; COMMENT["pref_lib_path"] = "open from within the preferences dialog" + ACTION["pref_lib_path_help"] = "n/a"; COMMENT["pref_lib_path_help"] = "open from within the preferences dialog" + ACTION["undo"] = "UndoDialog()" + ACTION["openems_excitation"] = "OpenEMSExcitation()" + ACTION["mesh"] = "mesh()" + ACTION["extedit"] = "extedit()" + ACTION["poly_hatch"] = "hatch(interactive)" + ACTION["propedit"] = "propedit()" + ACTION["report"] = "report()" + ACTION["live_script"] = "LiveScript()" + ACTION["scripts"] = "BrowseScript()" + ACTION["shape"] = "shape()" +} Index: tags/2.1.2/doc/user/09_appendix/src/dump_actions_to_html.sh =================================================================== --- tags/2.1.2/doc/user/09_appendix/src/dump_actions_to_html.sh (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/src/dump_actions_to_html.sh (revision 24813) @@ -0,0 +1,115 @@ +#!/bin/sh + +# collates the pcb-rnd action table into a html doc page + +asrc="../action_src" + +cd ../../../../src +pcb_rnd_ver=`./pcb-rnd --version` +pcb_rnd_rev=`svn info ^/ | awk '/Revision:/ { + print $0 + got_rev=1 + exit + } + END { + if (!got_rev) + print "Rev unknown" + } + '` +cd ../doc/user/09_appendix/src + +echo " + + + pcb-rnd user manual + + + + +

    +

    pcb-rnd User Manual: Appendix

    +

    +

    Action Reference

    +" +echo "" a "" "" "" "" + } + + a="" + s="" + d="" + c="" +} + + +/^A/ { + flush_sd() + sub("^A", "", $0) + a = a "
    " $0 + next +} + +/^D/ { + sub("^D", "", $0) + d = d "
    " $0 + next +} + +/^S/ { + sub("^S", "", $0) + s = s "
    " $0 + next +} + +/^C/ { + sub("^C", "", $0) + c = c "
    " $0 + next +} + +' | sort -u | awk -v "asrc=$asrc" ' +# insert links around actions where applicable + BEGIN { + q = "\"" + } + // { + pre = $0 + sub(".*", "", pre) + post = $0 + sub(".*", "", post) + act = $0 + sub(".*", "", act) + sub(".*", "", act) + loact = tolower(act) + fn = asrc "/" loact ".html" + if ((getline < fn) == 1) + print pre "" post + else + print pre "" post + close(fn) + next + } + + { print $0 } + + END { + print "
    \n" "" +echo $pcb_rnd_ver ", " $pcb_rnd_rev +echo "" +echo "
    Action Description Syntax Plugin" +( + cd ../../../../src + ./pcb-rnd --dump-actions 2>/dev/null +) | awk ' + +function flush_sd() +{ + if ( a != "" || s != "" || d != "" ) { + sub("^
    ", "", a) + sub("^
    ", "", d) + sub("^
    ", "", s) + sub("^
    ", "", c) + print "
    " d "" s "" c "" act "" act "
    " + print "" + print "" + } +' Property changes on: tags/2.1.2/doc/user/09_appendix/src/dump_actions_to_html.sh ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/2.1.2/doc/user/09_appendix/src/gen_dialogs.sh =================================================================== --- tags/2.1.2/doc/user/09_appendix/src/gen_dialogs.sh (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/src/gen_dialogs.sh (revision 24813) @@ -0,0 +1,95 @@ +#!/bin/sh + +trunk=../../../.. + +# exceptions +dlgtbl=' +BEGIN { + # if source filename is the index and value regex-matches either id or name + # just ignore that line + IGNORE["src_plugins/dialogs/dlg_view.c"] = "" + IGNORE["src_plugins/dialogs/act_dad.c"] = "" +} + +END { + out("view*", "view*", "src_plugins/dialogs/dlg_view.c") +} +' + +echo ' + + + + pcb-rnd - list of file formats + + + + + +

    pcb-rnd User Manual: Appendix

    +

    +

    List of GUI dialog boxes

    + + +
    ID + dialog box name + action + source + comments +' + +$trunk/util/devhelpers/list_dialogs.sh | awk -F "[\t]" ' +function orna(s) +{ + if ((s == "") || (s == "")) return "n/a" + return s +} + +'"$dlgtbl"' +'"`cat dialog_extra.awk`"' + +function out(id, name, src, action, comment ,acturl1,acturl2,fn,tmp) { + if (action == "") { + if (id in ACTION) action = ACTION[id] + else if (src in ACTION) action = ACTION[src] + } + + if (action != "") { + acturl1 = action + sub("[(].*", "", acturl1) + fn = "../action_src/" acturl1 ".html" + if ((getline tmp < fn) == 1) { + acturl1 = "" + acturl2 = "" + } + else { + acturl1 = "" + acturl2 = "" + } + close(fn) + } + + if (comment == "") { + if (id in COMMENT) comment = COMMENT[id] + else if (src in COMMENT) comment = COMMENT[src] + else comment = " " + } + + print "
    " orna(id) "" orna(name) "" acturl1 orna(action) acturl2 "" src "" comment +} + +{ + id=$1 + name=$2 + src=$3 + if ((src in IGNORE) && ((name ~ IGNORE[src]) || (id ~ IGNORE[src]))) + next + out(id, name, src) +} +' + +echo ' +
    + + +' Property changes on: tags/2.1.2/doc/user/09_appendix/src/gen_dialogs.sh ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/2.1.2/doc/user/09_appendix/src/gen_formats.sh =================================================================== --- tags/2.1.2/doc/user/09_appendix/src/gen_formats.sh (nonexistent) +++ tags/2.1.2/doc/user/09_appendix/src/gen_formats.sh (revision 24813) @@ -0,0 +1,104 @@ +#!/bin/sh + +PLUGINS=../../../../src_plugins + +echo ' + + + + pcb-rnd - list of file formats + + + + + +

    pcb-rnd User Manual: Appendix

    +

    +

    File format support

    + + + +
    plugin native state reads formats writes formats +' + +files_io=`ls $PLUGINS/io_*/*.pup | sort` +files_e=`ls $PLUGINS/export_*/*.pup | sort` +files_i=`ls $PLUGINS/import_*/*.pup | sort` + +for n in $files_io $files_i $files_e +do + bn=`basename $n` + bn=${bn%%.pup} + sed ' + /^[$]fmt[-]/ { s@^@'$bn' @; p } + /^[$]state/ { s@^@'$bn' @; p } + { d } + ' $n +done | awk ' + BEGIN { + plgs = 0 + } + { + if ($1 != last) { + PLG[plgs] = $1 + last = $1 + plgs++ + } + p=$1 + f=$2 + text=$0 + sub("^[^ \t]+[ \t]+[^ \t]+[ \t]+", "", text) + DATA[p, f] = DATA[p, f] SUBSEP text + } + + function col(mask ,n,v,i,A) { + print " " + v = split(DATA[mask], A, "[" SUBSEP "]") + if (v == 0) { + print "n/a" + return + } + i = 0; + for(n = 1; n <= v; n++) { + if (A[n] == "") + continue; + if (i) + print "
    " + print " " A[n] + i++ + } + } + + function strip(s) + { + gsub("[" SUBSEP "]", " ", s) + sub("^[ \t]*", "", s) + sub("[ \t]*$", "", s) + return s + } + + function row(plg) { + print "
    " plg + print "" strip(DATA[plg, "$fmt-native"]) + print "" strip(DATA[plg, "$state"]) + col(plg SUBSEP "$fmt-feature-r") + col(plg SUBSEP "$fmt-feature-w") + } + + END { + for(p=0; p < plgs; p++) + if (DATA[PLG[p], "$fmt-native"] ~ "yes") + row(PLG[p]) + + for(p=0; p < plgs; p++) + if (!(DATA[PLG[p], "$fmt-native"] ~ "yes")) + row(PLG[p]) + } +' + + +echo ' +
    + + +' Property changes on: tags/2.1.2/doc/user/09_appendix/src/gen_formats.sh ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/2.1.2/doc/user/Makefile =================================================================== --- tags/2.1.2/doc/user/Makefile (nonexistent) +++ tags/2.1.2/doc/user/Makefile (revision 24813) @@ -0,0 +1,35 @@ +ROOT=../.. +BUILD=$(ROOT)/util/build_ps.sh +USERDIR=$(DOCDIR)/user + +INSTD = 02_model 03_data 04_invoc 05_ui 06_feature 07_io \ + 08_util 09_appendix + +all: user.pdf + +user.ps: ps.lst $(BUILD) default.css Makefile + HTML2PS_OPTS="-f default.css" HTML2PS_SED="s^<[hH]1>.*^^g" $(BUILD) `cat ps.lst` > user.ps + +user.pdf: user.ps + ps2pdf user.ps + +ps.lst: */*.html */*.png + echo "title.html" > ps.lst + echo "index.html" >> ps.lst + ls */*.html | sort >> ps.lst + +include Makefile.inst + +regen: instgen + ./instgen + +install: + $(MAKE) install_all HOW="install -f" + +linstall: + $(MAKE) install_all HOW="install -f -l --absolute " + +uninstall: + $(MAKE) install_all HOW="install -u" + +include $(ROOT)/Makefile.conf Index: tags/2.1.2/doc/user/Makefile.inst =================================================================== --- tags/2.1.2/doc/user/Makefile.inst (nonexistent) +++ tags/2.1.2/doc/user/Makefile.inst (revision 24813) @@ -0,0 +1,114 @@ +### autogenerated, DO NOT EDIT (but do commit); run make regen on *NIX ### +install_all: + $(SCCBOX) mkdir -p $(USERDIR)/01_intro + $(SCCBOX) $(HOW) 01_intro/Makefile $(USERDIR)/01_intro/Makefile + $(SCCBOX) $(HOW) 01_intro/flow.svg $(USERDIR)/01_intro/flow.svg + $(SCCBOX) $(HOW) 01_intro/history.html $(USERDIR)/01_intro/history.html + $(SCCBOX) $(HOW) 01_intro/index.html $(USERDIR)/01_intro/index.html + $(SCCBOX) mkdir -p $(USERDIR)/02_model + $(SCCBOX) $(HOW) 02_model/index.html $(USERDIR)/02_model/index.html + $(SCCBOX) $(HOW) 02_model/obj_arc.png $(USERDIR)/02_model/obj_arc.png + $(SCCBOX) $(HOW) 02_model/obj_line.png $(USERDIR)/02_model/obj_line.png + $(SCCBOX) $(HOW) 02_model/objects_basic.png $(USERDIR)/02_model/objects_basic.png + $(SCCBOX) $(HOW) 02_model/objects_complex.png $(USERDIR)/02_model/objects_complex.png + $(SCCBOX) $(HOW) 02_model/via_therm_noconn.png $(USERDIR)/02_model/via_therm_noconn.png + $(SCCBOX) $(HOW) 02_model/via_therm_round_x45.png $(USERDIR)/02_model/via_therm_round_x45.png + $(SCCBOX) $(HOW) 02_model/via_therm_round_x90.png $(USERDIR)/02_model/via_therm_round_x90.png + $(SCCBOX) $(HOW) 02_model/via_therm_sharp_x45.png $(USERDIR)/02_model/via_therm_sharp_x45.png + $(SCCBOX) $(HOW) 02_model/via_therm_sharp_x90.png $(USERDIR)/02_model/via_therm_sharp_x90.png + $(SCCBOX) $(HOW) 02_model/via_therm_solid.png $(USERDIR)/02_model/via_therm_solid.png + $(SCCBOX) mkdir -p $(USERDIR)/03_data + $(SCCBOX) $(HOW) 03_data/index.html $(USERDIR)/03_data/index.html + $(SCCBOX) mkdir -p $(USERDIR)/04_invoc + $(SCCBOX) $(HOW) 04_invoc/index.html $(USERDIR)/04_invoc/index.html + $(SCCBOX) mkdir -p $(USERDIR)/05_ui/01_gtk + $(SCCBOX) $(HOW) 05_ui/01_gtk/base_window_highlight_coordsreadout.png $(USERDIR)/05_ui/01_gtk/base_window_highlight_coordsreadout.png + $(SCCBOX) $(HOW) 05_ui/01_gtk/base_window_highlight_layerops.png $(USERDIR)/05_ui/01_gtk/base_window_highlight_layerops.png + $(SCCBOX) $(HOW) 05_ui/01_gtk/base_window_highlight_main.png $(USERDIR)/05_ui/01_gtk/base_window_highlight_main.png + $(SCCBOX) $(HOW) 05_ui/01_gtk/base_window_highlight_menus.png $(USERDIR)/05_ui/01_gtk/base_window_highlight_menus.png + $(SCCBOX) $(HOW) 05_ui/01_gtk/base_window_highlight_opsreadout.png $(USERDIR)/05_ui/01_gtk/base_window_highlight_opsreadout.png + $(SCCBOX) $(HOW) 05_ui/01_gtk/base_window_highlight_routestyle.png $(USERDIR)/05_ui/01_gtk/base_window_highlight_routestyle.png + $(SCCBOX) $(HOW) 05_ui/01_gtk/base_window_highlight_workops.png $(USERDIR)/05_ui/01_gtk/base_window_highlight_workops.png + $(SCCBOX) $(HOW) 05_ui/01_gtk/index.html $(USERDIR)/05_ui/01_gtk/index.html + $(SCCBOX) mkdir -p $(USERDIR)/05_ui/02_cli + $(SCCBOX) $(HOW) 05_ui/02_cli/index.html $(USERDIR)/05_ui/02_cli/index.html + $(SCCBOX) mkdir -p $(USERDIR)/05_ui/05_batch + $(SCCBOX) $(HOW) 05_ui/05_batch/index.html $(USERDIR)/05_ui/05_batch/index.html + $(SCCBOX) mkdir -p $(USERDIR)/05_ui + $(SCCBOX) $(HOW) 05_ui/index.html $(USERDIR)/05_ui/index.html + $(SCCBOX) mkdir -p $(USERDIR)/06_feature/acompnet + $(SCCBOX) $(HOW) 06_feature/acompnet/index.html $(USERDIR)/06_feature/acompnet/index.html + $(SCCBOX) mkdir -p $(USERDIR)/06_feature/autocrop + $(SCCBOX) $(HOW) 06_feature/autocrop/index.html $(USERDIR)/06_feature/autocrop/index.html + $(SCCBOX) mkdir -p $(USERDIR)/06_feature/distalign + $(SCCBOX) $(HOW) 06_feature/distalign/align_mixed_parts_x.png $(USERDIR)/06_feature/distalign/align_mixed_parts_x.png + $(SCCBOX) $(HOW) 06_feature/distalign/align_parts_y.png $(USERDIR)/06_feature/distalign/align_parts_y.png + $(SCCBOX) $(HOW) 06_feature/distalign/distalign.txt $(USERDIR)/06_feature/distalign/distalign.txt + $(SCCBOX) $(HOW) 06_feature/distalign/distribute_parts_x.png $(USERDIR)/06_feature/distalign/distribute_parts_x.png + $(SCCBOX) $(HOW) 06_feature/distalign/distribute_y_gaps.png $(USERDIR)/06_feature/distalign/distribute_y_gaps.png + $(SCCBOX) $(HOW) 06_feature/distalign/import_parts.png $(USERDIR)/06_feature/distalign/import_parts.png + $(SCCBOX) $(HOW) 06_feature/distalign/index.html $(USERDIR)/06_feature/distalign/index.html + $(SCCBOX) $(HOW) 06_feature/distalign/result.png $(USERDIR)/06_feature/distalign/result.png + $(SCCBOX) mkdir -p $(USERDIR)/06_feature/distaligntext + $(SCCBOX) $(HOW) 06_feature/distaligntext/distaligntext_1.png $(USERDIR)/06_feature/distaligntext/distaligntext_1.png + $(SCCBOX) $(HOW) 06_feature/distaligntext/distaligntext_2.png $(USERDIR)/06_feature/distaligntext/distaligntext_2.png + $(SCCBOX) $(HOW) 06_feature/distaligntext/distaligntext_3.png $(USERDIR)/06_feature/distaligntext/distaligntext_3.png + $(SCCBOX) $(HOW) 06_feature/distaligntext/index.html $(USERDIR)/06_feature/distaligntext/index.html + $(SCCBOX) mkdir -p $(USERDIR)/06_feature/djopt + $(SCCBOX) $(HOW) 06_feature/djopt/Makefile $(USERDIR)/06_feature/djopt/Makefile + $(SCCBOX) $(HOW) 06_feature/djopt/Post.html $(USERDIR)/06_feature/djopt/Post.html + $(SCCBOX) $(HOW) 06_feature/djopt/Pre.html $(USERDIR)/06_feature/djopt/Pre.html + $(SCCBOX) $(HOW) 06_feature/djopt/debumpify.out.pcb $(USERDIR)/06_feature/djopt/debumpify.out.pcb + $(SCCBOX) $(HOW) 06_feature/djopt/debumpify.out.png $(USERDIR)/06_feature/djopt/debumpify.out.png + $(SCCBOX) $(HOW) 06_feature/djopt/debumpify.pcb $(USERDIR)/06_feature/djopt/debumpify.pcb + $(SCCBOX) $(HOW) 06_feature/djopt/debumpify.png $(USERDIR)/06_feature/djopt/debumpify.png + $(SCCBOX) $(HOW) 06_feature/djopt/debumpify.txt $(USERDIR)/06_feature/djopt/debumpify.txt + $(SCCBOX) $(HOW) 06_feature/djopt/index.html $(USERDIR)/06_feature/djopt/index.html + $(SCCBOX) $(HOW) 06_feature/djopt/miter.out.pcb $(USERDIR)/06_feature/djopt/miter.out.pcb + $(SCCBOX) $(HOW) 06_feature/djopt/miter.out.png $(USERDIR)/06_feature/djopt/miter.out.png + $(SCCBOX) $(HOW) 06_feature/djopt/miter.pcb $(USERDIR)/06_feature/djopt/miter.pcb + $(SCCBOX) $(HOW) 06_feature/djopt/miter.png $(USERDIR)/06_feature/djopt/miter.png + $(SCCBOX) $(HOW) 06_feature/djopt/miter.txt $(USERDIR)/06_feature/djopt/miter.txt + $(SCCBOX) $(HOW) 06_feature/djopt/orthopull.out.pcb $(USERDIR)/06_feature/djopt/orthopull.out.pcb + $(SCCBOX) $(HOW) 06_feature/djopt/orthopull.out.png $(USERDIR)/06_feature/djopt/orthopull.out.png + $(SCCBOX) $(HOW) 06_feature/djopt/orthopull.pcb $(USERDIR)/06_feature/djopt/orthopull.pcb + $(SCCBOX) $(HOW) 06_feature/djopt/orthopull.png $(USERDIR)/06_feature/djopt/orthopull.png + $(SCCBOX) $(HOW) 06_feature/djopt/orthopull.txt $(USERDIR)/06_feature/djopt/orthopull.txt + $(SCCBOX) $(HOW) 06_feature/djopt/unjaggy.out.pcb $(USERDIR)/06_feature/djopt/unjaggy.out.pcb + $(SCCBOX) $(HOW) 06_feature/djopt/unjaggy.out.png $(USERDIR)/06_feature/djopt/unjaggy.out.png + $(SCCBOX) $(HOW) 06_feature/djopt/unjaggy.pcb $(USERDIR)/06_feature/djopt/unjaggy.pcb + $(SCCBOX) $(HOW) 06_feature/djopt/unjaggy.png $(USERDIR)/06_feature/djopt/unjaggy.png + $(SCCBOX) $(HOW) 06_feature/djopt/unjaggy.txt $(USERDIR)/06_feature/djopt/unjaggy.txt + $(SCCBOX) $(HOW) 06_feature/djopt/vianudge.out.pcb $(USERDIR)/06_feature/djopt/vianudge.out.pcb + $(SCCBOX) $(HOW) 06_feature/djopt/vianudge.out.png $(USERDIR)/06_feature/djopt/vianudge.out.png + $(SCCBOX) $(HOW) 06_feature/djopt/vianudge.pcb $(USERDIR)/06_feature/djopt/vianudge.pcb + $(SCCBOX) $(HOW) 06_feature/djopt/vianudge.png $(USERDIR)/06_feature/djopt/vianudge.png + $(SCCBOX) $(HOW) 06_feature/djopt/vianudge.txt $(USERDIR)/06_feature/djopt/vianudge.txt + $(SCCBOX) $(HOW) 06_feature/djopt/viatrim.out.pcb $(USERDIR)/06_feature/djopt/viatrim.out.pcb + $(SCCBOX) $(HOW) 06_feature/djopt/viatrim.out.png $(USERDIR)/06_feature/djopt/viatrim.out.png + $(SCCBOX) $(HOW) 06_feature/djopt/viatrim.pcb $(USERDIR)/06_feature/djopt/viatrim.pcb + $(SCCBOX) $(HOW) 06_feature/djopt/viatrim.png $(USERDIR)/06_feature/djopt/viatrim.png + $(SCCBOX) $(HOW) 06_feature/djopt/viatrim.txt $(USERDIR)/06_feature/djopt/viatrim.txt + $(SCCBOX) mkdir -p $(USERDIR)/06_feature + $(SCCBOX) $(HOW) 06_feature/index.html $(USERDIR)/06_feature/index.html + $(SCCBOX) mkdir -p $(USERDIR)/06_feature/query + $(SCCBOX) $(HOW) 06_feature/query/tutor_cli.html $(USERDIR)/06_feature/query/tutor_cli.html + $(SCCBOX) mkdir -p $(USERDIR)/06_feature/vendordrill + $(SCCBOX) $(HOW) 06_feature/vendordrill/index.html $(USERDIR)/06_feature/vendordrill/index.html + $(SCCBOX) mkdir -p $(USERDIR)/07_io/export_openscad + $(SCCBOX) $(HOW) 07_io/export_openscad/1206.scad $(USERDIR)/07_io/export_openscad/1206.scad + $(SCCBOX) $(HOW) 07_io/export_openscad/preliminary.txt $(USERDIR)/07_io/export_openscad/preliminary.txt + $(SCCBOX) mkdir -p $(USERDIR)/08_util + $(SCCBOX) $(HOW) 08_util/01_gsch2pcb-rnd.htm $(USERDIR)/08_util/01_gsch2pcb-rnd.htm + $(SCCBOX) $(HOW) 08_util/install_cgi.html $(USERDIR)/08_util/install_cgi.html + $(SCCBOX) mkdir -p $(USERDIR)/09_appendix + $(SCCBOX) $(HOW) 09_appendix/action_reference.html $(USERDIR)/09_appendix/action_reference.html + $(SCCBOX) $(HOW) 09_appendix/bridges.svg $(USERDIR)/09_appendix/bridges.svg + $(SCCBOX) $(HOW) 09_appendix/combined_glossary.html $(USERDIR)/09_appendix/combined_glossary.html + $(SCCBOX) $(HOW) 09_appendix/dialogs.html $(USERDIR)/09_appendix/dialogs.html + $(SCCBOX) $(HOW) 09_appendix/external_resources.html $(USERDIR)/09_appendix/external_resources.html + $(SCCBOX) $(HOW) 09_appendix/formats.html $(USERDIR)/09_appendix/formats.html + $(SCCBOX) $(HOW) 09_appendix/index.html $(USERDIR)/09_appendix/index.html + $(SCCBOX) $(HOW) default.css $(USERDIR)/default.css + $(SCCBOX) $(HOW) index.html $(USERDIR)/index.html + $(SCCBOX) $(HOW) title.html $(USERDIR)/title.html Index: tags/2.1.2/doc/user/default.css =================================================================== --- tags/2.1.2/doc/user/default.css (nonexistent) +++ tags/2.1.2/doc/user/default.css (revision 24813) @@ -0,0 +1,65 @@ +H1 { + border-bottom-style: solid; + border-bottom-width: 3px; +} + +H2 { + border-bottom-style: solid; + border-bottom-width: 1px; +} + +P { + text-align: justify; + margin-left: 20px; +} + +PRE { + margin-left: 20px; +} + +table.actsum { + border: none; + margin-left: 20px; +} + +td.actsum { + background-color: #f0f0f0; + border: none; + padding: 15px; + align: left; +} + +th.actsum { + background-color: #f0f0f0; + border: none; + padding: 15px; + align: right; +} + +table { + border-collapse: collapse; + border: 2px solid #555555; + margin-left: 20px; +} + +td { + border: 1px solid #777777; + padding: 5px; +} + +th { + border: 1px solid #777777; + background-color: #e0e0e0; + padding: 5px; +} + + +ul.toc { + list-style-type: none; + padding: 20px; +} + +ul.toc li { + padding: 5px; + font-size: 120%; +} Index: tags/2.1.2/doc/user/index.html =================================================================== --- tags/2.1.2/doc/user/index.html (nonexistent) +++ tags/2.1.2/doc/user/index.html (revision 24813) @@ -0,0 +1,24 @@ + + + + pcb-rnd user manual + + + + +

    pcb-rnd - user manual

    + +

    Table of Contents

    +

    +

    + Index: tags/2.1.2/doc/user/instgen =================================================================== --- tags/2.1.2/doc/user/instgen (nonexistent) +++ tags/2.1.2/doc/user/instgen (revision 24813) @@ -0,0 +1,26 @@ +#!/bin/sh +export LANG=C +find 0*_* *.html *.css -type f -print | sort | awk ' +BEGIN { + print "### autogenerated, DO NOT EDIT (but do commit); run make regen on *NIX ###" + print "install_all:" +} +($0 ~ "[/][.]") { next } +($0 ~ "[/]src[/]") { next } +/[.]bak$/ { next } +/[.]backup$/ { next } +/~$/ { next } + +($0 ~ "/") { + path = $0 + sub("/[^/]*$", "", path) + if (!(path in PATHS)) { + print " $(SCCBOX) mkdir -p $(USERDIR)/" path + PATHS[path]=1 + } +} + +{ + print " $(SCCBOX) $(HOW) " $0 " $(USERDIR)/" $0 +} +' > Makefile.inst Property changes on: tags/2.1.2/doc/user/instgen ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/2.1.2/doc/user/title.html =================================================================== --- tags/2.1.2/doc/user/title.html (nonexistent) +++ tags/2.1.2/doc/user/title.html (revision 24813) @@ -0,0 +1,19 @@ + + +

    +

    +

    +

    +

    +

    +

    +

    +

    +

    PCB-rnd

    +

    +

    +

    User manual

    +

    +

    + + Index: tags/2.1.2/doc/windows.txt =================================================================== --- tags/2.1.2/doc/windows.txt (nonexistent) +++ tags/2.1.2/doc/windows.txt (revision 24813) @@ -0,0 +1,38 @@ +State on windows +~~~~~~~~~~~~~~~~ + +Does not work yet. This file documents how far we got. The situation +is constantly improving. + +1. Cross compilation from Linux to win32 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +(developers may need this, if you are an user, skip to 2.) + +TODO: deps with mpk + +Use mingw and wine: + + ./configure --emu="wine cmd /c" --target=i586-mingw32msvc "$@" + +(Replace i586- with whatever toolchain prefix you have) + +2. download the binary pack +~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Temporary URL: http://igor2.repo.hu/tmp/pcb-rnd-pack.zip + +Download, unpack, run setup.bat then pcb-rnd.bat + +All binaries in the pack are cross-compiled from source, using mingw and +mpk. All binaries are 32-bit. The pack is self-contained, no gtk or other +external dependencies. + +Known bugs: + - inserting elements fail (even static ones) + - no shell and awk in the pack -> parametric footprints fail + - text (including menu text) doesn't appear on XP + - no exporters that depend on libgd (png, jpeg, gif) + +Worked on systems: + - Windows 8.1 pro, Hungarian, 32 bit + - Windows 7 pro, Hungarian, 64 bit + - Windows 7 pro, English, 64 bit Index: tags/2.1.2/doc/wishlist.txt =================================================================== --- tags/2.1.2/doc/wishlist.txt (nonexistent) +++ tags/2.1.2/doc/wishlist.txt (revision 24813) @@ -0,0 +1,14 @@ +Active user wishes: + W4: user doc [Miloh] + W7: programmable drc (star grounding) [James] + W9: push & shove [Erich, Evan] + +Being done: + W1: cschem [Chris] + +User wishes fulfilled: + W2: proper primitives - data model rewrite [Chris] + W3: more generic footprints [Chris, Evan] -> subcircuits + W5: 3d modeller export [Miloh, Evan] (bdale's sponsoration) + W6: GUI access to object attributes: gtk editor, find/select by attrib [James] + W8: gl support [Erich, Evan] Index: tags/2.1.2/font/HersheySans1.pcb_font =================================================================== --- tags/2.1.2/font/HersheySans1.pcb_font (nonexistent) +++ tags/2.1.2/font/HersheySans1.pcb_font (revision 24813) @@ -0,0 +1,1205 @@ +##name:Hershey Sans 1 Stroke Font v1.0 +##source:https://github.com/evil-mad/EggBot/blob/master/inkscape_driver/hersheydata.py +##ported_by:Erich S. Heinzle 2014 +##license:TODO +# +Symbol[' ' 1800] +( +) +Symbol['!' 1200] +( + SymbolLine[1191 1000 1191 3666 800] + SymbolLine[1191 4619 1000 4809 800] + SymbolLine[1000 4809 1191 4999 800] + SymbolLine[1191 4999 1381 4809 800] + SymbolLine[1381 4809 1191 4619 800] +) +Symbol['"' 1200] +( + SymbolLine[1000 1000 1000 2334 800] + SymbolLine[2523 1000 2523 2334 800] +) +Symbol['#' 1200] +( + SymbolLine[2573 1000 1239 5000 800] + SymbolLine[3916 1000 2582 5000 800] + SymbolLine[1339 2325 4207 2325 800] + SymbolLine[1000 3675 3866 3675 800] +) +Symbol['$' 1200] +( + SymbolLine[2333 300 2333 5824 800] + SymbolLine[3666 1633 3286 1252 800] + SymbolLine[3286 1252 2714 1062 800] + SymbolLine[2714 1062 1952 1062 800] + SymbolLine[1952 1062 1381 1252 800] + SymbolLine[1381 1252 1000 1633 800] + SymbolLine[1000 1633 1000 2015 800] + SymbolLine[1000 2015 1191 2395 800] + SymbolLine[1191 2395 1381 2586 800] + SymbolLine[1381 2586 1762 2776 800] + SymbolLine[1762 2776 2905 3157 800] + SymbolLine[2905 3157 3286 3347 800] + SymbolLine[3286 3347 3477 3538 800] + SymbolLine[3477 3538 3666 3919 800] + SymbolLine[3666 3919 3666 4490 800] + SymbolLine[3666 4490 3286 4872 800] + SymbolLine[3286 4872 2714 5062 800] + SymbolLine[2714 5062 1952 5062 800] + SymbolLine[1952 5062 1381 4872 800] + SymbolLine[1381 4872 1000 4490 800] + +) +Symbol['%' 1200] +( + SymbolLine[11285 1000 7857 4999 800] + SymbolLine[8809 1000 9191 1380 800] + SymbolLine[9191 1380 9191 1762 800] + SymbolLine[9191 1762 9000 2142 800] + SymbolLine[9000 2142 8619 2333 800] + SymbolLine[8619 2333 8238 2333 800] + SymbolLine[8238 2333 7857 1952 800] + SymbolLine[7857 1952 7857 1571 800] + SymbolLine[7857 1571 8048 1190 800] + SymbolLine[8048 1190 8428 1000 800] + SymbolLine[8428 1000 8809 1000 800] + SymbolLine[8809 1000 9191 1190 800] + SymbolLine[9191 1190 9762 1380 800] + SymbolLine[9762 1380 10332 1380 800] + SymbolLine[10332 1380 10905 1190 800] + SymbolLine[10905 1190 11285 1000 800] + SymbolLine[10523 3666 10143 3857 800] + SymbolLine[10143 3857 9952 4237 800] + SymbolLine[9952 4237 9952 4619 800] + SymbolLine[9952 4619 10332 4999 800] + SymbolLine[10332 4999 10714 4999 800] + SymbolLine[10714 4999 11095 4809 800] + SymbolLine[11095 4809 11285 4428 800] + SymbolLine[11285 4428 11285 4047 800] + SymbolLine[11285 4047 10905 3666 800] + SymbolLine[10905 3666 10523 3666 800] +) +Symbol['&' 1200] +( + SymbolLine[4809 2714 4809 2523 800] + SymbolLine[4809 2523 4618 2333 800] + SymbolLine[4618 2333 4428 2333 800] + SymbolLine[4428 2333 4237 2523 800] + SymbolLine[4237 2523 4046 2905 800] + SymbolLine[4046 2905 3666 3857 800] + SymbolLine[3666 3857 3285 4428 800] + SymbolLine[3285 4428 2905 4809 800] + SymbolLine[2905 4809 2523 4999 800] + SymbolLine[2523 4999 1762 4999 800] + SymbolLine[1762 4999 1380 4809 800] + SymbolLine[1380 4809 1189 4619 800] + SymbolLine[1189 4619 1000 4237 800] + SymbolLine[1000 4237 1000 3857 800] + SymbolLine[1000 3857 1189 3476 800] + SymbolLine[1189 3476 1380 3285 800] + SymbolLine[1380 3285 2714 2523 800] + SymbolLine[2714 2523 2905 2333 800] + SymbolLine[2905 2333 3094 1952 800] + SymbolLine[3094 1952 3094 1571 800] + SymbolLine[3094 1571 2905 1190 800] + SymbolLine[2905 1190 2523 1000 800] + SymbolLine[2523 1000 2142 1190 800] + SymbolLine[2142 1190 1952 1571 800] + SymbolLine[1952 1571 1952 1952 800] + SymbolLine[1952 1952 2142 2523 800] + SymbolLine[2142 2523 2523 3095 800] + SymbolLine[2523 3095 3475 4428 800] + SymbolLine[3475 4428 3857 4809 800] + SymbolLine[3857 4809 4237 4999 800] + SymbolLine[4237 4999 4618 4999 800] + SymbolLine[4618 4999 4809 4809 800] + SymbolLine[4809 4809 4809 4619 800] +) +Symbol[''' 1200] +( + SymbolLine[1191 1381 1000 1191 800] + SymbolLine[1000 1191 1191 1000 800] + SymbolLine[1191 1000 1381 1191 800] + SymbolLine[1381 1191 1381 1571 800] + SymbolLine[1381 1571 1191 1952 800] + SymbolLine[1191 1952 1000 2143 800] +) +Symbol['(' 1200] +( + SymbolLine[2333 0 1952 381 800] + SymbolLine[1952 381 1571 952 800] + SymbolLine[1571 952 1189 1715 800] + SymbolLine[1189 1715 1000 2667 800] + SymbolLine[1000 2667 1000 3429 800] + SymbolLine[1000 3429 1189 4381 800] + SymbolLine[1189 4381 1571 5143 800] + SymbolLine[1571 5143 1952 5714 800] + SymbolLine[1952 5714 2333 6095 800] +) +Symbol[')' 1200] +( + SymbolLine[1000 0 1380 381 800] + SymbolLine[1380 381 1762 952 800] + SymbolLine[1762 952 2143 1715 800] + SymbolLine[2143 1715 2332 2667 800] + SymbolLine[2332 2667 2332 3429 800] + SymbolLine[2332 3429 2143 4381 800] + SymbolLine[2143 4381 1762 5143 800] + SymbolLine[1762 5143 1380 5714 800] + SymbolLine[1380 5714 1000 6095 800] +) +Symbol['*' 1200] +( + SymbolLine[2667 1000 2667 5000 800] + SymbolLine[1000 2001 4333 4001 800] + SymbolLine[4333 2001 1000 4001 800] +) +Symbol['+' 1200] +( + SymbolLine[2714 1250 2714 4678 800] + SymbolLine[1000 2964 4428 2964 800] +) +Symbol[',' 1200] +( + SymbolLine[1381 4891 1191 5080 800] + SymbolLine[1191 5080 1000 4891 800] + SymbolLine[1000 4891 1191 4700 800] + SymbolLine[1191 4700 1381 4891 800] + SymbolLine[1381 4891 1381 5271 800] + SymbolLine[1381 5271 1000 5652 800] + +) +Symbol['-' 1200] +( + SymbolLine[0 3000 2500 3000 800] +) +Symbol['.' 1200] +( + SymbolLine[1190 4700 1000 4891 800] + SymbolLine[1000 4891 1190 5080 800] + SymbolLine[1190 5080 1380 4891 800] + SymbolLine[1380 4891 1190 4700 800] +) +Symbol['/' 1200] +( + SymbolLine[3251 1000 1000 5000 800] +) +Symbol['0' 1200] #numbers are new +( + SymbolLine[2143 1000 1572 1190 800] + SymbolLine[1572 1190 1190 1761 800] + SymbolLine[1190 1761 1000 2713 800] + SymbolLine[1000 2713 1000 3285 800] + SymbolLine[1000 3285 1190 4238 800] + SymbolLine[1190 4238 1572 4809 800] + SymbolLine[1572 4809 2143 5000 800] + SymbolLine[2143 5000 2524 5000 800] + SymbolLine[2524 5000 3095 4809 800] + SymbolLine[3095 4809 3476 4238 800] + SymbolLine[3476 4238 3667 3285 800] + SymbolLine[3667 3285 3667 2713 800] + SymbolLine[3667 2713 3476 1761 800] + SymbolLine[3476 1761 3095 1190 800] + SymbolLine[3095 1190 2524 1000 800] + SymbolLine[2524 1000 2143 1000 800] +) +Symbol['1' 1200] +( + SymbolLine[1000 1761 1380 1571 800] + SymbolLine[1380 1571 1952 1000 800] + SymbolLine[1952 1000 1952 5000 800] +) +Symbol['2' 1200] +( + SymbolLine[1190 1952 1190 1761 800] + SymbolLine[1190 1761 1381 1381 800] + SymbolLine[1381 1381 1570 1190 800] + SymbolLine[1570 1190 1952 1000 800] + SymbolLine[1952 1000 2713 1000 800] + SymbolLine[2713 1000 3095 1190 800] + SymbolLine[3095 1190 3285 1381 800] + SymbolLine[3285 1381 3475 1761 800] + SymbolLine[3475 1761 3475 2143 800] + SymbolLine[3475 2143 3285 2524 800] + SymbolLine[3285 2524 2904 3095 800] + SymbolLine[2904 3095 1000 5000 800] + SymbolLine[1000 5000 3666 5000 800] +) +Symbol['3' 1200] +( + SymbolLine[1380 1000 3475 1000 800] + SymbolLine[3475 1000 2332 2524 800] + SymbolLine[2332 2524 2904 2524 800] + SymbolLine[2904 2524 3284 2713 800] + SymbolLine[3284 2713 3475 2904 800] + SymbolLine[3475 2904 3666 3476 800] + SymbolLine[3666 3476 3666 3856 800] + SymbolLine[3666 3856 3475 4428 800] + SymbolLine[3475 4428 3095 4809 800] + SymbolLine[3095 4809 2523 5000 800] + SymbolLine[2523 5000 1952 5000 800] + SymbolLine[1952 5000 1380 4809 800] + SymbolLine[1380 4809 1190 4618 800] + SymbolLine[1190 4618 1000 4238 800] +) +Symbol['4' 1200] +( + SymbolLine[2904 1000 1000 3666 800] + SymbolLine[1000 3666 3856 3666 800] + SymbolLine[2904 1000 2904 5000 800] +) +Symbol['5' 1200] +( + SymbolLine[3286 1000 1381 1000 800] + SymbolLine[1381 1000 1190 2713 800] + SymbolLine[1190 2713 1381 2524 800] + SymbolLine[1381 2524 1952 2333 800] + SymbolLine[1952 2333 2524 2333 800] + SymbolLine[2524 2333 3095 2524 800] + SymbolLine[3095 2524 3476 2904 800] + SymbolLine[3476 2904 3667 3476 800] + SymbolLine[3667 3476 3667 3856 800] + SymbolLine[3667 3856 3476 4428 800] + SymbolLine[3476 4428 3095 4809 800] + SymbolLine[3095 4809 2524 5000 800] + SymbolLine[2524 5000 1952 5000 800] + SymbolLine[1952 5000 1381 4809 800] + SymbolLine[1381 4809 1190 4618 800] + SymbolLine[1190 4618 1000 4238 800] +) +Symbol['6' 1200] +( + SymbolLine[3285 1571 3095 1190 800] + SymbolLine[3095 1190 2523 1000 800] + SymbolLine[2523 1000 2143 1000 800] + SymbolLine[2143 1000 1570 1190 800] + SymbolLine[1570 1190 1190 1761 800] + SymbolLine[1190 1761 1000 2713 800] + SymbolLine[1000 2713 1000 3666 800] + SymbolLine[1000 3666 1190 4428 800] + SymbolLine[1190 4428 1570 4809 800] + SymbolLine[1570 4809 2143 5000 800] + SymbolLine[2143 5000 2333 5000 800] + SymbolLine[2333 5000 2904 4809 800] + SymbolLine[2904 4809 3285 4428 800] + SymbolLine[3285 4428 3475 3856 800] + SymbolLine[3475 3856 3475 3666 800] + SymbolLine[3475 3666 3285 3095 800] + SymbolLine[3285 3095 2904 2713 800] + SymbolLine[2904 2713 2333 2524 800] + SymbolLine[2333 2524 2143 2524 800] + SymbolLine[2143 2524 1570 2713 800] + SymbolLine[1570 2713 1190 3095 800] + SymbolLine[1190 3095 1000 3666 800] +) +Symbol['7' 1200] +( + SymbolLine[3666 1000 1761 5000 800] + SymbolLine[1000 1000 3666 1000 800] +) +Symbol['8' 1200] +( + SymbolLine[1952 1000 1380 1190 800] + SymbolLine[1380 1190 1190 1571 800] + SymbolLine[1190 1571 1190 1952 800] + SymbolLine[1190 1952 1380 2333 800] + SymbolLine[1380 2333 1761 2524 800] + SymbolLine[1761 2524 2523 2713 800] + SymbolLine[2523 2713 3095 2904 800] + SymbolLine[3095 2904 3475 3285 800] + SymbolLine[3475 3285 3666 3666 800] + SymbolLine[3666 3666 3666 4238 800] + SymbolLine[3666 4238 3475 4618 800] + SymbolLine[3475 4618 3284 4809 800] + SymbolLine[3284 4809 2713 5000 800] + SymbolLine[2713 5000 1952 5000 800] + SymbolLine[1952 5000 1380 4809 800] + SymbolLine[1380 4809 1190 4618 800] + SymbolLine[1190 4618 1000 4238 800] + SymbolLine[1000 4238 1000 3666 800] + SymbolLine[1000 3666 1190 3285 800] + SymbolLine[1190 3285 1570 2904 800] + SymbolLine[1570 2904 2142 2713 800] + SymbolLine[2142 2713 2904 2524 800] + SymbolLine[2904 2524 3284 2333 800] + SymbolLine[3284 2333 3475 1952 800] + SymbolLine[3475 1952 3475 1571 800] + SymbolLine[3475 1571 3284 1190 800] + SymbolLine[3284 1190 2713 1000 800] + SymbolLine[2713 1000 1952 1000 800] +) +Symbol['9' 1200] +( + SymbolLine[3475 2333 3285 2904 800] + SymbolLine[3285 2904 2904 3285 800] + SymbolLine[2904 3285 2332 3476 800] + SymbolLine[2332 3476 2142 3476 800] + SymbolLine[2142 3476 1571 3285 800] + SymbolLine[1571 3285 1189 2904 800] + SymbolLine[1189 2904 1000 2333 800] + SymbolLine[1000 2333 1000 2143 800] + SymbolLine[1000 2143 1189 1571 800] + SymbolLine[1189 1571 1571 1190 800] + SymbolLine[1571 1190 2142 1000 800] + SymbolLine[2142 1000 2332 1000 800] + SymbolLine[2332 1000 2904 1190 800] + SymbolLine[2904 1190 3285 1571 800] + SymbolLine[3285 1571 3475 2333 800] + SymbolLine[3475 2333 3475 3285 800] + SymbolLine[3475 3285 3285 4238 800] + SymbolLine[3285 4238 2904 4809 800] + SymbolLine[2904 4809 2332 5000 800] + SymbolLine[2332 5000 1952 5000 800] + SymbolLine[1952 5000 1380 4809 800] + SymbolLine[1380 4809 1189 4428 800] +) +Symbol[':' 1200] +( + SymbolLine[1190 3400 1000 3591 800] + SymbolLine[1000 3591 1190 3781 800] + SymbolLine[1190 3781 1380 3591 800] + SymbolLine[1380 3591 1190 3400 800] + SymbolLine[1190 4734 1000 4925 800] + SymbolLine[1000 4925 1190 5114 800] + SymbolLine[1190 5114 1380 4925 800] + SymbolLine[1380 4925 1190 4734 800] +) +Symbol[';' 1200] +( + SymbolLine[1191 3400 1000 3591 800] + SymbolLine[1000 3591 1191 3781 800] + SymbolLine[1191 3781 1380 3591 800] + SymbolLine[1380 3591 1191 3400 800] + SymbolLine[1380 4925 1191 5114 800] + SymbolLine[1191 5114 1000 4925 800] + SymbolLine[1000 4925 1191 4734 800] + SymbolLine[1191 4734 1380 4925 800] + SymbolLine[1380 4925 1380 5305 800] + SymbolLine[1380 5305 1000 5686 800] + +) +Symbol['<' 1200] +( + SymbolLine[3540 1000 1000 3001 800] + SymbolLine[1000 3001 3540 5000 800] +) +Symbol['=' 1200] +( + SymbolLine[0 2400 2500 2400 800] + SymbolLine[0 3600 2500 3600 800] +) +Symbol['>' 1200] +( + SymbolLine[1000 1000 3540 3001 800] + SymbolLine[3540 3001 1000 5000 800] +) +Symbol['?' 1200] +( + SymbolLine[1000 1952 1000 1762 800] + SymbolLine[1000 1762 1191 1381 800] + SymbolLine[1191 1381 1380 1191 800] + SymbolLine[1380 1191 1762 1000 800] + SymbolLine[1762 1000 2523 1000 800] + SymbolLine[2523 1000 2905 1191 800] + SymbolLine[2905 1191 3095 1381 800] + SymbolLine[3095 1381 3285 1762 800] + SymbolLine[3285 1762 3285 2143 800] + SymbolLine[3285 2143 3095 2523 800] + SymbolLine[3095 2523 2905 2714 800] + SymbolLine[2905 2714 2143 3095 800] + SymbolLine[2143 3095 2143 3666 800] + SymbolLine[2143 4618 1952 4809 800] + SymbolLine[1952 4809 2143 5000 800] + SymbolLine[2143 5000 2332 4809 800] + SymbolLine[2332 4809 2143 4618 800] + +) +Symbol['@' 1200] +( + SymbolLine[4751 3000 4500 2499 800] + SymbolLine[4500 2499 4001 2250 800] + SymbolLine[4001 2250 3250 2250 800] + SymbolLine[3250 2250 2751 2499 800] + SymbolLine[2751 2499 2500 2750 800] + SymbolLine[2500 2750 2250 3501 800] + SymbolLine[2250 3501 2250 4250 800] + SymbolLine[2250 4250 2500 4751 800] + SymbolLine[2500 4751 3001 5000 800] + SymbolLine[3001 5000 3751 5000 800] + SymbolLine[3751 5000 4251 4751 800] + SymbolLine[4251 4751 4500 4250 800] + SymbolLine[3250 2250 2751 2750 800] + SymbolLine[2751 2750 2500 3501 800] + SymbolLine[2500 3501 2500 4250 800] + SymbolLine[2500 4250 2751 4751 800] + SymbolLine[2751 4751 3001 5000 800] + SymbolLine[4751 2250 4500 4250 800] + SymbolLine[4500 4250 4500 4751 800] + SymbolLine[4500 4751 5001 5000 800] + SymbolLine[5001 5000 5502 5000 800] + SymbolLine[5502 5000 6001 4501 800] + SymbolLine[6001 4501 6251 3750 800] + SymbolLine[6251 3750 6251 3250 800] + SymbolLine[6251 3250 6001 2499 800] + SymbolLine[6001 2499 5751 2000 800] + SymbolLine[5751 2000 5251 1499 800] + SymbolLine[5251 1499 4751 1249 800] + SymbolLine[4751 1249 4001 1000 800] + SymbolLine[4001 1000 3250 1000 800] + SymbolLine[3250 1000 2500 1249 800] + SymbolLine[2500 1249 2000 1499 800] + SymbolLine[2000 1499 1501 2000 800] + SymbolLine[1501 2000 1250 2499 800] + SymbolLine[1250 2499 1000 3250 800] + SymbolLine[1000 3250 1000 4000 800] + SymbolLine[1000 4000 1250 4751 800] + SymbolLine[1250 4751 1501 5250 800] + SymbolLine[1501 5250 2000 5751 800] + SymbolLine[2000 5751 2500 6001 800] + SymbolLine[2500 6001 3250 6250 800] + SymbolLine[3250 6250 4001 6250 800] + SymbolLine[4001 6250 4751 6001 800] + SymbolLine[4751 6001 5251 5751 800] + SymbolLine[5251 5751 5502 5501 800] + SymbolLine[5001 2250 4751 4250 800] + SymbolLine[4751 4250 4751 4751 800] + SymbolLine[4751 4751 5001 5000 800] +) +Symbol['A' 1200] +( + SymbolLine[1524 1000 0 5000 800] + SymbolLine[1524 1000 3048 5000 800] + SymbolLine[572 3667 2477 3667 800] +) +Symbol['B' 1200] +( + SymbolLine[1000 1000 1000 5000 800] + SymbolLine[1000 1000 2714 1000 800] + SymbolLine[2714 1000 3285 1191 800] + SymbolLine[3285 1191 3476 1381 800] + SymbolLine[3476 1381 3666 1763 800] + SymbolLine[3666 1763 3666 2143 800] + SymbolLine[3666 2143 3476 2524 800] + SymbolLine[3476 2524 3285 2715 800] + SymbolLine[3285 2715 2714 2905 800] + SymbolLine[1000 2905 2714 2905 800] + SymbolLine[2714 2905 3285 3095 800] + SymbolLine[3285 3095 3476 3286 800] + SymbolLine[3476 3286 3666 3667 800] + SymbolLine[3666 3667 3666 4238 800] + SymbolLine[3666 4238 3476 4620 800] + SymbolLine[3476 4620 3285 4809 800] + SymbolLine[3285 4809 2714 5000 800] + SymbolLine[2714 5000 1000 5000 800] +) +Symbol['C' 1200] +( + SymbolLine[3857 1952 3666 1572 800] + SymbolLine[3666 1572 3285 1191 800] + SymbolLine[3285 1191 2905 1000 800] + SymbolLine[2905 1000 2142 1000 800] + SymbolLine[2142 1000 1762 1191 800] + SymbolLine[1762 1191 1380 1572 800] + SymbolLine[1380 1572 1190 1952 800] + SymbolLine[1190 1952 1000 2524 800] + SymbolLine[1000 2524 1000 3477 800] + SymbolLine[1000 3477 1190 4048 800] + SymbolLine[1190 4048 1380 4429 800] + SymbolLine[1380 4429 1762 4809 800] + SymbolLine[1762 4809 2142 5000 800] + SymbolLine[2142 5000 2905 5000 800] + SymbolLine[2905 5000 3285 4809 800] + SymbolLine[3285 4809 3666 4429 800] + SymbolLine[3666 4429 3857 4048 800] +) +Symbol['D' 1200] +( + SymbolLine[1000 1000 1000 5000 800] + SymbolLine[1000 1000 2334 1000 800] + SymbolLine[2334 1000 2905 1191 800] + SymbolLine[2905 1191 3286 1572 800] + SymbolLine[3286 1572 3476 1952 800] + SymbolLine[3476 1952 3666 2524 800] + SymbolLine[3666 2524 3666 3477 800] + SymbolLine[3666 3477 3476 4048 800] + SymbolLine[3476 4048 3286 4429 800] + SymbolLine[3286 4429 2905 4809 800] + SymbolLine[2905 4809 2334 5000 800] + SymbolLine[2334 5000 1000 5000 800] +) +Symbol['E' 1200] +( + SymbolLine[1000 1000 1000 5000 800] + SymbolLine[1000 1000 3476 1000 800] + SymbolLine[1000 2905 2523 2905 800] + SymbolLine[1000 5000 3476 5000 800] +) +Symbol['F' 1200] +( + SymbolLine[1000 1000 1000 5000 800] + SymbolLine[1000 1000 3475 1000 800] + SymbolLine[1000 2905 2523 2905 800] +) +Symbol['G' 1200] +( + SymbolLine[3857 1952 3666 1572 800] + SymbolLine[3666 1572 3286 1191 800] + SymbolLine[3286 1191 2905 1000 800] + SymbolLine[2905 1000 2143 1000 800] + SymbolLine[2143 1000 1762 1191 800] + SymbolLine[1762 1191 1381 1572 800] + SymbolLine[1381 1572 1191 1952 800] + SymbolLine[1191 1952 1000 2524 800] + SymbolLine[1000 2524 1000 3477 800] + SymbolLine[1000 3477 1191 4048 800] + SymbolLine[1191 4048 1381 4429 800] + SymbolLine[1381 4429 1762 4809 800] + SymbolLine[1762 4809 2143 5000 800] + SymbolLine[2143 5000 2905 5000 800] + SymbolLine[2905 5000 3286 4809 800] + SymbolLine[3286 4809 3666 4429 800] + SymbolLine[3666 4429 3857 4048 800] + SymbolLine[3857 4048 3857 3477 800] + SymbolLine[2905 3477 3857 3477 800] +) +Symbol['H' 1200] +( + SymbolLine[1000 1000 1000 5000 800] + SymbolLine[3667 5000 3667 1000 800] + SymbolLine[1000 2905 3667 2905 800] +) +Symbol['I' 1200] +( + SymbolLine[0 1000 1000 1000 800] + SymbolLine[500 1000 500 5000 800] + SymbolLine[0 5000 1000 5000 800] +) +Symbol['J' 1200] +( + SymbolLine[2905 1000 2905 4048 800] + SymbolLine[2905 4048 2715 4620 800] + SymbolLine[2715 4620 2524 4809 800] + SymbolLine[2524 4809 2143 5000 800] + SymbolLine[2143 5000 1763 5000 800] + SymbolLine[1763 5000 1381 4809 800] + SymbolLine[1381 4809 1191 4620 800] + SymbolLine[1191 4620 1000 4048 800] + SymbolLine[1000 4048 1000 3667 800] +) +Symbol['K' 1200] +( + SymbolLine[1000 1000 1000 5000 800] + SymbolLine[3666 1000 1000 3667 800] + SymbolLine[1952 2715 3666 5000 800] +) +Symbol['L' 1200] +( + SymbolLine[1000 1000 1000 5000 800] + SymbolLine[1000 5000 3285 5000 800] +) +Symbol['M' 1200] +( + SymbolLine[1000 1000 1000 5000 800] + SymbolLine[1000 1000 2523 5000 800] + SymbolLine[4048 1000 2523 5000 800] + SymbolLine[4048 1000 4048 5000 800] +) +Symbol['N' 1200] +( + SymbolLine[1000 1000 1000 5000 800] + SymbolLine[1000 1000 3666 5000 800] + SymbolLine[3666 1000 3666 5000 800] +) +Symbol['O' 1200] +( + SymbolLine[2142 1000 1762 1191 800] + SymbolLine[1762 1191 1380 1572 800] + SymbolLine[1380 1572 1190 1952 800] + SymbolLine[1190 1952 1000 2524 800] + SymbolLine[1000 2524 1000 3476 800] + SymbolLine[1000 3476 1190 4049 800] + SymbolLine[1190 4048 1380 4429 800] + SymbolLine[1380 4429 1762 4809 800] + SymbolLine[1762 4809 2142 5000 800] + SymbolLine[2142 5000 2905 5000 800] + SymbolLine[2905 5000 3285 4809 800] + SymbolLine[3285 4809 3666 4429 800] + SymbolLine[3666 4429 3857 4048 800] + SymbolLine[3857 4048 4046 3476 800] + SymbolLine[4046 3476 4046 2524 800] + SymbolLine[4046 2524 3857 1952 800] + SymbolLine[3857 1952 3666 1572 800] + SymbolLine[3666 1572 3285 1191 800] + SymbolLine[3285 1191 2905 1000 800] + SymbolLine[2905 1000 2142 1000 800] +) +Symbol['P' 1200] +( + SymbolLine[1000 1000 1000 5000 800] + SymbolLine[1000 1000 2714 1000 800] + SymbolLine[2714 1000 3285 1191 800] + SymbolLine[3285 1191 3476 1381 800] + SymbolLine[3476 1381 3666 1762 800] + SymbolLine[3666 1762 3666 2334 800] + SymbolLine[3666 2334 3476 2714 800] + SymbolLine[3476 2714 3285 2905 800] + SymbolLine[3285 2905 2714 3095 800] + SymbolLine[2714 3095 1000 3095 800] +) +Symbol['Q' 1200] +( + SymbolLine[2142 1000 1762 1191 800] + SymbolLine[1762 1191 1380 1572 800] + SymbolLine[1380 1572 1190 1952 800] + SymbolLine[1190 1952 1000 2524 800] + SymbolLine[1000 2524 1000 3476 800] + SymbolLine[1000 3476 1190 4048 800] + SymbolLine[1190 4048 1380 4429 800] + SymbolLine[1380 4429 1762 4809 800] + SymbolLine[1762 4809 2142 5000 800] + SymbolLine[2142 5000 2905 5000 800] + SymbolLine[2905 5000 3285 4809 800] + SymbolLine[3285 4809 3666 4429 800] + SymbolLine[3666 4429 3857 4048 800] + SymbolLine[3857 4048 4047 3476 800] + SymbolLine[4047 3476 4047 2524 800] + SymbolLine[4047 2524 3857 1952 800] + SymbolLine[3857 1952 3666 1572 800] + SymbolLine[3666 1572 3285 1191 800] + SymbolLine[3285 1191 2905 1000 800] + SymbolLine[2905 1000 2142 1000 800] + SymbolLine[2714 4238 3857 5381 800] +) +Symbol['R' 1200] +( + SymbolLine[1000 1000 1000 5000 800] + SymbolLine[1000 1000 2714 1000 800] + SymbolLine[2714 1000 3285 1191 800] + SymbolLine[3285 1191 3476 1381 800] + SymbolLine[3476 1381 3666 1762 800] + SymbolLine[3666 1762 3666 2143 800] + SymbolLine[3666 2143 3476 2524 800] + SymbolLine[3476 2524 3285 2714 800] + SymbolLine[3285 2714 2714 2905 800] + SymbolLine[2714 2905 1000 2905 800] + SymbolLine[2333 2905 3666 5000 800] +) +Symbol['S' 1200] +( + SymbolLine[3666 1572 3285 1191 800] + SymbolLine[3285 1191 2714 1000 800] + SymbolLine[2714 1000 1952 1000 800] + SymbolLine[1952 1000 1380 1191 800] + SymbolLine[1380 1191 1000 1572 800] + SymbolLine[1000 1572 1000 1952 800] + SymbolLine[1000 1952 1189 2334 800] + SymbolLine[1189 2334 1380 2524 800] + SymbolLine[1380 2524 1762 2714 800] + SymbolLine[1762 2714 2905 3095 800] + SymbolLine[2905 3095 3285 3286 800] + SymbolLine[3285 3286 3475 3476 800] + SymbolLine[3475 3476 3666 3857 800] + SymbolLine[3666 3857 3666 4429 800] + SymbolLine[3666 4429 3285 4809 800] + SymbolLine[3285 4809 2714 5000 800] + SymbolLine[2714 5000 1952 5000 800] + SymbolLine[1952 5000 1380 4809 800] + SymbolLine[1380 4809 1000 4429 800] +) +Symbol['T' 1200] +( + SymbolLine[2333 1000 2333 5000 800] + SymbolLine[1000 1000 3666 1000 800] +) +Symbol['U' 1200] +( + SymbolLine[1000 1000 1000 3857 800] + SymbolLine[1000 3857 1191 4429 800] + SymbolLine[1191 4429 1571 4809 800] + SymbolLine[1571 4809 2143 5000 800] + SymbolLine[2143 5000 2523 5000 800] + SymbolLine[2523 5000 3095 4809 800] + SymbolLine[3095 4809 3476 4429 800] + SymbolLine[3476 4429 3666 3857 800] + SymbolLine[3666 3857 3666 1000 800] + +) +Symbol['V' 1200] +( + SymbolLine[1000 1000 2523 5000 800] + SymbolLine[4048 1000 2523 5000 800] +) +Symbol['W' 1200] +( + SymbolLine[1000 1000 1952 5000 800] + SymbolLine[2905 1000 1952 5000 800] + SymbolLine[2905 1000 3857 5000 800] + SymbolLine[4809 1000 3857 5000 800] +) +Symbol['X' 1200] +( + SymbolLine[1000 1000 3666 5000 800] + SymbolLine[3666 1000 1000 5000 800] +) +Symbol['Y' 1200] +( + SymbolLine[1000 1000 2523 2905 800] + SymbolLine[2523 2905 2523 5000 800] + SymbolLine[4048 1000 2523 2905 800] +) +Symbol['Z' 1200] +( + SymbolLine[3666 1000 1000 5000 800] + SymbolLine[1000 1000 3666 1000 800] + SymbolLine[1000 5000 3666 5000 800] +) +Symbol['[' 1200] +( + SymbolLine[1000 0 1000 6094 800] + SymbolLine[1191 0 1191 6094 800] + SymbolLine[1000 0 2334 0 800] + SymbolLine[1000 6094 2334 6094 800] +) +Symbol['\' 1200] +( + SymbolLine[1000 1000 3251 5000 800] + +) +Symbol[']' 1200] +( + SymbolLine[7666 0 7666 6094 800] + SymbolLine[7857 0 7857 6094 800] + SymbolLine[6524 0 7857 0 800] + SymbolLine[6524 6094 7857 6094 800] +) +Symbol['^' 1200] +( + SymbolLine[2523 1000 1000 3222 800] + SymbolLine[2523 1000 4046 3222 800] +) +Symbol['_' 1200] +( +SymbolLine[1000 5000 3500 5000 800] +) +Symbol['a' 1200] #new +( + SymbolLine[3286 2333 3286 4999 800] + SymbolLine[3286 2903 2904 2522 800] + SymbolLine[2904 2522 2524 2333 800] + SymbolLine[2524 2333 1952 2333 800] + SymbolLine[1952 2333 1572 2522 800] + SymbolLine[1572 2522 1190 2903 800] + SymbolLine[1190 2903 1000 3474 800] + SymbolLine[1000 3474 1000 3856 800] + SymbolLine[1000 3856 1190 4427 800] + SymbolLine[1190 4427 1572 4808 800] + SymbolLine[1572 4808 1952 4999 800] + SymbolLine[1952 4999 2524 4999 800] + SymbolLine[2524 4999 2904 4808 800] + SymbolLine[2904 4808 3286 4427 800] +) +Symbol['b' 1200] #new +( + SymbolLine[1000 1000 1000 5000 800] + SymbolLine[1000 2904 1381 2523 800] + SymbolLine[1381 2523 1761 2333 800] + SymbolLine[1761 2333 2333 2333 800] + SymbolLine[2333 2333 2713 2523 800] + SymbolLine[2713 2523 3095 2904 800] + SymbolLine[3095 2904 3286 3475 800] + SymbolLine[3286 3475 3286 3856 800] + SymbolLine[3286 3856 3095 4427 800] + SymbolLine[3095 4427 2713 4809 800] + SymbolLine[2713 4809 2333 5000 800] + SymbolLine[2333 5000 1761 5000 800] + SymbolLine[1761 5000 1381 4809 800] + SymbolLine[1381 4809 1000 4427 800] +) + +Symbol['c' 1200] #new +( + SymbolLine[3286 2903 2904 2522 800] + SymbolLine[2904 2522 2524 2333 800] + SymbolLine[2524 2333 1952 2333 800] + SymbolLine[1952 2333 1572 2522 800] + SymbolLine[1572 2522 1190 2903 800] + SymbolLine[1190 2903 1000 3474 800] + SymbolLine[1000 3474 1000 3856 800] + SymbolLine[1000 3856 1190 4427 800] + SymbolLine[1190 4427 1572 4808 800] + SymbolLine[1572 4808 1952 4999 800] + SymbolLine[1952 4999 2524 4999 800] + SymbolLine[2524 4999 2904 4808 800] + SymbolLine[2904 4808 3286 4427 800] +) +Symbol['d' 1200] #new +( + SymbolLine[3284 1000 3284 5000 800] + SymbolLine[3284 2904 2904 2523 800] + SymbolLine[2904 2523 2523 2333 800] + SymbolLine[2523 2333 1952 2333 800] + SymbolLine[1952 2333 1570 2523 800] + SymbolLine[1570 2523 1189 2904 800] + SymbolLine[1189 2904 1000 3475 800] + SymbolLine[1000 3475 1000 3856 800] + SymbolLine[1000 3856 1189 4427 800] + SymbolLine[1189 4427 1570 4809 800] + SymbolLine[1570 4809 1952 5000 800] + SymbolLine[1952 5000 2523 5000 800] + SymbolLine[2523 5000 2904 4809 800] + SymbolLine[2904 4809 3284 4427 800] +) +Symbol['e' 1200] #NEW +( + SymbolLine[1000 3474 3284 3474 800] + SymbolLine[3284 3474 3284 3094 800] + SymbolLine[3284 3094 3094 2713 800] + SymbolLine[3094 2713 2904 2522 800] + SymbolLine[2904 2522 2523 2333 800] + SymbolLine[2523 2333 1952 2333 800] + SymbolLine[1952 2333 1570 2522 800] + SymbolLine[1570 2522 1189 2903 800] + SymbolLine[1189 2903 1000 3474 800] + SymbolLine[1000 3474 1000 3856 800] + SymbolLine[1000 3856 1189 4427 800] + SymbolLine[1189 4427 1570 4808 800] + SymbolLine[1570 4808 1952 4999 800] + SymbolLine[1952 4999 2523 4999 800] + SymbolLine[2523 4999 2904 4808 800] + SymbolLine[2904 4808 3284 4427 800] +) + +Symbol['f' 1200] #new +( + SymbolLine[2523 1000 2143 1000 800] + SymbolLine[2143 1000 1761 1190 800] + SymbolLine[1761 1190 1570 1761 800] + SymbolLine[1570 1761 1570 5000 800] + SymbolLine[1000 2333 2333 2333 800] +) + +Symbol['g' 1200] #NEW +( + SymbolLine[3286 2333 3286 5379 800] + SymbolLine[3286 5379 3095 5951 800] + SymbolLine[3095 5951 2904 6142 800] + SymbolLine[2904 6142 2524 6331 800] + SymbolLine[2524 6331 1952 6331 800] + SymbolLine[1952 6331 1572 6142 800] + SymbolLine[3286 2903 2904 2522 800] + SymbolLine[2904 2522 2524 2333 800] + SymbolLine[2524 2333 1952 2333 800] + SymbolLine[1952 2333 1572 2522 800] + SymbolLine[1572 2522 1190 2903 800] + SymbolLine[1190 2903 1000 3474 800] + SymbolLine[1000 3474 1000 3856 800] + SymbolLine[1000 3856 1190 4427 800] + SymbolLine[1190 4427 1572 4808 800] + SymbolLine[1572 4808 1952 4999 800] + SymbolLine[1952 4999 2524 4999 800] + SymbolLine[2524 4999 2904 4808 800] + SymbolLine[2904 4808 3286 4427 800] +) +Symbol['h' 1200] #new +( + SymbolLine[1000 1000 1000 5000 800] + SymbolLine[1000 3095 1570 2523 800] + SymbolLine[1570 2523 1952 2333 800] + SymbolLine[1952 2333 2523 2333 800] + SymbolLine[2523 2333 2904 2523 800] + SymbolLine[2904 2523 3095 3095 800] + SymbolLine[3095 3095 3095 5000 800] +) + +Symbol['i' 1200] #new +( + SymbolLine[1190 2324 1190 4990 800] + SymbolLine[1000 990 1190 1181 800] + SymbolLine[1190 1181 1381 990 800] + SymbolLine[1381 990 1190 800 800] + SymbolLine[1190 800 1000 990 800] +) +Symbol['j' 1200] #new +( + SymbolLine[1952 2324 1952 5561 800] + SymbolLine[1952 5561 1761 6133 800] + SymbolLine[1761 6133 1380 6323 800] + SymbolLine[1380 6323 1000 6323 800] + SymbolLine[1761 990 1952 1181 800] + SymbolLine[1952 1181 2143 990 800] + SymbolLine[2143 990 1952 800 800] + SymbolLine[1952 800 1761 990 800] +) +Symbol['k' 1200] #new +( + SymbolLine[1000 1000 1000 5000 800] + SymbolLine[2904 2333 1000 4238 800] + SymbolLine[1761 3475 3095 5000 800] +) + +Symbol['l' 1200] #new +( + SymbolLine[1000 1000 1000 5000 800] +) +Symbol['m' 1200] #new +( + SymbolLine[1000 2333 1000 4999 800] + SymbolLine[1000 3094 1570 2522 800] + SymbolLine[1570 2522 1952 2333 800] + SymbolLine[1952 2333 2523 2333 800] + SymbolLine[2523 2333 2904 2522 800] + SymbolLine[2904 2522 3094 3094 800] + SymbolLine[3094 3094 3094 4999 800] + SymbolLine[3094 3094 3666 2522 800] + SymbolLine[3666 2522 4046 2333 800] + SymbolLine[4046 2333 4618 2333 800] + SymbolLine[4618 2333 4998 2522 800] + SymbolLine[4998 2522 5189 3094 800] + SymbolLine[5189 3094 5189 4999 800] +) +Symbol['n' 1200] #new +( + SymbolLine[1000 2333 1000 4999 800] + SymbolLine[1000 3094 1572 2522 800] + SymbolLine[1572 2522 1952 2333 800] + SymbolLine[1952 2333 2524 2333 800] + SymbolLine[2524 2333 2904 2522 800] + SymbolLine[2904 2522 3095 3094 800] + SymbolLine[3095 3094 3095 4999 800] +) +Symbol['o' 1200] #new +( + SymbolLine[1952 2333 1570 2522 800] + SymbolLine[1570 2522 1189 2903 800] + SymbolLine[1189 2903 1000 3474 800] + SymbolLine[1000 3474 1000 3856 800] + SymbolLine[1000 3856 1189 4427 800] + SymbolLine[1189 4427 1570 4808 800] + SymbolLine[1570 4808 1952 4999 800] + SymbolLine[1952 4999 2523 4999 800] + SymbolLine[2523 4999 2904 4808 800] + SymbolLine[2904 4808 3284 4427 800] + SymbolLine[3284 4427 3475 3856 800] + SymbolLine[3475 3856 3475 3474 800] + SymbolLine[3475 3474 3284 2903 800] + SymbolLine[3284 2903 2904 2522 800] + SymbolLine[2904 2522 2523 2333 800] + SymbolLine[2523 2333 1952 2333 800] +) +Symbol['p' 1200] #new +( + SymbolLine[1000 2333 1000 6333 800] + SymbolLine[1000 2903 1381 2523 800] + SymbolLine[1381 2523 1761 2333 800] + SymbolLine[1761 2333 2333 2333 800] + SymbolLine[2333 2333 2714 2523 800] + SymbolLine[2714 2523 3095 2903 800] + SymbolLine[3095 2903 3286 3476 800] + SymbolLine[3286 3476 3286 3856 800] + SymbolLine[3286 3856 3095 4428 800] + SymbolLine[3095 4428 2714 4808 800] + SymbolLine[2714 4808 2333 4999 800] + SymbolLine[2333 4999 1761 4999 800] + SymbolLine[1761 4999 1381 4808 800] + SymbolLine[1381 4808 1000 4428 800] +) +Symbol['q' 1200] #new +( + SymbolLine[3285 2333 3285 6333 800] + SymbolLine[3285 2903 2904 2523 800] + SymbolLine[2904 2523 2524 2333 800] + SymbolLine[2524 2333 1952 2333 800] + SymbolLine[1952 2333 1571 2523 800] + SymbolLine[1571 2523 1190 2903 800] + SymbolLine[1190 2903 1000 3476 800] + SymbolLine[1000 3476 1000 3856 800] + SymbolLine[1000 3856 1190 4428 800] + SymbolLine[1190 4428 1571 4808 800] + SymbolLine[1571 4808 1952 4999 800] + SymbolLine[1952 4999 2524 4999 800] + SymbolLine[2524 4999 2904 4808 800] + SymbolLine[2904 4808 3285 4428 800] +) +Symbol['r' 1200] #new +( + SymbolLine[1000 2333 1000 4999 800] + SymbolLine[1000 3476 1190 2903 800] + SymbolLine[1190 2903 1572 2523 800] + SymbolLine[1572 2523 1952 2333 800] + SymbolLine[1952 2333 2524 2333 800] +) +Symbol['s' 1200] #new +( + SymbolLine[3094 2903 2904 2523 800] + SymbolLine[2904 2523 2332 2333 800] + SymbolLine[2332 2333 1761 2333 800] + SymbolLine[1761 2333 1189 2523 800] + SymbolLine[1189 2523 1000 2903 800] + SymbolLine[1000 2903 1189 3285 800] + SymbolLine[1189 3285 1570 3476 800] + SymbolLine[1570 3476 2523 3666 800] + SymbolLine[2523 3666 2904 3856 800] + SymbolLine[2904 3856 3094 4237 800] + SymbolLine[3094 4237 3094 4428 800] + SymbolLine[3094 4428 2904 4808 800] + SymbolLine[2904 4808 2332 4999 800] + SymbolLine[2332 4999 1761 4999 800] + SymbolLine[1761 4999 1189 4808 800] + SymbolLine[1189 4808 1000 4428 800] +) +Symbol['t' 1200] #new +( + SymbolLine[1572 1000 1572 4238 800] + SymbolLine[1572 4238 1761 4809 800] + SymbolLine[1761 4809 2143 5000 800] + SymbolLine[2143 5000 2524 5000 800] + SymbolLine[1000 2333 2333 2333 800] +) +Symbol['u' 1200] #new +( + SymbolLine[1000 2333 1000 4237 800] + SymbolLine[1000 4237 1190 4808 800] + SymbolLine[1190 4808 1572 4999 800] + SymbolLine[1572 4999 2143 4999 800] + SymbolLine[2143 4999 2524 4808 800] + SymbolLine[2524 4808 3095 4237 800] + SymbolLine[3095 2333 3095 4999 800] +) + +Symbol['v' 1200] #new +( + SymbolLine[1000 2333 2142 4999 800] + SymbolLine[3284 2333 2142 4999 800] +) + +Symbol['w' 1200] #new +( + SymbolLine[1000 2333 1761 4999 800] + SymbolLine[2523 2333 1761 4999 800] + SymbolLine[2523 2333 3286 4999 800] + SymbolLine[4047 2333 3286 4999 800] +) +Symbol['x' 1200] #new +( + SymbolLine[1000 2333 3095 4999 800] + SymbolLine[3095 2333 1000 4999 800] +) + + +Symbol['y' 1200] #new +( + SymbolLine[1190 2333 2333 4999 800] + SymbolLine[3476 2333 2333 4999 800] + SymbolLine[2333 4999 1952 5760 800] + SymbolLine[1952 5760 1572 6142 800] + SymbolLine[1572 6142 1190 6333 800] + SymbolLine[1190 6333 1000 6333 800] +) +Symbol['z' 1200] #new +( + SymbolLine[3095 2333 1000 4999 800] + SymbolLine[1000 2333 3095 2333 800] + SymbolLine[1000 4999 3095 4999 800] +) +Symbol['{' 1200] +( + SymbolLine[1952 0 1572 191 800] + SymbolLine[1572 191 1381 380 800] + SymbolLine[1381 380 1191 762 800] + SymbolLine[1191 762 1191 1143 800] + SymbolLine[1191 1143 1381 1523 800] + SymbolLine[1381 1523 1572 1714 800] + SymbolLine[1572 1714 1763 2095 800] + SymbolLine[1763 2095 1763 2475 800] + SymbolLine[1763 2475 1381 2857 800] + SymbolLine[1572 191 1381 571 800] + SymbolLine[1381 571 1381 952 800] + SymbolLine[1381 952 1572 1332 800] + SymbolLine[1572 1332 1763 1523 800] + SymbolLine[1763 1523 1952 1905 800] + SymbolLine[1952 1905 1952 2285 800] + SymbolLine[1952 2285 1763 2666 800] + SymbolLine[1763 2666 1000 3048 800] + SymbolLine[1000 3048 1763 3428 800] + SymbolLine[1763 3428 1952 3809 800] + SymbolLine[1952 3809 1952 4189 800] + SymbolLine[1952 4189 1763 4571 800] + SymbolLine[1763 4571 1572 4761 800] + SymbolLine[1572 4761 1381 5142 800] + SymbolLine[1381 5142 1381 5523 800] + SymbolLine[1381 5523 1572 5904 800] + SymbolLine[1381 3237 1763 3619 800] + SymbolLine[1763 3619 1763 4000 800] + SymbolLine[1763 4000 1572 4380 800] + SymbolLine[1572 4380 1381 4571 800] + SymbolLine[1381 4571 1191 4952 800] + SymbolLine[1191 4952 1191 5332 800] + SymbolLine[1191 5332 1381 5714 800] + SymbolLine[1381 5714 1572 5904 800] + SymbolLine[1572 5904 1952 6094 800] +) +Symbol['|' 1200] +( + SymbolLine[1000 250 1000 5750 800] +) +Symbol['}' 1200] +( + SymbolLine[1000 0 1381 191 800] + SymbolLine[1381 191 1572 380 800] + SymbolLine[1572 380 1762 762 800] + SymbolLine[1762 762 1762 1143 800] + SymbolLine[1762 1143 1572 1523 800] + SymbolLine[1572 1523 1381 1714 800] + SymbolLine[1381 1714 1191 2095 800] + SymbolLine[1191 2095 1191 2475 800] + SymbolLine[1191 2475 1572 2857 800] + SymbolLine[1381 191 1572 571 800] + SymbolLine[1572 571 1572 952 800] + SymbolLine[1572 952 1381 1332 800] + SymbolLine[1381 1332 1191 1523 800] + SymbolLine[1191 1523 1000 1905 800] + SymbolLine[1000 1905 1000 2285 800] + SymbolLine[1000 2285 1191 2666 800] + SymbolLine[1191 2666 1952 3048 800] + SymbolLine[1952 3048 1191 3428 800] + SymbolLine[1191 3428 1000 3809 800] + SymbolLine[1000 3809 1000 4189 800] + SymbolLine[1000 4189 1191 4571 800] + SymbolLine[1191 4571 1381 4761 800] + SymbolLine[1381 4761 1572 5142 800] + SymbolLine[1572 5142 1572 5523 800] + SymbolLine[1572 5523 1381 5904 800] + SymbolLine[1572 3237 1191 3619 800] + SymbolLine[1191 3619 1191 4000 800] + SymbolLine[1191 4000 1381 4380 800] + SymbolLine[1381 4380 1572 4571 800] + SymbolLine[1572 4571 1762 4952 800] + SymbolLine[1762 4952 1762 5332 800] + SymbolLine[1762 5332 1572 5714 800] + SymbolLine[1572 5714 1381 5904 800] + SymbolLine[1381 5904 1000 6094 800] +) +Symbol['~' 1200] +( + SymbolLine[1000 3643 1000 3262 800] + SymbolLine[1000 3262 1191 2691 800] + SymbolLine[1191 2691 1572 2500 800] + SymbolLine[1572 2500 1952 2500 800] + SymbolLine[1952 2500 2334 2691 800] + SymbolLine[2334 2691 3095 3262 800] + SymbolLine[3095 3262 3477 3452 800] + SymbolLine[3477 3452 3857 3452 800] + SymbolLine[3857 3452 4238 3262 800] + SymbolLine[4238 3262 4429 2881 800] + SymbolLine[1000 3262 1191 2881 800] + SymbolLine[1191 2881 1572 2691 800] + SymbolLine[1572 2691 1952 2691 800] + SymbolLine[1952 2691 2334 2881 800] + SymbolLine[2334 2881 3095 3452 800] + SymbolLine[3095 3452 3477 3643 800] + SymbolLine[3477 3643 3857 3643 800] + SymbolLine[3857 3643 4238 3452 800] + SymbolLine[4238 3452 4429 2881 800] + SymbolLine[4429 2881 4429 2500 800] +) + Index: tags/2.1.2/font/default_arc.lht =================================================================== --- tags/2.1.2/font/default_arc.lht (nonexistent) +++ tags/2.1.2/font/default_arc.lht (revision 24813) @@ -0,0 +1,2856 @@ +li:pcb-rnd-font-v1 { + ha:geda_pcb { + id = 0 + ha:symbols { + + ha:&20 { + width = 0.4mm + delta = 14.0mil + li:objects { + } + height = 1.373633mm + } + ha:] { + width = 0.127001mm + delta = 14.0mil + li:objects { + ha:line.0 { + y2 = 14.08mil + thickness = 8.0mil + x1 = 0.0 + x2 = 5.0mil + y1 = 14.08mil + } + ha:line.1 { + y2 = 1.373632mm + thickness = 8.0mil + x1 = 5.0mil + x2 = 5.0mil + y1 = 14.08mil + } + ha:line.2 { + y2 = 1.373632mm + thickness = 8.0mil + x1 = 0.0 + x2 = 5.0mil + y1 = 1.373632mm + } + } + height = 1.373633mm + } + ha:&5c { + width = 0.762001mm + delta = 13.0mil + li:objects { + ha:line.0 { + y2 = 1.246632mm + thickness = 8.0mil + x1 = 0.0 + x2 = 30.0mil + y1 = 0.484632mm + } + } + height = 1.246633mm + } + ha:b { + width = 0.713756mm + delta = 4.0mil + li:objects { + ha:line.0 { + y2 = 1.373632mm + thickness = 8.0mil + x1 = 0.104909mm + x2 = 0.104909mm + y1 = 14.08mil + } + ha:simplearc.1 { + thickness = 8.0mil + adelta = -360.000000 + astart = 20.000000 + x = 0.356877mm + y = 44.0mil + r = 0.253245mm + } + } + height = 1.474479mm + } + ha:c { + width = 0.611633mm + delta = 0.203723mm + li:objects { + ha:line.0 { + y2 = 0.865632mm + thickness = 8.0mil + x1 = 0.357631mm + x2 = 0.611632mm + y1 = 34.0mil + } + ha:line.1 { + y2 = 1.373632mm + thickness = 8.0mil + x1 = 0.357631mm + x2 = 0.611632mm + y1 = 54.0mil + } + ha:simplearc.2 { + thickness = 8.0mil + adelta = -180.000000 + astart = 90.000000 + x = 14.08mil + y = 44.0mil + r = 10.0mil + } + } + height = 1.475234mm + } + ha:d { + width = 0.713756mm + delta = 4.0mil + li:objects { + ha:line.0 { + y2 = 1.373632mm + thickness = 8.0mil + x1 = 0.612909mm + x2 = 0.612909mm + y1 = 14.08mil + } + ha:simplearc.1 { + thickness = 8.0mil + adelta = -360.000000 + astart = 20.000000 + x = 0.356877mm + y = 44.0mil + r = 0.253245mm + } + } + height = 1.474479mm + } + ha:e { + width = 0.715266mm + delta = 0.152923mm + li:objects { + ha:line.0 { + y2 = 1.119632mm + thickness = 8.0mil + x1 = 4.08mil + x2 = 0.611632mm + y1 = 1.119632mm + } + ha:line.1 { + y2 = 1.373632mm + thickness = 8.0mil + x1 = 0.357631mm + x2 = 0.611632mm + y1 = 1.373632mm + } + ha:simplearc.2 { + thickness = 8.0mil + adelta = 270.000000 + astart = 180.000000 + x = 14.08mil + y = 1.119632mm + r = 10.0mil + } + } + height = 1.477266mm + } + ha:f { + width = 0.484634mm + delta = 4.0mil + li:objects { + ha:line.0 { + y2 = 1.373632mm + thickness = 8.0mil + x1 = 5.0mil + x2 = 5.0mil + y1 = 25.0mil + } + ha:line.1 { + y2 = 0.865632mm + thickness = 8.0mil + x1 = 0.0 + x2 = 10.0mil + y1 = 0.865632mm + } + ha:simplearc.2 { + thickness = 8.0mil + adelta = 90.000000 + astart = -90.000000 + x = 15.0mil + y = 0.611632mm + r = 10.0mil + } + } + height = 1.373633mm + } + ha:g { + width = 0.713756mm + delta = 0.128279mm + li:objects { + ha:line.0 { + y2 = 1.754632mm + thickness = 8.0mil + x1 = 0.104909mm + x2 = 0.231909mm + y1 = 1.627632mm + } + ha:line.1 { + y2 = 1.754632mm + thickness = 8.0mil + x1 = 0.231909mm + x2 = 0.485909mm + y1 = 1.754632mm + } + ha:line.2 { + y2 = 1.627632mm + thickness = 8.0mil + x1 = 0.485909mm + x2 = 0.612909mm + y1 = 1.754632mm + } + ha:line.3 { + y2 = 1.627632mm + thickness = 8.0mil + x1 = 0.612909mm + x2 = 0.612909mm + y1 = 0.865632mm + } + ha:simplearc.4 { + thickness = 8.0mil + adelta = -360.000000 + astart = 20.000000 + x = 0.356877mm + y = 44.0mil + r = 0.253245mm + } + } + height = 1.754633mm + } + ha:h { + width = 0.703348mm + delta = 11.0mil + li:objects { + ha:line.0 { + y2 = 1.373632mm + thickness = 8.0mil + x1 = 0.095849mm + x2 = 0.095849mm + y1 = 14.08mil + } + ha:line.1 { + y2 = 1.373632mm + thickness = 8.0mil + x1 = 0.603849mm + x2 = 0.603849mm + y1 = 45.0mil + } + ha:line.2 { + y2 = 45.0mil + thickness = 8.0mil + x1 = 0.600341mm + x2 = 0.603849mm + y1 = 1.017392mm + } + ha:simplearc.3 { + thickness = 8.0mil + adelta = -132.000000 + astart = 334.000000 + x = 0.347817mm + y = 44.0mil + r = 0.27168mm + } + } + height = 1.373633mm + } + ha:i { + width = 0.001um + delta = 10.0mil + li:objects { + ha:line.0 { + y2 = 0.637032mm + thickness = 10.0mil + x1 = 0.0 + x2 = 0.0 + y1 = 0.611632mm + } + ha:line.1 { + y2 = 1.373632mm + thickness = 8.0mil + x1 = 0.0 + x2 = 0.0 + y1 = 0.992632mm + } + } + height = 1.373633mm + } + ha:j { + width = 0.252632mm + delta = 11.0mil + li:objects { + ha:line.0 { + y2 = 0.637032mm + thickness = 10.0mil + x1 = 0.148998mm + x2 = 0.148998mm + y1 = 0.611632mm + } + ha:line.1 { + y2 = 1.576832mm + thickness = 8.0mil + x1 = 0.148998mm + x2 = 0.148998mm + y1 = 0.992632mm + } + ha:line.2 { + y2 = 1.754632mm + thickness = 8.0mil + x1 = 0.103944mm + x2 = 0.021998mm + y1 = 1.673856mm + } + ha:simplearc.3 { + thickness = 8.0mil + adelta = 50.000000 + astart = 130.000000 + x = 0.021998mm + y = 1.576832mm + r = 5.0mil + } + } + height = 1.777753mm + } + ha:k { + width = 0.381001mm + delta = 10.0mil + li:objects { + ha:line.0 { + y2 = 1.373632mm + thickness = 8.0mil + x1 = 0.0 + x2 = 0.0 + y1 = 14.08mil + } + ha:line.1 { + y2 = 1.373632mm + thickness = 8.0mil + x1 = 0.0 + x2 = 15.0mil + y1 = 0.992632mm + } + ha:line.2 { + y2 = 0.738632mm + thickness = 8.0mil + x1 = 0.0 + x2 = 10.0mil + y1 = 0.992632mm + } + } + height = 1.373633mm + } + ha:l { + width = 0.127001mm + delta = 10.0mil + li:objects { + ha:line.0 { + y2 = 1.246632mm + thickness = 8.0mil + x1 = 0.0 + x2 = 0.0 + y1 = 14.08mil + } + ha:line.1 { + y2 = 1.373632mm + thickness = 8.0mil + x1 = 0.0 + x2 = 5.0mil + y1 = 1.246632mm + } + } + height = 1.373633mm + } + ha:m { + width = 1.12574mm + delta = 0.148337mm + li:objects { + ha:line.0 { + y2 = 1.373632mm + thickness = 8.0mil + x1 = 8.24mil + x2 = 8.24mil + y1 = 0.992632mm + } + ha:line.1 { + y2 = 1.373632mm + thickness = 8.0mil + x1 = 0.615696mm + x2 = 0.615696mm + y1 = 0.992632mm + } + ha:line.2 { + y2 = 1.373632mm + thickness = 8.0mil + x1 = 40.24mil + x2 = 40.24mil + y1 = 0.992632mm + } + ha:line.3 { + y2 = 0.967232mm + thickness = 8.0mil + x1 = 8.24mil + x2 = 8.16mil + y1 = 0.992632mm + } + ha:simplearc.4 { + thickness = 8.0mil + adelta = 90.000000 + astart = 180.000000 + x = 4.08mil + y = 0.967232mm + r = 4.08mil + } + ha:simplearc.5 { + thickness = 8.0mil + adelta = -180.000000 + astart = 0.000000 + x = 32.32mil + y = 0.992632mm + r = 0.201178mm + } + ha:simplearc.6 { + thickness = 8.0mil + adelta = -180.000000 + astart = 0.000000 + x = 16.32mil + y = 0.992632mm + r = 0.201178mm + } + } + height = 1.373633mm + } + ha:n { + width = 0.71934mm + delta = 5.0mil + li:objects { + ha:line.0 { + y2 = 1.373632mm + thickness = 8.0mil + x1 = 8.24mil + x2 = 8.24mil + y1 = 0.992632mm + } + ha:line.1 { + y2 = 1.373632mm + thickness = 8.0mil + x1 = 0.615696mm + x2 = 0.615696mm + y1 = 0.992632mm + } + ha:line.2 { + y2 = 0.967232mm + thickness = 8.0mil + x1 = 8.24mil + x2 = 8.16mil + y1 = 0.992632mm + } + ha:simplearc.3 { + thickness = 8.0mil + adelta = 90.000000 + astart = 180.000000 + x = 4.08mil + y = 0.967232mm + r = 4.08mil + } + ha:simplearc.4 { + thickness = 8.0mil + adelta = -180.000000 + astart = 0.000000 + x = 16.32mil + y = 0.992632mm + r = 0.201178mm + } + } + height = 1.373633mm + } + ha:o { + width = 0.720439mm + delta = 0.132343mm + li:objects { + ha:simplearc.0 { + thickness = 8.0mil + adelta = -360.000000 + astart = 20.000000 + x = 13.92mil + y = 44.0mil + r = 0.263238mm + } + } + height = 1.269747mm + } + ha:p { + width = 0.735847mm + delta = 7.0mil + li:objects { + ha:line.0 { + y2 = 1.754632mm + thickness = 8.0mil + x1 = 5.0mil + x2 = 5.0mil + y1 = 0.992632mm + } + ha:line.1 { + y2 = 0.992632mm + thickness = 8.0mil + x1 = 0.0 + x2 = 5.0mil + y1 = 0.865632mm + } + ha:simplearc.2 { + thickness = 8.0mil + adelta = -360.000000 + astart = 20.000000 + x = 14.92mil + y = 44.0mil + r = 0.253245mm + } + } + height = 1.754633mm + } + ha:q { + width = 0.713756mm + delta = 0.173737mm + li:objects { + ha:line.0 { + y2 = 1.754632mm + thickness = 8.0mil + x1 = 24.0mil + x2 = 0.612909mm + y1 = 34.0mil + } + ha:simplearc.1 { + thickness = 8.0mil + adelta = -360.000000 + astart = 20.000000 + x = 0.356877mm + y = 44.0mil + r = 0.253245mm + } + } + height = 1.754633mm + } + ha:r { + width = 0.534157mm + delta = 6.0mil + li:objects { + ha:line.0 { + y2 = 1.373632mm + thickness = 8.0mil + x1 = 5.0mil + x2 = 5.0mil + y1 = 0.992632mm + } + ha:line.1 { + y2 = 0.992632mm + thickness = 8.0mil + x1 = 0.0 + x2 = 5.0mil + y1 = 0.865632mm + } + ha:simplearc.2 { + thickness = 8.0mil + adelta = -135.000000 + astart = 0.000000 + x = 12.0mil + y = 41.0mil + r = 7.0mil + } + } + height = 1.373633mm + } + ha:s { + width = 0.842266mm + delta = 6.0mil + li:objects { + ha:line.0 { + y2 = 1.119632mm + thickness = 8.0mil + x1 = 9.08mil + x2 = 0.611632mm + y1 = 1.119632mm + } + ha:line.1 { + y2 = 0.865632mm + thickness = 8.0mil + x1 = 9.08mil + x2 = 0.611632mm + y1 = 0.865632mm + } + ha:line.2 { + y2 = 1.373632mm + thickness = 8.0mil + x1 = 9.08mil + x2 = 0.611632mm + y1 = 1.373632mm + } + ha:simplearc.3 { + thickness = 8.0mil + adelta = 180.000000 + astart = -90.000000 + x = 9.08mil + y = 0.992632mm + r = 5.0mil + } + ha:simplearc.4 { + thickness = 8.0mil + adelta = -52.403729 + astart = -90.000000 + x = 0.611632mm + y = 0.992632mm + r = 5.0mil + } + ha:simplearc.5 { + thickness = 8.0mil + adelta = 45.578726 + astart = 44.421274 + x = 9.08mil + y = 1.246632mm + r = 5.0mil + } + ha:simplearc.6 { + thickness = 8.0mil + adelta = -180.000000 + astart = -90.000000 + x = 0.611632mm + y = 1.246632mm + r = 5.0mil + } + } + height = 1.477266mm + } + ha:t { + width = 0.254001mm + delta = 10.0mil + li:objects { + ha:line.0 { + y2 = 1.246632mm + thickness = 8.0mil + x1 = 5.0mil + x2 = 5.0mil + y1 = 14.08mil + } + ha:line.1 { + y2 = 1.373632mm + thickness = 8.0mil + x1 = 5.0mil + x2 = 10.0mil + y1 = 1.246632mm + } + ha:line.2 { + y2 = 0.738632mm + thickness = 8.0mil + x1 = 0.0 + x2 = 10.0mil + y1 = 0.738632mm + } + } + height = 1.373633mm + } + ha:u { + width = 0.711202mm + delta = 0.180588mm + li:objects { + ha:line.0 { + y2 = 45.0mil + thickness = 8.0mil + x1 = 3.92mil + x2 = 3.92mil + y1 = 0.865632mm + } + ha:line.1 { + y2 = 45.0mil + thickness = 8.0mil + x1 = 23.92mil + x2 = 23.92mil + y1 = 0.865632mm + } + ha:simplearc.2 { + thickness = 8.0mil + adelta = 180.000000 + astart = 0.000000 + x = 14.0mil + y = 45.0mil + r = 9.92mil + } + } + height = 1.498602mm + } + ha:v { + width = 0.508001mm + delta = 11.0mil + li:objects { + ha:line.0 { + y2 = 1.373632mm + thickness = 8.0mil + x1 = 0.0 + x2 = 10.0mil + y1 = 0.865632mm + } + ha:line.1 { + y2 = 1.373632mm + thickness = 8.0mil + x1 = 20.0mil + x2 = 10.0mil + y1 = 0.865632mm + } + } + height = 1.373633mm + } + ha:w { + width = 1.02639mm + delta = 7.0mil + li:objects { + ha:line.0 { + y2 = 1.170432mm + thickness = 8.0mil + x1 = 0.10414mm + x2 = 4.08mil + y1 = 0.86106mm + } + ha:line.1 { + y2 = 0.86106mm + thickness = 8.0mil + x1 = 0.514153mm + x2 = 0.514153mm + y1 = 1.15316mm + } + ha:line.2 { + y2 = 34.0mil + thickness = 8.0mil + x1 = 0.923093mm + x2 = 0.923093mm + y1 = 45.5mil + } + ha:line.3 { + y2 = 1.170432mm + thickness = 8.0mil + x1 = 0.514153mm + x2 = 0.513194mm + y1 = 1.15316mm + } + ha:line.4 { + y2 = 1.170432mm + thickness = 8.0mil + x1 = 0.923093mm + x2 = 0.922756mm + y1 = 45.5mil + } + ha:simplearc.5 { + thickness = 8.0mil + adelta = 180.000000 + astart = 0.000000 + x = 0.717975mm + y = 1.170432mm + r = 0.204781mm + } + ha:simplearc.6 { + thickness = 8.0mil + adelta = 180.000000 + astart = 0.000000 + x = 0.308413mm + y = 1.170432mm + r = 0.204781mm + } + } + height = 1.478847mm + } + ha:x { + width = 0.508001mm + delta = 11.0mil + li:objects { + ha:line.0 { + y2 = 1.373632mm + thickness = 8.0mil + x1 = 0.0 + x2 = 20.0mil + y1 = 0.865632mm + } + ha:line.1 { + y2 = 0.865632mm + thickness = 8.0mil + x1 = 0.0 + x2 = 20.0mil + y1 = 1.373632mm + } + } + height = 1.373633mm + } + ha:y { + width = 0.711202mm + delta = 6.0mil + li:objects { + ha:line.0 { + y2 = 45.0mil + thickness = 8.0mil + x1 = 3.92mil + x2 = 3.92mil + y1 = 0.865632mm + } + ha:line.1 { + y2 = 60.0mil + thickness = 8.0mil + x1 = 23.92mil + x2 = 23.92mil + y1 = 0.865632mm + } + ha:simplearc.2 { + thickness = 8.0mil + adelta = 156.225135 + astart = 23.774865 + x = 14.0mil + y = 60.0mil + r = 9.92mil + } + ha:simplearc.3 { + thickness = 8.0mil + adelta = 180.000000 + astart = 0.000000 + x = 14.0mil + y = 45.0mil + r = 9.92mil + } + } + height = 1.879602mm + } + ha:z { + width = 0.508001mm + delta = 11.0mil + li:objects { + ha:line.0 { + y2 = 0.865632mm + thickness = 8.0mil + x1 = 0.0 + x2 = 20.0mil + y1 = 0.865632mm + } + ha:line.1 { + y2 = 0.865632mm + thickness = 8.0mil + x1 = 0.0 + x2 = 20.0mil + y1 = 1.373632mm + } + ha:line.2 { + y2 = 1.373632mm + thickness = 8.0mil + x1 = 0.0 + x2 = 20.0mil + y1 = 1.373632mm + } + } + height = 1.373633mm + } + ha:~ { + width = 0.829902mm + delta = 8.08mil + li:objects { + ha:simplearc.0 { + thickness = 8.0mil + adelta = -152.513380 + astart = 0.000000 + x = 10.08mil + y = 0.992632mm + r = 0.169501mm + } + ha:simplearc.1 { + thickness = 8.0mil + adelta = -152.513380 + astart = 180.000000 + x = 21.92mil + y = 32.92mil + r = 0.169501mm + } + } + height = 0.925323mm + } + ha:&7b { + width = 0.254001mm + delta = 14.0mil + li:objects { + ha:line.0 { + y2 = 14.08mil + thickness = 8.0mil + x1 = 5.0mil + x2 = 10.0mil + y1 = 0.484632mm + } + ha:line.1 { + y2 = 0.738632mm + thickness = 8.0mil + x1 = 5.0mil + x2 = 5.0mil + y1 = 0.484632mm + } + ha:line.2 { + y2 = 0.738632mm + thickness = 8.0mil + x1 = 0.0 + x2 = 5.0mil + y1 = 0.865632mm + } + ha:line.3 { + y2 = 0.992632mm + thickness = 8.0mil + x1 = 0.0 + x2 = 5.0mil + y1 = 0.865632mm + } + ha:line.4 { + y2 = 1.246632mm + thickness = 8.0mil + x1 = 5.0mil + x2 = 5.0mil + y1 = 0.992632mm + } + ha:line.5 { + y2 = 1.373632mm + thickness = 8.0mil + x1 = 5.0mil + x2 = 10.0mil + y1 = 1.246632mm + } + } + height = 1.373633mm + } + ha:&7d { + width = 0.254001mm + delta = 13.0mil + li:objects { + ha:line.0 { + y2 = 0.484632mm + thickness = 8.0mil + x1 = 0.0 + x2 = 5.0mil + y1 = 14.08mil + } + ha:line.1 { + y2 = 0.738632mm + thickness = 8.0mil + x1 = 5.0mil + x2 = 5.0mil + y1 = 0.484632mm + } + ha:line.2 { + y2 = 0.865632mm + thickness = 8.0mil + x1 = 5.0mil + x2 = 10.0mil + y1 = 0.738632mm + } + ha:line.3 { + y2 = 0.865632mm + thickness = 8.0mil + x1 = 5.0mil + x2 = 10.0mil + y1 = 0.992632mm + } + ha:line.4 { + y2 = 1.246632mm + thickness = 8.0mil + x1 = 5.0mil + x2 = 5.0mil + y1 = 0.992632mm + } + ha:line.5 { + y2 = 1.246632mm + thickness = 8.0mil + x1 = 0.0 + x2 = 5.0mil + y1 = 1.373632mm + } + } + height = 1.373633mm + } + ha:| { + width = 0.001um + delta = 15.0mil + li:objects { + ha:line.0 { + y2 = 1.373632mm + thickness = 8.0mil + x1 = 0.0 + x2 = 0.0 + y1 = 14.08mil + } + } + height = 1.373633mm + } + ha:&23 { + width = 0.508001mm + delta = 12.0mil + li:objects { + ha:line.0 { + y2 = 0.992632mm + thickness = 8.0mil + x1 = 0.0 + x2 = 20.0mil + y1 = 0.992632mm + } + ha:line.1 { + y2 = 0.738632mm + thickness = 8.0mil + x1 = 0.0 + x2 = 20.0mil + y1 = 0.738632mm + } + ha:line.2 { + y2 = 1.119632mm + thickness = 8.0mil + x1 = 15.0mil + x2 = 15.0mil + y1 = 0.611632mm + } + ha:line.3 { + y2 = 1.119632mm + thickness = 8.0mil + x1 = 5.0mil + x2 = 5.0mil + y1 = 0.611632mm + } + } + height = 1.119633mm + } + ha:&26 { + width = 0.765439mm + delta = 11.0mil + li:objects { + ha:line.0 { + y2 = 1.373632mm + thickness = 8.0mil + x1 = 8.0mil + x2 = 0.765438mm + y1 = 32.0mil + } + ha:line.1 { + y2 = 28.0mil + thickness = 8.0mil + x1 = 8.0mil + x2 = 6.0mil + y1 = 32.0mil + } + ha:line.2 { + y2 = 0.703086mm + thickness = 8.0mil + x1 = 0.159004mm + x2 = 0.477924mm + y1 = 0.993314mm + } + ha:line.3 { + y2 = 44.0mil + thickness = 8.0mil + x1 = 0.520801mm + x2 = 0.689238mm + y1 = 1.276688mm + } + ha:line.4 { + y2 = 28.0mil + thickness = 8.0mil + x1 = 0.134492mm + x2 = 6.0mil + y1 = 0.560832mm + } + ha:simplearc.5 { + thickness = 8.0mil + adelta = -185.000000 + astart = 144.000000 + x = 0.333638mm + y = 45.0mil + r = 0.230006mm + } + ha:simplearc.6 { + thickness = 8.0mil + adelta = -225.000000 + astart = 0.000000 + x = 0.33567mm + y = 0.560832mm + r = 0.201178mm + } + } + height = 1.47664mm + } + ha:! { + width = 0.001um + delta = 13.0mil + li:objects { + ha:line.0 { + y2 = 1.373632mm + thickness = 8.0mil + x1 = 0.0 + x2 = 0.0 + y1 = 1.246632mm + } + ha:line.1 { + y2 = 0.992632mm + thickness = 8.0mil + x1 = 0.0 + x2 = 0.0 + y1 = 14.08mil + } + } + height = 1.373633mm + } + ha:" { + width = 0.254001mm + delta = 13.0mil + li:objects { + ha:line.0 { + y2 = 0.611632mm + thickness = 8.0mil + x1 = 0.0 + x2 = 0.0 + y1 = 14.08mil + } + ha:line.1 { + y2 = 0.611632mm + thickness = 8.0mil + x1 = 10.0mil + x2 = 10.0mil + y1 = 14.08mil + } + } + height = 0.611633mm + } + ha:$ { + width = 0.735821mm + delta = 8.0mil + li:objects { + ha:line.0 { + y2 = 65.0mil + thickness = 8.0mil + x1 = 0.381596mm + x2 = 0.381596mm + y1 = 10.0mil + } + ha:line.1 { + y2 = 0.954693mm + thickness = 8.0mil + x1 = 0.308266mm + x2 = 0.436371mm + y1 = 0.931603mm + } + ha:simplearc.2 { + thickness = 8.0mil + adelta = 227.000000 + astart = 25.000000 + x = 0.353178mm + y = 47.92mil + r = 0.275343mm + } + ha:simplearc.3 { + thickness = 8.0mil + adelta = 229.000000 + astart = 205.000000 + x = 0.382642mm + y = 0.666496mm + r = 0.275343mm + } + } + height = 1.651001mm + } + ha:% { + width = 1.274066mm + delta = 7.0mil + li:objects { + ha:line.0 { + y2 = 14.08mil + thickness = 8.0mil + x1 = 5.08mil + x2 = 1.145032mm + y1 = 1.373632mm + } + ha:simplearc.1 { + thickness = 8.0mil + adelta = -353.000000 + astart = 0.000000 + x = 0.967232mm + y = 1.195832mm + r = 8.0mil + } + ha:simplearc.2 { + thickness = 8.0mil + adelta = -353.000000 + astart = 0.000000 + x = 12.08mil + y = 0.535432mm + r = 8.0mil + } + } + height = 1.502666mm + } + ha:' { + width = 0.254001mm + delta = 11.0mil + li:objects { + ha:line.0 { + y2 = 14.08mil + thickness = 8.0mil + x1 = 0.0 + x2 = 10.0mil + y1 = 0.611632mm + } + } + height = 0.611633mm + } + ha:( { + width = 0.299452mm + delta = 0.068708mm + li:objects { + ha:line.0 { + y2 = 46.0mil + thickness = 8.0mil + x1 = 0.104704mm + x2 = 0.104704mm + y1 = 22.0mil + } + ha:line.1 { + y2 = 54.0mil + thickness = 8.0mil + x1 = 0.194119mm + x2 = 8.0mil + y1 = 1.367332mm + } + ha:line.2 { + y2 = 14.0mil + thickness = 8.0mil + x1 = 0.195191mm + x2 = 8.0mil + y1 = 0.363931mm + } + ha:simplearc.3 { + thickness = 8.0mil + adelta = 50.000000 + astart = -50.000000 + x = 0.359776mm + y = 22.0mil + r = 0.255072mm + } + ha:simplearc.4 { + thickness = 8.0mil + adelta = -50.000000 + astart = 50.000000 + x = 0.358704mm + y = 1.172464mm + r = 0.255072mm + } + } + height = 1.471494mm + } + ha:) { + width = 0.299453mm + delta = 0.123115mm + li:objects { + ha:line.0 { + y2 = 46.0mil + thickness = 8.0mil + x1 = 0.194747mm + x2 = 0.194747mm + y1 = 22.0mil + } + ha:line.1 { + y2 = 54.0mil + thickness = 8.0mil + x1 = 0.105332mm + x2 = 0.096251mm + y1 = 1.367332mm + } + ha:line.2 { + y2 = 14.0mil + thickness = 8.0mil + x1 = 0.10426mm + x2 = 0.096251mm + y1 = 0.363931mm + } + ha:simplearc.3 { + thickness = 8.0mil + adelta = -50.000000 + astart = 230.000000 + x = -60.325um + y = 22.0mil + r = 0.255072mm + } + ha:simplearc.4 { + thickness = 8.0mil + adelta = 50.000000 + astart = 130.000000 + x = -59.253um + y = 1.172464mm + r = 0.255072mm + } + } + height = 1.471494mm + } + ha:* { + width = 0.508001mm + delta = 10.0mil + li:objects { + ha:line.0 { + y2 = 1.119632mm + thickness = 8.0mil + x1 = 0.0 + x2 = 20.0mil + y1 = 0.611632mm + } + ha:line.1 { + y2 = 0.611632mm + thickness = 8.0mil + x1 = 0.0 + x2 = 20.0mil + y1 = 1.119632mm + } + ha:line.2 { + y2 = 0.865632mm + thickness = 8.0mil + x1 = 0.0 + x2 = 20.0mil + y1 = 0.865632mm + } + ha:line.3 { + y2 = 1.119632mm + thickness = 8.0mil + x1 = 10.0mil + x2 = 10.0mil + y1 = 0.611632mm + } + } + height = 1.119633mm + } + ha:+ { + width = 0.508001mm + delta = 12.0mil + li:objects { + ha:line.0 { + y2 = 0.865632mm + thickness = 8.0mil + x1 = 0.0 + x2 = 20.0mil + y1 = 0.865632mm + } + ha:line.1 { + y2 = 1.119632mm + thickness = 8.0mil + x1 = 10.0mil + x2 = 10.0mil + y1 = 0.611632mm + } + } + height = 1.119633mm + } + ha:, { + width = 0.254001mm + delta = 13.0mil + li:objects { + ha:line.0 { + y2 = 1.373632mm + thickness = 8.0mil + x1 = 0.0 + x2 = 10.0mil + y1 = 1.627632mm + } + } + height = 1.627633mm + } + ha:- { + width = 0.508001mm + delta = 14.0mil + li:objects { + ha:line.0 { + y2 = 0.865632mm + thickness = 8.0mil + x1 = 0.0 + x2 = 20.0mil + y1 = 0.865632mm + } + } + height = 0.865633mm + } + ha:. { + width = 0.127001mm + delta = 12.0mil + li:objects { + ha:line.0 { + y2 = 54.0mil + thickness = 8.0mil + x1 = 0.0 + x2 = 5.0mil + y1 = 54.0mil + } + } + height = 1.371601mm + } + ha:0 { + width = 0.715266mm + delta = 6.0mil + li:objects { + ha:line.0 { + y2 = 1.119632mm + thickness = 8.0mil + x1 = 4.08mil + x2 = 4.08mil + y1 = 0.611632mm + } + ha:line.1 { + y2 = 1.119632mm + thickness = 8.0mil + x1 = 0.611632mm + x2 = 0.611632mm + y1 = 0.611632mm + } + ha:line.2 { + y2 = 0.611632mm + thickness = 8.0mil + x1 = 4.08mil + x2 = 0.611632mm + y1 = 1.119632mm + } + ha:simplearc.3 { + thickness = 8.0mil + adelta = -180.000000 + astart = 180.000000 + x = 14.08mil + y = 1.119632mm + r = 10.0mil + } + ha:simplearc.4 { + thickness = 8.0mil + adelta = -180.000000 + astart = 0.000000 + x = 14.08mil + y = 0.611632mm + r = 10.0mil + } + } + height = 1.477266mm + } + ha:1 { + width = 0.381001mm + delta = 9.0mil + li:objects { + ha:line.0 { + y2 = 14.08mil + thickness = 8.0mil + x1 = 0.0 + x2 = 8.0mil + y1 = 0.560832mm + } + ha:line.1 { + y2 = 1.373632mm + thickness = 8.0mil + x1 = 8.0mil + x2 = 8.0mil + y1 = 14.08mil + } + ha:line.2 { + y2 = 1.373632mm + thickness = 8.0mil + x1 = 0.0 + x2 = 15.0mil + y1 = 1.373632mm + } + } + height = 1.373633mm + } + ha:2 { + width = 0.816866mm + delta = 6.0mil + li:objects { + ha:line.0 { + y2 = 0.80676mm + thickness = 8.0mil + x1 = 3.08mil + x2 = 0.642585mm + y1 = 1.373632mm + } + ha:line.1 { + y2 = 1.373632mm + thickness = 8.0mil + x1 = 3.08mil + x2 = 0.713232mm + y1 = 1.373632mm + } + ha:simplearc.2 { + thickness = 8.0mil + adelta = -220.000000 + astart = 0.000000 + x = 0.408432mm + y = 0.611632mm + r = 12.0mil + } + } + height = 1.373633mm + } + ha:3 { + width = 0.744275mm + delta = 6.0mil + li:objects { + ha:line.0 { + y2 = 0.814832mm + thickness = 8.0mil + x1 = 12.4419685mil + x2 = 0.466389mm + y1 = 0.814832mm + } + ha:simplearc.1 { + thickness = 8.0mil + adelta = 221.000000 + astart = 27.000000 + x = 0.356661mm + y = 42.38mil + r = 0.28398mm + } + ha:simplearc.2 { + thickness = 8.0mil + adelta = -218.000000 + astart = 337.000000 + x = 0.341421mm + y = 0.593852mm + r = 10.0mil + } + } + height = 1.464066mm + } + ha:4 { + width = 0.635001mm + delta = 9.0mil + li:objects { + ha:line.0 { + y2 = 14.08mil + thickness = 8.0mil + x1 = 0.0 + x2 = 20.0mil + y1 = 0.992632mm + } + ha:line.1 { + y2 = 0.992632mm + thickness = 8.0mil + x1 = 0.0 + x2 = 25.0mil + y1 = 0.992632mm + } + ha:line.2 { + y2 = 1.373632mm + thickness = 8.0mil + x1 = 20.0mil + x2 = 20.0mil + y1 = 14.08mil + } + } + height = 1.373633mm + } + ha:5 { + width = 0.762551mm + delta = 5.0mil + li:objects { + ha:line.0 { + y2 = 14.08mil + thickness = 8.0mil + x1 = 0.105039mm + x2 = 0.613039mm + y1 = 14.08mil + } + ha:line.1 { + y2 = 0.865632mm + thickness = 8.0mil + x1 = 0.105039mm + x2 = 0.105039mm + y1 = 14.08mil + } + ha:simplearc.2 { + thickness = 8.0mil + adelta = -261.000000 + astart = 315.000000 + x = 0.333639mm + y = 1.068832mm + r = 0.325278mm + } + } + height = 1.497744mm + } + ha:6 { + width = 0.725326mm + delta = 4.0mil + li:objects { + ha:line.0 { + y2 = 0.611632mm + thickness = 8.0mil + x1 = 0.10414mm + x2 = 0.10414mm + y1 = 1.094232mm + } + ha:simplearc.1 { + thickness = 8.0mil + adelta = 154.000000 + astart = 207.000000 + x = 0.362662mm + y = 0.611632mm + r = 0.25903mm + } + ha:simplearc.2 { + thickness = 8.0mil + adelta = 360.000000 + astart = 99.000000 + x = 0.362662mm + y = 1.094232mm + r = 0.25903mm + } + } + height = 1.456896mm + } + ha:7 { + width = 0.635001mm + delta = 10.0mil + li:objects { + ha:line.0 { + y2 = 14.08mil + thickness = 8.0mil + x1 = 5.0mil + x2 = 25.0mil + y1 = 1.373632mm + } + ha:line.1 { + y2 = 14.08mil + thickness = 8.0mil + x1 = 0.0 + x2 = 25.0mil + y1 = 14.08mil + } + } + height = 1.373633mm + } + ha:8 { + width = 0.718263mm + delta = 6.0mil + li:objects { + ha:simplearc.0 { + thickness = 8.0mil + adelta = 360.000000 + astart = 99.000000 + x = 14.0mil + y = 0.611632mm + r = 0.25903mm + } + ha:simplearc.1 { + thickness = 8.0mil + adelta = 360.000000 + astart = 99.000000 + x = 14.0mil + y = 1.119632mm + r = 0.25903mm + } + } + height = 1.270001mm + } + ha:9 { + width = 0.725326mm + delta = 6.0mil + li:objects { + ha:line.0 { + y2 = 1.094232mm + thickness = 8.0mil + x1 = 24.5mil + x2 = 24.5mil + y1 = 0.611632mm + } + ha:simplearc.1 { + thickness = 8.0mil + adelta = 153.000000 + astart = 27.000000 + x = 0.362662mm + y = 1.094232mm + r = 0.25903mm + } + ha:simplearc.2 { + thickness = 8.0mil + adelta = 360.000000 + astart = 279.000000 + x = 0.362662mm + y = 0.611632mm + r = 0.25903mm + } + } + height = 1.456896mm + } + ha:< { + width = 0.254001mm + delta = 13.0mil + li:objects { + ha:line.0 { + y2 = 0.611632mm + thickness = 8.0mil + x1 = 0.0 + x2 = 10.0mil + y1 = 0.865632mm + } + ha:line.1 { + y2 = 1.119632mm + thickness = 8.0mil + x1 = 0.0 + x2 = 10.0mil + y1 = 0.865632mm + } + } + height = 1.119633mm + } + ha:> { + width = 0.254001mm + delta = 12.0mil + li:objects { + ha:line.0 { + y2 = 0.840232mm + thickness = 8.0mil + x1 = 0.0 + x2 = 10.0mil + y1 = 0.586232mm + } + ha:line.1 { + y2 = 0.840232mm + thickness = 8.0mil + x1 = 0.0 + x2 = 10.0mil + y1 = 1.094232mm + } + } + height = 1.094233mm + } + ha:? { + width = 0.664986mm + delta = 5.0mil + li:objects { + ha:line.0 { + y2 = 0.711422mm + thickness = 8.0mil + x1 = 0.388699mm + x2 = 0.504827mm + y1 = 0.825376mm + } + ha:line.1 { + y2 = 1.373632mm + thickness = 8.0mil + x1 = 0.32543mm + x2 = 0.32543mm + y1 = 1.322832mm + } + ha:simplearc.2 { + thickness = 8.0mil + adelta = 46.000000 + astart = 320.000000 + x = 0.586492mm + y = 0.992632mm + r = 0.25903mm + } + ha:simplearc.3 { + thickness = 8.0mil + adelta = 227.000000 + astart = 139.000000 + x = 0.332492mm + y = 0.560832mm + r = 0.22886mm + } + } + height = 1.373633mm + } + ha:@ { + width = 1.477266mm + delta = 6.0mil + li:objects { + ha:line.0 { + y2 = 0.484632mm + thickness = 8.0mil + x1 = 0.992632mm + x2 = 0.992632mm + y1 = 0.865632mm + } + ha:line.1 { + y2 = 0.992632mm + thickness = 8.0mil + x1 = 1.119631mm + x2 = 1.310047mm + y1 = 0.992632mm + } + ha:simplearc.2 { + thickness = 8.0mil + adelta = 90.000000 + astart = 0.000000 + x = 1.119632mm + y = 0.865632mm + r = 5.0mil + } + ha:simplearc.3 { + thickness = 8.0mil + adelta = -307.000000 + astart = 153.000000 + x = 0.738632mm + y = 0.738632mm + r = 10.0mil + } + ha:simplearc.4 { + thickness = 8.0mil + adelta = -314.000000 + astart = 112.000000 + x = 0.738632mm + y = 0.738632mm + r = 25.0mil + } + } + height = 1.477266mm + } + ha:A { + width = 0.635001mm + delta = 13.0mil + li:objects { + ha:line.0 { + y2 = 1.373632mm + thickness = 8.0mil + x1 = 0.0 + x2 = 0.0 + y1 = 0.611632mm + } + ha:line.1 { + y2 = 1.373632mm + thickness = 8.0mil + x1 = 25.0mil + x2 = 25.0mil + y1 = 0.611632mm + } + ha:line.2 { + y2 = 0.865632mm + thickness = 8.0mil + x1 = 0.0 + x2 = 25.0mil + y1 = 0.865632mm + } + ha:line.3 { + y2 = 14.08mil + thickness = 8.0mil + x1 = 7.0mil + x2 = 18.0mil + y1 = 14.08mil + } + ha:line.4 { + y2 = 0.611632mm + thickness = 8.0mil + x1 = 18.0mil + x2 = 25.0mil + y1 = 14.08mil + } + ha:line.5 { + y2 = 14.08mil + thickness = 8.0mil + x1 = 0.0 + x2 = 7.0mil + y1 = 0.611632mm + } + } + height = 1.373633mm + } + ha:B { + width = 0.865633mm + delta = 6.0mil + li:objects { + ha:line.0 { + y2 = 1.373632mm + thickness = 8.0mil + x1 = 5.0mil + x2 = 5.0mil + y1 = 14.08mil + } + ha:line.1 { + y2 = 14.08mil + thickness = 8.0mil + x1 = 0.0 + x2 = 20.0mil + y1 = 14.08mil + } + ha:line.2 { + y2 = 1.373632mm + thickness = 8.0mil + x1 = 0.482598mm + x2 = 0.0 + y1 = 1.373632mm + } + ha:line.3 { + y2 = 0.814832mm + thickness = 8.0mil + x1 = 0.482599mm + x2 = 5.0mil + y1 = 0.814832mm + } + ha:simplearc.4 { + thickness = 8.0mil + adelta = 180.000000 + astart = 90.000000 + x = 0.482599mm + y = 1.094232mm + r = 11.0mil + } + ha:simplearc.5 { + thickness = 8.0mil + adelta = 180.000000 + astart = 90.000000 + x = 20.0mil + y = 0.586232mm + r = 9.0mil + } + } + height = 1.477266mm + } + ha:C { + width = 0.611633mm + delta = 11.0mil + li:objects { + ha:line.0 { + y2 = 1.373632mm + thickness = 8.0mil + x1 = 0.484632mm + x2 = 0.611632mm + y1 = 1.373632mm + } + ha:line.1 { + y2 = 14.08mil + thickness = 8.0mil + x1 = 0.484632mm + x2 = 0.611632mm + y1 = 14.08mil + } + ha:line.2 { + y2 = 0.992632mm + thickness = 8.0mil + x1 = 4.08mil + x2 = 4.08mil + y1 = 0.738632mm + } + ha:simplearc.3 { + thickness = 8.0mil + adelta = 90.000000 + astart = -90.000000 + x = 0.484632mm + y = 0.738632mm + r = 15.0mil + } + ha:simplearc.4 { + thickness = 8.0mil + adelta = -90.000000 + astart = 90.000000 + x = 0.484632mm + y = 0.992632mm + r = 15.0mil + } + } + height = 1.477266mm + } + ha:D { + width = 0.738634mm + delta = 9.0mil + li:objects { + ha:line.0 { + y2 = 1.373632mm + thickness = 8.0mil + x1 = 5.0mil + x2 = 5.0mil + y1 = 14.08mil + } + ha:line.1 { + y2 = 14.08mil + thickness = 8.0mil + x1 = 0.0 + x2 = 10.0mil + y1 = 14.08mil + } + ha:line.2 { + y2 = 1.373632mm + thickness = 8.0mil + x1 = 0.0 + x2 = 10.0mil + y1 = 1.373632mm + } + ha:line.3 { + y2 = 0.992632mm + thickness = 8.0mil + x1 = 25.0mil + x2 = 25.0mil + y1 = 0.738632mm + } + ha:simplearc.4 { + thickness = 8.0mil + adelta = 90.000000 + astart = 90.000000 + x = 10.0mil + y = 0.992632mm + r = 15.0mil + } + ha:simplearc.5 { + thickness = 8.0mil + adelta = -90.000000 + astart = 270.000000 + x = 10.0mil + y = 0.738632mm + r = 15.0mil + } + } + height = 1.477266mm + } + ha:E { + width = 0.508001mm + delta = 13.0mil + li:objects { + ha:line.0 { + y2 = 0.814832mm + thickness = 8.0mil + x1 = 0.0 + x2 = 15.0mil + y1 = 0.814832mm + } + ha:line.1 { + y2 = 1.373632mm + thickness = 8.0mil + x1 = 0.0 + x2 = 20.0mil + y1 = 1.373632mm + } + ha:line.2 { + y2 = 1.373632mm + thickness = 8.0mil + x1 = 0.0 + x2 = 0.0 + y1 = 14.08mil + } + ha:line.3 { + y2 = 14.08mil + thickness = 8.0mil + x1 = 0.0 + x2 = 20.0mil + y1 = 14.08mil + } + } + height = 1.373633mm + } + ha:F { + width = 0.508001mm + delta = 8.0mil + li:objects { + ha:line.0 { + y2 = 1.373632mm + thickness = 8.0mil + x1 = 0.0 + x2 = 0.0 + y1 = 14.08mil + } + ha:line.1 { + y2 = 14.08mil + thickness = 8.0mil + x1 = 0.0 + x2 = 20.0mil + y1 = 14.08mil + } + ha:line.2 { + y2 = 0.814832mm + thickness = 8.0mil + x1 = 0.0 + x2 = 15.0mil + y1 = 0.814832mm + } + } + height = 1.373633mm + } + ha:G { + width = 0.816866mm + delta = 8.0mil + li:objects { + ha:line.0 { + y2 = 1.043432mm + thickness = 8.0mil + x1 = 4.08mil + x2 = 4.08mil + y1 = 0.637032mm + } + ha:line.1 { + y2 = 0.881916mm + thickness = 8.0mil + x1 = 0.648647mm + x2 = 0.399316mm + y1 = 0.881916mm + } + ha:simplearc.2 { + thickness = 8.0mil + adelta = -149.000000 + astart = 0.000000 + x = 16.0mil + y = 0.637032mm + r = 11.92mil + } + ha:simplearc.3 { + thickness = 8.0mil + adelta = -218.000000 + astart = 218.000000 + x = 16.16mil + y = 1.068832mm + r = 11.92mil + } + } + height = 1.475234mm + } + ha:H { + width = 0.635001mm + delta = 12.0mil + li:objects { + ha:line.0 { + y2 = 1.373632mm + thickness = 8.0mil + x1 = 0.0 + x2 = 0.0 + y1 = 14.08mil + } + ha:line.1 { + y2 = 1.373632mm + thickness = 8.0mil + x1 = 25.0mil + x2 = 25.0mil + y1 = 14.08mil + } + ha:line.2 { + y2 = 0.865632mm + thickness = 8.0mil + x1 = 0.0 + x2 = 25.0mil + y1 = 0.865632mm + } + } + height = 1.373633mm + } + ha:I { + width = 0.254001mm + delta = 9.0mil + li:objects { + ha:line.0 { + y2 = 14.08mil + thickness = 8.0mil + x1 = 0.0 + x2 = 10.0mil + y1 = 14.08mil + } + ha:line.1 { + y2 = 1.373632mm + thickness = 8.0mil + x1 = 5.0mil + x2 = 5.0mil + y1 = 14.08mil + } + ha:line.2 { + y2 = 1.373632mm + thickness = 8.0mil + x1 = 0.0 + x2 = 10.0mil + y1 = 1.373632mm + } + } + height = 1.373633mm + } + ha:J { + width = 0.613666mm + delta = 9.0mil + li:objects { + ha:line.0 { + y2 = 14.08mil + thickness = 8.0mil + x1 = 12.08mil + x2 = 0.510032mm + y1 = 14.08mil + } + ha:line.1 { + y2 = 1.119632mm + thickness = 8.0mil + x1 = 0.510032mm + x2 = 0.510032mm + y1 = 14.08mil + } + ha:simplearc.2 { + thickness = 8.0mil + adelta = -180.000000 + astart = 180.000000 + x = 12.08mil + y = 1.170432mm + r = 8.0mil + } + } + height = 1.477266mm + } + ha:K { + width = 0.508001mm + delta = 11.0mil + li:objects { + ha:line.0 { + y2 = 1.373632mm + thickness = 8.0mil + x1 = 0.0 + x2 = 0.0 + y1 = 14.08mil + } + ha:line.1 { + y2 = 14.08mil + thickness = 8.0mil + x1 = 0.0 + x2 = 20.0mil + y1 = 0.865632mm + } + ha:line.2 { + y2 = 1.373632mm + thickness = 8.0mil + x1 = 0.0 + x2 = 20.0mil + y1 = 0.865632mm + } + } + height = 1.373633mm + } + ha:L { + width = 0.508001mm + delta = 12.0mil + li:objects { + ha:line.0 { + y2 = 1.373632mm + thickness = 8.0mil + x1 = 0.0 + x2 = 0.0 + y1 = 14.08mil + } + ha:line.1 { + y2 = 1.373632mm + thickness = 8.0mil + x1 = 0.0 + x2 = 20.0mil + y1 = 1.373632mm + } + } + height = 1.373633mm + } + ha:M { + width = 0.762001mm + delta = 12.0mil + li:objects { + ha:line.0 { + y2 = 1.399032mm + thickness = 8.0mil + x1 = 0.0 + x2 = 0.0 + y1 = 15.08mil + } + ha:line.1 { + y2 = 0.891032mm + thickness = 8.0mil + x1 = 0.0 + x2 = 15.0mil + y1 = 15.08mil + } + ha:line.2 { + y2 = 15.08mil + thickness = 8.0mil + x1 = 15.0mil + x2 = 30.0mil + y1 = 0.891032mm + } + ha:line.3 { + y2 = 1.399032mm + thickness = 8.0mil + x1 = 30.0mil + x2 = 30.0mil + y1 = 15.08mil + } + } + height = 1.399033mm + } + ha:&2f { + width = 0.762001mm + delta = 15.0mil + li:objects { + ha:line.0 { + y2 = 0.484632mm + thickness = 8.0mil + x1 = 0.0 + x2 = 30.0mil + y1 = 1.246632mm + } + } + height = 1.246633mm + } + ha:&3a { + width = 0.127001mm + delta = 14.0mil + li:objects { + ha:line.0 { + y2 = 0.738632mm + thickness = 8.0mil + x1 = 0.0 + x2 = 5.0mil + y1 = 0.738632mm + } + ha:line.1 { + y2 = 0.992632mm + thickness = 8.0mil + x1 = 0.0 + x2 = 5.0mil + y1 = 0.992632mm + } + } + height = 0.992633mm + } + ha:&3b { + width = 0.254001mm + delta = 14.0mil + li:objects { + ha:line.0 { + y2 = 0.865632mm + thickness = 8.0mil + x1 = 10.0mil + x2 = 10.0mil + y1 = 0.738632mm + } + ha:line.1 { + y2 = 1.119632mm + thickness = 8.0mil + x1 = 0.0 + x2 = 10.0mil + y1 = 1.373632mm + } + } + height = 1.373633mm + } + ha:&3d { + width = 0.508001mm + delta = 12.0mil + li:objects { + ha:line.0 { + y2 = 0.738632mm + thickness = 8.0mil + x1 = 0.0 + x2 = 20.0mil + y1 = 0.738632mm + } + ha:line.1 { + y2 = 0.992632mm + thickness = 8.0mil + x1 = 0.0 + x2 = 20.0mil + y1 = 0.992632mm + } + } + height = 0.992633mm + } + ha:O { + width = 0.715266mm + delta = 0.230633mm + li:objects { + ha:line.0 { + y2 = 1.119632mm + thickness = 8.0mil + x1 = 4.08mil + x2 = 4.08mil + y1 = 0.611632mm + } + ha:line.1 { + y2 = 1.119632mm + thickness = 8.0mil + x1 = 0.611632mm + x2 = 0.611632mm + y1 = 0.611632mm + } + ha:simplearc.2 { + thickness = 8.0mil + adelta = -180.000000 + astart = 180.000000 + x = 14.08mil + y = 1.119632mm + r = 10.0mil + } + ha:simplearc.3 { + thickness = 8.0mil + adelta = -180.000000 + astart = 0.000000 + x = 14.08mil + y = 0.611632mm + r = 10.0mil + } + } + height = 1.477266mm + } + ha:P { + width = 0.738634mm + delta = 6.0mil + li:objects { + ha:line.0 { + y2 = 1.373632mm + thickness = 8.0mil + x1 = 5.0mil + x2 = 5.0mil + y1 = 14.08mil + } + ha:line.1 { + y2 = 14.08mil + thickness = 8.0mil + x1 = 0.0 + x2 = 15.0mil + y1 = 14.08mil + } + ha:line.2 { + y2 = 0.865632mm + thickness = 8.0mil + x1 = 5.0mil + x2 = 15.0mil + y1 = 0.865632mm + } + ha:simplearc.3 { + thickness = 8.0mil + adelta = -180.000000 + astart = -90.000000 + x = 15.0mil + y = 0.611632mm + r = 10.0mil + } + } + height = 1.373633mm + } + ha:N { + width = 0.635001mm + delta = 10.0mil + li:objects { + ha:line.0 { + y2 = 1.373632mm + thickness = 8.0mil + x1 = 0.0 + x2 = 0.0 + y1 = 14.08mil + } + ha:line.1 { + y2 = 1.373632mm + thickness = 8.0mil + x1 = 0.0 + x2 = 25.0mil + y1 = 14.08mil + } + ha:line.2 { + y2 = 1.373632mm + thickness = 8.0mil + x1 = 25.0mil + x2 = 25.0mil + y1 = 14.08mil + } + } + height = 1.373633mm + } + ha:R { + width = 0.738634mm + delta = 5.0mil + li:objects { + ha:line.0 { + y2 = 14.08mil + thickness = 8.0mil + x1 = 0.0 + x2 = 15.0mil + y1 = 14.08mil + } + ha:line.1 { + y2 = 0.865632mm + thickness = 8.0mil + x1 = 5.0mil + x2 = 13.0mil + y1 = 0.865632mm + } + ha:line.2 { + y2 = 1.373632mm + thickness = 8.0mil + x1 = 5.0mil + x2 = 5.0mil + y1 = 14.08mil + } + ha:line.3 { + y2 = 1.373632mm + thickness = 8.0mil + x1 = 13.0mil + x2 = 25.0mil + y1 = 0.865632mm + } + ha:simplearc.4 { + thickness = 8.0mil + adelta = -180.000000 + astart = -90.000000 + x = 15.0mil + y = 0.611632mm + r = 10.0mil + } + } + height = 1.373633mm + } + ha:S { + width = 0.735821mm + delta = 0.204727mm + li:objects { + ha:line.0 { + y2 = 0.851061mm + thickness = 8.0mil + x1 = 0.308266mm + x2 = 0.436371mm + y1 = 0.827971mm + } + ha:simplearc.1 { + thickness = 8.0mil + adelta = 227.000000 + astart = 25.000000 + x = 0.353178mm + y = 43.84mil + r = 0.275343mm + } + ha:simplearc.2 { + thickness = 8.0mil + adelta = 229.000000 + astart = 205.000000 + x = 0.382642mm + y = 22.16mil + r = 0.275343mm + } + } + height = 1.492513mm + } + ha:Q { + width = 0.715266mm + delta = 0.230633mm + li:objects { + ha:line.0 { + y2 = 1.119632mm + thickness = 8.0mil + x1 = 4.08mil + x2 = 4.08mil + y1 = 0.611632mm + } + ha:line.1 { + y2 = 54.0mil + thickness = 8.0mil + x1 = 15.0mil + x2 = 27.0mil + y1 = 45.0mil + } + ha:line.2 { + y2 = 1.119632mm + thickness = 8.0mil + x1 = 0.611632mm + x2 = 0.611632mm + y1 = 0.611632mm + } + ha:simplearc.3 { + thickness = 8.0mil + adelta = -180.000000 + astart = 180.000000 + x = 14.08mil + y = 1.119632mm + r = 10.0mil + } + ha:simplearc.4 { + thickness = 8.0mil + adelta = -180.000000 + astart = 0.000000 + x = 14.08mil + y = 0.611632mm + r = 10.0mil + } + } + height = 1.477266mm + } + ha:U { + width = 0.715266mm + delta = 0.228093mm + li:objects { + ha:line.0 { + y2 = 44.0mil + thickness = 8.0mil + x1 = 0.10414mm + x2 = 0.10414mm + y1 = 14.08mil + } + ha:line.1 { + y2 = 44.0mil + thickness = 8.0mil + x1 = 24.1mil + x2 = 24.1mil + y1 = 14.08mil + } + ha:simplearc.2 { + thickness = 8.0mil + adelta = -180.000000 + astart = 180.000000 + x = 14.08mil + y = 1.117092mm + r = 10.0mil + } + } + height = 1.474726mm + } + ha:V { + width = 0.508001mm + delta = 13.0mil + li:objects { + ha:line.0 { + y2 = 1.373632mm + thickness = 8.0mil + x1 = 0.0 + x2 = 10.0mil + y1 = 14.08mil + } + ha:line.1 { + y2 = 14.08mil + thickness = 8.0mil + x1 = 10.0mil + x2 = 20.0mil + y1 = 1.373632mm + } + } + height = 1.373633mm + } + ha:T { + width = 0.508001mm + delta = 9.0mil + li:objects { + ha:line.0 { + y2 = 14.08mil + thickness = 8.0mil + x1 = 0.0 + x2 = 20.0mil + y1 = 14.08mil + } + ha:line.1 { + y2 = 1.373632mm + thickness = 8.0mil + x1 = 10.0mil + x2 = 10.0mil + y1 = 14.08mil + } + } + height = 1.373633mm + } + ha:X { + width = 0.635001mm + delta = 14.0mil + li:objects { + ha:line.0 { + y2 = 14.08mil + thickness = 8.0mil + x1 = 0.0 + x2 = 25.0mil + y1 = 1.373632mm + } + ha:line.1 { + y2 = 1.373632mm + thickness = 8.0mil + x1 = 0.0 + x2 = 25.0mil + y1 = 14.08mil + } + } + height = 1.373633mm + } + ha:Y { + width = 0.508001mm + delta = 13.0mil + li:objects { + ha:line.0 { + y2 = 0.865632mm + thickness = 8.0mil + x1 = 0.0 + x2 = 10.0mil + y1 = 14.08mil + } + ha:line.1 { + y2 = 14.08mil + thickness = 8.0mil + x1 = 10.0mil + x2 = 20.0mil + y1 = 0.865632mm + } + ha:line.2 { + y2 = 1.373632mm + thickness = 8.0mil + x1 = 10.0mil + x2 = 10.0mil + y1 = 0.865632mm + } + } + height = 1.373633mm + } + ha:W { + width = 0.762001mm + delta = 13.0mil + li:objects { + ha:line.0 { + y2 = 0.865632mm + thickness = 8.0mil + x1 = 0.0 + x2 = 0.0 + y1 = 14.08mil + } + ha:line.1 { + y2 = 1.373632mm + thickness = 8.0mil + x1 = 0.0 + x2 = 5.0mil + y1 = 0.865632mm + } + ha:line.2 { + y2 = 0.865632mm + thickness = 8.0mil + x1 = 5.0mil + x2 = 15.0mil + y1 = 1.373632mm + } + ha:line.3 { + y2 = 1.373632mm + thickness = 8.0mil + x1 = 15.0mil + x2 = 25.0mil + y1 = 0.865632mm + } + ha:line.4 { + y2 = 0.865632mm + thickness = 8.0mil + x1 = 25.0mil + x2 = 30.0mil + y1 = 1.373632mm + } + ha:line.5 { + y2 = 14.08mil + thickness = 8.0mil + x1 = 30.0mil + x2 = 30.0mil + y1 = 0.865632mm + } + } + height = 1.373633mm + } + ha:[ { + width = 0.127001mm + delta = 12.0mil + li:objects { + ha:line.0 { + y2 = 14.08mil + thickness = 8.0mil + x1 = 0.0 + x2 = 5.0mil + y1 = 14.08mil + } + ha:line.1 { + y2 = 1.373632mm + thickness = 8.0mil + x1 = 0.0 + x2 = 0.0 + y1 = 14.08mil + } + ha:line.2 { + y2 = 1.373632mm + thickness = 8.0mil + x1 = 0.0 + x2 = 5.0mil + y1 = 1.373632mm + } + } + height = 1.373633mm + } + ha:^ { + width = 0.254001mm + delta = 12.0mil + li:objects { + ha:line.0 { + y2 = 14.08mil + thickness = 8.0mil + x1 = 0.0 + x2 = 5.0mil + y1 = 0.484632mm + } + ha:line.1 { + y2 = 0.484632mm + thickness = 8.0mil + x1 = 5.0mil + x2 = 10.0mil + y1 = 14.08mil + } + } + height = 0.484633mm + } + ha:Z { + width = 0.635001mm + delta = 13.0mil + li:objects { + ha:line.0 { + y2 = 14.08mil + thickness = 8.0mil + x1 = 0.0 + x2 = 25.0mil + y1 = 14.08mil + } + ha:line.1 { + y2 = 14.08mil + thickness = 8.0mil + x1 = 0.0 + x2 = 25.0mil + y1 = 1.373632mm + } + ha:line.2 { + y2 = 1.373632mm + thickness = 8.0mil + x1 = 0.0 + x2 = 25.0mil + y1 = 1.373632mm + } + } + height = 1.373633mm + } + ha:a { + width = 0.73991mm + delta = 8.0mil + li:objects { + ha:line.0 { + y2 = 1.246632mm + thickness = 8.0mil + x1 = 0.612909mm + x2 = 0.612909mm + y1 = 0.865632mm + } + ha:line.1 { + y2 = 1.373632mm + thickness = 8.0mil + x1 = 0.612909mm + x2 = 0.739909mm + y1 = 1.246632mm + } + ha:simplearc.2 { + thickness = 8.0mil + adelta = -360.000000 + astart = 20.000000 + x = 0.356877mm + y = 44.0mil + r = 0.253245mm + } + } + height = 1.474479mm + } + ha:_ { + width = 0.508001mm + delta = 12.0mil + li:objects { + ha:line.0 { + y2 = 1.373632mm + thickness = 8.0mil + x1 = 0.0 + x2 = 20.0mil + y1 = 1.373632mm + } + } + height = 1.373633mm + } + } + cell_width = 1.477266mm + cell_height = 1.879602mm + } +} Index: tags/2.1.2/font/osifontASCII.lht =================================================================== --- tags/2.1.2/font/osifontASCII.lht (nonexistent) +++ tags/2.1.2/font/osifontASCII.lht (revision 24813) @@ -0,0 +1,8566 @@ +li:pcb-rnd-font-v1 { + ha:geda_pcb { + id = 0 + ha:symbols { + ha:! { + width=4mil; delta=12.0mil; + li:objects { + li:simplepoly.0 { + 0.0mil; 79.78mil + 0.0mil; 79.69mil + 0.0mil; 79.42mil + 0.0mil; 78.96mil + 0.0mil; 78.32mil + 0.0mil; 77.5mil + 0.0mil; 76.44mil + 0.03mil; 75.43mil + 0.21mil; 74.61mil + 0.51mil; 73.94mil + 0.94mil; 73.49mil + 1.46mil; 73.18mil + 2.16mil; 73.06mil + 2.89mil; 73.18mil + 3.47mil; 73.46mil + 3.95mil; 73.94mil + 4.29mil; 74.61mil + 4.47mil; 75.46mil + 4.56mil; 76.56mil + 4.47mil; 77.56mil + 4.29mil; 78.35mil + 3.98mil; 78.99mil + 3.56mil; 79.42mil + 2.98mil; 79.69mil + } + li:simplepoly.1 { + 4.56mil; 65.91mil + 4.47mil; 65.91mil + 4.29mil; 65.91mil + 3.98mil; 65.91mil + 3.56mil; 65.91mil + 2.98mil; 65.91mil + 2.28mil; 65.91mil + 1.58mil; 65.85mil + 1.0mil; 65.61mil + 0.55mil; 65.21mil + 0.24mil; 64.66mil + 0.06mil; 63.93mil + 0.0mil; 63.02mil + 0.0mil; 36.59mil + 0.06mil; 35.77mil + 0.24mil; 35.07mil + 0.55mil; 34.52mil + 0.97mil; 34.12mil + 1.55mil; 33.88mil + 2.28mil; 33.79mil + 2.95mil; 33.88mil + 3.53mil; 34.12mil + 3.98mil; 34.49mil + 4.29mil; 35.04mil + 4.47mil; 35.74mil + 4.56mil; 36.62mil + 4.56mil; 63.02mil + 4.47mil; 63.9mil + 4.29mil; 64.63mil + 3.98mil; 65.18mil + 3.56mil; 65.61mil + 2.98mil; 65.85mil + } + } + height = 63.33mil + } + ha:" { + width=18mil; delta=12.0mil; + li:objects { + li:simplepoly.0 { + 13.87mil; 27.07mil + 14.02mil; 26.49mil + 14.26mil; 26.0mil + 14.57mil; 25.64mil + 14.9mil; 25.36mil + 15.33mil; 25.18mil + 15.81mil; 25.12mil + 16.54mil; 25.18mil + 17.15mil; 25.33mil + 17.64mil; 25.61mil + 17.97mil; 25.97mil + 18.19mil; 26.43mil + 18.28mil; 27.01mil + 18.25mil; 27.25mil + 18.25mil; 27.52mil + 18.22mil; 27.8mil + 18.16mil; 28.1mil + 18.1mil; 28.44mil + 18.03mil; 28.77mil + 16.12mil; 36.68mil + 15.91mil; 37.32mil + 15.66mil; 37.84mil + 15.39mil; 38.23mil + 15.02mil; 38.54mil + 14.63mil; 38.72mil + 14.17mil; 38.75mil + 13.41mil; 38.72mil + 12.8mil; 38.54mil + 12.32mil; 38.26mil + 11.98mil; 37.87mil + 11.77mil; 37.35mil + 11.71mil; 36.71mil + 11.71mil; 36.53mil + 11.71mil; 36.35mil + 11.71mil; 36.16mil + 11.74mil; 36.01mil + 11.77mil; 35.83mil + 11.83mil; 35.68mil + } + li:simplepoly.1 { + 2.31mil; 27.07mil + 2.49mil; 26.49mil + 2.73mil; 26.03mil + 3.07mil; 25.64mil + 3.43mil; 25.39mil + 3.86mil; 25.21mil + 4.41mil; 25.15mil + 5.11mil; 25.21mil + 5.72mil; 25.39mil + 6.17mil; 25.7mil + 6.51mil; 26.09mil + 6.69mil; 26.61mil + 6.78mil; 27.25mil + 6.75mil; 27.37mil + 6.75mil; 27.52mil + 6.72mil; 27.68mil + 6.69mil; 27.86mil + 6.63mil; 28.07mil + 6.6mil; 28.28mil + 4.44mil; 36.8mil + 4.22mil; 37.41mil + 3.98mil; 37.9mil + 3.68mil; 38.26mil + 3.28mil; 38.54mil + 2.86mil; 38.72mil + 2.37mil; 38.75mil + 1.64mil; 38.72mil + 1.03mil; 38.54mil + 0.57mil; 38.26mil + 0.24mil; 37.9mil + 0.06mil; 37.41mil + 0.0mil; 36.77mil + 0.0mil; 36.62mil + 0.0mil; 36.44mil + 0.03mil; 36.28mil + 0.06mil; 36.1mil + 0.09mil; 35.89mil + 0.15mil; 35.68mil + } + } + height = 63.33mil + } + ha:\# { + width=32mil; delta=12.0mil; + li:objects { + li:simplepoly.1 { + 6.84mil; 36.28mil + 6.9mil; 35.58mil + 7.08mil; 34.98mil + 7.39mil; 34.52mil + 7.81mil; 34.19mil + 8.36mil; 34.0mil + 9.06mil; 33.91mil + 9.73mil; 34.0mil + 10.28mil; 34.19mil + 10.7mil; 34.55mil + 11.01mil; 35.01mil + 11.19mil; 35.62mil + 11.28mil; 36.38mil + 11.28mil; 47.66mil + 20.77mil; 47.66mil + 20.77mil; 61.53mil + 20.77mil; 52.19mil + 11.31mil; 52.19mil + 11.31mil; 61.53mil + 20.77mil; 61.53mil + 20.77mil; 47.66mil + 20.77mil; 36.19mil + 20.83mil; 35.49mil + 21.02mil; 34.89mil + 21.35mil; 34.43mil + 21.81mil; 34.09mil + 22.38mil; 33.91mil + 23.14mil; 33.82mil + 23.78mil; 33.91mil + 24.3mil; 34.12mil + 24.73mil; 34.46mil + 25.03mil; 34.95mil + 25.18mil; 35.55mil + 25.27mil; 36.31mil + 25.27mil; 47.69mil + 29.87mil; 47.69mil + 30.54mil; 47.78mil + 31.08mil; 47.96mil + 31.54mil; 48.27mil + 31.84mil; 48.7mil + 32.03mil; 49.24mil + 32.12mil; 49.91mil + 32.03mil; 50.61mil + 31.84mil; 51.19mil + 31.54mil; 51.65mil + 31.11mil; 51.95mil + 30.54mil; 52.13mil + 29.84mil; 52.19mil + 25.27mil; 52.19mil + 25.27mil; 61.59mil + 29.75mil; 61.59mil + 30.45mil; 61.65mil + 31.02mil; 61.84mil + 31.48mil; 62.14mil + 31.81mil; 62.57mil + 32.0mil; 63.08mil + 32.09mil; 63.75mil + 32.0mil; 64.45mil + 31.81mil; 65.0mil + 31.51mil; 65.46mil + 31.08mil; 65.76mil + 30.54mil; 65.94mil + 29.84mil; 66.0mil + 25.21mil; 66.0mil + 25.21mil; 77.29mil + 25.12mil; 78.08mil + 24.94mil; 78.69mil + 24.6mil; 79.2mil + 24.15mil; 79.54mil + 23.57mil; 79.75mil + 22.84mil; 79.81mil + 22.2mil; 79.75mil + 21.68mil; 79.54mil + 21.29mil; 79.2mil + 20.99mil; 78.72mil + 20.8mil; 78.08mil + 20.77mil; 77.26mil + 20.77mil; 66.0mil + 11.34mil; 66.0mil + 11.34mil; 77.29mil + 11.25mil; 78.08mil + 11.07mil; 78.75mil + 10.76mil; 79.23mil + 10.34mil; 79.6mil + 9.76mil; 79.81mil + 9.06mil; 79.87mil + 8.36mil; 79.81mil + 7.81mil; 79.6mil + 7.39mil; 79.23mil + 7.08mil; 78.75mil + 6.9mil; 78.08mil + 6.84mil; 77.26mil + 6.84mil; 66.0mil + 2.46mil; 66.0mil + 1.7mil; 65.94mil + 1.09mil; 65.76mil + 0.64mil; 65.42mil + 0.3mil; 65.0mil + 0.09mil; 64.42mil + 0.03mil; 63.66mil + 0.09mil; 63.05mil + 0.27mil; 62.54mil + 0.64mil; 62.14mil + 1.09mil; 61.87mil + 1.7mil; 61.68mil + 2.49mil; 61.62mil + 6.84mil; 61.62mil + 6.84mil; 52.19mil + 2.55mil; 52.19mil + 1.76mil; 52.13mil + 1.12mil; 51.95mil + 0.64mil; 51.62mil + 0.27mil; 51.19mil + 0.06mil; 50.61mil + 0.0mil; 49.85mil + 0.06mil; 49.18mil + 0.27mil; 48.63mil + 0.64mil; 48.21mil + 1.12mil; 47.9mil + 1.76mil; 47.72mil + 2.58mil; 47.63mil + 6.84mil; 47.63mil + } + } + height = 63.33mil + } + ha:$ { + width=22mil; delta=12.0mil; + li:objects { + li:simplepoly.2 { + 0.0mil; 47.66mil + 0.06mil; 46.5mil + 0.24mil; 45.38mil + 0.54mil; 44.35mil + 0.97mil; 43.4mil + 1.55mil; 42.52mil + 2.28mil; 41.67mil + 3.25mil; 40.79mil + 4.32mil; 40.06mil + 5.41mil; 39.48mil + 6.6mil; 39.08mil + 7.81mil; 38.81mil + 9.18mil; 38.72mil + 9.18mil; 36.47mil + 9.24mil; 35.77mil + 9.43mil; 35.19mil + 9.73mil; 34.76mil + 10.16mil; 34.43mil + 10.7mil; 34.25mil + 11.43mil; 34.16mil + 12.07mil; 34.25mil + 12.62mil; 34.46mil + 13.05mil; 34.82mil + 13.35mil; 35.31mil + 13.53mil; 35.98mil + 13.62mil; 36.77mil + 13.62mil; 38.96mil + 14.93mil; 39.17mil + 16.21mil; 39.42mil + 17.49mil; 39.72mil + 18.7mil; 40.09mil + 19.92mil; 40.48mil + 21.14mil; 40.94mil + 21.65mil; 41.21mil + 22.11mil; 41.52mil + 22.45mil; 41.88mil + 22.69mil; 42.28mil + 22.84mil; 42.7mil + 22.9mil; 43.19mil + 22.84mil; 43.77mil + 9.18mil; 53.11mil + 9.18mil; 52.86mil + 9.18mil; 52.04mil + 9.18mil; 50.67mil + 9.18mil; 48.79mil + 9.18mil; 46.32mil + 9.18mil; 43.22mil + 7.72mil; 43.37mil + 6.54mil; 43.77mil + 5.59mil; 44.41mil + 4.92mil; 45.32mil + 4.53mil; 46.47mil + 4.41mil; 47.93mil + 4.53mil; 48.91mil + 4.92mil; 49.82mil + 5.56mil; 50.7mil + 6.51mil; 51.55mil + 7.66mil; 52.35mil + 9.18mil; 53.11mil + 22.84mil; 43.77mil + 22.66mil; 44.22mil + 22.38mil; 44.62mil + 22.02mil; 44.95mil + 21.53mil; 45.2mil + 20.92mil; 45.38mil + 20.71mil; 45.41mil + 20.47mil; 45.41mil + 20.19mil; 45.38mil + 19.89mil; 45.29mil + 19.59mil; 45.2mil + 19.22mil; 45.04mil + 18.03mil; 44.62mil + 16.94mil; 44.22mil + 15.97mil; 43.95mil + 15.08mil; 43.74mil + 14.29mil; 43.62mil + 13.62mil; 43.55mil + 13.62mil; 55.72mil + 14.32mil; 56.06mil + 15.08mil; 56.45mil + 15.94mil; 56.91mil + 16.82mil; 57.42mil + 17.76mil; 58.0mil + 18.8mil; 58.64mil + 20.04mil; 59.62mil + 21.08mil; 60.68mil + 21.87mil; 61.87mil + 22.45mil; 63.2mil + 22.81mil; 64.63mil + 22.93mil; 66.25mil + 22.84mil; 67.43mil + 22.66mil; 68.56mil + 22.32mil; 69.59mil + 21.87mil; 70.6mil + 21.26mil; 71.51mil + 20.53mil; 72.39mil + 19.53mil; 73.33mil + 18.46mil; 74.06mil + 17.37mil; 74.64mil + 16.18mil; 75.07mil + 14.96mil; 75.34mil + 13.62mil; 75.4mil + 13.62mil; 77.53mil + 13.56mil; 78.29mil + 13.38mil; 78.9mil + 13.08mil; 79.39mil + 12.65mil; 79.72mil + 12.1mil; 79.93mil + 11.43mil; 80.0mil + 10.73mil; 79.93mil + 10.19mil; 79.75mil + 9.73mil; 79.42mil + 9.43mil; 78.93mil + 9.24mil; 78.35mil + 9.18mil; 77.56mil + 9.18mil; 75.07mil + 7.27mil; 74.79mil + 5.59mil; 74.46mil + 4.1mil; 74.12mil + 2.89mil; 73.76mil + 1.85mil; 73.36mil + 1.06mil; 72.91mil + 0.73mil; 72.69mil + 0.45mil; 72.42mil + 0.24mil; 72.09mil + 0.09mil; 71.75mil + 0.03mil; 71.39mil + 0.0mil; 70.93mil + 0.03mil; 70.29mil + 0.21mil; 69.74mil + 0.51mil; 69.32mil + 0.94mil; 69.04mil + 1.49mil; 68.86mil + 2.19mil; 68.77mil + 2.37mil; 68.8mil + 2.58mil; 68.83mil + 2.83mil; 68.86mil + 3.1mil; 68.92mil + 3.37mil; 69.01mil + 3.71mil; 69.11mil + 4.71mil; 69.47mil + 5.68mil; 69.77mil + 18.46mil; 65.94mil + 18.31mil; 65.0mil + 17.91mil; 64.06mil + 17.24mil; 63.2mil + 16.33mil; 62.38mil + 15.11mil; 61.62mil + 13.62mil; 60.89mil + 13.62mil; 70.96mil + 15.08mil; 70.84mil + 16.27mil; 70.41mil + 17.21mil; 69.74mil + 17.88mil; 68.77mil + 18.31mil; 67.52mil + 18.46mil; 65.94mil + 5.68mil; 69.77mil + 6.63mil; 70.05mil + 7.51mil; 70.29mil + 8.36mil; 70.47mil + 9.18mil; 70.6mil + 9.18mil; 58.25mil + 7.6mil; 57.55mil + 6.2mil; 56.82mil + 4.95mil; 56.09mil + 3.89mil; 55.36mil + 3.01mil; 54.6mil + 2.28mil; 53.84mil + 1.58mil; 52.95mil + 1.0mil; 52.01mil + 0.54mil; 51.01mil + 0.24mil; 49.94mil + 0.06mil; 48.85mil + } + } + height = 63.33mil + } + ha:% { + width=41mil; delta=12.0mil; + li:objects { + li:simplepoly.1 { + 39.33mil; 64.82mil + 39.97mil; 65.67mil + 40.51mil; 66.61mil + 40.94mil; 67.61mil + 41.21mil; 68.71mil + 41.4mil; 69.9mil + 41.49mil; 71.2mil + 41.4mil; 72.36mil + 41.18mil; 73.46mil + 40.79mil; 74.49mil + 40.27mil; 75.46mil + 39.6mil; 76.41mil + 38.78mil; 77.32mil + 37.81mil; 78.14mil + 36.83mil; 78.81mil + 35.89mil; 67.77mil + 35.43mil; 67.28mil + 34.92mil; 66.88mil + 34.34mil; 66.55mil + 33.7mil; 66.34mil + 33.0mil; 66.19mil + 32.21mil; 66.12mil + 31.54mil; 66.19mil + 30.93mil; 66.34mil + 30.35mil; 66.58mil + 29.78mil; 66.92mil + 29.26mil; 67.34mil + 28.74mil; 67.89mil + 28.41mil; 68.31mil + 28.16mil; 68.77mil + 27.95mil; 69.26mil + 27.8mil; 69.81mil + 27.71mil; 70.35mil + 27.71mil; 70.96mil + 27.74mil; 71.6mil + 27.86mil; 72.21mil + 28.04mil; 72.76mil + 28.32mil; 73.27mil + 28.68mil; 73.73mil + 29.14mil; 74.15mil + 29.62mil; 74.55mil + 30.14mil; 74.88mil + 30.66mil; 75.13mil + 31.18mil; 75.31mil + 31.72mil; 75.4mil + 32.3mil; 75.43mil + 32.85mil; 75.4mil + 33.43mil; 75.28mil + 34.0mil; 75.04mil + 34.61mil; 74.73mil + 35.22mil; 74.34mil + 35.86mil; 73.82mil + 36.19mil; 73.46mil + 36.5mil; 73.06mil + 36.74mil; 72.57mil + 36.89mil; 72.06mil + 36.98mil; 71.48mil + 37.05mil; 70.81mil + 36.98mil; 70.32mil + 36.89mil; 69.81mil + 36.74mil; 69.32mil + 36.53mil; 68.8mil + 36.22mil; 68.31mil + 35.89mil; 67.77mil + 36.83mil; 78.81mil + 35.77mil; 79.33mil + 34.67mil; 79.72mil + 33.52mil; 79.93mil + 32.27mil; 80.0mil + 31.27mil; 79.96mil + 30.32mil; 79.78mil + 29.38mil; 79.51mil + 28.47mil; 79.14mil + 27.59mil; 78.66mil + 26.7mil; 78.02mil + 25.64mil; 77.11mil + 24.76mil; 76.1mil + 24.09mil; 75.01mil + 23.6mil; 73.82mil + 23.33mil; 72.54mil + 23.24mil; 71.14mil + 23.3mil; 69.68mil + 23.57mil; 68.31mil + 24.0mil; 67.07mil + 24.6mil; 65.91mil + 25.37mil; 64.85mil + 26.37mil; 63.84mil + 27.22mil; 63.2mil + 28.1mil; 62.66mil + 29.02mil; 62.23mil + 29.99mil; 61.93mil + 30.99mil; 61.74mil + 32.09mil; 61.65mil + 33.49mil; 61.74mil + 34.79mil; 62.02mil + 36.04mil; 62.44mil + 37.2mil; 63.05mil + 38.29mil; 63.84mil + } + li:simplepoly.2 { + 37.14mil; 35.07mil + 37.44mil; 34.76mil + 37.78mil; 34.52mil + 38.11mil; 34.34mil + 38.44mil; 34.19mil + 38.78mil; 34.09mil + 39.18mil; 34.06mil + 39.84mil; 34.16mil + 40.39mil; 34.34mil + 40.85mil; 34.67mil + 41.15mil; 35.13mil + 41.33mil; 35.71mil + 41.43mil; 36.44mil + 41.4mil; 36.68mil + 41.3mil; 36.89mil + 41.18mil; 37.17mil + 41.0mil; 37.44mil + 40.79mil; 37.74mil + 40.51mil; 38.08mil + 4.1mil; 79.05mil + 3.8mil; 79.36mil + 3.53mil; 79.6mil + 3.19mil; 79.78mil + 2.86mil; 79.9mil + 2.52mil; 80.0mil + 2.16mil; 80.0mil + 1.49mil; 79.93mil + 0.94mil; 79.75mil + 0.51mil; 79.45mil + 0.24mil; 79.02mil + 0.06mil; 78.44mil + 0.0mil; 77.71mil + 0.0mil; 77.44mil + 0.06mil; 77.17mil + 0.18mil; 76.86mil + 0.33mil; 76.59mil + 0.51mil; 76.28mil + 0.79mil; 75.98mil + } + li:simplepoly.4 { + 16.09mil; 37.23mil + 16.73mil; 38.08mil + 17.27mil; 39.02mil + 17.7mil; 40.03mil + 17.97mil; 41.12mil + 18.16mil; 42.31mil + 18.25mil; 43.62mil + 18.16mil; 44.77mil + 17.94mil; 45.87mil + 17.55mil; 46.93mil + 17.03mil; 47.9mil + 16.36mil; 48.85mil + 15.54mil; 49.73mil + 14.57mil; 50.55mil + 13.59mil; 51.19mil + 12.53mil; 51.71mil + 11.43mil; 52.07mil + 12.65mil; 40.18mil + 12.19mil; 39.69mil + 11.68mil; 39.3mil + 11.1mil; 38.96mil + 10.46mil; 38.75mil + 9.76mil; 38.6mil + 8.97mil; 38.54mil + 8.3mil; 38.6mil + 7.69mil; 38.75mil + 7.11mil; 38.99mil + 6.54mil; 39.33mil + 6.02mil; 39.75mil + 5.5mil; 40.3mil + 5.17mil; 40.73mil + 4.92mil; 41.18mil + 4.71mil; 41.67mil + 4.56mil; 42.22mil + 4.47mil; 42.76mil + 4.47mil; 43.37mil + 4.5mil; 44.01mil + 4.62mil; 44.62mil + 4.8mil; 45.17mil + 5.08mil; 45.68mil + 5.44mil; 46.14mil + 5.9mil; 46.57mil + 6.38mil; 46.96mil + 6.9mil; 47.3mil + 7.42mil; 47.54mil + 7.94mil; 47.72mil + 8.48mil; 47.81mil + 9.06mil; 47.84mil + 9.61mil; 47.81mil + 10.19mil; 47.69mil + 10.76mil; 47.45mil + 11.37mil; 47.14mil + 11.98mil; 46.75mil + 12.62mil; 46.23mil + 12.95mil; 45.87mil + 13.26mil; 45.47mil + 13.5mil; 44.98mil + 13.65mil; 44.47mil + 13.75mil; 43.89mil + 13.81mil; 43.22mil + 13.75mil; 42.73mil + 13.65mil; 42.22mil + 13.5mil; 41.73mil + 13.29mil; 41.21mil + 12.99mil; 40.73mil + 12.65mil; 40.18mil + 11.43mil; 52.07mil + 10.28mil; 52.28mil + 9.03mil; 52.35mil + 8.03mil; 52.31mil + 7.08mil; 52.16mil + 6.14mil; 51.89mil + 5.23mil; 51.52mil + 4.35mil; 51.04mil + 3.46mil; 50.43mil + 2.4mil; 49.55mil + 1.52mil; 48.54mil + 0.85mil; 47.45mil + 0.36mil; 46.26mil + 0.09mil; 44.98mil + 0.0mil; 43.55mil + 0.06mil; 42.09mil + 0.33mil; 40.73mil + 0.76mil; 39.48mil + 1.37mil; 38.32mil + 2.13mil; 37.26mil + 3.13mil; 36.25mil + 3.98mil; 35.62mil + 4.86mil; 35.07mil + 5.78mil; 34.64mil + 6.75mil; 34.34mil + 7.75mil; 34.16mil + 8.85mil; 34.06mil + 10.25mil; 34.16mil + 11.56mil; 34.43mil + 12.8mil; 34.85mil + 13.96mil; 35.46mil + 15.05mil; 36.25mil + } + } + height = 63.33mil + } + ha:&26 { + width=32mil; delta=12.0mil; + li:objects { + li:simplepoly.2 { + 11.4mil; 33.91mil + 12.68mil; 34.0mil + 13.93mil; 34.25mil + 15.11mil; 34.67mil + 16.24mil; 35.25mil + 17.33mil; 35.98mil + 18.4mil; 36.92mil + 19.1mil; 37.74mil + 19.71mil; 38.63mil + 20.16mil; 39.57mil + 20.5mil; 40.57mil + 20.68mil; 41.64mil + 20.77mil; 42.76mil + 20.71mil; 43.8mil + 20.62mil; 44.71mil + 20.47mil; 45.56mil + 20.26mil; 46.32mil + 19.95mil; 47.02mil + 19.62mil; 47.63mil + 14.02mil; 55.63mil + 21.47mil; 67.4mil + 17.91mil; 70.14mil + 16.51mil; 67.98mil + 15.24mil; 66.0mil + 14.08mil; 64.15mil + 13.02mil; 62.5mil + 12.07mil; 61.01mil + 11.22mil; 59.62mil + 5.78mil; 67.37mil + 5.41mil; 67.92mil + 5.14mil; 68.5mil + 4.92mil; 69.04mil + 4.77mil; 69.59mil + 4.68mil; 70.14mil + 4.65mil; 70.72mil + 4.77mil; 72.18mil + 5.17mil; 73.33mil + 5.87mil; 74.25mil + 6.81mil; 74.92mil + 8.03mil; 75.31mil + 9.58mil; 75.43mil + 10.03mil; 75.4mil + 10.52mil; 75.31mil + 11.01mil; 75.13mil + 11.53mil; 74.88mil + 12.07mil; 74.58mil + 12.65mil; 74.15mil + 17.91mil; 70.14mil + 21.47mil; 67.4mil + 28.5mil; 62.2mil + 28.74mil; 62.05mil + 28.99mil; 61.9mil + 29.26mil; 61.77mil + 29.5mil; 61.71mil + 29.75mil; 61.65mil + 29.99mil; 61.62mil + 30.63mil; 61.71mil + 31.18mil; 61.9mil + 31.6mil; 62.23mil + 31.91mil; 62.66mil + 32.09mil; 63.23mil + 32.18mil; 63.96mil + 32.12mil; 64.3mil + 32.03mil; 64.63mil + 31.84mil; 65.0mil + 31.57mil; 65.33mil + 31.24mil; 65.67mil + 30.84mil; 66.0mil + 23.94mil; 71.3mil + 27.19mil; 76.38mil + 27.28mil; 76.62mil + 27.4mil; 76.83mil + 27.46mil; 77.07mil + 27.52mil; 77.32mil + 27.56mil; 77.53mil + 27.59mil; 77.77mil + 27.49mil; 78.47mil + 27.31mil; 79.02mil + 27.01mil; 79.45mil + 26.58mil; 79.75mil + 26.03mil; 79.93mil + 25.37mil; 80.0mil + 25.0mil; 80.0mil + 24.67mil; 79.9mil + 24.36mil; 79.75mil + 24.09mil; 79.54mil + 23.81mil; 79.26mil + 23.6mil; 78.93mil + 20.38mil; 74.0mil + 14.41mil; 78.35mil + 13.65mil; 78.87mil + 12.86mil; 79.26mil + 12.01mil; 79.6mil + 11.13mil; 79.81mil + 10.19mil; 79.96mil + 9.15mil; 80.0mil + + 11.4mil; 51.58mil + 15.42mil; 45.87mil + 15.66mil; 45.44mil + 15.91mil; 45.01mil + 16.06mil; 44.53mil + 16.18mil; 44.04mil + 16.27mil; 43.49mil + 16.3mil; 42.92mil + 16.24mil; 42.4mil + 16.12mil; 41.88mil + 15.94mil; 41.36mil + 15.66mil; 40.85mil + 15.3mil; 40.36mil + 14.87mil; 39.84mil + 14.38mil; 39.45mil + 13.9mil; 39.08mil + 13.35mil; 38.81mil + 12.8mil; 38.63mil + 12.22mil; 38.51mil + 11.59mil; 38.44mil + 10.92mil; 38.51mil + 10.31mil; 38.63mil + 9.73mil; 38.81mil + 9.21mil; 39.08mil + 8.7mil; 39.42mil + 8.24mil; 39.84mil + 7.81mil; 40.36mil + 7.45mil; 40.85mil + 7.18mil; 41.36mil + 6.99mil; 41.88mil + 6.87mil; 42.43mil + 6.84mil; 42.98mil + 6.84mil; 43.46mil + 6.93mil; 43.98mil + 7.05mil; 44.47mil + 7.27mil; 44.95mil + 7.48mil; 45.47mil + 7.81mil; 45.99mil + + 11.4mil; 51.58mil + + 9.15mil; 80.0mil + + 7.97mil; 79.96mil + 6.9mil; 79.78mil + 5.9mil; 79.51mil + 4.99mil; 79.11mil + 4.16mil; 78.6mil + 3.43mil; 77.96mil + 2.37mil; 76.83mil + 1.52mil; 75.65mil + 0.85mil; 74.4mil + 0.36mil; 73.12mil + 0.09mil; 71.78mil + 0.0mil; 70.32mil + 0.03mil; 69.47mil + 0.21mil; 68.62mil + 0.48mil; 67.74mil + 0.88mil; 66.85mil + 1.4mil; 65.94mil + 2.07mil; 65.0mil + 8.67mil; 55.54mil + 3.31mil; 47.08mil + 3.04mil; 46.6mil + 2.8mil; 45.99mil + 2.64mil; 45.32mil + 2.52mil; 44.59mil + 2.43mil; 43.77mil + 2.43mil; 42.82mil + 2.52mil; 41.52mil + 2.8mil; 40.27mil + 3.28mil; 39.08mil + 3.95mil; 37.96mil + 4.8mil; 36.92mil + 5.93mil; 35.89mil + 6.75mil; 35.31mil + 7.6mil; 34.82mil + 8.48mil; 34.43mil + 9.4mil; 34.16mil + 10.37mil; 33.97mil + } + } + height = 63.33mil + } + ha:' { + width=6mil; delta=12.0mil; + li:objects { + li:simplepoly.0 { + 2.19mil; 26.92mil + 2.37mil; 26.31mil + 2.64mil; 25.79mil + 2.95mil; 25.39mil + 3.34mil; 25.12mil + 3.77mil; 24.94mil + 4.32mil; 24.88mil + 4.99mil; 24.94mil + 5.56mil; 25.12mil + 6.02mil; 25.39mil + 6.32mil; 25.76mil + 6.51mil; 26.25mil + 6.6mil; 26.85mil + 6.57mil; 27.1mil + 6.57mil; 27.34mil + 6.54mil; 27.59mil + 6.51mil; 27.83mil + 6.45mil; 28.07mil + 6.41mil; 28.32mil + 4.44mil; 36.31mil + 4.19mil; 36.98mil + 3.92mil; 37.5mil + 3.59mil; 37.93mil + 3.19mil; 38.23mil + 2.73mil; 38.38mil + 2.19mil; 38.44mil + 1.52mil; 38.41mil + 0.97mil; 38.23mil + 0.54mil; 37.96mil + 0.24mil; 37.56mil + 0.06mil; 37.04mil + 0.0mil; 36.38mil + 0.0mil; 36.16mil + 0.03mil; 35.89mil + 0.06mil; 35.58mil + 0.12mil; 35.25mil + 0.18mil; 34.89mil + 0.3mil; 34.46mil + } + } + height = 63.33mil + } + ha:( { + width=8mil; delta=12.0mil; + li:objects { + li:simplepoly.0 { + 4.62mil; 30.78mil + 4.84mil; 30.35mil + 5.11mil; 29.99mil + 5.44mil; 29.71mil + 5.87mil; 29.5mil + 6.33mil; 29.38mil + 6.87mil; 29.32mil + 7.45mil; 29.38mil + 7.94mil; 29.56mil + 8.33mil; 29.87mil + 8.61mil; 30.29mil + 8.79mil; 30.84mil + 8.85mil; 31.51mil + 8.82mil; 31.78mil + 8.79mil; 32.09mil + 8.73mil; 32.42mil + 8.61mil; 32.79mil + 8.52mil; 33.15mil + 8.36mil; 33.58mil + 7.09mil; 37.32mil + 6.05mil; 41.06mil + 5.23mil; 44.77mil + 4.65mil; 48.51mil + 4.32mil; 52.22mil + 4.2mil; 56.03mil + 4.29mil; 60.5mil + 4.62mil; 64.76mil + 5.2mil; 68.86mil + 5.99mil; 72.79mil + 7.03mil; 76.56mil + 8.33mil; 80.27mil + 8.49mil; 80.69mil + 8.61mil; 81.12mil + 8.73mil; 81.52mil + 8.79mil; 81.88mil + 8.85mil; 82.25mil + 8.88mil; 82.58mil + 8.79mil; 83.16mil + 8.61mil; 83.65mil + 8.27mil; 84.01mil + 7.79mil; 84.28mil + 7.21mil; 84.47mil + 6.45mil; 84.53mil + 6.02mil; 84.47mil + 5.66mil; 84.31mil + 5.32mil; 84.07mil + 5.02mil; 83.71mil + 4.74mil; 83.25mil + 4.5mil; 82.7mil + 3.13mil; 78.69mil + 2.01mil; 74.52mil + 1.12mil; 70.17mil + 0.49mil; 65.64mil + 0.12mil; 60.95mil + 0.0mil; 55.93mil + 0.12mil; 51.55mil + 0.49mil; 47.27mil + 1.12mil; 43.04mil + 2.01mil; 38.9mil + 3.16mil; 34.89mil + } + } + height = 63.33mil + } + ha:) { + width=8mil; delta=12.0mil; + li:objects { + li:simplepoly.0 { + 4.26mil; 30.72mil + 5.65mil; 34.67mil + 6.81mil; 38.72mil + 7.69mil; 42.82mil + 8.33mil; 47.05mil + 8.73mil; 51.34mil + 8.88mil; 55.87mil + 8.73mil; 60.74mil + 8.36mil; 65.42mil + 7.75mil; 69.96mil + 6.87mil; 74.31mil + 5.78mil; 78.5mil + 4.38mil; 82.64mil + 4.1mil; 83.19mil + 3.83mil; 83.65mil + 3.53mil; 83.98mil + 3.19mil; 84.25mil + 2.83mil; 84.41mil + 2.43mil; 84.47mil + 1.67mil; 84.41mil + 1.06mil; 84.22mil + 0.61mil; 83.98mil + 0.27mil; 83.58mil + 0.06mil; 83.13mil + 0.0mil; 82.52mil + 0.0mil; 82.19mil + 0.03mil; 81.85mil + 0.12mil; 81.49mil + 0.21mil; 81.09mil + 0.36mil; 80.66mil + 0.54mil; 80.21mil + 1.79mil; 76.62mil + 2.83mil; 72.88mil + 3.62mil; 68.92mil + 4.19mil; 64.85mil + 4.56mil; 60.56mil + 4.68mil; 55.96mil + 4.56mil; 52.07mil + 4.19mil; 48.24mil + 3.65mil; 44.5mil + 2.83mil; 40.79mil + 1.79mil; 37.2mil + 0.51mil; 33.52mil + 0.33mil; 33.12mil + 0.21mil; 32.73mil + 0.12mil; 32.36mil + 0.03mil; 32.03mil + 0.0mil; 31.75mil + 0.0mil; 31.45mil + 0.03mil; 30.81mil + 0.21mil; 30.26mil + 0.48mil; 29.84mil + 0.88mil; 29.53mil + 1.37mil; 29.35mil + 2.0mil; 29.26mil + 2.52mil; 29.32mil + 2.98mil; 29.44mil + 3.37mil; 29.62mil + 3.74mil; 29.93mil + 4.01mil; 30.26mil + } + } + height = 63.33mil + } + ha:* { + width=22mil; delta=12.0mil; + li:objects { + li:simplepoly.0 { + 16.67mil; 59.89mil + 16.76mil; 59.89mil + 17.06mil; 59.89mil + 17.61mil; 59.89mil + 18.34mil; 59.89mil + 19.28mil; 59.89mil + 20.5mil; 59.89mil + 21.2mil; 59.95mil + 21.78mil; 60.13mil + 22.2mil; 60.41mil + 22.54mil; 60.8mil + 22.72mil; 61.32mil + 22.81mil; 61.96mil + 22.72mil; 62.63mil + 22.54mil; 63.17mil + 22.2mil; 63.6mil + 21.72mil; 63.9mil + 21.14mil; 64.09mil + 20.38mil; 64.15mil + 20.26mil; 64.15mil + 19.95mil; 64.15mil + 19.46mil; 64.15mil + 18.76mil; 64.15mil + 17.85mil; 64.15mil + 16.73mil; 64.15mil + 19.22mil; 66.67mil + 19.43mil; 66.95mil + 19.65mil; 67.19mil + 19.8mil; 67.46mil + 19.92mil; 67.71mil + 19.98mil; 67.95mil + 20.01mil; 68.16mil + 19.92mil; 68.83mil + 19.71mil; 69.35mil + 19.34mil; 69.77mil + 18.86mil; 70.08mil + 18.22mil; 70.23mil + 17.43mil; 70.29mil + 17.15mil; 70.29mil + 16.88mil; 70.2mil + 16.57mil; 70.08mil + 16.3mil; 69.9mil + 16.0mil; 69.65mil + 15.69mil; 69.35mil + 11.43mil; 65.12mil + 6.54mil; 70.02mil + 6.32mil; 70.2mil + 6.08mil; 70.35mil + 5.87mil; 70.47mil + 5.62mil; 70.54mil + 5.38mil; 70.6mil + 5.11mil; 70.6mil + 4.41mil; 70.54mil + 3.86mil; 70.35mil + 3.4mil; 70.05mil + 3.1mil; 69.62mil + 2.92mil; 69.07mil + 2.86mil; 68.38mil + 2.86mil; 68.1mil + 2.92mil; 67.86mil + 2.98mil; 67.58mil + 3.1mil; 67.34mil + 3.25mil; 67.1mil + 3.46mil; 66.85mil + 6.05mil; 64.15mil + 2.28mil; 64.15mil + 1.58mil; 64.09mil + 1.0mil; 63.9mil + 0.54mil; 63.6mil + 0.24mil; 63.17mil + 0.06mil; 62.63mil + 0.0mil; 61.93mil + 0.06mil; 61.29mil + 0.24mil; 60.77mil + 0.57mil; 60.35mil + 1.06mil; 60.04mil + 1.64mil; 59.89mil + 2.43mil; 59.8mil + 6.08mil; 59.8mil + 3.13mil; 56.82mil + 2.95mil; 56.66mil + 2.83mil; 56.45mil + 2.73mil; 56.24mil + 2.64mil; 56.03mil + 2.61mil; 55.75mil + 2.61mil; 55.48mil + 2.67mil; 54.75mil + 2.86mil; 54.14mil + 3.19mil; 53.68mil + 3.65mil; 53.35mil + 4.22mil; 53.14mil + 4.99mil; 53.04mil + 5.23mil; 53.08mil + 5.5mil; 53.14mil + 5.72mil; 53.2mil + 5.96mil; 53.32mil + 6.17mil; 53.47mil + 6.38mil; 53.65mil + 11.43mil; 58.85mil + 15.97mil; 54.32mil + 16.33mil; 53.99mil + 16.7mil; 53.68mil + 17.09mil; 53.47mil + 17.46mil; 53.32mil + 17.79mil; 53.23mil + 18.19mil; 53.17mil + 18.76mil; 53.26mil + 19.25mil; 53.44mil + 19.65mil; 53.77mil + 19.92mil; 54.23mil + 20.1mil; 54.81mil + 20.16mil; 55.54mil + 20.1mil; 55.84mil + 20.01mil; 56.15mil + 19.86mil; 56.48mil + 19.62mil; 56.85mil + 19.31mil; 57.21mil + 18.95mil; 57.61mil + } + } + height = 63.33mil + } + ha:+ { + width=22mil; delta=12.0mil; + li:objects { + li:simplepoly.0 { + 9.4mil; 52.92mil + 9.46mil; 52.19mil + 9.64mil; 51.58mil + 9.94mil; 51.13mil + 10.37mil; 50.79mil + 10.92mil; 50.58mil + 11.65mil; 50.49mil + 12.29mil; 50.58mil + 12.83mil; 50.79mil + 13.26mil; 51.16mil + 13.53mil; 51.65mil + 13.72mil; 52.31mil + 13.81mil; 53.11mil + 13.81mil; 59.71mil + 20.32mil; 59.71mil + 21.08mil; 59.8mil + 21.72mil; 59.98mil + 22.2mil; 60.28mil + 22.57mil; 60.71mil + 22.78mil; 61.26mil + 22.87mil; 61.93mil + 22.78mil; 62.57mil + 22.57mil; 63.11mil + 22.2mil; 63.51mil + 21.72mil; 63.81mil + 21.05mil; 63.96mil + 20.26mil; 64.03mil + 20.07mil; 64.03mil + 19.53mil; 64.03mil + 18.61mil; 64.03mil + 17.37mil; 64.03mil + 15.75mil; 64.03mil + 13.72mil; 64.03mil + 13.72mil; 70.69mil + 13.65mil; 71.48mil + 13.47mil; 72.09mil + 13.2mil; 72.6mil + 12.8mil; 72.94mil + 12.29mil; 73.15mil + 11.68mil; 73.21mil + 10.98mil; 73.15mil + 10.4mil; 72.97mil + 9.94mil; 72.6mil + 9.64mil; 72.15mil + 9.46mil; 71.54mil + 9.4mil; 70.75mil + 9.4mil; 64.03mil + 9.18mil; 64.03mil + 8.64mil; 64.03mil + 7.69mil; 64.03mil + 6.38mil; 64.03mil + 4.68mil; 64.03mil + 2.55mil; 64.03mil + 1.76mil; 63.96mil + 1.12mil; 63.78mil + 0.64mil; 63.48mil + 0.27mil; 63.05mil + 0.06mil; 62.5mil + 0.0mil; 61.77mil + 0.06mil; 61.17mil + 0.27mil; 60.62mil + 0.64mil; 60.22mil + 1.12mil; 59.92mil + 1.79mil; 59.77mil + 2.61mil; 59.68mil + 9.4mil; 59.68mil + } + } + height = 63.33mil + } + ha:, { + width=6mil; delta=12.0mil; + li:objects { + li:simplepoly.0 { + 2.19mil; 79.17mil + 2.37mil; 78.57mil + 2.65mil; 78.05mil + 2.95mil; 77.65mil + 3.35mil; 77.38mil + 3.77mil; 77.2mil + 4.32mil; 77.14mil + 4.99mil; 77.2mil + 5.57mil; 77.38mil + 6.02mil; 77.65mil + 6.33mil; 78.02mil + 6.51mil; 78.5mil + 6.6mil; 79.11mil + 6.57mil; 79.36mil + 6.57mil; 79.6mil + 6.54mil; 79.84mil + 6.51mil; 80.06mil + 6.45mil; 80.3mil + 6.42mil; 80.57mil + 4.44mil; 88.57mil + 4.2mil; 89.21mil + 3.92mil; 89.73mil + 3.59mil; 90.15mil + 3.19mil; 90.46mil + 2.74mil; 90.61mil + 2.19mil; 90.7mil + 1.52mil; 90.64mil + 0.97mil; 90.46mil + 0.55mil; 90.18mil + 0.24mil; 89.79mil + 0.06mil; 89.27mil + 0.0mil; 88.63mil + 0.0mil; 88.39mil + 0.03mil; 88.12mil + 0.06mil; 87.81mil + 0.12mil; 87.48mil + 0.18mil; 87.11mil + 0.3mil; 86.72mil + } + } + height = 63.33mil + } + ha:- { + width=22mil; delta=12.0mil; + li:objects { + li:simplepoly.0 { + 2.34mil; 59.58mil + 2.83mil; 59.58mil + 4.35mil; 59.58mil + 6.87mil; 59.58mil + 10.4mil; 59.58mil + 14.93mil; 59.58mil + 20.68mil; 59.58mil + 21.32mil; 59.68mil + 21.87mil; 59.86mil + 22.29mil; 60.19mil + 22.6mil; 60.62mil + 22.78mil; 61.2mil + 22.87mil; 61.93mil + 22.78mil; 62.57mil + 22.6mil; 63.08mil + 22.26mil; 63.48mil + 21.84mil; 63.75mil + 21.26mil; 63.93mil + 20.53mil; 63.96mil + 2.25mil; 63.96mil + 1.55mil; 63.9mil + 1.0mil; 63.72mil + 0.54mil; 63.42mil + 0.24mil; 62.99mil + 0.06mil; 62.41mil + 0.0mil; 61.68mil + 0.06mil; 61.08mil + 0.24mil; 60.53mil + 0.57mil; 60.13mil + 1.0mil; 59.83mil + 1.58mil; 59.68mil + } + } + height = 63.33mil + } + ha:. { + width=4mil; delta=12.0mil; + li:objects { + li:simplepoly.0 { + 0.0mil; 80.0mil + 0.0mil; 79.93mil + 0.0mil; 79.66mil + 0.0mil; 79.2mil + 0.0mil; 78.57mil + 0.0mil; 77.77mil + 0.0mil; 76.74mil + 0.03mil; 75.77mil + 0.21mil; 74.95mil + 0.52mil; 74.34mil + 0.91mil; 73.88mil + 1.46mil; 73.61mil + 2.13mil; 73.49mil + 2.86mil; 73.61mil + 3.5mil; 73.88mil + 3.98mil; 74.37mil + 4.32mil; 75.04mil + 4.53mil; 75.89mil + 4.62mil; 76.95mil + 4.53mil; 77.9mil + 4.35mil; 78.66mil + 4.01mil; 79.23mil + 3.59mil; 79.66mil + 3.01mil; 79.93mil + 2.28mil; 80.0mil + 1.58mil; 79.93mil + 1.0mil; 79.66mil + 0.55mil; 79.2mil + 0.24mil; 78.57mil + 0.06mil; 77.77mil + } + } + height = 63.33mil + } + ha:/ { + width=22mil; delta=12.0mil; + li:objects { + li:simplepoly.0 { + 0.0mil; 77.96mil + 0.0mil; 77.74mil + 0.03mil; 77.47mil + 0.12mil; 77.17mil + 0.21mil; 76.83mil + 0.36mil; 76.47mil + 0.55mil; 76.04mil + 18.25mil; 35.98mil + 18.52mil; 35.4mil + 18.86mil; 34.95mil + 19.22mil; 34.55mil + 19.62mil; 34.31mil + 20.01mil; 34.12mil + 20.5mil; 34.06mil + 21.14mil; 34.12mil + 21.69mil; 34.31mil + 22.11mil; 34.58mil + 22.42mil; 34.98mil + 22.6mil; 35.49mil + 22.69mil; 36.13mil + 22.66mil; 36.41mil + 22.63mil; 36.68mil + 22.6mil; 36.92mil + 22.54mil; 37.2mil + 22.48mil; 37.44mil + 22.39mil; 37.68mil + 4.53mil; 78.11mil + 4.23mil; 78.69mil + 3.92mil; 79.17mil + 3.56mil; 79.54mil + 3.19mil; 79.78mil + 2.8mil; 79.96mil + 2.37mil; 80.0mil + 1.64mil; 79.96mil + 1.03mil; 79.78mil + 0.58mil; 79.51mil + 0.24mil; 79.11mil + 0.06mil; 78.6mil + } + } + height = 63.33mil + } + ha:0 { + width=23mil; delta=12.0mil; + li:objects { + li:simplepoly.1 { + 11.62mil; 34.06mil + 12.92mil; 34.16mil + 14.14mil; 34.43mil + 15.27mil; 34.89mil + 16.27mil; 35.49mil + 17.15mil; 36.28mil + 17.97mil; 37.29mil + + 11.46mil; 38.44mil + 10.8mil; 38.51mil + 10.22mil; 38.66mil + 9.67mil; 38.9mil + 9.21mil; 39.27mil + 8.82mil; 39.72mil + 8.48mil; 40.27mil + 7.72mil; 41.88mil + 7.02mil; 43.55mil + 6.41mil; 45.29mil + 5.9mil; 47.08mil + 5.41mil; 49.0mil + 5.02mil; 51.01mil + 4.83mil; 51.95mil + 4.71mil; 52.89mil + 4.62mil; 53.87mil + 4.53mil; 54.81mil + 4.5mil; 55.78mil + 4.5mil; 56.76mil + 4.5mil; 57.49mil + 4.5mil; 58.19mil + 4.56mil; 58.89mil + 4.59mil; 59.58mil + 4.68mil; 60.28mil + 4.77mil; 60.98mil + 5.08mil; 63.23mil + 5.47mil; 65.33mil + 5.93mil; 67.31mil + 6.48mil; 69.2mil + 7.08mil; 70.96mil + 7.78mil; 72.66mil + 8.21mil; 73.55mil + 8.73mil; 74.28mil + 9.3mil; 74.82mil + 9.94mil; 75.25mil + 10.64mil; 75.49mil + 11.43mil; 75.55mil + 12.16mil; 75.49mil + 12.83mil; 75.28mil + 13.47mil; 74.92mil + 14.05mil; 74.43mil + 14.57mil; 73.76mil + 15.08mil; 72.94mil + 15.69mil; 71.6mil + 16.3mil; 70.08mil + 16.82mil; 68.41mil + 17.3mil; 66.55mil + 17.7mil; 64.57mil + 18.1mil; 62.32mil + 18.22mil; 61.38mil + 18.31mil; 60.44mil + 18.4mil; 59.52mil + 18.46mil; 58.58mil + 18.49mil; 57.67mil + 18.52mil; 56.73mil + 18.49mil; 55.84mil + 18.46mil; 54.96mil + 18.4mil; 54.08mil + 18.31mil; 53.23mil + 18.22mil; 52.38mil + 18.1mil; 51.49mil + 17.67mil; 49.43mil + 17.21mil; 47.42mil + 16.64mil; 45.5mil + 16.03mil; 43.68mil + 15.3mil; 41.94mil + 14.51mil; 40.21mil + 14.14mil; 39.69mil + 13.75mil; 39.24mil + 13.29mil; 38.9mil + 12.74mil; 38.66mil + 12.13mil; 38.51mil + 11.46mil; 38.44mil + 17.97mil; 37.29mil + 19.01mil; 39.05mil + 19.98mil; 41.03mil + 20.8mil; 43.22mil + 21.53mil; 45.65mil + 22.14mil; 48.3mil + 22.66mil; 51.25mil + 22.75mil; 52.16mil + 22.87mil; 53.08mil + 22.93mil; 53.99mil + 22.99mil; 54.87mil + 23.02mil; 55.78mil + 23.05mil; 56.73mil + 23.02mil; 57.7mil + 22.99mil; 58.67mil + 22.93mil; 59.65mil + 22.84mil; 60.59mil + 22.75mil; 61.56mil + 22.63mil; 62.54mil + 22.14mil; 65.39mil + 21.53mil; 68.04mil + 20.83mil; 70.47mil + 20.04mil; 72.69mil + 19.13mil; 74.7mil + 18.1mil; 76.53mil + 17.27mil; 77.59mil + 16.36mil; 78.47mil + 15.36mil; 79.14mil + 14.2mil; 79.63mil + 12.92mil; 79.9mil + 11.53mil; 80.0mil + 10.16mil; 79.9mil + 8.88mil; 79.63mil + 7.75mil; 79.11mil + 6.72mil; 78.44mil + 5.78mil; 77.53mil + 4.95mil; 76.41mil + 4.04mil; 74.82mil + 3.22mil; 72.97mil + 2.43mil; 70.84mil + 1.73mil; 68.44mil + 1.06mil; 65.76mil + 0.48mil; 62.69mil + 0.33mil; 61.81mil + 0.21mil; 60.89mil + 0.12mil; 59.98mil + 0.03mil; 59.07mil + 0.0mil; 58.12mil + 0.0mil; 57.15mil + 0.0mil; 56.18mil + 0.03mil; 55.2mil + 0.12mil; 54.23mil + 0.21mil; 53.23mil + 0.33mil; 52.25mil + 0.51mil; 51.22mil + 1.06mil; 48.3mil + 1.67mil; 45.65mil + 2.34mil; 43.28mil + 3.07mil; 41.18mil + 3.83mil; 39.39mil + 4.71mil; 37.81mil + 5.53mil; 36.68mil + 6.48mil; 35.74mil + 7.57mil; 35.04mil + 8.76mil; 34.49mil + 10.1mil; 34.19mil + } + } + height = 63.33mil + } + ha:1 { + width=13mil; delta=12.0mil; + li:objects { + li:simplepoly.0 { + 9.24mil; 35.04mil + 9.58mil; 34.76mil + 9.91mil; 34.52mil + 10.28mil; 34.34mil + 10.64mil; 34.19mil + 11.01mil; 34.09mil + 11.4mil; 34.06mil + 12.07mil; 34.16mil + 12.65mil; 34.37mil + 13.11mil; 34.7mil + 13.41mil; 35.19mil + 13.59mil; 35.83mil + 13.68mil; 36.59mil + 13.68mil; 77.26mil + 13.62mil; 78.05mil + 13.44mil; 78.72mil + 13.14mil; 79.2mil + 12.71mil; 79.57mil + 12.16mil; 79.78mil + 11.49mil; 79.84mil + 10.79mil; 79.78mil + 10.25mil; 79.57mil + 9.79mil; 79.2mil + 9.49mil; 78.72mil + 9.3mil; 78.05mil + 9.24mil; 77.23mil + 9.24mil; 76.25mil + 9.24mil; 73.3mil + 9.24mil; 68.38mil + 9.24mil; 61.47mil + 9.24mil; 52.62mil + 9.24mil; 41.36mil + 3.95mil; 46.66mil + 3.68mil; 46.93mil + 3.4mil; 47.11mil + 3.13mil; 47.3mil + 2.86mil; 47.39mil + 2.58mil; 47.48mil + 2.31mil; 47.48mil + 1.58mil; 47.45mil + 1.0mil; 47.27mil + 0.57mil; 46.99mil + 0.24mil; 46.6mil + 0.06mil; 46.08mil + 0.0mil; 45.44mil + 0.0mil; 45.11mil + 0.09mil; 44.8mil + 0.21mil; 44.47mil + 0.36mil; 44.16mil + 0.57mil; 43.86mil + 0.88mil; 43.52mil + } + } + height = 63.33mil + } + ha:2 { + width=22mil; delta=12.0mil; + li:objects { + li:simplepoly.0 { + 2.37mil; 45.35mil + 1.64mil; 45.32mil + 1.03mil; 45.14mil + 0.57mil; 44.83mil + 0.24mil; 44.44mil + 0.06mil; 43.89mil + 0.0mil; 43.22mil + 0.0mil; 43.01mil + 0.03mil; 42.73mil + 0.12mil; 42.46mil + 0.21mil; 42.16mil + 0.36mil; 41.82mil + 0.54mil; 41.46mil + 1.18mil; 40.27mil + 1.85mil; 39.2mil + 2.58mil; 38.26mil + 3.31mil; 37.41mil + 4.1mil; 36.71mil + 4.95mil; 36.07mil + 5.99mil; 35.46mil + 7.02mil; 34.98mil + 8.12mil; 34.58mil + 9.21mil; 34.31mil + 10.31mil; 34.12mil + 11.49mil; 34.06mil + 13.32mil; 34.19mil + 15.02mil; 34.55mil + 16.6mil; 35.16mil + 18.03mil; 36.01mil + 19.34mil; 37.11mil + 20.56mil; 38.47mil + 21.29mil; 39.57mil + 21.87mil; 40.7mil + 22.35mil; 41.82mil + 22.69mil; 42.98mil + 22.87mil; 44.16mil + 22.96mil; 45.41mil + 22.9mil; 46.5mil + 22.72mil; 47.57mil + 22.45mil; 48.66mil + 22.05mil; 49.73mil + 21.56mil; 50.82mil + 20.95mil; 51.92mil + 6.2mil; 75.74mil + 20.62mil; 75.74mil + 21.29mil; 75.83mil + 21.87mil; 76.01mil + 22.32mil; 76.31mil + 22.63mil; 76.74mil + 22.81mil; 77.32mil + 22.9mil; 78.02mil + 22.81mil; 78.63mil + 22.6mil; 79.11mil + 22.26mil; 79.51mil + 21.78mil; 79.78mil + 21.17mil; 79.96mil + 20.41mil; 80.0mil + 2.73mil; 80.0mil + 1.88mil; 79.96mil + 1.21mil; 79.78mil + 0.7mil; 79.54mil + 0.33mil; 79.14mil + 0.09mil; 78.69mil + 0.03mil; 78.05mil + 0.03mil; 77.77mil + 0.06mil; 77.53mil + 0.12mil; 77.26mil + 0.18mil; 77.01mil + 0.27mil; 76.8mil + 0.42mil; 76.56mil + 16.79mil; 50.19mil + 17.27mil; 49.33mil + 17.7mil; 48.48mil + 18.03mil; 47.66mil + 18.25mil; 46.9mil + 18.4mil; 46.14mil + 18.46mil; 45.41mil + 18.4mil; 44.59mil + 18.25mil; 43.77mil + 18.03mil; 42.98mil + 17.7mil; 42.25mil + 17.3mil; 41.55mil + 16.79mil; 40.85mil + 16.06mil; 40.15mil + 15.27mil; 39.54mil + 14.41mil; 39.08mil + 13.47mil; 38.75mil + 12.47mil; 38.57mil + 11.34mil; 38.47mil + 9.97mil; 38.63mil + 8.7mil; 39.05mil + 7.51mil; 39.72mil + 6.41mil; 40.7mil + 5.44mil; 41.91mil + 4.5mil; 43.46mil + 4.13mil; 44.04mil + 3.8mil; 44.53mil + 3.46mil; 44.89mil + 3.1mil; 45.14mil + 2.73mil; 45.32mil + } + } + height = 63.33mil + } + ha:3 { + width=22mil; delta=12.0mil; + li:objects { + li:simplepoly.0 { + 2.95mil; 33.91mil + 3.19mil; 33.91mil + 3.98mil; 33.91mil + 5.29mil; 33.91mil + 7.11mil; 33.91mil + 9.46mil; 33.91mil + 12.47mil; 33.91mil + 13.81mil; 34.03mil + 15.11mil; 34.31mil + 16.36mil; 34.79mil + 17.58mil; 35.49mil + 18.73mil; 36.38mil + 19.89mil; 37.47mil + 20.8mil; 38.6mil + 21.56mil; 39.78mil + 22.14mil; 41.03mil + 22.57mil; 42.34mil + 22.84mil; 43.71mil + 22.93mil; 45.17mil + 22.78mil; 46.96mil + 22.38mil; 48.66mil + 21.75mil; 50.28mil + 20.83mil; 51.83mil + 19.65mil; 53.26mil + 18.19mil; 54.63mil + 19.59mil; 55.78mil + 20.74mil; 57.03mil + 21.62mil; 58.37mil + 22.26mil; 59.77mil + 22.66mil; 61.26mil + 22.81mil; 62.87mil + 22.81mil; 63.08mil + 22.81mil; 63.63mil + 22.81mil; 64.54mil + 22.81mil; 65.82mil + 22.81mil; 67.49mil + 22.81mil; 69.56mil + 22.69mil; 70.87mil + 22.41mil; 72.12mil + 21.96mil; 73.33mil + 21.32mil; 74.55mil + 20.47mil; 75.71mil + 19.43mil; 76.86mil + 18.37mil; 77.77mil + 17.24mil; 78.53mil + 16.0mil; 79.11mil + 14.66mil; 79.51mil + 13.23mil; 79.78mil + 11.65mil; 79.84mil + 11.37mil; 79.84mil + 10.64mil; 79.84mil + 9.4mil; 79.84mil + 7.66mil; 79.84mil + 5.41mil; 79.84mil + 2.58mil; 79.84mil + 1.79mil; 79.78mil + 1.12mil; 79.6mil + 0.64mil; 79.3mil + 0.27mil; 78.87mil + 0.06mil; 78.32mil + 0.0mil; 77.59mil + 0.06mil; 76.98mil + 0.27mil; 76.47mil + 0.67mil; 76.07mil + 1.18mil; 75.8mil + 1.85mil; 75.61mil + 2.73mil; 75.55mil + 2.95mil; 75.55mil + 3.62mil; 75.55mil + 4.71mil; 75.55mil + 6.26mil; 75.55mil + 8.24mil; 75.55mil + 10.76mil; 75.55mil + 11.92mil; 75.52mil + 13.02mil; 75.34mil + 14.02mil; 75.04mil + 14.96mil; 74.61mil + 15.78mil; 74.06mil + 16.57mil; 73.36mil + 17.15mil; 72.66mil + 17.64mil; 71.9mil + 18.03mil; 71.05mil + 18.31mil; 70.14mil + 18.49mil; 69.14mil + 18.55mil; 68.04mil + 18.55mil; 64.09mil + 18.49mil; 63.11mil + 18.34mil; 62.17mil + 18.1mil; 61.32mil + 17.73mil; 60.5mil + 17.27mil; 59.77mil + 16.73mil; 59.07mil + 15.97mil; 58.37mil + 15.21mil; 57.79mil + 14.41mil; 57.33mil + 13.62mil; 57.0mil + 12.83mil; 56.82mil + 11.98mil; 56.73mil + 7.36mil; 56.73mil + 6.57mil; 56.66mil + 5.96mil; 56.48mil + 5.44mil; 56.18mil + 5.11mil; 55.75mil + 4.89mil; 55.17mil + 4.83mil; 54.44mil + 4.89mil; 53.84mil + 5.11mil; 53.35mil + 5.44mil; 52.95mil + 5.93mil; 52.68mil + 6.57mil; 52.5mil + 7.39mil; 52.44mil + 11.49mil; 52.44mil + 12.41mil; 52.41mil + 13.29mil; 52.22mil + 14.11mil; 51.95mil + 14.9mil; 51.55mil + 15.66mil; 51.04mil + 16.39mil; 50.37mil + 17.03mil; 49.64mil + 17.58mil; 48.88mil + 18.0mil; 48.06mil + 18.28mil; 47.2mil + 18.46mil; 46.32mil + 18.55mil; 45.38mil + 18.49mil; 44.47mil + 18.34mil; 43.62mil + 18.1mil; 42.82mil + 17.76mil; 42.09mil + 17.33mil; 41.39mil + 16.82mil; 40.76mil + 16.03mil; 40.03mil + 15.21mil; 39.45mil + 14.41mil; 38.96mil + 13.59mil; 38.63mil + 12.77mil; 38.44mil + 11.95mil; 38.35mil + 2.95mil; 38.35mil + 2.07mil; 38.29mil + 1.37mil; 38.11mil + 0.82mil; 37.81mil + 0.42mil; 37.38mil + 0.18mil; 36.8mil + 0.12mil; 36.07mil + 0.18mil; 35.43mil + 0.42mil; 34.89mil + 0.79mil; 34.46mil + 1.34mil; 34.19mil + 2.03mil; 34.0mil + } + } + height = 63.33mil + } + ha:4 { + width=27mil; delta=12.0mil; + li:objects { + li:simplepoly.0 { + 9.18mil; 35.62mil + 9.37mil; 35.1mil + 9.64mil; 34.7mil + 9.97mil; 34.37mil + 10.37mil; 34.12mil + 10.86mil; 33.97mil + 11.43mil; 33.91mil + 12.04mil; 33.97mil + 12.59mil; 34.16mil + 12.99mil; 34.46mil + 13.29mil; 34.85mil + 13.44mil; 35.37mil + 13.53mil; 36.01mil + 13.5mil; 36.19mil + 13.5mil; 36.38mil + 13.47mil; 36.59mil + 13.41mil; 36.8mil + 13.38mil; 37.01mil + 13.32mil; 37.23mil + 5.02mil; 66.19mil + 16.12mil; 66.19mil + 16.12mil; 59.55mil + 16.18mil; 58.79mil + 16.36mil; 58.15mil + 16.67mil; 57.67mil + 17.09mil; 57.3mil + 17.64mil; 57.09mil + 18.34mil; 57.0mil + 18.98mil; 57.09mil + 19.53mil; 57.3mil + 19.95mil; 57.7mil + 20.22mil; 58.22mil + 20.41mil; 58.89mil + 20.5mil; 59.74mil + 20.5mil; 66.22mil + 20.62mil; 66.22mil + 20.99mil; 66.22mil + 21.65mil; 66.22mil + 22.54mil; 66.22mil + 23.69mil; 66.22mil + 25.18mil; 66.22mil + 25.85mil; 66.31mil + 26.4mil; 66.49mil + 26.83mil; 66.82mil + 27.13mil; 67.28mil + 27.31mil; 67.89mil + 27.4mil; 68.62mil + 27.31mil; 69.23mil + 27.13mil; 69.71mil + 26.83mil; 70.08mil + 26.37mil; 70.35mil + 25.79mil; 70.54mil + 25.09mil; 70.57mil + 20.5mil; 70.57mil + 20.5mil; 77.44mil + 20.41mil; 78.2mil + 20.22mil; 78.81mil + 19.92mil; 79.3mil + 19.49mil; 79.63mil + 18.95mil; 79.84mil + 18.25mil; 79.9mil + 17.58mil; 79.84mil + 17.06mil; 79.66mil + 16.64mil; 79.33mil + 16.33mil; 78.87mil + 16.18mil; 78.29mil + 16.12mil; 77.53mil + 16.12mil; 70.66mil + 2.16mil; 70.66mil + 1.49mil; 70.63mil + 0.94mil; 70.44mil + 0.51mil; 70.17mil + 0.24mil; 69.77mil + 0.06mil; 69.26mil + 0.0mil; 68.62mil + 0.0mil; 68.38mil + 0.03mil; 68.1mil + 0.09mil; 67.77mil + 0.18mil; 67.37mil + 0.27mil; 66.95mil + 0.42mil; 66.43mil + 0.64mil; 65.61mil + 1.37mil; 63.05mil + 2.58mil; 58.82mil + 4.26mil; 52.89mil + 6.41mil; 45.29mil + } + } + height = 63.33mil + } + ha:5 { + width=23mil; delta=12.0mil; + li:objects { + li:simplepoly.0 { + 0.0mil; 36.38mil + 0.06mil; 35.68mil + 0.27mil; 35.1mil + 0.64mil; 34.67mil + 1.16mil; 34.34mil + 1.79mil; 34.16mil + 2.65mil; 34.06mil + 3.13mil; 34.06mil + 4.59mil; 34.06mil + 7.06mil; 34.06mil + 10.49mil; 34.06mil + 14.9mil; 34.06mil + 20.53mil; 34.06mil + 21.29mil; 34.12mil + 21.9mil; 34.31mil + 22.42mil; 34.61mil + 22.75mil; 35.04mil + 22.96mil; 35.58mil + 23.06mil; 36.25mil + 22.96mil; 36.92mil + 22.78mil; 37.47mil + 22.45mil; 37.9mil + 21.99mil; 38.2mil + 21.38mil; 38.38mil + 20.65mil; 38.44mil + 4.47mil; 38.44mil + 4.47mil; 52.53mil + 11.22mil; 52.53mil + 13.08mil; 52.65mil + 14.84mil; 53.01mil + 16.49mil; 53.62mil + 17.98mil; 54.47mil + 19.35mil; 55.54mil + 20.65mil; 56.91mil + 21.35mil; 57.91mil + 21.96mil; 58.98mil + 22.42mil; 60.1mil + 22.75mil; 61.29mil + 22.93mil; 62.57mil + 23.03mil; 63.9mil + 23.03mil; 68.8mil + 22.93mil; 70.38mil + 22.66mil; 71.84mil + 22.2mil; 73.21mil + 21.57mil; 74.49mil + 20.74mil; 75.65mil + 19.71mil; 76.74mil + 18.52mil; 77.74mil + 17.31mil; 78.57mil + 16.03mil; 79.17mil + 14.72mil; 79.63mil + 13.38mil; 79.9mil + 11.98mil; 80.0mil + 2.49mil; 80.0mil + 1.76mil; 79.96mil + 1.19mil; 79.78mil + 0.73mil; 79.48mil + 0.39mil; 79.08mil + 0.21mil; 78.53mil + 0.15mil; 77.87mil + 0.21mil; 77.23mil + 0.43mil; 76.68mil + 0.76mil; 76.25mil + 1.25mil; 75.98mil + 1.89mil; 75.8mil + 2.71mil; 75.71mil + 11.16mil; 75.71mil + 12.38mil; 75.65mil + 13.5mil; 75.43mil + 14.51mil; 75.07mil + 15.45mil; 74.58mil + 16.27mil; 73.91mil + 17.03mil; 73.09mil + 17.49mil; 72.45mil + 17.85mil; 71.75mil + 18.16mil; 70.99mil + 18.37mil; 70.23mil + 18.49mil; 69.41mil + 18.55mil; 68.5mil + 18.55mil; 63.9mil + 18.49mil; 63.02mil + 18.34mil; 62.17mil + 18.1mil; 61.38mil + 17.76mil; 60.62mil + 17.31mil; 59.89mil + 16.76mil; 59.16mil + 16.03mil; 58.49mil + 15.18mil; 57.94mil + 14.23mil; 57.49mil + 13.14mil; 57.18mil + 11.95mil; 57.0mil + 10.62mil; 56.91mil + 2.22mil; 56.91mil + 1.52mil; 56.85mil + 0.97mil; 56.63mil + 0.55mil; 56.27mil + 0.24mil; 55.78mil + 0.06mil; 55.14mil + 0.0mil; 54.32mil + } + } + height = 63.33mil + } + ha:6 { + width=22mil; delta=12.0mil; + li:objects { + li:simplepoly.0 { + 4.68mil; 52.56mil + 4.87mil; 52.56mil + 5.41mil; 52.56mil + 6.33mil; 52.56mil + 7.63mil; 52.56mil + 9.28mil; 52.56mil + 11.41mil; 52.56mil + 13.05mil; 52.68mil + 14.6mil; 52.98mil + 16.06mil; 53.5mil + 17.43mil; 54.23mil + 18.68mil; 55.17mil + 19.92mil; 56.36mil + 20.81mil; 57.49mil + 21.57mil; 58.61mil + 22.14mil; 59.77mil + 22.54mil; 60.95mil + 22.81mil; 62.17mil + 22.9mil; 63.42mil + 22.9mil; 63.6mil + 22.9mil; 64.12mil + 22.9mil; 64.94mil + 22.9mil; 66.12mil + 22.9mil; 67.65mil + 22.9mil; 69.56mil + 22.78mil; 70.87mil + 22.48mil; 72.15mil + 21.96mil; 73.42mil + 21.23mil; 74.67mil + 20.29mil; 75.92mil + 19.1mil; 77.17mil + 18.07mil; 78.05mil + 16.88mil; 78.75mil + 15.57mil; 79.3mil + 14.14mil; 79.69mil + 12.59mil; 79.93mil + 10.86mil; 80.0mil + 9.46mil; 79.93mil + 8.12mil; 79.66mil + 6.81mil; 79.2mil + 5.6mil; 78.6mil + 4.41mil; 77.8mil + 3.25mil; 76.77mil + 2.25mil; 75.71mil + 1.43mil; 74.58mil + 0.82mil; 73.42mil + 0.36mil; 72.21mil + 0.09mil; 70.93mil + 0.0mil; 69.56mil + 0.0mil; 53.68mil + 0.12mil; 51.43mil + 0.58mil; 49.18mil + 1.31mil; 46.96mil + 2.31mil; 44.8mil + 3.65mil; 42.67mil + + 4.35mil; 69.11mil + 4.41mil; 69.99mil + 4.62mil; 70.84mil + 4.96mil; 71.66mil + 5.44mil; 72.48mil + 6.08mil; 73.27mil + 6.9mil; 74.06mil + 7.51mil; 74.58mil + 8.18mil; 74.98mil + 8.91mil; 75.31mil + 9.7mil; 75.52mil + 10.55mil; 75.68mil + 11.5mil; 75.71mil + 12.2mil; 75.68mil + 12.99mil; 75.49mil + 13.78mil; 75.19mil + 14.63mil; 74.76mil + 15.51mil; 74.25mil + 16.49mil; 73.55mil + 17.09mil; 73.03mil + 17.58mil; 72.39mil + 17.98mil; 71.66mil + 18.25mil; 70.87mil + 18.43mil; 69.99mil + 18.49mil; 68.98mil + 18.49mil; 64.36mil + 18.43mil; 63.39mil + 18.25mil; 62.47mil + 17.98mil; 61.56mil + 17.58mil; 60.74mil + 17.06mil; 59.92mil + 16.42mil; 59.13mil + 15.73mil; 58.49mil + 15.0mil; 57.97mil + 14.2mil; 57.55mil + 13.35mil; 57.24mil + 12.44mil; 57.09mil + 11.47mil; 57.0mil + 4.35mil; 57.0mil + 4.35mil; 69.11mil + 3.65mil; 42.67mil + 5.32mil; 40.51mil + 6.45mil; 39.33mil + 7.7mil; 38.2mil + 9.06mil; 37.17mil + 10.55mil; 36.19mil + 12.17mil; 35.34mil + 13.96mil; 34.55mil + 14.33mil; 34.43mil + 14.72mil; 34.31mil + 15.06mil; 34.22mil + 15.39mil; 34.12mil + 15.73mil; 34.09mil + 16.03mil; 34.06mil + 16.67mil; 34.16mil + 17.22mil; 34.34mil + 17.64mil; 34.67mil + 17.95mil; 35.13mil + 18.13mil; 35.71mil + 18.22mil; 36.44mil + 18.16mil; 36.89mil + 18.01mil; 37.29mil + 17.73mil; 37.65mil + 17.37mil; 37.99mil + 16.88mil; 38.26mil + 16.3mil; 38.51mil + 14.9mil; 39.05mil + 13.66mil; 39.63mil + 12.47mil; 40.24mil + 11.41mil; 40.94mil + 10.43mil; 41.67mil + 9.55mil; 42.46mil + 8.24mil; 43.92mil + 7.15mil; 45.44mil + 6.23mil; 47.05mil + 5.54mil; 48.79mil + 4.99mil; 50.58mil + } + } + height = 63.33mil + } + ha:7 { + width=22mil; delta=12.0mil; + li:objects { + li:simplepoly.0 { + 20.22mil; 34.06mil + 20.99mil; 34.12mil + 21.62mil; 34.31mil + 22.11mil; 34.61mil + 22.48mil; 35.01mil + 22.69mil; 35.55mil + 22.78mil; 36.19mil + 22.75mil; 36.5mil + 22.69mil; 36.89mil + 22.6mil; 37.41mil + 22.48mil; 38.08mil + 22.32mil; 38.84mil + 22.14mil; 39.75mil + 21.9mil; 40.82mil + 21.2mil; 43.95mil + 20.04mil; 49.18mil + 18.43mil; 56.51mil + 16.33mil; 65.94mil + 13.72mil; 77.87mil + 13.5mil; 78.53mil + 13.26mil; 79.05mil + 12.95mil; 79.48mil + 12.56mil; 79.78mil + 12.13mil; 79.93mil + 11.62mil; 80.0mil + 10.89mil; 79.96mil + 10.31mil; 79.78mil + 9.85mil; 79.51mil + 9.52mil; 79.11mil + 9.34mil; 78.63mil + 9.27mil; 77.99mil + 9.27mil; 77.87mil + 9.27mil; 77.71mil + 9.27mil; 77.59mil + 9.3mil; 77.44mil + 9.34mil; 77.29mil + 9.37mil; 77.14mil + 17.94mil; 38.54mil + 4.32mil; 38.54mil + 4.32mil; 38.63mil + 4.32mil; 38.81mil + 4.32mil; 39.11mil + 4.32mil; 39.54mil + 4.32mil; 40.12mil + 4.32mil; 40.82mil + 4.22mil; 41.49mil + 4.04mil; 42.03mil + 3.74mil; 42.46mil + 3.31mil; 42.73mil + 2.76mil; 42.92mil + 2.1mil; 42.98mil + 1.46mil; 42.92mil + 0.91mil; 42.73mil + 0.51mil; 42.43mil + 0.21mil; 42.0mil + 0.06mil; 41.46mil + 0.0mil; 40.73mil + 0.0mil; 40.6mil + 0.0mil; 40.24mil + 0.0mil; 39.6mil + 0.0mil; 38.72mil + 0.0mil; 37.56mil + 0.0mil; 36.1mil + 0.06mil; 35.49mil + 0.24mil; 34.98mil + 0.57mil; 34.58mil + 1.06mil; 34.31mil + 1.64mil; 34.12mil + 2.43mil; 34.06mil + 2.92mil; 34.06mil + 4.38mil; 34.06mil + 6.81mil; 34.06mil + 10.25mil; 34.06mil + 14.63mil; 34.06mil + } + } + height = 63.33mil + } + ha:8 { + width=22mil; delta=12.0mil; + li:objects { + li:simplepoly.2 { + 4.59mil; 54.6mil + 3.19mil; 53.35mil + 2.04mil; 51.95mil + 1.15mil; 50.4mil + 0.51mil; 48.66mil + 0.12mil; 46.81mil + 0.0mil; 44.71mil + 0.09mil; 43.1mil + 0.42mil; 41.58mil + 1.0mil; 40.18mil + 6.63mil; 40.24mil + 5.93mil; 41.03mil + 5.38mil; 41.82mil + 4.96mil; 42.61mil + 4.65mil; 43.43mil + 4.47mil; 44.28mil + 4.41mil; 45.14mil + 4.44mil; 45.96mil + 4.56mil; 46.75mil + 4.77mil; 47.54mil + 5.08mil; 48.3mil + 5.47mil; 49.06mil + 5.96mil; 49.82mil + 6.57mil; 50.61mil + 7.33mil; 51.25mil + 8.15mil; 51.74mil + 9.09mil; 52.1mil + 10.16mil; 52.31mil + 11.34mil; 52.38mil + 12.44mil; 52.35mil + 13.47mil; 52.16mil + 14.42mil; 51.86mil + 15.27mil; 51.46mil + 16.03mil; 50.92mil + 16.73mil; 50.25mil + 17.28mil; 49.52mil + 17.73mil; 48.76mil + 18.1mil; 47.96mil + 18.37mil; 47.14mil + 18.52mil; 46.26mil + 18.58mil; 45.35mil + 18.49mil; 44.47mil + 18.31mil; 43.58mil + 17.97mil; 42.73mil + 17.52mil; 41.91mil + 16.91mil; 41.15mil + 16.18mil; 40.36mil + 15.45mil; 39.78mil + 14.69mil; 39.33mil + 13.9mil; 38.93mil + 13.05mil; 38.69mil + 12.2mil; 38.51mil + 11.28mil; 38.44mil + 10.34mil; 38.51mil + 9.46mil; 38.66mil + 8.67mil; 38.9mil + 7.91mil; 39.24mil + 7.24mil; 39.69mil + 6.63mil; 40.24mil + 1.0mil; 40.18mil + 1.79mil; 38.9mil + 2.8mil; 37.68mil + 4.1mil; 36.56mil + 5.26mil; 35.77mil + 6.45mil; 35.1mil + 7.69mil; 34.58mil + 8.94mil; 34.22mil + 10.19mil; 34.0mil + 11.56mil; 33.91mil + 12.59mil; 33.97mil + 13.62mil; 34.09mil + 14.57mil; 34.28mil + 15.51mil; 34.58mil + 16.36mil; 34.92mil + 17.21mil; 35.37mil + 18.95mil; 36.65mil + 20.35mil; 38.05mil + 21.47mil; 39.63mil + 22.26mil; 41.36mil + 22.75mil; 43.25mil + 22.93mil; 45.35mil + 22.78mil; 47.3mil + 22.42mil; 49.06mil + 21.78mil; 50.67mil + 20.89mil; 52.16mil + 19.77mil; 53.5mil + 18.34mil; 54.69mil + 19.74mil; 55.96mil + 20.89mil; 57.33mil + 21.81mil; 58.79mil + 22.45mil; 60.35mil + 22.84mil; 61.99mil + 22.99mil; 63.78mil + 22.99mil; 68.98mil + 22.87mil; 70.44mil + 22.54mil; 71.84mil + 22.02mil; 73.21mil + 21.26mil; 74.52mil + 20.29mil; 75.8mil + 19.07mil; 77.07mil + 18.04mil; 77.93mil + 16.91mil; 78.63mil + 15.72mil; 79.17mil + 14.45mil; 79.57mil + 13.11mil; 79.81mil + 11.65mil; 79.87mil + 11.4mil; 56.88mil + 10.52mil; 56.94mil + 9.67mil; 57.12mil + 8.85mil; 57.36mil + 8.09mil; 57.76mil + 7.33mil; 58.22mil + 6.63mil; 58.82mil + 5.93mil; 59.55mil + 5.38mil; 60.31mil + 4.93mil; 61.11mil + 4.62mil; 61.93mil + 4.44mil; 62.78mil + 4.38mil; 63.69mil + 4.38mil; 69.23mil + 4.44mil; 69.99mil + 4.65mil; 70.75mil + 5.02mil; 71.54mil + 5.53mil; 72.33mil + 6.17mil; 73.15mil + 7.02mil; 73.97mil + 7.57mil; 74.43mil + 8.18mil; 74.82mil + 8.88mil; 75.1mil + 9.64mil; 75.31mil + 10.49mil; 75.43mil + 11.43mil; 75.46mil + 12.23mil; 75.43mil + 13.05mil; 75.25mil + 13.87mil; 74.98mil + 14.66mil; 74.61mil + 15.48mil; 74.12mil + 16.33mil; 73.49mil + 16.97mil; 72.88mil + 17.52mil; 72.18mil + 17.94mil; 71.39mil + 18.22mil; 70.5mil + 18.4mil; 69.56mil + 18.49mil; 68.5mil + 18.49mil; 63.96mil + 18.43mil; 63.11mil + 18.25mil; 62.26mil + 17.94mil; 61.44mil + 17.52mil; 60.59mil + 16.97mil; 59.77mil + 16.3mil; 58.89mil + 15.66mil; 58.28mil + 14.96mil; 57.79mil + 14.2mil; 57.39mil + 13.35mil; 57.12mil + 12.41mil; 56.94mil + 11.4mil; 56.88mil + 11.65mil; 79.87mil + 10.04mil; 79.81mil + 8.55mil; 79.6mil + 7.21mil; 79.23mil + 6.02mil; 78.75mil + 4.93mil; 78.11mil + 3.98mil; 77.29mil + 2.77mil; 75.98mil + 1.76mil; 74.67mil + 1.0mil; 73.33mil + 0.42mil; 71.96mil + 0.09mil; 70.63mil + 0.0mil; 69.17mil + 0.0mil; 63.54mil + 0.12mil; 61.93mil + 0.48mil; 60.38mil + 1.12mil; 58.85mil + 2.01mil; 57.39mil + 3.13mil; 56.0mil + } + } + height = 63.33mil + } + ha:9 { + width=22mil; delta=12.0mil; + li:objects { + li:simplepoly.0 { + 4.56mil; 77.74mil + 4.59mil; 77.26mil + 4.77mil; 76.83mil + 5.08mil; 76.44mil + 5.5mil; 76.07mil + 6.02mil; 75.77mil + 6.72mil; 75.49mil + 7.7mil; 75.16mil + 8.61mil; 74.76mil + 9.52mil; 74.34mil + 10.34mil; 73.85mil + 11.16mil; 73.3mil + 11.95mil; 72.69mil + 13.6mil; 71.17mil + 15.0mil; 69.5mil + 16.15mil; 67.74mil + 17.06mil; 65.82mil + 17.73mil; 63.78mil + 18.19mil; 61.56mil + 10.8mil; 61.56mil + 9.52mil; 61.5mil + 8.3mil; 61.29mil + 7.12mil; 60.89mil + 5.99mil; 60.38mil + 4.87mil; 59.71mil + 3.8mil; 58.85mil + 2.62mil; 57.73mil + 1.67mil; 56.54mil + 0.94mil; 55.27mil + 0.43mil; 53.96mil + 0.09mil; 52.59mil + 0.0mil; 51.1mil + 0.0mil; 50.95mil + 0.0mil; 50.4mil + 0.0mil; 49.52mil + 0.0mil; 48.3mil + 0.0mil; 46.72mil + 0.0mil; 44.68mil + 0.12mil; 43.04mil + 0.52mil; 41.49mil + 18.31mil; 45.81mil + 18.25mil; 44.83mil + 18.1mil; 43.89mil + 17.82mil; 43.04mil + 17.49mil; 42.22mil + 17.03mil; 41.49mil + 16.46mil; 40.76mil + 15.73mil; 40.09mil + 14.93mil; 39.54mil + 14.11mil; 39.11mil + 13.23mil; 38.81mil + 12.32mil; 38.63mil + 11.31mil; 38.54mil + 10.43mil; 38.6mil + 9.61mil; 38.75mil + 8.79mil; 39.02mil + 8.0mil; 39.36mil + 7.24mil; 39.81mil + 6.51mil; 40.39mil + 5.84mil; 41.06mil + 5.29mil; 41.79mil + 4.87mil; 42.61mil + 4.56mil; 43.46mil + 4.38mil; 44.41mil + 4.32mil; 45.44mil + 4.32mil; 50.37mil + 4.38mil; 51.37mil + 4.59mil; 52.31mil + 4.93mil; 53.2mil + 5.41mil; 54.02mil + 6.02mil; 54.78mil + 6.81mil; 55.51mil + 7.51mil; 56.03mil + 8.3mil; 56.42mil + 9.22mil; 56.76mil + 10.22mil; 56.97mil + 11.31mil; 57.12mil + 12.56mil; 57.15mil + 18.31mil; 57.15mil + 18.31mil; 56.85mil + 18.31mil; 55.93mil + 18.31mil; 54.35mil + 18.31mil; 52.19mil + 18.31mil; 49.36mil + 18.31mil; 45.81mil + 0.52mil; 41.49mil + 1.22mil; 40.0mil + 2.16mil; 38.6mil + 3.38mil; 37.29mil + 4.96mil; 35.98mil + 5.84mil; 35.4mil + 6.84mil; 34.95mil + 7.91mil; 34.55mil + 9.06mil; 34.31mil + 10.31mil; 34.12mil + 11.68mil; 34.06mil + 13.08mil; 34.19mil + 14.45mil; 34.46mil + 15.79mil; 34.95mil + 17.09mil; 35.62mil + 18.34mil; 36.47mil + 19.59mil; 37.53mil + 20.56mil; 38.63mil + 21.35mil; 39.81mil + 21.99mil; 41.09mil + 22.42mil; 42.46mil + 22.69mil; 43.92mil + 22.81mil; 45.53mil + 22.81mil; 45.93mil + 22.81mil; 47.08mil + 22.81mil; 49.0mil + 22.81mil; 51.71mil + 22.81mil; 55.14mil + 22.81mil; 59.52mil + 22.75mil; 61.01mil + 22.63mil; 62.41mil + 22.42mil; 63.78mil + 22.11mil; 65.06mil + 21.72mil; 66.31mil + 21.23mil; 67.52mil + 20.35mil; 69.32mil + 19.41mil; 70.96mil + 18.43mil; 72.42mil + 17.43mil; 73.73mil + 16.36mil; 74.85mil + 15.24mil; 75.83mil + 13.47mil; 77.11mil + 11.86mil; 78.14mil + 10.4mil; 78.96mil + 9.03mil; 79.54mil + 7.85mil; 79.87mil + 6.75mil; 80.0mil + 6.08mil; 79.93mil + 5.54mil; 79.75mil + 5.11mil; 79.45mil + 4.81mil; 79.02mil + 4.62mil; 78.47mil + } + } + height = 63.33mil + } + ha:\: { + width=4mil; delta=12.0mil; + li:objects { + li:simplepoly.0 { + 0.0mil; 71.63mil + 0.03mil; 70.63mil + 0.21mil; 69.81mil + 0.51mil; 69.14mil + 0.91mil; 68.68mil + 1.46mil; 68.41mil + 2.13mil; 68.28mil + 2.86mil; 68.41mil + 3.5mil; 68.68mil + 3.98mil; 69.14mil + 4.32mil; 69.81mil + 4.53mil; 70.63mil + 4.62mil; 71.69mil + 4.53mil; 72.69mil + 4.35mil; 73.49mil + 4.01mil; 74.12mil + 3.56mil; 74.55mil + 2.98mil; 74.82mil + 2.25mil; 74.92mil + 1.55mil; 74.85mil + 1.0mil; 74.58mil + 0.55mil; 74.12mil + 0.24mil; 73.49mil + 0.06mil; 72.66mil + } + li:simplepoly.1 { + 0.0mil; 53.26mil + 0.06mil; 52.25mil + 0.24mil; 51.43mil + 0.55mil; 50.76mil + 0.97mil; 50.31mil + 1.52mil; 50.03mil + 2.22mil; 49.91mil + 2.95mil; 50.03mil + 3.59mil; 50.31mil + 4.07mil; 50.76mil + 4.41mil; 51.43mil + 4.62mil; 52.25mil + 4.71mil; 53.32mil + 4.62mil; 54.29mil + 4.44mil; 55.11mil + 4.1mil; 55.72mil + 3.65mil; 56.18mil + 3.07mil; 56.42mil + 2.34mil; 56.51mil + 1.61mil; 56.45mil + 1.03mil; 56.18mil + 0.58mil; 55.72mil + 0.24mil; 55.08mil + 0.06mil; 54.29mil + } + } + height = 63.33mil + } + ha:; { + width=6mil; delta=12.0mil; + li:objects { + li:simplepoly.0 { + 2.19mil; 72.0mil + 2.37mil; 71.39mil + 2.64mil; 70.87mil + 2.95mil; 70.47mil + 3.34mil; 70.2mil + 3.77mil; 70.02mil + 4.32mil; 69.96mil + 4.99mil; 70.02mil + 5.56mil; 70.2mil + 6.02mil; 70.47mil + 6.32mil; 70.84mil + 6.51mil; 71.33mil + 6.6mil; 71.93mil + 6.57mil; 72.18mil + 6.57mil; 72.42mil + 6.54mil; 72.66mil + 6.51mil; 72.91mil + 6.45mil; 73.15mil + 6.42mil; 73.39mil + 4.44mil; 81.39mil + 4.2mil; 82.03mil + 3.92mil; 82.55mil + 3.59mil; 82.98mil + 3.19mil; 83.28mil + 2.74mil; 83.43mil + 2.19mil; 83.52mil + 1.52mil; 83.46mil + 0.97mil; 83.28mil + 0.55mil; 83.01mil + 0.24mil; 82.61mil + 0.06mil; 82.09mil + 0.0mil; 81.46mil + 0.0mil; 81.21mil + 0.03mil; 80.94mil + 0.06mil; 80.63mil + 0.12mil; 80.3mil + 0.18mil; 79.96mil + 0.3mil; 79.54mil + } + li:simplepoly.1 { + 2.1mil; 54.84mil + 2.13mil; 53.84mil + 2.31mil; 53.01mil + 2.61mil; 52.35mil + 3.04mil; 51.89mil + 3.56mil; 51.62mil + 4.26mil; 51.49mil + 4.99mil; 51.62mil + 5.62mil; 51.89mil + 6.11mil; 52.35mil + 6.45mil; 53.01mil + 6.66mil; 53.84mil + 6.75mil; 54.9mil + 6.66mil; 55.9mil + 6.48mil; 56.69mil + 6.14mil; 57.33mil + 5.69mil; 57.76mil + 5.11mil; 58.03mil + 4.38mil; 58.12mil + 3.68mil; 58.06mil + 3.1mil; 57.79mil + 2.64mil; 57.33mil + 2.34mil; 56.69mil + 2.16mil; 55.87mil + } + } + height = 63.33mil + } + ha:< { + width=22mil; delta=12.0mil; + li:objects { + li:simplepoly.0 { + 21.05mil; 66.55mil + 21.59mil; 66.82mil + 22.05mil; 67.1mil + 22.38mil; 67.43mil + 22.66mil; 67.77mil + 22.81mil; 68.16mil + 22.87mil; 68.59mil + 22.81mil; 69.32mil + 22.63mil; 69.9mil + 22.35mil; 70.35mil + 21.99mil; 70.69mil + 21.5mil; 70.87mil + 20.89mil; 70.93mil + 20.65mil; 70.93mil + 20.41mil; 70.93mil + 20.19mil; 70.9mil + 19.98mil; 70.87mil + 19.77mil; 70.81mil + 19.59mil; 70.75mil + 2.1mil; 64.15mil + 1.46mil; 63.87mil + 0.91mil; 63.57mil + 0.51mil; 63.2mil + 0.21mil; 62.78mil + 0.06mil; 62.35mil + 0.0mil; 61.84mil + 0.06mil; 61.35mil + 0.24mil; 60.86mil + 0.57mil; 60.44mil + 1.0mil; 60.04mil + 1.58mil; 59.68mil + 2.34mil; 59.34mil + 19.37mil; 52.95mil + 19.59mil; 52.89mil + 19.83mil; 52.83mil + 20.07mil; 52.77mil + 20.32mil; 52.74mil + 20.56mil; 52.71mil + 20.8mil; 52.68mil + 21.41mil; 52.77mil + 21.9mil; 52.95mil + 22.29mil; 53.29mil + 22.57mil; 53.74mil + 22.75mil; 54.35mil + 22.81mil; 55.08mil + 22.75mil; 55.54mil + 22.57mil; 55.93mil + 22.29mil; 56.3mil + 21.9mil; 56.63mil + 21.38mil; 56.94mil + 20.74mil; 57.21mil + 8.57mil; 61.87mil + } + } + height = 63.33mil + } + ha:\= { + width=22mil; delta=12.0mil; + li:objects { + li:simplepoly.0 { + 20.47mil; 66.55mil + 21.14mil; 66.61mil + 21.72mil; 66.79mil + 22.17mil; 67.1mil + 22.48mil; 67.52mil + 22.66mil; 68.07mil + 22.75mil; 68.74mil + 22.69mil; 69.44mil + 22.51mil; 69.99mil + 22.2mil; 70.44mil + 21.81mil; 70.75mil + 21.26mil; 70.93mil + 20.62mil; 70.99mil + 20.1mil; 70.99mil + 18.58mil; 70.99mil + 16.03mil; 70.99mil + 12.5mil; 70.99mil + 7.94mil; 70.99mil + 2.16mil; 70.99mil + 1.49mil; 70.93mil + 0.94mil; 70.75mil + 0.51mil; 70.44mil + 0.24mil; 70.02mil + 0.06mil; 69.47mil + 0.0mil; 68.77mil + 0.03mil; 68.1mil + 0.21mil; 67.55mil + 0.51mil; 67.13mil + 0.94mil; 66.82mil + 1.49mil; 66.64mil + 2.19mil; 66.55mil + } + li:simplepoly.1 { + 20.53mil; 52.68mil + 21.2mil; 52.77mil + 21.78mil; 52.95mil + 22.23mil; 53.26mil + 22.54mil; 53.68mil + 22.72mil; 54.23mil + 22.81mil; 54.9mil + 22.75mil; 55.6mil + 22.57mil; 56.15mil + 22.26mil; 56.6mil + 21.87mil; 56.91mil + 21.32mil; 57.09mil + 20.68mil; 57.15mil + 2.22mil; 57.15mil + 1.55mil; 57.09mil + 1.0mil; 56.91mil + 0.57mil; 56.6mil + 0.27mil; 56.18mil + 0.09mil; 55.63mil + 0.03mil; 54.93mil + 0.09mil; 54.26mil + 0.27mil; 53.71mil + 0.57mil; 53.26mil + 1.0mil; 52.95mil + 1.55mil; 52.77mil + 2.25mil; 52.68mil + } + } + height = 63.33mil + } + ha:> { + width=22mil; delta=12.0mil; + li:objects { + li:simplepoly.0 { + 1.82mil; 66.58mil + 14.29mil; 61.9mil + 2.13mil; 57.24mil + 1.49mil; 57.0mil + 0.97mil; 56.69mil + 0.57mil; 56.36mil + 0.27mil; 56.0mil + 0.09mil; 55.57mil + 0.06mil; 55.11mil + 0.09mil; 54.38mil + 0.27mil; 53.81mil + 0.54mil; 53.32mil + 0.94mil; 52.98mil + 1.43mil; 52.8mil + 2.07mil; 52.71mil + 2.28mil; 52.74mil + 2.52mil; 52.74mil + 2.76mil; 52.8mil + 2.98mil; 52.83mil + 3.22mil; 52.92mil + 3.49mil; 52.98mil + 20.53mil; 59.37mil + 21.23mil; 59.71mil + 21.81mil; 60.04mil + 22.26mil; 60.44mil + 22.6mil; 60.89mil + 22.78mil; 61.35mil + 22.87mil; 61.87mil + 22.81mil; 62.35mil + 22.63mil; 62.81mil + 22.32mil; 63.2mil + 21.93mil; 63.57mil + 21.41mil; 63.9mil + 20.77mil; 64.18mil + 3.28mil; 70.78mil + 3.07mil; 70.84mil + 2.86mil; 70.9mil + 2.64mil; 70.93mil + 2.43mil; 70.96mil + 2.22mil; 70.96mil + 1.97mil; 70.96mil + 1.37mil; 70.9mil + 0.88mil; 70.72mil + 0.48mil; 70.38mil + 0.21mil; 69.96mil + 0.03mil; 69.38mil + 0.0mil; 68.62mil + 0.03mil; 68.19mil + 0.18mil; 67.83mil + 0.42mil; 67.46mil + 0.79mil; 67.13mil + 1.24mil; 66.85mil + } + } + height = 63.33mil + } + ha:? { + width=22mil; delta=12.0mil; + li:objects { + li:simplepoly.0 { + 1.09mil; 36.71mil + 2.98mil; 35.92mil + 4.95mil; 35.25mil + 6.99mil; 34.73mil + 9.12mil; 34.37mil + 11.31mil; 34.16mil + 13.68mil; 34.06mil + 15.02mil; 34.16mil + 16.3mil; 34.43mil + 17.49mil; 34.85mil + 18.58mil; 35.46mil + 19.62mil; 36.25mil + 20.59mil; 37.23mil + 21.26mil; 38.14mil + 21.81mil; 39.08mil + 22.26mil; 40.06mil + 22.57mil; 41.09mil + 22.75mil; 42.16mil + 22.84mil; 43.31mil + 22.75mil; 44.53mil + 22.54mil; 45.68mil + 22.17mil; 46.75mil + 21.68mil; 47.75mil + 21.02mil; 48.7mil + 20.22mil; 49.58mil + 14.72mil; 54.87mil + 14.32mil; 55.3mil + 14.02mil; 55.72mil + 13.81mil; 56.18mil + 13.62mil; 56.69mil + 13.53mil; 57.24mil + 13.5mil; 57.82mil + 13.5mil; 63.6mil + 13.44mil; 64.39mil + 13.26mil; 65.0mil + 12.95mil; 65.52mil + 12.53mil; 65.85mil + 11.98mil; 66.06mil + 11.31mil; 66.12mil + 10.64mil; 66.06mil + 10.1mil; 65.88mil + 9.67mil; 65.55mil + 9.37mil; 65.09mil + 9.18mil; 64.51mil + 9.12mil; 63.75mil + 9.12mil; 57.55mil + 9.15mil; 56.51mil + 9.34mil; 55.51mil + 9.64mil; 54.6mil + 10.07mil; 53.74mil + 10.58mil; 52.98mil + 11.28mil; 52.22mil + 17.33mil; 46.26mil + 17.61mil; 45.93mil + 17.85mil; 45.56mil + 18.03mil; 45.14mil + 18.19mil; 44.71mil + 18.28mil; 44.22mil + 18.31mil; 43.68mil + 18.16mil; 42.12mil + 17.7mil; 40.82mil + 16.94mil; 39.81mil + 15.87mil; 39.11mil + 14.51mil; 38.66mil + 12.77mil; 38.51mil + 11.53mil; 38.57mil + 10.19mil; 38.72mil + 8.73mil; 38.99mil + 7.21mil; 39.33mil + 5.56mil; 39.78mil + 3.77mil; 40.36mil + 3.43mil; 40.48mil + 3.1mil; 40.57mil + 2.83mil; 40.63mil + 2.58mil; 40.7mil + 2.34mil; 40.73mil + 2.13mil; 40.73mil + 2.1mil; 40.73mil + 2.1mil; 40.73mil + 2.1mil; 40.73mil + 2.1mil; 40.73mil + 2.07mil; 40.73mil + 2.07mil; 40.73mil + 1.43mil; 40.66mil + 0.91mil; 40.48mil + 0.51mil; 40.18mil + 0.21mil; 39.75mil + 0.03mil; 39.2mil + 0.0mil; 38.51mil + 0.0mil; 38.11mil + 0.09mil; 37.74mil + 0.24mil; 37.44mil + 0.45mil; 37.17mil + 0.73mil; 36.92mil + } + li:simplepoly.1 { + 9.12mil; 76.62mil + 9.15mil; 75.61mil + 9.34mil; 74.79mil + 9.61mil; 74.12mil + 10.0mil; 73.67mil + 10.49mil; 73.39mil + 11.13mil; 73.27mil + 11.83mil; 73.39mil + 12.41mil; 73.67mil + 12.83mil; 74.12mil + 13.17mil; 74.76mil + 13.35mil; 75.61mil + 13.44mil; 76.65mil + 13.38mil; 77.68mil + 13.2mil; 78.5mil + 12.89mil; 79.17mil + 12.5mil; 79.63mil + 11.95mil; 79.9mil + 11.31mil; 80.0mil + 10.64mil; 79.9mil + 10.1mil; 79.63mil + 9.67mil; 79.17mil + 9.37mil; 78.53mil + 9.18mil; 77.68mil + } + } + height = 63.33mil + } + ha:@ { + width=41mil; delta=12.0mil; + li:objects { + li:simplepoly.1 { + 17.28mil; 86.69mil + 15.45mil; 86.57mil + 13.62mil; 86.23mil + 11.86mil; 85.65mil + 10.1mil; 84.86mil + 8.36mil; 83.86mil + 6.63mil; 82.58mil + 4.59mil; 80.66mil + 2.95mil; 78.47mil + 1.67mil; 75.98mil + 0.73mil; 73.21mil + 0.18mil; 70.11mil + 0.0mil; 66.61mil + 0.0mil; 66.12mil + 0.0mil; 64.6mil + 0.0mil; 62.08mil + 0.0mil; 58.55mil + 0.0mil; 54.02mil + 0.0mil; 48.24mil + 0.18mil; 44.86mil + 0.82mil; 41.73mil + 1.88mil; 38.84mil + 3.34mil; 36.22mil + 5.26mil; 33.82mil + 7.66mil; 31.6mil + 9.7mil; 30.14mil + 11.83mil; 28.95mil + 14.02mil; 28.01mil + 16.3mil; 27.34mil + 18.64mil; 26.95mil + 21.17mil; 26.79mil + 23.42mil; 26.95mil + 25.61mil; 27.34mil + 27.77mil; 28.04mil + 29.87mil; 28.98mil + 31.94mil; 30.2mil + 34.0mil; 31.72mil + 36.23mil; 33.88mil + 38.05mil; 36.28mil + 39.48mil; 38.9mil + 40.51mil; 41.79mil + 41.12mil; 44.92mil + 41.37mil; 48.39mil + 41.37mil; 48.82mil + 41.37mil; 50.09mil + 41.37mil; 52.16mil + 41.37mil; 55.11mil + 41.37mil; 58.89mil + 41.37mil; 63.63mil + 41.31mil; 65.03mil + 41.18mil; 66.28mil + 40.94mil; 67.4mil + 40.64mil; 68.38mil + 40.21mil; 69.2mil + 39.72mil; 69.9mil + 38.78mil; 70.84mil + 37.84mil; 71.6mil + 36.8mil; 72.18mil + 35.74mil; 72.6mil + 34.61mil; 72.88mil + 33.43mil; 72.94mil + 32.33mil; 72.88mil + 31.3mil; 72.63mil + 30.29mil; 72.24mil + 29.32mil; 71.66mil + 28.38mil; 70.96mil + 27.43mil; 70.02mil + 26.43mil; 70.93mil + 25.4mil; 71.66mil + 24.27mil; 72.21mil + 23.12mil; 72.63mil + 21.87mil; 72.88mil + 20.56mil; 72.94mil + 19.83mil; 72.91mil + 19.1mil; 72.82mil + 18.34mil; 72.63mil + 17.61mil; 72.39mil + 16.88mil; 72.09mil + 16.12mil; 71.66mil + 14.75mil; 70.75mil + 13.62mil; 69.62mil + 12.77mil; 68.34mil + 12.13mil; 66.88mil + 11.77mil; 65.24mil + 11.65mil; 63.36mil + 11.65mil; 50.34mil + 11.71mil; 48.94mil + 11.92mil; 47.63mil + 12.29mil; 46.41mil + 12.8mil; 45.29mil + 13.47mil; 44.28mil + 14.32mil; 43.31mil + 15.27mil; 42.52mil + 16.33mil; 41.88mil + 17.52mil; 41.36mil + 18.83mil; 41.0mil + 20.26mil; 40.79mil + 21.87mil; 40.7mil + 25.4mil; 45.17mil + 25.27mil; 45.17mil + 24.94mil; 45.17mil + 24.39mil; 45.17mil + 23.6mil; 45.17mil + 22.6mil; 45.17mil + 21.35mil; 45.17mil + 19.71mil; 45.35mil + 18.37mil; 45.81mil + 17.31mil; 46.63mil + 16.58mil; 47.72mil + 16.12mil; 49.18mil + 15.97mil; 50.98mil + 15.97mil; 51.31mil + 15.97mil; 52.22mil + 15.97mil; 53.74mil + 15.97mil; 55.87mil + 15.97mil; 58.64mil + 15.97mil; 62.11mil + 16.09mil; 64.06mil + 16.48mil; 65.64mil + 17.15mil; 66.85mil + 18.1mil; 67.74mil + 19.28mil; 68.25mil + 20.83mil; 68.44mil + 22.2mil; 68.28mil + 23.33mil; 67.77mil + 24.24mil; 66.95mil + 24.85mil; 65.76mil + 25.24mil; 64.24mil + 25.4mil; 62.29mil + 25.4mil; 61.84mil + 25.4mil; 60.44mil + 25.4mil; 58.06mil + 25.4mil; 54.78mil + 25.4mil; 50.55mil + 25.4mil; 45.17mil + 21.87mil; 40.7mil + 27.01mil; 40.7mil + 27.83mil; 40.79mil + 28.5mil; 41.0mil + 29.05mil; 41.36mil + 29.41mil; 41.85mil + 29.66mil; 42.52mil + 29.75mil; 43.31mil + 29.75mil; 62.69mil + 29.84mil; 64.45mil + 30.14mil; 65.88mil + 30.63mil; 67.01mil + 31.33mil; 67.8mil + 32.21mil; 68.28mil + 33.37mil; 68.44mil + 34.43mil; 68.34mil + 35.31mil; 67.98mil + 35.98mil; 67.37mil + 36.47mil; 66.55mil + 36.77mil; 65.49mil + 36.89mil; 64.12mil + 36.89mil; 47.42mil + 36.74mil; 45.14mil + 36.29mil; 42.95mil + 35.56mil; 40.91mil + 34.55mil; 38.99mil + 33.21mil; 37.2mil + 31.57mil; 35.46mil + 29.99mil; 34.22mil + 28.35mil; 33.15mil + 26.64mil; 32.33mil + 24.88mil; 31.75mil + 23.05mil; 31.42mil + 21.11mil; 31.27mil + 19.04mil; 31.39mil + 17.09mil; 31.72mil + 15.21mil; 32.3mil + 13.41mil; 33.09mil + 11.68mil; 34.12mil + 9.97mil; 35.4mil + 8.27mil; 37.04mil + 6.9mil; 38.84mil + 5.84mil; 40.82mil + 5.08mil; 42.92mil + 4.62mil; 45.2mil + 4.47mil; 47.72mil + 4.47mil; 67.04mil + 4.59mil; 69.32mil + 4.99mil; 71.48mil + 5.62mil; 73.52mil + 6.54mil; 75.43mil + 7.72mil; 77.23mil + 9.21mil; 78.93mil + 10.34mil; 79.93mil + 11.59mil; 80.73mil + 12.99mil; 81.36mil + 14.51mil; 81.82mil + 16.15mil; 82.09mil + 18.01mil; 82.22mil + 18.8mil; 82.28mil + 19.43mil; 82.46mil + 19.95mil; 82.79mil + 20.32mil; 83.25mil + 20.53mil; 83.86mil + 20.62mil; 84.62mil + 20.5mil; 85.23mil + 20.23mil; 85.74mil + 19.77mil; 86.14mil + 19.13mil; 86.44mil + 18.31mil; 86.63mil + } + } + height = 63.33mil + } + ha:A { + width=32mil; delta=12.0mil; + li:objects { + li:simplepoly.0 { + 14.11mil; 35.74mil + 14.29mil; 35.25mil + 14.57mil; 34.82mil + 14.9mil; 34.49mil + 15.27mil; 34.28mil + 15.72mil; 34.12mil + 16.24mil; 34.06mil + 16.7mil; 34.12mil + 17.12mil; 34.28mil + 17.49mil; 34.49mil + 17.82mil; 34.82mil + 18.07mil; 35.22mil + 16.12mil; 43.31mil + 9.12mil; 64.09mil + 23.14mil; 64.09mil + 16.12mil; 43.31mil + 18.07mil; 35.22mil + 18.31mil; 35.74mil + 31.91mil; 76.62mil + 31.97mil; 76.89mil + 32.03mil; 77.14mil + 32.09mil; 77.38mil + 32.12mil; 77.59mil + 32.15mil; 77.77mil + 32.18mil; 77.96mil + 32.12mil; 78.53mil + 31.94mil; 78.99mil + 31.63mil; 79.39mil + 31.21mil; 79.66mil + 30.66mil; 79.87mil + 29.99mil; 80.0mil + 29.47mil; 79.96mil + 29.02mil; 79.78mil + 28.59mil; 79.51mil + 28.25mil; 79.11mil + 27.95mil; 78.63mil + 27.71mil; 77.99mil + 27.62mil; 77.74mil + 27.34mil; 76.95mil + 26.92mil; 75.61mil + 26.34mil; 73.79mil + 25.55mil; 71.39mil + 24.6mil; 68.38mil + 7.75mil; 68.38mil + 4.44mil; 78.23mil + 4.19mil; 78.81mil + 3.92mil; 79.26mil + 3.59mil; 79.63mil + 3.22mil; 79.9mil + 2.83mil; 80.03mil + 2.37mil; 80.09mil + 1.64mil; 80.0mil + 1.03mil; 79.84mil + 0.57mil; 79.54mil + 0.24mil; 79.11mil + 0.06mil; 78.57mil + 0.0mil; 77.87mil + 0.0mil; 77.74mil + 0.06mil; 77.5mil + 0.15mil; 77.17mil + 0.27mil; 76.74mil + 0.45mil; 76.22mil + 0.67mil; 75.58mil + } + } + height = 63.33mil + } + ha:B { + width=27mil; delta=12.0mil; + li:objects { + li:simplepoly.0 { + 27.74mil; 66.0mil + 27.62mil; 68.16mil + 27.25mil; 70.11mil + 26.67mil; 71.93mil + 25.85mil; 73.55mil + 24.82mil; 75.01mil + 23.51mil; 76.34mil + 22.11mil; 77.47mil + 20.74mil; 78.38mil + 19.4mil; 79.08mil + 18.07mil; 79.6mil + 16.79mil; 79.9mil + 15.48mil; 80.0mil + 4.68mil; 57.24mil + 4.68mil; 75.77mil + 14.17mil; 75.77mil + 15.48mil; 75.71mil + 16.73mil; 75.46mil + 17.85mil; 75.07mil + 18.92mil; 74.52mil + 19.89mil; 73.82mil + 20.8mil; 72.91mil + 21.53mil; 71.96mil + 22.17mil; 70.96mil + 22.66mil; 69.93mil + 22.99mil; 68.86mil + 23.21mil; 67.77mil + 23.3mil; 66.58mil + 23.21mil; 65.46mil + 23.02mil; 64.36mil + 22.69mil; 63.27mil + 22.26mil; 62.23mil + 21.69mil; 61.2mil + 20.96mil; 60.16mil + 20.1mil; 59.28mil + 19.19mil; 58.55mil + 18.13mil; 58.0mil + 16.97mil; 57.58mil + 15.69mil; 57.33mil + 14.26mil; 57.24mil + 4.68mil; 57.24mil + 15.48mil; 80.0mil + 2.13mil; 80.0mil + 1.46mil; 79.93mil + 0.94mil; 79.72mil + 0.51mil; 79.33mil + 0.21mil; 78.81mil + 0.06mil; 78.11mil + 0.0mil; 77.23mil + 0.0mil; 36.92mil + 0.06mil; 36.07mil + 0.3mil; 35.37mil + 0.67mil; 34.79mil + 1.21mil; 34.4mil + 1.91mil; 34.16mil + 2.83mil; 34.06mil + 4.68mil; 38.6mil + 4.68mil; 52.5mil + 13.96mil; 52.5mil + 15.05mil; 52.47mil + 16.06mil; 52.31mil + 17.0mil; 52.04mil + 17.79mil; 51.68mil + 18.52mil; 51.22mil + 19.19mil; 50.61mil + 19.71mil; 49.97mil + 20.13mil; 49.27mil + 20.47mil; 48.51mil + 20.71mil; 47.69mil + 20.89mil; 46.84mil + 20.96mil; 45.87mil + 20.89mil; 44.95mil + 20.74mil; 44.07mil + 20.47mil; 43.19mil + 20.13mil; 42.4mil + 19.68mil; 41.61mil + 19.1mil; 40.82mil + 18.43mil; 40.18mil + 17.67mil; 39.63mil + 16.85mil; 39.17mil + 15.94mil; 38.87mil + 14.93mil; 38.69mil + 13.84mil; 38.6mil + 4.68mil; 38.6mil + 2.83mil; 34.06mil + 12.32mil; 34.06mil + 14.14mil; 34.16mil + 15.78mil; 34.34mil + 17.28mil; 34.64mil + 18.58mil; 35.1mil + 19.74mil; 35.68mil + 20.74mil; 36.38mil + 22.14mil; 37.78mil + 23.3mil; 39.2mil + 24.18mil; 40.7mil + 24.82mil; 42.25mil + 25.21mil; 43.86mil + 25.37mil; 45.56mil + 25.24mil; 47.36mil + 24.88mil; 49.03mil + 24.3mil; 50.58mil + 23.48mil; 52.01mil + 22.42mil; 53.32mil + 21.11mil; 54.5mil + 21.99mil; 55.11mil + 22.87mil; 55.75mil + 23.66mil; 56.51mil + 24.42mil; 57.33mil + 25.12mil; 58.22mil + 25.82mil; 59.22mil + 26.37mil; 60.28mil + 26.86mil; 61.35mil + 27.22mil; 62.44mil + 27.5mil; 63.6mil + 27.65mil; 64.76mil + } + } + height = 63.33mil + } + ha:C { + width=22mil; delta=12.0mil; + li:objects { + li:simplepoly.0 { + 11.25mil; 33.91mil + 11.5mil; 33.91mil + 12.26mil; 33.91mil + 13.53mil; 33.91mil + 15.33mil; 33.91mil + 17.64mil; 33.91mil + 20.56mil; 33.91mil + 21.23mil; 34.0mil + 21.78mil; 34.19mil + 22.23mil; 34.49mil + 22.54mil; 34.92mil + 22.72mil; 35.49mil + 22.81mil; 36.19mil + 22.72mil; 36.92mil + 22.54mil; 37.5mil + 22.2mil; 37.93mil + 21.72mil; 38.26mil + 21.14mil; 38.44mil + 20.38mil; 38.51mil + 11.22mil; 38.51mil + 10.37mil; 38.6mil + 9.52mil; 38.78mil + 8.7mil; 39.08mil + 7.88mil; 39.51mil + 7.09mil; 40.06mil + 6.26mil; 40.73mil + 5.69mil; 41.33mil + 5.23mil; 42.0mil + 4.89mil; 42.73mil + 4.62mil; 43.49mil + 4.47mil; 44.35mil + 4.44mil; 45.29mil + 4.44mil; 68.53mil + 4.47mil; 69.47mil + 4.62mil; 70.35mil + 4.89mil; 71.2mil + 5.26mil; 72.0mil + 5.75mil; 72.73mil + 6.36mil; 73.46mil + 7.02mil; 74.12mil + 7.69mil; 74.64mil + 8.36mil; 75.07mil + 9.06mil; 75.37mil + 9.76mil; 75.52mil + 10.52mil; 75.58mil + 20.74mil; 75.58mil + 21.38mil; 75.68mil + 21.93mil; 75.86mil + 22.35mil; 76.16mil + 22.66mil; 76.59mil + 22.84mil; 77.14mil + 22.93mil; 77.8mil + 22.84mil; 78.44mil + 22.66mil; 78.99mil + 22.35mil; 79.39mil + 21.93mil; 79.69mil + 21.38mil; 79.84mil + 20.71mil; 79.9mil + 10.34mil; 79.9mil + 8.94mil; 79.81mil + 7.6mil; 79.48mil + 6.29mil; 78.93mil + 4.99mil; 78.14mil + 3.74mil; 77.14mil + 2.49mil; 75.86mil + 1.73mil; 74.92mil + 1.09mil; 73.88mil + 0.61mil; 72.73mil + 0.27mil; 71.51mil + 0.06mil; 70.23mil + 0.0mil; 68.77mil + 0.0mil; 44.95mil + 0.09mil; 43.49mil + 0.36mil; 42.06mil + 0.88mil; 40.73mil + 1.55mil; 39.45mil + 2.46mil; 38.23mil + 3.59mil; 37.01mil + 4.68mil; 36.07mil + 5.87mil; 35.31mil + 7.12mil; 34.7mil + 8.42mil; 34.28mil + 9.76mil; 34.0mil + } + } + height = 63.33mil + } + ha:D { + width=27mil; delta=12.0mil; + li:objects { + li:simplepoly.1 { + 0.0mil; 36.56mil + 0.06mil; 35.83mil + 0.27mil; 35.19mil + 0.61mil; 34.7mil + 1.09mil; 34.37mil + 1.73mil; 34.16mil + 2.52mil; 34.06mil + 16.79mil; 34.06mil + 18.13mil; 34.16mil + 19.47mil; 34.43mil + 20.71mil; 34.89mil + 21.93mil; 35.52mil + 23.08mil; 36.35mil + 24.24mil; 37.35mil + 25.21mil; 38.47mil + 23.08mil; 44.59mil + 22.9mil; 43.74mil + 22.63mil; 42.92mil + 22.26mil; 42.12mil + 21.78mil; 41.36mil + 21.17mil; 40.6mil + 20.47mil; 39.97mil + 19.71mil; 39.42mil + 18.86mil; 38.99mil + 17.97mil; 38.72mil + 17.0mil; 38.54mil + 15.94mil; 38.44mil + 4.47mil; 38.44mil + 4.47mil; 39.48mil + 4.47mil; 42.55mil + 4.47mil; 47.66mil + 4.47mil; 54.81mil + 4.47mil; 64.0mil + 4.47mil; 75.61mil + 4.74mil; 75.61mil + 5.62mil; 75.61mil + 7.05mil; 75.61mil + 9.09mil; 75.61mil + 11.71mil; 75.61mil + 15.02mil; 75.61mil + 16.3mil; 75.58mil + 17.49mil; 75.4mil + 18.55mil; 75.1mil + 19.5mil; 74.7mil + 20.35mil; 74.19mil + 21.11mil; 73.52mil + 21.72mil; 72.82mil + 22.2mil; 72.03mil + 22.6mil; 71.2mil + 22.87mil; 70.32mil + 23.05mil; 69.35mil + 23.15mil; 68.31mil + 23.15mil; 45.47mil + 23.08mil; 44.59mil + 25.21mil; 38.47mil + 26.04mil; 39.63mil + 26.67mil; 40.85mil + 27.13mil; 42.09mil + 27.4mil; 43.4mil + 27.53mil; 44.8mil + 27.53mil; 69.35mil + 27.43mil; 70.72mil + 27.16mil; 72.03mil + 26.7mil; 73.27mil + 26.07mil; 74.49mil + 25.24mil; 75.61mil + 24.24mil; 76.74mil + 23.12mil; 77.74mil + 21.99mil; 78.53mil + 20.83mil; 79.17mil + 19.68mil; 79.63mil + 18.46mil; 79.9mil + 17.21mil; 80.0mil + 2.04mil; 80.0mil + 1.4mil; 79.93mil + 0.88mil; 79.72mil + 0.48mil; 79.33mil + 0.21mil; 78.81mil + 0.03mil; 78.14mil + 0.0mil; 77.29mil + } + } + height = 63.33mil + } + ha:E { + width=22mil; delta=12.0mil; + li:objects { + li:simplepoly.0 { + 4.38mil; 75.46mil + 20.59mil; 75.46mil + 21.26mil; 75.52mil + 21.81mil; 75.71mil + 22.26mil; 76.01mil + 22.57mil; 76.44mil + 22.75mil; 76.98mil + 22.84mil; 77.65mil + 22.78mil; 78.32mil + 22.6mil; 78.87mil + 22.29mil; 79.3mil + 21.87mil; 79.6mil + 21.35mil; 79.78mil + 20.68mil; 79.84mil + 2.01mil; 79.84mil + 1.37mil; 79.78mil + 0.88mil; 79.6mil + 0.48mil; 79.3mil + 0.21mil; 78.87mil + 0.03mil; 78.29mil + 0.0mil; 77.56mil + 0.0mil; 36.28mil + 0.06mil; 35.58mil + 0.27mil; 34.98mil + 0.67mil; 34.52mil + 1.18mil; 34.19mil + 1.85mil; 34.0mil + 2.7mil; 33.91mil + 20.44mil; 33.91mil + 21.17mil; 34.0mil + 21.78mil; 34.19mil + 22.26mil; 34.49mil + 22.6mil; 34.92mil + 22.81mil; 35.46mil + 22.9mil; 36.13mil + 22.81mil; 36.8mil + 22.63mil; 37.35mil + 22.26mil; 37.78mil + 21.81mil; 38.08mil + 21.2mil; 38.26mil + 20.44mil; 38.32mil + 4.38mil; 38.32mil + 4.38mil; 52.5mil + 16.12mil; 52.5mil + 16.79mil; 52.56mil + 17.34mil; 52.74mil + 17.76mil; 53.04mil + 18.07mil; 53.47mil + 18.25mil; 54.02mil + 18.34mil; 54.69mil + 18.28mil; 55.33mil + 18.1mil; 55.84mil + 17.79mil; 56.24mil + 17.37mil; 56.54mil + 16.85mil; 56.73mil + 16.18mil; 56.76mil + 4.38mil; 56.76mil + } + } + height = 63.33mil + } + ha:F { + width=22mil; delta=12.0mil; + li:objects { + li:simplepoly.0 { + 4.5mil; 56.79mil + 4.5mil; 77.38mil + 4.41mil; 78.14mil + 4.23mil; 78.78mil + 3.92mil; 79.26mil + 3.5mil; 79.6mil + 2.92mil; 79.81mil + 2.22mil; 79.87mil + 1.52mil; 79.81mil + 0.97mil; 79.6mil + 0.55mil; 79.26mil + 0.24mil; 78.78mil + 0.06mil; 78.14mil + 0.0mil; 77.35mil + 0.0mil; 76.22mil + 0.0mil; 72.82mil + 0.0mil; 67.16mil + 0.0mil; 59.22mil + 0.0mil; 49.0mil + 0.0mil; 36.04mil + 0.06mil; 35.4mil + 0.24mil; 34.89mil + 0.58mil; 34.46mil + 1.03mil; 34.16mil + 1.61mil; 34.0mil + 2.37mil; 33.91mil + 2.86mil; 33.91mil + 4.35mil; 33.91mil + 6.84mil; 33.91mil + 10.31mil; 33.91mil + 14.81mil; 33.91mil + 20.5mil; 33.91mil + 21.23mil; 33.97mil + 21.81mil; 34.16mil + 22.29mil; 34.46mil + 22.63mil; 34.89mil + 22.81mil; 35.43mil + 22.9mil; 36.1mil + 22.81mil; 36.77mil + 22.63mil; 37.32mil + 22.29mil; 37.74mil + 21.84mil; 38.05mil + 21.26mil; 38.23mil + 20.53mil; 38.29mil + 4.53mil; 38.29mil + 4.53mil; 52.35mil + 20.53mil; 52.35mil + 21.23mil; 52.44mil + 21.84mil; 52.62mil + 22.29mil; 52.92mil + 22.63mil; 53.35mil + 22.81mil; 53.9mil + 22.9mil; 54.57mil + 22.81mil; 55.27mil + 22.63mil; 55.81mil + 22.29mil; 56.24mil + 21.84mil; 56.54mil + 21.23mil; 56.73mil + 20.5mil; 56.79mil + } + } + height = 63.33mil + } + ha:G { + width=27mil; delta=12.0mil; + li:objects { + li:simplepoly.0 { + 23.15mil; 75.46mil + 23.15mil; 56.79mil + 18.37mil; 56.79mil + 17.7mil; 56.76mil + 17.15mil; 56.57mil + 16.73mil; 56.27mil + 16.45mil; 55.84mil + 16.27mil; 55.33mil + 16.21mil; 54.63mil + 16.24mil; 53.99mil + 16.42mil; 53.44mil + 16.7mil; 53.01mil + 17.09mil; 52.71mil + 17.61mil; 52.53mil + 18.28mil; 52.44mil + 25.55mil; 52.44mil + 26.13mil; 52.53mil + 26.61mil; 52.77mil + 26.98mil; 53.17mil + 27.25mil; 53.71mil + 27.43mil; 54.44mil + 27.5mil; 55.33mil + 27.5mil; 77.2mil + 27.4mil; 78.02mil + 27.19mil; 78.69mil + 26.86mil; 79.2mil + 26.37mil; 79.57mil + 25.73mil; 79.78mil + 24.97mil; 79.84mil + 10.19mil; 79.84mil + 9.06mil; 79.78mil + 7.97mil; 79.54mil + 6.84mil; 79.11mil + 5.72mil; 78.53mil + 4.59mil; 77.8mil + 3.43mil; 76.86mil + 2.37mil; 75.8mil + 1.52mil; 74.52mil + 0.85mil; 73.03mil + 0.36mil; 71.36mil + 0.09mil; 69.5mil + 0.0mil; 67.34mil + 0.0mil; 44.68mil + 0.09mil; 43.31mil + 0.36mil; 41.97mil + 0.85mil; 40.7mil + 1.52mil; 39.48mil + 2.37mil; 38.32mil + 3.47mil; 37.17mil + 4.62mil; 36.19mil + 5.87mil; 35.4mil + 7.18mil; 34.76mil + 8.51mil; 34.31mil + 9.91mil; 34.03mil + 11.47mil; 33.91mil + 24.91mil; 33.91mil + 25.7mil; 33.97mil + 26.37mil; 34.16mil + 26.89mil; 34.46mil + 27.28mil; 34.89mil + 27.5mil; 35.43mil + 27.59mil; 36.1mil + 27.5mil; 36.77mil + 27.28mil; 37.32mil + 26.92mil; 37.74mil + 26.4mil; 38.05mil + 25.76mil; 38.23mil + 24.94mil; 38.29mil + 11.95mil; 38.29mil + 10.86mil; 38.35mil + 9.85mil; 38.54mil + 8.91mil; 38.84mil + 8.03mil; 39.27mil + 7.24mil; 39.81mil + 6.48mil; 40.48mil + 5.81mil; 41.24mil + 5.29mil; 42.06mil + 4.86mil; 42.92mil + 4.56mil; 43.83mil + 4.41mil; 44.77mil + 4.35mil; 45.81mil + 4.35mil; 67.83mil + 4.38mil; 68.92mil + 4.56mil; 69.96mil + 4.83mil; 70.9mil + 5.2mil; 71.78mil + 5.69mil; 72.57mil + 6.32mil; 73.33mil + 6.96mil; 74.0mil + 7.66mil; 74.52mil + 8.39mil; 74.95mil + 9.12mil; 75.25mil + 9.91mil; 75.4mil + 10.74mil; 75.46mil + } + } + height = 63.33mil + } + ha:H { + width=27mil; delta=12.0mil; + li:objects { + li:simplepoly.0 { + 23.36mil; 56.88mil + 4.47mil; 56.88mil + 4.47mil; 77.65mil + 4.38mil; 78.38mil + 4.2mil; 78.96mil + 3.89mil; 79.42mil + 3.47mil; 79.75mil + 2.92mil; 79.93mil + 2.25mil; 80.0mil + 1.55mil; 79.93mil + 1.0mil; 79.75mil + 0.58mil; 79.45mil + 0.24mil; 78.99mil + 0.06mil; 78.41mil + 0.0mil; 77.68mil + 0.0mil; 36.65mil + 0.06mil; 35.89mil + 0.24mil; 35.22mil + 0.55mil; 34.73mil + 0.97mil; 34.37mil + 1.52mil; 34.16mil + 2.22mil; 34.06mil + 2.89mil; 34.16mil + 3.43mil; 34.37mil + 3.86mil; 34.73mil + 4.2mil; 35.22mil + 4.38mil; 35.86mil + 4.47mil; 36.65mil + 4.47mil; 52.5mil + 23.36mil; 52.5mil + 23.36mil; 36.47mil + 23.39mil; 35.8mil + 23.57mil; 35.22mil + 23.88mil; 34.76mil + 24.3mil; 34.46mil + 24.82mil; 34.28mil + 25.52mil; 34.19mil + 26.16mil; 34.28mil + 26.7mil; 34.46mil + 27.13mil; 34.76mil + 27.4mil; 35.19mil + 27.59mil; 35.74mil + 27.68mil; 36.44mil + 27.68mil; 77.56mil + 27.62mil; 78.32mil + 27.43mil; 78.93mil + 27.13mil; 79.39mil + 26.7mil; 79.72mil + 26.19mil; 79.93mil + 25.52mil; 80.0mil + 24.85mil; 79.93mil + 24.3mil; 79.75mil + 23.88mil; 79.42mil + 23.6mil; 78.96mil + 23.42mil; 78.38mil + 23.36mil; 77.62mil + } + } + height = 63.33mil + } + ha:I { + width=4mil; delta=12.0mil; + li:objects { + li:simplepoly.0 { + 4.62mil; 80.0mil + 4.53mil; 80.0mil + 4.35mil; 80.0mil + 4.04mil; 80.0mil + 3.59mil; 80.0mil + 3.01mil; 80.0mil + 2.31mil; 80.0mil + 1.58mil; 79.93mil + 1.0mil; 79.69mil + 0.58mil; 79.3mil + 0.24mil; 78.75mil + 0.06mil; 78.05mil + 0.0mil; 77.14mil + 0.0mil; 36.8mil + 0.06mil; 35.98mil + 0.24mil; 35.31mil + 0.55mil; 34.76mil + 1.0mil; 34.4mil + 1.58mil; 34.16mil + 2.31mil; 34.06mil + 3.01mil; 34.16mil + 3.59mil; 34.4mil + 4.01mil; 34.76mil + 4.35mil; 35.31mil + 4.53mil; 36.01mil + 4.62mil; 36.89mil + 4.62mil; 77.07mil + 4.53mil; 77.99mil + 4.35mil; 78.72mil + 4.04mil; 79.26mil + 3.59mil; 79.69mil + 3.01mil; 79.93mil + } + } + height = 63.33mil + } + ha:J { + width=18mil; delta=12.0mil; + li:objects { + li:simplepoly.0 { + 13.81mil; 36.44mil + 13.84mil; 35.74mil + 14.02mil; 35.13mil + 14.32mil; 34.67mil + 14.75mil; 34.34mil + 15.3mil; 34.16mil + 16.0mil; 34.06mil + 16.64mil; 34.16mil + 17.18mil; 34.34mil + 17.61mil; 34.67mil + 17.88mil; 35.1mil + 18.07mil; 35.68mil + 18.16mil; 36.41mil + 18.16mil; 68.86mil + 18.07mil; 70.35mil + 17.79mil; 71.75mil + 17.33mil; 73.09mil + 16.7mil; 74.34mil + 15.91mil; 75.52mil + 14.9mil; 76.68mil + 13.78mil; 77.68mil + 12.56mil; 78.5mil + 11.28mil; 79.14mil + 9.94mil; 79.63mil + 8.48mil; 79.9mil + 6.93mil; 80.0mil + 2.25mil; 80.0mil + 1.55mil; 79.93mil + 1.0mil; 79.75mil + 0.54mil; 79.45mil + 0.24mil; 79.02mil + 0.06mil; 78.47mil + 0.0mil; 77.74mil + 0.06mil; 77.07mil + 0.27mil; 76.53mil + 0.64mil; 76.07mil + 1.15mil; 75.77mil + 1.79mil; 75.58mil + 2.64mil; 75.49mil + 7.14mil; 75.49mil + 8.06mil; 75.46mil + 8.91mil; 75.28mil + 9.73mil; 75.01mil + 10.49mil; 74.61mil + 11.19mil; 74.09mil + 11.89mil; 73.42mil + 12.44mil; 72.73mil + 12.92mil; 72.0mil + 13.29mil; 71.23mil + 13.56mil; 70.44mil + 13.72mil; 69.62mil + 13.81mil; 68.74mil + } + } + height = 63.33mil + } + ha:K { + width=27mil; delta=12.0mil; + li:objects { + li:simplepoly.0 { + 2.1mil; 79.9mil + 1.46mil; 79.84mil + 0.91mil; 79.6mil + 0.51mil; 79.23mil + 0.21mil; 78.69mil + 0.06mil; 77.99mil + 0.0mil; 77.07mil + 0.0mil; 36.07mil + 0.03mil; 35.46mil + 0.21mil; 34.98mil + 0.51mil; 34.58mil + 0.91mil; 34.31mil + 1.43mil; 34.12mil + 2.1mil; 34.06mil + 2.77mil; 34.16mil + 3.34mil; 34.34mil + 3.8mil; 34.64mil + 4.1mil; 35.07mil + 4.29mil; 35.65mil + 4.38mil; 36.35mil + 4.38mil; 55.75mil + 23.24mil; 35.07mil + 23.57mil; 34.73mil + 23.91mil; 34.43mil + 24.24mil; 34.22mil + 24.58mil; 34.06mil + 24.88mil; 33.97mil + 25.21mil; 33.91mil + 25.49mil; 33.94mil + 25.79mil; 34.0mil + 26.04mil; 34.12mil + 26.31mil; 34.25mil + 26.55mil; 34.46mil + 26.8mil; 34.67mil + 26.98mil; 34.95mil + 27.13mil; 35.19mil + 27.25mil; 35.43mil + 27.34mil; 35.71mil + 27.4mil; 35.98mil + 27.43mil; 36.25mil + 27.4mil; 36.56mil + 27.31mil; 36.83mil + 27.16mil; 37.17mil + 26.95mil; 37.5mil + 26.67mil; 37.87mil + 26.34mil; 38.26mil + 13.69mil; 52.28mil + 26.95mil; 76.22mil + 27.1mil; 76.56mil + 27.25mil; 76.86mil + 27.37mil; 77.14mil + 27.43mil; 77.38mil + 27.5mil; 77.56mil + 27.53mil; 77.74mil + 27.5mil; 78.08mil + 27.43mil; 78.35mil + 27.31mil; 78.63mil + 27.16mil; 78.9mil + 26.95mil; 79.14mil + 26.7mil; 79.39mil + 26.46mil; 79.6mil + 26.22mil; 79.75mil + 25.94mil; 79.84mil + 25.67mil; 79.93mil + 25.4mil; 80.0mil + 25.12mil; 80.0mil + 24.76mil; 79.96mil + 24.39mil; 79.87mil + 24.09mil; 79.66mil + 23.78mil; 79.42mil + 23.48mil; 79.08mil + 23.24mil; 78.63mil + 10.55mil; 55.72mil + 4.44mil; 62.41mil + 4.44mil; 76.98mil + 4.35mil; 77.9mil + 4.16mil; 78.63mil + 3.83mil; 79.17mil + 3.4mil; 79.6mil + 2.83mil; 79.84mil + } + } + height = 63.33mil + } + ha:L { + width=23mil; delta=12.0mil; + li:objects { + li:simplepoly.0 { + 4.41mil; 36.41mil + 4.41mil; 75.58mil + 20.26mil; 75.58mil + 21.08mil; 75.65mil + 21.78mil; 75.83mil + 22.29mil; 76.13mil + 22.69mil; 76.56mil + 22.93mil; 77.11mil + 23.02mil; 77.77mil + 22.93mil; 78.44mil + 22.69mil; 78.99mil + 22.29mil; 79.45mil + 21.75mil; 79.75mil + 21.05mil; 79.93mil + 20.16mil; 80.0mil + 2.16mil; 80.0mil + 1.49mil; 79.93mil + 0.94mil; 79.72mil + 0.51mil; 79.33mil + 0.24mil; 78.81mil + 0.06mil; 78.14mil + 0.0mil; 77.29mil + 0.0mil; 36.41mil + 0.03mil; 35.71mil + 0.21mil; 35.13mil + 0.51mil; 34.67mil + 0.94mil; 34.34mil + 1.49mil; 34.16mil + 2.19mil; 34.06mil + 2.83mil; 34.16mil + 3.37mil; 34.34mil + 3.83mil; 34.67mil + 4.13mil; 35.1mil + 4.32mil; 35.68mil + } + } + height = 63.33mil + } + ha:M { + width=32mil; delta=12.0mil; + li:objects { + li:simplepoly.0 { + 28.1mil; 35.22mil + 28.35mil; 34.89mil + 28.62mil; 34.58mil + 28.93mil; 34.37mil + 29.26mil; 34.22mil + 29.62mil; 34.12mil + 30.05mil; 34.06mil + 30.75mil; 34.16mil + 31.33mil; 34.34mil + 31.75mil; 34.67mil + 32.09mil; 35.16mil + 32.27mil; 35.74mil + 32.36mil; 36.5mil + 32.36mil; 76.98mil + 32.27mil; 77.93mil + 32.09mil; 78.66mil + 31.78mil; 79.23mil + 31.36mil; 79.66mil + 30.81mil; 79.93mil + 30.11mil; 80.0mil + 29.41mil; 79.93mil + 28.86mil; 79.69mil + 28.41mil; 79.26mil + 28.1mil; 78.69mil + 27.92mil; 77.96mil + 27.86mil; 76.98mil + 27.86mil; 44.35mil + 18.37mil; 59.8mil + 17.97mil; 60.41mil + 17.58mil; 60.86mil + 17.21mil; 61.26mil + 16.82mil; 61.5mil + 16.45mil; 61.68mil + 16.06mil; 61.71mil + 15.66mil; 61.68mil + 15.3mil; 61.53mil + 14.9mil; 61.26mil + 14.54mil; 60.92mil + 14.17mil; 60.47mil + 13.81mil; 59.86mil + 4.5mil; 44.41mil + 4.5mil; 77.14mil + 4.41mil; 78.02mil + 4.23mil; 78.72mil + 3.89mil; 79.3mil + 3.47mil; 79.69mil + 2.89mil; 79.93mil + 2.16mil; 80.0mil + 1.49mil; 79.93mil + 0.94mil; 79.69mil + 0.51mil; 79.33mil + 0.24mil; 78.78mil + 0.06mil; 78.08mil + 0.0mil; 77.2mil + 0.0mil; 36.47mil + 0.06mil; 35.74mil + 0.24mil; 35.16mil + 0.55mil; 34.67mil + 1.0mil; 34.34mil + 1.58mil; 34.16mil + 2.31mil; 34.06mil + 2.67mil; 34.09mil + 3.04mil; 34.19mil + 3.34mil; 34.34mil + 3.65mil; 34.55mil + 3.92mil; 34.82mil + 4.2mil; 35.13mil + 15.94mil; 54.93mil + } + } + height = 63.33mil + } + ha:N { + width=27mil; delta=12.0mil; + li:objects { + li:simplepoly.0 { + 23.24mil; 69.14mil + 23.24mil; 36.22mil + 23.27mil; 35.52mil + 23.45mil; 34.95mil + 23.75mil; 34.52mil + 24.15mil; 34.19mil + 24.67mil; 34.0mil + 25.34mil; 33.91mil + 25.94mil; 34.0mil + 26.49mil; 34.19mil + 26.89mil; 34.49mil + 27.19mil; 34.92mil + 27.34mil; 35.46mil + 27.43mil; 36.13mil + 27.43mil; 77.29mil + 27.37mil; 78.08mil + 27.19mil; 78.69mil + 26.92mil; 79.2mil + 26.52mil; 79.54mil + 26.04mil; 79.75mil + 25.43mil; 79.81mil + 24.97mil; 79.78mil + 24.54mil; 79.66mil + 24.15mil; 79.42mil + 23.78mil; 79.11mil + 23.42mil; 78.69mil + 23.12mil; 78.17mil + 4.38mil; 44.74mil + 4.38mil; 77.29mil + 4.29mil; 78.05mil + 4.1mil; 78.66mil + 3.8mil; 79.11mil + 3.34mil; 79.45mil + 2.77mil; 79.66mil + 2.07mil; 79.72mil + 1.43mil; 79.66mil + 0.91mil; 79.45mil + 0.51mil; 79.11mil + 0.21mil; 78.63mil + 0.03mil; 78.02mil + 0.0mil; 77.23mil + 0.0mil; 36.62mil + 0.03mil; 35.8mil + 0.21mil; 35.13mil + 0.51mil; 34.61mil + 0.94mil; 34.25mil + 1.49mil; 34.0mil + 2.19mil; 33.91mil + 2.64mil; 33.97mil + 3.04mil; 34.09mil + 3.43mil; 34.28mil + 3.8mil; 34.55mil + 4.1mil; 34.89mil + 4.41mil; 35.31mil + } + } + height = 63.33mil + } + ha:O { + width=27mil; delta=12.0mil; + li:objects { + li:simplepoly.1 { + 0.0mil; 46.9mil + 0.09mil; 45.26mil + 0.42mil; 43.68mil + 0.97mil; 42.16mil + 1.73mil; 40.7mil + 2.7mil; 39.3mil + 3.98mil; 37.9mil + 5.35mil; 36.71mil + 6.81mil; 35.71mil + 8.39mil; 34.95mil + 10.07mil; 34.37mil + 11.83mil; 34.03mil + 13.78mil; 33.91mil + 15.54mil; 34.03mil + 17.24mil; 34.37mil + 18.86mil; 34.92mil + 20.41mil; 35.68mil + 21.84mil; 36.65mil + 23.27mil; 37.87mil + 24.51mil; 39.3mil + 25.58mil; 40.79mil + 26.4mil; 42.37mil + 26.98mil; 43.98mil + 27.31mil; 45.71mil + 27.47mil; 47.54mil + 27.47mil; 66.12mil + 27.34mil; 68.07mil + 26.98mil; 69.9mil + 26.43mil; 71.6mil + 25.61mil; 73.21mil + 24.58mil; 74.7mil + 23.3mil; 76.13mil + 21.9mil; 77.32mil + 20.44mil; 78.29mil + 18.89mil; 79.02mil + 17.21mil; 79.57mil + 15.48mil; 79.9mil + 13.56mil; 80.0mil + 11.8mil; 79.9mil + 10.1mil; 79.6mil + 8.51mil; 79.05mil + 6.96mil; 78.32mil + 5.5mil; 77.35mil + 4.1mil; 76.13mil + 4.47mil; 67.13mil + 4.53mil; 68.22mil + 4.77mil; 69.26mil + 5.2mil; 70.26mil + 5.78mil; 71.27mil + 6.54mil; 72.21mil + 7.51mil; 73.15mil + 8.39mil; 73.88mil + 9.31mil; 74.46mil + 10.28mil; 74.92mil + 11.28mil; 75.25mil + 12.32mil; 75.43mil + 13.44mil; 75.49mil + 14.66mil; 75.46mil + 15.81mil; 75.28mil + 16.88mil; 74.98mil + 17.88mil; 74.55mil + 18.8mil; 74.03mil + 19.68mil; 73.33mil + 20.68mil; 72.3mil + 21.53mil; 71.23mil + 22.17mil; 70.08mil + 22.66mil; 68.86mil + 22.93mil; 67.61mil + 23.05mil; 66.25mil + 23.05mil; 47.75mil + 22.96mil; 46.35mil + 22.69mil; 45.01mil + 22.26mil; 43.8mil + 21.62mil; 42.7mil + 20.83mil; 41.67mil + 19.86mil; 40.73mil + 18.89mil; 40.03mil + 17.88mil; 39.45mil + 16.82mil; 39.02mil + 15.72mil; 38.69mil + 14.6mil; 38.51mil + 13.41mil; 38.41mil + 12.41mil; 38.51mil + 11.4mil; 38.69mil + 10.43mil; 39.02mil + 9.46mil; 39.45mil + 8.48mil; 40.03mil + 7.51mil; 40.76mil + 6.57mil; 41.64mil + 5.81mil; 42.61mil + 5.23mil; 43.71mil + 4.8mil; 44.89mil + 4.53mil; 46.2mil + 4.47mil; 47.63mil + 4.47mil; 67.13mil + 4.1mil; 76.13mil + 2.83mil; 74.79mil + 1.82mil; 73.39mil + 1.03mil; 71.9mil + 0.45mil; 70.35mil + 0.09mil; 68.74mil + 0.0mil; 66.98mil + } + } + height = 63.33mil + } + ha:P { + width=27mil; delta=12.0mil; + li:objects { + li:simplepoly.1 { + 4.5mil; 77.32mil + 4.41mil; 78.11mil + 4.23mil; 78.72mil + 3.92mil; 79.23mil + 3.5mil; 79.57mil + 2.95mil; 79.78mil + 2.25mil; 79.84mil + 1.55mil; 79.78mil + 1.0mil; 79.57mil + 0.55mil; 79.2mil + 0.24mil; 78.72mil + 0.06mil; 78.08mil + 0.0mil; 77.26mil + 0.0mil; 36.47mil + 0.06mil; 35.74mil + 0.27mil; 35.16mil + 0.61mil; 34.67mil + 1.09mil; 34.34mil + 1.7mil; 34.16mil + 2.49mil; 34.06mil + 4.5mil; 38.44mil + 4.5mil; 38.96mil + 4.5mil; 40.51mil + 4.5mil; 43.07mil + 4.5mil; 46.63mil + 4.5mil; 51.22mil + 4.5mil; 57.03mil + 14.6mil; 57.03mil + 15.6mil; 56.97mil + 16.58mil; 56.76mil + 17.55mil; 56.36mil + 18.49mil; 55.84mil + 19.43mil; 55.17mil + 20.38mil; 54.32mil + 21.17mil; 53.41mil + 21.84mil; 52.44mil + 22.35mil; 51.37mil + 22.75mil; 50.22mil + 22.96mil; 49.03mil + 23.05mil; 47.69mil + 22.96mil; 46.44mil + 22.75mil; 45.23mil + 22.39mil; 44.1mil + 21.87mil; 43.04mil + 21.2mil; 42.06mil + 20.38mil; 41.09mil + 19.43mil; 40.3mil + 18.4mil; 39.63mil + 17.28mil; 39.11mil + 16.06mil; 38.75mil + 14.75mil; 38.54mil + 13.32mil; 38.44mil + 4.5mil; 38.44mil + 2.49mil; 34.06mil + 14.26mil; 34.06mil + 16.09mil; 34.22mil + 17.85mil; 34.58mil + 19.5mil; 35.22mil + 21.08mil; 36.07mil + 22.57mil; 37.23mil + 24.03mil; 38.63mil + 25.06mil; 39.93mil + 25.88mil; 41.24mil + 26.55mil; 42.61mil + 27.04mil; 44.01mil + 27.31mil; 45.44mil + 27.43mil; 46.96mil + 27.34mil; 48.76mil + 27.16mil; 50.4mil + 26.83mil; 51.89mil + 26.37mil; 53.29mil + 25.79mil; 54.54mil + 25.06mil; 55.66mil + 23.54mil; 57.46mil + 21.93mil; 58.92mil + 20.26mil; 60.07mil + 18.46mil; 60.89mil + 16.61mil; 61.38mil + 14.6mil; 61.53mil + 4.5mil; 61.53mil + } + } + height = 63.33mil + } + ha:Q { + width=32mil; delta=12.0mil; + li:objects { + li:simplepoly.1 { + 26.7mil; 71.11mil + 31.12mil; 75.61mil + 31.45mil; 76.01mil + 31.75mil; 76.41mil + 32.0mil; 76.77mil + 32.15mil; 77.11mil + 32.24mil; 77.44mil + 32.3mil; 77.74mil + 32.21mil; 78.44mil + 32.03mil; 78.99mil + 31.72mil; 79.45mil + 31.27mil; 79.75mil + 30.69mil; 79.93mil + 29.99mil; 80.0mil + 29.66mil; 79.96mil + 29.32mil; 79.87mil + 28.99mil; 79.72mil + 28.62mil; 79.48mil + 28.26mil; 79.17mil + 27.86mil; 78.78mil + 24.33mil; 75.16mil + 24.0mil; 75.61mil + 23.57mil; 76.1mil + 23.08mil; 76.56mil + 22.51mil; 77.01mil + 21.87mil; 77.5mil + 21.14mil; 77.99mil + 20.04mil; 78.63mil + 18.95mil; 79.11mil + 17.82mil; 79.51mil + 16.64mil; 79.78mil + 15.45mil; 79.96mil + 14.17mil; 80.0mil + 12.16mil; 79.9mil + 10.28mil; 79.54mil + 8.51mil; 78.96mil + 6.9mil; 78.14mil + 5.38mil; 77.07mil + 3.98mil; 75.71mil + 2.77mil; 74.25mil + 1.76mil; 72.73mil + 1.0mil; 71.14mil + 0.42mil; 69.5mil + 0.09mil; 67.8mil + 0.0mil; 65.97mil + 0.0mil; 47.69mil + 0.06mil; 46.26mil + 0.3mil; 44.86mil + 0.67mil; 43.49mil + 1.21mil; 42.12mil + 1.91mil; 40.82mil + 2.8mil; 39.48mil + 4.2mil; 37.84mil + 5.78mil; 36.5mil + 7.51mil; 35.43mil + 9.46mil; 34.7mil + 11.59mil; 34.25mil + 11.71mil; 38.69mil + 10.77mil; 38.96mil + 9.82mil; 39.36mil + 8.94mil; 39.84mil + 8.09mil; 40.45mil + 6.99mil; 41.46mil + 6.11mil; 42.58mil + 5.41mil; 43.8mil + 4.93mil; 45.14mil + 4.62mil; 46.6mil + 4.53mil; 48.18mil + 4.53mil; 66.37mil + 4.59mil; 67.55mil + 4.83mil; 68.68mil + 5.26mil; 69.77mil + 5.84mil; 70.84mil + 6.57mil; 71.87mil + 7.51mil; 72.88mil + 8.39mil; 73.67mil + 9.37mil; 74.34mil + 10.43mil; 74.82mil + 11.56mil; 75.19mil + 12.77mil; 75.4mil + 14.11mil; 75.46mil + 15.42mil; 75.37mil + 16.7mil; 75.1mil + 17.88mil; 74.61mil + 19.04mil; 73.94mil + 20.1mil; 73.09mil + 21.17mil; 71.96mil + 20.41mil; 71.33mil + 19.8mil; 70.75mil + 19.31mil; 70.17mil + 18.98mil; 69.65mil + 18.77mil; 69.2mil + 18.7mil; 68.74mil + 18.74mil; 68.01mil + 18.92mil; 67.4mil + 19.22mil; 66.95mil + 19.65mil; 66.61mil + 20.2mil; 66.4mil + 20.89mil; 66.31mil + 21.29mil; 66.37mil + 21.69mil; 66.49mil + 22.05mil; 66.7mil + 22.42mil; 66.98mil + 22.75mil; 67.34mil + 23.12mil; 67.8mil + 23.12mil; 67.25mil + 23.12mil; 65.58mil + 23.12mil; 62.78mil + 23.12mil; 58.85mil + 23.12mil; 53.81mil + 23.12mil; 47.42mil + 23.02mil; 46.2mil + 22.78mil; 45.04mil + 22.39mil; 43.95mil + 21.84mil; 42.89mil + 21.11mil; 41.91mil + 20.23mil; 40.94mil + 19.28mil; 40.21mil + 18.31mil; 39.57mil + 17.28mil; 39.08mil + 16.18mil; 38.75mil + 15.02mil; 38.54mil + 13.78mil; 38.44mil + 12.71mil; 38.51mil + 11.71mil; 38.69mil + 11.59mil; 34.25mil + 13.99mil; 34.06mil + 15.94mil; 34.19mil + 17.79mil; 34.55mil + 19.5mil; 35.13mil + 21.08mil; 35.92mil + 22.51mil; 36.95mil + 23.88mil; 38.26mil + 25.0mil; 39.69mil + 25.94mil; 41.09mil + 26.67mil; 42.49mil + 27.19mil; 43.89mil + 27.53mil; 45.26mil + 27.65mil; 46.69mil + 27.65mil; 65.79mil + 27.62mil; 66.88mil + 27.53mil; 67.89mil + 27.4mil; 68.83mil + 27.22mil; 69.65mil + 26.98mil; 70.41mil + } + } + height = 63.33mil + } + ha:R { + width=27mil; delta=12.0mil; + li:objects { + li:simplepoly.1 { + 2.37mil; 34.25mil + 14.39mil; 34.25mil + 16.18mil; 34.4mil + 17.94mil; 34.82mil + 19.65mil; 35.49mil + 21.32mil; 36.47mil + 22.9mil; 37.68mil + 24.51mil; 39.24mil + 25.43mil; 40.36mil + 26.16mil; 41.55mil + 26.73mil; 42.76mil + 27.16mil; 44.01mil + 27.43mil; 45.35mil + 27.53mil; 46.75mil + 27.47mil; 48.09mil + 27.34mil; 49.43mil + 27.13mil; 50.7mil + 26.86mil; 51.95mil + 26.46mil; 53.2mil + 26.0mil; 54.41mil + 25.34mil; 55.69mil + 24.48mil; 56.85mil + 23.45mil; 57.91mil + 22.2mil; 58.85mil + 20.77mil; 59.74mil + 19.1mil; 60.53mil + 27.04mil; 76.13mil + 27.16mil; 76.44mil + 27.28mil; 76.74mil + 27.37mil; 77.01mil + 27.43mil; 77.26mil + 22.57mil; 51.34mil + 22.9mil; 50.22mil + 23.12mil; 48.97mil + 23.21mil; 47.54mil + 23.12mil; 46.5mil + 22.9mil; 45.47mil + 22.54mil; 44.47mil + 22.02mil; 43.49mil + 21.35mil; 42.52mil + 20.53mil; 41.55mil + 19.56mil; 40.66mil + 18.58mil; 39.93mil + 17.58mil; 39.36mil + 16.55mil; 38.96mil + 15.48mil; 38.69mil + 14.39mil; 38.6mil + 4.47mil; 38.6mil + 4.47mil; 57.15mil + 4.71mil; 57.15mil + 5.53mil; 57.15mil + 6.9mil; 57.15mil + 8.82mil; 57.15mil + 11.28mil; 57.15mil + 14.42mil; 57.15mil + 15.45mil; 57.09mil + 16.48mil; 56.85mil + 17.55mil; 56.42mil + 18.58mil; 55.84mil + 19.65mil; 55.11mil + 20.74mil; 54.14mil + 21.47mil; 53.32mil + 22.08mil; 52.41mil + 22.57mil; 51.34mil + 27.43mil; 77.26mil + 27.47mil; 77.47mil + 27.5mil; 77.68mil + 27.4mil; 78.41mil + 27.22mil; 78.99mil + 26.92mil; 79.42mil + 26.49mil; 79.75mil + 25.94mil; 79.93mil + 25.24mil; 80.0mil + 24.85mil; 79.96mil + 24.48mil; 79.81mil + 24.12mil; 79.57mil + 23.81mil; 79.23mil + 23.48mil; 78.81mil + 23.21mil; 78.26mil + 14.69mil; 61.62mil + 4.38mil; 61.62mil + 4.38mil; 77.59mil + 4.29mil; 78.35mil + 4.1mil; 78.93mil + 3.8mil; 79.42mil + 3.37mil; 79.75mil + 2.83mil; 79.93mil + 2.16mil; 80.0mil + 1.49mil; 79.93mil + 0.94mil; 79.75mil + 0.51mil; 79.42mil + 0.24mil; 78.93mil + 0.06mil; 78.35mil + 0.0mil; 77.56mil + 0.0mil; 36.59mil + 0.06mil; 35.89mil + 0.24mil; 35.31mil + 0.58mil; 34.85mil + 1.03mil; 34.52mil + 1.61mil; 34.34mil + } + } + height = 63.33mil + } + ha:S { + width=27mil; delta=12.0mil; + li:objects { + li:simplepoly.0 { + 0.0mil; 45.59mil + 0.06mil; 44.07mil + 0.33mil; 42.61mil + 0.79mil; 41.21mil + 1.43mil; 39.9mil + 2.25mil; 38.69mil + 3.28mil; 37.47mil + 4.41mil; 36.47mil + 5.59mil; 35.62mil + 6.87mil; 34.95mil + 8.21mil; 34.49mil + 9.64mil; 34.19mil + 11.22mil; 34.06mil + 13.32mil; 34.12mil + 15.36mil; 34.31mil + 17.33mil; 34.58mil + 19.22mil; 34.95mil + 21.08mil; 35.43mil + 22.93mil; 36.04mil + 23.57mil; 36.35mil + 24.12mil; 36.71mil + 24.54mil; 37.11mil + 24.85mil; 37.53mil + 25.03mil; 38.02mil + 25.12mil; 38.57mil + 25.06mil; 39.2mil + 24.88mil; 39.75mil + 24.57mil; 40.15mil + 24.18mil; 40.45mil + 23.66mil; 40.6mil + 23.02mil; 40.66mil + 22.69mil; 40.66mil + 22.32mil; 40.6mil + 21.9mil; 40.51mil + 21.41mil; 40.36mil + 20.86mil; 40.18mil + 20.26mil; 39.93mil + 18.92mil; 39.48mil + 17.58mil; 39.11mil + 16.21mil; 38.81mil + 14.81mil; 38.6mil + 13.38mil; 38.47mil + 11.89mil; 38.41mil + 10.58mil; 38.51mil + 9.43mil; 38.75mil + 8.36mil; 39.14mil + 7.39mil; 39.69mil + 6.54mil; 40.39mil + 5.78mil; 41.27mil + 5.38mil; 41.88mil + 5.05mil; 42.55mil + 4.8mil; 43.28mil + 4.62mil; 44.07mil + 4.53mil; 44.92mil + 4.5mil; 45.84mil + 4.62mil; 47.08mil + 5.02mil; 48.24mil + 5.65mil; 49.33mil + 6.57mil; 50.34mil + 7.72mil; 51.25mil + 9.21mil; 52.1mil + 20.32mil; 57.73mil + 22.51mil; 59.07mil + 24.3mil; 60.56mil + 25.7mil; 62.26mil + 26.7mil; 64.15mil + 27.31mil; 66.19mil + 27.52mil; 68.5mil + 27.4mil; 70.2mil + 27.1mil; 71.78mil + 26.58mil; 73.27mil + 25.85mil; 74.64mil + 24.91mil; 75.89mil + 23.75mil; 77.04mil + 22.57mil; 77.96mil + 21.32mil; 78.69mil + 20.01mil; 79.26mil + 18.61mil; 79.66mil + 17.15mil; 79.93mil + 15.57mil; 80.0mil + 13.17mil; 79.9mil + 10.83mil; 79.54mil + 8.51mil; 78.93mil + 6.23mil; 78.11mil + 3.98mil; 77.01mil + 1.7mil; 75.65mil + 1.15mil; 75.28mil + 0.76mil; 74.88mil + 0.42mil; 74.49mil + 0.18mil; 74.06mil + 0.03mil; 73.64mil + 0.0mil; 73.15mil + 0.06mil; 72.54mil + 0.24mil; 72.0mil + 0.54mil; 71.6mil + 0.97mil; 71.3mil + 1.52mil; 71.14mil + 2.25mil; 71.05mil + 2.52mil; 71.08mil + 2.83mil; 71.17mil + 3.19mil; 71.3mil + 3.56mil; 71.51mil + 3.98mil; 71.72mil + 4.44mil; 72.03mil + 6.08mil; 73.09mil + 7.81mil; 73.94mil + 9.67mil; 74.61mil + 11.65mil; 75.1mil + 13.72mil; 75.37mil + 15.97mil; 75.46mil + 16.6mil; 75.46mil + 17.21mil; 75.4mil + 17.82mil; 75.28mil + 18.4mil; 75.13mil + 18.95mil; 74.92mil + 19.53mil; 74.64mil + 20.56mil; 73.97mil + 21.44mil; 73.15mil + 22.11mil; 72.18mil + 22.6mil; 71.08mil + 22.9mil; 69.81mil + 23.02mil; 68.34mil + 22.87mil; 67.01mil + 22.51mil; 65.76mil + 21.87mil; 64.63mil + 20.99mil; 63.6mil + 19.86mil; 62.66mil + 18.43mil; 61.81mil + 6.48mil; 55.75mil + 4.5mil; 54.57mil + 2.89mil; 53.2mil + 1.61mil; 51.62mil + 0.73mil; 49.82mil + 0.18mil; 47.84mil + } + } + height = 63.33mil + } + ha:T { + width=27mil; delta=12.0mil; + li:objects { + li:simplepoly.0 { + 0.0mil; 36.01mil + 0.06mil; 35.4mil + 0.27mil; 34.85mil + 0.64mil; 34.46mil + 1.15mil; 34.16mil + 1.82mil; 34.0mil + 2.67mil; 33.91mil + 25.21mil; 33.91mil + 25.85mil; 33.97mil + 26.4mil; 34.16mil + 26.83mil; 34.46mil + 27.13mil; 34.89mil + 27.31mil; 35.43mil + 27.4mil; 36.1mil + 27.34mil; 36.8mil + 27.16mil; 37.35mil + 26.86mil; 37.78mil + 26.46mil; 38.08mil + 25.91mil; 38.26mil + 25.27mil; 38.32mil + 15.94mil; 38.32mil + 15.94mil; 77.59mil + 15.84mil; 78.35mil + 15.66mil; 78.93mil + 15.36mil; 79.42mil + 14.93mil; 79.75mil + 14.38mil; 79.93mil + 13.72mil; 80.0mil + 13.02mil; 79.93mil + 12.47mil; 79.75mil + 12.04mil; 79.42mil + 11.74mil; 78.99mil + 11.56mil; 78.41mil + 11.49mil; 77.65mil + 11.49mil; 38.32mil + 2.61mil; 38.32mil + 1.79mil; 38.26mil + 1.15mil; 38.08mil + 0.64mil; 37.78mil + 0.27mil; 37.32mil + 0.06mil; 36.74mil + } + } + height = 63.33mil + } + ha:U { + width=27mil; delta=12.0mil; + li:objects { + li:simplepoly.0 { + 0.0mil; 36.28mil + 0.03mil; 35.58mil + 0.21mil; 34.98mil + 0.51mil; 34.52mil + 0.91mil; 34.19mil + 1.46mil; 34.0mil + 2.13mil; 33.91mil + 2.83mil; 34.0mil + 3.4mil; 34.19mil + 3.83mil; 34.52mil + 4.16mil; 34.98mil + 4.35mil; 35.55mil + 4.44mil; 36.28mil + 4.44mil; 65.76mil + 4.5mil; 67.34mil + 4.77mil; 68.77mil + 5.23mil; 70.08mil + 5.87mil; 71.27mil + 6.69mil; 72.3mil + 7.72mil; 73.24mil + 8.67mil; 73.94mil + 9.64mil; 74.49mil + 10.61mil; 74.95mil + 11.62mil; 75.25mil + 12.62mil; 75.43mil + 13.69mil; 75.49mil + 14.9mil; 75.43mil + 16.12mil; 75.19mil + 17.28mil; 74.76mil + 18.4mil; 74.19mil + 19.47mil; 73.42mil + 20.56mil; 72.45mil + 21.29mil; 71.6mil + 21.93mil; 70.63mil + 22.42mil; 69.53mil + 22.75mil; 68.34mil + 22.96mil; 67.07mil + 23.05mil; 65.61mil + 23.05mil; 36.28mil + 23.12mil; 35.58mil + 23.3mil; 34.98mil + 23.6mil; 34.52mil + 24.03mil; 34.19mil + 24.61mil; 34.0mil + 25.34mil; 33.91mil + 26.0mil; 34.0mil + 26.55mil; 34.22mil + 26.98mil; 34.58mil + 27.28mil; 35.1mil + 27.47mil; 35.77mil + 27.56mil; 36.59mil + 27.56mil; 65.42mil + 27.43mil; 67.52mil + 27.1mil; 69.44mil + 26.55mil; 71.23mil + 25.79mil; 72.85mil + 24.82mil; 74.34mil + 23.57mil; 75.71mil + 22.08mil; 76.98mil + 20.56mil; 78.02mil + 18.95mil; 78.81mil + 17.24mil; 79.39mil + 15.51mil; 79.75mil + 13.62mil; 79.84mil + 11.98mil; 79.78mil + 10.4mil; 79.51mil + 8.88mil; 79.05mil + 7.45mil; 78.41mil + 6.05mil; 77.59mil + 4.68mil; 76.56mil + 3.25mil; 75.22mil + 2.07mil; 73.73mil + 1.15mil; 72.12mil + 0.51mil; 70.38mil + 0.12mil; 68.53mil + 0.0mil; 66.46mil + } + } + height = 63.33mil + } + ha:V { + width=32mil; delta=12.0mil; + li:objects { + li:simplepoly.0 { + 16.06mil; 70.87mil + 27.77mil; 36.07mil + 28.01mil; 35.46mil + 28.29mil; 34.98mil + 28.62mil; 34.58mil + 29.02mil; 34.31mil + 29.44mil; 34.12mil + 29.96mil; 34.06mil + 30.63mil; 34.12mil + 31.18mil; 34.31mil + 31.63mil; 34.61mil + 31.94mil; 35.01mil + 32.12mil; 35.55mil + 32.21mil; 36.19mil + 32.18mil; 36.41mil + 32.18mil; 36.62mil + 32.12mil; 36.83mil + 32.09mil; 37.08mil + 32.0mil; 37.32mil + 31.94mil; 37.59mil + 18.52mil; 77.93mil + 18.25mil; 78.57mil + 17.94mil; 79.08mil + 17.58mil; 79.48mil + 17.15mil; 79.78mil + 16.67mil; 79.96mil + 16.12mil; 80.0mil + 15.63mil; 79.96mil + 15.21mil; 79.78mil + 14.84mil; 79.51mil + 14.51mil; 79.11mil + 14.2mil; 78.63mil + 13.96mil; 77.99mil + 0.18mil; 37.17mil + 0.12mil; 37.01mil + 0.06mil; 36.83mil + 0.03mil; 36.65mil + 0.0mil; 36.5mil + 0.0mil; 36.35mil + 0.0mil; 36.16mil + 0.06mil; 35.58mil + 0.24mil; 35.1mil + 0.57mil; 34.7mil + 1.03mil; 34.43mil + 1.64mil; 34.25mil + 2.4mil; 34.19mil + 2.83mil; 34.25mil + 3.22mil; 34.43mil + 3.62mil; 34.73mil + 3.92mil; 35.13mil + 4.22mil; 35.68mil + 4.5mil; 36.31mil + } + } + height = 63.33mil + } + ha:W { + width=41mil; delta=12.0mil; + li:objects { + li:simplepoly.0 { + 37.02mil; 36.04mil + 37.2mil; 35.49mil + 37.44mil; 35.04mil + 37.75mil; 34.67mil + 38.14mil; 34.4mil + 38.6mil; 34.25mil + 39.14mil; 34.19mil + 39.78mil; 34.25mil + 40.33mil; 34.4mil + 40.76mil; 34.67mil + 41.06mil; 35.04mil + 41.24mil; 35.49mil + 41.33mil; 36.07mil + 41.3mil; 36.35mil + 41.3mil; 36.59mil + 41.27mil; 36.86mil + 41.24mil; 37.14mil + 41.18mil; 37.38mil + 41.15mil; 37.65mil + 32.15mil; 77.77mil + 31.94mil; 78.47mil + 31.69mil; 79.02mil + 31.39mil; 79.45mil + 30.99mil; 79.75mil + 30.54mil; 79.93mil + 30.02mil; 80.0mil + 29.44mil; 79.96mil + 28.95mil; 79.78mil + 28.53mil; 79.51mil + 28.13mil; 79.11mil + 27.83mil; 78.6mil + 27.59mil; 77.96mil + 20.62mil; 57.12mil + 13.68mil; 78.08mil + 13.44mil; 78.69mil + 13.14mil; 79.14mil + 12.8mil; 79.54mil + 12.41mil; 79.78mil + 11.98mil; 79.96mil + 11.49mil; 80.0mil + 10.92mil; 79.96mil + 10.4mil; 79.81mil + 9.97mil; 79.54mil + 9.64mil; 79.2mil + 9.4mil; 78.75mil + 9.21mil; 78.14mil + 0.09mil; 37.26mil + 0.06mil; 37.11mil + 0.03mil; 36.95mil + 0.0mil; 36.77mil + 0.0mil; 36.59mil + 0.0mil; 36.38mil + 0.0mil; 36.13mil + 0.06mil; 35.52mil + 0.24mil; 35.01mil + 0.57mil; 34.61mil + 1.0mil; 34.31mil + 1.58mil; 34.12mil + 2.34mil; 34.06mil + 2.83mil; 34.12mil + 3.28mil; 34.31mil + 3.65mil; 34.58mil + 3.98mil; 34.95mil + 4.22mil; 35.43mil + 4.41mil; 36.04mil + 11.8mil; 69.35mil + 18.37mil; 49.85mil + 18.61mil; 49.24mil + 18.92mil; 48.73mil + 19.31mil; 48.33mil + 19.74mil; 48.06mil + 20.22mil; 47.87mil + 20.8mil; 47.81mil + 21.26mil; 47.9mil + 21.68mil; 48.09mil + 22.05mil; 48.39mil + 22.41mil; 48.82mil + 22.72mil; 49.36mil + 22.99mil; 50.03mil + 29.5mil; 69.47mil + } + } + height = 63.33mil + } + ha:X { + width=32mil; delta=12.0mil; + li:objects { + li:simplepoly.0 { + 13.5mil; 57.03mil + 13.14mil; 56.51mil + 12.07mil; 54.93mil + 10.28mil; 52.25mil + 7.81mil; 48.54mil + 4.62mil; 43.74mil + 0.57mil; 37.65mil + 0.42mil; 37.41mil + 0.3mil; 37.17mil + 0.21mil; 36.92mil + 0.12mil; 36.68mil + 0.09mil; 36.44mil + 0.09mil; 36.16mil + 0.15mil; 35.55mil + 0.33mil; 35.07mil + 0.64mil; 34.67mil + 1.06mil; 34.4mil + 1.61mil; 34.22mil + 2.34mil; 34.16mil + 2.7mil; 34.22mil + 3.04mil; 34.31mil + 3.4mil; 34.49mil + 3.71mil; 34.76mil + 4.04mil; 35.1mil + 4.38mil; 35.49mil + 16.15mil; 52.95mil + 28.1mil; 35.19mil + 28.38mil; 34.85mil + 28.65mil; 34.58mil + 28.99mil; 34.37mil + 29.32mil; 34.22mil + 29.68mil; 34.12mil + 30.11mil; 34.06mil + 30.75mil; 34.12mil + 31.3mil; 34.31mil + 31.72mil; 34.58mil + 32.03mil; 34.98mil + 32.21mil; 35.49mil + 32.3mil; 36.1mil + 32.27mil; 36.41mil + 32.21mil; 36.71mil + 32.09mil; 37.01mil + 31.94mil; 37.38mil + 31.75mil; 37.71mil + 31.51mil; 38.11mil + 18.83mil; 57.03mil + 31.72mil; 76.5mil + 31.84mil; 76.74mil + 31.97mil; 76.95mil + 32.06mil; 77.17mil + 32.15mil; 77.38mil + 32.18mil; 77.56mil + 32.21mil; 77.74mil + 32.12mil; 78.44mil + 31.94mil; 78.99mil + 31.63mil; 79.45mil + 31.21mil; 79.75mil + 30.66mil; 79.93mil + 29.99mil; 80.0mil + 29.56mil; 79.96mil + 29.17mil; 79.87mil + 28.8mil; 79.69mil + 28.47mil; 79.45mil + 28.16mil; 79.11mil + 27.86mil; 78.69mil + 16.15mil; 60.98mil + 4.29mil; 78.84mil + 4.01mil; 79.2mil + 3.71mil; 79.51mil + 3.43mil; 79.72mil + 3.13mil; 79.87mil + 2.8mil; 79.96mil + 2.46mil; 80.0mil + 1.7mil; 79.96mil + 1.09mil; 79.78mil + 0.61mil; 79.48mil + 0.27mil; 79.08mil + 0.06mil; 78.53mil + 0.0mil; 77.87mil + 0.0mil; 77.65mil + 0.06mil; 77.38mil + 0.15mil; 77.11mil + 0.27mil; 76.8mil + 0.45mil; 76.5mil + 0.67mil; 76.13mil + } + } + height = 63.33mil + } + ha:Y { + width=32mil; delta=12.0mil; + li:objects { + li:simplepoly.0 { + 13.96mil; 56.85mil + 13.56mil; 56.33mil + 12.47mil; 54.75mil + 10.61mil; 52.1mil + 8.03mil; 48.42mil + 4.68mil; 43.68mil + 0.48mil; 37.65mil + 0.33mil; 37.44mil + 0.21mil; 37.2mil + 0.12mil; 36.98mil + 0.03mil; 36.74mil + 0.0mil; 36.5mil + 0.0mil; 36.25mil + 0.06mil; 35.62mil + 0.24mil; 35.07mil + 0.57mil; 34.64mil + 1.03mil; 34.34mil + 1.64mil; 34.16mil + 2.4mil; 34.06mil + 2.73mil; 34.12mil + 3.07mil; 34.22mil + 3.4mil; 34.4mil + 3.71mil; 34.67mil + 4.01mil; 35.01mil + 4.35mil; 35.4mil + 16.09mil; 52.44mil + 27.95mil; 35.13mil + 28.19mil; 34.82mil + 28.5mil; 34.55mil + 28.8mil; 34.34mil + 29.14mil; 34.19mil + 29.47mil; 34.12mil + 29.87mil; 34.06mil + 30.57mil; 34.12mil + 31.14mil; 34.31mil + 31.57mil; 34.58mil + 31.91mil; 34.98mil + 32.09mil; 35.49mil + 32.18mil; 36.13mil + 32.15mil; 36.41mil + 32.09mil; 36.68mil + 32.03mil; 36.92mil + 31.91mil; 37.2mil + 31.75mil; 37.5mil + 31.6mil; 37.78mil + 18.31mil; 56.97mil + 18.31mil; 77.41mil + 18.25mil; 78.2mil + 18.07mil; 78.87mil + 17.76mil; 79.36mil + 17.37mil; 79.72mil + 16.82mil; 79.93mil + 16.18mil; 80.0mil + 15.48mil; 79.93mil + 14.93mil; 79.72mil + 14.51mil; 79.36mil + 14.2mil; 78.84mil + 14.02mil; 78.2mil + 13.96mil; 77.35mil + } + } + height = 63.33mil + } + ha:Z { + width=27mil; delta=12.0mil; + li:objects { + li:simplepoly.0 { + 5.87mil; 75.68mil + 25.18mil; 75.68mil + 25.88mil; 75.77mil + 26.49mil; 75.95mil + 26.95mil; 76.25mil + 27.28mil; 76.68mil + 27.46mil; 77.26mil + 27.56mil; 77.96mil + 27.46mil; 78.6mil + 27.28mil; 79.11mil + 26.95mil; 79.51mil + 26.49mil; 79.78mil + 25.88mil; 79.96mil + 25.15mil; 80.0mil + 2.31mil; 80.0mil + 1.58mil; 79.96mil + 1.0mil; 79.78mil + 0.57mil; 79.48mil + 0.24mil; 79.05mil + 0.06mil; 78.5mil + 0.0mil; 77.8mil + 0.0mil; 77.53mil + 0.06mil; 77.23mil + 0.15mil; 76.89mil + 0.3mil; 76.56mil + 0.45mil; 76.16mil + 0.7mil; 75.74mil + 21.56mil; 38.47mil + 2.61mil; 38.47mil + 1.82mil; 38.41mil + 1.18mil; 38.23mil + 0.7mil; 37.9mil + 0.33mil; 37.44mil + 0.12mil; 36.83mil + 0.06mil; 36.07mil + 0.12mil; 35.46mil + 0.33mil; 34.98mil + 0.7mil; 34.58mil + 1.21mil; 34.31mil + 1.85mil; 34.12mil + 2.7mil; 34.06mil + 24.6mil; 34.06mil + 25.46mil; 34.12mil + 26.16mil; 34.31mil + 26.73mil; 34.58mil + 27.13mil; 34.98mil + 27.37mil; 35.46mil + 27.46mil; 36.07mil + 27.43mil; 36.38mil + 27.4mil; 36.68mil + 27.34mil; 36.98mil + 27.22mil; 37.29mil + 27.13mil; 37.59mil + 26.98mil; 37.87mil + } + } + height = 63.33mil + } + ha:[ { + width=8mil; delta=12.0mil; + li:objects { + li:simplepoly.0 { + 0.0mil; 31.81mil + 0.06mil; 31.11mil + 0.24mil; 30.54mil + 0.55mil; 30.08mil + 0.97mil; 29.74mil + 1.52mil; 29.56mil + 2.25mil; 29.47mil + 2.34mil; 29.47mil + 2.7mil; 29.47mil + 3.31mil; 29.47mil + 4.13mil; 29.47mil + 5.23mil; 29.47mil + 6.6mil; 29.47mil + 7.3mil; 29.53mil + 7.88mil; 29.71mil + 8.33mil; 30.02mil + 8.67mil; 30.44mil + 8.85mil; 30.99mil + 8.94mil; 31.66mil + 8.85mil; 32.36mil + 8.67mil; 32.91mil + 8.36mil; 33.36mil + 7.94mil; 33.67mil + 7.36mil; 33.85mil + 6.66mil; 33.91mil + 4.44mil; 33.91mil + 4.44mil; 80.36mil + 6.63mil; 80.36mil + 7.33mil; 80.39mil + 7.91mil; 80.57mil + 8.33mil; 80.85mil + 8.67mil; 81.24mil + 8.85mil; 81.76mil + 8.94mil; 82.43mil + 8.85mil; 83.1mil + 8.67mil; 83.65mil + 8.3mil; 84.07mil + 7.85mil; 84.38mil + 7.24mil; 84.56mil + 6.48mil; 84.65mil + 2.13mil; 84.65mil + 1.46mil; 84.56mil + 0.94mil; 84.38mil + 0.51mil; 84.07mil + 0.21mil; 83.65mil + 0.06mil; 83.1mil + 0.0mil; 82.43mil + 0.0mil; 81.03mil + 0.0mil; 76.89mil + 0.0mil; 69.93mil + 0.0mil; 60.19mil + 0.0mil; 47.69mil + } + } + height = 63.33mil + } + ha:\\ { + width=22mil; delta=12.0mil; + li:objects { + li:simplepoly.0 { + 22.69mil; 77.96mil + 22.6mil; 78.6mil + 22.41mil; 79.11mil + 22.08mil; 79.51mil + 21.62mil; 79.78mil + 21.05mil; 79.96mil + 20.32mil; 80.0mil + 19.86mil; 79.96mil + 19.46mil; 79.81mil + 19.1mil; 79.54mil + 18.76mil; 79.17mil + 18.43mil; 78.72mil + 18.16mil; 78.11mil + 0.3mil; 37.68mil + 0.18mil; 37.44mil + 0.12mil; 37.2mil + 0.06mil; 36.92mil + 0.03mil; 36.68mil + 0.0mil; 36.41mil + 0.0mil; 36.13mil + 0.03mil; 35.52mil + 0.21mil; 35.01mil + 0.51mil; 34.61mil + 0.94mil; 34.31mil + 1.49mil; 34.12mil + 2.19mil; 34.06mil + 2.61mil; 34.12mil + 3.04mil; 34.28mil + 3.43mil; 34.55mil + 3.8mil; 34.92mil + 4.1mil; 35.4mil + 4.44mil; 35.98mil + 22.14mil; 76.04mil + 22.29mil; 76.47mil + 22.41mil; 76.83mil + 22.54mil; 77.17mil + 22.6mil; 77.47mil + 22.66mil; 77.71mil + } + } + height = 63.33mil + } + ha:] { + width=8mil; delta=12.0mil; + li:objects { + li:simplepoly.0 { + 8.94mil; 31.81mil + 8.94mil; 33.21mil + 8.94mil; 37.38mil + 8.94mil; 44.35mil + 8.94mil; 54.08mil + 8.94mil; 66.58mil + 8.94mil; 82.43mil + 8.88mil; 83.1mil + 8.7mil; 83.65mil + 8.39mil; 84.07mil + 8.0mil; 84.38mil + 7.45mil; 84.56mil + 6.81mil; 84.65mil + 2.46mil; 84.65mil + 1.7mil; 84.56mil + 1.09mil; 84.38mil + 0.61mil; 84.07mil + 0.27mil; 83.65mil + 0.06mil; 83.1mil + 0.0mil; 82.43mil + 0.06mil; 81.79mil + 0.24mil; 81.27mil + 0.54mil; 80.88mil + 1.0mil; 80.57mil + 1.58mil; 80.39mil + 2.31mil; 80.36mil + 4.5mil; 80.36mil + 4.5mil; 33.91mil + 2.28mil; 33.91mil + 1.58mil; 33.85mil + 1.0mil; 33.67mil + 0.54mil; 33.36mil + 0.24mil; 32.94mil + 0.06mil; 32.39mil + 0.0mil; 31.66mil + 0.06mil; 31.02mil + 0.24mil; 30.47mil + 0.57mil; 30.05mil + 1.0mil; 29.74mil + 1.58mil; 29.56mil + 2.34mil; 29.47mil + 6.69mil; 29.47mil + 7.36mil; 29.56mil + 7.91mil; 29.74mil + 8.36mil; 30.08mil + 8.67mil; 30.51mil + 8.85mil; 31.08mil + } + } + height = 63.33mil + } + ha:^ { + width=18mil; delta=12.0mil; + li:objects { + li:simplepoly.0 { + 13.9mil; 35.25mil + 13.75mil; 35.13mil + 13.35mil; 34.73mil + 12.71mil; 34.06mil + 11.8mil; 33.15mil + 10.64mil; 31.97mil + 9.18mil; 30.44mil + 4.38mil; 35.1mil + 3.95mil; 35.49mil + 3.56mil; 35.8mil + 3.19mil; 36.04mil + 2.86mil; 36.22mil + 2.52mil; 36.31mil + 2.22mil; 36.35mil + 1.52mil; 36.31mil + 0.97mil; 36.13mil + 0.54mil; 35.86mil + 0.24mil; 35.49mil + 0.06mil; 35.01mil + 0.0mil; 34.37mil + 0.0mil; 34.06mil + 0.09mil; 33.76mil + 0.24mil; 33.43mil + 0.42mil; 33.09mil + 0.7mil; 32.73mil + 1.03mil; 32.36mil + 7.05mil; 26.16mil + 7.39mil; 25.82mil + 7.75mil; 25.55mil + 8.12mil; 25.33mil + 8.45mil; 25.18mil + 8.82mil; 25.09mil + 9.18mil; 25.03mil + 9.46mil; 25.09mil + 9.76mil; 25.18mil + 10.1mil; 25.33mil + 10.43mil; 25.55mil + 10.76mil; 25.82mil + 11.16mil; 26.16mil + 17.09mil; 32.12mil + 17.4mil; 32.48mil + 17.67mil; 32.85mil + 17.88mil; 33.21mil + 18.03mil; 33.58mil + 18.13mil; 33.94mil + 18.19mil; 34.31mil + 18.1mil; 34.95mil + 17.91mil; 35.46mil + 17.61mil; 35.86mil + 17.15mil; 36.13mil + 16.57mil; 36.31mil + 15.87mil; 36.35mil + 15.54mil; 36.35mil + 15.24mil; 36.25mil + 14.9mil; 36.1mil + 14.57mil; 35.89mil + 14.23mil; 35.62mil + } + } + height = 63.33mil + } + ha:_ { + width=22mil; delta=12.0mil; + li:objects { + li:simplepoly.0 { + 2.19mil; 80.0mil + 2.67mil; 80.0mil + 4.19mil; 80.0mil + 6.75mil; 80.0mil + 10.31mil; 80.0mil + 14.87mil; 80.0mil + 20.68mil; 80.0mil + 21.32mil; 80.06mil + 21.87mil; 80.24mil + 22.29mil; 80.57mil + 22.6mil; 81.0mil + 22.78mil; 81.58mil + 22.87mil; 82.34mil + 22.78mil; 82.95mil + 22.6mil; 83.46mil + 22.29mil; 83.86mil + 21.87mil; 84.13mil + 21.29mil; 84.31mil + 20.59mil; 84.38mil + 2.25mil; 84.38mil + 1.55mil; 84.28mil + 1.0mil; 84.1mil + 0.54mil; 83.8mil + 0.24mil; 83.34mil + 0.06mil; 82.76mil + 0.0mil; 82.06mil + 0.03mil; 81.42mil + 0.21mil; 80.91mil + 0.51mil; 80.51mil + 0.94mil; 80.21mil + 1.49mil; 80.03mil + } + } + height = 63.33mil + } + ha:` { + width=13mil; delta=12.0mil; + li:objects { + li:simplepoly.0 { + 3.92mil; 27.46mil + 4.13mil; 27.65mil + 4.83mil; 28.19mil + 6.02mil; 29.08mil + 7.66mil; 30.29mil + 9.76mil; 31.87mil + 12.47mil; 33.88mil + 12.77mil; 34.16mil + 13.05mil; 34.46mil + 13.26mil; 34.76mil + 13.41mil; 35.1mil + 13.5mil; 35.43mil + 13.56mil; 35.8mil + 13.5mil; 36.5mil + 13.32mil; 37.08mil + 13.05mil; 37.53mil + 12.65mil; 37.84mil + 12.13mil; 38.02mil + 11.49mil; 38.08mil + 11.22mil; 38.08mil + 10.95mil; 38.02mil + 10.67mil; 37.96mil + 10.4mil; 37.84mil + 10.1mil; 37.68mil + 9.82mil; 37.47mil + 9.58mil; 37.32mil + 8.85mil; 36.77mil + 7.66mil; 35.86mil + 5.99mil; 34.61mil + 3.86mil; 33.0mil + 1.15mil; 30.93mil + 0.79mil; 30.66mil + 0.48mil; 30.35mil + 0.27mil; 30.08mil + 0.12mil; 29.78mil + 0.03mil; 29.44mil + 0.0mil; 29.11mil + 0.06mil; 28.38mil + 0.24mil; 27.8mil + 0.54mil; 27.31mil + 1.0mil; 26.98mil + 1.58mil; 26.79mil + 2.31mil; 26.7mil + 2.52mil; 26.73mil + 2.76mil; 26.79mil + 3.01mil; 26.92mil + 3.28mil; 27.04mil + 3.59mil; 27.25mil + } + } + height = 63.33mil + } + ha:a { + width=22mil; delta=12.0mil; + li:objects { + li:simplepoly.1 { + 4.68mil; 52.16mil + 3.98mil; 52.1mil + 3.4mil; 51.92mil + 2.95mil; 51.62mil + 2.64mil; 51.19mil + 2.46mil; 50.64mil + 2.4mil; 49.91mil + 2.46mil; 49.27mil + 2.64mil; 48.73mil + 2.95mil; 48.3mil + 3.37mil; 48.0mil + 3.95mil; 47.81mil + 4.68mil; 47.72mil + 14.14mil; 47.72mil + 15.39mil; 47.81mil + 16.57mil; 48.06mil + 17.67mil; 48.45mil + 18.67mil; 49.03mil + 19.62mil; 49.73mil + 20.53mil; 50.64mil + 21.26mil; 51.65mil + 21.87mil; 52.62mil + 22.35mil; 53.62mil + 22.69mil; 54.63mil + 22.9mil; 55.63mil + 22.99mil; 56.69mil + 22.99mil; 77.14mil + 22.96mil; 77.56mil + 22.9mil; 77.96mil + 22.81mil; 78.32mil + 22.66mil; 78.66mil + 22.51mil; 78.93mil + 22.29mil; 79.2mil + 22.02mil; 79.45mil + 21.75mil; 79.63mil + 21.44mil; 79.78mil + 21.14mil; 79.9mil + 20.77mil; 79.96mil + 20.38mil; 80.0mil + 8.82mil; 80.0mil + 7.69mil; 79.93mil + 6.6mil; 79.69mil + 5.56mil; 79.33mil + 4.59mil; 78.78mil + 3.62mil; 78.08mil + 2.7mil; 77.2mil + 1.88mil; 76.25mil + 1.21mil; 75.28mil + 0.67mil; 74.25mil + 0.3mil; 73.18mil + 0.06mil; 72.09mil + 0.0mil; 70.87mil + 0.06mil; 69.62mil + 0.27mil; 68.41mil + 0.61mil; 67.28mil + 1.09mil; 66.22mil + 1.73mil; 65.24mil + 2.55mil; 64.27mil + 3.4mil; 63.48mil + 4.38mil; 62.81mil + 5.38mil; 62.26mil + 6.48mil; 61.9mil + 7.66mil; 61.65mil + 8.94mil; 61.56mil + 9.55mil; 65.97mil + 8.73mil; 66.03mil + 8.0mil; 66.15mil + 7.33mil; 66.37mil + 6.75mil; 66.64mil + 6.23mil; 67.01mil + 5.78mil; 67.46mil + 5.38mil; 67.98mil + 5.08mil; 68.5mil + 4.83mil; 69.04mil + 4.65mil; 69.62mil + 4.53mil; 70.2mil + 4.5mil; 70.81mil + 4.53mil; 71.48mil + 4.65mil; 72.09mil + 4.83mil; 72.63mil + 5.11mil; 73.15mil + 5.47mil; 73.64mil + 5.93mil; 74.09mil + 6.38mil; 74.49mil + 6.9mil; 74.82mil + 7.42mil; 75.07mil + 7.97mil; 75.25mil + 8.51mil; 75.37mil + 9.12mil; 75.4mil + 18.43mil; 75.4mil + 18.43mil; 65.97mil + 9.55mil; 65.97mil + 8.94mil; 61.56mil + 18.43mil; 61.56mil + 18.43mil; 55.96mil + 18.37mil; 55.6mil + 18.28mil; 55.2mil + 18.07mil; 54.78mil + 17.82mil; 54.38mil + 17.49mil; 53.96mil + 17.06mil; 53.5mil + 16.57mil; 53.11mil + 16.12mil; 52.8mil + 15.6mil; 52.53mil + 15.08mil; 52.35mil + 14.57mil; 52.22mil + 14.02mil; 52.16mil + } + } + height = 63.33mil + } + ha:b { + width=22mil; delta=12.0mil; + li:objects { + li:simplepoly.1 { + 2.74mil; 79.87mil + 1.88mil; 79.84mil + 1.21mil; 79.66mil + 0.67mil; 79.39mil + 0.3mil; 78.99mil + 0.06mil; 78.47mil + 0.0mil; 77.8mil + 0.0mil; 36.16mil + 0.03mil; 35.49mil + 0.21mil; 34.95mil + 0.51mil; 34.49mil + 0.91mil; 34.19mil + 1.43mil; 34.0mil + 2.1mil; 33.91mil + 2.77mil; 34.0mil + 3.31mil; 34.19mil + 3.77mil; 34.49mil + 4.07mil; 34.92mil + 4.26mil; 35.46mil + 4.35mil; 36.16mil + 4.35mil; 47.81mil + + 13.23mil; 75.49mil + 14.81mil; 75.37mil + 16.12mil; 74.95mil + 17.12mil; 74.22mil + 17.85mil; 73.24mil + 18.28mil; 71.96mil + 18.46mil; 70.32mil + 18.46mil; 69.99mil + 18.46mil; 68.89mil + 18.46mil; 67.1mil + 18.46mil; 64.6mil + 18.46mil; 61.38mil + 18.46mil; 57.27mil + 18.4mil; 56.54mil + 18.31mil; 55.84mil + 18.1mil; 55.2mil + 17.85mil; 54.6mil + 17.52mil; 54.08mil + 17.09mil; 53.56mil + 16.61mil; 53.17mil + 16.06mil; 52.83mil + 15.51mil; 52.56mil + 14.87mil; 52.35mil + 14.2mil; 52.22mil + 13.47mil; 52.16mil + 4.29mil; 52.16mil + 4.29mil; 75.49mil + 13.23mil; 75.49mil + + 4.35mil; 47.81mil + 14.39mil; 47.81mil + 15.63mil; 47.93mil + 16.82mil; 48.21mil + 17.94mil; 48.7mil + 19.04mil; 49.36mil + 20.07mil; 50.22mil + 21.08mil; 51.28mil + 21.59mil; 52.01mil + 22.02mil; 52.8mil + 22.35mil; 53.59mil + 22.6mil; 54.44mil + 22.75mil; 55.33mil + 22.81mil; 56.27mil + 22.81mil; 71.54mil + 22.72mil; 72.69mil + 22.51mil; 73.79mil + 22.14mil; 74.79mil + 21.66mil; 75.74mil + 20.99mil; 76.65mil + 20.2mil; 77.47mil + 19.28mil; 78.2mil + 18.31mil; 78.81mil + 17.24mil; 79.26mil + 16.15mil; 79.6mil + 14.93mil; 79.81mil + 13.66mil; 79.87mil + } + } + height = 63.33mil + } + ha:c { + width=18mil; delta=12.0mil; + li:objects { + li:simplepoly.0 { + 15.91mil; 47.69mil + 16.61mil; 47.75mil + 17.19mil; 47.93mil + 17.61mil; 48.24mil + 17.95mil; 48.63mil + 18.13mil; 49.18mil + 18.22mil; 49.82mil + 18.13mil; 50.52mil + 17.95mil; 51.1mil + 17.64mil; 51.55mil + 17.19mil; 51.86mil + 16.61mil; 52.04mil + 15.91mil; 52.1mil + 15.73mil; 52.1mil + 15.24mil; 52.1mil + 14.39mil; 52.1mil + 13.23mil; 52.1mil + 11.74mil; 52.1mil + 9.85mil; 52.1mil + 8.18mil; 52.25mil + 6.84mil; 52.68mil + 5.78mil; 53.38mil + 5.05mil; 54.35mil + 4.59mil; 55.63mil + 4.44mil; 57.21mil + 4.44mil; 57.58mil + 4.44mil; 58.61mil + 4.44mil; 60.38mil + 4.44mil; 62.81mil + 4.44mil; 65.94mil + 4.44mil; 69.9mil + 4.56mil; 71.6mil + 4.99mil; 72.97mil + 5.69mil; 74.03mil + 6.66mil; 74.79mil + 7.94mil; 75.25mil + 9.55mil; 75.4mil + 15.76mil; 75.4mil + 16.49mil; 75.49mil + 17.09mil; 75.68mil + 17.58mil; 76.01mil + 17.92mil; 76.44mil + 18.13mil; 77.01mil + 18.22mil; 77.74mil + 18.13mil; 78.41mil + 17.95mil; 78.93mil + 17.61mil; 79.36mil + 17.19mil; 79.66mil + 16.61mil; 79.81mil + 15.88mil; 79.87mil + 15.66mil; 79.87mil + 15.09mil; 79.87mil + 14.11mil; 79.87mil + 12.74mil; 79.87mil + 10.98mil; 79.87mil + 8.79mil; 79.87mil + 7.6mil; 79.81mil + 6.48mil; 79.6mil + 5.38mil; 79.23mil + 4.38mil; 78.72mil + 3.41mil; 78.05mil + 2.49mil; 77.2mil + 1.73mil; 76.34mil + 1.09mil; 75.4mil + 0.61mil; 74.43mil + 0.27mil; 73.36mil + 0.06mil; 72.24mil + 0.0mil; 70.99mil + 0.0mil; 70.63mil + 0.0mil; 69.47mil + 0.0mil; 67.58mil + 0.0mil; 64.91mil + 0.0mil; 61.47mil + 0.0mil; 57.09mil + 0.06mil; 55.78mil + 0.24mil; 54.54mil + 0.58mil; 53.38mil + 1.06mil; 52.35mil + 1.64mil; 51.4mil + 2.43mil; 50.49mil + 3.38mil; 49.67mil + 4.44mil; 48.97mil + 5.54mil; 48.42mil + 6.75mil; 48.03mil + 8.03mil; 47.78mil + 9.43mil; 47.69mil + 9.58mil; 47.69mil + 10.13mil; 47.69mil + 11.01mil; 47.69mil + 12.26mil; 47.69mil + 13.87mil; 47.69mil + } + } + height = 63.33mil + } + ha:d { + width=22mil; delta=12.0mil; + li:objects { + li:simplepoly.1 { + 18.4mil; 36.25mil + 18.46mil; 35.55mil + 18.65mil; 34.98mil + 18.95mil; 34.52mil + 19.38mil; 34.19mil + 19.92mil; 34.0mil + 20.62mil; 33.91mil + 21.29mil; 34.0mil + 21.84mil; 34.22mil + 22.27mil; 34.55mil + 22.57mil; 35.04mil + 22.75mil; 35.65mil + 22.84mil; 36.41mil + 22.84mil; 77.14mil + 22.75mil; 78.02mil + 22.51mil; 78.72mil + 22.11mil; 79.3mil + 21.57mil; 79.69mil + 20.84mil; 79.93mil + 19.95mil; 80.0mil + 9.4mil; 80.0mil + 8.12mil; 79.93mil + 6.93mil; 79.75mil + 5.81mil; 79.39mil + 4.81mil; 78.93mil + 3.86mil; 78.32mil + 2.98mil; 77.53mil + 2.07mil; 76.53mil + 1.31mil; 75.49mil + 0.73mil; 74.43mil + 0.33mil; 73.33mil + 0.06mil; 72.18mil + 0.0mil; 70.96mil + 0.0mil; 56.45mil + 0.03mil; 55.51mil + 0.21mil; 54.57mil + 0.52mil; 53.62mil + 0.91mil; 52.74mil + 1.43mil; 51.86mil + 2.1mil; 50.95mil + 3.01mil; 49.97mil + 4.08mil; 49.18mil + 5.26mil; 48.54mil + 6.54mil; 48.12mil + 7.94mil; 47.84mil + 9.55mil; 47.72mil + 9.58mil; 52.13mil + 7.97mil; 52.31mil + 6.66mil; 52.8mil + 5.63mil; 53.59mil + 4.9mil; 54.72mil + 4.47mil; 56.15mil + 4.32mil; 57.97mil + 4.32mil; 58.31mil + 4.32mil; 59.31mil + 4.32mil; 60.95mil + 4.32mil; 63.27mil + 4.32mil; 66.22mil + 4.32mil; 69.96mil + 4.47mil; 71.63mil + 4.93mil; 73.0mil + 5.69mil; 74.03mil + 6.75mil; 74.79mil + 8.15mil; 75.25mil + 9.92mil; 75.4mil + 10.13mil; 75.4mil + 10.83mil; 75.4mil + 11.98mil; 75.4mil + 13.63mil; 75.4mil + 15.73mil; 75.4mil + 18.4mil; 75.4mil + 18.4mil; 74.76mil + 18.4mil; 72.85mil + 18.4mil; 69.65mil + 18.4mil; 65.18mil + 18.4mil; 59.43mil + 18.4mil; 52.13mil + 18.16mil; 52.13mil + 17.43mil; 52.13mil + 16.21mil; 52.13mil + 14.51mil; 52.13mil + 12.32mil; 52.13mil + 9.58mil; 52.13mil + 9.55mil; 47.72mil + 18.4mil; 47.72mil + } + } + height = 63.33mil + } + ha:e { + width=22mil; delta=12.0mil; + li:objects { + li:simplepoly.1 { + 0.0mil; 58.76mil + 0.09mil; 57.21mil + 0.43mil; 55.75mil + 0.97mil; 54.35mil + 1.73mil; 53.04mil + 2.71mil; 51.83mil + 3.98mil; 50.61mil + 5.14mil; 49.73mil + 6.36mil; 49.0mil + 7.6mil; 48.45mil + 8.88mil; 48.03mil + 10.19mil; 47.78mil + 11.62mil; 47.69mil + 13.2mil; 47.81mil + 14.72mil; 48.12mil + 16.15mil; 48.63mil + 17.52mil; 49.36mil + 18.8mil; 50.31mil + 20.04mil; 51.49mil + 20.9mil; 52.56mil + 21.6mil; 53.59mil + 22.14mil; 54.66mil + 22.54mil; 55.75mil + 22.78mil; 56.85mil + 22.87mil; 57.97mil + 22.87mil; 63.75mil + 22.81mil; 64.42mil + 22.63mil; 64.97mil + 22.36mil; 65.39mil + 21.96mil; 65.7mil + 21.44mil; 65.88mil + 20.84mil; 65.94mil + 4.5mil; 65.94mil + 4.5mil; 69.96mil + 4.62mil; 71.66mil + 5.02mil; 73.06mil + 4.56mil; 61.62mil + 18.52mil; 61.62mil + 18.46mil; 60.13mil + 18.34mil; 58.79mil + 18.13mil; 57.58mil + 17.85mil; 56.51mil + 17.46mil; 55.6mil + 17.0mil; 54.81mil + 16.3mil; 54.02mil + 15.54mil; 53.38mil + 14.72mil; 52.86mil + 13.81mil; 52.5mil + 12.81mil; 52.28mil + 11.71mil; 52.19mil + 10.65mil; 52.28mil + 9.64mil; 52.5mil + 8.7mil; 52.86mil + 7.79mil; 53.38mil + 6.9mil; 54.05mil + 6.08mil; 54.87mil + 5.6mil; 55.54mil + 5.23mil; 56.39mil + 4.93mil; 57.39mil + 4.71mil; 58.61mil + 4.59mil; 60.01mil + 4.56mil; 61.62mil + 5.02mil; 73.06mil + 5.66mil; 74.15mil + 6.57mil; 74.95mil + 7.76mil; 75.4mil + 9.25mil; 75.55mil + 20.29mil; 75.55mil + 21.08mil; 75.65mil + 21.75mil; 75.83mil + 22.27mil; 76.13mil + 22.66mil; 76.56mil + 22.87mil; 77.11mil + 22.96mil; 77.8mil + 22.87mil; 78.47mil + 22.66mil; 79.02mil + 22.3mil; 79.45mil + 21.78mil; 79.75mil + 21.14mil; 79.93mil + 20.32mil; 80.0mil + 9.12mil; 80.0mil + 7.91mil; 79.93mil + 6.75mil; 79.69mil + 5.66mil; 79.3mil + 4.62mil; 78.72mil + 3.62mil; 77.99mil + 2.65mil; 77.04mil + 1.82mil; 76.1mil + 1.16mil; 75.1mil + 0.64mil; 74.0mil + 0.27mil; 72.88mil + 0.06mil; 71.69mil + 0.0mil; 70.38mil + 0.0mil; 70.08mil + 0.0mil; 69.14mil + 0.0mil; 67.52mil + 0.0mil; 65.3mil + 0.0mil; 62.41mil + } + } + height = 63.33mil + } + ha:f { + width=18mil; delta=12.0mil; + li:objects { + li:simplepoly.0 { + 15.88mil; 33.82mil + 16.58mil; 33.91mil + 17.15mil; 34.09mil + 17.58mil; 34.4mil + 17.91mil; 34.82mil + 18.1mil; 35.37mil + 18.19mil; 36.04mil + 18.1mil; 36.74mil + 17.88mil; 37.32mil + 17.55mil; 37.78mil + 17.06mil; 38.08mil + 16.45mil; 38.26mil + 15.69mil; 38.32mil + 14.35mil; 38.32mil + 13.66mil; 38.38mil + 13.02mil; 38.47mil + 12.41mil; 38.66mil + 11.83mil; 38.9mil + 11.25mil; 39.2mil + 10.74mil; 39.57mil + 10.19mil; 40.09mil + 9.76mil; 40.6mil + 9.43mil; 41.21mil + 9.18mil; 41.85mil + 9.03mil; 42.52mil + 9.0mil; 43.28mil + 9.0mil; 47.69mil + 15.66mil; 47.69mil + 16.42mil; 47.78mil + 17.06mil; 47.96mil + 17.55mil; 48.27mil + 17.91mil; 48.7mil + 18.13mil; 49.24mil + 18.22mil; 49.94mil + 18.13mil; 50.61mil + 17.91mil; 51.13mil + 17.55mil; 51.55mil + 17.06mil; 51.86mil + 16.42mil; 52.01mil + 15.63mil; 52.07mil + 8.97mil; 52.07mil + 8.97mil; 77.56mil + 8.88mil; 78.29mil + 8.7mil; 78.87mil + 8.36mil; 79.3mil + 7.94mil; 79.63mil + 7.36mil; 79.81mil + 6.63mil; 79.87mil + 5.99mil; 79.81mil + 5.47mil; 79.6mil + 5.08mil; 79.26mil + 4.77mil; 78.78mil + 4.59mil; 78.14mil + 4.56mil; 77.35mil + 4.56mil; 52.07mil + 2.1mil; 52.07mil + 1.46mil; 52.01mil + 0.91mil; 51.83mil + 0.51mil; 51.52mil + 0.21mil; 51.1mil + 0.06mil; 50.55mil + 0.0mil; 49.85mil + 0.06mil; 49.21mil + 0.24mil; 48.66mil + 0.55mil; 48.24mil + 0.97mil; 47.96mil + 1.52mil; 47.78mil + 2.22mil; 47.69mil + 4.56mil; 47.69mil + 4.56mil; 43.07mil + 4.62mil; 41.85mil + 4.83mil; 40.73mil + 5.17mil; 39.63mil + 5.66mil; 38.66mil + 6.29mil; 37.71mil + 7.09mil; 36.83mil + 8.12mil; 35.92mil + 9.18mil; 35.19mil + 10.25mil; 34.61mil + 11.34mil; 34.19mil + 12.47mil; 33.91mil + 13.66mil; 33.82mil + } + } + height = 63.33mil + } + ha:g { + width=22mil; delta=12.0mil; + li:objects { + li:simplepoly.1 { + 9.22mil; 47.84mil + 9.52mil; 47.84mil + 10.43mil; 47.84mil + 11.98mil; 47.84mil + 14.17mil; 47.84mil + 16.94mil; 47.84mil + 20.5mil; 47.84mil + 21.17mil; 47.93mil + 21.75mil; 48.15mil + 22.2mil; 48.48mil + 22.51mil; 48.97mil + 22.69mil; 49.58mil + 22.78mil; 50.34mil + 22.78mil; 51.31mil + 22.78mil; 54.23mil + 22.78mil; 59.04mil + 22.78mil; 65.82mil + 22.78mil; 74.49mil + 22.78mil; 85.5mil + 22.69mil; 86.6mil + 22.48mil; 87.66mil + 22.11mil; 88.69mil + 21.63mil; 89.64mil + 20.99mil; 90.55mil + 20.2mil; 91.43mil + 19.31mil; 92.16mil + 18.37mil; 92.77mil + 17.4mil; 93.23mil + 16.36mil; 93.56mil + 15.27mil; 93.77mil + 14.11mil; 93.87mil + 13.84mil; 93.87mil + 13.05mil; 93.87mil + 11.74mil; 93.87mil + 9.92mil; 93.87mil + 7.57mil; 93.87mil + 4.59mil; 93.87mil + 3.86mil; 93.8mil + 3.25mil; 93.62mil + 2.8mil; 93.32mil + 2.46mil; 92.89mil + 2.28mil; 92.38mil + 2.22mil; 91.71mil + 2.28mil; 91.01mil + 2.49mil; 90.46mil + 2.83mil; 90.0mil + 3.31mil; 89.7mil + 3.92mil; 89.52mil + 4.71mil; 89.45mil + 4.9mil; 89.45mil + 5.54mil; 89.45mil + 6.6mil; 89.45mil + 8.06mil; 89.45mil + 9.98mil; 89.45mil + + 9.58mil; 52.28mil + 8.88mil; 52.35mil + 8.21mil; 52.44mil + 7.6mil; 52.62mil + 7.0mil; 52.89mil + 6.45mil; 53.23mil + 5.9mil; 53.62mil + 5.41mil; 54.11mil + 5.02mil; 54.66mil + 4.71mil; 55.27mil + 4.47mil; 55.9mil + 4.35mil; 56.6mil + 4.32mil; 57.39mil + 4.32mil; 70.08mil + 4.35mil; 70.96mil + 4.44mil; 71.75mil + 4.62mil; 72.48mil + 4.9mil; 73.15mil + 5.23mil; 73.73mil + 5.66mil; 74.25mil + 6.08mil; 74.67mil + 6.6mil; 75.01mil + 7.18mil; 75.25mil + 7.82mil; 75.46mil + 8.55mil; 75.55mil + 9.37mil; 75.58mil + 18.37mil; 75.58mil + 18.37mil; 52.28mil + 9.58mil; 52.28mil + + 9.98mil; 89.45mil + 12.38mil; 89.45mil + 14.14mil; 89.33mil + 15.63mil; 88.97mil + 16.76mil; 88.36mil + 17.58mil; 87.54mil + 18.1mil; 86.47mil + 18.28mil; 85.14mil + 18.28mil; 80.0mil + 18.01mil; 80.0mil + 17.19mil; 80.0mil + 15.82mil; 80.0mil + 13.93mil; 80.0mil + 11.5mil; 80.0mil + 8.43mil; 80.0mil + 7.21mil; 79.93mil + 6.08mil; 79.72mil + 5.05mil; 79.33mil + 4.08mil; 78.81mil + 3.19mil; 78.11mil + 2.34mil; 77.23mil + 1.61mil; 76.31mil + 1.03mil; 75.31mil + 0.58mil; 74.25mil + 0.24mil; 73.15mil + 0.06mil; 71.96mil + 0.0mil; 70.69mil + 0.0mil; 70.32mil + 0.0mil; 69.17mil + 0.0mil; 67.25mil + 0.0mil; 64.57mil + 0.0mil; 61.14mil + 0.0mil; 56.76mil + 0.06mil; 55.57mil + 0.27mil; 54.41mil + 0.61mil; 53.35mil + 1.09mil; 52.35mil + 1.73mil; 51.43mil + 2.55mil; 50.52mil + 3.47mil; 49.73mil + 4.47mil; 49.06mil + 5.57mil; 48.54mil + 6.69mil; 48.15mil + 7.88mil; 47.93mil + } + } + height = 63.33mil + } + ha:h { + width=22mil; delta=12.0mil; + li:objects { + li:simplepoly.0 { + 0.0mil; 36.62mil + 0.06mil; 35.8mil + 0.24mil; 35.13mil + 0.55mil; 34.61mil + 0.97mil; 34.25mil + 1.55mil; 34.0mil + 2.28mil; 33.91mil + 2.92mil; 34.0mil + 3.47mil; 34.22mil + 3.89mil; 34.58mil + 4.16mil; 35.07mil + 4.35mil; 35.71mil + 4.44mil; 36.5mil + 4.44mil; 47.75mil + 13.87mil; 47.75mil + 15.02mil; 47.84mil + 16.18mil; 48.09mil + 17.31mil; 48.45mil + 18.37mil; 49.0mil + 19.4mil; 49.7mil + 20.47mil; 50.58mil + 21.17mil; 51.4mil + 21.78mil; 52.28mil + 22.23mil; 53.26mil + 22.57mil; 54.35mil + 22.75mil; 55.54mil + 22.84mil; 56.85mil + 22.84mil; 77.44mil + 22.78mil; 78.17mil + 22.6mil; 78.78mil + 22.32mil; 79.23mil + 21.93mil; 79.57mil + 21.44mil; 79.75mil + 20.83mil; 79.81mil + 20.1mil; 79.75mil + 19.53mil; 79.57mil + 19.07mil; 79.23mil + 18.74mil; 78.75mil + 18.55mil; 78.17mil + 18.49mil; 77.38mil + 18.49mil; 57.36mil + 18.34mil; 55.78mil + 17.88mil; 54.47mil + 17.15mil; 53.47mil + 16.12mil; 52.74mil + 14.81mil; 52.31mil + 13.14mil; 52.13mil + 4.44mil; 52.13mil + 4.44mil; 77.35mil + 4.35mil; 78.11mil + 4.16mil; 78.72mil + 3.86mil; 79.2mil + 3.4mil; 79.54mil + 2.83mil; 79.75mil + 2.13mil; 79.81mil + 1.46mil; 79.75mil + 0.94mil; 79.54mil + 0.51mil; 79.17mil + 0.21mil; 78.69mil + 0.06mil; 78.02mil + 0.0mil; 77.2mil + } + } + height = 63.33mil + } + ha:i { + width=4mil; delta=12.0mil; + li:objects { + li:simplepoly.0 { + 4.47mil; 50.19mil + 4.47mil; 77.32mil + 4.41mil; 78.11mil + 4.23mil; 78.72mil + 3.92mil; 79.23mil + 3.5mil; 79.57mil + 2.95mil; 79.78mil + 2.28mil; 79.84mil + 1.58mil; 79.78mil + 1.0mil; 79.6mil + 0.55mil; 79.23mil + 0.24mil; 78.78mil + 0.06mil; 78.17mil + 0.0mil; 77.38mil + 0.0mil; 50.22mil + 0.06mil; 49.49mil + 0.24mil; 48.85mil + 0.55mil; 48.36mil + 0.97mil; 48.03mil + 1.52mil; 47.81mil + 2.25mil; 47.72mil + 2.92mil; 47.81mil + 3.47mil; 48.0mil + 3.89mil; 48.36mil + 4.2mil; 48.82mil + 4.38mil; 49.43mil + } + li:simplepoly.1 { + 0.09mil; 36.04mil + 0.12mil; 35.4mil + 0.3mil; 34.89mil + 0.61mil; 34.46mil + 1.0mil; 34.16mil + 1.52mil; 34.0mil + 2.19mil; 33.91mil + 2.86mil; 34.0mil + 3.4mil; 34.19mil + 3.86mil; 34.49mil + 4.16mil; 34.92mil + 4.35mil; 35.49mil + 4.44mil; 36.19mil + 4.44mil; 38.17mil + 4.35mil; 38.9mil + 4.16mil; 39.51mil + 3.86mil; 39.97mil + 3.4mil; 40.3mil + 2.83mil; 40.48mil + 2.13mil; 40.54mil + 1.49mil; 40.48mil + 0.97mil; 40.3mil + 0.58mil; 40.0mil + 0.3mil; 39.57mil + 0.12mil; 39.02mil + 0.09mil; 38.32mil + } + } + height = 63.33mil + } + ha:j { + width=13mil; delta=12.0mil; + li:objects { + li:simplepoly.0 { + 9.15mil; 50.22mil + 9.18mil; 49.55mil + 9.36mil; 48.97mil + 9.67mil; 48.51mil + 10.09mil; 48.21mil + 10.64mil; 48.03mil + 11.34mil; 47.93mil + 11.98mil; 48.03mil + 12.52mil; 48.21mil + 12.98mil; 48.51mil + 13.28mil; 48.94mil + 13.47mil; 49.49mil + 13.56mil; 50.19mil + 13.56mil; 85.2mil + 13.47mil; 86.26mil + 13.25mil; 87.3mil + 12.92mil; 88.27mil + 12.43mil; 89.24mil + 11.82mil; 90.12mil + 11.06mil; 91.04mil + 10.12mil; 91.89mil + 9.15mil; 92.59mil + 8.14mil; 93.14mil + 7.11mil; 93.53mil + 6.05mil; 93.77mil + 4.95mil; 93.87mil + 2.31mil; 93.87mil + 1.61mil; 93.77mil + 1.04mil; 93.59mil + 0.61mil; 93.29mil + 0.28mil; 92.86mil + 0.09mil; 92.31mil + 0.0mil; 91.61mil + 0.06mil; 90.95mil + 0.25mil; 90.4mil + 0.55mil; 89.97mil + 0.98mil; 89.7mil + 1.49mil; 89.52mil + 2.16mil; 89.45mil + 4.8mil; 89.45mil + 5.29mil; 89.39mil + 5.8mil; 89.27mil + 6.29mil; 89.06mil + 6.81mil; 88.76mil + 7.29mil; 88.36mil + 7.84mil; 87.87mil + 8.24mil; 87.39mil + 8.54mil; 86.93mil + 8.81mil; 86.44mil + 9.0mil; 85.93mil + 9.09mil; 85.41mil + 9.15mil; 84.86mil + } + li:simplepoly.1 { + 9.15mil; 36.38mil + 9.21mil; 35.65mil + 9.39mil; 35.04mil + 9.73mil; 34.55mil + 10.18mil; 34.22mil + 10.79mil; 34.0mil + 11.55mil; 33.91mil + 12.16mil; 34.0mil + 12.65mil; 34.22mil + 13.04mil; 34.58mil + 13.32mil; 35.07mil + 13.5mil; 35.74mil + 13.56mil; 36.53mil + 13.56mil; 38.41mil + 13.5mil; 39.08mil + 13.32mil; 39.63mil + 13.01mil; 40.06mil + 12.59mil; 40.36mil + 12.04mil; 40.54mil + 11.37mil; 40.6mil + 10.7mil; 40.57mil + 10.15mil; 40.39mil + 9.7mil; 40.12mil + 9.39mil; 39.72mil + 9.21mil; 39.2mil + 9.15mil; 38.57mil + } + } + height = 63.33mil + } + ha:k { + width=23mil; delta=12.0mil; + li:objects { + li:simplepoly.0 { + 0.0mil; 36.53mil + 0.03mil; 35.8mil + 0.21mil; 35.19mil + 0.51mil; 34.7mil + 0.94mil; 34.37mil + 1.46mil; 34.16mil + 2.16mil; 34.06mil + 2.83mil; 34.16mil + 3.37mil; 34.34mil + 3.8mil; 34.7mil + 4.1mil; 35.16mil + 4.29mil; 35.77mil + 4.38mil; 36.53mil + 4.38mil; 59.55mil + 18.98mil; 48.54mil + 19.28mil; 48.36mil + 19.59mil; 48.21mil + 19.92mil; 48.12mil + 20.23mil; 48.03mil + 20.53mil; 47.96mil + 20.86mil; 47.93mil + 21.5mil; 48.0mil + 22.05mil; 48.18mil + 22.48mil; 48.48mil + 22.75mil; 48.88mil + 22.93mil; 49.43mil + 23.02mil; 50.06mil + 22.99mil; 50.43mil + 22.9mil; 50.73mil + 22.75mil; 51.04mil + 22.57mil; 51.34mil + 22.29mil; 51.62mil + 21.99mil; 51.89mil + 13.17mil; 58.55mil + 22.6mil; 76.59mil + 22.69mil; 76.83mil + 22.78mil; 77.04mil + 22.84mil; 77.26mil + 22.9mil; 77.44mil + 22.93mil; 77.65mil + 22.96mil; 77.84mil + 22.87mil; 78.5mil + 22.69mil; 79.05mil + 22.35mil; 79.48mil + 21.9mil; 79.75mil + 21.32mil; 79.93mil + 20.59mil; 80.0mil + 20.2mil; 79.96mil + 19.86mil; 79.87mil + 19.56mil; 79.72mil + 19.28mil; 79.48mil + 19.01mil; 79.17mil + 18.8mil; 78.78mil + 9.61mil; 61.2mil + 4.53mil; 65.15mil + 4.53mil; 77.59mil + 4.44mil; 78.32mil + 4.26mil; 78.9mil + 3.95mil; 79.33mil + 3.53mil; 79.66mil + 2.98mil; 79.84mil + 2.28mil; 79.9mil + 1.58mil; 79.84mil + 1.0mil; 79.66mil + 0.55mil; 79.36mil + 0.24mil; 78.93mil + 0.06mil; 78.35mil + 0.0mil; 77.62mil + } + } + height = 63.33mil + } + ha:l { + width=9mil; delta=12.0mil; + li:objects { + li:simplepoly.0 { + 0.0mil; 36.44mil + 0.06mil; 35.71mil + 0.24mil; 35.13mil + 0.58mil; 34.64mil + 1.06mil; 34.31mil + 1.64mil; 34.12mil + 2.43mil; 34.03mil + 3.04mil; 34.12mil + 3.56mil; 34.34mil + 3.95mil; 34.67mil + 4.23mil; 35.16mil + 4.41mil; 35.77mil + 4.47mil; 36.53mil + 4.47mil; 37.53mil + 4.47mil; 40.45mil + 4.47mil; 45.35mil + 4.47mil; 52.19mil + 4.47mil; 60.98mil + 4.47mil; 72.12mil + 4.5mil; 73.15mil + 4.68mil; 74.0mil + 4.96mil; 74.64mil + 5.35mil; 75.13mil + 5.87mil; 75.4mil + 6.54mil; 75.49mil + 7.3mil; 75.58mil + 7.91mil; 75.77mil + 8.42mil; 76.07mil + 8.76mil; 76.5mil + 8.97mil; 77.07mil + 9.06mil; 77.77mil + 8.97mil; 78.47mil + 8.79mil; 79.02mil + 8.45mil; 79.45mil + 8.0mil; 79.75mil + 7.42mil; 79.93mil + 6.69mil; 80.0mil + 5.78mil; 79.96mil + 4.93mil; 79.78mil + 4.1mil; 79.48mil + 3.31mil; 79.05mil + 2.55mil; 78.53mil + 1.85mil; 77.84mil + 1.28mil; 77.17mil + 0.82mil; 76.44mil + 0.45mil; 75.65mil + 0.18mil; 74.79mil + 0.03mil; 73.88mil + 0.0mil; 72.85mil + 0.0mil; 71.87mil + 0.0mil; 68.86mil + 0.0mil; 63.87mil + 0.0mil; 56.85mil + 0.0mil; 47.84mil + } + } + height = 63.33mil + } + ha:m { + width=32mil; delta=12.0mil; + li:objects { + li:simplepoly.0 { + 0.0mil; 49.85mil + 0.0mil; 49.52mil + 0.06mil; 49.21mil + 0.18mil; 48.88mil + 0.33mil; 48.6mil + 0.52mil; 48.33mil + 0.79mil; 48.06mil + 0.94mil; 47.93mil + 1.19mil; 47.81mil + 1.46mil; 47.72mil + 1.76mil; 47.66mil + 2.1mil; 47.63mil + 2.52mil; 47.6mil + 3.07mil; 47.6mil + 4.71mil; 47.6mil + 7.45mil; 47.6mil + 11.28mil; 47.6mil + 16.21mil; 47.6mil + 22.48mil; 47.6mil + 23.73mil; 47.69mil + 24.94mil; 47.87mil + 26.07mil; 48.21mil + 27.1mil; 48.66mil + 28.08mil; 49.24mil + 29.02mil; 49.97mil + 29.93mil; 50.95mil + 30.69mil; 51.92mil + 31.3mil; 52.98mil + 31.73mil; 54.05mil + 32.0mil; 55.2mil + 32.09mil; 56.39mil + 32.09mil; 56.97mil + 32.09mil; 58.7mil + 32.09mil; 61.56mil + 32.09mil; 65.55mil + 32.09mil; 70.69mil + 32.09mil; 77.2mil + 32.03mil; 78.02mil + 31.85mil; 78.69mil + 31.54mil; 79.2mil + 31.15mil; 79.6mil + 30.6mil; 79.81mil + 29.96mil; 79.87mil + 29.23mil; 79.81mil + 28.65mil; 79.6mil + 28.2mil; 79.2mil + 27.86mil; 78.69mil + 27.68mil; 77.99mil + 27.62mil; 77.11mil + 27.62mil; 76.56mil + 27.62mil; 74.88mil + 27.62mil; 72.12mil + 27.62mil; 68.22mil + 27.62mil; 63.2mil + 27.62mil; 56.85mil + 27.56mil; 56.18mil + 27.47mil; 55.57mil + 27.28mil; 54.99mil + 27.04mil; 54.47mil + 26.74mil; 53.99mil + 26.34mil; 53.53mil + 25.82mil; 53.11mil + 25.25mil; 52.77mil + 24.67mil; 52.47mil + 24.03mil; 52.28mil + 23.36mil; 52.16mil + 22.63mil; 52.1mil + 18.31mil; 52.1mil + 18.31mil; 77.14mil + 18.25mil; 77.96mil + 18.07mil; 78.63mil + 17.76mil; 79.14mil + 17.34mil; 79.51mil + 16.82mil; 79.72mil + 16.15mil; 79.78mil + 15.39mil; 79.72mil + 14.78mil; 79.54mil + 14.33mil; 79.2mil + 13.99mil; 78.72mil + 13.78mil; 78.14mil + 13.72mil; 77.35mil + 13.72mil; 52.1mil + 4.38mil; 52.1mil + 4.38mil; 77.5mil + 4.32mil; 78.23mil + 4.14mil; 78.81mil + 3.83mil; 79.23mil + 3.41mil; 79.57mil + 2.86mil; 79.75mil + 2.19mil; 79.81mil + 1.52mil; 79.78mil + 0.97mil; 79.6mil + 0.55mil; 79.3mil + 0.24mil; 78.87mil + 0.06mil; 78.35mil + 0.0mil; 77.65mil + } + } + height = 63.33mil + } + ha:n { + width=22mil; delta=12.0mil; + li:objects { + li:simplepoly.0 { + 0.0mil; 49.94mil + 0.06mil; 49.27mil + 0.24mil; 48.7mil + 0.55mil; 48.24mil + 0.97mil; 47.93mil + 1.52mil; 47.75mil + 2.22mil; 47.66mil + 2.52mil; 47.66mil + 3.5mil; 47.66mil + 5.11mil; 47.66mil + 7.36mil; 47.66mil + 10.25mil; 47.66mil + 13.93mil; 47.66mil + 15.12mil; 47.75mil + 16.27mil; 48.0mil + 17.4mil; 48.39mil + 18.49mil; 48.97mil + 19.53mil; 49.7mil + 20.59mil; 50.61mil + 21.26mil; 51.4mil + 21.81mil; 52.25mil + 22.27mil; 53.17mil + 22.57mil; 54.2mil + 22.75mil; 55.27mil + 22.84mil; 56.45mil + 22.84mil; 57.03mil + 22.84mil; 58.7mil + 22.84mil; 61.5mil + 22.84mil; 65.42mil + 22.84mil; 70.47mil + 22.84mil; 76.86mil + 22.78mil; 77.77mil + 22.6mil; 78.5mil + 22.3mil; 79.05mil + 21.9mil; 79.48mil + 21.35mil; 79.72mil + 20.71mil; 79.78mil + 19.98mil; 79.72mil + 19.41mil; 79.48mil + 18.98mil; 79.05mil + 18.65mil; 78.47mil + 18.46mil; 77.74mil + 18.4mil; 76.8mil + 18.4mil; 76.25mil + 18.4mil; 74.61mil + 18.4mil; 71.87mil + 18.4mil; 68.04mil + 18.4mil; 63.08mil + 18.4mil; 56.82mil + 18.34mil; 56.12mil + 18.25mil; 55.48mil + 18.1mil; 54.9mil + 17.85mil; 54.38mil + 17.58mil; 53.96mil + 17.22mil; 53.53mil + 16.73mil; 53.14mil + 16.21mil; 52.8mil + 15.73mil; 52.56mil + 15.18mil; 52.35mil + 14.63mil; 52.25mil + 14.08mil; 52.19mil + 13.81mil; 52.19mil + 12.99mil; 52.19mil + 11.65mil; 52.19mil + 9.76mil; 52.19mil + 7.33mil; 52.19mil + 4.29mil; 52.19mil + 4.29mil; 77.2mil + 4.23mil; 77.99mil + 4.04mil; 78.63mil + 3.74mil; 79.11mil + 3.35mil; 79.48mil + 2.8mil; 79.69mil + 2.16mil; 79.75mil + 1.49mil; 79.69mil + 0.94mil; 79.48mil + 0.52mil; 79.14mil + 0.24mil; 78.66mil + 0.06mil; 78.02mil + 0.0mil; 77.23mil + 0.0mil; 76.5mil + 0.0mil; 74.25mil + 0.0mil; 70.5mil + 0.0mil; 65.24mil + 0.0mil; 58.49mil + } + } + height = 63.33mil + } + ha:o { + width=22mil; delta=12.0mil; + li:objects { + li:simplepoly.1 { + 11.04mil; 47.66mil + 12.65mil; 47.75mil + 14.2mil; 48.03mil + 15.63mil; 48.45mil + 16.97mil; 49.09mil + 18.19mil; 49.88mil + 19.38mil; 50.85mil + 20.41mil; 52.01mil + 21.23mil; 53.17mil + 21.9mil; 54.32mil + 22.39mil; 55.54mil + 22.66mil; 56.76mil + 22.78mil; 58.03mil + 22.78mil; 68.62mil + 22.66mil; 70.26mil + 22.36mil; 71.81mil + 21.87mil; 73.24mil + 21.14mil; 74.58mil + 20.23mil; 75.8mil + 19.1mil; 76.95mil + 17.98mil; 77.8mil + 16.82mil; 78.5mil + 15.57mil; 79.05mil + 14.27mil; 79.45mil + 12.87mil; 79.69mil + 11.38mil; 79.75mil + 9.82mil; 79.69mil + 8.36mil; 79.45mil + 7.03mil; 79.05mil + 5.81mil; 78.47mil + 4.71mil; 77.77mil + 3.68mil; 76.83mil + 2.55mil; 75.58mil + 1.64mil; 74.28mil + 0.91mil; 72.91mil + 0.39mil; 71.51mil + 0.09mil; 70.05mil + 0.0mil; 68.47mil + 0.0mil; 58.52mil + 0.09mil; 56.94mil + 0.46mil; 55.45mil + 1.03mil; 54.02mil + 1.85mil; 52.68mil + 2.89mil; 51.43mil + 4.23mil; 50.19mil + 5.26mil; 49.43mil + 6.33mil; 48.82mil + 7.45mil; 48.3mil + 6.78mil; 53.77mil + 6.02mil; 54.44mil + 5.41mil; 55.2mil + 4.96mil; 56.06mil + 4.62mil; 57.03mil + 4.41mil; 58.12mil + 4.35mil; 59.34mil + 4.35mil; 59.62mil + 4.35mil; 60.38mil + 4.35mil; 61.65mil + 4.35mil; 63.45mil + 4.35mil; 65.76mil + 4.35mil; 68.68mil + 4.44mil; 69.81mil + 4.71mil; 70.84mil + 5.17mil; 71.78mil + 5.81mil; 72.66mil + 6.63mil; 73.49mil + 7.7mil; 74.22mil + 8.33mil; 74.61mil + 8.97mil; 74.92mil + 9.61mil; 75.13mil + 10.25mil; 75.31mil + 10.92mil; 75.4mil + 11.59mil; 75.43mil + 12.23mil; 75.4mil + 12.87mil; 75.31mil + 13.5mil; 75.13mil + 14.17mil; 74.85mil + 14.81mil; 74.52mil + 15.51mil; 74.09mil + 16.39mil; 73.39mil + 17.16mil; 72.51mil + 17.73mil; 71.54mil + 18.13mil; 70.41mil + 18.4mil; 69.17mil + 18.49mil; 67.74mil + 18.49mil; 59.98mil + 18.4mil; 58.76mil + 18.22mil; 57.64mil + 17.92mil; 56.6mil + 17.49mil; 55.66mil + 16.91mil; 54.84mil + 16.21mil; 54.05mil + 15.45mil; 53.44mil + 14.72mil; 52.95mil + 13.96mil; 52.56mil + 13.2mil; 52.28mil + 12.41mil; 52.1mil + 11.59mil; 52.04mil + 10.77mil; 52.1mil + 9.98mil; 52.25mil + 9.16mil; 52.5mil + 8.36mil; 52.83mil + 7.57mil; 53.26mil + 6.78mil; 53.77mil + 7.45mil; 48.3mil + 8.61mil; 47.96mil + 9.76mil; 47.75mil + } + } + height = 63.33mil + } + ha:p { + width=23mil; delta=12.0mil; + li:objects { + li:simplepoly.1 { + 0.0mil; 50.52mil + 0.06mil; 49.76mil + 0.27mil; 49.09mil + 0.64mil; 48.6mil + 1.12mil; 48.24mil + 1.76mil; 48.03mil + 2.58mil; 47.93mil + 2.89mil; 47.93mil + 3.86mil; 47.93mil + 5.47mil; 47.93mil + 7.75mil; 47.93mil + 10.64mil; 47.93mil + 14.35mil; 47.93mil + 15.48mil; 48.03mil + 16.58mil; 48.27mil + 17.64mil; 48.7mil + 18.67mil; 49.27mil + 19.65mil; 50.0mil + 20.65mil; 50.95mil + 21.38mil; 51.86mil + 21.99mil; 52.8mil + 22.45mil; 53.81mil + 22.78mil; 54.87mil + 22.99mil; 56.0mil + 23.08mil; 57.21mil + 23.08mil; 57.58mil + 23.08mil; 58.64mil + 23.08mil; 60.41mil + 23.08mil; 62.87mil + 23.08mil; 66.03mil + 23.08mil; 70.05mil + 23.02mil; 71.45mil + 22.84mil; 72.73mil + 22.54mil; 73.91mil + 22.11mil; 74.98mil + 21.59mil; 75.98mil + 20.93mil; 76.86mil + 19.98mil; 77.84mil + 19.01mil; 78.6mil + 17.94mil; 79.2mil + 16.85mil; 79.66mil + 15.69mil; 79.9mil + 14.45mil; 80.0mil + 14.23mil; 75.61mil + 14.87mil; 75.58mil + 15.48mil; 75.43mil + 16.06mil; 75.16mil + 16.61mil; 74.82mil + 17.12mil; 74.37mil + 17.64mil; 73.76mil + 17.91mil; 73.36mil + 18.13mil; 72.91mil + 18.31mil; 72.42mil + 18.43mil; 71.87mil + 18.52mil; 71.33mil + 18.55mil; 70.69mil + 18.55mil; 57.36mil + 18.49mil; 56.66mil + 18.4mil; 56.03mil + 18.22mil; 55.42mil + 17.97mil; 54.84mil + 17.67mil; 54.32mil + 17.28mil; 53.81mil + 16.79mil; 53.38mil + 16.3mil; 53.04mil + 15.75mil; 52.74mil + 15.18mil; 52.56mil + 14.57mil; 52.44mil + 13.9mil; 52.38mil + 4.47mil; 52.38mil + 4.47mil; 75.61mil + 14.23mil; 75.61mil + 14.45mil; 80.0mil + 4.47mil; 80.0mil + 4.47mil; 91.1mil + 4.38mil; 91.92mil + 4.2mil; 92.62mil + 3.86mil; 93.14mil + 3.4mil; 93.53mil + 2.83mil; 93.77mil + 2.1mil; 93.87mil + 1.46mil; 93.77mil + 0.91mil; 93.53mil + 0.51mil; 93.14mil + 0.21mil; 92.59mil + 0.06mil; 91.86mil + 0.0mil; 90.98mil + 0.0mil; 89.85mil + 0.0mil; 86.5mil + 0.0mil; 80.97mil + 0.0mil; 73.21mil + 0.0mil; 63.2mil + } + } + height = 63.33mil + } + ha:q { + width=23mil; delta=12.0mil; + li:objects { + li:simplepoly.1 { + 23.09mil; 50.64mil + 23.09mil; 91.1mil + 23.03mil; 91.95mil + 22.84mil; 92.68mil + 22.54mil; 93.23mil + 22.14mil; 93.65mil + 21.63mil; 93.9mil + 20.99mil; 93.99mil + 20.26mil; 93.9mil + 19.65mil; 93.68mil + 19.19mil; 93.29mil + 18.86mil; 92.77mil + 18.68mil; 92.07mil + 18.62mil; 91.22mil + 18.62mil; 80.12mil + 8.64mil; 80.12mil + 8.85mil; 75.74mil + 9.09mil; 75.74mil + 9.92mil; 75.74mil + 11.25mil; 75.74mil + 13.14mil; 75.74mil + 15.54mil; 75.74mil + 18.62mil; 75.74mil + 18.62mil; 52.5mil + 9.19mil; 52.5mil + 8.52mil; 52.56mil + 7.91mil; 52.68mil + 7.33mil; 52.86mil + 6.78mil; 53.14mil + 6.27mil; 53.5mil + 5.81mil; 53.93mil + 5.41mil; 54.41mil + 5.08mil; 54.93mil + 4.84mil; 55.51mil + 4.65mil; 56.12mil + 4.56mil; 56.79mil + 4.53mil; 57.49mil + 4.53mil; 70.81mil + 4.53mil; 71.42mil + 4.62mil; 72.0mil + 4.74mil; 72.51mil + 4.93mil; 73.0mil + 5.14mil; 73.46mil + 5.44mil; 73.88mil + 5.9mil; 74.46mil + 6.42mil; 74.92mil + 6.97mil; 75.28mil + 7.54mil; 75.55mil + 8.15mil; 75.71mil + 8.85mil; 75.74mil + 8.64mil; 80.12mil + 7.39mil; 80.03mil + 6.23mil; 79.78mil + 5.14mil; 79.36mil + 4.08mil; 78.75mil + 3.1mil; 77.99mil + 2.16mil; 76.98mil + 1.49mil; 76.13mil + 0.94mil; 75.16mil + 0.52mil; 74.06mil + 0.24mil; 72.88mil + 0.06mil; 71.6mil + 0.0mil; 70.17mil + 0.0mil; 57.33mil + 0.06mil; 56.15mil + 0.24mil; 55.02mil + 0.58mil; 53.96mil + 1.06mil; 52.92mil + 1.64mil; 51.98mil + 2.43mil; 51.07mil + 3.38mil; 50.19mil + 4.35mil; 49.46mil + 5.38mil; 48.88mil + 6.45mil; 48.48mil + 7.54mil; 48.21mil + 8.73mil; 48.12mil + 20.5mil; 48.12mil + 21.26mil; 48.21mil + 21.93mil; 48.42mil + 22.42mil; 48.76mil + 22.78mil; 49.24mil + 23.0mil; 49.88mil + } + } + height = 63.33mil + } + ha:r { + width=18mil; delta=12.0mil; + li:objects { + li:simplepoly.0 { + 0.0mil; 50.22mil + 0.06mil; 49.49mil + 0.27mil; 48.85mil + 0.64mil; 48.36mil + 1.12mil; 48.03mil + 1.76mil; 47.81mil + 2.58mil; 47.72mil + 2.92mil; 47.72mil + 4.01mil; 47.72mil + 5.84mil; 47.72mil + 8.39mil; 47.72mil + 11.65mil; 47.72mil + 15.82mil; 47.72mil + 16.58mil; 47.78mil + 17.22mil; 47.96mil + 17.7mil; 48.27mil + 18.07mil; 48.66mil + 18.28mil; 49.18mil + 18.37mil; 49.82mil + 18.37mil; 49.97mil + 18.37mil; 50.34mil + 18.37mil; 50.95mil + 18.37mil; 51.8mil + 18.37mil; 52.89mil + 18.37mil; 54.29mil + 18.31mil; 55.08mil + 18.13mil; 55.69mil + 17.85mil; 56.21mil + 17.46mil; 56.54mil + 16.97mil; 56.76mil + 16.36mil; 56.82mil + 15.6mil; 56.76mil + 15.0mil; 56.57mil + 14.54mil; 56.24mil + 14.2mil; 55.78mil + 13.99mil; 55.2mil + 13.93mil; 54.44mil + 13.93mil; 54.38mil + 13.93mil; 54.2mil + 13.93mil; 53.9mil + 13.93mil; 53.47mil + 13.93mil; 52.92mil + 13.93mil; 52.19mil + 4.5mil; 52.19mil + 4.5mil; 77.5mil + 4.41mil; 78.26mil + 4.23mil; 78.84mil + 3.89mil; 79.33mil + 3.47mil; 79.66mil + 2.89mil; 79.84mil + 2.16mil; 79.9mil + 1.49mil; 79.84mil + 0.94mil; 79.63mil + 0.52mil; 79.3mil + 0.24mil; 78.81mil + 0.06mil; 78.2mil + 0.0mil; 77.41mil + 0.0mil; 76.68mil + 0.0mil; 74.43mil + 0.0mil; 70.69mil + 0.0mil; 65.49mil + 0.0mil; 58.76mil + } + } + height = 63.33mil + } + ha:s { + width=22mil; delta=12.0mil; + li:objects { + li:simplepoly.0 { + 19.1mil; 50.0mil + 19.53mil; 50.28mil + 19.89mil; 50.58mil + 20.16mil; 50.92mil + 20.38mil; 51.25mil + 20.5mil; 51.62mil + 20.56mil; 51.98mil + 20.5mil; 52.71mil + 20.32mil; 53.32mil + 20.01mil; 53.77mil + 19.62mil; 54.11mil + 19.1mil; 54.29mil + 18.46mil; 54.35mil + 18.25mil; 54.35mil + 18.0mil; 54.32mil + 17.73mil; 54.26mil + 17.43mil; 54.17mil + 17.09mil; 54.05mil + 16.73mil; 53.9mil + 15.21mil; 53.38mil + 13.78mil; 52.92mil + 12.41mil; 52.56mil + 11.13mil; 52.31mil + 9.91mil; 52.16mil + 8.73mil; 52.1mil + 7.42mil; 52.22mil + 6.35mil; 52.53mil + 5.5mil; 53.04mil + 4.92mil; 53.77mil + 4.56mil; 54.69mil + 4.44mil; 55.84mil + 4.5mil; 56.54mil + 4.68mil; 57.18mil + 4.99mil; 57.73mil + 5.41mil; 58.25mil + 5.99mil; 58.67mil + 6.72mil; 59.07mil + 17.94mil; 64.33mil + 19.43mil; 65.18mil + 20.68mil; 66.15mil + 21.65mil; 67.31mil + 22.35mil; 68.59mil + 22.78mil; 70.05mil + 22.93mil; 71.69mil + 22.81mil; 73.0mil + 22.51mil; 74.25mil + 22.02mil; 75.4mil + 21.32mil; 76.5mil + 20.44mil; 77.53mil + 19.31mil; 78.5mil + 18.67mil; 78.93mil + 18.0mil; 79.26mil + 17.27mil; 79.54mil + 16.48mil; 79.72mil + 15.66mil; 79.84mil + 14.75mil; 79.87mil + 12.83mil; 79.81mil + 10.83mil; 79.63mil + 8.76mil; 79.33mil + 6.6mil; 78.87mil + 4.38mil; 78.29mil + 1.97mil; 77.56mil + 1.37mil; 77.35mil + 0.88mil; 77.07mil + 0.48mil; 76.74mil + 0.21mil; 76.34mil + 0.03mil; 75.92mil + 0.0mil; 75.43mil + 0.03mil; 74.76mil + 0.21mil; 74.22mil + 0.48mil; 73.76mil + 0.88mil; 73.46mil + 1.37mil; 73.27mil + 2.0mil; 73.18mil + 2.37mil; 73.21mil + 2.8mil; 73.24mil + 3.19mil; 73.3mil + 3.59mil; 73.42mil + 4.01mil; 73.52mil + 4.44mil; 73.67mil + 5.96mil; 74.22mil + 7.51mil; 74.67mil + 9.09mil; 75.01mil + 10.7mil; 75.25mil + 12.35mil; 75.4mil + 14.11mil; 75.43mil + 14.66mil; 75.43mil + 15.21mil; 75.37mil + 15.66mil; 75.31mil + 16.09mil; 75.19mil + 16.48mil; 75.04mil + 16.85mil; 74.82mil + 17.33mil; 74.46mil + 17.73mil; 74.03mil + 18.03mil; 73.55mil + 18.25mil; 73.0mil + 18.4mil; 72.36mil + 18.46mil; 71.66mil + 18.37mil; 71.02mil + 18.13mil; 70.38mil + 17.76mil; 69.81mil + 17.21mil; 69.26mil + 16.51mil; 68.74mil + 15.63mil; 68.25mil + 4.86mil; 63.11mil + 3.37mil; 62.29mil + 2.16mil; 61.26mil + 1.21mil; 60.07mil + 0.54mil; 58.73mil + 0.12mil; 57.24mil + 0.0mil; 55.48mil + 0.03mil; 54.5mil + 0.21mil; 53.53mil + 0.51mil; 52.62mil + 0.94mil; 51.77mil + 1.46mil; 50.95mil + 2.16mil; 50.12mil + 2.95mil; 49.39mil + 3.83mil; 48.79mil + 4.77mil; 48.3mil + 5.81mil; 47.96mil + 6.9mil; 47.75mil + 8.12mil; 47.66mil + 10.22mil; 47.75mil + 12.22mil; 47.93mil + 14.11mil; 48.27mil + 15.87mil; 48.7mil + 17.52mil; 49.27mil + } + } + height = 63.33mil + } + ha:t { + width=18mil; delta=12.0mil; + li:objects { + li:simplepoly.0 { + 4.56mil; 36.35mil + 4.62mil; 35.65mil + 4.81mil; 35.07mil + 5.11mil; 34.64mil + 5.54mil; 34.31mil + 6.11mil; 34.12mil + 6.84mil; 34.03mil + 7.45mil; 34.12mil + 8.0mil; 34.31mil + 8.4mil; 34.64mil + 8.7mil; 35.13mil + 8.85mil; 35.71mil + 8.94mil; 36.47mil + 8.94mil; 36.8mil + 8.94mil; 37.74mil + 8.94mil; 39.33mil + 8.94mil; 41.52mil + 8.94mil; 44.35mil + 8.94mil; 47.93mil + 9.13mil; 47.93mil + 9.7mil; 47.93mil + 10.65mil; 47.93mil + 11.98mil; 47.93mil + 13.72mil; 47.93mil + 15.91mil; 47.93mil + 16.61mil; 48.03mil + 17.22mil; 48.21mil + 17.67mil; 48.54mil + 18.01mil; 49.0mil + 18.19mil; 49.58mil + 18.28mil; 50.31mil + 18.19mil; 50.92mil + 18.01mil; 51.4mil + 17.67mil; 51.77mil + 17.19mil; 52.04mil + 16.61mil; 52.22mil + 15.85mil; 52.25mil + 8.94mil; 52.25mil + 8.94mil; 77.65mil + 8.88mil; 78.38mil + 8.7mil; 78.96mil + 8.4mil; 79.42mil + 7.97mil; 79.75mil + 7.42mil; 79.93mil + 6.75mil; 80.0mil + 6.08mil; 79.93mil + 5.54mil; 79.72mil + 5.11mil; 79.39mil + 4.81mil; 78.9mil + 4.62mil; 78.26mil + 4.56mil; 77.44mil + 4.56mil; 52.25mil + 2.25mil; 52.25mil + 1.55mil; 52.22mil + 1.0mil; 52.04mil + 0.55mil; 51.74mil + 0.24mil; 51.34mil + 0.06mil; 50.79mil + 0.0mil; 50.12mil + 0.06mil; 49.49mil + 0.24mil; 48.94mil + 0.55mil; 48.51mil + 0.97mil; 48.21mil + 1.52mil; 48.03mil + 2.22mil; 47.93mil + 4.56mil; 47.93mil + } + } + height = 63.33mil + } + ha:u { + width=22mil; delta=12.0mil; + li:objects { + li:simplepoly.0 { + 0.0mil; 50.46mil + 0.03mil; 49.67mil + 0.21mil; 49.0mil + 0.52mil; 48.48mil + 0.94mil; 48.12mil + 1.49mil; 47.9mil + 2.19mil; 47.81mil + 2.83mil; 47.9mil + 3.38mil; 48.12mil + 3.8mil; 48.51mil + 4.08mil; 49.03mil + 4.26mil; 49.7mil + 4.35mil; 50.52mil + 4.35mil; 51.1mil + 4.35mil; 52.74mil + 4.35mil; 55.54mil + 4.35mil; 59.4mil + 4.35mil; 64.42mil + 4.35mil; 70.72mil + 4.38mil; 71.42mil + 4.47mil; 72.03mil + 4.65mil; 72.63mil + 4.93mil; 73.18mil + 5.26mil; 73.67mil + 5.69mil; 74.12mil + 6.14mil; 74.55mil + 6.66mil; 74.92mil + 7.18mil; 75.19mil + 7.76mil; 75.37mil + 8.3mil; 75.49mil + 8.94mil; 75.52mil + 18.46mil; 75.52mil + 18.46mil; 50.34mil + 18.52mil; 49.61mil + 18.71mil; 49.03mil + 19.01mil; 48.54mil + 19.44mil; 48.21mil + 20.01mil; 48.03mil + 20.74mil; 47.93mil + 21.38mil; 48.03mil + 21.9mil; 48.21mil + 22.33mil; 48.57mil + 22.63mil; 49.03mil + 22.78mil; 49.64mil + 22.87mil; 50.4mil + 22.87mil; 77.5mil + 22.78mil; 78.26mil + 22.6mil; 78.9mil + 22.3mil; 79.39mil + 21.87mil; 79.72mil + 21.29mil; 79.93mil + 20.59mil; 80.0mil + 8.64mil; 80.0mil + 7.45mil; 79.93mil + 6.3mil; 79.69mil + 5.23mil; 79.3mil + 4.2mil; 78.75mil + 3.25mil; 78.05mil + 2.31mil; 77.14mil + 1.58mil; 76.28mil + 1.0mil; 75.37mil + 0.58mil; 74.37mil + 0.24mil; 73.27mil + 0.06mil; 72.12mil + 0.0mil; 70.81mil + 0.0mil; 70.26mil + 0.0mil; 68.59mil + 0.0mil; 65.79mil + 0.0mil; 61.87mil + 0.0mil; 56.85mil + } + } + height = 63.33mil + } + ha:v { + width=22mil; delta=12.0mil; + li:objects { + li:simplepoly.0 { + 18.52mil; 49.55mil + 18.7mil; 49.06mil + 18.98mil; 48.66mil + 19.31mil; 48.36mil + 19.74mil; 48.15mil + 20.19mil; 48.0mil + 20.77mil; 47.93mil + 21.41mil; 48.0mil + 21.96mil; 48.15mil + 22.38mil; 48.42mil + 22.66mil; 48.79mil + 22.84mil; 49.24mil + 22.93mil; 49.82mil + 22.9mil; 50.03mil + 22.9mil; 50.22mil + 22.87mil; 50.43mil + 22.81mil; 50.64mil + 22.78mil; 50.82mil + 22.72mil; 51.04mil + 22.45mil; 51.8mil + 21.72mil; 54.02mil + 20.47mil; 57.7mil + 18.73mil; 62.87mil + 16.51mil; 69.53mil + 13.72mil; 77.93mil + 13.44mil; 78.57mil + 13.17mil; 79.08mil + 12.8mil; 79.48mil + 12.44mil; 79.78mil + 11.98mil; 79.96mil + 11.49mil; 80.0mil + 10.98mil; 79.96mil + 10.52mil; 79.81mil + 10.13mil; 79.57mil + 9.76mil; 79.2mil + 9.49mil; 78.75mil + 9.24mil; 78.17mil + 8.97mil; 77.44mil + 8.24mil; 75.22mil + 7.02mil; 71.54mil + 5.29mil; 66.37mil + 3.07mil; 59.71mil + 0.27mil; 51.28mil + 0.18mil; 51.04mil + 0.12mil; 50.79mil + 0.06mil; 50.55mil + 0.03mil; 50.37mil + 0.0mil; 50.16mil + 0.0mil; 49.97mil + 0.06mil; 49.36mil + 0.27mil; 48.85mil + 0.64mil; 48.45mil + 1.15mil; 48.18mil + 1.79mil; 48.0mil + 2.64mil; 47.93mil + 3.01mil; 48.0mil + 3.37mil; 48.18mil + 3.71mil; 48.45mil + 3.98mil; 48.82mil + 4.26mil; 49.3mil + 4.5mil; 49.91mil + 4.68mil; 50.49mil + 5.26mil; 52.22mil + 6.2mil; 55.05mil + 7.54mil; 59.07mil + 9.27mil; 64.21mil + 11.46mil; 70.69mil + 11.65mil; 70.11mil + 12.22mil; 68.38mil + 13.2mil; 65.49mil + 14.54mil; 61.41mil + 16.3mil; 56.18mil + } + } + height = 63.33mil + } + ha:w { + width=32mil; delta=12.0mil; + li:objects { + li:simplepoly.0 { + 27.74mil; 50.0mil + 27.95mil; 49.36mil + 28.22mil; 48.82mil + 28.56mil; 48.39mil + 28.95mil; 48.09mil + 29.38mil; 47.9mil + 29.93mil; 47.81mil + 30.54mil; 47.87mil + 31.08mil; 48.06mil + 31.48mil; 48.33mil + 31.78mil; 48.73mil + 31.94mil; 49.21mil + 32.03mil; 49.82mil + 32.0mil; 50.03mil + 32.0mil; 50.22mil + 31.97mil; 50.4mil + 31.94mil; 50.58mil + 31.91mil; 50.79mil + 31.87mil; 50.98mil + 31.69mil; 51.74mil + 31.14mil; 53.96mil + 30.23mil; 57.64mil + 28.99mil; 62.81mil + 27.37mil; 69.44mil + 25.33mil; 77.84mil + 25.12mil; 78.5mil + 24.85mil; 79.05mil + 24.51mil; 79.48mil + 24.09mil; 79.75mil + 23.63mil; 79.93mil + 23.08mil; 80.0mil + 22.54mil; 79.96mil + 22.05mil; 79.78mil + 21.59mil; 79.51mil + 21.23mil; 79.11mil + 20.89mil; 78.63mil + 20.62mil; 77.99mil + 20.47mil; 77.65mil + 20.1mil; 76.65mil + 19.46mil; 74.92mil + 18.58mil; 72.54mil + 17.43mil; 69.47mil + 16.0mil; 65.55mil + 11.4mil; 78.02mil + 11.13mil; 78.63mil + 10.83mil; 79.11mil + 10.49mil; 79.51mil + 10.13mil; 79.78mil + 9.7mil; 79.96mil + 9.21mil; 80.0mil + 8.64mil; 79.96mil + 8.15mil; 79.81mil + 7.72mil; 79.54mil + 7.39mil; 79.17mil + 7.11mil; 78.72mil + 6.93mil; 78.11mil + 6.72mil; 77.41mil + 6.17mil; 75.25mil + 5.26mil; 71.63mil + 3.98mil; 66.58mil + 2.34mil; 60.1mil + 0.27mil; 51.86mil + 0.18mil; 51.52mil + 0.12mil; 51.19mil + 0.06mil; 50.89mil + 0.03mil; 50.58mil + 0.0mil; 50.31mil + 0.0mil; 50.03mil + 0.06mil; 49.43mil + 0.24mil; 48.88mil + 0.57mil; 48.48mil + 1.06mil; 48.18mil + 1.64mil; 48.03mil + 2.43mil; 47.93mil + 2.86mil; 48.0mil + 3.28mil; 48.15mil + 3.62mil; 48.36mil + 3.89mil; 48.7mil + 4.13mil; 49.12mil + 4.32mil; 49.64mil + 4.44mil; 50.22mil + 4.86mil; 51.92mil + 5.59mil; 54.72mil + 6.6mil; 58.67mil + 7.91mil; 63.72mil + 9.55mil; 70.14mil + 9.64mil; 69.84mil + 10.0mil; 68.92mil + 10.61mil; 67.34mil + 11.46mil; 65.18mil + 12.53mil; 62.35mil + 13.93mil; 58.79mil + 14.14mil; 58.31mil + 14.41mil; 57.88mil + 14.75mil; 57.55mil + 15.14mil; 57.33mil + 15.57mil; 57.18mil + 16.06mil; 57.12mil + 16.54mil; 57.18mil + 17.0mil; 57.33mil + 17.43mil; 57.61mil + 17.79mil; 57.94mil + 18.1mil; 58.4mil + 18.37mil; 58.98mil + 18.46mil; 59.28mil + 18.8mil; 60.19mil + 19.37mil; 61.71mil + 20.16mil; 63.84mil + 21.17mil; 66.58mil + 22.48mil; 70.02mil + } + } + height = 63.33mil + } + ha:x { + width=22mil; delta=12.0mil; + li:objects { + li:simplepoly.0 { + 8.91mil; 63.96mil + 8.67mil; 63.63mil + 7.97mil; 62.6mil + 6.81mil; 60.86mil + 5.2mil; 58.46mil + 3.1mil; 55.36mil + 0.48mil; 51.4mil + 0.33mil; 51.19mil + 0.21mil; 50.95mil + 0.12mil; 50.7mil + 0.03mil; 50.49mil + 0.0mil; 50.28mil + 0.0mil; 50.03mil + 0.06mil; 49.39mil + 0.24mil; 48.85mil + 0.57mil; 48.42mil + 1.03mil; 48.12mil + 1.61mil; 47.93mil + 2.37mil; 47.84mil + 2.67mil; 47.87mil + 3.01mil; 47.96mil + 3.31mil; 48.12mil + 3.59mil; 48.33mil + 3.86mil; 48.6mil + 4.13mil; 48.94mil + 11.46mil; 59.95mil + 18.83mil; 48.94mil + 19.07mil; 48.63mil + 19.34mil; 48.39mil + 19.62mil; 48.21mil + 19.95mil; 48.06mil + 20.32mil; 47.96mil + 20.71mil; 47.93mil + 21.32mil; 48.0mil + 21.84mil; 48.15mil + 22.23mil; 48.42mil + 22.51mil; 48.79mil + 22.69mil; 49.27mil + 22.75mil; 49.85mil + 22.72mil; 50.22mil + 22.69mil; 50.55mil + 22.63mil; 50.85mil + 22.54mil; 51.16mil + 22.41mil; 51.43mil + 22.29mil; 51.68mil + 22.05mil; 52.04mil + 21.38mil; 53.04mil + 20.22mil; 54.72mil + 18.64mil; 57.09mil + 16.6mil; 60.1mil + 14.05mil; 63.93mil + 14.26mil; 64.27mil + 14.93mil; 65.27mil + 16.03mil; 66.92mil + 17.58mil; 69.23mil + 19.56mil; 72.18mil + 22.08mil; 75.92mil + 22.29mil; 76.31mil + 22.48mil; 76.68mil + 22.63mil; 76.98mil + 22.75mil; 77.29mil + 22.81mil; 77.56mil + 22.84mil; 77.8mil + 22.78mil; 78.47mil + 22.6mil; 79.02mil + 22.29mil; 79.45mil + 21.9mil; 79.75mil + 21.38mil; 79.93mil + 20.74mil; 80.0mil + 20.32mil; 80.0mil + 19.95mil; 79.9mil + 19.59mil; 79.75mil + 19.28mil; 79.54mil + 19.01mil; 79.26mil + 18.76mil; 78.93mil + 18.55mil; 78.66mil + 17.94mil; 77.74mil + 16.97mil; 76.22mil + 15.57mil; 74.09mil + 13.78mil; 71.36mil + 11.53mil; 67.86mil + 11.31mil; 68.16mil + 10.7mil; 69.07mil + 9.7mil; 70.6mil + 8.3mil; 72.69mil + 6.51mil; 75.4mil + 4.22mil; 78.81mil + 3.95mil; 79.17mil + 3.65mil; 79.48mil + 3.34mil; 79.72mil + 3.01mil; 79.87mil + 2.67mil; 79.96mil + 2.31mil; 80.0mil + 1.58mil; 79.96mil + 1.0mil; 79.78mil + 0.57mil; 79.51mil + 0.24mil; 79.11mil + 0.06mil; 78.6mil + 0.0mil; 77.93mil + 0.0mil; 77.68mil + 0.03mil; 77.38mil + 0.12mil; 77.11mil + 0.21mil; 76.83mil + 0.36mil; 76.56mil + 0.54mil; 76.25mil + 0.76mil; 75.92mil + 1.46mil; 74.92mil + 2.58mil; 73.24mil + 4.19mil; 70.87mil + 6.26mil; 67.83mil + } + } + height = 63.33mil + } + ha:y { + width=22mil; delta=12.0mil; + li:objects { + li:simplepoly.0 { + 22.35mil; 52.16mil + 9.09mil; 91.77mil + 8.82mil; 92.38mil + 8.48mil; 92.92mil + 8.06mil; 93.32mil + 7.57mil; 93.62mil + 7.02mil; 93.77mil + 6.38mil; 93.87mil + 6.26mil; 93.87mil + 5.93mil; 93.87mil + 5.41mil; 93.87mil + 4.65mil; 93.87mil + 3.68mil; 93.87mil + 2.46mil; 93.87mil + 1.7mil; 93.8mil + 1.09mil; 93.62mil + 0.61mil; 93.32mil + 0.27mil; 92.89mil + 0.06mil; 92.38mil + 0.0mil; 91.71mil + 0.06mil; 91.01mil + 0.27mil; 90.46mil + 0.61mil; 90.0mil + 1.09mil; 89.7mil + 1.73mil; 89.52mil + 2.55mil; 89.45mil + 5.14mil; 89.45mil + 5.23mil; 89.12mil + 5.53mil; 88.21mil + 6.05mil; 86.66mil + 6.78mil; 84.47mil + 7.69mil; 81.67mil + 8.88mil; 78.14mil + 0.39mil; 52.01mil + 0.27mil; 51.65mil + 0.15mil; 51.31mil + 0.09mil; 50.98mil + 0.03mil; 50.64mil + 0.0mil; 50.34mil + 0.0mil; 50.03mil + 0.06mil; 49.43mil + 0.24mil; 48.88mil + 0.54mil; 48.48mil + 0.97mil; 48.18mil + 1.52mil; 48.03mil + 2.22mil; 47.93mil + 2.7mil; 48.0mil + 3.16mil; 48.18mil + 3.56mil; 48.48mil + 3.89mil; 48.88mil + 4.19mil; 49.39mil + 4.47mil; 50.03mil + 11.28mil; 70.99mil + 18.49mil; 49.79mil + 18.7mil; 49.24mil + 18.98mil; 48.79mil + 19.31mil; 48.42mil + 19.68mil; 48.15mil + 20.1mil; 48.0mil + 20.59mil; 47.93mil + 21.26mil; 48.0mil + 21.81mil; 48.18mil + 22.26mil; 48.48mil + 22.57mil; 48.88mil + 22.75mil; 49.39mil + 22.84mil; 50.03mil + 22.81mil; 50.31mil + 22.78mil; 50.58mil + 22.72mil; 50.92mil + 22.6mil; 51.28mil + 22.51mil; 51.71mil + } + } + height = 63.33mil + } + ha:z { + width=22mil; delta=12.0mil; + li:objects { + li:simplepoly.0 { + 6.41mil; 75.31mil + 20.32mil; 75.31mil + 21.02mil; 75.4mil + 21.62mil; 75.61mil + 22.08mil; 75.98mil + 22.41mil; 76.47mil + 22.6mil; 77.11mil + 22.69mil; 77.9mil + 22.6mil; 78.53mil + 22.41mil; 79.08mil + 22.08mil; 79.48mil + 21.62mil; 79.78mil + 21.05mil; 79.93mil + 20.32mil; 80.0mil + 2.76mil; 80.0mil + 1.91mil; 79.93mil + 1.21mil; 79.75mil + 0.7mil; 79.42mil + 0.3mil; 78.93mil + 0.06mil; 78.35mil + 0.0mil; 77.56mil + 0.0mil; 77.29mil + 0.06mil; 76.98mil + 0.15mil; 76.71mil + 0.27mil; 76.41mil + 0.45mil; 76.07mil + 0.67mil; 75.74mil + 16.42mil; 52.13mil + 2.28mil; 52.13mil + 1.58mil; 52.1mil + 1.03mil; 51.92mil + 0.57mil; 51.62mil + 0.27mil; 51.19mil + 0.09mil; 50.67mil + 0.03mil; 49.97mil + 0.09mil; 49.27mil + 0.27mil; 48.7mil + 0.57mil; 48.24mil + 1.03mil; 47.9mil + 1.61mil; 47.72mil + 2.34mil; 47.63mil + 19.71mil; 47.63mil + 20.65mil; 47.72mil + 21.41mil; 47.9mil + 22.02mil; 48.21mil + 22.45mil; 48.63mil + 22.72mil; 49.18mil + 22.81mil; 49.88mil + 22.78mil; 50.16mil + 22.75mil; 50.4mil + 22.69mil; 50.64mil + 22.57mil; 50.89mil + 22.48mil; 51.13mil + 22.32mil; 51.37mil + } + } + height = 63.33mil + } + ha:\{ { + width=13mil; delta=12.0mil; + li:objects { + li:simplepoly.0 { + 8.64mil; 29.05mil + 8.7mil; 29.05mil + 8.88mil; 29.05mil + 9.21mil; 29.05mil + 9.67mil; 29.05mil + 10.28mil; 29.05mil + 11.04mil; 29.05mil + 11.77mil; 29.11mil + 12.35mil; 29.29mil + 12.83mil; 29.59mil + 13.17mil; 29.99mil + 13.35mil; 30.51mil + 13.44mil; 31.14mil + 13.38mil; 31.78mil + 13.2mil; 32.33mil + 12.89mil; 32.79mil + 12.5mil; 33.12mil + 11.95mil; 33.36mil + 11.31mil; 33.49mil + 10.58mil; 33.67mil + 9.97mil; 33.94mil + 9.52mil; 34.31mil + 9.18mil; 34.76mil + 9.0mil; 35.34mil + 8.94mil; 36.04mil + 8.94mil; 52.19mil + 8.88mil; 52.92mil + 8.73mil; 53.68mil + 8.48mil; 54.41mil + 8.15mil; 55.14mil + 7.69mil; 55.9mil + 7.14mil; 56.66mil + 7.63mil; 57.21mil + 8.06mil; 57.85mil + 8.39mil; 58.52mil + 8.61mil; 59.25mil + 8.76mil; 60.07mil + 8.82mil; 60.95mil + 8.82mil; 61.41mil + 8.82mil; 62.75mil + 8.82mil; 64.94mil + 8.82mil; 68.04mil + 8.82mil; 72.0mil + 8.82mil; 77.01mil + 8.88mil; 77.8mil + 9.06mil; 78.47mil + 9.43mil; 79.02mil + 9.88mil; 79.42mil + 10.49mil; 79.72mil + 11.28mil; 79.87mil + 11.95mil; 80.0mil + 12.5mil; 80.24mil + 12.92mil; 80.57mil + 13.23mil; 80.97mil + 13.41mil; 81.52mil + 13.5mil; 82.15mil + 13.41mil; 82.76mil + 13.2mil; 83.28mil + 12.86mil; 83.68mil + 12.38mil; 83.95mil + 11.74mil; 84.13mil + 10.98mil; 84.19mil + 10.03mil; 84.13mil + 9.15mil; 83.95mil + 8.33mil; 83.65mil + 7.57mil; 83.25mil + 6.84mil; 82.7mil + 6.2mil; 82.06mil + 5.65mil; 81.36mil + 5.23mil; 80.6mil + 4.89mil; 79.81mil + 4.65mil; 78.96mil + 4.5mil; 78.02mil + 4.47mil; 76.95mil + 4.47mil; 76.53mil + 4.47mil; 75.22mil + 4.47mil; 73.06mil + 4.47mil; 70.02mil + 4.47mil; 66.12mil + 4.47mil; 61.17mil + 4.38mil; 60.56mil + 4.19mil; 60.04mil + 3.83mil; 59.62mil + 3.37mil; 59.28mil + 2.76mil; 59.04mil + 2.0mil; 58.85mil + 1.37mil; 58.73mil + 0.88mil; 58.49mil + 0.48mil; 58.19mil + 0.21mil; 57.76mil + 0.03mil; 57.27mil + 0.0mil; 56.63mil + 0.03mil; 56.0mil + 0.21mil; 55.45mil + 0.51mil; 55.02mil + 0.91mil; 54.72mil + 1.43mil; 54.54mil + 2.1mil; 54.44mil + 2.8mil; 54.41mil + 3.4mil; 54.23mil + 3.86mil; 53.93mil + 4.19mil; 53.5mil + 4.38mil; 52.95mil + 4.47mil; 52.25mil + 4.47mil; 35.31mil + 4.5mil; 34.52mil + 4.68mil; 33.76mil + 4.99mil; 33.0mil + 5.38mil; 32.3mil + 5.93mil; 31.6mil + 6.6mil; 30.9mil + 7.27mil; 30.35mil + 7.97mil; 29.9mil + 8.7mil; 29.53mil + 9.46mil; 29.26mil + 10.22mil; 29.11mil + } + } + height = 63.33mil + } + ha:| { + width=4mil; delta=12.0mil; + li:objects { + li:simplepoly.0 { + 2.13mil; 86.93mil + 1.46mil; 86.84mil + 0.94mil; 86.6mil + 0.51mil; 86.17mil + 0.21mil; 85.59mil + 0.06mil; 84.86mil + 0.0mil; 83.95mil + 0.0mil; 29.68mil + 0.06mil; 28.86mil + 0.24mil; 28.16mil + 0.58mil; 27.62mil + 1.0mil; 27.22mil + 1.58mil; 26.98mil + 2.34mil; 26.89mil + 3.01mil; 26.98mil + 3.59mil; 27.22mil + 4.04mil; 27.59mil + 4.35mil; 28.13mil + 4.53mil; 28.83mil + 4.62mil; 29.71mil + 4.62mil; 84.04mil + 4.53mil; 84.89mil + 4.32mil; 85.62mil + 3.98mil; 86.17mil + 3.5mil; 86.6mil + 2.89mil; 86.84mil + } + } + height = 63.33mil + } + ha:&7D { + width=13mil; delta=12.0mil; + li:objects { + li:simplepoly.0 { + 2.46mil; 29.05mil + 3.25mil; 29.11mil + 4.01mil; 29.26mil + 4.77mil; 29.53mil + 5.5mil; 29.87mil + 6.2mil; 30.32mil + 6.93mil; 30.9mil + 7.57mil; 31.57mil + 8.09mil; 32.27mil + 8.51mil; 32.97mil + 8.82mil; 33.73mil + 8.97mil; 34.49mil + 9.06mil; 35.31mil + 9.06mil; 52.25mil + 9.12mil; 52.92mil + 9.3mil; 53.47mil + 9.64mil; 53.9mil + 10.1mil; 54.2mil + 10.67mil; 54.38mil + 11.43mil; 54.44mil + 12.04mil; 54.5mil + 12.56mil; 54.69mil + 12.95mil; 54.99mil + 13.26mil; 55.42mil + 13.44mil; 55.96mil + 13.5mil; 56.63mil + 13.44mil; 57.24mil + 13.26mil; 57.76mil + 12.99mil; 58.19mil + 12.59mil; 58.49mil + 12.1mil; 58.73mil + 11.49mil; 58.85mil + 10.73mil; 59.04mil + 10.1mil; 59.28mil + 9.61mil; 59.62mil + 9.27mil; 60.04mil + 9.06mil; 60.56mil + 9.0mil; 61.17mil + 9.0mil; 76.95mil + 8.94mil; 77.99mil + 8.79mil; 78.93mil + 8.57mil; 79.81mil + 8.24mil; 80.57mil + 7.81mil; 81.33mil + 7.3mil; 82.06mil + 6.66mil; 82.7mil + 5.96mil; 83.22mil + 5.2mil; 83.65mil + 4.38mil; 83.95mil + 3.49mil; 84.1mil + 2.55mil; 84.19mil + 1.76mil; 84.13mil + 1.12mil; 83.95mil + 0.64mil; 83.68mil + 0.27mil; 83.28mil + 0.06mil; 82.76mil + 0.0mil; 82.15mil + 0.06mil; 81.52mil + 0.24mil; 81.0mil + 0.54mil; 80.57mil + 0.97mil; 80.24mil + 1.52mil; 80.0mil + 2.22mil; 79.87mil + 2.95mil; 79.72mil + 3.59mil; 79.45mil + 4.07mil; 79.02mil + 4.41mil; 78.5mil + 4.62mil; 77.84mil + 4.71mil; 77.01mil + 4.71mil; 60.95mil + 4.74mil; 60.1mil + 4.86mil; 59.28mil + 5.11mil; 58.55mil + 5.41mil; 57.85mil + 5.84mil; 57.24mil + 6.35mil; 56.66mil + 5.81mil; 55.93mil + 5.35mil; 55.17mil + 4.99mil; 54.44mil + 4.74mil; 53.68mil + 4.59mil; 52.95mil + 4.56mil; 52.19mil + 4.56mil; 36.04mil + 4.47mil; 35.37mil + 4.29mil; 34.76mil + 3.95mil; 34.31mil + 3.49mil; 33.94mil + 2.92mil; 33.67mil + 2.19mil; 33.49mil + 1.52mil; 33.36mil + 1.0mil; 33.12mil + 0.57mil; 32.79mil + 0.27mil; 32.36mil + 0.12mil; 31.81mil + 0.06mil; 31.14mil + 0.12mil; 30.54mil + 0.3mil; 29.99mil + 0.64mil; 29.59mil + 1.09mil; 29.29mil + 1.7mil; 29.14mil + } + } + height = 63.33mil + } + ha:&7E { + width=22mil; delta=12.0mil; + li:objects { + li:simplepoly.0 { + 18.31mil; 54.87mil + 18.64mil; 54.54mil + 19.04mil; 54.23mil + 19.43mil; 53.99mil + 19.86mil; 53.84mil + 20.32mil; 53.74mil + 20.83mil; 53.68mil + 21.44mil; 53.77mil + 21.99mil; 53.96mil + 22.38mil; 54.26mil + 22.69mil; 54.69mil + 22.84mil; 55.27mil + 22.93mil; 55.96mil + 22.87mil; 56.24mil + 22.78mil; 56.51mil + 22.63mil; 56.82mil + 22.41mil; 57.12mil + 22.14mil; 57.46mil + 21.81mil; 57.79mil + 20.92mil; 58.55mil + 20.01mil; 59.16mil + 19.07mil; 59.65mil + 18.07mil; 59.98mil + 17.06mil; 60.19mil + 15.97mil; 60.25mil + 15.05mil; 60.22mil + 14.17mil; 60.07mil + 13.38mil; 59.8mil + 12.59mil; 59.46mil + 11.89mil; 59.01mil + 11.19mil; 58.4mil + 10.25mil; 57.61mil + 9.43mil; 56.94mil + 8.64mil; 56.42mil + 7.94mil; 56.03mil + 7.33mil; 55.81mil + 6.75mil; 55.72mil + 6.41mil; 55.78mil + 6.05mil; 55.87mil + 5.68mil; 56.03mil + 5.29mil; 56.24mil + 4.89mil; 56.51mil + 4.44mil; 56.85mil + 3.98mil; 57.21mil + 3.56mil; 57.49mil + 3.16mil; 57.7mil + 2.8mil; 57.85mil + 2.46mil; 57.94mil + 2.16mil; 57.97mil + 1.49mil; 57.91mil + 0.94mil; 57.7mil + 0.51mil; 57.36mil + 0.24mil; 56.88mil + 0.06mil; 56.27mil + 0.0mil; 55.48mil + 0.0mil; 55.27mil + 0.09mil; 55.02mil + 0.24mil; 54.78mil + 0.42mil; 54.5mil + 0.7mil; 54.23mil + 1.03mil; 53.9mil + 1.97mil; 53.14mil + 2.92mil; 52.5mil + 3.86mil; 52.01mil + 4.83mil; 51.65mil + 5.81mil; 51.43mil + 6.81mil; 51.34mil + 7.78mil; 51.43mil + 8.79mil; 51.65mil + 9.76mil; 52.01mil + 10.73mil; 52.5mil + 11.74mil; 53.17mil + 12.74mil; 53.96mil + 13.41mil; 54.57mil + 14.02mil; 55.02mil + 14.6mil; 55.42mil + 15.08mil; 55.66mil + 15.54mil; 55.84mil + 15.97mil; 55.87mil + 16.42mil; 55.87mil + 16.85mil; 55.78mil + 17.27mil; 55.63mil + 17.64mil; 55.45mil + 17.97mil; 55.2mil + } + } + height = 63.33mil + } + + } + cell_width = 2.87641mm + cell_height = 1.879602mm + } +} Index: tags/2.1.2/pcblib/Makefile =================================================================== --- tags/2.1.2/pcblib/Makefile (nonexistent) +++ tags/2.1.2/pcblib/Makefile (revision 24813) @@ -0,0 +1,36 @@ +# This Makefile is a plain old hand written one; all configuration settings +# are included from ../Makefile.conf which is scconfig generated + +ROOT=.. + +all: + +# NOTE: this rule is _not_ called from linstall +install_: + $(MKDIR) "$(DATADIR)/pcblib" + $(MKDIR) "$(DATADIR)/pcblib/connector" + $(CPC) "`pwd`/connector"/* "$(DATADIR)/pcblib/connector" + $(MKDIR) "$(DATADIR)/pcblib/parametric" + $(CPC) "`pwd`/parametric"/* "$(DATADIR)/pcblib/parametric" + $(MKDIR) "$(DATADIR)/pcblib/smd" + $(CPC) "`pwd`/smd"/* "$(DATADIR)/pcblib/smd" + $(MKDIR) "$(DATADIR)/pcblib/tru-hole" + $(CPC) "`pwd`/tru-hole"/* "$(DATADIR)/pcblib/tru-hole" + +install: + $(MAKE) install_ CPC="$(CP)" + +# hack: pcb's chdir() based approach gets fooled on symlinks because of "cd .." +# returns to the wrong dir - rather symlink the whole dir +linstall: + $(MAKE) uninstall + $(MKDIR) "$(DATADIR)" + $(LN) "`pwd`" "$(DATADIR)/pcblib" + +uninstall: + $(RM) "$(DATADIR)/pcblib" + +clean: + +include $(ROOT)/Makefile.conf + Index: tags/2.1.2/pcblib/README =================================================================== --- tags/2.1.2/pcblib/README (nonexistent) +++ tags/2.1.2/pcblib/README (revision 24813) @@ -0,0 +1,8 @@ +This directory hosts the pcb-rnd's new footprint library. To avoid +confusuin with "newlib", which is in use in mainline, this one is called +pcblib. + +Some footprints are dynamically generated by scripts; they are +called parametric footprints and are in parametric/. Other footprints +are plain old data file footprints (static footpritns) in all the other +directories. Index: tags/2.1.2/pcblib/connector/BNC_LAY.fp =================================================================== --- tags/2.1.2/pcblib/connector/BNC_LAY.fp (nonexistent) +++ tags/2.1.2/pcblib/connector/BNC_LAY.fp (revision 24813) @@ -0,0 +1,15 @@ +##from:pcb +##geo:90 +##geo:female + +Element(0x00 "right angle BNC" "" "BNC_LAY" 200 0 3 100 0x00) +( + ElementLine(-60 -290 490 -290 10) + ElementLine(490 -290 490 290 10) + ElementLine(490 290 -60 290 10) + ElementLine(-60 290 -60 -290 10) + Pin(0 0 60 35 "1" 0x101) + Pin(0 -100 60 35 "2" 0x01) + Pin(200 -200 100 81 "m1" 0x01) + Pin(200 200 100 81 "m2" 0x01) +) Index: tags/2.1.2/pcblib/connector/DB15F.fp =================================================================== --- tags/2.1.2/pcblib/connector/DB15F.fp (nonexistent) +++ tags/2.1.2/pcblib/connector/DB15F.fp (revision 24813) @@ -0,0 +1,72 @@ +##from:pcb +##geo:90 +##geo:female + +Element(0x00 "DSUB connector, female/male" "" "DB15F" 1000 2026 1 150 0x00) +( + # Gehaeuse (schmaler Kasten incl. Bohrungen) + ElementLine(635 880 665 880 10) + ElementLine(665 880 665 2416 10) + ElementLine(665 2416 635 2416 10) + ElementLine(635 2416 635 880 10) + ElementLine(635 940 665 940 10) + ElementLine(635 1060 665 1060 10) + ElementLine(635 2356 665 2356 10) + ElementLine(635 2236 665 2236 10) + # Gehaeuse (aeusserer Kasten) + # This part of the connector normally hangs off the circuit board, + # so it is confusing to actually mark it on the silkscreen + # define(`X1', `eval(BASEX-PANEL_DISTANCE-260)') + # define(`Y1', `eval(PY1-100)') + # define(`X2', `eval(BASEX-PANEL_DISTANCE)') + # define(`Y2', `eval(PY2+100)') + # ElementLine(X1 Y1 X2 Y1 20) + # ElementLine(X2 Y1 X2 Y2 10) + # ElementLine(X2 Y2 X1 Y2 20) + # ElementLine(X1 Y2 X1 Y1 20) + # Gehaeuse (innerer Kasten) + ElementLine(665 1110 770 1110 20) + ElementLine(770 1110 770 2186 20) + ElementLine(770 2186 665 2186 20) + ElementLine(665 2186 665 1110 10) + # Pins + # Pin 1 + Pin(1056 2026 60 35 "1" 0x101) + ElementLine(1016 2026 770 2026 20) + # Plazierungsmarkierung == PIN 1 + # Changed PY1 to PY2 13-Dec-1999 LRD + Mark(1056 2026) + # Remainder of the first row + Pin(1056 1918 60 35 "2" 0x01) + ElementLine(1016 1918 770 1918 20) + Pin(1056 1810 60 35 "3" 0x01) + ElementLine(1016 1810 770 1810 20) + Pin(1056 1702 60 35 "4" 0x01) + ElementLine(1016 1702 770 1702 20) + Pin(1056 1594 60 35 "5" 0x01) + ElementLine(1016 1594 770 1594 20) + Pin(1056 1486 60 35 "6" 0x01) + ElementLine(1016 1486 770 1486 20) + Pin(1056 1378 60 35 "7" 0x01) + ElementLine(1016 1378 770 1378 20) + Pin(1056 1270 60 35 "8" 0x01) + ElementLine(1016 1270 770 1270 20) + # Second row + Pin(944 1972 60 35 "9" 0x01) + ElementLine(904 1972 770 1972 20) + Pin(944 1864 60 35 "10" 0x01) + ElementLine(904 1864 770 1864 20) + Pin(944 1756 60 35 "11" 0x01) + ElementLine(904 1756 770 1756 20) + Pin(944 1648 60 35 "12" 0x01) + ElementLine(904 1648 770 1648 20) + Pin(944 1540 60 35 "13" 0x01) + ElementLine(904 1540 770 1540 20) + Pin(944 1432 60 35 "14" 0x01) + ElementLine(904 1432 770 1432 20) + Pin(944 1324 60 35 "15" 0x01) + ElementLine(904 1324 770 1324 20) + # Befestigungsbohrung + Pin(1000 1000 250 125 "C1" 0x01) + Pin(1000 2296 250 125 "C2" 0x01) +) Index: tags/2.1.2/pcblib/connector/DB15M.fp =================================================================== --- tags/2.1.2/pcblib/connector/DB15M.fp (nonexistent) +++ tags/2.1.2/pcblib/connector/DB15M.fp (revision 24813) @@ -0,0 +1,71 @@ +##from:pcb +##geo:90 +##geo:male + +Element(0x00 "DSUB connector, female/male" "" "DB15M" 1000 2026 1 150 0x00) +( + # Gehaeuse (schmaler Kasten incl. Bohrungen) + ElementLine(635 880 665 880 10) + ElementLine(665 880 665 2416 10) + ElementLine(665 2416 635 2416 10) + ElementLine(635 2416 635 880 10) + ElementLine(635 940 665 940 10) + ElementLine(635 1060 665 1060 10) + ElementLine(635 2356 665 2356 10) + ElementLine(635 2236 665 2236 10) + # Gehaeuse (aeusserer Kasten) + # This part of the connector normally hangs off the circuit board, + # so it is confusing to actually mark it on the silkscreen + # define(`X1', `eval(BASEX-PANEL_DISTANCE-260)') + # define(`Y1', `eval(PY1-100)') + # define(`X2', `eval(BASEX-PANEL_DISTANCE)') + # define(`Y2', `eval(PY2+100)') + # ElementLine(X1 Y1 X2 Y1 20) + # ElementLine(X2 Y1 X2 Y2 10) + # ElementLine(X2 Y2 X1 Y2 20) + # ElementLine(X1 Y2 X1 Y1 20) + # Gehaeuse (innerer Kasten) + ElementLine(665 1110 770 1110 20) + ElementLine(770 1110 770 2186 20) + ElementLine(770 2186 665 2186 20) + ElementLine(665 2186 665 1110 10) + # Pins + # First row + Pin(1056 1270 60 35 "1" 0x101) + ElementLine(1016 1270 770 1270 20) + Pin(1056 1378 60 35 "2" 0x01) + ElementLine(1016 1378 770 1378 20) + Pin(1056 1486 60 35 "3" 0x01) + ElementLine(1016 1486 770 1486 20) + Pin(1056 1594 60 35 "4" 0x01) + ElementLine(1016 1594 770 1594 20) + Pin(1056 1702 60 35 "5" 0x01) + ElementLine(1016 1702 770 1702 20) + Pin(1056 1810 60 35 "6" 0x01) + ElementLine(1016 1810 770 1810 20) + Pin(1056 1918 60 35 "7" 0x01) + ElementLine(1016 1918 770 1918 20) + # Last pin in first row + Pin(1056 2026 60 35 "8" 0x01) + ElementLine(1016 2026 770 2026 20) + # Second row + Pin(944 1324 60 35 "9" 0x01) + ElementLine(904 1324 770 1324 20) + Pin(944 1432 60 35 "10" 0x01) + ElementLine(904 1432 770 1432 20) + Pin(944 1540 60 35 "11" 0x01) + ElementLine(904 1540 770 1540 20) + Pin(944 1648 60 35 "12" 0x01) + ElementLine(904 1648 770 1648 20) + Pin(944 1756 60 35 "13" 0x01) + ElementLine(904 1756 770 1756 20) + Pin(944 1864 60 35 "14" 0x01) + ElementLine(904 1864 770 1864 20) + Pin(944 1972 60 35 "15" 0x01) + ElementLine(904 1972 770 1972 20) + # Plazierungsmarkierung == PIN 1 + Mark(1050 1270) + # Befestigungsbohrung + Pin(1000 1000 250 125 "C1" 0x01) + Pin(1000 2296 250 125 "C2" 0x01) +) Index: tags/2.1.2/pcblib/connector/DB25F.fp =================================================================== --- tags/2.1.2/pcblib/connector/DB25F.fp (nonexistent) +++ tags/2.1.2/pcblib/connector/DB25F.fp (revision 24813) @@ -0,0 +1,92 @@ +##from:pcb +##geo:90 +##geo:female + +Element(0x00 "DSUB connector, female/male" "" "DB25F" 1000 2566 1 150 0x00) +( + # Gehaeuse (schmaler Kasten incl. Bohrungen) + ElementLine(635 880 665 880 10) + ElementLine(665 880 665 2956 10) + ElementLine(665 2956 635 2956 10) + ElementLine(635 2956 635 880 10) + ElementLine(635 940 665 940 10) + ElementLine(635 1060 665 1060 10) + ElementLine(635 2896 665 2896 10) + ElementLine(635 2776 665 2776 10) + # Gehaeuse (aeusserer Kasten) + # This part of the connector normally hangs off the circuit board, + # so it is confusing to actually mark it on the silkscreen + # define(`X1', `eval(BASEX-PANEL_DISTANCE-260)') + # define(`Y1', `eval(PY1-100)') + # define(`X2', `eval(BASEX-PANEL_DISTANCE)') + # define(`Y2', `eval(PY2+100)') + # ElementLine(X1 Y1 X2 Y1 20) + # ElementLine(X2 Y1 X2 Y2 10) + # ElementLine(X2 Y2 X1 Y2 20) + # ElementLine(X1 Y2 X1 Y1 20) + # Gehaeuse (innerer Kasten) + ElementLine(665 1110 770 1110 20) + ElementLine(770 1110 770 2726 20) + ElementLine(770 2726 665 2726 20) + ElementLine(665 2726 665 1110 10) + # Pins + # Pin 1 + Pin(1056 2566 60 35 "1" 0x101) + ElementLine(1016 2566 770 2566 20) + # Plazierungsmarkierung == PIN 1 + # Changed PY1 to PY2 13-Dec-1999 LRD + Mark(1056 2566) + # Remainder of the first row + Pin(1056 2458 60 35 "2" 0x01) + ElementLine(1016 2458 770 2458 20) + Pin(1056 2350 60 35 "3" 0x01) + ElementLine(1016 2350 770 2350 20) + Pin(1056 2242 60 35 "4" 0x01) + ElementLine(1016 2242 770 2242 20) + Pin(1056 2134 60 35 "5" 0x01) + ElementLine(1016 2134 770 2134 20) + Pin(1056 2026 60 35 "6" 0x01) + ElementLine(1016 2026 770 2026 20) + Pin(1056 1918 60 35 "7" 0x01) + ElementLine(1016 1918 770 1918 20) + Pin(1056 1810 60 35 "8" 0x01) + ElementLine(1016 1810 770 1810 20) + Pin(1056 1702 60 35 "9" 0x01) + ElementLine(1016 1702 770 1702 20) + Pin(1056 1594 60 35 "10" 0x01) + ElementLine(1016 1594 770 1594 20) + Pin(1056 1486 60 35 "11" 0x01) + ElementLine(1016 1486 770 1486 20) + Pin(1056 1378 60 35 "12" 0x01) + ElementLine(1016 1378 770 1378 20) + Pin(1056 1270 60 35 "13" 0x01) + ElementLine(1016 1270 770 1270 20) + # Second row + Pin(944 2512 60 35 "14" 0x01) + ElementLine(904 2512 770 2512 20) + Pin(944 2404 60 35 "15" 0x01) + ElementLine(904 2404 770 2404 20) + Pin(944 2296 60 35 "16" 0x01) + ElementLine(904 2296 770 2296 20) + Pin(944 2188 60 35 "17" 0x01) + ElementLine(904 2188 770 2188 20) + Pin(944 2080 60 35 "18" 0x01) + ElementLine(904 2080 770 2080 20) + Pin(944 1972 60 35 "19" 0x01) + ElementLine(904 1972 770 1972 20) + Pin(944 1864 60 35 "20" 0x01) + ElementLine(904 1864 770 1864 20) + Pin(944 1756 60 35 "21" 0x01) + ElementLine(904 1756 770 1756 20) + Pin(944 1648 60 35 "22" 0x01) + ElementLine(904 1648 770 1648 20) + Pin(944 1540 60 35 "23" 0x01) + ElementLine(904 1540 770 1540 20) + Pin(944 1432 60 35 "24" 0x01) + ElementLine(904 1432 770 1432 20) + Pin(944 1324 60 35 "25" 0x01) + ElementLine(904 1324 770 1324 20) + # Befestigungsbohrung + Pin(1000 1000 250 125 "C1" 0x01) + Pin(1000 2836 250 125 "C2" 0x01) +) Index: tags/2.1.2/pcblib/connector/DB25M.fp =================================================================== --- tags/2.1.2/pcblib/connector/DB25M.fp (nonexistent) +++ tags/2.1.2/pcblib/connector/DB25M.fp (revision 24813) @@ -0,0 +1,91 @@ +##from:pcb +##geo:90 +##geo:male + +Element(0x00 "DSUB connector, female/male" "" "DB25M" 1000 2566 1 150 0x00) +( + # Gehaeuse (schmaler Kasten incl. Bohrungen) + ElementLine(635 880 665 880 10) + ElementLine(665 880 665 2956 10) + ElementLine(665 2956 635 2956 10) + ElementLine(635 2956 635 880 10) + ElementLine(635 940 665 940 10) + ElementLine(635 1060 665 1060 10) + ElementLine(635 2896 665 2896 10) + ElementLine(635 2776 665 2776 10) + # Gehaeuse (aeusserer Kasten) + # This part of the connector normally hangs off the circuit board, + # so it is confusing to actually mark it on the silkscreen + # define(`X1', `eval(BASEX-PANEL_DISTANCE-260)') + # define(`Y1', `eval(PY1-100)') + # define(`X2', `eval(BASEX-PANEL_DISTANCE)') + # define(`Y2', `eval(PY2+100)') + # ElementLine(X1 Y1 X2 Y1 20) + # ElementLine(X2 Y1 X2 Y2 10) + # ElementLine(X2 Y2 X1 Y2 20) + # ElementLine(X1 Y2 X1 Y1 20) + # Gehaeuse (innerer Kasten) + ElementLine(665 1110 770 1110 20) + ElementLine(770 1110 770 2726 20) + ElementLine(770 2726 665 2726 20) + ElementLine(665 2726 665 1110 10) + # Pins + # First row + Pin(1056 1270 60 35 "1" 0x101) + ElementLine(1016 1270 770 1270 20) + Pin(1056 1378 60 35 "2" 0x01) + ElementLine(1016 1378 770 1378 20) + Pin(1056 1486 60 35 "3" 0x01) + ElementLine(1016 1486 770 1486 20) + Pin(1056 1594 60 35 "4" 0x01) + ElementLine(1016 1594 770 1594 20) + Pin(1056 1702 60 35 "5" 0x01) + ElementLine(1016 1702 770 1702 20) + Pin(1056 1810 60 35 "6" 0x01) + ElementLine(1016 1810 770 1810 20) + Pin(1056 1918 60 35 "7" 0x01) + ElementLine(1016 1918 770 1918 20) + Pin(1056 2026 60 35 "8" 0x01) + ElementLine(1016 2026 770 2026 20) + Pin(1056 2134 60 35 "9" 0x01) + ElementLine(1016 2134 770 2134 20) + Pin(1056 2242 60 35 "10" 0x01) + ElementLine(1016 2242 770 2242 20) + Pin(1056 2350 60 35 "11" 0x01) + ElementLine(1016 2350 770 2350 20) + Pin(1056 2458 60 35 "12" 0x01) + ElementLine(1016 2458 770 2458 20) + # Last pin in first row + Pin(1056 2566 60 35 "13" 0x01) + ElementLine(1016 2566 770 2566 20) + # Second row + Pin(944 1324 60 35 "14" 0x01) + ElementLine(904 1324 770 1324 20) + Pin(944 1432 60 35 "15" 0x01) + ElementLine(904 1432 770 1432 20) + Pin(944 1540 60 35 "16" 0x01) + ElementLine(904 1540 770 1540 20) + Pin(944 1648 60 35 "17" 0x01) + ElementLine(904 1648 770 1648 20) + Pin(944 1756 60 35 "18" 0x01) + ElementLine(904 1756 770 1756 20) + Pin(944 1864 60 35 "19" 0x01) + ElementLine(904 1864 770 1864 20) + Pin(944 1972 60 35 "20" 0x01) + ElementLine(904 1972 770 1972 20) + Pin(944 2080 60 35 "21" 0x01) + ElementLine(904 2080 770 2080 20) + Pin(944 2188 60 35 "22" 0x01) + ElementLine(904 2188 770 2188 20) + Pin(944 2296 60 35 "23" 0x01) + ElementLine(904 2296 770 2296 20) + Pin(944 2404 60 35 "24" 0x01) + ElementLine(904 2404 770 2404 20) + Pin(944 2512 60 35 "25" 0x01) + ElementLine(904 2512 770 2512 20) + # Plazierungsmarkierung == PIN 1 + Mark(1050 1270) + # Befestigungsbohrung + Pin(1000 1000 250 125 "C1" 0x01) + Pin(1000 2836 250 125 "C2" 0x01) +) Index: tags/2.1.2/pcblib/connector/DB37F.fp =================================================================== --- tags/2.1.2/pcblib/connector/DB37F.fp (nonexistent) +++ tags/2.1.2/pcblib/connector/DB37F.fp (revision 24813) @@ -0,0 +1,116 @@ +##from:pcb +##geo:90 +##geo:female + +Element(0x00 "DSUB connector, female/male" "" "DB37F" 1000 3214 1 150 0x00) +( + # Gehaeuse (schmaler Kasten incl. Bohrungen) + ElementLine(635 880 665 880 10) + ElementLine(665 880 665 3604 10) + ElementLine(665 3604 635 3604 10) + ElementLine(635 3604 635 880 10) + ElementLine(635 940 665 940 10) + ElementLine(635 1060 665 1060 10) + ElementLine(635 3544 665 3544 10) + ElementLine(635 3424 665 3424 10) + # Gehaeuse (aeusserer Kasten) + # This part of the connector normally hangs off the circuit board, + # so it is confusing to actually mark it on the silkscreen + # define(`X1', `eval(BASEX-PANEL_DISTANCE-260)') + # define(`Y1', `eval(PY1-100)') + # define(`X2', `eval(BASEX-PANEL_DISTANCE)') + # define(`Y2', `eval(PY2+100)') + # ElementLine(X1 Y1 X2 Y1 20) + # ElementLine(X2 Y1 X2 Y2 10) + # ElementLine(X2 Y2 X1 Y2 20) + # ElementLine(X1 Y2 X1 Y1 20) + # Gehaeuse (innerer Kasten) + ElementLine(665 1110 770 1110 20) + ElementLine(770 1110 770 3374 20) + ElementLine(770 3374 665 3374 20) + ElementLine(665 3374 665 1110 10) + # Pins + # Pin 1 + Pin(1056 3214 60 35 "1" 0x101) + ElementLine(1016 3214 770 3214 20) + # Plazierungsmarkierung == PIN 1 + # Changed PY1 to PY2 13-Dec-1999 LRD + Mark(1056 3214) + # Remainder of the first row + Pin(1056 3106 60 35 "2" 0x01) + ElementLine(1016 3106 770 3106 20) + Pin(1056 2998 60 35 "3" 0x01) + ElementLine(1016 2998 770 2998 20) + Pin(1056 2890 60 35 "4" 0x01) + ElementLine(1016 2890 770 2890 20) + Pin(1056 2782 60 35 "5" 0x01) + ElementLine(1016 2782 770 2782 20) + Pin(1056 2674 60 35 "6" 0x01) + ElementLine(1016 2674 770 2674 20) + Pin(1056 2566 60 35 "7" 0x01) + ElementLine(1016 2566 770 2566 20) + Pin(1056 2458 60 35 "8" 0x01) + ElementLine(1016 2458 770 2458 20) + Pin(1056 2350 60 35 "9" 0x01) + ElementLine(1016 2350 770 2350 20) + Pin(1056 2242 60 35 "10" 0x01) + ElementLine(1016 2242 770 2242 20) + Pin(1056 2134 60 35 "11" 0x01) + ElementLine(1016 2134 770 2134 20) + Pin(1056 2026 60 35 "12" 0x01) + ElementLine(1016 2026 770 2026 20) + Pin(1056 1918 60 35 "13" 0x01) + ElementLine(1016 1918 770 1918 20) + Pin(1056 1810 60 35 "14" 0x01) + ElementLine(1016 1810 770 1810 20) + Pin(1056 1702 60 35 "15" 0x01) + ElementLine(1016 1702 770 1702 20) + Pin(1056 1594 60 35 "16" 0x01) + ElementLine(1016 1594 770 1594 20) + Pin(1056 1486 60 35 "17" 0x01) + ElementLine(1016 1486 770 1486 20) + Pin(1056 1378 60 35 "18" 0x01) + ElementLine(1016 1378 770 1378 20) + Pin(1056 1270 60 35 "19" 0x01) + ElementLine(1016 1270 770 1270 20) + # Second row + Pin(944 3160 60 35 "20" 0x01) + ElementLine(904 3160 770 3160 20) + Pin(944 3052 60 35 "21" 0x01) + ElementLine(904 3052 770 3052 20) + Pin(944 2944 60 35 "22" 0x01) + ElementLine(904 2944 770 2944 20) + Pin(944 2836 60 35 "23" 0x01) + ElementLine(904 2836 770 2836 20) + Pin(944 2728 60 35 "24" 0x01) + ElementLine(904 2728 770 2728 20) + Pin(944 2620 60 35 "25" 0x01) + ElementLine(904 2620 770 2620 20) + Pin(944 2512 60 35 "26" 0x01) + ElementLine(904 2512 770 2512 20) + Pin(944 2404 60 35 "27" 0x01) + ElementLine(904 2404 770 2404 20) + Pin(944 2296 60 35 "28" 0x01) + ElementLine(904 2296 770 2296 20) + Pin(944 2188 60 35 "29" 0x01) + ElementLine(904 2188 770 2188 20) + Pin(944 2080 60 35 "30" 0x01) + ElementLine(904 2080 770 2080 20) + Pin(944 1972 60 35 "31" 0x01) + ElementLine(904 1972 770 1972 20) + Pin(944 1864 60 35 "32" 0x01) + ElementLine(904 1864 770 1864 20) + Pin(944 1756 60 35 "33" 0x01) + ElementLine(904 1756 770 1756 20) + Pin(944 1648 60 35 "34" 0x01) + ElementLine(904 1648 770 1648 20) + Pin(944 1540 60 35 "35" 0x01) + ElementLine(904 1540 770 1540 20) + Pin(944 1432 60 35 "36" 0x01) + ElementLine(904 1432 770 1432 20) + Pin(944 1324 60 35 "37" 0x01) + ElementLine(904 1324 770 1324 20) + # Befestigungsbohrung + Pin(1000 1000 250 125 "C1" 0x01) + Pin(1000 3484 250 125 "C2" 0x01) +) Index: tags/2.1.2/pcblib/connector/DB37M.fp =================================================================== --- tags/2.1.2/pcblib/connector/DB37M.fp (nonexistent) +++ tags/2.1.2/pcblib/connector/DB37M.fp (revision 24813) @@ -0,0 +1,115 @@ +##from:pcb +##geo:90 +##geo:male + +Element(0x00 "DSUB connector, female/male" "" "DB37M" 1000 3214 1 150 0x00) +( + # Gehaeuse (schmaler Kasten incl. Bohrungen) + ElementLine(635 880 665 880 10) + ElementLine(665 880 665 3604 10) + ElementLine(665 3604 635 3604 10) + ElementLine(635 3604 635 880 10) + ElementLine(635 940 665 940 10) + ElementLine(635 1060 665 1060 10) + ElementLine(635 3544 665 3544 10) + ElementLine(635 3424 665 3424 10) + # Gehaeuse (aeusserer Kasten) + # This part of the connector normally hangs off the circuit board, + # so it is confusing to actually mark it on the silkscreen + # define(`X1', `eval(BASEX-PANEL_DISTANCE-260)') + # define(`Y1', `eval(PY1-100)') + # define(`X2', `eval(BASEX-PANEL_DISTANCE)') + # define(`Y2', `eval(PY2+100)') + # ElementLine(X1 Y1 X2 Y1 20) + # ElementLine(X2 Y1 X2 Y2 10) + # ElementLine(X2 Y2 X1 Y2 20) + # ElementLine(X1 Y2 X1 Y1 20) + # Gehaeuse (innerer Kasten) + ElementLine(665 1110 770 1110 20) + ElementLine(770 1110 770 3374 20) + ElementLine(770 3374 665 3374 20) + ElementLine(665 3374 665 1110 10) + # Pins + # First row + Pin(1056 1270 60 35 "1" 0x101) + ElementLine(1016 1270 770 1270 20) + Pin(1056 1378 60 35 "2" 0x01) + ElementLine(1016 1378 770 1378 20) + Pin(1056 1486 60 35 "3" 0x01) + ElementLine(1016 1486 770 1486 20) + Pin(1056 1594 60 35 "4" 0x01) + ElementLine(1016 1594 770 1594 20) + Pin(1056 1702 60 35 "5" 0x01) + ElementLine(1016 1702 770 1702 20) + Pin(1056 1810 60 35 "6" 0x01) + ElementLine(1016 1810 770 1810 20) + Pin(1056 1918 60 35 "7" 0x01) + ElementLine(1016 1918 770 1918 20) + Pin(1056 2026 60 35 "8" 0x01) + ElementLine(1016 2026 770 2026 20) + Pin(1056 2134 60 35 "9" 0x01) + ElementLine(1016 2134 770 2134 20) + Pin(1056 2242 60 35 "10" 0x01) + ElementLine(1016 2242 770 2242 20) + Pin(1056 2350 60 35 "11" 0x01) + ElementLine(1016 2350 770 2350 20) + Pin(1056 2458 60 35 "12" 0x01) + ElementLine(1016 2458 770 2458 20) + Pin(1056 2566 60 35 "13" 0x01) + ElementLine(1016 2566 770 2566 20) + Pin(1056 2674 60 35 "14" 0x01) + ElementLine(1016 2674 770 2674 20) + Pin(1056 2782 60 35 "15" 0x01) + ElementLine(1016 2782 770 2782 20) + Pin(1056 2890 60 35 "16" 0x01) + ElementLine(1016 2890 770 2890 20) + Pin(1056 2998 60 35 "17" 0x01) + ElementLine(1016 2998 770 2998 20) + Pin(1056 3106 60 35 "18" 0x01) + ElementLine(1016 3106 770 3106 20) + # Last pin in first row + Pin(1056 3214 60 35 "19" 0x01) + ElementLine(1016 3214 770 3214 20) + # Second row + Pin(944 1324 60 35 "20" 0x01) + ElementLine(904 1324 770 1324 20) + Pin(944 1432 60 35 "21" 0x01) + ElementLine(904 1432 770 1432 20) + Pin(944 1540 60 35 "22" 0x01) + ElementLine(904 1540 770 1540 20) + Pin(944 1648 60 35 "23" 0x01) + ElementLine(904 1648 770 1648 20) + Pin(944 1756 60 35 "24" 0x01) + ElementLine(904 1756 770 1756 20) + Pin(944 1864 60 35 "25" 0x01) + ElementLine(904 1864 770 1864 20) + Pin(944 1972 60 35 "26" 0x01) + ElementLine(904 1972 770 1972 20) + Pin(944 2080 60 35 "27" 0x01) + ElementLine(904 2080 770 2080 20) + Pin(944 2188 60 35 "28" 0x01) + ElementLine(904 2188 770 2188 20) + Pin(944 2296 60 35 "29" 0x01) + ElementLine(904 2296 770 2296 20) + Pin(944 2404 60 35 "30" 0x01) + ElementLine(904 2404 770 2404 20) + Pin(944 2512 60 35 "31" 0x01) + ElementLine(904 2512 770 2512 20) + Pin(944 2620 60 35 "32" 0x01) + ElementLine(904 2620 770 2620 20) + Pin(944 2728 60 35 "33" 0x01) + ElementLine(904 2728 770 2728 20) + Pin(944 2836 60 35 "34" 0x01) + ElementLine(904 2836 770 2836 20) + Pin(944 2944 60 35 "35" 0x01) + ElementLine(904 2944 770 2944 20) + Pin(944 3052 60 35 "36" 0x01) + ElementLine(904 3052 770 3052 20) + Pin(944 3160 60 35 "37" 0x01) + ElementLine(904 3160 770 3160 20) + # Plazierungsmarkierung == PIN 1 + Mark(1050 1270) + # Befestigungsbohrung + Pin(1000 1000 250 125 "C1" 0x01) + Pin(1000 3484 250 125 "C2" 0x01) +) Index: tags/2.1.2/pcblib/connector/DB9F.fp =================================================================== --- tags/2.1.2/pcblib/connector/DB9F.fp (nonexistent) +++ tags/2.1.2/pcblib/connector/DB9F.fp (revision 24813) @@ -0,0 +1,60 @@ +##from:pcb +##geo:90 +##geo:female + +Element(0x00 "DSUB connector, female/male" "" "DB9F" 1000 1702 1 150 0x00) +( + # Gehaeuse (schmaler Kasten incl. Bohrungen) + ElementLine(635 880 665 880 10) + ElementLine(665 880 665 2092 10) + ElementLine(665 2092 635 2092 10) + ElementLine(635 2092 635 880 10) + ElementLine(635 940 665 940 10) + ElementLine(635 1060 665 1060 10) + ElementLine(635 2032 665 2032 10) + ElementLine(635 1912 665 1912 10) + # Gehaeuse (aeusserer Kasten) + # This part of the connector normally hangs off the circuit board, + # so it is confusing to actually mark it on the silkscreen + # define(`X1', `eval(BASEX-PANEL_DISTANCE-260)') + # define(`Y1', `eval(PY1-100)') + # define(`X2', `eval(BASEX-PANEL_DISTANCE)') + # define(`Y2', `eval(PY2+100)') + # ElementLine(X1 Y1 X2 Y1 20) + # ElementLine(X2 Y1 X2 Y2 10) + # ElementLine(X2 Y2 X1 Y2 20) + # ElementLine(X1 Y2 X1 Y1 20) + # Gehaeuse (innerer Kasten) + ElementLine(665 1110 770 1110 20) + ElementLine(770 1110 770 1862 20) + ElementLine(770 1862 665 1862 20) + ElementLine(665 1862 665 1110 10) + # Pins + # Pin 1 + Pin(1056 1702 60 35 "1" 0x101) + ElementLine(1016 1702 770 1702 20) + # Plazierungsmarkierung == PIN 1 + # Changed PY1 to PY2 13-Dec-1999 LRD + Mark(1056 1702) + # Remainder of the first row + Pin(1056 1594 60 35 "2" 0x01) + ElementLine(1016 1594 770 1594 20) + Pin(1056 1486 60 35 "3" 0x01) + ElementLine(1016 1486 770 1486 20) + Pin(1056 1378 60 35 "4" 0x01) + ElementLine(1016 1378 770 1378 20) + Pin(1056 1270 60 35 "5" 0x01) + ElementLine(1016 1270 770 1270 20) + # Second row + Pin(944 1648 60 35 "6" 0x01) + ElementLine(904 1648 770 1648 20) + Pin(944 1540 60 35 "7" 0x01) + ElementLine(904 1540 770 1540 20) + Pin(944 1432 60 35 "8" 0x01) + ElementLine(904 1432 770 1432 20) + Pin(944 1324 60 35 "9" 0x01) + ElementLine(904 1324 770 1324 20) + # Befestigungsbohrung + Pin(1000 1000 250 125 "C1" 0x01) + Pin(1000 1972 250 125 "C2" 0x01) +) Index: tags/2.1.2/pcblib/connector/DB9M.fp =================================================================== --- tags/2.1.2/pcblib/connector/DB9M.fp (nonexistent) +++ tags/2.1.2/pcblib/connector/DB9M.fp (revision 24813) @@ -0,0 +1,59 @@ +##from:pcb +##geo:90 +##geo:male + +Element(0x00 "DSUB connector, female/male" "" "DB9M" 1000 1702 1 150 0x00) +( + # Gehaeuse (schmaler Kasten incl. Bohrungen) + ElementLine(635 880 665 880 10) + ElementLine(665 880 665 2092 10) + ElementLine(665 2092 635 2092 10) + ElementLine(635 2092 635 880 10) + ElementLine(635 940 665 940 10) + ElementLine(635 1060 665 1060 10) + ElementLine(635 2032 665 2032 10) + ElementLine(635 1912 665 1912 10) + # Gehaeuse (aeusserer Kasten) + # This part of the connector normally hangs off the circuit board, + # so it is confusing to actually mark it on the silkscreen + # define(`X1', `eval(BASEX-PANEL_DISTANCE-260)') + # define(`Y1', `eval(PY1-100)') + # define(`X2', `eval(BASEX-PANEL_DISTANCE)') + # define(`Y2', `eval(PY2+100)') + # ElementLine(X1 Y1 X2 Y1 20) + # ElementLine(X2 Y1 X2 Y2 10) + # ElementLine(X2 Y2 X1 Y2 20) + # ElementLine(X1 Y2 X1 Y1 20) + # Gehaeuse (innerer Kasten) + ElementLine(665 1110 770 1110 20) + ElementLine(770 1110 770 1862 20) + ElementLine(770 1862 665 1862 20) + ElementLine(665 1862 665 1110 10) + # Pins + # First row + Pin(1056 1270 60 35 "1" 0x101) + ElementLine(1016 1270 770 1270 20) + Pin(1056 1378 60 35 "2" 0x01) + ElementLine(1016 1378 770 1378 20) + Pin(1056 1486 60 35 "3" 0x01) + ElementLine(1016 1486 770 1486 20) + Pin(1056 1594 60 35 "4" 0x01) + ElementLine(1016 1594 770 1594 20) + # Last pin in first row + Pin(1056 1702 60 35 "5" 0x01) + ElementLine(1016 1702 770 1702 20) + # Second row + Pin(944 1324 60 35 "6" 0x01) + ElementLine(904 1324 770 1324 20) + Pin(944 1432 60 35 "7" 0x01) + ElementLine(904 1432 770 1432 20) + Pin(944 1540 60 35 "8" 0x01) + ElementLine(904 1540 770 1540 20) + Pin(944 1648 60 35 "9" 0x01) + ElementLine(904 1648 770 1648 20) + # Plazierungsmarkierung == PIN 1 + Mark(1050 1270) + # Befestigungsbohrung + Pin(1000 1000 250 125 "C1" 0x01) + Pin(1000 1972 250 125 "C2" 0x01) +) Index: tags/2.1.2/pcblib/connector/pwrjack.fp =================================================================== --- tags/2.1.2/pcblib/connector/pwrjack.fp (nonexistent) +++ tags/2.1.2/pcblib/connector/pwrjack.fp (revision 24813) @@ -0,0 +1,16 @@ +##from:repo.hu/projects/openhw +##geo:90 +##geo:male + +Element["" "" "" "pwrjack" 124016 141732 0 0 0 100 ""] +( + Pin[0 0 19685 2000 20285 11811 "" "2" ""] + Pin[0 -27559 19685 2000 20285 11811 "" "1" ""] + Pin[-17717 -13779 19685 2000 20285 11811 "" "3" ""] + ElementLine [-17717 -55118 -17717 0 1000] + ElementLine [-17717 0 17716 0 1000] + ElementLine [17716 0 17716 -55118 1000] + ElementLine [17716 -55118 -17717 -55118 1000] + ElementLine [-17717 -43307 17716 -43307 1000] + + ) Index: tags/2.1.2/pcblib/parametric/acy =================================================================== --- tags/2.1.2/pcblib/parametric/acy (nonexistent) +++ tags/2.1.2/pcblib/parametric/acy (revision 24813) @@ -0,0 +1,56 @@ +#!/bin/sh + +#@@example acy(300) + +#@@purpose Generate axial lead through-hole component + +#@@desc Generate axial lead through-hole component with 2 pins (typical use: resistor) +#@@params spacing,type,pol,dia + +#@@param:spacing spacing between the two pins +#@@dim:spacing + +#@@param:type silk symbol type +#@@enum:type:block eu-style block resistor symbol +#@@enum:type:endcap block resistor with caps on the ends +#@@enum:type:zigzag us-style zigzag resistor symbol +#@@enum:type:line a single line (e.g. for jumper wires) +#@@enum:type:standing vertically aligned, body standing on pin 1, pin 2 bent back +#@@enum:type:coil wavy coil symbol +#@@enum:type:core wavy coil symbol with a parallel line +#@@enum:type:core2 wavy coil symbol with two parallel lines +#@@optional:type +#@@default:type block +#@@preview_args:type 300 + +#@@param:pol how to mark polarity +#@@enum:pol:none no marking +#@@enum:pol:sign + and - signs; pin 1 is + +#@@enum:pol:bar bar next to pin 1 +#@@enum:pol:dot dot next to pin 1 +#@@optional:pol +#@@default:pol none +#@@preview_args:pol 300 + +#@@param:dia body diameter - affects silk size +#@@dim:dia +#@@optional:dia +#@@default:dia spacing/6 + + +#@@param:wiper silk symbol wiper type +#@@enum:wiper:none no wiper +#@@enum:wiper:parrow perpendicular arrow, pointing inwards +#@@enum:wiper:aarrow angled arrow, pointing outwards +#@@enum:wiper:looparrow arrow starting at pin 2 looping back to point inwards on the body +#@@enum:wiper:thermistor wiper of a thermistor symbol +#@@optional:wiper +#@@default:wiper none +#@@preview_args:wiper 400 + +#@@thumbsize 2 + +#@@include common.awk + +awk -f `dirname $0`/common.awk -f `dirname $0`/acy.awk -v "args=$*" -v gen=`basename $0` -v "genfull=$0" + Property changes on: tags/2.1.2/pcblib/parametric/acy ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/2.1.2/pcblib/parametric/acy.awk =================================================================== --- tags/2.1.2/pcblib/parametric/acy.awk (nonexistent) +++ tags/2.1.2/pcblib/parametric/acy.awk (revision 24813) @@ -0,0 +1,153 @@ +function wave(type, repeat, step,x,y) +{ + step = len/repeat + for(x = sx1; x < sx2; x += step) { + if (type == 1) { + element_arc(x+step/2, 0, step/2, step/2, 0, -180) + } + else if (type == 2) { + y = dia + element_line(x, 0, x+step/4, -y) + element_line(x+step/4, -y, x+3*step/4, y) + element_line(x+3*step/4, y, x+step, 0) + + } + } +} + +BEGIN { + help_auto() + set_arg(P, "?type", "block") + proc_args(P, "spacing,type,pol,dia", "spacing") + + spacing = parse_dim(P["spacing"]) + dia = either(parse_dim(P["dia"]), spacing/6) + +# oops, dia is a radius rather + dia=dia/2 + + offs_x = +spacing/2 + + element_begin("", "R1", "acy" P["spacing"] ,0,0, spacing/2-spacing/5,-mil(20)) + + element_pin(-spacing/2, 0, 1) + element_pin(+spacing/2, 0, 2) + + dimension(-spacing/2, 0, +spacing/2, 0, dia*4, "spacing") + +# silk pins + if (P["type"] != "line") { + element_line(-spacing/2, 0, -spacing/4, 0) + element_line(+spacing/4, 0, +spacing/2, 0) + } + +# silk symbol + sx1 = -spacing/4 + sx2 = +spacing/4 + len = sx2-sx1 + if (P["type"] == "block") { + element_rectangle(sx1, -dia, sx2, +dia) + } + else if (P["type"] == "zigzag") { + wave(2, 3) + } + else if (P["type"] == "coil") { + wave(1, 4) + } + else if (P["type"] == "endcap") { + cl1 = len/9 + cl2 = len/8 + y1 = dia*1.2 + y2 = dia + rarc = dia/5 + element_line(sx1+cl2, y2, sx2-cl2, y2) + element_line(sx1+cl2, y2, sx1+cl1, y1) + element_line(sx2-cl2, y2, sx2-cl1, y1) + + element_line(sx1+cl2, -y2, sx2-cl2, -y2) + element_line(sx1+cl2, -y2, sx1+cl1, -y1) + element_line(sx2-cl2, -y2, sx2-cl1, -y1) + + element_rectangle(sx1, y1, sx1+cl1, -y1, "right,NE,SE", rarc) + element_rectangle(sx2-cl1, y1, sx2, -y1, "left,NW,SW", rarc) + } + else if (P["type"] ~ "^core") { + wave(1, 4) + nlines = P["type"] + sub("^core", "", nlines) + if (nlines == "") + nlines = 1 + + cdist = 3 * DEFAULT["line_thickness"] + y = -len/8 + for(nlines = int(nlines); nlines > 0; nlines--) { + y-=cdist + element_line(sx1, y, sx2, y) + } + } + else if (P["type"] == "line") { + element_line(-spacing/2, 0, +spacing/2, 0) + } + else if (P["type"] == "standing") { + r = dia*2 + if (r < DEFAULT["pin_ringdia"]/2*1.2) + r = DEFAULT["pin_ringdia"]/2*1.2 + element_arc(-spacing/2, 0, r, r, 0, 360) + element_line(-spacing/2, 0, +spacing/2, 0) + } + else { + error("Invalid type") + } + + dimension(sx2, -dia, sx2, dia, spacing/2, "dia") + +# silk wiper + if (P["wiper"] == "thermistor") { + x = len/3 + element_line(-4*x/4, dia*2, -2*x/4, dia*2) + element_line(-2*x/4, dia*2, +2*x/4, -dia*2) + } + else if (P["wiper"] == "aarrow") { + x = len/3 + element_arrow(-2*x/4, dia*2, +2*x/4, -dia*2-mil(30)) + } + else if (P["wiper"] == "parrow") { + element_arrow(0, -dia*2-mil(30), 0, -dia) + } + else if (P["wiper"] == "looparrow") { + y = -dia*2-mil(30) + x = sx2+len/8 + element_arrow(0, y, 0, -dia) + element_line(0, y, x, y) + element_line(x, y, x, 0) + } + else if ((P["wiper"] != "none") && (P["wiper"] != "")) { + error("Invalid wiper") + } + +# silk sign + if (P["pol"] == "sign") { + size=mil(10) + + offs_y = size*2.2 + offs_x = DEFAULT["pin_ringdia"]/2+size*1.1 + element_line(-size, 0, +size, 0) + + offs_x = spacing - (DEFAULT["pin_ringdia"]/2+size*1.1) + element_line(-size, 0, +size, 0) + element_line(0, -size, 0, +size) + } + else if (P["pol"] == "bar") { + offs=DEFAULT["line_thickness"] + element_rectangle(-spacing/4-offs, -dia, -spacing/4+offs, +dia, DEFAULT["line_thickness"]*4) + } + else if (P["pol"] == "dot") { + r=2*DEFAULT["line_thickness"]/3 + element_arc(-spacing/4-r*3, -dia/2, r, r, 0, 360) + } + else if ((P["pol"] != "") && (P["pol"] != "none")) { + error("Invalid pol") + } + + element_end() +} Index: tags/2.1.2/pcblib/parametric/alf =================================================================== --- tags/2.1.2/pcblib/parametric/alf (nonexistent) +++ tags/2.1.2/pcblib/parametric/alf (revision 24813) @@ -0,0 +1,37 @@ +#!/bin/sh + +#@@example alf(300, schottky) + +#@@purpose Generate ALF: axial lead through-hole component for diodes + +#@@desc Generate axial lead through-hole component with 2 pin diodes +#@@params spacing,type,dia +#@@thumbsize 2 + +#@@param:spacing spacing between the two pins +#@@dim:spacing + +#@@param:type symbol type +#@@enum:type:normal +#@@enum:type:schottky +#@@enum:type:zener +#@@enum:type:tunnel +#@@enum:type:varactor +#@@optional:type +#@@default:type normal +#@@preview_args:type 300 + +#@@param:dia body diameter - affects silk symbol size +#@@dim:dia +#@@optional:dia +#@@default:dia spacing/12 + +#@@param:aspect silk symbol aspect: total width expressed as a portion of spacing +#@@optional:aspect +#@@default:aspect spacing/6 + + +#@@include common.awk + +awk -f `dirname $0`/common.awk -f `dirname $0`/alf.awk -v "args=$*" -v gen=`basename $0` -v "genfull=$0" + Property changes on: tags/2.1.2/pcblib/parametric/alf ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/2.1.2/pcblib/parametric/alf.awk =================================================================== --- tags/2.1.2/pcblib/parametric/alf.awk (nonexistent) +++ tags/2.1.2/pcblib/parametric/alf.awk (revision 24813) @@ -0,0 +1,65 @@ +BEGIN { + help_auto() + set_arg(P, "?aspect", 6) + set_arg(P, "?type", "normal") + + proc_args(P, "spacing,type,dia,aspect", "spacing") + + spacing = parse_dim(P["spacing"]) + dia = either(parse_dim(P["dia"]), spacing/6) + aspect = P["aspect"] + + offs_x = +spacing/2 + + element_begin("", "D1", "acy" P["spacing"] ,0,0, 2.2*spacing/3,-mil(50)) + + element_pin(-spacing/2, 0, 1) + element_pin(+spacing/2, 0, 2) + dimension(-spacing/2, 0, +spacing/2, 0, dia*4, "spacing") + +# pins + element_line(-spacing/2, 0, -spacing/aspect, 0) + element_line(+spacing/aspect, 0, +spacing/2, 0) + +# triangle + element_line(+spacing/aspect, -dia, +spacing/aspect, +dia) + element_line(+spacing/aspect, -dia, -spacing/aspect, 0) + element_line(+spacing/aspect, +dia, -spacing/aspect, 0) + + dimension(+spacing/aspect, -dia, +spacing/aspect, dia, "@" spacing*1.2 ";0", "dia") + + +# front cross line with decoration + r = dia*0.3 + if (P["type"] == "normal") { + element_line(-spacing/aspect, -dia, -spacing/aspect, +dia) + } + else if (P["type"] == "zener") { + element_line(-spacing/aspect, -dia, -spacing/aspect, +dia) + element_line(-spacing/aspect, +dia, -spacing/aspect-r, +dia) + element_line(-spacing/aspect, -dia, -spacing/aspect+r, -dia) + } + else if (P["type"] == "tunnel") { + element_line(-spacing/aspect, -dia, -spacing/aspect, +dia) + element_line(-spacing/aspect, +dia, -spacing/aspect+r, +dia) + element_line(-spacing/aspect, -dia, -spacing/aspect+r, -dia) + } + else if (P["type"] == "varactor") { + element_line(-spacing/aspect, -dia, -spacing/aspect, +dia) + element_line(-spacing/aspect-r, -dia, -spacing/aspect-r, +dia) + } + else if (P["type"] == "schottky") { + cx = -spacing/aspect + r + cy = -(dia-r) + element_line(-spacing/aspect, -(dia-r), -spacing/aspect, +dia-r) + element_arc(cx, cy, r, r, 0, -180) + cx = -spacing/aspect - r + cy = +(dia-r) + element_arc(cx, cy, r, r, 0, +180) + } + else if ((P["type"] != "") && (P["type"] != "none")) { + error("Invalid type") + } + + element_end() +} Index: tags/2.1.2/pcblib/parametric/bga =================================================================== --- tags/2.1.2/pcblib/parametric/bga (nonexistent) +++ tags/2.1.2/pcblib/parametric/bga (revision 24813) @@ -0,0 +1,74 @@ +#!/bin/sh + +# Reference: Microchip Packaging Specification DS00000049BX (en012702.pdf), SSOP + +#@@example bga(map=a1:a2:a2:#:b1:!:b3:#:c1:c2:!) + +#@@purpose Generate ball grid array + +#@@desc Generate a grid of circular pads for BGA chips + +#@@params nx,ny,spacing,balldia,silkmark,map,width,height,automap,automap2 + +#@@param:nx number of pins in the X direction +#@@optional:nx +#@@default:nx deduced from the map + +#@@param:ny number of pins in the Y direction +#@@optional:ny +#@@default:ny deduced from the map + +#@@param:spacing spacing between the pins +#@@dim:spacing +#@@default:spacing 0.5 mm + +#@@param:balldia diameter of a ball +#@@dim:balldia +#@@default:spacing 0.35 mm + +#@@include silkmark.help +#@@optional:silkmark +#@@default:silkmark square +#@@preview_args:silkmark 3,3 + +#@@param:map pin name map; a colon separated list of names, from left to right, rows first. If a name is empty or is a hash mark, a new row is started. If a name is a !, the given pin is missing and no pad is generated. +#@@optional:map + +#@@param:width width of the box (silk rectangle x size) +#@@dim:width +#@@optional:width +#@@default:width two columns wider than the array + +#@@param:height height of the box (silk rectangle y size) +#@@dim:height +#@@optional:height +#@@default:height two columns higher than the array + + +#@@param:automap assume a regular nx*ny array, automap (autonumber) the pins +#@@optional:automap +#@@enum:automap:none do not autonumber pins +#@@enum:automap:alnum number y rows from A..Z (then AA..AZ) from top to bottom, number x rows from 0..nx left to right +#@@default:none +#@@preview_args:automap 3,3 +#@@thumbsize:automap 3 +#@@thumbnum:automap 1 + +#@@param:automap2 change how automap behaves - multiple values separated by colon are accepted (e.g. automap2=pivot,reversex) +#@@enum:automap2:pivot swap x and y +#@@enum:automap2:reversex number x from right to left +#@@enum:automap2:reversey number y from bottom up +#@@preview_args:automap2 3,3,automap=alnum +#@@thumbsize:automap2 3 +#@@thumbnum:automap2 1 + +#@@param:alphabet the alphabet automap may use for rows; use A..Z if unspecified, else use the letters in this alphabet (in order). List letters without separator, e.g. ABCDEF +#@@preview_args:automap2 3,3,automap=alnum,alphabet=QDT +#@@thumbsize:automap2 3 +#@@thumbnum:automap2 1 + + +#@@include common.awk + +awk -f `dirname $0`/common.awk -f `dirname $0`/bga.awk -v "args=$*" -v gen=`basename $0` -v "genfull=$0" + Property changes on: tags/2.1.2/pcblib/parametric/bga ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/2.1.2/pcblib/parametric/bga.awk =================================================================== --- tags/2.1.2/pcblib/parametric/bga.awk (nonexistent) +++ tags/2.1.2/pcblib/parametric/bga.awk (revision 24813) @@ -0,0 +1,123 @@ +function pinalpha(p, s) +{ + if (p >= alphabet_len) + s = pinalpha(int(p/alphabet_len)-1) + return s sprintf("%s", substr(alphabet, (p % alphabet_len)+1, 1)) +} + +function automap(algo, pivot, revx, revy ,xx,yy) +{ + if (algo == 1) { + for(y = 0; y < ny; y++) { + if (revy) + yy = ny - y - 1 + else + yy = y + for(x = 0; x < nx; x++) { + if (revx) + xx = nx - x - 1 + else + xx = x + if (pivot) + MAP[x,y] = pinalpha(xx) yy+1 + else + MAP[x,y] = pinalpha(yy) xx+1 + } + } + } +} + +BEGIN { + help_auto() + set_arg(P, "?spacing", "0.5mm") + set_arg(P, "?balldia", "0.35mm") + set_arg(P, "?silkmark", "arc") + + proc_args(P, "nx,ny,spacing,balldia,silkmark,map,width,height,automap,automap2,alphabet", "") + + step = parse_dim(P["spacing"]) + + half=step/2 + + nx = int(P["nx"]) + ny = int(P["ny"]) + + alphabet = P["alphabet"] + if (alphabet == "") + alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + alphabet_len = length(alphabet) + + if (P["map"] != "") { + v = split(P["map"], A, ":") + x = 0 + y = 0 + for(n = 1; n <= v; n++) { + if ((A[n] == "") || (A[n] == "#")) { + x = 0 + y++ + continue; + } + if (x > nx) + nx = x + if (y > ny) + ny = y + print x,y,A[n] > "/dev/stderr" + MAP[x, y] = A[n] + x++ + } + ny++; + } + else { + if ((nx == "") || (ny == "")) + error("missing argument: need nx,ny or a map") + if (P["automap"] ~ "alnum") + automap(1, (P["automap2"] ~ "pivot"), (P["automap2"] ~ "reversex"), (P["automap2"] ~ "reversey")) + else if ((P["automap"] ~ "none") || (P["automap"] == "")) { + } + else + error("automap should be alnum or none") + } + + balldia = parse_dim(P["balldia"]) + bw = parse_dim(P["width"]) + bh = parse_dim(P["height"]) + + if (bw == "") + bw = (nx+1)*step + if (bh == "") + bh = (ny+1)*step + + xo = (nx-1)*step/2 + yo = (ny-1)*step/2 + + element_begin("", "U1", nx "*" ny ,0,0, 0, -bh) + + for(x = 0; x < nx; x++) { + for(y = 0; y < ny; y++) { + xx = x * step - xo + yy = y * step - yo + name = MAP[x,y] + if (name == "!") + continue + if (name == "") + name = "NC" + element_pad_circle(xx, yy, balldia, name) + } + } + + dimension(-xo, -yo, -xo+step, -yo, bw/2, "spacing") + dimension(-xo-balldia/2, +yo, -xo+balldia/2, +yo, -bw*0.75, "balldia") + + + xx = -1 * (bw/2) + yy = -1 * (bh/2) + element_rectangle(xx, yy, bw/2, bh/2) + + dimension(xx, yy, bw/2, yy, bw/2, "width") + dimension(bw/2, yy, bw/2, bh/2, +bh/2, "height") + + silkmark(P["silkmark"], xx, yy, half*1.5) + + + element_end() +} Index: tags/2.1.2/pcblib/parametric/common.awk =================================================================== --- tags/2.1.2/pcblib/parametric/common.awk (nonexistent) +++ tags/2.1.2/pcblib/parametric/common.awk (revision 24813) @@ -0,0 +1,639 @@ +#@@param:pin_ringdia pin's copper ring (annulus) outer diameter (in mil by default, mm suffix can be used) +#@@optional:pin_ringdia +#@@dim:pin_ringdia + +#@@param:pin_clearance pin's copper clearance diameter (in mil by default, mm suffix can be used) +#@@optional:pin_clearance +#@@dim:pin_clearance + +#@@param:pin_mask pin's solder mask diameter (in mil by default, mm suffix can be used) +#@@optional:pin_mask +#@@dim:pin_mask + +#@@param:pin_drill copper pin's drill diameter (in mil by default, mm suffix can be used) +#@@optional:pin_drill +#@@dim:pin_drill + +#@@param:pad_thickness width of pads (in mil by default, mm suffix can be used) +#@@optional:pad_thickness +#@@dim:pad_thickness + +#@@param:pad_clearance copper clearance around the pad (in mil by default, mm suffix can be used) +#@@optional:pad_clearance +#@@dim:pad_clearance + +#@@param:pad_mask pin's solder mask (in mil by default, mm suffix can be used) +#@@optional:pad_mask +#@@dim:pad_mask + +#@@param:line_thickness silk line thickness (in mil by default, mm suffix can be used) +#@@optional:line_thickness +#@@dim:line_thickness + +BEGIN { + q="\"" + + DEFAULT["pin_ringdia"] = 8000 + DEFAULT["pin_ringdia", "dim"] = 1 + + DEFAULT["pin_clearance"] = 5000 + DEFAULT["pin_clearance", "dim"] = 1 + + DEFAULT["pin_mask"] = 8600 + DEFAULT["pin_mask", "dim"] = 1 + + DEFAULT["pin_drill"] = 3937 + DEFAULT["pin_drill", "dim"] = 1 + + DEFAULT["line_thickness"] = 1000 + DEFAULT["line_thickness", "dim"] = 1 + + DEFAULT["pad_thickness"] = 2000 + DEFAULT["pad_thickness", "dim"] = 1 + DEFAULT["pad_clearance"] = 1000 + DEFAULT["pad_clearance", "dim"] = 1 + DEFAULT["pad_mask"] = 3000 + DEFAULT["pad_mask", "dim"] = 1 + + DEFAULT["pin_flags"] = "__auto" + + s_default=1 + s_weak=2 + s_explicit=3 + + offs_x = 0 + offs_y = 0 + + pi=3.141592654 +} + +# Throw an error and exit +function error(msg) +{ + print "Error: " msg > "/dev/stderr" + exit 1 +} + +# return a if it is not empty, else return b +function either(a, b) +{ + return a != "" ? a : b +} + +# strip leading/trailing whitespaces +function strip(s) +{ + sub("^[ \t\r\n]*", "", s) + sub("[ \t\r\n]*$", "", s) + return s +} + +# translate coordinates +function coord_x(x) { return int(x + offs_x) } +function coord_y(y) { return int(y + offs_y) } + +# generate an element header line; any argument may be empty +function element_begin(desc, name, value, cent_x, cent_y, text_x, text_y, text_dir, text_scale) +{ + if (desc == "") { + desc = gen "(" args ")" + gsub("[\r\n\t ]*[?][^,]*,[\r\n\t ]*", "", desc) + gsub("[\r\n\t]", " ", desc) + } + print "Element[" q q, q desc q, q name q, q value q, + int(either(cent_x, 0)), int(either(cent_y, 0)), + int(either(text_x, 0)), int(either(text_y, 0)), + int(either(text_dir, 0)), int(either(text_scale, 100)), q q "]" + print "(" +} + +# generate an element footer line +function element_end() +{ + print ")" +} + +# generate a pin; arguments from ringdia are optional (defaults are in global vars pin_*) +function element_pin(x, y, number, flags, ringdia, clearance, mask, drill, name) +{ + if (number == "") + number = ++pin_number + + flags = either(flags, DEFAULT["pin_flags"]) + + if (flags == "__auto") { + if (number == 1) + flags = "square" + else + flags = "" + } + + if (flags == "none") + flags = "" + + print " Pin[" coord_x(x), coord_y(y), + int(either(ringdia, DEFAULT["pin_ringdia"])), int(either(clearance, DEFAULT["pin_clearance"])), int(either(mask, DEFAULT["pin_mask"])), + int(either(drill, DEFAULT["pin_drill"])), q name q, q number q, q flags q "]" +} + +# draw element pad +function element_pad(x1, y1, x2, y2, thickness, number, flags, clearance, mask, name) +{ + print " Pad[", coord_x(x1), coord_y(y1), coord_x(x2), coord_y(y2), int(either(thickness, DEFAULT["pad_thickness"])), + int(either(clearance, DEFAULT["pad_clearance"])), int(either(mask, DEFAULT["pad_mask"])), + q name q, q number q, q flags q "]" +} + +# draw element pad - no thickness, but exact corner coordinates given +function element_pad_rectangle(x1, y1, x2, y2, number, flags, clearance, mask, name, th,dx,dy,cx,cy) +{ + if (x2 < x1) { + th = x2 + x2 = x1 + x1 = th + } + if (y2 < y1) { + th = y2 + y2 = y1 + y1 = th + } + + dx = x2-x1 + dy = y2-y1 + + if (dx >= dy) { + th = dy + cy = (y1+y2)/2 + + print " Pad[", coord_x(x1)+th/2, coord_y(cy), coord_x(x2)-th/2, coord_y(cy), th, + int(either(clearance, DEFAULT["pad_clearance"])), int(either(mask, DEFAULT["pad_mask"])), + q name q, q number q, q flags q "]" + } + else { + th = dx + cx = (x1+x2)/2 + + print " Pad[", coord_x(cx), coord_y(y1)+th/2, coord_x(cx), coord_y(y2)-th/2, th, + int(either(clearance, DEFAULT["pad_clearance"])), int(either(mask, DEFAULT["pad_mask"])), + q name q, q number q, q flags q "]" + } +} + +# draw a matrix of pads; top-left corner is x1;y1, there are nx*ny pads +# of w*h size. rows/cols of pads are drawn with ox and oy offset +function element_pad_matrix(x1, y1, nx, ny, w, h, ox, oy, number, flags, clearance, mask, name, ix,iy) +{ + for(iy = 0; iy < ny; iy++) + for(ix = 0; ix < nx; ix++) + element_pad_rectangle(x1+ix*ox, y1+iy*oy, x1+ix*ox+w, y1+iy*oy+h, number, flags, clearance, mask, name) +} + +# draw element pad circle +function element_pad_circle(x1, y1, radius, number, clearance, mask, name) +{ + print " Pad[", coord_x(x1), coord_y(y1), coord_x(x1), coord_y(y1), int(either(radius, DEFAULT["pad_thickness"])), + int(either(clearance, DEFAULT["pad_clearance"])), int(either(mask, DEFAULT["pad_mask"])), + q name q, q number q, q "" q "]" +} + +# draw a line on silk; thickness is optional (default: line_thickness) +function element_line(x1, y1, x2, y2, thickness) +{ + print " ElementLine[" coord_x(x1), coord_y(y1), coord_x(x2), coord_y(y2), int(either(thickness, DEFAULT["line_thickness"])) "]" +} + +function element_arrow(x1, y1, x2, y2, asize, thickness ,vx,vy,nx,ny,len,xb,yb) +{ + element_line(x1, y1, x2,y2, thickness) + + if (asize == 0) + asize = mil(20) + + vx = x2-x1 + vy = y2-y1 + len = sqrt(vx*vx+vy*vy) + if (len != 0) { + vx /= len + vy /= len + nx = vy + ny = -vx + xb = x2 - vx*asize + yb = y2 - vy*asize +# element_line(x2, y2, xb + 1000, yb + 1000) + element_line(x2, y2, xb + nx*asize/2, yb + ny*asize/2) + element_line(x2, y2, xb - nx*asize/2, yb - ny*asize/2) + element_line(xb - nx*asize/2, yb - ny*asize/2, xb + nx*asize/2, yb + ny*asize/2) + } +} + +# draw a rectangle of silk lines +# omit sides as requested in omit +# if r is non-zero, round corners - omit applies as NW, NW, SW, SE +# if omit includes "arc", corners are "rounded" with lines +function element_rectangle(x1, y1, x2, y2, omit, r, thickness ,tmp,r1,r2) +{ +# order coords for round corners + if (x1 > x2) { + tmp = x1 + x1 = x2 + x2 = tmp + } + if (y1 > y2) { + tmp = y1 + y1 = y2 + y2 = tmp + } + + if (!(omit ~ "left")) { + r1 = (omit ~ "NW") ? 0 : r + r2 = (omit ~ "SW") ? 0 : r + element_line(x1, y1+r1, x1, y2-r2, thickness) + } + if (!(omit ~ "top")) { + r1 = (omit ~ "NW") ? 0 : r + r2 = (omit ~ "NE") ? 0 : r + element_line(x1+r1, y1, x2-r2, y1, thickness) + } + if (!(omit ~ "bottom")) { + r1 = (omit ~ "SE") ? 0 : r + r2 = (omit ~ "SW") ? 0 : r + element_line(x2-r1, y2, x1+r2, y2, thickness) + } + if (!(omit ~ "right")) { + r1 = (omit ~ "SE") ? 0 : r + r2 = (omit ~ "NE") ? 0 : r + element_line(x2, y2-r1, x2, y1+r2, thickness) + } + + if (r > 0) { + if (omit ~ "arc") { + if (!(omit ~ "NW")) + element_line(x1, y1+r, x1+r, y1) + if (!(omit ~ "SW")) + element_line(x1, y2-r, x1+r, y2) + if (!(omit ~ "NE")) + element_line(x2, y1+r, x2-r, y1) + if (!(omit ~ "SE")) + element_line(x2, y2-r, x2-r, y2) + } + else { + if (!(omit ~ "NW")) + element_arc(x1+r, y1+r, r, r, 270, 90) + if (!(omit ~ "SW")) + element_arc(x1+r, y2-r, r, r, 0, 90) + if (!(omit ~ "NE")) + element_arc(x2-r, y1+r, r, r, 180, 90) + if (!(omit ~ "SE")) + element_arc(x2-r, y2-r, r, r, 90, 90) + } + } +} + +# draw a rectangle corners of silk lines, wx and wy long in x and y directions +# omit sides as requested in omit: NW, NW, SW, SE +# corners are always sharp +function element_rectangle_corners(x1, y1, x2, y2, wx, wy, omit, thickness ,tmp) +{ + if (!(omit ~ "NW")) { + element_line(x1, y1, x1+wx, y1, thickness) + element_line(x1, y1, x1, y1+wy, thickness) + } + if (!(omit ~ "NE")) { + element_line(x2-wx, y1, x2, y1, thickness) + element_line(x2, y1, x2, y1+wy, thickness) + } + if (!(omit ~ "SW")) { + element_line(x1, y2, x1+wx, y2, thickness) + element_line(x1, y2-wy, x1, y2, thickness) + } + if (!(omit ~ "SE")) { + element_line(x2-wx, y2, x2, y2, thickness) + element_line(x2, y2-wy, x2, y2, thickness) + } +} + +# draw a line on silk; thickness is optional (default: line_thickness) +function element_arc(cx, cy, rx, ry, a_start, a_delta, thickness) +{ + print " ElementArc[" coord_x(cx), coord_y(cy), int(rx), int(ry), int(a_start), int(a_delta), int(either(thickness, DEFAULT["line_thickness"])) "]" +} + + +# convert coord given in mils to footprint units +function mil(coord) +{ + return coord * 100 +} + +# reverse mil(): converts footprint units back to mil +function rev_mil(coord) +{ + return coord/100 +} + + +# convert coord given in mm to footprint units +function mm(coord) +{ + return coord*3937 +} + +# reverse mm(): converts footprint units back to mm +function rev_mm(coord) +{ + return coord/3937 +} + + +function set_arg_(OUT, key, value, strength) +{ + if (OUT[key, "strength"] > strength) + return + + OUT[key] = value + OUT[key, "strength"] = strength +} + +# set parameter key=value with optioal strength (s_* consts) in array OUT[] +# set only if current strength is stronger than the original value +# if key starts with a "?", use s_weak +# if key is in DEFAULT[], use DEFAULT[] instead of OUT[] +function set_arg(OUT, key, value ,strength) +{ + if (strength == "") + strength = s_explicit + if (key ~ "^[?]") { + sub("^[?]", "", key) + strength = s_weak + } + + if (key in DEFAULT) { + if (DEFAULT[key, "dim"]) + value = parse_dim_(value, 0) + set_arg_(DEFAULT, key, value, strength) + } + else + set_arg_(OUT, key, value, strength) +} + +# Process a generator argument list from arg_names. Save the result in +# array OUT. If mandatory is specified, check whether all mandatory +# parameters are specified +# Both arg_names and mandatory are comma separated list of argument names +function proc_args(OUT, arg_names, mandatory, N,A,M,v,n,key,val,pos) +{ + gsub(" ", "", arg_names) + gsub(" ", "", mandatory) + split(arg_names, N, ",") + v = split(args, A, ",") + +# fill in all named and positional arguments + pos = 1 + for(n = 1; n <= v; n++) { + A[n] = strip(A[n]) + if (A[n] == "") + continue + if (A[n] ~ "=") { +# named + key=A[n] + val=A[n] + sub("=.*", "", key) + sub("^[^=]*=", "", val) + set_arg(OUT, key, val, s_explicit) + } + else { +# positional + if (N[pos] == "") { + error("too many positional arguments at " A[n]) + } + while((N[pos] in OUT) && (N[pos, "strength"] == s_explicit)) pos++ + set_arg(OUT, N[pos], A[n], s_explicit) + pos++ + } + } + +# check whether all mandatory arguments are specified + v = split(mandatory, M, ",") + for(n = 1; n <= v; n++) { + if (!(M[n] in OUT)) { + error("missing argument " M[n] " (or positional " n ")") + exit 1 + } + } +} + +function parse_dim_(h, fallback_mil) +{ + if (h == "") + return "" + if (h ~ "mm$") { + sub("mm", "", h) + return mm(h) + } + if (h ~ "um$") { + sub("um", "", h) + return mm(h)/1000 + } + if (h ~ "nm$") { + sub("nm", "", h) + return mm(h)/1000000 + } + if (h ~ "cm$") { + sub("cm", "", h) + return mm(h)*10 + } + if (h ~ "m$") { + sub("m", "", h) + return mm(h)*1000 + } + if (h ~ "km$") { + sub("km", "", h) + return mm(h)*1000000 + } + + if (h ~ "in$") { + sub("in", "", h) + return mil(h)*1000 + } + if (h ~ "dmil$") { + sub("dmil", "", h) + return mil(h)/10 + } + if (h ~ "cmil$") { + sub("cmil", "", h) + return mil(h)/100 + } + if (h ~ "mil$") { + sub("mil", "", h) + return mil(h) + } + if (fallback_mil) + return mil(h) + else + return h +} + +# Assume h is a dimension and convert it +function parse_dim(h) +{ + return parse_dim_(h, 1) +} + +# Draw a DIP outline: useful for any rectangular package with a little +# half circle centered on the top line +# arcr: radius of the half circle +# xhalf: optional coordinate where the circle should be put +function dip_outline(x1, y1, x2, y2, arcr ,xhalf) +{ + if (xhalf == "") + xhalf=(x1+x2)/2 + + element_rectangle(x1, y1, x2, y2, "top") + element_line(x1, y1, xhalf-arcr, y1) + element_line(xhalf+arcr, y1, x2, y1) + + element_arc(xhalf, y1, arcr, arcr, 0, 180) +} + +# decide whether x is true or false +# returns 1 if true +# returns 0 if false +function tobool(x) +{ + if (x == int(x)) + return (int(x) != 0) + + x = tolower(x) + return (x == "true") || (x == "yes") || (x == "on") +} + +# default pin1 mark on a box +# style: mark style, ":" separated list +# x,y: the coordinates of the origin corner (top-left) +# half: half the stepping of the pin grid - the size of the mark +# step: optional size of the external arrow or square (defaults to 2*half) +function silkmark(style, x, y, half, step, S,n,v) +{ + if (step == "") + step = half*2 + + v = split(style, S, ":") + + for(n = 1; n <= v; n++) { + if (S[n] == "angled") { + element_line(x+half, y, x, y+half) + } + else if (S[n] == "square") { + element_line(x, y+step, x+2*half, y+step) + element_line(x+step, y, x+2*half, y+step) + } + else if ((S[n] == "external") || (S[n] == "externalx")) { + element_line(x, y+half, x-step+half, y+half/2) + element_line(x, y+half, x-step+half, y+half*1.5) + element_line(x-step+half, y+half/2, x-step+half, y+half*1.5) + } + else if (S[n] == "externaly") { + element_line(x+half, y, x-half/2+half, y-step+half) + element_line(x+half, y, x+half/2+half, y-step+half) + element_line(x-half/2+half, y-step+half, x+half/2+half, y-step+half) + } + else if (S[n] == "external45") { + element_line(x, y, x-half, y-half/3) + element_line(x, y, x-half/3, y-half) + element_line(x-half, y-half/3, x-half/3, y-half) + } + else if (S[n] == "arc") { + element_arc(x, y, step/2, step/2, 180, 270) + } + else if (S[n] == "circle") { + element_arc(x, y, step/2, step/2, 0, 360) + } + else if (S[n] == "dot") { + element_arc(x-step/2, y-step/2, step/4, step/4, 0, 360) + } + else if ((S[n] != "none") && (S[n] != "")) { + error("invalid silkmark parameter: " S[n]) + } + } +} + +# output a dimension specification between x1;y1 and x2;y2, text distance at dist +# for a name,value pair +# if name is empty, only value is printed +# if value is empty, it's calculated +# if only name should be printed, value should be "!" +# if dist starts with a "@", it's the absolute coordinate of the center of the dim line (text base), else it's relative distance from the measured line +function dimension(x1, y1, x2, y2, dist, name, value, vx,vy) +{ + print "#dimension", coord_x(x1), coord_y(y1), coord_x(x2), coord_y(y2), dist, name, value +} + +function help_extract(SEEN, fn, dirn, OVER, IGN, WANT,tmp,key,val,i,skip) +{ + if (fn in SEEN) + return + SEEN[fn]++ + print "#@@info-gen-extract " fn + close(fn) + while((getline line < fn) > 0) { + if (line ~ "^#@@include") { + sub("^#@@include[ \t]*", "", line) + tmp = dirn "/" line + WANT[tmp]++ + } + else if (line ~ "^#@@over@ignore") { + key = line + sub("^#@@over@ignore:", "", key) + sub(" .*", "", key) + IGN[key] = 1 + } + else if (line ~ "^#@@over@") { + key = line + sub("^#@@over@", "", key) + val = "#@@" key + sub(" .*", "", key) + OVER[key] = val + } + else if (line ~ "^#@@") { + key = line + sub("^#@@", "", key) + sub(" .*", "", key) + skip = 0 + for(i in IGN) { + if (key ~ i) + skip = 1 + } + if (skip) + continue + if (key in OVER) { + print OVER[key] + OVER[key "::PRINTED"] = 1 + } + else + print line + } + } + close(fn) + for(tmp in WANT) + help_extract(SEEN, tmp, dirn, OVER, IGN) +} + +function help_print( SEEN, OVER, dirn, k) +{ + print "#@@info-generator pcblib common.awk" + dirn = genfull + sub("/[^/]*$", "", dirn) + help_extract(SEEN, genfull, dirn, OVER) + for(k in OVER) { + if (!(k ~ "::PRINTED$") && !((k "::PRINTED") in OVER)) + print OVER[k] + } +} + +function help_auto() +{ + if ((args ~ "^--help") || (args ~ ",[ \t]*--help")) { + help_print() + exit(0) + } +} Index: tags/2.1.2/pcblib/parametric/connector =================================================================== --- tags/2.1.2/pcblib/parametric/connector (nonexistent) +++ tags/2.1.2/pcblib/parametric/connector (revision 24813) @@ -0,0 +1,53 @@ +#!/bin/sh + +#@@example connector(2, 3, silkmark=external, spacing=100) + +#@@purpose Generate pin-array connectors (e.g. headers). + +#@@desc Generate thru-hole connectors that consits of an array of +#@@desc evenly spaced pins, a plain frame and some optional pin marks +#@@desc on the silk layer. + +#@@params nx, ny, spacing, silkmark, eshift, etrunc + +#@@param:nx number of pins in the X direction +#@@param:ny number of pins in the Y direction +#@@param:spacing spacing between the pins +#@@dim:spacing +#@@default:spacing 100 mil + +#@@include silkmark.help +#@@optional:silkmark +#@@default:silkmark square +#@@preview_args:silkmark 2,3 + +#@@param:eshift shift even rows or columns by half spacing (optional; default: don't shift) +#@@enum:eshift:x shift columns +#@@enum:eshift:y shift rows +#@@enum:eshift:none do not shift anything +#@@default:eshift none +#@@optional:eshift +#@@preview_args:eshift 2,3 + +#@@param:etrunc truncate the last pin of a shifted row or column +#@@bool:etrunc +#@@default:etrunc false +#@@optional:etrunc +#@@preview_args:etrunc 2,3,eshift=x + +#@@param:sequence pin numbering sequence +#@@enum:sequence:normal increase by y first, then by x +#@@enum:sequence:pivot increase by x first, then by y +#@@enum:sequence:zigzag "dip-style" numbering in zig-zag: number odd x rows by y ascending, even x rows by y descending +#@@preview_args:sequence 2,4 +#@@thumbsize:sequence 3 +#@@thumbnum:sequence 1 +#@@default:sequence normal +#@@optional:sequence + + + +#@@include common.awk + +awk -f `dirname $0`/common.awk -f `dirname $0`/connector.awk -v "args=$*" -v gen=`basename $0` -v "genfull=$0" + Property changes on: tags/2.1.2/pcblib/parametric/connector ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/2.1.2/pcblib/parametric/connector.awk =================================================================== --- tags/2.1.2/pcblib/parametric/connector.awk (nonexistent) +++ tags/2.1.2/pcblib/parametric/connector.awk (revision 24813) @@ -0,0 +1,88 @@ +BEGIN { + help_auto() + set_arg(P, "?spacing", 100) + set_arg(P, "?silkmark", "square") + set_arg(P, "?sequence", "normal") + + proc_args(P, "nx,ny,spacing,silkmark,eshift,etrunc", "nx,ny") + + + step = parse_dim(P["spacing"]) + + if (pin_ringdia > step*0.9) + pin_ringdia = step*0.9 + + if (pin_drill > pin_ringdia*0.9) + pin_drill = pin_ringdia*0.9 + + half=step/2 + + P["nx"] = int(P["nx"]) + P["ny"] = int(P["ny"]) + + eshift=tolower(P["eshift"]) + etrunc=tobool(P["etrunc"]) + if ((eshift != "x") && (eshift != "y") && (eshift != "") && (eshift != "none")) + error("eshift must be x or y or none (got: " eshift ")"); + + element_begin("", "CONN1", P["nx"] "*" P["ny"] ,0,0, 0, -step) + + for(x = 0; x < P["nx"]; x++) { + if ((eshift == "x") && ((x % 2) == 1)) + yo = step/2 + else + yo = 0 + for(y = 0; y < P["ny"]; y++) { + if ((eshift == "y") && ((y % 2) == 1)) { + xo = step/2 + if ((etrunc) && (x == P["nx"]-1)) + continue + } + else { + xo = 0 + if ((etrunc) && (y == P["ny"]-1) && (yo != 0)) + continue + } + if (P["sequence"] == "normal") { + pinno++ + } + else if (P["sequence"] == "pivot") { + pinno = y * P["nx"] + x + 1 + } + else if (P["sequence"] == "zigzag") { + if (x % 2) { + pinno = (x+1) * P["ny"] - y + if ((etrunc) && (eshift == "x")) + pinno -= int(x/2)+1 + else if ((etrunc) && (eshift == "y")) + pinno += int(x/2) + } + else { + pinno = x * P["ny"] + y + 1 + if ((etrunc) && (eshift == "x")) + pinno -= x/2 + else if ((etrunc) && (eshift == "y")) + pinno += x/2-1 + } + } + element_pin(x * step + xo, y * step + yo, pinno) + } + } + + xo = 0 + yo = 0 + if (!etrunc) { + if (eshift == "y") + xo = step/2 + if (eshift == "x") + yo = step/2 + } + + element_rectangle(-half, -half, P["nx"] * step - half + xo, P["ny"] * step - half + yo) + + silkmark(P["silkmark"], -half, -half, half) + + dimension(0, step, step, step, step*2, "spacing") + + element_end() +} Index: tags/2.1.2/pcblib/parametric/dip =================================================================== --- tags/2.1.2/pcblib/parametric/dip (nonexistent) +++ tags/2.1.2/pcblib/parametric/dip (revision 24813) @@ -0,0 +1,21 @@ +#!/bin/sh + +#@@example dip(18) + +#@@purpose Generate classic DIP packages. + +#@@desc Generate thru-hole DIP packages with variable number of pins and +#@@desc row spacing +#@@params n, spacing + +#@@param:n number of pins + +#@@param:spacing spacing between the two rows of pins +#@@dim:spacing +#@@optional:spacing +#@@default:spacing 100 mil + +#@@include common.awk + +awk -f `dirname $0`/common.awk -f `dirname $0`/dip.awk -v "args=$*" -v gen=`basename $0` -v "genfull=$0" + Property changes on: tags/2.1.2/pcblib/parametric/dip ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/2.1.2/pcblib/parametric/dip.awk =================================================================== --- tags/2.1.2/pcblib/parametric/dip.awk (nonexistent) +++ tags/2.1.2/pcblib/parametric/dip.awk (revision 24813) @@ -0,0 +1,28 @@ +BEGIN { + help_auto() + set_arg(P, "?spacing", 300) + + proc_args(P, "n,spacing", "n") + + P["n"] = int(P["n"]) + if ((P["n"] < 2) || ((P["n"] % 2) != 0)) + error("Number of pins have to be an even positive number") + + spacing=parse_dim(P["spacing"]) + + element_begin("", "U1", P["n"] "*" P["spacing"] ,0,0, 0, mil(-100)) + + half = mil(50) + + for(n = 1; n <= P["n"]/2; n++) { + element_pin(0, (n-1) * mil(100), n) + element_pin(spacing, (n-1) * mil(100), P["n"] - n + 1) + } + + dip_outline(-half, -half, spacing + half , (n-2) * mil(100) + half, half) + + + dimension(0, 0, spacing, 0, mil(100), "spacing") + + element_end() +} Index: tags/2.1.2/pcblib/parametric/msop =================================================================== --- tags/2.1.2/pcblib/parametric/msop (nonexistent) +++ tags/2.1.2/pcblib/parametric/msop (revision 24813) @@ -0,0 +1,34 @@ +#!/bin/sh + +# Reference: Microchip Packaging Specification DS00000049BX (en012702.pdf), MSOP + +#@@example msop(8) + +#@@purpose Generate MSOP packages. + +#@@desc Generate MSOP packages with variable number of pins and +#@@desc row spacing + +#@@include so +#@@include common.awk + +#@@over@default:pad_spacing 0.65 mm +#@@over@default:row_spacing 4.9 mm +#@@over@default:int_bloat 0.6 mm +#@@over@default:ext_bloat 0.6 mm +#@@over@default:pad_thickness 0.45 mm + + +defaults=' +?pad_spacing=0.65mm, +?row_spacing=4.9mm, +?int_bloat=0.6mm, +?ext_bloat=0.4mm, +?rarc=25, +?silk_ext_x=18, +?silk_ext_y=22, +?pad_thickness=0.45mm +' + +awk -f `dirname $0`/common.awk -f `dirname $0`/so.awk -v "args=$defaults,$*" -v gen=`basename $0` -v "genfull=$0" + Property changes on: tags/2.1.2/pcblib/parametric/msop ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/2.1.2/pcblib/parametric/plcc =================================================================== --- tags/2.1.2/pcblib/parametric/plcc (nonexistent) +++ tags/2.1.2/pcblib/parametric/plcc (revision 24813) @@ -0,0 +1,29 @@ +#!/bin/sh + +# Reference: Microchip Packaging Specification DS00000049BX (en012702.pdf), SSOP + +#@@example plcc(20) + +#@@purpose Generate PLCC packages +#@@desc Generate square PLCC packages - a simplified frontend to qf() - +#@@desc only the number of pins is really needed for a square PLCC footprint! +#@@desc NOTE: some of the qf() parameters can be also used; PLCC32 is non-square, and can not be properly generated using this generator. + +#@@params pins,size,pitch,cpad_size + +#@@param:pins total number of pins (leads); must be divisible by 4 + +#@@param:size a single integer N or NxN or NxNxH; outmost dimensions (width or height of the package, leads included) in mil +#@@optional:size +#@@default:size calculated from total number of pins and pitch + +#@@param:pitch lead pitch (distance between the centerline of two adjacent leads), in mil; must be 50 for now +#@@optional:pitch +#@@default:pitch 50mil + +#@@param:cpad_size width (and height) of the central pad, in mil +#@@optional:cpad_size +#@@default:cpad_size empty, there's no central pad + +awk -f `dirname $0`/common.awk -f `dirname $0`/plcc.awk -f `dirname $0`/qf.awk -v "args=$*" -v gen=`basename $0` -v "genfull=$0" + Property changes on: tags/2.1.2/pcblib/parametric/plcc ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/2.1.2/pcblib/parametric/plcc.awk =================================================================== --- tags/2.1.2/pcblib/parametric/plcc.awk (nonexistent) +++ tags/2.1.2/pcblib/parametric/plcc.awk (revision 24813) @@ -0,0 +1,58 @@ +function parri(A ,s,i) +{ + for(i in A) + s = s " " i + return s +} + +BEGIN { + help_auto() + PT["50"] = "26mil" + set_arg(P, "?pitch", "50") + + proc_args(P, "pins,size,pitch,cpad_size,pad_thickness", "pins") + + pitch = P["pitch"] + sub("[.]0*$", "", pitch) + + if (!(args ~ "pad_thickness=")) { + if (!(pitch in PT)) + error("Unknown pitch (" pitch "), should be one of:" parri(PT)) + pt = PT[pitch] + } + else + pt = rev_mil(DEFAULT["pad_thickness"]) + + if (P["size"] == "") + P["size"] = int(P["pins"] * (pitch/4) + 140) + + split(P["size"], S, "x") + if (S[2] == "") + S[2] = S[1] + if (S[1] != S[2]) + error("need n*n size") + + pins = int(P["pins"]) + if (pins / 4 != int(pins / 4)) + error("number of pins must be divisible by 4") + + pins=pins/4 + + if ((pins % 2) != 1) + error("number of pins per side must be odd") + + S[1] -= 60 + S[2] -= 60 + args = args ",nx=" pins ",ny=" pins ",x_spacing=" S[1] "mil,y_spacing=" S[2] "mil,pad_spacing=" pitch "mil,pad_thickness=" pt "mil" + + args = args ",width=" S[1]-150 " mil,height=" S[2]-150 " mil" + + + if (P["cpad_size"] != "") + args = args ",cpad_width=" P["cpad_size"] "mil,cpad_height=" P["cpad_size"] "mil" + + args = args ",int_bloat=47mil,ext_bloat=47mil" + args = args ",?bodysilk=plcc,?silkmark=circle,pinoffs=" int(pins/2+0.5) + + +} Index: tags/2.1.2/pcblib/parametric/qf =================================================================== --- tags/2.1.2/pcblib/parametric/qf (nonexistent) +++ tags/2.1.2/pcblib/parametric/qf (revision 24813) @@ -0,0 +1,114 @@ +#!/bin/sh + +#@@example qf(nx=4,ny=4,cpad_auto=1) + +#@@purpose Generate generic *qf* (e.g. tqfp, qfn) packages + +#@@desc Generate *qf* (e.g. tqfp, qfn) packages: smd pads around a square; this is the generic implementation, end users may want to use the specific ones, e.g. tqfp(), qfn(), etc. +#@@params nx,ny,x_spacing,y_spacing,pad_spacing,ext_bloat,int_bloat,width,height,cpad_width,cpad_height,cpad_auto,bodysilk,pinoffs,silkmark + +#@@param:nx number of pins along the horizontal sides + +#@@param:ny number of pins along the vertical sides +#@@optional:ny +#@@default:ny assume ny=nx + +#@@param:x_spacing spacing between the two vertical rows of pins +#@@dim:x_spacing +#@@optional:x_spacing +#@@default:x_spacing calculated using nx and pad_spacing + +#@@param:y_spacing spacing between the two vertical rows of pins +#@@dim:y_spacing +#@@optional:y_spacing +#@@default:y_spacing calculated using ny and pad_spacing + +#@@param:pad_spacing spacing between the centerlines of two adjacent pads (aka pitch) +#@@dim:pad_spacing +#@@optional:pad_spacing + +#@@param:ext_bloat how much longer the pad should extend outwards from the end-point of the pin +#@@dim:ext_bloat +#@@optional:ext_bloat +#@@default:ext_bloat 0.37 mm + +#@@param:int_bloat how much longer the pad should extend inwards from the end-point of the pin +#@@dim:int_bloat +#@@optional:int_bloat +#@@default:int_bloat 0.37 mm + +#@@param:width width (horizontal, x axis size) of the box drawn on silk +#@@dim:width +#@@optional:width +#@@default:width calculated from the pad row geometry + +#@@param:height height (vertical, y axis size) of the box drawn on silk +#@@dim:height +#@@optional:height +#@@default:height calculated from the pad row geometry + +#@@param:cpad_width width (horizontal, x axis size) of the central pad +#@@dim:cpad_width +#@@optional:cpad_width +#@@default:cpad_width empty, no central pad + +#@@param:cpad_height height (vertical, y axis size) of the central pad +#@@dim:cpad_height +#@@optional:cpad_height +#@@default:cpad_height empty, no central pad + +#@@param:cpad_auto when true, calculate central pad sizes automatically from the pad row geometry +#@@bool:cpad_auto +#@@optional:cpad_height +#@@default:cpad_height false, no central pad + +#@@param:cpm_nx central pad paste matrix, number of paste pads in x direction +#@@optional:cpm_nx +#@@default:cpm_nx 2 + +#@@param:cpm_ny central pad paste matrix, number of paste pads in y direction +#@@optional:cpm_ny +#@@default:cpm_ny 2 + +#@@param:cpm_width central pad paste matrix, paste pad width (dimension of each paste rectangle) +#@@dim:cpm_width +#@@optional:cpm_width +#@@default:cpm_width 1mm + +#@@param:cpm_height central pad paste matrix, paste pad height (dimension of each paste rectangle) +#@@dim:cpm_height +#@@optional:cpm_height +#@@default:cpm_height 1mm + +#@@param:cpad_mask center pad mask; if not specified, use the same gap as for the rows (pad_mask) +#@@dim:cpad_mask +#@@optional:cpad_mask + +#@@param:rpad_round when true, row pads are round +#@@bool:rpad_round +#@@optional:rpad_round +#@@default:rpad_round false, row pads are square + +#@@param:bodysilk how to draw body on the silk layer +#@@enum:bodysilk:none no drawing +#@@enum:bodysilk:corners draw the corners, silkmark is outside of the top-left corner +#@@enum:bodysilk:full draw a full rectanlge, silkmark of the top-left corner +#@@enum:bodysilk:plcc angled top-left corner, horizontal line on the top +#@@optional:bodysilk +#@@default:bodysilk corners + +#@@param:pinoffs rotate pins by this amount, CW +#@@optional:pinoffs +#@@default:pinoffs 0 + +#@@include silkmark.help +#@@optional:silkmark +#@@default:silkmark square +#@@preview_args:silkmark 4,4 + +#@@default:silkmark dot +#@@include common.awk + + +awk -f `dirname $0`/common.awk -f `dirname $0`/qf.awk -v "args=$*" -v gen=`basename $0` -v "genfull=$0" + Property changes on: tags/2.1.2/pcblib/parametric/qf ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/2.1.2/pcblib/parametric/qf.awk =================================================================== --- tags/2.1.2/pcblib/parametric/qf.awk (nonexistent) +++ tags/2.1.2/pcblib/parametric/qf.awk (revision 24813) @@ -0,0 +1,180 @@ +function qf_globals(pre_args, post_args ,reqs) +{ + DEFAULT["cpad_mask", "dim"] = 1 + + if (hook_spc_conv == "") + hook_spc_conv = 1.8 + if (hook_cpad_mult == "") + hook_cpad_mult = 1 + + if (!qf_no_defaults) { + set_arg(P, "?pad_spacing", "0.5mm") + set_arg(P, "?ext_bloat", "0.37mm") + set_arg(P, "?int_bloat", "0.37mm") + set_arg(P, "?pad_thickness", "0.3mm") + set_arg(P, "?silkmark", "dot") + set_arg(P, "?line_thickness", "0.1mm") + set_arg(P, "?cpm_width", "1mm") + set_arg(P, "?cpm_height", "1mm") + set_arg(P, "?cpm_nx", "2") + set_arg(P, "?cpm_ny", "2") + } + + reqs = "nx,ny" + + if (pre_args != "") + reqs="" + + if ((post_args != "") && (!(post_args ~ "^,"))) + post_args = "," post_args + + if ((pre_args != "") && (!(pre_args ~ ",$"))) + pre_args = pre_args "," + + proc_args(P, pre_args "nx,ny,x_spacing,y_spacing,pad_spacing,ext_bloat,int_bloat,width,height,cpad_width,cpad_height,cpad_auto,cpm_nx,cpm_ny,cpm_width,cpm_height,cpad_mask,rpad_round,bodysilk,pinoffs,silkmark" post_args, reqs) + + nx = int(P["nx"]) + ny = int(P["ny"]) + + if (P["ny"] == "") + ny = nx + + if ((nx < 2) || (ny < 2)) + error("Number of pins have to be more than 2 in both directions") + + x_spacing=parse_dim(P["x_spacing"]) + y_spacing=parse_dim(P["y_spacing"]) + pad_spacing=parse_dim(P["pad_spacing"]) + pt = DEFAULT["pad_thickness"] + ext_bloat=parse_dim(P["ext_bloat"]) - pt/2 + int_bloat=parse_dim(P["int_bloat"]) - pt/2 + width=parse_dim(P["width"]) + height=parse_dim(P["height"]) + pinoffs = int(P["pinoffs"]) + + if (x_spacing == "") + x_spacing = (nx+hook_spc_conv) * pad_spacing + if (y_spacing == "") + y_spacing = (ny+hook_spc_conv) * pad_spacing + + cpad_width=parse_dim(P["cpad_width"]) + cpad_height=parse_dim(P["cpad_height"]) + + if (P["cpad_mask"] == "") + cpad_mask = (cpad_width > cpad_height ? cpad_width : cpad_height) + either(parse_dim(P["pad_mask"]), DEFAULT["pad_mask"]) + else + cpad_mask=parse_dim(P["cpad_mask"]) + + + if (tobool(P["cpad_auto"]) || hook_cpad_auto) { + if (cpad_width == "") + cpad_width = (x_spacing*0.85 - int_bloat*2 - pt) * hook_cpad_mult + if (cpad_height == "") + cpad_height = (y_spacing*0.85 - int_bloat*2 - pt) * hook_cpad_mult + } + + + if (width == "") + width = x_spacing + if (height == "") + height = y_spacing + + pinmax=(nx+ny)*2 + + if (!tobool(P["rpad_round"])) + rpad_round = "square" + else + rpad_round = "" + + + cpm_width = parse_dim(P["cpm_width"]) + cpm_height = parse_dim(P["cpm_height"]) + cpm_nx = int(P["cpm_nx"]) + cpm_ny = int(P["cpm_ny"]) +} + +function pinnum(num) +{ + return ((num-1) + pinoffs) % (pinmax)+1 +} + +BEGIN { + help_auto() + qf_globals() + + element_begin("", "U1", 2*nx + 2*ny ,0,0, -width/2 - mm(1), -height/2 - mm(2)) + + cx = (nx+1)/2 + cy = (ny+1)/2 + + for(n = 1; n <= ny; n++) { + y = (-cy + n) * pad_spacing + x1 = -x_spacing/2 + x2 = x_spacing/2 + element_pad(x1-ext_bloat, y, x1+int_bloat, y, pad_width, pinnum(n), rpad_round) + element_pad(x2-int_bloat, y, x2+ext_bloat, y, pad_width, pinnum(nx+2*ny-n+1), rpad_round) + if (n == 1) + y1 = y + if (n == 2) + dimension(x1, y1, x1, y, (ext_bloat * -3), "pad_spacing") + } + + dimension(x1, y-pt/2, x1, y+pt/2, (ext_bloat * -3), "pad_thickness") + + for(n = 1; n <= nx; n++) { + x = (-cx + n) * pad_spacing + y1 = -y_spacing/2 + y2 = y_spacing/2 + element_pad(x, y1-ext_bloat, x, y1+int_bloat, pad_width, pinnum(nx*2+ny*2-n+1), rpad_round) + element_pad(x, y2-int_bloat, x, y2+ext_bloat, pad_width, pinnum(n+ny), rpad_round) + } + + + if ((cpad_width != "") && (cpad_height != "")) { +# center pad paste matrix + if ((cpm_nx > 0) && (cpm_ny > 0)) { + ox = (cpad_width - (cpm_nx*cpm_width)) / (cpm_nx - 1) + oy = (cpad_height - (cpm_ny*cpm_height)) / (cpm_ny - 1) + element_pad_matrix(-cpad_width/2, -cpad_height/2, cpm_nx,cpm_ny, cpm_width,cpm_height, ox+cpm_width,oy+cpm_height, 2*nx+2*ny+1, "square,nopaste") + } + +# center pad + tmp = DEFAULT["pad_mask"] + DEFAULT["pad_mask"] = cpad_mask + element_pad_rectangle(-cpad_width/2, -cpad_height/2, +cpad_width/2, +cpad_height/2, 2*nx+2*ny+1, "square,nopaste") + DEFAULT["pad_mask"] = tmp + dimension(-cpad_width/2, -cpad_height/2, +cpad_width/2, -cpad_height/2, "@0;" (height * -0.6-ext_bloat), "cpad_width") + dimension(cpad_width/2, -cpad_height/2, cpad_width/2, +cpad_height/2, "@" (width * 0.8+ext_bloat) ";0", "cpad_height") + } + + wx = (width - nx * pad_spacing) / 3.5 + wy = (height - ny * pad_spacing) / 3.5 + + bodysilk = P["bodysilk"] + if ((bodysilk == "corners") || (bodysilk == "")) { + element_rectangle_corners(-width/2, -height/2, width/2, height/2, wx, wy) + silkmark(P["silkmark"], -width/2 - wx/2, -height/2+wy*1.5, (wx+wy)/4) + } + else if (bodysilk == "full") { + element_rectangle(-width/2, -height/2, width/2, height/2) + silkmark(P["silkmark"], -width/2 + wx*3, -height/2+wy*3, (wx+wy)/2) + } + else if (bodysilk == "plcc") { + r = (width+height)/10 + element_rectangle(-width/2, -height/2, width/2, height/2, "arc,NE,SW,SE", r) + element_line(-width/2, -height/2+r, width/2, -height/2+r) + silkmark(P["silkmark"], 0, -height*0.2, height/40) + } + else if (bodysilk != "none") + error("invalid bodysilk parameter") + + dimension(-width/2, -height/2, +width/2, -height/2, "@0;" height*-0.8-ext_bloat, "width") + dimension(+width/2, -height/2, +width/2, +height/2, "@" (width * 1+ext_bloat) ";0", "height") + + dimension(-x_spacing/2, -height/2, +x_spacing/2, -height/2, "@0;" height*-1-ext_bloat, "x_spacing") + dimension(+width/2, -y_spacing/2, +width/2, +y_spacing/2, "@" (width * 1.2+ext_bloat) ";0", "y_spacing") + + + + element_end() +} Index: tags/2.1.2/pcblib/parametric/qfn =================================================================== --- tags/2.1.2/pcblib/parametric/qfn (nonexistent) +++ tags/2.1.2/pcblib/parametric/qfn (revision 24813) @@ -0,0 +1,24 @@ +#!/bin/sh + +# Reference: Microchip Packaging Specification DS00000049BX (en012702.pdf), SSOP + +#@@example qfn(16,3x3,0.5) + +#@@purpose Generate QFN packages +#@@desc Generate QFN packages - a simplified frontend to qf() - +#@@desc look up 3..4 data in the datasheet and get a regular QFN footprint! +#@@desc Should work for QFN, TQFN, etc. +#@@desc NOTE: some of the qf() parameters can be also used. + +#@@params pins,size,pitch,cpad_size + +#@@param:pins total number of pins (leads); must be divisible by 4 +#@@param:size a single integer N or NxN or NxNxH; the pad spacing dimension (outer dimension, lead-to-lead) in mm +#@@param:pitch lead pitch (distance between the centerline of two adjacent leads), in mm; must be one of 0.4, 0.5, 0.65 + +#@@param:cpad_size width (and height) of the central pad, in mm +#@@optional:cpad_size +#@@default:cpad_size empty, there's no central pad + +awk -f `dirname $0`/common.awk -f `dirname $0`/qfn.awk -f `dirname $0`/qf.awk -v "args=$*" -v gen=`basename $0` -v "genfull=$0" + Property changes on: tags/2.1.2/pcblib/parametric/qfn ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/2.1.2/pcblib/parametric/qfn.awk =================================================================== --- tags/2.1.2/pcblib/parametric/qfn.awk (nonexistent) +++ tags/2.1.2/pcblib/parametric/qfn.awk (revision 24813) @@ -0,0 +1,50 @@ +function parri(A ,s,i) +{ + for(i in A) + s = s " " i + return s +} + +BEGIN { + help_auto() + PT["0.65"] = "0.35mm" + PT["0.5"] = "0.3mm" + PT["0.4"] = "0.2mm" + + proc_args(P, "pins,size,pitch,cpad_size,pad_thickness", "pins,size,pitch") + + pitch = P["pitch"] + sub("0*$", "", pitch) + + if (!(args ~ "pad_thickness=")) { + if (!(pitch in PT)) + error("Unknown pitch, should be one of:" parri(PT)) + pt = PT[pitch] + } + else + pt = rev_mm(DEFAULT["pad_thickness"]) "mm" + + split(P["size"], S, "x") + if (S[2] == "") + S[2] = S[1] + if (S[1] != S[2]) + error("need n*n size") + + pins = int(P["pins"]) + if (pins / 4 != int(pins / 4)) + error("number of pins must be divisible by 4") + + pins=pins/4 + + + args = args ",nx=" pins ",ny=" pins ",x_spacing=" S[1] "mm,y_spacing=" S[2] "mm,pad_spacing=" pitch "mm,pad_thickness=" pt + + if (P["cpad_size"] != "") + args = args ",cpad_width=" P["cpad_size"] "mm,cpad_height=" P["cpad_size"] "mm" + + + print "args=" args > "/dev/stderr" + +# qf_globals("pins,size") + +} Index: tags/2.1.2/pcblib/parametric/qfp =================================================================== --- tags/2.1.2/pcblib/parametric/qfp (nonexistent) +++ tags/2.1.2/pcblib/parametric/qfp (revision 24813) @@ -0,0 +1,24 @@ +#!/bin/sh + +# Reference: Microchip Packaging Specification DS00000049BX (en012702.pdf), SSOP + +#@@example qfp(32,7x7,0.8) + +#@@purpose Generate QFP packages +#@@desc Generate QFP packages - a simplified frontend to qf() - +#@@desc look up 3..4 data in the datasheet and get a regular QFP footprint! +#@@desc NOTE: some of the qf() parameters can be also used. +#@@desc Should work for QFP, TQFP, LQFP, etc. + +#@@params pins,size,pitch,cpad_size + +#@@param:pins total number of pins (leads); must be divisible by 4 +#@@param:size a single integer N or NxN or NxNxH; body dimension (width or height of the plastic body) in mm +#@@param:pitch lead pitch (distance between the centerline of two adjacent leads), in mm; must be one of 0.4, 0.5, 0.65 + +#@@param:cpad_size width (and height) of the central pad, in mm +#@@optional:cpad_size +#@@default:cpad_size empty, there's no central pad + +awk -f `dirname $0`/common.awk -f `dirname $0`/qfp.awk -f `dirname $0`/qf.awk -v "args=$*" -v gen=`basename $0` -v "genfull=$0" + Property changes on: tags/2.1.2/pcblib/parametric/qfp ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/2.1.2/pcblib/parametric/qfp.awk =================================================================== --- tags/2.1.2/pcblib/parametric/qfp.awk (nonexistent) +++ tags/2.1.2/pcblib/parametric/qfp.awk (revision 24813) @@ -0,0 +1,52 @@ +function parri(A ,s,i) +{ + for(i in A) + s = s " " i + return s +} + +BEGIN { + help_auto() + PT["0.8"] = "0.55mm" + PT["0.65"] = "0.35mm" + PT["0.5"] = "0.3mm" + PT["0.4"] = "0.2mm" + + proc_args(P, "pins,size,pitch,cpad_size,pad_thickness", "pins,size,pitch") + + pitch = P["pitch"] + sub("0*$", "", pitch) + + if (!(args ~ "pad_thickness=")) { + if (!(pitch in PT)) + error("Unknown pitch, should be one of:" parri(PT)) + pt = PT[pitch] + } + else + pt = rev_mm(DEFAULT["pad_thickness"]) "mm" + + split(P["size"], S, "x") + if (S[2] == "") + S[2] = S[1] + if (S[1] != S[2]) + error("need n*n size") + + pins = int(P["pins"]) + if (pins / 4 != int(pins / 4)) + error("number of pins must be divisible by 4") + + pins=pins/4 + + args = args ",width=" S[1] " mm,height=" S[2] " mm" + + S[1] += 1.45 + S[2] += 1.45 + args = args ",nx=" pins ",ny=" pins ",x_spacing=" S[1] "mm,y_spacing=" S[2] "mm,pad_spacing=" pitch "mm,pad_thickness=" pt "mm" + + + if (P["cpad_size"] != "") + args = args ",cpad_width=" P["cpad_size"] "mm,cpad_height=" P["cpad_size"] "mm" + + args = args ",int_bloat=0.5mm,ext_bloat=1.1mm" + args = args ",?bodysilk=full,?silkmark=circle" +} Index: tags/2.1.2/pcblib/parametric/qsop =================================================================== --- tags/2.1.2/pcblib/parametric/qsop (nonexistent) +++ tags/2.1.2/pcblib/parametric/qsop (revision 24813) @@ -0,0 +1,34 @@ +#!/bin/sh + +# Reference: Microchip Packaging Specification DS00000049BX (en012702.pdf), QSOP + +#@@example qsop(14) + +#@@purpose Generate QSOP packages. + +#@@desc Generate QSOP packages with variable number of pins and +#@@desc row spacing + +#@@include so +#@@include common.awk + +#@@over@default:pad_spacing 25 mil +#@@over@default:row_spacing 213 mil +#@@over@default:int_vloat 22 mil +#@@over@default:ext_bloat 23 mil +#@@over@default:pad_thickness 16 mil + + +defaults=' +?pad_spacing=25mil, +?row_spacing=213mil, +?int_bloat=22mil, +?ext_bloat=23mil, +?rarc=25, +?silk_ext_x=18, +?silk_ext_y=22, +?pad_thickness=16mil +' + +awk -f `dirname $0`/common.awk -f `dirname $0`/so.awk -v "args=$defaults,$*" -v gen=`basename $0` -v "genfull=$0" + Property changes on: tags/2.1.2/pcblib/parametric/qsop ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/2.1.2/pcblib/parametric/rcy =================================================================== --- tags/2.1.2/pcblib/parametric/rcy (nonexistent) +++ tags/2.1.2/pcblib/parametric/rcy (revision 24813) @@ -0,0 +1,32 @@ +#!/bin/sh + +#@@example rcy(300,bar+) + +#@@purpose Generate radial lead through-hole component + +#@@desc Generate radial lead through-hole component with 2 pins (typical use: electrolytic caps) +#@@params spacing,pol,dia + +#@@param:spacing spacing between the two pins +#@@dim:spacing + +#@@param:pol how to mark polarity: (optional; default: sign) +#@@enum:pol:none no marking +#@@enum:pol:sign print + next to pin 1 and - next to pin 2 +#@@enum:pol:bar+ draw a bar inside the circle, around pin 2 +#@@enum:pol:bar- draw a bar inside the circle, around pin 1 +#@@enum:pol:bar same as bar+ +#@@enum:pol:bar+sign bar+ and sign combined +#@@enum:pol:bar-sign bar- and sign combined +#@@optional:pol +#@@default:pol sign +#@@preview_args:pol 300 + +#@@param:dia body diameter - affects the silk circle +#@@optional:dia +#@@default:dia spacing*2 + +#@@include common.awk + +awk -f `dirname $0`/common.awk -f `dirname $0`/rcy.awk -v "args=$*" -v gen=`basename $0` -v "genfull=$0" + Property changes on: tags/2.1.2/pcblib/parametric/rcy ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/2.1.2/pcblib/parametric/rcy.awk =================================================================== --- tags/2.1.2/pcblib/parametric/rcy.awk (nonexistent) +++ tags/2.1.2/pcblib/parametric/rcy.awk (revision 24813) @@ -0,0 +1,93 @@ +function pol_sign( ox,oy) +{ + ox = offs_x + + size=mil(20) + + offs_x = spacing/2 +dia/2+size*2 + element_line(-size, 0, +size, 0) + + offs_x = spacing/2 -dia/2-size*2 + element_line(-size, 0, +size, 0) + element_line(0, -size, 0, +size) + + offs_x = ox +} + +BEGIN { + help_auto() + set_arg(P, "?pol", "sign") + proc_args(P, "spacing,pol,dia", "spacing") + + spacing = parse_dim(P["spacing"]) + dia = either(parse_dim(P["dia"]), spacing*2) + + offs_x = +spacing/2 + + element_begin("", "C1", "acy" P["spacing"] ,0,0, spacing/2-spacing/5,-mil(20)) + + element_pin(-spacing/2, 0, 1) + element_pin(+spacing/2, 0, 2) + dimension(-spacing/2, 0, +spacing/2, 0, dia*0.8, "spacing") + + +# silk rectangle and pins + element_arc(0, 0, dia/2, dia/2, 0, 360) + dimension(-dia/2, 0, +dia/2, 0, dia*-0.8, "dia") + + + if (P["pol"] == "sign") { + pol_sign() + } + else if (P["pol"] ~ "^bar") { +# determine bar side (default to -) + side=P["pol"] + sub("^bar", "", side) + if (side ~ "sign") { + pol_sign() + sub("sign", "", side) + } + if (side == "") + side = "-" + side = int(side "1") * -1 + + th = mm(1) + ystep = th/2 + r = dia/2-th/2 + xs = dia/8 + ring = DEFAULT["pin_ringdia"] + for(y = 0; y < dia/2; y+=ystep) { + x = r*r-y*y + if (x < 0) + break + x = sqrt(x) + if (x <= xs) + break + if (y > ring/2+th/2) { + element_line(side*xs, y, side*x, y, th) + if (y != 0) + element_line(side*xs, -y, side*x, -y, th) + } + else { +# keep out a rectangle around the pin + end1=spacing/2-ring + end2=spacing/2+ring + if (end1 > xs) + element_line(side*xs, y, side*end1, y, th) + if (end2 < x) + element_line(side*end2, y, side*x, y, th) + if (y != 0) { + if (end1 > xs) + element_line(side*xs, -y, side*end1, -y, th) + if (end2 < x) + element_line(side*end2, -y, side*x, -y, th) + } + } + } + } + else if ((P["pol"] != "") && (P["pol"] != "none")) { + error("Invalid pol") + } + + element_end() +} Index: tags/2.1.2/pcblib/parametric/screw =================================================================== --- tags/2.1.2/pcblib/parametric/screw (nonexistent) +++ tags/2.1.2/pcblib/parametric/screw (revision 24813) @@ -0,0 +1,35 @@ +#!/bin/sh + +#@@example screw(3.2mm, 6mm, circle:hex) + +#@@purpose Generic screw. + +#@@desc Generate a "single pin" screw with optional head shapes +#@@params hole,head,shape,ring + +#@@param:hole hole diameter or name of a standard screw (e.g. M3) +#@@dim:hole + + +#@@param:head head outmost diameter (or optional head name for a standard screw: pan, button, cheese, flat-washer, internal-lock-washer) +#@@dim:head + +#@@param:ring copper ring outer diameter +#@@dim:ring +#@@optional:ring +#@@default:ring 80% of head diameter + + +#@@param:shape shape of the head drawn on silkmark; multiple values can be listed separated with colons, e.g. "shape=circle:hex" +#@@enum:shape:circle circle +#@@enum:shape:hex hexagon with straight line edges, size is from corner to corner +#@@enum:shape:tx "torx": hexagon with arced edges +#@@enum:shape:xzn "triple square" +#@@enum:shape:ph philips slot (cross) - useful together with circle +#@@enum:shape:slot a single straight line slot - useful together with circle +#@@default:shape circle +#@@preview_args:shape 3mm,6mm + +#@@include common.awk + +awk -f `dirname $0`/common.awk -f `dirname $0`/screw.awk -v "args=$*" -v gen=`basename $0` -v "genfull=$0" -v "genfull=$0" Property changes on: tags/2.1.2/pcblib/parametric/screw ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/2.1.2/pcblib/parametric/screw.awk =================================================================== --- tags/2.1.2/pcblib/parametric/screw.awk (nonexistent) +++ tags/2.1.2/pcblib/parametric/screw.awk (revision 24813) @@ -0,0 +1,128 @@ +function shp(r, edges, tx ,a,x,y,xl,yl,step,x1,y1,x2,y2,tx1,tx2,txs) +{ + step = 2*3.141592654/edges + if (tx == 1) { + tx1 = 0.7 + tx2 = 0.6 + txs = 5 + } + else if (tx == 2) { + tx1 = 0.85 + tx2 = 0.8 + txs = 5 + } + else if (tx == 3) { + tx1 = 0.2 + tx2 = 0.2 + txs = 3 + } + for(n = 0; n <= edges; n++) { + a += step + x = cos(a)*r + y = sin(a)*r + if (xl != "") { + if (tx) { + x1 = cos(a-(txs-1)*step/txs)*r*tx1 + y1 = sin(a-(txs-1)*step/txs)*r*tx1 + x2 = cos(a-step/txs)*r*tx1 + y2 = sin(a-step/txs)*r*tx1 + x3 = cos(a-step/2)*r*tx2 + y3 = sin(a-step/2)*r*tx2 + element_line(xl, yl, x1, y1) + element_line(x, y, x2, y2) + element_line(x3, y3, x1, y1) + element_line(x3, y3, x2, y2) + } + else + element_line(xl, yl, x, y) + } + xl = x + yl = y + } +} + +function round_up(num, to) +{ + if ((num/to) == int(num/to)) + return num + return int(num/to+1)*to +} + +BEGIN { + help_auto() + set_arg(P, "?shape", "circle") + proc_args(P, "hole,head,shape,ring", "hole") + + element_begin("", "S1", "screw:" P["hole"] "," P["head"]"," P["shape"] ,0,0, 0, mil(-100)) + + if (P["hole"] ~ "^M") { + hole = P["hole"] + sub("^M", "", hole) + h = parse_dim(int(hole) "mm") + if ((hole ~ "tight") || (hole ~ "close.fit")) + hole = h * 1.05 + else + hole = h * 1.1 + hd = parse_dim(P["head"]) + if ((hd == 0) || (hd == "")) { + hd = P["head"] + if (hd == "button") + head = 1.9*h + else if (hd == "button") + head = 1.9*h + else if (hd == "cheese") + head = round_up(1.7*h, mm(0.5)) + else if (hd ~ "flat.washer") + head = round_up(2.1*h, mm(1)) + else if ((hd == "") || (hd == "pan") || (hd ~ "int.*.lock.washer")) + head = 2*h + else + error("Unknown standard head: " hd) + } + else + head = hd +# print hole, head > "/dev/stderr" + } + else { + hole = parse_dim(P["hole"]) + head = parse_dim(P["head"]) + } + + if (head == "") + error("need a standard screw name, e.g. M3, or a head diameter") + + if (head < hole) + error("head diameter must be larger than hole diameter") + + ring = parse_dim(P["ring"]) + + if (ring == "") + ring = head*0.8 + + element_pin(0, 0, 1, "none", ring, "", "", hole) + + shape = ":" P["shape"] ":" + + if (shape ~ ":circle:") + element_arc(0, 0, head/2, head/2, 0, 360) + + if (shape ~ ":hex:") + shp(head/2, 6, 0) + + if (shape ~ ":tx:") + shp(head/2, 6, 1) + + if (shape ~ ":xzn:") + shp(head/2, 12, 2) + + if (shape ~ ":ph:") + shp(head*0.4, 4, 3) + + if (shape ~ ":slot:") + element_line(-head/2, 0, head/2, 0) + + dimension(-head/2, 0, head/2, 0, head*0.7, "head") + dimension(-hole/2, 0, hole/2, 0, head*0.6, "hole") + + element_end() +} Index: tags/2.1.2/pcblib/parametric/silkmark.help =================================================================== --- tags/2.1.2/pcblib/parametric/silkmark.help (nonexistent) +++ tags/2.1.2/pcblib/parametric/silkmark.help (revision 24813) @@ -0,0 +1,11 @@ +#@@param:silkmark how to mark pin 1 on the silk layer; multiple values can be listed separated with colons, e.g. "silkmark=externalx:angled" +#@@enum:silkmark:square a rectangle around pin 1 +#@@enum:silkmark:externalx a little triangle placed outside of the box pointing in line with the first x row +#@@enum:silkmark:externaly a little triangle placed outside of the box pointing in line with the first y row +#@@enum:silkmark:external45 a little triangle placed outside of the box pointing at the corner in 45 degree +#@@enum:silkmark:external shorthand for external +#@@enum:silkmark:angled an angled line in the corner +#@@enum:silkmark:arc an external 270 degree arc +#@@enum:silkmark:circle a circle, 270 degrees external +#@@enum:silkmark:dot a small external dot +#@@enum:silkmark:none no mark Index: tags/2.1.2/pcblib/parametric/so =================================================================== --- tags/2.1.2/pcblib/parametric/so (nonexistent) +++ tags/2.1.2/pcblib/parametric/so (revision 24813) @@ -0,0 +1,40 @@ +#!/bin/sh + +#@@example so(14) + +#@@purpose Generate SO and SO-like packages. + +#@@desc Generate SO packages with variable number of pins and +#@@desc row spacing +#@@params n, row_spacing, pad_spacing + +#@@param:n number of pins + +#@@param:row_spacing spacing between the two rows of pads: distance between the end of the first and last pins +#@@dim:row_spacing +#@@optional:row_spacing +#@@default:row_spacing 250 mil + + +#@@param:pad_spacing spacing between the centerline of two pads +#@@dim:pad_spacing +#@@optional:pad_spacing +#@@default:pad_spacing 50 mil + + +#@@param:ext_bloat how much longer the pad should extend outwards from the end-point of the pin +#@@dim:ext_bloat +#@@optional:ext_bloat +#@@default:ext_bloat 10 mil + +#@@param:int_bloat how much longer the pad should extend inwards from the end-point of the pin +#@@dim:int_bloat +#@@optional:int_bloat +#@@default:int_bloat 55 mil + +#@@include common.awk + +#@@over@ignore::pin_ + +awk -f `dirname $0`/common.awk -f `dirname $0`/so.awk -v "args=$*" -v gen=`basename $0` -v "genfull=$0" + Property changes on: tags/2.1.2/pcblib/parametric/so ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/2.1.2/pcblib/parametric/so.awk =================================================================== --- tags/2.1.2/pcblib/parametric/so.awk (nonexistent) +++ tags/2.1.2/pcblib/parametric/so.awk (revision 24813) @@ -0,0 +1,51 @@ +BEGIN { + help_auto() + set_arg(P, "?row_spacing", 250) + set_arg(P, "?pad_spacing", 50) + set_arg(P, "?ext_bloat", 10) + set_arg(P, "?int_bloat", 55) + + proc_args(P, "n,row_spacing,pad_spacing,ext_bloat,int_bloat", "n") + + P["n"] = int(P["n"]) + if ((P["n"] < 2) || ((P["n"] % 2) != 0)) + error("Number of pins have to be an even positive number") + + row_spacing=parse_dim(P["row_spacing"]) + pad_spacing=parse_dim(P["pad_spacing"]) + ext_bloat=parse_dim(P["ext_bloat"]) + int_bloat=parse_dim(P["int_bloat"]) + +# translate origin to the middle (int() and -0.5 rounds it for odd number of pins) + offs_x = -(row_spacing/2) + offs_y = -int((P["n"]/4-0.5) * pad_spacing) + + element_begin("", "U1", P["n"] "*" P["row_spacing"] ,0,0, 0, mil(-100)) + + for(n = 1; n <= P["n"]/2; n++) { + y = (n-1) * pad_spacing + element_pad(-ext_bloat, y, int_bloat, y, pad_width, n, "square") + element_pad(row_spacing-int_bloat, y, row_spacing+ext_bloat, y, pad_width, P["n"] - n + 1, "square") + } + + silk_dist_x = either(parse_dim(P["silk_ext_x"]), pad_spacing/2) + silk_dist_y = either(parse_dim(P["silk_ext_y"]), pad_spacing/2) + rarc = either(parse_dim(P["rarc"]), pad_spacing/2) + + dip_outline(-silk_dist_x-ext_bloat, -silk_dist_y, row_spacing + silk_dist_x+ext_bloat , (n-2) * pad_spacing + silk_dist_y, rarc) + + left_dim="@" -silk_dist_x-ext_bloat-pad_spacing ";0" + dimension(0, 0, 0, pad_spacing, left_dim, "pad_spacing") + dimension(0, 0, row_spacing, 0, (pad_spacing * 1.8), "row_spacing") + dimension(-ext_bloat, 0, 0, 0, (pad_spacing * 1.2), "ext_bloat") + dimension(row_spacing-int_bloat, 0, row_spacing, 0, (pad_spacing * 1.2), "int_bloat") + + th=DEFAULT["pad_thickness"] + y = (n-2) * pad_spacing + dimension(-ext_bloat-th/2, y, +int_bloat+th/2, y, (pad_spacing * -1.2), "") + dimension(0, y-th/2, 0, y+th/2, left_dim, "pad_thickness") + +# dimension(-silk_dist_x-ext_bloat, -silk_dist_y, row_spacing + silk_dist_x+ext_bloat, -silk_dist_y, pad_spacing*2.5, "") + + element_end() +} Index: tags/2.1.2/pcblib/parametric/ssop =================================================================== --- tags/2.1.2/pcblib/parametric/ssop (nonexistent) +++ tags/2.1.2/pcblib/parametric/ssop (revision 24813) @@ -0,0 +1,33 @@ +#!/bin/sh + +# Reference: Microchip Packaging Specification DS00000049BX (en012702.pdf), SSOP + +#@@example ssop(14) + +#@@purpose Generate SSOP packages. + +#@@desc Generate SSOP packages with variable number of pins and +#@@desc row spacing + +#@@include so +#@@include common.awk + +#@@over@default:pad_spacing 0.65 mm +#@@over@default:row_spacing 7.8 mm +#@@over@default:int_bloat 0.5 mm +#@@over@default:ext_bloat 0.13 mm +#@@over@default:pad_thickness 0.45 mm + +defaults=' +?pad_spacing=0.65mm, +?row_spacing=7.8mm, +?int_bloat=0.5mm, +?ext_bloat=0.13mm, +?rarc=25, +?silk_ext_x=18, +?silk_ext_y=22, +?pad_thickness=0.45mm +' + +awk -f `dirname $0`/common.awk -f `dirname $0`/so.awk -v "args=$defaults,$*" -v gen=`basename $0` -v "genfull=$0" + Property changes on: tags/2.1.2/pcblib/parametric/ssop ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/2.1.2/pcblib/parametric/tssop =================================================================== --- tags/2.1.2/pcblib/parametric/tssop (nonexistent) +++ tags/2.1.2/pcblib/parametric/tssop (revision 24813) @@ -0,0 +1,33 @@ +#!/bin/sh + +# Reference: Microchip Packaging Specification DS00000049BX (en012702.pdf), MSOP + +#@@example tssop(8) + +#@@purpose Generate TSSOP packages. + +#@@desc Generate TSSOP 4.4mm body packages with variable number of pins and +#@@desc row spacing + +#@@include so +#@@include common.awk + +#@@over@default:pad_spacing 0.65 mm +#@@over@default:row_spacing 6.4 mm +#@@over@default:int_bloat 0.6 mm +#@@over@default:ext_bloat 0.4 mm +#@@over@default:pad_thickness 0.45 mm + +defaults=' +?pad_spacing=0.65mm, +?row_spacing=6.4mm, +?int_bloat=0.6mm, +?ext_bloat=0.4mm, +?rarc=25, +?silk_ext_x=18, +?silk_ext_y=22, +?pad_thickness=0.45mm +' + +awk -f `dirname $0`/common.awk -f `dirname $0`/so.awk -v "args=$defaults,$*" -v gen=`basename $0` -v "genfull=$0" + Property changes on: tags/2.1.2/pcblib/parametric/tssop ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/2.1.2/pcblib/smd/01005.fp =================================================================== --- tags/2.1.2/pcblib/smd/01005.fp (nonexistent) +++ tags/2.1.2/pcblib/smd/01005.fp (revision 24813) @@ -0,0 +1,32 @@ +##from:pcb +##for:resistor +##for:capacitor +##for:led + + # grab the input values and convert to 1/100 mil + # how much to grow the pads by for soldermask [1/100 mil] + # clearance from planes [1/100 mil] + # silk screen width [1/100 mil] + # courtyard silk screen width [1/100 mil] +# element_flags, description, pcb-name, value, mark_x, mark_y, +# text_x, text_y, text_direction, text_scale, text_flags +Element[0x00000000 "Standard SMT resistor, capacitor etc" "" "01005" 0 0 -3150 -3150 0 100 ""] +( +# +# Pad[x1, y1, x2, y2, thickness, clearance, mask, name , pad number, flags] + Pad[-807 -19 + -807 19 + 984 2000 1584 "1" "1" "square"] + Pad[807 -19 + 807 19 + 984 2000 1584 "2" "2" "square"] +# +# This draws a 1 mil placement courtyard outline in silk. It should probably +# not be included since you wont want to try and fab a 1 mil silk line. Then +# again, it is most useful during parts placement. It really is time for some +# additional non-fab layers... +# ElementLine[eval(-1*V1/2) eval(-1*V2/2) eval(-1*V1/2) eval( V2/2) CYW] +# ElementLine[eval(-1*V1/2) eval(-1*V2/2) eval( V1/2) eval(-1*V2/2) CYW] +# ElementLine[eval( V1/2) eval( V2/2) eval( V1/2) eval(-1*V2/2) CYW] +# ElementLine[eval( V1/2) eval( V2/2) eval(-1*V1/2) eval( V2/2) CYW] +) Index: tags/2.1.2/pcblib/smd/01005.scad =================================================================== --- tags/2.1.2/pcblib/smd/01005.scad (nonexistent) +++ tags/2.1.2/pcblib/smd/01005.scad (revision 24813) @@ -0,0 +1,19 @@ +module part_01005(len=0.4, width=0.2, height=0.13, pad_len=0.1) +{ + union() { + translate([0,0,height/2]) { + // body + color([0.1,0.1,0.1]) + cube([len-2*pad_len,width,height], center=true); + // terminals + color([0.8,0.8,0.8]) { + translate([+len/2-pad_len/2, 0, 0]) + cube([pad_len, width, height], center=true); + } + color([0.8,0.8,0.8]) { + translate([-len/2+pad_len/2, 0, 0]) + cube([pad_len, width, height], center=true); + } + } + } +} Index: tags/2.1.2/pcblib/smd/0201.fp =================================================================== --- tags/2.1.2/pcblib/smd/0201.fp (nonexistent) +++ tags/2.1.2/pcblib/smd/0201.fp (revision 24813) @@ -0,0 +1,32 @@ +##from:pcb +##for:resistor +##for:capacitor +##for:led + + # grab the input values and convert to 1/100 mil + # how much to grow the pads by for soldermask [1/100 mil] + # clearance from planes [1/100 mil] + # silk screen width [1/100 mil] + # courtyard silk screen width [1/100 mil] +# element_flags, description, pcb-name, value, mark_x, mark_y, +# text_x, text_y, text_direction, text_scale, text_flags +Element[0x00000000 "Standard SMT resistor, capacitor etc" "" "0201" 0 0 -3150 -3150 0 100 ""] +( +# +# Pad[x1, y1, x2, y2, thickness, clearance, mask, name , pad number, flags] + Pad[-1181 0 + -1181 0 + 1574 2000 2174 "1" "1" "square"] + Pad[1181 0 + 1181 0 + 1574 2000 2174 "2" "2" "square"] +# +# This draws a 1 mil placement courtyard outline in silk. It should probably +# not be included since you wont want to try and fab a 1 mil silk line. Then +# again, it is most useful during parts placement. It really is time for some +# additional non-fab layers... +# ElementLine[eval(-1*V1/2) eval(-1*V2/2) eval(-1*V1/2) eval( V2/2) CYW] +# ElementLine[eval(-1*V1/2) eval(-1*V2/2) eval( V1/2) eval(-1*V2/2) CYW] +# ElementLine[eval( V1/2) eval( V2/2) eval( V1/2) eval(-1*V2/2) CYW] +# ElementLine[eval( V1/2) eval( V2/2) eval(-1*V1/2) eval( V2/2) CYW] +) Index: tags/2.1.2/pcblib/smd/0201.scad =================================================================== --- tags/2.1.2/pcblib/smd/0201.scad (nonexistent) +++ tags/2.1.2/pcblib/smd/0201.scad (revision 24813) @@ -0,0 +1,20 @@ +module part_0201(len=0.6, width=0.3, height=0.23, pad_len=0.15) +{ + union() { + translate([0,0,height/2]) { + // body + color([0.1,0.1,0.1]) + cube([len-2*pad_len,width,height], center=true); + // terminals + color([0.8,0.8,0.8]) { + translate([+len/2-pad_len/2, 0, 0]) + cube([pad_len, width, height], center=true); + } + color([0.8,0.8,0.8]) { + translate([-len/2+pad_len/2, 0, 0]) + cube([pad_len, width, height], center=true); + } + } + } +} + Index: tags/2.1.2/pcblib/smd/0402.fp =================================================================== --- tags/2.1.2/pcblib/smd/0402.fp (nonexistent) +++ tags/2.1.2/pcblib/smd/0402.fp (revision 24813) @@ -0,0 +1,32 @@ +##from:pcb +##for:resistor +##for:capacitor +##for:led + + # grab the input values and convert to 1/100 mil + # how much to grow the pads by for soldermask [1/100 mil] + # clearance from planes [1/100 mil] + # silk screen width [1/100 mil] + # courtyard silk screen width [1/100 mil] +# element_flags, description, pcb-name, value, mark_x, mark_y, +# text_x, text_y, text_direction, text_scale, text_flags +Element[0x00000000 "Standard SMT resistor, capacitor etc" "" "0402" 0 0 -3150 -3150 0 100 ""] +( +# +# Pad[x1, y1, x2, y2, thickness, clearance, mask, name , pad number, flags] + Pad[-1574 -393 + -1574 393 + 1968 2000 2568 "1" "1" "square"] + Pad[1574 -393 + 1574 393 + 1968 2000 2568 "2" "2" "square"] +# +# This draws a 1 mil placement courtyard outline in silk. It should probably +# not be included since you wont want to try and fab a 1 mil silk line. Then +# again, it is most useful during parts placement. It really is time for some +# additional non-fab layers... +# ElementLine[eval(-1*V1/2) eval(-1*V2/2) eval(-1*V1/2) eval( V2/2) CYW] +# ElementLine[eval(-1*V1/2) eval(-1*V2/2) eval( V1/2) eval(-1*V2/2) CYW] +# ElementLine[eval( V1/2) eval( V2/2) eval( V1/2) eval(-1*V2/2) CYW] +# ElementLine[eval( V1/2) eval( V2/2) eval(-1*V1/2) eval( V2/2) CYW] +) Index: tags/2.1.2/pcblib/smd/0402.scad =================================================================== --- tags/2.1.2/pcblib/smd/0402.scad (nonexistent) +++ tags/2.1.2/pcblib/smd/0402.scad (revision 24813) @@ -0,0 +1,20 @@ +module part_0402(len=1.0, width=0.5, height=0.35, pad_len=0.25) +{ + union() { + translate([0,0,height/2]) { + // body + color([0.1,0.1,0.1]) + cube([len-2*pad_len,width,height], center=true); + // terminals + color([0.8,0.8,0.8]) { + translate([+len/2-pad_len/2, 0, 0]) + cube([pad_len, width, height], center=true); + } + color([0.8,0.8,0.8]) { + translate([-len/2+pad_len/2, 0, 0]) + cube([pad_len, width, height], center=true); + } + } + } +} + Index: tags/2.1.2/pcblib/smd/0603.fp =================================================================== --- tags/2.1.2/pcblib/smd/0603.fp (nonexistent) +++ tags/2.1.2/pcblib/smd/0603.fp (revision 24813) @@ -0,0 +1,32 @@ +##from:pcb +##for:resistor +##for:capacitor +##for:led + + # grab the input values and convert to 1/100 mil + # how much to grow the pads by for soldermask [1/100 mil] + # clearance from planes [1/100 mil] + # silk screen width [1/100 mil] + # courtyard silk screen width [1/100 mil] +# element_flags, description, pcb-name, value, mark_x, mark_y, +# text_x, text_y, text_direction, text_scale, text_flags +Element[0x00000000 "Standard SMT resistor, capacitor etc" "" "0603" 0 0 -3150 -3150 0 100 ""] +( +# +# Pad[x1, y1, x2, y2, thickness, clearance, mask, name , pad number, flags] + Pad[-2559 -492 + -2559 492 + 2952 2000 3552 "1" "1" "square"] + Pad[2559 -492 + 2559 492 + 2952 2000 3552 "2" "2" "square"] +# +# This draws a 1 mil placement courtyard outline in silk. It should probably +# not be included since you wont want to try and fab a 1 mil silk line. Then +# again, it is most useful during parts placement. It really is time for some +# additional non-fab layers... +# ElementLine[eval(-1*V1/2) eval(-1*V2/2) eval(-1*V1/2) eval( V2/2) CYW] +# ElementLine[eval(-1*V1/2) eval(-1*V2/2) eval( V1/2) eval(-1*V2/2) CYW] +# ElementLine[eval( V1/2) eval( V2/2) eval( V1/2) eval(-1*V2/2) CYW] +# ElementLine[eval( V1/2) eval( V2/2) eval(-1*V1/2) eval( V2/2) CYW] +) Index: tags/2.1.2/pcblib/smd/0603.scad =================================================================== --- tags/2.1.2/pcblib/smd/0603.scad (nonexistent) +++ tags/2.1.2/pcblib/smd/0603.scad (revision 24813) @@ -0,0 +1,20 @@ +module part_0603(len=1.6, width=0.8, height=0.45, pad_len=0.3) +{ + union() { + translate([0,0,height/2]) { + // body + color([0.1,0.1,0.1]) + cube([len-2*pad_len,width,height], center=true); + // terminals + color([0.8,0.8,0.8]) { + translate([+len/2-pad_len/2, 0, 0]) + cube([pad_len, width, height], center=true); + } + color([0.8,0.8,0.8]) { + translate([-len/2+pad_len/2, 0, 0]) + cube([pad_len, width, height], center=true); + } + } + } +} + Index: tags/2.1.2/pcblib/smd/0805.fp =================================================================== --- tags/2.1.2/pcblib/smd/0805.fp (nonexistent) +++ tags/2.1.2/pcblib/smd/0805.fp (revision 24813) @@ -0,0 +1,34 @@ +##from:pcb +##for:resistor +##for:capacitor +##for:led + + # grab the input values and convert to 1/100 mil + # how much to grow the pads by for soldermask [1/100 mil] + # clearance from planes [1/100 mil] + # silk screen width [1/100 mil] + # courtyard silk screen width [1/100 mil] +# element_flags, description, pcb-name, value, mark_x, mark_y, +# text_x, text_y, text_direction, text_scale, text_flags +Element[0x00000000 "Standard SMT resistor, capacitor etc" "" "0805" 0 0 -3150 -3150 0 100 ""] +( +# +# Pad[x1, y1, x2, y2, thickness, clearance, mask, name , pad number, flags] + Pad[-3543 -393 + -3543 393 + 5118 2000 5718 "1" "1" "square"] + Pad[3543 -393 + 3543 393 + 5118 2000 5718 "2" "2" "square"] + ElementLine[-393 -2755 393 -2755 800] + ElementLine[-393 2755 393 2755 800] +# +# This draws a 1 mil placement courtyard outline in silk. It should probably +# not be included since you wont want to try and fab a 1 mil silk line. Then +# again, it is most useful during parts placement. It really is time for some +# additional non-fab layers... +# ElementLine[eval(-1*V1/2) eval(-1*V2/2) eval(-1*V1/2) eval( V2/2) CYW] +# ElementLine[eval(-1*V1/2) eval(-1*V2/2) eval( V1/2) eval(-1*V2/2) CYW] +# ElementLine[eval( V1/2) eval( V2/2) eval( V1/2) eval(-1*V2/2) CYW] +# ElementLine[eval( V1/2) eval( V2/2) eval(-1*V1/2) eval( V2/2) CYW] +) Index: tags/2.1.2/pcblib/smd/0805.scad =================================================================== --- tags/2.1.2/pcblib/smd/0805.scad (nonexistent) +++ tags/2.1.2/pcblib/smd/0805.scad (revision 24813) @@ -0,0 +1,19 @@ +module part_0805(len=2, width=1.2, height=0.5, pad_len=0.4) +{ + union() { + translate([0,0,height/2]) { + // body + color([0.1,0.1,0.1]) + cube([len-2*pad_len,width,height], center=true); + // terminals + color([0.8,0.8,0.8]) { + translate([+len/2-pad_len/2, 0, 0]) + cube([pad_len, width, height], center=true); + } + color([0.8,0.8,0.8]) { + translate([-len/2+pad_len/2, 0, 0]) + cube([pad_len, width, height], center=true); + } + } + } +} Index: tags/2.1.2/pcblib/smd/1008.fp =================================================================== --- tags/2.1.2/pcblib/smd/1008.fp (nonexistent) +++ tags/2.1.2/pcblib/smd/1008.fp (revision 24813) @@ -0,0 +1,34 @@ +##from:pcb +##for:resistor +##for:capacitor +##for:led + + # grab the input values and convert to 1/100 mil + # how much to grow the pads by for soldermask [1/100 mil] + # clearance from planes [1/100 mil] + # silk screen width [1/100 mil] + # courtyard silk screen width [1/100 mil] +# element_flags, description, pcb-name, value, mark_x, mark_y, +# text_x, text_y, text_direction, text_scale, text_flags +Element[0x00000000 "Standard SMT resistor, capacitor etc" "" "1008" 0 0 -3150 -3150 0 100 ""] +( +# +# Pad[x1, y1, x2, y2, thickness, clearance, mask, name , pad number, flags] + Pad[-5118 -2362 + -5118 2362 + 4330 2000 4930 "1" "1" "square"] + Pad[5118 -2362 + 5118 2362 + 4330 2000 4930 "2" "2" "square"] + ElementLine[-1377 -4527 1377 -4527 800] + ElementLine[-1377 4527 1377 4527 800] +# +# This draws a 1 mil placement courtyard outline in silk. It should probably +# not be included since you wont want to try and fab a 1 mil silk line. Then +# again, it is most useful during parts placement. It really is time for some +# additional non-fab layers... +# ElementLine[eval(-1*V1/2) eval(-1*V2/2) eval(-1*V1/2) eval( V2/2) CYW] +# ElementLine[eval(-1*V1/2) eval(-1*V2/2) eval( V1/2) eval(-1*V2/2) CYW] +# ElementLine[eval( V1/2) eval( V2/2) eval( V1/2) eval(-1*V2/2) CYW] +# ElementLine[eval( V1/2) eval( V2/2) eval(-1*V1/2) eval( V2/2) CYW] +) Index: tags/2.1.2/pcblib/smd/1206.fp =================================================================== --- tags/2.1.2/pcblib/smd/1206.fp (nonexistent) +++ tags/2.1.2/pcblib/smd/1206.fp (revision 24813) @@ -0,0 +1,34 @@ +##from:pcb +##for:resistor +##for:capacitor +##for:led + + # grab the input values and convert to 1/100 mil + # how much to grow the pads by for soldermask [1/100 mil] + # clearance from planes [1/100 mil] + # silk screen width [1/100 mil] + # courtyard silk screen width [1/100 mil] +# element_flags, description, pcb-name, value, mark_x, mark_y, +# text_x, text_y, text_direction, text_scale, text_flags +Element[0x00000000 "Standard SMT resistor, capacitor etc" "" "1206" 0 0 -3150 -3150 0 100 ""] +( +# +# Pad[x1, y1, x2, y2, thickness, clearance, mask, name , pad number, flags] + Pad[-5905 -1181 + -5905 1181 + 5118 2000 5718 "1" "1" "square"] + Pad[5905 -1181 + 5905 1181 + 5118 2000 5718 "2" "2" "square"] + ElementLine[-2362 -3740 2362 -3740 800] + ElementLine[-2362 3740 2362 3740 800] +# +# This draws a 1 mil placement courtyard outline in silk. It should probably +# not be included since you wont want to try and fab a 1 mil silk line. Then +# again, it is most useful during parts placement. It really is time for some +# additional non-fab layers... +# ElementLine[eval(-1*V1/2) eval(-1*V2/2) eval(-1*V1/2) eval( V2/2) CYW] +# ElementLine[eval(-1*V1/2) eval(-1*V2/2) eval( V1/2) eval(-1*V2/2) CYW] +# ElementLine[eval( V1/2) eval( V2/2) eval( V1/2) eval(-1*V2/2) CYW] +# ElementLine[eval( V1/2) eval( V2/2) eval(-1*V1/2) eval( V2/2) CYW] +) Index: tags/2.1.2/pcblib/smd/1206.scad =================================================================== --- tags/2.1.2/pcblib/smd/1206.scad (nonexistent) +++ tags/2.1.2/pcblib/smd/1206.scad (revision 24813) @@ -0,0 +1,20 @@ +module part_1206(len=3.2, width=1.6, height=0.6, pad_len=0.5) +{ + union() { + translate([0,0,height/2]) { + // body + color([0.1,0.1,0.1]) + cube([len-2*pad_len,width,height], center=true); + // terminals + color([0.8,0.8,0.8]) { + translate([+len/2-pad_len/2, 0, 0]) + cube([pad_len, width, height], center=true); + } + color([0.8,0.8,0.8]) { + translate([-len/2+pad_len/2, 0, 0]) + cube([pad_len, width, height], center=true); + } + } + } +} + Index: tags/2.1.2/pcblib/smd/1210.fp =================================================================== --- tags/2.1.2/pcblib/smd/1210.fp (nonexistent) +++ tags/2.1.2/pcblib/smd/1210.fp (revision 24813) @@ -0,0 +1,34 @@ +##from:pcb +##for:resistor +##for:capacitor +##for:led + + # grab the input values and convert to 1/100 mil + # how much to grow the pads by for soldermask [1/100 mil] + # clearance from planes [1/100 mil] + # silk screen width [1/100 mil] + # courtyard silk screen width [1/100 mil] +# element_flags, description, pcb-name, value, mark_x, mark_y, +# text_x, text_y, text_direction, text_scale, text_flags +Element[0x00000000 "Standard SMT resistor, capacitor etc" "" "1210" 0 0 -3150 -3150 0 100 ""] +( +# +# Pad[x1, y1, x2, y2, thickness, clearance, mask, name , pad number, flags] + Pad[-5905 -2755 + -5905 2755 + 5118 2000 5718 "1" "1" "square"] + Pad[5905 -2755 + 5905 2755 + 5118 2000 5718 "2" "2" "square"] + ElementLine[-1968 -5314 1968 -5314 800] + ElementLine[-1968 5314 1968 5314 800] +# +# This draws a 1 mil placement courtyard outline in silk. It should probably +# not be included since you wont want to try and fab a 1 mil silk line. Then +# again, it is most useful during parts placement. It really is time for some +# additional non-fab layers... +# ElementLine[eval(-1*V1/2) eval(-1*V2/2) eval(-1*V1/2) eval( V2/2) CYW] +# ElementLine[eval(-1*V1/2) eval(-1*V2/2) eval( V1/2) eval(-1*V2/2) CYW] +# ElementLine[eval( V1/2) eval( V2/2) eval( V1/2) eval(-1*V2/2) CYW] +# ElementLine[eval( V1/2) eval( V2/2) eval(-1*V1/2) eval( V2/2) CYW] +) Index: tags/2.1.2/pcblib/smd/1806.fp =================================================================== --- tags/2.1.2/pcblib/smd/1806.fp (nonexistent) +++ tags/2.1.2/pcblib/smd/1806.fp (revision 24813) @@ -0,0 +1,34 @@ +##from:pcb +##for:resistor +##for:capacitor +##for:led + + # grab the input values and convert to 1/100 mil + # how much to grow the pads by for soldermask [1/100 mil] + # clearance from planes [1/100 mil] + # silk screen width [1/100 mil] + # courtyard silk screen width [1/100 mil] +# element_flags, description, pcb-name, value, mark_x, mark_y, +# text_x, text_y, text_direction, text_scale, text_flags +Element[0x00000000 "Standard SMT resistor, capacitor etc" "" "1806" 0 0 -3150 -3150 0 100 ""] +( +# +# Pad[x1, y1, x2, y2, thickness, clearance, mask, name , pad number, flags] + Pad[-7874 -3543 + -7874 3543 + 6299 2000 6899 "1" "1" "square"] + Pad[7874 -3543 + 7874 3543 + 6299 2000 6899 "2" "2" "square"] + ElementLine[-3149 -6692 3149 -6692 800] + ElementLine[-3149 6692 3149 6692 800] +# +# This draws a 1 mil placement courtyard outline in silk. It should probably +# not be included since you wont want to try and fab a 1 mil silk line. Then +# again, it is most useful during parts placement. It really is time for some +# additional non-fab layers... +# ElementLine[eval(-1*V1/2) eval(-1*V2/2) eval(-1*V1/2) eval( V2/2) CYW] +# ElementLine[eval(-1*V1/2) eval(-1*V2/2) eval( V1/2) eval(-1*V2/2) CYW] +# ElementLine[eval( V1/2) eval( V2/2) eval( V1/2) eval(-1*V2/2) CYW] +# ElementLine[eval( V1/2) eval( V2/2) eval(-1*V1/2) eval( V2/2) CYW] +) Index: tags/2.1.2/pcblib/smd/1825.fp =================================================================== --- tags/2.1.2/pcblib/smd/1825.fp (nonexistent) +++ tags/2.1.2/pcblib/smd/1825.fp (revision 24813) @@ -0,0 +1,34 @@ +##from:pcb +##for:resistor +##for:capacitor +##for:led + + # grab the input values and convert to 1/100 mil + # how much to grow the pads by for soldermask [1/100 mil] + # clearance from planes [1/100 mil] + # silk screen width [1/100 mil] + # courtyard silk screen width [1/100 mil] +# element_flags, description, pcb-name, value, mark_x, mark_y, +# text_x, text_y, text_direction, text_scale, text_flags +Element[0x00000000 "Standard SMT resistor, capacitor etc" "" "1825" 0 0 -3150 -3150 0 100 ""] +( +# +# Pad[x1, y1, x2, y2, thickness, clearance, mask, name , pad number, flags] + Pad[-7874 -10236 + -7874 10236 + 6299 2000 6899 "1" "1" "square"] + Pad[7874 -10236 + 7874 10236 + 6299 2000 6899 "2" "2" "square"] + ElementLine[-3149 -13385 3149 -13385 800] + ElementLine[-3149 13385 3149 13385 800] +# +# This draws a 1 mil placement courtyard outline in silk. It should probably +# not be included since you wont want to try and fab a 1 mil silk line. Then +# again, it is most useful during parts placement. It really is time for some +# additional non-fab layers... +# ElementLine[eval(-1*V1/2) eval(-1*V2/2) eval(-1*V1/2) eval( V2/2) CYW] +# ElementLine[eval(-1*V1/2) eval(-1*V2/2) eval( V1/2) eval(-1*V2/2) CYW] +# ElementLine[eval( V1/2) eval( V2/2) eval( V1/2) eval(-1*V2/2) CYW] +# ElementLine[eval( V1/2) eval( V2/2) eval(-1*V1/2) eval( V2/2) CYW] +) Index: tags/2.1.2/pcblib/smd/2706.fp =================================================================== --- tags/2.1.2/pcblib/smd/2706.fp (nonexistent) +++ tags/2.1.2/pcblib/smd/2706.fp (revision 24813) @@ -0,0 +1,20 @@ +##from:pcb +##for:resistor +##for:capacitor +##for:led + + # how much to grow the pads by for soldermask + # clearance from planes +Element(0x00 "Standard SMT resistor, capacitor etc" "" "2706" 0 0 179 0 3 100 0x00) +( + ElementLine(-159 -54 -159 54 10) + ElementLine(-159 54 159 54 10) + ElementLine(159 54 159 -54 10) + ElementLine(159 -54 -159 -54 10) + Pad(-108 -3 + -108 3 + 78 20 84 "1" "1" 0x00000100) + Pad(108 -3 + 108 3 + 78 20 84 "2" "2" 0x00000100) +) Index: tags/2.1.2/pcblib/smd/DO214.fp =================================================================== --- tags/2.1.2/pcblib/smd/DO214.fp (nonexistent) +++ tags/2.1.2/pcblib/smd/DO214.fp (revision 24813) @@ -0,0 +1,20 @@ +##from:pcb +##for:diode + + # how much to grow the pads by for soldermask + # clearance from planes +Element(0x00 "SMT diode (pin 1 is cathode)" "" "DO214" 0 0 221 0 3 100 0x00) +( + ElementLine(-211 -89 -211 89 20) + ElementLine(-211 89 -141 114 10) + ElementLine(-141 114 201 114 10) + ElementLine(201 114 201 -114 10) + ElementLine(201 -114 -141 -114 10) + ElementLine(-141 -114 -211 -89 10) + Pad(-106 -19 + -106 19 + 140 20 146 "1" "1" 0x00000100) + Pad(106 -19 + 106 19 + 140 20 146 "2" "2" 0x00000100) +) Index: tags/2.1.2/pcblib/smd/DO214AB.fp =================================================================== --- tags/2.1.2/pcblib/smd/DO214AB.fp (nonexistent) +++ tags/2.1.2/pcblib/smd/DO214AB.fp (revision 24813) @@ -0,0 +1,20 @@ +##from:pcb +##for:diode + + # how much to grow the pads by for soldermask + # clearance from planes +Element(0x00 "SMT diode (pin 1 is cathode)" "" "DO214AB" 0 0 227 0 3 100 0x00) +( + ElementLine(-217 -92 -217 92 20) + ElementLine(-217 92 -145 118 10) + ElementLine(-145 118 207 118 10) + ElementLine(207 118 207 -118 10) + ElementLine(207 -118 -145 -118 10) + ElementLine(-145 -118 -217 -92 10) + Pad(-109 -20 + -109 20 + 145 20 151 "1" "1" 0x00000100) + Pad(109 -20 + 109 20 + 145 20 151 "2" "2" 0x00000100) +) Index: tags/2.1.2/pcblib/smd/MPAK.fp =================================================================== --- tags/2.1.2/pcblib/smd/MPAK.fp (nonexistent) +++ tags/2.1.2/pcblib/smd/MPAK.fp (revision 24813) @@ -0,0 +1,31 @@ +##from:pcb +##for:transistor +##for:stabilizer +##for:linear + +Element(0x00 "Pressure transducer" "" "MPAK" 235 0 3 100 0x00) +( + ElementLine(0 0 0 558 10) + ElementLine(0 558 215 558 10) + ElementLine(215 558 215 0 10) + ElementLine(215 0 0 0 10) + # 1st pin on pin side + Pad(32 469 + 32 525 + 31 "1" "1" 0x100) + Pad(82 469 + 82 525 + 31 "2" "2" 0x100) + Pad(132 469 + 132 525 + 31 "3" "3" 0x100) + # last pin on pin side + Pad(182 469 + 182 525 + 31 "4" "4" 0x100) + # extra wide pin on opposite side + Pad(144 60 + 70 60 + 87 "5" "5" 0x100) + Mark(32 497) +) Index: tags/2.1.2/pcblib/smd/SC70_3.fp =================================================================== --- tags/2.1.2/pcblib/smd/SC70_3.fp (nonexistent) +++ tags/2.1.2/pcblib/smd/SC70_3.fp (revision 24813) @@ -0,0 +1,33 @@ +##from:pcb +##for:transistor + + # 78 for SOT23 + # 82 for SOT23 + # 41 for SOT23 + # 34 for SOT23, 24 for SOT25 +Element(0x00 "SMT transistor, 3 pins" "" "SC70_3" 114 0 3 100 0x00) +( + ElementLine(0 0 0 119 10) + ElementLine(0 119 94 119 10) + ElementLine(94 119 94 0 10) + ElementLine(94 0 0 0 10) + # 1st side, 1st pin + Pad(21 91 + 21 97 + 29 + "1" "1" 0x100) + # 1st side, 2nd pin + # 1st side, 3rd pin + Pad(72 91 + 72 97 + 29 + "2" "2" 0x100) + # 2nd side, 3rd pin + # 2nd side, 2nd pin + Pad(47 21 + 47 27 + 29 + "3" "3" 0x100) + # 2nd side, 1st pin + Mark(21 94) +) Index: tags/2.1.2/pcblib/smd/SC70_4.fp =================================================================== --- tags/2.1.2/pcblib/smd/SC70_4.fp (nonexistent) +++ tags/2.1.2/pcblib/smd/SC70_4.fp (revision 24813) @@ -0,0 +1,40 @@ +##from:pcb +##for:transistor +##for:stabilizer +##for:linear + + # 78 for SOT23 + # 82 for SOT23 + # 41 for SOT23 + # 34 for SOT23, 24 for SOT25 +Element(0x00 "SMT transistor, 4 pins" "" "SC70_4" 114 0 3 100 0x00) +( + ElementLine(0 0 0 119 10) + ElementLine(0 119 94 119 10) + ElementLine(94 119 94 0 10) + ElementLine(94 0 0 0 10) + # 1st side, 1st pin + # extra width + Pad(24 94 + 27 94 + 29 + "1" "1" 0x100) + # 1st side, 2nd pin + # 1st side, 3rd pin + Pad(72 91 + 72 97 + 29 + "2" "2" 0x100) + # 2nd side, 3rd pin + Pad(72 21 + 72 27 + 29 + "3" "3" 0x100) + # 2nd side, 2nd pin + # 2nd side, 1st pin + Pad(21 21 + 21 27 + 29 + "4" "4" 0x100) + Mark(21 94) +) Index: tags/2.1.2/pcblib/smd/SC90.fp =================================================================== --- tags/2.1.2/pcblib/smd/SC90.fp (nonexistent) +++ tags/2.1.2/pcblib/smd/SC90.fp (revision 24813) @@ -0,0 +1,33 @@ +##from:pcb +##for:transistor + + # 78 for SOT23 + # 82 for SOT23 + # 41 for SOT23 + # 34 for SOT23, 24 for SOT25 +Element(0x00 "SMT transistor, 3 pins" "" "SC90" 93 0 3 100 0x00) +( + ElementLine(0 0 0 98 10) + ElementLine(0 98 73 98 10) + ElementLine(73 98 73 0 10) + ElementLine(73 0 0 0 10) + # 1st side, 1st pin + Pad(17 76 + 17 80 + 24 + "1" "1" 0x100) + # 1st side, 2nd pin + # 1st side, 3rd pin + Pad(56 76 + 56 80 + 24 + "2" "2" 0x100) + # 2nd side, 3rd pin + # 2nd side, 2nd pin + Pad(36 17 + 36 21 + 24 + "3" "3" 0x100) + # 2nd side, 1st pin + Mark(17 78) +) Index: tags/2.1.2/pcblib/smd/SOD106A.fp =================================================================== --- tags/2.1.2/pcblib/smd/SOD106A.fp (nonexistent) +++ tags/2.1.2/pcblib/smd/SOD106A.fp (revision 24813) @@ -0,0 +1,20 @@ +##from:pcb +##for:diode + + # how much to grow the pads by for soldermask + # clearance from planes +Element(0x00 "SMT diode (pin 1 is cathode)" "" "SOD106A" 0 0 166 0 3 100 0x00) +( + ElementLine(-156 -68 -156 68 20) + ElementLine(-156 68 -105 87 10) + ElementLine(-105 87 146 87 10) + ElementLine(146 87 146 -87 10) + ElementLine(146 -87 -105 -87 10) + ElementLine(-105 -87 -156 -68 10) + Pad(-76 -17 + -76 17 + 102 20 108 "1" "1" 0x00000100) + Pad(76 -17 + 76 17 + 102 20 108 "2" "2" 0x00000100) +) Index: tags/2.1.2/pcblib/smd/SOD110.fp =================================================================== --- tags/2.1.2/pcblib/smd/SOD110.fp (nonexistent) +++ tags/2.1.2/pcblib/smd/SOD110.fp (revision 24813) @@ -0,0 +1,20 @@ +##from:pcb +##for:diode + + # how much to grow the pads by for soldermask + # clearance from planes +Element(0x00 "SMT diode (pin 1 is cathode)" "" "SOD110" 0 0 83 0 3 100 0x00) +( + ElementLine(-73 -38 -73 38 20) + ElementLine(-73 38 -50 49 10) + ElementLine(-50 49 63 49 10) + ElementLine(63 49 63 -49 10) + ElementLine(63 -49 -50 -49 10) + ElementLine(-50 -49 -73 -38 10) + Pad(-29 -15 + -29 15 + 46 20 52 "1" "1" 0x00000100) + Pad(29 -15 + 29 15 + 46 20 52 "2" "2" 0x00000100) +) Index: tags/2.1.2/pcblib/smd/SOD123.fp =================================================================== --- tags/2.1.2/pcblib/smd/SOD123.fp (nonexistent) +++ tags/2.1.2/pcblib/smd/SOD123.fp (revision 24813) @@ -0,0 +1,20 @@ +##from:pcb +##for:diode + + # how much to grow the pads by for soldermask + # clearance from planes +Element(0x00 "SMT diode (pin 1 is cathode)" "" "SOD123" 0 0 120 0 3 100 0x00) +( + ElementLine(-110 -40 -110 40 20) + ElementLine(-110 40 -76 51 10) + ElementLine(-76 51 100 51 10) + ElementLine(100 51 100 -51 10) + ElementLine(100 -51 -76 -51 10) + ElementLine(-76 -51 -110 -40 10) + Pad(-55 -6 + -55 6 + 69 20 75 "1" "1" 0x00000100) + Pad(55 -6 + 55 6 + 69 20 75 "2" "2" 0x00000100) +) Index: tags/2.1.2/pcblib/smd/SOD323.fp =================================================================== --- tags/2.1.2/pcblib/smd/SOD323.fp (nonexistent) +++ tags/2.1.2/pcblib/smd/SOD323.fp (revision 24813) @@ -0,0 +1,20 @@ +##from:pcb +##for:diode + + # how much to grow the pads by for soldermask + # clearance from planes +Element(0x00 "SMT diode (pin 1 is cathode)" "" "SOD323" 0 0 93 0 3 100 0x00) +( + ElementLine(-83 -35 -83 35 20) + ElementLine(-83 35 -58 45 10) + ElementLine(-58 45 73 45 10) + ElementLine(73 45 73 -45 10) + ElementLine(73 -45 -58 -45 10) + ElementLine(-58 -45 -83 -35 10) + Pad(-37 -10 + -37 10 + 51 20 57 "1" "1" 0x00000100) + Pad(37 -10 + 37 10 + 51 20 57 "2" "2" 0x00000100) +) Index: tags/2.1.2/pcblib/smd/SOD80.fp =================================================================== --- tags/2.1.2/pcblib/smd/SOD80.fp (nonexistent) +++ tags/2.1.2/pcblib/smd/SOD80.fp (revision 24813) @@ -0,0 +1,20 @@ +##from:pcb +##for:diode + + # how much to grow the pads by for soldermask + # clearance from planes +Element(0x00 "SMT diode (pin 1 is cathode)" "" "SOD80" 0 0 116 0 3 100 0x00) +( + ElementLine(-106 -43 -106 43 20) + ElementLine(-106 43 -80 55 10) + ElementLine(-80 55 96 55 10) + ElementLine(96 55 96 -55 10) + ElementLine(96 -55 -80 -55 10) + ElementLine(-80 -55 -106 -43 10) + Pad(-58 -16 + -58 16 + 53 20 59 "1" "1" 0x00000100) + Pad(58 -16 + 58 16 + 53 20 59 "2" "2" 0x00000100) +) Index: tags/2.1.2/pcblib/smd/SOD87.fp =================================================================== --- tags/2.1.2/pcblib/smd/SOD87.fp (nonexistent) +++ tags/2.1.2/pcblib/smd/SOD87.fp (revision 24813) @@ -0,0 +1,20 @@ +##from:pcb +##for:diode + + # how much to grow the pads by for soldermask + # clearance from planes +Element(0x00 "SMT diode (pin 1 is cathode)" "" "SOD87" 0 0 124 0 3 100 0x00) +( + ElementLine(-114 -57 -114 57 20) + ElementLine(-114 57 -84 73 10) + ElementLine(-84 73 104 73 10) + ElementLine(104 73 104 -73 10) + ElementLine(104 -73 -84 -73 10) + ElementLine(-84 -73 -114 -57 10) + Pad(-58 -26 + -58 26 + 61 20 67 "1" "1" 0x00000100) + Pad(58 -26 + 58 26 + 61 20 67 "2" "2" 0x00000100) +) Index: tags/2.1.2/pcblib/smd/SOT143.fp =================================================================== --- tags/2.1.2/pcblib/smd/SOT143.fp (nonexistent) +++ tags/2.1.2/pcblib/smd/SOT143.fp (revision 24813) @@ -0,0 +1,38 @@ +##from:pcb +##for:transistor + + # 78 for SOT23 + # 82 for SOT23 + # 41 for SOT23 + # 34 for SOT23, 24 for SOT25 +Element(0x00 "SMT transistor, 4 pins" "" "SOT143" 144 0 3 100 0x00) +( + ElementLine(0 0 0 139 10) + ElementLine(0 139 124 139 10) + ElementLine(124 139 124 0 10) + ElementLine(124 0 0 0 10) + # 1st side, 1st pin + # extra width + Pad(28 110 + 31 110 + 34 + "1" "1" 0x100) + # 1st side, 2nd pin + # 1st side, 3rd pin + Pad(99 107 + 99 113 + 34 + "2" "2" 0x100) + # 2nd side, 3rd pin + Pad(99 25 + 99 31 + 34 + "3" "3" 0x100) + # 2nd side, 2nd pin + # 2nd side, 1st pin + Pad(25 25 + 25 31 + 34 + "4" "4" 0x100) + Mark(25 110) +) Index: tags/2.1.2/pcblib/smd/SOT223.fp =================================================================== --- tags/2.1.2/pcblib/smd/SOT223.fp (nonexistent) +++ tags/2.1.2/pcblib/smd/SOT223.fp (revision 24813) @@ -0,0 +1,29 @@ +##from:pcb +##for:transistor + +Element(0x00 "SMT transistor, 4 pins" "" "SOT223" 305 0 3 100 0x00) +( + ElementLine(0 0 0 414 10) + ElementLine(0 414 285 414 10) + ElementLine(285 414 285 0 10) + ElementLine(285 0 0 0 10) + # 1st pin on pin side + Pad(52 296 + 52 362 + 56 + "1" "1" 0x100) + Pad(142 296 + 142 362 + 56 + "2" "2" 0x100) + # last pin on pin side + Pad(233 296 + 233 362 + 56 + "3" "3" 0x100) + # extra wide pin on opposite side + Pad(187 85 + 97 85 + 122 "4" "4" 0x100) + Mark(52 329) +) Index: tags/2.1.2/pcblib/smd/SOT23.fp =================================================================== --- tags/2.1.2/pcblib/smd/SOT23.fp (nonexistent) +++ tags/2.1.2/pcblib/smd/SOT23.fp (revision 24813) @@ -0,0 +1,33 @@ +##from:pcb +##for:transistor + + # 78 for SOT23 + # 82 for SOT23 + # 41 for SOT23 + # 34 for SOT23, 24 for SOT25 +Element(0x00 "SMT transistor, 3 pins" "" "SOT23" 148 0 3 100 0x00) +( + ElementLine(0 0 0 139 10) + ElementLine(0 139 128 139 10) + ElementLine(128 139 128 0 10) + ElementLine(128 0 0 0 10) + # 1st side, 1st pin + Pad(25 107 + 25 113 + 34 + "1" "1" 0x100) + # 1st side, 2nd pin + # 1st side, 3rd pin + Pad(103 107 + 103 113 + 34 + "2" "2" 0x100) + # 2nd side, 3rd pin + # 2nd side, 2nd pin + Pad(64 25 + 64 31 + 34 + "3" "3" 0x100) + # 2nd side, 1st pin + Mark(25 110) +) Index: tags/2.1.2/pcblib/smd/SOT23D.fp =================================================================== --- tags/2.1.2/pcblib/smd/SOT23D.fp (nonexistent) +++ tags/2.1.2/pcblib/smd/SOT23D.fp (revision 24813) @@ -0,0 +1,33 @@ +##from:pcb +##for:transistor + + # 78 for SOT23 + # 82 for SOT23 + # 41 for SOT23 + # 34 for SOT23, 24 for SOT25 +Element(0x00 "SMT diode (pin 1 is cathode)" "" "SOT23D" 148 0 3 100 0x00) +( + ElementLine(0 0 0 139 10) + ElementLine(0 139 128 139 10) + ElementLine(128 139 128 0 10) + ElementLine(128 0 0 0 10) + # 1st side, 1st pin + Pad(25 107 + 25 113 + 34 + "2" "2" 0x100) + # 1st side, 2nd pin + # 1st side, 3rd pin + Pad(103 107 + 103 113 + 34 + "3" "3" 0x100) + # 2nd side, 3rd pin + # 2nd side, 2nd pin + Pad(64 25 + 64 31 + 34 + "1" "1" 0x100) + # 2nd side, 1st pin + Mark(25 110) +) Index: tags/2.1.2/pcblib/smd/SOT25.fp =================================================================== --- tags/2.1.2/pcblib/smd/SOT25.fp (nonexistent) +++ tags/2.1.2/pcblib/smd/SOT25.fp (revision 24813) @@ -0,0 +1,38 @@ +##from:pcb +##for:transistor +##for:stabilizer +##for:linear + + # 78 for SOT23 + # 82 for SOT23 + # 41 for SOT23 + # 34 for SOT23, 24 for SOT25 +Element(0x00 "SMT transistor, 5 pins" "" "SOT25" 138 0 3 100 0x00) +( + ElementLine(0 0 0 139 10) + ElementLine(0 139 118 139 10) + ElementLine(118 139 118 0 10) + ElementLine(118 0 0 0 10) + # 1st side, 1st pin + Pad(20 102 + 20 118 + 24 "1" "1" 0x100) + # 1st side, 2nd pin + # 1st side, 3rd pin + Pad(98 102 + 98 118 + 24 "2" "2" 0x100) + # 2nd side, 3rd pin + Pad(98 20 + 98 36 + 24 "3" "3" 0x100) + # 2nd side, 2nd pin + Pad(59 20 + 59 36 + 24 "4" "4" 0x100) + # 2nd side, 1st pin + Pad(20 20 + 20 36 + 24 "5" "5" 0x100) + Mark(20 110) +) Index: tags/2.1.2/pcblib/smd/SOT26.fp =================================================================== --- tags/2.1.2/pcblib/smd/SOT26.fp (nonexistent) +++ tags/2.1.2/pcblib/smd/SOT26.fp (revision 24813) @@ -0,0 +1,41 @@ +##from:pcb +##for:transistor +##for:stabilizer +##for:linear + + # 78 for SOT23 + # 82 for SOT23 + # 41 for SOT23 + # 34 for SOT23, 24 for SOT25 +Element(0x00 "SMT transistor, 6 pins" "" "SOT26" 138 0 3 100 0x00) +( + ElementLine(0 0 0 139 10) + ElementLine(0 139 118 139 10) + ElementLine(118 139 118 0 10) + ElementLine(118 0 0 0 10) + # 1st side, 1st pin + Pad(20 102 + 20 118 + 24 "1" "1" 0x100) + # 1st side, 2nd pin + Pad(59 102 + 59 118 + 24 "2" "2" 0x100) + # 1st side, 3rd pin + Pad(98 102 + 98 118 + 24 "3" "3" 0x100) + # 2nd side, 3rd pin + Pad(98 20 + 98 36 + 24 "4" "4" 0x100) + # 2nd side, 2nd pin + Pad(59 20 + 59 36 + 24 "5" "5" 0x100) + # 2nd side, 1st pin + Pad(20 20 + 20 36 + 24 "6" "6" 0x100) + Mark(20 110) +) Index: tags/2.1.2/pcblib/smd/SOT323.fp =================================================================== --- tags/2.1.2/pcblib/smd/SOT323.fp (nonexistent) +++ tags/2.1.2/pcblib/smd/SOT323.fp (revision 24813) @@ -0,0 +1,33 @@ +##from:pcb +##for:transistor + + # 78 for SOT23 + # 82 for SOT23 + # 41 for SOT23 + # 34 for SOT23, 24 for SOT25 +Element(0x00 "SMT transistor, 3 pins" "" "SOT323" 114 0 3 100 0x00) +( + ElementLine(0 0 0 119 10) + ElementLine(0 119 94 119 10) + ElementLine(94 119 94 0 10) + ElementLine(94 0 0 0 10) + # 1st side, 1st pin + Pad(21 91 + 21 97 + 29 + "1" "1" 0x100) + # 1st side, 2nd pin + # 1st side, 3rd pin + Pad(72 91 + 72 97 + 29 + "2" "2" 0x100) + # 2nd side, 3rd pin + # 2nd side, 2nd pin + Pad(47 21 + 47 27 + 29 + "3" "3" 0x100) + # 2nd side, 1st pin + Mark(21 94) +) Index: tags/2.1.2/pcblib/smd/SOT323D.fp =================================================================== --- tags/2.1.2/pcblib/smd/SOT323D.fp (nonexistent) +++ tags/2.1.2/pcblib/smd/SOT323D.fp (revision 24813) @@ -0,0 +1,33 @@ +##from:pcb +##for:transistor + + # 78 for SOT23 + # 82 for SOT23 + # 41 for SOT23 + # 34 for SOT23, 24 for SOT25 +Element(0x00 "SMT diode (pin 1 is cathode)" "" "SOT323D" 114 0 3 100 0x00) +( + ElementLine(0 0 0 119 10) + ElementLine(0 119 94 119 10) + ElementLine(94 119 94 0 10) + ElementLine(94 0 0 0 10) + # 1st side, 1st pin + Pad(21 91 + 21 97 + 29 + "2" "2" 0x100) + # 1st side, 2nd pin + # 1st side, 3rd pin + Pad(72 91 + 72 97 + 29 + "3" "3" 0x100) + # 2nd side, 3rd pin + # 2nd side, 2nd pin + Pad(47 21 + 47 27 + 29 + "1" "1" 0x100) + # 2nd side, 1st pin + Mark(21 94) +) Index: tags/2.1.2/pcblib/smd/SOT325.fp =================================================================== --- tags/2.1.2/pcblib/smd/SOT325.fp (nonexistent) +++ tags/2.1.2/pcblib/smd/SOT325.fp (revision 24813) @@ -0,0 +1,40 @@ +##from:pcb +##for:transistor +##for:stabilizer +##for:linear + + + # 78 for SOT23 + # 82 for SOT23 + # 41 for SOT23 + # 34 for SOT23, 24 for SOT25 +# alias sc70-5 +Element(0x00 "SMT transistor, 5 pins" "" "SOT325" 100 0 3 100 0x00) +( + ElementLine(0 0 0 119 10) + ElementLine(0 119 80 119 10) + ElementLine(80 119 80 0 10) + ElementLine(80 0 0 0 10) + # 1st side, 1st pin + Pad(14 84 + 14 104 + 15 "1" "1" 0x100) + # 1st side, 2nd pin + # 1st side, 3rd pin + Pad(65 84 + 65 104 + 15 "2" "2" 0x100) + # 2nd side, 3rd pin + Pad(65 14 + 65 34 + 15 "3" "3" 0x100) + # 2nd side, 2nd pin + Pad(40 14 + 40 34 + 15 "4" "4" 0x100) + # 2nd side, 1st pin + Pad(14 14 + 14 34 + 15 "5" "5" 0x100) + Mark(14 94) +) Index: tags/2.1.2/pcblib/smd/SOT326.fp =================================================================== --- tags/2.1.2/pcblib/smd/SOT326.fp (nonexistent) +++ tags/2.1.2/pcblib/smd/SOT326.fp (revision 24813) @@ -0,0 +1,42 @@ +##from:pcb +##for:transistor +##for:stabilizer +##for:linear + + # 78 for SOT23 + # 82 for SOT23 + # 41 for SOT23 + # 34 for SOT23, 24 for SOT25 +# alias sc70-6 +Element(0x00 "SMT transistor, 6 pins" "" "SOT326" 100 0 3 100 0x00) +( + ElementLine(0 0 0 119 10) + ElementLine(0 119 80 119 10) + ElementLine(80 119 80 0 10) + ElementLine(80 0 0 0 10) + # 1st side, 1st pin + Pad(14 84 + 14 104 + 15 "1" "1" 0x100) + # 1st side, 2nd pin + Pad(40 84 + 40 104 + 15 "2" "2" 0x100) + # 1st side, 3rd pin + Pad(65 84 + 65 104 + 15 "3" "3" 0x100) + # 2nd side, 3rd pin + Pad(65 14 + 65 34 + 15 "4" "4" 0x100) + # 2nd side, 2nd pin + Pad(40 14 + 40 34 + 15 "5" "5" 0x100) + # 2nd side, 1st pin + Pad(14 14 + 14 34 + 15 "6" "6" 0x100) + Mark(14 94) +) Index: tags/2.1.2/pcblib/smd/SOT89.fp =================================================================== --- tags/2.1.2/pcblib/smd/SOT89.fp (nonexistent) +++ tags/2.1.2/pcblib/smd/SOT89.fp (revision 24813) @@ -0,0 +1,31 @@ +##from:pcb +##for:transistor +##for:stabilizer +##for:linear + +Element(0x00 "SMT transistor, 4 pins" "" "SOT89" 203 0 3 100 0x00) +( + ElementLine(0 0 0 207 10) + ElementLine(0 207 183 207 10) + ElementLine(183 207 183 0 10) + ElementLine(183 0 0 0 10) + # 1st pin on pin side + Pad(30 152 + 30 176 + 37 + "1" "1" 0x100) + Pad(91 152 + 91 176 + 37 + "2" "2" 0x100) + # last pin on pin side + Pad(152 152 + 152 176 + 37 + "3" "3" 0x100) + # extra wide pin on opposite side + Pad(121 42 + 61 42 + 61 "4" "4" 0x100) + Mark(30 164) +) Index: tags/2.1.2/pcblib/smd/TANT_A.fp =================================================================== --- tags/2.1.2/pcblib/smd/TANT_A.fp (nonexistent) +++ tags/2.1.2/pcblib/smd/TANT_A.fp (revision 24813) @@ -0,0 +1,21 @@ +##from:pcb +##for:capacitor +##for:tantal + + # how much to grow the pads by for soldermask + # clearance from planes +Element(0x00 "Tantalum SMT capacitor (pin 1 is +)" "" "TANT_A" 0 0 106 0 3 100 0x00) +( + ElementLine(-96 -43 -96 43 20) + ElementLine(-96 43 -72 55 10) + ElementLine(-72 55 86 55 10) + ElementLine(86 55 86 -55 10) + ElementLine(86 -55 -72 -55 10) + ElementLine(-72 -55 -96 -43 10) + Pad(-50 -18 + -50 18 + 49 20 55 "1" "1" 0x00000100) + Pad(50 -18 + 50 18 + 49 20 55 "2" "2" 0x00000100) +) Index: tags/2.1.2/pcblib/smd/TANT_B.fp =================================================================== --- tags/2.1.2/pcblib/smd/TANT_B.fp (nonexistent) +++ tags/2.1.2/pcblib/smd/TANT_B.fp (revision 24813) @@ -0,0 +1,21 @@ +##from:pcb +##for:capacitor +##for:tantal + + # how much to grow the pads by for soldermask + # clearance from planes +Element(0x00 "Tantalum SMT capacitor (pin 1 is +)" "" "TANT_B" 0 0 132 0 3 100 0x00) +( + ElementLine(-122 -77 -122 77 20) + ElementLine(-122 77 -87 99 10) + ElementLine(-87 99 112 99 10) + ElementLine(112 99 112 -99 10) + ElementLine(112 -99 -87 -99 10) + ElementLine(-87 -99 -122 -77 10) + Pad(-55 -41 + -55 41 + 71 20 77 "1" "1" 0x00000100) + Pad(55 -41 + 55 41 + 71 20 77 "2" "2" 0x00000100) +) Index: tags/2.1.2/pcblib/smd/TANT_C.fp =================================================================== --- tags/2.1.2/pcblib/smd/TANT_C.fp (nonexistent) +++ tags/2.1.2/pcblib/smd/TANT_C.fp (revision 24813) @@ -0,0 +1,21 @@ +##from:pcb +##for:capacitor +##for:tantal + + # how much to grow the pads by for soldermask + # clearance from planes +Element(0x00 "Tantalum SMT capacitor (pin 1 is +)" "" "TANT_C" 0 0 188 0 3 100 0x00) +( + ElementLine(-178 -87 -178 87 20) + ElementLine(-178 87 -130 112 10) + ElementLine(-130 112 168 112 10) + ElementLine(168 112 168 -112 10) + ElementLine(168 -112 -130 -112 10) + ElementLine(-130 -112 -178 -87 10) + Pad(-94 -39 + -94 39 + 97 20 103 "1" "1" 0x00000100) + Pad(94 -39 + 94 39 + 97 20 103 "2" "2" 0x00000100) +) Index: tags/2.1.2/pcblib/smd/TANT_D.fp =================================================================== --- tags/2.1.2/pcblib/smd/TANT_D.fp (nonexistent) +++ tags/2.1.2/pcblib/smd/TANT_D.fp (revision 24813) @@ -0,0 +1,21 @@ +##from:pcb +##for:capacitor +##for:tantal + + # how much to grow the pads by for soldermask + # clearance from planes +Element(0x00 "Tantalum SMT capacitor (pin 1 is +)" "" "TANT_D" 0 0 229 0 3 100 0x00) +( + ElementLine(-219 -117 -219 117 20) + ElementLine(-219 117 -158 150 10) + ElementLine(-158 150 209 150 10) + ElementLine(209 150 209 -150 10) + ElementLine(209 -150 -158 -150 10) + ElementLine(-158 -150 -219 -117 10) + Pad(-115 -56 + -115 56 + 123 20 129 "1" "1" 0x00000100) + Pad(115 -56 + 115 56 + 123 20 129 "2" "2" 0x00000100) +) Index: tags/2.1.2/pcblib/smd/minimelf.fp =================================================================== --- tags/2.1.2/pcblib/smd/minimelf.fp (nonexistent) +++ tags/2.1.2/pcblib/smd/minimelf.fp (revision 24813) @@ -0,0 +1,12 @@ +##from:repo.hu/projects/openhw +##for:diode + + +Element["" "" "D101" "" 145669 141732 -3720 -2087 0 70 ""] +( + Pad[7087 -984 7087 984 5118 5000 7618 "" "1" "square"] + Pad[-7087 -984 -7087 984 5118 5000 7618 "" "2" "square"] + ElementLine [-3937 -3150 3937 -3150 787] + ElementLine [-3937 3150 3937 3150 787] + + ) Index: tags/2.1.2/pcblib/smd/sot23.scad =================================================================== --- tags/2.1.2/pcblib/smd/sot23.scad (nonexistent) +++ tags/2.1.2/pcblib/smd/sot23.scad (revision 24813) @@ -0,0 +1,36 @@ + +module sot23() +{ + + // pin prototype + module pin(length, height, thick) + { + linear_extrude(height=thick) + scale([length, -height, 1]) + polygon([[0.3400,0.0000],[0.3900,0.0100],[0.4300,0.0300],[0.4600,0.0600],[0.4789,0.0908],[0.6279,0.8307],[0.6500,0.8600],[0.6900,0.8900],[0.7300,0.9000],[1.0000,0.9000],[1.0000,1.0000],[0.6700,1.0012],[0.6100,0.9900],[0.5600,0.9600],[0.5300,0.9200],[0.5200,0.9000],[0.3721,0.1693],[0.3500,0.1400],[0.3100,0.1100],[0.2700,0.1000],[0.0000,0.1000],[0.0000,0.0000]]); + } + + rotate([90,0,-90]) scale([1.13,1.13,1.13]) translate([-0.9, 0.4, -2.1 - 0.43/2]) { + // body + color([0.1,0.1,0.1]) + linear_extrude(height=2.9) + polygon([[-0.55,0],[-0.45,0.53],[0.45,0.53],[0.55,0],[0.45,-0.35],[-0.45,-0.35]]); + + // 3 pins + color([0.9, 0.9, 0.9]) { + translate([0.5,0,0.5-0.43/2]) + pin(0.5, 0.4, 0.43); + + translate([0.5,0,2.3-0.43/2]) + pin(0.5, 0.4, 0.43); + + translate([-0.5,0,1.45-0.43/2]) + pin(-0.5, 0.4, 0.43); + } + } +} + + +sot23(); + +cube([0.1,0.1,0.1]); Index: tags/2.1.2/pcblib/tru-hole/HC49.fp =================================================================== --- tags/2.1.2/pcblib/tru-hole/HC49.fp (nonexistent) +++ tags/2.1.2/pcblib/tru-hole/HC49.fp (revision 24813) @@ -0,0 +1,13 @@ +##from:pcb +##for:crystal +##for:xtal +Element(0x00 "Crystals" "" "HC49" 0 -60 0 100 0x00) +( + Pin(50 50 60 28 "1" 0x101) + Pin(250 50 60 28 "2" 0x01) + ElementLine(50 0 250 0 20) + ElementArc(250 50 50 50 90 180 20) + ElementLine(250 100 50 100 20) + ElementArc(50 50 50 50 270 180 20) + Mark(50 50) +) Index: tags/2.1.2/pcblib/tru-hole/HC49U.fp =================================================================== --- tags/2.1.2/pcblib/tru-hole/HC49U.fp (nonexistent) +++ tags/2.1.2/pcblib/tru-hole/HC49U.fp (revision 24813) @@ -0,0 +1,13 @@ +##from:pcb +##for:crystal +##for:xtal +Element(0x00 "Crystals" "" "HC49U" 0 -60 0 100 0x00) +( + Pin(121 91 60 32 "1" 0x101) + Pin(313 91 60 32 "2" 0x01) + ElementLine(91 0 344 0 20) + ElementArc(344 91 91 91 90 180 20) + ElementLine(344 183 91 183 20) + ElementArc(91 91 91 91 270 180 20) + Mark(121 91) +) Index: tags/2.1.2/pcblib/tru-hole/HC49UH.fp =================================================================== --- tags/2.1.2/pcblib/tru-hole/HC49UH.fp (nonexistent) +++ tags/2.1.2/pcblib/tru-hole/HC49UH.fp (revision 24813) @@ -0,0 +1,13 @@ +##from:pcb +##for:crystal +##for:xtal +Element(0x00 "Crystals" "" "HC49UH" 0 -60 0 100 0x00) +( + Pin(121 615 60 32 "1" 0x101) + Pin(313 615 60 32 "2" 0x01) + ElementLine(0 0 435 0 20) + ElementLine(435 0 435 515 20) + ElementLine(435 515 0 515 20) + ElementLine(0 515 0 0 20) + Mark(121 615) +) Index: tags/2.1.2/pcblib/tru-hole/HC49U_3.fp =================================================================== --- tags/2.1.2/pcblib/tru-hole/HC49U_3.fp (nonexistent) +++ tags/2.1.2/pcblib/tru-hole/HC49U_3.fp (revision 24813) @@ -0,0 +1,14 @@ +##from:pcb +##for:crystal +##for:xtal +Element(0x00 "Crystals" "" "HC49U_3" 0 -60 0 100 0x00) +( + Pin(121 91 60 32 "1" 0x101) + Pin(217 91 60 32 "2" 0x01) + Pin(313 91 60 32 "3" 0x01) + ElementLine(91 0 344 0 20) + ElementArc(344 91 91 91 90 180 20) + ElementLine(344 183 91 183 20) + ElementArc(91 91 91 91 270 180 20) + Mark(121 91) +) Index: tags/2.1.2/pcblib/tru-hole/HC49U_3H.fp =================================================================== --- tags/2.1.2/pcblib/tru-hole/HC49U_3H.fp (nonexistent) +++ tags/2.1.2/pcblib/tru-hole/HC49U_3H.fp (revision 24813) @@ -0,0 +1,14 @@ +##from:pcb +##for:crystal +##for:xtal +Element(0x00 "Crystals" "" "HC49U_3H" 0 -60 0 100 0x00) +( + Pin(121 615 60 32 "1" 0x101) + Pin(217 615 60 32 "2" 0x01) + Pin(313 615 60 32 "3" 0x01) + ElementLine(0 0 435 0 20) + ElementLine(435 0 435 515 20) + ElementLine(435 515 0 515 20) + ElementLine(0 515 0 0 20) + Mark(121 615) +) Index: tags/2.1.2/pcblib/tru-hole/HC51U.fp =================================================================== --- tags/2.1.2/pcblib/tru-hole/HC51U.fp (nonexistent) +++ tags/2.1.2/pcblib/tru-hole/HC51U.fp (revision 24813) @@ -0,0 +1,13 @@ +##from:pcb +##for:crystal +##for:xtal +Element(0x00 "Crystals" "" "HC51U" 0 -60 0 100 0x00) +( + Pin(136 176 80 40 "1" 0x101) + Pin(621 176 80 40 "2" 0x01) + ElementLine(176 0 581 0 20) + ElementArc(581 176 176 176 90 180 20) + ElementLine(581 352 176 352 20) + ElementArc(176 176 176 176 270 180 20) + Mark(136 176) +) Index: tags/2.1.2/pcblib/tru-hole/HC51UH.fp =================================================================== --- tags/2.1.2/pcblib/tru-hole/HC51UH.fp (nonexistent) +++ tags/2.1.2/pcblib/tru-hole/HC51UH.fp (revision 24813) @@ -0,0 +1,13 @@ +##from:pcb +##for:crystal +##for:xtal +Element(0x00 "Crystals" "" "HC51UH" 0 -60 0 100 0x00) +( + Pin(136 975 80 40 "1" 0x101) + Pin(621 975 80 40 "2" 0x01) + ElementLine(0 0 757 0 20) + ElementLine(757 0 757 775 20) + ElementLine(757 775 0 775 20) + ElementLine(0 775 0 0 20) + Mark(136 975) +) Index: tags/2.1.2/pcblib/tru-hole/HEPTAWATT.fp =================================================================== --- tags/2.1.2/pcblib/tru-hole/HEPTAWATT.fp (nonexistent) +++ tags/2.1.2/pcblib/tru-hole/HEPTAWATT.fp (revision 24813) @@ -0,0 +1,20 @@ +##from:pcb +##for:IC +Element(0x00 "Power IC, as in MULTIWATT15" "" "HEPTAWATT" 469 50 3 100 0x00) +( + Pin(54 310 90 60 "1" 0x101) + Pin(104 110 90 60 "2" 0x01) + Pin(154 310 90 60 "3" 0x01) + Pin(204 110 90 60 "4" 0x01) + Pin(254 310 90 60 "5" 0x01) + Pin(304 110 90 60 "6" 0x01) + Pin(354 310 90 60 "7" 0x01) + ElementLine(0 0 0 189 20) + ElementLine(0 189 409 189 20) + ElementLine(409 189 409 0 20) + ElementLine(409 0 0 0 20) + ElementLine(0 50 409 50 10) + ElementLine(129 0 129 50 10) + ElementLine(279 0 279 50 10) + Mark(54 249) + ) Index: tags/2.1.2/pcblib/tru-hole/LED3.fp =================================================================== --- tags/2.1.2/pcblib/tru-hole/LED3.fp (nonexistent) +++ tags/2.1.2/pcblib/tru-hole/LED3.fp (revision 24813) @@ -0,0 +1,19 @@ +##from:pcb +##for:crystal +##for:led +##ref:http://www.lumex.com +Element(0x00 "LED, size in mm (pin 1 is +, 2 is -)" "" "LED3" 100 70 0 100 0x00) +( +# typical LED is 0.5 mm or 0.020" square pin. See for example +# http://www.lumex.com and part number SSL-LX3054LGD. +# 0.020" square is 0.0288" diagonal. A number 57 drill is +# 0.043" which should be enough. a 65 mil pad gives 11 mils +# of annular ring. + Pin(-50 0 65 43 "1" 0x101) + Pin(50 0 65 43 "2" 0x01) + ElementArc(0 0 59 59 45 90 10) + ElementArc(0 0 59 59 225 90 10) + ElementArc(0 0 79 79 45 90 10) + ElementArc(0 0 79 79 225 90 10) + Mark(0 0) +) Index: tags/2.1.2/pcblib/tru-hole/LED5.fp =================================================================== --- tags/2.1.2/pcblib/tru-hole/LED5.fp (nonexistent) +++ tags/2.1.2/pcblib/tru-hole/LED5.fp (revision 24813) @@ -0,0 +1,16 @@ +##from:pcb +##for:led +##ref:http://www.lumex.com +Element(0x00 "LED, size in mm (pin 1 is +, 2 is -)" "" "LED5" 100 70 0 100 0x00) +( +# typical LED is 0.5 mm or 0.020" square pin. See for example +# http://www.lumex.com and part number SSL-LX3054LGD. +# 0.020" square is 0.0288" diagonal. A number 57 drill is +# 0.043" which should be enough. a 65 mil pad gives 11 mils +# of annular ring. + Pin(-50 0 65 43 "1" 0x101) + Pin(50 0 65 43 "2" 0x01) + ElementArc(0 0 118 118 0 360 10) + ElementArc(0 0 138 138 0 360 10) + Mark(0 0) +) Index: tags/2.1.2/pcblib/tru-hole/MULTIWATT11.fp =================================================================== --- tags/2.1.2/pcblib/tru-hole/MULTIWATT11.fp (nonexistent) +++ tags/2.1.2/pcblib/tru-hole/MULTIWATT11.fp (revision 24813) @@ -0,0 +1,24 @@ +##from:pcb +##for:IC +Element(0x00 "Power IC, as in MULTIWATT15" "" "MULTIWATT11" 860 50 3 100 0x00) +( + Pin(65 380 90 60 "1" 0x101) + Pin(132 180 90 60 "2" 0x01) + Pin(199 380 90 60 "3" 0x01) + Pin(266 180 90 60 "4" 0x01) + Pin(333 380 90 60 "5" 0x01) + Pin(400 180 90 60 "6" 0x01) + Pin(467 380 90 60 "7" 0x01) + Pin(534 180 90 60 "8" 0x01) + Pin(601 380 90 60 "9" 0x01) + Pin(668 180 90 60 "10" 0x01) + Pin(735 380 90 60 "11" 0x01) + ElementLine(0 0 0 200 20) + ElementLine(0 200 800 200 20) + ElementLine(800 200 800 0 20) + ElementLine(800 0 0 0 20) + ElementLine(0 50 800 50 10) + ElementLine(325 0 325 50 10) + ElementLine(475 0 475 50 10) + Mark(65 260) + ) Index: tags/2.1.2/pcblib/tru-hole/MULTIWATT15.fp =================================================================== --- tags/2.1.2/pcblib/tru-hole/MULTIWATT15.fp (nonexistent) +++ tags/2.1.2/pcblib/tru-hole/MULTIWATT15.fp (revision 24813) @@ -0,0 +1,28 @@ +##from:pcb +##for:IC +Element(0x00 "Power IC, as in MULTIWATT15" "" "MULTIWATT15" 860 50 3 100 0x00) +( + Pin(50 380 90 60 "1" 0x101) + Pin(100 180 90 60 "2" 0x01) + Pin(150 380 90 60 "3" 0x01) + Pin(200 180 90 60 "4" 0x01) + Pin(250 380 90 60 "5" 0x01) + Pin(300 180 90 60 "6" 0x01) + Pin(350 380 90 60 "7" 0x01) + Pin(400 180 90 60 "8" 0x01) + Pin(450 380 90 60 "9" 0x01) + Pin(500 180 90 60 "10" 0x01) + Pin(550 380 90 60 "11" 0x01) + Pin(600 180 90 60 "12" 0x01) + Pin(650 380 90 60 "13" 0x01) + Pin(700 180 90 60 "14" 0x01) + Pin(750 380 90 60 "15" 0x01) + ElementLine(0 0 0 200 20) + ElementLine(0 200 800 200 20) + ElementLine(800 200 800 0 20) + ElementLine(800 0 0 0 20) + ElementLine(0 50 800 50 10) + ElementLine(325 0 325 50 10) + ElementLine(475 0 475 50 10) + Mark(50 260) + ) Index: tags/2.1.2/pcblib/tru-hole/MULTIWATT8.fp =================================================================== --- tags/2.1.2/pcblib/tru-hole/MULTIWATT8.fp (nonexistent) +++ tags/2.1.2/pcblib/tru-hole/MULTIWATT8.fp (revision 24813) @@ -0,0 +1,21 @@ +##from:pcb +##for:IC +Element(0x00 "Power IC, as in MULTIWATT15" "" "MULTIWATT8" 860 50 3 100 0x00) +( + Pin(50 115 90 60 "1" 0x101) + Pin(150 115 90 60 "2" 0x01) + Pin(250 115 90 60 "3" 0x01) + Pin(350 115 90 60 "4" 0x01) + Pin(450 115 90 60 "5" 0x01) + Pin(550 115 90 60 "6" 0x01) + Pin(650 115 90 60 "7" 0x01) + Pin(750 115 90 60 "8" 0x01) + ElementLine(0 0 0 200 20) + ElementLine(0 200 800 200 20) + ElementLine(800 200 800 0 20) + ElementLine(800 0 0 0 20) + ElementLine(0 50 800 50 10) + ElementLine(325 0 325 50 10) + ElementLine(475 0 475 50 10) + Mark(50 260) + ) Index: tags/2.1.2/pcblib/tru-hole/OSC14.fp =================================================================== --- tags/2.1.2/pcblib/tru-hole/OSC14.fp (nonexistent) +++ tags/2.1.2/pcblib/tru-hole/OSC14.fp (revision 24813) @@ -0,0 +1,26 @@ +##from:pcb +##for:oscillator +##for:xtal + Element(0x00 "Crystal oscillator" "" "OSC14" 270 300 3 100 0x00) +( + Pin(100 100 50 28 "NC" 0x01) + Pin(100 700 50 28 "GND" 0x01) + Pin(400 700 50 28 "CLK" 0x01) + Pin(400 100 50 28 "VCC" 0x01) + ElementLine(5 5 400 5 10) + ElementArc(400 100 95 95 180 90 10) + ElementLine(495 100 495 700 10) + ElementArc(400 700 95 95 90 90 10) + ElementLine(400 795 100 795 10) + ElementArc(100 700 95 95 0 90 10) + ElementLine(5 700 5 5 10) + ElementLine(100 60 400 60 10) + ElementArc(400 100 40 40 180 90 10) + ElementLine(440 100 440 700 10) + ElementArc(400 700 40 40 90 90 10) + ElementLine(400 740 100 740 10) + ElementArc(100 700 40 40 0 90 10) + ElementLine(60 700 60 100 10) + ElementArc(100 100 40 40 270 90 10) + Mark(100 100) +) Index: tags/2.1.2/pcblib/tru-hole/PENTAWATT.fp =================================================================== --- tags/2.1.2/pcblib/tru-hole/PENTAWATT.fp (nonexistent) +++ tags/2.1.2/pcblib/tru-hole/PENTAWATT.fp (revision 24813) @@ -0,0 +1,18 @@ +##from:pcb +##for:IC +Element(0x00 "Power IC, as in MULTIWATT15" "" "PENTAWATT" 469 50 3 100 0x00) +( + Pin(70 334 90 60 "1" 0x101) + Pin(137 177 90 60 "2" 0x01) + Pin(204 334 90 60 "3" 0x01) + Pin(271 177 90 60 "4" 0x01) + Pin(338 334 90 60 "5" 0x01) + ElementLine(0 0 0 189 20) + ElementLine(0 189 409 189 20) + ElementLine(409 189 409 0 20) + ElementLine(409 0 0 0 20) + ElementLine(0 50 409 50 10) + ElementLine(129 0 129 50 10) + ElementLine(279 0 279 50 10) + Mark(70 249) + ) Index: tags/2.1.2/pcblib/tru-hole/TACT_6x6_4p =================================================================== --- tags/2.1.2/pcblib/tru-hole/TACT_6x6_4p (nonexistent) +++ tags/2.1.2/pcblib/tru-hole/TACT_6x6_4p (revision 24813) @@ -0,0 +1,37 @@ +##from:repo.hu/projects/openhw +##geo:180 +##for:switch +##for:button + +Element["" "" "" "" 175500 115500 0 0 0 100 ""] +( + Pin[13091 9000 9000 5000 9600 3937 "" "4" "edge2,intconn(2)"] + Pin[-12500 9000 9000 5000 9600 3937 "" "3" "edge2,intconn(2)"] + Pin[13091 -9000 9000 5000 9600 3937 "" "2" "edge2,intconn(1)"] + Pin[-12500 -9000 9000 5000 9600 3937 "" "1" "edge2,intconn(1)"] + ElementLine [12181 11736 12181 -11886 787] + ElementLine [-11441 11736 12181 11736 787] + ElementLine [-11441 -11886 -11441 11736 787] + ElementLine [-11441 -11886 12181 -11886 787] + ElementArc [7815 -8031 2756 2756 90 90 787] + ElementArc [7815 -8031 2756 2756 0 90 787] + ElementArc [7815 -8031 2756 2756 270 90 787] + ElementArc [7815 -8031 2756 2756 180 90 787] + ElementArc [7815 7717 2756 2756 0 90 787] + ElementArc [7815 7717 2756 2756 270 90 787] + ElementArc [7815 7717 2756 2756 180 90 787] + ElementArc [7815 7717 2756 2756 90 90 787] + ElementArc [-7933 7717 2756 2756 270 90 787] + ElementArc [-7933 7717 2756 2756 180 90 787] + ElementArc [-7933 7717 2756 2756 90 90 787] + ElementArc [-7933 7717 2756 2756 0 90 787] + ElementArc [-7933 -8031 2756 2756 180 90 787] + ElementArc [-7933 -8031 2756 2756 90 90 787] + ElementArc [-7933 -8031 2756 2756 0 90 787] + ElementArc [-7933 -8031 2756 2756 270 90 787] + ElementArc [-59 -157 6693 6693 270 90 787] + ElementArc [-59 -157 6693 6693 180 90 787] + ElementArc [-59 -157 6693 6693 90 90 787] + ElementArc [-59 -157 6693 6693 0 90 787] + + ) Index: tags/2.1.2/pcblib/tru-hole/TO126.fp =================================================================== --- tags/2.1.2/pcblib/tru-hole/TO126.fp (nonexistent) +++ tags/2.1.2/pcblib/tru-hole/TO126.fp (revision 24813) @@ -0,0 +1,35 @@ +##from:pcb +##for:transistor +##for:linear +##for:stabilizer +##geo:laying + Element(0x00 "Transistor" "" "TO126" 80 480 1 100 0x00) +( +# From the JEDEC drawing, the pins are rectangular with dimensions +# 25-35 mil X 15-25 mil +# +# This gives a diagonal dimension of 29.2 to 43.0 mils. +# Pin pitch is 80 to 100 mils. +# +# For a minimum clearance of 10 mils (probably not unreasonable if +# you are doing a design with leaded parts, this gives a max pad size +# of 80 mils. A 52 mil drill will give 14 mil annular ring which should +# be plenty. +# +# The mounting hole is 100 to 130 mils diameter + Pin(110 600 80 52 "1" 0x101) + Pin(200 600 80 52 "2" 0x01) + Pin(290 600 80 52 "3" 0x01) + # Befestigungsbohrung + Pin(200 170 130 110 "4" 0x01) + # Anschlussdraehte + ElementLine(100 600 100 500 30) + ElementLine(200 600 200 500 30) + ElementLine(300 600 300 500 30) + # Gehaeuse + ElementLine( 50 500 350 500 20) + ElementLine(350 500 350 70 20) + ElementLine(350 70 50 70 20) + ElementLine( 50 70 50 500 20) + Mark(100 600) +) Index: tags/2.1.2/pcblib/tru-hole/TO126S.fp =================================================================== --- tags/2.1.2/pcblib/tru-hole/TO126S.fp (nonexistent) +++ tags/2.1.2/pcblib/tru-hole/TO126S.fp (revision 24813) @@ -0,0 +1,23 @@ +##from:pcb +##for:transistor +##for:linear +##for:stabilizer +##geo:standing + Element(0x00 "Transistor" "" "TO126S" 80 480 1 100 0x00) +( + Pin(110 600 80 52 "1" 0x101) + Pin(200 700 80 52 "2" 0x01) + Pin(290 600 80 52 "3" 0x01) + # Befestigungsbohrung + Pin(200 170 130 110 "4" 0x01) + # Anschlussdraehte + ElementLine(100 600 100 500 30) + ElementLine(200 700 200 500 30) + ElementLine(300 600 300 500 30) + # Gehaeuse + ElementLine( 50 500 350 500 20) + ElementLine(350 500 350 70 20) + ElementLine(350 70 50 70 20) + ElementLine( 50 70 50 500 20) + Mark(100 600) +) Index: tags/2.1.2/pcblib/tru-hole/TO126SW.fp =================================================================== --- tags/2.1.2/pcblib/tru-hole/TO126SW.fp (nonexistent) +++ tags/2.1.2/pcblib/tru-hole/TO126SW.fp (revision 24813) @@ -0,0 +1,21 @@ +##from:pcb +##for:transistor +##for:linear +##for:stabilizer +##geo:standing + Element(0x00 "Transistor" "" "TO126SW" 270 170 0 100 0x00) +( + Pin(110 100 80 52 "1" 0x101) + Pin(200 200 80 52 "2" 0x01) + Pin(290 100 80 52 "3" 0x01) + # Gehaeuse + ElementLine(200 200 200 150 30) + ElementLine( 50 50 350 50 20) + ElementLine(350 50 350 150 20) + ElementLine(350 150 50 150 20) + ElementLine( 50 150 50 50 20) + # Bohrung + ElementLine(150 50 150 150 10) + ElementLine(250 50 250 150 10) + Mark(100 100) +) Index: tags/2.1.2/pcblib/tru-hole/TO126W.fp =================================================================== --- tags/2.1.2/pcblib/tru-hole/TO126W.fp (nonexistent) +++ tags/2.1.2/pcblib/tru-hole/TO126W.fp (revision 24813) @@ -0,0 +1,16 @@ +##from:pcb +##for:transistor +##for:linear +##for:stabilizer +##geo:standing + Element(0x00 "Transistor" "" "TO126W" 60 170 0 100 0x00) +( + Pin(110 100 80 52 "1" 0x101) + Pin(200 100 80 52 "2" 0x01) + Pin(290 100 80 52 "3" 0x01) + ElementLine(50 50 350 50 20) + ElementLine(350 50 350 150 20) + ElementLine(350 150 50 150 20) + ElementLine(50 150 50 50 20) + Mark(100 100) +) Index: tags/2.1.2/pcblib/tru-hole/TO18.fp =================================================================== --- tags/2.1.2/pcblib/tru-hole/TO18.fp (nonexistent) +++ tags/2.1.2/pcblib/tru-hole/TO18.fp (revision 24813) @@ -0,0 +1,36 @@ +##from:pcb +##for:transistor +##for:linear +##for:stabilizer + Element["" "Transistor" "" "TO18" 10300 11100 6000 7000 0 100 ""] +( +# The JEDEC drawing shows a pin diameter of 16-21 mils +# +# +# ___x_ +# / \ +# TO18: |3 1| <-- bottom view (supposed to be a circle) +# \ 2 / +# --- +# +# NOTE: some vendors, ST for example, number the pins +# differently. Here we follow the JEDEC drawing. +# +# the pins are arranged along a 100 mil diameter +# circle. The can outline is 178 to 195 mils +# for the top of the can and 209 to 230 mils +# for the bottom edge of the can +# + Pin[0 -5000 5500 3000 6100 3500 "1" "1" ""] + Pin[-5000 0 5500 3000 6100 3500 "2" "2" ""] + Pin[0 5000 5500 3000 6100 3500 "3" "3" ""] +# x, y, width, height, start angle, delta angle, thickness + ElementArc [0 0 9800 9800 0 360 1000] +# tab is 28 to 48 mils long, 36 to 46 wide +# and comes off at an angle of 45 deg clockwise from +# pin 1 when looking at the top of the board + ElementLine [6700 -7900 9400 -10600 1000] + ElementLine [7300 -7300 10000 -10000 1000] + ElementLine [7900 -6700 10600 -9400 1000] + ElementLine [9400 -10600 10600 -9400 1000] +) Index: tags/2.1.2/pcblib/tru-hole/TO218.fp =================================================================== --- tags/2.1.2/pcblib/tru-hole/TO218.fp (nonexistent) +++ tags/2.1.2/pcblib/tru-hole/TO218.fp (revision 24813) @@ -0,0 +1,17 @@ +##from:pcb +##for:diode +##geo:standing +Element(0x00 "diode in TO220" "" "TO218" 675 50 3 100 0x00) +( + Pin(88 120 100 60 "1" 0x101) + Pin(307 120 100 60 "2" 0x01) + Pin(526 120 100 60 "3" 0x01) + ElementLine(0 0 0 200 20) + ElementLine(0 200 615 200 20) + ElementLine(615 200 615 0 20) + ElementLine(615 0 0 0 20) + ElementLine(0 50 615 50 10) + ElementLine(232 0 232 50 10) + ElementLine(382 0 382 50 10) + Mark(88 260) + ) Index: tags/2.1.2/pcblib/tru-hole/TO220.fp =================================================================== --- tags/2.1.2/pcblib/tru-hole/TO220.fp (nonexistent) +++ tags/2.1.2/pcblib/tru-hole/TO220.fp (revision 24813) @@ -0,0 +1,47 @@ +##from:pcb +##for:transistor +##for:linear +##for:stabilizer +##geo:laying +##ref:http://www.zetex.com/3.0/pdf/TO220.pdf + Element(0x00 "Transistor" "" "TO220" 50 570 1 100 0x00) +( +# I have been unable to locate the JEDEC drawing. However, refering +# to http://www.zetex.com/3.0/pdf/TO220.pdf which claims to be JEDEC +# compliant, I see that the pins are rectangular with dimensions: +# +# 15-40 mils X 16-20 mils which gives a diagonal of +# 21.9 to 44.7 mils +# +# The pin pitch is 90 to 110 mils. +# +# The mounting hole is 139 to 160 mils diameter + Pin(100 800 90 60 "1" 0x101) + Pin(200 800 90 60 "2" 0x01) + Pin(300 800 90 60 "3" 0x01) + # Befestigungsbohrung + Pin(200 130 150 130 "4" 0x01) + # Anschlussdraehte + ElementLine(100 800 100 620 30) + ElementLine(200 800 200 620 30) + ElementLine(300 800 300 620 30) + # Gehaeuse + ElementLine( 0 620 400 620 20) + ElementLine(400 620 400 245 20) + ElementLine(400 245 0 245 20) + ElementLine( 0 245 0 620 20) + # Kuehlfahne mit Kerben + ElementLine( 0 245 400 245 20) + ElementLine(400 245 400 120 20) + ElementLine(400 120 385 120 20) + ElementLine(385 120 385 50 20) + ElementLine(385 50 400 50 20) + ElementLine(400 50 400 10 20) + ElementLine(400 10 0 10 20) + ElementLine( 0 10 0 50 20) + ElementLine( 0 50 15 50 20) + ElementLine( 15 50 15 120 20) + ElementLine( 15 120 0 120 20) + ElementLine( 0 120 0 245 20) + Mark(200 800) +) Index: tags/2.1.2/pcblib/tru-hole/TO220ACSTAND.fp =================================================================== --- tags/2.1.2/pcblib/tru-hole/TO220ACSTAND.fp (nonexistent) +++ tags/2.1.2/pcblib/tru-hole/TO220ACSTAND.fp (revision 24813) @@ -0,0 +1,16 @@ +##from:pcb +##for:diode +##geo:standing +Element(0x00 "diode in TO220" "" "TO220ACSTAND" 460 50 3 100 0x00) +( + Pin(100 100 80 40 "1" 0x101) + Pin(300 100 80 40 "2" 0x01) + ElementLine(0 0 0 180 20) + ElementLine(0 180 400 180 20) + ElementLine(400 180 400 0 20) + ElementLine(400 0 0 0 20) + ElementLine(0 50 400 50 10) + ElementLine(125 0 125 50 10) + ElementLine(275 0 275 50 10) + Mark(100 220) + ) Index: tags/2.1.2/pcblib/tru-hole/TO220S.fp =================================================================== --- tags/2.1.2/pcblib/tru-hole/TO220S.fp (nonexistent) +++ tags/2.1.2/pcblib/tru-hole/TO220S.fp (revision 24813) @@ -0,0 +1,36 @@ +##from:pcb +##for:transistor +##for:linear +##for:stabilizer +##geo:stadning + Element(0x00 "Transistor" "" "TO220S" 50 570 1 100 0x00) +( + Pin(100 800 90 60 "1" 0x101) + Pin(200 900 90 60 "2" 0x01) + Pin(300 800 90 60 "3" 0x01) + # Befestigungsbohrung + Pin(200 130 150 130 "4" 0x01) + # Anschlussdraehte + ElementLine(100 800 100 620 30) + ElementLine(200 900 200 620 30) + ElementLine(300 800 300 620 30) + # Gehaeuse + ElementLine( 0 620 400 620 20) + ElementLine(400 620 400 245 20) + ElementLine(400 245 0 245 20) + ElementLine( 0 245 0 620 20) + # Kuehlfahne mit Kerben + ElementLine( 0 245 400 245 20) + ElementLine(400 245 400 120 20) + ElementLine(400 120 385 120 20) + ElementLine(385 120 385 50 20) + ElementLine(385 50 400 50 20) + ElementLine(400 50 400 10 20) + ElementLine(400 10 0 10 20) + ElementLine( 0 10 0 50 20) + ElementLine( 0 50 15 50 20) + ElementLine( 15 50 15 120 20) + ElementLine( 15 120 0 120 20) + ElementLine( 0 120 0 245 20) + Mark(200 800) +) Index: tags/2.1.2/pcblib/tru-hole/TO220SW.fp =================================================================== --- tags/2.1.2/pcblib/tru-hole/TO220SW.fp (nonexistent) +++ tags/2.1.2/pcblib/tru-hole/TO220SW.fp (revision 24813) @@ -0,0 +1,26 @@ +##from:pcb +##for:transistor +##for:linear +##for:stabilizer +##geo:standing + Element(0x00 "Transistor" "" "TO220SW" 0 10 0 100 0x00) +( + Pin(100 200 90 60 "1" 0x101) + Pin(200 300 90 60 "2" 0x01) + Pin(300 200 90 60 "3" 0x01) + # Gehaeuse + ElementLine( 0 80 400 80 20) + ElementLine(400 80 400 260 20) + ElementLine(400 260 0 260 20) + ElementLine( 0 260 0 80 20) + # Kuehlfahne icl. Bohrung + ElementLine( 0 80 400 80 20) + ElementLine(400 80 400 140 20) + ElementLine(400 140 0 140 20) + ElementLine( 0 140 0 80 20) + ElementLine(130 80 130 140 10) + ElementLine(270 80 270 140 10) + # Anschlussdraht + ElementLine(200 300 200 260 30) + Mark(100 200) +) Index: tags/2.1.2/pcblib/tru-hole/TO220W.fp =================================================================== --- tags/2.1.2/pcblib/tru-hole/TO220W.fp (nonexistent) +++ tags/2.1.2/pcblib/tru-hole/TO220W.fp (revision 24813) @@ -0,0 +1,23 @@ +##from:pcb +##for:transistor +##for:linear +##for:stabilizer +##geo:standing Element(0x00 "Transistor" "" "TO220W" 0 10 0 100 0x00) +( + Pin(100 200 90 60 "1" 0x101) + Pin(200 200 90 60 "2" 0x01) + Pin(300 200 90 60 "3" 0x01) + # Gehaeuse + ElementLine( 0 80 400 80 20) + ElementLine(400 80 400 260 20) + ElementLine(400 260 0 260 20) + ElementLine( 0 260 0 80 20) + # Kuehlfahne icl. Bohrung + ElementLine( 0 80 400 80 20) + ElementLine(400 80 400 140 20) + ElementLine(400 140 0 140 20) + ElementLine( 0 140 0 80 20) + ElementLine(130 80 130 140 10) + ElementLine(270 80 270 140 10) + Mark(100 200) +) Index: tags/2.1.2/pcblib/tru-hole/TO247.fp =================================================================== --- tags/2.1.2/pcblib/tru-hole/TO247.fp (nonexistent) +++ tags/2.1.2/pcblib/tru-hole/TO247.fp (revision 24813) @@ -0,0 +1,19 @@ +##from:pcb +##for:transistor +##for:linear +##for:stabilizer +##geo:standing +Element(0x00 "diode in TO220" "" "TO247" 690 50 3 100 0x00) +( + Pin(96 130 100 60 "1" 0x101) + Pin(315 130 100 60 "2" 0x01) + Pin(534 130 100 60 "3" 0x01) + ElementLine(0 0 0 210 20) + ElementLine(0 210 630 210 20) + ElementLine(630 210 630 0 20) + ElementLine(630 0 0 0 20) + ElementLine(0 50 630 50 10) + ElementLine(240 0 240 50 10) + ElementLine(390 0 390 50 10) + Mark(96 270) + ) Index: tags/2.1.2/pcblib/tru-hole/TO247_2.fp =================================================================== --- tags/2.1.2/pcblib/tru-hole/TO247_2.fp (nonexistent) +++ tags/2.1.2/pcblib/tru-hole/TO247_2.fp (revision 24813) @@ -0,0 +1,17 @@ +##from:pcb +##for:diode +##geo:standing + +Element(0x00 "diode in TO220" "" "TO247_2" 690 50 3 100 0x00) +( + Pin(96 130 100 60 "1" 0x101) + Pin(534 130 100 60 "2" 0x01) + ElementLine(0 0 0 210 20) + ElementLine(0 210 630 210 20) + ElementLine(630 210 630 0 20) + ElementLine(630 0 0 0 20) + ElementLine(0 50 630 50 10) + ElementLine(240 0 240 50 10) + ElementLine(390 0 390 50 10) + Mark(96 270) + ) Index: tags/2.1.2/pcblib/tru-hole/TO251.fp =================================================================== --- tags/2.1.2/pcblib/tru-hole/TO251.fp (nonexistent) +++ tags/2.1.2/pcblib/tru-hole/TO251.fp (revision 24813) @@ -0,0 +1,20 @@ +##from:pcb +##for:transistor +##for:linear +##for:stabilizer +##geo:standing + +Element(0x00 "diode in TO220" "" "TO251" 325 50 3 100 0x00) +( + Pin(42 50 70 40 "1" 0x101) + Pin(132 50 70 40 "2" 0x01) + Pin(222 50 70 40 "3" 0x01) + ElementLine(0 0 0 100 20) + ElementLine(0 100 265 100 20) + ElementLine(265 100 265 0 20) + ElementLine(265 0 0 0 20) + ElementLine(0 50 265 50 10) + ElementLine(57 0 57 50 10) + ElementLine(207 0 207 50 10) + Mark(42 140) + ) Index: tags/2.1.2/pcblib/tru-hole/TO264.fp =================================================================== --- tags/2.1.2/pcblib/tru-hole/TO264.fp (nonexistent) +++ tags/2.1.2/pcblib/tru-hole/TO264.fp (revision 24813) @@ -0,0 +1,18 @@ +##from:pcb +##for:diode +##geo:standing + +Element(0x00 "diode in TO220" "" "TO264" 860 50 3 100 0x00) +( + Pin(181 130 100 60 "1" 0x101) + Pin(400 130 100 60 "2" 0x01) + Pin(619 130 100 60 "3" 0x01) + ElementLine(0 0 0 210 20) + ElementLine(0 210 800 210 20) + ElementLine(800 210 800 0 20) + ElementLine(800 0 0 0 20) + ElementLine(0 50 800 50 10) + ElementLine(325 0 325 50 10) + ElementLine(475 0 475 50 10) + Mark(181 270) + ) Index: tags/2.1.2/pcblib/tru-hole/TO39.fp =================================================================== --- tags/2.1.2/pcblib/tru-hole/TO39.fp (nonexistent) +++ tags/2.1.2/pcblib/tru-hole/TO39.fp (revision 24813) @@ -0,0 +1,37 @@ +##from:pcb +##for:transistor +##for:linear +##for:stabilizer + + Element["" "Transistor" "" "TO39" 18800 18800 6000 7000 0 100 ""] +( +# The JEDEC drawing shows a pin diameter of 16-21 mils +# +# +# ___x_ +# / \ +# TO39: |3 1| <-- bottom view (supposed to be a circle) +# \ 2 / +# --- +# +# NOTE: some vendors, ST for example, number the pins +# differently. Here we follow the JEDEC drawing. +# +# the pins are arranged along a 200 mil diameter +# circle. The can outline is 315 to 335 mils (320 nom) +# for the top of the can and 350 to 370 mils (360 nom) +# for the bottom edge of thecan +# + Pin[0 -10000 5500 3000 6100 3500 "1" "1" "square"] + Pin[-10000 0 5500 3000 6100 3500 "2" "2" ""] + Pin[0 10000 5500 3000 6100 3500 "3" "3" ""] +# tab is 29 to 40 mils long, 28 to 34 wide +# and comes off at an angle of 45 deg clockwise from +# pin 1 when looking at the top of the board + ElementLine [12700 -13900 14800 -16000 1000] + ElementLine [13300 -13300 15400 -15400 1000] + ElementLine [13900 -12700 16000 -14800 1000] + ElementLine [16000 -14800 14800 -16000 1000] +# x, y, width, height, start angle, delta angle, thickness + ElementArc [0 0 18300 18300 0 360 1000] + ) Index: tags/2.1.2/pcblib/tru-hole/TO92.fp =================================================================== --- tags/2.1.2/pcblib/tru-hole/TO92.fp (nonexistent) +++ tags/2.1.2/pcblib/tru-hole/TO92.fp (revision 24813) @@ -0,0 +1,23 @@ +##from:pcb +##for:transistor +##for:linear +##for:stabilizer +##geo:standing + + Element(0x00 "Transistor" "" "TO92" 60 70 0 100 0x00) +( +# The JEDEC drawing shows a pin diameter of 16-21 mils +# +# +# _______ +# TO92: | 1 2 3 | <-- bottom view +# \_____/ +# +# The pin to pin spacing is 100 mils. + Pin(250 200 72 42 "1" 0x101) + Pin(150 200 72 42 "2" 0x01) + Pin(50 200 72 42 "3" 0x01) + ElementArc(150 200 100 100 315 270 10) + ElementLine( 80 130 220 130 10) + Mark(50 200) +) Index: tags/2.1.2/scconfig/Makefile =================================================================== --- tags/2.1.2/scconfig/Makefile (nonexistent) +++ tags/2.1.2/scconfig/Makefile (revision 24813) @@ -0,0 +1,106 @@ +# --- configuration part -- + +# - generic configuration - +SRC=src +BIN=src + +# what cflags to use to compile scconfig +USER_CFLAGS = -DGENCALL -Isrc +#USER_CFLAGS = -Wall -Wextra -g -DGENCALL -Isrc + +# what ldflags to use to link scconfig +USER_LDFLAGS = + +# in case hooks.c needs to link to something local +USER_OBJS = src/util/arg_auto_set.o + +# what to build - a ./configure +all: configure cquote + +# This line imports scconfig core and default tests +include src/default/Makefile.plugin + +# +# - PLUGINS - +# +# Comment this line if you are not interested in c99 features +include src/c99/Makefile.plugin + +# Comment this line if you do not need script libs to be detected +include src/scripts/Makefile.plugin + +# Comment this line if you do not need parser libs to be detected +# include src/parser/Makefile.plugin + +# Comment this line if you do not need to detect parser generators +include src/parsgen/Makefile.plugin + +# Comment this line if you do not need math related libs +include src/math/Makefile.plugin + +# Comment this line if you do not need socket/networking +include src/socket/Makefile.plugin + +# Comment this line if you do not need user/password API detection +include src/userpass/Makefile.plugin + +# Comment this line if you do not need gui (X11, toolkits) +include src/gui/Makefile.plugin + +# Comment this line if you do not need software utility libs (glib) +include src/sul/Makefile.plugin + +# Uncomment this line if you need menus +include src/menulib/Makefile.plugin + +# Comment this line if you do not need generator (templating) +#include src/generator/Makefile.plugin + +# Comment this line if you do not need tmpasm (templating); conflicts with generator +include src/tmpasm/Makefile.plugin + +# --- you shouldn't edit the lines below --- +OBJS = $(USER_OBJS) hooks.o $(DEFAULT_NOMAIN_OBJS) $(SCRIPT_OBJS) $(PARSER_OBJS) $(GENERATOR_OBJS) $(TMPASM_OBJS) $(C99_OBJS) $(PARSGEN_OBJS) $(MATH_OBJS) $(SOCKET_OBJS) $(USERPASS_OBJS) $(GUI_OBJS) $(SUL_OBJS) +CFLAGS = $(USER_CFLAGS) $(DEFAULT_CFLAGS) $(SCRIPT_CFLAGS) $(PARSER_CFLAGS) $(GENERATOR_CFLAGS) $(TMPASM_CFLAGS) $(C99_CFLAGS) $(PARSGEN_CFLAGS) $(MATH_CFLAGS) $(SOCKET_CFLAGS) $(USERPASS_CFLAGS) $(GUI_CFLAGS) $(SUL_CFLAGS) $(MENULIB_CFLAGS) -Isrc/default +LDFLAGS = $(USER_LDFLAGS) $(DEFAULT_LDFLAGS) $(SCRIPT_LDFLAGS) $(PARSER_LDFLAGS) $(GENERATOR_LDFLAGS) $(TMPASM_LDFLAGS) $(C99_LDFLAGS) $(PARSGEN_LDFLAGS) $(MATH_LDFLAGS) $(SOCKET_LDFLAGS) $(USERPASS_LDFLAGS) $(GUI_LDFLAGS) $(SUL_LDFLAGS) $(MENULIB_LDFLAGS) + +all: configure revtest sccbox + +revtest: revtest.o + $(CC) -o revtest revtest.o + +revtest.o: revtest.c Rev.h + $(CC) -c $(CFLAGS) -o revtest.o revtest.c + +configure: $(OBJS) $(DEFAULT_MAIN_OBJS) + $(CC) -o configure $(OBJS) $(DEFAULT_MAIN_OBJS) + +menuconfig: menucfg + ./menucfg + +menucfg: $(OBJS) $(MENULIB_OBJS) src/default/main_lib.o src/default/main_custom_args.o menucfg.o src/util/arg_auto_menu.o src/util/arg_auto_set.o + $(CC) -o menucfg $(OBJS) $(MENULIB_OBJS) menucfg.o src/default/main_lib.o src/default/main_custom_args.o src/util/arg_auto_menu.o + +menucfg.o: menucfg.c + $(CC) -c $(CFLAGS) -o menucfg.o menucfg.c + +hooks.o: plugin_3state.h plugins.h Rev.h ../src_3rd/puplug/scconfig_hooks.h + +src/util/arg_auto_set.o: src/util/arg_auto_set.c src/util/arg_auto_set.h + $(CC) -c $(CFLAGS) -o src/util/arg_auto_set.o src/util/arg_auto_set.c + +src/util/sccbox.o: src/util/sccbox.c + $(CC) -c $(CFLAGS) -o src/util/sccbox.o src/util/sccbox.c + +sccbox: src/util/sccbox.o + $(CC) $(LDFLAGS) -o sccbox src/util/sccbox.o + +cquote: src/util/cquote.c + $(CC) $(CFLAGS) $(LDFLAGS) -o cquote src/util/cquote.c + +clean: + -rm $(OBJS) $(DEFAULT_MAIN_OBJS) configure revtest revtest.o cquote core src/util/sccbox.o + +distclean: + -rm ../config.h ../Makefile.conf ../src/Makefile ../util/gsch2pcb-rnd/Makefile config.cache config.log Rev.stamp sccbox gmon.out ../src_3rd/puplug/Makefile ../src_3rd/puplug/config.h ../src_plugins/lib_hid_gl/opengl.h + -$(MAKE) clean Index: tags/2.1.2/scconfig/README =================================================================== --- tags/2.1.2/scconfig/README (nonexistent) +++ tags/2.1.2/scconfig/README (revision 24813) @@ -0,0 +1,3 @@ +The configuration system that runs ./configure. + +The engine is scconfig. Index: tags/2.1.2/scconfig/Rev.h =================================================================== --- tags/2.1.2/scconfig/Rev.h (nonexistent) +++ tags/2.1.2/scconfig/Rev.h (revision 24813) @@ -0,0 +1 @@ +static const int myrev = 24736; Index: tags/2.1.2/scconfig/Rev.tab =================================================================== --- tags/2.1.2/scconfig/Rev.tab (nonexistent) +++ tags/2.1.2/scconfig/Rev.tab (revision 24813) @@ -0,0 +1,198 @@ +24736 configure make distclean fixes to really remove all generated files +24625 configure io_kicad common layer table code among read and write side +24585 configure io_kicad depends on the shape plugin for round-rect pads +24494 configure core shall not use glib for CFLAGS/LDFLAGS as core doesn't depend on glib +24429 configure move paper sizes out from ps to common code (io_kicad needs it too) +24389 configure live scripting: new source files for the new feature +24292 configure preparing for hidlib, splitting source files, scconfig hidlib deps +23917 configure compound DAD widgets, for DAD based spinboxes +23902 configure cleanup: remove dead code from gtk +23857 configure new, centralized log dialog +23788 configure lesstif tabbed widget reimplementation for portability +23737 configure new fileselect dialog API and new, centralized load/save actions +23602 configure io_tedax namespace cleanup +23589 configure removing the old netlist dialog leftover from gtk +23585 configure removing the mincut stub (switched over to the event API) +23579 configure removing old netlist +23486 configure gerber/excellon splitup +23462 configure splitting up the dialog plugin code linking into multiple objects for compilation speed +23292 configure rewriting user lead, moving the code from gtk to common +23140 configure netlist rewrite +23099 configure merge copy.[ch] into move.[ch] for compactness +22617 distclean enable the socket plugin in scconfig for detecting select() as an alternative to usleep() +22462 configure lesstif tree table widget code, low level +22305 configure new source files for lesstif color button +22264 configure new source files for tEDAx layer, board and drc save +22167 configure removal of the old gtk-only preferences dialog code +22119 configure dialogs config for window placement +21977 configure new propedit +21972 configure boardflip plugin removed (core functionality took over) +21942 configure io_tedax for new blocks +21876 configure moving out the old drc to a plugin +21580 configure HID API cleanup, including dialogs rewritten with DAD and new DAD features +21289 configure new drc infra and GUI +21098 configure old pinout dialog removal +20317 configure new core color infra +20260 configure plugin frame for ttf import +20249 configure central gettimeofday() wrapper to fix a compilation bug on IRIX +20233 configure new plugin: act_draw +20188 configure dad() action +20152 configure remove notebook helper from gtk for the DAD transition +20061 configure made asm configurable +20030 configure new plugin: asm +19890 configure tree-table widget in DAD core +19656 configure new plugin for c-pcb +19626 configure retired the nelma exporter +19343 configure export_gerber: plugin configuration for G85 slots +19048 configure gtk: command line source cleanup/rename and centralize history handling +18668 configure ddraft: sphash for constraints +18603 configure ddraft: default buildin +18569 configure ddraft: new plugin +18446 configure fp_wget configuration +18380 configure siwtched over to the new about box and export dialog +18304 configure introducing the cam system: rename hid_helper to hid_cam + cam plugin +18166 configure swithc over to scconfig's cquote +17960 configure script plugin +17691 configure action code cleanup +17436 configure renamed hid_actions.[ch] +17426 configure introduce new 3rd party lib dep: fungw +17304 configure new plugin: expfeat for experimental features +17216 configure rendering optimizations: gl inlining +17200 configure moved clip.h out from core +16898 configure new stroke plugin +16616 configure fixes for large boards and 64 bit coords +16591 configure export_xy: tempalte config +16456 configure new plugin: import_ipcd356; rewrite export_ipcd356 +16265 configure introducing pcb api ver +16233 configure retire hid_srv_ws: we are not going to use websockets for the web variant +16155 configure rewrite route style anchored menu to be central +16109 configure split off grid code from crosshair code and move gui-specific part out from core +15944 configure new default menu file preparation: embed the new menu, do not embed the old menus +15910 configure old data model removal +15352 configure typo in LIBDIR_INSTALLED +15104 configure openems mesher code +14724 configure subc hash and compare +13953 configure rtree switchover +13726 configure opnegl code moved to a separate plugin for reuse +13584 configure opengl -lGLU bugfix +13386 configure proper detection of includes for fileno() and usleep() +13364 configure new plugin: extedit +13269 configure remove free_atexit +13171 configure io_eagle: new source file for parsing dru files +13037 configure code simplification: PCB_INLINE +12835 configure new plugin: shape +12748 configure libminuid cflags fix +12708 configure new source file for the 'brave' feature +12673 configure new lib plugin: compat helper (because of the data model rewrite) +12595 configure new source files for padstacks +12401 configure new source files for more generic thermal support +12108 configure tool code splitup +11724 configure new default pcb +11611 configure enforce safe_fs +11529 configure gsch2pcb-rnd uses safe_fs +11436 configure dialogs plugin for moving dialog boxes out from core +11396 configure hid_lesstif linking bug +11265 configure deprecate dbus +11247 configure HPGL importer +11189 configure replace the openscad exporter +11159 configure new source files in hid_gtk2_gl for new HID API +11156 configure new source files in core for safe FS access +11151 configure new source files in dxf_export +11051 make clean new HID API for composite layer drawing +10867 configure loghid resurrect +10799 configure attributes dialog split in gtk +10679 configure infra for new core feature: subcircuit terminal +10672 configure switching over to libuundo +10662 configure split undo code, preparing for a more modular undo +10356 configure move genht out of liblihata +10285 configure control variable name fix in 3 lib plugins +10042 configure generalize lib_netmap and lib_padstack_hash and add lib_polyhelp +9966 configure hyperlynx write +9919 configure rubberband_orig got its own config subtree +9840 configure compile and link libminuid +9600 configure eagle bin parser +9271 configure core cleanup (split select.c and operation.c) +9036 configure diag configuration for integrity checks +9025 configure new source files for eagle subformats +9019 configure new source file in diag for integrity checks +8990 configure new source files for subcircuits +8920 configure build changes in puplug +8912 configure fp_board enabled by default; new plugin for mentor cell footprints +8817 configure fp_board: new plugin +8774 configure layer: all-hid common library plugin for the layer menus +8748 configure core: new pcb_bool source file +8593 configure gtk: new layer selector +8331 configure cquote generates C98-safe long strings +8275 configure puplug +8153 configure enable io_hyp by default +8054 configure setenv() detection for parametric footprint env +7998 configure gtk GTK3 box compatibility +7968 configure clean up global namespace: rename VERSION, PACKAGE and REVISION +7967 configure rename import_hyp to io_hyp +7954 configure fp_wget configuration, edakrill integration +7720 configure new route feature +7594 configure gtk splitup and gl +7509 configure rubber band upgrade, new go code +7439 configure tEDAx chnaged from import to io +7432 configure mentor_sch plugin upgrades +7372 configure gtk splitup +7241 configure gtk parametric footprint handling +7217 configure gtk splitup +7136 configure mentor sch import plugin +7117 configure gtk splitup: DRC dialog +7105 configure font selector gui dependencies +7086 configure gtk splitup +7063 configure gtk dialog for font selection +7055 configure gtk splitup +7050 configure multifont support: merge all draw stubs for simplicity +7042 configure gtk splitup +7022 configure multifont support: new actions +6980 configure gtk splitup: preferences dialog +6924 configure new import plugins +6735 configure gtk splitup +6392 configure draw cross section plugin (gtk and lesstif depend on it) +6365 configure gtk splitup +6111 configure layer vs. layer group code split +6093 distclean,configure hid API extension for the common Cursor action +6087 configure start splitting up hid_gtk: new plugin that hid_gtk depends on: lib_gtk_common +6056 configure gschp2pcb-rnd build deps bug +6007 configure switch over Makefiles to use sccbox +6004 distclean,configure scconfig compiles sccbox thast will ease portable clean and installation rules +5982 make clean gsch2pcb-rnd build fix +5611 configure new feature: UI layer +5487 configure layer cleanup: layer visibility in a new source file +5472 configure draw_fab config subtree +5278 configure prepare for arc UI extension: blank arc_ui.[ch] to move arc UI logics into +5256 configure move rubberband code into a plugin +5199 configure new export plugin: export_stat +5108 configure cleanup: remove old pointer list and use genvt +5019 configure unravel - remove set.[ch] +4616 configure unravel - the big cleanup, moving code +4904 make clean,configure unravel2 - regenerate action registration because regiestrator function name changed +4882 configure unravel2 - the big cleanup, renaming types +4608 configure unravel - the big cleanup, moving code and files +4588 configure disable bison by default +4587 configure draw_fab moved to a plugin +4450 configure io_lihata plugin config and 3rd party lib dependency fix +4398 configure io_kicad plugin interdeps and enable io_kicad by default +4375 configure custom output style support in io_lihata +4321 configure imported lihata persistent save lib in src_3rd as svn extern +4160 configure lib_* plugins (renames, s-expression) +4063 configure netlist.c split and cleanup +4019 configure case sensitive string regex for query +4011 configure sphash available for all plugins (needed by query first) +4002 configure auto-enable the query plugin +3926 configure advanced search in gtk, imported 10 old plugins +3841 configure link string->int hash table (for the query language) +3822 configure new global struct: obj_any_t that will allow a query to list objects +3745 configure gsch2pcb-rnd footprint lib initialization bug fixed +3695 configure bind signals to emergency save so that a copy of the in-memory PCB is saved on most crashes +3513 configure rename detect gcc attribute "unused" and use it for static inline local functions +3510 configure rename the debug plugin to diag plugin to avoid confusion with --debug in ./configure +3509 configure solve non-c89-compliant function pointer <-> data pointer casts +3361 configure cleanup: layer.c is compiled into layer.o now +3339 configure C89: round() is detected by scconfig +3183 distclean,configure C89 switchover +3179 configure C89 correctness: do not depend on hardwired long long, detect it +2985 configure Revcheck installed in Makefiles. +2984 configure Introduction of the config-rev system. Index: tags/2.1.2/scconfig/gen_conf.sh =================================================================== --- tags/2.1.2/scconfig/gen_conf.sh (nonexistent) +++ tags/2.1.2/scconfig/gen_conf.sh (revision 24813) @@ -0,0 +1,122 @@ +#!/bin/sh + +# TODO: rewrite this in C for better portability + +if test -z "$AWK" +then + AWK="awk" +fi + +$AWK -v "docdir=$1" ' + BEGIN { + level = -1 + q = "\"" + cm = "," + } + + function doc_head(fn, path) + { + if (fn in DOCS) + return + DOCS[fn]++ + print "" > fn + print "

    pcb-rnd conf tree

    " > fn + print "

    subtree: " path "

    " > fn + print "" > fn + print "
    node name type flags description" > fn + + } + + function doc_foot(fn) + { + print "
    " > fn + } + + /[{]/ { level++ } + + /struct.*/ { + name = $0 + sub(".*struct[ \t]*", "", name) + sub("[ \t{].*", "", name) + if (level == 0) + path = "" + else + path = path "/" name + } + + /^[ \t]*[\/][\/]/ { next } + + /CFT_/ { + if (level < 1) + next + + name=$0 + sub("^.*CFT_", "CFN_", name) + sub(";.*", "", name) + type=name + sub("[ \t]*[^ \t]*$", "", type) + sub("[^ \t]*[ \t]*", "", name) + array = (name ~ "[[]") + if (array) + sub("[[].*$", "", name) + id = path + sub("^/", "", id) + gsub("/", ".", id) + id = id "." name + + desc = $0 + if (desc ~ "/[*]") { + sub("^.*/[*]", "", desc) + sub("[*]/.*$", "", desc) + sub("^[ \t]*", "", desc) + sub("[ \t]*$", "", desc) + } + else + desc = "" + if (desc == "") + desc = "<" name ">" + + flags = ""; + while(match(desc, "@[a-zA-Z_]+")) { + flag=substr(desc, RSTART, RLENGTH) + sub("[ \t]*" flag "[ \t]*", " ", desc) + sub("^@", "",flag) + flag="CFF_" toupper(flag) + if (flags == "") + flags = flag + else + flags = flags " | " flag + } + if (flags == "") + flags = 0; + sub("^[ \t]*", "", desc) + sub("[ \t]*$", "", desc) + + path_tmp=path + sub("^/", "", path_tmp) + printf("conf_reg(%-36s %s %-16s %-25s %-25s %s, %s)\n", id cm, (array ? "array, " : "scalar,"), type cm, q path_tmp q cm, q name q cm, q desc q, flags) + if (docdir != "") { + path_tmp2 = path_tmp + gsub("/", "_", path_tmp2) + fn = docdir "/" path_tmp2 ".html" + doc_head(fn, path_tmp) + type2 = tolower(type) + sub("^cfn_", "", type2) + + print "
  • ", name, "", type2, "", flags, "", desc > fn + } + } + + /[}]/ { + level-- + sub("[/][^/]*$", "", path) + } + + + END { + if (level != -1) + print "Error: unbalanced braces" > "/dev/stderr" + for(fn in DOCS) + doc_foot(fn) + } +' Property changes on: tags/2.1.2/scconfig/gen_conf.sh ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/2.1.2/scconfig/gen_core_lists.sh =================================================================== --- tags/2.1.2/scconfig/gen_core_lists.sh (nonexistent) +++ tags/2.1.2/scconfig/gen_core_lists.sh (revision 24813) @@ -0,0 +1,62 @@ +#!/bin/sh + +if test -z "$AWK" +then + AWK="awk" +fi + +for f in $* +do + echo "___name___ $f" + cat $f +done | $AWK ' +BEGIN { + q = "\"" + print "/**** DO NOT EDIT - automatically generated by gen_core_lists.sh ****/" + print "" +} + +/^___name___/ { + fullname = $2 + basename = $2 + sub("/[^/]*$", "", basename) + if (fullname ~ "src_plugins/") + TYPE[basename]="plugdir" +} + +/^type=/ { + type = $0 + sub("^type=", "", type) + TYPE[basename] = type + print "/* ", type, basename " */" +} + + +/^PCB_REGISTER/ { + LIST[basename] = LIST[basename] $0 "\n" +} + +END { + for(n in LIST) { + hn = n + sub("^hid/", "", hn) +# if (hn in HIDNAME_FIXUP) +# hn = HIDNAME_FIXUP[hn] + + print "/* " n " (" TYPE[n] ") */" + if (TYPE[n] == "gui") + print "if ((gui != NULL) && (strcmp(gui->name, " q hn q ") == 0)) {" + if (TYPE[n] == "plugdir") { + vname = LIST[n] + sub("PCB_REGISTER_ACTIONS.*[(]", "", vname) + sub("[)].*[\\n\\r]*", "", vname) + print "extern HID_Action " vname "[];" + } + print LIST[n] + if (TYPE[n] == "gui") + print "}" + } +} + +' + Property changes on: tags/2.1.2/scconfig/gen_core_lists.sh ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/2.1.2/scconfig/hooks.c =================================================================== --- tags/2.1.2/scconfig/hooks.c (nonexistent) +++ tags/2.1.2/scconfig/hooks.c (revision 24813) @@ -0,0 +1,1023 @@ +#include +#include +#include "arg.h" +#include "log.h" +#include "dep.h" +#include "libs.h" +#include "db.h" +#include "tmpasm.h" +#include "tmpasm_scconfig.h" +#include "util/arg_auto_set.h" +#include "Rev.h" + +#define version "2.1.2" + +#include "plugin_3state.h" + +#include "../src_3rd/puplug/scconfig_hooks.h" +#include "../src_3rd/libfungw/scconfig_hooks.h" + +int want_coord_bits; + +/* if any of these are enabled, we need the dialog plugin; dialog can not be + a pup dep because it must be omitted from the hidlib */ +const char *dialog_deps[] = { + "/local/pcb/dialogs/controls", /* so we don't relax user's explicit request */ + "/local/pcb/hid_remote/controls", + "/local/pcb/lib_gtk_common/controls", + "/local/pcb/hid_lesstif/controls", + NULL +}; + + +const arg_auto_set_t disable_libs[] = { /* list of --disable-LIBs and the subtree they affect */ + {"disable-xrender", "libs/gui/xrender", arg_lib_nodes, "$do not use xrender for lesstif"}, + {"disable-xinerama", "libs/gui/xinerama", arg_lib_nodes, "$do not use xinerama for lesstif"}, + {"disable-gd", "libs/gui/gd", arg_lib_nodes, "$do not use gd (many exporters need it)"}, + {"disable-gd-gif", "libs/gui/gd/gdImageGif", arg_lib_nodes, "$no gif support in the png pcb_exporter"}, + {"disable-gd-png", "libs/gui/gd/gdImagePng", arg_lib_nodes, "$no png support in the png pcb_exporter"}, + {"disable-gd-jpg", "libs/gui/gd/gdImageJpeg", arg_lib_nodes, "$no jpeg support in the png pcb_exporter"}, + {"enable-bison", "/local/pcb/want_bison", arg_true, "$enable generating language files"}, + {"disable-bison", "/local/pcb/want_bison", arg_false, "$disable generating language files"}, + {"enable-dmalloc", "/local/pcb/want_dmalloc", arg_true, "$compile with lib dmalloc"}, + {"disable-dmalloc", "/local/pcb/want_dmalloc", arg_false, "$compile without lib dmalloc"}, + +#undef plugin_def +#undef plugin_header +#undef plugin_dep +#define plugin_def(name, desc, default_, all_) plugin3_args(name, desc) +#define plugin_header(sect) +#define plugin_dep(plg, on, hidlib) +#include "plugins.h" + + {NULL, NULL, NULL, NULL} +}; + +static void help1(void) +{ + argtbl_t *a; + + printf("./configure: configure pcb-rnd.\n"); + printf("\n"); + printf("Usage: ./configure [options]\n"); + printf("\n"); + printf("options are:\n"); + printf(" --prefix=path change installation prefix from /usr/local to path\n"); + printf(" --debug build full debug version (-g -O0, extra asserts)\n"); + printf(" --profile build profiling version if available (-pg)\n"); + printf(" --symbols include symbols (add -g, but no -O0 or extra asserts)\n"); + printf(" --coord=32|64 set coordinate integer type's width in bits\n"); + printf(" --dot_pcb_pcb=path .pcb-rnd config path under $HOME/\n"); + printf(" --workaround-gtk-ctrl enable GTK control key query workaround\n"); + printf(" --man1dir=path change installation path of man1 files (under prefix)\n"); + printf(" --all=plugin enable all working plugins for dynamic load\n"); + printf(" --all=buildin enable all working plugins for static link\n"); + printf(" --all=disable disable all plugins (compile core only)\n"); + printf(" --force-all=plugin enable even broken plugins for dynamic load\n"); + printf(" --force-all=buildin enable even broken plugins for static link\n"); + + for(a = main_argument_table; a->arg != NULL; a++) { + if (a->help != NULL) { + char tmp[64]; + sprintf(tmp, "%s=str", a->arg); + printf(" --%-24s %s\n", tmp, a->help); + } + } + + +} + +static void help2(void) +{ + printf("\n"); + printf("Some of the --disable options will make ./configure to skip detection of the given feature and mark them \"not found\"."); + printf("\n"); +} + +char *repeat = NULL; +#define report_repeat(msg) \ +do { \ + report(msg); \ + if (repeat != NULL) { \ + char *old = repeat; \ + repeat = str_concat("", old, msg, NULL); \ + free(old); \ + } \ + else \ + repeat = strclone(msg); \ +} while(0) + +static void all_plugin_select(const char *state, int force); + +/* Runs when a custom command line argument is found + returns true if no further argument processing should be done */ +int hook_custom_arg(const char *key, const char *value) +{ + if (strcmp(key, "prefix") == 0) { + report("Setting prefix to '%s'\n", value); + put("/local/prefix", strclone(value)); + return 1; + } + if (strcmp(key, "debug") == 0) { + put("/local/pcb/debug", strue); + pup_set_debug(strue); + return 1; + } + if (strcmp(key, "profile") == 0) { + put("/local/pcb/profile", strue); + return 1; + } + if (strcmp(key, "symbols") == 0) { + put("/local/pcb/symbols", strue); + return 1; + } + if (strcmp(key, "coord") == 0) { + int v = atoi(value); + if ((v != 32) && (v != 64)) { + report("ERROR: --coord needs to be 32 or 64.\n"); + exit(1); + } + put("/local/pcb/coord_bits", value); + want_coord_bits = v; + return 1; + } + if ((strcmp(key, "all") == 0) || (strcmp(key, "force-all") == 0)) { + if ((strcmp(value, sbuildin) == 0) || (strcmp(value, splugin) == 0) || (strcmp(value, sdisable) == 0)) { + all_plugin_select(value, (key[0] == 'f')); + return 1; + } + report("Error: unknown --all argument: %s\n", value); + exit(1); + } + if (strcmp(key, "coord") == 0) { + put("/local/pcb/dot_pcb_rnd", value); + return 1; + } + if (strcmp(key, "man1dir") == 0) { + put("/local/man1dir", value); + return 1; + } + if (strncmp(key, "workaround-", 11) == 0) { + const char *what = key+11; + if (strcmp(what, "gtk-ctrl") == 0) append("/local/pcb/workaround_defs", "\n#define PCB_WORKAROUND_GTK_CTRL 1"); + else if (strcmp(what, "gtk-shift") == 0) append("/local/pcb/workaround_defs", "\n#define PCB_WORKAROUND_GTK_SHIFT 1"); + else { + report("ERROR: unknown workaround '%s'\n", what); + exit(1); + } + return 1; + } + if ((strcmp(key, "with-intl") == 0) || (strcmp(key, "enable-intl") == 0)) { + report("ERROR: --with-intl is no longer supported, please do not use it\n"); + return 1; + } + else if (strcmp(key, "help") == 0) { + help1(); + arg_auto_print_options(stdout, " ", " ", disable_libs); + help2(); + exit(0); + } + + if (arg_auto_set(key, value, disable_libs) == 0) { + fprintf(stderr, "Error: unknown argument %s\n", key); + exit(1); + } + return 1; /* handled by arg_auto_set() */ +} + +/* execute plugin dependency statements, depending on "require": + require = 0 - attempt to mark any dep as buildin + require = 1 - check if dependencies are met, disable plugins that have + unmet deps +*/ +int plugin_dep1(int require, const char *plugin, const char *deps_on, int hidlib) +{ + char buff[1024]; + const char *st_plugin, *st_deps_on; + int dep_chg = 0; + + sprintf(buff, "/local/pcb/%s/hidlib", plugin); + if (!hidlib) { /* may be inherited */ + hidlib = get(buff) != NULL; + } + + if (hidlib) { + put(buff, strue); + sprintf(buff, "/local/pcb/%s/hidlib", deps_on); + put(buff, strue); + } + + sprintf(buff, "/local/pcb/%s/controls", plugin); + st_plugin = get(buff); + sprintf(buff, "/local/pcb/%s/controls", deps_on); + st_deps_on = get(buff); + + if (require) { + if ((strcmp(st_plugin, sbuildin) == 0)) { + if (strcmp(st_deps_on, sbuildin) != 0) { + sprintf(buff, "WARNING: disabling (ex-buildin) %s because the %s is not enabled as a buildin...\n", plugin, deps_on); + report_repeat(buff); + sprintf(buff, "disable-%s", plugin); + hook_custom_arg(buff, NULL); + dep_chg++; + } + } + else if ((strcmp(st_plugin, splugin) == 0)) { + if ((strcmp(st_deps_on, sbuildin) != 0) && (strcmp(st_deps_on, splugin) != 0)) { + sprintf(buff, "WARNING: disabling (ex-plugin) %s because the %s is not enabled as a buildin or plugin...\n", plugin, deps_on); + report_repeat(buff); + sprintf(buff, "disable-%s", plugin); + hook_custom_arg(buff, NULL); + dep_chg++; + } + } + } + else { + if (strcmp(st_plugin, sbuildin) == 0) + put(buff, sbuildin); + else if (strcmp(st_plugin, splugin) == 0) { + if ((st_deps_on == NULL) || (strcmp(st_deps_on, "disable") == 0)) + put(buff, splugin); + } + dep_chg++; + } + return dep_chg; +} + +static void all_plugin_select(const char *state, int force) +{ + char buff[1024]; + +#undef plugin_def +#undef plugin_header +#undef plugin_dep +#define plugin_def(name, desc, default_, all_) \ + if ((all_) || force) { \ + sprintf(buff, "/local/pcb/%s/controls", name); \ + put(buff, state); \ + } +#define plugin_header(sect) +#define plugin_dep(plg, on, hidlib) +#include "plugins.h" +} + +int plugin_deps(int require) +{ + int dep_chg = 0; +#undef plugin_def +#undef plugin_header +#undef plugin_dep +#define plugin_def(name, desc, default_, all_) +#define plugin_header(sect) +#define plugin_dep(plg, on, hidlib) dep_chg += plugin_dep1(require, plg, on, hidlib); +#include "plugins.h" + return dep_chg; +} + + +/* Runs before anything else */ +int hook_preinit() +{ + return 0; +} + +/* Runs after initialization */ +int hook_postinit() +{ + db_mkdir("/local"); + db_mkdir("/local/pcb"); + + pup_hook_postinit(); + fungw_hook_postinit(); + + /* DEFAULTS */ + put("/local/prefix", "/usr/local"); + put("/local/man1dir", "/share/man/man1"); + put("/local/man1dir", "/share/man/man1"); + put("/local/pcb/hid_gtk3_cairo/controls", sfalse); /* enable gtk3 only when explicitly requested */ + +#undef plugin_def +#undef plugin_header +#undef plugin_dep +#define plugin_def(name, desc, default_, all_) plugin3_default(name, default_) +#define plugin_header(sect) +#define plugin_dep(plg, on, hidlib) +#include "plugins.h" + + put("/local/pcb/want_bison", sfalse); + put("/local/pcb/debug", sfalse); + put("/local/pcb/profile", sfalse); + put("/local/pcb/symbols", sfalse); + put("/local/pcb/coord_bits", "32"); + want_coord_bits = 32; + put("/local/pcb/dot_pcb_rnd", ".pcb-rnd"); + + return 0; +} + +static int all_plugin_check_explicit(void) +{ + char pwanted[1024], pgot[1024]; + const char *wanted, *got; + int tainted = 0; + +#undef plugin_def +#undef plugin_header +#undef plugin_dep +#define plugin_def(name, desc, default_, all_) \ + sprintf(pwanted, "/local/pcb/%s/explicit", name); \ + wanted = get(pwanted); \ + if (wanted != NULL) { \ + sprintf(pgot, "/local/pcb/%s/controls", name); \ + got = get(pgot); \ + if (strcmp(got, wanted) != 0) {\ + report("ERROR: %s was requested to be %s but I had to %s it\n", name, wanted, got); \ + tainted = 1; \ + } \ + } +#define plugin_header(sect) +#define plugin_dep(plg, on, hidlib) +#include "plugins.h" + return tainted; +} + + +/* Runs after all arguments are read and parsed */ +int hook_postarg() +{ + int limit = 128; + + /* repeat as long as there are changes - this makes it "recursive" on + resolving deps */ + while(plugin_deps(0) && (limit > 0)) limit--; + + return 0; +} + + + +/* Runs when things should be detected for the host system */ +int hook_detect_host() +{ + pup_hook_detect_host(); + fungw_hook_detect_host(); + + require("fstools/ar", 0, 1); + require("fstools/mkdir", 0, 1); + require("fstools/rm", 0, 1); + require("fstools/cp", 0, 1); + require("fstools/ln", 0, 1); + +/* until we rewrite the generators in C */ + require("fstools/awk", 0, 1); + + require("cc/argstd/*", 0, 0); + + require("cc/func_attr/unused/*", 0, 0); + require("cc/inline", 0, 0); + + return 0; +} + +int safe_atoi(const char *s) +{ + if (s == NULL) + return 0; + return atoi(s); +} + + /* figure if we need the dialogs plugin */ +static void calc_dialog_deps(void) +{ + int buildin = 0, plugin = 0; + const char **p; + for(p = dialog_deps; *p != NULL; p++) { + const char *st = get(*p); + if (strcmp(st, "buildin") == 0) { + buildin = 1; + break; + } + if (strcmp(st, "plugin") == 0) + plugin = 1; + } + if (buildin) { + hook_custom_arg("buildin-draw_csect", NULL); + hook_custom_arg("buildin-draw_fontsel", NULL); + hook_custom_arg("buildin-dialogs", NULL); + } + else if (plugin) { + hook_custom_arg("plugin-draw_csect", NULL); + hook_custom_arg("plugin-draw_fontsel", NULL); + hook_custom_arg("plugin-dialogs", NULL); + } +} + +/* Runs when things should be detected for the target system */ +int hook_detect_target() +{ + int need_gtklibs = 0, want_glib = 0, want_gtk, want_gtk2, want_gtk3, want_gd, want_stroke, need_inl = 0, want_cairo, want_xml2, has_gtk2 = 0, has_gtk3 = 0, want_gl, want_freetype2, want_fuse; + const char *host_ansi, *host_ped, *target_ansi, *target_ped, *target_pg, *target_no_pie; + + want_gtk2 = plug_is_enabled("hid_gtk2_gdk") || plug_is_enabled("hid_gtk2_gl"); + want_gtk3 = plug_is_enabled("hid_gtk3_cairo"); + want_gtk = want_gtk2 | want_gtk3; + want_gd = plug_is_enabled("export_png") || plug_is_enabled("export_gcode"); + want_stroke = plug_is_enabled("stroke"); + want_cairo = plug_is_enabled("export_bboard") | plug_is_enabled("hid_gtk3_cairo"); + want_xml2 = plug_is_enabled("io_eagle"); + want_freetype2 = plug_is_enabled("import_ttf"); + want_fuse = plug_is_enabled("export_vfs_fuse"); + +/****** TODO #21: core depends on this plugin (yes, this is a bug) ******/ + hook_custom_arg("buildin-lib_compat_help", NULL); + + require("cc/fpic", 0, 0); + host_ansi = get("/host/cc/argstd/ansi"); + host_ped = get("/host/cc/argstd/pedantic"); + target_ansi = get("/target/cc/argstd/ansi"); + target_ped = get("/target/cc/argstd/pedantic"); + target_pg = get("/target/cc/argstd/pg"); + target_no_pie = get("/target/cc/argstd/no-pie"); + require("cc/pragma_message", 0, 0); + + { /* need to set debug flags here to make sure libs are detected with the modified cflags; -ansi matters in what #defines we need for some #includes */ + const char *tmp, *fpic, *debug; + fpic = get("/target/cc/fpic"); + if (fpic == NULL) fpic = ""; + debug = get("/arg/debug"); + if (debug == NULL) debug = ""; + tmp = str_concat(" ", fpic, debug, NULL); + put("/local/global_cflags", tmp); + + /* for --debug mode, use -ansi -pedantic for all detection */ + put("/local/cc_flags_save", get("/target/cc/cflags")); + if (istrue(get("/local/pcb/debug"))) { + append("/target/cc/cflags", " "); + append("/target/cc/cflags", target_ansi); + append("/target/cc/cflags", " "); + append("/target/cc/cflags", target_ped); + } + if (istrue(get("/local/pcb/profile"))) { + append("/target/cc/cflags", " "); + append("/target/cc/cflags", target_pg); + append("/target/cc/cflags", " "); + append("/target/cc/cflags", target_no_pie); + } + } + + pup_hook_detect_target(); + + require("signal/names/*", 0, 0); + require("libs/env/setenv/*", 0, 0); + if (!istrue(get("libs/env/setenv/presents"))) + require("libs/env/putenv/*", 0, 0); + require("libs/fs/mkdtemp/*", 0, 0); + require("libs/fs/realpath/*", 0, 0); + require("libs/fs/readdir/*", 0, 1); + require("libs/io/fileno/*", 0, 1); + require("libs/io/popen/*", 0, 1); + require("libs/math/rint/*", 0, 0); + require("libs/math/round/*", 0, 0); + require("libs/userpass/getpwuid/*", 0, 0); + require("libs/script/fungw/*", 0, 0); + + if (!istrue(get("libs/script/fungw/presents"))) + fungw_hook_detect_target(); + + { + int miss_select = require("libs/socket/select/*", 0, 0); + if (require("libs/time/usleep/*", 0, 0) && require("libs/time/Sleep/*", 0, 0) && miss_select) { + report_repeat("\nERROR: can not find usleep() or Sleep() or select() - no idea how to sleep ms.\n\n"); + return 1; + } + } + + require("libs/time/gettimeofday/*", 0, 1); + + if (require("libs/ldl", 0, 0) != 0) { + if (require("libs/LoadLibrary", 0, 0) != 0) { + report_repeat("\nERROR: no dynamic linking found on your system. Can not compile pcb-rnd.\n\n"); + return 1; + } + } + + if (require("libs/proc/wait", 0, 0) != 0) { + if (require("libs/proc/_spawnvp", 0, 0) != 0) { + report_repeat("\nERROR: no fork or _spawnvp. Can not compile pcb-rnd.\n\n"); + return 1; + } + } + + if (require("libs/fs/_mkdir", 0, 0) != 0) { + if (require("libs/fs/mkdir", 0, 0) != 0) { + report_repeat("\nERROR: no mkdir() or _mkdir(). Can not compile pcb-rnd.\n\n"); + return 1; + } + } + + if (require("libs/fs/getcwd/*", 0, 0) != 0) + if (require("libs/fs/_getcwd/*", 0, 0) != 0) + if (require("libs/fs/getwd/*", 0, 0) != 0) { + report_repeat("\nERROR: Can not find any getcwd() variant.\n\n"); + return 1; + } + + if (want_fuse) { + require("libs/sul/fuse/*", 0, 0); + if (!istrue(get("libs/sul/fuse/presents"))) { + report_repeat("WARNING: Since there's no fuse found, disabling export_vfs_fuse plugin...\n"); + hook_custom_arg("disable-export_vfs_fuse", NULL); + } + } + + if (want_stroke) { + require("libs/gui/libstroke/presents", 0, 0); + if (!istrue(get("libs/gui/libstroke/presents"))) { + report_repeat("WARNING: Since there's no libstroke found, disabling the stroke plugin...\n"); + hook_custom_arg("disable-stroke", NULL); + } + } + + if (want_freetype2) { + require("libs/sul/freetype2/presents", 0, 0); + if (!istrue(get("libs/sul/freetype2/presents"))) { + report_repeat("WARNING: Since there's no libfreetype2 found, disabling the import_ttf plugin...\n"); + hook_custom_arg("disable-import_ttf", NULL); + } + } + + if (want_cairo) { + require("libs/gui/cairo/presents", 0, 0); + if (!istrue(get("libs/gui/cairo/presents"))) { + report_repeat("WARNING: Since there's no cairo found, disabling the export_bboard plugin...\n"); + hook_custom_arg("disable-export_bboard", NULL); + } + } + + if (want_gtk2) { + require("libs/gui/gtk2/presents", 0, 0); + if (istrue(get("libs/gui/gtk2/presents"))) { + require("libs/gui/gtk2gl/presents", 0, 0); + if (!istrue(get("libs/gui/gtk2gl/presents"))) { + report_repeat("WARNING: Since there's no gl support for gtk found, disabling the gl rendering...\n"); + hook_custom_arg("disable-hid_gtk2_gl", NULL); + } + need_gtklibs = 1; + has_gtk2 = 1; + } + else { + report_repeat("WARNING: Since there's no libgtk2 found, disabling hid_gtk2*...\n"); + hook_custom_arg("disable-hid_gtk2_gdk", NULL); + hook_custom_arg("disable-hid_gtk2_gl", NULL); + } + } + + if (want_gtk3) { + if (istrue(get("libs/gui/cairo/presents"))) { + require("libs/gui/gtk3/presents", 0, 0); + if (!istrue(get("libs/gui/gtk3/presents"))) { + report_repeat("WARNING: Since there's no libgtk3 found, disabling hid_gtk3*...\n"); + hook_custom_arg("disable-hid_gtk3_cairo", NULL); + } + else { + need_gtklibs = 1; + has_gtk3 = 1; + } + } + else { + report_repeat("WARNING: not going to try gtk3 because cairo is not found\n"); + hook_custom_arg("disable-hid_gtk3_cairo", NULL); + } + } + + want_gl = plug_is_enabled("hid_gtk2_gl"); + if (want_gl) { + require("libs/gui/glu/presents", 0, 0); + if (!istrue(get("libs/gui/glu/presents"))) { + report_repeat("WARNING: Since there's no GLU found, disabling the hid_gtk2_gl plugin...\n"); + goto disable_gl; + } + else + put("/local/pcb/has_glu", strue); + } + else { + disable_gl:; + hook_custom_arg("disable-lib_hid_gl", NULL); + hook_custom_arg("disable-hid_gtk2_gl", NULL); + } + + /* gtk2 vs. gtk3 xor logic */ + if (has_gtk2 && has_gtk3) { + report_repeat("Selected both gtk2 and gtk3 HIDs; gtk2 and gtk3 are incompatible, disabling gtk2 in favor of gtk3.\n"); + hook_custom_arg("disable-hid_gtk2_gdk", NULL); + hook_custom_arg("disable-hid_gtk2_gl", NULL); + has_gtk2 = 0; + } + + /* libs/gui/gtkx is the version-independent set of flags in the XOR model */ + if (has_gtk3) { + put("/target/libs/gui/gtkx/cflags", get("/target/libs/gui/gtk3/cflags")); + put("/target/libs/gui/gtkx/ldflags", get("/target/libs/gui/gtk3/ldflags")); + } + if (has_gtk2) { + put("/target/libs/gui/gtkx/cflags", get("/target/libs/gui/gtk2/cflags")); + put("/target/libs/gui/gtkx/ldflags", get("/target/libs/gui/gtk2/ldflags")); + } + + if (!need_gtklibs) { + report("No gtk support available, disabling lib_gtk_*...\n"); + hook_custom_arg("disable-lib_gtk_common", NULL); + hook_custom_arg("disable-lib_gtk_hid", NULL); + } + + if (want_xml2) { + require("libs/sul/libxml2/presents", 0, 0); + if (!istrue(get("libs/sul/libxml2/presents"))) { + report("libxml2 is not available, disabling io_eagle...\n"); + report_repeat("WARNING: Since there's no libxml2 found, disabling the Eagle IO plugin...\n"); + hook_custom_arg("disable-io_eagle", NULL); + } + put("/local/pcb/want_libxml2", strue); + } + else + put("/local/pcb/want_libxml2", strue); + + + if (plug_is_enabled("hid_lesstif")) { + require("libs/gui/lesstif2/presents", 0, 0); + if (istrue(get("libs/gui/lesstif2/presents"))) { + require("libs/gui/xinerama/presents", 0, 0); + require("libs/gui/xrender/presents", 0, 0); + } + else { + report_repeat("WARNING: Since there's no lesstif2 found, disabling the lesstif HID and xinerama and xrender...\n"); + hook_custom_arg("disable-xinerama", NULL); + hook_custom_arg("disable-xrender", NULL); + hook_custom_arg("disable-hid_lesstif", NULL); + } + } + else { + hook_custom_arg("disable-xinerama", NULL); + hook_custom_arg("disable-xrender", NULL); + } + + if (want_gtk) + want_glib = 1; + + if (plug_is_enabled("puller")) + want_glib = 1; + + if (want_glib) { + require("libs/sul/glib", 0, 0); + if (!istrue(get("libs/sul/glib/presents"))) { + if (want_gtk) { + report_repeat("WARNING: Since GLIB is not found, disabling the GTK HID...\n"); + hook_custom_arg("disable-hid_gtk2_gdk", NULL); + hook_custom_arg("disable-hid_gtk2_gl", NULL); + hook_custom_arg("disable-hid_gtk3_cairo", NULL); + } + if (plug_is_enabled("puller")) { + report_repeat("WARNING: Since GLIB is not found, disabling the puller...\n"); + hook_custom_arg("disable-puller", NULL); + } + } + } + else { + report("No need for glib, skipping GLIB detection\n"); + put("libs/sul/glib/presents", "false"); + put("libs/sul/glib/cflags", ""); + put("libs/sul/glib/ldflags", ""); + } + + if (!istrue(get("libs/sul/glib/presents"))) { + /* Makefile templates will still reference these variables, they should be empty */ + put("libs/sul/glib/cflags", ""); + put("libs/sul/glib/ldflags", ""); + } + + calc_dialog_deps(); + + if (want_gd) { + require("libs/gui/gd/presents", 0, 0); + if (!istrue(get("libs/gui/gd/presents"))) { + report_repeat("WARNING: Since there's no libgd, disabling gd based exports (png, gcode)...\n"); + hook_custom_arg("disable-gd-gif", NULL); + hook_custom_arg("disable-gd-png", NULL); + hook_custom_arg("disable-gd-jpg", NULL); + hook_custom_arg("disable-export_png", NULL); + hook_custom_arg("disable-export_gcode", NULL); + want_gd = 0; + goto disable_gd_formats; + } + else { + require("libs/gui/gd/gdImagePng/presents", 0, 0); + require("libs/gui/gd/gdImageGif/presents", 0, 0); + require("libs/gui/gd/gdImageJpeg/presents", 0, 0); + require("libs/gui/gd/gdImageSetResolution/presents", 0, 0); + if (!istrue(get("libs/gui/gd/gdImagePng/presents"))) { + report_repeat("WARNING: libgd is installed, but its png code fails, some exporters will be compiled with reduced functionality; exporters affected: export_gcode\n"); + } + } + } + else { + put("libs/gui/gd/presents", sfalse); + disable_gd_formats:; + put("libs/gui/gd/gdImagePng/presents", sfalse); + put("libs/gui/gd/gdImageGif/presents", sfalse); + put("libs/gui/gd/gdImageJpeg/presents", sfalse); + } + + if ((!istrue(get("libs/script/fungw/presents"))) && plug_is_enabled("script")) { + report_repeat("WARNING: Since there's no system-installed fungw, disabling the script plugin...\n"); + hook_custom_arg("disable-script", NULL); + } + + /* generic utils for Makefiles */ + require("sys/ext_exe", 0, 1); + require("sys/sysid", 0, 1); + + /* options for config.h */ + require("sys/path_sep", 0, 1); + require("sys/types/size/*", 0, 1); + require("cc/rdynamic", 0, 0); + require("libs/snprintf", 0, 0); + require("libs/vsnprintf", 0, 0); + require("libs/fs/getcwd", 0, 0); + require("libs/fs/stat/macros/*", 0, 0); + + if (istrue(get("/local/pcb/want_dmalloc"))) { + require("libs/sul/dmalloc/*", 0, 1); + } + else { + put("libs/sul/dmalloc/presents", sfalse); + put("libs/sul/dmalloc/cflags", ""); + put("libs/sul/dmalloc/ldflags", ""); + } + + /* yacc/lex - are we able to regenerate languages? */ + if (istrue(get("/local/pcb/want_bison"))) { + require("parsgen/flex/*", 0, 0); + require("parsgen/bison/*", 0, 0); + if (!istrue(get("parsgen/flex/presents")) || !istrue(get("parsgen/bison/presents"))) + put("/local/pcb/want_parsgen", sfalse); + else + put("/local/pcb/want_parsgen", strue); + } + else { + report("Bison/flex are disabled, among with parser generation.\n"); + put("/local/pcb/want_parsgen", sfalse); + } + + + if (get("cc/rdynamic") == NULL) + put("cc/rdynamic", ""); + + /* plugin dependencies */ + plugin_deps(1); + + /* figure coordinate bits */ + { + int int_bits = safe_atoi(get("sys/types/size/signed_int")) * 8; + int long_bits = safe_atoi(get("sys/types/size/signed_long_int")) * 8; + int long_long_bits = safe_atoi(get("sys/types/size/signed_long_long_int")) * 8; + int int64_bits = safe_atoi(get("sys/types/size/uint64_t")) * 8; + const char *chosen, *postfix; + char tmp[64]; + int need_stdint = 0; + + if (want_coord_bits == int_bits) { postfix="U"; chosen = "int"; } + else if (want_coord_bits == long_bits) { postfix="UL"; chosen = "long int"; } + else if (want_coord_bits == int64_bits) { postfix="ULL"; chosen = "int64_t"; need_stdint = 1; } + else if (want_coord_bits == long_long_bits) { postfix="ULL"; chosen = "long long int"; } + else { + report("ERROR: can't find a suitable integer type for coord to be %d bits wide\n", want_coord_bits); + exit(1); + } + + sprintf(tmp, "((1%s<<%d)-1)", postfix, want_coord_bits - 1); + put("/local/pcb/coord_type", chosen); + put("/local/pcb/coord_max", tmp); + + chosen = NULL; + if (istrue(get("/local/pcb/debug"))) { /* debug: c89 */ + if (int64_bits >= 64) { + /* to suppress warnings on systems that support c99 but are forced to compile in c89 mode */ + chosen = "int64_t"; + need_stdint = 1; + } + } + + if (chosen == NULL) { /* non-debug, thus non-c89 */ + if (long_long_bits >= 64) chosen = "long long int"; + else if (long_bits >= 64) chosen = "long int"; + else chosen = "double"; + } + put("/local/pcb/long64", chosen); + if (need_stdint) + put("/local/pcb/include_stdint", "#include "); + } + + /* set cflags for C89 */ + put("/local/pcb/c89flags", ""); + if (istrue(get("/local/pcb/debug"))) { + + if ((target_ansi != NULL) && (*target_ansi != '\0')) { + append("/local/pcb/c89flags", " "); + append("/local/pcb/c89flags", target_ansi); + need_inl = 1; + } + if ((target_ped != NULL) && (*target_ped != '\0')) { + append("/local/pcb/c89flags", " "); + append("/local/pcb/c89flags", target_ped); + need_inl = 1; + } + } + + if (istrue(get("/local/pcb/profile"))) { + append("/local/pcb/cflags_profile", " "); + append("/local/pcb/cflags_profile", target_pg); + append("/local/pcb/cflags_profile", " "); + append("/local/pcb/cflags_profile", target_no_pie); + } + + if (!istrue(get("cc/inline"))) + need_inl = 1; + + if (need_inl) { + /* disable inline for C89 */ + append("/local/pcb/c89flags", " "); + append("/local/pcb/c89flags", "-Dinline= "); + } + + /* restore the original CFLAGS, without the effects of --debug, so Makefiles can decide when to use what cflag (c99 needs different ones) */ + put("/target/cc/cflags", get("/local/cc_flags_save")); + + return 0; +} + +#ifdef GENCALL +/* If enabled, generator implements ###call *### and generator_callback is + the callback function that will be executed upon ###call### */ +void generator_callback(char *cmd, char *args) +{ + printf("* generator_callback: '%s' '%s'\n", cmd, args); +} +#endif + +static void plugin_stat(const char *header, const char *path, const char *name) +{ + const char *val = get(path); + + if (*header == '#') /* don't print hidden plugins */ + return; + + printf(" %-32s", header); + + if (val == NULL) + printf("??? (NULL) "); + else if (strcmp(val, sbuildin) == 0) + printf("yes, buildin "); + else if (strcmp(val, splugin) == 0) + printf("yes, PLUGIN "); + else + printf("no "); + + printf(" [%s]\n", name); +} + +static void print_sum_setting_or(const char *node, const char *desc, int or) +{ + const char *res, *state; + state = get(node); + if (or) + res = "enabled (implicit)"; + else if (istrue(state)) + res = "enabled"; + else if (isfalse(state)) + res = "disabled"; + else + res = "UNKNOWN - disabled?"; + printf("%-55s %s\n", desc, res); +} + +static void print_sum_setting(const char *node, const char *desc) +{ + print_sum_setting_or(node, desc, 0); +} + +static void print_sum_cfg_val(const char *node, const char *desc) +{ + const char *state = get(node); + printf("%-55s %s\n", desc, state); +} + +/* Runs after detection hooks, should generate the output (Makefiles, etc.) */ +int hook_generate() +{ + char *next, *rev = "non-svn", *curr, *tmp; + int generr = 0; + int res = 0; + char apiver[32]; + long r = 0; + int v1, v2, v3; + + tmp = svn_info(0, "../src", "Revision:"); + if (tmp != NULL) { + r = strtol(tmp, NULL, 10); + rev = str_concat("", "svn r", tmp, NULL); + free(tmp); + } + strcpy(apiver, version); + curr = apiver; next = strchr(curr, '.'); *next = '\n'; + v1 = atoi(curr); + curr = next+1; next = strchr(curr, '.'); *next = '\n'; + v2 = atoi(curr); + v3 = atoi(next+1); + sprintf(apiver, "%01d%01d%02d%05ld", v1, v2, v3, r); + + logprintf(0, "scconfig generate version info: version='%s' rev='%s'\n", version, rev); + put("/local/revision", rev); + put("/local/version", version); + put("/local/apiver", apiver); + put("/local/pup/sccbox", "../../scconfig/sccbox"); + + printf("\n"); + + printf("Generating Makefile.conf (%d)\n", generr |= tmpasm("..", "Makefile.conf.in", "Makefile.conf")); + + printf("Generating pcb/Makefile (%d)\n", generr |= tmpasm("../src", "Makefile.in", "Makefile")); + + printf("Generating util/gsch2pcb-rnd/Makefile (%d)\n", generr |= tmpasm("../util", "gsch2pcb-rnd/Makefile.in", "gsch2pcb-rnd/Makefile")); + + printf("Generating config.h (%d)\n", generr |= tmpasm("..", "config.h.in", "config.h")); + + printf("Generating compat_inc.h (%d)\n", generr |= tmpasm("../src", "compat_inc.h.in", "compat_inc.h")); + + printf("Generating opengl.h (%d)\n", generr |= tmpasm("../src_plugins/lib_hid_gl", "opengl.h.in", "opengl.h")); + + printf("Generating fuse_includes.h (%d)\n", generr |= tmpasm("../src_plugins/export_vfs_fuse", "fuse_includes.h.in", "fuse_includes.h")); + + generr |= pup_hook_generate("../src_3rd/puplug"); + + if (!istrue(get("libs/script/fungw/presents"))) + generr |= fungw_hook_generate("../src_3rd/libfungw"); + + + if (!generr) { + printf("\n\n"); + printf("=====================\n"); + printf("Configuration summary\n"); + printf("=====================\n"); + + print_sum_setting("/local/pcb/want_parsgen", "Regenerating languages with bison & flex"); + print_sum_setting("/local/pcb/debug", "Compilation for debugging"); + print_sum_setting_or("/local/pcb/symbols", "Include debug symbols", istrue(get("/local/pcb/debug"))); + print_sum_setting("libs/sul/dmalloc/presents", "Compile with dmalloc"); + print_sum_cfg_val("/local/pcb/coord_bits", "Coordinate type bits"); + print_sum_cfg_val("/local/pcb/dot_pcb_rnd", ".pcb_rnd config dir under $HOME"); + +#undef plugin_def +#undef plugin_header +#undef plugin_dep +#define plugin_def(name, desc, default_, all_) plugin3_stat(name, desc) +#define plugin_header(sect) printf(sect); +#define plugin_dep(plg, on, hidlib) +#include "plugins.h" + + if (repeat != NULL) { + printf("\n%s\n", repeat); + } + + if (all_plugin_check_explicit()) { + printf("\nNevertheless the configuration is complete, if you accept these differences\nyou can go on compiling.\n\n"); + res = 1; + } + else + printf("\nConfiguration complete, ready to compile.\n\n"); + + { + FILE *f; + f = fopen("Rev.stamp", "w"); + fprintf(f, "%d", myrev); + fclose(f); + } + + } + else { + fprintf(stderr, "Error generating some of the files\n"); + res = 1; + } + + return res; +} + +/* Runs before everything is uninitialized */ +void hook_preuninit() +{ +} + +/* Runs at the very end, when everything is already uninitialized */ +void hook_postuninit() +{ +} + Index: tags/2.1.2/scconfig/menucfg.c =================================================================== --- tags/2.1.2/scconfig/menucfg.c (nonexistent) +++ tags/2.1.2/scconfig/menucfg.c (revision 24813) @@ -0,0 +1,69 @@ +#include +#include +#include "default/hooks.h" +#include "default/libs.h" +#include "default/main_custom_args.h" +#include "default/main_lib.h" +#include "menulib/scmenu.h" +#include "util/arg_auto_set.h" +#include "util/arg_auto_menu.h" + + +void re_fail(char *s, char c) +{ + fprintf(stderr, "Regex error: %s [opcode %o]\n", s, c); + abort(); +} + +int cb_configure(scm_ctx_t *ctx, scm_menu_t *menu, scm_win_t *w, int selection) +{ + printf("configure!!\n"); + sleep(1); + return -1; +} + + + +scm_menu_entry_t me_hid_gtk[8] = {{SCM_TERMINATOR, NULL, NULL, NULL, NULL, NULL, 0}}; +scm_menu_entry_t me_hid_lesstif[8] = {{SCM_TERMINATOR, NULL, NULL, NULL, NULL, NULL, 0}}; +scm_menu_entry_t me_export[8] = {{SCM_TERMINATOR, NULL, NULL, NULL, NULL, NULL, 0}}; +scm_menu_entry_t me_autorouter[8] = {{SCM_TERMINATOR, NULL, NULL, NULL, NULL, NULL, 0}}; +scm_menu_entry_t me_all_settings[32] = {{SCM_TERMINATOR, NULL, NULL, NULL, NULL, NULL, 0}}; + +scm_menu_entry_t me_settings[] = { + {SCM_SUBMENU, NULL, "HID: gtk", "gtk settings -->", NULL, me_hid_gtk, SCM_AUTO_RUN}, + {SCM_SUBMENU, NULL, "HID: lesstif", "lesstif settings -->", NULL, me_hid_lesstif, SCM_AUTO_RUN}, + {SCM_SUBMENU, NULL, "HID: exporters", "export format settings -->", NULL, me_export, SCM_AUTO_RUN}, + {SCM_SUBMENU, NULL, "auto routers", "autorouter settings -->", NULL, me_autorouter, SCM_AUTO_RUN}, + {SCM_EMPTY, NULL, NULL, NULL, NULL, 0}, + {SCM_SUBMENU, NULL, "all", "all settings at once -->", NULL, me_all_settings, SCM_AUTO_RUN}, + {SCM_TERMINATOR, NULL, NULL, NULL, NULL, NULL, 0} +}; + +scm_menu_entry_t me_main[] = { + {SCM_SUBMENU, NULL, "Edit settings", "Edit user configurable settings -->", NULL, me_settings, SCM_AUTO_RUN}, + {SCM_SUBMENU, NULL, "Manual detection", "Run detection of individual libs -->", NULL, NULL, SCM_AUTO_RUN}, + {SCM_SUBMENU_CB, NULL, "Configure pcb-rnd", "Run the configuration process -->", NULL, cb_configure, SCM_AUTO_RUN}, + {SCM_EMPTY, NULL, NULL, NULL, NULL, 0}, + {SCM_KEY_VALUE, NULL, "Exit & save", "Exit with saving the settings", NULL, NULL, SCM_AUTO_RUN}, + {SCM_KEY_VALUE, NULL, "Exit", "Exit without saving the settings", NULL, NULL, SCM_AUTO_RUN}, + {SCM_TERMINATOR, NULL, NULL, NULL, NULL, NULL, 0} +}; + +extern const arg_auto_set_t disable_libs[] ; + +int main() +{ + scm_ctx_t ctx; + + main_init(); + + append_settings_auto_set(me_export, 32, disable_libs, "-gd", NULL, "^disable-", SCM_SUBMENU, 0); + + scm_init(&ctx); + scm_menu_autowin(&ctx, "main menu", me_main); + + main_uninit(); + + return 0; +} Index: tags/2.1.2/scconfig/plugin_3state.h =================================================================== --- tags/2.1.2/scconfig/plugin_3state.h (nonexistent) +++ tags/2.1.2/scconfig/plugin_3state.h (revision 24813) @@ -0,0 +1,63 @@ +/* 3-state plugin system; possible states of each plugin, stored in + /local/pcb/PLUGIN_NAME/controls: + "disable" = do not compile it at all + "buildin" = enable, static link into the executable + "plugin" = enable, make it a dynamic link library (runtime load plugin) +*/ + +#define sdisable "disable" +#define sbuildin "buildin" +#define splugin "plugin" + + +/* Macros to check the state */ + +#define plug_eq(name, val) \ + ((get("/local/pcb/" name "/controls") != NULL) && (strcmp(get("/local/pcb/" name "/controls"), val) == 0)) + +#define plug_is_enabled(name) (plug_eq(name, splugin) || plug_eq(name, sbuildin)) +#define plug_is_disabled(name) (plug_eq(name, sdisabled)) +#define plug_is_buildin(name) (plug_eq(name, sbuildin)) +#define plug_is_plugin(name) (plug_eq(name, splugin)) + +/* auto-set tables to change control to the desired value */ +const arg_auto_set_node_t arg_disable[] = { + {"controls", sdisable}, + {"explicit", sdisable}, + {NULL, NULL} +}; + +const arg_auto_set_node_t arg_Disable[] = { + {"controls", sdisable}, + {NULL, NULL} +}; + +const arg_auto_set_node_t arg_buildin[] = { + {"controls", sbuildin}, + {"explicit", sbuildin}, + {NULL, NULL} +}; + +const arg_auto_set_node_t arg_plugin[] = { + {"controls", splugin}, + {"explicit", splugin}, + {NULL, NULL} +}; + + +/* plugin_def implementation to create CLI args */ +#define plugin3_args(name, desc) \ + {"disable-" name, "/local/pcb/" name, arg_disable, "$do not compile " desc}, \ + {"Disable-" name, "/local/pcb/" name, arg_Disable, NULL }, \ + {"buildin-" name, "/local/pcb/" name, arg_buildin, "$static link " desc " into the executable"}, \ + {"plugin-" name, "/local/pcb/" name, arg_plugin, "$" desc " is a dynamic loadable plugin"}, + + +/* plugin_def implementation to set default state */ +#define plugin3_default(name, default_) \ + db_mkdir("/local/pcb/" name); \ + put("/local/pcb/" name "/controls", default_); + +/* plugin_def implementation to print a report with the final state */ +#define plugin3_stat(name, desc) \ + plugin_stat(desc, "/local/pcb/" name "/controls", name); Index: tags/2.1.2/scconfig/plugins.h =================================================================== --- tags/2.1.2/scconfig/plugins.h (nonexistent) +++ tags/2.1.2/scconfig/plugins.h (revision 24813) @@ -0,0 +1,173 @@ +/****************************************************************************** + Auto-generated by trunk/src_plugins/map_plugins.sh - do NOT edit, + run make map_plugins in trunk/src/ - to change any of the data below, + edit trunk/src_plugins/PLUGIN/PLUGIN.pup +******************************************************************************/ + +plugin_header("\nLibrary plugins:\n") +plugin_def("lib_compat_help", "#compatibility helper functions", sbuildin, 1) +plugin_def("lib_gensexpr", "#s-expression library", sdisable, 0) +plugin_def("lib_gtk_common", "all-hid_gtk common code", sdisable, 0) +plugin_def("lib_gtk_hid", "hid_gtk generic part", sdisable, 0) +plugin_def("lib_hid_common", "all-hid common code", sdisable, 0) +plugin_def("lib_hid_gl", "openGL rendering", sdisable, 0) +plugin_def("lib_legacy_func", "legacy functions", sbuildin, 1) +plugin_def("lib_netmap", "map nets and objects", sdisable, 0) +plugin_def("lib_polyhelp", "polygon helpers", sbuildin, 1) +plugin_def("lib_vfs", "fetch data for VFS export", sdisable, 0) + +plugin_header("\nFeature plugins:\n") +plugin_def("acompnet", "net auto-completion", sdisable, 1) +plugin_def("act_draw", "action wrappers for drawing", sbuildin, 1) +plugin_def("ar_cpcb", "autoroute with c-pcb", sbuildin, 1) +plugin_def("asm", "assembly GUI", sbuildin, 1) +plugin_def("autocrop", "crop board to fit objects", sbuildin, 1) +plugin_def("autoplace", "auto place components", sbuildin, 1) +plugin_def("autoroute", "the original autorouter", sbuildin, 1) +plugin_def("diag", "diagnostic acts. for devs", sdisable, 1) +plugin_def("dialogs", "HID-independent GUI dialogs", sdisable, 1) +plugin_def("distaligntext", "distribute and align text", sbuildin, 1) +plugin_def("distalign", "distribute and align objs", sbuildin, 1) +plugin_def("djopt", "djopt board optimization", sbuildin, 1) +plugin_def("draw_csect", "draw cross-section (layers)", sdisable, 1) +plugin_def("draw_fab", "fab layer in some exports", sbuildin, 1) +plugin_def("draw_fontsel", "font selection GUI", sdisable, 1) +plugin_def("drc_orig", "the original DRC code", sbuildin, 1) +plugin_def("expfeat", "experimental features", sdisable, 1) +plugin_def("extedit", "edit with external program", sbuildin, 1) +plugin_def("fontmode", "font editor", sbuildin, 1) +plugin_def("jostle", "push lines out of the way", sbuildin, 1) +plugin_def("loghid", "diagnostics: log HID calls", sdisable, 1) +plugin_def("millpath", "calculate toolpath for milling", sdisable, 1) +plugin_def("mincut", "minimal cut shorts", sbuildin, 1) +plugin_def("oldactions", "old/obsolete actions", sdisable, 1) +plugin_def("polycombine", "combine selected polygons", sbuildin, 1) +plugin_def("polystitch", "stitch polygon at cursor", sbuildin, 1) +plugin_def("propedit", "object property editor", sbuildin, 1) +plugin_def("puller", "puller", sbuildin, 1) +plugin_def("query", "query language", sbuildin, 1) +plugin_def("renumber", "renumber action", sbuildin, 1) +plugin_def("report", "report actions", sbuildin, 1) +plugin_def("rubberband_orig", "the original rubberband", sbuildin, 1) +plugin_def("script", "fungw turing complete scripting", sbuildin, 1) +plugin_def("serpentine", "Serpentine creation", sdisable, 0) +plugin_def("shand_cmd", "command shorthands", sbuildin, 1) +plugin_def("shape", "generate regular shapes", sbuildin, 1) +plugin_def("sketch_route", "assisted semi-auto-routing", sdisable, 1) +plugin_def("smartdisperse", "netlist based dispenser", sbuildin, 1) +plugin_def("stroke", "mouse gestures", sbuildin, 1) +plugin_def("teardrops", "draw teardrops on pins", sbuildin, 1) +plugin_def("vendordrill", "vendor drill mapping", sbuildin, 1) + +plugin_header("\nFootprint backends:\n") +plugin_def("fp_board", "footprint library from boards", sbuildin, 1) +plugin_def("fp_fs", "filesystem footprints", sbuildin, 1) +plugin_def("fp_wget", "web footprints", sbuildin, 1) + +plugin_header("\nImport plugins:\n") +plugin_def("import_calay", "import calay .net", sbuildin, 1) +plugin_def("import_dsn", "specctra .dsn importer", sbuildin, 1) +plugin_def("import_edif", "import edif", sbuildin, 1) +plugin_def("import_fpcb_nl", "import freepcb netlist", sbuildin, 1) +plugin_def("import_hpgl", "import HP-GL plot files", sbuildin, 1) +plugin_def("import_ipcd356", "import IPC-D-356 Netlist", sbuildin, 1) +plugin_def("import_ltspice", "import ltspice .net+.asc", sbuildin, 1) +plugin_def("import_mentor_sch","import mentor graphics sch", sbuildin, 1) +plugin_def("import_mucs", "import mucs routing", sbuildin, 1) +plugin_def("import_netlist", "import netlist", sbuildin, 1) +plugin_def("import_sch", "import sch", sbuildin, 1) +plugin_def("import_tinycad", "import tinycad .net", sbuildin, 1) +plugin_def("import_ttf", "import ttf glyphs", sbuildin, 1) + +plugin_header("\nExport plugins:\n") +plugin_def("cam", "cam/job based export", sbuildin, 1) +plugin_def("ddraft", "2D drafting helper", sbuildin, 1) +plugin_def("export_bboard", "breadboard pcb_exporter", sdisable, 0) +plugin_def("export_bom", "bom pcb_exporter", sbuildin, 1) +plugin_def("export_dsn", "specctra .dsn pcb_exporter", sbuildin, 1) +plugin_def("export_dxf", "DXF pcb_exporter", sbuildin, 1) +plugin_def("export_fidocadj", "FidoCadJ .fcd pcb_exporter", sbuildin, 1) +plugin_def("export_gcode", "gcode pcb_exporter", sbuildin, 1) +plugin_def("export_gerber", "Gerber pcb_exporter", sbuildin, 1) +plugin_def("export_ipcd356", "IPC-D-356 Netlist pcb_exporter", sbuildin, 1) +plugin_def("export_lpr", "lpr pcb_exporter (printer)", sbuildin, 1) +plugin_def("export_oldconn", "old connection data format", sbuildin, 1) +plugin_def("export_openems", "openems exporter", sdisable, 1) +plugin_def("export_openscad", "openscad pcb_exporter", sbuildin, 1) +plugin_def("export_png", "png/gif/jpg pcb_exporter", sbuildin, 1) +plugin_def("export_ps", "postscript pcb_exporter", sbuildin, 1) +plugin_def("export_stat", "export board statistics", sbuildin, 1) +plugin_def("export_svg", "SVG pcb_exporter", sbuildin, 1) +plugin_def("export_test", "dummy test pcb_exporter", sdisable, 1) +plugin_def("export_vfs_fuse", "FUSE VFS server", sdisable, 1) +plugin_def("export_vfs_mc", "GNU mc VFS server", sdisable, 1) +plugin_def("export_xy", "xy (centroid) pcb_exporter", sbuildin, 1) + +plugin_header("\nIO plugins (file formats):\n") +plugin_def("io_autotrax", "autotrax (freeware PCB CAD)", sbuildin, 1) +plugin_def("io_dsn", "specctra .dsn", sdisable, 1) +plugin_def("io_eagle", "Eagle's xml and binary formats", sbuildin, 1) +plugin_def("io_hyp", "hyperlynx .hyp loader", sbuildin, 1) +plugin_def("io_kicad_legacy", "Kicad's legacy format", sbuildin, 1) +plugin_def("io_kicad", "Kicad's s-expr format", sbuildin, 1) +plugin_def("io_lihata", "lihata board format", sbuildin, 1) +plugin_def("io_mentor_cell", "Mentor Graphics cell footprints", sdisable, 1) +plugin_def("io_pcb", "the original pcb format", sbuildin, 1) +plugin_def("io_tedax", "tEDAx (Trivial EDA eXchange)", sbuildin, 1) + +plugin_header("\nHID plugins:\n") +plugin_def("hid_batch", "batch process (no-gui HID)", sbuildin, 1) +plugin_def("hid_gtk2_gdk", "GTK2 GUI, software render", sbuildin, 1) +plugin_def("hid_gtk2_gl", "GTK2 GUI, opengl render", sbuildin, 1) +plugin_def("hid_gtk3_cairo", "#GTK3 GUI, cairo render", sdisable, 0) +plugin_def("hid_lesstif", "the lesstif gui", sbuildin, 1) +plugin_def("hid_remote", "remote HID server", sdisable, 0) + + +plugin_dep("ar_cpcb", "lib_compat_help", 0) +plugin_dep("ar_cpcb", "lib_gensexpr", 0) +plugin_dep("ar_cpcb", "lib_netmap", 0) +plugin_dep("autoroute", "lib_compat_help", 0) +plugin_dep("dialogs", "draw_csect", 0) +plugin_dep("dialogs", "draw_fontsel", 0) +plugin_dep("draw_fab", "report", 0) +plugin_dep("export_fidocadj", "lib_compat_help", 0) +plugin_dep("export_ipcd356", "lib_compat_help", 0) +plugin_dep("export_lpr", "export_ps", 0) +plugin_dep("export_openems", "lib_polyhelp", 0) +plugin_dep("export_openscad", "lib_polyhelp", 0) +plugin_dep("export_ps", "lib_compat_help", 0) +plugin_dep("export_vfs_fuse", "lib_vfs", 0) +plugin_dep("export_vfs_mc", "lib_vfs", 0) +plugin_dep("export_xy", "export_bom", 0) +plugin_dep("extedit", "io_lihata", 0) +plugin_dep("fp_wget", "fp_fs", 0) +plugin_dep("hid_gtk2_gdk", "lib_gtk_common", 01) +plugin_dep("hid_gtk2_gdk", "lib_gtk_hid", 01) +plugin_dep("hid_gtk2_gl", "lib_gtk_common", 0) +plugin_dep("hid_gtk2_gl", "lib_gtk_hid", 0) +plugin_dep("hid_gtk2_gl", "lib_hid_gl", 0) +plugin_dep("hid_gtk3_cairo", "lib_gtk_common", 0) +plugin_dep("hid_gtk3_cairo", "lib_gtk_hid", 0) +plugin_dep("hid_lesstif", "dialogs", 0) +plugin_dep("hid_lesstif", "lib_hid_common", 0) +plugin_dep("import_dsn", "lib_compat_help", 0) +plugin_dep("import_ipcd356", "lib_compat_help", 0) +plugin_dep("import_mentor_sch", "lib_gensexpr", 0) +plugin_dep("import_mucs", "lib_compat_help", 0) +plugin_dep("io_autotrax", "lib_polyhelp", 0) +plugin_dep("io_dsn", "lib_gensexpr", 0) +plugin_dep("io_hyp", "lib_netmap", 0) +plugin_dep("io_kicad", "lib_compat_help", 0) +plugin_dep("io_kicad", "lib_gensexpr", 0) +plugin_dep("io_kicad", "shape", 0) +plugin_dep("io_kicad_legacy", "io_kicad", 0) +plugin_dep("io_lihata", "lib_compat_help", 0) +plugin_dep("io_pcb", "lib_compat_help", 0) +plugin_dep("io_tedax", "lib_compat_help", 0) +plugin_dep("io_tedax", "lib_netmap", 0) +plugin_dep("lib_gtk_common", "dialogs", 0) +plugin_dep("lib_gtk_hid", "dialogs", 0) +plugin_dep("lib_gtk_hid", "lib_hid_common", 0) +plugin_dep("lib_vfs", "propedit", 0) +plugin_dep("millpath", "lib_polyhelp", 0) Index: tags/2.1.2/scconfig/revtest.c =================================================================== --- tags/2.1.2/scconfig/revtest.c (nonexistent) +++ tags/2.1.2/scconfig/revtest.c (revision 24813) @@ -0,0 +1,85 @@ +#include +#include +#include +#include "Rev.h" + +const char *act_names[] = { + "distclean", + "configure", + "make clean", + NULL +}; + +const char *act_desc[] = { + "run 'make distclean' in trunk/", + "rerun ./configure", + "run 'make clean' in trunk/", + NULL +}; + +int act_needed[16]; + +int main(int argc, char *argv[]) +{ + char line[8192]; + int res = 0, stamp = 0, banner = 0; + FILE *f = NULL; + + if (argc > 1) { + f = fopen(argv[1], "r"); + } + if (f != NULL) { + fscanf(f, "%d", &stamp); + fclose(f); + } + + while(fgets(line, sizeof(line), stdin) != NULL) { + char *end; + int rev; + + if (*line == '#') + continue; + rev = strtol(line, &end, 10); + if (*end != '\t') + continue; + + if (rev > stamp) { + char *act, *txt; + const char **a; + int idx; + res = 1; + act = end; + while(*act == '\t') + act++; + txt = strchr(act, '\t'); + if (txt != NULL) { + *txt = '\0'; + txt++; + while(*txt == '\t') + txt++; + } + if (!banner) { + fprintf(stderr, "\nYour source tree is stale (last configured after config-milestone r%d).\nRecent new features:\n", stamp); + banner = 1; + } + fprintf(stderr, "\nr%d: %s\n", rev, txt); + for(idx = 0, a = act_names; *a != NULL; idx++, a++) + if (strstr(act, *a) != NULL) + act_needed[idx]++; + } + } + + if (res) { + const char **a; + int idx; + + fprintf(stderr, "(Stamp: %d myrev: %d)\n", stamp, myrev); + fprintf(stderr, "\nBefore running make, please do the following actions in this order:\n"); + for(idx = 0, a = act_names; *a != NULL; idx++, a++) + if (act_needed[idx]) + fprintf(stderr, " %s\n", act_desc[idx]); + fprintf(stderr, "\n"); + } + + return res; +} Index: tags/2.1.2/scconfig/template/cdep.tmpasm =================================================================== --- tags/2.1.2/scconfig/template/cdep.tmpasm (nonexistent) +++ tags/2.1.2/scconfig/template/cdep.tmpasm (revision 24813) @@ -0,0 +1,60 @@ +# Generate Makefile code that can generate Makefile.dep +# Arguments: +# /local/dep/CFLAGS CFLAGS used for compiling +# /local/dep/SRCS list of c soures +# /local/pcb/DEPDEPS targets make dep should generate first + +sortuniq /local/pcb/DEPDEPS_SORTED /local/pcb/DEPDEPS + +print [@ + +### generate dependencies (requires gcc) ### +FORCE: + +include Makefile.dep + +DEPDEPS=@/local/pcb/DEPDEPS_SORTED@ + +dep: FORCE $(DEPDEPS) + make -f Makefile.depgen PLUGDIR=$(PLUGDIR) SRC_3RD_DIR=$(SRC_3RD_DIR) +@] + +append /local/dep/CFLAGS {-D_PCB_DEP_} +gsub /local/dep/CFLAGS {-I} {-isystem } +gsub /local/dep/CFLAGS {-isystem [.][.]} {-I ..} +gsub /local/dep/CFLAGS {-isystem [.]} {-I .} +sortuniq /local/dep/SRCS_SORTED /local/dep/SRCS + +redir {Makefile.depgen} + +print [@ +# Generated by configure - DO NOT EDIT + +# Calculate dependencies, assuming all generated files present and +# SRC_3RD_DIR and PLUGDIR are set + +all: + echo "### Generated file, do not edit, run make dep ###" > Makefile.dep + echo "" >> Makefile.dep +@] + +foreach /local/c in /local/dep/SRCS_SORTED + put /local/o /local/c + sub {/local/o} {.c$} {.o} + sub {/local/c} {.o$} {.c} + switch /local/c + case {/src_plugins/} end + case {$(PLUGDIR)} + print [@ gcc -MT @/local/o@ -MM @/local/c@ @/local/dep/CFLAGS@ @/local/pcb/DEPCFLAGS@ >> Makefile.dep +@]; end + case {$(SRC_3RD_DIR)} + print [@ gcc -MT @/local/o@ -MM @/local/c@ @/local/dep/CFLAGS@ >> Makefile.dep +@]; end + case {../src_3rd/} + print [@ gcc -MT @/local/o@ -MM @/local/c@ @/local/dep/CFLAGS@ >> Makefile.dep +@]; end + + default print [@ gcc -MM @/local/c@ @/local/dep/CFLAGS@ >> Makefile.dep +@]; end + end +end Index: tags/2.1.2/scconfig/template/comp_var.tmpasm =================================================================== --- tags/2.1.2/scconfig/template/comp_var.tmpasm (nonexistent) +++ tags/2.1.2/scconfig/template/comp_var.tmpasm (revision 24813) @@ -0,0 +1,31 @@ +# Generate Makefile code to compile .c -> .o +# Arguments: +# /local/comp/OBJS list of .o files (assuming each have at least a .c) +# /local/comp/OBJS_C99 list of .o files (assuming each have at least a .c) for non-c89 compilation + +put /local/comp/output {} +append /local/comp/CFLAGS {} + +foreach /local/o in /local/comp/OBJS +put /local/c /local/o +sub /local/c {.o$} {.c} +append /local/comp/output [@ +@/local/o@: @/local/c@ + $(CC) -c $(C89FLAGS) @/local/comp/CFLAGS@ -o @/local/o@ $< +@] +end + +append /local/comp/OBJS_C99 {} +foreach /local/o in /local/comp/OBJS_C99 +put /local/c /local/o +sub /local/c {.o$} {.c} +append /local/comp/output [@ +@/local/o@: @/local/c@ + $(CC) -c $(CFLAGS) @/local/comp/CFLAGS@ -o @/local/o@ $< +@] +end + +put /local/comp/OBJS {} +put /local/comp/OBJS_C99 {} +put /local/comp/CFLAGS {} + Index: tags/2.1.2/scconfig/template/compile.tmpasm =================================================================== --- tags/2.1.2/scconfig/template/compile.tmpasm (nonexistent) +++ tags/2.1.2/scconfig/template/compile.tmpasm (revision 24813) @@ -0,0 +1,60 @@ +# Generate Makefile code to compile .c -> .o +# Arguments: +# /local/comp/OBJS list of .o files (assuming each have at least a .c) +# /local/comp/OBJS_C99 list of .o files (assuming each have at least a .c), for non-c89 compilation + +print { +### explicit rules for .c -> .o ### +} + +append /local/comp/CFLAGS {} + +foreach /local/o in /local/comp/OBJS +put /local/c /local/o +sub /local/c {.o$} {.c} +switch /local/c + case {.*_y[.]c} + put /local/extinc [@ -I@/local/c@@] + sub /local/extinc {/[^/]*$} {} + end + case {.*_l[.]c} + put /local/extinc [@ -I@/local/c@@] + sub /local/extinc {/[^/]*$} {} + end + default + put /local/extinc {} + end +end +print [@ +@/local/o@: @/local/c@ + $(CC) -c $(C89FLAGS) @/local/comp/CFLAGS@@/local/extinc@ -o @/local/o@ $< +@] +end + +append /local/comp/OBJS_C99 {} +foreach /local/o in /local/comp/OBJS_C99 +put /local/c /local/o +sub /local/c {.o$} {.c} +switch /local/c + case {.*_y[.]c} + put /local/extinc [@ -I@/local/c@@] + sub /local/extinc {/[^/]*$} {} + end + case {.*_l[.]c} + put /local/extinc [@ -I@/local/c@@] + sub /local/extinc {/[^/]*$} {} + end + default + put /local/extinc {} + end +end +print [@ +@/local/o@: @/local/c@ + $(CC) -c $(CFLAGS) @/local/comp/CFLAGS@@/local/extinc@ -o @/local/o@ $< +@] +end + +put /local/comp/OBJS {} +put /local/comp/OBJS_C99 {} +put /local/comp/CFLAGS {} + Index: tags/2.1.2/scconfig/template/debug.tmpasm =================================================================== --- tags/2.1.2/scconfig/template/debug.tmpasm (nonexistent) +++ tags/2.1.2/scconfig/template/debug.tmpasm (revision 24813) @@ -0,0 +1,10 @@ +# append debug or production flags to CFLAGS, depending on the global debug flag + +if /local/pcb/debug then + append /local/pcb/CFLAGS [@ -g -O0 @?cc/argstd/Wall@ @] +else + if /local/pcb/symbols then + append /local/pcb/CFLAGS [@ -g @] + end + append /local/pcb/CFLAGS { -O3 -DNDEBUG } +end Index: tags/2.1.2/scconfig/template/plugin_conf.tmpasm =================================================================== --- tags/2.1.2/scconfig/template/plugin_conf.tmpasm (nonexistent) +++ tags/2.1.2/scconfig/template/plugin_conf.tmpasm (revision 24813) @@ -0,0 +1,18 @@ +# explicit conf_fields.h generation rules + +switch /local/pcb/mod/CONF + case {^$} end + default + put /local/pcb/mod/CONFOUT /local/pcb/mod/CONF + sub {/local/pcb/mod/CONFOUT} {.h$} {_fields.h} + append /local/pcb/CLEANFILES /local/pcb/mod/CONFOUT + append /local/pcb/DEPDEPS /local/pcb/mod/CONFOUT + append /local/pcb/RULES [@ +# conf generation for @/local/pcb/mod@ '@/local/pcb/mod/CONF@' +@/local/pcb/mod/CONFOUT@: @/local/pcb/mod/CONF@ + AWK=@/host/fstools/awk@ ../scconfig/gen_conf.sh < @/local/pcb/mod/CONF@ > @/local/pcb/mod/CONFOUT@ +@] + end +end + +put /local/pcb/mod/CONF {} Index: tags/2.1.2/scconfig/template/plugin_intconf.tmpasm =================================================================== --- tags/2.1.2/scconfig/template/plugin_intconf.tmpasm (nonexistent) +++ tags/2.1.2/scconfig/template/plugin_intconf.tmpasm (revision 24813) @@ -0,0 +1,30 @@ +# Set up internal embedde dconfig +# Input: /local/pcb/mod/CONFFILE is the file name of the conf file (without path) +# /local/pcb/mod/CONFVAR is the variable name to use in conf_internal.c + +switch ?/local/pcb/mod/CONFFILE +case {...} +put /local/pcb/MCFG [@$(PLUGDIR)/@/local/pcb/mod@/@/local/pcb/mod/CONFFILE@@] +put /local/pcb/ICFG [@$(PLUGDIR)/@/local/pcb/mod@/conf_internal.c@] + +append /local/pcb/DEPDEPS [@ @/local/pcb/ICFG@ @] +append /local/pcb/DISTCLEANFILES [@ @/local/pcb/ICFG@ @] +append /local/pcb/RULES [@ +@/local/pcb/ICFG@: @/local/pcb/MCFG@ $(CQUOTE) + $(CQUOTE) -n @/local/pcb/mod/CONFVAR@ < @/local/pcb/MCFG@ > @/local/pcb/ICFG@ +@] + + +switch /local/pcb/mod/enabled + case {1} + append /local/pcb/rules/install_ [@ + $(SCCBOX) $(HOW) "@/local/pcb/MCFG@" "$(DATADIR)/@/local/pcb/mod/CONFFILE@"@] + end + default end; +end + +end +default +end +end + Index: tags/2.1.2/scconfig/template/plugin_sphash.tmpasm =================================================================== --- tags/2.1.2/scconfig/template/plugin_sphash.tmpasm (nonexistent) +++ tags/2.1.2/scconfig/template/plugin_sphash.tmpasm (revision 24813) @@ -0,0 +1,39 @@ +# explicit rules: .sphash -> .c +# Space separated list of .sphash input files +# Optional: aux data fileds: $(PLUGDIR)/query/consts.sphash::long:int:val; +switch ?/local/pcb/mod/SPHASH + case {^$} end + default + foreach /local/nn in /local/pcb/mod/SPHASH + put /local/n /local/nn + sub {/local/n} {::.*$} {} + put /local/bn /local/n + sub {/local/bn} {.[^.]*$} {} + put /local/pr /local/bn + sub {/local/pr} {^.*/} {} + switch /local/nn + case {::} + put /local/aux /local/nn + sub {/local/aux} {^.*::} {} + gsub {/local/aux} {:} { } + sub {/local/aux} {^} {--aux "} + append {/local/aux} {"} + end + default + put /local/aux {} + end + end + append /local/pcb/RULES [@ +# sphash for @/local/pcb/mod@ +@/local/bn@_sphash.c @/local/bn@_sphash.h: $(SPHASH) @/local/n@ + $(SPHASH) @/local/aux@ --prefix @/local/pcb/mod@_@/local/pr@ --out @/local/bn@_sphash < @/local/n@ +@] + append /local/pcb/CLEANFILES [@@/local/bn@_sphash.c@] + append /local/pcb/CLEANFILES [@@/local/bn@_sphash.h@] + append /local/pcb/DEPDEPS [@@/local/bn@_sphash.c@] + append /local/pcb/DEPDEPS [@@/local/bn@_sphash.h@] + end + end +end + +put /local/pcb/mod/SPHASH {} Index: tags/2.1.2/scconfig =================================================================== --- tags/2.1.2/scconfig (nonexistent) +++ tags/2.1.2/scconfig (revision 24813) Property changes on: tags/2.1.2/scconfig ___________________________________________________________________ Added: svn:externals ## -0,0 +1 ## +svn://repo.hu/scconfig/trunk/src src Index: tags/2.1.2/src/Makefile.dep =================================================================== --- tags/2.1.2/src/Makefile.dep (nonexistent) +++ tags/2.1.2/src/Makefile.dep (revision 24813) @@ -0,0 +1,8503 @@ +### Generated file, do not edit, run make dep ### + +../src_plugins/acompnet/acompnet.o: ../src_plugins/acompnet/acompnet.c \ + ../config.h board.h ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h \ + global_typedefs.h pcb_bool.h unit.h vtroutestyle.h attrib.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h board.h data.h crosshair.h vtonpoint.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h error.h route.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h layer.h layer_ui.h actions.h plugins.h \ + ../src_3rd/puplug/puplug.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/os_dep.h ../src_3rd/puplug/config.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/error.h search.h polygon.h \ + conf.h pcb-printf.h ../src_3rd/liblihata/lihata.h list_conf.h conf.h \ + conf_core.h compat_misc.h error.h ../src_plugins/acompnet/meshgraph.h \ + rtree.h box.h dolists.h +../src_plugins/acompnet/meshgraph.o: ../src_plugins/acompnet/meshgraph.c \ + ../config.h ../src_3rd/genht/hash.h board.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h global_typedefs.h pcb_bool.h unit.h vtroutestyle.h \ + attrib.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h board.h conf_core.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/dom.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/parser.h \ + ../src_3rd/genvector/vtp0.h list_conf.h data.h crosshair.h vtonpoint.h \ + hid.h error.h route.h buffer.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h obj_rat_list.h obj_rat.h idpath.h \ + obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h vtpadstack.h \ + obj_pstk_shape.h polygon.h vtpadstack_t.h \ + ../src_plugins/acompnet/meshgraph.h rtree.h box.h error.h layer.h \ + route.h +../src_plugins/act_draw/act_draw.o: ../src_plugins/act_draw/act_draw.c \ + ../config.h conf_core.h conf.h global_typedefs.h pcb_bool.h unit.h \ + pcb-printf.h ../src_3rd/genvector/gds_char.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h globalconst.h color.h actions.h hid.h \ + error.h attrib.h layer.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h obj_line_list.h \ + obj_line.h obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h \ + obj_text.h font.h ../src_3rd/genht/htip.h box.h math_helper.h \ + misc_util.h ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h board.h \ + vtroutestyle.h layer_grp.h rats_patch.h board.h compat_misc.h flag_str.h \ + obj_arc.h obj_line.h obj_pstk.h obj_pstk_shape.h polygon.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h vtpadstack_t.h \ + obj_text.h plugins.h ../src_3rd/puplug/puplug.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/os_dep.h ../src_3rd/puplug/config.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/error.h undo.h \ + ../src_3rd/libuundo/uundo.h undo_old.h dolists.h +../src_plugins/ar_cpcb/ar_cpcb.o: ../src_plugins/ar_cpcb/ar_cpcb.c \ + ../config.h ../src_3rd/gensexpr/gsxl.h \ + ../src_3rd/gensexpr/gensexpr_impl.h ../src_3rd/gensexpr/gsx_parse.h \ + ../src_3rd/genht/htpi.h ../src_3rd/genht/ht.h board.h \ + ../src_3rd/genht/htsp.h global_typedefs.h pcb_bool.h unit.h \ + vtroutestyle.h attrib.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h board.h data.h crosshair.h vtonpoint.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h error.h route.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h plugins.h ../src_3rd/puplug/puplug.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/os_dep.h \ + ../src_3rd/puplug/config.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/error.h actions.h safe_fs.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h list_conf.h conf_core.h obj_pstk_inlines.h \ + data.h thermal.h ../src_plugins/lib_compat_help/pstk_compat.h obj_pstk.h \ + ../src_plugins/lib_netmap/netmap.h netlist2.h dolists.h +../src_plugins/asm/asm.o: ../src_plugins/asm/asm.c ../config.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/genlist/gendlist.h \ + board.h ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h global_typedefs.h \ + pcb_bool.h unit.h vtroutestyle.h attrib.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h layer_grp.h \ + rats_patch.h board.h data.h crosshair.h vtonpoint.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h error.h route.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h plugins.h ../src_3rd/puplug/puplug.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/os_dep.h \ + ../src_3rd/puplug/config.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/error.h actions.h compat_misc.h obj_subc.h \ + pcb-printf.h hid_dad.h compat_misc.h hid_attrib.h pcb-printf.h \ + hid_dad_tree.h hid_dad.h search.h draw.h select.h operation.h \ + ../src_plugins/asm/asm_conf.h conf.h ../src_3rd/liblihata/lihata.h \ + list_conf.h conf.h ../src_plugins/asm/conf_internal.c dolists.h \ + ../src_plugins/asm/asm_conf_fields.h +../src_plugins/autocrop/autocrop.o: ../src_plugins/autocrop/autocrop.c \ + ../config.h board.h ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h \ + global_typedefs.h pcb_bool.h unit.h vtroutestyle.h attrib.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h board.h data.h crosshair.h vtonpoint.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h error.h route.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h draw.h undo.h ../src_3rd/libuundo/uundo.h undo_old.h \ + actions.h plugins.h ../src_3rd/puplug/puplug.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/os_dep.h ../src_3rd/puplug/config.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/error.h dolists.h +../src_plugins/autoplace/action.o: ../src_plugins/autoplace/action.c \ + ../config.h ../src_plugins/autoplace/autoplace.h global_typedefs.h \ + pcb_bool.h unit.h plugins.h ../src_3rd/puplug/puplug.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/os_dep.h \ + ../src_3rd/puplug/config.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/error.h actions.h hid.h ../src_3rd/liblihata/dom.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/parser.h \ + ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h error.h global_typedefs.h \ + attrib.h layer.h globalconst.h color.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h board.h vtroutestyle.h layer_grp.h rats_patch.h \ + board.h event.h dolists.h +../src_plugins/autoplace/autoplace.o: \ + ../src_plugins/autoplace/autoplace.c ../config.h board.h \ + ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h global_typedefs.h \ + pcb_bool.h unit.h vtroutestyle.h attrib.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h board.h ../src_plugins/autoplace/autoplace.h \ + global_typedefs.h box.h compat_misc.h data.h crosshair.h vtonpoint.h \ + hid.h ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h error.h route.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h draw.h error.h layer.h intersect.h rtree.h macro.h move.h \ + netlist2.h remove.h rotate.h compat_misc.h obj_rat.h obj_term.h \ + obj_pstk_inlines.h data.h thermal.h data_it.h +../src_plugins/autoroute/action.o: ../src_plugins/autoroute/action.c \ + ../config.h ../src_plugins/autoroute/autoroute.h board.h \ + ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h global_typedefs.h \ + pcb_bool.h unit.h vtroutestyle.h attrib.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h board.h plugins.h ../src_3rd/puplug/puplug.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/os_dep.h \ + ../src_3rd/puplug/config.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/error.h actions.h hid.h ../src_3rd/liblihata/dom.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/parser.h error.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h event.h \ + funchash_core.h funchash.h funchash_core_list.h dolists.h +../src_plugins/autoroute/autoroute.o: \ + ../src_plugins/autoroute/autoroute.c ../config.h conf_core.h conf.h \ + global_typedefs.h pcb_bool.h unit.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h globalconst.h color.h data.h layer.h \ + attrib.h obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h obj_line_list.h obj_line.h obj_poly_list.h \ + obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h crosshair.h \ + vtonpoint.h hid.h error.h route.h buffer.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h obj_rat_list.h obj_rat.h layer_grp.h idpath.h \ + obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h macro.h \ + ../src_plugins/autoroute/autoroute.h board.h vtroutestyle.h rats_patch.h \ + board.h box.h draw.h error.h find.h heap.h rtree.h netlist2.h \ + ../src_plugins/autoroute/mtspace.h ../src_plugins/autoroute/vector.h \ + polygon.h remove.h obj_pinvia_therm.h undo.h ../src_3rd/libuundo/uundo.h \ + undo_old.h pcb-printf.h layer.h obj_line_draw.h draw.h obj_pstk_draw.h \ + obj_pstk_inlines.h data.h thermal.h \ + ../src_plugins/lib_compat_help/pstk_compat.h obj_pstk.h +../src_plugins/autoroute/mtspace.o: ../src_plugins/autoroute/mtspace.c \ + ../config.h box.h math_helper.h global_typedefs.h pcb_bool.h unit.h \ + obj_common.h flag.h globalconst.h attrib.h data_parent.h misc_util.h \ + heap.h rtree.h ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h \ + ../src_plugins/autoroute/mtspace.h ../src_plugins/autoroute/vector.h +../src_plugins/autoroute/vector.o: ../src_plugins/autoroute/vector.c \ + ../config.h math_helper.h ../src_plugins/autoroute/vector.h macro.h +../src_plugins/cam/cam.o: ../src_plugins/cam/cam.c ../config.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h board.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h global_typedefs.h pcb_bool.h unit.h vtroutestyle.h \ + attrib.h layer.h globalconst.h color.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h layer_grp.h \ + rats_patch.h board.h hid_cam.h hid_attrib.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h error.h hid_attrib.h hid_init.h \ + ../src_3rd/puplug/puplug.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/os_dep.h ../src_3rd/puplug/config.h \ + ../src_3rd/puplug/libs.h hid_nogui.h plugins.h ../src_3rd/puplug/error.h \ + actions.h ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h \ + ../src_plugins/cam/cam_conf.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/genvector/vtp0.h list_conf.h \ + conf.h compat_misc.h safe_fs.h ../src_plugins/cam/conf_internal.c \ + ../src_plugins/cam/cam_compile.c ../src_plugins/cam/cam_compile.h \ + layer_vis.h event.h ../src_3rd/genvector/genvector_impl.c \ + ../src_plugins/cam/cam_gui.c hid_dad.h compat_misc.h hid_dad_tree.h \ + hid_dad.h ../src_3rd/genht/hash.h dolists.h \ + ../src_plugins/cam/cam_conf_fields.h +../src_plugins/ddraft/centgeo.o: ../src_plugins/ddraft/centgeo.c \ + ../config.h ../src_plugins/ddraft/centgeo.h obj_line.h \ + ../src_3rd/genlist/gendlist.h obj_common.h flag.h globalconst.h attrib.h \ + global_typedefs.h pcb_bool.h unit.h data_parent.h obj_arc.h \ + math_helper.h compat_misc.h search.h layer.h color.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h ../src_3rd/genht/ht.h box.h math_helper.h \ + misc_util.h ../src_3rd/genvector/gds_char.h +../src_plugins/ddraft/ddraft.o: ../src_plugins/ddraft/ddraft.c \ + ../config.h ../src_3rd/genvector/gds_char.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/genvector/vtp0.h \ + hid_attrib.h hid.h ../src_3rd/liblihata/dom.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/parser.h \ + ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h error.h global_typedefs.h \ + pcb_bool.h unit.h attrib.h layer.h globalconst.h color.h obj_common.h \ + flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h hid_init.h ../src_3rd/puplug/puplug.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/os_dep.h \ + ../src_3rd/puplug/config.h ../src_3rd/puplug/libs.h plugins.h \ + ../src_3rd/puplug/error.h event.h actions.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h funchash_core.h funchash.h funchash_core_list.h \ + search.h ../src_plugins/ddraft/centgeo.h obj_line.h misc_util.h board.h \ + vtroutestyle.h layer_grp.h rats_patch.h board.h data_it.h data.h \ + crosshair.h vtonpoint.h route.h buffer.h obj_rat_list.h obj_rat.h \ + idpath.h obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h \ + rtree.h ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h undo.h \ + ../src_3rd/libuundo/uundo.h undo_old.h \ + ../src_plugins/ddraft/fields_sphash.h draw_wireframe.h conf_core.h \ + conf.h pcb-printf.h ../src_3rd/liblihata/lihata.h list_conf.h conf_hid.h \ + vtc0.h ../src_plugins/ddraft/trim.c undo_old.h \ + ../src_plugins/ddraft/constraint.c crosshair.h tool.h \ + ../src_plugins/ddraft/constraint_gui.c hid_dad.h compat_misc.h \ + hid_attrib.h ../src_plugins/ddraft/cli.c hid_inlines.h compat_misc.h \ + ../src_plugins/ddraft/cli_line.c dolists.h +../src_plugins/ddraft/fields_sphash.o: \ + ../src_plugins/ddraft/fields_sphash.c +../src_plugins/diag/diag.o: ../src_plugins/diag/diag.c ../config.h \ + board.h ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h global_typedefs.h \ + pcb_bool.h unit.h vtroutestyle.h attrib.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h board.h data.h crosshair.h vtonpoint.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h error.h route.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h data_it.h data.h flag_str.h layer.h \ + ../src_plugins/diag/diag_conf.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h list_conf.h conf.h actions.h plugins.h \ + ../src_3rd/puplug/puplug.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/os_dep.h ../src_3rd/puplug/config.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/error.h error.h event.h \ + ../src_plugins/diag/integrity.h hid.h hid_attrib.h hid_dad.h \ + compat_misc.h hid_attrib.h search.h macro.h funchash_core.h funchash.h \ + funchash_core_list.h find.h dolists.h \ + ../src_plugins/diag/diag_conf_fields.h +../src_plugins/diag/diag_conf.o: ../src_plugins/diag/diag_conf.c \ + ../config.h conf.h global_typedefs.h pcb_bool.h unit.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h +../src_plugins/diag/integrity.o: ../src_plugins/diag/integrity.c \ + ../config.h board.h ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h \ + global_typedefs.h pcb_bool.h unit.h vtroutestyle.h attrib.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h board.h data.h crosshair.h vtonpoint.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h error.h route.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h error.h undo.h ../src_3rd/libuundo/uundo.h undo_old.h +../src_plugins/dialogs/act_dad.o: ../src_plugins/dialogs/act_dad.c \ + ../config.h ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h \ + ../src_3rd/genht/hash.h ../src_3rd/genvector/vts0.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h actions.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h error.h global_typedefs.h pcb_bool.h \ + unit.h attrib.h layer.h globalconst.h color.h obj_common.h flag.h \ + data_parent.h obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h compat_misc.h hid_dad.h compat_misc.h \ + hid_attrib.h pcb-printf.h hid_dad_tree.h hid_dad.h error.h \ + ../src_plugins/dialogs/act_dad.h +../src_plugins/dialogs/dialogs.o: ../src_plugins/dialogs/dialogs.c \ + ../config.h hid.h ../src_3rd/liblihata/dom.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/parser.h \ + ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h error.h global_typedefs.h \ + pcb_bool.h unit.h attrib.h layer.h globalconst.h color.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h \ + ../src_3rd/genvector/gds_char.h hid_attrib.h hid.h actions.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h hid_dad.h \ + compat_misc.h hid_attrib.h pcb-printf.h plugins.h \ + ../src_3rd/puplug/puplug.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/os_dep.h ../src_3rd/puplug/config.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/error.h funchash_core.h \ + funchash.h funchash_core_list.h ../src_plugins/dialogs/dialogs_conf.h \ + conf.h ../src_3rd/liblihata/lihata.h ../src_3rd/genvector/vtp0.h \ + list_conf.h conf.h ../src_plugins/dialogs/dlg_test.c board.h \ + vtroutestyle.h layer_grp.h rats_patch.h board.h obj_text.h \ + hid_dad_tree.h hid_dad.h ../src_3rd/genht/hash.h hid_dad_spin.h \ + ../src_plugins/dialogs/dlg_about.h ../src_plugins/dialogs/dlg_comm_m.h \ + ../src_plugins/dialogs/dlg_export.h \ + ../src_plugins/dialogs/dlg_flag_edit.h \ + ../src_plugins/dialogs/dlg_fontsel.h \ + ../src_plugins/dialogs/dlg_layer_binding.h \ + ../src_plugins/dialogs/dlg_layer_flags.h \ + ../src_plugins/dialogs/dlg_lib_pstk.h \ + ../src_plugins/dialogs/dlg_loadsave.h ../src_plugins/dialogs/dlg_log.h \ + ../src_plugins/dialogs/dlg_padstack.h obj_pstk.h obj_pstk_shape.h \ + polygon.h rtree.h ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h \ + vtpadstack_t.h ../src_plugins/dialogs/dlg_pinout.c build_run.h \ + pcb-printf.h obj_subc_parent.h data.h crosshair.h vtonpoint.h route.h \ + buffer.h obj_rat_list.h obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h ht_subc.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h vtpadstack.h draw.h obj_term.h rtree.h \ + search.h search_r.h netlist2.h ../src_plugins/dialogs/dlg_undo.c \ + ../src_3rd/libuundo/uundo.h event.h undo.h undo_old.h \ + ../src_plugins/dialogs/dlg_netlist.c \ + ../src_plugins/dialogs/dlg_plugins.c \ + ../src_plugins/dialogs/dlg_printcalib.c hid_init.h \ + ../src_plugins/dialogs/place.c safe_fs.h ../src_3rd/genht/ht.c \ + ../src_3rd/genht/ht_inlines.h ../src_plugins/dialogs/dlg_view.h \ + ../src_plugins/dialogs/dlg_pref.h conf_hid.h \ + ../src_plugins/dialogs/dlg_pref_sizes.h \ + ../src_plugins/dialogs/dlg_pref_board.h \ + ../src_plugins/dialogs/dlg_pref_general.h \ + ../src_plugins/dialogs/dlg_pref_lib.h \ + ../src_plugins/dialogs/dlg_pref_color.h \ + ../src_plugins/dialogs/dlg_pref_win.h \ + ../src_plugins/dialogs/dlg_pref_conf.h ../src_plugins/dialogs/act_dad.h \ + dolists.h ../src_plugins/dialogs/dialogs_conf_fields.h +../src_plugins/dialogs/dlg_about.o: ../src_plugins/dialogs/dlg_about.c \ + ../config.h ../src_3rd/genvector/gds_char.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h actions.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h error.h global_typedefs.h pcb_bool.h unit.h \ + attrib.h layer.h globalconst.h color.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h build_run.h \ + file_loaded.h hid_dad.h compat_misc.h hid_attrib.h pcb-printf.h \ + pcb-printf.h ../src_plugins/dialogs/dlg_about.h +../src_plugins/dialogs/dlg_comm_m.o: ../src_plugins/dialogs/dlg_comm_m.c \ + ../config.h actions.h hid.h ../src_3rd/liblihata/dom.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/parser.h \ + ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h error.h global_typedefs.h \ + pcb_bool.h unit.h attrib.h layer.h globalconst.h color.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h hid_dad.h compat_misc.h hid_attrib.h \ + pcb-printf.h ../src_plugins/dialogs/xpm.h \ + ../src_plugins/dialogs/dlg_comm_m.h +../src_plugins/dialogs/dlg_export.o: ../src_plugins/dialogs/dlg_export.c \ + ../config.h actions.h hid.h ../src_3rd/liblihata/dom.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/parser.h \ + ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h error.h global_typedefs.h \ + pcb_bool.h unit.h attrib.h layer.h globalconst.h color.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h hid.h hid_dad.h compat_misc.h hid_attrib.h \ + pcb-printf.h hid_init.h ../src_3rd/puplug/puplug.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/os_dep.h \ + ../src_3rd/puplug/config.h ../src_3rd/puplug/libs.h \ + ../src_plugins/dialogs/dlg_export.h +../src_plugins/dialogs/dlg_flag_edit.o: \ + ../src_plugins/dialogs/dlg_flag_edit.c ../config.h actions.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h error.h global_typedefs.h pcb_bool.h unit.h \ + attrib.h layer.h globalconst.h color.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h hid_dad.h compat_misc.h hid_attrib.h \ + pcb-printf.h flag.h flag_str.h change.h board.h vtroutestyle.h \ + layer_grp.h rats_patch.h undo.h ../src_3rd/libuundo/uundo.h undo_old.h \ + search.h funchash_core.h funchash.h funchash_core_list.h \ + ../src_plugins/dialogs/dlg_flag_edit.h +../src_plugins/dialogs/dlg_fontsel.o: \ + ../src_plugins/dialogs/dlg_fontsel.c ../config.h actions.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h error.h global_typedefs.h pcb_bool.h unit.h \ + attrib.h layer.h globalconst.h color.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h board.h vtroutestyle.h layer_grp.h rats_patch.h \ + board.h change.h conf_core.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/genvector/vtp0.h list_conf.h \ + event.h hid_dad.h compat_misc.h hid_attrib.h stub_draw.h draw.h idpath.h \ + search.h ../src_plugins/dialogs/dlg_fontsel.h +../src_plugins/dialogs/dlg_layer_binding.o: \ + ../src_plugins/dialogs/dlg_layer_binding.c ../config.h actions.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h error.h global_typedefs.h pcb_bool.h unit.h \ + attrib.h layer.h globalconst.h color.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h board.h vtroutestyle.h layer_grp.h rats_patch.h \ + board.h data.h crosshair.h vtonpoint.h route.h buffer.h obj_rat_list.h \ + obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h event.h conf_core.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h list_conf.h compat_misc.h hid_dad.h \ + compat_misc.h hid_attrib.h funchash_core.h funchash.h \ + funchash_core_list.h obj_subc.h search.h \ + ../src_plugins/dialogs/dlg_layer_binding.h +../src_plugins/dialogs/dlg_layer_flags.o: \ + ../src_plugins/dialogs/dlg_layer_flags.c ../config.h board.h \ + ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h global_typedefs.h \ + pcb_bool.h unit.h vtroutestyle.h attrib.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h board.h actions.h hid.h ../src_3rd/liblihata/dom.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/parser.h error.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h event.h hid_dad.h \ + compat_misc.h hid_attrib.h pcb-printf.h \ + ../src_plugins/dialogs/dlg_layer_binding.h \ + ../src_plugins/dialogs/dlg_layer_flags.h +../src_plugins/dialogs/dlg_lib_pstk.o: \ + ../src_plugins/dialogs/dlg_lib_pstk.c ../config.h actions.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h error.h global_typedefs.h pcb_bool.h unit.h \ + attrib.h layer.h globalconst.h color.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h data.h crosshair.h vtonpoint.h route.h buffer.h \ + obj_rat_list.h obj_rat.h layer_grp.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h obj_subc.h vtpadstack.h hid_inlines.h hid_dad.h \ + compat_misc.h hid_attrib.h pcb-printf.h hid_dad_tree.h hid_dad.h \ + obj_pstk.h obj_pstk_inlines.h board.h vtroutestyle.h rats_patch.h data.h \ + thermal.h obj_text_draw.h draw.h obj_pstk_draw.h undo_old.h select.h \ + operation.h search.h ../src_plugins/dialogs/dlg_padstack.h \ + ../src_plugins/dialogs/dlg_lib_pstk.h +../src_plugins/dialogs/dlg_loadsave.o: \ + ../src_plugins/dialogs/dlg_loadsave.c ../config.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h actions.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h error.h global_typedefs.h pcb_bool.h unit.h \ + attrib.h layer.h globalconst.h color.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h board.h \ + vtroutestyle.h layer_grp.h rats_patch.h board.h data.h crosshair.h \ + vtonpoint.h route.h buffer.h obj_rat_list.h obj_rat.h idpath.h \ + obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h event.h hid_dad.h compat_misc.h hid_attrib.h pcb-printf.h \ + compat_fs.h conf_core.h conf.h ../src_3rd/liblihata/lihata.h list_conf.h \ + plug_io.h ../src_plugins/dialogs/dlg_loadsave.h +../src_plugins/dialogs/dlg_log.o: ../src_plugins/dialogs/dlg_log.c \ + ../config.h actions.h hid.h ../src_3rd/liblihata/dom.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/parser.h \ + ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h error.h global_typedefs.h \ + pcb_bool.h unit.h attrib.h layer.h globalconst.h color.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h conf_hid.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/genvector/vtp0.h list_conf.h \ + hid_dad.h compat_misc.h hid_attrib.h event.h error.h \ + ../src_plugins/dialogs/dlg_log.h +../src_plugins/dialogs/dlg_padstack.o: \ + ../src_plugins/dialogs/dlg_padstack.c ../config.h actions.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h error.h global_typedefs.h pcb_bool.h unit.h \ + attrib.h layer.h globalconst.h color.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h hid_dad.h compat_misc.h hid_attrib.h \ + pcb-printf.h funchash_core.h funchash.h funchash_core_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h obj_pstk_shape.h polygon.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h vtpadstack_t.h \ + obj_pstk_op.h operation.h obj_pstk_inlines.h board.h vtroutestyle.h \ + layer_grp.h rats_patch.h data.h crosshair.h vtonpoint.h route.h buffer.h \ + obj_rat_list.h obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h ht_subc.h ../src_3rd/genht/ht.h \ + ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h vtpadstack.h \ + thermal.h obj_subc_parent.h search.h operation.h \ + ../src_plugins/dialogs/dlg_lib_pstk.h \ + ../src_plugins/dialogs/dlg_padstack.h +../src_plugins/dialogs/dlg_pref.o: ../src_plugins/dialogs/dlg_pref.c \ + ../config.h ../src_3rd/genvector/gds_char.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h actions.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h error.h global_typedefs.h pcb_bool.h unit.h \ + attrib.h layer.h globalconst.h color.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h build_run.h \ + pcb-printf.h error.h event.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/genvector/vtp0.h list_conf.h \ + conf.h conf_hid.h hid_dad.h compat_misc.h hid_attrib.h hid_dad_tree.h \ + hid_dad.h ../src_3rd/genht/hash.h ../src_plugins/dialogs/dlg_pref.h \ + ../src_plugins/dialogs/dlg_pref_sizes.h \ + ../src_plugins/dialogs/dlg_pref_board.h \ + ../src_plugins/dialogs/dlg_pref_general.h \ + ../src_plugins/dialogs/dlg_pref_lib.h \ + ../src_plugins/dialogs/dlg_pref_color.h \ + ../src_plugins/dialogs/dlg_pref_win.h \ + ../src_plugins/dialogs/dlg_pref_conf.h \ + ../src_plugins/dialogs/dlg_pref_sizes.c board.h vtroutestyle.h \ + layer_grp.h rats_patch.h board.h conf_core.h \ + ../src_plugins/dialogs/dlg_pref_board.c \ + ../src_plugins/dialogs/dlg_pref_general.c \ + ../src_plugins/dialogs/dlg_pref_lib.c ../src_3rd/liblihata/tree.h \ + paths.h ../src_plugins/dialogs/dlg_pref_layer.c stub_draw.h draw.h \ + ../src_plugins/dialogs/dlg_pref_color.c \ + ../src_plugins/dialogs/dlg_pref_win.c \ + ../src_plugins/dialogs/dialogs_conf.h \ + ../src_plugins/dialogs/dlg_pref_conf.c misc_util.h \ + ../src_plugins/dialogs/dlg_pref_confedit.c +../src_plugins/dialogs/dlg_view.o: ../src_plugins/dialogs/dlg_view.c \ + ../config.h ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h \ + ../src_3rd/genht/hash.h actions.h hid.h ../src_3rd/liblihata/dom.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/parser.h error.h \ + global_typedefs.h pcb_bool.h unit.h attrib.h layer.h globalconst.h \ + color.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h board.h vtroutestyle.h layer_grp.h rats_patch.h \ + board.h conf_core.h conf.h pcb-printf.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/genvector/vtp0.h list_conf.h view.h idpath.h draw.h drc.h \ + view.h event.h hid_inlines.h hid_dad.h compat_misc.h hid_attrib.h \ + hid_dad_tree.h hid_dad.h undo.h ../src_3rd/libuundo/uundo.h undo_old.h \ + safe_fs.h misc_util.h +../src_plugins/dialogs/xpm.o: ../src_plugins/dialogs/xpm.c ../config.h \ + ../src_plugins/dialogs/xpm/question.xpm \ + ../src_plugins/dialogs/xpm/warning.xpm +../src_plugins/distalign/distalign.o: \ + ../src_plugins/distalign/distalign.c board.h ../config.h \ + ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h global_typedefs.h \ + pcb_bool.h unit.h vtroutestyle.h attrib.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h board.h data.h crosshair.h vtonpoint.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h error.h route.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h hid.h rtree.h undo.h ../src_3rd/libuundo/uundo.h \ + undo_old.h error.h move.h draw.h plugins.h ../src_3rd/puplug/puplug.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/os_dep.h \ + ../src_3rd/puplug/config.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/error.h macro.h actions.h compat_misc.h dolists.h +../src_plugins/distaligntext/distaligntext.o: \ + ../src_plugins/distaligntext/distaligntext.c ../config.h board.h \ + ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h global_typedefs.h \ + pcb_bool.h unit.h vtroutestyle.h attrib.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h board.h data.h crosshair.h vtonpoint.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h error.h route.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h hid.h rtree.h undo.h ../src_3rd/libuundo/uundo.h \ + undo_old.h error.h move.h draw.h plugins.h ../src_3rd/puplug/puplug.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/os_dep.h \ + ../src_3rd/puplug/config.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/error.h actions.h conf_core.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h list_conf.h box.h macro.h compat_misc.h \ + dolists.h +../src_plugins/djopt/djopt.o: ../src_plugins/djopt/djopt.c ../config.h \ + conf_core.h conf.h global_typedefs.h pcb_bool.h unit.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h globalconst.h color.h board.h \ + vtroutestyle.h attrib.h layer.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h obj_line_list.h \ + obj_line.h obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h \ + obj_text.h font.h ../src_3rd/genht/htip.h box.h math_helper.h \ + misc_util.h layer_grp.h rats_patch.h board.h data.h crosshair.h \ + vtonpoint.h hid.h error.h route.h buffer.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h obj_rat_list.h obj_rat.h idpath.h \ + obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h remove.h move.h \ + draw.h undo.h ../src_3rd/libuundo/uundo.h undo_old.h flag_str.h find.h \ + layer.h pcb-printf.h compat_misc.h plugins.h ../src_3rd/puplug/puplug.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/os_dep.h \ + ../src_3rd/puplug/config.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/error.h actions.h ../src_plugins/djopt/djopt_conf.h \ + conf.h obj_line.h event.h macro.h obj_pstk_inlines.h data.h thermal.h \ + dolists.h ../src_plugins/djopt/djopt_conf_fields.h +../src_plugins/draw_csect/draw_csect.o: \ + ../src_plugins/draw_csect/draw_csect.c ../config.h board.h \ + ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h global_typedefs.h \ + pcb_bool.h unit.h vtroutestyle.h attrib.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h board.h data.h crosshair.h vtonpoint.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h error.h route.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h draw.h plugins.h ../src_3rd/puplug/puplug.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/os_dep.h \ + ../src_3rd/puplug/config.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/error.h stub_draw.h draw.h compat_misc.h actions.h \ + event.h layer_vis.h obj_text_draw.h obj_line_draw.h dolists.h +../src_plugins/draw_fab/draw_fab.o: ../src_plugins/draw_fab/draw_fab.c \ + ../config.h board.h ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h \ + global_typedefs.h pcb_bool.h unit.h vtroutestyle.h attrib.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h board.h build_run.h compat_misc.h data.h crosshair.h \ + vtonpoint.h hid.h ../src_3rd/liblihata/dom.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/parser.h error.h \ + route.h buffer.h ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h \ + obj_rat_list.h obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h draw.h ../src_plugins/draw_fab/../report/drill.h \ + plugins.h ../src_3rd/puplug/puplug.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/os_dep.h ../src_3rd/puplug/config.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/error.h stub_draw.h draw.h \ + ../src_plugins/draw_fab/draw_fab_conf.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h list_conf.h conf.h conf_core.h macro.h \ + obj_pstk_inlines.h data.h thermal.h hid_inlines.h funchash_core.h \ + funchash.h funchash_core_list.h obj_text_draw.h \ + ../src_plugins/draw_fab/draw_fab_conf_fields.h +../src_plugins/draw_fontsel/draw_fontsel.o: \ + ../src_plugins/draw_fontsel/draw_fontsel.c ../config.h board.h \ + ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h global_typedefs.h \ + pcb_bool.h unit.h vtroutestyle.h attrib.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h board.h build_run.h data.h crosshair.h vtonpoint.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h error.h route.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h draw.h font.h actions.h plugins.h \ + ../src_3rd/puplug/puplug.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/os_dep.h ../src_3rd/puplug/config.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/error.h stub_draw.h draw.h \ + pcb-printf.h compat_misc.h conf_core.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h list_conf.h obj_text.h obj_text_draw.h \ + obj_line_draw.h +../src_plugins/drc_orig/drc_orig.o: ../src_plugins/drc_orig/drc_orig.c \ + ../config.h drc.h view.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h unit.h idpath.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_common.h flag.h globalconst.h \ + attrib.h global_typedefs.h pcb_bool.h data_parent.h box.h math_helper.h \ + misc_util.h view.h data_it.h data.h layer.h color.h obj_arc_list.h \ + obj_arc.h obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h \ + polyarea.h obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h crosshair.h vtonpoint.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h error.h route.h \ + buffer.h ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h \ + obj_rat_list.h obj_rat.h layer_grp.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h conf_core.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h list_conf.h find.h event.h plugins.h \ + ../src_3rd/puplug/puplug.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/os_dep.h ../src_3rd/puplug/config.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/error.h layer_vis.h \ + obj_arc_draw.h draw.h obj_rat_draw.h obj_line_draw.h obj_text_draw.h \ + obj_poly_draw.h obj_pstk_draw.h board.h vtroutestyle.h rats_patch.h \ + obj_subc_list.h dolists.h +../src_plugins/expfeat/expfeat.o: ../src_plugins/expfeat/expfeat.c \ + ../config.h conf.h global_typedefs.h pcb_bool.h unit.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h data.h globalconst.h layer.h attrib.h \ + color.h obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h obj_line_list.h obj_line.h obj_poly_list.h \ + obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h crosshair.h \ + vtonpoint.h hid.h error.h route.h buffer.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h obj_rat_list.h obj_rat.h layer_grp.h idpath.h \ + obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h change.h board.h \ + vtroutestyle.h rats_patch.h error.h undo.h ../src_3rd/libuundo/uundo.h \ + undo_old.h plugins.h ../src_3rd/puplug/puplug.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/os_dep.h ../src_3rd/puplug/config.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/error.h actions.h dolists.h +../src_plugins/export_bboard/bboard.o: \ + ../src_plugins/export_bboard/bboard.c ../config.h math_helper.h board.h \ + ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h global_typedefs.h \ + pcb_bool.h unit.h vtroutestyle.h attrib.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h board.h data.h crosshair.h vtonpoint.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h error.h route.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h error.h buffer.h layer.h layer_grp.h layer_vis.h \ + plugins.h ../src_3rd/puplug/puplug.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/os_dep.h ../src_3rd/puplug/config.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/error.h compat_misc.h \ + compat_fs.h misc_util.h funchash_core.h funchash.h funchash_core_list.h \ + rtree.h hid.h hid_attrib.h hid_nogui.h hid_draw_helpers.h hid_init.h \ + hid_cam.h hid_attrib.h +../src_plugins/export_bom/bom.o: ../src_plugins/export_bom/bom.c \ + ../config.h conf_core.h conf.h global_typedefs.h pcb_bool.h unit.h \ + pcb-printf.h ../src_3rd/genvector/gds_char.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h globalconst.h color.h build_run.h board.h \ + vtroutestyle.h attrib.h layer.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h obj_line_list.h \ + obj_line.h obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h \ + obj_text.h font.h ../src_3rd/genht/htip.h box.h math_helper.h \ + misc_util.h layer_grp.h rats_patch.h board.h data.h crosshair.h \ + vtonpoint.h hid.h error.h route.h buffer.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h obj_rat_list.h obj_rat.h idpath.h \ + obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h error.h \ + pcb-printf.h plugins.h ../src_3rd/puplug/puplug.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/os_dep.h \ + ../src_3rd/puplug/config.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/error.h compat_misc.h safe_fs.h hid.h hid_nogui.h \ + hid_attrib.h hid_cam.h hid_attrib.h hid_init.h macro.h +../src_plugins/export_dsn/dsn.o: ../src_plugins/export_dsn/dsn.c \ + ../config.h ../src_3rd/genvector/gds_char.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h board.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h global_typedefs.h pcb_bool.h unit.h vtroutestyle.h \ + attrib.h layer.h globalconst.h color.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h layer_grp.h \ + rats_patch.h board.h data.h crosshair.h vtonpoint.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h error.h route.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h error.h buffer.h change.h draw.h undo.h \ + ../src_3rd/libuundo/uundo.h undo_old.h pcb-printf.h polygon.h \ + compat_misc.h layer.h safe_fs.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h list_conf.h netlist2.h hid.h \ + hid_draw_helpers.h hid_nogui.h actions.h hid_init.h \ + ../src_3rd/puplug/puplug.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/os_dep.h ../src_3rd/puplug/config.h \ + ../src_3rd/puplug/libs.h hid_attrib.h hid_cam.h hid_attrib.h plugins.h \ + ../src_3rd/puplug/error.h obj_line.h obj_pstk_inlines.h data.h thermal.h \ + dolists.h +../src_plugins/export_dxf/dxf.o: ../src_plugins/export_dxf/dxf.c \ + ../config.h conf_core.h conf.h global_typedefs.h pcb_bool.h unit.h \ + pcb-printf.h ../src_3rd/genvector/gds_char.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h globalconst.h color.h math_helper.h \ + board.h vtroutestyle.h attrib.h layer.h obj_common.h flag.h \ + data_parent.h obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h layer_grp.h rats_patch.h board.h data.h \ + crosshair.h vtonpoint.h hid.h error.h route.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h draw.h error.h \ + layer.h layer_vis.h plugins.h ../src_3rd/puplug/puplug.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/os_dep.h \ + ../src_3rd/puplug/config.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/error.h pcb-printf.h compat_misc.h \ + ../src_plugins/export_dxf/lht_template.h safe_fs.h funchash_core.h \ + funchash.h funchash_core_list.h hid.h hid_nogui.h hid_draw_helpers.h \ + hid_init.h hid_attrib.h hid_color.h hid_cam.h hid_attrib.h \ + ../src_plugins/export_dxf/dxf_draw.c dolists.h +../src_plugins/export_dxf/dxf_templ_lht.o: \ + ../src_plugins/export_dxf/dxf_templ_lht.c +../src_plugins/export_dxf/lht_template.o: \ + ../src_plugins/export_dxf/lht_template.c ../config.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/liblihata/tree.h \ + ../src_plugins/export_dxf/lht_template.h +../src_plugins/export_fidocadj/fidocadj.o: \ + ../src_plugins/export_fidocadj/fidocadj.c ../config.h conf_core.h conf.h \ + global_typedefs.h pcb_bool.h unit.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h globalconst.h color.h \ + ../src_3rd/genht/htsi.h math_helper.h board.h vtroutestyle.h attrib.h \ + layer.h obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h obj_line_list.h obj_line.h obj_poly_list.h \ + obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h layer_grp.h \ + rats_patch.h board.h data.h crosshair.h vtonpoint.h hid.h error.h \ + route.h buffer.h ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h \ + obj_rat_list.h obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h layer_vis.h \ + plugins.h ../src_3rd/puplug/puplug.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/os_dep.h ../src_3rd/puplug/config.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/error.h pcb-printf.h \ + compat_misc.h plug_io.h safe_fs.h hid.h hid_nogui.h hid_draw_helpers.h \ + hid_init.h hid_attrib.h hid_color.h hid_cam.h hid_attrib.h \ + ../src_plugins/lib_compat_help/pstk_compat.h obj_pstk.h dolists.h +../src_plugins/export_gcode/curve.o: ../src_plugins/export_gcode/curve.c \ + ../config.h ../src_plugins/export_gcode/potracelib.h \ + ../src_plugins/export_gcode/lists.h ../src_plugins/export_gcode/curve.h \ + ../src_plugins/export_gcode/auxiliary.h +../src_plugins/export_gcode/decompose.o: \ + ../src_plugins/export_gcode/decompose.c ../config.h \ + ../src_plugins/export_gcode/potracelib.h \ + ../src_plugins/export_gcode/curve.h \ + ../src_plugins/export_gcode/auxiliary.h \ + ../src_plugins/export_gcode/lists.h ../src_plugins/export_gcode/bitmap.h \ + ../src_plugins/export_gcode/decompose.h +../src_plugins/export_gcode/gcode.o: ../src_plugins/export_gcode/gcode.c \ + ../config.h conf_core.h conf.h global_typedefs.h pcb_bool.h unit.h \ + pcb-printf.h ../src_3rd/genvector/gds_char.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h globalconst.h color.h plugins.h \ + ../src_3rd/puplug/puplug.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/os_dep.h ../src_3rd/puplug/config.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/error.h board.h \ + vtroutestyle.h attrib.h layer.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h obj_line_list.h \ + obj_line.h obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h \ + obj_text.h font.h ../src_3rd/genht/htip.h box.h math_helper.h \ + misc_util.h layer_grp.h rats_patch.h board.h error.h data.h crosshair.h \ + vtonpoint.h hid.h error.h route.h buffer.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h obj_rat_list.h obj_rat.h idpath.h \ + obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h draw.h hid_cam.h \ + hid_attrib.h layer.h layer_vis.h compat_misc.h safe_fs.h hid.h \ + hid_nogui.h hid_draw_helpers.h ../src_plugins/export_gcode/gcode.h \ + ../src_plugins/export_gcode/bitmap.h \ + ../src_plugins/export_gcode/potracelib.h \ + ../src_plugins/export_gcode/curve.h \ + ../src_plugins/export_gcode/auxiliary.h \ + ../src_plugins/export_gcode/trace.h \ + ../src_plugins/export_gcode/decompose.h pcb-printf.h funchash_core.h \ + funchash.h funchash_core_list.h hid_init.h hid_attrib.h hid_color.h \ + dolists.h +../src_plugins/export_gcode/trace.o: ../src_plugins/export_gcode/trace.c \ + ../config.h ../src_plugins/export_gcode/potracelib.h \ + ../src_plugins/export_gcode/curve.h \ + ../src_plugins/export_gcode/auxiliary.h \ + ../src_plugins/export_gcode/lists.h ../src_plugins/export_gcode/trace.h \ + compat_cc.h +../src_plugins/export_gerber/aperture.o: \ + ../src_plugins/export_gerber/aperture.c ../config.h global_typedefs.h \ + pcb_bool.h unit.h ../src_plugins/export_gerber/aperture.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h \ + ../src_3rd/genvector/genvector_impl.c +../src_plugins/export_gerber/excellon.o: \ + ../src_plugins/export_gerber/excellon.c ../config.h board.h \ + ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h global_typedefs.h \ + pcb_bool.h unit.h vtroutestyle.h attrib.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h board.h global_typedefs.h pcb-printf.h safe_fs.h conf.h \ + pcb-printf.h ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/dom.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/parser.h \ + ../src_3rd/genvector/vtp0.h list_conf.h error.h draw.h hid.h error.h \ + compat_misc.h layer.h layer_vis.h hid.h hid_attrib.h hid_cam.h \ + hid_attrib.h hid_init.h ../src_3rd/puplug/puplug.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/os_dep.h \ + ../src_3rd/puplug/config.h ../src_3rd/puplug/libs.h hid_nogui.h \ + hid_draw_helpers.h plugins.h ../src_3rd/puplug/error.h funchash_core.h \ + funchash.h funchash_core_list.h conf_core.h \ + ../src_plugins/export_gerber/gerber_conf.h conf.h \ + ../src_plugins/export_gerber/excellon.h \ + ../src_plugins/export_gerber/aperture.h +../src_plugins/export_gerber/gerber.o: \ + ../src_plugins/export_gerber/gerber.c ../config.h math_helper.h board.h \ + ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h global_typedefs.h \ + pcb_bool.h unit.h vtroutestyle.h attrib.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h board.h build_run.h data.h crosshair.h vtonpoint.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h error.h route.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h error.h draw.h layer.h layer_vis.h pcb-printf.h plugins.h \ + ../src_3rd/puplug/puplug.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/os_dep.h ../src_3rd/puplug/config.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/error.h hid_cam.h \ + hid_attrib.h compat_misc.h safe_fs.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h list_conf.h macro.h funchash_core.h \ + funchash.h funchash_core_list.h \ + ../src_plugins/export_gerber/gerber_conf.h conf.h hid.h hid_nogui.h \ + hid_draw_helpers.h hid_init.h hid_attrib.h hid_inlines.h conf_core.h \ + ../src_plugins/export_gerber/aperture.h \ + ../src_plugins/export_gerber/excellon.h \ + ../src_plugins/export_gerber/gerber_conf_fields.h +../src_plugins/export_ipcd356/ipcd356.o: \ + ../src_plugins/export_ipcd356/ipcd356.c ../config.h board.h \ + ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h global_typedefs.h \ + pcb_bool.h unit.h vtroutestyle.h attrib.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h board.h data.h crosshair.h vtonpoint.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h error.h route.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h safe_fs.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h list_conf.h conf_core.h compat_misc.h \ + netlist2.h math_helper.h layer.h obj_arc.h obj_line.h obj_poly.h \ + obj_subc.h obj_pstk.h obj_pstk_inlines.h data.h thermal.h hid.h \ + hid_nogui.h hid_cam.h hid_attrib.h hid_attrib.h hid_init.h \ + ../src_3rd/puplug/puplug.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/os_dep.h ../src_3rd/puplug/config.h \ + ../src_3rd/puplug/libs.h plugins.h ../src_3rd/puplug/error.h +../src_plugins/export_lpr/lpr.o: ../src_plugins/export_lpr/lpr.c \ + ../config.h data.h globalconst.h global_typedefs.h pcb_bool.h unit.h \ + layer.h attrib.h color.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h ../src_3rd/genht/ht.h box.h math_helper.h \ + misc_util.h ../src_3rd/genvector/gds_char.h crosshair.h vtonpoint.h \ + hid.h ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h error.h route.h \ + buffer.h ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h \ + obj_rat_list.h obj_rat.h layer_grp.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h plugins.h ../src_3rd/puplug/puplug.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/os_dep.h \ + ../src_3rd/puplug/config.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/error.h compat_misc.h safe_fs.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h list_conf.h hid.h \ + ../src_plugins/export_lpr/../export_ps/ps.h hid_nogui.h hid_init.h \ + hid_attrib.h actions.h +../src_plugins/export_oldconn/oldconn.o: \ + ../src_plugins/export_oldconn/oldconn.c ../config.h conf_core.h conf.h \ + global_typedefs.h pcb_bool.h unit.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h globalconst.h color.h actions.h hid.h \ + error.h attrib.h layer.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h obj_line_list.h \ + obj_line.h obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h \ + obj_text.h font.h ../src_3rd/genht/htip.h box.h math_helper.h \ + misc_util.h ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h board.h \ + vtroutestyle.h layer_grp.h rats_patch.h board.h compat_fs.h data.h \ + crosshair.h vtonpoint.h route.h buffer.h obj_rat_list.h obj_rat.h \ + idpath.h obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h \ + rtree.h ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h data_it.h data.h \ + draw.h plugins.h ../src_3rd/puplug/puplug.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/os_dep.h ../src_3rd/puplug/config.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/error.h plug_io.h safe_fs.h \ + find.h macro.h obj_subc_parent.h undo.h ../src_3rd/libuundo/uundo.h \ + undo_old.h funchash_core.h funchash.h funchash_core_list.h search.h \ + hid_init.h hid_attrib.h dolists.h +../src_plugins/export_openems/export_openems.o: \ + ../src_plugins/export_openems/export_openems.c ../config.h conf_core.h \ + conf.h global_typedefs.h pcb_bool.h unit.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h globalconst.h color.h board.h \ + vtroutestyle.h attrib.h layer.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h obj_line_list.h \ + obj_line.h obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h \ + obj_text.h font.h ../src_3rd/genht/htip.h box.h math_helper.h \ + misc_util.h layer_grp.h rats_patch.h board.h data.h crosshair.h \ + vtonpoint.h hid.h error.h route.h buffer.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h obj_rat_list.h obj_rat.h idpath.h \ + obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h data_it.h data.h \ + draw.h compat_misc.h plugins.h ../src_3rd/puplug/puplug.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/os_dep.h \ + ../src_3rd/puplug/config.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/error.h safe_fs.h layer_vis.h obj_subc_parent.h \ + obj_pstk_inlines.h thermal.h hid.h actions.h hid_nogui.h hid_cam.h \ + hid_attrib.h hid_attrib.h hid_init.h hid_draw_helpers.h \ + ../src_plugins/lib_polyhelp/topoly.h obj_common.h \ + ../src_plugins/export_openems/mesh.h layer.h vtc0.h vtr0.h \ + ../src_plugins/export_openems/excitation.c hid_dad.h compat_misc.h \ + event.h dolists.h +../src_plugins/export_openems/mesh.o: \ + ../src_plugins/export_openems/mesh.c ../config.h \ + ../src_plugins/export_openems/mesh.h layer.h globalconst.h \ + global_typedefs.h pcb_bool.h unit.h attrib.h color.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h ../src_3rd/genht/ht.h box.h math_helper.h \ + misc_util.h ../src_3rd/genvector/gds_char.h vtc0.h vtr0.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/htpp.h layer_ui.h ../src_3rd/genvector/vtp0.h actions.h \ + hid.h ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h error.h layer.h board.h vtroutestyle.h \ + layer_grp.h rats_patch.h board.h data.h crosshair.h vtonpoint.h route.h \ + buffer.h obj_rat_list.h obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h hid_dad.h \ + compat_misc.h hid_attrib.h pcb-printf.h event.h safe_fs.h conf.h \ + ../src_3rd/liblihata/lihata.h list_conf.h +../src_plugins/export_openscad/export_openscad.o: \ + ../src_plugins/export_openscad/export_openscad.c ../config.h conf_core.h \ + conf.h global_typedefs.h pcb_bool.h unit.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h globalconst.h color.h \ + ../src_3rd/genvector/vti0.h compat_misc.h board.h vtroutestyle.h \ + attrib.h layer.h obj_common.h flag.h data_parent.h obj_arc_list.h \ + obj_arc.h ../src_3rd/genlist/gendlist.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h layer_grp.h \ + rats_patch.h board.h data.h crosshair.h vtonpoint.h hid.h error.h \ + route.h buffer.h ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h \ + obj_rat_list.h obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h draw.h error.h \ + layer.h layer_vis.h math_helper.h misc_util.h plugins.h \ + ../src_3rd/puplug/puplug.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/os_dep.h ../src_3rd/puplug/config.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/error.h safe_fs.h \ + obj_pstk_inlines.h data.h thermal.h funchash_core.h funchash.h \ + funchash_core_list.h hid.h hid_nogui.h hid_draw_helpers.h hid_init.h \ + actions.h hid_attrib.h hid_color.h hid_cam.h hid_attrib.h \ + ../src_plugins/export_openscad/scad_draw.c \ + ../src_plugins/export_openscad/../lib_polyhelp/topoly.h obj_common.h \ + plug_io.h ../src_plugins/export_openscad/scad_models.c dolists.h +../src_plugins/export_png/png.o: ../src_plugins/export_png/png.c \ + ../config.h conf_core.h conf.h global_typedefs.h pcb_bool.h unit.h \ + pcb-printf.h ../src_3rd/genvector/gds_char.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h globalconst.h color.h board.h \ + vtroutestyle.h attrib.h layer.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h obj_line_list.h \ + obj_line.h obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h \ + obj_text.h font.h ../src_3rd/genht/htip.h box.h math_helper.h \ + misc_util.h layer_grp.h rats_patch.h board.h data.h crosshair.h \ + vtonpoint.h hid.h error.h route.h buffer.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h obj_rat_list.h obj_rat.h idpath.h \ + obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h draw.h error.h \ + layer.h layer_vis.h misc_util.h compat_misc.h plugins.h \ + ../src_3rd/puplug/puplug.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/os_dep.h ../src_3rd/puplug/config.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/error.h safe_fs.h \ + funchash_core.h funchash.h funchash_core_list.h hid.h hid_nogui.h \ + hid_draw_helpers.h ../src_plugins/export_png/png.h hid_init.h \ + hid_attrib.h hid_color.h hid_cam.h hid_attrib.h dolists.h +../src_plugins/export_ps/eps.o: ../src_plugins/export_ps/eps.c \ + ../config.h conf_core.h conf.h global_typedefs.h pcb_bool.h unit.h \ + pcb-printf.h ../src_3rd/genvector/gds_char.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h globalconst.h color.h math_helper.h \ + board.h vtroutestyle.h attrib.h layer.h obj_common.h flag.h \ + data_parent.h obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h layer_grp.h rats_patch.h board.h data.h \ + crosshair.h vtonpoint.h hid.h error.h route.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h draw.h layer.h \ + layer_vis.h pcb-printf.h safe_fs.h hid.h hid_nogui.h hid_draw_helpers.h \ + ../src_plugins/export_ps/ps.h hid_init.h ../src_3rd/puplug/puplug.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/os_dep.h \ + ../src_3rd/puplug/config.h ../src_3rd/puplug/libs.h hid_attrib.h \ + hid_cam.h hid_attrib.h hid_color.h funchash_core.h funchash.h \ + funchash_core_list.h +../src_plugins/export_ps/ps.o: ../src_plugins/export_ps/ps.c ../config.h \ + math_helper.h board.h ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h \ + global_typedefs.h pcb_bool.h unit.h vtroutestyle.h attrib.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h board.h data.h crosshair.h vtonpoint.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h error.h route.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h layer.h error.h draw.h pcb-printf.h plugins.h \ + ../src_3rd/puplug/puplug.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/os_dep.h ../src_3rd/puplug/config.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/error.h hid_cam.h \ + hid_attrib.h safe_fs.h conf.h pcb-printf.h ../src_3rd/liblihata/lihata.h \ + list_conf.h funchash_core.h funchash.h funchash_core_list.h layer_vis.h \ + hid.h hid_nogui.h hid_draw_helpers.h ../src_plugins/export_ps/ps.h \ + hid_init.h hid_attrib.h actions.h conf_core.h compat_misc.h stub_draw.h \ + draw.h ../src_plugins/lib_compat_help/media.h dolists.h +../src_plugins/export_stat/stat.o: ../src_plugins/export_stat/stat.c \ + ../config.h conf_core.h conf.h global_typedefs.h pcb_bool.h unit.h \ + pcb-printf.h ../src_3rd/genvector/gds_char.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h globalconst.h color.h \ + ../src_3rd/genht/htsi.h ../src_3rd/genht/hash.h math_helper.h board.h \ + vtroutestyle.h attrib.h layer.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h obj_line_list.h \ + obj_line.h obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h \ + obj_text.h font.h ../src_3rd/genht/htip.h box.h math_helper.h \ + misc_util.h layer_grp.h rats_patch.h board.h data.h crosshair.h \ + vtonpoint.h hid.h error.h route.h buffer.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h obj_rat_list.h obj_rat.h idpath.h \ + obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h vtpadstack.h \ + obj_pstk_shape.h polygon.h vtpadstack_t.h data_it.h data.h netlist2.h \ + plugins.h ../src_3rd/puplug/puplug.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/os_dep.h ../src_3rd/puplug/config.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/error.h pcb-printf.h \ + compat_misc.h plug_io.h safe_fs.h obj_pstk_inlines.h thermal.h hid.h \ + hid_nogui.h hid_draw_helpers.h hid_init.h hid_attrib.h hid_color.h \ + hid_cam.h hid_attrib.h dolists.h +../src_plugins/export_svg/svg.o: ../src_plugins/export_svg/svg.c \ + ../config.h conf_core.h conf.h global_typedefs.h pcb_bool.h unit.h \ + pcb-printf.h ../src_3rd/genvector/gds_char.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h globalconst.h color.h math_helper.h \ + board.h vtroutestyle.h attrib.h layer.h obj_common.h flag.h \ + data_parent.h obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h layer_grp.h rats_patch.h board.h data.h \ + crosshair.h vtonpoint.h hid.h error.h route.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h draw.h error.h \ + layer.h layer_vis.h misc_util.h compat_misc.h plugins.h \ + ../src_3rd/puplug/puplug.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/os_dep.h ../src_3rd/puplug/config.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/error.h safe_fs.h \ + funchash_core.h funchash.h funchash_core_list.h hid.h hid_nogui.h \ + hid_draw_helpers.h hid_init.h hid_attrib.h hid_color.h hid_cam.h \ + hid_attrib.h dolists.h +../src_plugins/export_test/export_test.o: \ + ../src_plugins/export_test/export_test.c ../config.h conf_core.h conf.h \ + global_typedefs.h pcb_bool.h unit.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h globalconst.h color.h build_run.h board.h \ + vtroutestyle.h attrib.h layer.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h obj_line_list.h \ + obj_line.h obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h \ + obj_text.h font.h ../src_3rd/genht/htip.h box.h math_helper.h \ + misc_util.h layer_grp.h rats_patch.h board.h data.h crosshair.h \ + vtonpoint.h hid.h error.h route.h buffer.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h obj_rat_list.h obj_rat.h idpath.h \ + obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h error.h \ + pcb-printf.h plugins.h ../src_3rd/puplug/puplug.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/os_dep.h \ + ../src_3rd/puplug/config.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/error.h hid.h hid_nogui.h hid_attrib.h hid_cam.h \ + hid_attrib.h hid_init.h +../src_plugins/export_vfs_fuse/export_vfs_fuse.o: \ + ../src_plugins/export_vfs_fuse/export_vfs_fuse.c \ + ../src_plugins/export_vfs_fuse/fuse_includes.h ../config.h conf_core.h \ + conf.h global_typedefs.h pcb_bool.h unit.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h globalconst.h color.h build_run.h board.h \ + vtroutestyle.h attrib.h layer.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h obj_line_list.h \ + obj_line.h obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h \ + obj_text.h font.h ../src_3rd/genht/htip.h box.h math_helper.h \ + misc_util.h layer_grp.h rats_patch.h board.h data.h crosshair.h \ + vtonpoint.h hid.h error.h route.h buffer.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h obj_rat_list.h obj_rat.h idpath.h \ + obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h error.h \ + pcb-printf.h plugins.h ../src_3rd/puplug/puplug.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/os_dep.h \ + ../src_3rd/puplug/config.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/error.h plug_io.h safe_fs.h compat_fs.h hid.h \ + hid_attrib.h hid_init.h hid_nogui.h ../src_plugins/lib_vfs/lib_vfs.h +../src_plugins/export_vfs_mc/export_vfs_mc.o: \ + ../src_plugins/export_vfs_mc/export_vfs_mc.c ../config.h conf_core.h \ + conf.h global_typedefs.h pcb_bool.h unit.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h globalconst.h color.h build_run.h board.h \ + vtroutestyle.h attrib.h layer.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h obj_line_list.h \ + obj_line.h obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h \ + obj_text.h font.h ../src_3rd/genht/htip.h box.h math_helper.h \ + misc_util.h layer_grp.h rats_patch.h board.h data.h crosshair.h \ + vtonpoint.h hid.h error.h route.h buffer.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h obj_rat_list.h obj_rat.h idpath.h \ + obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h error.h \ + pcb-printf.h plugins.h ../src_3rd/puplug/puplug.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/os_dep.h \ + ../src_3rd/puplug/config.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/error.h plug_io.h hid.h hid_attrib.h hid_init.h \ + hid_nogui.h ../src_plugins/lib_vfs/lib_vfs.h +../src_plugins/export_xy/xy.o: ../src_plugins/export_xy/xy.c ../config.h \ + conf_core.h conf.h global_typedefs.h pcb_bool.h unit.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h globalconst.h color.h \ + ../src_3rd/genvector/vts0.h math_helper.h build_run.h board.h \ + vtroutestyle.h attrib.h layer.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h obj_line_list.h \ + obj_line.h obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h \ + obj_text.h font.h ../src_3rd/genht/htip.h box.h math_helper.h \ + misc_util.h layer_grp.h rats_patch.h board.h data.h crosshair.h \ + vtonpoint.h hid.h error.h route.h buffer.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h obj_rat_list.h obj_rat.h idpath.h \ + obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h data_it.h data.h \ + error.h pcb-printf.h plugins.h ../src_3rd/puplug/puplug.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/os_dep.h \ + ../src_3rd/puplug/config.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/error.h compat_misc.h obj_pstk_inlines.h thermal.h \ + obj_subc_op.h operation.h layer.h netlist2.h safe_fs.h macro.h \ + operation.h ../src_plugins/export_xy/xy_conf.h conf.h hid.h hid_nogui.h \ + hid_attrib.h hid_cam.h hid_attrib.h hid_init.h \ + ../src_plugins/lib_compat_help/elem_rot.h \ + ../src_plugins/export_xy/conf_internal.c \ + ../src_plugins/export_xy/xy_conf_fields.h +../src_plugins/extedit/extedit.o: ../src_plugins/extedit/extedit.c \ + ../config.h hid.h ../src_3rd/liblihata/dom.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/parser.h \ + ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h error.h global_typedefs.h \ + pcb_bool.h unit.h attrib.h layer.h globalconst.h color.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h \ + ../src_3rd/genvector/gds_char.h hid_attrib.h hid.h actions.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h hid_dad.h \ + compat_misc.h hid_attrib.h pcb-printf.h plugins.h \ + ../src_3rd/puplug/puplug.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/os_dep.h ../src_3rd/puplug/config.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/error.h board.h \ + vtroutestyle.h layer_grp.h rats_patch.h board.h compat_fs.h \ + compat_misc.h conf_core.h conf.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/genvector/vtp0.h list_conf.h data.h crosshair.h vtonpoint.h \ + route.h buffer.h obj_rat_list.h obj_rat.h idpath.h obj_subc_list.h \ + obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h buffer.h paths.h \ + remove.h safe_fs.h search.h undo.h ../src_3rd/libuundo/uundo.h \ + undo_old.h ../src_plugins/io_lihata/io_lihata.h conf.h \ + ../src_plugins/io_lihata/lht_conf.h ../src_plugins/io_lihata/write.h \ + ../src_plugins/io_lihata/read.h plug_io.h \ + ../src_plugins/extedit/extedit_dad.c dolists.h +../src_plugins/fontmode/fontmode.o: ../src_plugins/fontmode/fontmode.c \ + ../config.h conf_core.h conf.h global_typedefs.h pcb_bool.h unit.h \ + pcb-printf.h ../src_3rd/genvector/gds_char.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h globalconst.h color.h board.h \ + vtroutestyle.h attrib.h layer.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h obj_line_list.h \ + obj_line.h obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h \ + obj_text.h font.h ../src_3rd/genht/htip.h box.h math_helper.h \ + misc_util.h layer_grp.h rats_patch.h board.h data.h crosshair.h \ + vtonpoint.h hid.h error.h route.h buffer.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h obj_rat_list.h obj_rat.h idpath.h \ + obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h draw.h flag.h \ + layer.h move.h remove.h rtree.h flag_str.h undo.h \ + ../src_3rd/libuundo/uundo.h undo_old.h pcb-printf.h plugins.h \ + ../src_3rd/puplug/puplug.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/os_dep.h ../src_3rd/puplug/config.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/error.h actions.h \ + compat_misc.h event.h polygon.h obj_poly_draw.h draw.h dolists.h +../src_plugins/fp_board/fp_board.o: ../src_plugins/fp_board/fp_board.c \ + ../config.h plugins.h ../src_3rd/puplug/puplug.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/os_dep.h \ + ../src_3rd/puplug/config.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/error.h plug_footprint.h vtlibrary.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h data.h globalconst.h \ + global_typedefs.h pcb_bool.h unit.h layer.h attrib.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h box.h math_helper.h misc_util.h \ + ../src_3rd/genvector/gds_char.h crosshair.h vtonpoint.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h error.h route.h \ + buffer.h ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h \ + obj_rat_list.h obj_rat.h layer_grp.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h board.h vtroutestyle.h rats_patch.h board.h buffer.h \ + data.h error.h obj_subc.h obj_subc_list.h obj_subc_op.h operation.h \ + compat_misc.h pcb-printf.h operation.h plug_io.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h list_conf.h safe_fs.h +../src_plugins/fp_fs/fp_fs.o: ../src_plugins/fp_fs/fp_fs.c ../config.h \ + data.h globalconst.h global_typedefs.h pcb_bool.h unit.h layer.h \ + attrib.h color.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h ../src_3rd/genht/ht.h box.h math_helper.h \ + misc_util.h ../src_3rd/genvector/gds_char.h crosshair.h vtonpoint.h \ + hid.h ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h error.h route.h \ + buffer.h ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h \ + obj_rat_list.h obj_rat.h layer_grp.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h paths.h plugins.h ../src_3rd/puplug/puplug.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/os_dep.h \ + ../src_3rd/puplug/config.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/error.h plug_footprint.h vtlibrary.h data.h \ + compat_fs.h compat_misc.h error.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h list_conf.h conf.h conf_core.h macro.h \ + safe_fs.h compat_inc.h +../src_plugins/fp_wget/edakrill.o: ../src_plugins/fp_wget/edakrill.c \ + ../config.h ../src_3rd/genvector/gds_char.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h error.h \ + ../src_plugins/fp_wget/wget_common.h ../src_plugins/fp_wget/edakrill.h \ + plug_footprint.h vtlibrary.h data.h globalconst.h global_typedefs.h \ + pcb_bool.h unit.h layer.h attrib.h color.h obj_common.h flag.h \ + data_parent.h obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h crosshair.h \ + vtonpoint.h hid.h ../src_3rd/liblihata/dom.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/parser.h error.h \ + route.h buffer.h ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h \ + obj_rat_list.h obj_rat.h layer_grp.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h ../src_plugins/fp_wget/fp_wget_conf.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h list_conf.h conf.h plugins.h \ + ../src_3rd/puplug/puplug.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/os_dep.h ../src_3rd/puplug/config.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/error.h compat_misc.h \ + safe_fs.h globalconst.h +../src_plugins/fp_wget/fp_wget.o: ../src_plugins/fp_wget/fp_wget.c \ + ../config.h ../src_plugins/fp_wget/gedasymbols.h plug_footprint.h \ + vtlibrary.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h data.h globalconst.h \ + global_typedefs.h pcb_bool.h unit.h layer.h attrib.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h box.h math_helper.h misc_util.h \ + ../src_3rd/genvector/gds_char.h crosshair.h vtonpoint.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h error.h route.h \ + buffer.h ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h \ + obj_rat_list.h obj_rat.h layer_grp.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h ../src_plugins/fp_wget/fp_wget_conf.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h list_conf.h conf.h \ + ../src_plugins/fp_wget/edakrill.h plugins.h ../src_3rd/puplug/puplug.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/os_dep.h \ + ../src_3rd/puplug/config.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/error.h ../src_plugins/fp_wget/conf_internal.c \ + ../src_plugins/fp_wget/fp_wget_conf_fields.h +../src_plugins/fp_wget/gedasymbols.o: \ + ../src_plugins/fp_wget/gedasymbols.c ../config.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h error.h \ + ../src_plugins/fp_wget/wget_common.h \ + ../src_plugins/fp_wget/gedasymbols.h plug_footprint.h vtlibrary.h data.h \ + globalconst.h global_typedefs.h pcb_bool.h unit.h layer.h attrib.h \ + color.h obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h crosshair.h vtonpoint.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h error.h route.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h layer_grp.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h ../src_plugins/fp_wget/fp_wget_conf.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h list_conf.h conf.h plugins.h \ + ../src_3rd/puplug/puplug.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/os_dep.h ../src_3rd/puplug/config.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/error.h compat_misc.h \ + safe_fs.h globalconst.h +../src_plugins/fp_wget/wget_common.o: \ + ../src_plugins/fp_wget/wget_common.c ../config.h \ + ../src_plugins/fp_wget/wget_common.h compat_misc.h safe_fs.h conf.h \ + global_typedefs.h pcb_bool.h unit.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h +../src_plugins/hid_batch/batch.o: ../src_plugins/hid_batch/batch.c \ + ../config.h board.h ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h \ + global_typedefs.h pcb_bool.h unit.h vtroutestyle.h attrib.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h board.h hid.h ../src_3rd/liblihata/dom.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/parser.h error.h \ + data.h crosshair.h vtonpoint.h hid.h route.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h layer.h pcb-printf.h plugins.h ../src_3rd/puplug/puplug.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/os_dep.h \ + ../src_3rd/puplug/config.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/error.h compat_misc.h event.h conf_core.h conf.h \ + pcb-printf.h ../src_3rd/liblihata/lihata.h list_conf.h \ + hid_draw_helpers.h hid_nogui.h actions.h hid_init.h hid_attrib.h \ + dolists.h +../src_plugins/hid_gtk2_gdk/gtkhid-gdk.o: \ + ../src_plugins/hid_gtk2_gdk/gtkhid-gdk.c ../config.h conf_core.h conf.h \ + global_typedefs.h pcb_bool.h unit.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h globalconst.h color.h crosshair.h \ + vtonpoint.h hid.h error.h attrib.h layer.h obj_common.h flag.h \ + data_parent.h obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h route.h data.h crosshair.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h layer_grp.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h draw.h layer.h \ + grid.h board.h vtroutestyle.h rats_patch.h hid_draw_helpers.h \ + hid_attrib.h hid_color.h funchash_core.h funchash.h funchash_core_list.h \ + ../src_plugins/lib_gtk_hid/gui.h hid.h \ + ../src_plugins/lib_gtk_common/ui_zoompan.h unit.h pcb_bool.h \ + ../src_plugins/lib_gtk_common/in_mouse.h hid_cfg_input.h hid_cfg.h \ + ../src_plugins/lib_gtk_common/glue.h conf.h \ + ../src_plugins/lib_gtk_common/compat.h \ + ../src_plugins/lib_gtk_common/dlg_topwin.h hid_cfg.h \ + ../src_plugins/lib_gtk_common/util_ext_chg.h \ + ../src_plugins/lib_gtk_common/bu_info_bar.h \ + ../src_plugins/lib_gtk_common/bu_menu.h \ + ../src_plugins/lib_gtk_common/wt_route_style.h route_style.h conf_hid.h \ + ../src_plugins/lib_gtk_common/bu_mode_btn.h \ + ../src_plugins/lib_gtk_common/bu_cursor_pos.h \ + ../src_plugins/lib_gtk_common/bu_command.h \ + ../src_plugins/lib_gtk_common/wt_layersel.h layer_grp.h \ + ../src_plugins/lib_gtk_common/in_mouse.h \ + ../src_plugins/lib_gtk_common/glue.h board.h event.h \ + ../src_plugins/lib_gtk_hid/render.h ../src_plugins/lib_gtk_hid/gui.h \ + ../src_plugins/lib_gtk_hid/coord_conv.h compat_misc.h \ + ../src_plugins/lib_gtk_hid/preview_helper.h \ + ../src_plugins/lib_gtk_common/hid_gtk_conf.h \ + ../src_plugins/lib_gtk_common/lib_gtk_config.h \ + ../src_plugins/lib_hid_common/clip.h global_typedefs.h +../src_plugins/hid_gtk2_gdk/gtkhid-main.o: \ + ../src_plugins/hid_gtk2_gdk/gtkhid-main.c ../config.h error.h \ + pcb-printf.h ../src_3rd/genvector/gds_char.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h unit.h plugins.h \ + ../src_3rd/puplug/puplug.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/os_dep.h ../src_3rd/puplug/config.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/error.h hid_init.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h error.h global_typedefs.h pcb_bool.h attrib.h \ + layer.h globalconst.h color.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h conf_core.h \ + conf.h pcb-printf.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_plugins/lib_gtk_common/glue.h hid.h conf.h \ + ../src_plugins/lib_gtk_common/compat.h \ + ../src_plugins/lib_gtk_common/lib_gtk_config.h event.h conf_hid.h \ + ../src_plugins/lib_gtk_common/hid_gtk_conf.h \ + ../src_plugins/lib_gtk_hid/gui.h \ + ../src_plugins/lib_gtk_common/ui_zoompan.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h unit.h pcb_bool.h \ + ../src_plugins/lib_gtk_common/in_mouse.h hid_cfg_input.h hid_cfg.h \ + ../src_plugins/lib_gtk_common/glue.h \ + ../src_plugins/lib_gtk_common/dlg_topwin.h hid_cfg.h \ + ../src_plugins/lib_gtk_common/util_ext_chg.h \ + ../src_plugins/lib_gtk_common/bu_info_bar.h \ + ../src_plugins/lib_gtk_common/bu_menu.h \ + ../src_plugins/lib_gtk_common/wt_route_style.h route_style.h \ + vtroutestyle.h ../src_plugins/lib_gtk_common/bu_mode_btn.h \ + ../src_plugins/lib_gtk_common/bu_cursor_pos.h \ + ../src_plugins/lib_gtk_common/bu_command.h \ + ../src_plugins/lib_gtk_common/wt_layersel.h layer.h layer_grp.h \ + ../src_plugins/lib_gtk_common/in_mouse.h board.h layer_grp.h \ + rats_patch.h board.h ../src_plugins/lib_gtk_hid/render.h \ + ../src_plugins/lib_gtk_hid/gui.h \ + ../src_plugins/lib_gtk_hid/glue_common.h \ + ../src_plugins/lib_gtk_hid/glue_hid.h \ + ../src_plugins/lib_gtk_hid/glue_conf.h \ + ../src_plugins/lib_gtk_hid/glue_event.h \ + ../src_plugins/lib_gtk_hid/glue_win32.h \ + ../src_plugins/lib_gtk_hid/common.h ../src_plugins/lib_gtk_hid/render.h +../src_plugins/hid_gtk2_gl/gtkhid-gl.o: \ + ../src_plugins/hid_gtk2_gl/gtkhid-gl.c ../config.h crosshair.h \ + vtonpoint.h global_typedefs.h pcb_bool.h unit.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h hid.h ../src_3rd/liblihata/dom.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/parser.h \ + ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h error.h attrib.h layer.h \ + globalconst.h color.h obj_common.h flag.h data_parent.h obj_arc_list.h \ + obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h \ + ../src_3rd/genvector/gds_char.h route.h data.h crosshair.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h layer_grp.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h draw.h layer.h hid_draw_helpers.h hid_attrib.h \ + hid_color.h funchash_core.h funchash.h funchash_core_list.h \ + ../src_plugins/lib_hid_common/clip.h global_typedefs.h \ + ../src_plugins/lib_gtk_common/hid_gtk_conf.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h list_conf.h conf.h \ + ../src_plugins/lib_gtk_common/lib_gtk_config.h hid.h event.h conf_hid.h \ + ../src_plugins/lib_gtk_hid/gui.h \ + ../src_plugins/lib_gtk_common/ui_zoompan.h unit.h pcb_bool.h \ + ../src_plugins/lib_gtk_common/in_mouse.h hid_cfg_input.h hid_cfg.h \ + ../src_plugins/lib_gtk_common/glue.h \ + ../src_plugins/lib_gtk_common/compat.h \ + ../src_plugins/lib_gtk_common/dlg_topwin.h hid_cfg.h \ + ../src_plugins/lib_gtk_common/util_ext_chg.h \ + ../src_plugins/lib_gtk_common/bu_info_bar.h \ + ../src_plugins/lib_gtk_common/bu_menu.h \ + ../src_plugins/lib_gtk_common/wt_route_style.h route_style.h \ + vtroutestyle.h ../src_plugins/lib_gtk_common/bu_mode_btn.h \ + ../src_plugins/lib_gtk_common/bu_cursor_pos.h \ + ../src_plugins/lib_gtk_common/bu_command.h \ + ../src_plugins/lib_gtk_common/wt_layersel.h layer_grp.h \ + ../src_plugins/lib_gtk_common/in_mouse.h \ + ../src_plugins/lib_gtk_common/glue.h board.h rats_patch.h board.h \ + ../src_plugins/lib_gtk_hid/render.h ../src_plugins/lib_gtk_hid/gui.h \ + ../src_plugins/lib_gtk_hid/coord_conv.h compat_misc.h conf_core.h \ + ../src_plugins/lib_gtk_hid/render.h \ + ../src_plugins/lib_gtk_hid/preview_helper.h \ + ../src_plugins/lib_hid_gl/opengl.h ../src_plugins/lib_hid_gl/draw_gl.h \ + ../src_plugins/lib_hid_gl/opengl.h ../src_plugins/lib_hid_gl/hidgl.h \ + ../src_plugins/lib_hid_gl/stencil_gl.h +../src_plugins/hid_gtk2_gl/gtkhid-main.o: \ + ../src_plugins/hid_gtk2_gl/gtkhid-main.c ../config.h error.h \ + pcb-printf.h ../src_3rd/genvector/gds_char.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h unit.h plugins.h \ + ../src_3rd/puplug/puplug.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/os_dep.h ../src_3rd/puplug/config.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/error.h hid_init.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h error.h global_typedefs.h pcb_bool.h attrib.h \ + layer.h globalconst.h color.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h conf_core.h \ + conf.h pcb-printf.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_plugins/lib_hid_gl/draw_gl.h ../src_plugins/lib_hid_gl/opengl.h \ + ../src_plugins/lib_gtk_common/glue.h hid.h conf.h \ + ../src_plugins/lib_gtk_common/compat.h \ + ../src_plugins/lib_gtk_common/lib_gtk_config.h event.h conf_hid.h \ + ../src_plugins/lib_gtk_common/hid_gtk_conf.h \ + ../src_plugins/lib_gtk_hid/gui.h \ + ../src_plugins/lib_gtk_common/ui_zoompan.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h unit.h pcb_bool.h \ + ../src_plugins/lib_gtk_common/in_mouse.h hid_cfg_input.h hid_cfg.h \ + ../src_plugins/lib_gtk_common/glue.h \ + ../src_plugins/lib_gtk_common/dlg_topwin.h hid_cfg.h \ + ../src_plugins/lib_gtk_common/util_ext_chg.h \ + ../src_plugins/lib_gtk_common/bu_info_bar.h \ + ../src_plugins/lib_gtk_common/bu_menu.h \ + ../src_plugins/lib_gtk_common/wt_route_style.h route_style.h \ + vtroutestyle.h ../src_plugins/lib_gtk_common/bu_mode_btn.h \ + ../src_plugins/lib_gtk_common/bu_cursor_pos.h \ + ../src_plugins/lib_gtk_common/bu_command.h \ + ../src_plugins/lib_gtk_common/wt_layersel.h layer.h layer_grp.h \ + ../src_plugins/lib_gtk_common/in_mouse.h board.h layer_grp.h \ + rats_patch.h board.h ../src_plugins/lib_gtk_hid/render.h \ + ../src_plugins/lib_gtk_hid/gui.h \ + ../src_plugins/lib_gtk_hid/glue_common.h \ + ../src_plugins/lib_gtk_hid/glue_hid.h \ + ../src_plugins/lib_gtk_hid/glue_conf.h \ + ../src_plugins/lib_gtk_hid/glue_event.h \ + ../src_plugins/lib_gtk_hid/glue_win32.h \ + ../src_plugins/lib_gtk_hid/common.h ../src_plugins/lib_gtk_hid/render.h +../src_plugins/hid_gtk3_cairo/gtkhid-cairo.o: \ + ../src_plugins/hid_gtk3_cairo/gtkhid-cairo.c ../config.h conf_core.h \ + conf.h global_typedefs.h pcb_bool.h unit.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h globalconst.h color.h crosshair.h \ + vtonpoint.h hid.h error.h attrib.h layer.h obj_common.h flag.h \ + data_parent.h obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h route.h data.h crosshair.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h layer_grp.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h layer.h grid.h \ + board.h vtroutestyle.h rats_patch.h hid_draw_helpers.h hid_attrib.h \ + hid_color.h funchash_core.h funchash.h funchash_core_list.h \ + ../src_plugins/lib_gtk_hid/gui.h hid.h \ + ../src_plugins/lib_gtk_common/ui_zoompan.h unit.h pcb_bool.h \ + ../src_plugins/lib_gtk_common/in_mouse.h hid_cfg_input.h hid_cfg.h \ + ../src_plugins/lib_gtk_common/glue.h conf.h \ + ../src_plugins/lib_gtk_common/compat.h \ + ../src_plugins/lib_gtk_common/dlg_topwin.h hid_cfg.h \ + ../src_plugins/lib_gtk_common/util_ext_chg.h \ + ../src_plugins/lib_gtk_common/bu_info_bar.h \ + ../src_plugins/lib_gtk_common/bu_menu.h \ + ../src_plugins/lib_gtk_common/wt_route_style.h route_style.h conf_hid.h \ + ../src_plugins/lib_gtk_common/bu_mode_btn.h \ + ../src_plugins/lib_gtk_common/bu_cursor_pos.h \ + ../src_plugins/lib_gtk_common/bu_command.h \ + ../src_plugins/lib_gtk_common/wt_layersel.h layer_grp.h \ + ../src_plugins/lib_gtk_common/in_mouse.h \ + ../src_plugins/lib_gtk_common/glue.h board.h event.h \ + ../src_plugins/lib_gtk_hid/render.h ../src_plugins/lib_gtk_hid/gui.h \ + ../src_plugins/lib_gtk_hid/coord_conv.h compat_misc.h \ + ../src_plugins/lib_gtk_hid/preview_helper.h \ + ../src_plugins/lib_gtk_common/hid_gtk_conf.h \ + ../src_plugins/lib_gtk_common/lib_gtk_config.h \ + ../src_plugins/lib_hid_common/clip.h global_typedefs.h +../src_plugins/hid_gtk3_cairo/gtkhid-main.o: \ + ../src_plugins/hid_gtk3_cairo/gtkhid-main.c ../config.h error.h \ + pcb-printf.h ../src_3rd/genvector/gds_char.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h unit.h plugins.h \ + ../src_3rd/puplug/puplug.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/os_dep.h ../src_3rd/puplug/config.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/error.h hid_init.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h error.h global_typedefs.h pcb_bool.h attrib.h \ + layer.h globalconst.h color.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h conf_core.h \ + conf.h pcb-printf.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_plugins/lib_gtk_common/glue.h hid.h conf.h \ + ../src_plugins/lib_gtk_common/compat.h \ + ../src_plugins/lib_gtk_common/lib_gtk_config.h event.h conf_hid.h \ + ../src_plugins/lib_gtk_common/hid_gtk_conf.h \ + ../src_plugins/lib_gtk_hid/gui.h \ + ../src_plugins/lib_gtk_common/ui_zoompan.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h unit.h pcb_bool.h \ + ../src_plugins/lib_gtk_common/in_mouse.h hid_cfg_input.h hid_cfg.h \ + ../src_plugins/lib_gtk_common/glue.h \ + ../src_plugins/lib_gtk_common/dlg_topwin.h hid_cfg.h \ + ../src_plugins/lib_gtk_common/util_ext_chg.h \ + ../src_plugins/lib_gtk_common/bu_info_bar.h \ + ../src_plugins/lib_gtk_common/bu_menu.h \ + ../src_plugins/lib_gtk_common/wt_route_style.h route_style.h \ + vtroutestyle.h ../src_plugins/lib_gtk_common/bu_mode_btn.h \ + ../src_plugins/lib_gtk_common/bu_cursor_pos.h \ + ../src_plugins/lib_gtk_common/bu_command.h \ + ../src_plugins/lib_gtk_common/wt_layersel.h layer.h layer_grp.h \ + ../src_plugins/lib_gtk_common/in_mouse.h board.h layer_grp.h \ + rats_patch.h board.h ../src_plugins/lib_gtk_hid/render.h \ + ../src_plugins/lib_gtk_hid/gui.h \ + ../src_plugins/lib_gtk_hid/glue_common.h \ + ../src_plugins/lib_gtk_hid/glue_hid.h \ + ../src_plugins/lib_gtk_hid/glue_conf.h \ + ../src_plugins/lib_gtk_hid/glue_event.h \ + ../src_plugins/lib_gtk_hid/glue_win32.h \ + ../src_plugins/lib_gtk_hid/common.h ../src_plugins/lib_gtk_hid/render.h +../src_plugins/hid_lesstif/FillBox.o: \ + ../src_plugins/hid_lesstif/FillBox.c ../config.h \ + ../src_plugins/hid_lesstif/FillBoxP.h \ + ../src_plugins/hid_lesstif/FillBox.h \ + ../src_plugins/hid_lesstif/pxm_helper.h +../src_plugins/hid_lesstif/Pages.o: ../src_plugins/hid_lesstif/Pages.c \ + ../config.h ../src_plugins/hid_lesstif/PagesP.h \ + ../src_plugins/hid_lesstif/Pages.h \ + ../src_plugins/hid_lesstif/pxm_helper.h +../src_plugins/hid_lesstif/dialogs.o: \ + ../src_plugins/hid_lesstif/dialogs.c \ + ../src_plugins/hid_lesstif/xincludes.h ../config.h conf_core.h conf.h \ + global_typedefs.h pcb_bool.h unit.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h globalconst.h color.h \ + ../src_plugins/hid_lesstif/FillBox.h compat_misc.h data.h layer.h \ + attrib.h obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h obj_line_list.h obj_line.h obj_poly_list.h \ + obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h crosshair.h \ + vtonpoint.h hid.h error.h route.h buffer.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h obj_rat_list.h obj_rat.h layer_grp.h idpath.h \ + obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h event.h \ + build_run.h crosshair.h layer.h pcb-printf.h hid.h \ + ../src_plugins/hid_lesstif/lesstif.h hid_cfg_input.h hid_cfg.h board.h \ + vtroutestyle.h rats_patch.h board.h hid_attrib.h actions.h hid_init.h \ + ../src_3rd/puplug/puplug.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/os_dep.h ../src_3rd/puplug/config.h \ + ../src_3rd/puplug/libs.h ../src_plugins/hid_lesstif/stdarg.h color.h \ + misc_util.h search.h change.h plug_io.h \ + ../src_plugins/hid_lesstif/dlg_attr_misc.c \ + ../src_plugins/hid_lesstif/wt_xpm.h \ + ../src_plugins/hid_lesstif/wt_colorbtn.h \ + ../src_plugins/lib_hid_common/dad_markup.h \ + ../src_plugins/hid_lesstif/wt_preview.h \ + ../src_plugins/hid_lesstif/dlg_attr_box.c \ + ../src_plugins/hid_lesstif/Pages.h brave.h \ + ../src_plugins/hid_lesstif/dlg_attr_tree.c \ + ../src_plugins/hid_lesstif/xm_tree_table_widget.h hid_dad_tree.h \ + hid_attrib.h hid_dad.h compat_misc.h +../src_plugins/hid_lesstif/dlg_fileselect.o: \ + ../src_plugins/hid_lesstif/dlg_fileselect.c ../config.h \ + ../src_plugins/hid_lesstif/xincludes.h \ + ../src_plugins/hid_lesstif/lesstif.h hid_cfg_input.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/htip.h ../src_3rd/genht/htpp.h \ + hid_cfg.h global_typedefs.h pcb_bool.h unit.h hid.h error.h attrib.h \ + layer.h globalconst.h color.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + box.h math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h board.h \ + vtroutestyle.h layer_grp.h rats_patch.h board.h \ + ../src_plugins/hid_lesstif/stdarg.h color.h hid.h hid_dad.h \ + compat_misc.h hid_attrib.h pcb-printf.h event.h \ + ../src_plugins/hid_lesstif/dlg_fileselect.h global_typedefs.h +../src_plugins/hid_lesstif/library.o: \ + ../src_plugins/hid_lesstif/library.c \ + ../src_plugins/hid_lesstif/xincludes.h ../config.h conf_core.h conf.h \ + global_typedefs.h pcb_bool.h unit.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h globalconst.h color.h compat_misc.h data.h \ + layer.h attrib.h obj_common.h flag.h data_parent.h obj_arc_list.h \ + obj_arc.h ../src_3rd/genlist/gendlist.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h crosshair.h \ + vtonpoint.h hid.h error.h route.h buffer.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h obj_rat_list.h obj_rat.h layer_grp.h idpath.h \ + obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h actions.h \ + buffer.h plug_footprint.h vtlibrary.h data.h hid.h \ + ../src_plugins/hid_lesstif/lesstif.h hid_cfg_input.h hid_cfg.h board.h \ + vtroutestyle.h rats_patch.h board.h ../src_plugins/hid_lesstif/stdarg.h \ + color.h event.h tool.h +../src_plugins/hid_lesstif/main.o: ../src_plugins/hid_lesstif/main.c \ + ../src_plugins/hid_lesstif/xincludes.h ../config.h math_helper.h \ + conf_core.h conf.h global_typedefs.h pcb_bool.h unit.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h globalconst.h color.h data.h layer.h \ + attrib.h obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h obj_line_list.h obj_line.h obj_poly_list.h \ + obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h crosshair.h \ + vtonpoint.h hid.h error.h route.h buffer.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h obj_rat_list.h obj_rat.h layer_grp.h idpath.h \ + obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h draw.h \ + crosshair.h conf_hid.h layer.h pcb-printf.h event.h error.h plugins.h \ + ../src_3rd/puplug/puplug.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/os_dep.h ../src_3rd/puplug/config.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/error.h macro.h safe_fs.h \ + funchash_core.h funchash.h funchash_core_list.h hid.h hid_nogui.h \ + hid_draw_helpers.h hid_cfg.h ../src_plugins/hid_lesstif/lesstif.h \ + hid_cfg_input.h hid_cfg.h board.h vtroutestyle.h rats_patch.h board.h \ + hid_attrib.h hid_init.h hid_color.h actions.h \ + ../src_plugins/hid_lesstif/stdarg.h color.h grid.h misc_util.h \ + compat_misc.h layer_vis.h tool.h \ + ../src_plugins/hid_lesstif/dlg_fileselect.h global_typedefs.h \ + ../src_plugins/lib_hid_common/clip.h \ + ../src_plugins/lib_hid_common/util.h \ + ../src_plugins/lib_hid_common/cli_history.h \ + ../src_plugins/hid_lesstif/wt_preview.c \ + ../src_plugins/hid_lesstif/wt_preview.h dolists.h +../src_plugins/hid_lesstif/menu.o: ../src_plugins/hid_lesstif/menu.c \ + ../src_plugins/hid_lesstif/xincludes.h ../config.h conf_core.h conf.h \ + global_typedefs.h pcb_bool.h unit.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h globalconst.h color.h data.h layer.h \ + attrib.h obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h obj_line_list.h obj_line.h obj_poly_list.h \ + obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h crosshair.h \ + vtonpoint.h hid.h error.h route.h buffer.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h obj_rat_list.h obj_rat.h layer_grp.h idpath.h \ + obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h error.h \ + pcb-printf.h layer.h hid.h hid_cfg.h hid_cfg_action.h hid_cfg.h \ + hid_cfg_input.h conf_hid.h ../src_plugins/hid_lesstif/lesstif.h board.h \ + vtroutestyle.h rats_patch.h board.h paths.h actions.h hid_flags.h \ + ../src_plugins/hid_lesstif/stdarg.h color.h event.h compat_misc.h \ + layer_vis.h +../src_plugins/hid_lesstif/netlist.o: \ + ../src_plugins/hid_lesstif/netlist.c ../config.h \ + ../src_plugins/hid_lesstif/xincludes.h compat_misc.h data.h \ + globalconst.h global_typedefs.h pcb_bool.h unit.h layer.h attrib.h \ + color.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h ../src_3rd/genht/ht.h box.h math_helper.h \ + misc_util.h ../src_3rd/genvector/gds_char.h crosshair.h vtonpoint.h \ + hid.h ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h error.h route.h \ + buffer.h ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h \ + obj_rat_list.h obj_rat.h layer_grp.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h find.h netlist2.h board.h vtroutestyle.h rats_patch.h \ + select.h operation.h undo.h ../src_3rd/libuundo/uundo.h undo_old.h \ + remove.h crosshair.h draw.h event.h fptr_cast.h hid.h actions.h \ + ../src_plugins/hid_lesstif/lesstif.h hid_cfg_input.h hid_cfg.h board.h \ + ../src_plugins/hid_lesstif/stdarg.h color.h +../src_plugins/hid_lesstif/stdarg.o: ../src_plugins/hid_lesstif/stdarg.c \ + ../src_plugins/hid_lesstif/stdarg.h \ + ../src_plugins/hid_lesstif/xincludes.h color.h global_typedefs.h \ + ../config.h pcb_bool.h unit.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h +../src_plugins/hid_lesstif/styles.o: ../src_plugins/hid_lesstif/styles.c \ + ../src_plugins/hid_lesstif/xincludes.h ../config.h conf_core.h conf.h \ + global_typedefs.h pcb_bool.h unit.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h globalconst.h color.h compat_misc.h data.h \ + layer.h attrib.h obj_common.h flag.h data_parent.h obj_arc_list.h \ + obj_arc.h ../src_3rd/genlist/gendlist.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h crosshair.h \ + vtonpoint.h hid.h error.h route.h buffer.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h obj_rat_list.h obj_rat.h layer_grp.h idpath.h \ + obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h pcb-printf.h \ + actions.h hid.h ../src_plugins/hid_lesstif/lesstif.h hid_cfg_input.h \ + hid_cfg.h board.h vtroutestyle.h rats_patch.h board.h \ + ../src_plugins/hid_lesstif/stdarg.h color.h misc_util.h event.h +../src_plugins/hid_lesstif/wt_colorbtn.o: \ + ../src_plugins/hid_lesstif/wt_colorbtn.c compat_misc.h ../config.h \ + color.h global_typedefs.h pcb_bool.h unit.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h +../src_plugins/hid_lesstif/wt_xpm.o: ../src_plugins/hid_lesstif/wt_xpm.c \ + compat_misc.h ../config.h +../src_plugins/hid_lesstif/xm_tree_table_pixmaps.o: \ + ../src_plugins/hid_lesstif/xm_tree_table_pixmaps.c \ + ../src_plugins/hid_lesstif/xm_tree_table_priv.h \ + ../src_plugins/hid_lesstif/xm_tree_table_widget.h \ + ../src_3rd/genlist/gendlist.h +../src_plugins/hid_lesstif/xm_tree_table_priv.o: \ + ../src_plugins/hid_lesstif/xm_tree_table_priv.c ../config.h \ + ../src_3rd/genvector/vtp0.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h \ + ../src_plugins/hid_lesstif/xm_tree_table_priv.h \ + ../src_plugins/hid_lesstif/xm_tree_table_widget.h \ + ../src_3rd/genlist/gendlist.h +../src_plugins/hid_lesstif/xm_tree_table_widget.o: \ + ../src_plugins/hid_lesstif/xm_tree_table_widget.c ../config.h \ + ../src_plugins/hid_lesstif/xm_tree_table_priv.h \ + ../src_plugins/hid_lesstif/xm_tree_table_widget.h \ + ../src_3rd/genlist/gendlist.h +../src_plugins/hid_remote/base64.o: ../src_plugins/hid_remote/base64.c \ + ../src_plugins/hid_remote/base64.h +../src_plugins/hid_remote/proto.o: ../src_plugins/hid_remote/proto.c \ + pcb-printf.h ../src_3rd/genvector/gds_char.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h unit.h ../config.h \ + ../src_plugins/hid_remote/proto_lowcommon.h \ + ../src_plugins/hid_remote/proto_lowsend.h \ + ../src_plugins/hid_remote/base64.h \ + ../src_plugins/hid_remote/proto_lowparse.h layer.h globalconst.h \ + global_typedefs.h pcb_bool.h attrib.h color.h obj_common.h flag.h \ + data_parent.h obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h ../src_3rd/genht/ht.h box.h math_helper.h \ + misc_util.h layer_grp.h layer.h +../src_plugins/hid_remote/remote.o: ../src_plugins/hid_remote/remote.c \ + ../config.h board.h ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h \ + global_typedefs.h pcb_bool.h unit.h vtroutestyle.h attrib.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h board.h hid.h ../src_3rd/liblihata/dom.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/parser.h error.h \ + data.h crosshair.h vtonpoint.h hid.h route.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h draw.h layer.h pcb-printf.h plugins.h \ + ../src_3rd/puplug/puplug.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/os_dep.h ../src_3rd/puplug/config.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/error.h compat_misc.h \ + funchash_core.h funchash.h funchash_core_list.h event.h \ + ../src_plugins/hid_remote/proto.h hid_draw_helpers.h hid_nogui.h \ + actions.h hid_init.h dolists.h +../src_plugins/import_calay/calay.o: ../src_plugins/import_calay/calay.c \ + ../config.h board.h ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h \ + global_typedefs.h pcb_bool.h unit.h vtroutestyle.h attrib.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h board.h data.h crosshair.h vtonpoint.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h error.h route.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h error.h pcb-printf.h compat_misc.h safe_fs.h conf.h \ + pcb-printf.h ../src_3rd/liblihata/lihata.h list_conf.h actions.h \ + plugins.h ../src_3rd/puplug/puplug.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/os_dep.h ../src_3rd/puplug/config.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/error.h hid.h dolists.h +../src_plugins/import_dsn/dsn.o: ../src_plugins/import_dsn/dsn.c \ + ../config.h ../src_3rd/gensexpr/gsxl.h \ + ../src_3rd/gensexpr/gensexpr_impl.h ../src_3rd/gensexpr/gsx_parse.h \ + board.h ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h global_typedefs.h \ + pcb_bool.h unit.h vtroutestyle.h attrib.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h board.h data.h crosshair.h vtonpoint.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h error.h route.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h polygon.h safe_fs.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h list_conf.h actions.h hid.h plugins.h \ + ../src_3rd/puplug/puplug.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/os_dep.h ../src_3rd/puplug/config.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/error.h \ + ../src_plugins/lib_compat_help/pstk_compat.h obj_pstk.h dolists.h +../src_plugins/import_edif/edif.o: ../src_plugins/import_edif/edif.c \ + math_helper.h board.h ../config.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h global_typedefs.h pcb_bool.h unit.h vtroutestyle.h \ + attrib.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h board.h data.h crosshair.h vtonpoint.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h error.h route.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h error.h netlist2.h plugins.h ../src_3rd/puplug/puplug.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/os_dep.h \ + ../src_3rd/puplug/config.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/error.h compat_misc.h safe_fs.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h list_conf.h +../src_plugins/import_edif/import_edif.o: \ + ../src_plugins/import_edif/import_edif.c ../config.h board.h \ + ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h global_typedefs.h \ + pcb_bool.h unit.h vtroutestyle.h attrib.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h board.h data.h crosshair.h vtonpoint.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h error.h route.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h plugins.h ../src_3rd/puplug/puplug.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/os_dep.h \ + ../src_3rd/puplug/config.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/error.h plug_import.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h list_conf.h rats_patch.h plug_io.h +../src_plugins/import_fpcb_nl/fpcb_nl.o: \ + ../src_plugins/import_fpcb_nl/fpcb_nl.c ../config.h \ + ../src_3rd/qparse/qparse.h board.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h global_typedefs.h pcb_bool.h unit.h vtroutestyle.h \ + attrib.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h board.h data.h crosshair.h vtonpoint.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h error.h route.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h error.h pcb-printf.h compat_misc.h safe_fs.h conf.h \ + pcb-printf.h ../src_3rd/liblihata/lihata.h list_conf.h actions.h \ + plugins.h ../src_3rd/puplug/puplug.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/os_dep.h ../src_3rd/puplug/config.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/error.h hid.h dolists.h +../src_plugins/import_hpgl/hpgl.o: ../src_plugins/import_hpgl/hpgl.c \ + ../config.h ../src_3rd/libuhpgl/libuhpgl.h ../src_3rd/libuhpgl/parse.h \ + ../src_3rd/libuhpgl/libuhpgl.h board.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h global_typedefs.h pcb_bool.h unit.h vtroutestyle.h \ + attrib.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h board.h conf_core.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/dom.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/parser.h \ + ../src_3rd/genvector/vtp0.h list_conf.h data.h crosshair.h vtonpoint.h \ + hid.h error.h route.h buffer.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h obj_rat_list.h obj_rat.h idpath.h \ + obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h buffer.h error.h \ + pcb-printf.h compat_misc.h safe_fs.h actions.h plugins.h \ + ../src_3rd/puplug/puplug.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/os_dep.h ../src_3rd/puplug/config.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/error.h hid.h dolists.h +../src_plugins/import_ipcd356/ipcd356.o: \ + ../src_plugins/import_ipcd356/ipcd356.c ../config.h \ + ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h \ + board.h global_typedefs.h pcb_bool.h unit.h vtroutestyle.h attrib.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h board.h data.h crosshair.h vtonpoint.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h error.h route.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h safe_fs.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h list_conf.h conf_core.h hid.h \ + compat_misc.h actions.h plugins.h ../src_3rd/puplug/puplug.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/os_dep.h \ + ../src_3rd/puplug/config.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/error.h rtree.h \ + ../src_plugins/lib_compat_help/pstk_help.h obj_pstk.h dolists.h +../src_plugins/import_ltspice/ltspice.o: \ + ../src_plugins/import_ltspice/ltspice.c ../config.h \ + ../src_3rd/qparse/qparse.h board.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h global_typedefs.h pcb_bool.h unit.h vtroutestyle.h \ + attrib.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h board.h data.h crosshair.h vtonpoint.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h error.h route.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h error.h pcb-printf.h compat_misc.h safe_fs.h conf.h \ + pcb-printf.h ../src_3rd/liblihata/lihata.h list_conf.h actions.h \ + plugins.h ../src_3rd/puplug/puplug.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/os_dep.h ../src_3rd/puplug/config.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/error.h hid.h dolists.h +../src_plugins/import_mentor_sch/mentor_sch.o: \ + ../src_plugins/import_mentor_sch/mentor_sch.c ../config.h board.h \ + ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h global_typedefs.h \ + pcb_bool.h unit.h vtroutestyle.h attrib.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h board.h data.h crosshair.h vtonpoint.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h error.h route.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h error.h pcb-printf.h compat_misc.h \ + ../src_3rd/gensexpr/gsxl.h ../src_3rd/gensexpr/gensexpr_impl.h \ + ../src_3rd/gensexpr/gsx_parse.h actions.h plugins.h \ + ../src_3rd/puplug/puplug.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/os_dep.h ../src_3rd/puplug/config.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/error.h hid.h \ + ../src_plugins/import_mentor_sch/mentor_sch_conf.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h list_conf.h conf.h paths.h safe_fs.h \ + ../src_plugins/import_mentor_sch/netlist_helper.h \ + ../src_3rd/genregex/regex_se.h ../src_3rd/genregex/regex_templ.h \ + ../src_3rd/genregex/regex.h dolists.h \ + ../src_plugins/import_mentor_sch/mentor_sch_conf_fields.h +../src_plugins/import_mentor_sch/netlist_helper.o: \ + ../src_plugins/import_mentor_sch/netlist_helper.c ../config.h \ + ../src_3rd/genht/hash.h \ + ../src_plugins/import_mentor_sch/netlist_helper.h \ + ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h \ + ../src_3rd/genregex/regex_se.h ../src_3rd/genregex/regex_templ.h \ + ../src_3rd/genregex/regex.h compat_misc.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h unit.h error.h actions.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h error.h global_typedefs.h pcb_bool.h \ + attrib.h layer.h globalconst.h color.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h safe_fs.h conf.h \ + pcb-printf.h ../src_3rd/liblihata/lihata.h ../src_3rd/genvector/vtp0.h \ + list_conf.h +../src_plugins/import_mucs/mucs.o: ../src_plugins/import_mucs/mucs.c \ + ../config.h board.h ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h \ + global_typedefs.h pcb_bool.h unit.h vtroutestyle.h attrib.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h board.h data.h crosshair.h vtonpoint.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h error.h route.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h error.h pcb-printf.h compat_misc.h safe_fs.h conf.h \ + pcb-printf.h ../src_3rd/liblihata/lihata.h list_conf.h actions.h \ + plugins.h ../src_3rd/puplug/puplug.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/os_dep.h ../src_3rd/puplug/config.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/error.h layer.h conf_core.h \ + ../src_plugins/lib_compat_help/pstk_compat.h obj_pstk.h dolists.h +../src_plugins/import_netlist/import_netlist.o: \ + ../src_plugins/import_netlist/import_netlist.c ../config.h board.h \ + ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h global_typedefs.h \ + pcb_bool.h unit.h vtroutestyle.h attrib.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h board.h plugins.h ../src_3rd/puplug/puplug.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/os_dep.h \ + ../src_3rd/puplug/config.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/error.h plug_io.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/dom.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/parser.h \ + ../src_3rd/genvector/vtp0.h list_conf.h plug_import.h conf_core.h \ + error.h data.h crosshair.h vtonpoint.h hid.h error.h route.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h rats_patch.h \ + compat_misc.h paths.h safe_fs.h macro.h netlist2.h +../src_plugins/import_sch/import_sch.o: \ + ../src_plugins/import_sch/import_sch.c ../config.h conf_core.h conf.h \ + global_typedefs.h pcb_bool.h unit.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h globalconst.h color.h board.h \ + vtroutestyle.h attrib.h layer.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h obj_line_list.h \ + obj_line.h obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h \ + obj_text.h font.h ../src_3rd/genht/htip.h box.h math_helper.h \ + misc_util.h layer_grp.h rats_patch.h board.h data.h crosshair.h \ + vtonpoint.h hid.h error.h route.h buffer.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h obj_rat_list.h obj_rat.h idpath.h \ + obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h change.h error.h \ + undo.h ../src_3rd/libuundo/uundo.h undo_old.h plugins.h \ + ../src_3rd/puplug/puplug.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/os_dep.h ../src_3rd/puplug/config.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/error.h paths.h compat_fs.h \ + pcb-printf.h remove.h actions.h \ + ../src_plugins/import_sch/import_sch_conf.h conf.h misc_util.h \ + compat_misc.h obj_rat.h dolists.h \ + ../src_plugins/import_sch/import_sch_conf_fields.h +../src_plugins/import_tinycad/tinycad.o: \ + ../src_plugins/import_tinycad/tinycad.c ../config.h \ + ../src_3rd/qparse/qparse.h board.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h global_typedefs.h pcb_bool.h unit.h vtroutestyle.h \ + attrib.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h board.h data.h crosshair.h vtonpoint.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h error.h route.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h error.h pcb-printf.h compat_misc.h safe_fs.h conf.h \ + pcb-printf.h ../src_3rd/liblihata/lihata.h list_conf.h actions.h \ + plugins.h ../src_3rd/puplug/puplug.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/os_dep.h ../src_3rd/puplug/config.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/error.h hid.h dolists.h +../src_plugins/import_ttf/str_approx.o: \ + ../src_plugins/import_ttf/str_approx.c \ + ../src_plugins/import_ttf/ttf_load.h \ + ../src_plugins/import_ttf/str_approx.h +../src_plugins/import_ttf/ttf.o: ../src_plugins/import_ttf/ttf.c \ + ../config.h board.h ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h \ + global_typedefs.h pcb_bool.h unit.h vtroutestyle.h attrib.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h board.h data.h crosshair.h vtonpoint.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h error.h route.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h actions.h plugins.h ../src_3rd/puplug/puplug.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/os_dep.h \ + ../src_3rd/puplug/config.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/error.h hid.h ../src_plugins/import_ttf/ttf_load.h \ + dolists.h +../src_plugins/import_ttf/ttf_load.o: \ + ../src_plugins/import_ttf/ttf_load.c \ + ../src_plugins/import_ttf/ttf_load.h +../src_plugins/io_autotrax/io_autotrax.o: \ + ../src_plugins/io_autotrax/io_autotrax.c ../config.h plugins.h \ + ../src_3rd/puplug/puplug.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/os_dep.h ../src_3rd/puplug/config.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/error.h plug_io.h \ + global_typedefs.h pcb_bool.h unit.h conf.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_plugins/io_autotrax/write.h data.h \ + globalconst.h layer.h attrib.h color.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h obj_line_list.h \ + obj_line.h obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h \ + obj_text.h font.h ../src_3rd/genht/htip.h box.h math_helper.h \ + misc_util.h crosshair.h vtonpoint.h hid.h error.h route.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h layer_grp.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h \ + ../src_plugins/io_autotrax/read.h actions.h board.h vtroutestyle.h \ + rats_patch.h board.h conf_core.h buffer.h hid.h compat_misc.h +../src_plugins/io_autotrax/read.o: ../src_plugins/io_autotrax/read.c \ + ../config.h ../src_3rd/qparse/qparse.h compat_misc.h board.h \ + ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h global_typedefs.h \ + pcb_bool.h unit.h vtroutestyle.h attrib.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h board.h plug_io.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/dom.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/parser.h \ + ../src_3rd/genvector/vtp0.h list_conf.h error.h data.h crosshair.h \ + vtonpoint.h hid.h error.h route.h buffer.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h obj_rat_list.h obj_rat.h idpath.h \ + obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h \ + ../src_plugins/io_autotrax/read.h layer.h polygon.h misc_util.h \ + conf_core.h move.h macro.h safe_fs.h rotate.h compat_misc.h actions.h \ + undo.h ../src_3rd/libuundo/uundo.h undo_old.h \ + ../src_plugins/lib_compat_help/pstk_compat.h obj_pstk.h \ + ../src_plugins/lib_compat_help/pstk_help.h \ + ../src_plugins/lib_compat_help/subc_help.h obj_subc.h +../src_plugins/io_autotrax/write.o: ../src_plugins/io_autotrax/write.c \ + ../config.h compat_misc.h board.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h global_typedefs.h pcb_bool.h unit.h vtroutestyle.h \ + attrib.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h board.h plug_io.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/dom.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/parser.h \ + ../src_3rd/genvector/vtp0.h list_conf.h error.h netlist2.h data.h \ + crosshair.h vtonpoint.h hid.h error.h route.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h \ + ../src_plugins/io_autotrax/write.h layer.h polygon_offs.h \ + ../src_plugins/io_autotrax/../lib_polyhelp/polyhelp.h obj_poly.h \ + ../src_plugins/lib_compat_help/pstk_compat.h obj_pstk.h +../src_plugins/io_dsn/io_dsn.o: ../src_plugins/io_dsn/io_dsn.c \ + ../config.h ../src_plugins/io_dsn/read.h plug_io.h global_typedefs.h \ + pcb_bool.h unit.h conf.h pcb-printf.h ../src_3rd/genvector/gds_char.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_plugins/io_dsn/write.h hid.h \ + error.h attrib.h layer.h globalconst.h color.h obj_common.h flag.h \ + data_parent.h obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h compat_misc.h plugins.h \ + ../src_3rd/puplug/puplug.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/os_dep.h ../src_3rd/puplug/config.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/error.h dolists.h +../src_plugins/io_dsn/read.o: ../src_plugins/io_dsn/read.c ../config.h \ + ../src_3rd/gensexpr/gsxl.h ../src_3rd/gensexpr/gensexpr_impl.h \ + ../src_3rd/gensexpr/gsx_parse.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h board.h global_typedefs.h pcb_bool.h unit.h \ + vtroutestyle.h attrib.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h board.h data.h crosshair.h vtonpoint.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h error.h route.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h plug_io.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h list_conf.h error.h pcb_bool.h safe_fs.h \ + compat_misc.h layer_grp.h conf_core.h math_helper.h actions.h netlist2.h \ + polygon_offs.h ../src_plugins/io_dsn/read.h +../src_plugins/io_dsn/write.o: ../src_plugins/io_dsn/write.c ../config.h \ + plug_io.h global_typedefs.h pcb_bool.h unit.h conf.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h error.h pcb_bool.h board.h vtroutestyle.h \ + attrib.h layer.h globalconst.h color.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h obj_line_list.h \ + obj_line.h obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h \ + obj_text.h font.h ../src_3rd/genht/htip.h box.h math_helper.h \ + misc_util.h layer_grp.h rats_patch.h board.h data.h crosshair.h \ + vtonpoint.h hid.h error.h route.h buffer.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h obj_rat_list.h obj_rat.h idpath.h \ + obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h layer.h \ + layer_grp.h ../src_plugins/io_dsn/write.h \ + ../src_plugins/lib_netmap/netmap.h netlist2.h +../src_plugins/io_eagle/eagle_bin.o: ../src_plugins/io_eagle/eagle_bin.c \ + ../config.h ../src_plugins/io_eagle/eagle_bin.h \ + ../src_plugins/io_eagle/egb_tree.h ../src_3rd/genht/htss.h \ + ../src_3rd/genht/ht.h error.h math_helper.h misc_util.h unit.h \ + pcb_bool.h +../src_plugins/io_eagle/egb_tree.o: ../src_plugins/io_eagle/egb_tree.c \ + ../config.h ../src_3rd/genht/hash.h ../src_plugins/io_eagle/egb_tree.h \ + ../src_3rd/genht/htss.h ../src_3rd/genht/ht.h compat_misc.h +../src_plugins/io_eagle/io_eagle.o: ../src_plugins/io_eagle/io_eagle.c \ + ../config.h plugins.h ../src_3rd/puplug/puplug.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/os_dep.h \ + ../src_3rd/puplug/config.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/error.h hid.h ../src_3rd/liblihata/dom.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/parser.h \ + ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h error.h global_typedefs.h \ + pcb_bool.h unit.h attrib.h layer.h globalconst.h color.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h \ + ../src_3rd/genvector/gds_char.h plug_io.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_plugins/io_eagle/read.h board.h vtroutestyle.h layer_grp.h \ + rats_patch.h board.h conf.h ../src_plugins/io_eagle/read_dru.h actions.h \ + hid.h ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h dolists.h +../src_plugins/io_eagle/read.o: ../src_plugins/io_eagle/read.c \ + ../config.h board.h ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h \ + global_typedefs.h pcb_bool.h unit.h vtroutestyle.h attrib.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h board.h data.h crosshair.h vtonpoint.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h error.h route.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h ../src_plugins/io_eagle/read.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h list_conf.h conf.h plug_io.h conf_core.h \ + error.h polygon.h rtree.h actions.h undo.h ../src_3rd/libuundo/uundo.h \ + undo_old.h compat_misc.h ../src_plugins/io_eagle/trparse.h \ + ../src_plugins/io_eagle/trparse_xml.h \ + ../src_plugins/io_eagle/trparse_bin.h obj_subc.h \ + ../src_plugins/lib_compat_help/pstk_compat.h obj_pstk.h \ + ../src_plugins/lib_compat_help/subc_help.h layer.h \ + ../src_plugins/lib_compat_help/pstk_help.h +../src_plugins/io_eagle/read_dru.o: ../src_plugins/io_eagle/read_dru.c \ + ../config.h ../src_3rd/genvector/gds_char.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h \ + ../src_plugins/io_eagle/read_dru.h plug_io.h global_typedefs.h \ + pcb_bool.h unit.h conf.h pcb-printf.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h conf_core.h globalconst.h color.h \ + safe_fs.h board.h vtroutestyle.h attrib.h layer.h obj_common.h flag.h \ + data_parent.h obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h layer_grp.h rats_patch.h board.h layer_grp.h \ + error.h +../src_plugins/io_eagle/trparse_bin.o: \ + ../src_plugins/io_eagle/trparse_bin.c ../config.h error.h safe_fs.h \ + conf.h global_typedefs.h pcb_bool.h unit.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_plugins/io_eagle/egb_tree.h \ + ../src_3rd/genht/htss.h ../src_plugins/io_eagle/eagle_bin.h \ + ../src_plugins/io_eagle/trparse.h ../src_plugins/io_eagle/trparse_bin.h +../src_plugins/io_eagle/trparse_xml.o: \ + ../src_plugins/io_eagle/trparse_xml.c ../config.h error.h safe_fs.h \ + conf.h global_typedefs.h pcb_bool.h unit.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_plugins/io_eagle/trparse.h \ + ../src_plugins/io_eagle/trparse_xml.h +../src_plugins/io_hyp/hyp_l.o: ../src_plugins/io_hyp/hyp_l.c \ + ../src_plugins/io_hyp/hyp_y.h ../src_plugins/io_hyp/parser.h pcb_bool.h \ + board.h ../config.h ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h \ + global_typedefs.h pcb_bool.h unit.h vtroutestyle.h attrib.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h board.h +../src_plugins/io_hyp/hyp_y.o: ../src_plugins/io_hyp/hyp_y.c \ + ../src_plugins/io_hyp/parser.h pcb_bool.h board.h ../config.h \ + ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h global_typedefs.h \ + pcb_bool.h unit.h vtroutestyle.h attrib.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h board.h ../src_plugins/io_hyp/hyp_l.h +../src_plugins/io_hyp/io_hyp.o: ../src_plugins/io_hyp/io_hyp.c \ + ../config.h hid.h ../src_3rd/liblihata/dom.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/parser.h \ + ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h error.h global_typedefs.h \ + pcb_bool.h unit.h attrib.h layer.h globalconst.h color.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h \ + ../src_3rd/genvector/gds_char.h hid_draw_helpers.h hid_nogui.h actions.h \ + hid.h ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h hid_init.h \ + ../src_3rd/puplug/puplug.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/os_dep.h ../src_3rd/puplug/config.h \ + ../src_3rd/puplug/libs.h hid_attrib.h plugins.h \ + ../src_3rd/puplug/error.h event.h plug_io.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_plugins/io_hyp/parser.h pcb_bool.h board.h vtroutestyle.h \ + layer_grp.h rats_patch.h board.h ../src_plugins/io_hyp/write.h obj_rat.h \ + idpath.h dolists.h +../src_plugins/io_hyp/parser.o: ../src_plugins/io_hyp/parser.c \ + ../src_plugins/io_hyp/parser.h pcb_bool.h board.h ../config.h \ + ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h global_typedefs.h \ + pcb_bool.h unit.h vtroutestyle.h attrib.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h board.h ../src_plugins/io_hyp/hyp_l.h \ + ../src_plugins/io_hyp/hyp_y.h error.h pcb-printf.h flag_str.h polygon.h \ + rtree.h ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h layer.h \ + data.h crosshair.h vtonpoint.h hid.h ../src_3rd/liblihata/dom.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/parser.h error.h \ + route.h buffer.h ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h \ + obj_rat_list.h obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h ht_subc.h ../src_3rd/genht/ht.h \ + ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h search.h rotate.h compat_misc.h actions.h plug_io.h \ + conf.h pcb-printf.h ../src_3rd/liblihata/lihata.h list_conf.h \ + compat_misc.h safe_fs.h ../src_plugins/lib_compat_help/pstk_help.h \ + obj_pstk.h ../src_plugins/lib_compat_help/subc_help.h obj_subc.h +../src_plugins/io_hyp/write.o: ../src_plugins/io_hyp/write.c ../config.h \ + ../src_plugins/io_hyp/write.h pcb_bool.h plug_io.h global_typedefs.h \ + pcb_bool.h unit.h conf.h pcb-printf.h ../src_3rd/genvector/gds_char.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h board.h vtroutestyle.h attrib.h layer.h \ + globalconst.h color.h obj_common.h flag.h data_parent.h obj_arc_list.h \ + obj_arc.h ../src_3rd/genlist/gendlist.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h layer_grp.h \ + rats_patch.h board.h data.h crosshair.h vtonpoint.h hid.h error.h \ + route.h buffer.h ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h \ + obj_rat_list.h obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h compat_misc.h \ + polygon.h obj_subc_parent.h data.h obj_pstk_inlines.h thermal.h \ + ../src_plugins/lib_netmap/netmap.h netlist2.h funchash_core.h funchash.h \ + funchash_core_list.h ../src_3rd/genht/htpi.h +../src_plugins/io_kicad/io_kicad.o: ../src_plugins/io_kicad/io_kicad.c \ + ../config.h plugins.h ../src_3rd/puplug/puplug.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/os_dep.h \ + ../src_3rd/puplug/config.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/error.h plug_io.h global_typedefs.h pcb_bool.h unit.h \ + conf.h pcb-printf.h ../src_3rd/genvector/gds_char.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_plugins/io_kicad/write.h data.h \ + globalconst.h layer.h attrib.h color.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h obj_line_list.h \ + obj_line.h obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h \ + obj_text.h font.h ../src_3rd/genht/htip.h box.h math_helper.h \ + misc_util.h crosshair.h vtonpoint.h hid.h error.h route.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h layer_grp.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h \ + ../src_plugins/io_kicad/read.h ../src_plugins/io_kicad/read_net.h unit.h \ + actions.h dolists.h +../src_plugins/io_kicad/layertab.o: ../src_plugins/io_kicad/layertab.c \ + ../config.h ../src_plugins/io_kicad/layertab.h layer.h globalconst.h \ + global_typedefs.h pcb_bool.h unit.h attrib.h color.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h ../src_3rd/genht/ht.h box.h math_helper.h \ + misc_util.h ../src_3rd/genvector/gds_char.h +../src_plugins/io_kicad/read.o: ../src_plugins/io_kicad/read.c \ + ../config.h ../src_3rd/gensexpr/gsxl.h \ + ../src_3rd/gensexpr/gensexpr_impl.h ../src_3rd/gensexpr/gsx_parse.h \ + ../src_3rd/genht/htsi.h ../src_3rd/genht/ht.h \ + ../src_3rd/genvector/vtp0.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h compat_misc.h board.h \ + ../src_3rd/genht/htsp.h global_typedefs.h pcb_bool.h unit.h \ + vtroutestyle.h attrib.h layer.h globalconst.h color.h obj_common.h \ + flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h board.h plug_io.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/dom.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/parser.h list_conf.h \ + error.h data.h crosshair.h vtonpoint.h hid.h error.h route.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h \ + ../src_plugins/io_kicad/read.h layer.h polygon.h plug_footprint.h \ + vtlibrary.h data.h misc_util.h conf_core.h move.h macro.h rotate.h \ + compat_misc.h safe_fs.h attrib.h netlist2.h math_helper.h \ + obj_pstk_inlines.h thermal.h \ + ../src_plugins/lib_compat_help/pstk_compat.h obj_pstk.h \ + ../src_plugins/lib_compat_help/pstk_help.h \ + ../src_plugins/lib_compat_help/subc_help.h obj_subc.h \ + ../src_plugins/lib_compat_help/media.h ../src_plugins/shape/shape.h \ + pcb_bool.h ../src_plugins/io_kicad/layertab.h +../src_plugins/io_kicad/read_net.o: ../src_plugins/io_kicad/read_net.c \ + ../config.h ../src_3rd/gensexpr/gsxl.h \ + ../src_3rd/gensexpr/gensexpr_impl.h ../src_3rd/gensexpr/gsx_parse.h \ + ../src_plugins/io_kicad/read_net.h unit.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h ../src_3rd/genht/htpp.h \ + board.h global_typedefs.h pcb_bool.h unit.h vtroutestyle.h attrib.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h board.h data.h crosshair.h vtonpoint.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h error.h route.h buffer.h obj_rat_list.h \ + obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h error.h pcb-printf.h compat_misc.h safe_fs.h conf.h \ + pcb-printf.h ../src_3rd/liblihata/lihata.h list_conf.h actions.h \ + plugins.h ../src_3rd/puplug/puplug.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/os_dep.h ../src_3rd/puplug/config.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/error.h hid.h +../src_plugins/io_kicad/uniq_name.o: ../src_plugins/io_kicad/uniq_name.c \ + ../src_3rd/genht/hash.h ../config.h ../src_plugins/io_kicad/uniq_name.h \ + ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h compat_misc.h +../src_plugins/io_kicad/write.o: ../src_plugins/io_kicad/write.c \ + ../config.h compat_misc.h board.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h global_typedefs.h pcb_bool.h unit.h vtroutestyle.h \ + attrib.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h board.h plug_io.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/dom.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/parser.h \ + ../src_3rd/genvector/vtp0.h list_conf.h error.h \ + ../src_plugins/io_kicad/uniq_name.h data.h crosshair.h vtonpoint.h hid.h \ + error.h route.h buffer.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h obj_rat_list.h obj_rat.h idpath.h \ + obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h \ + ../src_plugins/io_kicad/write.h layer.h netlist2.h obj_pstk_inlines.h \ + data.h thermal.h funchash_core.h funchash.h funchash_core_list.h \ + ../src_plugins/lib_compat_help/pstk_compat.h obj_pstk.h +../src_plugins/io_kicad_legacy/io_kicad_legacy.o: \ + ../src_plugins/io_kicad_legacy/io_kicad_legacy.c ../config.h plugins.h \ + ../src_3rd/puplug/puplug.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/os_dep.h ../src_3rd/puplug/config.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/error.h plug_io.h \ + global_typedefs.h pcb_bool.h unit.h conf.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_plugins/io_kicad_legacy/write.h \ + data.h globalconst.h layer.h attrib.h color.h obj_common.h flag.h \ + data_parent.h obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h crosshair.h vtonpoint.h hid.h error.h route.h \ + buffer.h ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h \ + obj_rat_list.h obj_rat.h layer_grp.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h +../src_plugins/io_kicad_legacy/write.o: \ + ../src_plugins/io_kicad_legacy/write.c ../config.h compat_misc.h board.h \ + ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h global_typedefs.h \ + pcb_bool.h unit.h vtroutestyle.h attrib.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h board.h plug_io.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/dom.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/parser.h \ + ../src_3rd/genvector/vtp0.h list_conf.h error.h data.h crosshair.h \ + vtonpoint.h hid.h error.h route.h buffer.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h obj_rat_list.h obj_rat.h idpath.h \ + obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h \ + ../src_plugins/io_kicad_legacy/write.h layer.h netlist2.h macro.h \ + obj_pstk_inlines.h data.h thermal.h \ + ../src_plugins/io_kicad_legacy/../io_kicad/uniq_name.h \ + ../src_plugins/lib_compat_help/pstk_compat.h obj_pstk.h +../src_plugins/io_lihata/common.o: ../src_plugins/io_lihata/common.c \ + ../config.h data.h globalconst.h global_typedefs.h pcb_bool.h unit.h \ + layer.h attrib.h color.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h ../src_3rd/genht/ht.h box.h math_helper.h \ + misc_util.h ../src_3rd/genvector/gds_char.h crosshair.h vtonpoint.h \ + hid.h ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h error.h route.h \ + buffer.h ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h \ + obj_rat_list.h obj_rat.h layer_grp.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h macro.h ../src_plugins/io_lihata/common.h thermal.h +../src_plugins/io_lihata/io_lihata.o: \ + ../src_plugins/io_lihata/io_lihata.c ../config.h plugins.h \ + ../src_3rd/puplug/puplug.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/os_dep.h ../src_3rd/puplug/config.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/error.h plug_io.h \ + global_typedefs.h pcb_bool.h unit.h conf.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_plugins/io_lihata/read.h \ + ../src_plugins/io_lihata/write.h ../src_plugins/io_lihata/io_lihata.h \ + conf.h ../src_plugins/io_lihata/lht_conf.h \ + ../src_plugins/io_lihata/lht_conf_fields.h +../src_plugins/io_lihata/read.o: ../src_plugins/io_lihata/read.c \ + ../src_3rd/liblihata/tree.h ../src_3rd/liblihata/dom.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/parser.h \ + ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h \ + ../src_3rd/libminuid/libminuid.h ../config.h board.h global_typedefs.h \ + pcb_bool.h unit.h vtroutestyle.h attrib.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h board.h data.h crosshair.h vtonpoint.h hid.h error.h \ + route.h buffer.h ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h \ + obj_rat_list.h obj_rat.h idpath.h obj_subc_list.h obj_subc.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h plugins.h ../src_3rd/puplug/puplug.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/os_dep.h \ + ../src_3rd/puplug/config.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/error.h plug_io.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h list_conf.h flag_str.h compat_misc.h \ + macro.h error.h misc_util.h layer.h ../src_plugins/io_lihata/common.h \ + polygon.h conf_core.h obj_subc.h pcb_minuid.h thermal.h \ + ../src_plugins/io_lihata/io_lihata.h conf.h \ + ../src_plugins/io_lihata/lht_conf.h safe_fs.h plug_footprint.h \ + vtlibrary.h data.h vtpadstack.h obj_pstk_inlines.h thermal.h netlist2.h \ + ../src_plugins/lib_compat_help/subc_help.h \ + ../src_plugins/lib_compat_help/pstk_compat.h obj_pstk.h \ + ../src_plugins/lib_compat_help/elem_rot.h +../src_plugins/io_lihata/write.o: ../src_plugins/io_lihata/write.c \ + ../src_3rd/liblihata/tree.h ../src_3rd/liblihata/dom.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/parser.h \ + ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h \ + ../src_3rd/libminuid/libminuid.h ../config.h board.h global_typedefs.h \ + pcb_bool.h unit.h vtroutestyle.h attrib.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h board.h conf_core.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/genvector/vtp0.h list_conf.h \ + data.h crosshair.h vtonpoint.h hid.h error.h route.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h idpath.h obj_subc_list.h obj_subc.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h plugins.h \ + ../src_3rd/puplug/puplug.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/os_dep.h ../src_3rd/puplug/config.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/error.h plug_io.h flag_str.h \ + compat_misc.h rats_patch.h actions.h misc_util.h macro.h layer.h \ + ../src_plugins/io_lihata/common.h ../src_plugins/io_lihata/write_style.h \ + ../src_3rd/liblhtpers/lhtpers.h ../src_plugins/io_lihata/io_lihata.h \ + conf.h ../src_plugins/io_lihata/lht_conf.h paths.h obj_subc_list.h \ + pcb_minuid.h safe_fs.h thermal.h funchash_core.h funchash.h \ + funchash_core_list.h netlist2.h \ + ../src_plugins/lib_compat_help/pstk_compat.h obj_pstk.h +../src_plugins/io_lihata/write_style.o: \ + ../src_plugins/io_lihata/write_style.c ../config.h \ + ../src_plugins/io_lihata/write_style.h ../src_3rd/liblhtpers/lhtpers.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h +../src_plugins/io_mentor_cell/io_mentor_cell.o: \ + ../src_plugins/io_mentor_cell/io_mentor_cell.c ../config.h plugins.h \ + ../src_3rd/puplug/puplug.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/os_dep.h ../src_3rd/puplug/config.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/error.h plug_io.h \ + global_typedefs.h pcb_bool.h unit.h conf.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_plugins/io_mentor_cell/read.h \ + actions.h hid.h error.h attrib.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h obj_line_list.h obj_line.h obj_poly_list.h \ + obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h dolists.h +../src_plugins/io_mentor_cell/read.o: \ + ../src_plugins/io_mentor_cell/read.c ../config.h \ + ../src_3rd/qparse/qparse.h ../src_3rd/genvector/gds_char.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h board.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h global_typedefs.h pcb_bool.h unit.h vtroutestyle.h \ + attrib.h layer.h globalconst.h color.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h layer_grp.h \ + rats_patch.h board.h conf_core.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/dom.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/parser.h \ + ../src_3rd/genvector/vtp0.h list_conf.h plug_io.h error.h safe_fs.h +../src_plugins/io_pcb/attribs.o: ../src_plugins/io_pcb/attribs.c \ + ../config.h conf.h global_typedefs.h pcb_bool.h unit.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h board.h vtroutestyle.h attrib.h layer.h \ + globalconst.h color.h obj_common.h flag.h data_parent.h obj_arc_list.h \ + obj_arc.h ../src_3rd/genlist/gendlist.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h layer_grp.h \ + rats_patch.h board.h compat_misc.h +../src_plugins/io_pcb/file.o: ../src_plugins/io_pcb/file.c ../config.h \ + conf_core.h conf.h global_typedefs.h pcb_bool.h unit.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h globalconst.h color.h buffer.h \ + obj_common.h flag.h attrib.h data_parent.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h change.h board.h vtroutestyle.h layer.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h obj_line_list.h \ + obj_line.h obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h \ + obj_text.h font.h ../src_3rd/genht/htip.h box.h math_helper.h \ + misc_util.h layer_grp.h rats_patch.h crosshair.h vtonpoint.h hid.h \ + error.h route.h data.h crosshair.h buffer.h obj_rat_list.h obj_rat.h \ + idpath.h obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h \ + rtree.h ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h error.h \ + ../src_plugins/io_pcb/file.h board.h plug_io.h hid.h layer.h layer_grp.h \ + move.h ../src_plugins/io_pcb/parse_common.h pcb-printf.h polygon.h \ + remove.h flag_str.h compat_fs.h compat_misc.h paths.h rats_patch.h \ + actions.h ../src_plugins/io_pcb/attribs.h route_style.h obj_poly.h \ + thermal.h event.h macro.h funchash_core.h funchash.h \ + funchash_core_list.h netlist2.h \ + ../src_plugins/lib_compat_help/layer_compat.h \ + ../src_plugins/lib_compat_help/pstk_compat.h obj_pstk.h \ + ../src_plugins/lib_compat_help/subc_help.h obj_subc.h \ + ../src_plugins/lib_compat_help/elem_rot.h +../src_plugins/io_pcb/io_pcb.o: ../src_plugins/io_pcb/io_pcb.c \ + ../config.h plugins.h ../src_3rd/puplug/puplug.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/os_dep.h \ + ../src_3rd/puplug/config.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/error.h ../src_plugins/io_pcb/parse_common.h plug_io.h \ + global_typedefs.h pcb_bool.h unit.h conf.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_plugins/io_pcb/file.h board.h \ + vtroutestyle.h attrib.h layer.h globalconst.h color.h obj_common.h \ + flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h obj_line_list.h obj_line.h obj_poly_list.h \ + obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h layer_grp.h \ + rats_patch.h board.h +../src_plugins/io_pcb/parse_l.o: ../src_plugins/io_pcb/parse_l.c \ + ../config.h conf_core.h conf.h global_typedefs.h pcb_bool.h unit.h \ + pcb-printf.h ../src_3rd/genvector/gds_char.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h globalconst.h color.h flag_str.h flag.h \ + crosshair.h vtonpoint.h hid.h error.h attrib.h layer.h obj_common.h \ + data_parent.h obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h route.h data.h crosshair.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h layer_grp.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h error.h \ + ../src_plugins/io_pcb/file.h board.h vtroutestyle.h rats_patch.h board.h \ + plug_io.h ../src_plugins/io_pcb/parse_common.h \ + ../src_plugins/io_pcb/parse_y.h plug_footprint.h vtlibrary.h data.h \ + ../src_plugins/io_pcb/attribs.h compat_misc.h compat_cc.h obj_common.h \ + paths.h safe_fs.h macro.h +../src_plugins/io_pcb/parse_y.o: ../src_plugins/io_pcb/parse_y.c \ + ../config.h flag.h globalconst.h board.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h global_typedefs.h pcb_bool.h unit.h vtroutestyle.h \ + attrib.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h color.h obj_common.h \ + flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h board.h conf_core.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/dom.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/parser.h \ + ../src_3rd/genvector/vtp0.h list_conf.h layer.h data.h crosshair.h \ + vtonpoint.h hid.h error.h route.h buffer.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h obj_rat_list.h obj_rat.h idpath.h \ + obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h error.h \ + ../src_plugins/io_pcb/file.h plug_io.h ../src_plugins/io_pcb/parse_l.h \ + polygon.h remove.h rtree.h flag_str.h obj_pinvia_therm.h rats_patch.h \ + route_style.h compat_misc.h ../src_plugins/lib_compat_help/pstk_compat.h \ + obj_pstk.h netlist2.h ../src_plugins/io_pcb/parse_y.h +../src_plugins/io_tedax/footprint.o: ../src_plugins/io_tedax/footprint.c \ + ../config.h ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h \ + ../src_3rd/genht/htip.h ../src_3rd/genht/hash.h \ + ../src_plugins/io_tedax/footprint.h data.h globalconst.h \ + global_typedefs.h pcb_bool.h unit.h layer.h attrib.h color.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + box.h math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h \ + crosshair.h vtonpoint.h hid.h ../src_3rd/liblihata/dom.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/parser.h error.h \ + route.h buffer.h ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h \ + obj_rat_list.h obj_rat.h layer_grp.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h ../src_plugins/io_tedax/parse.h unit.h attrib.h error.h \ + board.h vtroutestyle.h rats_patch.h board.h pcb-printf.h compat_misc.h \ + safe_fs.h conf.h pcb-printf.h ../src_3rd/liblihata/lihata.h list_conf.h \ + obj_line.h obj_arc.h obj_pstk.h obj_pstk_inlines.h data.h thermal.h \ + ../src_plugins/lib_compat_help/subc_help.h obj_subc.h layer.h \ + ../src_plugins/lib_compat_help/pstk_help.h +../src_plugins/io_tedax/io_tedax.o: ../src_plugins/io_tedax/io_tedax.c \ + ../config.h ../src_plugins/io_tedax/footprint.h data.h globalconst.h \ + global_typedefs.h pcb_bool.h unit.h layer.h attrib.h color.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h ../src_3rd/genht/ht.h box.h math_helper.h \ + misc_util.h ../src_3rd/genvector/gds_char.h crosshair.h vtonpoint.h \ + hid.h ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h error.h route.h \ + buffer.h ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h \ + obj_rat_list.h obj_rat.h layer_grp.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h board.h vtroutestyle.h rats_patch.h board.h conf_core.h \ + conf.h pcb-printf.h ../src_3rd/liblihata/lihata.h list_conf.h buffer.h \ + plugins.h ../src_3rd/puplug/puplug.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/os_dep.h ../src_3rd/puplug/config.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/error.h hid.h actions.h \ + compat_misc.h plug_io.h ../src_plugins/io_tedax/stackup.h \ + ../src_plugins/io_tedax/tlayer.h layer.h \ + ../src_plugins/io_tedax/tboard.h ../src_plugins/io_tedax/tdrc.h \ + ../src_plugins/io_tedax/tnetlist.h dolists.h +../src_plugins/io_tedax/parse.o: ../src_plugins/io_tedax/parse.c \ + ../config.h ../src_plugins/io_tedax/parse.h error.h compat_misc.h +../src_plugins/io_tedax/stackup.o: ../src_plugins/io_tedax/stackup.c \ + ../config.h ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h \ + ../src_3rd/genht/htip.h ../src_3rd/genht/hash.h \ + ../src_plugins/io_tedax/stackup.h board.h global_typedefs.h pcb_bool.h \ + unit.h vtroutestyle.h attrib.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h box.h math_helper.h misc_util.h \ + ../src_3rd/genvector/gds_char.h layer_grp.h rats_patch.h board.h \ + ../src_3rd/genvector/vtp0.h ../src_plugins/io_tedax/parse.h \ + compat_misc.h safe_fs.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/dom.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/parser.h list_conf.h \ + error.h plug_io.h +../src_plugins/io_tedax/tboard.o: ../src_plugins/io_tedax/tboard.c \ + ../config.h ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h \ + ../src_3rd/genht/htsi.h ../src_3rd/genht/hash.h \ + ../src_plugins/lib_netmap/placement.h board.h global_typedefs.h \ + pcb_bool.h unit.h vtroutestyle.h attrib.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h board.h data.h crosshair.h vtonpoint.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h error.h route.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h ht_subc.h ../src_plugins/io_tedax/tboard.h \ + ../src_plugins/io_tedax/parse.h error.h safe_fs.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h list_conf.h \ + ../src_plugins/io_tedax/stackup.h ../src_plugins/io_tedax/footprint.h \ + ../src_plugins/io_tedax/tdrc.h ../src_plugins/io_tedax/tlayer.h layer.h \ + obj_pstk.h compat_misc.h plug_io.h ../src_plugins/io_tedax/tnetlist.h +../src_plugins/io_tedax/tdrc.o: ../src_plugins/io_tedax/tdrc.c \ + ../config.h board.h ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h \ + global_typedefs.h pcb_bool.h unit.h vtroutestyle.h attrib.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h board.h ../src_plugins/io_tedax/parse.h safe_fs.h conf.h \ + pcb-printf.h ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/dom.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/parser.h \ + ../src_3rd/genvector/vtp0.h list_conf.h error.h \ + ../src_plugins/io_tedax/tdrc.h +../src_plugins/io_tedax/tlayer.o: ../src_plugins/io_tedax/tlayer.c \ + ../config.h ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h \ + ../src_3rd/genht/hash.h data.h globalconst.h global_typedefs.h \ + pcb_bool.h unit.h layer.h attrib.h color.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h \ + ../src_3rd/genvector/gds_char.h crosshair.h vtonpoint.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h error.h route.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h layer_grp.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h ../src_plugins/io_tedax/tlayer.h board.h vtroutestyle.h \ + rats_patch.h board.h layer.h safe_fs.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h list_conf.h error.h \ + ../src_plugins/io_tedax/parse.h compat_misc.h obj_line.h obj_arc.h \ + obj_poly.h vtc0.h plug_io.h +../src_plugins/io_tedax/tnetlist.o: ../src_plugins/io_tedax/tnetlist.c \ + ../config.h ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h \ + ../src_3rd/genht/hash.h board.h global_typedefs.h pcb_bool.h unit.h \ + vtroutestyle.h attrib.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h board.h data.h crosshair.h vtonpoint.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h error.h route.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h error.h pcb-printf.h compat_misc.h actions.h safe_fs.h \ + conf.h pcb-printf.h ../src_3rd/liblihata/lihata.h list_conf.h obj_subc.h \ + netlist2.h ../src_plugins/io_tedax/tnetlist.h \ + ../src_plugins/io_tedax/parse.h +../src_plugins/jostle/jostle.o: ../src_plugins/jostle/jostle.c \ + ../config.h board.h ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h \ + global_typedefs.h pcb_bool.h unit.h vtroutestyle.h attrib.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h board.h data.h crosshair.h vtonpoint.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h error.h route.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h hid.h rtree.h undo.h ../src_3rd/libuundo/uundo.h \ + undo_old.h polygon.h remove.h error.h pcb-printf.h plugins.h \ + ../src_3rd/puplug/puplug.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/os_dep.h ../src_3rd/puplug/config.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/error.h actions.h layer.h \ + conf_core.h conf.h pcb-printf.h ../src_3rd/liblihata/lihata.h \ + list_conf.h misc_util.h obj_line.h event.h dolists.h +../src_plugins/lib_compat_help/lib_compat_help.o: \ + ../src_plugins/lib_compat_help/lib_compat_help.c plugins.h \ + ../src_3rd/puplug/puplug.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/os_dep.h ../src_3rd/puplug/config.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/error.h \ + ../src_plugins/lib_compat_help/layer_compat.c ../config.h \ + ../src_plugins/lib_compat_help/layer_compat.h layer.h globalconst.h \ + global_typedefs.h pcb_bool.h unit.h attrib.h color.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h ../src_3rd/genht/ht.h box.h math_helper.h \ + misc_util.h ../src_3rd/genvector/gds_char.h \ + ../src_plugins/lib_compat_help/pstk_compat.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h layer.h obj_pstk_shape.h polygon.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h vtpadstack_t.h \ + board.h ../src_3rd/genht/htsp.h vtroutestyle.h layer_grp.h rats_patch.h \ + board.h data.h crosshair.h vtonpoint.h hid.h ../src_3rd/liblihata/dom.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/parser.h error.h \ + route.h buffer.h ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h \ + obj_rat_list.h obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h ht_subc.h ../src_3rd/genht/ht.h \ + ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h vtpadstack.h \ + ../src_plugins/lib_compat_help/pstk_compat.c obj_pstk_inlines.h data.h \ + thermal.h compat_misc.h plug_io.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h list_conf.h \ + ../src_plugins/lib_compat_help/pstk_help.c \ + ../src_plugins/lib_compat_help/pstk_help.h search.h remove.h find.h \ + ../src_plugins/lib_compat_help/subc_help.c \ + ../src_plugins/lib_compat_help/subc_help.h obj_subc.h \ + ../src_plugins/lib_compat_help/elem_rot.c \ + ../src_plugins/lib_compat_help/elem_rot.h conf_core.h data_it.h macro.h +../src_plugins/lib_compat_help/media.o: \ + ../src_plugins/lib_compat_help/media.c ../config.h unit.h \ + ../src_plugins/lib_compat_help/media.h +../src_plugins/lib_gensexpr/lib_gensexpr.o: \ + ../src_plugins/lib_gensexpr/lib_gensexpr.c ../config.h plugins.h \ + ../src_3rd/puplug/puplug.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/os_dep.h ../src_3rd/puplug/config.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/error.h +../src_plugins/lib_gtk_common/bu_box.o: \ + ../src_plugins/lib_gtk_common/bu_box.c ../config.h \ + ../src_plugins/lib_gtk_common/bu_box.h \ + ../src_plugins/lib_gtk_common/compat.h +../src_plugins/lib_gtk_common/bu_command.o: \ + ../src_plugins/lib_gtk_common/bu_command.c ../config.h \ + ../src_plugins/lib_gtk_common/bu_command.h pcb_bool.h \ + ../src_plugins/lib_gtk_common/glue.h hid.h ../src_3rd/liblihata/dom.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/parser.h \ + ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h error.h global_typedefs.h \ + pcb_bool.h unit.h attrib.h layer.h globalconst.h color.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h \ + ../src_3rd/genvector/gds_char.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/genvector/vtp0.h list_conf.h \ + conf.h ../src_plugins/lib_gtk_common/compat.h conf_core.h board.h \ + vtroutestyle.h layer_grp.h rats_patch.h board.h crosshair.h vtonpoint.h \ + hid.h route.h actions.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h ../src_plugins/lib_gtk_common/bu_status_line.h \ + ../src_plugins/lib_gtk_common/hid_gtk_conf.h \ + ../src_plugins/lib_hid_common/cli_history.h +../src_plugins/lib_gtk_common/bu_cursor_pos.o: \ + ../src_plugins/lib_gtk_common/bu_cursor_pos.c ../config.h \ + ../src_plugins/lib_gtk_common/bu_cursor_pos.h conf_core.h conf.h \ + global_typedefs.h pcb_bool.h unit.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h globalconst.h color.h actions.h hid.h \ + error.h attrib.h layer.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h obj_line_list.h \ + obj_line.h obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h \ + obj_text.h font.h ../src_3rd/genht/htip.h box.h math_helper.h \ + misc_util.h ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h \ + crosshair.h vtonpoint.h route.h misc_util.h math_helper.h +../src_plugins/lib_gtk_common/bu_dwg_tooltip.o: \ + ../src_plugins/lib_gtk_common/bu_dwg_tooltip.c ../config.h \ + ../src_plugins/lib_gtk_common/bu_dwg_tooltip.h layer.h globalconst.h \ + global_typedefs.h pcb_bool.h unit.h attrib.h color.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h ../src_3rd/genht/ht.h box.h math_helper.h \ + misc_util.h ../src_3rd/genvector/gds_char.h search.h layer.h find.h \ + ../src_3rd/genvector/vtp0.h board.h ../src_3rd/genht/htsp.h \ + vtroutestyle.h layer_grp.h rats_patch.h board.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h obj_subc_parent.h \ + data.h crosshair.h vtonpoint.h hid.h ../src_3rd/liblihata/dom.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/parser.h error.h \ + route.h buffer.h ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h \ + obj_rat_list.h obj_rat.h idpath.h obj_subc_list.h obj_subc.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h netlist2.h +../src_plugins/lib_gtk_common/bu_icons.o: \ + ../src_plugins/lib_gtk_common/bu_icons.c ../config.h \ + ../src_plugins/lib_gtk_common/bu_icons.h \ + ../src_plugins/lib_gtk_common/bu_icons.data +../src_plugins/lib_gtk_common/bu_info_bar.o: \ + ../src_plugins/lib_gtk_common/bu_info_bar.c ../config.h \ + ../src_plugins/lib_gtk_common/bu_info_bar.h board.h \ + ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h global_typedefs.h \ + pcb_bool.h unit.h vtroutestyle.h attrib.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h board.h plug_io.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/dom.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/parser.h \ + ../src_3rd/genvector/vtp0.h list_conf.h +../src_plugins/lib_gtk_common/bu_menu.o: \ + ../src_plugins/lib_gtk_common/bu_menu.c ../config.h \ + ../src_3rd/liblihata/tree.h ../src_3rd/liblihata/dom.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/parser.h \ + ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h board.h global_typedefs.h \ + pcb_bool.h unit.h vtroutestyle.h attrib.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h board.h pcb-printf.h misc_util.h error.h conf.h \ + pcb-printf.h ../src_3rd/liblihata/lihata.h ../src_3rd/genvector/vtp0.h \ + list_conf.h conf.h hid_flags.h hid_cfg.h hid.h error.h hid_cfg_action.h \ + hid_cfg.h event.h ../src_plugins/lib_gtk_common/bu_menu.h \ + ../src_plugins/lib_gtk_common/wt_route_style.h route_style.h \ + ../src_plugins/lib_gtk_common/glue.h hid.h \ + ../src_plugins/lib_gtk_common/compat.h hid_cfg_input.h \ + ../src_3rd/genht/htpp.h conf_hid.h \ + ../src_plugins/lib_gtk_common/in_keyboard.h \ + ../src_plugins/lib_gtk_common/ui_zoompan.h ../src_3rd/libfungw/fungw.h \ + unit.h pcb_bool.h ../src_plugins/lib_gtk_common/in_mouse.h \ + ../src_plugins/lib_gtk_common/wt_accel_label.h +../src_plugins/lib_gtk_common/bu_mode_btn.o: \ + ../src_plugins/lib_gtk_common/bu_mode_btn.c ../config.h \ + ../src_plugins/lib_gtk_common/bu_mode_btn.h \ + ../src_plugins/lib_gtk_common/glue.h hid.h ../src_3rd/liblihata/dom.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/parser.h \ + ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h error.h global_typedefs.h \ + pcb_bool.h unit.h attrib.h layer.h globalconst.h color.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h \ + ../src_3rd/genvector/gds_char.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/genvector/vtp0.h list_conf.h \ + conf.h ../src_plugins/lib_gtk_common/compat.h \ + ../src_plugins/lib_gtk_common/bu_mode_btn.data crosshair.h vtonpoint.h \ + hid.h route.h conf_core.h tool.h \ + ../src_plugins/lib_gtk_common/hid_gtk_conf.h +../src_plugins/lib_gtk_common/bu_spin_button.o: \ + ../src_plugins/lib_gtk_common/bu_spin_button.c ../config.h \ + ../src_plugins/lib_gtk_common/bu_spin_button.h \ + ../src_plugins/lib_gtk_common/compat.h +../src_plugins/lib_gtk_common/bu_status_line.o: \ + ../src_plugins/lib_gtk_common/bu_status_line.c ../config.h \ + ../src_plugins/lib_gtk_common/bu_status_line.h \ + ../src_plugins/lib_gtk_common/in_keyboard.h hid_cfg_input.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/htip.h ../src_3rd/genht/htpp.h \ + hid_cfg.h global_typedefs.h pcb_bool.h unit.h hid.h error.h attrib.h \ + layer.h globalconst.h color.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + box.h math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h \ + ../src_plugins/lib_gtk_common/ui_zoompan.h ../src_3rd/libfungw/fungw.h \ + unit.h pcb_bool.h ../src_plugins/lib_gtk_common/in_mouse.h \ + ../src_plugins/lib_gtk_common/glue.h hid.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/genvector/vtp0.h list_conf.h \ + conf.h ../src_plugins/lib_gtk_common/compat.h conf_core.h compat_misc.h \ + board.h vtroutestyle.h layer_grp.h rats_patch.h board.h +../src_plugins/lib_gtk_common/dlg_attribute.o: \ + ../src_plugins/lib_gtk_common/dlg_attribute.c ../config.h conf_core.h \ + conf.h global_typedefs.h pcb_bool.h unit.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h globalconst.h color.h \ + ../src_plugins/lib_gtk_common/dlg_attribute.h hid.h error.h attrib.h \ + layer.h obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h obj_line_list.h obj_line.h obj_poly_list.h \ + obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h \ + ../src_plugins/lib_gtk_common/glue.h conf.h \ + ../src_plugins/lib_gtk_common/compat.h pcb-printf.h hid_attrib.h hid.h \ + hid_dad_tree.h hid_attrib.h hid_dad.h compat_misc.h \ + ../src_3rd/genht/hash.h hid_init.h ../src_3rd/puplug/puplug.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/os_dep.h \ + ../src_3rd/puplug/config.h ../src_3rd/puplug/libs.h misc_util.h \ + compat_misc.h event.h ../src_plugins/lib_gtk_common/bu_box.h \ + ../src_plugins/lib_gtk_common/bu_spin_button.h \ + ../src_plugins/lib_gtk_common/wt_coord_entry.h unit.h \ + ../src_plugins/lib_gtk_common/win_place.h \ + ../src_plugins/lib_gtk_common/dlg_attr_tree.c \ + ../src_plugins/lib_gtk_common/dlg_attr_misc.c \ + ../src_plugins/lib_gtk_common/wt_preview.h \ + ../src_plugins/lib_gtk_common/ui_zoompan.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h pcb_bool.h \ + ../src_plugins/lib_gtk_common/in_mouse.h hid_cfg_input.h hid_cfg.h \ + ../src_plugins/lib_hid_common/dad_markup.h \ + ../src_plugins/lib_gtk_common/dlg_attr_txt.c \ + ../src_plugins/lib_gtk_common/dlg_attr_box.c +../src_plugins/lib_gtk_common/dlg_attributes.o: \ + ../src_plugins/lib_gtk_common/dlg_attributes.c ../config.h conf_core.h \ + conf.h global_typedefs.h pcb_bool.h unit.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h globalconst.h color.h \ + ../src_plugins/lib_gtk_common/dlg_attributes.h hid.h error.h attrib.h \ + layer.h obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h obj_line_list.h obj_line.h obj_poly_list.h \ + obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h pcb-printf.h \ + hid_attrib.h hid.h hid_init.h ../src_3rd/puplug/puplug.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/os_dep.h \ + ../src_3rd/puplug/config.h ../src_3rd/puplug/libs.h misc_util.h \ + compat_misc.h ../src_plugins/lib_gtk_common/compat.h \ + ../src_plugins/lib_gtk_common/wt_coord_entry.h unit.h +../src_plugins/lib_gtk_common/dlg_fileselect.o: \ + ../src_plugins/lib_gtk_common/dlg_fileselect.c ../config.h \ + ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h \ + hid.h ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h error.h global_typedefs.h pcb_bool.h \ + unit.h attrib.h layer.h globalconst.h color.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h \ + ../src_3rd/genvector/gds_char.h hid_dad.h compat_misc.h hid_attrib.h \ + hid.h pcb-printf.h compat_misc.h ../src_plugins/lib_gtk_common/compat.h \ + event.h safe_fs.h conf.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_plugins/lib_gtk_common/dlg_attribute.h \ + ../src_plugins/lib_gtk_common/glue.h conf.h +../src_plugins/lib_gtk_common/dlg_library.o: \ + ../src_plugins/lib_gtk_common/dlg_library.c ../config.h \ + ../src_plugins/lib_gtk_common/dlg_library.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h error.h global_typedefs.h pcb_bool.h unit.h \ + attrib.h layer.h globalconst.h color.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h \ + ../src_3rd/genvector/gds_char.h ../src_plugins/lib_gtk_common/glue.h \ + conf.h pcb-printf.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/genvector/vtp0.h list_conf.h conf.h \ + ../src_plugins/lib_gtk_common/compat.h conf_core.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h data.h crosshair.h \ + vtonpoint.h hid.h route.h buffer.h obj_rat_list.h obj_rat.h layer_grp.h \ + idpath.h obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h \ + rtree.h ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h plug_footprint.h \ + vtlibrary.h data.h compat_misc.h actions.h draw.h \ + ../src_plugins/lib_gtk_common/bu_box.h \ + ../src_plugins/lib_gtk_common/wt_preview.h \ + ../src_plugins/lib_gtk_common/ui_zoompan.h unit.h pcb_bool.h \ + ../src_plugins/lib_gtk_common/in_mouse.h hid_cfg_input.h hid_cfg.h \ + ../src_plugins/lib_gtk_common/win_place.h tool.h event.h \ + ../src_plugins/lib_gtk_common/hid_gtk_conf.h \ + ../src_plugins/lib_gtk_common/dlg_library_param.h +../src_plugins/lib_gtk_common/dlg_library_param.o: \ + ../src_plugins/lib_gtk_common/dlg_library_param.c ../config.h \ + hid_attrib.h hid.h ../src_3rd/liblihata/dom.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/parser.h \ + ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h error.h global_typedefs.h \ + pcb_bool.h unit.h attrib.h layer.h globalconst.h color.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h \ + ../src_3rd/genvector/gds_char.h compat_misc.h safe_fs.h conf.h \ + pcb-printf.h ../src_3rd/liblihata/lihata.h ../src_3rd/genvector/vtp0.h \ + list_conf.h ../src_plugins/lib_gtk_common/dlg_library_param.h \ + plug_footprint.h vtlibrary.h data.h crosshair.h vtonpoint.h route.h \ + buffer.h ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h \ + obj_rat_list.h obj_rat.h layer_grp.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h \ + ../src_plugins/lib_gtk_common/dlg_library.h hid.h \ + ../src_plugins/lib_gtk_common/glue.h conf.h \ + ../src_plugins/lib_gtk_common/compat.h \ + ../src_plugins/lib_gtk_common/dlg_attribute.h +../src_plugins/lib_gtk_common/dlg_route_style.o: \ + ../src_plugins/lib_gtk_common/dlg_route_style.c ../config.h \ + compat_misc.h polygon.h flag.h globalconst.h rtree.h global_typedefs.h \ + pcb_bool.h unit.h ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h \ + math_helper.h polyarea.h ../src_plugins/lib_gtk_common/bu_box.h \ + ../src_plugins/lib_gtk_common/compat.h board.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h vtroutestyle.h attrib.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h color.h obj_common.h \ + data_parent.h obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h misc_util.h \ + ../src_3rd/genvector/gds_char.h layer_grp.h rats_patch.h board.h \ + conf_core.h conf.h pcb-printf.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genvector/vtp0.h list_conf.h \ + error.h event.h ../src_plugins/lib_gtk_common/dlg_route_style.h \ + ../src_plugins/lib_gtk_common/wt_route_style.h route_style.h \ + ../src_plugins/lib_gtk_common/glue.h hid.h error.h conf.h \ + ../src_plugins/lib_gtk_common/wt_coord_entry.h unit.h +../src_plugins/lib_gtk_common/dlg_search.o: \ + ../src_plugins/lib_gtk_common/dlg_search.c ../config.h \ + ../src_plugins/lib_gtk_common/dlg_search.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h compat_misc.h actions.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h error.h global_typedefs.h pcb_bool.h unit.h \ + attrib.h layer.h globalconst.h color.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h misc_util.h pcb-printf.h conf_core.h conf.h \ + pcb-printf.h ../src_3rd/liblihata/lihata.h ../src_3rd/genvector/vtp0.h \ + list_conf.h ../src_plugins/lib_gtk_common/win_place.h \ + ../src_plugins/lib_gtk_common/wt_coord_entry.h unit.h \ + ../src_plugins/lib_gtk_common/bu_box.h \ + ../src_plugins/lib_gtk_common/compat.h \ + ../src_plugins/lib_gtk_common/dlg_search_tab.h +../src_plugins/lib_gtk_common/dlg_topwin.o: \ + ../src_plugins/lib_gtk_common/dlg_topwin.c ../config.h \ + ../src_plugins/lib_gtk_common/dlg_topwin.h hid_cfg.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h global_typedefs.h pcb_bool.h unit.h hid.h error.h \ + attrib.h layer.h globalconst.h color.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h \ + ../src_3rd/genvector/gds_char.h \ + ../src_plugins/lib_gtk_common/util_ext_chg.h pcb_bool.h \ + ../src_plugins/lib_gtk_common/bu_info_bar.h \ + ../src_plugins/lib_gtk_common/bu_menu.h \ + ../src_plugins/lib_gtk_common/wt_route_style.h route_style.h \ + vtroutestyle.h ../src_plugins/lib_gtk_common/glue.h hid.h conf.h \ + pcb-printf.h ../src_3rd/liblihata/lihata.h ../src_3rd/genvector/vtp0.h \ + list_conf.h conf.h ../src_plugins/lib_gtk_common/compat.h \ + hid_cfg_input.h ../src_3rd/genht/htpp.h hid_cfg.h conf_hid.h \ + ../src_plugins/lib_gtk_common/bu_mode_btn.h \ + ../src_plugins/lib_gtk_common/bu_cursor_pos.h \ + ../src_plugins/lib_gtk_common/bu_command.h \ + ../src_plugins/lib_gtk_common/wt_layersel.h layer.h layer_grp.h \ + conf_core.h board.h layer_grp.h rats_patch.h board.h crosshair.h \ + vtonpoint.h route.h pcb-printf.h actions.h ../src_3rd/libfungw/fungw.h \ + compat_misc.h ../src_plugins/lib_gtk_common/bu_box.h \ + ../src_plugins/lib_gtk_common/bu_status_line.h \ + ../src_plugins/lib_gtk_common/bu_icons.h \ + ../src_plugins/lib_gtk_common/dlg_route_style.h \ + ../src_plugins/lib_gtk_common/util_listener.h \ + ../src_plugins/lib_gtk_common/in_mouse.h \ + ../src_plugins/lib_gtk_common/in_keyboard.h \ + ../src_plugins/lib_gtk_common/ui_zoompan.h unit.h tool.h \ + ../src_plugins/lib_gtk_common/lib_gtk_config.h event.h \ + ../src_plugins/lib_gtk_common/hid_gtk_conf.h \ + ../src_plugins/lib_gtk_common/win_place.h +../src_plugins/lib_gtk_common/in_keyboard.o: \ + ../src_plugins/lib_gtk_common/in_keyboard.c ../config.h \ + ../src_plugins/lib_gtk_common/in_keyboard.h hid_cfg_input.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/htip.h ../src_3rd/genht/htpp.h \ + hid_cfg.h global_typedefs.h pcb_bool.h unit.h hid.h error.h attrib.h \ + layer.h globalconst.h color.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + box.h math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h \ + ../src_plugins/lib_gtk_common/ui_zoompan.h ../src_3rd/libfungw/fungw.h \ + unit.h pcb_bool.h ../src_plugins/lib_gtk_common/in_mouse.h \ + ../src_plugins/lib_gtk_common/glue.h hid.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/genvector/vtp0.h list_conf.h \ + conf.h ../src_plugins/lib_gtk_common/compat.h event.h compat_misc.h +../src_plugins/lib_gtk_common/in_mouse.o: \ + ../src_plugins/lib_gtk_common/in_mouse.c ../config.h \ + ../src_plugins/lib_gtk_common/in_mouse.h hid_cfg_input.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/htip.h ../src_3rd/genht/htpp.h \ + hid_cfg.h global_typedefs.h pcb_bool.h unit.h hid.h error.h attrib.h \ + layer.h globalconst.h color.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + box.h math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h \ + ../src_plugins/lib_gtk_common/glue.h hid.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/genvector/vtp0.h list_conf.h \ + conf.h ../src_plugins/lib_gtk_common/compat.h board.h vtroutestyle.h \ + layer_grp.h rats_patch.h board.h crosshair.h vtonpoint.h route.h \ + conf_core.h undo.h ../src_3rd/libuundo/uundo.h undo_old.h tool.h \ + ../src_plugins/lib_gtk_common/in_keyboard.h \ + ../src_plugins/lib_gtk_common/ui_zoompan.h ../src_3rd/libfungw/fungw.h \ + unit.h pcb_bool.h ../src_plugins/lib_gtk_common/bu_status_line.h \ + ../src_plugins/lib_gtk_common/bu_icons.h +../src_plugins/lib_gtk_common/lib_gtk_common.o: \ + ../src_plugins/lib_gtk_common/lib_gtk_common.c ../config.h plugins.h \ + ../src_3rd/puplug/puplug.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/os_dep.h ../src_3rd/puplug/config.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/error.h \ + ../src_plugins/lib_gtk_common/lib_gtk_config.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h error.h global_typedefs.h pcb_bool.h unit.h \ + attrib.h layer.h globalconst.h color.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h \ + ../src_3rd/genvector/gds_char.h event.h conf_hid.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/genvector/vtp0.h list_conf.h +../src_plugins/lib_gtk_common/lib_gtk_config.o: \ + ../src_plugins/lib_gtk_common/lib_gtk_config.c ../config.h \ + ../src_plugins/lib_gtk_common/lib_gtk_config.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h error.h global_typedefs.h pcb_bool.h unit.h \ + attrib.h layer.h globalconst.h color.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h \ + ../src_3rd/genvector/gds_char.h event.h conf_hid.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_plugins/lib_gtk_common/hid_gtk_conf.h conf.h plugins.h \ + ../src_3rd/puplug/puplug.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/os_dep.h ../src_3rd/puplug/config.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/error.h \ + ../src_plugins/dialogs/place.h \ + ../src_plugins/lib_gtk_common/hid_gtk_conf_fields.h +../src_plugins/lib_gtk_common/ui_crosshair.o: \ + ../src_plugins/lib_gtk_common/ui_crosshair.c ../config.h \ + ../src_plugins/lib_gtk_common/ui_crosshair.h \ + ../src_plugins/lib_gtk_common/ui_zoompan.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h ../src_3rd/genht/htpp.h \ + unit.h pcb_bool.h ../src_plugins/lib_gtk_common/in_mouse.h \ + hid_cfg_input.h ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htip.h hid_cfg.h \ + global_typedefs.h pcb_bool.h unit.h hid.h error.h attrib.h layer.h \ + globalconst.h color.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + box.h math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h \ + ../src_plugins/lib_gtk_common/glue.h hid.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/genvector/vtp0.h list_conf.h \ + conf.h ../src_plugins/lib_gtk_common/compat.h \ + ../src_plugins/lib_gtk_common/bu_cursor_pos.h \ + ../src_plugins/lib_gtk_common/hid_gtk_conf.h conf_core.h +../src_plugins/lib_gtk_common/ui_zoompan.o: \ + ../src_plugins/lib_gtk_common/ui_zoompan.c ../config.h \ + ../src_plugins/lib_gtk_common/ui_zoompan.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h ../src_3rd/genht/htpp.h \ + unit.h pcb_bool.h ../src_plugins/lib_gtk_common/in_mouse.h \ + hid_cfg_input.h ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htip.h hid_cfg.h \ + global_typedefs.h pcb_bool.h unit.h hid.h error.h attrib.h layer.h \ + globalconst.h color.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + box.h math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h \ + ../src_plugins/lib_gtk_common/glue.h hid.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/genvector/vtp0.h list_conf.h \ + conf.h ../src_plugins/lib_gtk_common/compat.h actions.h error.h \ + conf_core.h board.h vtroutestyle.h layer_grp.h rats_patch.h board.h \ + compat_misc.h draw.h data.h crosshair.h vtonpoint.h route.h buffer.h \ + obj_rat_list.h obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h layer_vis.h \ + ../src_plugins/lib_gtk_common/bu_status_line.h \ + ../src_plugins/lib_hid_common/util.h +../src_plugins/lib_gtk_common/util_ext_chg.o: \ + ../src_plugins/lib_gtk_common/util_ext_chg.c ../config.h \ + ../src_plugins/lib_gtk_common/util_ext_chg.h pcb_bool.h board.h \ + ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h global_typedefs.h \ + pcb_bool.h unit.h vtroutestyle.h attrib.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h board.h +../src_plugins/lib_gtk_common/util_listener.o: \ + ../src_plugins/lib_gtk_common/util_listener.c ../config.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h error.h global_typedefs.h pcb_bool.h unit.h \ + attrib.h layer.h globalconst.h color.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h \ + ../src_3rd/genvector/gds_char.h actions.h hid.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h compat_misc.h +../src_plugins/lib_gtk_common/util_timer.o: \ + ../src_plugins/lib_gtk_common/util_timer.c ../config.h \ + ../src_plugins/lib_gtk_common/util_timer.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h error.h global_typedefs.h pcb_bool.h unit.h \ + attrib.h layer.h globalconst.h color.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h \ + ../src_3rd/genvector/gds_char.h ../src_plugins/lib_gtk_common/glue.h \ + conf.h pcb-printf.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/genvector/vtp0.h list_conf.h conf.h \ + ../src_plugins/lib_gtk_common/compat.h conf_core.h +../src_plugins/lib_gtk_common/util_watch.o: \ + ../src_plugins/lib_gtk_common/util_watch.c ../config.h \ + ../src_plugins/lib_gtk_common/util_watch.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h error.h global_typedefs.h pcb_bool.h unit.h \ + attrib.h layer.h globalconst.h color.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h \ + ../src_3rd/genvector/gds_char.h ../src_plugins/lib_gtk_common/glue.h \ + conf.h pcb-printf.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/genvector/vtp0.h list_conf.h conf.h \ + ../src_plugins/lib_gtk_common/compat.h \ + ../src_plugins/lib_gtk_common/in_mouse.h hid_cfg_input.h \ + ../src_3rd/genht/htpp.h hid_cfg.h hid.h conf_core.h +../src_plugins/lib_gtk_common/win_place.o: \ + ../src_plugins/lib_gtk_common/win_place.c ../config.h \ + ../src_plugins/lib_gtk_common/win_place.h conf_core.h conf.h \ + global_typedefs.h pcb_bool.h unit.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h globalconst.h color.h event.h +../src_plugins/lib_gtk_common/wt_accel_label.o: \ + ../src_plugins/lib_gtk_common/wt_accel_label.c ../config.h \ + ../src_plugins/lib_gtk_common/wt_accel_label.h \ + ../src_plugins/lib_gtk_common/compat.h +../src_plugins/lib_gtk_common/wt_coord_entry.o: \ + ../src_plugins/lib_gtk_common/wt_coord_entry.c ../config.h \ + ../src_plugins/lib_gtk_common/wt_coord_entry.h unit.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h unit.h +../src_plugins/lib_gtk_common/wt_layersel.o: \ + ../src_plugins/lib_gtk_common/wt_layersel.c ../config.h layer.h \ + globalconst.h global_typedefs.h pcb_bool.h unit.h attrib.h color.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h ../src_3rd/genht/ht.h box.h math_helper.h \ + misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h layer.h \ + layer_ui.h ../src_3rd/genvector/vtp0.h layer_vis.h board.h \ + ../src_3rd/genht/htsp.h vtroutestyle.h layer_grp.h rats_patch.h board.h \ + data.h crosshair.h vtonpoint.h hid.h ../src_3rd/liblihata/dom.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/parser.h error.h \ + route.h buffer.h ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h \ + obj_rat_list.h obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h event.h \ + conf_core.h conf.h pcb-printf.h ../src_3rd/liblihata/lihata.h \ + list_conf.h actions.h math_helper.h \ + ../src_plugins/lib_gtk_common/wt_layersel.h \ + ../src_plugins/lib_gtk_common/glue.h hid.h conf.h \ + ../src_plugins/lib_gtk_common/compat.h +../src_plugins/lib_gtk_common/wt_preview.o: \ + ../src_plugins/lib_gtk_common/wt_preview.c ../config.h conf_core.h \ + conf.h global_typedefs.h pcb_bool.h unit.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h globalconst.h color.h \ + ../src_plugins/lib_gtk_common/in_mouse.h hid_cfg_input.h \ + ../src_3rd/genht/htip.h ../src_3rd/genht/htpp.h hid_cfg.h hid.h error.h \ + attrib.h layer.h obj_common.h flag.h data_parent.h obj_arc_list.h \ + obj_arc.h ../src_3rd/genlist/gendlist.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + box.h math_helper.h misc_util.h ../src_plugins/lib_gtk_common/glue.h \ + hid.h conf.h ../src_plugins/lib_gtk_common/compat.h \ + ../src_plugins/lib_gtk_common/wt_preview.h \ + ../src_plugins/lib_gtk_common/ui_zoompan.h ../src_3rd/libfungw/fungw.h \ + unit.h pcb_bool.h board.h vtroutestyle.h layer_grp.h rats_patch.h \ + board.h data.h crosshair.h vtonpoint.h route.h buffer.h obj_rat_list.h \ + obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h draw.h \ + compat_misc.h +../src_plugins/lib_gtk_common/wt_route_style.o: \ + ../src_plugins/lib_gtk_common/wt_route_style.c ../config.h conf_core.h \ + conf.h global_typedefs.h pcb_bool.h unit.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h globalconst.h color.h \ + ../src_plugins/lib_gtk_common/dlg_route_style.h \ + ../src_plugins/lib_gtk_common/wt_route_style.h route_style.h \ + vtroutestyle.h attrib.h ../src_plugins/lib_gtk_common/glue.h hid.h \ + error.h layer.h obj_common.h flag.h data_parent.h obj_arc_list.h \ + obj_arc.h ../src_3rd/genlist/gendlist.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h conf.h \ + ../src_plugins/lib_gtk_common/compat.h pcb-printf.h board.h layer_grp.h \ + rats_patch.h board.h ../src_plugins/lib_gtk_common/bu_status_line.h +../src_plugins/lib_gtk_hid/actions.o: \ + ../src_plugins/lib_gtk_hid/actions.c ../config.h \ + ../src_plugins/lib_gtk_hid/gui.h hid.h ../src_3rd/liblihata/dom.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/parser.h \ + ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h error.h global_typedefs.h \ + pcb_bool.h unit.h attrib.h layer.h globalconst.h color.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h \ + ../src_3rd/genvector/gds_char.h \ + ../src_plugins/lib_gtk_common/ui_zoompan.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h unit.h pcb_bool.h \ + ../src_plugins/lib_gtk_common/in_mouse.h hid_cfg_input.h hid_cfg.h hid.h \ + ../src_plugins/lib_gtk_common/glue.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/genvector/vtp0.h list_conf.h \ + conf.h ../src_plugins/lib_gtk_common/compat.h \ + ../src_plugins/lib_gtk_common/dlg_topwin.h hid_cfg.h \ + ../src_plugins/lib_gtk_common/util_ext_chg.h \ + ../src_plugins/lib_gtk_common/bu_info_bar.h \ + ../src_plugins/lib_gtk_common/bu_menu.h \ + ../src_plugins/lib_gtk_common/wt_route_style.h route_style.h \ + vtroutestyle.h conf_hid.h ../src_plugins/lib_gtk_common/bu_mode_btn.h \ + ../src_plugins/lib_gtk_common/bu_cursor_pos.h \ + ../src_plugins/lib_gtk_common/bu_command.h \ + ../src_plugins/lib_gtk_common/wt_layersel.h layer.h layer_grp.h \ + ../src_plugins/lib_gtk_common/in_mouse.h \ + ../src_plugins/lib_gtk_common/glue.h board.h layer_grp.h rats_patch.h \ + board.h event.h ../src_plugins/lib_gtk_hid/render.h \ + ../src_plugins/lib_gtk_hid/actions.h data.h crosshair.h vtonpoint.h \ + route.h buffer.h obj_rat_list.h obj_rat.h idpath.h obj_subc_list.h \ + obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h search.h change.h \ + hid_attrib.h ../src/actions.h ../src/hid.h compat_misc.h \ + ../src_plugins/lib_gtk_common/wt_layersel.h \ + ../src_plugins/lib_gtk_common/dlg_route_style.h \ + ../src_plugins/lib_gtk_common/dlg_library.h \ + ../src_plugins/lib_gtk_common/dlg_search.h \ + ../src_plugins/lib_gtk_common/lib_gtk_config.h dolists.h +../src_plugins/lib_gtk_hid/common.o: ../src_plugins/lib_gtk_hid/common.c \ + ../config.h crosshair.h vtonpoint.h global_typedefs.h pcb_bool.h unit.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h hid.h ../src_3rd/liblihata/dom.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/parser.h \ + ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h error.h attrib.h layer.h \ + globalconst.h color.h obj_common.h flag.h data_parent.h obj_arc_list.h \ + obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h \ + ../src_3rd/genvector/gds_char.h route.h conf_core.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_plugins/lib_gtk_hid/gui.h hid.h \ + ../src_plugins/lib_gtk_common/ui_zoompan.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h unit.h pcb_bool.h \ + ../src_plugins/lib_gtk_common/in_mouse.h hid_cfg_input.h hid_cfg.h \ + ../src_plugins/lib_gtk_common/glue.h conf.h \ + ../src_plugins/lib_gtk_common/compat.h \ + ../src_plugins/lib_gtk_common/dlg_topwin.h hid_cfg.h \ + ../src_plugins/lib_gtk_common/util_ext_chg.h \ + ../src_plugins/lib_gtk_common/bu_info_bar.h \ + ../src_plugins/lib_gtk_common/bu_menu.h \ + ../src_plugins/lib_gtk_common/wt_route_style.h route_style.h \ + vtroutestyle.h conf_hid.h ../src_plugins/lib_gtk_common/bu_mode_btn.h \ + ../src_plugins/lib_gtk_common/bu_cursor_pos.h \ + ../src_plugins/lib_gtk_common/bu_command.h \ + ../src_plugins/lib_gtk_common/wt_layersel.h layer.h layer_grp.h \ + ../src_plugins/lib_gtk_common/in_mouse.h \ + ../src_plugins/lib_gtk_common/glue.h board.h layer_grp.h rats_patch.h \ + board.h event.h ../src_plugins/lib_gtk_hid/render.h \ + ../src_plugins/lib_gtk_hid/common.h \ + ../src_plugins/lib_gtk_common/wt_layersel.h \ + ../src_plugins/lib_gtk_common/in_keyboard.h \ + ../src_plugins/lib_gtk_common/ui_zoompan.h \ + ../src_plugins/lib_gtk_common/hid_gtk_conf.h +../src_plugins/lib_gtk_hid/glue_common.o: \ + ../src_plugins/lib_gtk_hid/glue_common.c ../config.h \ + ../src_plugins/lib_gtk_hid/glue_common.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h error.h global_typedefs.h pcb_bool.h unit.h \ + attrib.h layer.h globalconst.h color.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h \ + ../src_3rd/genvector/gds_char.h tool.h ../src_3rd/genvector/vtp0.h \ + ../src_plugins/lib_gtk_hid/gui.h \ + ../src_plugins/lib_gtk_common/ui_zoompan.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h unit.h pcb_bool.h \ + ../src_plugins/lib_gtk_common/in_mouse.h hid_cfg_input.h hid_cfg.h hid.h \ + ../src_plugins/lib_gtk_common/glue.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h list_conf.h conf.h \ + ../src_plugins/lib_gtk_common/compat.h \ + ../src_plugins/lib_gtk_common/dlg_topwin.h hid_cfg.h \ + ../src_plugins/lib_gtk_common/util_ext_chg.h \ + ../src_plugins/lib_gtk_common/bu_info_bar.h \ + ../src_plugins/lib_gtk_common/bu_menu.h \ + ../src_plugins/lib_gtk_common/wt_route_style.h route_style.h \ + vtroutestyle.h conf_hid.h ../src_plugins/lib_gtk_common/bu_mode_btn.h \ + ../src_plugins/lib_gtk_common/bu_cursor_pos.h \ + ../src_plugins/lib_gtk_common/bu_command.h \ + ../src_plugins/lib_gtk_common/wt_layersel.h layer.h layer_grp.h \ + ../src_plugins/lib_gtk_common/in_mouse.h \ + ../src_plugins/lib_gtk_common/glue.h board.h layer_grp.h rats_patch.h \ + board.h event.h ../src_plugins/lib_gtk_hid/render.h \ + ../src_plugins/lib_gtk_hid/common.h conf_core.h \ + ../src_plugins/lib_gtk_common/bu_status_line.h \ + ../src_plugins/lib_gtk_common/hid_gtk_conf.h +../src_plugins/lib_gtk_hid/glue_conf.o: \ + ../src_plugins/lib_gtk_hid/glue_conf.c ../config.h \ + ../src_plugins/lib_gtk_hid/glue_conf.h conf.h global_typedefs.h \ + pcb_bool.h unit.h pcb-printf.h ../src_3rd/genvector/gds_char.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_plugins/lib_gtk_hid/glue_event.h \ + conf_core.h globalconst.h color.h ../src_plugins/lib_gtk_hid/gui.h hid.h \ + error.h attrib.h layer.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h obj_line_list.h \ + obj_line.h obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h \ + obj_text.h font.h ../src_3rd/genht/htip.h box.h math_helper.h \ + misc_util.h ../src_plugins/lib_gtk_common/ui_zoompan.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h unit.h pcb_bool.h \ + ../src_plugins/lib_gtk_common/in_mouse.h hid_cfg_input.h hid_cfg.h hid.h \ + ../src_plugins/lib_gtk_common/glue.h \ + ../src_plugins/lib_gtk_common/compat.h \ + ../src_plugins/lib_gtk_common/dlg_topwin.h hid_cfg.h \ + ../src_plugins/lib_gtk_common/util_ext_chg.h \ + ../src_plugins/lib_gtk_common/bu_info_bar.h \ + ../src_plugins/lib_gtk_common/bu_menu.h \ + ../src_plugins/lib_gtk_common/wt_route_style.h route_style.h \ + vtroutestyle.h conf_hid.h ../src_plugins/lib_gtk_common/bu_mode_btn.h \ + ../src_plugins/lib_gtk_common/bu_cursor_pos.h \ + ../src_plugins/lib_gtk_common/bu_command.h \ + ../src_plugins/lib_gtk_common/wt_layersel.h layer.h layer_grp.h \ + ../src_plugins/lib_gtk_common/in_mouse.h \ + ../src_plugins/lib_gtk_common/glue.h board.h layer_grp.h rats_patch.h \ + board.h event.h ../src_plugins/lib_gtk_hid/render.h +../src_plugins/lib_gtk_hid/glue_event.o: \ + ../src_plugins/lib_gtk_hid/glue_event.c \ + ../src_plugins/lib_gtk_hid/common.h event.h ../config.h unit.h \ + global_typedefs.h pcb_bool.h ../src_plugins/lib_gtk_common/dlg_topwin.h \ + hid_cfg.h ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h hid.h error.h attrib.h layer.h globalconst.h \ + color.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h \ + ../src_3rd/genvector/gds_char.h \ + ../src_plugins/lib_gtk_common/util_ext_chg.h pcb_bool.h \ + ../src_plugins/lib_gtk_common/bu_info_bar.h \ + ../src_plugins/lib_gtk_common/bu_menu.h \ + ../src_plugins/lib_gtk_common/wt_route_style.h route_style.h \ + vtroutestyle.h ../src_plugins/lib_gtk_common/glue.h hid.h conf.h \ + pcb-printf.h ../src_3rd/liblihata/lihata.h ../src_3rd/genvector/vtp0.h \ + list_conf.h conf.h ../src_plugins/lib_gtk_common/compat.h \ + hid_cfg_input.h ../src_3rd/genht/htpp.h hid_cfg.h conf_hid.h \ + ../src_plugins/lib_gtk_common/bu_mode_btn.h \ + ../src_plugins/lib_gtk_common/bu_cursor_pos.h \ + ../src_plugins/lib_gtk_common/bu_command.h \ + ../src_plugins/lib_gtk_common/wt_layersel.h layer.h layer_grp.h \ + ../src_plugins/lib_gtk_hid/gui.h \ + ../src_plugins/lib_gtk_common/ui_zoompan.h ../src_3rd/libfungw/fungw.h \ + unit.h ../src_plugins/lib_gtk_common/in_mouse.h \ + ../src_plugins/lib_gtk_common/in_mouse.h \ + ../src_plugins/lib_gtk_common/glue.h board.h layer_grp.h rats_patch.h \ + board.h ../src_plugins/lib_gtk_hid/render.h conf_core.h tool.h \ + ../src_plugins/lib_gtk_common/win_place.h \ + ../src_plugins/lib_gtk_common/hid_gtk_conf.h \ + ../src_plugins/lib_gtk_common/lib_gtk_config.h +../src_plugins/lib_gtk_hid/glue_hid.o: \ + ../src_plugins/lib_gtk_hid/glue_hid.c ../config.h \ + ../src_plugins/lib_gtk_hid/glue_hid.h hid.h ../src_3rd/liblihata/dom.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/parser.h \ + ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h error.h global_typedefs.h \ + pcb_bool.h unit.h attrib.h layer.h globalconst.h color.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h \ + ../src_3rd/genvector/gds_char.h ../src_plugins/lib_gtk_hid/gui.h \ + ../src_plugins/lib_gtk_common/ui_zoompan.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h unit.h pcb_bool.h \ + ../src_plugins/lib_gtk_common/in_mouse.h hid_cfg_input.h hid_cfg.h hid.h \ + ../src_plugins/lib_gtk_common/glue.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/genvector/vtp0.h list_conf.h \ + conf.h ../src_plugins/lib_gtk_common/compat.h \ + ../src_plugins/lib_gtk_common/dlg_topwin.h hid_cfg.h \ + ../src_plugins/lib_gtk_common/util_ext_chg.h \ + ../src_plugins/lib_gtk_common/bu_info_bar.h \ + ../src_plugins/lib_gtk_common/bu_menu.h \ + ../src_plugins/lib_gtk_common/wt_route_style.h route_style.h \ + vtroutestyle.h conf_hid.h ../src_plugins/lib_gtk_common/bu_mode_btn.h \ + ../src_plugins/lib_gtk_common/bu_cursor_pos.h \ + ../src_plugins/lib_gtk_common/bu_command.h \ + ../src_plugins/lib_gtk_common/wt_layersel.h layer.h layer_grp.h \ + ../src_plugins/lib_gtk_common/in_mouse.h \ + ../src_plugins/lib_gtk_common/glue.h board.h layer_grp.h rats_patch.h \ + board.h event.h ../src_plugins/lib_gtk_hid/render.h \ + ../src_plugins/lib_gtk_hid/actions.h ../src_plugins/lib_gtk_hid/common.h \ + hid_nogui.h hid_attrib.h hid_draw_helpers.h \ + ../src_plugins/lib_gtk_hid/coord_conv.h compat_misc.h conf_core.h \ + ../src_plugins/lib_gtk_common/in_keyboard.h \ + ../src_plugins/lib_gtk_common/ui_zoompan.h \ + ../src_plugins/lib_gtk_common/bu_dwg_tooltip.h \ + ../src_plugins/lib_gtk_common/ui_crosshair.h \ + ../src_plugins/lib_gtk_common/dlg_fileselect.h global_typedefs.h \ + ../src_plugins/lib_gtk_common/dlg_attribute.h \ + ../src_plugins/lib_gtk_common/dlg_attributes.h \ + ../src_plugins/lib_gtk_common/util_listener.h \ + ../src_plugins/lib_gtk_common/util_timer.h \ + ../src_plugins/lib_gtk_common/util_watch.h \ + ../src_plugins/lib_gtk_common/win_place.h \ + ../src_plugins/lib_gtk_common/hid_gtk_conf.h \ + ../src_plugins/lib_gtk_common/lib_gtk_config.h +../src_plugins/lib_gtk_hid/glue_win32.o: \ + ../src_plugins/lib_gtk_hid/glue_win32.c \ + ../src_plugins/lib_gtk_hid/glue_win32.h +../src_plugins/lib_gtk_hid/lib_gtk_hid.o: \ + ../src_plugins/lib_gtk_hid/lib_gtk_hid.c ../config.h plugins.h \ + ../src_3rd/puplug/puplug.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/os_dep.h ../src_3rd/puplug/config.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/error.h +../src_plugins/lib_gtk_hid/render.o: ../src_plugins/lib_gtk_hid/render.c \ + ../config.h ../src_plugins/lib_gtk_hid/gui.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h error.h global_typedefs.h pcb_bool.h unit.h \ + attrib.h layer.h globalconst.h color.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h \ + ../src_3rd/genvector/gds_char.h \ + ../src_plugins/lib_gtk_common/ui_zoompan.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h unit.h pcb_bool.h \ + ../src_plugins/lib_gtk_common/in_mouse.h hid_cfg_input.h hid_cfg.h hid.h \ + ../src_plugins/lib_gtk_common/glue.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/genvector/vtp0.h list_conf.h \ + conf.h ../src_plugins/lib_gtk_common/compat.h \ + ../src_plugins/lib_gtk_common/dlg_topwin.h hid_cfg.h \ + ../src_plugins/lib_gtk_common/util_ext_chg.h \ + ../src_plugins/lib_gtk_common/bu_info_bar.h \ + ../src_plugins/lib_gtk_common/bu_menu.h \ + ../src_plugins/lib_gtk_common/wt_route_style.h route_style.h \ + vtroutestyle.h conf_hid.h ../src_plugins/lib_gtk_common/bu_mode_btn.h \ + ../src_plugins/lib_gtk_common/bu_cursor_pos.h \ + ../src_plugins/lib_gtk_common/bu_command.h \ + ../src_plugins/lib_gtk_common/wt_layersel.h layer.h layer_grp.h \ + ../src_plugins/lib_gtk_common/in_mouse.h \ + ../src_plugins/lib_gtk_common/glue.h board.h layer_grp.h rats_patch.h \ + board.h event.h ../src_plugins/lib_gtk_hid/render.h +../src_plugins/lib_hid_common/cli_history.o: \ + ../src_plugins/lib_hid_common/cli_history.c ../config.h \ + ../src_3rd/genlist/gendlist.h \ + ../src_plugins/lib_hid_common/cli_history.h \ + ../src_plugins/lib_hid_common/lib_hid_common.h \ + ../src_plugins/lib_hid_common/lib_hid_common_conf.h conf.h \ + global_typedefs.h pcb_bool.h unit.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h safe_fs.h paths.h +../src_plugins/lib_hid_common/grid_menu.o: \ + ../src_plugins/lib_hid_common/grid_menu.c ../config.h conf.h \ + global_typedefs.h pcb_bool.h unit.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h conf_core.h globalconst.h color.h grid.h \ + board.h vtroutestyle.h attrib.h layer.h obj_common.h flag.h \ + data_parent.h obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h layer_grp.h rats_patch.h event.h hid_cfg.h \ + hid.h error.h hid.h ../src_plugins/lib_hid_common/grid_menu.h +../src_plugins/lib_hid_common/layer_menu.o: \ + ../src_plugins/lib_hid_common/layer_menu.c ../config.h board.h \ + ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h global_typedefs.h \ + pcb_bool.h unit.h vtroutestyle.h attrib.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h board.h data.h crosshair.h vtonpoint.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h error.h route.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h conf_core.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h list_conf.h event.h layer.h layer_ui.h \ + layer_grp.h pcb-printf.h hid_cfg.h hid.h \ + ../src_plugins/lib_hid_common/layer_menu.h +../src_plugins/lib_hid_common/lead_user.o: \ + ../src_plugins/lib_hid_common/lead_user.c ../config.h draw.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h error.h global_typedefs.h pcb_bool.h unit.h \ + attrib.h layer.h globalconst.h color.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h \ + ../src_3rd/genvector/gds_char.h unit.h event.h hid.h +../src_plugins/lib_hid_common/lib_hid_common.o: \ + ../src_plugins/lib_hid_common/lib_hid_common.c ../config.h plugins.h \ + ../src_3rd/puplug/puplug.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/os_dep.h ../src_3rd/puplug/config.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/error.h conf_hid.h conf.h \ + global_typedefs.h pcb_bool.h unit.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h error.h \ + ../src_plugins/lib_hid_common/grid_menu.h conf.h event.h \ + ../src_plugins/lib_hid_common/layer_menu.h \ + ../src_plugins/lib_hid_common/routest_menu.h \ + ../src_plugins/lib_hid_common/cli_history.h \ + ../src_plugins/lib_hid_common/util.c \ + ../src_plugins/lib_hid_common/util.h data.h globalconst.h layer.h \ + attrib.h color.h obj_common.h flag.h data_parent.h obj_arc_list.h \ + obj_arc.h ../src_3rd/genlist/gendlist.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h crosshair.h \ + vtonpoint.h hid.h route.h buffer.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h obj_rat_list.h obj_rat.h layer_grp.h idpath.h \ + obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h data_it.h data.h \ + flag.h ../src_plugins/lib_hid_common/lead_user.h \ + ../src_plugins/lib_hid_common/lib_hid_common.h \ + ../src_plugins/lib_hid_common/lib_hid_common_conf.h \ + ../src_plugins/lib_hid_common/lib_hid_common_conf_fields.h +../src_plugins/lib_hid_common/routest_menu.o: \ + ../src_plugins/lib_hid_common/routest_menu.c ../config.h board.h \ + ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h global_typedefs.h \ + pcb_bool.h unit.h vtroutestyle.h attrib.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h board.h conf.h pcb-printf.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genvector/vtp0.h list_conf.h \ + conf.h conf_core.h route_style.h event.h hid_cfg.h hid.h error.h hid.h \ + ../src_plugins/lib_hid_common/routest_menu.h +../src_plugins/lib_hid_gl/hidgl.o: ../src_plugins/lib_hid_gl/hidgl.c \ + ../config.h conf_core.h conf.h global_typedefs.h pcb_bool.h unit.h \ + pcb-printf.h ../src_3rd/genvector/gds_char.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h globalconst.h color.h crosshair.h \ + vtonpoint.h hid.h error.h attrib.h layer.h obj_common.h flag.h \ + data_parent.h obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h route.h data.h crosshair.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h layer_grp.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h board.h \ + vtroutestyle.h rats_patch.h board.h grid.h hid.h \ + ../src_plugins/lib_hid_gl/hidgl.h ../src_plugins/lib_hid_gl/draw_gl.c \ + ../src_plugins/lib_hid_gl/stencil_gl.h \ + ../src_plugins/lib_hid_gl/opengl.h +../src_plugins/lib_hid_gl/lib_hid_gl.o: \ + ../src_plugins/lib_hid_gl/lib_hid_gl.c ../config.h plugins.h \ + ../src_3rd/puplug/puplug.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/os_dep.h ../src_3rd/puplug/config.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/error.h +../src_plugins/lib_hid_gl/stencil_gl.o: \ + ../src_plugins/lib_hid_gl/stencil_gl.c \ + ../src_plugins/lib_hid_gl/stencil_gl.h \ + ../src_plugins/lib_hid_gl/opengl.h +../src_plugins/lib_legacy_func/lib_legacy_func.o: \ + ../src_plugins/lib_legacy_func/lib_legacy_func.c \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../config.h data.h globalconst.h \ + global_typedefs.h pcb_bool.h unit.h layer.h attrib.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h box.h math_helper.h misc_util.h crosshair.h \ + vtonpoint.h hid.h ../src_3rd/liblihata/dom.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/parser.h \ + ../src_3rd/genht/htsp.h error.h route.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h layer_grp.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h change.h board.h vtroutestyle.h rats_patch.h error.h \ + undo.h ../src_3rd/libuundo/uundo.h undo_old.h plugins.h \ + ../src_3rd/puplug/puplug.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/os_dep.h ../src_3rd/puplug/config.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/error.h safe_fs.h conf.h \ + pcb-printf.h ../src_3rd/liblihata/lihata.h list_conf.h +../src_plugins/lib_netmap/netmap.o: ../src_plugins/lib_netmap/netmap.c \ + ../config.h ../src_3rd/genht/htpp.h ../src_3rd/genht/ht.h \ + ../src_plugins/lib_netmap/netmap.h board.h ../src_3rd/genht/htsp.h \ + global_typedefs.h pcb_bool.h unit.h vtroutestyle.h attrib.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h board.h netlist2.h ../src_3rd/genvector/vtp0.h data.h \ + crosshair.h vtonpoint.h hid.h ../src_3rd/liblihata/dom.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/parser.h error.h \ + route.h buffer.h ../src_3rd/libfungw/fungw.h obj_rat_list.h obj_rat.h \ + idpath.h obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h \ + rtree.h ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h find.h \ + pcb-printf.h plugins.h ../src_3rd/puplug/puplug.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/os_dep.h \ + ../src_3rd/puplug/config.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/error.h +../src_plugins/lib_netmap/placement.o: \ + ../src_plugins/lib_netmap/placement.c ../config.h \ + ../src_plugins/lib_netmap/placement.h board.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h global_typedefs.h pcb_bool.h unit.h vtroutestyle.h \ + attrib.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h board.h data.h crosshair.h vtonpoint.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h error.h route.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h ht_subc.h +../src_plugins/lib_polyhelp/polyhelp.o: \ + ../src_plugins/lib_polyhelp/polyhelp.c ../config.h \ + ../src_plugins/lib_polyhelp/polyhelp.h obj_poly.h \ + ../src_3rd/genlist/gendlist.h obj_common.h flag.h globalconst.h attrib.h \ + global_typedefs.h pcb_bool.h unit.h data_parent.h polyarea.h polygon.h \ + rtree.h ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h math_helper.h \ + plugins.h ../src_3rd/puplug/puplug.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/os_dep.h ../src_3rd/puplug/config.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/error.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_line.h box.h misc_util.h \ + polygon_offs.h hid_dad.h compat_misc.h hid_attrib.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h error.h layer.h color.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h pcb-printf.h \ + ../src_plugins/lib_polyhelp/topoly.h board.h vtroutestyle.h layer_grp.h \ + rats_patch.h board.h obj_common.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h data.h crosshair.h vtonpoint.h route.h buffer.h \ + obj_rat_list.h obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h ht_subc.h ../src_3rd/genht/ht.h \ + ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h conf_core.h conf.h ../src_3rd/liblihata/lihata.h \ + list_conf.h compat_misc.h hid_attrib.h actions.h dolists.h +../src_plugins/lib_polyhelp/topoly.o: \ + ../src_plugins/lib_polyhelp/topoly.c ../config.h \ + ../src_3rd/genvector/vtp0.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/genvector/vti0.h \ + ../src_plugins/lib_polyhelp/topoly.h board.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h global_typedefs.h pcb_bool.h unit.h vtroutestyle.h \ + attrib.h layer.h globalconst.h color.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h \ + ../src_3rd/genvector/gds_char.h layer_grp.h rats_patch.h board.h \ + obj_common.h ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h error.h \ + rtree.h ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h data.h \ + crosshair.h vtonpoint.h hid.h ../src_3rd/liblihata/dom.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/parser.h error.h \ + route.h buffer.h obj_rat_list.h obj_rat.h idpath.h obj_subc_list.h \ + obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h obj_arc.h \ + obj_line.h obj_poly.h obj_poly_draw.h draw.h polygon.h search.h hid.h \ + actions.h funchash_core.h funchash.h funchash_core_list.h +../src_plugins/lib_vfs/lib_vfs.o: ../src_plugins/lib_vfs/lib_vfs.c \ + ../config.h board.h ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h \ + global_typedefs.h pcb_bool.h unit.h vtroutestyle.h attrib.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h board.h data.h crosshair.h vtonpoint.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h error.h route.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h plugins.h ../src_3rd/puplug/puplug.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/os_dep.h \ + ../src_3rd/puplug/config.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/error.h pcb-printf.h compat_misc.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h list_conf.h conf.h \ + ../src_plugins/propedit/props.h global_typedefs.h \ + ../src_3rd/genvector/vtl0.h idpath.h color.h \ + ../src_plugins/propedit/propsel.h ../src_plugins/lib_vfs/lib_vfs.h +../src_plugins/loghid/hid-logger.o: ../src_plugins/loghid/hid-logger.c \ + ../config.h ../src_plugins/loghid/hid-logger.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h error.h global_typedefs.h pcb_bool.h unit.h \ + attrib.h layer.h globalconst.h color.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h \ + ../src_3rd/genvector/gds_char.h pcb-printf.h +../src_plugins/loghid/loghid.o: ../src_plugins/loghid/loghid.c \ + ../config.h conf.h global_typedefs.h pcb_bool.h unit.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h data.h globalconst.h layer.h attrib.h \ + color.h obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h obj_line_list.h obj_line.h obj_poly_list.h \ + obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h crosshair.h \ + vtonpoint.h hid.h error.h route.h buffer.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h obj_rat_list.h obj_rat.h layer_grp.h idpath.h \ + obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h change.h board.h \ + vtroutestyle.h rats_patch.h error.h undo.h ../src_3rd/libuundo/uundo.h \ + undo_old.h plugins.h ../src_3rd/puplug/puplug.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/os_dep.h ../src_3rd/puplug/config.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/error.h \ + ../src_plugins/loghid/hid-logger.h hid.h hid_init.h hid_attrib.h \ + hid_nogui.h dolists.h +../src_plugins/millpath/millpath.o: ../src_plugins/millpath/millpath.c \ + ../config.h plugins.h ../src_3rd/puplug/puplug.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/os_dep.h \ + ../src_3rd/puplug/config.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/error.h actions.h hid.h ../src_3rd/liblihata/dom.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/parser.h \ + ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h error.h global_typedefs.h \ + pcb_bool.h unit.h attrib.h layer.h globalconst.h color.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h ../src_plugins/millpath/toolpath.h layer.h \ + layer_grp.h polygon.h rtree.h ../src_3rd/genrtree/genrtree_api.h \ + rtree2_compat.h board.h vtroutestyle.h layer_grp.h rats_patch.h board.h \ + data.h crosshair.h vtonpoint.h route.h buffer.h obj_rat_list.h obj_rat.h \ + idpath.h obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h \ + ht_subc.h ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h \ + obj_pstk.h ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h \ + polygon.h vtpadstack_t.h dolists.h +../src_plugins/millpath/toolpath.o: ../src_plugins/millpath/toolpath.c \ + ../config.h ../src_plugins/millpath/toolpath.h layer.h globalconst.h \ + global_typedefs.h pcb_bool.h unit.h attrib.h color.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h ../src_3rd/genht/ht.h box.h math_helper.h \ + misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h layer.h \ + polygon.h rtree.h ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h \ + board.h ../src_3rd/genht/htsp.h vtroutestyle.h layer_grp.h rats_patch.h \ + board.h data.h crosshair.h vtonpoint.h hid.h ../src_3rd/liblihata/dom.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/parser.h error.h \ + route.h buffer.h ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h \ + obj_rat_list.h obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h ht_subc.h ../src_3rd/genht/ht.h \ + ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h flag.h layer_ui.h obj_line.h obj_line_op.h operation.h \ + obj_arc.h obj_poly.h obj_poly_op.h funchash_core.h funchash.h \ + funchash_core_list.h ../src_plugins/lib_polyhelp/polyhelp.h +../src_plugins/mincut/pcb-mincut/graph.o: \ + ../src_plugins/mincut/pcb-mincut/graph.c \ + ../src_plugins/mincut/pcb-mincut/graph.h \ + ../src_plugins/mincut/pcb-mincut/../../../config.h safe_fs.h conf.h \ + ../config.h global_typedefs.h pcb_bool.h unit.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h +../src_plugins/mincut/pcb-mincut/solve.o: \ + ../src_plugins/mincut/pcb-mincut/solve.c \ + ../src_plugins/mincut/pcb-mincut/solve.h \ + ../src_plugins/mincut/pcb-mincut/graph.h \ + ../src_plugins/mincut/pcb-mincut/../../../config.h compat_misc.h \ + ../config.h +../src_plugins/mincut/rats_mincut.o: ../src_plugins/mincut/rats_mincut.c \ + ../config.h board.h ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h \ + global_typedefs.h pcb_bool.h unit.h vtroutestyle.h attrib.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h board.h data.h crosshair.h vtonpoint.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h error.h route.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h draw.h error.h event.h plug_io.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h list_conf.h find.h polygon.h search.h \ + undo.h ../src_3rd/libuundo/uundo.h undo_old.h plugins.h \ + ../src_3rd/puplug/puplug.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/os_dep.h ../src_3rd/puplug/config.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/error.h netlist2.h \ + compat_misc.h obj_common.h obj_subc_parent.h data.h \ + ../src_plugins/mincut/pcb-mincut/graph.h \ + ../src_plugins/mincut/pcb-mincut/../../../config.h \ + ../src_plugins/mincut/pcb-mincut/solve.h \ + ../src_plugins/mincut/pcb-mincut/graph.h conf.h \ + ../src_plugins/mincut/rats_mincut_conf.h \ + ../src_plugins/mincut/rats_mincut_conf_fields.h +../src_plugins/oldactions/oldactions.o: \ + ../src_plugins/oldactions/oldactions.c ../config.h conf.h \ + global_typedefs.h pcb_bool.h unit.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h data.h globalconst.h layer.h attrib.h \ + color.h obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h obj_line_list.h obj_line.h obj_poly_list.h \ + obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h crosshair.h \ + vtonpoint.h hid.h error.h route.h buffer.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h obj_rat_list.h obj_rat.h layer_grp.h idpath.h \ + obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h event.h change.h \ + board.h vtroutestyle.h rats_patch.h error.h undo.h \ + ../src_3rd/libuundo/uundo.h undo_old.h plugins.h \ + ../src_3rd/puplug/puplug.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/os_dep.h ../src_3rd/puplug/config.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/error.h actions.h \ + plug_footprint.h vtlibrary.h data.h obj_subc.h macro.h compat_misc.h \ + netlist2.h dolists.h +../src_plugins/polycombine/polycombine.o: \ + ../src_plugins/polycombine/polycombine.c ../config.h board.h \ + ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h global_typedefs.h \ + pcb_bool.h unit.h vtroutestyle.h attrib.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h board.h data.h crosshair.h vtonpoint.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h error.h route.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h macro.h remove.h hid.h error.h rtree.h polygon.h \ + polyarea.h flag_str.h find.h draw.h undo.h ../src_3rd/libuundo/uundo.h \ + undo_old.h plugins.h ../src_3rd/puplug/puplug.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/os_dep.h ../src_3rd/puplug/config.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/error.h actions.h obj_poly.h \ + dolists.h +../src_plugins/polystitch/polystitch.o: \ + ../src_plugins/polystitch/polystitch.c ../config.h board.h \ + ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h global_typedefs.h \ + pcb_bool.h unit.h vtroutestyle.h attrib.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h board.h data.h crosshair.h vtonpoint.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h error.h route.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h macro.h remove.h hid.h error.h rtree.h draw.h polygon.h \ + plugins.h ../src_3rd/puplug/puplug.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/os_dep.h ../src_3rd/puplug/config.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/error.h actions.h obj_poly.h \ + obj_poly_draw.h draw.h dolists.h +../src_plugins/propedit/propdlg.o: ../src_plugins/propedit/propdlg.c \ + ../config.h ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h board.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h global_typedefs.h pcb_bool.h unit.h vtroutestyle.h \ + attrib.h layer.h globalconst.h color.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h layer_grp.h rats_patch.h board.h actions.h \ + hid.h ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h error.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h hid_dad.h compat_misc.h hid_attrib.h \ + pcb-printf.h hid_dad_tree.h hid_dad.h conf_hid.h conf.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_plugins/propedit/props.h global_typedefs.h \ + ../src_3rd/genvector/vtl0.h idpath.h color.h ../src_3rd/genht/ht.h \ + ../src_plugins/propedit/propsel.h +../src_plugins/propedit/propedit.o: ../src_plugins/propedit/propedit.c \ + board.h ../config.h ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h \ + global_typedefs.h pcb_bool.h unit.h vtroutestyle.h attrib.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h board.h data.h crosshair.h vtonpoint.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h error.h route.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h plugins.h ../src_3rd/puplug/puplug.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/os_dep.h \ + ../src_3rd/puplug/config.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/error.h ../src_plugins/propedit/props.h \ + global_typedefs.h ../src_3rd/genvector/vtl0.h idpath.h color.h \ + ../src_plugins/propedit/propsel.h ../src_plugins/propedit/propdlg.h \ + actions.h pcb-printf.h error.h layer.h layer_grp.h search.h crosshair.h \ + dolists.h +../src_plugins/propedit/props.o: ../src_plugins/propedit/props.c \ + ../config.h ../src_plugins/propedit/props.h global_typedefs.h pcb_bool.h \ + unit.h ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h \ + ../src_3rd/genvector/vtl0.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h idpath.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_common.h flag.h globalconst.h attrib.h global_typedefs.h \ + data_parent.h color.h ../src_3rd/genht/ht.h \ + ../src_plugins/propedit/propsel.h compat_misc.h board.h vtroutestyle.h \ + layer.h color.h obj_arc_list.h obj_arc.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h \ + ../src_3rd/genvector/gds_char.h layer_grp.h rats_patch.h board.h \ + pcb-printf.h hid.h ../src_3rd/liblihata/dom.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/parser.h error.h \ + ../src_3rd/genht/hash.h ../src_3rd/genht/ht.c \ + ../src_3rd/genht/ht_inlines.h +../src_plugins/propedit/propsel.o: ../src_plugins/propedit/propsel.c \ + ../config.h data.h globalconst.h global_typedefs.h pcb_bool.h unit.h \ + layer.h attrib.h color.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h ../src_3rd/genht/ht.h box.h math_helper.h \ + misc_util.h ../src_3rd/genvector/gds_char.h crosshair.h vtonpoint.h \ + hid.h ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h error.h route.h \ + buffer.h ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h \ + obj_rat_list.h obj_rat.h layer_grp.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h data_it.h data.h ../src_plugins/propedit/props.h \ + global_typedefs.h ../src_3rd/genvector/vtl0.h idpath.h color.h \ + ../src_plugins/propedit/propsel.h change.h board.h vtroutestyle.h \ + rats_patch.h misc_util.h flag_str.h compat_misc.h undo.h \ + ../src_3rd/libuundo/uundo.h undo_old.h rotate.h compat_misc.h \ + obj_pstk_inlines.h thermal.h pcb-printf.h conf_core.h conf.h \ + pcb-printf.h ../src_3rd/liblihata/lihata.h list_conf.h +../src_plugins/puller/puller.o: ../src_plugins/puller/puller.c \ + ../config.h conf_core.h conf.h global_typedefs.h pcb_bool.h unit.h \ + pcb-printf.h ../src_3rd/genvector/gds_char.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h globalconst.h color.h board.h \ + vtroutestyle.h attrib.h layer.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h obj_line_list.h \ + obj_line.h obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h \ + obj_text.h font.h ../src_3rd/genht/htip.h box.h math_helper.h \ + misc_util.h layer_grp.h rats_patch.h board.h data.h crosshair.h \ + vtonpoint.h hid.h error.h route.h buffer.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h obj_rat_list.h obj_rat.h idpath.h \ + obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h draw.h move.h \ + pcb-printf.h remove.h rtree.h flag_str.h undo.h \ + ../src_3rd/libuundo/uundo.h undo_old.h layer.h plugins.h \ + ../src_3rd/puplug/puplug.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/os_dep.h ../src_3rd/puplug/config.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/error.h actions.h misc_util.h \ + compat_misc.h obj_pstk_inlines.h data.h thermal.h funchash_core.h \ + funchash.h funchash_core_list.h search.h find.h dolists.h +../src_plugins/query/basic_fnc.o: ../src_plugins/query/basic_fnc.c \ + ../config.h data.h globalconst.h global_typedefs.h pcb_bool.h unit.h \ + layer.h attrib.h color.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h ../src_3rd/genht/ht.h box.h math_helper.h \ + misc_util.h ../src_3rd/genvector/gds_char.h crosshair.h vtonpoint.h \ + hid.h ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h error.h route.h \ + buffer.h ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h \ + obj_rat_list.h obj_rat.h layer_grp.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h ../src_plugins/query/query_access.h \ + ../src_plugins/query/query.h ../src_3rd/genht/htsi.h \ + ../src_3rd/genregex/regex_se.h ../src_3rd/genregex/regex_templ.h \ + ../src_3rd/genregex/regex.h ../src_plugins/query/fields_sphash.h \ + obj_common.h layer.h flag_str.h ../src_plugins/query/query_exec.h +../src_plugins/query/fields_sphash.o: \ + ../src_plugins/query/fields_sphash.c +../src_plugins/query/query.o: ../src_plugins/query/query.c ../config.h \ + ../src_3rd/genht/hash.h ../src_3rd/genht/htsi.h ../src_3rd/genht/ht.h \ + conf.h global_typedefs.h pcb_bool.h unit.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genvector/vtp0.h list_conf.h conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h data.h globalconst.h layer.h attrib.h \ + color.h obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h obj_line_list.h obj_line.h obj_poly_list.h \ + obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h crosshair.h \ + vtonpoint.h hid.h error.h route.h buffer.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h obj_rat_list.h obj_rat.h layer_grp.h idpath.h \ + obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h vtpadstack.h \ + obj_pstk_shape.h polygon.h vtpadstack_t.h change.h board.h \ + vtroutestyle.h rats_patch.h error.h undo.h ../src_3rd/libuundo/uundo.h \ + undo_old.h plugins.h ../src_3rd/puplug/puplug.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/os_dep.h ../src_3rd/puplug/config.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/error.h hid_init.h actions.h \ + compat_misc.h ../src_plugins/query/query.h \ + ../src_3rd/genregex/regex_se.h ../src_3rd/genregex/regex_templ.h \ + ../src_3rd/genregex/regex.h ../src_plugins/query/fields_sphash.h \ + obj_common.h layer.h flag_str.h fptr_cast.h +../src_plugins/query/query_access.o: ../src_plugins/query/query_access.c \ + ../config.h math_helper.h compat_misc.h board.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h global_typedefs.h pcb_bool.h unit.h vtroutestyle.h \ + attrib.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h board.h data.h crosshair.h vtonpoint.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h error.h route.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h ../src_plugins/query/query_access.h \ + ../src_plugins/query/query.h ../src_3rd/genht/htsi.h \ + ../src_3rd/genregex/regex_se.h ../src_3rd/genregex/regex_templ.h \ + ../src_3rd/genregex/regex.h ../src_plugins/query/fields_sphash.h \ + obj_common.h layer.h flag_str.h ../src_plugins/query/query_exec.h \ + obj_pstk_inlines.h data.h thermal.h obj_subc_parent.h +../src_plugins/query/query_act.o: ../src_plugins/query/query_act.c \ + ../config.h actions.h hid.h ../src_3rd/liblihata/dom.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/parser.h \ + ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h error.h global_typedefs.h \ + pcb_bool.h unit.h attrib.h layer.h globalconst.h color.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h ../src_plugins/query/query.h \ + ../src_3rd/genvector/vtp0.h ../src_3rd/genht/htsi.h \ + ../src_3rd/genregex/regex_se.h ../src_3rd/genregex/regex_templ.h \ + ../src_3rd/genregex/regex.h ../src_plugins/query/fields_sphash.h \ + obj_common.h layer.h flag_str.h ../src_plugins/query/query_y.h \ + ../src_plugins/query/query_exec.h draw.h select.h operation.h board.h \ + vtroutestyle.h layer_grp.h rats_patch.h board.h macro.h dolists.h +../src_plugins/query/query_exec.o: ../src_plugins/query/query_exec.c \ + ../config.h data.h globalconst.h global_typedefs.h pcb_bool.h unit.h \ + layer.h attrib.h color.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h ../src_3rd/genht/ht.h box.h math_helper.h \ + misc_util.h ../src_3rd/genvector/gds_char.h crosshair.h vtonpoint.h \ + hid.h ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h error.h route.h \ + buffer.h ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h \ + obj_rat_list.h obj_rat.h layer_grp.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h ../src_plugins/query/query.h ../src_3rd/genht/htsi.h \ + ../src_3rd/genregex/regex_se.h ../src_3rd/genregex/regex_templ.h \ + ../src_3rd/genregex/regex.h ../src_plugins/query/fields_sphash.h \ + obj_common.h layer.h flag_str.h ../src_plugins/query/query_exec.h \ + ../src_plugins/query/query_access.h pcb-printf.h +../src_plugins/query/query_l.o: ../src_plugins/query/query_l.c unit.h \ + ../config.h ../src_plugins/query/query.h ../src_3rd/genvector/vtp0.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/genht/htsi.h \ + ../src_3rd/genht/ht.h ../src_3rd/genregex/regex_se.h \ + ../src_3rd/genregex/regex_templ.h ../src_3rd/genregex/regex.h \ + ../src_plugins/query/fields_sphash.h obj_common.h flag.h globalconst.h \ + attrib.h global_typedefs.h pcb_bool.h unit.h data_parent.h layer.h \ + color.h obj_common.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h flag_str.h \ + ../src_plugins/query/query_y.h compat_misc.h +../src_plugins/query/query_y.o: ../src_plugins/query/query_y.c unit.h \ + ../config.h ../src_plugins/query/query.h ../src_3rd/genvector/vtp0.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/genht/htsi.h \ + ../src_3rd/genht/ht.h ../src_3rd/genregex/regex_se.h \ + ../src_3rd/genregex/regex_templ.h ../src_3rd/genregex/regex.h \ + ../src_plugins/query/fields_sphash.h obj_common.h flag.h globalconst.h \ + attrib.h global_typedefs.h pcb_bool.h unit.h data_parent.h layer.h \ + color.h obj_common.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h flag_str.h \ + ../src_plugins/query/query_l.h compat_misc.h +../src_plugins/renumber/renumber.o: ../src_plugins/renumber/renumber.c \ + ../config.h board.h ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h \ + global_typedefs.h pcb_bool.h unit.h vtroutestyle.h attrib.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h board.h data.h crosshair.h vtonpoint.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h error.h route.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h change.h error.h undo.h ../src_3rd/libuundo/uundo.h \ + undo_old.h plugins.h ../src_3rd/puplug/puplug.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/os_dep.h ../src_3rd/puplug/config.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/error.h actions.h conf_core.h \ + conf.h pcb-printf.h ../src_3rd/liblihata/lihata.h list_conf.h \ + compat_misc.h netlist2.h safe_fs.h macro.h pcb-printf.h dolists.h +../src_plugins/renumber/renumberblock.o: \ + ../src_plugins/renumber/renumberblock.c ../config.h board.h \ + ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h global_typedefs.h \ + pcb_bool.h unit.h vtroutestyle.h attrib.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h board.h actions.h hid.h ../src_3rd/liblihata/dom.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/parser.h error.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h data.h crosshair.h \ + vtonpoint.h route.h buffer.h obj_rat_list.h obj_rat.h idpath.h \ + obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h hid.h rtree.h undo.h ../src_3rd/libuundo/uundo.h \ + undo_old.h error.h change.h conf_core.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h list_conf.h +../src_plugins/report/drill.o: ../src_plugins/report/drill.c ../config.h \ + data.h globalconst.h global_typedefs.h pcb_bool.h unit.h layer.h \ + attrib.h color.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h ../src_3rd/genht/ht.h box.h math_helper.h \ + misc_util.h ../src_3rd/genvector/gds_char.h crosshair.h vtonpoint.h \ + hid.h ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h error.h route.h \ + buffer.h ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h \ + obj_rat_list.h obj_rat.h layer_grp.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h ../src_plugins/report/drill.h macro.h obj_pstk_inlines.h \ + board.h vtroutestyle.h rats_patch.h data.h thermal.h +../src_plugins/report/report.o: ../src_plugins/report/report.c \ + ../config.h conf_core.h conf.h global_typedefs.h pcb_bool.h unit.h \ + pcb-printf.h ../src_3rd/genvector/gds_char.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h globalconst.h color.h \ + ../src_plugins/report/report.h math_helper.h crosshair.h vtonpoint.h \ + hid.h error.h attrib.h layer.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h obj_line_list.h \ + obj_line.h obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h \ + obj_text.h font.h ../src_3rd/genht/htip.h box.h math_helper.h \ + misc_util.h route.h board.h vtroutestyle.h layer_grp.h rats_patch.h \ + board.h data.h crosshair.h buffer.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h obj_rat_list.h obj_rat.h idpath.h \ + obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h data_it.h data.h \ + ../src_plugins/report/drill.h error.h search.h rtree.h flag_str.h \ + macro.h undo.h ../src_3rd/libuundo/uundo.h undo_old.h find.h draw.h \ + pcb-printf.h plugins.h ../src_3rd/puplug/puplug.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/os_dep.h \ + ../src_3rd/puplug/config.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/error.h actions.h misc_util.h \ + ../src_plugins/report/report_conf.h conf.h compat_misc.h layer.h \ + obj_term.h obj_pstk.h obj_pstk_inlines.h thermal.h obj_subc_parent.h \ + hid_dad.h compat_misc.h hid_attrib.h netlist2.h \ + ../src_3rd/genregex/regex_sei.h ../src_3rd/genregex/regex_templ.h \ + ../src_3rd/genregex/regex.h dolists.h \ + ../src_plugins/report/report_conf_fields.h +../src_plugins/rubberband_orig/fgeometry.o: \ + ../src_plugins/rubberband_orig/fgeometry.c \ + ../src_plugins/rubberband_orig/fgeometry.h obj_common.h flag.h \ + globalconst.h ../config.h attrib.h global_typedefs.h pcb_bool.h unit.h \ + data_parent.h +../src_plugins/rubberband_orig/rubberband.o: \ + ../src_plugins/rubberband_orig/rubberband.c ../config.h board.h \ + ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h global_typedefs.h \ + pcb_bool.h unit.h vtroutestyle.h attrib.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h board.h data.h crosshair.h vtonpoint.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h error.h route.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h data_it.h data.h data_list.h error.h event.h undo.h \ + ../src_3rd/libuundo/uundo.h undo_old.h operation.h rotate.h \ + compat_misc.h draw.h draw_wireframe.h crosshair.h obj_rat_draw.h \ + obj_line_op.h operation.h obj_line_draw.h draw.h obj_pstk_inlines.h \ + thermal.h route_draw.h plugins.h ../src_3rd/puplug/puplug.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/os_dep.h \ + ../src_3rd/puplug/config.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/error.h conf_core.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h list_conf.h layer_grp.h \ + ../src_plugins/rubberband_orig/fgeometry.h obj_common.h search.h \ + polygon.h ../src_plugins/rubberband_orig/rubberband_conf.h conf.h \ + ../src_3rd/genvector/genvector_impl.c \ + ../src_plugins/rubberband_orig/rubberband_conf_fields.h +../src_plugins/script/live_script.o: ../src_plugins/script/live_script.c \ + ../config.h compat_inc.h ../src_3rd/genvector/vtp0.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h actions.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h error.h global_typedefs.h pcb_bool.h \ + unit.h attrib.h layer.h globalconst.h color.h obj_common.h flag.h \ + data_parent.h obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h plugins.h ../src_3rd/puplug/puplug.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/os_dep.h \ + ../src_3rd/puplug/config.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/error.h hid_cfg.h hid_dad.h compat_misc.h hid_attrib.h \ + pcb-printf.h safe_fs.h conf.h ../src_3rd/liblihata/lihata.h list_conf.h \ + compat_fs.h event.h undo.h ../src_3rd/libuundo/uundo.h undo_old.h \ + ../src_plugins/script/script.h ../src_plugins/script/live_script.h +../src_plugins/script/script.o: ../src_plugins/script/script.c \ + ../config.h ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h \ + ../src_3rd/genht/hash.h ../src_3rd/puplug/puplug.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/os_dep.h \ + ../src_3rd/puplug/config.h ../src_3rd/puplug/libs.h \ + ../src_3rd/genregex/regex_se.h ../src_3rd/genregex/regex_templ.h \ + ../src_3rd/genregex/regex.h actions.h hid.h ../src_3rd/liblihata/dom.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/parser.h error.h \ + global_typedefs.h pcb_bool.h unit.h attrib.h layer.h globalconst.h \ + color.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h plugins.h ../src_3rd/puplug/error.h error.h \ + compat_misc.h compat_fs.h safe_fs.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/genvector/vtp0.h list_conf.h \ + pcb-printf.h globalconst.h ../src_plugins/script/script.h \ + ../src_plugins/script/c_script.c fptr_cast.h conf_core.h \ + ../src_plugins/script/timer.c ../src_plugins/script/script_act.c \ + hid_dad.h compat_misc.h hid_attrib.h hid_dad_tree.h hid_dad.h \ + ../src_plugins/script/live_script.h dolists.h +../src_plugins/serpentine/serpentine.o: \ + ../src_plugins/serpentine/serpentine.c ../config.h conf_core.h conf.h \ + global_typedefs.h pcb_bool.h unit.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h globalconst.h color.h crosshair.h \ + vtonpoint.h hid.h error.h attrib.h layer.h obj_common.h flag.h \ + data_parent.h obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h route.h board.h vtroutestyle.h layer_grp.h \ + rats_patch.h board.h data.h crosshair.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h data_it.h data.h \ + error.h search.h tool.h rtree.h flag_str.h macro.h undo.h \ + ../src_3rd/libuundo/uundo.h undo_old.h find.h draw.h draw_wireframe.h \ + pcb-printf.h plugins.h ../src_3rd/puplug/puplug.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/os_dep.h \ + ../src_3rd/puplug/config.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/error.h actions.h \ + ../src_plugins/serpentine/serpentine_conf.h conf.h layer.h route.h \ + dolists.h ../src_plugins/serpentine/serpentine_conf_fields.h +../src_plugins/shand_cmd/command.o: ../src_plugins/shand_cmd/command.c \ + ../config.h conf_core.h conf.h global_typedefs.h pcb_bool.h unit.h \ + pcb-printf.h ../src_3rd/genvector/gds_char.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h globalconst.h color.h board.h \ + vtroutestyle.h attrib.h layer.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h obj_line_list.h \ + obj_line.h obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h \ + obj_text.h font.h ../src_3rd/genht/htip.h box.h math_helper.h \ + misc_util.h layer_grp.h rats_patch.h board.h build_run.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h \ + ../src_plugins/shand_cmd/command.h data.h crosshair.h vtonpoint.h hid.h \ + error.h route.h buffer.h obj_rat_list.h obj_rat.h idpath.h \ + obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h error.h plug_io.h \ + plugins.h ../src_3rd/puplug/puplug.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/os_dep.h ../src_3rd/puplug/config.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/error.h actions.h \ + compat_misc.h misc_util.h tool.h dolists.h +../src_plugins/shape/shape.o: ../src_plugins/shape/shape.c ../config.h \ + ../src_plugins/shape/shape.h board.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h global_typedefs.h pcb_bool.h unit.h vtroutestyle.h \ + attrib.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h board.h data.h crosshair.h vtonpoint.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h error.h route.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h layer.h pcb_bool.h plugins.h ../src_3rd/puplug/puplug.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/os_dep.h \ + ../src_3rd/puplug/config.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/error.h actions.h buffer.h compat_misc.h conf_core.h \ + conf.h pcb-printf.h ../src_3rd/liblihata/lihata.h list_conf.h error.h \ + event.h math_helper.h obj_poly.h obj_poly_draw.h draw.h rotate.h \ + compat_misc.h tool.h ../src_plugins/shape/shape_dialog.c hid_dad.h \ + hid_attrib.h dolists.h +../src_plugins/sketch_route/cdt/cdt.o: \ + ../src_plugins/sketch_route/cdt/cdt.c \ + ../src_plugins/sketch_route/cdt/cdt.h \ + ../src_plugins/sketch_route/cdt/typedefs.h \ + ../src_plugins/sketch_route/cdt/point.h \ + ../src_plugins/sketch_route/cdt/list/list.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h \ + ../src_plugins/sketch_route/cdt/edge.h \ + ../src_plugins/sketch_route/cdt/triangle.h +../src_plugins/sketch_route/cdt/edge.o: \ + ../src_plugins/sketch_route/cdt/edge.c \ + ../src_plugins/sketch_route/cdt/edge.h \ + ../src_plugins/sketch_route/cdt/typedefs.h \ + ../src_plugins/sketch_route/cdt/list/list.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h \ + ../src_plugins/sketch_route/cdt/list/list.c \ + ../src_3rd/genvector/genvector_impl.c +../src_plugins/sketch_route/cdt/point.o: \ + ../src_plugins/sketch_route/cdt/point.c \ + ../src_plugins/sketch_route/cdt/point.h \ + ../src_plugins/sketch_route/cdt/typedefs.h \ + ../src_plugins/sketch_route/cdt/list/list.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h \ + ../src_plugins/sketch_route/cdt/list/list.c \ + ../src_3rd/genvector/genvector_impl.c +../src_plugins/sketch_route/cdt/triangle.o: \ + ../src_plugins/sketch_route/cdt/triangle.c \ + ../src_plugins/sketch_route/cdt/triangle.h \ + ../src_plugins/sketch_route/cdt/typedefs.h \ + ../src_plugins/sketch_route/cdt/list/list.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h \ + ../src_plugins/sketch_route/cdt/list/list.c \ + ../src_3rd/genvector/genvector_impl.c +../src_plugins/sketch_route/ewire.o: ../src_plugins/sketch_route/ewire.c \ + ../src_plugins/sketch_route/ewire.h ../config.h \ + ../src_plugins/sketch_route/sktypedefs.h \ + ../src_plugins/sketch_route/ewire_point.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h \ + ../src_3rd/genvector/genvector_impl.c +../src_plugins/sketch_route/ewire_point.o: \ + ../src_plugins/sketch_route/ewire_point.c \ + ../src_plugins/sketch_route/ewire_point.h \ + ../src_plugins/sketch_route/sktypedefs.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h \ + ../src_3rd/genvector/genvector_impl.c +../src_plugins/sketch_route/pointdata.o: \ + ../src_plugins/sketch_route/pointdata.c \ + ../src_plugins/sketch_route/pointdata.h \ + ../src_plugins/sketch_route/sktypedefs.h \ + ../src_plugins/sketch_route/spoke.h obj_common.h flag.h globalconst.h \ + ../config.h attrib.h global_typedefs.h pcb_bool.h unit.h data_parent.h \ + ../src_plugins/sketch_route/ewire.h \ + ../src_plugins/sketch_route/ewire_point.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h \ + ../src_plugins/sketch_route/cdt/point.h \ + ../src_plugins/sketch_route/cdt/typedefs.h \ + ../src_plugins/sketch_route/cdt/list/list.h ../src_3rd/genvector/vtp0.h \ + ../src_plugins/sketch_route/wire.h \ + ../src_plugins/sketch_route/cdt/typedefs.h \ + ../src_plugins/sketch_route/cdt/list/list.h +../src_plugins/sketch_route/sketch_route.o: \ + ../src_plugins/sketch_route/sketch_route.c ../config.h plugins.h \ + ../src_3rd/puplug/puplug.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/os_dep.h ../src_3rd/puplug/config.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/error.h actions.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h error.h global_typedefs.h pcb_bool.h unit.h \ + attrib.h layer.h globalconst.h color.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h board.h vtroutestyle.h layer_grp.h rats_patch.h \ + board.h conf_core.h conf.h pcb-printf.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/genvector/vtp0.h list_conf.h data.h crosshair.h vtonpoint.h \ + route.h buffer.h obj_rat_list.h obj_rat.h idpath.h obj_subc_list.h \ + obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h event.h \ + list_common.h obj_line_list.h obj_pstk.h obj_pstk_inlines.h data.h \ + thermal.h obj_subc_parent.h pcb-printf.h search.h tool.h layer_ui.h \ + netlist2.h ../src_plugins/sketch_route/sktypedefs.h \ + ../src_plugins/sketch_route/wire.h \ + ../src_plugins/sketch_route/cdt/typedefs.h \ + ../src_plugins/sketch_route/cdt/list/list.h \ + ../src_plugins/sketch_route/ewire.h \ + ../src_plugins/sketch_route/ewire_point.h \ + ../src_plugins/sketch_route/pointdata.h \ + ../src_plugins/sketch_route/spoke.h obj_common.h \ + ../src_plugins/sketch_route/cdt/point.h \ + ../src_plugins/sketch_route/cdt/typedefs.h \ + ../src_plugins/sketch_route/cdt/list/list.h \ + ../src_plugins/sketch_route/cdt/cdt.h \ + ../src_plugins/sketch_route/cdt/point.h \ + ../src_plugins/sketch_route/cdt/edge.h \ + ../src_plugins/sketch_route/cdt/triangle.h dolists.h +../src_plugins/sketch_route/spoke.o: ../src_plugins/sketch_route/spoke.c \ + ../config.h conf_core.h conf.h global_typedefs.h pcb_bool.h unit.h \ + pcb-printf.h ../src_3rd/genvector/gds_char.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h globalconst.h color.h \ + ../src_plugins/sketch_route/spoke.h \ + ../src_plugins/sketch_route/sktypedefs.h obj_common.h flag.h attrib.h \ + data_parent.h ../src_plugins/sketch_route/ewire.h \ + ../src_plugins/sketch_route/ewire_point.h \ + ../src_plugins/sketch_route/cdt/point.h \ + ../src_plugins/sketch_route/cdt/typedefs.h \ + ../src_plugins/sketch_route/cdt/list/list.h \ + ../src_plugins/sketch_route/pointdata.h \ + ../src_plugins/sketch_route/wire.h \ + ../src_plugins/sketch_route/cdt/typedefs.h \ + ../src_plugins/sketch_route/cdt/list/list.h +../src_plugins/sketch_route/wire.o: ../src_plugins/sketch_route/wire.c \ + ../src_plugins/sketch_route/pointdata.h \ + ../src_plugins/sketch_route/sktypedefs.h \ + ../src_plugins/sketch_route/spoke.h obj_common.h flag.h globalconst.h \ + ../config.h attrib.h global_typedefs.h pcb_bool.h unit.h data_parent.h \ + ../src_plugins/sketch_route/ewire.h \ + ../src_plugins/sketch_route/ewire_point.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h \ + ../src_plugins/sketch_route/cdt/point.h \ + ../src_plugins/sketch_route/cdt/typedefs.h \ + ../src_plugins/sketch_route/cdt/list/list.h ../src_3rd/genvector/vtp0.h \ + ../src_plugins/sketch_route/wire.h \ + ../src_plugins/sketch_route/cdt/typedefs.h \ + ../src_plugins/sketch_route/cdt/list/list.h \ + ../src_plugins/sketch_route/cdt/list/list.c \ + ../src_3rd/genvector/genvector_impl.c +../src_plugins/smartdisperse/smartdisperse.o: \ + ../src_plugins/smartdisperse/smartdisperse.c ../src_3rd/genht/htpi.h \ + ../src_3rd/genht/ht.h ../config.h board.h ../src_3rd/genht/htsp.h \ + global_typedefs.h pcb_bool.h unit.h vtroutestyle.h attrib.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h board.h data.h crosshair.h vtonpoint.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h error.h route.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h hid.h rtree.h undo.h ../src_3rd/libuundo/uundo.h \ + undo_old.h netlist2.h error.h move.h draw.h plugins.h \ + ../src_3rd/puplug/puplug.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/os_dep.h ../src_3rd/puplug/config.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/error.h actions.h obj_subc.h \ + obj_subc_parent.h data.h obj_term.h funchash_core.h funchash.h \ + funchash_core_list.h dolists.h +../src_plugins/stroke/stroke.o: ../src_plugins/stroke/stroke.c \ + ../config.h board.h ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h \ + global_typedefs.h pcb_bool.h unit.h vtroutestyle.h attrib.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h board.h conf_core.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/dom.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/parser.h \ + ../src_3rd/genvector/vtp0.h list_conf.h crosshair.h vtonpoint.h hid.h \ + error.h route.h actions.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h unit.h plugins.h ../src_3rd/puplug/puplug.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/os_dep.h \ + ../src_3rd/puplug/config.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/error.h stub_stroke.h compat_misc.h tool.h \ + ../src_plugins/stroke/conf_internal.c \ + ../src_plugins/stroke/stroke_conf.h conf.h dolists.h \ + ../src_plugins/stroke/stroke_conf_fields.h +../src_plugins/teardrops/teardrops.o: \ + ../src_plugins/teardrops/teardrops.c ../config.h math_helper.h board.h \ + ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h global_typedefs.h \ + pcb_bool.h unit.h vtroutestyle.h attrib.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h board.h data.h crosshair.h vtonpoint.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h error.h route.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h hid.h rtree.h undo.h ../src_3rd/libuundo/uundo.h \ + undo_old.h plugins.h ../src_3rd/puplug/puplug.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/os_dep.h ../src_3rd/puplug/config.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/error.h actions.h \ + obj_pstk_inlines.h data.h thermal.h dolists.h +../src_plugins/vendordrill/vendor.o: ../src_plugins/vendordrill/vendor.c \ + ../config.h conf_core.h conf.h global_typedefs.h pcb_bool.h unit.h \ + pcb-printf.h ../src_3rd/genvector/gds_char.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h globalconst.h color.h \ + ../src_3rd/genregex/regex_sei.h ../src_3rd/genregex/regex_templ.h \ + ../src_3rd/genregex/regex.h change.h board.h vtroutestyle.h attrib.h \ + layer.h obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h obj_line_list.h obj_line.h obj_poly_list.h \ + obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h layer_grp.h \ + rats_patch.h board.h data.h crosshair.h vtonpoint.h hid.h error.h \ + route.h buffer.h ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h \ + obj_rat_list.h obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h draw.h error.h \ + undo.h ../src_3rd/libuundo/uundo.h undo_old.h plugins.h \ + ../src_3rd/puplug/puplug.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/os_dep.h ../src_3rd/puplug/config.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/error.h actions.h hid_cfg.h \ + ../src_plugins/vendordrill/vendor_conf.h conf.h compat_misc.h \ + obj_pstk_inlines.h data.h thermal.h event.h macro.h \ + ../src_3rd/liblihata/tree.h dolists.h \ + ../src_plugins/vendordrill/vendor_conf_fields.h +../src_3rd/gensexpr/gsx_parse.o: ../src_3rd/gensexpr/gsx_parse.c \ + ../src_3rd/gensexpr/gsx_parse.h +../src_3rd/gensexpr/gsxl.o: ../src_3rd/gensexpr/gsxl.c \ + ../src_3rd/gensexpr/gsxl.h ../src_3rd/gensexpr/gensexpr_impl.h \ + ../src_3rd/gensexpr/gsx_parse.h ../src_3rd/gensexpr/gensexpr_impl.c +../src_3rd/libuhpgl/parse.o: ../src_3rd/libuhpgl/parse.c \ + ../src_3rd/libuhpgl/uhpgl_math.h ../src_3rd/libuhpgl/libuhpgl.h \ + ../src_3rd/libuhpgl/parse.h ../src_3rd/libuhpgl/arc_iterate.h +../src_3rd/genht/hash.o: ../src_3rd/genht/hash.c +../src_3rd/genht/htip.o: ../src_3rd/genht/htip.c ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/ht.c \ + ../src_3rd/genht/ht_inlines.h +../src_3rd/genht/htpi.o: ../src_3rd/genht/htpi.c ../src_3rd/genht/htpi.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/ht.c \ + ../src_3rd/genht/ht_inlines.h +../src_3rd/genht/htpp.o: ../src_3rd/genht/htpp.c ../src_3rd/genht/htpp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/ht.c \ + ../src_3rd/genht/ht_inlines.h +../src_3rd/genht/htsi.o: ../src_3rd/genht/htsi.c ../src_3rd/genht/htsi.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/ht.c \ + ../src_3rd/genht/ht_inlines.h +../src_3rd/genht/htsp.o: ../src_3rd/genht/htsp.c ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/ht.c \ + ../src_3rd/genht/ht_inlines.h +../src_3rd/genht/htss.o: ../src_3rd/genht/htss.c ../src_3rd/genht/htss.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/ht.c \ + ../src_3rd/genht/ht_inlines.h +../src_3rd/genregex/regex.o: ../src_3rd/genregex/regex.c \ + ../src_3rd/genregex/regex.h +../src_3rd/genregex/regex_se.o: ../src_3rd/genregex/regex_se.c \ + ../src_3rd/genregex/regex_templ.c ../src_3rd/genregex/regex_templ.h \ + ../src_3rd/genregex/regex.h +../src_3rd/genregex/regex_sei.o: ../src_3rd/genregex/regex_sei.c \ + ../src_3rd/genregex/regex_templ.c ../src_3rd/genregex/regex_templ.h \ + ../src_3rd/genregex/regex.h +../src_3rd/genvector/gds_char.o: ../src_3rd/genvector/gds_char.c \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h \ + ../src_3rd/genvector/genvector_impl.c +../src_3rd/genvector/vti0.o: ../src_3rd/genvector/vti0.c \ + ../src_3rd/genvector/vti0.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h \ + ../src_3rd/genvector/genvector_impl.c +../src_3rd/genvector/vtl0.o: ../src_3rd/genvector/vtl0.c \ + ../src_3rd/genvector/vtl0.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h \ + ../src_3rd/genvector/genvector_impl.c +../src_3rd/genvector/vtp0.o: ../src_3rd/genvector/vtp0.c \ + ../src_3rd/genvector/vtp0.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h \ + ../src_3rd/genvector/genvector_impl.c +../src_3rd/genvector/vts0.o: ../src_3rd/genvector/vts0.c \ + ../src_3rd/genvector/vts0.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h \ + ../src_3rd/genvector/genvector_impl.c +../src_3rd/libfungw/fungw.o: ../src_3rd/libfungw/fungw.c \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/htpp.h ../src_3rd/genht/hash.h +../src_3rd/libfungw/fungw_call.o: ../src_3rd/libfungw/fungw_call.c \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/htpp.h +../src_3rd/libfungw/fungw_conv.o: ../src_3rd/libfungw/fungw_conv.c \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/htpp.h \ + ../src_3rd/libfungw/fungw_conv.h +../src_3rd/libfungw/fungw_debug.o: ../src_3rd/libfungw/fungw_debug.c \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/htpp.h +../src_3rd/libfungw/fungw_ptr.o: ../src_3rd/libfungw/fungw_ptr.c \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/htpp.h +../src_3rd/liblhtpers/lhtpers.o: ../src_3rd/liblhtpers/lhtpers.c \ + ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h \ + ../src_3rd/liblhtpers/lhtpers.h ../src_3rd/liblihata/dom.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/parser.h \ + ../src_3rd/liblhtpers/output.c ../src_3rd/liblhtpers/pers_list.c \ + ../src_3rd/liblhtpers/pers_hash.c ../src_3rd/liblhtpers/pers_text.c \ + ../src_3rd/liblhtpers/pers_table.c +../src_3rd/liblihata/dom.o: ../src_3rd/liblihata/dom.c \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/liblihata/dom_internal.h \ + ../src_3rd/liblihata/hash_str.h +../src_3rd/liblihata/dom_hash.o: ../src_3rd/liblihata/dom_hash.c \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/liblihata/dom_internal.h \ + ../src_3rd/liblihata/hash_str.h +../src_3rd/liblihata/dom_list.o: ../src_3rd/liblihata/dom_list.c \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/liblihata/dom_internal.h +../src_3rd/liblihata/dom_table.o: ../src_3rd/liblihata/dom_table.c \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/liblihata/dom_internal.h \ + ../src_3rd/liblihata/tree.h ../src_3rd/liblihata/dom.h +../src_3rd/liblihata/hash_str.o: ../src_3rd/liblihata/hash_str.c +../src_3rd/liblihata/lihata.o: ../src_3rd/liblihata/lihata.c \ + ../src_3rd/liblihata/lihata.h +../src_3rd/liblihata/parser.o: ../src_3rd/liblihata/parser.c \ + ../src_3rd/liblihata/parser.h ../src_3rd/liblihata/lihata.h +../src_3rd/liblihata/tree.o: ../src_3rd/liblihata/tree.c \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/liblihata/tree.h \ + ../src_3rd/liblihata/dom_internal.h +../src_3rd/liblihata/tree_hash.o: ../src_3rd/liblihata/tree_hash.c \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/liblihata/dom_internal.h \ + ../src_3rd/liblihata/tree.h ../src_3rd/liblihata/dom.h +../src_3rd/liblihata/tree_list.o: ../src_3rd/liblihata/tree_list.c \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/liblihata/dom_internal.h \ + ../src_3rd/liblihata/tree.h ../src_3rd/liblihata/dom.h +../src_3rd/liblihata/tree_path.o: ../src_3rd/liblihata/tree_path.c \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/liblihata/tree.h +../src_3rd/liblihata/tree_symlink.o: ../src_3rd/liblihata/tree_symlink.c \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/liblihata/tree.h +../src_3rd/liblihata/tree_table.o: ../src_3rd/liblihata/tree_table.c \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/liblihata/dom_internal.h \ + ../src_3rd/liblihata/tree.h ../src_3rd/liblihata/dom.h +../src_3rd/libuundo/uundo.o: ../src_3rd/libuundo/uundo.c \ + ../src_3rd/libuundo/uundo.h +../src_3rd/libuundo/uundo_debug.o: ../src_3rd/libuundo/uundo_debug.c \ + ../src_3rd/libuundo/uundo.h ../src_3rd/libuundo/uundo_debug.h +../src_3rd/qparse/qparse.o: ../src_3rd/qparse/qparse.c \ + ../src_3rd/qparse/qparse.h +actions.o: actions.c ../config.h conf_core.h conf.h global_typedefs.h \ + pcb_bool.h unit.h pcb-printf.h ../src_3rd/genvector/gds_char.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h globalconst.h color.h \ + ../src_3rd/libfungw/fungw_conv.h error.h event.h actions.h hid.h \ + attrib.h layer.h obj_common.h flag.h data_parent.h obj_arc_list.h \ + obj_arc.h ../src_3rd/genlist/gendlist.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h compat_misc.h \ + funchash.h +actions_pcb.o: actions_pcb.c ../config.h ../src_3rd/libfungw/fungw_conv.h \ + actions.h hid.h ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h error.h global_typedefs.h pcb_bool.h unit.h \ + attrib.h layer.h globalconst.h color.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h board.h vtroutestyle.h layer_grp.h rats_patch.h \ + data.h crosshair.h vtonpoint.h route.h buffer.h obj_rat_list.h obj_rat.h \ + idpath.h obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h \ + rtree.h ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h compat_misc.h pcb-printf.h conf_core.h conf.h \ + ../src_3rd/liblihata/lihata.h list_conf.h +attrib.o: attrib.c ../config.h compat_misc.h attrib.h +board.o: board.c ../config.h board.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h global_typedefs.h pcb_bool.h unit.h vtroutestyle.h \ + attrib.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h data.h crosshair.h vtonpoint.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h error.h route.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h conf_core.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h list_conf.h plug_io.h compat_misc.h \ + actions.h paths.h undo.h ../src_3rd/libuundo/uundo.h undo_old.h draw.h \ + event.h safe_fs.h tool.h netlist2.h defpcb_internal.c obj_pstk_inlines.h \ + thermal.h +box.o: box.c ../config.h rotate.h global_typedefs.h pcb_bool.h unit.h \ + compat_misc.h box.h math_helper.h obj_common.h flag.h globalconst.h \ + attrib.h data_parent.h misc_util.h +brave.o: brave.c ../config.h ../src_3rd/genvector/gds_char.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h brave.h actions.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h error.h global_typedefs.h pcb_bool.h unit.h \ + attrib.h layer.h globalconst.h color.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h conf_core.h conf.h \ + pcb-printf.h ../src_3rd/liblihata/lihata.h ../src_3rd/genvector/vtp0.h \ + list_conf.h conf_hid.h compat_misc.h hid_dad.h hid_attrib.h +buffer.o: buffer.c ../config.h conf_core.h conf.h global_typedefs.h \ + pcb_bool.h unit.h pcb-printf.h ../src_3rd/genvector/gds_char.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h globalconst.h color.h buffer.h \ + obj_common.h flag.h attrib.h data_parent.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h board.h vtroutestyle.h layer.h obj_arc_list.h \ + obj_arc.h ../src_3rd/genlist/gendlist.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h layer_grp.h \ + rats_patch.h move.h data.h crosshair.h vtonpoint.h hid.h error.h route.h \ + obj_rat_list.h obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h plug_io.h \ + rotate.h compat_misc.h remove.h select.h operation.h draw.h undo.h \ + ../src_3rd/libuundo/uundo.h undo_old.h funchash_core.h funchash.h \ + funchash_core_list.h obj_arc_op.h obj_line_op.h obj_text_op.h \ + obj_subc_op.h obj_poly_op.h obj_pstk_op.h obj_rat_op.h event.h safe_fs.h \ + actions.h +build_run.o: build_run.c ../config.h ../src_3rd/genvector/gds_char.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h conf_core.h conf.h \ + global_typedefs.h pcb_bool.h unit.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/dom.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/parser.h \ + ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h \ + ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h globalconst.h color.h board.h \ + vtroutestyle.h attrib.h layer.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h obj_line_list.h \ + obj_line.h obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h \ + obj_text.h font.h ../src_3rd/genht/htip.h box.h math_helper.h \ + misc_util.h layer_grp.h rats_patch.h build_run.h hid_init.h \ + ../src_3rd/puplug/puplug.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/os_dep.h ../src_3rd/puplug/config.h \ + ../src_3rd/puplug/libs.h hid.h error.h plug_io.h compat_misc.h +buildin.o: buildin.c ../src_3rd/puplug/libs.h ../src_3rd/puplug/puplug.h \ + ../src_3rd/puplug/os_dep.h ../src_3rd/puplug/config.h \ + ../src_3rd/puplug/libs.h +change.o: change.c ../config.h conf_core.h conf.h global_typedefs.h \ + pcb_bool.h unit.h pcb-printf.h ../src_3rd/genvector/gds_char.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h globalconst.h color.h change.h board.h \ + vtroutestyle.h attrib.h layer.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h obj_line_list.h \ + obj_line.h obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h \ + obj_text.h font.h ../src_3rd/genht/htip.h box.h math_helper.h \ + misc_util.h layer_grp.h rats_patch.h data.h crosshair.h vtonpoint.h \ + hid.h error.h route.h buffer.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h obj_rat_list.h obj_rat.h idpath.h \ + obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h draw.h select.h \ + operation.h undo.h ../src_3rd/libuundo/uundo.h undo_old.h actions.h \ + macro.h obj_pstk_op.h obj_subc_parent.h obj_term.h obj_arc_op.h \ + obj_line_op.h obj_poly_op.h obj_text_op.h obj_subc_op.h +change_act.o: change_act.c ../config.h conf_core.h conf.h \ + global_typedefs.h pcb_bool.h unit.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h globalconst.h color.h data.h layer.h \ + attrib.h obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h obj_line_list.h obj_line.h obj_poly_list.h \ + obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h crosshair.h \ + vtonpoint.h hid.h error.h route.h buffer.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h obj_rat_list.h obj_rat.h layer_grp.h idpath.h \ + obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h funchash_core.h \ + funchash.h funchash_core_list.h board.h vtroutestyle.h rats_patch.h \ + actions.h change.h draw.h search.h undo.h ../src_3rd/libuundo/uundo.h \ + undo_old.h event.h compat_misc.h obj_rat_draw.h data_it.h macro.h grid.h \ + route_style.h +color.o: color.c ../config.h color.h global_typedefs.h pcb_bool.h unit.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h \ + ../src_3rd/genvector/genvector_impl.c +compat_fs.o: compat_fs.c ../config.h compat_inc.h compat_fs.h \ + compat_misc.h globalconst.h safe_fs.h conf.h global_typedefs.h \ + pcb_bool.h unit.h pcb-printf.h ../src_3rd/genvector/gds_char.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h error.h +compat_lrealpath.o: compat_lrealpath.c compat_inc.h ../config.h \ + compat_lrealpath.h compat_misc.h +compat_misc.o: compat_misc.c compat_inc.h ../config.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h compat_misc.h +conf.o: conf.c ../src_3rd/genht/htsi.h ../src_3rd/genht/ht.h \ + ../src_3rd/genht/hash.h ../src_3rd/liblihata/tree.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h ../config.h conf.h \ + global_typedefs.h pcb_bool.h unit.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h conf_core.h globalconst.h color.h \ + conf_hid.h error.h hid_cfg.h hid.h attrib.h layer.h obj_common.h flag.h \ + data_parent.h obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h paths.h compat_fs.h compat_misc.h safe_fs.h \ + file_loaded.h ../src_3rd/genvector/genvector_impl.c conf_regfile.c +conf_act.o: conf_act.c ../config.h board.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h global_typedefs.h pcb_bool.h unit.h vtroutestyle.h \ + attrib.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h actions.h hid.h ../src_3rd/liblihata/dom.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/parser.h error.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h conf_core.h conf.h \ + pcb-printf.h ../src_3rd/liblihata/lihata.h ../src_3rd/genvector/vtp0.h \ + list_conf.h funchash_core.h funchash.h funchash_core_list.h \ + route_style.h tool.h macro.h +conf_core.o: conf_core.c ../config.h conf.h global_typedefs.h pcb_bool.h \ + unit.h pcb-printf.h ../src_3rd/genvector/gds_char.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h conf_core.h globalconst.h color.h \ + conf_core_fields.h +conf_hid.o: conf_hid.c ../config.h conf_hid.h conf.h global_typedefs.h \ + pcb_bool.h unit.h pcb-printf.h ../src_3rd/genvector/gds_char.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h error.h ../src_3rd/genht/hash.h \ + ../src_3rd/genht/htpp.h conf_core.h globalconst.h color.h +conf_internal.o: conf_internal.c +crosshair.o: crosshair.c ../config.h conf_core.h conf.h global_typedefs.h \ + pcb_bool.h unit.h pcb-printf.h ../src_3rd/genvector/gds_char.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h globalconst.h color.h board.h \ + vtroutestyle.h attrib.h layer.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h obj_line_list.h \ + obj_line.h obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h \ + obj_text.h font.h ../src_3rd/genht/htip.h box.h math_helper.h \ + misc_util.h layer_grp.h rats_patch.h crosshair.h vtonpoint.h hid.h \ + error.h route.h data.h buffer.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h obj_rat_list.h obj_rat.h idpath.h \ + obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h draw.h \ + draw_wireframe.h search.h actions.h hid_inlines.h compat_misc.h find.h \ + undo.h ../src_3rd/libuundo/uundo.h undo_old.h event.h macro.h grid.h \ + stub_stroke.h obj_line_draw.h obj_arc_draw.h obj_text_draw.h \ + obj_pstk_draw.h route_draw.h obj_arc_ui.h obj_subc_parent.h tool.h +data.o: data.c ../config.h board.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h global_typedefs.h pcb_bool.h unit.h vtroutestyle.h \ + attrib.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h data.h crosshair.h vtonpoint.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h error.h route.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h data_list.h data_it.h list_common.h compat_misc.h \ + layer_it.h operation.h obj_pstk_draw.h draw.h obj_text_draw.h \ + obj_poly_draw.h obj_arc_draw.h obj_line_draw.h conf_core.h conf.h \ + pcb-printf.h ../src_3rd/liblihata/lihata.h list_conf.h undo.h \ + ../src_3rd/libuundo/uundo.h undo_old.h +draw.o: draw.c ../config.h conf_core.h conf.h global_typedefs.h \ + pcb_bool.h unit.h pcb-printf.h ../src_3rd/genvector/gds_char.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h globalconst.h color.h math_helper.h \ + board.h vtroutestyle.h attrib.h layer.h obj_common.h flag.h \ + data_parent.h obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + misc_util.h layer_grp.h rats_patch.h data.h crosshair.h vtonpoint.h \ + hid.h error.h route.h buffer.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h obj_rat_list.h obj_rat.h idpath.h \ + obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h draw.h event.h \ + rotate.h compat_misc.h stub_draw.h layer_ui.h hid_inlines.h \ + layer_inlines.h funchash_core.h funchash.h funchash_core_list.h \ + obj_pstk_draw.h obj_line_draw.h obj_arc_draw.h obj_rat_draw.h \ + obj_poly_draw.h obj_text_draw.h obj_subc_parent.h draw_composite.c \ + draw_ly_spec.c +drc.o: drc.c ../config.h actions.h hid.h ../src_3rd/liblihata/dom.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/parser.h \ + ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h error.h global_typedefs.h \ + pcb_bool.h unit.h attrib.h layer.h globalconst.h color.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h drc.h view.h idpath.h conf_core.h conf.h \ + pcb-printf.h ../src_3rd/liblihata/lihata.h ../src_3rd/genvector/vtp0.h \ + list_conf.h compat_misc.h event.h +error.o: error.c ../config.h actions.h hid.h ../src_3rd/liblihata/dom.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/parser.h \ + ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h error.h global_typedefs.h \ + pcb_bool.h unit.h attrib.h layer.h globalconst.h color.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h data.h crosshair.h vtonpoint.h route.h buffer.h \ + obj_rat_list.h obj_rat.h layer_grp.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h event.h hid_dad.h compat_misc.h hid_attrib.h pcb-printf.h \ + safe_fs.h conf.h ../src_3rd/liblihata/lihata.h list_conf.h \ + funchash_core.h funchash.h funchash_core_list.h conf_core.h +event.o: event.c ../config.h event.h unit.h global_typedefs.h pcb_bool.h \ + error.h actions.h hid.h ../src_3rd/liblihata/dom.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/parser.h \ + ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h attrib.h layer.h \ + globalconst.h color.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h fptr_cast.h +file_act.o: file_act.c ../config.h board.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h global_typedefs.h pcb_bool.h unit.h vtroutestyle.h \ + attrib.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h build_run.h conf_core.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/dom.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/parser.h \ + ../src_3rd/genvector/vtp0.h list_conf.h funchash_core.h funchash.h \ + funchash_core_list.h data.h crosshair.h vtonpoint.h hid.h error.h \ + route.h buffer.h ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h \ + obj_rat_list.h obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h plug_io.h \ + plug_import.h remove.h draw.h find.h search.h actions.h compat_misc.h \ + hid_init.h ../src_3rd/puplug/puplug.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/os_dep.h ../src_3rd/puplug/config.h \ + ../src_3rd/puplug/libs.h layer_vis.h safe_fs.h tool.h netlist2.h +file_loaded.o: file_loaded.c ../config.h ../src_3rd/genht/hash.h \ + file_loaded.h ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h \ + compat_misc.h +find.o: find.c ../config.h find.h ../src_3rd/genvector/vtp0.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h global_typedefs.h pcb_bool.h \ + unit.h flag.h globalconst.h undo.h ../src_3rd/libuundo/uundo.h \ + undo_old.h obj_subc_parent.h data.h layer.h attrib.h color.h \ + obj_common.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h box.h math_helper.h misc_util.h \ + ../src_3rd/genvector/gds_char.h crosshair.h vtonpoint.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h error.h route.h \ + buffer.h ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h \ + obj_rat_list.h obj_rat.h layer_grp.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h find_geo.c \ + macro.h obj_arc_ui.h obj_pstk_inlines.h board.h vtroutestyle.h \ + rats_patch.h thermal.h search.h find_any_isect.c +flag.o: flag.c ../config.h flag.h globalconst.h operation.h \ + global_typedefs.h pcb_bool.h unit.h +flag_str.o: flag_str.c ../config.h flag_str.h flag.h globalconst.h \ + compat_misc.h obj_common.h attrib.h global_typedefs.h pcb_bool.h unit.h \ + data_parent.h macro.h +font.o: font.c ../config.h ../src_3rd/genht/hash.h font.h \ + ../src_3rd/genht/htip.h ../src_3rd/genht/ht.h global_typedefs.h \ + pcb_bool.h unit.h obj_poly.h ../src_3rd/genlist/gendlist.h obj_common.h \ + flag.h globalconst.h attrib.h data_parent.h polyarea.h obj_poly_list.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_arc.h obj_arc_list.h box.h \ + math_helper.h misc_util.h board.h ../src_3rd/genht/htsp.h vtroutestyle.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h color.h obj_line_list.h \ + obj_line.h obj_text_list.h obj_text.h ../src_3rd/genvector/gds_char.h \ + layer_grp.h rats_patch.h conf_core.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/dom.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/parser.h \ + ../src_3rd/genvector/vtp0.h list_conf.h error.h plug_io.h paths.h \ + compat_misc.h event.h file_loaded.h font_internal.c +font_act.o: font_act.c ../config.h board.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h global_typedefs.h pcb_bool.h unit.h vtroutestyle.h \ + attrib.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h actions.h hid.h ../src_3rd/liblihata/dom.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/parser.h error.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h conf_core.h conf.h \ + pcb-printf.h ../src_3rd/liblihata/lihata.h ../src_3rd/genvector/vtp0.h \ + list_conf.h plug_io.h event.h +fptr_cast.o: fptr_cast.c ../config.h fptr_cast.h +funchash.o: funchash.c ../src_3rd/genht/htpi.h ../src_3rd/genht/ht.h \ + ../src_3rd/genht/hash.h funchash_core.h funchash.h funchash_core_list.h \ + ../config.h macro.h compat_misc.h +grid.o: grid.c ../config.h ../src_3rd/genvector/gds_char.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h unit.h grid.h pcb_bool.h board.h \ + ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h global_typedefs.h \ + vtroutestyle.h attrib.h layer.h globalconst.h color.h obj_common.h \ + flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h layer_grp.h rats_patch.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/dom.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/parser.h \ + ../src_3rd/genvector/vtp0.h list_conf.h conf_core.h conf_hid.h error.h \ + compat_misc.h +gui_act.o: gui_act.c ../config.h board.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h global_typedefs.h pcb_bool.h unit.h vtroutestyle.h \ + attrib.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h build_run.h conf_core.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/dom.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/parser.h \ + ../src_3rd/genvector/vtp0.h list_conf.h data.h crosshair.h vtonpoint.h \ + hid.h error.h route.h buffer.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h obj_rat_list.h obj_rat.h idpath.h \ + obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h tool.h grid.h \ + undo.h ../src_3rd/libuundo/uundo.h undo_old.h funchash_core.h funchash.h \ + funchash_core_list.h change.h draw.h search.h find.h stub_stroke.h \ + actions.h hid_init.h ../src_3rd/puplug/puplug.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/os_dep.h ../src_3rd/puplug/config.h \ + ../src_3rd/puplug/libs.h compat_misc.h event.h layer_ui.h layer_vis.h \ + hid_attrib.h operation.h obj_subc_op.h route_style.h +heap.o: heap.c ../config.h heap.h +hid_attrib.o: hid_attrib.c ../config.h hid_attrib.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h error.h global_typedefs.h pcb_bool.h unit.h \ + attrib.h layer.h globalconst.h color.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h \ + ../src_3rd/genvector/gds_char.h compat_misc.h pcb-printf.h macro.h +hid_cam.o: hid_cam.c ../config.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h board.h global_typedefs.h \ + pcb_bool.h unit.h vtroutestyle.h attrib.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h data.h crosshair.h vtonpoint.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h error.h route.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h hid_cam.h hid_attrib.h compat_misc.h layer_vis.h \ + plug_io.h conf.h pcb-printf.h ../src_3rd/liblihata/lihata.h list_conf.h +hid_cfg.o: hid_cfg.c ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/tree.h ../src_3rd/liblihata/dom.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/parser.h \ + ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h ../config.h hid.h error.h \ + global_typedefs.h pcb_bool.h unit.h attrib.h layer.h globalconst.h \ + color.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h \ + ../src_3rd/genvector/gds_char.h hid_cfg.h paths.h safe_fs.h conf.h \ + pcb-printf.h ../src_3rd/genvector/vtp0.h list_conf.h compat_misc.h \ + file_loaded.h conf_core.h +hid_cfg_action.o: hid_cfg_action.c ../config.h hid_cfg_action.h hid_cfg.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h global_typedefs.h pcb_bool.h unit.h hid.h error.h \ + attrib.h layer.h globalconst.h color.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h \ + ../src_3rd/genvector/gds_char.h actions.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h +hid_cfg_input.o: hid_cfg_input.c ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/tree.h ../src_3rd/liblihata/dom.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/parser.h \ + ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../config.h hid_cfg_input.h \ + ../src_3rd/genht/htip.h ../src_3rd/genht/htpp.h hid_cfg.h \ + global_typedefs.h pcb_bool.h unit.h hid.h error.h attrib.h layer.h \ + globalconst.h color.h obj_common.h flag.h data_parent.h obj_arc_list.h \ + obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + box.h math_helper.h misc_util.h hid_cfg_action.h compat_misc.h event.h \ + crosshair.h vtonpoint.h route.h +hid_color.o: hid_color.c ../config.h hid_color.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h error.h global_typedefs.h pcb_bool.h unit.h \ + attrib.h layer.h globalconst.h color.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genht/hash.h compat_misc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/ht.c \ + ../src_3rd/genht/ht_inlines.h +hid_dad_spin.o: hid_dad_spin.c ../config.h hid_attrib.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h error.h global_typedefs.h pcb_bool.h unit.h \ + attrib.h layer.h globalconst.h color.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h \ + ../src_3rd/genvector/gds_char.h hid_dad.h compat_misc.h pcb-printf.h \ + hid_dad_spin.h conf_core.h conf.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/genvector/vtp0.h list_conf.h +hid_dad_tree.o: hid_dad_tree.c ../config.h hid_dad_tree.h hid_attrib.h \ + hid.h ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h error.h global_typedefs.h pcb_bool.h unit.h \ + attrib.h layer.h globalconst.h color.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h \ + ../src_3rd/genvector/gds_char.h hid_dad.h compat_misc.h pcb-printf.h \ + ../src_3rd/genht/hash.h +hid_dlg.o: hid_dlg.c ../config.h actions.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h error.h global_typedefs.h pcb_bool.h unit.h \ + attrib.h layer.h globalconst.h color.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h event.h hid_dad.h compat_misc.h hid_attrib.h \ + pcb-printf.h hid_nogui.h +hid_draw_helpers.o: hid_draw_helpers.c ../config.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h error.h global_typedefs.h pcb_bool.h unit.h \ + attrib.h layer.h globalconst.h color.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h \ + ../src_3rd/genvector/gds_char.h polygon.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h hid_inlines.h +hid_flags.o: hid_flags.c ../config.h data.h globalconst.h \ + global_typedefs.h pcb_bool.h unit.h layer.h attrib.h color.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h ../src_3rd/genht/ht.h box.h math_helper.h \ + misc_util.h ../src_3rd/genvector/gds_char.h crosshair.h vtonpoint.h \ + hid.h ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h error.h route.h \ + buffer.h ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h \ + obj_rat_list.h obj_rat.h layer_grp.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h board.h vtroutestyle.h rats_patch.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h list_conf.h hid_flags.h actions.h +hid_init.o: hid_init.c ../config.h hid.h ../src_3rd/liblihata/dom.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/parser.h \ + ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h error.h global_typedefs.h \ + pcb_bool.h unit.h attrib.h layer.h globalconst.h color.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h \ + ../src_3rd/genvector/gds_char.h hid_nogui.h event.h plugins.h \ + ../src_3rd/puplug/puplug.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/os_dep.h ../src_3rd/puplug/config.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/error.h actions.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h hid_attrib.h \ + hid_init.h conf_core.h conf.h pcb-printf.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/genvector/vtp0.h list_conf.h compat_misc.h compat_inc.h \ + file_loaded.h +hid_nogui.o: hid_nogui.c ../config.h actions.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h error.h global_typedefs.h pcb_bool.h unit.h \ + attrib.h layer.h globalconst.h color.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h compat_misc.h conf_core.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/genvector/vtp0.h list_conf.h +hidlib.o: hidlib.c ../config.h +ht_subc.o: ht_subc.c ../config.h obj_subc_list.h obj_subc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/libminuid/libminuid.h \ + ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h obj_common.h flag.h \ + globalconst.h attrib.h global_typedefs.h pcb_bool.h unit.h data_parent.h \ + layer.h color.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h \ + ../src_3rd/genvector/gds_char.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h ../src_3rd/genht/ht.c \ + ../src_3rd/genht/ht_inlines.h +idpath.o: idpath.c ../config.h idpath.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_common.h flag.h globalconst.h \ + attrib.h global_typedefs.h pcb_bool.h unit.h data_parent.h \ + ../src_3rd/genlist/gentdlist_impl.c data.h layer.h color.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_arc_list.h obj_arc.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h box.h math_helper.h misc_util.h \ + ../src_3rd/genvector/gds_char.h crosshair.h vtonpoint.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h error.h route.h \ + buffer.h ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h \ + obj_rat_list.h obj_rat.h layer_grp.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h +insert.o: insert.c ../config.h conf_core.h conf.h global_typedefs.h \ + pcb_bool.h unit.h pcb-printf.h ../src_3rd/genvector/gds_char.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h globalconst.h color.h board.h \ + vtroutestyle.h attrib.h layer.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h obj_line_list.h \ + obj_line.h obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h \ + obj_text.h font.h ../src_3rd/genht/htip.h box.h math_helper.h \ + misc_util.h layer_grp.h rats_patch.h data.h crosshair.h vtonpoint.h \ + hid.h error.h route.h buffer.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h obj_rat_list.h obj_rat.h idpath.h \ + obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h select.h \ + operation.h undo.h ../src_3rd/libuundo/uundo.h undo_old.h obj_line_op.h \ + obj_arc_op.h obj_rat_op.h obj_poly_op.h +intersect.o: intersect.c ../config.h intersect.h global_typedefs.h \ + pcb_bool.h unit.h box.h math_helper.h obj_common.h flag.h globalconst.h \ + attrib.h data_parent.h misc_util.h +layer.o: layer.c ../config.h board.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h global_typedefs.h pcb_bool.h unit.h vtroutestyle.h \ + attrib.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h data.h crosshair.h vtonpoint.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h error.h route.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h conf_core.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h list_conf.h compat_misc.h undo.h \ + ../src_3rd/libuundo/uundo.h undo_old.h event.h layer_ui.h layer_vis.h \ + funchash_core.h funchash.h funchash_core_list.h obj_pstk_inlines.h \ + thermal.h list_common.h +layer_grp.o: layer_grp.c ../config.h board.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h global_typedefs.h pcb_bool.h unit.h vtroutestyle.h \ + attrib.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h data.h crosshair.h vtonpoint.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h error.h route.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h compat_misc.h event.h funchash.h funchash_core.h \ + funchash_core_list.h +layer_ui.o: layer_ui.c ../config.h layer.h globalconst.h \ + global_typedefs.h pcb_bool.h unit.h attrib.h color.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h ../src_3rd/genht/ht.h box.h math_helper.h \ + misc_util.h ../src_3rd/genvector/gds_char.h event.h compat_misc.h \ + ../src_3rd/genvector/vtp0.h layer_ui.h +layer_vis.o: layer_vis.c ../config.h board.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h global_typedefs.h pcb_bool.h unit.h vtroutestyle.h \ + attrib.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h data.h crosshair.h vtonpoint.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h error.h route.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h conf_core.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h list_conf.h layer_ui.h layer_vis.h event.h \ + compat_misc.h conf_hid.h +list_conf.o: list_conf.c conf.h ../config.h global_typedefs.h pcb_bool.h \ + unit.h pcb-printf.h ../src_3rd/genvector/gds_char.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.c +main.o: main.c ../config.h ../src_3rd/libminuid/libminuid.h board.h \ + ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h global_typedefs.h \ + pcb_bool.h unit.h vtroutestyle.h attrib.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h brave.h data.h crosshair.h vtonpoint.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h error.h route.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h idpath.h obj_subc_list.h obj_subc.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h plug_io.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h list_conf.h compat_lrealpath.h buildin.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/puplug.h \ + ../src_3rd/puplug/os_dep.h ../src_3rd/puplug/config.h \ + ../src_3rd/puplug/libs.h build_run.h file_loaded.h flag_str.h plugins.h \ + ../src_3rd/puplug/error.h plug_footprint.h vtlibrary.h plug_import.h \ + event.h funchash.h conf_core.h layer_vis.h layer_ui.h pcb_minuid.h \ + tool.h netlist2.h actions.h actions_pcb.h hid_init.h compat_misc.h \ + dolists.h generated_lists.h +main_act.o: main_act.c ../config.h undo.h ../src_3rd/libuundo/uundo.h \ + undo_old.h global_typedefs.h pcb_bool.h unit.h change.h board.h \ + ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h vtroutestyle.h attrib.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h data.h crosshair.h vtonpoint.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h error.h route.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h compat_misc.h actions.h hid_init.h \ + ../src_3rd/puplug/puplug.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/os_dep.h ../src_3rd/puplug/config.h \ + ../src_3rd/puplug/libs.h conf_core.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h list_conf.h plugins.h \ + ../src_3rd/puplug/error.h build_run.h file_loaded.h safe_fs.h flag_str.h +misc_util.o: misc_util.c ../config.h ../src_3rd/genvector/gds_char.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h misc_util.h unit.h pcb_bool.h +move.o: move.c ../config.h conf_core.h conf.h global_typedefs.h \ + pcb_bool.h unit.h pcb-printf.h ../src_3rd/genvector/gds_char.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h globalconst.h color.h board.h \ + vtroutestyle.h attrib.h layer.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h obj_line_list.h \ + obj_line.h obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h \ + obj_text.h font.h ../src_3rd/genht/htip.h box.h math_helper.h \ + misc_util.h layer_grp.h rats_patch.h data.h crosshair.h vtonpoint.h \ + hid.h error.h route.h buffer.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h obj_rat_list.h obj_rat.h idpath.h \ + obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h draw.h move.h \ + select.h operation.h undo.h ../src_3rd/libuundo/uundo.h undo_old.h \ + event.h actions.h compat_misc.h obj_arc_op.h obj_line_op.h obj_text_op.h \ + obj_subc_op.h obj_poly_op.h obj_pstk_op.h obj_rat_op.h +netlist2.o: netlist2.c ../config.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h \ + ../src_3rd/genregex/regex_sei.h ../src_3rd/genregex/regex_templ.h \ + ../src_3rd/genregex/regex.h board.h global_typedefs.h pcb_bool.h unit.h \ + vtroutestyle.h attrib.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h data.h crosshair.h vtonpoint.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h error.h route.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h data_it.h event.h compat_misc.h find.h obj_term.h \ + conf_core.h conf.h pcb-printf.h ../src_3rd/liblihata/lihata.h \ + list_conf.h undo.h ../src_3rd/libuundo/uundo.h undo_old.h obj_rat_draw.h \ + obj_subc_parent.h search.h remove.h draw.h netlist2.h \ + ../src_3rd/genlist/gentdlist_impl.c netlist_geo.c obj_pstk_inlines.h \ + thermal.h +netlist_act.o: netlist_act.c ../config.h ../src_3rd/genregex/regex_sei.h \ + ../src_3rd/genregex/regex_templ.h ../src_3rd/genregex/regex.h \ + funchash_core.h funchash.h funchash_core_list.h data.h globalconst.h \ + global_typedefs.h pcb_bool.h unit.h layer.h attrib.h color.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h ../src_3rd/genht/ht.h box.h math_helper.h \ + misc_util.h ../src_3rd/genvector/gds_char.h crosshair.h vtonpoint.h \ + hid.h ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h error.h route.h \ + buffer.h ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h \ + obj_rat_list.h obj_rat.h layer_grp.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h data_it.h board.h vtroutestyle.h rats_patch.h plug_io.h \ + conf.h pcb-printf.h ../src_3rd/liblihata/lihata.h list_conf.h actions.h \ + compat_misc.h netlist2.h find.h obj_term.h search.h obj_subc_parent.h +obj_arc.o: obj_arc.c ../config.h board.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h global_typedefs.h pcb_bool.h unit.h vtroutestyle.h \ + attrib.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h data.h crosshair.h vtonpoint.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h error.h route.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h undo.h ../src_3rd/libuundo/uundo.h undo_old.h rotate.h \ + compat_misc.h move.h conf_core.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h list_conf.h draw_wireframe.h hid_inlines.h \ + obj_arc_op.h operation.h obj_subc_parent.h obj_hash.h draw.h \ + obj_arc_draw.h +obj_arc_list.o: obj_arc_list.c obj_arc_list.h obj_common.h flag.h \ + globalconst.h ../config.h attrib.h global_typedefs.h pcb_bool.h unit.h \ + data_parent.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.c +obj_arc_ui.o: obj_arc_ui.c ../config.h obj_arc_ui.h crosshair.h \ + vtonpoint.h global_typedefs.h pcb_bool.h unit.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h hid.h ../src_3rd/liblihata/dom.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/parser.h \ + ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h error.h attrib.h layer.h \ + globalconst.h color.h obj_common.h flag.h data_parent.h obj_arc_list.h \ + obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h \ + ../src_3rd/genvector/gds_char.h route.h +obj_common.o: obj_common.c ../config.h conf_core.h conf.h \ + global_typedefs.h pcb_bool.h unit.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h globalconst.h color.h flag_str.h flag.h \ + error.h obj_common.h attrib.h data_parent.h obj_arc_ui.h crosshair.h \ + vtonpoint.h hid.h layer.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h obj_line_list.h obj_line.h obj_poly_list.h \ + obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h route.h \ + obj_pstk.h obj_pstk_shape.h polygon.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h vtpadstack_t.h +obj_line.o: obj_line.c ../config.h undo.h ../src_3rd/libuundo/uundo.h \ + undo_old.h global_typedefs.h pcb_bool.h unit.h board.h \ + ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h vtroutestyle.h attrib.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h data.h crosshair.h vtonpoint.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h error.h route.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h move.h search.h conf_core.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h list_conf.h compat_misc.h rotate.h \ + hid_inlines.h obj_line_op.h operation.h obj_subc_parent.h obj_hash.h \ + draw.h draw_wireframe.h obj_line_draw.h obj_rat_draw.h obj_pstk_draw.h \ + ../src_plugins/lib_compat_help/pstk_compat.h obj_pstk.h +obj_line_drcenf.o: obj_line_drcenf.c ../config.h conf_core.h conf.h \ + global_typedefs.h pcb_bool.h unit.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h globalconst.h color.h math_helper.h \ + board.h vtroutestyle.h attrib.h layer.h obj_common.h flag.h \ + data_parent.h obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + misc_util.h layer_grp.h rats_patch.h data.h crosshair.h vtonpoint.h \ + hid.h error.h route.h buffer.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h obj_rat_list.h obj_rat.h idpath.h \ + obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h find.h macro.h +obj_line_list.o: obj_line_list.c obj_line_list.h obj_line.h \ + ../src_3rd/genlist/gendlist.h obj_common.h flag.h globalconst.h \ + ../config.h attrib.h global_typedefs.h pcb_bool.h unit.h data_parent.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.c +obj_pinvia_therm.o: obj_pinvia_therm.c ../config.h board.h \ + ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h global_typedefs.h \ + pcb_bool.h unit.h vtroutestyle.h attrib.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h polygon.h rtree.h ../src_3rd/genrtree/genrtree_api.h \ + rtree2_compat.h obj_pinvia_therm.h +obj_poly.o: obj_poly.c ../config.h board.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h global_typedefs.h pcb_bool.h unit.h vtroutestyle.h \ + attrib.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h data.h crosshair.h vtonpoint.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h error.h route.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h undo.h ../src_3rd/libuundo/uundo.h undo_old.h \ + polygon_offs.h rotate.h compat_misc.h search.h hid_inlines.h conf_core.h \ + conf.h pcb-printf.h ../src_3rd/liblihata/lihata.h list_conf.h \ + obj_poly_op.h operation.h obj_poly_draw.h draw.h obj_subc_parent.h \ + obj_hash.h +obj_poly_list.o: obj_poly_list.c obj_poly_list.h obj_poly.h ../config.h \ + ../src_3rd/genlist/gendlist.h obj_common.h flag.h globalconst.h attrib.h \ + global_typedefs.h pcb_bool.h unit.h data_parent.h polyarea.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.c +obj_pstk.o: obj_pstk.c ../config.h board.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h global_typedefs.h pcb_bool.h unit.h vtroutestyle.h \ + attrib.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h conf_core.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/dom.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/parser.h \ + ../src_3rd/genvector/vtp0.h list_conf.h data.h crosshair.h vtonpoint.h \ + hid.h error.h route.h buffer.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h obj_rat_list.h obj_rat.h idpath.h \ + obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h data_list.h \ + draw.h draw_wireframe.h obj_pstk_draw.h obj_pstk_inlines.h thermal.h \ + obj_pstk_op.h operation.h obj_subc_parent.h obj_hash.h compat_misc.h \ + search.h undo.h ../src_3rd/libuundo/uundo.h undo_old.h event.h \ + hid_inlines.h polygon_offs.h obj_pstk_op.c rotate.h +obj_pstk_act.o: obj_pstk_act.c ../config.h obj_pstk.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genvector/vtp0.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_common.h flag.h globalconst.h \ + attrib.h global_typedefs.h pcb_bool.h unit.h data_parent.h layer.h \ + color.h obj_arc_list.h obj_arc.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h box.h math_helper.h misc_util.h \ + ../src_3rd/genvector/gds_char.h obj_pstk_shape.h polygon.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h vtpadstack_t.h \ + obj_pstk_inlines.h board.h ../src_3rd/genht/htsp.h vtroutestyle.h \ + layer_grp.h rats_patch.h data.h crosshair.h vtonpoint.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h error.h route.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h ht_subc.h ../src_3rd/genht/ht.h \ + ../src_3rd/genht/hash.h obj_pstk_list.h vtpadstack.h thermal.h \ + funchash_core.h funchash.h funchash_core_list.h conf_core.h conf.h \ + pcb-printf.h ../src_3rd/liblihata/lihata.h list_conf.h actions.h \ + search.h data_list.h +obj_pstk_list.o: obj_pstk_list.c obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genvector/vtp0.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_common.h flag.h globalconst.h \ + ../config.h attrib.h global_typedefs.h pcb_bool.h unit.h data_parent.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.c +obj_pstk_proto.o: obj_pstk_proto.c ../config.h board.h \ + ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h global_typedefs.h \ + pcb_bool.h unit.h vtroutestyle.h attrib.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h buffer.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h compat_misc.h conf_core.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/dom.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/parser.h \ + ../src_3rd/genvector/vtp0.h list_conf.h data.h crosshair.h vtonpoint.h \ + hid.h error.h route.h obj_rat_list.h obj_rat.h idpath.h obj_subc_list.h \ + obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h data_list.h \ + obj_pstk_inlines.h thermal.h rotate.h undo.h ../src_3rd/libuundo/uundo.h \ + undo_old.h obj_hash.h funchash_core.h funchash.h funchash_core_list.h \ + polygon_offs.h +obj_rat.o: obj_rat.c ../config.h board.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h global_typedefs.h pcb_bool.h unit.h vtroutestyle.h \ + attrib.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h data.h crosshair.h vtonpoint.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h error.h route.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h data_it.h conf_core.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h list_conf.h hid_inlines.h undo.h \ + ../src_3rd/libuundo/uundo.h undo_old.h search.h obj_line_draw.h draw.h \ + obj_rat_op.h operation.h obj_rat_draw.h +obj_rat_list.o: obj_rat_list.c ../config.h layer_grp.h layer.h \ + globalconst.h global_typedefs.h pcb_bool.h unit.h attrib.h color.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h ../src_3rd/genht/ht.h box.h math_helper.h \ + misc_util.h ../src_3rd/genvector/gds_char.h obj_rat.h idpath.h \ + obj_rat_list.h ../src_3rd/genlist/gentdlist_impl.c +obj_subc.o: obj_subc.c ../config.h ../src_3rd/genvector/vtp0.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h buffer.h obj_common.h flag.h \ + globalconst.h attrib.h global_typedefs.h pcb_bool.h unit.h data_parent.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/htpp.h board.h vtroutestyle.h \ + layer.h color.h obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h \ + ../src_3rd/genvector/gds_char.h layer_grp.h rats_patch.h crosshair.h \ + vtonpoint.h hid.h ../src_3rd/liblihata/dom.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/parser.h error.h \ + route.h brave.h data.h obj_rat_list.h obj_rat.h idpath.h obj_subc_list.h \ + obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h obj_subc_op.h \ + operation.h obj_subc_parent.h obj_poly_op.h obj_pstk_inlines.h thermal.h \ + obj_pstk_draw.h draw.h obj_line_op.h obj_term.h obj_text_draw.h \ + draw_wireframe.h undo.h ../src_3rd/libuundo/uundo.h undo_old.h macro.h \ + compat_misc.h pcb_minuid.h conf_core.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h list_conf.h +obj_subc_hash.o: obj_subc_hash.c ../config.h data.h globalconst.h \ + global_typedefs.h pcb_bool.h unit.h layer.h attrib.h color.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h ../src_3rd/genht/ht.h box.h math_helper.h \ + misc_util.h ../src_3rd/genvector/gds_char.h crosshair.h vtonpoint.h \ + hid.h ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h error.h route.h \ + buffer.h ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h \ + obj_rat_list.h obj_rat.h layer_grp.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h +obj_subc_list.o: obj_subc_list.c ../config.h obj_subc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/libminuid/libminuid.h \ + ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h obj_common.h flag.h \ + globalconst.h attrib.h global_typedefs.h pcb_bool.h unit.h data_parent.h \ + layer.h color.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h \ + ../src_3rd/genvector/gds_char.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h obj_subc_list.h \ + ht_subc.h ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gentdlist_impl.c +obj_term.o: obj_term.c ../config.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h change.h board.h \ + global_typedefs.h pcb_bool.h unit.h vtroutestyle.h attrib.h layer.h \ + globalconst.h color.h obj_common.h flag.h data_parent.h obj_arc_list.h \ + obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h \ + ../src_3rd/genvector/gds_char.h layer_grp.h rats_patch.h compat_misc.h \ + obj_term.h obj_subc_parent.h data.h crosshair.h vtonpoint.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h error.h route.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h pcb-printf.h \ + undo.h ../src_3rd/libuundo/uundo.h undo_old.h macro.h +obj_text.o: obj_text.c ../config.h rotate.h global_typedefs.h pcb_bool.h \ + unit.h compat_misc.h board.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h vtroutestyle.h attrib.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h data.h crosshair.h vtonpoint.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h error.h route.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h hid_inlines.h undo.h ../src_3rd/libuundo/uundo.h \ + undo_old.h polygon_offs.h event.h obj_text_op.h operation.h \ + obj_poly_draw.h draw.h obj_arc_draw.h obj_subc_parent.h obj_hash.h \ + obj_line_draw.h obj_text_draw.h conf_core.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h list_conf.h +obj_text_list.o: obj_text_list.c obj_poly_list.h obj_poly.h ../config.h \ + ../src_3rd/genlist/gendlist.h obj_common.h flag.h globalconst.h attrib.h \ + global_typedefs.h pcb_bool.h unit.h data_parent.h polyarea.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_arc_list.h obj_arc.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h box.h math_helper.h misc_util.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h \ + ../src_3rd/genlist/gentdlist_impl.c +object_act.o: object_act.c ../config.h conf_core.h conf.h \ + global_typedefs.h pcb_bool.h unit.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h globalconst.h color.h data.h layer.h \ + attrib.h obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h obj_line_list.h obj_line.h obj_poly_list.h \ + obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h crosshair.h \ + vtonpoint.h hid.h error.h route.h buffer.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h obj_rat_list.h obj_rat.h layer_grp.h idpath.h \ + obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h board.h \ + vtroutestyle.h rats_patch.h tool.h change.h undo.h \ + ../src_3rd/libuundo/uundo.h undo_old.h event.h funchash_core.h \ + funchash.h funchash_core_list.h search.h draw.h move.h remove.h \ + compat_misc.h layer_vis.h operation.h macro.h rotate.h actions.h +operation.o: operation.c ../config.h operation.h global_typedefs.h \ + pcb_bool.h unit.h board.h ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h \ + vtroutestyle.h attrib.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h data.h crosshair.h vtonpoint.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h error.h route.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h conf_core.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h list_conf.h undo.h \ + ../src_3rd/libuundo/uundo.h undo_old.h brave.h +paths.o: paths.c ../config.h paths.h ../src_3rd/genvector/gds_char.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h error.h conf_core.h conf.h \ + global_typedefs.h pcb_bool.h unit.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/dom.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/parser.h \ + ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h \ + ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h globalconst.h color.h +pcb-printf.o: pcb-printf.c ../config.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h unit.h +pcb_bool.o: pcb_bool.c ../config.h pcb_bool.h compat_misc.h +pcb_menu_default.o: pcb_menu_default.c +pcb_minuid.o: pcb_minuid.c ../src_3rd/libminuid/libminuid.h compat_misc.h \ + ../config.h pcb_minuid.h +plug_footprint.o: plug_footprint.c ../config.h plug_footprint.h \ + vtlibrary.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h data.h globalconst.h \ + global_typedefs.h pcb_bool.h unit.h layer.h attrib.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h box.h math_helper.h misc_util.h \ + ../src_3rd/genvector/gds_char.h crosshair.h vtonpoint.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h error.h route.h \ + buffer.h ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h \ + obj_rat_list.h obj_rat.h layer_grp.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h plugins.h ../src_3rd/puplug/puplug.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/os_dep.h \ + ../src_3rd/puplug/config.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/error.h conf_core.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h list_conf.h compat_misc.h event.h +plug_footprint_act.o: plug_footprint_act.c ../config.h actions.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h error.h global_typedefs.h pcb_bool.h unit.h \ + attrib.h layer.h globalconst.h color.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h plug_footprint.h vtlibrary.h data.h crosshair.h \ + vtonpoint.h route.h buffer.h obj_rat_list.h obj_rat.h layer_grp.h \ + idpath.h obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h \ + rtree.h ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h +plug_import.o: plug_import.c ../config.h conf_core.h conf.h \ + global_typedefs.h pcb_bool.h unit.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h globalconst.h color.h plugins.h \ + ../src_3rd/puplug/puplug.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/os_dep.h ../src_3rd/puplug/config.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/error.h plug_import.h error.h \ + safe_fs.h +plug_io.o: plug_io.c ../config.h conf_core.h conf.h global_typedefs.h \ + pcb_bool.h unit.h pcb-printf.h ../src_3rd/genvector/gds_char.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h globalconst.h color.h change.h board.h \ + vtroutestyle.h attrib.h layer.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h obj_line_list.h \ + obj_line.h obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h \ + obj_text.h font.h ../src_3rd/genht/htip.h box.h math_helper.h \ + misc_util.h layer_grp.h rats_patch.h data.h crosshair.h vtonpoint.h \ + hid.h error.h route.h buffer.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h obj_rat_list.h obj_rat.h idpath.h \ + obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h plug_io.h \ + remove.h paths.h actions.h plugins.h ../src_3rd/puplug/puplug.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/os_dep.h \ + ../src_3rd/puplug/config.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/error.h event.h compat_misc.h route_style.h \ + compat_fs.h compat_lrealpath.h layer_vis.h safe_fs.h plug_footprint.h \ + vtlibrary.h file_loaded.h macro.h view.h compat_inc.h +plugins.o: plugins.c plugins.h ../src_3rd/puplug/puplug.h \ + ../src_3rd/puplug/libs.h ../src_3rd/puplug/os_dep.h \ + ../src_3rd/puplug/config.h ../src_3rd/puplug/libs.h \ + ../src_3rd/puplug/error.h ../config.h ../src_3rd/genvector/gds_char.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h compat_misc.h actions.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h error.h global_typedefs.h pcb_bool.h unit.h \ + attrib.h layer.h globalconst.h color.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h +polygon.o: polygon.c ../config.h conf_core.h conf.h global_typedefs.h \ + pcb_bool.h unit.h pcb-printf.h ../src_3rd/genvector/gds_char.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h globalconst.h color.h board.h \ + vtroutestyle.h attrib.h layer.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h obj_line_list.h \ + obj_line.h obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h \ + obj_text.h font.h ../src_3rd/genht/htip.h box.h math_helper.h \ + misc_util.h layer_grp.h rats_patch.h data.h crosshair.h vtonpoint.h \ + hid.h error.h route.h buffer.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h obj_rat_list.h obj_rat.h idpath.h \ + obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h draw.h remove.h \ + search.h thermal.h undo.h ../src_3rd/libuundo/uundo.h undo_old.h \ + obj_poly_draw.h polygon_selfi.h event.h polygon_offs.c compat_misc.h \ + polygon_offs.h +polygon1.o: polygon1.c ../config.h rtree.h global_typedefs.h pcb_bool.h \ + unit.h ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h math_helper.h \ + heap.h compat_cc.h pcb-printf.h ../src_3rd/genvector/gds_char.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h polyarea.h obj_common.h flag.h \ + globalconst.h attrib.h data_parent.h macro.h box.h misc_util.h \ + polygon_selfi.c polygon_selfi.h ../src_3rd/genvector/vtp0.h +polygon_act.o: polygon_act.c ../config.h conf_core.h conf.h \ + global_typedefs.h pcb_bool.h unit.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h globalconst.h color.h board.h \ + vtroutestyle.h attrib.h layer.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h obj_line_list.h \ + obj_line.h obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h \ + obj_text.h font.h ../src_3rd/genht/htip.h box.h math_helper.h \ + misc_util.h layer_grp.h rats_patch.h data.h crosshair.h vtonpoint.h \ + hid.h error.h route.h buffer.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h obj_rat_list.h obj_rat.h idpath.h \ + obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h undo.h \ + ../src_3rd/libuundo/uundo.h undo_old.h funchash_core.h funchash.h \ + funchash_core_list.h draw.h search.h tool.h actions.h +rats_act.o: rats_act.c ../config.h conf_core.h conf.h global_typedefs.h \ + pcb_bool.h unit.h pcb-printf.h ../src_3rd/genvector/gds_char.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h globalconst.h color.h board.h \ + vtroutestyle.h attrib.h layer.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h obj_line_list.h \ + obj_line.h obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h \ + obj_text.h font.h ../src_3rd/genht/htip.h box.h math_helper.h \ + misc_util.h layer_grp.h rats_patch.h data.h crosshair.h vtonpoint.h \ + hid.h error.h route.h buffer.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h obj_rat_list.h obj_rat.h idpath.h \ + obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h undo.h \ + ../src_3rd/libuundo/uundo.h undo_old.h find.h remove.h funchash_core.h \ + funchash.h funchash_core_list.h actions.h netlist2.h draw.h \ + obj_rat_draw.h +rats_patch.o: rats_patch.c rats_patch.h board.h ../config.h \ + ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h global_typedefs.h \ + pcb_bool.h unit.h vtroutestyle.h attrib.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + ../src_3rd/genht/hash.h actions.h hid.h ../src_3rd/liblihata/dom.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/parser.h error.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h data.h crosshair.h \ + vtonpoint.h route.h buffer.h obj_rat_list.h obj_rat.h idpath.h \ + obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h move.h compat_misc.h safe_fs.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h list_conf.h funchash_core.h funchash.h \ + funchash_core_list.h search.h undo.h ../src_3rd/libuundo/uundo.h \ + undo_old.h conf_core.h netlist2.h +remove.o: remove.c ../config.h conf_core.h conf.h global_typedefs.h \ + pcb_bool.h unit.h pcb-printf.h ../src_3rd/genvector/gds_char.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h globalconst.h color.h board.h \ + vtroutestyle.h attrib.h layer.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h obj_line_list.h \ + obj_line.h obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h \ + obj_text.h font.h ../src_3rd/genht/htip.h box.h math_helper.h \ + misc_util.h layer_grp.h rats_patch.h draw.h hid.h error.h remove.h \ + select.h operation.h undo.h ../src_3rd/libuundo/uundo.h undo_old.h \ + obj_arc_op.h obj_line_op.h obj_poly_op.h obj_text_op.h obj_rat_op.h \ + obj_subc_op.h obj_pstk_op.h +remove_act.o: remove_act.c ../config.h data.h globalconst.h \ + global_typedefs.h pcb_bool.h unit.h layer.h attrib.h color.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h ../src_3rd/genht/ht.h box.h math_helper.h \ + misc_util.h ../src_3rd/genvector/gds_char.h crosshair.h vtonpoint.h \ + hid.h ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h error.h route.h \ + buffer.h ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h \ + obj_rat_list.h obj_rat.h layer_grp.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h actions.h tool.h remove.h board.h vtroutestyle.h \ + rats_patch.h funchash_core.h funchash.h funchash_core_list.h +rotate.o: rotate.c ../config.h board.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h global_typedefs.h pcb_bool.h unit.h vtroutestyle.h \ + attrib.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h data.h crosshair.h vtonpoint.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h error.h route.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h draw.h rotate.h compat_misc.h search.h select.h \ + operation.h undo.h ../src_3rd/libuundo/uundo.h undo_old.h event.h \ + conf_core.h conf.h pcb-printf.h ../src_3rd/liblihata/lihata.h \ + list_conf.h obj_arc_op.h obj_line_op.h obj_poly_op.h obj_text_op.h \ + obj_subc_op.h obj_pstk_op.h obj_line_draw.h obj_rat_draw.h +route.o: route.c ../config.h compat_misc.h conf_core.h conf.h \ + global_typedefs.h pcb_bool.h unit.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h globalconst.h color.h math_helper.h \ + board.h vtroutestyle.h attrib.h layer.h obj_common.h flag.h \ + data_parent.h obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + misc_util.h layer_grp.h rats_patch.h data.h crosshair.h vtonpoint.h \ + hid.h error.h route.h buffer.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h obj_rat_list.h obj_rat.h idpath.h \ + obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h find.h undo.h \ + ../src_3rd/libuundo/uundo.h undo_old.h obj_line_draw.h draw.h \ + obj_arc_draw.h route_draw.h obj_line_op.h operation.h draw_wireframe.h +route_style.o: route_style.c ../config.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h unit.h route_style.h \ + vtroutestyle.h attrib.h global_typedefs.h pcb_bool.h error.h conf.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/dom.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/parser.h \ + ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h \ + ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h misc_util.h board.h layer.h globalconst.h \ + color.h obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h obj_line_list.h obj_line.h obj_poly_list.h \ + obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h layer_grp.h rats_patch.h \ + funchash_core.h funchash.h funchash_core_list.h conf_core.h +rtree.o: rtree.c ../config.h unit.h rtree.h global_typedefs.h pcb_bool.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h \ + ../src_3rd/genrtree/genrtree_impl.h \ + ../src_3rd/genrtree/genrtree_search.h \ + ../src_3rd/genrtree/genrtree_delete.h \ + ../src_3rd/genrtree/genrtree_debug.h +safe_fs.o: safe_fs.c compat_inc.h ../config.h safe_fs.h conf.h \ + global_typedefs.h pcb_bool.h unit.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h compat_fs.h compat_misc.h error.h \ + globalconst.h paths.h +search.o: search.c ../config.h conf_core.h conf.h global_typedefs.h \ + pcb_bool.h unit.h pcb-printf.h ../src_3rd/genvector/gds_char.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h globalconst.h color.h board.h \ + vtroutestyle.h attrib.h layer.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h obj_line_list.h \ + obj_line.h obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h \ + obj_text.h font.h ../src_3rd/genht/htip.h box.h math_helper.h \ + misc_util.h layer_grp.h rats_patch.h data.h crosshair.h vtonpoint.h \ + hid.h error.h route.h buffer.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h obj_rat_list.h obj_rat.h idpath.h \ + obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h find.h search.h \ + obj_subc_parent.h obj_pstk_inlines.h thermal.h +select.o: select.c ../config.h conf_core.h conf.h global_typedefs.h \ + pcb_bool.h unit.h pcb-printf.h ../src_3rd/genvector/gds_char.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h globalconst.h color.h board.h \ + vtroutestyle.h attrib.h layer.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h obj_line_list.h \ + obj_line.h obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h \ + obj_text.h font.h ../src_3rd/genht/htip.h box.h math_helper.h \ + misc_util.h layer_grp.h rats_patch.h data.h crosshair.h vtonpoint.h \ + hid.h error.h route.h buffer.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h obj_rat_list.h obj_rat.h idpath.h \ + obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h data_it.h draw.h \ + search.h select.h operation.h undo.h ../src_3rd/libuundo/uundo.h \ + undo_old.h find.h compat_misc.h obj_arc_draw.h obj_line_draw.h \ + obj_poly_draw.h obj_text_draw.h obj_rat_draw.h obj_pstk_draw.h \ + ../src_3rd/genregex/regex_sei.h ../src_3rd/genregex/regex_templ.h \ + ../src_3rd/genregex/regex.h +select_act.o: select_act.c ../config.h conf_core.h conf.h \ + global_typedefs.h pcb_bool.h unit.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h globalconst.h color.h board.h \ + vtroutestyle.h attrib.h layer.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h obj_line_list.h \ + obj_line.h obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h \ + obj_text.h font.h ../src_3rd/genht/htip.h box.h math_helper.h \ + misc_util.h layer_grp.h rats_patch.h data.h crosshair.h vtonpoint.h \ + hid.h error.h route.h buffer.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h obj_rat_list.h obj_rat.h idpath.h \ + obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h undo.h \ + ../src_3rd/libuundo/uundo.h undo_old.h funchash_core.h funchash.h \ + funchash_core_list.h tool.h select.h operation.h draw.h remove.h move.h \ + grid.h hid_attrib.h compat_misc.h actions.h +stub_draw.o: stub_draw.c ../config.h stub_draw.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h error.h global_typedefs.h pcb_bool.h unit.h \ + attrib.h layer.h globalconst.h color.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h box.h math_helper.h misc_util.h \ + ../src_3rd/genvector/gds_char.h draw.h obj_text_draw.h +stub_stroke.o: stub_stroke.c error.h ../config.h pcb_bool.h +thermal.o: thermal.c ../config.h thermal.h obj_common.h flag.h \ + globalconst.h attrib.h global_typedefs.h pcb_bool.h unit.h data_parent.h \ + layer.h color.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h box.h math_helper.h misc_util.h \ + ../src_3rd/genvector/gds_char.h compat_misc.h data.h crosshair.h \ + vtonpoint.h hid.h ../src_3rd/liblihata/dom.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/parser.h \ + ../src_3rd/genht/htsp.h error.h route.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h layer_grp.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h obj_pstk_inlines.h board.h vtroutestyle.h rats_patch.h \ + obj_pinvia_therm.h +tool.o: tool.c ../config.h tool.h ../src_3rd/genvector/vtp0.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h global_typedefs.h pcb_bool.h \ + unit.h board.h ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h \ + vtroutestyle.h attrib.h layer.h globalconst.h color.h obj_common.h \ + flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h conf_core.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/dom.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/parser.h list_conf.h \ + crosshair.h vtonpoint.h hid.h error.h route.h data.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h draw.h event.h \ + find.h grid.h undo.h ../src_3rd/libuundo/uundo.h undo_old.h actions.h \ + tool_arc.h tool_arrow.h tool_buffer.h tool_copy.h tool_insert.h \ + tool_line.h tool_lock.h tool_move.h tool_poly.h tool_polyhole.h \ + tool_rectangle.h tool_remove.h tool_rotate.h tool_text.h tool_thermal.h \ + tool_via.h +tool_arc.o: tool_arc.c ../config.h conf_core.h conf.h global_typedefs.h \ + pcb_bool.h unit.h pcb-printf.h ../src_3rd/genvector/gds_char.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h globalconst.h color.h board.h \ + vtroutestyle.h attrib.h layer.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h obj_line_list.h \ + obj_line.h obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h \ + obj_text.h font.h ../src_3rd/genht/htip.h box.h math_helper.h \ + misc_util.h layer_grp.h rats_patch.h crosshair.h vtonpoint.h hid.h \ + error.h route.h data.h buffer.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h obj_rat_list.h obj_rat.h idpath.h \ + obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h draw.h \ + draw_wireframe.h search.h tool.h undo.h ../src_3rd/libuundo/uundo.h \ + undo_old.h macro.h obj_arc_draw.h +tool_arrow.o: tool_arrow.c ../config.h conf_core.h conf.h \ + global_typedefs.h pcb_bool.h unit.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h globalconst.h color.h board.h \ + vtroutestyle.h attrib.h layer.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h obj_line_list.h \ + obj_line.h obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h \ + obj_text.h font.h ../src_3rd/genht/htip.h box.h math_helper.h \ + misc_util.h layer_grp.h rats_patch.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h crosshair.h \ + vtonpoint.h hid.h error.h route.h data.h obj_rat_list.h obj_rat.h \ + idpath.h obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h \ + rtree.h ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h actions.h \ + remove.h move.h search.h select.h operation.h tool.h undo.h \ + ../src_3rd/libuundo/uundo.h undo_old.h +tool_buffer.o: tool_buffer.c ../config.h conf_core.h conf.h \ + global_typedefs.h pcb_bool.h unit.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h globalconst.h color.h board.h \ + vtroutestyle.h attrib.h layer.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h obj_line_list.h \ + obj_line.h obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h \ + obj_text.h font.h ../src_3rd/genht/htip.h box.h math_helper.h \ + misc_util.h layer_grp.h rats_patch.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h compat_misc.h data.h \ + crosshair.h vtonpoint.h hid.h error.h route.h obj_rat_list.h obj_rat.h \ + idpath.h obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h \ + rtree.h ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h actions.h \ + search.h tool.h undo.h ../src_3rd/libuundo/uundo.h undo_old.h +tool_copy.o: tool_copy.c ../config.h board.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h global_typedefs.h pcb_bool.h unit.h vtroutestyle.h \ + attrib.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h move.h crosshair.h vtonpoint.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h error.h route.h search.h tool.h \ + ../src_3rd/genvector/vtp0.h +tool_insert.o: tool_insert.c ../config.h board.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h global_typedefs.h pcb_bool.h unit.h vtroutestyle.h \ + attrib.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h crosshair.h vtonpoint.h hid.h ../src_3rd/liblihata/dom.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/parser.h error.h \ + route.h insert.h polygon.h rtree.h ../src_3rd/genrtree/genrtree_api.h \ + rtree2_compat.h search.h tool.h ../src_3rd/genvector/vtp0.h +tool_line.o: tool_line.c ../config.h conf_core.h conf.h global_typedefs.h \ + pcb_bool.h unit.h pcb-printf.h ../src_3rd/genvector/gds_char.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h globalconst.h color.h board.h \ + vtroutestyle.h attrib.h layer.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h obj_line_list.h \ + obj_line.h obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h \ + obj_text.h font.h ../src_3rd/genht/htip.h box.h math_helper.h \ + misc_util.h layer_grp.h rats_patch.h crosshair.h vtonpoint.h hid.h \ + error.h route.h data.h buffer.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h obj_rat_list.h obj_rat.h idpath.h \ + obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h draw.h \ + draw_wireframe.h find.h search.h tool.h undo.h \ + ../src_3rd/libuundo/uundo.h undo_old.h netlist2.h obj_line_draw.h \ + obj_pstk_draw.h obj_rat_draw.h route_draw.h \ + ../src_plugins/lib_compat_help/pstk_compat.h obj_pstk.h +tool_lock.o: tool_lock.c ../config.h board.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h global_typedefs.h pcb_bool.h unit.h vtroutestyle.h \ + attrib.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h change.h data.h crosshair.h vtonpoint.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h error.h route.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h draw.h actions.h search.h tool.h tool_lock.h +tool_move.o: tool_move.c ../config.h board.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h global_typedefs.h pcb_bool.h unit.h vtroutestyle.h \ + attrib.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h move.h crosshair.h vtonpoint.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h error.h route.h search.h tool.h \ + ../src_3rd/genvector/vtp0.h +tool_poly.o: tool_poly.c ../config.h conf_core.h conf.h global_typedefs.h \ + pcb_bool.h unit.h pcb-printf.h ../src_3rd/genvector/gds_char.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h globalconst.h color.h crosshair.h \ + vtonpoint.h hid.h error.h attrib.h layer.h obj_common.h flag.h \ + data_parent.h obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h route.h actions.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h polygon.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h tool.h +tool_polyhole.o: tool_polyhole.c ../config.h conf_core.h conf.h \ + global_typedefs.h pcb_bool.h unit.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h globalconst.h color.h crosshair.h \ + vtonpoint.h hid.h error.h attrib.h layer.h obj_common.h flag.h \ + data_parent.h obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h route.h actions.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h polygon.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h search.h tool.h +tool_rectangle.o: tool_rectangle.c ../config.h conf_core.h conf.h \ + global_typedefs.h pcb_bool.h unit.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h globalconst.h color.h board.h \ + vtroutestyle.h attrib.h layer.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h obj_line_list.h \ + obj_line.h obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h \ + obj_text.h font.h ../src_3rd/genht/htip.h box.h math_helper.h \ + misc_util.h layer_grp.h rats_patch.h crosshair.h vtonpoint.h hid.h \ + error.h route.h data.h buffer.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h obj_rat_list.h obj_rat.h idpath.h \ + obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h draw.h tool.h \ + undo.h ../src_3rd/libuundo/uundo.h undo_old.h obj_poly_draw.h +tool_remove.o: tool_remove.c ../config.h board.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h global_typedefs.h pcb_bool.h unit.h vtroutestyle.h \ + attrib.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h event.h actions.h hid.h ../src_3rd/liblihata/dom.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/parser.h error.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h undo.h \ + ../src_3rd/libuundo/uundo.h undo_old.h remove.h search.h tool.h \ + ../src_3rd/genvector/vtp0.h +tool_rotate.o: tool_rotate.c ../config.h conf_core.h conf.h \ + global_typedefs.h pcb_bool.h unit.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h globalconst.h color.h actions.h hid.h \ + error.h attrib.h layer.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h obj_line_list.h \ + obj_line.h obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h \ + obj_text.h font.h ../src_3rd/genht/htip.h box.h math_helper.h \ + misc_util.h ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h board.h \ + vtroutestyle.h layer_grp.h rats_patch.h rotate.h compat_misc.h tool.h +tool_text.o: tool_text.c ../config.h conf_core.h conf.h global_typedefs.h \ + pcb_bool.h unit.h pcb-printf.h ../src_3rd/genvector/gds_char.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h globalconst.h color.h board.h \ + vtroutestyle.h attrib.h layer.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h obj_line_list.h \ + obj_line.h obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h \ + obj_text.h font.h ../src_3rd/genht/htip.h box.h math_helper.h \ + misc_util.h layer_grp.h rats_patch.h data.h crosshair.h vtonpoint.h \ + hid.h error.h route.h buffer.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h obj_rat_list.h obj_rat.h idpath.h \ + obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h draw.h actions.h \ + tool.h undo.h ../src_3rd/libuundo/uundo.h undo_old.h obj_text_draw.h +tool_thermal.o: tool_thermal.c ../config.h board.h \ + ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h global_typedefs.h \ + pcb_bool.h unit.h vtroutestyle.h attrib.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h change.h data.h crosshair.h vtonpoint.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h error.h route.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h actions.h search.h thermal.h tool.h +tool_via.o: tool_via.c ../config.h conf_core.h conf.h global_typedefs.h \ + pcb_bool.h unit.h pcb-printf.h ../src_3rd/genvector/gds_char.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h globalconst.h color.h board.h \ + vtroutestyle.h attrib.h layer.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h obj_line_list.h \ + obj_line.h obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h \ + obj_text.h font.h ../src_3rd/genht/htip.h box.h math_helper.h \ + misc_util.h layer_grp.h rats_patch.h change.h hid_inlines.h hid.h \ + error.h data.h crosshair.h vtonpoint.h route.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h draw.h tool.h \ + tool_thermal.h undo.h ../src_3rd/libuundo/uundo.h undo_old.h \ + obj_pstk_draw.h ../src_plugins/lib_compat_help/pstk_compat.h obj_pstk.h +undo.o: undo.c ../config.h ../src_3rd/libuundo/uundo_debug.h \ + ../src_3rd/libuundo/uundo.h board.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h global_typedefs.h pcb_bool.h unit.h vtroutestyle.h \ + attrib.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h change.h data.h crosshair.h vtonpoint.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h error.h route.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h draw.h event.h insert.h remove.h rotate.h compat_misc.h \ + search.h undo.h ../src_3rd/libuundo/uundo.h undo_old.h flag_str.h \ + conf_core.h conf.h pcb-printf.h ../src_3rd/liblihata/lihata.h \ + list_conf.h obj_poly_draw.h +undo_act.o: undo_act.c ../config.h conf_core.h conf.h global_typedefs.h \ + pcb_bool.h unit.h pcb-printf.h ../src_3rd/genvector/gds_char.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h globalconst.h color.h board.h \ + vtroutestyle.h attrib.h layer.h obj_common.h flag.h data_parent.h \ + obj_arc_list.h obj_arc.h ../src_3rd/genlist/gendlist.h obj_line_list.h \ + obj_line.h obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h \ + obj_text.h font.h ../src_3rd/genht/htip.h box.h math_helper.h \ + misc_util.h layer_grp.h rats_patch.h actions.h hid.h error.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h data.h crosshair.h \ + vtonpoint.h route.h buffer.h obj_rat_list.h obj_rat.h idpath.h \ + obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h compat_misc.h \ + funchash_core.h funchash.h funchash_core_list.h undo.h \ + ../src_3rd/libuundo/uundo.h undo_old.h undo_act.h search.h \ + obj_line_draw.h draw.h tool.h +undo_old.o: undo_old.c ../config.h ../src_3rd/libuundo/uundo.h board.h \ + ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h global_typedefs.h \ + pcb_bool.h unit.h vtroutestyle.h attrib.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h color.h \ + obj_common.h flag.h data_parent.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_line_list.h obj_line.h obj_poly_list.h obj_poly.h polyarea.h \ + obj_text_list.h obj_text.h font.h ../src_3rd/genht/htip.h box.h \ + math_helper.h misc_util.h ../src_3rd/genvector/gds_char.h layer_grp.h \ + rats_patch.h change.h data.h crosshair.h vtonpoint.h hid.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h error.h route.h buffer.h \ + ../src_3rd/libfungw/fungw.h ../src_3rd/genht/htpp.h obj_rat_list.h \ + obj_rat.h idpath.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/hash.h obj_pstk_list.h obj_pstk.h \ + ../src_3rd/genvector/vtp0.h vtpadstack.h obj_pstk_shape.h polygon.h \ + vtpadstack_t.h draw.h move.h insert.h remove.h rotate.h compat_misc.h \ + search.h undo.h undo_old.h flag_str.h conf_core.h conf.h pcb-printf.h \ + ../src_3rd/liblihata/lihata.h list_conf.h netlist2.h obj_poly_draw.h \ + obj_subc_parent.h brave.h undo_old_str.h +unit.o: unit.c ../config.h compat_misc.h unit.h +view.o: view.c ../config.h idpath.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_common.h flag.h globalconst.h \ + attrib.h global_typedefs.h pcb_bool.h unit.h data_parent.h view.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h box.h math_helper.h misc_util.h \ + ../src_3rd/genlist/gentdlist_impl.c ../src_3rd/liblihata/dom.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/parser.h \ + ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h actions.h hid.h error.h \ + layer.h color.h obj_arc_list.h obj_arc.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h ../src_3rd/libfungw/fungw.h \ + ../src_3rd/genht/htpp.h compat_misc.h pcb-printf.h +vtc0.o: vtc0.c vtc0.h ../config.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h \ + ../src_3rd/genvector/genvector_impl.c +vtlibrary.o: vtlibrary.c vtlibrary.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h \ + ../src_3rd/genvector/genvector_impl.c +vtonpoint.o: vtonpoint.c ../config.h vtonpoint.h global_typedefs.h \ + pcb_bool.h unit.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h \ + ../src_3rd/genvector/genvector_impl.c +vtpadstack.o: vtpadstack.c obj_pstk.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genvector/vtp0.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_common.h flag.h globalconst.h \ + ../config.h attrib.h global_typedefs.h pcb_bool.h unit.h data_parent.h \ + layer.h color.h obj_arc_list.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h polyarea.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h ../src_3rd/genht/ht.h box.h math_helper.h \ + misc_util.h ../src_3rd/genvector/gds_char.h obj_pstk_shape.h polygon.h \ + rtree.h ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h \ + vtpadstack_t.h vtpadstack.h ../src_3rd/genvector/genvector_impl.c +vtpadstack_t.o: vtpadstack_t.c ../src_3rd/genvector/vtp0.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h ../src_3rd/genvector/gds_char.h \ + color.h global_typedefs.h ../config.h pcb_bool.h unit.h vtpadstack_t.h \ + obj_pstk_shape.h polygon.h flag.h globalconst.h rtree.h \ + ../src_3rd/genrtree/genrtree_api.h rtree2_compat.h math_helper.h \ + polyarea.h layer.h attrib.h obj_common.h data_parent.h obj_arc_list.h \ + obj_arc.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_line_list.h obj_line.h \ + obj_poly_list.h obj_poly.h obj_text_list.h obj_text.h font.h \ + ../src_3rd/genht/htip.h ../src_3rd/genht/ht.h box.h misc_util.h \ + ../src_3rd/genvector/genvector_impl.c +vtr0.o: vtr0.c vtr0.h ../config.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h \ + ../src_3rd/genvector/genvector_impl.c +vtroutestyle.o: vtroutestyle.c vtroutestyle.h unit.h ../config.h attrib.h \ + global_typedefs.h pcb_bool.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h \ + ../src_3rd/genvector/genvector_impl.c Index: tags/2.1.2/src/Makefile.in =================================================================== --- tags/2.1.2/src/Makefile.in (nonexistent) +++ tags/2.1.2/src/Makefile.in (revision 24813) @@ -0,0 +1,522 @@ +# TODO default compiler flags +put /local/pcb/CFLAGS cc/cflags +append /local/pcb/CFLAGS cc/fpic +append /local/pcb/CFLAGS ?/local/pcb/cflags_profile +append /local/pcb/CFLAGS {-I. -I.. -I../src_3rd -I../src_3rd/liblihata -Iicons -DHAVE_CONFIG_H} +append /local/pcb/LDFLAGS cc/ldflags +append /local/pcb/LDFLAGS cc/rdynamic +append /local/pcb/LDFLAGS ?/local/pcb/cflags_profile +put /local/pcb/DEPCFLAGS {} +put /local/pcb/OBJS_HIDLIB {} +put /local/pcb/OBJS_C99_HIDLIB_PLG {} +put /local/pcb/OBJS_HIDLIB_PLG {} +put /tmpasm/OFS { } + +if ?libs/script/fungw/presents +then + append /local/pcb/CFLAGS libs/script/fungw/cflags + append /local/pcb/LDFLAGS libs/script/fungw/ldflags +else +# no system installed fungw means we need to use local genht + append /local/pcb/OBJS_HIDLIB [@ + ../src_3rd/genht/hash.o + ../src_3rd/genht/htsp.o + ../src_3rd/genht/htss.o + ../src_3rd/genht/htsi.o + ../src_3rd/genht/htpi.o + ../src_3rd/genht/htip.o + ../src_3rd/genht/htpp.o + @] +# local compilation of fungw objects + append /local/pcb/OBJS_HIDLIB [@ + ../src_3rd/libfungw/fungw.o + ../src_3rd/libfungw/fungw_conv.o + ../src_3rd/libfungw/fungw_ptr.o + ../src_3rd/libfungw/fungw_debug.o + ../src_3rd/libfungw/fungw_call.o + @] +end + +# These files are to be generated before make dep is run +put /local/pcb/DEPDEPS { conf_core_fields.h conf_internal.c generated_lists.h defpcb_internal.c buildin.c pcb_menu_default.c } + +include {../scconfig/template/debug.tmpasm} + +# main: objects +# hidlib will be a library that provides: +# - the plugin system +# - the conf system +# - some basic/generic types like pcb_coord_t +# - the HID infra, including DAD +# but nothing else; in short the HID part of pcb-rnd for developing a +# GUI program based on pcb-rnd HIDs. + +# These have constructs that are not c89 strictly speaking but are +# effectively c89; typical example is casting a function pointer to a +# data pointer for dlsym(). +put /local/pcb/OBJS_C99_HIDLIB [@ + fptr_cast.o +@] + +append /local/pcb/OBJS_HIDLIB [@ + actions.o + attrib.o + color.o + conf.o + conf_core.o + conf_hid.o + conf_internal.o + compat_fs.o + compat_lrealpath.o + compat_misc.o + error.o + event.o + file_loaded.o + funchash.o + hid_attrib.o + hid_cfg.o + hid_cfg_action.o + hid_cfg_input.o + hid_color.o + hid_dlg.o + hid_dad_tree.o + hid_dad_spin.o + hid_flags.o + hid_init.o + hid_nogui.o + list_conf.o + misc_util.o + paths.o + pcb_bool.o + pcb-printf.o + plugins.o + plug_import.o + safe_fs.o + unit.o + vtc0.o + ../src_3rd/liblihata/parser.o + ../src_3rd/liblihata/dom.o + ../src_3rd/liblihata/dom_list.o + ../src_3rd/liblihata/dom_hash.o + ../src_3rd/liblihata/dom_table.o + ../src_3rd/liblihata/lihata.o + ../src_3rd/liblihata/hash_str.o + ../src_3rd/liblihata/tree.o + ../src_3rd/liblihata/tree_list.o + ../src_3rd/liblihata/tree_hash.o + ../src_3rd/liblihata/tree_table.o + ../src_3rd/liblihata/tree_symlink.o + ../src_3rd/liblihata/tree_path.o + ../src_3rd/liblhtpers/lhtpers.o + ../src_3rd/genvector/gds_char.o + ../src_3rd/genvector/vtp0.o + ../src_3rd/genvector/vts0.o + ../src_3rd/genvector/vti0.o + ../src_3rd/genvector/vtl0.o + ../src_3rd/genregex/regex_sei.o + ../src_3rd/genregex/regex_se.o + ../src_3rd/genregex/regex.o +@] + +put /local/pcb/OBJS_C99 /local/pcb/OBJS_C99_HIDLIB +put /local/pcb/OBJS /local/pcb/OBJS_HIDLIB +append /local/pcb/OBJS [@ + actions_pcb.o + board.o + box.o + brave.o + buffer.o + build_run.o + change.o + change_act.o + conf_act.o + crosshair.o + data.o + draw.o + drc.o + font.o + font_act.o + file_act.o + find.o + flag.o + flag_str.o + grid.o + gui_act.o + heap.o + hid_cam.o + hid_draw_helpers.o + ht_subc.o + idpath.o + insert.o + intersect.o + layer.o + layer_grp.o + layer_ui.o + layer_vis.o + main.o + main_act.o + move.o + netlist2.o + netlist_act.o + object_act.o + obj_common.o + obj_arc.o + obj_arc_list.o + obj_arc_ui.o + obj_line.o + obj_line_drcenf.o + obj_line_list.o + obj_pstk.o + obj_pstk_act.o + obj_pstk_list.o + obj_pstk_proto.o + obj_pinvia_therm.o + obj_poly.o + obj_poly_list.o + obj_rat.o + obj_rat_list.o + obj_subc.o + obj_subc_hash.o + obj_subc_list.o + obj_term.o + obj_text.o + obj_text_list.o + operation.o + pcb_menu_default.o + pcb_minuid.o + plug_io.o + plug_footprint.o + plug_footprint_act.o + polygon.o + polygon1.o + polygon_act.o + rats_act.o + rats_patch.o + remove.o + remove_act.o + rotate.o + route.o + route_style.o + rtree.o + search.o + select.o + select_act.o + stub_draw.o + stub_stroke.o + thermal.o + tool.o + tool_arc.o + tool_arrow.o + tool_buffer.o + tool_copy.o + tool_insert.o + tool_line.o + tool_lock.o + tool_move.o + tool_poly.o + tool_polyhole.o + tool_rectangle.o + tool_remove.o + tool_rotate.o + tool_text.o + tool_thermal.o + tool_via.o + undo.o + undo_act.o + undo_old.o + view.o + vtlibrary.o + vtonpoint.o + vtpadstack.o + vtpadstack_t.o + vtr0.o + vtroutestyle.o + buildin.o + ../src_3rd/qparse/qparse.o + ../src_3rd/libuundo/uundo.o + ../src_3rd/libuundo/uundo_debug.o +@] + +# linked only in the hidlib, dummy/bridge code +append /local/pcb/OBJS_HIDLIB_ONLY [@ + hidlib.o +@] + +put /local/pcb/LIBS_3RD [@ + ../src_3rd/puplug/libpuplug.a + ../src_3rd/libminuid/libminuid.a +@] + +put /local/pcb/LIBS /local/pcb/LIBS_3RD + +# We do not compile these in the executable but we need rules for these for utils +# e.g. ../src_3rd/genht/htsp.o +put /local/pcb/OBJS_UTIL [@ +@] + +# main: action registrations +put /local/pcb/ACTION_REG_SRC { + buffer.c brave.c change_act.c conf_act.c file_act.c drc.c error.c + gui_act.c hid_dlg.c hid_nogui.c main_act.c netlist_act.c font_act.c + object_act.c obj_pstk_act.c polygon_act.c plug_footprint_act.c rats_act.c + rats_patch.c remove_act.c select_act.c undo_act.c +} + +#---- modules ----# +# extra rules for modules +put /local/pcb/RULES {} +put /local/pcb/CLEANFILES {} +put /local/pcb/CLEANRULES {} +put /local/pcb/EXEDEPS {} +put /local/pcb/all {} +put /local/pcb/buildin_init {} +put /local/pcb/rules/install_ {} +put /local/pcb/rules/install {} +put /local/pcb/rules/linstall {} +put /local/pcb/rules/uninstall {} +put /local/pcb/mod/OBJS {} +put /local/pcb/mod/OBJS_C99 {} +put /local/pcb/mod/CONF {} +put /local/pcb/mod/LDFLAGS {} +put /local/pcb/mod/CFLAGS {} +put /local/pcb/mod/YACC {} +put /local/pcb/mod/LEX {} + +put /local/pcb/tmpasm/buildin {../src_plugins/Buildin.tmpasm} +put /local/pcb/tmpasm/plugin {../src_plugins/Plugin.tmpasm} +put /local/pcb/tmpasm/disable {../src_plugins/Disable.tmpasm} +put /local/pcb/tmpasm/common_enabled {../src_plugins/Common_enabled.tmpasm} +put /local/pcb/tmpasm/plugin_sphash {../scconfig/template/plugin_sphash.tmpasm} +put /local/pcb/tmpasm/plugin_conf {../scconfig/template/plugin_conf.tmpasm} +put /local/pcb/tmpasm/plugin_intconf {../scconfig/template/plugin_intconf.tmpasm} + +include {../src_plugins/plugins_ALL.tmpasm} + +append /local/pcb/CFLAGS /target/libs/sul/dmalloc/cflags +append /local/pcb/LIBS /target/libs/sul/dmalloc/ldflags + +# Lesstif requires that -lXm is before -lXt or else there is a runtime BadWindow error +order /local/pcb/LDFLAGS {-lXm} {before} {-lXt} + +# ---- logic ---- + + +# Clean up variables +uniq /local/pcb/OBJS +uniq /local/pcb/OBJS_C99 +uniq /local/pcb/OBJS_HIDLIB +uniq /local/pcb/OBJS_C99_HIDLIB +uniq /local/pcb/OBJS_HIDLIB_PLG +uniq /local/pcb/OBJS_C99_HIDLIB_PLG +uniq /local/pcb/OBJS_HIDLIB_ONLY +uniq /local/pcb/OBJS_UTIL +uniq /local/pcb/CFLAGS +uniq /local/pcb/LDFLAGS +uniq /local/pcb/LIBS +uniq /local/pcb/LIBS_PRE +uniq /local/pcb/LIBS_3RD +uniq /local/pcb/ACTION_REG_SRC +uniq /local/pcb/EXEDEPS +uniq /local/pcb/CLEANFILES +uniq /local/pcb/DISTCLEANFILES +uniq /local/pcb/CLEANRULES +uniq /local/pcb/all +put /local/pcb/SRCS /local/pcb/OBJS +append /local/pcb/SRCS ?/local/pcb/OBJS_C99 +append /local/pcb/SRCS ?/local/pcb/OBJS_HIDLIB +append /local/pcb/SRCS ?/local/pcb/OBJS_HIDLIB_ONLY +gsub /local/pcb/SRCS {.o } {.c } + +# Makefile, static +print [@ +# *** DO NOT EDIT THIS FILE *** +# This file has been generated from Makefile.in by configure +# *** DO NOT EDIT THIS FILE *** + +ROOT=.. + +# plugin source +PLUGDIR=$(ROOT)/src_plugins + +# plugin source install - so that pcb-rnd runs from source properly +PLUGIDIR=plugins + +# src_3rd dir for the lib_ wrapper plugins +SRC_3RD_DIR=$(ROOT)/src_3rd + +@?/local/pcb/TOPVARS@ +OBJS=@/local/pcb/OBJS@ +OBJS_C99=@/local/pcb/OBJS_C99@ +OBJS_HIDLIB=@/local/pcb/OBJS_HIDLIB@ +OBJS_C99_HIDLIB=@/local/pcb/OBJS_C99_HIDLIB@ +OBJS_HIDLIB_PLG=@/local/pcb/OBJS_HIDLIB_PLG@ +OBJS_C99_HIDLIB_PLG=@/local/pcb/OBJS_C99_HIDLIB_PLG@ +OBJS_HIDLIB_ONLY=@/local/pcb/OBJS_HIDLIB_ONLY@ +OBJS_UTIL=@/local/pcb/OBJS_UTIL@ +SRCS=@/local/pcb/SRCS@ +CFLAGS=@?cc/argstd/std_c99@ @/local/pcb/CFLAGS@ +C89FLAGS=@/local/pcb/c89flags@ @/local/pcb/CFLAGS@ +LDFLAGS=@/local/pcb/LDFLAGS@ +LIBS_PRE=@/local/pcb/LIBS_PRE@ +LIBS=@/local/pcb/LIBS@ -lm @?/target/libs/ldl@ +LIBS_3RD=@/local/pcb/LIBS_3RD@ +EXEDEPS=@/local/pcb/EXEDEPS@ +CLEANFILES=@/local/pcb/CLEANFILES@ +CLEANRULES=@/local/pcb/CLEANRULES@ +CC=@cc/cc@ +CQUOTE=$(ROOT)/scconfig/cquote +SPHASH_PATH=$(ROOT)/src_3rd/sphash +SPHASH=$(SPHASH_PATH)/sphash +PUPLUG=$(ROOT)/src_3rd/puplug/util/puplug +LIBMINUID_CFLAGS=@cc/cflags@ +LIBMINUID_LDFLAGS=@cc/ldflags@ +GENLIST_CFLAGS=@cc/cflags@ +GENLIST_LDFLAGS=@cc/ldflags@ + +all: + $(MAKE) revcheck + $(MAKE) all_exe + +include $(ROOT)/Makefile.conf + +revcheck: + cd $(ROOT)/scconfig && ./revtest Rev.stamp < Rev.tab + +all_exe: pcb-rnd$(EXE) @/local/pcb/all@ + +pcb-rnd$(EXE): $(OBJS) $(OBJS_C99) $(EXEDEPS) $(LIBS_3RD) + $(CC) $(OBJS) $(OBJS_C99) -o pcb-rnd$(EXE) $(LIBS_PRE) $(LDFLAGS) $(LIBS) + +# temporary, for testig +hidlib$(EXE): $(OBJS_HIDLIB) $(OBJS_C99_HIDLIB) $(OBJS_HIDLIB_PLG) $(OBJS_C99_HIDLIB_PLG) $(OBJS_HIDLIB_ONLY) $(EXEDEPS) $(LIBS_3RD) + $(CC) $(OBJS_HIDLIB_PLG) $(OBJS_C99_HIDLIB_PLG) $(OBJS_HIDLIB) $(OBJS_C99_HIDLIB) $(OBJS_HIDLIB_ONLY) -o hidlib$(EXE) $(LIBS_PRE) $(LDFLAGS) $(LIBS) $(LIBS_3RD) + + +$(SPHASH_PATH)/sphash: $(SPHASH_PATH)/sphash.c + $(CC) -o pcb-rnd$(EXE) $(SPHASH_PATH)/sphash.c -o $(SPHASH_PATH)/sphash + +# needed by gsch2pcb-rnd +../src_3rd/genlist/genadlist.o ../src_3rd/genlist/genlistalloc.o: + cd ../src_3rd/genlist && $(MAKE) GENLIST_CFLAGS="$(GENLIST_CFLAGS)" GENLIST_LDFLAGS="$(GENLIST_LDFLAGS)" + +buildin.c: $(PLUGDIR)/.builtin.pups $(PUPLUG) + cd $(PLUGDIR) && $(PUPLUG) buildin.c "-" < $(PLUGDIR)/.builtin.pups > $(ROOT)/src/buildin.c + +buildin.h: $(PLUGDIR)/.builtin.pups $(PUPLUG) + $(PUPLUG) buildin.h > buildin.h + +$(PUPLUG): + cd ../src_3rd/puplug && make + +../src_3rd/libminuid/libminuid.a: ../src_3rd/libminuid/libminuid.c ../src_3rd/libminuid/libminuid.h + cd ../src_3rd/libminuid && $(MAKE) libminuid.a LIBMINUID_CFLAGS="$(LIBMINUID_CFLAGS)" LIBMINUID_LDFLAGS="$(LIBMINUID_LDFLAGS)" + +@] + +print [@ +##### module rules begin ##### + +@/local/pcb/RULES@ + +##### module rules end ##### + +### default menu embed +pcb_menu_default.c: pcb-menu-default.lht $(CQUOTE) + $(CQUOTE) -n pcb_menu_default pcb_menu_default.c + +pcblib_DATA= \ + default_font \ + default2.lht \ + default4.lht \ + pcb-menu-default.lht \ + pcb-menu-lesstif.lht \ + pcb-menu-gtk.lht \ + pcb-menu-mkey.lht + + +EXTRA_DIST= \ + default_font \ + default2.lht \ + default4.lht \ + pcbtest.sh.in + +all-local: pcbtest.sh + +generated_lists.h: @/local/pcb/ACTION_REG_SRC@ Makefile + AWK=@/host/fstools/awk@ $(ROOT)/scconfig/gen_core_lists.sh @/local/pcb/ACTION_REG_SRC@ > generated_lists.h + +conf_core_fields.h: conf_core.h + AWK=@/host/fstools/awk@ $(ROOT)/scconfig/gen_conf.sh $(ROOT)/doc/conf/tree < conf_core.h > conf_core_fields.h + +conf_internal.c: pcb-conf.lht $(CQUOTE) + $(CQUOTE) -n conf_internal < pcb-conf.lht > conf_internal.c + +defpcb_internal.c: default4.lht + $(CQUOTE) -n default_pcb_internal < default4.lht > defpcb_internal.c + +# do not make this automatic, most users won't need to regenerate font_internal.c +gen_font: + $(ROOT)/util/devhelpers/font2c.sh < default_font > font_internal.c + +util_deps: $(OBJS) $(OBJS_UTIL) ../src_3rd/genlist/genadlist.o ../src_3rd/genlist/genlistalloc.o + +FORCE: + + +DISTCLEANFILES = Makefile.depgen core_lists.h buildin.c compat_inc.h conf_core_fields.h conf_internal.c generated_lists.h defpcb_internal.c pcb_menu_default.c ../src_plugins/.builtin.pups @/local/pcb/DISTCLEANFILES@ + +clean: $(CLEANRULES) + $(SCCBOX) rm -f -q pcb-rnd $(OBJS) $(OBJS_C99) $(CLEANFILES) + +distclean: FORCE + $(SCCBOX) rm -f -q $(DISTCLEANFILES) + +install_all: + $(SCCBOX) mkdir -p "$(BINDIR)" "$(DATADIR)" "$(LIBDIR)" "$(LIBDIR)/plugins" + $(SCCBOX) $(HOW) "pcb-rnd" "$(BINDIR)/pcb-rnd" + $(SCCBOX) $(HOW) "default2.lht" "$(DATADIR)/default2.lht" + $(SCCBOX) $(HOW) "default4.lht" "$(DATADIR)/default4.lht" + $(SCCBOX) $(HOW) "pcb-conf.lht" "$(DATADIR)/pcb-conf.lht" + $(SCCBOX) $(HOW) "pcb-menu-default.lht" "$(DATADIR)/pcb-menu-default.lht" + $(SCCBOX) $(HOW) "pcb-menu-lesstif.lht" "$(DATADIR)/pcb-menu-lesstif.lht" + $(SCCBOX) $(HOW) "pcb-menu-gtk.lht" "$(DATADIR)/pcb-menu-gtk.lht" + $(SCCBOX) $(HOW) "default_font" "$(DATADIR)/default_font"@/local/pcb/rules/install_@ + +install: + $(MAKE) install_all HOW="install -f" + +linstall: + $(MAKE) install_all HOW="linstall -f" + +uninstall: + $(MAKE) install_all HOW="uninstall" + +map_plugins: + cd ../src_plugins && ./map_plugins.sh + +@] + +# generate explicit rules for .c -> .o +put /local/comp/OBJS /local/pcb/OBJS +put /local/comp/OBJS_C99 ?/local/pcb/OBJS_C99 +include {../scconfig/template/compile.tmpasm} + +print [@ +# for extern utils:@] + +put /local/comp/OBJS /local/pcb/OBJS_UTIL +include {../scconfig/template/compile.tmpasm} + +# generate deps +put /local/dep/CFLAGS /local/pcb/CFLAGS +put /local/dep/SRCS /local/pcb/SRCS + +gsub /local/pcb/DEPSRCS {.o } {.c } +append /local/dep/SRCS /local/pcb/DEPSRCS +include {../scconfig/template/cdep.tmpasm} + +redir {../src_plugins/.builtin.pups} +print [@# Autogenerated by ./configure - do NOT edit - contains the list of buildins +@?/local/pcb/buildin_pups@ +@] + Index: tags/2.1.2/src/actions.c =================================================================== --- tags/2.1.2/src/actions.c (nonexistent) +++ tags/2.1.2/src/actions.c (revision 24813) @@ -0,0 +1,902 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * Copyright (C) 2004 harry eaton + * Copyright (C) 2016..2018 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +#include "config.h" +#include "conf_core.h" + +#include + +#include +#include + +#include "error.h" +#include "event.h" +#include "actions.h" +#include "compat_misc.h" +#include "funchash.h" + +const pcb_action_t *pcb_current_action = NULL; + +fgw_ctx_t pcb_fgw; +fgw_obj_t *pcb_fgw_obj; + +typedef struct { + const char *cookie; + const pcb_action_t *action; +} hid_cookie_action_t; + +static const char *check_action_name(const char *s) +{ + while (*s) + if (isspace((int) *s++) || *s == '(') + return (s - 1); + return NULL; +} + +char *pcb_make_action_name(char *out, const char *inp, int inp_len) +{ + char *s; + + if (inp_len >= PCB_ACTION_NAME_MAX) { + *out = '\0'; + return out; + } + + memcpy(out, inp, inp_len+1); + for(s = out; *s != '\0'; s++) + *s = tolower(*s); + return out; +} + +void pcb_register_actions(const pcb_action_t *a, int n, const char *cookie) +{ + int i; + hid_cookie_action_t *ca; + fgw_func_t *f; + + for (i = 0; i < n; i++) { + char fn[PCB_ACTION_NAME_MAX]; + int len; + + if (check_action_name(a[i].name)) { + pcb_message(PCB_MSG_ERROR, "ERROR! Invalid action name, " "action \"%s\" not registered.\n", a[i].name); + continue; + } + len = strlen(a[i].name); + if (len >= sizeof(fn)) { + pcb_message(PCB_MSG_ERROR, "Invalid action name: \"%s\" (too long).\n", a[i].name); + continue; + } + + ca = malloc(sizeof(hid_cookie_action_t)); + ca->cookie = cookie; + ca->action = a+i; + + pcb_make_action_name(fn, a[i].name, len); + f = fgw_func_reg(pcb_fgw_obj, fn, a[i].trigger_cb); + if (f == NULL) { + pcb_message(PCB_MSG_ERROR, "Failed to register action \"%s\" (already registered?)\n", a[i].name); + free(ca); + continue; + } + f->reg_data = ca; + } +} + +void pcb_register_action(const pcb_action_t *a, const char *cookie) +{ + pcb_register_actions(a, 1, cookie); +} + +static void pcb_remove_action(fgw_func_t *f) +{ + hid_cookie_action_t *ca = f->reg_data; + fgw_func_unreg(pcb_fgw_obj, f->name); + free(ca); +} + +fgw_func_t *pcb_act_lookup(const char *aname) +{ + char fn[PCB_ACTION_NAME_MAX]; + fgw_func_t *f = fgw_func_lookup(&pcb_fgw, pcb_aname(fn, aname)); + return f; +} + +void pcb_remove_actions(const pcb_action_t *a, int n) +{ + int i; + + for (i = 0; i < n; i++) { + fgw_func_t *f = pcb_act_lookup(a[i].name); + if (f == NULL) { + pcb_message(PCB_MSG_WARNING, "Failed to remove action \"%s\" (is it registered?)\n", a[i].name); + continue; + } + pcb_remove_action(f); + } +} + +void pcb_remove_actions_by_cookie(const char *cookie) +{ + htsp_entry_t *e; + + /* Slow linear search - probably OK, this will run only on uninit */ + for (e = htsp_first(&pcb_fgw.func_tbl); e; e = htsp_next(&pcb_fgw.func_tbl, e)) { + fgw_func_t *f = e->value; + hid_cookie_action_t *ca = f->reg_data; + if ((ca != NULL) && (ca->cookie == cookie)) + pcb_remove_action(f); + } +} + +const pcb_action_t *pcb_find_action(const char *name, fgw_func_t **f_out) +{ + fgw_func_t *f; + hid_cookie_action_t *ca; + + if (name == NULL) + return NULL; + + f = pcb_act_lookup(name); + if (f == NULL) { + pcb_message(PCB_MSG_ERROR, "unknown action `%s'\n", name); + return NULL; + } + ca = f->reg_data; + if (f_out != NULL) + *f_out = f; + return ca->action; +} + +void pcb_print_actions() +{ + htsp_entry_t *e; + + fprintf(stderr, "Registered Actions:\n"); + for (e = htsp_first(&pcb_fgw.func_tbl); e; e = htsp_next(&pcb_fgw.func_tbl, e)) { + fgw_func_t *f = e->value; + hid_cookie_action_t *ca = f->reg_data; + if (ca->action->description) + fprintf(stderr, " %s - %s\n", ca->action->name, ca->action->description); + else + fprintf(stderr, " %s\n", ca->action->name); + if (ca->action->syntax) { + const char *bb, *eb; + bb = eb = ca->action->syntax; + while (1) { + for (eb = bb; *eb && *eb != '\n'; eb++); + fwrite(" ", 4, 1, stderr); + fwrite(bb, eb - bb, 1, stderr); + fputc('\n', stderr); + if (*eb == 0) + break; + bb = eb + 1; + } + } + } +} + +static void dump_string(char prefix, const char *str) +{ + int eol = 1; + while (*str) { + if (eol) { + putchar(prefix); + eol = 0; + } + putchar(*str); + if (*str == '\n') + eol = 1; + str++; + } + if (!eol) + putchar('\n'); +} + +void pcb_dump_actions(void) +{ + htsp_entry_t *e; + + fprintf(stderr, "Registered Actions:\n"); + for (e = htsp_first(&pcb_fgw.func_tbl); e; e = htsp_next(&pcb_fgw.func_tbl, e)) { + fgw_func_t *f = e->value; + hid_cookie_action_t *ca = f->reg_data; + const char *desc = ca->action->description; + const char *synt = ca->action->syntax; + const char *ck = ca->cookie; + + desc = desc ? desc : ""; + synt = synt ? synt : ""; + ck = ck ? ck : ""; + + printf("A%s\n", ca->action->name); + dump_string('D', desc); + dump_string('S', synt); + dump_string('C', ck); + } +} + +int pcb_action(const char *name) +{ + return pcb_actionv(name, 0, 0); +} + +int pcb_actionl(const char *name, ...) +{ + const char *argv[20]; + int argc = 0; + va_list ap; + char *arg; + + va_start(ap, name); + while ((arg = va_arg(ap, char *)) != 0) + argv[argc++] = arg; + va_end(ap); + return pcb_actionv(name, argc, argv); +} + +fgw_error_t pcb_actionv_(const fgw_func_t *f, fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + fgw_error_t ret; + int i; + const pcb_action_t *old_action; + hid_cookie_action_t *ca = f->reg_data; + + if (conf_core.rc.verbose) { + fprintf(stderr, "Action: \033[34m%s(", f->name); + for (i = 0; i < argc; i++) + fprintf(stderr, "%s%s", i ? "," : "", (argv[i].type & FGW_STR) == FGW_STR ? argv[i].val.str : ""); + fprintf(stderr, ")\033[0m\n"); + } + + if (ca != NULL) { + /* pcb-rnd action with a lot of metadata */ + old_action = pcb_current_action; + pcb_current_action = ca->action; + ret = pcb_current_action->trigger_cb(res, argc, argv); + pcb_current_action = old_action; + } + else { + /* direct call, no metadata */ + ret = f->func(res, argc, argv); + } + + fgw_argv_free(&pcb_fgw, argc, argv); + + return ret; +} + +fgw_error_t pcb_actionv_bin(const char *name, fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + fgw_func_t *f = pcb_act_lookup(name); + + if (f == NULL) + return FGW_ERR_NOT_FOUND; + + argv[0].type = FGW_FUNC; + argv[0].val.func = f; + + res->type = FGW_INVALID; + return pcb_actionv_(f, res, argc, argv); +} + + +int pcb_actionv(const char *name, int argc, const char **argsv) +{ + fgw_func_t *f; + fgw_arg_t res, argv[PCB_ACTION_MAX_ARGS+1]; + int n; + + if (name == NULL) + return 1; + + if (argc >= PCB_ACTION_MAX_ARGS) { + pcb_message(PCB_MSG_ERROR, "can not call action %s with this many arguments (%d >= %d)\n", name, argc, PCB_ACTION_MAX_ARGS); + return 1; + } + + f = pcb_act_lookup(name); + if (f == NULL) { + int i; + pcb_message(PCB_MSG_ERROR, "no action %s(", name); + for (i = 0; i < argc; i++) + pcb_message(PCB_MSG_ERROR, "%s%s", i ? ", " : "", argsv[i]); + pcb_message(PCB_MSG_ERROR, ")\n"); + return 1; + } + argv[0].type = FGW_FUNC; + argv[0].val.func = f; + for(n = 0; n < argc; n++) { + argv[n+1].type = FGW_STR; + argv[n+1].val.str = (char *)argsv[n]; + } + res.type = FGW_INVALID; + if (pcb_actionv_(f, &res, argc+1, argv) != 0) + return -1; + if (fgw_arg_conv(&pcb_fgw, &res, FGW_INT) != 0) + return -1; + return res.val.nat_int; +} + +void pcb_hid_get_coords(const char *msg, pcb_coord_t *x, pcb_coord_t *y, int force) +{ + if (pcb_gui == NULL) { + fprintf(stderr, "pcb_hid_get_coords: can not get coordinates (no gui) for '%s'\n", msg); + *x = 0; + *y = 0; + } + else + pcb_gui->get_coords(msg, x, y, force); +} + +static int hid_parse_actionstring(const char *rstr, char require_parens) +{ + const char **list = NULL; + int max = 0; + int num; + char *str = NULL; + const char *sp; + char *cp, *aname, *cp2; + int maybe_empty = 0; + char in_quotes = 0; + char parens = 0; + int retcode = 0; + + /*fprintf(stderr, "invoke: `%s'\n", rstr); */ + + sp = rstr; + str = (char *) malloc(strlen(rstr) + 1); + +another: + num = 0; + cp = str; + + /* eat leading spaces and tabs */ + while (*sp && isspace((int) *sp)) + sp++; + + if ((*sp == '\0') || (*sp == '#')) { + retcode = 0; + goto cleanup; + } + + aname = cp; + + /* copy the action name, assumes name does not have a space or '(' + * in its name */ + while (*sp && !isspace((int) *sp) && *sp != '(') + *cp++ = *sp++; + *cp++ = 0; + + /* skip whitespace */ + while (*sp && isspace((int) *sp)) + sp++; + + /* + * we only have an action name, so invoke the action + * with no parameters or event. + */ + if (*sp == '\0') { + retcode = pcb_actionv(aname, 0, 0); + goto cleanup; + } + + /* are we using parenthesis? */ + if (*sp == '(') { + parens = 1; + sp++; + } + else if (require_parens) { + pcb_message(PCB_MSG_ERROR, "Syntax error: %s\n", rstr); + pcb_message(PCB_MSG_ERROR, " expected: Action(arg1, arg2)"); + retcode = 1; + goto cleanup; + } + + /* get the parameters to pass to the action */ + while (1) { + /* + * maybe_empty == 0 means that the last char examined was not a + * "," + */ + if (!maybe_empty && ((parens && *sp == ')') || (!parens && !*sp))) { + retcode = pcb_actionv(aname, num, list); + if (retcode) + goto cleanup; + + /* strip any white space or ';' following the action */ + if (parens) + sp++; + while (*sp && (isspace((int) *sp) || *sp == ';')) + sp++; + goto another; + } + else if (*sp == 0 && !maybe_empty) + break; + else { + maybe_empty = 0; + in_quotes = 0; + /* + * if we have more parameters than memory in our array of + * pointers, then either allocate some or grow the array + */ + if (num >= max) { + max += 10; + if (list) + list = (const char **) realloc(list, max * sizeof(char *)); + else + list = (const char **) malloc(max * sizeof(char *)); + } + /* Strip leading whitespace. */ + while (*sp && isspace((int) *sp)) + sp++; + list[num++] = cp; + + /* search for the end of the argument, we want to keep going + * if we are in quotes or the char is not a delimiter + */ + while (*sp && (in_quotes || ((*sp != ',') + && (!parens || *sp != ')') + && (parens || !isspace((int) *sp))))) { + /* + * single quotes give literal value inside, including '\'. + * you can't have a single inside single quotes. + * doubles quotes gives literal value inside, but allows escape. + */ + if ((*sp == '"' || *sp == '\'') && (!in_quotes || *sp == in_quotes)) { + in_quotes = in_quotes ? 0 : *sp; + sp++; + continue; + } + /* unless within single quotes, \ will just be */ + else if (*sp == '\\' && in_quotes != '\'') + sp++; + *cp++ = *sp++; + } + cp2 = cp - 1; + *cp++ = 0; + if (*sp == ',' || (!parens && isspace((int) *sp))) { + maybe_empty = 1; + sp++; + } + /* Strip trailing whitespace. */ + for (; isspace((int) *cp2) && cp2 >= list[num - 1]; cp2--) + *cp2 = 0; + } + } + +cleanup: + + if (list != NULL) + free(list); + + if (str != NULL) + free(str); + + return retcode; +} + +const char *pcb_cli_prompt(const char *suffix) +{ + const char *base; + static char prompt[128]; + int blen, slen, len; + + if ((conf_core.rc.cli_prompt != NULL) && (*conf_core.rc.cli_prompt != '\0')) + base = conf_core.rc.cli_prompt; + else if ((conf_core.rc.cli_backend == NULL) || (*conf_core.rc.cli_backend == '\0')) + base = "action"; + else + base = conf_core.rc.cli_backend; + + if ((suffix == NULL) || (*suffix == '\0')) + return base; + + blen = strlen(base); + slen = strlen(suffix); + + len = blen; + if (len >= sizeof(prompt)-1-slen) + len = sizeof(prompt)-1-slen; + + memcpy(prompt, base, len); + memcpy(prompt+len, suffix, slen); + prompt[len+slen] = '\0'; + return prompt; +} + +static vtp0_t cli_stack; + +static void cli_push(const char *val) +{ + if (val == NULL) + val = ""; + vtp0_append(&cli_stack, pcb_strdup(val)); +} + +static char *cli_pop(void) +{ + if (cli_stack.used == 0) + return NULL; + return cli_stack.array[--cli_stack.used]; +} + +int pcb_cli_enter(const char *backend, const char *prompt) +{ + cli_push(conf_core.rc.cli_backend); + cli_push(conf_core.rc.cli_prompt); + + if (conf_set(CFR_CLI, "rc/cli_backend", 0, backend, POL_OVERWRITE) != 0) + return -1; + return conf_set(CFR_CLI, "rc/cli_prompt", 0, prompt, POL_OVERWRITE); +} + +int pcb_cli_leave(void) +{ + if (vtp0_len(&cli_stack) >= 2) { + char *prompt = NULL, *backend = NULL; + prompt = cli_pop(); + backend = cli_pop(); + conf_set(CFR_CLI, "rc/cli_backend", 0, backend, POL_OVERWRITE); + conf_set(CFR_CLI, "rc/cli_prompt", 0, prompt, POL_OVERWRITE); + free(prompt); + free(backend); + return 0; + } + + conf_set(CFR_CLI, "rc/cli_backend", 0, "", POL_OVERWRITE); + conf_set(CFR_CLI, "rc/cli_prompt", 0, "", POL_OVERWRITE); + return -1; +} + +static int pcb_cli_common(fgw_arg_t *args) +{ + const pcb_action_t *a; + fgw_func_t *f; + + /* no backend: let the original action work */ + if ((conf_core.rc.cli_backend == NULL) || (*conf_core.rc.cli_backend == '\0')) + return -1; + + /* backend: let the backend action handle it */ + a = pcb_find_action(conf_core.rc.cli_backend, &f); + if (!a) + return -1; + + args[0].type = FGW_FUNC; + args[0].val.func = f; + return 0; +} + +int pcb_cli_tab(void) +{ + fgw_arg_t res, args[2]; + + if (pcb_cli_common(args) != 0) + return -1; + + args[1].type = FGW_STR; + args[1].val.str = "/tab"; + + if (pcb_actionv_(args[0].val.func, &res, 2, args) != 0) + return -1; + fgw_arg_conv(&pcb_fgw, &res, FGW_INT); + return res.val.nat_int; +} + +int pcb_cli_edit(void) +{ + fgw_arg_t res, args[2]; + + if (pcb_cli_common(args) != 0) + return -1; + + args[1].type = FGW_STR; + args[1].val.str = "/edit"; + + if (pcb_actionv_(args[0].val.func, &res, 2, args) != 0) + return -1; + fgw_arg_conv(&pcb_fgw, &res, FGW_INT); + return res.val.nat_int; +} + +int pcb_cli_mouse(pcb_bool notify) +{ + fgw_arg_t res, args[3]; + + if (pcb_cli_common(args) != 0) + return -1; + + args[1].type = FGW_STR; + args[1].val.str = "/click"; + args[2].type = FGW_INT; + args[2].val.nat_int = notify; + + if (pcb_actionv_(args[0].val.func, &res, 3, args) != 0) + return -1; + fgw_arg_conv(&pcb_fgw, &res, FGW_INT); + return res.val.nat_int; +} + + +void pcb_cli_uninit(void) +{ + while(vtp0_len(&cli_stack) > 0) + free(cli_pop()); +} + +int pcb_parse_command(const char *str_, pcb_bool force_action_mode) +{ + fgw_arg_t res, args[2]; + fgw_func_t *f; + const pcb_action_t *a; + const char *end; + + /* no backend or forced action mode: classic pcb-rnd action parse */ + if (force_action_mode || (conf_core.rc.cli_backend == NULL) || (*conf_core.rc.cli_backend == '\0')) { + pcb_event(PCB_EVENT_CLI_ENTER, "s", str_); + return hid_parse_actionstring(str_, pcb_false); + } + + /* backend: let the backend action handle it */ + a = pcb_find_action(conf_core.rc.cli_backend, &f); + if (!a) { + pcb_message(PCB_MSG_ERROR, "cli: no action %s; leaving mode\n", conf_core.rc.cli_backend); + pcb_cli_leave(); + return -1; + } + + end = strpbrk(str_, "\n\r"); + + args[0].type = FGW_FUNC; + args[0].val.func = f; + if (end == NULL) { + /* optimization: string doesn't contain newline - pass it as is to save an strdup */ + args[1].type = FGW_STR; + args[1].val.str = pcb_strdup(str_); + } + else { + /* string contains a newline; need to cut there, which needs a dup; let fungw free it as dynamic string, cleaning up args after the fungw call */ + args[1].type = FGW_STR | FGW_DYN; + args[1].val.str = pcb_strdup(str_); + args[1].val.str[end - str_] = '\0'; + } + + if (pcb_actionv_(f, &res, 2, args) != 0) + return -1; + fgw_arg_conv(&pcb_fgw, &res, FGW_INT); + return res.val.nat_int; +} + +int pcb_parse_actions(const char *str_) +{ + return hid_parse_actionstring(str_, pcb_true); +} + +/*** custom fungw types ***/ +#define conv_str2kw(dst, src) dst = pcb_funchash_get(src, NULL) + +static int keyword_arg_conv(fgw_ctx_t *ctx, fgw_arg_t *arg, fgw_type_t target) +{ + if (target == FGW_KEYWORD) { /* convert to keyword */ + long tmp; + switch(FGW_BASE_TYPE(arg->type)) { + ARG_CONV_CASE_LONG(tmp, conv_err) + ARG_CONV_CASE_LLONG(tmp, conv_err) + ARG_CONV_CASE_DOUBLE(tmp, conv_err) + ARG_CONV_CASE_LDOUBLE(tmp, conv_err) + ARG_CONV_CASE_STR(tmp, conv_str2kw) + ARG_CONV_CASE_PTR(tmp, conv_err) + ARG_CONV_CASE_CLASS(tmp, conv_err) + ARG_CONV_CASE_INVALID(tmp, conv_err) + } + arg->type = FGW_KEYWORD; + fgw_keyword(arg) = tmp; + return 0; + } + if (arg->type == FGW_KEYWORD) { /* convert from keyword */ + long tmp = fgw_keyword(arg); + switch(target) { + ARG_CONV_CASE_LONG(tmp, conv_rev_assign) + ARG_CONV_CASE_LLONG(tmp, conv_rev_assign) + ARG_CONV_CASE_DOUBLE(tmp, conv_rev_assign) + ARG_CONV_CASE_LDOUBLE(tmp, conv_rev_assign) + ARG_CONV_CASE_PTR(tmp, conv_err) + ARG_CONV_CASE_CLASS(tmp, conv_err) + ARG_CONV_CASE_INVALID(tmp, conv_err) + case FGW_STR: + arg->val.str = (char *)pcb_funchash_reverse(tmp); + arg->type = FGW_STR; + return 0; + } + arg->type = target; + return 0; + } + fprintf(stderr, "Neither side of the conversion is keyword\n"); + abort(); +} + +char *fgw_str2coord_unit = NULL; +#define conv_str2coord(dst, src) \ +do { \ + pcb_bool succ; \ + dst = pcb_get_value_ex(src, NULL, NULL, NULL, fgw_str2coord_unit, &succ); \ + if (!succ) \ + return -1; \ +} while(0) + +static int coord_arg_conv(fgw_ctx_t *ctx, fgw_arg_t *arg, fgw_type_t target) +{ + if (target == FGW_COORD) { /* convert to coord */ + pcb_coord_t tmp; + switch(FGW_BASE_TYPE(arg->type)) { + ARG_CONV_CASE_LONG(tmp, conv_assign) + ARG_CONV_CASE_LLONG(tmp, conv_assign) + ARG_CONV_CASE_DOUBLE(tmp, conv_assign) + ARG_CONV_CASE_LDOUBLE(tmp, conv_assign) + ARG_CONV_CASE_STR(tmp, conv_str2coord) + ARG_CONV_CASE_PTR(tmp, conv_err) + ARG_CONV_CASE_CLASS(tmp, conv_err) + ARG_CONV_CASE_INVALID(tmp, conv_err) + } + arg->type = FGW_COORD; + fgw_coord(arg) = tmp; + return 0; + } + if (arg->type == FGW_COORD) { /* convert from coord */ + pcb_coord_t tmp = fgw_coord(arg); + switch(target) { + ARG_CONV_CASE_LONG(tmp, conv_rev_assign) + ARG_CONV_CASE_LLONG(tmp, conv_rev_assign) + ARG_CONV_CASE_DOUBLE(tmp, conv_rev_assign) + ARG_CONV_CASE_LDOUBLE(tmp, conv_rev_assign) + ARG_CONV_CASE_PTR(tmp, conv_err) + ARG_CONV_CASE_CLASS(tmp, conv_err) + ARG_CONV_CASE_INVALID(tmp, conv_err) + case FGW_STR: + arg->val.str = (char *)pcb_strdup_printf("%.08$mH", tmp); + arg->type = FGW_STR | FGW_DYN; + return 0; + } + arg->type = target; + return 0; + } + fprintf(stderr, "Neither side of the conversion is coord\n"); + abort(); +} + +#define conv_str2coords(dst, src) \ +do { \ + pcb_bool succ, abso; \ + dst.c[0] = pcb_get_value_ex(src, NULL, &abso, NULL, fgw_str2coord_unit, &succ); \ + if (!succ) \ + return -1; \ + dst.len = 1; \ + dst.absolute[0] = abso; \ +} while(0) + + + +#define conv_loadcoords(dst, src) \ +do { \ + dst.len = 1; \ + dst.absolute[0] = 1; \ + dst.c[0] = src; \ +} while(0) + +static int coords_arg_conv(fgw_ctx_t *ctx, fgw_arg_t *arg, fgw_type_t target) +{ + if (target == FGW_COORDS) { /* convert to coord */ + fgw_coords_t tmp; + switch(FGW_BASE_TYPE(arg->type)) { + ARG_CONV_CASE_LONG(tmp, conv_loadcoords) + ARG_CONV_CASE_LLONG(tmp, conv_loadcoords) + ARG_CONV_CASE_DOUBLE(tmp, conv_loadcoords) + ARG_CONV_CASE_LDOUBLE(tmp, conv_loadcoords) + ARG_CONV_CASE_STR(tmp, conv_str2coords) + ARG_CONV_CASE_PTR(tmp, conv_err) + ARG_CONV_CASE_CLASS(tmp, conv_err) + ARG_CONV_CASE_INVALID(tmp, conv_err) + } + arg->type = FGW_COORDS | FGW_DYN; + fgw_coords(arg) = malloc(sizeof(tmp)); + memcpy(fgw_coords(arg), &tmp, sizeof(tmp)); + return 0; + } + if (arg->type == FGW_COORDS) { /* convert from coord */ + fgw_coords_t *tmp = fgw_coords(arg); + switch(target) { + ARG_CONV_CASE_LONG(tmp, conv_err) + ARG_CONV_CASE_LLONG(tmp, conv_err) + ARG_CONV_CASE_DOUBLE(tmp, conv_err) + ARG_CONV_CASE_LDOUBLE(tmp, conv_err) + ARG_CONV_CASE_PTR(tmp, conv_err) + ARG_CONV_CASE_CLASS(tmp, conv_err) + ARG_CONV_CASE_INVALID(tmp, conv_err) + case FGW_STR: + arg->val.str = (char *)pcb_strdup_printf("%.08$mH", tmp); + arg->type = FGW_STR | FGW_DYN; + return 0; + } + arg->type = target; + return 0; + } + fprintf(stderr, "Neither side of the conversion is coords\n"); + abort(); +} + +static int coords_arg_free(fgw_ctx_t *ctx, fgw_arg_t *arg) +{ + assert(arg->type == (FGW_COORDS | FGW_DYN)); + free(arg->val.ptr_void); + return 0; +} + +static void pcb_action_err(fgw_obj_t *obj, const char *msg) +{ + pcb_message(PCB_MSG_ERROR, "fungw(%s): %s", obj->name, msg); +} + +void pcb_actions_init(void) +{ + fgw_init(&pcb_fgw, "pcb-rnd"); + pcb_fgw.async_error = pcb_action_err; + pcb_fgw_obj = fgw_obj_reg(&pcb_fgw, "core"); + if (fgw_reg_custom_type(&pcb_fgw, FGW_KEYWORD, "keyword", keyword_arg_conv, NULL) != FGW_KEYWORD) { + fprintf(stderr, "pcb_actions_init: failed to register FGW_KEYWORD\n"); + abort(); + } + if (fgw_reg_custom_type(&pcb_fgw, FGW_COORD, "coord", coord_arg_conv, NULL) != FGW_COORD) { + fprintf(stderr, "pcb_actions_init: failed to register FGW_COORD\n"); + abort(); + } + if (fgw_reg_custom_type(&pcb_fgw, FGW_COORDS, "coords", coords_arg_conv, coords_arg_free) != FGW_COORDS) { + fprintf(stderr, "pcb_actions_init: failed to register FGW_COORDS\n"); + abort(); + } +} + +void pcb_actions_uninit(void) +{ + htsp_entry_t *e; + + for (e = htsp_first(&pcb_fgw.func_tbl); e; e = htsp_next(&pcb_fgw.func_tbl, e)) { + fgw_func_t *f = e->value; + hid_cookie_action_t *ca = f->reg_data; + if (ca->cookie != NULL) + fprintf(stderr, "ERROR: hid_actions_uninit: action '%s' with cookie '%s' left registered, check your plugins!\n", e->key, ca->cookie); + pcb_remove_action(f); + } + + fgw_obj_unreg(&pcb_fgw, pcb_fgw_obj); + fgw_uninit(&pcb_fgw); + fgw_atexit(); +} + Index: tags/2.1.2/src/actions.h =================================================================== --- tags/2.1.2/src/actions.h (nonexistent) +++ tags/2.1.2/src/actions.h (revision 24813) @@ -0,0 +1,200 @@ +#ifndef PCB_ACTIONS_H +#define PCB_ACTIONS_H + +#include "hid.h" +#include + +#define PCB_ACTION_NAME_MAX 128 + +struct pcb_action_s { + const char *name; /* action command name */ + fgw_error_t (*trigger_cb)(fgw_arg_t *ores, int argc, fgw_arg_t *argv); /* Action implementation; if this returns non-zero, no further actions will be invoked for this key/mouse event. */ + const char *description;/* Short description (help text) */ + const char *syntax; /* Full allowed syntax; use \n to separate lines. */ +}; + +extern fgw_ctx_t pcb_fgw; + +typedef struct fgw_coords_s { + int len; + pcb_coord_t c[4]; + char absolute[4]; +} fgw_coords_t; + +typedef enum { + FGW_KEYWORD_ = FGW_CUSTOM, + FGW_COORD_, + FGW_COORDS_, + FGW_LAYERID_, + FGW_LAYER_, + FGW_DATA_ +} pcb_fgw_types_e; +#define fgw_keyword(arg) ((arg)->val.nat_int) +#define fgw_coord(arg) (*(pcb_coord_t *)(&((arg)->val.custom.c))) +#define fgw_coords(arg) ((arg)->val.ptr_void) +#define fgw_layerid(arg) ((arg)->val.nat_long) +#define fgw_layer(arg) ((arg)->val.ptr_void) +#define fgw_data(arg) ((arg)->val.ptr_void) +#define FGW_KEYWORD ((fgw_type_t)FGW_KEYWORD_) +#define FGW_COORD ((fgw_type_t)FGW_COORD_) +#define FGW_COORDS ((fgw_type_t)FGW_COORDS_) +#define FGW_LAYERID ((fgw_type_t)FGW_LAYERID_) +#define FGW_LAYER ((fgw_type_t)FGW_LAYER_) +#define FGW_DATA ((fgw_type_t)FGW_DATA_) + +void pcb_register_action(const pcb_action_t *a, const char *cookie); +void pcb_register_actions(const pcb_action_t *a, int, const char *cookie); +#define PCB_REGISTER_ACTIONS(a, cookie) PCB_HIDCONCAT(void register_,a) ()\ + { pcb_register_actions(a, sizeof(a)/sizeof(a[0]), cookie); } + +/* Inits and uninits the whole action framework */ +void pcb_actions_init(void); +void pcb_actions_uninit(void); + +/* These are called from main_act.c */ +void pcb_print_actions(void); +void pcb_dump_actions(void); + +const pcb_action_t *pcb_find_action(const char *name, fgw_func_t **f_out); + +void pcb_remove_actions(const pcb_action_t *a, int n); +void pcb_remove_actions_by_cookie(const char *cookie); + +int pcb_action(const char *action_); +int pcb_actionl(const char *action_, ...); /* NULL terminated */ +int pcb_actionv(const char *action_, int argc_, const char **argv_); +fgw_error_t pcb_actionv_(const fgw_func_t *f, fgw_arg_t *res, int argc, fgw_arg_t *argv); + +/* Call an action by name, passing arguments and res in fungw binary format; + Caller must leave argv[0] empty for the function designator. */ +fgw_error_t pcb_actionv_bin(const char *name, fgw_arg_t *res, int argc, fgw_arg_t *argv); + + +/* Parse the given command string into action calls, and call + hid_actionv for each action found. Accepts both "action(arg1, + arg2)" and command-style "action arg1 arg2", allowing only one + action in the later case. If force_action_mode is true, str + is interpreted as pcb-rnd action despite of the cli mode. + Returns nonzero if the action handler(s) return nonzero. */ +int pcb_parse_command(const char *str_, pcb_bool force_action_mode); + +/* Parse the given string into action calls, and call + hid_actionv for each action found. Accepts only + "action(arg1, arg2)" */ +int pcb_parse_actions(const char *str_); + +/* Return a static buffer with the current prompt plus an optional + suffix glued to it. Valid until the next call. */ +const char *pcb_cli_prompt(const char *suffix); + +/* Change the cli backend/prompt, entering a new cli mode; the old + mode is pushed on a stack */ +int pcb_cli_enter(const char *backend, const char *prompt); + +/* Leave the current cli mode, returning to the previous mode + (popped from a stack) */ +int pcb_cli_leave(void); + +/* Request for tab completion */ +int pcb_cli_tab(void); + +/* Called on each key press so indication can be updated */ +int pcb_cli_edit(void); + +/* Mouse event while the command line is open; returns zero if + normal event processing shall be inhibited; notify is true if + called in notify mode, false if called in release mode */ +int pcb_cli_mouse(pcb_bool notify); + +/* Discard the cli mode stack */ +void pcb_cli_uninit(void); + +/* If the mouse cursor is in the drawin area, set x;y silently and return; + else show msg and let the user click in the drawing area. If force is + non-zero and msg is non-NULL, discard the cache and force querying a + new coord. This mode must NOT be used unless action arguments explictly + requested it. */ +void pcb_hid_get_coords(const char *msg, pcb_coord_t *x, pcb_coord_t *y, int force); + +#define PCB_ACTION_MAX_ARGS 16 + +/* low level action function lookup */ +fgw_func_t *pcb_act_lookup(const char *aname); + +char *pcb_make_action_name(char *out, const char *inp, int inp_len); +PCB_INLINE char *pcb_aname(char *out, const char *inp) +{ + return pcb_make_action_name(out, inp, strlen(inp)); +} + +/* Return 0 on success after an action call */ +PCB_INLINE int pcb_act_result(fgw_arg_t *res, fgw_error_t ret) +{ + if (ret != 0) + return -1; + + if (fgw_arg_conv(&pcb_fgw, res, FGW_INT) != 0) + return -1; + + return res->val.nat_int; +} + +/* Call an action function directly, bypassing fungw; evaluates to an int + that is 0 on success */ +#define PCB_ACT_CALL_C(func, res, argc, argv) \ + pcb_act_result(res, func(res, argc, argv)) + +/* Require argument idx to exist and convert it to type; on success, also execute stmt */ +#define PCB_ACT_CONVARG(idx, type, aname, stmt) \ +do { \ + if (argc <= idx) { \ + PCB_ACT_FAIL(aname); \ + return FGW_ERR_ARGC; \ + } \ + if (fgw_arg_conv(&pcb_fgw, &argv[idx], type) != 0) { \ + PCB_ACT_FAIL(aname); \ + return FGW_ERR_ARG_CONV; \ + } \ + { stmt; } \ +} while(0) + +/* If argument idx exists, convert it to type; on success, also execute stmt */ +#define PCB_ACT_MAY_CONVARG(idx, type, aname, stmt) \ +do { \ + if (argc > idx) { \ + if (fgw_arg_conv(&pcb_fgw, &argv[idx], type) != 0) { \ + PCB_ACT_FAIL(aname); \ + return FGW_ERR_ARG_CONV; \ + } \ + { stmt; } \ + } \ +} while(0) + +/* Set integer res value */ +#define PCB_ACT_IRES(v) \ +do { \ + res->type = FGW_INT; \ + res->val.nat_int = v; \ +} while(0) + +/* Set double res value */ +#define PCB_ACT_DRES(v) \ +do { \ + res->type = FGW_DOUBLE; \ + res->val.nat_double = v; \ +} while(0) + +#define PCB_ACT_FAIL(x) { pcb_message(PCB_MSG_ERROR, "Syntax error. Usage:\n%s\n", (pcb_acts_ ## x)); return FGW_ERR_ARG_CONV; } + +/*** The default unit to use when a coord value doesn't have its own unit ***/ +extern char *fgw_str2coord_unit; /* saved is char * too */ +#define fgw_str2coord_unit_set(saved, newval) \ +do { \ + saved = fgw_str2coord_unit; \ + fgw_str2coord_unit = newval; \ +} while(0) + +#define fgw_str2coord_unit_restore(saved) \ + fgw_str2coord_unit = saved + +#endif Index: tags/2.1.2/src/actions_pcb.c =================================================================== --- tags/2.1.2/src/actions_pcb.c (nonexistent) +++ tags/2.1.2/src/actions_pcb.c (revision 24813) @@ -0,0 +1,189 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2019 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +/* fungw type extensions for pcb-rnd-only actions (not part of the hidlib) */ + +#include "config.h" + +#include + +#include + +#include "actions.h" +#include "board.h" +#include "data.h" +#include "compat_misc.h" +#include "layer.h" +#include "pcb-printf.h" +#include "conf_core.h" + +#define conv_str2layerid(dst, src) \ +do { \ + pcb_layer_id_t lid = pcb_layer_str2id(PCB->Data, src); \ + if (lid < 0) \ + return -1; \ + dst = lid; \ +} while(0) + +static int layerid_arg_conv(fgw_ctx_t *ctx, fgw_arg_t *arg, fgw_type_t target) +{ + if (target == FGW_LAYERID) { /* convert to layer id */ + pcb_layer_id_t tmp; + switch(FGW_BASE_TYPE(arg->type)) { + ARG_CONV_CASE_LONG(tmp, conv_assign) + ARG_CONV_CASE_LLONG(tmp, conv_assign) + ARG_CONV_CASE_DOUBLE(tmp, conv_assign) + ARG_CONV_CASE_LDOUBLE(tmp, conv_assign) + ARG_CONV_CASE_STR(tmp, conv_str2layerid) + ARG_CONV_CASE_PTR(tmp, conv_err) + ARG_CONV_CASE_CLASS(tmp, conv_err) + ARG_CONV_CASE_INVALID(tmp, conv_err) + } + arg->type = FGW_LAYERID; + fgw_layerid(arg) = tmp; + return 0; + } + if (arg->type == FGW_LAYERID) { /* convert from layer id */ + pcb_layer_id_t tmp = fgw_layerid(arg); + switch(target) { + ARG_CONV_CASE_LONG(tmp, conv_rev_assign) + ARG_CONV_CASE_LLONG(tmp, conv_rev_assign) + ARG_CONV_CASE_DOUBLE(tmp, conv_rev_assign) + ARG_CONV_CASE_LDOUBLE(tmp, conv_rev_assign) + ARG_CONV_CASE_PTR(tmp, conv_err) + ARG_CONV_CASE_CLASS(tmp, conv_err) + ARG_CONV_CASE_INVALID(tmp, conv_err) + case FGW_STR: + arg->val.str = (char *)pcb_strdup_printf("#%ld", (long)tmp); + arg->type = FGW_STR | FGW_DYN; + return 0; + } + arg->type = target; + return 0; + } + fprintf(stderr, "Neither side of the conversion is layer id\n"); + abort(); +} + +static int layer_arg_conv(fgw_ctx_t *ctx, fgw_arg_t *arg, fgw_type_t target) +{ + if (target == FGW_LAYER) { /* convert to layer */ + pcb_layer_id_t lid; + if (layerid_arg_conv(ctx, arg, FGW_LAYERID) != 0) + return -1; + lid = fgw_layerid(arg); + arg->val.ptr_void = pcb_get_layer(PCB->Data, lid); + if (arg->val.ptr_void == NULL) { + arg->type = FGW_INVALID; + return -1; + } + arg->type = FGW_LAYER; + return 0; + } + if (arg->type == FGW_LAYER) { /* convert from layer */ + pcb_layer_id_t lid; + pcb_layer_t *ly = arg->val.ptr_void; + pcb_data_t *data; + if (ly == NULL) + return -1; + data = ly->parent.data; + lid = ly - data->Layer; + if ((lid >= 0) && (lid < data->LayerN)) { + arg->type = FGW_LAYERID; + arg->val.nat_long = lid; + if (layerid_arg_conv(ctx, arg, target) != 0) + return -1; + return 0; + } + return -1; + } + fprintf(stderr, "Neither side of the conversion is layer\n"); + abort(); +} + +static int data_arg_conv(fgw_ctx_t *ctx, fgw_arg_t *arg, fgw_type_t target) +{ + if (target == FGW_DATA) { /* convert to data */ + if (FGW_BASE_TYPE(arg->type) == FGW_STR) { + if (pcb_strcasecmp(arg->val.str, "pcb") == 0) { + arg->val.ptr_void = PCB->Data; + arg->type = FGW_DATA; + return 0; + } + else if (pcb_strncasecmp(arg->val.str, "buffer#", 7) == 0) { + char *end; + long idx = strtol(arg->val.str+7, &end, 10); + if ((*end == '\0') && (idx >= 0) && (idx < PCB_MAX_BUFFER)) { + arg->val.ptr_void = pcb_buffers[idx].Data; + arg->type = FGW_DATA; + return 0; + } + } + else if (pcb_strcasecmp(arg->val.str, "buffer") == 0) { + arg->val.ptr_void = PCB_PASTEBUFFER->Data; + arg->type = FGW_DATA; + return 0; + } + } + arg->type = FGW_INVALID; + return -1; + } + if (arg->type == FGW_DATA) { /* convert from layer */ + int n; + if (arg->val.ptr_void == PCB->Data) { + arg->val.str = "pcb"; + arg->type = FGW_STR; + return 0; + } + for(n = 0; n < PCB_MAX_BUFFER; n++) { + if (arg->val.ptr_void == pcb_buffers[n].Data) { + arg->val.str = pcb_strdup_printf("buffer#%d", n); + arg->type = FGW_STR | FGW_DYN; + return 0; + } + } + arg->type = FGW_INVALID; + return -1; + } + fprintf(stderr, "Neither side of the conversion is data\n"); + abort(); +} + +void pcb_actions_init_pcb_only(void) +{ + if (fgw_reg_custom_type(&pcb_fgw, FGW_LAYERID, "layerid", layerid_arg_conv, NULL) != FGW_LAYERID) { + fprintf(stderr, "pcb_actions_init: failed to register FGW_LAYERID\n"); + abort(); + } + if (fgw_reg_custom_type(&pcb_fgw, FGW_LAYER, "layer", layer_arg_conv, NULL) != FGW_LAYER) { + fprintf(stderr, "pcb_actions_init: failed to register FGW_LAYER\n"); + abort(); + } + if (fgw_reg_custom_type(&pcb_fgw, FGW_DATA, "data", data_arg_conv, NULL) != FGW_DATA) { + fprintf(stderr, "pcb_actions_init: failed to register FGW_DATA\n"); + abort(); + } +} Index: tags/2.1.2/src/actions_pcb.h =================================================================== --- tags/2.1.2/src/actions_pcb.h (nonexistent) +++ tags/2.1.2/src/actions_pcb.h (revision 24813) @@ -0,0 +1 @@ +void pcb_actions_init_pcb_only(void); Index: tags/2.1.2/src/attrib.c =================================================================== --- tags/2.1.2/src/attrib.c (nonexistent) +++ tags/2.1.2/src/attrib.c (revision 24813) @@ -0,0 +1,178 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996,2004,2006 Thomas Nau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +/* attribute lists */ +#include +#include +#include +#include "config.h" +#include "compat_misc.h" +#include "attrib.h" + +#define NOTIFY(list, name, value) \ +do { \ + if (list->post_change != NULL) \ + list->post_change(list, name, value); \ +} while(0) + +char *pcb_attribute_get(const pcb_attribute_list_t *list, const char *name) +{ + int i; + for (i = 0; i < list->Number; i++) + if (strcmp(name, list->List[i].name) == 0) + return list->List[i].value; + return NULL; +} + +int pcb_attribute_put(pcb_attribute_list_t * list, const char *name, const char *value) +{ + int i; + + if ((name == NULL) || (*name == '\0')) + return -1; + + /* Replace an existing attribute if there is a name match. */ + for (i = 0; i < list->Number; i++) { + if (strcmp(name, list->List[i].name) == 0) { + free(list->List[i].value); + list->List[i].value = pcb_strdup_null(value); + NOTIFY(list, list->List[i].name, list->List[i].value); + return 1; + } + } + + /* At this point, we're going to need to add a new attribute to the + list. See if there's room. */ + if (list->Number >= list->Max) { + list->Max += 10; + list->List = (pcb_attribute_t *) realloc(list->List, list->Max * sizeof(pcb_attribute_t)); + } + + /* Now add the new attribute. */ + i = list->Number; + list->List[i].name = pcb_strdup_null(name); + list->List[i].value = pcb_strdup_null(value); + list->List[i].cpb_written = 1; + NOTIFY(list, list->List[i].name, list->List[i].value); + list->Number++; + return 0; +} + +int pcb_attribute_remove_idx(pcb_attribute_list_t * list, int idx) +{ + int j; + char *old_name = list->List[idx].name, *old_value = list->List[idx].value; + + for (j = idx; j < list->Number-1; j++) + list->List[j] = list->List[j + 1]; + list->Number--; + + NOTIFY(list, old_name, NULL); + free(old_name); + free(old_value); + return 0; +} + +int pcb_attribute_remove(pcb_attribute_list_t * list, const char *name) +{ + int i, found = 0; + for (i = 0; i < list->Number; i++) + if (strcmp(name, list->List[i].name) == 0) { + found++; + pcb_attribute_remove_idx(list, i); + } + return found; +} + +void pcb_attribute_free(pcb_attribute_list_t *list) +{ + int i; + + for (i = 0; i < list->Number; i++) { + free(list->List[i].name); + free(list->List[i].value); + } + free(list->List); + list->List = NULL; + list->Max = 0; +} + +void pcb_attribute_copy_all(pcb_attribute_list_t *dest, const pcb_attribute_list_t *src) +{ + int i; + + for (i = 0; i < src->Number; i++) + pcb_attribute_put(dest, src->List[i].name, src->List[i].value); +} + + +void pcb_attribute_copyback_begin(pcb_attribute_list_t *dst) +{ + int i; + + for (i = 0; i < dst->Number; i++) + dst->List[i].cpb_written = 0; +} + +void pcb_attribute_copyback(pcb_attribute_list_t *dst, const char *name, const char *value) +{ + int i; + for (i = 0; i < dst->Number; i++) { + if (strcmp(name, dst->List[i].name) == 0) { + dst->List[i].cpb_written = 1; + if (strcmp(value, dst->List[i].value) != 0) { + free(dst->List[i].value); + dst->List[i].value = pcb_strdup(value); + NOTIFY(dst, dst->List[i].name, dst->List[i].value); + } + return; + } + } + pcb_attribute_put(dst, name, value); +} + +void pcb_attribute_copyback_end(pcb_attribute_list_t *dst) +{ + int i; + for (i = 0; i < dst->Number; i++) + if (!dst->List[i].cpb_written) + pcb_attribute_remove_idx(dst, i); +} + + +void pcb_attrib_compat_set_intconn(pcb_attribute_list_t *dst, int intconn) +{ + char buff[32]; + + if (intconn <= 0) + return; + + sprintf(buff, "%d", intconn & 0xFF); + pcb_attribute_put(dst, "intconn", buff); +} + Index: tags/2.1.2/src/attrib.h =================================================================== --- tags/2.1.2/src/attrib.h (nonexistent) +++ tags/2.1.2/src/attrib.h (revision 24813) @@ -0,0 +1,81 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996,2006 Thomas Nau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +/* attribute lists */ + +#ifndef PCB_ATTRIB_H +#define PCB_ATTRIB_H + +typedef struct pcb_attribute_list_s pcb_attribute_list_t; + +typedef struct pcb_attribute_s { + char *name; + char *value; + unsigned cpb_written:1; /* copyback: written */ +} pcb_attribute_t; + +struct pcb_attribute_list_s { + int Number, Max; + pcb_attribute_t *List; + void (*post_change)(pcb_attribute_list_t *list, const char *name, const char *value); /* called after put or remove, but not after free(); value is NULL if removed */ +}; + +/* Returns NULL if the name isn't found, else the value for that named + attribute. */ +char *pcb_attribute_get(const pcb_attribute_list_t *list, const char *name); + +/* Adds an attribute to the list. If the attribute already exists, the value + is replaced. Returns non-zero if an existing attribute was replaced. */ +int pcb_attribute_put(pcb_attribute_list_t * list, const char *name, const char *value); +/* Simplistic version: Takes a pointer to an object, looks up attributes in it. */ +#define pcb_attrib_get(OBJ,name) pcb_attribute_get(&(OBJ->Attributes), name) +/* Simplistic version: Takes a pointer to an object, sets attributes in it. */ +#define pcb_attrib_put(OBJ,name,value) pcb_attribute_put(&(OBJ->Attributes), name, value) +/* Remove an attribute by name; returns number of items removed */ +int pcb_attribute_remove(pcb_attribute_list_t * list, const char *name); +/* Simplistic version of Remove. */ +#define pcb_attrib_remove(OBJ, name) pcb_attribute_remove(&(OBJ->Attributes), name) + +/* remove item by index - WARNING: no checks are made, idx has to be valid! */ +int pcb_attribute_remove_idx(pcb_attribute_list_t * list, int idx); + +/* Frees memory used by an attribute list */ +void pcb_attribute_free(pcb_attribute_list_t *list); + +/* Copy each attribute from src to dest */ +void pcb_attribute_copy_all(pcb_attribute_list_t *dest, const pcb_attribute_list_t *src); + +/* Copy back a mirrored attribute list, minimizing the changes */ +void pcb_attribute_copyback_begin(pcb_attribute_list_t *dst); +void pcb_attribute_copyback(pcb_attribute_list_t *dst, const char *name, const char *value); +void pcb_attribute_copyback_end(pcb_attribute_list_t *dst); + +/* Set the intconn attribute - hack for compatibility parsing */ +void pcb_attrib_compat_set_intconn(pcb_attribute_list_t *dst, int intconn); + +#endif Index: tags/2.1.2/src/board.c =================================================================== --- tags/2.1.2/src/board.c (nonexistent) +++ tags/2.1.2/src/board.c (revision 24813) @@ -0,0 +1,390 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ +#include "config.h" +#include "board.h" +#include "data.h" +#include "conf_core.h" +#include "plug_io.h" +#include "compat_misc.h" +#include "actions.h" +#include "paths.h" +#include "rtree.h" +#include "undo.h" +#include "draw.h" +#include "event.h" +#include "safe_fs.h" +#include "tool.h" +#include "layer.h" +#include "netlist2.h" + +pcb_board_t *PCB; + +void pcb_board_free(pcb_board_t * pcb) +{ + int i; + + if (pcb == NULL) + return; + + free(pcb->Name); + free(pcb->Filename); + free(pcb->PrintFilename); + pcb_ratspatch_destroy(pcb); + pcb_data_free(pcb->Data); + + /* release font symbols */ + pcb_fontkit_free(&pcb->fontkit); + for (i = 0; i < PCB_NUM_NETLISTS; i++) + pcb_netlist_uninit(&(pcb->netlist[i])); + vtroutestyle_uninit(&pcb->RouteStyle); + pcb_attribute_free(&pcb->Attributes); + + pcb_layergroup_free_stack(&pcb->LayerGroups); + + /* clear struct */ + memset(pcb, 0, sizeof(pcb_board_t)); +} + +/* creates a new PCB */ +pcb_board_t *pcb_board_new_(pcb_bool SetDefaultNames) +{ + pcb_board_t *ptr; + int i; + + /* allocate memory, switch all layers on and copy resources */ + ptr = calloc(1, sizeof(pcb_board_t)); + ptr->Data = pcb_buffer_new(ptr); + + for(i = 0; i < PCB_NUM_NETLISTS; i++) + pcb_netlist_init(&(ptr->netlist[i])); + + conf_set(CFR_INTERNAL, "design/poly_isle_area", -1, "200000000", POL_OVERWRITE); + + ptr->RatDraw = pcb_false; + + /* NOTE: we used to set all the pcb flags on ptr here, but we don't need to do that anymore due to the new conf system */ + ptr->Grid = conf_core.editor.grid; + + ptr->MaxHeight = ptr->MaxWidth = PCB_MM_TO_COORD(20); /* should be overriden by the default design */ + ptr->ID = pcb_create_ID_get(); + ptr->ThermScale = 0.5; + + pcb_font_create_default(ptr); + + return ptr; +} + +#include "defpcb_internal.c" + +pcb_board_t *pcb_board_new(int inhibit_events) +{ + pcb_board_t *old, *nw = NULL; + int dpcb; + unsigned int inh = inhibit_events ? PCB_INHIBIT_BOARD_CHANGED : 0; + + old = PCB; + PCB = NULL; + + dpcb = -1; + pcb_io_err_inhibit_inc(); + conf_list_foreach_path_first(dpcb, &conf_core.rc.default_pcb_file, pcb_load_pcb(__path__, NULL, pcb_false, 1 | 0x10 | inh)); + pcb_io_err_inhibit_dec(); + + if (dpcb != 0) { /* no default PCB in file, use embedded version */ + FILE *f; + char *efn; + const char *tmp_fn = ".pcb-rnd.default.pcb"; + + /* We can parse from file only, make a temp file */ + f = pcb_fopen_fn(tmp_fn, "wb", &efn); + if (f != NULL) { + fwrite(default_pcb_internal, strlen(default_pcb_internal), 1, f); + fclose(f); + dpcb = pcb_load_pcb(efn, NULL, pcb_false, 1 | 0x10); + if (dpcb == 0) + pcb_message(PCB_MSG_WARNING, "Couldn't find default.pcb - using the embedded fallback\n"); + else + pcb_message(PCB_MSG_ERROR, "Couldn't find default.pcb and failed to load the embedded fallback\n"); + pcb_remove(efn); + free(efn); + } + } + + if (dpcb == 0) { + nw = PCB; + if (nw->Filename != NULL) { + /* make sure the new PCB doesn't inherit the name and loader of the default pcb */ + free(nw->Filename); + nw->Filename = NULL; + nw->Data->loader = NULL; + } + } + + pcb_event(PCB_EVENT_ROUTE_STYLES_CHANGED, NULL); + + PCB = old; + return nw; +} + +int pcb_board_new_postproc(pcb_board_t *pcb, int use_defaults) +{ + int n; + + /* copy default settings */ + pcb_layer_colors_from_conf(pcb, 0); + + for(n = 0; n < PCB_MAX_BUFFER; n++) { + if (pcb_buffers[n].Data != NULL) { + pcb_data_unbind_layers(pcb_buffers[n].Data); + pcb_data_binding_update(pcb, pcb_buffers[n].Data); + } + } + + return 0; +} + +void pcb_layer_colors_from_conf(pcb_board_t *ptr, int force) +{ + int i; + + /* copy default settings */ + for (i = 0; i < PCB_MAX_LAYER; i++) + if (force || (ptr->Data->Layer[i].meta.real.color.str[0] == '\0')) + memcpy(&ptr->Data->Layer[i].meta.real.color, pcb_layer_default_color(i, pcb_layer_flags(ptr, i)), sizeof(pcb_color_t)); +} + +typedef struct { + int nplated; + int nunplated; +} HoleCountStruct; + +TODO("padstack: move this to obj_pstk.c after pinvia removal") +#include "obj_pstk_inlines.h" +static pcb_r_dir_t hole_counting_callback(const pcb_box_t * b, void *cl) +{ + pcb_pstk_t *ps = (pcb_pstk_t *)b; + pcb_pstk_proto_t *proto = pcb_pstk_get_proto(ps); + HoleCountStruct *hcs = (HoleCountStruct *)cl; + + if ((proto != NULL) && (proto->hdia > 0)) { + if (proto->hplated) + hcs->nplated++; + else + hcs->nunplated++; + } + return PCB_R_DIR_FOUND_CONTINUE; +} + +static pcb_r_dir_t slot_counting_callback(const pcb_box_t *b, void *cl) +{ + pcb_pstk_t *ps = (pcb_pstk_t *)b; + pcb_pstk_proto_t *proto = pcb_pstk_get_proto(ps); + HoleCountStruct *hcs = (HoleCountStruct *)cl; + + if ((proto != NULL) && (proto->mech_idx >= 0)) { + if (proto->hplated) + hcs->nplated++; + else + hcs->nunplated++; + } + return PCB_R_DIR_FOUND_CONTINUE; +} + +void pcb_board_count_holes(pcb_board_t *pcb, int *plated, int *unplated, const pcb_box_t *within_area) +{ + HoleCountStruct hcs = { 0, 0 }; + + pcb_r_search(pcb->Data->padstack_tree, within_area, NULL, hole_counting_callback, &hcs, NULL); + + if (plated != NULL) + *plated = hcs.nplated; + if (unplated != NULL) + *unplated = hcs.nunplated; +} + +void pcb_board_count_slots(pcb_board_t *pcb, int *plated, int *unplated, const pcb_box_t *within_area) +{ + HoleCountStruct hcs = { 0, 0 }; + + pcb_r_search(pcb->Data->padstack_tree, within_area, NULL, slot_counting_callback, &hcs, NULL); + + if (plated != NULL) + *plated = hcs.nplated; + if (unplated != NULL) + *unplated = hcs.nunplated; +} + +const char *pcb_board_get_filename(void) +{ + return PCB->Filename; +} + +const char *pcb_board_get_name(void) +{ + return PCB->Name; +} + +pcb_bool pcb_board_change_name(char *Name) +{ + free(PCB->Name); + PCB->Name = Name; + pcb_board_changed(0); + return pcb_true; +} + +void pcb_board_resize(pcb_coord_t Width, pcb_coord_t Height) +{ + PCB->MaxWidth = Width; + PCB->MaxHeight = Height; + + /* crosshair range is different if pastebuffer-mode + * is enabled + */ + if (conf_core.editor.mode == PCB_MODE_PASTE_BUFFER) + pcb_crosshair_set_range(PCB_PASTEBUFFER->X - PCB_PASTEBUFFER->BoundingBox.X1, + PCB_PASTEBUFFER->Y - PCB_PASTEBUFFER->BoundingBox.Y1, + MAX(0, + Width - (PCB_PASTEBUFFER->BoundingBox.X2 - + PCB_PASTEBUFFER->X)), MAX(0, Height - (PCB_PASTEBUFFER->BoundingBox.Y2 - PCB_PASTEBUFFER->Y))); + else + pcb_crosshair_set_range(0, 0, Width, Height); + + pcb_board_changed(0); +} + +void pcb_board_remove(pcb_board_t *Ptr) +{ + pcb_undo_clear_list(pcb_true); + pcb_board_free(Ptr); + free(Ptr); +} + +/* sets cursor grid with respect to grid offset values */ +void pcb_board_set_grid(pcb_coord_t Grid, pcb_bool align, pcb_coord_t ox, pcb_coord_t oy) +{ + if (Grid >= 1 && Grid <= PCB_MAX_GRID) { + if (align) { + PCB->GridOffsetX = ox % Grid; + PCB->GridOffsetY = oy % Grid; + } + PCB->Grid = Grid; + conf_set_design("editor/grid", "%$mS", Grid); + if (conf_core.editor.draw_grid) + pcb_redraw(); + } +} + +void pcb_board_set_unit(pcb_board_t *pcb, const pcb_unit_t *new_unit) +{ + if (new_unit != NULL && new_unit->allow != PCB_UNIT_NO_PRINT) { + conf_set(CFR_DESIGN, "editor/grid_unit", -1, new_unit->suffix, POL_OVERWRITE); + pcb_attrib_put(pcb, "PCB::grid::unit", new_unit->suffix); + } +} + +/* sets a new line thickness */ +void pcb_board_set_line_width(pcb_coord_t Size) +{ + if (Size >= PCB_MIN_LINESIZE && Size <= PCB_MAX_LINESIZE) { + conf_set_design("design/line_thickness", "%$mS", Size); + if (conf_core.editor.auto_drc) + pcb_crosshair_grid_fit(pcb_crosshair.X, pcb_crosshair.Y); + } +} + +/* sets a new via thickness */ +void pcb_board_set_via_size(pcb_coord_t Size, pcb_bool Force) +{ + if (Force || (Size <= PCB_MAX_PINORVIASIZE && Size >= PCB_MIN_PINORVIASIZE && Size >= conf_core.design.via_drilling_hole + PCB_MIN_PINORVIACOPPER)) { + conf_set_design("design/via_thickness", "%$mS", Size); + } +} + +/* sets a new via drilling hole */ +void pcb_board_set_via_drilling_hole(pcb_coord_t Size, pcb_bool Force) +{ + if (Force || (Size <= PCB_MAX_PINORVIASIZE && Size >= PCB_MIN_PINORVIAHOLE && Size <= conf_core.design.via_thickness - PCB_MIN_PINORVIACOPPER)) { + conf_set_design("design/via_drilling_hole", "%$mS", Size); + } +} + +/* sets a clearance width */ +void pcb_board_set_clearance(pcb_coord_t Width) +{ + if (Width <= PCB_MAX_LINESIZE) { + conf_set_design("design/clearance", "%$mS", Width); + } +} + +/* sets a text scaling */ +void pcb_board_set_text_scale(int Scale) +{ + if (Scale <= PCB_MAX_TEXTSCALE && Scale >= PCB_MIN_TEXTSCALE) { + conf_set_design("design/text_scale", "%d", Scale); + } +} + +/* sets or resets changed flag and redraws status */ +void pcb_board_set_changed_flag(pcb_bool New) +{ + pcb_bool old = PCB->Changed; + + PCB->Changed = New; + + if (old != New) + pcb_event(PCB_EVENT_BOARD_META_CHANGED, NULL); +} + + +void pcb_board_changed(int reverted) +{ + pcb_event(PCB_EVENT_BOARD_CHANGED, "i", reverted); +} + +int pcb_board_normalize(pcb_board_t *pcb) +{ + pcb_box_t b; + int chg = 0; + + if (pcb_data_bbox(&b, pcb->Data, pcb_false) == NULL) + return -1; + + if ((b.X2 - b.X1) > pcb->MaxWidth) { + pcb->MaxWidth = b.X2 - b.X1; + chg++; + } + + if ((b.Y2 - b.Y1) > pcb->MaxHeight) { + pcb->MaxHeight = b.Y2 - b.Y1; + chg++; + } + + chg += pcb_data_normalize_(pcb->Data, &b); + + return chg; +} Index: tags/2.1.2/src/board.h =================================================================== --- tags/2.1.2/src/board.h (nonexistent) +++ tags/2.1.2/src/board.h (revision 24813) @@ -0,0 +1,189 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996, 2004 Thomas Nau + * 15 Oct 2008 Ineiev: add different crosshair shapes + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +/* definition of types */ +#ifndef PCB_BOARD_H +#define PCB_BOARD_H + +#include "config.h" + +enum { + PCB_NETLIST_INPUT = 0, /* index of the original netlist as imported */ + PCB_NETLIST_EDITED = 1, /* index of the netlist produced by applying netlist patches on [PCB_NETLIST_INPUT] */ + PCB_NUM_NETLISTS /* so that we know how many netlists we are dealing with */ +}; + +#include +#include +#include +#include +#include +#include +#include + +#include "global_typedefs.h" +#include "vtroutestyle.h" +#include "layer.h" +#include "layer_grp.h" +#include "attrib.h" +#include "rats_patch.h" +#include "font.h" + +typedef htsp_t pcb_netlist_t; + + /* The pcb_board_t struct holds information about board layout most of which is + | saved with the layout. A new PCB layout struct is first initialized + | with values from the user configurable Settings struct and then reset + | to the saved layout values when a layout is loaded. + | This struct is also used for the remove list and for buffer handling + */ +struct pcb_board_s { + long ID; + char *Name; /* name of board */ + char *Filename; /* name of file (from load) */ + char *PrintFilename; /* from print dialog */ + char *Netlistname; /* name of netlist file */ + + pcb_bool Changed; /* layout has been changed */ + + pcb_bool pstk_on, RatOn, InvisibleObjectsOn, + SubcOn, SubcPartsOn, + padstack_mark_on, hole_on; /* visibility flags */ + pcb_bool RatDraw; /* we're drawing rats */ + + pcb_bool loose_subc; /* when set, subc parts are not locked into the subc */ + pcb_coord_t Grid, GridOffsetX, GridOffsetY; /* as saved with layout */ + pcb_coord_t MaxWidth, MaxHeight; /* board dimensions (drawing area extents) */ + + double ThermScale; /* scale factor used with thermals */ + + pcb_fontkit_t fontkit; + pcb_layer_stack_t LayerGroups; + vtroutestyle_t RouteStyle; + pcb_netlist_t netlist[PCB_NUM_NETLISTS]; + /* htsp_t netlist_subc[PCB_NUM_NETLISTS]; hierarchic netlists */ + pcb_ratspatch_line_t *NetlistPatches, *NetlistPatchLast; + pcb_attribute_list_t Attributes; + + pcb_data_t *Data; /* entire database */ + pcb_bool is_footprint; /* If set, the user has loaded a footprint, not a pcb. */ + + const pcb_attribute_list_t *pen_attr; + +/* netlist states */ + int netlist_frozen; /* counter */ + unsigned netlist_needs_update:1; +}; + +extern pcb_board_t *PCB; /* the board being edited */ + +/* free memory used by a board */ +void pcb_board_free(pcb_board_t *pcb); + +/* creates a new PCB - low level */ +pcb_board_t *pcb_board_new_(pcb_bool SetDefaultNames); + +/* creates a new PCB - high level (uses a template board); does not generate + new board event if inhibit_events is set */ +pcb_board_t *pcb_board_new(int inhibit_events); + +/* Called after PCB->Data->LayerN is set. Returns non-zero on error */ +int pcb_board_new_postproc(pcb_board_t *pcb, int use_defaults); + +/* Set the color field of each layer that does not yet have an explicit + color, from the config, using default colors per layer type. If + force is non-zero, overwrite even existing colors. */ +void pcb_layer_colors_from_conf(pcb_board_t *pcb, int force); + +/* counts the number of plated and unplated holes or slots in the design within + a given area of the board. To count for the whole board, pass NULL within_area. */ +void pcb_board_count_holes(pcb_board_t *pcb, int *plated, int *unplated, const pcb_box_t *within_area); +void pcb_board_count_slots(pcb_board_t *pcb, int *plated, int *unplated, const pcb_box_t *within_area); + +#define PCB_SWAP_X(x) (PCB_SWAP_SIGN_X(x)) +#define PCB_SWAP_Y(y) (PCB->MaxHeight +PCB_SWAP_SIGN_Y(y)) + +#define PCB_CSWAP_X(x, w, cond) ((cond) ? (PCB_SWAP_SIGN_X(x)) : (x)) +#define PCB_CSWAP_Y(y, h, cond) ((cond) ? (h+PCB_SWAP_SIGN_Y(y)) : (y)) + +/* Conditionally allow subc parts to be reached directly in search masks */ +#define PCB_LOOSE_SUBC (PCB->loose_subc ? PCB_OBJ_SUBC_PART : 0) + + +/* changes the name of a layout; Name is allocated by the caller (no strdup() is made) */ +pcb_bool pcb_board_change_name(char *Name); + +/* changes the maximum size of a layout, notifies the GUI + * and adjusts the cursor confinement box */ +void pcb_board_resize(pcb_coord_t Width, pcb_coord_t Height); + + +/* free the board and remove its undo list */ +void pcb_board_remove(pcb_board_t *Ptr); + +/* sets cursor grid with respect to grid offset values or default unit*/ +void pcb_board_set_grid(pcb_coord_t Grid, pcb_bool align, pcb_coord_t ox, pcb_coord_t oy); +void pcb_board_set_unit(pcb_board_t *pcb, const pcb_unit_t *new_unit); + + +/* sets a new line thickness */ +void pcb_board_set_line_width(pcb_coord_t Size); + +/* sets a new via thickness */ +void pcb_board_set_via_size(pcb_coord_t Size, pcb_bool Force); + +/* sets a new via drilling hole */ +void pcb_board_set_via_drilling_hole(pcb_coord_t Size, pcb_bool Force); + +/* sets a clearance width */ +void pcb_board_set_clearance(pcb_coord_t Width); + +/* sets a text scaling */ +void pcb_board_set_text_scale(int Scale); + +/* make sure the data of the board fits the PCB (move it out from negative, + make the board large enough); returns -1 on error, the number of changes on success */ +int pcb_board_normalize(pcb_board_t *pcb); + +/* sets or resets changed flag and redraws status */ +void pcb_board_set_changed_flag(pcb_bool New); + +/* Shorthand for emitting a board changed event (PCB_EVENT_BOARD_CHANGED) */ +void pcb_board_changed(int reverted); + + +/* pcb_board_t field accessors - do not use; required for path.[ch] to not depend on board.h */ +const char *pcb_board_get_filename(void); +const char *pcb_board_get_name(void); + +/* Update the bounding box of the subc being edited as board; if the + board is not a subc, this call is a NOP; implemented in obj_subc.c */ +void pcb_subc_as_board_update(pcb_board_t *pcb); + +#endif Index: tags/2.1.2/src/box.c =================================================================== --- tags/2.1.2/src/box.c (nonexistent) +++ tags/2.1.2/src/box.c (revision 24813) @@ -0,0 +1,63 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * Copyright (C) 2017 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +#include "config.h" + +#include +#include "rotate.h" +#include "box.h" + +void pcb_set_point_bounding_box(pcb_point_t *Pnt) +{ + Pnt->X2 = Pnt->X + 1; + Pnt->Y2 = Pnt->Y + 1; +} + +void pcb_box_rotate90(pcb_box_t *Box, pcb_coord_t X, pcb_coord_t Y, unsigned Number) +{ + pcb_coord_t x1 = Box->X1, y1 = Box->Y1, x2 = Box->X2, y2 = Box->Y2; + + PCB_COORD_ROTATE90(x1, y1, X, Y, Number); + PCB_COORD_ROTATE90(x2, y2, X, Y, Number); + Box->X1 = MIN(x1, x2); + Box->Y1 = MIN(y1, y2); + Box->X2 = MAX(x1, x2); + Box->Y2 = MAX(y1, y2); +} + +void pcb_box_enlarge(pcb_box_t *box, double xfactor, double yfactor) +{ + double w = (double)(box->X2 - box->X1) * xfactor / 2.0; + double h = (double)(box->Y2 - box->Y1) * yfactor / 2.0; + + box->X1 = pcb_round(box->X1 - w); + box->Y1 = pcb_round(box->Y1 - h); + box->X2 = pcb_round(box->X2 + w); + box->Y2 = pcb_round(box->Y2 + h); +} Index: tags/2.1.2/src/box.h =================================================================== --- tags/2.1.2/src/box.h (nonexistent) +++ tags/2.1.2/src/box.h (revision 24813) @@ -0,0 +1,267 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * Copyright (C) 1998,1999,2000,2001 harry eaton + * + * this file, box.h, was written and is + * Copyright (c) 2001 C. Scott Ananian. + * + * Copyright (C) 2017 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + * + * Old contact info: + * harry eaton, 6697 Buttonhole Ct, Columbia, MD 21044 USA + * haceaton@aplcomm.jhuapl.edu + * + */ + + +/* random box-related utilities. */ + +#ifndef PCB_BOX_H +#define PCB_BOX_H + +#include +#include "math_helper.h" +#include "global_typedefs.h" +#include "config.h" +#include "obj_common.h" + +struct pcb_box_list_s { + pcb_cardinal_t BoxN, /* the number of boxes contained */ + BoxMax; /* max boxes from malloc */ + pcb_box_t *Box; +}; + +#include "misc_util.h" + +typedef enum { + PCB_NORTH = 0, PCB_EAST = 1, PCB_SOUTH = 2, PCB_WEST = 3, + PCB_NE = 4, PCB_SE = 5, PCB_SW = 6, PCB_NW = 7, + PCB_ANY_DIR = 8 +} pcb_direction_t; + +/* rotates box 90-degrees cw */ +/* that's a strange rotation! */ +#define PCB_BOX_ROTATE_CW(box) { pcb_coord_t t;\ + t = (box).X1; (box).X1 = -(box).Y2; (box).Y2 = (box).X2;\ + (box).X2 = -(box).Y1; (box).Y1 = t;\ +} +#define PCB_BOX_ROTATE_TO_NORTH(box, dir) do { pcb_coord_t t;\ + switch(dir) {\ + case PCB_EAST: \ + t = (box).X1; (box).X1 = (box).Y1; (box).Y1 = -(box).X2;\ + (box).X2 = (box).Y2; (box).Y2 = -t; break;\ + case PCB_SOUTH: \ + t = (box).X1; (box).X1 = -(box).X2; (box).X2 = -t;\ + t = (box).Y1; (box).Y1 = -(box).Y2; (box).Y2 = -t; break;\ + case PCB_WEST: \ + t = (box).X1; (box).X1 = -(box).Y2; (box).Y2 = (box).X2;\ + (box).X2 = -(box).Y1; (box).Y1 = t; break;\ + case PCB_NORTH: break;\ + default: assert(0);\ + }\ + } while (0) +#define PCB_BOX_ROTATE_FROM_NORTH(box, dir) do { pcb_coord_t t;\ + switch(dir) {\ + case PCB_WEST: \ + t = (box).X1; (box).X1 = (box).Y1; (box).Y1 = -(box).X2;\ + (box).X2 = (box).Y2; (box).Y2 = -t; break;\ + case PCB_SOUTH: \ + t = (box).X1; (box).X1 = -(box).X2; (box).X2 = -t;\ + t = (box).Y1; (box).Y1 = -(box).Y2; (box).Y2 = -t; break;\ + case PCB_EAST: \ + t = (box).X1; (box).X1 = -(box).Y2; (box).Y2 = (box).X2;\ + (box).X2 = -(box).Y1; (box).Y1 = t; break;\ + case PCB_NORTH: break;\ + default: assert(0);\ + }\ + } while (0) + +/* to avoid overflow, we calculate centers this way */ +#define PCB_BOX_CENTER_X(b) ((b).X1 + ((b).X2 - (b).X1)/2) +#define PCB_BOX_CENTER_Y(b) ((b).Y1 + ((b).Y2 - (b).Y1)/2) + +#define PCB_MOVE_POINT(xs,ys,deltax,deltay) \ + do { \ + ((xs) += (deltax)); \ + ((ys) += (deltay)); \ + } while(0) + +#define PCB_BOX_MOVE_LOWLEVEL(b,dx,dy) \ + do { \ + PCB_MOVE_POINT((b)->X1,(b)->Y1,(dx),(dy)); \ + PCB_MOVE_POINT((b)->X2,(b)->Y2,(dx),(dy)); \ + } while(0) + + +typedef struct pcb_cheap_point_s { + pcb_coord_t X, Y; +} pcb_cheap_point_t; + + +/* note that boxes are closed on top and left and open on bottom and right. */ +/* this means that top-left corner is in box, *but bottom-right corner is + * not*. */ +PCB_INLINE pcb_bool pcb_point_in_box(const pcb_box_t * box, pcb_coord_t X, pcb_coord_t Y) +{ + return (X >= box->X1) && (Y >= box->Y1) && (X < box->X2) && (Y < box->Y2); +} + +PCB_INLINE pcb_bool pcb_point_in_closed_box(const pcb_box_t * box, pcb_coord_t X, pcb_coord_t Y) +{ + return (X >= box->X1) && (Y >= box->Y1) && (X <= box->X2) && (Y <= box->Y2); +} + +PCB_INLINE pcb_bool pcb_box_is_good(const pcb_box_t * b) +{ + return (b->X1 < b->X2) && (b->Y1 < b->Y2); +} + +PCB_INLINE pcb_bool pcb_box_intersect(const pcb_box_t * a, const pcb_box_t * b) +{ + return (a->X1 < b->X2) && (b->X1 < a->X2) && (a->Y1 < b->Y2) && (b->Y1 < a->Y2); +} + +PCB_INLINE pcb_cheap_point_t pcb_closest_pcb_point_in_box(const pcb_cheap_point_t * from, const pcb_box_t * box) +{ + pcb_cheap_point_t r; + assert(box->X1 < box->X2 && box->Y1 < box->Y2); + r.X = (from->X < box->X1) ? box->X1 : (from->X > box->X2 - 1) ? box->X2 - 1 : from->X; + r.Y = (from->Y < box->Y1) ? box->Y1 : (from->Y > box->Y2 - 1) ? box->Y2 - 1 : from->Y; + assert(pcb_point_in_box(box, r.X, r.Y)); + return r; +} + +PCB_INLINE pcb_bool pcb_box_in_box(const pcb_box_t * outer, const pcb_box_t * inner) +{ + return (outer->X1 <= inner->X1) && (inner->X2 <= outer->X2) && (outer->Y1 <= inner->Y1) && (inner->Y2 <= outer->Y2); +} + +PCB_INLINE pcb_box_t pcb_clip_box(const pcb_box_t * box, const pcb_box_t * clipbox) +{ + pcb_box_t r; + assert(pcb_box_intersect(box, clipbox)); + r.X1 = MAX(box->X1, clipbox->X1); + r.X2 = MIN(box->X2, clipbox->X2); + r.Y1 = MAX(box->Y1, clipbox->Y1); + r.Y2 = MIN(box->Y2, clipbox->Y2); + assert(pcb_box_in_box(clipbox, &r)); + return r; +} + +PCB_INLINE pcb_box_t pcb_shrink_box(const pcb_box_t * box, pcb_coord_t amount) +{ + pcb_box_t r = *box; + r.X1 += amount; + r.Y1 += amount; + r.X2 -= amount; + r.Y2 -= amount; + return r; +} + +PCB_INLINE pcb_box_t pcb_bloat_box(const pcb_box_t * box, pcb_coord_t amount) +{ + return pcb_shrink_box(box, -amount); +} + +/* construct a minimum box that touches the input box at the center */ +PCB_INLINE pcb_box_t pcb_box_center(const pcb_box_t * box) +{ + pcb_box_t r; + r.X1 = box->X1 + (box->X2 - box->X1) / 2; + r.X2 = r.X1 + 1; + r.Y1 = box->Y1 + (box->Y2 - box->Y1) / 2; + r.Y2 = r.Y1 + 1; + return r; +} + +/* construct a minimum box that touches the input box at the corner */ +PCB_INLINE pcb_box_t pcb_box_corner(const pcb_box_t * box) +{ + pcb_box_t r; + r.X1 = box->X1; + r.X2 = r.X1 + 1; + r.Y1 = box->Y1; + r.Y2 = r.Y1 + 1; + return r; +} + +/* construct a box that holds a single point */ +PCB_INLINE pcb_box_t pcb_point_box(pcb_coord_t X, pcb_coord_t Y) +{ + pcb_box_t r; + r.X1 = X; + r.X2 = X + 1; + r.Y1 = Y; + r.Y2 = Y + 1; + return r; +} + +/* close a bounding box by pushing its upper right corner */ +PCB_INLINE void pcb_close_box(pcb_box_t * r) +{ + r->X2++; + r->Y2++; +} + +/* return the square of the minimum distance from a point to some point + * inside a box. The box is half-closed! That is, the top-left corner + * is considered in the box, but the bottom-right corner is not. */ +PCB_INLINE double pcb_dist2_to_box(const pcb_cheap_point_t * p, const pcb_box_t * b) +{ + pcb_cheap_point_t r = pcb_closest_pcb_point_in_box(p, b); + return pcb_distance(r.X, r.Y, p->X, p->Y); +} + + +/* Modify dst to include src */ +PCB_INLINE void pcb_box_bump_box(pcb_box_t *dst, const pcb_box_t *src) +{ + if (src->X1 < dst->X1) dst->X1 = src->X1; + if (src->Y1 < dst->Y1) dst->Y1 = src->Y1; + if (src->X2 > dst->X2) dst->X2 = src->X2; + if (src->Y2 > dst->Y2) dst->Y2 = src->Y2; +} + +/* Modify dst to include src */ +PCB_INLINE void pcb_box_bump_point(pcb_box_t *dst, pcb_coord_t x, pcb_coord_t y) +{ + if (x < dst->X1) dst->X1 = x; + if (y < dst->Y1) dst->Y1 = y; + if (x > dst->X2) dst->X2 = x; + if (y > dst->Y2) dst->Y2 = y; +} + +/* sets the bounding box of a point */ +void pcb_set_point_bounding_box(pcb_point_t *Pnt); + +/* rotates a box in 90 degree steps */ +void pcb_box_rotate90(pcb_box_t *Box, pcb_coord_t X, pcb_coord_t Y, unsigned Number); + +/* Enlarge a box by adding current width,height multiplied by xfactor,yfactor */ +void pcb_box_enlarge(pcb_box_t *box, double xfactor, double yfactor); + +#endif /* __BOX_H_INCLUDED__ */ Index: tags/2.1.2/src/brave.c =================================================================== --- tags/2.1.2/src/brave.c (nonexistent) +++ tags/2.1.2/src/brave.c (revision 24813) @@ -0,0 +1,300 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2017 Tibor 'Igor2' Palinkas + * + * This module, diag, was written and is Copyright (C) 2016 by Tibor Palinkas + * this module is also subject to the GNU GPL as described below + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "config.h" + +#include + +#include "brave.h" +#include "actions.h" +#include "conf_core.h" +#include "conf_hid.h" +#include "compat_misc.h" +#include "error.h" +#include "hid_dad.h" + +pcb_brave_t pcb_brave = 0; +static const char brave_cookie[] = "brave"; +static conf_hid_id_t brave_conf_id; + +typedef struct { + pcb_brave_t bit; + const char *name, *shrt, *lng; + int widget; +} desc_t; + +static desc_t desc[] = { + {PCB_BRAVE_NOXOR, "noxor", "avoid xor drawing", "use alternative rendering instead of xor draw", 0}, + {PCB_BRAVE_CLIPBATCH, "clipbatch", "batch poly clipping", "batch polygon clipping in some expensive user operations", 0}, + {PCB_BRAVE_LESSTIF_TREETABLE, "lesstifttbl", "lesstif tree table", "enable experimental lesstif tree table support", 0}, + {0, NULL, NULL, NULL} +}; + +static desc_t *find_by_name(const char *name) +{ + desc_t *d; + for(d = desc; d->name != NULL; d++) + if (pcb_strcasecmp(name, d->name) == 0) + return d; + return NULL; +} + +/* convert the brave bits into a config string, save in CLI */ +static void set_conf(pcb_brave_t br) +{ + gds_t tmp; + desc_t *d; + + gds_init(&tmp); + + for(d = desc; d->name != NULL; d++) { + if (br & d->bit) { + gds_append_str(&tmp, d->name); + gds_append(&tmp, ','); + } + } + + /* truncate last comma */ + gds_truncate(&tmp, gds_len(&tmp)-1); + + conf_set(CFR_CLI, "rc/brave", 0, tmp.array, POL_OVERWRITE); + + gds_uninit(&tmp); +} + +/* Upon a change in the config, parse the new config string and set the brave bits */ +static void brave_conf_chg(conf_native_t *cfg, int arr_idx) +{ + char *curr, *next, old; + desc_t *d; + + pcb_brave = 0; + if ((conf_core.rc.brave == NULL) || (*conf_core.rc.brave == '\0')) + return; + for(curr = (char *)conf_core.rc.brave; *curr != '\0'; curr = next) { + next = strpbrk(curr, ", "); + if (next == NULL) + next = curr + strlen(curr); + old = *next; + *next = '\0'; + d = find_by_name(curr); + + if (d != NULL) + pcb_brave |= d->bit; + *next = old; + if (*next != '\0') + next++; + while((*next == ',') || (*next == ' ')) next++; + } +} + +/* Set one bit; if changed, update the config */ +static void brave_set(pcb_brave_t bit, int on) +{ + int state = pcb_brave & bit; + pcb_brave_t nb; + + if (state == on) + return; + + if (on) + nb = pcb_brave | bit; + else + nb = pcb_brave & ~bit; + + set_conf(nb); +} + +/*** interactive mode (DAD dialog) ***/ + +/* Convert the current brave bits into dialog box widget states, update the dialog */ +static void brave2dlg(void *hid_ctx) +{ + desc_t *d; + int len; + + for(d = desc, len=0; d->name != NULL; d++,len++) { + if (pcb_brave & d->bit) + PCB_DAD_SET_VALUE(hid_ctx, d->widget, int_value, 1); + else + PCB_DAD_SET_VALUE(hid_ctx, d->widget, int_value, 0); + } +} + +/* Convert the current state of dialog box widget into brave bits, update the conf */ +static void dlg2brave(pcb_hid_attribute_t *attrs) +{ + desc_t *d; + for(d = desc; d->name != NULL; d++) + brave_set(d->bit, attrs[d->widget].default_val.int_value); +} + +/* If a checkbox changes, do the conversion forth and back to ensure sync */ +static void brave_dialog_chg(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + dlg2brave(caller_data); + brave2dlg(hid_ctx); +} + +/* Tick in all - button callback */ +static void brave_dialog_allon(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + desc_t *d; + for(d = desc; d->name != NULL; d++) + brave_set(d->bit, 1); + brave2dlg(hid_ctx); +} + +/* Tick off all - button callback */ +static void brave_dialog_alloff(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + desc_t *d; + for(d = desc; d->name != NULL; d++) + brave_set(d->bit, 0); + brave2dlg(hid_ctx); +} + +/* Copy the config from CLI to USER and flush the file */ +static void brave_dialog_save(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + conf_set(CFR_USER, "rc/brave", 0, conf_core.rc.brave, POL_OVERWRITE); + if (conf_isdirty(CFR_USER)) + conf_save_file(NULL, NULL, CFR_USER, NULL); +} + +static int brave_interact(void) +{ + desc_t *d; + int len; + pcb_hid_dad_buttons_t btn[] = {{"Close", 0}, {NULL, 0}}; + PCB_DAD_DECL(dlg); + + PCB_DAD_BEGIN_VBOX(dlg); + PCB_DAD_COMPFLAG(dlg, PCB_HATF_EXPFILL); + PCB_DAD_LABEL(dlg, "Experimental features for the brave"); + + PCB_DAD_BEGIN_TABLE(dlg, 3); + for(d = desc, len=0; d->name != NULL; d++,len++) { + PCB_DAD_LABEL(dlg, d->name); + PCB_DAD_HELP(dlg, d->lng); + PCB_DAD_BOOL(dlg, ""); + d->widget = PCB_DAD_CURRENT(dlg); + PCB_DAD_CHANGE_CB(dlg, brave_dialog_chg); + PCB_DAD_HELP(dlg, d->lng); + PCB_DAD_LABEL(dlg, d->shrt); + PCB_DAD_HELP(dlg, d->lng); + } + PCB_DAD_END(dlg); + PCB_DAD_BEGIN_VBOX(dlg); + PCB_DAD_COMPFLAG(dlg, PCB_HATF_EXPFILL); + PCB_DAD_END(dlg); + PCB_DAD_BEGIN_HBOX(dlg); + if (len != 0) { + PCB_DAD_BUTTON(dlg, "all ON"); + PCB_DAD_HELP(dlg, "Tick in all boxes\nenabling all experimental features\n(Super Brave Mode)"); + PCB_DAD_CHANGE_CB(dlg, brave_dialog_allon); + PCB_DAD_BUTTON(dlg, "all OFF"); + PCB_DAD_HELP(dlg, "Tick off all boxes\ndisabling all experimental features\n(Safe Mode)"); + PCB_DAD_CHANGE_CB(dlg, brave_dialog_alloff); + PCB_DAD_BUTTON(dlg, "save in user cfg"); + PCB_DAD_HELP(dlg, "Save current brave state in the \nuser configuration file"); + PCB_DAD_CHANGE_CB(dlg, brave_dialog_save); + } + PCB_DAD_END(dlg); + + if (len == 0) + PCB_DAD_LABEL(dlg, "(There are no brave features at the moment)"); + + PCB_DAD_BUTTON_CLOSES(dlg, btn); + PCB_DAD_END(dlg); + + + PCB_DAD_NEW("brave", dlg, "Brave features", dlg, pcb_true, NULL); + brave2dlg(dlg_hid_ctx); + PCB_DAD_RUN(dlg); + PCB_DAD_FREE(dlg); + return 0; +} + +/*** action ***/ + +static const char pcb_acts_Brave[] = + "Brave()\n" + "Brave(setting, on|off)\n"; +static const char pcb_acth_Brave[] = "Changes brave settings."; +static fgw_error_t pcb_act_Brave(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + desc_t *d; + const char *name, *op; + if (argc <= 1) { + PCB_ACT_IRES(brave_interact()); + return 0; + } + + /* look up */ + PCB_ACT_CONVARG(1, FGW_STR, Brave, name = argv[1].val.str); + PCB_ACT_CONVARG(2, FGW_STR, Brave, op = argv[2].val.str); + d = find_by_name(name); + if (d == NULL) { + pcb_message(PCB_MSG_ERROR, "Unknown brave setting: %s\n", name); + PCB_ACT_IRES(-1); + return 0; + } + brave_set(d->bit, (pcb_strcasecmp(op, "on") == 0)); + + pcb_message(PCB_MSG_INFO, "Brave setting: %s in %s\n", name, (pcb_brave & d->bit) ? "on" : "off"); + + PCB_ACT_IRES(0); + return 0; +} + +pcb_action_t brave_action_list[] = { + {"Brave", pcb_act_Brave, pcb_acth_Brave, pcb_acts_Brave} +}; + +PCB_REGISTER_ACTIONS(brave_action_list, NULL) + + +void pcb_brave_init(void) +{ + conf_native_t *n = conf_get_field("rc/brave"); + brave_conf_id = conf_hid_reg(brave_cookie, NULL); + + if (n != NULL) { + static conf_hid_callbacks_t cbs; + memset(&cbs, 0, sizeof(conf_hid_callbacks_t)); + cbs.val_change_post = brave_conf_chg; + conf_hid_set_cb(n, brave_conf_id, &cbs); + } +} + +void pcb_brave_uninit(void) +{ + conf_hid_unreg(brave_cookie); +} Index: tags/2.1.2/src/brave.h =================================================================== --- tags/2.1.2/src/brave.h (nonexistent) +++ tags/2.1.2/src/brave.h (revision 24813) @@ -0,0 +1,15 @@ +#ifndef PCB_BRAVE_H +#define PCB_BRAVE_H +typedef enum { /* bitfield */ + PCB_BRAVE_OFF = 0, + PCB_BRAVE_NOXOR = 1, + PCB_BRAVE_CLIPBATCH = 2, + PCB_BRAVE_LESSTIF_TREETABLE = 4, + PCB_BRAVE_max +} pcb_brave_t; + +extern pcb_brave_t pcb_brave; /* cache generated from the config */ + +void pcb_brave_init(void); +void pcb_brave_uninit(void); +#endif Index: tags/2.1.2/src/buffer.c =================================================================== --- tags/2.1.2/src/buffer.c (nonexistent) +++ tags/2.1.2/src/buffer.c (revision 24813) @@ -0,0 +1,962 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996, 2005 Thomas Nau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +/* functions used by paste- and move/copy buffer + */ +#include "config.h" +#include "conf_core.h" + +#include "buffer.h" +#include "board.h" +#include "move.h" +#include "data.h" +#include "plug_io.h" +#include "polygon.h" +#include "rotate.h" +#include "remove.h" +#include "select.h" +#include "draw.h" +#include "undo.h" +#include "funchash_core.h" +#include "compat_misc.h" +#include "obj_arc_op.h" +#include "obj_line_op.h" +#include "obj_text_op.h" +#include "obj_subc_op.h" +#include "obj_poly_op.h" +#include "obj_pstk_op.h" +#include "obj_rat_op.h" +#include "obj_pstk.h" +#include "layer_grp.h" +#include "event.h" +#include "safe_fs.h" +#include "actions.h" + +static pcb_opfunc_t AddBufferFunctions = { + pcb_lineop_add_to_buffer, + pcb_textop_add_to_buffer, + pcb_polyop_add_to_buffer, + NULL, + NULL, + pcb_arcop_add_to_buffer, + pcb_ratop_add_to_buffer, + NULL, + pcb_subcop_add_to_buffer, + pcb_pstkop_add_to_buffer, +}; + +static pcb_opfunc_t MoveBufferFunctions = { + pcb_lineop_move_buffer, + pcb_textop_move_buffer, + pcb_polyop_move_buffer, + NULL, + NULL, + pcb_arcop_move_buffer, + pcb_ratop_move_buffer, + NULL, + pcb_subcop_move_buffer, + pcb_pstkop_move_buffer, +}; + +int pcb_set_buffer_bbox(pcb_buffer_t *Buffer) +{ + pcb_box_t tmp, *box; + int res = 0; + + box = pcb_data_bbox(&tmp, Buffer->Data, pcb_false); + if (box) + Buffer->BoundingBox = *box; + else + res = -1; + + box = pcb_data_bbox_naked(&tmp, Buffer->Data, pcb_false); + if (box) + Buffer->bbox_naked = *box; + else + res = -1; + + return res; +} + +static void pcb_buffer_clear_(pcb_board_t *pcb, pcb_buffer_t *Buffer, pcb_bool bind) +{ + if (Buffer && Buffer->Data) { + void *old_parent = Buffer->Data->parent.any; + pcb_parenttype_t old_pt = Buffer->Data->parent_type; + + pcb_data_uninit(Buffer->Data); + pcb_data_init(Buffer->Data); + + Buffer->Data->parent.any = old_parent; + Buffer->Data->parent_type = old_pt; + if ((pcb != NULL) && (bind)) + pcb_data_bind_board_layers(pcb, Buffer->Data, 0); + } + Buffer->from_outside = 0; +} + +void pcb_buffer_clear(pcb_board_t *pcb, pcb_buffer_t *Buffer) +{ + pcb_buffer_clear_(pcb, Buffer, pcb_true); +} + +/* add (or move) selected */ +static void pcb_buffer_toss_selected(pcb_opfunc_t *fnc, pcb_board_t *pcb, pcb_buffer_t *Buffer, pcb_coord_t X, pcb_coord_t Y, pcb_bool LeaveSelected, pcb_bool on_locked_too) +{ + pcb_opctx_t ctx; + + ctx.buffer.pcb = pcb; + + /* switch crosshair off because adding objects to the pastebuffer + * may change the 'valid' area for the cursor + */ + if (!LeaveSelected) + ctx.buffer.extraflg = PCB_FLAG_SELECTED; + else + ctx.buffer.extraflg = 0; + + pcb_notify_crosshair_change(pcb_false); + ctx.buffer.src = pcb->Data; + ctx.buffer.dst = Buffer->Data; + pcb_selected_operation(pcb, pcb->Data, fnc, &ctx, pcb_false, PCB_OBJ_ANY & (~PCB_OBJ_SUBC_PART), on_locked_too); + + /* set origin to passed or current position */ + if (X || Y) { + Buffer->X = X; + Buffer->Y = Y; + } + else { + Buffer->X = pcb_crosshair.X; + Buffer->Y = pcb_crosshair.Y; + } + Buffer->from_outside = 0; + pcb_notify_crosshair_change(pcb_true); +} + +void pcb_buffer_add_selected(pcb_board_t *pcb, pcb_buffer_t *Buffer, pcb_coord_t X, pcb_coord_t Y, pcb_bool LeaveSelected) +{ + pcb_buffer_toss_selected(&AddBufferFunctions, pcb, Buffer, X, Y, LeaveSelected, pcb_false); +} + +static const char pcb_acts_LoadFootprint[] = "pcb_load_footprint(filename[,refdes,value])"; +static const char pcb_acth_LoadFootprint[] = "Loads a single footprint by name."; +/* DOC: loadfootprint.html */ +fgw_error_t pcb_act_LoadFootprint(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + const char *name, *refdes = NULL, *value = NULL; + pcb_subc_t *s; + pcb_cardinal_t len; + + + PCB_ACT_CONVARG(1, FGW_STR, LoadFootprint, name = argv[1].val.str); + PCB_ACT_MAY_CONVARG(2, FGW_STR, LoadFootprint, refdes = argv[2].val.str); + PCB_ACT_MAY_CONVARG(3, FGW_STR, LoadFootprint, value = argv[3].val.str); + + if (!pcb_buffer_load_footprint(PCB_PASTEBUFFER, name, NULL)) { + PCB_ACT_IRES(1); + return 0; + } + + len = pcb_subclist_length(&PCB_PASTEBUFFER->Data->subc); + + if (len == 0) { + pcb_message(PCB_MSG_ERROR, "Footprint %s contains no subcircuits", name); + PCB_ACT_IRES(1); + return 0; + } + if (len > 1) { + pcb_message(PCB_MSG_ERROR, "Footprint %s contains multiple subcircuits", name); + PCB_ACT_IRES(1); + return 0; + } + + s = pcb_subclist_first(&PCB_PASTEBUFFER->Data->subc); + pcb_attribute_put(&s->Attributes, "refdes", refdes); + pcb_attribute_put(&s->Attributes, "footprint", name); + pcb_attribute_put(&s->Attributes, "value", value); + + PCB_ACT_IRES(0); + return 0; +} + +pcb_bool pcb_buffer_load_layout(pcb_board_t *pcb, pcb_buffer_t *Buffer, const char *Filename, const char *fmt) +{ + pcb_board_t *newPCB = pcb_board_new_(pcb_false); + + /* new data isn't added to the undo list */ + if (!pcb_parse_pcb(newPCB, Filename, fmt, CFR_invalid, 0)) { + /* clear data area and replace pointer */ + pcb_buffer_clear(pcb, Buffer); + free(Buffer->Data); + Buffer->Data = newPCB->Data; + newPCB->Data = NULL; + Buffer->X = 0; + Buffer->Y = 0; + PCB_CLEAR_PARENT(Buffer->Data); + pcb_data_make_layers_bound(newPCB, Buffer->Data); + pcb_data_binding_update(pcb, Buffer->Data); + pcb_board_remove(newPCB); + Buffer->from_outside = 1; + pcb_event(PCB_EVENT_LAYERS_CHANGED, NULL); /* undo the events generated on load */ + return pcb_true; + } + + /* release unused memory */ + pcb_board_remove(newPCB); + if (Buffer->Data != NULL) + PCB_CLEAR_PARENT(Buffer->Data); + pcb_event(PCB_EVENT_LAYERS_CHANGED, NULL); /* undo the events generated on load */ + Buffer->from_outside = 0; + return pcb_false; +} + +void pcb_buffer_rotate90(pcb_buffer_t *Buffer, unsigned int Number) +{ + pcb_undo_freeze_serial(); + pcb_undo_freeze_add(); + + PCB_PADSTACK_LOOP(Buffer->Data); + { + pcb_pstk_rotate90(padstack, Buffer->X, Buffer->Y, Number); + } + PCB_END_LOOP; + + PCB_SUBC_LOOP(Buffer->Data); + { + pcb_obj_rotate90(PCB_OBJ_SUBC, subc, subc, subc, Buffer->X, Buffer->Y, Number); + } + PCB_END_LOOP; + + /* all layer related objects */ + PCB_LINE_ALL_LOOP(Buffer->Data); + { + if (layer->line_tree != NULL) + pcb_r_delete_entry(layer->line_tree, (pcb_box_t *) line); + pcb_line_rotate90(line, Buffer->X, Buffer->Y, Number); + if (layer->line_tree != NULL) + pcb_r_insert_entry(layer->line_tree, (pcb_box_t *) line); + } + PCB_ENDALL_LOOP; + PCB_ARC_ALL_LOOP(Buffer->Data); + { + if (layer->arc_tree != NULL) + pcb_r_delete_entry(layer->arc_tree, (pcb_box_t *) arc); + pcb_arc_rotate90(arc, Buffer->X, Buffer->Y, Number); + if (layer->arc_tree != NULL) + pcb_r_insert_entry(layer->arc_tree, (pcb_box_t *) arc); + } + PCB_ENDALL_LOOP; + PCB_TEXT_ALL_LOOP(Buffer->Data); + { + if (layer->text_tree != NULL) + pcb_r_delete_entry(layer->text_tree, (pcb_box_t *) text); + pcb_text_rotate90(text, Buffer->X, Buffer->Y, Number); + if (layer->text_tree != NULL) + pcb_r_insert_entry(layer->text_tree, (pcb_box_t *) text); + } + PCB_ENDALL_LOOP; + PCB_POLY_ALL_LOOP(Buffer->Data); + { + if (layer->polygon_tree != NULL) + pcb_r_delete_entry(layer->polygon_tree, (pcb_box_t *) polygon); + pcb_poly_rotate90(polygon, Buffer->X, Buffer->Y, Number); + if (layer->polygon_tree != NULL) + pcb_r_insert_entry(layer->polygon_tree, (pcb_box_t *) polygon); + } + PCB_ENDALL_LOOP; + + /* finally the origin and the bounding box */ + PCB_COORD_ROTATE90(Buffer->X, Buffer->Y, Buffer->X, Buffer->Y, Number); + pcb_box_rotate90(&Buffer->BoundingBox, Buffer->X, Buffer->Y, Number); + + pcb_undo_unfreeze_add(); + pcb_undo_unfreeze_serial(); +} + +void pcb_buffer_rotate(pcb_buffer_t *Buffer, pcb_angle_t angle) +{ + double cosa, sina; + + pcb_undo_freeze_serial(); + pcb_undo_freeze_add(); + + cosa = cos(angle * M_PI / 180.0); + sina = sin(angle * M_PI / 180.0); + + PCB_PADSTACK_LOOP(Buffer->Data); + { + pcb_pstk_rotate(padstack, Buffer->X, Buffer->Y, cosa, sina, angle); + } + PCB_END_LOOP; + + PCB_SUBC_LOOP(Buffer->Data); + { + pcb_subc_rotate(subc, Buffer->X, Buffer->Y, cosa, sina, angle); + } + PCB_END_LOOP; + + /* all layer related objects */ + PCB_LINE_ALL_LOOP(Buffer->Data); + { + pcb_line_rotate(layer, line, Buffer->X, Buffer->Y, cosa, sina); + } + PCB_ENDALL_LOOP; + PCB_ARC_ALL_LOOP(Buffer->Data); + { + pcb_arc_rotate(layer, arc, Buffer->X, Buffer->Y, cosa, sina, angle); + } + PCB_ENDALL_LOOP; + PCB_TEXT_ALL_LOOP(Buffer->Data); + { + pcb_text_rotate(text, Buffer->X, Buffer->Y, cosa, sina, angle); + } + PCB_ENDALL_LOOP; + PCB_POLY_ALL_LOOP(Buffer->Data); + { + pcb_poly_rotate(layer, polygon, Buffer->X, Buffer->Y, cosa, sina); + } + PCB_ENDALL_LOOP; + + pcb_set_buffer_bbox(Buffer); + pcb_undo_unfreeze_add(); + pcb_undo_unfreeze_serial(); +} + +pcb_data_t *pcb_buffer_new(pcb_board_t *pcb) +{ + return pcb_data_new(pcb); +} + + +static const char pcb_acts_FreeRotateBuffer[] = "FreeRotateBuffer([Angle])"; +static const char pcb_acth_FreeRotateBuffer[] = + "Rotates the current paste buffer contents by the specified angle. The\n" + "angle is given in degrees. If no angle is given, the user is prompted\n" "for one.\n"; +/* DOC: freerotatebuffer */ +fgw_error_t pcb_act_FreeRotateBuffer(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + char *angle_s = NULL; + double ang; + + PCB_ACT_MAY_CONVARG(1, FGW_STR, FreeRotateBuffer, angle_s = pcb_strdup(argv[1].val.str)); + PCB_ACT_IRES(0); + + if (angle_s == NULL) + angle_s = pcb_hid_prompt_for("Enter Rotation (degrees, CCW):", "0", "Rotation angle"); + + if ((angle_s == NULL) || (*angle_s == '\0')) { + free(angle_s); + PCB_ACT_IRES(-1); + return 0; + } + + PCB_ACT_IRES(0); + ang = strtod(angle_s, 0); + free(angle_s); + if (ang == 0) { + PCB_ACT_IRES(-1); + return 0; + } + + if ((ang < -360000) || (ang > +360000)) { + pcb_message(PCB_MSG_ERROR, "Angle too large\n"); + PCB_ACT_IRES(-1); + return 0; + } + + pcb_notify_crosshair_change(pcb_false); + pcb_buffer_rotate(PCB_PASTEBUFFER, ang); + pcb_notify_crosshair_change(pcb_true); + return 0; +} + +static const char pcb_acts_ScaleBuffer[] = "ScaleBuffer(x [,y [,thickness [,subc]]])"; +static const char pcb_acth_ScaleBuffer[] = + "Scales the buffer by multiplying all coordinates by a floating point number.\n" + "If only x is given, it is also used for y and thickness too. If subc is not\n" + "empty, subcircuits are also scaled\n"; +fgw_error_t pcb_act_ScaleBuffer(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + char *sx = NULL; + double x, y, th; + int recurse = 0; + char *end; + + PCB_ACT_MAY_CONVARG(1, FGW_STR, ScaleBuffer, sx = pcb_strdup(argv[1].val.str)); + + if (sx == NULL) + sx = pcb_hid_prompt_for("Enter scaling factor (unitless multiplier):", "1.0", "scaling factor"); + if ((sx == NULL) || (*sx == '\0')) { + free(sx); + PCB_ACT_IRES(-1); + return 0; + } + x = strtod(sx, &end); + if (*end != '\0') { + free(sx); + PCB_ACT_IRES(-1); + return 0; + } + free(sx); + y = th = x; + + PCB_ACT_MAY_CONVARG(2, FGW_DOUBLE, ScaleBuffer, y = argv[2].val.nat_double); + PCB_ACT_MAY_CONVARG(3, FGW_DOUBLE, ScaleBuffer, th = argv[3].val.nat_double); + PCB_ACT_MAY_CONVARG(4, FGW_STR, ScaleBuffer, recurse = (argv[4].val.str != NULL)); + + PCB_ACT_IRES(0); + + + pcb_notify_crosshair_change(pcb_false); + pcb_buffer_scale(PCB_PASTEBUFFER, x, y, th, recurse); + pcb_notify_crosshair_change(pcb_true); + return 0; +} + + +void pcb_init_buffers(pcb_board_t *pcb) +{ + int i; + + for (i = 0; i < PCB_MAX_BUFFER; i++) + pcb_buffers[i].Data = pcb_buffer_new(NULL); +} + +void pcb_uninit_buffers(pcb_board_t *pcb) +{ + int i; + + for (i = 0; i < PCB_MAX_BUFFER; i++) { + pcb_buffer_clear_(pcb, pcb_buffers+i, pcb_false); + pcb_data_uninit(pcb_buffers[i].Data); + free(pcb_buffers[i].Data); + } +} + +void pcb_buffer_mirror(pcb_board_t *pcb, pcb_buffer_t *Buffer) +{ + int i, num_layers; + + num_layers = PCB_PASTEBUFFER->Data->LayerN; + if (num_layers == 0) /* some buffers don't have layers, just simple objects */ + num_layers = pcb->Data->LayerN; + + for (i = 0; i < num_layers; i++) { + pcb_layer_t *layer = Buffer->Data->Layer + i; + if (textlist_length(&layer->Text)) { + pcb_message(PCB_MSG_ERROR, "You can't mirror a buffer that has text!\n"); + return; + } + } + /* set buffer offset to 'mark' position */ + Buffer->X = PCB_SWAP_X(Buffer->X); + Buffer->Y = PCB_SWAP_Y(Buffer->Y); + pcb_undo_freeze_add(); + pcb_data_mirror(Buffer->Data, 0, PCB_TXM_COORD, pcb_false); + pcb_undo_unfreeze_add(); + pcb_set_buffer_bbox(Buffer); +} + +void pcb_buffer_scale(pcb_buffer_t *Buffer, double sx, double sy, double sth, int recurse) +{ + pcb_data_scale(Buffer->Data, sx, sy, sth, recurse); + Buffer->X = pcb_round((double)Buffer->X * sx); + Buffer->Y = pcb_round((double)Buffer->Y * sy); + pcb_set_buffer_bbox(Buffer); +} + +void pcb_buffer_flip_side(pcb_board_t *pcb, pcb_buffer_t *Buffer) +{ + int j, k; + pcb_layer_id_t SLayer = -1, CLayer = -1; + pcb_layergrp_id_t sgroup, cgroup; + pcb_layer_t swap; + +#if 0 +/* this results in saving flipped (bottom-side) footprints whenlooking at the board from the bottom */ + PCB_SUBC_LOOP(Buffer->Data); + { + pcb_subc_change_side(subc, /*2 * pcb_crosshair.Y - PCB->MaxHeight*/0); + } + PCB_END_LOOP; +#endif + + /* set buffer offset to 'mark' position */ + Buffer->X = PCB_SWAP_X(Buffer->X); + Buffer->Y = PCB_SWAP_Y(Buffer->Y); + + PCB_PADSTACK_LOOP(Buffer->Data); + { + pcb_pstk_mirror(padstack, PCB_PSTK_DONT_MIRROR_COORDS, 1, 0); + } + PCB_END_LOOP; + PCB_LINE_ALL_LOOP(Buffer->Data); + { + pcb_line_flip_side(layer, line); + } + PCB_ENDALL_LOOP; + PCB_ARC_ALL_LOOP(Buffer->Data); + { + pcb_arc_flip_side(layer, arc); + } + PCB_ENDALL_LOOP; + PCB_POLY_ALL_LOOP(Buffer->Data); + { + pcb_poly_flip_side(layer, polygon); + } + PCB_ENDALL_LOOP; + PCB_TEXT_ALL_LOOP(Buffer->Data); + { + pcb_text_flip_side(layer, text, 0); + } + PCB_ENDALL_LOOP; + + /* swap silkscreen layers */ + pcb_layer_list(pcb, PCB_LYT_BOTTOM | PCB_LYT_SILK, &SLayer, 1); + pcb_layer_list(pcb, PCB_LYT_TOP | PCB_LYT_SILK, &CLayer, 1); + assert(SLayer != -1); + assert(CLayer != -1); + swap = Buffer->Data->Layer[SLayer]; + Buffer->Data->Layer[SLayer] = Buffer->Data->Layer[CLayer]; + Buffer->Data->Layer[CLayer] = swap; + + /* swap layer groups when balanced */ + sgroup = pcb_layer_get_group(pcb, SLayer); + cgroup = pcb_layer_get_group(pcb, CLayer); +TODO("layer: revise this code for the generic physical layer support; move this code to layer*.c") + if (pcb->LayerGroups.grp[cgroup].len == pcb->LayerGroups.grp[sgroup].len) { + for (j = k = 0; j < pcb->LayerGroups.grp[sgroup].len; j++) { + pcb_layer_id_t cnumber = pcb->LayerGroups.grp[cgroup].lid[k]; + pcb_layer_id_t snumber = pcb->LayerGroups.grp[sgroup].lid[j]; + + if ((pcb_layer_flags(pcb, snumber)) & PCB_LYT_SILK) + continue; + swap = Buffer->Data->Layer[snumber]; + + while ((pcb_layer_flags(pcb, cnumber)) & PCB_LYT_SILK) { + k++; + cnumber = pcb->LayerGroups.grp[cgroup].lid[k]; + } + Buffer->Data->Layer[snumber] = Buffer->Data->Layer[cnumber]; + Buffer->Data->Layer[cnumber] = swap; + k++; + } + } + pcb_set_buffer_bbox(Buffer); +} + +void pcb_buffers_flip_side(pcb_board_t *pcb) +{ + int i; + + for (i = 0; i < PCB_MAX_BUFFER; i++) + pcb_buffer_flip_side(pcb, &pcb_buffers[i]); + pcb_crosshair_range_to_buffer(); +} + +void *pcb_move_obj_to_buffer(pcb_board_t *pcb, pcb_data_t *Destination, pcb_data_t *Src, int Type, void *Ptr1, void *Ptr2, void *Ptr3) +{ + pcb_opctx_t ctx; + + /* setup local identifiers used by move operations */ + ctx.buffer.pcb = pcb; + ctx.buffer.dst = Destination; + ctx.buffer.src = Src; + return (pcb_object_operation(&MoveBufferFunctions, &ctx, Type, Ptr1, Ptr2, Ptr3)); +} + +void *pcb_copy_obj_to_buffer(pcb_board_t *pcb, pcb_data_t *Destination, pcb_data_t *Src, int Type, void *Ptr1, void *Ptr2, void *Ptr3) +{ + pcb_opctx_t ctx; + + ctx.buffer.pcb = pcb; + ctx.buffer.dst = Destination; + ctx.buffer.src = Src; + return (pcb_object_operation(&AddBufferFunctions, &ctx, Type, Ptr1, Ptr2, Ptr3)); +} + +pcb_bool pcb_buffer_copy_to_layout(pcb_board_t *pcb, pcb_coord_t X, pcb_coord_t Y) +{ + pcb_cardinal_t i; + pcb_bool changed = pcb_false; + pcb_opctx_t ctx; + int num_layers; + +#ifdef DEBUG + printf("Entering CopyPastebufferToLayout.....\n"); +#endif + + pcb_data_clip_inhibit_inc(pcb->Data); + + /* set movement vector */ + ctx.copy.pcb = pcb; + ctx.copy.DeltaX = X - PCB_PASTEBUFFER->X; + ctx.copy.DeltaY = Y - PCB_PASTEBUFFER->Y; + ctx.copy.from_outside = PCB_PASTEBUFFER->from_outside; + + /* paste all layers */ + num_layers = PCB_PASTEBUFFER->Data->LayerN; + if (num_layers != 0) /* some buffers don't have layers, just global objects */ + for (i = 0; i < num_layers; i++) { + pcb_layer_t *sourcelayer = &PCB_PASTEBUFFER->Data->Layer[i]; + pcb_layer_t *destlayer = pcb_layer_resolve_binding(pcb, sourcelayer); + + if (destlayer == NULL) { + if ((!(sourcelayer->meta.bound.type & PCB_LYT_VIRTUAL)) && (!pcb_layer_is_pure_empty(sourcelayer))) { + const char *src_name = sourcelayer->name; + if ((src_name == NULL) || (*src_name == '\0')) + src_name = ""; + pcb_message(PCB_MSG_WARNING, "Couldn't resolve buffer layer #%d (%s) on the current board\n", i, src_name); + } + continue; + } + + destlayer = pcb_loose_subc_layer(PCB, destlayer, pcb_true); + + if (destlayer->meta.real.vis) { + PCB_LINE_LOOP(sourcelayer); + { + if (pcb_lineop_copy(&ctx, destlayer, line)) + changed = 1; + } + PCB_END_LOOP; + PCB_ARC_LOOP(sourcelayer); + { + if (pcb_arcop_copy(&ctx, destlayer, arc)) + changed = 1; + } + PCB_END_LOOP; + PCB_TEXT_LOOP(sourcelayer); + { + if (pcb_textop_copy(&ctx, destlayer, text)) + changed = 1; + } + PCB_END_LOOP; + PCB_POLY_LOOP(sourcelayer); + { + if (pcb_polyop_copy(&ctx, destlayer, polygon)) + changed = 1; + } + PCB_END_LOOP; + } + } + + /* paste subcircuits */ + PCB_SUBC_LOOP(PCB_PASTEBUFFER->Data); + { + if (pcb->is_footprint) { + pcb_message(PCB_MSG_WARNING, "Can not paste subcircuit in the footprint edit mode\n"); + break; + } + pcb_subcop_copy(&ctx, subc); + changed = pcb_true; + } + PCB_END_LOOP; + + /* finally: padstacks */ + if (pcb->pstk_on) { + pcb_board_t dummy; + changed |= (padstacklist_length(&(PCB_PASTEBUFFER->Data->padstack)) != 0); + + /* set up a dummy board to work around that pcb_pstkop_copy() requires a + pcb_board_t instead of a pcb_data_t */ +TODO("subc: fix this after the element removal") + if (pcb->is_footprint) { + pcb_subc_t *sc = pcb_subclist_first(&pcb->Data->subc); + if (sc != NULL) { + ctx.copy.pcb = &dummy; + memset(&dummy, 0, sizeof(dummy)); + dummy.Data = sc->data; + } + } + + PCB_PADSTACK_LOOP(PCB_PASTEBUFFER->Data); + { + pcb_pstkop_copy(&ctx, padstack); + } + PCB_END_LOOP; + } + + if (changed) { + pcb_subc_as_board_update(PCB); + pcb_draw(); + pcb_undo_inc_serial(); + } + +#ifdef DEBUG + printf(" .... Leaving CopyPastebufferToLayout.\n"); +#endif + + pcb_data_clip_inhibit_dec(pcb->Data, pcb_true); + + return changed; +} + +void pcb_buffer_set_number(int Number) +{ + if (Number >= 0 && Number < PCB_MAX_BUFFER) { + conf_set_design("editor/buffer_number", "%d", Number); + + /* do an update on the crosshair range */ + pcb_crosshair_range_to_buffer(); + } +} + +/* loads footprint data from file/library into buffer (as subcircuit) + * returns pcb_false on error + * if successful, update some other stuff and reposition the pastebuffer */ +pcb_bool pcb_buffer_load_footprint(pcb_buffer_t *Buffer, const char *Name, const char *fmt) +{ + pcb_buffer_clear(PCB, Buffer); + if (!pcb_parse_footprint(Buffer->Data, Name, fmt)) { + if (conf_core.editor.show_solder_side) + pcb_buffer_flip_side(PCB, Buffer); + pcb_set_buffer_bbox(Buffer); + + Buffer->X = 0; + Buffer->Y = 0; + Buffer->from_outside = 1; + + if (pcb_subclist_length(&Buffer->Data->subc)) { + pcb_subc_t *subc = pcb_subclist_first(&Buffer->Data->subc); + pcb_subc_get_origin(subc, &Buffer->X, &Buffer->Y); + } + return pcb_true; + } + + /* release memory which might have been acquired */ + pcb_buffer_clear(PCB, Buffer); + return pcb_false; +} + + +static const char pcb_acts_PasteBuffer[] = + "PasteBuffer(AddSelected|Clear|1..PCB_MAX_BUFFER)\n" + "PasteBuffer(Rotate, 1..3)\n" + "PasteBuffer(Convert|Restore|Mirror)\n" + "PasteBuffer(ToLayout, X, Y, units)\n" + "PasteBuffer(ToLayout, crosshair)\n" + "PasteBuffer(Save, Filename, [format], [force])\n" + "PasteBuffer(Push)\n" + "PasteBuffer(Pop)\n" + ; +static const char pcb_acth_PasteBuffer[] = "Various operations on the paste buffer."; +/* DOC: pastebuffer.html */ +static fgw_error_t pcb_act_PasteBuffer(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + int op, force; + const char *sbufnum = "", *fmt = NULL, *forces = NULL, *name, *tmp; + static char *default_file = NULL; + pcb_bool free_name = pcb_false; + static int stack[32]; + static int sp = 0; + int number; + + PCB_ACT_CONVARG(1, FGW_STR, PasteBuffer, tmp = argv[1].val.str); + number = atoi(tmp); + PCB_ACT_CONVARG(1, FGW_KEYWORD, PasteBuffer, op = fgw_keyword(&argv[1])); + PCB_ACT_MAY_CONVARG(2, FGW_STR, PasteBuffer, sbufnum = argv[2].val.str); + PCB_ACT_MAY_CONVARG(3, FGW_STR, PasteBuffer, fmt = argv[3].val.str); + PCB_ACT_MAY_CONVARG(4, FGW_STR, PasteBuffer, forces = argv[4].val.str); + + force = (forces != NULL) && ((*forces == '1') || (*forces == 'y') || (*forces == 'Y')); + + pcb_notify_crosshair_change(pcb_false); + switch (op) { + /* clear contents of paste buffer */ + case F_Clear: + pcb_buffer_clear(PCB, PCB_PASTEBUFFER); + break; + + case F_Push: + if (sp < sizeof(stack) / sizeof(stack[0])) + stack[sp++] = conf_core.editor.buffer_number; + else + pcb_message(PCB_MSG_ERROR, "Paste buffer stack overflow on push.\n"); + break; + + case F_Pop: + if (sp > 0) + pcb_buffer_set_number(stack[--sp]); + else + pcb_message(PCB_MSG_ERROR, "Paste buffer stack underflow on pop.\n"); + break; + + /* copies objects to paste buffer */ + case F_AddSelected: + pcb_buffer_add_selected(PCB, PCB_PASTEBUFFER, 0, 0, pcb_false); + if (pcb_data_is_empty(PCB_PASTEBUFFER->Data)) { + pcb_message(PCB_MSG_WARNING, "Nothing buffer-movable is selected, nothing copied to the paste buffer\n"); + goto error; + } + break; + + /* moves objects to paste buffer: kept for compatibility with old menu files */ + case F_MoveSelected: + pcb_buffer_add_selected(PCB, PCB_PASTEBUFFER, 0, 0, pcb_false); + if (pcb_data_is_empty(PCB_PASTEBUFFER->Data)) { + pcb_message(PCB_MSG_WARNING, "Nothing buffer-movable is selected, nothing moved to the paste buffer\n"); + goto error; + } + pcb_actionl("RemoveSelected", NULL); + break; + + /* converts buffer contents into a subcircuit */ + case F_Convert: + case F_ConvertSubc: + pcb_subc_convert_from_buffer(PCB_PASTEBUFFER); + break; + + /* break up subcircuit for editing */ + case F_Restore: + if (!pcb_subc_smash_buffer(PCB_PASTEBUFFER)) + pcb_message(PCB_MSG_ERROR, "Error breaking up subcircuits - only one can be broken up at a time\n"); + break; + + /* Mirror buffer */ + case F_Mirror: + pcb_buffer_mirror(PCB, PCB_PASTEBUFFER); + break; + + case F_Rotate: + if (sbufnum) { + int numtmp = atoi(sbufnum); + if (numtmp < 0) + numtmp = 4-numtmp; + pcb_buffer_rotate90(PCB_PASTEBUFFER, (unsigned int)numtmp); + pcb_crosshair_range_to_buffer(); + } + break; + + case F_Save: + free_name = pcb_false; + if (argc <= 1) { + name = pcb_gui->fileselect("Save Paste Buffer As ...", + "Choose a file to save the contents of the\n" + "paste buffer to.\n", default_file, ".fp", NULL, "footprint", 0, NULL); + + if (default_file) { + free(default_file); + default_file = NULL; + } + if (name && *name) { + default_file = pcb_strdup(name); + } + free_name = pcb_true; + } + + else + name = sbufnum; + + { + FILE *exist; + + if ((!force) && ((exist = pcb_fopen(name, "r")))) { + fclose(exist); + if (pcb_hid_message_box("warning", "Buffer: overwrite file", "File exists! Ok to overwrite?", "cancel", 0, "yes", 1, NULL) == 1) + pcb_save_buffer_elements(name, fmt); + } + else + pcb_save_buffer_elements(name, fmt); + + if (free_name && name) + free((char*)name); + } + break; + + case F_ToLayout: + { + static pcb_coord_t oldx = 0, oldy = 0; + pcb_coord_t x, y; + pcb_bool absolute; + if (argc == 2) { + x = y = 0; + } + else if (strcmp(sbufnum, "crosshair") == 0) { + x = pcb_crosshair.X; + y = pcb_crosshair.Y; + } + else if (argc == 4 || argc == 5) { + x = pcb_get_value(sbufnum, forces, &absolute, NULL); + if (!absolute) + x += oldx; + y = pcb_get_value(fmt, forces, &absolute, NULL); + if (!absolute) + y += oldy; + } + + else { + pcb_notify_crosshair_change(pcb_true); + PCB_ACT_FAIL(PasteBuffer); + } + + oldx = x; + oldy = y; + if (pcb_buffer_copy_to_layout(PCB, x, y)) + pcb_board_set_changed_flag(pcb_true); + } + break; + + case F_Normalize: + pcb_set_buffer_bbox(PCB_PASTEBUFFER); + PCB_PASTEBUFFER->X = pcb_round(((double)PCB_PASTEBUFFER->BoundingBox.X1 + (double)PCB_PASTEBUFFER->BoundingBox.X2) / 2.0); + PCB_PASTEBUFFER->Y = pcb_round(((double)PCB_PASTEBUFFER->BoundingBox.Y1 + (double)PCB_PASTEBUFFER->BoundingBox.Y2) / 2.0); + pcb_crosshair_range_to_buffer(); + break; + + /* set number */ + default: + { + + + /* correct number */ + if (number) + pcb_buffer_set_number(number - 1); + } + } + + pcb_notify_crosshair_change(pcb_true); + PCB_ACT_IRES(0); + return 0; + + error:; + pcb_notify_crosshair_change(pcb_true); + PCB_ACT_IRES(-1); + return 0; +} + +/* --------------------------------------------------------------------------- */ + +pcb_action_t buffer_action_list[] = { + {"FreeRotateBuffer", pcb_act_FreeRotateBuffer, pcb_acth_FreeRotateBuffer, pcb_acts_FreeRotateBuffer}, + {"ScaleBuffer", pcb_act_ScaleBuffer, pcb_acth_ScaleBuffer, pcb_acts_ScaleBuffer}, + {"LoadFootprint", pcb_act_LoadFootprint, pcb_acth_LoadFootprint, pcb_acts_LoadFootprint}, + {"PasteBuffer", pcb_act_PasteBuffer, pcb_acth_PasteBuffer, pcb_acts_PasteBuffer} +}; + +PCB_REGISTER_ACTIONS(buffer_action_list, NULL) Index: tags/2.1.2/src/buffer.h =================================================================== --- tags/2.1.2/src/buffer.h (nonexistent) +++ tags/2.1.2/src/buffer.h (revision 24813) @@ -0,0 +1,108 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +/* Board independent paste buffers */ + +#ifndef PCB_BUFFER_H +#define PCB_BUFFER_H + +#include "obj_common.h" +#include + +struct pcb_buffer_s { /* information about the paste buffer */ + pcb_coord_t X, Y; /* offset */ + pcb_box_t BoundingBox; + pcb_box_t bbox_naked; + pcb_data_t *Data; /* data; not all members of pcb_board_t */ + int from_outside; /* data is coming from outside of the current board (lib, loaded board) */ + /* are used */ +}; + +/* Recalculates the bounding box of the buffer; returns 0 on success */ +int pcb_set_buffer_bbox(pcb_buffer_t *); + +/* clears the contents of the paste buffer: free's data, but preserves parent */ +void pcb_buffer_clear(pcb_board_t *pcb, pcb_buffer_t *Buffer); + +/* adds (copies) all selected and visible objects to the paste buffer */ +void pcb_buffer_add_selected(pcb_board_t *pcb, pcb_buffer_t *, pcb_coord_t, pcb_coord_t, pcb_bool); + +/* load a board into buffer parse the file with enabled 'PCB mode' */ +pcb_bool pcb_buffer_load_layout(pcb_board_t *pcb, pcb_buffer_t *Buffer, const char *Filename, const char *fmt); + +/* rotates the contents of the pastebuffer by Number * 90 degrees or free angle*/ +void pcb_buffer_rotate90(pcb_buffer_t *Buffer, unsigned int Number); +void pcb_buffer_rotate(pcb_buffer_t *Buffer, pcb_angle_t angle); + +/* flip elements/subcircuits/tracks from one side to the other; also swap + the layer stackup of padstacks */ +void pcb_buffers_flip_side(pcb_board_t *pcb); + +/* graphically mirror the buffer on the current side */ +void pcb_buffer_mirror(pcb_board_t *pcb, pcb_buffer_t *Buffer); + +/* Scale all coords and sizes by sx;sy and thicknesses by sth; + if recurse is non-zero, also scale subcircuits */ +void pcb_buffer_scale(pcb_buffer_t *Buffer, double sx, double sy, double sth, int recurse); + +/* Init/uninit all buffers (stored in board-independent global variables) */ +void pcb_init_buffers(pcb_board_t *pcb); +void pcb_uninit_buffers(pcb_board_t *pcb); + +/* Creates a new empty paste buffer */ +pcb_data_t *pcb_buffer_new(pcb_board_t *pcb); + +/* Moves the passed object to the passed buffer's data and removes it from its + original data; returns the new object pointer on success or NULL on fail */ +void *pcb_move_obj_to_buffer(pcb_board_t *pcb, pcb_data_t *Destination, pcb_data_t *Src, int Type, void *Ptr1, void *Ptr2, void *Ptr3); + +/* Adds/copies the passed object to the passed buffer's data; + returns the new object pointer on success or NULL on fail */ +void *pcb_copy_obj_to_buffer(pcb_board_t *pcb, pcb_data_t *Destination, pcb_data_t *Src, int Type, void *Ptr1, void *Ptr2, void *Ptr3); + + +/* This action is called from ActionElementAddIf() */ +fgw_error_t pcb_act_LoadFootprint(fgw_arg_t *res, int oargc, fgw_arg_t *oargv); + +/* pastes the contents of the buffer to the layout. Only visible objects + are handled by the routine. */ +pcb_bool pcb_buffer_copy_to_layout(pcb_board_t *pcb, pcb_coord_t X, pcb_coord_t Y); + +/* change the side of all objects in the buffer */ +void pcb_buffer_flip_side(pcb_board_t *pcb, pcb_buffer_t *Buffer); + +/* Load a footprint by name into a buffer; fmt is optional (may be NULL). */ +pcb_bool pcb_buffer_load_footprint(pcb_buffer_t *Buffer, const char *Name, const char *fmt); + +/* sets currently active buffer */ +void pcb_buffer_set_number(int Number); + +/* Address of the currently active paste buffer */ +#define PCB_PASTEBUFFER (&pcb_buffers[conf_core.editor.buffer_number]) + +#endif Index: tags/2.1.2/src/build_run.c =================================================================== --- tags/2.1.2/src/build_run.c (nonexistent) +++ tags/2.1.2/src/build_run.c (revision 24813) @@ -0,0 +1,257 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996,2006 Thomas Nau + * pcb-rnd Copyright (C) 2017,2018 Alain Vigne + * pcb-rnd Copyright (C) 2018,2019 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +#include "config.h" +#include +#include +#include "conf_core.h" +#include "board.h" +#include "build_run.h" +#include "hid_init.h" +#include "plug_io.h" +#include "compat_misc.h" + +extern void pcb_main_uninit(void); + +void pcb_quit_app(void) +{ + /* save data if necessary. It not needed, then don't trigger EmergencySave + * via our atexit() registering of pcb_emergency_save(). We presumably wanted to + * exit here and thus it is not an emergency. */ + if (PCB->Changed && conf_core.editor.save_in_tmp) + pcb_emergency_save(); + else + pcb_disable_emergency_save(); + + if (pcb_gui->do_exit == NULL) { + pcb_main_uninit(); + exit(0); + } + else + pcb_gui->do_exit(pcb_gui); +} + +char *pcb_get_info_program(void) +{ + static gds_t info; + static int first_time = 1; + + if (first_time) { + first_time = 0; + gds_init(&info); + gds_append_str(&info, "This is pcb-rnd " PCB_VERSION " (" PCB_REVISION ")" "\n an interactive "); + gds_append_str(&info, "printed circuit board editor\n"); + } + return info.array; +} + +char *pcb_get_info_copyright(void) +{ + static gds_t info; + static int first_time = 1; + + if (first_time) { + first_time = 0; + gds_init(&info); + + gds_append_str(&info, "Recent pcb-rnd copyright:\n"); + gds_append_str(&info, "Copyright (C) Tibor Palinkas 2013..2019 (pcb-rnd)\n"); + gds_append_str(&info, "For a more complete list of pcb-rnd authors and\ncontributors, see http://repo.hu/cgi-bin/pcb-rnd-people.cgi\n\n"); + + gds_append_str(&info, "Historical copyright:\n"); + gds_append_str(&info, "pcb-rnd was originally forked from gEDA/PCB:\n"); + gds_append_str(&info, "Copyright (C) Thomas Nau 1994..1997\n"); + gds_append_str(&info, "Copyright (C) harry eaton 1998..2007\n"); + gds_append_str(&info, "Copyright (C) C. Scott Ananian 2001\n"); + gds_append_str(&info, "Copyright (C) DJ Delorie 2003..2008\n"); + gds_append_str(&info, "Copyright (C) Dan McMahill 2003..2008\n\n"); + } + return info.array; +} + +char *pcb_get_info_websites(const char **url_out) +{ + static gds_t info; + static int first_time = 1; + static const char *URL = "http://pcb-rnd.repo.hu\n"; + + if (first_time) { + first_time = 0; + gds_init(&info); + + gds_append_str(&info, "For more information see:\n"); + gds_append_str(&info, URL); + } + + if (url_out != NULL) + *url_out = URL; + + return info.array; +} + +char *pcb_get_info_comments(void) +{ + static gds_t info; + static int first_time = 1; + char *tmp; + + if (first_time) { + first_time = 0; + gds_init(&info); + + tmp = pcb_get_info_program(); + gds_append_str(&info, tmp); + tmp = pcb_get_info_websites(NULL); + gds_append_str(&info, tmp); + } + return info.array; +} + + +char *pcb_get_info_compile_options(void) +{ + pcb_hid_t **hids; + int i; + static gds_t info; + static int first_time = 1; + +#define TAB " " + + if (first_time) { + first_time = 0; + gds_init(&info); + + gds_append_str(&info, "----- Run Time Options -----\n"); + gds_append_str(&info, "GUI: "); + if (pcb_gui != NULL) { + gds_append_str(&info, pcb_gui->name); + gds_append_str(&info, "\n"); + } + else + gds_append_str(&info, "none\n"); + + gds_append_str(&info, "\n----- Compile Time Options -----\n"); + hids = pcb_hid_enumerate(); + gds_append_str(&info, "GUI:\n"); + for (i = 0; hids[i]; i++) { + if (hids[i]->gui) { + gds_append_str(&info, TAB); + gds_append_str(&info, hids[i]->name); + gds_append_str(&info, " : "); + gds_append_str(&info, hids[i]->description); + gds_append_str(&info, "\n"); + } + } + + gds_append_str(&info, "Exporters:\n"); + for (i = 0; hids[i]; i++) { + if (hids[i]->exporter) { + gds_append_str(&info, TAB); + gds_append_str(&info, hids[i]->name); + gds_append_str(&info, " : "); + gds_append_str(&info, hids[i]->description); + gds_append_str(&info, "\n"); + } + } + + gds_append_str(&info, "Printers:\n"); + for (i = 0; hids[i]; i++) { + if (hids[i]->printer) { + gds_append_str(&info, TAB); + gds_append_str(&info, hids[i]->name); + gds_append_str(&info, " : "); + gds_append_str(&info, hids[i]->description); + gds_append_str(&info, "\n"); + } + } + } +#undef TAB + return info.array; +} + +char *pcb_get_info_license(void) +{ + static gds_t info; + static int first_time = 1; + + if (first_time) { + first_time = 0; + gds_init(&info); + + gds_append_str(&info, "pcb-rnd is licensed under the terms of the GNU\n"); + gds_append_str(&info, "General Public License version 2\n"); + gds_append_str(&info, "See the COPYING file for more information\n\n"); + } + return info.array; +} + +const char *pcb_author(void) +{ + if (conf_core.design.fab_author && conf_core.design.fab_author[0]) + return conf_core.design.fab_author; + else + return pcb_get_user_name(); +} + +/* Catches signals which abort the program. */ +void pcb_catch_signal(int Signal) +{ + const char *s; + + switch (Signal) { +#ifdef SIGHUP + case SIGHUP: + s = "SIGHUP"; + break; +#endif + case SIGINT: + s = "SIGINT"; + break; +#ifdef SIGQUIT + case SIGQUIT: + s = "SIGQUIT"; + break; +#endif + case SIGABRT: + s = "SIGABRT"; + break; + case SIGTERM: + s = "SIGTERM"; + break; + case SIGSEGV: + s = "SIGSEGV"; + break; + default: + s = "unknown"; + break; + } + pcb_message(PCB_MSG_ERROR, "aborted by %s signal\n", s); + exit(1); +} Index: tags/2.1.2/src/build_run.h =================================================================== --- tags/2.1.2/src/build_run.h (nonexistent) +++ tags/2.1.2/src/build_run.h (revision 24813) @@ -0,0 +1,58 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996,2006 Thomas Nau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +#ifndef PCB_BUILD_RUN_H +#define PCB_BUILD_RUN_H + +void pcb_quit_app(void); + +/* Returns a string that has a bunch of information about this program. */ +char *pcb_get_info_program(void); + +/* Returns a string that has a bunch of information about the copyrights. */ +char *pcb_get_info_copyright(void); + +/* Returns a string about how the program is licensed. */ +char *pcb_get_info_license(void); + +/* Returns a string that has a bunch of information about the websites. */ +char *pcb_get_info_websites(const char **url_out); + +/* Returns a string as the concatenation of pcb_get_info_program() and pcb_get_info_websites() */ +char *pcb_get_info_comments(void); + +/* Returns a string that has a bunch of information about the options selected at compile time. */ +char *pcb_get_info_compile_options(void); + +/* Author's name: either from the config system (typically from the design) or + as a last resort from the OS */ +const char *pcb_author(void); + +void pcb_catch_signal(int Signal); + +#endif Index: tags/2.1.2/src/buildin.h =================================================================== --- tags/2.1.2/src/buildin.h (nonexistent) +++ tags/2.1.2/src/buildin.h (revision 24813) @@ -0,0 +1,4 @@ +/* This file is generated by the puplug utility. Please DO NOT edit this file. */ + +#include +extern const pup_buildin_t pup_buildins[]; Index: tags/2.1.2/src/change.c =================================================================== --- tags/2.1.2/src/change.c (nonexistent) +++ tags/2.1.2/src/change.c (revision 24813) @@ -0,0 +1,822 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996, 2005 Thomas Nau + * Copyright (C) 2018 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +#include "config.h" + +#include "conf_core.h" + +#include "change.h" +#include "board.h" +#include "data.h" +#include "draw.h" +#include "select.h" +#include "undo.h" +#include "actions.h" +#include "macro.h" +#include "obj_pstk_op.h" +#include "obj_subc_parent.h" +#include "obj_term.h" +#include "obj_arc_op.h" +#include "obj_line_op.h" +#include "obj_poly_op.h" +#include "obj_text_op.h" +#include "obj_subc_op.h" + +int defer_updates = 0; +int defer_needs_update = 0; + +pcb_opfunc_t ChangeSizeFunctions = { + pcb_lineop_change_size, + pcb_textop_change_size, + pcb_polyop_change_clear, + NULL, + NULL, + pcb_arcop_change_size, + NULL, + NULL, + pcb_subcop_change_size, + pcb_pstkop_change_size +}; + +pcb_opfunc_t Change1stSizeFunctions = { + pcb_lineop_change_size, + pcb_textop_change_size, + pcb_polyop_change_clear, + NULL, + NULL, + pcb_arcop_change_size, + NULL, + NULL, + pcb_subcop_change_1st_size, + NULL /* padstack */ +}; + +pcb_opfunc_t Change2ndSizeFunctions = { + NULL, + pcb_textop_change_2nd_size, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + pcb_subcop_change_2nd_size, + pcb_pstkop_change_2nd_size +}; + +pcb_opfunc_t ChangeRotFunctions = { + NULL, + pcb_textop_change_rot, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + pcb_pstkop_rotate +}; + +static pcb_opfunc_t ChangeThermalFunctions = { + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* subc */ + pcb_pstkop_change_thermal +}; + +pcb_opfunc_t ChangeClearSizeFunctions = { + pcb_lineop_change_clear_size, + NULL, + pcb_polyop_change_clear_size, /* just to tell the user not to :-) */ + NULL, + NULL, + pcb_arcop_change_clear_size, + NULL, + NULL, + pcb_subcop_change_clear_size, + pcb_pstkop_change_clear_size +}; + +static pcb_opfunc_t ChangeNameFunctions = { + NULL, + pcb_textop_change_name, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + pcb_subcop_change_name, + NULL /* padstack */ +}; + +static pcb_opfunc_t ChangeNonetlistFunctions = { + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + pcb_subcop_change_nonetlist, + NULL /* padstack */ +}; + +static pcb_opfunc_t ChangeJoinFunctions = { + pcb_lineop_change_join, + pcb_textop_change_join, + pcb_polyop_change_join, + NULL, + NULL, + pcb_arcop_change_join, + NULL, + NULL, + NULL, /* subc */ + NULL /* padstack */ +}; + +static pcb_opfunc_t SetJoinFunctions = { + pcb_lineop_set_join, + pcb_textop_set_join, + NULL, + NULL, + NULL, + pcb_arcop_set_join, + NULL, + NULL, + NULL, /* subc */ + NULL /* padstack */ +}; + +static pcb_opfunc_t ClrJoinFunctions = { + pcb_lineop_clear_join, + pcb_textop_clear_join, + NULL, + NULL, + NULL, + pcb_arcop_clear_join, + NULL, + NULL, + NULL, /* subc */ + NULL /* padstack */ +}; + +static pcb_opfunc_t ChangeRadiusFunctions = { + NULL, + NULL, + NULL, + NULL, + NULL, + pcb_arcop_change_radius, + NULL, + NULL, + NULL, /* subc */ + NULL /* padstack */ +}; + +static pcb_opfunc_t ChangeAngleFunctions = { + NULL, + NULL, + NULL, + NULL, + NULL, + pcb_arcop_change_angle, + NULL, + NULL, + NULL, /* subc */ + NULL /* padstack */ +}; + +pcb_opfunc_t ChgFlagFunctions = { + pcb_lineop_change_flag, + pcb_textop_change_flag, + pcb_polyop_change_flag, + NULL, + NULL, + pcb_arcop_change_flag, + NULL, + NULL, + pcb_subcop_change_flag, + pcb_pstkop_change_flag +}; + +static pcb_opfunc_t InvalLabelFunctions = { + pcb_lineop_invalidate_label, + pcb_textop_invalidate_label, + pcb_polyop_invalidate_label, + NULL, + NULL, + pcb_arcop_invalidate_label, + NULL, + NULL, + /*pcb_subcop_invalidate_flag*/ NULL, + NULL /* padstack */ +}; + + +/* ---------------------------------------------------------------------- + * changes the thermals on all selected and visible padstacks. + * Returns pcb_true if anything has changed + */ +pcb_bool pcb_chg_selected_thermals(int types, int therm_style, unsigned long lid) +{ + pcb_bool change = pcb_false; + pcb_opctx_t ctx; + + ctx.chgtherm.pcb = PCB; + ctx.chgtherm.style = therm_style; + ctx.chgtherm.lid = lid; + + change = pcb_selected_operation(PCB, PCB->Data, &ChangeThermalFunctions, &ctx, pcb_false, types, pcb_false); + if (change) { + pcb_draw(); + pcb_undo_inc_serial(); + } + return change; +} + +/* ---------------------------------------------------------------------- + * changes the size of all selected and visible object types + * returns pcb_true if anything has changed + */ +pcb_bool pcb_chg_selected_size(int types, pcb_coord_t Difference, pcb_bool fixIt) +{ + pcb_bool change = pcb_false; + pcb_opctx_t ctx; + + ctx.chgsize.pcb = PCB; + ctx.chgsize.is_primary = 1; + ctx.chgsize.is_absolute = fixIt; + ctx.chgsize.value = Difference; + + change = pcb_selected_operation(PCB, PCB->Data, &ChangeSizeFunctions, &ctx, pcb_false, types, pcb_false); + if (change) { + pcb_draw(); + pcb_undo_inc_serial(); + } + return change; +} + +/* ---------------------------------------------------------------------- + * changes the clearance size of all selected and visible objects + * returns pcb_true if anything has changed + */ +pcb_bool pcb_chg_selected_clear_size(int types, pcb_coord_t Difference, pcb_bool fixIt) +{ + pcb_bool change = pcb_false; + pcb_opctx_t ctx; + + ctx.chgsize.pcb = PCB; + ctx.chgsize.is_primary = 1; + ctx.chgsize.is_absolute = fixIt; + ctx.chgsize.value = Difference; + + change = pcb_selected_operation(PCB, PCB->Data, &ChangeClearSizeFunctions, &ctx, pcb_false, types, pcb_false); + if (change) { + pcb_draw(); + pcb_undo_inc_serial(); + } + return change; +} + +/* -------------------------------------------------------------------------- + * changes the 2nd size (drilling hole) of all selected and visible objects + * returns pcb_true if anything has changed + */ +pcb_bool pcb_chg_selected_2nd_size(int types, pcb_coord_t Difference, pcb_bool fixIt) +{ + pcb_bool change = pcb_false; + pcb_opctx_t ctx; + + ctx.chgsize.pcb = PCB; + ctx.chgsize.is_primary = 1; + ctx.chgsize.is_absolute = fixIt; + ctx.chgsize.value = Difference; + + change = pcb_selected_operation(PCB, PCB->Data, &Change2ndSizeFunctions, &ctx, pcb_false, types, pcb_false); + if (change) { + pcb_draw(); + pcb_undo_inc_serial(); + } + return change; +} + +/* -------------------------------------------------------------------------- + * changes the internal/self rotation all selected and visible objects + * returns pcb_true if anything has changed + */ +pcb_bool pcb_chg_selected_rot(int types, double Difference, pcb_bool fixIt) +{ + pcb_bool change = pcb_false; + pcb_opctx_t ctx; + + ctx.chgsize.pcb = PCB; + ctx.chgsize.is_primary = 1; + ctx.chgsize.is_absolute = fixIt; + ctx.chgsize.value = Difference; + + change = pcb_selected_operation(PCB, PCB->Data, &ChangeRotFunctions, &ctx, pcb_false, types, pcb_false); + if (change) { + pcb_draw(); + pcb_undo_inc_serial(); + } + return change; +} + +/* ---------------------------------------------------------------------- + * changes the clearance flag (join) of all selected and visible lines + * and/or arcs. Returns pcb_true if anything has changed + */ +pcb_bool pcb_chg_selected_join(int types) +{ + pcb_bool change = pcb_false; + pcb_opctx_t ctx; + + ctx.chgsize.pcb = PCB; + + change = pcb_selected_operation(PCB, PCB->Data, &ChangeJoinFunctions, &ctx, pcb_false, types, pcb_false); + if (change) { + pcb_draw(); + pcb_undo_inc_serial(); + } + return change; +} + +/* ---------------------------------------------------------------------- + * changes the clearance flag (join) of all selected and visible lines + * and/or arcs. Returns pcb_true if anything has changed + */ +pcb_bool pcb_set_selected_join(int types) +{ + pcb_bool change = pcb_false; + pcb_opctx_t ctx; + + ctx.chgsize.pcb = PCB; + + change = pcb_selected_operation(PCB, PCB->Data, &SetJoinFunctions, &ctx, pcb_false, types, pcb_false); + if (change) { + pcb_draw(); + pcb_undo_inc_serial(); + } + return change; +} + +/* ---------------------------------------------------------------------- + * changes the clearance flag (join) of all selected and visible lines + * and/or arcs. Returns pcb_true if anything has changed + */ +pcb_bool pcb_clr_selected_join(int types) +{ + pcb_bool change = pcb_false; + pcb_opctx_t ctx; + + ctx.chgsize.pcb = PCB; + + change = pcb_selected_operation(PCB, PCB->Data, &ClrJoinFunctions, &ctx, pcb_false, types, pcb_false); + if (change) { + pcb_draw(); + pcb_undo_inc_serial(); + } + return change; +} + +/* ---------------------------------------------------------------------- + * changes the nonetlist-flag of all selected and visible subcircuits + * returns pcb_true if anything has changed + */ +pcb_bool pcb_chg_selected_nonetlist(int types) +{ + pcb_bool change = pcb_false; + pcb_opctx_t ctx; + + ctx.chgsize.pcb = PCB; + + change = pcb_selected_operation(PCB, PCB->Data, &ChangeNonetlistFunctions, &ctx, pcb_false, types, pcb_false); + if (change) { + pcb_draw(); + pcb_undo_inc_serial(); + } + return change; +} + +/* ---------------------------------------------------------------------- + * changes the angle of all selected and visible object types + * returns pcb_true if anything has changed + */ +pcb_bool pcb_chg_selected_angle(int types, int is_start, pcb_angle_t Difference, pcb_bool fixIt) +{ + pcb_bool change = pcb_false; + pcb_opctx_t ctx; + + ctx.chgangle.pcb = PCB; + ctx.chgangle.is_primary = is_start; + ctx.chgangle.is_absolute = fixIt; + ctx.chgangle.value = Difference; + + change = pcb_selected_operation(PCB, PCB->Data, &ChangeAngleFunctions, &ctx, pcb_false, types, pcb_false); + if (change) { + pcb_draw(); + pcb_undo_inc_serial(); + } + return change; +} + +/* ---------------------------------------------------------------------- + * changes the radius of all selected and visible object types + * returns pcb_true if anything has changed + */ +pcb_bool pcb_chg_selected_radius(int types, int is_start, pcb_angle_t Difference, pcb_bool fixIt) +{ + pcb_bool change = pcb_false; + pcb_opctx_t ctx; + + ctx.chgsize.pcb = PCB; + ctx.chgsize.is_primary = is_start; + ctx.chgsize.is_absolute = fixIt; + ctx.chgsize.value = Difference; + + change = pcb_selected_operation(PCB, PCB->Data, &ChangeRadiusFunctions, &ctx, pcb_false, types, pcb_false); + if (change) { + pcb_draw(); + pcb_undo_inc_serial(); + } + return change; +} + +TODO("subc: check if it is true:") +/* --------------------------------------------------------------------------- + * changes the size of the passed object; subc size is silk size (TODO: check if it is true) + * Returns pcb_true if anything is changed + */ +pcb_bool pcb_chg_obj_size(int Type, void *Ptr1, void *Ptr2, void *Ptr3, pcb_coord_t Difference, pcb_bool fixIt) +{ + pcb_bool change; + pcb_opctx_t ctx; + + ctx.chgsize.pcb = PCB; + ctx.chgsize.is_primary = 1; + ctx.chgsize.is_absolute = fixIt; + ctx.chgsize.value = Difference; + + change = (pcb_object_operation(&ChangeSizeFunctions, &ctx, Type, Ptr1, Ptr2, Ptr3) != NULL); + if (change) { + pcb_draw(); + pcb_undo_inc_serial(); + } + return change; +} + +TODO("subc: check if it is true:") +/* --------------------------------------------------------------------------- + * changes the size of the passed object; element size is pin ring sizes + * Returns pcb_true if anything is changed + */ +pcb_bool pcb_chg_obj_1st_size(int Type, void *Ptr1, void *Ptr2, void *Ptr3, pcb_coord_t Difference, pcb_bool fixIt) +{ + pcb_bool change; + pcb_opctx_t ctx; + + ctx.chgsize.pcb = PCB; + ctx.chgsize.is_primary = 1; + ctx.chgsize.is_absolute = fixIt; + ctx.chgsize.value = Difference; + + change = (pcb_object_operation(&Change1stSizeFunctions, &ctx, Type, Ptr1, Ptr2, Ptr3) != NULL); + if (change) { + pcb_draw(); + pcb_undo_inc_serial(); + } + return change; +} + +/* --------------------------------------------------------------------------- + * changes the radius of the passed object (e.g. arc width/height) + * Returns pcb_true if anything is changed + */ +pcb_bool pcb_chg_obj_radius(int Type, void *Ptr1, void *Ptr2, void *Ptr3, int is_x, pcb_coord_t r, pcb_bool fixIt) +{ + pcb_bool change; + pcb_opctx_t ctx; + + ctx.chgsize.pcb = PCB; + ctx.chgsize.is_primary = is_x; + ctx.chgsize.is_absolute = fixIt; + ctx.chgsize.value = r; + + change = (pcb_object_operation(&ChangeRadiusFunctions, &ctx, Type, Ptr1, Ptr2, Ptr3) != NULL); + if (change) { + pcb_draw(); + pcb_undo_inc_serial(); + } + return change; +} + +/* --------------------------------------------------------------------------- + * changes the angles of the passed object (e.g. arc start/ctx->chgsize.value) + * Returns pcb_true if anything is changed + */ +pcb_bool pcb_chg_obj_angle(int Type, void *Ptr1, void *Ptr2, void *Ptr3, int is_start, pcb_angle_t a, pcb_bool fixIt) +{ + pcb_bool change; + pcb_opctx_t ctx; + + ctx.chgangle.pcb = PCB; + ctx.chgangle.is_primary = is_start; + ctx.chgangle.is_absolute = fixIt; + ctx.chgangle.value = a; + + change = (pcb_object_operation(&ChangeAngleFunctions, &ctx, Type, Ptr1, Ptr2, Ptr3) != NULL); + if (change) { + pcb_draw(); + pcb_undo_inc_serial(); + } + return change; +} + + +/* --------------------------------------------------------------------------- + * changes the clearance size of the passed object + * Returns pcb_true if anything is changed + */ +pcb_bool pcb_chg_obj_clear_size(int Type, void *Ptr1, void *Ptr2, void *Ptr3, pcb_coord_t Difference, pcb_bool fixIt) +{ + pcb_bool change; + pcb_opctx_t ctx; + + ctx.chgsize.pcb = PCB; + ctx.chgsize.is_primary = 1; + ctx.chgsize.is_absolute = fixIt; + ctx.chgsize.value = Difference; + + change = (pcb_object_operation(&ChangeClearSizeFunctions, &ctx, Type, Ptr1, Ptr2, Ptr3) != NULL); + if (change) { + pcb_draw(); + pcb_undo_inc_serial(); + } + return change; +} + +/* --------------------------------------------------------------------------- + * changes the thermal of the passed object + * Returns pcb_true if anything is changed + * + */ +pcb_bool pcb_chg_obj_thermal(int Type, void *Ptr1, void *Ptr2, void *Ptr3, int therm_type, unsigned long lid) +{ + pcb_bool change; + pcb_opctx_t ctx; + + ctx.chgtherm.pcb = PCB; + ctx.chgtherm.style = therm_type; + ctx.chgtherm.lid = lid; + + change = (pcb_object_operation(&ChangeThermalFunctions, &ctx, Type, Ptr1, Ptr2, Ptr3) != NULL); + if (change) { + pcb_draw(); + pcb_undo_inc_serial(); + } + return change; +} + +/* --------------------------------------------------------------------------- + * changes the 2nd size of the passed object + * Returns pcb_true if anything is changed + */ +pcb_bool pcb_chg_obj_2nd_size(int Type, void *Ptr1, void *Ptr2, void *Ptr3, pcb_coord_t Difference, pcb_bool fixIt, pcb_bool incundo) +{ + pcb_bool change; + pcb_opctx_t ctx; + + ctx.chgsize.pcb = PCB; + ctx.chgsize.is_primary = 1; + ctx.chgsize.is_absolute = fixIt; + ctx.chgsize.value = Difference; + + change = (pcb_object_operation(&Change2ndSizeFunctions, &ctx, Type, Ptr1, Ptr2, Ptr3) != NULL); + if (change) { + pcb_draw(); + if (incundo) + pcb_undo_inc_serial(); + } + return change; +} + +/* --------------------------------------------------------------------------- + * changes the internal/self rotation of the passed object + * Returns pcb_true if anything is changed + */ +pcb_bool pcb_chg_obj_rot(int Type, void *Ptr1, void *Ptr2, void *Ptr3, double Difference, pcb_bool fixIt, pcb_bool incundo) +{ + pcb_bool change; + pcb_opctx_t ctx; + + ctx.chgsize.pcb = PCB; + ctx.chgsize.is_primary = 1; + ctx.chgsize.is_absolute = fixIt; + ctx.chgsize.value = Difference; + + change = (pcb_object_operation(&ChangeRotFunctions, &ctx, Type, Ptr1, Ptr2, Ptr3) != NULL); + if (change) { + pcb_draw(); + if (incundo) + pcb_undo_inc_serial(); + } + return change; +} + +/* --------------------------------------------------------------------------- + * changes the name of the passed object + * returns the old name + * + * The allocated memory isn't freed because the old string is used + * by the undo module. + */ +void *pcb_chg_obj_name(int Type, void *Ptr1, void *Ptr2, void *Ptr3, char *Name) +{ + void *result; + pcb_opctx_t ctx; + + ctx.chgname.pcb = PCB; + ctx.chgname.new_name = Name; + + result = pcb_object_operation(&ChangeNameFunctions, &ctx, Type, Ptr1, Ptr2, Ptr3); + pcb_draw(); + return result; +} + +/* --------------------------------------------------------------------------- + * changes the clearance-flag of the passed object + * Returns pcb_true if anything is changed + */ +pcb_bool pcb_chg_obj_join(int Type, void *Ptr1, void *Ptr2, void *Ptr3) +{ + pcb_opctx_t ctx; + + ctx.chgsize.pcb = PCB; + + if (pcb_object_operation(&ChangeJoinFunctions, &ctx, Type, Ptr1, Ptr2, Ptr3) != NULL) { + pcb_draw(); + pcb_undo_inc_serial(); + return pcb_true; + } + return pcb_false; +} + +/* --------------------------------------------------------------------------- + * sets the clearance-flag of the passed object + * Returns pcb_true if anything is changed + */ +pcb_bool pcb_set_obj_join(int Type, void *Ptr1, void *Ptr2, void *Ptr3) +{ + pcb_opctx_t ctx; + + ctx.chgsize.pcb = PCB; + + if (pcb_object_operation(&SetJoinFunctions, &ctx, Type, Ptr1, Ptr2, Ptr3) != NULL) { + pcb_draw(); + pcb_undo_inc_serial(); + return pcb_true; + } + return pcb_false; +} + +/* --------------------------------------------------------------------------- + * clears the clearance-flag of the passed object + * Returns pcb_true if anything is changed + */ +pcb_bool pcb_clr_obj_join(int Type, void *Ptr1, void *Ptr2, void *Ptr3) +{ + pcb_opctx_t ctx; + + ctx.chgsize.pcb = PCB; + + if (pcb_object_operation(&ClrJoinFunctions, &ctx, Type, Ptr1, Ptr2, Ptr3) != NULL) { + pcb_draw(); + pcb_undo_inc_serial(); + return pcb_true; + } + return pcb_false; +} + +/* --------------------------------------------------------------------------- + * changes the square-flag of the passed object + * Returns pcb_true if anything is changed + */ +pcb_bool pcb_chg_obj_nonetlist(int Type, void *Ptr1, void *Ptr2, void *Ptr3) +{ + pcb_opctx_t ctx; + + ctx.chgsize.pcb = PCB; + + if (pcb_object_operation(&ChangeNonetlistFunctions, &ctx, Type, Ptr1, Ptr2, Ptr3) != NULL) { + pcb_draw(); + pcb_undo_inc_serial(); + return pcb_true; + } + return pcb_false; +} + +void *pcb_chg_obj_name_query(pcb_any_obj_t *obj) +{ + char *name = NULL; + pcb_subc_t *parent_subc; + + parent_subc = pcb_obj_parent_subc(obj); + + switch(obj->type) { + case PCB_OBJ_TEXT: + if ((parent_subc != NULL) && !PCB_FLAG_TEST(PCB_FLAG_FLOATER, obj) && !PCB_FLAG_TEST(PCB_FLAG_DYNTEXT, obj)) + goto term_name; /* special case: dyntext floaters are rarely temrinals */ + if ((parent_subc != NULL) && PCB_FLAG_TEST(PCB_FLAG_DYNTEXT, obj) && (strstr(((pcb_text_t *)obj)->TextString, "%a.parent.refdes%"))) { + if (pcb_hid_message_box("question", "Text edit: refdes or template?", "Text object seems to be a refdes text", "edit the text (template)", 0, "edit subcircuit refdes", 1, NULL) == 1) { + obj = (pcb_any_obj_t *)parent_subc; + goto subc_name; + } + } + name = pcb_hid_prompt_for("Enter text:", PCB_EMPTY(((pcb_text_t *)obj)->TextString), "Change text"); + break; + + case PCB_OBJ_SUBC: + subc_name:; + name = pcb_hid_prompt_for("Subcircuit refdes:", PCB_EMPTY(((pcb_subc_t *)obj)->refdes), "Change refdes"); + break; + + default: + term_name:; + if (parent_subc != NULL) { + name = pcb_hid_prompt_for("Enter terminal ID:", PCB_EMPTY(obj->term), "Change terminal ID"); + if (name != NULL) { + pcb_term_undoable_rename(PCB, obj, name); + pcb_draw(); + } + free(name); + return obj; + } + break; + } + + if (name) { + /* ChangeObjectName takes ownership of the passed memory; do not free old name, it's kept for undo */ + char *old; + old = (char *)pcb_chg_obj_name(obj->type, obj->parent.any, obj, obj, name); + + if (old != (char *)-1) { + pcb_undo_add_obj_to_change_name(obj->type, obj->parent.any, obj, obj, old); + pcb_undo_inc_serial(); + } + pcb_draw(); + return obj; + } + return NULL; +} + +void pcb_flag_change(pcb_board_t *pcb, pcb_change_flag_t how, pcb_flag_values_t flag, int Type, void *Ptr1, void *Ptr2, void *Ptr3) +{ + pcb_opctx_t ctx; + + ctx.chgflag.pcb = pcb; + ctx.chgflag.how = how; + ctx.chgflag.flag = flag; + + pcb_object_operation(&ChgFlagFunctions, &ctx, Type, Ptr1, Ptr2, Ptr3); +} + +void *pcb_obj_invalidate_label(pcb_objtype_t Type, void *Ptr1, void *Ptr2, void *Ptr3) +{ + pcb_opctx_t ctx; + ctx.noarg.pcb = PCB; + return pcb_object_operation(&InvalLabelFunctions, &ctx, Type, Ptr1, Ptr2, Ptr3); +} Index: tags/2.1.2/src/change.h =================================================================== --- tags/2.1.2/src/change.h (nonexistent) +++ tags/2.1.2/src/change.h (revision 24813) @@ -0,0 +1,111 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +/* Generic, object-type independent change calls */ + +#ifndef PCB_CHANGE_H +#define PCB_CHANGE_H + +#include "config.h" +#include "board.h" +#include "flag.h" +#include "pcb_bool.h" +#include "unit.h" + +extern int defer_updates, defer_needs_update; + +#define PCB_CHANGENAME_TYPES \ + (PCB_OBJ_PSTK | PCB_OBJ_TEXT | PCB_OBJ_SUBC | PCB_OBJ_LINE | \ + PCB_OBJ_ARC | PCB_OBJ_POLY | PCB_OBJ_SUBC_PART | PCB_OBJ_SUBC) + +#define PCB_CHANGESIZE_TYPES \ + (PCB_OBJ_PSTK | PCB_OBJ_POLY | PCB_OBJ_LINE | PCB_OBJ_ARC | \ + PCB_OBJ_TEXT | PCB_OBJ_SUBC | PCB_OBJ_SUBC_PART) + +#define PCB_CHANGE2NDSIZE_TYPES \ + (PCB_OBJ_PSTK | PCB_OBJ_SUBC | PCB_OBJ_SUBC_PART) + +#define PCB_CHANGEROT_TYPES \ + (PCB_OBJ_PSTK | PCB_OBJ_TEXT) + +/* We include polygons here only to inform the user not to do it that way. */ +#define PCB_CHANGECLEARSIZE_TYPES \ + (PCB_OBJ_PSTK | PCB_OBJ_LINE | PCB_OBJ_ARC | PCB_OBJ_POLY | PCB_OBJ_SUBC | \ + PCB_OBJ_SUBC_PART) + +#define PCB_CHANGENONETLIST_TYPES \ + (PCB_OBJ_SUBC) + +#define PCB_CHANGESQUARE_TYPES \ + (PCB_OBJ_SUBC | PCB_OBJ_SUBC_PART) + +#define PCB_CHANGEOCTAGON_TYPES \ + (PCB_OBJ_SUBC | PCB_OBJ_SUBC_PART) + +#define PCB_CHANGEJOIN_TYPES \ + (PCB_OBJ_ARC | PCB_OBJ_LINE | PCB_OBJ_TEXT | PCB_OBJ_POLY) + +#define PCB_CHANGETHERMAL_TYPES \ + (PCB_OBJ_SUBC_PART) + +pcb_bool pcb_chg_selected_size(int, pcb_coord_t, pcb_bool); +pcb_bool pcb_chg_selected_clear_size(int, pcb_coord_t, pcb_bool); +pcb_bool pcb_chg_selected_2nd_size(int, pcb_coord_t, pcb_bool); +pcb_bool pcb_chg_selected_rot(int, double, pcb_bool); +pcb_bool pcb_chg_selected_join(int); +pcb_bool pcb_set_selected_join(int); +pcb_bool pcb_clr_selected_join(int); +pcb_bool pcb_chg_selected_nonetlist(int); +pcb_bool pcb_chg_selected_thermals(int types, int therm_style, unsigned long lid); +pcb_bool pcb_chg_obj_size(int, void *, void *, void *, pcb_coord_t, pcb_bool); +pcb_bool pcb_chg_obj_1st_size(int, void *, void *, void *, pcb_coord_t, pcb_bool); +pcb_bool pcb_chg_obj_thermal(int Type, void *Ptr1, void *Ptr2, void *Ptr3, int therm_type, unsigned long lid); +pcb_bool pcb_chg_obj_clear_size(int, void *, void *, void *, pcb_coord_t, pcb_bool); +pcb_bool pcb_chg_obj_2nd_size(int, void *, void *, void *, pcb_coord_t, pcb_bool, pcb_bool); +pcb_bool pcb_chg_obj_rot(int, void *, void *, void *, double, pcb_bool, pcb_bool); +pcb_bool pcb_chg_obj_join(int, void *, void *, void *); +pcb_bool pcb_set_obj_join(int, void *, void *, void *); +pcb_bool pcb_clr_obj_join(int, void *, void *, void *); +pcb_bool pcb_chg_obj_nonetlist(int Type, void *Ptr1, void *Ptr2, void *Ptr3); +void *pcb_chg_obj_name(int, void *, void *, void *, char *); + +/* queries the user for a new object name and changes it */ +void *pcb_chg_obj_name_query(pcb_any_obj_t *obj); + +pcb_bool pcb_chg_obj_radius(int Type, void *Ptr1, void *Ptr2, void *Ptr3, int is_x, pcb_coord_t r, pcb_bool absolute); +pcb_bool pcb_chg_obj_angle(int Type, void *Ptr1, void *Ptr2, void *Ptr3, int is_start, pcb_angle_t a, pcb_bool absolute); +pcb_bool pcb_chg_selected_angle(int types, int is_start, pcb_angle_t Difference, pcb_bool fixIt); +pcb_bool pcb_chg_selected_radius(int types, int is_start, pcb_angle_t Difference, pcb_bool fixIt); + +/* Change flag flg of an object in a way dictated by 'how' */ +void pcb_flag_change(pcb_board_t *pcb, pcb_change_flag_t how, pcb_flag_values_t flg, int Type, void *Ptr1, void *Ptr2, void *Ptr3); + +/* Invalidate the term label of an object */ +void *pcb_obj_invalidate_label(pcb_objtype_t Type, void *Ptr1, void *Ptr2, void *Ptr3); + +#endif Index: tags/2.1.2/src/change_act.c =================================================================== --- tags/2.1.2/src/change_act.c (nonexistent) +++ tags/2.1.2/src/change_act.c (revision 24813) @@ -0,0 +1,986 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * Copyright (C) 1997, 1998, 1999, 2000, 2001 Harry Eaton + * Copyright (C) 2018 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + * + * Old contact info: + * Harry Eaton, 6697 Buttonhole Ct, Columbia, MD 21044, USA + * haceaton@aplcomm.jhuapl.edu + * + */ + +/* action routines for output window + */ + +#include "config.h" +#include "conf_core.h" + +#include "data.h" +#include "funchash_core.h" + +#include "board.h" +#include "actions.h" +#include "change.h" +#include "draw.h" +#include "search.h" +#include "undo.h" +#include "event.h" +#include "compat_misc.h" +#include "obj_rat_draw.h" +#include "data_it.h" +#include "macro.h" +#include "grid.h" +#include "route_style.h" + +static void ChangeFlag(const char *, const char *, int, const char *); +static fgw_error_t pcb_act_ChangeSize(fgw_arg_t *ores, int oargc, fgw_arg_t *oargv); +static fgw_error_t pcb_act_Change2ndSize(fgw_arg_t *ores, int oargc, fgw_arg_t *oargv); + +/* --------------------------------------------------------------------------- */ + +static const char pcb_acts_ChangeClearSize[] = + "ChangeClearSize(Object, delta|style)\n" + "ChangeClearSize(SelectedPins|SelectedPads|SelectedVias, delta|style)\n" + "ChangeClearSize(SelectedLines|SelectedArcs, delta|style)\n" + "ChangeClearSize(Selected|SelectedObjects, delta|style)"; +static const char pcb_acth_ChangeClearSize[] = "Changes the clearance size of objects."; +/* DOC: changeclearsize.html */ +static fgw_error_t pcb_act_ChangeClearSize(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + const char *function; + const char *delta = NULL; + const char *units = NULL; + pcb_bool absolute; + pcb_coord_t value; + int type = PCB_OBJ_VOID; + void *ptr1, *ptr2, *ptr3; + pcb_coord_t x, y; + int got_coords = 0; + + PCB_ACT_CONVARG(1, FGW_STR, ChangeClearSize, function = argv[1].val.str); + PCB_ACT_MAY_CONVARG(2, FGW_STR, ChangeClearSize, delta = argv[2].val.str); + PCB_ACT_MAY_CONVARG(3, FGW_STR, ChangeClearSize, units = argv[3].val.str); + + if (function && delta) { + int funcid = pcb_funchash_get(function, NULL); + + if (funcid == F_Object) { + pcb_hid_get_coords("Select an Object", &x, &y, 0); + got_coords = 1; + type = pcb_search_screen(x, y, PCB_CHANGECLEARSIZE_TYPES, &ptr1, &ptr2, &ptr3); + } + + if (strcmp(delta, "style") == 0) { + if (!got_coords) { + pcb_hid_get_coords("Select an Object", &x, &y, 0); + got_coords = 1; + } + + if ((type == PCB_OBJ_VOID) || (type == PCB_OBJ_POLY)) /* workaround: pcb_search_screen(PCB_CHANGECLEARSIZE_TYPES) wouldn't return elements */ + type = pcb_search_screen(x, y, PCB_CHANGE2NDSIZE_TYPES, &ptr1, &ptr2, &ptr3); + if (pcb_get_style_size(funcid, &value, type, 2) != 0) { + PCB_ACT_IRES(-1); + return 0; + } + absolute = 1; + value *= 2; + } + else + value = 2 * pcb_get_value(delta, units, &absolute, NULL); + switch (pcb_funchash_get(function, NULL)) { + case F_Object: + { + if (type != PCB_OBJ_VOID) + if (pcb_chg_obj_clear_size(type, ptr1, ptr2, ptr3, value, absolute)) + pcb_board_set_changed_flag(pcb_true); + break; + } + case F_SelectedVias: + case F_SelectedPads: + case F_SelectedPins: + if (pcb_chg_selected_clear_size(PCB_OBJ_PSTK, value, absolute)) + pcb_board_set_changed_flag(pcb_true); + break; + case F_SelectedLines: + if (pcb_chg_selected_clear_size(PCB_OBJ_LINE, value, absolute)) + pcb_board_set_changed_flag(pcb_true); + break; + case F_SelectedArcs: + if (pcb_chg_selected_clear_size(PCB_OBJ_ARC, value, absolute)) + pcb_board_set_changed_flag(pcb_true); + break; + case F_Selected: + case F_SelectedObjects: + if (pcb_chg_selected_clear_size(PCB_CHANGECLEARSIZE_TYPES, value, absolute)) + pcb_board_set_changed_flag(pcb_true); + break; + } + } + PCB_ACT_IRES(0); + return 0; +} + +/* --------------------------------------------------------------------------- */ + +static const char pcb_acts_ChangeFlag[] = + "ChangeFlag(Object|Selected|SelectedObjects, flag, value)\n" + "ChangeFlag(SelectedLines|SelectedPins|SelectedVias, flag, value)\n" + "ChangeFlag(SelectedPads|SelectedTexts|SelectedNames, flag, value)\n" + "ChangeFlag(SelectedElements, flag, value)\n" "flag = thermal | join\n" "value = 0 | 1"; +static const char pcb_acth_ChangeFlag[] = "Sets or clears flags on objects."; +/* DOC: changeflag.html */ +static fgw_error_t pcb_act_ChangeFlag(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + const char *function; + const char *flag; + int value; + + PCB_ACT_CONVARG(1, FGW_STR, ChangeFlag, function = argv[1].val.str); + PCB_ACT_CONVARG(2, FGW_STR, ChangeFlag, flag = argv[2].val.str); + PCB_ACT_CONVARG(2, FGW_INT, ChangeFlag, value = argv[3].val.nat_int); + + if (value != 0 && value != 1) + PCB_ACT_FAIL(ChangeFlag); + + ChangeFlag(function, flag, value, "ChangeFlag"); + PCB_ACT_IRES(0); + return 0; +} + + +static void ChangeFlag(const char *what, const char *flag_name, int value, + const char *cmd_name) +{ + pcb_bool(*set_object) (int, void *, void *, void *); + pcb_bool(*set_selected) (int); + + if (PCB_NSTRCMP(flag_name, "join") == 0) { + /* Note: these are backwards, because the flag is "clear" but + the command is "join". */ + set_object = value ? pcb_clr_obj_join : pcb_set_obj_join; + set_selected = value ? pcb_clr_selected_join : pcb_set_selected_join; + } + else { + pcb_message(PCB_MSG_ERROR, "%s(): Flag \"%s\" is not valid\n", cmd_name, flag_name); + return; + } + + switch (pcb_funchash_get(what, NULL)) { + case F_Object: + { + int type; + void *ptr1, *ptr2, *ptr3; + pcb_coord_t x, y; + + pcb_hid_get_coords("Click on object to change", &x, &y, 0); + + if ((type = pcb_search_screen(x, y, PCB_CHANGESIZE_TYPES, &ptr1, &ptr2, &ptr3)) != PCB_OBJ_VOID) { + pcb_any_obj_t *obj = (pcb_any_obj_t *)ptr2; + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, obj)) + pcb_message(PCB_MSG_WARNING, "Sorry, %s object is locked\n", pcb_obj_type_name(obj->type)); + } + if (set_object(type, ptr1, ptr2, ptr3)) + pcb_board_set_changed_flag(pcb_true); + break; + } + + case F_SelectedVias: + case F_SelectedPins: + case F_SelectedPads: + if (set_selected(PCB_OBJ_PSTK)) + pcb_board_set_changed_flag(pcb_true); + break; + + case F_SelectedLines: + if (set_selected(PCB_OBJ_LINE)) + pcb_board_set_changed_flag(pcb_true); + break; + + case F_SelectedTexts: + if (set_selected(PCB_OBJ_TEXT)) + pcb_board_set_changed_flag(pcb_true); + break; + + case F_SelectedNames: + case F_SelectedElements: + pcb_message(PCB_MSG_ERROR, "Feature not supported\n"); + break; + + case F_Selected: + case F_SelectedObjects: + if (set_selected(PCB_CHANGESIZE_TYPES)) + pcb_board_set_changed_flag(pcb_true); + break; + } +} + +/* --------------------------------------------------------------------------- */ + +static const char pcb_acts_ChangeSizes[] = + "ChangeSizes(Object, delta|style)\n" + "ChangeSizes(SelectedObjects|Selected, delta|style)\n" + "ChangeSizes(SelectedLines|SelectedPins|SelectedVias, delta|style)\n" + "ChangeSizes(SelectedPads|SelectedTexts|SelectedNames, delta|style)\n" "ChangeSizes(SelectedElements, delta|style)"; +static const char pcb_acth_ChangeSizes[] = "Changes all sizes of objects."; +/* DOC: changesizes.html */ +static fgw_error_t pcb_act_ChangeSizes(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + fgw_error_t a, b, c; + pcb_undo_save_serial(); + a = pcb_act_ChangeSize(res, argc, argv); + pcb_undo_restore_serial(); + b = pcb_act_Change2ndSize(res, argc, argv); + pcb_undo_restore_serial(); + c = pcb_act_ChangeClearSize(res, argc, argv); + pcb_undo_restore_serial(); + pcb_undo_inc_serial(); + PCB_ACT_IRES(!(!a || !b || !c)); + return 0; +} + +/* --------------------------------------------------------------------------- */ + +static const char pcb_acts_ChangeSize[] = + "ChangeSize(Object, delta|style)\n" + "ChangeSize(SelectedObjects|Selected, delta|style)\n" + "ChangeSize(SelectedLines|SelectedPins|SelectedVias, delta|style)\n" + "ChangeSize(SelectedPads|SelectedTexts|SelectedNames, delta|style)\n" "ChangeSize(SelectedElements, delta|style)"; +static const char pcb_acth_ChangeSize[] = "Changes the size of objects."; +/* DOC: changesize.html */ +static fgw_error_t pcb_act_ChangeSize(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + const char *function; + const char *delta; + const char *units = NULL; + pcb_bool absolute; /* indicates if absolute size is given */ + pcb_coord_t value; + int type = PCB_OBJ_VOID, tostyle = 0; + void *ptr1, *ptr2, *ptr3; + + PCB_ACT_CONVARG(1, FGW_STR, ChangeSize, function = argv[1].val.str); + PCB_ACT_CONVARG(2, FGW_STR, ChangeSize, delta = argv[2].val.str); + PCB_ACT_MAY_CONVARG(3, FGW_STR, ChangeSize, units = argv[3].val.str); + + + if (function && delta) { + int funcid = pcb_funchash_get(function, NULL); + + if (funcid == F_Object) { + pcb_coord_t x, y; + pcb_hid_get_coords("Click on object to change size of", &x, &y, 0); + type = pcb_search_screen(x, y, PCB_CHANGESIZE_TYPES, &ptr1, &ptr2, &ptr3); + } + + if (strcmp(delta, "style") == 0) { + if (pcb_get_style_size(funcid, &value, type, 0) != 0) + return 1; + absolute = 1; + tostyle = 1; + } + else + value = pcb_get_value(delta, units, &absolute, NULL); + switch (funcid) { + case F_Object: + { + if (type != PCB_OBJ_VOID) { + pcb_any_obj_t *obj = (pcb_any_obj_t *)ptr2; + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, obj)) + pcb_message(PCB_MSG_WARNING, "Sorry, %s object is locked\n", pcb_obj_type_name(obj->type)); + } + if (tostyle) { + if (pcb_chg_obj_1st_size(type, ptr1, ptr2, ptr3, value, absolute)) + pcb_board_set_changed_flag(pcb_true); + } + else { + if (pcb_chg_obj_size(type, ptr1, ptr2, ptr3, value, absolute)) + pcb_board_set_changed_flag(pcb_true); + } + break; + } + case F_SelectedVias: + case F_SelectedPins: + case F_SelectedPads: + if (pcb_chg_selected_size(PCB_OBJ_PSTK, value, absolute)) + pcb_board_set_changed_flag(pcb_true); + break; + + case F_SelectedArcs: + if (pcb_chg_selected_size(PCB_OBJ_ARC, value, absolute)) + pcb_board_set_changed_flag(pcb_true); + break; + + case F_SelectedLines: + if (pcb_chg_selected_size(PCB_OBJ_LINE, value, absolute)) + pcb_board_set_changed_flag(pcb_true); + break; + + case F_SelectedTexts: + if (pcb_chg_selected_size(PCB_OBJ_TEXT, value, absolute)) + pcb_board_set_changed_flag(pcb_true); + break; + + case F_SelectedNames: + case F_SelectedElements: + pcb_message(PCB_MSG_ERROR, "Feature not supported.\n"); + break; + + case F_Selected: + case F_SelectedObjects: + if (pcb_chg_selected_size(PCB_CHANGESIZE_TYPES, value, absolute)) + pcb_board_set_changed_flag(pcb_true); + break; + } + } + + PCB_ACT_IRES(0); + return 0; +} + +/* --------------------------------------------------------------------------- */ + +static const char pcb_acts_Change2ndSize[] = + "ChangeDrillSize(Object, delta|style)\n" "ChangeDrillSize(SelectedPins|SelectedVias|Selected|SelectedObjects, delta|style)"; + +static const char pcb_acth_Change2ndSize[] = "Changes the drilling hole size of objects."; + +static fgw_error_t pcb_act_Change2ndSize(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + const char *function; + const char *delta; + const char *units = NULL; + int type = PCB_OBJ_VOID; + void *ptr1, *ptr2, *ptr3; + pcb_bool absolute; + pcb_coord_t value; + + PCB_ACT_CONVARG(1, FGW_STR, Change2ndSize, function = argv[1].val.str); + PCB_ACT_CONVARG(2, FGW_STR, Change2ndSize, delta = argv[2].val.str); + PCB_ACT_MAY_CONVARG(3, FGW_STR, Change2ndSize, units = argv[3].val.str); + + if (function && delta) { + int funcid = pcb_funchash_get(function, NULL); + + if (funcid == F_Object) { + pcb_coord_t x, y; + pcb_hid_get_coords("Select an Object", &x, &y, 0); + type = pcb_search_screen(x, y, PCB_CHANGE2NDSIZE_TYPES, &ptr1, &ptr2, &ptr3); + } + + if (strcmp(delta, "style") == 0) { + if (pcb_get_style_size(funcid, &value, type, 1) != 0) + return 1; + absolute = 1; + } + else + value = pcb_get_value(delta, units, &absolute, NULL); + + switch (pcb_funchash_get(function, NULL)) { + case F_Object: + { + + if (type != PCB_OBJ_VOID) + if (pcb_chg_obj_2nd_size(type, ptr1, ptr2, ptr3, value, absolute, pcb_true)) + pcb_board_set_changed_flag(pcb_true); + break; + } + + case F_SelectedPadstacks: + case F_SelectedVias: + case F_SelectedPins: + if (pcb_chg_selected_2nd_size(PCB_OBJ_PSTK, value, absolute)) + pcb_board_set_changed_flag(pcb_true); + break; + + case F_Selected: + case F_SelectedObjects: + if (pcb_chg_selected_2nd_size(PCB_OBJ_CLASS_PIN, value, absolute)) + pcb_board_set_changed_flag(pcb_true); + break; + } + } + PCB_ACT_IRES(0); + return 0; +} + +/* --------------------------------------------------------------------------- */ + +static const char pcb_acts_ChangePinName[] = "ChangePinName(Refdes,PinNumber,PinName)"; +static const char pcb_acth_ChangePinName[] = "Sets the name of a specific pin on a specific subcircuit."; +/* DOC: changepinname.html */ +static fgw_error_t pcb_act_ChangePinName(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + pcb_cardinal_t changed = 0; + const char *refdes, *pinnum, *pinname; + + PCB_ACT_CONVARG(1, FGW_STR, ChangePinName, refdes = argv[1].val.str); + PCB_ACT_CONVARG(2, FGW_STR, ChangePinName, pinnum = argv[2].val.str); + PCB_ACT_CONVARG(3, FGW_STR, ChangePinName, pinname = argv[3].val.str); + + PCB_SUBC_LOOP(PCB->Data); + { + if ((subc->refdes != NULL) && (PCB_NSTRCMP(refdes, subc->refdes) == 0)) { + pcb_any_obj_t *o; + pcb_data_it_t it; + + for(o = pcb_data_first(&it, subc->data, PCB_OBJ_CLASS_REAL); o != NULL; o = pcb_data_next(&it)) { + if ((o->term != NULL) && (PCB_NSTRCMP(pinnum, o->term) == 0)) { +TODO(": make this undoable") + pcb_attribute_put(&o->Attributes, "name", pinname); + pcb_board_set_changed_flag(pcb_true); + changed++; + } + } + } + } + PCB_END_LOOP; + + /* + * done with our action so increment the undo # if we actually + * changed anything + */ + if (changed) { + if (defer_updates) + defer_needs_update = 1; + else { + /* pcb_undo_inc_serial(); */ + pcb_gui->invalidate_all(); + } + } + + PCB_ACT_IRES(0); + return 0; +} + +static const char pcb_acts_ChangeName[] = "ChangeName(Object)\n" "ChangeName(Refdes)\n" "ChangeName(Layout|Layer)"; +static const char pcb_acth_ChangeName[] = "Sets the name, text string, terminal ID or refdes of objects."; +/* DOC: changename.html */ +static fgw_error_t pcb_act_ChangeName(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + int op; + char *name; + pcb_objtype_t type; + + PCB_ACT_CONVARG(1, FGW_KEYWORD, ChangeName, op = fgw_keyword(&argv[1])); + + switch(op) { + /* change the refdes of a subcircuit */ + case F_Subc: + { + pcb_coord_t x, y; + pcb_hid_get_coords("Select a subcircuit", &x, &y, 0); + type = PCB_OBJ_SUBC; + goto do_chg_name; + } + /* change the name of an object */ + case F_Object: + case F_Refdes: + { + pcb_coord_t x, y; + void *ptr1, *ptr2, *ptr3; + pcb_hid_get_coords("Select an Object", &x, &y, 0); + type = op == F_Refdes ? PCB_OBJ_SUBC : PCB_CHANGENAME_TYPES; + do_chg_name:; + if ((type = pcb_search_screen(x, y, type, &ptr1, &ptr2, &ptr3)) != PCB_OBJ_VOID) { + pcb_undo_save_serial(); + if (pcb_chg_obj_name_query(ptr2)) { + pcb_redraw(); + pcb_board_set_changed_flag(pcb_true); + pcb_actionl("DeleteRats", "AllRats", NULL); + } + } + break; + } + + /* change the layout's name */ + case F_Layout: + name = pcb_hid_prompt_for("Enter the layout name:", PCB_EMPTY(PCB->Name), "Layout name"); + /* NB: ChangeLayoutName takes ownership of the passed memory */ + if (name && pcb_board_change_name(name)) + pcb_board_set_changed_flag(pcb_true); + break; + + /* change the name of the active layer */ + case F_Layer: + name = pcb_hid_prompt_for("Enter the layer name:", PCB_EMPTY(CURRENT->name), "Layer name"); + /* NB: pcb_layer_rename_ takes ownership of the passed memory */ + if (name && (pcb_layer_rename_(CURRENT, name) == 0)) + pcb_board_set_changed_flag(pcb_true); + else + free(name); + break; + + default: + return FGW_ERR_ARG_CONV; + } + + PCB_ACT_IRES(0); + return 0; +} + +/* --------------------------------------------------------------------------- */ + +static const char pcb_acts_ChangeJoin[] = "ChangeJoin(ToggleObject|SelectedLines|SelectedArcs|Selected)"; + +static const char pcb_acth_ChangeJoin[] = "Changes the join (clearance through polygons) of objects."; + +/* DOC: changejoin.html */ + +static fgw_error_t pcb_act_ChangeJoin(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + int op; + + PCB_ACT_CONVARG(1, FGW_KEYWORD, ChangeJoin, op = fgw_keyword(&argv[1])); + + switch(op) { + case F_ToggleObject: + case F_Object: + { + pcb_coord_t x, y; + int type; + void *ptr1, *ptr2, *ptr3; + + pcb_hid_get_coords("Select an Object", &x, &y, 0); + if ((type = pcb_search_screen(x, y, PCB_CHANGEJOIN_TYPES, &ptr1, &ptr2, &ptr3)) != PCB_OBJ_VOID) + if (pcb_chg_obj_join(type, ptr1, ptr2, ptr3)) + pcb_board_set_changed_flag(pcb_true); + break; + } + + case F_SelectedLines: + if (pcb_chg_selected_join(PCB_OBJ_LINE)) + pcb_board_set_changed_flag(pcb_true); + break; + + case F_SelectedArcs: + if (pcb_chg_selected_join(PCB_OBJ_ARC)) + pcb_board_set_changed_flag(pcb_true); + break; + + case F_Selected: + case F_SelectedObjects: + if (pcb_chg_selected_join(PCB_CHANGEJOIN_TYPES)) + pcb_board_set_changed_flag(pcb_true); + break; + + default: + return FGW_ERR_ARG_CONV; + } + + PCB_ACT_IRES(0); + return 0; +} + +static const char pcb_acts_ChangeNonetlist[] = + "ChangeNonetlist(ToggleObject)\n" "ChangeNonetlist(SelectedElements)\n" "ChangeNonetlist(Selected|SelectedObjects)"; +static const char pcb_acth_ChangeNonetlist[] = "Changes the nonetlist flag of subcircuits."; +static fgw_error_t pcb_act_ChangeNonetlist(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + int op; + + PCB_ACT_CONVARG(1, FGW_KEYWORD, ChangeJoin, op = fgw_keyword(&argv[1])); + + switch(op) { + case F_ToggleObject: + case F_Object: + case F_Element: + { + pcb_coord_t x, y; + int type; + void *ptr1, *ptr2, *ptr3; + pcb_hid_get_coords("Select an Element", &x, &y, 0); + + ptr3 = NULL; + type = pcb_search_screen(x, y, PCB_CHANGENONETLIST_TYPES, &ptr1, &ptr2, &ptr3); + if (pcb_chg_obj_nonetlist(type, ptr1, ptr2, ptr3)) + pcb_board_set_changed_flag(pcb_true); + break; + } + case F_SelectedElements: + case F_Selected: + case F_SelectedObjects: + if (pcb_chg_selected_nonetlist(PCB_OBJ_SUBC)) + pcb_board_set_changed_flag(pcb_true); + break; + + default: + return FGW_ERR_ARG_CONV; + } + + PCB_ACT_IRES(0); + return 0; +} + + +static const char pcb_acts_SetThermal[] = "SetThermal(Object|SelectedPins|SelectedVias|Selected, Style)"; +static const char pcb_acth_SetThermal[] = + "Set the thermal (on the current layer) of padstacks to the given style.\n" + "Style = 0 means no thermal.\n" + "Style = 1 has diagonal fingers with sharp edges.\n" + "Style = 2 has horizontal and vertical fingers with sharp edges.\n" + "Style = 3 is a solid connection to the plane.\n" + "Style = 4 has diagonal fingers with rounded edges.\n" + "Style = 5 has horizontal and vertical fingers with rounded edges.\n"; +/* DOC: setthermal.html */ +static fgw_error_t pcb_act_SetThermal(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + const char *function; + const char *style; + void *ptr1, *ptr2, *ptr3; + int type, kind; + int err = 0; + pcb_coord_t gx, gy; + + PCB_ACT_CONVARG(1, FGW_STR, SetThermal, function = argv[1].val.str); + PCB_ACT_CONVARG(2, FGW_STR, SetThermal, style = argv[2].val.str); + + if (function && *function && style && *style) { + pcb_bool absolute; + + kind = pcb_get_value_ex(style, NULL, &absolute, NULL, NULL, NULL); + if (absolute && (kind <= 5)) + switch (pcb_funchash_get(function, NULL)) { + case F_Object: + pcb_hid_get_coords("Click on object for SetThermal", &gx, &gy, 0); + if ((type = pcb_search_screen(gx, gy, PCB_CHANGETHERMAL_TYPES, &ptr1, &ptr2, &ptr3)) != PCB_OBJ_VOID) { + pcb_chg_obj_thermal(type, ptr1, ptr2, ptr3, kind, INDEXOFCURRENT); + pcb_undo_inc_serial(); + pcb_draw(); + } + break; + case F_SelectedPins: + case F_SelectedVias: + pcb_chg_selected_thermals(PCB_OBJ_PSTK, kind, INDEXOFCURRENT); + break; + case F_Selected: + case F_SelectedElements: + pcb_chg_selected_thermals(PCB_CHANGETHERMAL_TYPES, kind, INDEXOFCURRENT); + break; + default: + err = 1; + break; + } + else + err = 1; + if (!err) { + PCB_ACT_IRES(0); + return 0; + } + } + + PCB_ACT_FAIL(SetThermal); +} + + +/* --------------------------------------------------------------------------- */ + +static const char pcb_acts_SetFlag[] = + "SetFlag(Object|Selected|SelectedObjects, flag)\n" + "SetFlag(SelectedLines|SelectedPins|SelectedVias, flag)\n" + "SetFlag(SelectedPads|SelectedTexts|SelectedNames, flag)\n" + "SetFlag(SelectedElements, flag)\n" "flag = thermal | join"; +static const char pcb_acth_SetFlag[] = "Sets flags on objects."; +/* DOC: setflag.html */ +static fgw_error_t pcb_act_SetFlag(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + const char *function; + const char *flag; + + PCB_ACT_CONVARG(1, FGW_STR, SetFlag, function = argv[1].val.str); + PCB_ACT_CONVARG(2, FGW_STR, SetFlag, flag = argv[2].val.str); + + ChangeFlag(function, flag, 1, "SetFlag"); + + PCB_ACT_IRES(0); + return 0; +} + +/* --------------------------------------------------------------------------- */ + +static const char pcb_acts_ClrFlag[] = + "ClrFlag(Object|Selected|SelectedObjects, flag)\n" + "ClrFlag(SelectedLines|SelectedPins|SelectedVias, flag)\n" + "ClrFlag(SelectedPads|SelectedTexts|SelectedNames, flag)\n" + "ClrFlag(SelectedElements, flag)\n" "flag = thermal | join"; +static const char pcb_acth_ClrFlag[] = "Clears flags on objects."; +/* DOC: clrflag.html */ +static fgw_error_t pcb_act_ClrFlag(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + const char *function; + const char *flag; + + PCB_ACT_CONVARG(1, FGW_STR, SetFlag, function = argv[1].val.str); + PCB_ACT_CONVARG(2, FGW_STR, SetFlag, flag = argv[2].val.str); + + ChangeFlag(function, flag, 0, "ClrFlag"); + + PCB_ACT_IRES(0); + return 0; +} + +static const char pcb_acts_SetValue[] = "SetValue(Grid|Line|LineSize|Text|TextScale, delta)"; +static const char pcb_acth_SetValue[] = "Change various board-wide values and sizes."; +/* DOC: setvalue.html */ +static fgw_error_t pcb_act_SetValue(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + int fnc_id; + const char *val; + const char *units = NULL; + pcb_bool absolute; /* flag for 'absolute' value */ + double value; + int err = 0; + + PCB_ACT_CONVARG(1, FGW_KEYWORD, SetValue, fnc_id = fgw_keyword(&argv[1])); + PCB_ACT_CONVARG(2, FGW_STR, SetValue, val = argv[2].val.str); + PCB_ACT_MAY_CONVARG(3, FGW_STR, SetValue, units = argv[3].val.str); + + /* special case: can't convert with pcb_get_value() */ + if ((fnc_id == F_Grid) && ((val[0] == '*') || (val[0] == '/'))) { + double d; + char *end; + + d = strtod(val+1, &end); + if ((*end != '\0') || (d <= 0)) { + pcb_message(PCB_MSG_ERROR, "SetValue: Invalid multiplier/divider for grid set: needs to be a positive number\n"); + return 1; + } + pcb_grid_inval(); + if (val[0] == '*') + pcb_board_set_grid(pcb_round(PCB->Grid * d), pcb_false, 0, 0); + else + pcb_board_set_grid(pcb_round(PCB->Grid / d), pcb_false, 0, 0); + } + + value = pcb_get_value(val, units, &absolute, NULL); + + switch(fnc_id) { + case F_Grid: + pcb_grid_inval(); + if (absolute) + pcb_board_set_grid(value, pcb_false, 0, 0); + else { + /* On the way down, short against the minimum + * PCB drawing unit */ + if ((value + PCB->Grid) < 1) + pcb_board_set_grid(1, pcb_false, 0, 0); + else if (PCB->Grid == 1) + pcb_board_set_grid(value, pcb_false, 0, 0); + else + pcb_board_set_grid(value + PCB->Grid, pcb_false, 0, 0); + } + break; + + case F_LineSize: + case F_Line: + pcb_board_set_line_width(absolute ? value : value + conf_core.design.line_thickness); + pcb_event(PCB_EVENT_ROUTE_STYLES_CHANGED, NULL); + break; + + case F_Text: + case F_TextScale: + value = pcb_round(value / (double)PCB_FONT_CAPHEIGHT * 100.0); + pcb_board_set_text_scale(absolute ? value : (value + conf_core.design.text_scale)); + break; + default: + err = 1; + break; + } + if (!err) { + PCB_ACT_IRES(0); + return 0; + } + + PCB_ACT_FAIL(SetValue); +} + +/* --------------------------------------------------------------------------- */ + +static const char pcb_acts_ChangeAngle[] = + "ChangeAngle(Object, start|delta|both, delta)\n" + "ChangeAngle(SelectedObjects|Selected, start|delta|both, delta)\n" + "ChangeAngle(SelectedArcs, start|delta|both, delta)\n"; +static const char pcb_acth_ChangeAngle[] = "Changes the start angle, delta angle or both angles of an arc."; +static fgw_error_t pcb_act_ChangeAngle(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + const char *prim; + const char *delta; + pcb_bool absolute; /* indicates if absolute size is given */ + double value; + int funcid, type = PCB_OBJ_VOID, which; + void *ptr1, *ptr2, *ptr3; + + PCB_ACT_CONVARG(1, FGW_KEYWORD, ChangeAngle, funcid = fgw_keyword(&argv[1])); + PCB_ACT_CONVARG(2, FGW_STR, ChangeAngle, prim = argv[2].val.str); + PCB_ACT_CONVARG(3, FGW_STR, ChangeAngle, delta = argv[3].val.str); + + + if (pcb_strcasecmp(prim, "start") == 0) which = 0; + else if (pcb_strcasecmp(prim, "delta") == 0) which = 1; + else if (pcb_strcasecmp(prim, "both") == 0) which = 2; + else { + pcb_message(PCB_MSG_ERROR, "Second argument of ChangeAngle must be start, delta or both\n"); + return -1; + } + + if (funcid == F_Object) { + pcb_coord_t x, y; + pcb_hid_get_coords("Click on object to change angle of", &x, &y, 0); + type = pcb_search_screen(x, y, PCB_CHANGESIZE_TYPES, &ptr1, &ptr2, &ptr3); + } + + { /* convert angle from string */ + char *end; + while(isspace(*delta)) delta++; + value = strtod(delta, &end); + if (*end != '\0') { + pcb_message(PCB_MSG_ERROR, "Invalid numeric (in angle)\n"); + return -1; + } + absolute = ((*delta != '-') && (*delta != '+')); + } + + switch(funcid) { + case F_Object: + { + if (type != PCB_OBJ_VOID) { + pcb_any_obj_t *obj = (pcb_any_obj_t *)ptr2; + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, obj)) + pcb_message(PCB_MSG_WARNING, "Sorry, %s object is locked\n", pcb_obj_type_name(obj->type)); + else { + if (pcb_chg_obj_angle(type, ptr1, ptr2, ptr3, which, value, absolute)) + pcb_board_set_changed_flag(pcb_true); + } + } + break; + } + + case F_SelectedArcs: + if (pcb_chg_selected_angle(PCB_OBJ_ARC, which, value, absolute)) + pcb_board_set_changed_flag(pcb_true); + break; + + case F_Selected: + case F_SelectedObjects: + if (pcb_chg_selected_angle(PCB_CHANGESIZE_TYPES, which, value, absolute)) + pcb_board_set_changed_flag(pcb_true); + break; + } + + PCB_ACT_IRES(0); + return 0; +} + +/* --------------------------------------------------------------------------- */ + +static const char pcb_acts_ChangeRadius[] = + "ChangeRadius(Object, width|x|height|y|both, delta)\n" + "ChangeRadius(SelectedObjects|Selected, width|x|height|y|both, delta)\n" + "ChangeRadius(SelectedArcs, width|x|height|y|both, delta)\n"; +static const char pcb_acth_ChangeRadius[] = "Changes the width or height (radius) of an arc."; +static fgw_error_t pcb_act_ChangeRadius(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + const char *prim; + const char *delta; + const char *units; + pcb_bool absolute; /* indicates if absolute size is given */ + double value; + int funcid, type = PCB_OBJ_VOID, which; + void *ptr1, *ptr2, *ptr3; + + PCB_ACT_CONVARG(1, FGW_KEYWORD, ChangeRadius, funcid = fgw_keyword(&argv[1])); + PCB_ACT_CONVARG(2, FGW_STR, ChangeRadius, prim = argv[2].val.str); + PCB_ACT_CONVARG(3, FGW_STR, ChangeRadius, delta = argv[3].val.str); + PCB_ACT_MAY_CONVARG(4, FGW_STR, ChangeRadius, units = argv[4].val.str); + + if ((pcb_strcasecmp(prim, "width") == 0) || (pcb_strcasecmp(prim, "x") == 0)) which = 0; + else if ((pcb_strcasecmp(prim, "height") == 0) || (pcb_strcasecmp(prim, "y") == 0)) which = 1; + else if (pcb_strcasecmp(prim, "both") == 0) which = 2; + else { + pcb_message(PCB_MSG_ERROR, "Second argument of ChangeRadius must be width, x, height, y or both\n"); + return -1; + } + + if (funcid == F_Object) { + pcb_coord_t x, y; + pcb_hid_get_coords("Click on object to change radius of", &x, &y, 0); + type = pcb_search_screen(x, y, PCB_CHANGESIZE_TYPES, &ptr1, &ptr2, &ptr3); + } + + value = pcb_get_value(delta, units, &absolute, NULL); + + switch(funcid) { + case F_Object: + { + if (type != PCB_OBJ_VOID) { + pcb_any_obj_t *obj = (pcb_any_obj_t *)ptr2; + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, obj)) + pcb_message(PCB_MSG_WARNING, "Sorry, %s object is locked\n", pcb_obj_type_name(obj->type)); + else { + if (pcb_chg_obj_radius(type, ptr1, ptr2, ptr3, which, value, absolute)) + pcb_board_set_changed_flag(pcb_true); + } + } + break; + } + + case F_SelectedArcs: + if (pcb_chg_selected_radius(PCB_OBJ_ARC, which, value, absolute)) + pcb_board_set_changed_flag(pcb_true); + break; + + case F_Selected: + case F_SelectedObjects: + if (pcb_chg_selected_radius(PCB_CHANGESIZE_TYPES, which, value, absolute)) + pcb_board_set_changed_flag(pcb_true); + break; + } + + PCB_ACT_IRES(0); + return 0; +} + + +/* --------------------------------------------------------------------------- */ + +pcb_action_t change_action_list[] = { + {"ChangeAngle", pcb_act_ChangeAngle, pcb_acth_ChangeAngle, pcb_acts_ChangeAngle}, + {"ChangeClearSize", pcb_act_ChangeClearSize, pcb_acth_ChangeClearSize, pcb_acts_ChangeClearSize}, + {"ChangeDrillSize", pcb_act_Change2ndSize, pcb_acth_Change2ndSize, pcb_acts_Change2ndSize}, + {"ChangeJoin", pcb_act_ChangeJoin, pcb_acth_ChangeJoin, pcb_acts_ChangeJoin}, + {"ChangeName", pcb_act_ChangeName, pcb_acth_ChangeName, pcb_acts_ChangeName}, + {"ChangePinName", pcb_act_ChangePinName, pcb_acth_ChangePinName, pcb_acts_ChangePinName}, + {"ChangeRadius", pcb_act_ChangeRadius, pcb_acth_ChangeRadius, pcb_acts_ChangeRadius}, + {"ChangeSize", pcb_act_ChangeSize, pcb_acth_ChangeSize, pcb_acts_ChangeSize}, + {"ChangeSizes", pcb_act_ChangeSizes, pcb_acth_ChangeSizes, pcb_acts_ChangeSizes}, + {"ChangeNonetlist", pcb_act_ChangeNonetlist, pcb_acth_ChangeNonetlist, pcb_acts_ChangeNonetlist}, + {"ChangeFlag", pcb_act_ChangeFlag, pcb_acth_ChangeFlag, pcb_acts_ChangeFlag}, + {"SetThermal", pcb_act_SetThermal, pcb_acth_SetThermal, pcb_acts_SetThermal}, + {"SetValue", pcb_act_SetValue, pcb_acth_SetValue, pcb_acts_SetValue}, + {"SetFlag", pcb_act_SetFlag, pcb_acth_SetFlag, pcb_acts_SetFlag}, + {"ClrFlag", pcb_act_ClrFlag, pcb_acth_ClrFlag, pcb_acts_ClrFlag} +}; + +PCB_REGISTER_ACTIONS(change_action_list, NULL) Index: tags/2.1.2/src/color.c =================================================================== --- tags/2.1.2/src/color.c (nonexistent) +++ tags/2.1.2/src/color.c (revision 24813) @@ -0,0 +1,167 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2018 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "config.h" + +#include +#include +#include + +#define GVT_DONT_UNDEF +#include "color.h" +#include + +#define PACK_COLOR_(r,g,b,a) ((((unsigned long)(r)) << 24) || (((unsigned long)(g)) << 16) || (((unsigned long)(b)) << 8) || (((unsigned long)(a)))) +#define PACK_COLOR(clr) PACK_COLOR_(clr->r, clr->g, clr->b, clr->a) +#define COLOR_TO_FLOAT(clr) \ +do { \ + clr->fr = (float)clr->r / 255.0; \ + clr->fg = (float)clr->g / 255.0; \ + clr->fb = (float)clr->b / 255.0; \ + clr->fa = (float)clr->a / 255.0; \ +} while(0) + +#define COLOR_TO_STR(clr) \ +do { \ + if (clr->a == 255) \ + sprintf(clr->str, "#%02x%02x%02x", clr->r, clr->g, clr->b); \ + else \ + sprintf(clr->str, "#%02x%02x%02x%02x", clr->r, clr->g, clr->b, clr->a); \ +} while(0) + +#define CLAMP01(c) (((c) < 0.0) ? 0.0 : (((c) > 1.0) ? 1.0 : (c))) + +int pcb_color_load_int(pcb_color_t *dst, unsigned char r, unsigned char g, unsigned char b, unsigned char a) +{ + dst->r = r; + dst->g = g; + dst->b = b; + dst->a = a; + dst->packed = PACK_COLOR(dst); + COLOR_TO_FLOAT(dst); + COLOR_TO_STR(dst); + return 0; +} + +int pcb_color_load_packed(pcb_color_t *dst, unsigned long p) +{ + dst->r = (p & 0xff000000UL) >> 24; + dst->g = (p & 0x00ff0000UL) >> 16; + dst->b = (p & 0x0000ff00UL) >> 8; + dst->a = (p & 0x000000ffUL); + COLOR_TO_FLOAT(dst); + COLOR_TO_STR(dst); + return 0; +} + +int pcb_color_load_float(pcb_color_t *dst, float r, float g, float b, float a) +{ + dst->r = CLAMP01(r) * 255.0; + dst->g = CLAMP01(g) * 255.0; + dst->b = CLAMP01(b) * 255.0; + dst->a = CLAMP01(a) * 255.0; + dst->packed = PACK_COLOR(dst); + COLOR_TO_STR(dst); + return 0; +} + +/* Convert a hex digit or return -1 on error */ +#define HEXDIGCONV(res, chr) \ +do { \ + if ((chr >= '0') && (chr <= '9')) res = chr - '0'; \ + else if ((chr >= 'a') && (chr <= 'f')) res = chr - 'a' + 10; \ + else if ((chr >= 'A') && (chr <= 'F')) res = chr - 'A' + 10; \ + else \ + return -1; \ +} while(0) + +/* convert a 2 digit hex number or return -1 on error */ +#define HEXCONV(dst_fld, src, idx) \ +do { \ + unsigned int tmp1, tmp2; \ + HEXDIGCONV(tmp1, src[idx]); \ + HEXDIGCONV(tmp2, src[idx+1]); \ + dst_fld = tmp1 << 4 | tmp2; \ +} while(0) + +int pcb_color_load_str(pcb_color_t *dst, const char *src) +{ + if (src[0] != '#') + return -1; + + HEXCONV(dst->r, src, 1); + HEXCONV(dst->g, src, 3); + HEXCONV(dst->b, src, 5); + if (src[7] != '\0') + HEXCONV(dst->a, src, 7); + else + dst->a = 255; + + dst->packed = PACK_COLOR(dst); + COLOR_TO_FLOAT(dst); + COLOR_TO_STR(dst); + return 0; +} + +pcb_color_t *pcb_clrdup(const pcb_color_t *src) +{ + pcb_color_t *dst = malloc(sizeof(pcb_color_t)); + memcpy(dst, src, sizeof(pcb_color_t)); + return dst; +} + +static pcb_color_t pcb_color_black_; +static pcb_color_t pcb_color_cyan_; +static pcb_color_t pcb_color_red_; +static pcb_color_t pcb_color_blue_; +static pcb_color_t pcb_color_drill_; +static pcb_color_t pcb_color_magenta_; +static pcb_color_t pcb_color_golden_; +static pcb_color_t pcb_color_grey33_; + +const pcb_color_t *pcb_color_black = &pcb_color_black_; +const pcb_color_t *pcb_color_cyan = &pcb_color_cyan_; +const pcb_color_t *pcb_color_red = &pcb_color_red_; +const pcb_color_t *pcb_color_blue = &pcb_color_blue_; +const pcb_color_t *pcb_color_drill = &pcb_color_drill_; +const pcb_color_t *pcb_color_grey33 = &pcb_color_grey33_; +const pcb_color_t *pcb_color_magenta = &pcb_color_magenta_; +const pcb_color_t *pcb_color_golden = &pcb_color_golden_; + +void pcb_color_init(void) +{ + pcb_color_load_str(&pcb_color_black_, "#000000"); + pcb_color_load_str(&pcb_color_cyan_, "#00ffff"); + pcb_color_load_str(&pcb_color_red_, "#ff0000"); + pcb_color_load_str(&pcb_color_blue_, "#0000ff"); + pcb_color_load_str(&pcb_color_grey33_, "#333333"); + pcb_color_load_str(&pcb_color_magenta_, "#ff00ff"); + pcb_color_load_str(&pcb_color_golden_, "#dddd22"); + pcb_color_load_str(&pcb_color_drill_, "#ff00ff"); + strcpy(pcb_color_drill_.str, "drill"); +} + + Index: tags/2.1.2/src/color.h =================================================================== --- tags/2.1.2/src/color.h (nonexistent) +++ tags/2.1.2/src/color.h (revision 24813) @@ -0,0 +1,84 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2018 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#ifndef PCB_COLOR_H +#define PCB_COLOR_H + +#include "global_typedefs.h" +#include + +struct pcb_color_s { + unsigned char r, g, b, a; /* primary storage; alpha is not really supported at the moment */ + unsigned long packed; /* cache: 32 bit portable (byte-order-safe) packed version used for lookups */ + float fr, fg, fb, fa; /* cache: 0..1 version; using float to save memory^1 */ + char str[10]; /* cache: "#rrggbb[aa]" \0 terminated string version */ +}; + +extern const pcb_color_t *pcb_color_black; +extern const pcb_color_t *pcb_color_cyan; +extern const pcb_color_t *pcb_color_red; +extern const pcb_color_t *pcb_color_blue; +extern const pcb_color_t *pcb_color_grey33; +extern const pcb_color_t *pcb_color_magenta; +extern const pcb_color_t *pcb_color_golden; +extern const pcb_color_t *pcb_color_drill; + +/* Convert a color from various formats to a pcb color; returns 0 on success */ +int pcb_color_load_int(pcb_color_t *dst, unsigned char r, unsigned char g, unsigned char b, unsigned char a); +int pcb_color_load_packed(pcb_color_t *dst, unsigned long p); +int pcb_color_load_float(pcb_color_t *dst, float r, float g, float b, float a); +int pcb_color_load_str(pcb_color_t *dst, const char *src); + +/* Same as strdup(), but for colors */ +pcb_color_t *pcb_clrdup(const pcb_color_t *src); + +void pcb_color_init(void); + + +/* temporary hack */ +#define pcb_color_is_drill(clr) (strcmp((clr)->str, "drill") == 0) + +/*** color vector ***/ + +#define GVT(x) vtclr_ ## x +#define GVT_ELEM_TYPE pcb_color_t +#define GVT_SIZE_TYPE size_t +#define GVT_DOUBLING_THRS 512 +#define GVT_START_SIZE 16 +#define GVT_FUNC +#define GVT_SET_NEW_BYTES_TO 0 + +#include +#define GVT_REALLOC(vect, ptr, size) realloc(ptr, size) +#define GVT_FREE(vect, ptr) free(ptr) +#include + +/* Note ^1: openGL uses GLfloat which is guaranteed to be at least 32 bits; +but at the end for each color component it's unreasonable to use more than 8 +bits and it is unlikely to encounter a system that is capable of doing opengl +but having a float type with less integer bits than 8. */ + +#endif Index: tags/2.1.2/src/color_cache.h =================================================================== --- tags/2.1.2/src/color_cache.h (nonexistent) +++ tags/2.1.2/src/color_cache.h (revision 24813) @@ -0,0 +1,89 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2018 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#ifndef PCB_COLOR_CACHE_H +#define PCB_COLOR_CACHE_H + +#include +#include +#include +#include "global_typedefs.h" +#include "color.h" + +typedef void (*pcb_clrcache_free_t)(pcb_clrcache_t *cache, void *hidclr); + +struct pcb_clrcache_s { + htip_t ht; + int hidsize; + pcb_clrcache_free_t hidfree; + + void *user_data; /* the caller can set this up after pcb_clrcache_init and use it in hidfree() */ +}; + +PCB_INLINE void pcb_clrcache_init(pcb_clrcache_t *cache, int hidsize, pcb_clrcache_free_t hidfree) +{ + htip_init(&cache->ht, longhash, longkeyeq); + cache->hidsize = hidsize; + cache->hidfree = hidfree; + cache->user_data = NULL; +} + +PCB_INLINE void pcb_clrcache_del(pcb_clrcache_t *cache, const pcb_color_t *color) +{ + void *old = htip_get(&cache->ht, color->packed); + if (old == NULL) + return; + if (cache->hidfree != NULL) + cache->hidfree(cache, old); + free(old); +} + +PCB_INLINE void *pcb_clrcache_get(pcb_clrcache_t *cache, const pcb_color_t *color, int alloc) +{ + void *clr = htip_get(&cache->ht, color->packed); + if (clr != NULL) + return clr; + + if (!alloc) + return NULL; + + clr = calloc(cache->hidsize, 1); + htip_set(&cache->ht, color->packed, clr); + return clr; +} + +PCB_INLINE void pcb_clrcache_uninit(pcb_clrcache_t *cache) +{ + htip_entry_t *e; + + for(e = htip_first(&cache->ht); e != NULL; e = htip_next(&cache->ht, e)) { + cache->hidfree(cache, e->value); + free(e->value); + } + htip_uninit(&cache->ht); +} + +#endif Index: tags/2.1.2/src/compat_cc.h =================================================================== --- tags/2.1.2/src/compat_cc.h (nonexistent) +++ tags/2.1.2/src/compat_cc.h (revision 24813) @@ -0,0 +1,73 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996, 2004 Thomas Nau + * 15 Oct 2008 Ineiev: add different crosshair shapes + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +#ifndef PCB_COMPAT_CC_H +#define PCB_COMPAT_CC_H + +/* --------------------------------------------------------------------------- + * Macros to annotate branch-prediction information. + * Taken from GLib 2.16.3 (LGPL 2).G_ / g_ prefixes have + * been removed to avoid namespace clashes. + */ + +/* The LIKELY and UNLIKELY macros let the programmer give hints to + * the compiler about the expected result of an expression. Some compilers + * can use this information for optimizations. + * + * The PCB_BOOLEAN_EXPR macro is intended to trigger a gcc warning when + * putting assignments inside the test. + */ +#if defined(__GNUC__) && (__GNUC__ > 2) && defined(__OPTIMIZE__) +# define PCB_BOOLEAN_EXPR(expr) \ + __extension__ ({ \ + int _boolean_var_; \ + if (expr) \ + _boolean_var_ = 1; \ + else \ + _boolean_var_ = 0; \ + _boolean_var_; \ +}) +# define PCB_LIKELY(expr) (__builtin_expect (PCB_BOOLEAN_EXPR(expr), 1)) +# define PCB_UNLIKELY(expr) (__builtin_expect (PCB_BOOLEAN_EXPR(expr), 0)) +#else +# define PCB_LIKELY(expr) (expr) +# define PCB_UNLIKELY(expr) (expr) +#endif + +#ifndef GCC_VERSION +# define GCC_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__) +#endif /* GCC_VERSION */ + +#if GCC_VERSION > 2007 +# define PCB_ATTRIBUTE_UNUSED __attribute__((unused)) +#else +# define PCB_ATTRIBUTE_UNUSED +#endif + +#endif Index: tags/2.1.2/src/compat_fs.c =================================================================== --- tags/2.1.2/src/compat_fs.c (nonexistent) +++ tags/2.1.2/src/compat_fs.c (revision 24813) @@ -0,0 +1,332 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996,2004,2006 Thomas Nau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + + +/* misc functions used by several modules */ + +#define PCB_SAFE_FS +#include "config.h" + +#include "compat_inc.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "compat_fs.h" +#include "compat_misc.h" +#include "globalconst.h" +#include "safe_fs.h" + +#include + +#include "error.h" + +char *pcb_get_wd(char *path) +{ +#if defined(HAVE_GETCWD) + return getcwd(path, PCB_PATH_MAX); +#elif defined(HAVE__GETCWD) + return _getcwd(path, PCB_PATH_MAX); +#else + /* seems that some BSD releases lack of a prototype for getwd() */ + return getwd(path); +#endif +} + +#if defined(USE_MKDIR) +# define MKDIR mkdir +#elif defined(USE__MKDIR) +# define MKDIR _mkdir +#else +# error no mkdir() available +#endif +int pcb_mkdir_(const char *path, int mode) +{ +#if MKDIR_NUM_ARGS == 1 + return MKDIR(path); +#elif MKDIR_NUM_ARGS == 2 + return MKDIR(path, mode); +#else +# error invalid number of arguments for mkdir +#endif +} +#undef MKDIR + +int pcb_file_readable(const char *path) +{ + FILE *f; + f = pcb_fopen(path, "r"); + if (f != NULL) { + fclose(f); + return 1; + } + return 0; +} + +int pcb_spawnvp(const char **argv) +{ +#if defined(USE_SPAWNVP) + int result = _spawnvp(_P_WAIT, argv[0], (const char *const *) argv); + if (result == -1) + return 1; + else + return 0; +#elif defined(USE_FORK_WAIT) + int pid; + pid = fork(); + if (pid < 0) { + /* error */ + pcb_message(PCB_MSG_ERROR, "Cannot fork!"); + return 1; + } + else if (pid == 0) { + /* Child */ + execvp(argv[0], (char* const*) argv); + exit(1); + } + else { + int rv; + /* Parent */ + wait(&rv); + } + return 0; +#else +# error Do not know how to run a background process. +#endif +} + + +/* Hopefully the operating system + * provides a mkdtemp() function to securely create a temporary + * directory with mode 0700. If so then that directory is created and + * the returned string is made up of the directory plus the name + * variable. For example: + * + * pcb_tempfile_name_new("myfile") might return + * "/var/tmp/pcb.123456/myfile". + * + * If mkdtemp() is not available then 'name' is ignored and the + * insecure tmpnam() function is used. + * + * Files/names created with pcb_tempfile_name_new() should be unlinked + * with tempfile_unlink to make sure the temporary directory is also + * removed when mkdtemp() is used. + */ +char *pcb_tempfile_name_new(const char *name) +{ + char *tmpfile = NULL; +#ifdef HAVE_MKDTEMP +#ifdef inline + /* Suppress compiler warnings; -Dinline means we are compiling in + --debug with -ansi -pedantic; we do know that mkdtemp exists on the system, + since HAVE_MKDTEMP is set. */ + char *mkdtemp(char *template); +#endif + const char *tmpdir; + char *mytmpdir; + size_t len; +#endif + + assert(name != NULL); + +#ifdef HAVE_MKDTEMP +#define TEMPLATE "pcb.XXXXXXXX" + + + tmpdir = getenv("TMPDIR"); + + /* FIXME -- what about win32? */ + if (tmpdir == NULL) { + tmpdir = "/tmp"; + } + + mytmpdir = (char *) malloc(sizeof(char) * (strlen(tmpdir) + 1 + strlen(TEMPLATE) + 1)); + if (mytmpdir == NULL) { + fprintf(stderr, "pcb_tempfile_name_new(): malloc failed()\n"); + exit(1); + } + + *mytmpdir = '\0'; + (void) strcat(mytmpdir, tmpdir); + (void) strcat(mytmpdir, PCB_DIR_SEPARATOR_S); + (void) strcat(mytmpdir, TEMPLATE); + if (mkdtemp(mytmpdir) == NULL) { + fprintf(stderr, "pcb_spawnvp(): mkdtemp (\"%s\") failed\n", mytmpdir); + free(mytmpdir); + return NULL; + } + + + len = strlen(mytmpdir) + /* the temp directory name */ + 1 + /* the directory sep. */ + strlen(name) + /* the file name */ + 1 /* the \0 termination */ + ; + + tmpfile = (char *) malloc(sizeof(char) * len); + + *tmpfile = '\0'; + (void) strcat(tmpfile, mytmpdir); + (void) strcat(tmpfile, PCB_DIR_SEPARATOR_S); + (void) strcat(tmpfile, name); + + free(mytmpdir); +#undef TEMPLATE +#else + /* + * tmpnam() uses a static buffer so pcb_strdup() the result right away + * in case someone decides to create multiple temp names. + */ + tmpfile = pcb_strdup(tmpnam(NULL)); +#ifdef __WIN32__ + { + /* Guile doesn't like \ separators */ + char *c; + for (c = tmpfile; *c; c++) + if (*c == '\\') + *c = '/'; + } +#endif +#endif + + return tmpfile; +} + +/* If we have mkdtemp() then our temp file lives in a temporary directory and + * we need to remove that directory too. */ +int pcb_tempfile_unlink(char *name) +{ +#ifdef DEBUG + /* SDB says: Want to keep old temp files for examination when debugging */ + return 0; +#endif + +#ifdef HAVE_MKDTEMP + int e, rc2 = 0; + char *dname; + + unlink(name); + /* it is possible that the file was never created so it is OK if the + unlink fails */ + + /* now figure out the directory name to remove */ + e = strlen(name) - 1; + while (e > 0 && name[e] != PCB_DIR_SEPARATOR_C) { + e--; + } + + dname = pcb_strdup(name); + dname[e] = '\0'; + + /* + * at this point, e *should* point to the end of the directory part + * but lets make sure. + */ + if (e > 0) { + rc2 = rmdir(dname); + if (rc2 != 0) { + perror(dname); + } + + } + else { + fprintf(stderr, "pcb_tempfile_unlink(): Unable to determine temp directory name from the temp file\n"); + fprintf(stderr, "pcb_tempfile_unlink(): \"%s\"\n", name); + rc2 = -1; + } + + /* name was allocated with malloc */ + free(dname); + free(name); + + /* + * FIXME - should also return -1 if the temp file exists and was not + * removed. + */ + if (rc2 != 0) { + return -1; + } + +#else + int rc = unlink(name); + + if (rc != 0) { + fprintf(stderr, "Failed to unlink \"%s\"\n", name); + free(name); + return rc; + } + free(name); + +#endif + + return 0; +} + +int pcb_is_dir_(const char *path) +{ + struct stat st; + if (stat(path, &st) != 0) + return 0; + return S_ISDIR(st.st_mode); +} + +long pcb_file_size_(const char *path) +{ + struct stat st; + if (stat(path, &st) != 0) + return -1; + if (st.st_size > LONG_MAX) + return -1; + return st.st_size; +} + +int pcb_is_path_abs(const char *fn) +{ +#ifdef __WIN32__ + /* full path with drive, e.g. c:\foo */ + if (isalpha(fn[0]) && (fn[1] == ':') && ((fn[2] == '\\') || (fn[2] == '/'))) + return 1; + + /* full path without drive and remote paths, e.g. \\workgroup\foo */ + if ((fn[0] == '\\') || (fn[0] == '/'))) + return 1; + + return 0; +#else + return (*fn == '/'); +#endif +} Index: tags/2.1.2/src/compat_fs.h =================================================================== --- tags/2.1.2/src/compat_fs.h (nonexistent) +++ tags/2.1.2/src/compat_fs.h (revision 24813) @@ -0,0 +1,20 @@ +/* Returns pointer to current working directory. If 'path' is not NULL, then + the current working directory is copied to the array pointed to by 'path' */ +char *pcb_get_wd(char *path); + +/* alternative to system() for proper argument passing */ +int pcb_spawnvp(const char **argv); + +/* Return 1 if path is a file that can be opened for read */ +int pcb_file_readable(const char *path); + +/* Creates a new temporary file name. Warning: race condition: doesn't create +the file! */ +char *pcb_tempfile_name_new(const char *name); + +/* remove temporary file and _also_ free the memory for name + * (this fact is a little confusing) */ +int pcb_tempfile_unlink(char *name); + +/* Return non-zero if fn is an absolute path */ +int pcb_is_path_abs(const char *fn); Index: tags/2.1.2/src/compat_inc.h.in =================================================================== --- tags/2.1.2/src/compat_inc.h.in (nonexistent) +++ tags/2.1.2/src/compat_inc.h.in (revision 24813) @@ -0,0 +1,60 @@ +put /local/pcb/compat_inc [@ + +@?/host/libs/fs/realpath/includes@ +@?libs/ldl/includes@ +@?libs/LoadLibrary/includes@ +@?libs/fs/getcwd/includes@ +@?libs/fs/_getcwd/includes@ +@?libs/fs/getwd/includes@ +@?/target/libs/proc/wait/includes@ +@?/target/libs/proc/fork/includes@ +@?/target/libs/proc/_spawnvp/includes@ +@?/target/libs/fs/mkdir/includes@ +@?/target/libs/fs/_mkdir/includes@ +@?/target/libs/fs/mkdtemp/includes@ +@?/target/libs/userpass/getpwuid/includes@ +@?/target/libs/math/round/includes@ +@?/target/libs/env/setenv/includes@ +@?/target/libs/fs/readdir/includes@ +@?/target/libs/io/fileno/includes@ +@?/target/libs/time/Sleep/includes@ +@?/target/libs/time/usleep/includes@ +@?/target/libs/time/gettimeofday/includes@ +@?/target/libs/socket/select/includes@ +@] + +put /tmpasm/IFS {\n} +put /local/OFS_save /tmpasm/OFS +put /tmpasm/OFS {\n} +gsub /local/pcb/compat_inc {\\\\n *} {\n} +uniq /local/pcb/compat_inc /local/pcb/compat_inc {#define} {#include} + +# do not redefine _XOPEN_SOURCE, which is hardwired in this template +gsub /local/pcb/compat_inc {#define *_XOPEN_SOURCE} {} + +put /tmpasm/OFS /local/OFS_save + + +print [@ +/*** DO NOT EDIT - automatically generated by scconfig ***/ + +#ifndef _DEFAULT_SOURCE +#define _DEFAULT_SOURCE +#endif + +#define _XOPEN_SOURCE 500 + +/* system-dependent includes, as detected in ./configure */ + +@/local/pcb/compat_inc@ + +/* These are required for stat() but are C89. Keeping them here, just in case. */ +#include +#include + + +/* Name of fileno() differs on windows */ +#define PCB_HOST_FILENO(f) @/target/libs/io/fileno/call@(f) +@] + + Index: tags/2.1.2/src/compat_lrealpath.c =================================================================== --- tags/2.1.2/src/compat_lrealpath.c (nonexistent) +++ tags/2.1.2/src/compat_lrealpath.c (revision 24813) @@ -0,0 +1,157 @@ +/* Libiberty realpath. Like realpath, but more consistent behavior. + Based on gdb_realpath from GDB. + + Copyright 2003 Free Software Foundation, Inc. + + This file is part of the libiberty library. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, + Boston, MA 02110-1301, USA. */ + +/* + +@deftypefn Replacement {const char*} pcb_lrealpath(const char *@var{name}) + +Given a pointer to a string containing a pathname, returns a canonical +version of the filename. Symlinks will be resolved, and ``.'' and ``..'' +components will be simplified. The returned value will be allocated using +@code{malloc}, or @code{NULL} will be returned on a memory allocation error. + +@end deftypefn + +*/ + +#include "compat_inc.h" +#include "config.h" +#include "compat_lrealpath.h" +#include +#include +#ifdef HAVE_UNISTD_H +#include +#endif +#include +#include "compat_misc.h" + +/* On GNU libc systems the declaration is only visible with _GNU_SOURCE. */ +#if defined(HAVE_CANONICALIZE_FILE_NAME) \ + && defined(NEED_DECLARATION_CANONICALIZE_FILE_NAME) +extern char *canonicalize_file_name(const char *); +#endif + +#if defined(HAVE_REALPATH) +#if defined (PATH_MAX) +#define REALPATH_LIMIT PATH_MAX +#else +#if defined (PCB_PATH_MAX) +#define REALPATH_LIMIT PCB_PATH_MAX +#endif +#endif +#else + /* cygwin has realpath, so it won't get here. */ +#if defined (_WIN32) +#define WIN32_LEAN_AND_MEAN +#include /* for GetFullPathName */ +#endif +#endif + +char *pcb_lrealpath(const char *filename) +{ + /* Method 1: The system has a compile time upper bound on a filename + path. Use that and realpath() to canonicalize the name. This is + the most common case. Note that, if there isn't a compile time + upper bound, you want to avoid realpath() at all costs. */ +#if defined(REALPATH_LIMIT) + { + char buf[REALPATH_LIMIT]; + const char *rp = realpath(filename, buf); + if (rp == NULL) + rp = filename; + return pcb_strdup(rp); + } + /* REALPATH_LIMIT */ + + /* Method 2: The host system (i.e., GNU) has the function + canonicalize_file_name() which malloc's a chunk of memory and + returns that, use that. */ +#elif defined(HAVE_CANONICALIZE_FILE_NAME) + { + char *rp = canonicalize_file_name(filename); + if (rp == NULL) + return pcb_strdup(filename); + else + return rp; + } + /* HAVE_CANONICALIZE_FILE_NAME */ + + /* Method 3: Now we're getting desperate! The system doesn't have a + compile time buffer size and no alternative function. Query the + OS, using pathconf(), for the buffer limit. Care is needed + though, some systems do not limit PATH_MAX (return -1 for + pathconf()) making it impossible to pass a correctly sized buffer + to realpath() (it could always overflow). On those systems, we + skip this. */ +#elif defined (HAVE_REALPATH) && defined (HAVE_UNISTD_H) + { +#ifdef inline + /* Suppress compiler warnings; -Dinline means we are compiling in + --debug with -ansi -pedantic; we do know that realpath exists on the system, + because of the the ifdefs. */ + char *realpath(const char *path, char *resolved_path); +#endif + + /* Find out the max path size. */ + long path_max = pathconf("/", _PC_PATH_MAX); + if (path_max > 0) { + /* PATH_MAX is bounded. */ + char *buf, *rp, *ret; + buf = (char *) malloc(path_max); + if (buf == NULL) + return NULL; + rp = realpath(filename, buf); + ret = pcb_strdup(rp ? rp : filename); + free(buf); + return ret; + } + return NULL; + } + /* HAVE_REALPATH && HAVE_UNISTD_H */ + + /* The MS Windows method. If we don't have realpath, we assume we + don't have symlinks and just canonicalize to a Windows absolute + path. GetFullPath converts ../ and ./ in relative paths to + absolute paths, filling in current drive if one is not given + or using the current directory of a specified drive (eg, "E:foo"). + It also converts all forward slashes to back slashes. */ +#elif defined (_WIN32) + { + char buf[MAX_PATH]; + char *basename; + DWORD len = GetFullPathName(filename, MAX_PATH, buf, &basename); + if (len == 0 || len > MAX_PATH - 1) + return pcb_strdup(filename); + else { + /* The file system is case-preserving but case-insensitive, + Canonicalize to lowercase, using the codepage associated + with the process locale. */ + CharLowerBuff(buf, len); + return pcb_strdup(buf); + } + } +#else + + /* This system is a lost cause, just duplicate the filename. */ + return pcb_strdup(filename); +#endif +} Index: tags/2.1.2/src/compat_lrealpath.h =================================================================== --- tags/2.1.2/src/compat_lrealpath.h (nonexistent) +++ tags/2.1.2/src/compat_lrealpath.h (revision 24813) @@ -0,0 +1,7 @@ +#ifndef PCB_LREALPATH_H +#define PCB_LREALPATH_H + +/* A well-defined realpath () that is always compiled in. */ +char *pcb_lrealpath(const char *); + +#endif /* PCB_LREALPATH_H */ Index: tags/2.1.2/src/compat_misc.c =================================================================== --- tags/2.1.2/src/compat_misc.c (nonexistent) +++ tags/2.1.2/src/compat_misc.c (revision 24813) @@ -0,0 +1,246 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 2004, 2006 Dan McMahill + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "compat_inc.h" +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include "compat_misc.h" + +/* On some old systems random() works better than rand(). Unfortunately +random() is less portable than rand(), which is C89. By default, just +use rand(). Later on: scconfig should detect and enable random() if +we find a system where it really breaks. */ +#ifdef HAVE_RANDOM +long pcb_rand(void) +{ + return (long) random(); +} +#else +long pcb_rand(void) +{ + return (long) rand(); +} +#endif + +const char *pcb_get_user_name(void) +{ +#ifdef HAVE_GETPWUID + static struct passwd *pwentry; + + int len; + char *comma, *gecos, *fab_author; + + /* ID the user. */ + pwentry = getpwuid(getuid()); + gecos = pwentry->pw_gecos; + comma = strchr(gecos, ','); + if (comma) + len = comma - gecos; + else + len = strlen(gecos); + fab_author = (char *) malloc(len + 1); + if (!fab_author) { + perror("pcb: out of memory.\n"); + exit(-1); + } + memcpy(fab_author, gecos, len); + fab_author[len] = 0; + return fab_author; +#else + return "Unknown"; +#endif +} + +int pcb_getpid(void) +{ + return getpid(); +} + +char *pcb_strndup(const char *s, int len) +{ + int a, l = strlen(s); + char *o; + + a = (len < l) ? len : l; + o = malloc(a+1); + memcpy(o, s, a); + o[a] = '\0'; + return o; +} + +char *pcb_strdup(const char *s) +{ + int l = strlen(s); + char *o; + o = malloc(l+1); + memcpy(o, s, l+1); + return o; +} + +#ifdef HAVE_ROUND +#undef round +extern double round(double x); +double pcb_round(double x) +{ + return round(x); +} +#else + +/* Implementation idea borrowed from an old gcc (GPL'd) */ +double pcb_round(double x) +{ + double t; + +/* We should check for inf here, but inf is not in C89; if we'd have isinf(), + we'd have round() as well and we wouldn't be here at all. */ + + if (x >= 0.0) { + t = ceil(x); + if (t - x > 0.5) + t -= 1.0; + return t; + } + + t = ceil(-x); + if ((t + x) > 0.5) + t -= 1.0; + return -t; +} +#endif + +int pcb_strcasecmp(const char *s1, const char *s2) +{ + while(tolower(*s1) == tolower(*s2)) { + if (*s1 == '\0') + return 0; + s1++; + s2++; + } + return tolower(*s1) - tolower(*s2); +} + +int pcb_strncasecmp(const char *s1, const char *s2, size_t n) +{ + if (n == 0) + return 0; + + while(tolower(*s1) == tolower(*s2)) { + n--; + if (n == 0) + return 0; + if (*s1 == '\0') + return 0; + s1++; + s2++; + } + return tolower(*s1) - tolower(*s2); +} + +#ifdef PCB_HAVE_SETENV + extern int setenv(); +#endif + +int pcb_setenv(const char *name, const char *val, int overwrite) +{ +#ifdef PCB_HAVE_SETENV + return setenv(name, val, overwrite); +#else +# ifdef PCB_HAVE_PUTENV + int res; + gds_t tmp; + gds_init(&tmp); + gds_append_str(&tmp, name); + gds_append(&tmp, '='); + gds_append_str(&tmp, val); + res = putenv(tmp.array); + gds_uninit(&tmp); + return res; +# else + return -1; +# endif +#endif +} + +size_t pcb_print_utc(char *out, size_t out_len, time_t when) +{ + static const char *fmt = "%Y-%m-%d %H:%M:%S UTC"; + if (when <= 0) + when = time(NULL); + + return strftime(out, out_len, fmt, gmtime(&when)); +} + +void pcb_ms_sleep(long ms) +{ +#ifdef PCB_HAVE_USLEEP + usleep(ms*1000); +#else +# ifdef PCB_HAVE_WSLEEP + Sleep(ms); +# else +# ifdef PCB_HAVE_SELECT + fd_set s; + struct timeval tv; + + FD_ZERO(&s); + tv.tv_sec = 0; + tv.tv_usec = ms*1000; + select(0, &s, &s, &s, &tv); +# else +# error pcb_ms_sleep(): no milisecond sleep on this host. +# endif +# endif +#endif +} + +void pcb_ltime(unsigned long *secs, unsigned long *usecs) +{ + struct timeval tv; + gettimeofday(&tv, NULL); + *secs = tv.tv_sec; + if (usecs != NULL) + *usecs = tv.tv_usec; +} + +double pcb_dtime(void) +{ + unsigned long s, u; + + pcb_ltime(&s, &u); + return (double)u / 1000000.0 + (double)s; +} + +int pcb_fileno(FILE *f) +{ + return PCB_HOST_FILENO(f); +} Index: tags/2.1.2/src/compat_misc.h =================================================================== --- tags/2.1.2/src/compat_misc.h (nonexistent) +++ tags/2.1.2/src/compat_misc.h (revision 24813) @@ -0,0 +1,73 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 2004 Dan McMahill + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#ifndef PCB_COMPAT_MISC_H +#define PCB_COMPAT_MISC_H + +#include "config.h" + +#include +#include +#include +#include + +long pcb_rand(void); + +/* Gets the user's real name when available; normally shouldn't be used, + consider using pcb_author() that allows config override */ +const char *pcb_get_user_name(void); + +int pcb_getpid(void); + +char *pcb_strndup(const char *s, int len); +char *pcb_strdup(const char *s); + +#define pcb_strdup_null(x) (((x) != NULL) ? pcb_strdup (x) : NULL) + +double pcb_round(double x); + +int pcb_strcasecmp(const char *s1, const char *s2); +int pcb_strncasecmp(const char *s1, const char *s2, size_t n); + +int pcb_setenv(const char *name, const char *val, int overwrite); + +/* Print a date in UTC; if when is 0, print current date */ +size_t pcb_print_utc(char *out, size_t out_len, time_t when); + +/* Sleep for the specified number if miliseconds */ +void pcb_ms_sleep(long ms); + +/* Return system time (local, time zoned) in seconds and microseconds + since epoch. (gettimeofday() wrapper) */ +void pcb_ltime(unsigned long *secs, unsigned long *usecs); + +/* Return system time (local, time zoned) since epoch. (gettimeofday() wrapper) */ +double pcb_dtime(void); + +int pcb_fileno(FILE *f); + +#endif /* PCB_COMPAT_MISC_H */ Index: tags/2.1.2/src/conf.c =================================================================== --- tags/2.1.2/src/conf.c (nonexistent) +++ tags/2.1.2/src/conf.c (revision 24813) @@ -0,0 +1,2114 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2016 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include +#include +#include +#include +#include +#include +#include +#include "config.h" +#include "conf.h" +#include "conf_core.h" +#include "conf_hid.h" +#include "hid_cfg.h" +#include "misc_util.h" +#include "error.h" +#include "paths.h" +#include "compat_fs.h" +#include "compat_misc.h" +#include "safe_fs.h" +#include "file_loaded.h" + +#define CONF_USER_DIR "~/" DOT_PCB_RND + +/* conf list node's name */ +const char *conf_list_name = "pcb-rnd-conf-v1"; +static const char *conf_user_fn = CONF_USER_DIR "/pcb-conf.lht"; +static const char *flcat = "conf"; + +/* plugin config files and interns */ +static htsi_t conf_files; +static htsi_t conf_interns; +static int conf_files_inited = 0; + + +int conf_in_production = 0; + +/* The main conf: monolithic config files affecting all parts of the conf tree; + By default every operation is done on these trees. */ +lht_doc_t *conf_main_root[CFR_max_alloc]; +int conf_main_root_lock[CFR_max_alloc]; +int conf_lht_dirty[CFR_max_alloc]; + +/* Plugin config: only plugin configuration is accepted; never edited, only + merged in. Merge takes two steps: first all files per role are merged into + a single conf_plug_root[R] (lihata level merge), then conf_plug_root[R] + is merged in using the normal conf merge mechanism. Plug roots are + merged before main roots so main root overwrite are stronger. */ +lht_doc_t *conf_plug_root[CFR_max_alloc]; + + +htsp_t *conf_fields = NULL; +const int conf_default_prio[] = { +/* CFR_INTERNAL */ 100, +/* CFR_SYSTEM */ 200, +/* CFR_DEFAULTPCB */ 300, +/* CFR_USER */ 400, +/* CFR_ENV */ 500, +/* CFR_PROJECT */ 600, +/* CFR_DESIGN */ 700, +/* CFR_CLI */ 800, +0, 0, 0, 0, 0, 0, 0, 0, 0 /* make sure the array is addressable until CFR_max_alloc */ +}; + +extern const char *conf_internal; + + +static lht_node_t *conf_lht_get_confroot(lht_node_t *cwd) +{ + if (cwd == NULL) + return NULL; + + /* if it's a list with a matching name, we found it */ + if ((cwd->type == LHT_LIST) && (strcmp(cwd->name, conf_list_name) == 0)) + return cwd; + + /* else it may be the parent-hash of the list */ + if (cwd->type != LHT_HASH) + return NULL; + + return lht_dom_hash_get(cwd, conf_list_name); +} + +int conf_insert_tree_as(conf_role_t role, lht_node_t *root) +{ + lht_doc_t *d; + + if ((root->type != LHT_LIST) || (strcmp(root->name, "pcb-rnd-conf-v1") != 0)) + return -1; + + if (conf_main_root[role] != NULL) { + lht_dom_uninit(conf_main_root[role]); + conf_main_root[role] = NULL; + } + + d = lht_dom_init(); + d->root = lht_dom_node_alloc(LHT_LIST, "pcb-rnd-conf-v1"); + d->root->doc = d; + lht_tree_merge(d->root, root); + conf_main_root[role] = d; + return 0; +} + +static lht_doc_t *conf_load_plug_file(const char *fn, int fn_is_text) +{ + lht_doc_t *d; + const char *ifn; + + if (fn_is_text) { + d = pcb_hid_cfg_load_str(fn); + ifn = ""; + } + else { + d = pcb_hid_cfg_load_lht(fn); + ifn = fn; + } + + if (d == NULL) { + pcb_message(PCB_MSG_ERROR, "error: failed to load lht plugin config: %s (can't open the file or syntax error)\n", ifn); + return NULL; + } + + if (d->root == NULL) { + pcb_message(PCB_MSG_ERROR, "error: failed to load lht plugin config: %s (no root)\n", ifn); + lht_dom_uninit(d); + return NULL; + } + + if ((d->root->type != LHT_LIST) || (strcmp(d->root->name, "pcb-rnd-conf-v1") != 0)) { + pcb_message(PCB_MSG_ERROR, "error: failed to load lht plugin config: %s (not a pcb-rnd-conf-v1)\n", ifn); + lht_dom_uninit(d); + return NULL; + } + + return d; +} + +int conf_load_as(conf_role_t role, const char *fn, int fn_is_text) +{ + lht_doc_t *d; + const char *ifn, *role_name = conf_role_name(role); + + if (conf_main_root_lock[role]) + return -1; + if (conf_main_root[role] != NULL) { + lht_dom_uninit(conf_main_root[role]); + conf_main_root[role] = NULL; + if (role_name != NULL) + pcb_file_loaded_del_at(flcat, role_name); + } + if (fn_is_text) { + d = pcb_hid_cfg_load_str(fn); + ifn = ""; + } + else { + d = pcb_hid_cfg_load_lht(fn); + ifn = fn; + } + + if (d == NULL) { + FILE *f; + char *efn; + + f = pcb_fopen_fn(fn, "r", &efn); + if (f != NULL) { /* warn only if the file is there - missing file is normal */ + pcb_message(PCB_MSG_ERROR, "error: failed to load lht config: %s (%s)\n", fn, efn); + fclose(f); + } + free(efn); + return -1; + } + + if (d->root == NULL) { + lht_node_t *prjroot, *confroot; + prjroot = lht_dom_node_alloc(LHT_HASH, "coraleda-project-v1"); + confroot = lht_dom_node_alloc(LHT_LIST, "pcb-rnd-conf-v1"); + lht_dom_hash_put(prjroot, confroot); + prjroot->doc = d; + confroot->doc = d; + d->root = prjroot; + conf_main_root[role] = d; + if (role_name != NULL) + pcb_file_loaded_set_at(flcat, role_name, ifn, "project/conf"); + return 0; + } + + if ((d->root->type == LHT_LIST) && (strcmp(d->root->name, "pcb-rnd-conf-v1") == 0)) { + conf_main_root[role] = d; + if (role_name != NULL) + pcb_file_loaded_set_at(flcat, role_name, ifn, "conf"); + return 0; + } + + if ((d->root->type == LHT_HASH) && ((strcmp(d->root->name, "geda-project-v1") == 0) || (strcmp(d->root->name, "coraleda-project-v1") == 0))) { + lht_node_t *confroot; + confroot = lht_tree_path_(d, d->root, "pcb-rnd-conf-v1", 1, 0, NULL); + + if (role_name != NULL) + pcb_file_loaded_set_at(flcat, role_name, ifn, "project/conf"); + + if ((confroot != NULL) && (confroot->type == LHT_LIST) && (strcmp(confroot->name, "li:pcb-rnd-conf-v1") == 0)) { + conf_main_root[role] = d; + return 0; + } + + /* project file with no config root */ + confroot = lht_dom_node_alloc(LHT_LIST, "pcb-rnd-conf-v1"); + lht_dom_hash_put(d->root, confroot); + conf_main_root[role] = d; + return 0; + } + + pcb_hid_cfg_error(d->root, "Root node must be one of li:pcb-rnd-conf-v1, ha:coraleda-project-v1 or ha:geda-project-v1\n"); + + if (d != NULL) + lht_dom_uninit(d); + return -1; +} + + +static int conf_merge_plug(lht_doc_t *d, conf_role_t role, const char *path) +{ + lht_err_t err; + + if (conf_plug_root[role] == NULL) { + conf_plug_root[role] = lht_dom_init(); + conf_plug_root[role]->root = lht_dom_node_alloc(LHT_LIST, "pcb-rnd-conf-v1"); + conf_plug_root[role]->root->doc = conf_plug_root[role]; + } + err = lht_tree_merge(conf_plug_root[role]->root, d->root); + lht_dom_uninit(d); + if (err != 0) { + pcb_message(PCB_MSG_ERROR, "Failed to lihata-merge plugin config %s: %s\n", path, lht_err_str(err)); + return 0; + } + return 1; +} + +/* Load plugin config files */ +static int conf_load_plug_files(conf_role_t role, const char *dir) +{ + char path[PCB_PATH_MAX], *fn; + int dlen, cnt = 0; + htsi_entry_t *e; + + if (conf_plug_root[role] != NULL) { + lht_dom_uninit(conf_plug_root[role]); + conf_plug_root[role] = NULL; + } + + if (!conf_files_inited) return 0; + + dlen = strlen(dir); + memcpy(path, dir, dlen); + path[dlen] = '/'; + fn = path+dlen+1; + + for (e = htsi_first(&conf_files); e; e = htsi_next(&conf_files, e)) { + strcpy(fn, e->key); + if (pcb_file_readable(path)) { + lht_doc_t *d = conf_load_plug_file(path, 0); + if (d != NULL) { + int res = conf_merge_plug(d, role, path); + if (res) { + char id[256]; + pcb_snprintf(id, sizeof(id), "%s:%s", conf_role_name(role), fn); + pcb_file_loaded_set_at("conf/plugin", id, path, NULL); + } + cnt += res; + } + } + } + + return cnt; +} + +static int conf_load_plug_interns(conf_role_t role) +{ + int cnt = 0; + htsi_entry_t *e; + + if (conf_plug_root[role] != NULL) { + lht_dom_uninit(conf_plug_root[role]); + conf_plug_root[role] = NULL; + } + + if (!conf_files_inited) return 0; + for (e = htsi_first(&conf_interns); e; e = htsi_next(&conf_interns, e)) { + lht_doc_t *d = conf_load_plug_file(e->key, 1); + if (d != NULL) { + int res = conf_merge_plug(d, role, NULL); + cnt += res; + } + } + + return cnt; +} + +conf_policy_t conf_policy_parse(const char *s) +{ + if (pcb_strcasecmp(s, "overwrite") == 0) return POL_OVERWRITE; + if (pcb_strcasecmp(s, "prepend") == 0) return POL_PREPEND; + if (pcb_strcasecmp(s, "append") == 0) return POL_APPEND; + if (pcb_strcasecmp(s, "disable") == 0) return POL_DISABLE; + return POL_invalid; +} + +const char *conf_policy_name(conf_policy_t p) +{ + switch(p) { + case POL_OVERWRITE: return "overwrite"; + case POL_PREPEND: return "prepend"; + case POL_APPEND: return "append"; + case POL_DISABLE: return "disable"; + case POL_invalid: return "(invalid)"; + } + return "(unknown)"; +} + +conf_role_t conf_role_parse(const char *s) +{ + if (pcb_strcasecmp(s, "internal") == 0) return CFR_INTERNAL; + if (pcb_strcasecmp(s, "system") == 0) return CFR_SYSTEM; + if (pcb_strcasecmp(s, "defaultpcb") == 0) return CFR_DEFAULTPCB; + if (pcb_strcasecmp(s, "user") == 0) return CFR_USER; + if (pcb_strcasecmp(s, "env") == 0) return CFR_ENV; + if (pcb_strcasecmp(s, "project") == 0) return CFR_PROJECT; + if (pcb_strcasecmp(s, "design") == 0) return CFR_DESIGN; + if (pcb_strcasecmp(s, "cli") == 0) return CFR_CLI; + return CFR_invalid; +} + +const char *conf_role_name(conf_role_t r) +{ + switch(r) { + case CFR_INTERNAL: return "internal"; + case CFR_SYSTEM: return "system"; + case CFR_DEFAULTPCB: return "defaultpcb"; + case CFR_USER: return "user"; + case CFR_ENV: return "env"; + case CFR_PROJECT: return "project"; + case CFR_DESIGN: return "design"; + case CFR_CLI: return "cli"; + case CFR_file: return "(file)"; + case CFR_binary: return "(binary)"; + + case CFR_max_alloc: + case CFR_max_real: + case CFR_invalid: return "(invalid role)"; + } + return "(unknown role)"; +} + + +void conf_extract_poliprio(lht_node_t *root, conf_policy_t *gpolicy, long *gprio) +{ + long len = strlen(root->name), p = -1; + char tmp[128]; + char *sprio, *end; + conf_policy_t pol; + + if (len >= sizeof(tmp)) { + pcb_hid_cfg_error(root, "Invalid policy-prio '%s', subtree is ignored\n", root->name); + return; + } + + memcpy(tmp, root->name, len+1); + + /* split and convert prio */ + sprio = strchr(tmp, '-'); + if (sprio != NULL) { + *sprio = '\0'; + sprio++; + p = strtol(sprio, &end, 10); + if ((*end != '\0') || (p < 0)) { + pcb_hid_cfg_error(root, "Invalid prio in '%s', subtree is ignored\n", root->name); + return; + } + } + + /* convert policy */ + pol = conf_policy_parse(tmp); + if (pol == POL_invalid) { + pcb_hid_cfg_error(root, "Invalid policy in '%s', subtree is ignored\n", root->name); + return; + } + + /* by now the syntax is checked; save the output */ + *gpolicy = pol; + if (p >= 0) + *gprio = p; +} + + +int conf_get_policy_prio(lht_node_t *node, conf_policy_t *gpolicy, long *gprio) +{ + for(;;node = node->parent) { + if (node->parent == node->doc->root) { + conf_extract_poliprio(node, gpolicy, gprio); + return 0; + } + if (node->parent == NULL) + return -1; + } +} + +const char *conf_get_user_conf_name() +{ + return conf_user_fn; +} + +const char *conf_get_project_conf_name(const char *project_fn, const char *pcb_fn, const char **try) +{ + static char res[PCB_PATH_MAX+1]; + static const char *project_name = "project.lht"; + FILE *f; + char *efn; + + if (project_fn != NULL) { + strncpy(res, project_fn, sizeof(res)-1); + res[sizeof(res)-1] = '\0'; + goto check; + } + + if (pcb_fn != NULL) { + char *end; + /* replace pcb name with project_name and test */ + strncpy(res, pcb_fn, sizeof(res)-1); + res[sizeof(res)-1] = '\0'; + end = strrchr(res, PCB_DIR_SEPARATOR_C); + if (end != NULL) { + if (end+1+sizeof(project_name) >= res + sizeof(res)) + return NULL; + strcpy(end+1, project_name); + goto check; + } + /* no path in pcb, try cwd */ + strcpy(res, project_name); + goto check; + } + + /* no pcb - no project */ + *try = ""; + return NULL; + + check:; + *try = res; + f = pcb_fopen_fn(res, "r", &efn); + if (f != NULL) { + fclose(f); + strncpy(res, efn, sizeof(res)-1); + res[sizeof(res)-1] = '\0'; + free(efn); + return res; + } + + return NULL; +} + +int conf_parse_text(confitem_t *dst, int idx, conf_native_type_t type, const char *text, lht_node_t *err_node) +{ + const char *strue[] = {"true", "yes", "on", "1", NULL}; + const char *sfalse[] = {"false", "no", "off", "0", NULL}; + const char **s; + char *end; + long l; + int base = 10; + double d; + const pcb_unit_t *u; + + switch(type) { + case CFN_STRING: + dst->string[idx] = text; + break; + case CFN_BOOLEAN: + while(isspace(*text)) text++; + for(s = strue; *s != NULL; s++) + if (pcb_strncasecmp(*s, text, strlen(*s)) == 0) { + dst->boolean[idx] = 1; + return 0; + } + for(s = sfalse; *s != NULL; s++) + if (pcb_strncasecmp(*s, text, strlen(*s)) == 0) { + dst->boolean[idx] = 0; + return 0; + } + pcb_hid_cfg_error(err_node, "Invalid boolean value: %s\n", text); + return -1; + case CFN_INTEGER: + if ((text[0] == '0') && (text[1] == 'x')) { + text += 2; + base = 16; + } + l = strtol(text, &end, base); + while(isspace(*end)) + end++; + if (*end == '\0') { + dst->integer[idx] = l; + return 0; + } + pcb_hid_cfg_error(err_node, "Invalid integer value: %s\n", text); + return -1; + case CFN_REAL: + d = strtod(text, &end); + if (*end == '\0') { + dst->real[idx] = d; + return 0; + } + pcb_hid_cfg_error(err_node, "Invalid numeric value: %s\n", text); + return -1; + case CFN_COORD: + { + pcb_bool succ; + dst->coord[idx] = pcb_get_value(text, NULL, NULL, &succ); + if (!succ) + pcb_hid_cfg_error(err_node, "Invalid numeric value (coordinate): %s\n", text); + } + break; + case CFN_UNIT: + u = get_unit_struct(text); + if (u == NULL) + pcb_hid_cfg_error(err_node, "Invalid unit: %s\n", text); + else + dst->unit[idx] = u; + break; + case CFN_COLOR: + if (pcb_color_load_str(&dst->color[idx], text) != 0) { + pcb_hid_cfg_error(err_node, "Invalid color value: '%s'\n", text); + return -1; + } + break; + default: + /* unknown field type registered in the fields hash: internal error */ + return -1; + } + return 0; +} + +int conf_merge_patch_text(conf_native_t *dest, lht_node_t *src, int prio, conf_policy_t pol) +{ + if ((pol == POL_DISABLE) || (dest->prop[0].prio > prio)) + return 0; + + if (dest->random_flags.read_only) { + pcb_hid_cfg_error(src, "WARNING: not going to overwrite read-only value %s from a config file\n", dest->hash_path); + return 0; + } + + if (conf_parse_text(&dest->val, 0, dest->type, src->data.text.value, src) == 0) { + dest->prop[0].prio = prio; + dest->prop[0].src = src; + dest->used = 1; + dest->conf_rev = conf_rev; + } + return 0; +} + +static void conf_insert_arr(conf_native_t *dest, int offs) +{ +#define CASE_PCB_MOVE(typ, fld) \ + case typ: memmove(dest->val.fld+offs, dest->val.fld, dest->used * sizeof(dest->val.fld[0])); return + + memmove(dest->prop+offs, dest->prop, dest->used * sizeof(dest->prop[0])); + if (dest->used > 0) { + switch(dest->type) { + CASE_PCB_MOVE(CFN_STRING, string); + CASE_PCB_MOVE(CFN_BOOLEAN, boolean); + CASE_PCB_MOVE(CFN_INTEGER, integer); + CASE_PCB_MOVE(CFN_REAL, real); + CASE_PCB_MOVE(CFN_COORD, coord); + CASE_PCB_MOVE(CFN_UNIT, unit); + CASE_PCB_MOVE(CFN_COLOR, color); + CASE_PCB_MOVE(CFN_LIST, list); + case CFN_max: break; + } + } +#undef CASE_MOVE + abort(); /* unhandled type */ +} + +int conf_merge_patch_array(conf_native_t *dest, lht_node_t *src_lst, int prio, conf_policy_t pol) +{ + lht_node_t *s; + int res, idx, didx, maxpr; + + if ((pol == POL_DISABLE) || (pol == POL_invalid)) + return 0; + + if (pol == POL_PREPEND) { + for(s = src_lst->data.list.first, maxpr = 0; s != NULL; s = s->next, maxpr++) ; + + if (dest->used+maxpr >= dest->array_size) + maxpr = dest->array_size - dest->used - 1; + + conf_insert_arr(dest, maxpr); + dest->used += maxpr; + } +/*printf("arr merge prio: %d\n", prio);*/ + for(s = src_lst->data.list.first, idx = 0; s != NULL; s = s->next, idx++) { + if (s->type == LHT_TEXT) { + switch(pol) { + case POL_PREPEND: + if (idx < maxpr) + didx = idx; + else + didx = dest->array_size+1; /* indicate array full */ + break; + case POL_APPEND: + didx = dest->used++; + break; + case POL_OVERWRITE: + didx = idx; + break; + case POL_DISABLE: case POL_invalid: return 0; /* compiler warning */ + } +/*printf(" didx: %d / %d '%s'\n", didx, dest->array_size, s->data.text.value);*/ + if (didx >= dest->array_size) { + pcb_hid_cfg_error(s, "Array is already full [%d] of [%d] ignored value: '%s' policy=%d\n", dest->used, dest->array_size, s->data.text.value, pol); + res = -1; + break; + } + + if ((s->data.text.value != NULL) && (conf_parse_text(&dest->val, didx, dest->type, s->data.text.value, s) == 0)) { + dest->prop[didx].prio = prio; + dest->prop[didx].src = s; + if (didx >= dest->used) + dest->used = didx+1; + } + } + else { + pcb_hid_cfg_error(s, "List item (in an array) must be text\n"); + res = -1; + } + } + + return res; +} + +int conf_merge_patch_list(conf_native_t *dest, lht_node_t *src_lst, int prio, conf_policy_t pol) +{ + lht_node_t *s, *prev; + int res = 0; + conf_listitem_t *i; + + switch(pol) { + case POL_DISABLE: + case POL_invalid: + return 0; + + case POL_PREPEND: + for(s = src_lst->data.list.last; s != NULL; s = prev) { + /* because lihata lists are single linked, need to look up the previous node manually; O(N^2) */ + if (s != src_lst->data.list.first) + for(prev = src_lst->data.list.first; prev->next != s; prev = prev->next); + else + prev = NULL; + if (s->type == LHT_TEXT) { + i = calloc(sizeof(conf_listitem_t), 1); + i->name = s->name; + i->val.string = &i->payload; + i->prop.prio = prio; + i->prop.src = s; + if (conf_parse_text(&i->val, 0, CFN_STRING, s->data.text.value, s) != 0) { + free(i); + continue; + } + conflist_insert(dest->val.list, i); + dest->used |= 1; + } + else { + pcb_hid_cfg_error(s, "List item (on a list, prepend) must be text\n"); + res = -1; + } + } + break; + case POL_OVERWRITE: + /* overwrite the whole list: make it empty then append new elements */ + while((i = conflist_first(dest->val.list)) != NULL) { + conflist_remove(i); + free(i); + } + /* fall through */ + case POL_APPEND: + for(s = src_lst->data.list.first; s != NULL; s = s->next) { + if (s->type == LHT_TEXT) { + i = calloc(sizeof(conf_listitem_t), 1); + i->name = s->name; + i->val.string = &i->payload; + i->prop.prio = prio; + i->prop.src = s; + if (conf_parse_text(&i->val, 0, CFN_STRING, s->data.text.value, s) != 0) { + free(i); + continue; + } + conflist_append(dest->val.list, i); + dest->used |= 1; + } + else { + pcb_hid_cfg_error(s, "List item (on a list) must be text\n"); + res = -1; + } + } + break; + } + return res; +} + +int conf_merge_patch_recurse(lht_node_t *sect, conf_role_t role, int default_prio, conf_policy_t default_policy, const char *path_prefix); + +typedef struct conf_ignore_s { + const char *name; + int len; + int warned; +} conf_ignore_t; + +static conf_ignore_t conf_ignores[] = { + /* it is normal to have configuration for plugins and utils not loaded - ignore these */ + {"plugins/", 8, 1}, + {"utils/", 6, 1}, + + /* old config paths - warn once and move on */ + {"editor/show_mask", 16, 0}, + {"editor/show_paste", 17, 0}, + {"editor/increments", 17, 0}, + {"design/max_width", 16, 0}, + {"design/max_height", 17, 0}, + {"design/groups", 13, 1}, + {"design/default_layer_name", 25, 1}, + + {NULL, 0, 0} +}; + +/* for security reasons ignore these nodes when coming from a board or project file */ +static conf_ignore_t conf_board_ignores[] = { + {"rc/action_string", 16, 0}, + {"rc/library_shell", 16, 0}, + {"rc/file_command", 15, 0}, + {"rc/font_command", 15, 0}, + {"rc/save_command", 15, 0}, + {"rc/rat_command", 14, 0}, + {NULL, 0, 0} +}; + +static void conf_warn_unknown_paths(const char *path, lht_node_t *n) +{ + conf_ignore_t *i; + + for(i = conf_ignores; i->name != NULL; i++) { + if (strncmp(path, i->name, i->len) == 0) { + if (i->warned) + return; /* do not warn again */ + i->warned = 1; + break; + } + } + pcb_hid_cfg_error(n, "conf error: lht->bin conversion: can't find path '%s'\n(it may be an obsolete setting, check your lht)\n", path); +} + +/* returns 1 if the config node should be ignored */ +static int conf_board_ignore(const char *path, lht_node_t *n) +{ + conf_ignore_t *i; + + for(i = conf_board_ignores; i->name != NULL; i++) { + if (strncmp(path, i->name, i->len) == 0) { + if (!i->warned) { + i->warned = 1; + pcb_hid_cfg_error(n, "conf error: lht->bin conversion: path '%s' from board or project file\nis ignored (probably due to security considerations)\n", path); + } + return 1; + } + } + return 0; +} + + +int conf_merge_patch_item(const char *path, lht_node_t *n, conf_role_t role, int default_prio, conf_policy_t default_policy) +{ + conf_native_t *target = conf_get_field(path); + int res = 0; + + if ((role == CFR_DESIGN) || (role == CFR_PROJECT)) { + if (conf_board_ignore(path, n)) + return 0; + } + + switch(n->type) { + case LHT_TEXT: + if (target == NULL) + conf_warn_unknown_paths(path, n); + else + conf_merge_patch_text(target, n, default_prio, default_policy); + break; + case LHT_HASH: + if (target == NULL) /* no leaf: another level of structs */ + res |= conf_merge_patch_recurse(n, role, default_prio, default_policy, path); + else /* leaf: pretend it's text so it gets parsed */ + conf_merge_patch_text(target, n, default_prio, default_policy); + break; + case LHT_LIST: + if (target == NULL) + conf_warn_unknown_paths(path, n); + else if (target->type == CFN_LIST) + res |= conf_merge_patch_list(target, n, default_prio, default_policy); + else if (target->array_size > 1) + res |= conf_merge_patch_array(target, n, default_prio, default_policy); + else + pcb_hid_cfg_error(n, "Attempt to initialize a scalar with a list - this node should be a text node\n"); + break; + case LHT_SYMLINK: +TODO("TODO") + break; + case LHT_INVALID_TYPE: + case LHT_TABLE: + /* intentionally unhandled types */ + break; + } + return res; +} + + +/* merge main subtree of a patch */ +int conf_merge_patch_recurse(lht_node_t *sect, conf_role_t role, int default_prio, conf_policy_t default_policy, const char *path_prefix) +{ + lht_dom_iterator_t it; + lht_node_t *n; + char path[256], *pathe; + char *namee; + int nl, ppl = strlen(path_prefix), res = 0; + + if (ppl >= sizeof(path)) { + pcb_message(PCB_MSG_ERROR, "Can not merge conf patch: name too long: '%s'\n", path_prefix); + return -1; + } + + memcpy(path, path_prefix, ppl); + path[ppl] = '/'; + pathe = path + ppl + 1; + + for(n = lht_dom_first(&it, sect); n != NULL; n = lht_dom_next(&it)) { + nl = strlen(n->name); + if (nl >= (sizeof(path) - (pathe - path))) { + pcb_message(PCB_MSG_ERROR, "Can not merge conf patch: name too long: '%s'\n", n->name); + return -1; + } + memcpy(pathe, n->name, nl); + namee = pathe+nl; + *namee = '\0'; + res |= conf_merge_patch_item(path, n, role, default_prio, default_policy); + } + return res; +} + +int conf_merge_patch(lht_node_t *root, conf_role_t role, long gprio) +{ + conf_policy_t gpolicy; + lht_node_t *n; + lht_dom_iterator_t it; + + if (root->type != LHT_HASH) { + pcb_hid_cfg_error(root, "patch root should be a hash\n"); + return -1; + } + + conf_extract_poliprio(root, &gpolicy, &gprio); + + /* iterate over all hashes and insert them recursively */ + for(n = lht_dom_first(&it, root); n != NULL; n = lht_dom_next(&it)) + if (n->type == LHT_HASH) + conf_merge_patch_recurse(n, role, gprio, gpolicy, n->name); + + return 0; +} + +typedef struct { + conf_role_t role; + long prio; + conf_policy_t policy; + lht_node_t *subtree; +} merge_subtree_t; + +#define GVT(x) vmst_ ## x +#define GVT_ELEM_TYPE merge_subtree_t +#define GVT_SIZE_TYPE size_t +#define GVT_DOUBLING_THRS 64 +#define GVT_START_SIZE 32 +#define GVT_FUNC +#define GVT_REALLOC(vect, ptr, size) realloc(ptr, size) +#define GVT_FREE(vect, ptr) free(ptr) +#include +#include +#include + +vmst_t merge_subtree; /* automatically initialized to all-zero */ + +static void add_subtree(conf_role_t role, lht_node_t *subtree_parent_root, lht_node_t *subtree_root) +{ + merge_subtree_t *m; + + m = vmst_alloc_append(&merge_subtree, 1); + m->role = role; + m->prio = conf_default_prio[role]; + m->policy = POL_invalid; + + conf_extract_poliprio(subtree_parent_root, &m->policy, &m->prio); + m->subtree = subtree_root; +} + +static int mst_prio_cmp(const void *a, const void *b) +{ + const merge_subtree_t *s1 = a, *s2 = b; + if (s1->prio > s2->prio) + return 1; + return -1; +} + +static void conf_merge_all_top(conf_role_t role, const char *path, lht_node_t *cr) +{ + lht_node_t *r, *r2; + for(r = cr->data.list.first; r != NULL; r = r->next) { + if (path != NULL) { + r2 = lht_tree_path_(r->doc, r, path, 1, 0, NULL); + if (r2 != NULL) + add_subtree(role, r, r2); + } + else + add_subtree(role, r, r); + } +} + +int conf_merge_all(const char *path) +{ + int n, ret = 0; + vmst_truncate(&merge_subtree, 0); + + for(n = 0; n < CFR_max_real; n++) { + lht_node_t *cr; + if (conf_main_root[n] != NULL) { + cr = conf_lht_get_confroot(conf_main_root[n]->root); + if (cr != NULL) + conf_merge_all_top(n, path, cr); + } + if (conf_plug_root[n] != NULL) { + cr = conf_lht_get_confroot(conf_plug_root[n]->root); + if (cr != NULL) + conf_merge_all_top(n, path, cr); + } + } + + qsort(merge_subtree.array, vmst_len(&merge_subtree), sizeof(merge_subtree_t), mst_prio_cmp); + for(n = 0; n < vmst_len(&merge_subtree); n++) { + if (path != NULL) + ret |= conf_merge_patch_item(path, merge_subtree.array[n].subtree, merge_subtree.array[n].role, merge_subtree.array[n].prio, merge_subtree.array[n].policy); + else + ret |= conf_merge_patch(merge_subtree.array[n].subtree, merge_subtree.array[n].role, merge_subtree.array[n].prio); + } + return ret; +} + +static void conf_field_clear(conf_native_t *f) +{ + if (strncmp(f->hash_path, "temp", 4) == 0) + return; + if (f->used > 0) { +#define clr(field) memset(f->val.field, 0, sizeof(*(f->val.field)) * f->used) + switch(f->type) { + case CFN_STRING: clr(string); break; + case CFN_BOOLEAN: clr(boolean); break; + case CFN_INTEGER: clr(integer); break; + case CFN_REAL: clr(real); break; + case CFN_COORD: clr(coord); break; + case CFN_UNIT: clr(unit); break; + case CFN_COLOR: clr(color); break; + case CFN_LIST: + while(conflist_first(f->val.list)) { /* need to free all items of a list before clearing the main struct */ + conf_listitem_t *i = conflist_first(f->val.list); + conflist_remove(i); + free(i); + } + clr(list); + break; + case CFN_max: break; + } + memset(f->prop, 0, sizeof(confprop_t) * f->used); +#undef clr + } + + f->used = 0; + f->conf_rev = conf_rev; +} + +int conf_rev = 0; +void conf_update(const char *path, int arr_idx) +{ + conf_native_t *n; + + /* clear memory-bin data first */ + if (path == NULL) { + htsp_entry_t *e; + conf_fields_foreach(e) { + conf_hid_global_cb((conf_native_t *)e->value, -1, val_change_pre); + conf_hid_local_cb((conf_native_t *)e->value, -1, val_change_pre); + conf_field_clear(e->value); + } + } + else { + n = conf_get_field(path); + if (n == NULL) { + char *path_, *field; + path_ = pcb_strdup(path); + + /* It might be an array element - truncate */ + field = strrchr(path_, '['); + if (field != NULL) { + arr_idx = atoi(field+1); + *field = '\0'; + n = conf_get_field(path_); + } + + /* if a valid node is found, update it */ + if (n != NULL) + conf_update(path_, arr_idx); + + free(path_); + return; + } + conf_field_clear(n); + conf_hid_global_cb(n, arr_idx, val_change_pre); + conf_hid_local_cb(n, arr_idx, val_change_pre); + } + + /* merge all memory-lht data to memory-bin */ + conf_merge_all(path); + conf_core_postproc(); + + if (path == NULL) { + htsp_entry_t *e; + conf_fields_foreach(e) { + conf_hid_local_cb((conf_native_t *)e->value, -1, val_change_post); + conf_hid_global_cb((conf_native_t *)e->value, -1, val_change_post); + } + } + else { + conf_hid_local_cb(n, arr_idx, val_change_post); + conf_hid_global_cb(n, arr_idx, val_change_post); + } + conf_rev++; +} + +#define POL_ANY 63 + +static lht_node_t *conf_lht_get_first_(lht_node_t *cwd, conf_policy_t pol, int create) +{ + lht_node_t *ov; /* normally the "overwrite" node */ + + /* assume root is a li and add to the first hash */ + cwd = conf_lht_get_confroot(cwd); + if (cwd == NULL) + return NULL; + + + ov = cwd->data.list.first; + if (pol != POL_ANY) { + for(; ov != NULL; ov = ov->next) + if (conf_policy_parse(ov->name) == pol) + break; + } + else + pol = POL_OVERWRITE; /* this is what is created by default */ + + if (ov == NULL) { + lht_node_t *new_ov; + if (!create) + return NULL; + new_ov = lht_dom_node_alloc(LHT_HASH, conf_policy_name(pol)); + lht_dom_list_append(cwd, new_ov); + ov = new_ov; + } + else if (ov->type != LHT_HASH) + return NULL; + + return ov; +} + +lht_node_t *conf_lht_get_first(conf_role_t target, int create) +{ + assert(target != CFR_invalid); + assert(target >= 0); + assert(target < CFR_max_alloc); + if (conf_main_root[target] == NULL) + return NULL; + return conf_lht_get_first_(conf_main_root[target]->root, POL_ANY, create); +} + +lht_node_t *conf_lht_get_first_pol(conf_role_t target, conf_policy_t pol, int create) +{ + assert(target != CFR_invalid); + assert(target >= 0); + assert(target < CFR_max_alloc); + if (conf_main_root[target] == NULL) + return NULL; + return conf_lht_get_first_(conf_main_root[target]->root, pol, create); +} + +static lht_node_t *conf_lht_get_at_(conf_role_t target, const char *conf_path, const char *lht_path, int create) +{ + lht_node_t *n, *r = NULL; + n = conf_lht_get_first(target, create); + if (n == NULL) + return NULL; + r = lht_tree_path_(n->doc, n, lht_path, 1, 0, NULL); + if ((r == NULL) && (create)) { + conf_set_dry(target, conf_path, -1, "", POL_OVERWRITE, 0); + r = lht_tree_path_(n->doc, n, lht_path, 1, 0, NULL); + } + return r; +} + +lht_node_t *conf_lht_get_at(conf_role_t target, const char *path, int create) +{ + lht_node_t *r; + char *pc, *end; + if (conf_main_root[target] == NULL) { + if (!create) + return NULL; + conf_reset(target, ""); + } + end = strchr(path, '['); + if (end == NULL) { + r = conf_lht_get_at_(target, path, path, create); + } + else { + /* lihata syntax differs from conf syntax in array indexing */ + pc = pcb_strdup(path); + pc[end-path] = '/'; + end = strchr(pc+(end-path), ']'); + if (end != NULL) + *end = '\0'; + r = conf_lht_get_at_(target, path, pc, create); + free(pc); + } + return r; +} + + +void conf_load_all(const char *project_fn, const char *pcb_fn) +{ + const char *pc, *try; + + /* the ultimate fallback: all essential values are built in the executable + on a low priority */ + conf_load_as(CFR_INTERNAL, conf_internal, 1); + + /* load config files */ + conf_load_as(CFR_SYSTEM, PCBSHAREDIR "/pcb-conf.lht", 0); + conf_load_as(CFR_USER, conf_user_fn, 0); + pc = conf_get_project_conf_name(project_fn, pcb_fn, &try); + if (pc != NULL) + conf_load_as(CFR_PROJECT, pc, 0); + conf_merge_all(NULL); + + /* create the user config (in-memory-lht) if it does not exist on disk; + this is needed so if the user makes config changes from the GUI things + get saved. */ + if (conf_main_root[CFR_USER] == NULL) + conf_reset(CFR_USER, conf_user_fn); + + conf_in_production = 1; +} + +void conf_load_extra(const char *project_fn, const char *pcb_fn) +{ + int cnt; + cnt = conf_load_plug_files(CFR_SYSTEM, PCBSHAREDIR); + cnt += conf_load_plug_files(CFR_USER, CONF_USER_DIR); + cnt += conf_load_plug_interns(CFR_INTERNAL); + if (cnt > 0) + conf_merge_all(NULL); +} + + +void conf_load_project(const char *project_fn, const char *pcb_fn) +{ + const char *pc, *try; + + assert((project_fn != NULL) || (pcb_fn != NULL)); + + pc = conf_get_project_conf_name(project_fn, pcb_fn, &try); + if (pc != NULL) + if (conf_load_as(CFR_PROJECT, pc, 0) != 0) + pc = NULL; + if (pc == NULL) + conf_reset(CFR_PROJECT, ""); + conf_update(NULL, -1); +} + +void conf_reg_field_(void *value, int array_size, conf_native_type_t type, const char *path, const char *desc, conf_flag_t flags) +{ + conf_native_t *node; + + if (conf_fields == NULL) { + conf_fields = htsp_alloc(strhash, strkeyeq); + assert(conf_fields != NULL); + } + assert(array_size >= 1); + + assert(htsp_get(conf_fields, path) == NULL); + + node = calloc(sizeof(conf_native_t), 1); + node->array_size = array_size; + node->type = type; + node->val.any = value; + node->prop = calloc(sizeof(confprop_t), array_size); + node->description = desc; + node->hash_path = path; + node->flags = flags; + vtp0_init(&(node->hid_data)); + vtp0_init(&(node->hid_callbacks)); + + htsp_set(conf_fields, (char *)path, node); +} + +void conf_free_native(conf_native_t *node) +{ + if (node->type == CFN_LIST) { + while(conflist_first(node->val.list) != NULL) { + conf_listitem_t *first = conflist_first(node->val.list); + conflist_remove(first); + free(first); + } + } + + vtp0_uninit(&(node->hid_data)); + vtp0_uninit(&(node->hid_callbacks)); + free(node->prop); + free(node); +} + +void conf_unreg_fields(const char *prefix) +{ + int len = strlen(prefix); + htsp_entry_t *e; + + assert(prefix[len-1] == '/'); + + conf_fields_foreach(e) { + if (strncmp(e->key, prefix, len) == 0) { + conf_free_native(e->value); + htsp_delentry(conf_fields, e); + } + } +} + +conf_native_t *conf_get_field(const char *path) +{ + return htsp_get(conf_fields, path); +} + +int conf_set_dry(conf_role_t target, const char *path_, int arr_idx, const char *new_val, conf_policy_t pol, int mkdirp) +{ + char *path, *basename, *next, *last, *sidx; + conf_native_t *nat; + lht_node_t *cwd, *nn; + lht_node_type_t ty; + int idx = -1; + + /* Remove in overwrite only */ + if ((new_val == NULL) && (pol != POL_OVERWRITE)) + return -1; + + if (mkdirp) + conf_lht_get_first_pol(target, pol, 1); + + path = pcb_strdup(path_); + sidx = strrchr(path, '['); + if (sidx != NULL) { + char *end; + *sidx = '\0'; + sidx++; + idx = strtol(sidx, &end, 10); + if ((*end != ']') || (strchr(sidx, '/') != NULL)) { + free(path); + return -1; + } + if ((arr_idx >= 0) && (arr_idx != idx)) { + free(path); + return -1; + } + } + else if (arr_idx >= 0) + idx = arr_idx; + + nat = conf_get_field(path); + if (nat == NULL) { + free(path); + return -1; + } + + + if (conf_main_root[target] == NULL) { + free(path); + return -1; + } + if (pol == POL_DISABLE) { + free(path); + return 0; + } + if ((pol != POL_OVERWRITE) && (idx >= 0)) { + free(path); + return -1; + } + + cwd = conf_lht_get_first_pol(target, pol, 0); + if (cwd == NULL) { + free(path); + return -1; + } + + if (idx >= nat->array_size) { + pcb_message(PCB_MSG_ERROR, "Error: can't conf_set() %s[%d]: %d is beyond the end of the array (%d)\n", path, idx, idx, nat->array_size); + free(path); + return -1; + } + + basename = strrchr(path, '/'); + if (basename == NULL) { + free(path); + return -1; + } + *basename = '\0'; + basename++; + + /* create parents if they do not exist */ + last = next = path; + do { + next = strchr(last, '/'); + if (next != NULL) + *next = '\0'; + + nn = lht_tree_path_(conf_main_root[target], cwd, last, 1, 0, NULL); + if (nn == NULL) { + if (new_val == NULL) { + free(path); + return 0; + } + if (conf_main_root_lock[target]) { + pcb_message(PCB_MSG_WARNING, "WARNING: can't set config item %s because target in-memory lihata does not have the node and is tree-locked\n", path_); + free(path); + return -1; + } + /* create a new hash node */ + nn = lht_dom_node_alloc(LHT_HASH, last); + if (lht_dom_hash_put(cwd, nn) != LHTE_SUCCESS) { + lht_dom_node_free(nn); + free(path); + return -1; + } + } + cwd = nn; + if (next != NULL) + last = next+1; + } while(next != NULL); + + /* add the last part of the path, which is either a list or a text node */ + if ((nat->array_size > 1) || (nat->type == CFN_LIST)) + ty = LHT_LIST; + else + ty = LHT_TEXT; + + nn = lht_tree_path_(conf_main_root[target], cwd, basename, 1, 0, NULL); + if (nn == NULL) { + if (conf_main_root_lock[target]) { + free(path); + return -1; + } + nn = lht_dom_node_alloc(ty, basename); + if (cwd->type != LHT_HASH) { + pcb_message(PCB_MSG_ERROR, "Expected HASH conf subtree '%s' (in path '%s'); cleaning up broken conf, check your config sources!\n", cwd->name, path); + lht_tree_del(cwd); + free(path); + return -1; + } + if (lht_dom_hash_put(cwd, nn) != LHTE_SUCCESS) { + lht_dom_node_free(nn); + free(path); + return -1; + } + } + cwd = nn; + + /* set value */ + if (ty == LHT_LIST) { + lht_err_t err = 0; + + if (new_val != NULL) + nn = lht_dom_node_alloc(LHT_TEXT, ""); + + if (pol == POL_OVERWRITE) { + if (idx == -1) { + /* empty the list so that we insert to an empty list which is overwriting the list */ + while(cwd->data.list.first != NULL) + lht_tree_del(cwd->data.list.first); + if (new_val != NULL) + lht_dom_list_append(cwd, nn); + } + else { + lht_node_t *old = lht_tree_list_nth(cwd, idx); + if (old != NULL) { + /* the list is large enough already: overwrite the element at idx */ + if (new_val == NULL) { + err = lht_tree_del(old); + free(path); + return 0; + } + else + err = lht_tree_list_replace_child(cwd, old, nn); + } + else if (new_val == NULL) { + free(path); + return 0; + } + else { + int n; + lht_node_t *i; + /* count members */ + for (n = 0, i = cwd->data.list.first; i != NULL; i = i->next) n++; + /* append just enough elements to get one less than needed */ + err = 0; + for(n = idx - n; n > 0; n--) { + lht_node_t *dummy = lht_dom_node_alloc(LHT_TEXT, ""); + err |= lht_dom_list_append(cwd, dummy); + } + /* append the new node */ + err |= lht_dom_list_append(cwd, nn); + } + } + } + else if ((pol == POL_PREPEND) || (pol == POL_OVERWRITE)) + err = lht_dom_list_insert(cwd, nn); + else if (pol == POL_APPEND) + err = lht_dom_list_append(cwd, nn); + if (err != LHTE_SUCCESS) { + lht_dom_node_free(nn); + free(path); + return -1; + } + cwd = nn; + } + else { + if (idx > 0) { + free(path); + return -1; /* only lists/array path should have index larger than 0 */ + } + cwd = nn; + } + + /* by now cwd is the text node we need to load with the new value; it is + either a text config value under a hash or a list item already allocated */ + if (cwd->type != LHT_TEXT) { + free(path); + return -1; + } + + if (new_val != NULL) { + if (cwd->data.text.value != NULL) + free(cwd->data.text.value); + + cwd->data.text.value = pcb_strdup(new_val); + cwd->file_name = conf_main_root[target]->active_file; + } + else + lht_tree_del(cwd); + + conf_lht_dirty[target]++; + + free(path); + return 0; +} + +int conf_set(conf_role_t target, const char *path, int arr_idx, const char *new_val, conf_policy_t pol) +{ + int res; + res = conf_set_dry(target, path, arr_idx, new_val, pol, 1); + if (res < 0) + return res; + conf_update(path, arr_idx); + return 0; +} + +int conf_del(conf_role_t target, const char *path, int arr_idx) +{ + int res; + res = conf_set_dry(target, path, arr_idx, NULL, POL_OVERWRITE, 0); + if (res < 0) + return res; + conf_update(path, arr_idx); + return 0; +} + + +int conf_set_native(conf_native_t *field, int arr_idx, const char *new_val) +{ + lht_node_t *node; + + if (arr_idx >= field->used) + return -1; + + node = field->prop[arr_idx].src; + + if (node->data.text.value != NULL) + free(node->data.text.value); + + node->data.text.value = pcb_strdup(new_val); + return 0; +} + + +int conf_set_from_cli(const char *prefix, const char *arg_, const char *val, const char **why) +{ + char *arg = NULL, *op, *s; + const char *sc; + conf_policy_t pol = POL_OVERWRITE; + int ret; + + if (prefix != NULL) { + for(sc = arg_; (*sc != '=') && (*sc != '\0'); sc++) + if (*sc == '/') + arg = pcb_strdup(arg_); /* full path, don't use prefix */ + + if (arg == NULL) { /* insert prefix */ + int pl = strlen(prefix), al = strlen(arg_); + while((pl > 0) && (prefix[pl-1] == '/')) pl--; + arg = malloc(pl+al+2); + memcpy(arg, prefix, pl); + arg[pl] = '/'; + strcpy(arg+pl+1, arg_); + } + } + else + arg = pcb_strdup(arg_); + + /* replace any - with _ in the path part; cli accepts dash but the backing C + struct field names don't */ + for(s = arg, op = NULL; (*s != '\0') && (op == NULL); s++) { + if (*s == '=') + op = s; + else if (*s == '-') + *s = '_'; + } + + /* extract val, if we need to */ + if (val == NULL) { + *why = ""; + if (op == arg) { + free(arg); + *why = "value not specified; syntax is path=val"; + return -1; + } + if (op == NULL) { + conf_native_t *n = conf_get_field(arg); + if ((n == NULL) || (n->type != CFN_BOOLEAN)) { + free(arg); + *why = "value not specified for non-boolean variable; syntax is path=val"; + return -1; + } + val = "1"; /* auto-value for boolean */ + } + else { + *op = '\0'; + val = op+1; + op--; + switch(*op) { + case '+': pol = POL_APPEND; *op = '\0'; break; + case '^': pol = POL_PREPEND; *op = '\0'; break; + } + } + } + + /* now that we have a clean path (arg) and a value, try to set the config */ + conf_lht_get_first_pol(CFR_CLI, pol, 1); /* make sure the root for the given policy is created */ + ret = conf_set(CFR_CLI, arg, -1, val, pol); + if (ret != 0) + *why = "invalid config path"; + + free(arg); + return ret; +} + +int conf_parse_arguments(const char *prefix, int *argc, char ***argv) +{ + int n, dst; + + for(n = 0, dst = 0; n < *argc; n++,dst++) { + char *a = (*argv)[n]; + const char *why; + int try_again = -1; + + if (a[0] == '-') a++; + if (a[0] == '-') a++; + + try_again = conf_set_from_cli(prefix, a, NULL, &why); + if (try_again && (n < (*argc) - 1)) { + try_again = conf_set_from_cli(prefix, a, (*argv)[n+1], &why); + if (!try_again) + n++; + } + if (try_again) + (*argv)[dst] = (*argv)[n]; + else + dst--; + } + *argc = dst; + return 0; +} + +void conf_usage(const char *prefix, void (*print)(const char *name, const char *help)) +{ + htsp_entry_t *e; + int pl = (prefix == NULL ? 0 : strlen(prefix)); + + conf_fields_foreach(e) { + if ((prefix == NULL) || (strncmp(prefix, e->key, pl) == 0)) { + conf_native_t *n = e->value; + if (n->flags & CFF_USAGE) { + int kl = strlen(n->hash_path); + char *s, *name = malloc(kl+32); + const char *sc; + for(sc = n->hash_path + pl; *sc == '/'; sc++) ; + name[0] = '-'; + name[1] = '-'; + strcpy(name+2, sc); + for(s = name; *s != '\0'; s++) + if (*s == '_') + *s = '-'; + switch(n->type) { + case CFN_BOOLEAN: /* implicit true */ break; + case CFN_STRING: strcpy(s, " str"); break; + case CFN_INTEGER: strcpy(s, " int"); break; + case CFN_REAL: strcpy(s, " num"); break; + case CFN_COORD: strcpy(s, " coord"); break; + case CFN_UNIT: strcpy(s, " unit"); break; + case CFN_COLOR: strcpy(s, " color"); break; + case CFN_LIST: strcpy(s, " "); break; + case CFN_max: break; + } + print(name, n->description); + free(name); + } + } + } +} + +int conf_replace_subtree(conf_role_t dst_role, const char *dst_path, conf_role_t src_role, const char *src_path) +{ + lht_node_t *dst = conf_lht_get_at(dst_role, dst_path, 1); + lht_node_t *src, *new_src = NULL; + + if (src_role == CFR_binary) { + char *name; + lht_node_t *ch = NULL; + int isarr, i; + conf_native_t *n = conf_get_field(src_path); + + if (n == NULL) + return -1; + name = strrchr(n->hash_path, '/'); + if (name == NULL) + return -1; + + isarr = n->array_size > 1; + if (isarr) + src = lht_dom_node_alloc(LHT_LIST, name+1); + + for(i = 0; i < n->array_size; i++) { + gds_t s; + + gds_init(&s); + if (n->type == CFN_LIST) { + conf_listitem_t *it; + ch = lht_dom_node_alloc(LHT_LIST, name+1); + for(it = conflist_first(n->val.list); it != NULL; it = conflist_next(it)) { + lht_node_t *txt; + txt = lht_dom_node_alloc(LHT_TEXT, ""); + txt->data.text.value = pcb_strdup(it->payload); + lht_dom_list_append(ch, txt); + } + } + else { + conf_print_native_field((conf_pfn)pcb_append_printf, &s, 0, &n->val, n->type, n->prop+i, i); + ch = lht_dom_node_alloc(LHT_TEXT, isarr ? "" : name+1); + ch->data.text.value = s.array; + if (isarr) + lht_dom_list_append(src, ch); + s.array = NULL; + gds_uninit(&s); + } + } + + if (!isarr) + src = ch; + } + else + src = conf_lht_get_at(src_role, src_path, 0); + + if ((src == NULL) && (dst != NULL)) { + lht_tree_del(dst); + return 0; + } + + if (dst == NULL) + goto err; + + new_src = lht_dom_duptree(src); + if (new_src == NULL) + goto err; + + if (lht_tree_replace(dst, new_src) != LHTE_SUCCESS) + goto err; + + conf_lht_dirty[dst_role]++; + + lht_tree_del(dst); + if (src_role == CFR_binary) + lht_dom_node_free(src); + return 0; + + err:; + if (src_role == CFR_binary) + lht_dom_node_free(src); + if (new_src != NULL) + lht_dom_node_free(new_src); + return -1; +} + + +int conf_save_file(const char *project_fn, const char *pcb_fn, conf_role_t role, const char *fn) +{ + int fail = 1; + lht_node_t *r = conf_lht_get_first(role, 0); + const char *try; + char *efn; + + /* do not save if there's no change */ + if (conf_lht_dirty[role] == 0) + return 0; + + if (fn == NULL) { + switch(role) { + case CFR_USER: + fn = conf_user_fn; + break; + case CFR_PROJECT: + fn = conf_get_project_conf_name(project_fn, pcb_fn, &try); + if (fn == NULL) { + pcb_message(PCB_MSG_ERROR, "Error: can not save config to project file: %s does not exist - please create an empty file there first\n", try); + return -1; + } + break; + default: return -1; + } + } + + if (r != NULL) { + FILE *f; + + f = pcb_fopen_fn(fn, "w", &efn); + if ((f == NULL) && (role == CFR_USER)) { + /* create the directory and try again */ + char *path = NULL, *end; + + if (efn != NULL) + path = pcb_strdup(efn); + else + path = pcb_build_fn(fn); + + if (path == NULL) { + pcb_message(PCB_MSG_ERROR, "Error: failed to calculate the project file name (board file name or allocation error)\n"); + fclose(f); + return -1; + } + + end = strrchr(path, '/'); + if (end != NULL) { + *end = '\0'; + if (pcb_mkdir(path, 0755) == 0) { + pcb_message(PCB_MSG_INFO, "Created directory %s for saving %s\n", path, fn); + *end = '/'; + f = pcb_fopen(path, "w"); + } + else + pcb_message(PCB_MSG_ERROR, "Error: failed to create directory %s for saving %s\n", path, efn); + } + free(path); + } + + if (f != NULL) { +TODO("CONF: a project file needs to be loaded, merged, then written (to preserve non-config nodes)") + lht_dom_export(r->doc->root, f, ""); + fail = 0; + conf_lht_dirty[role] = 0; + fclose(f); + } + else + pcb_message(PCB_MSG_ERROR, "Error: can't save config to %s - can't open the file for write\n", fn); + } + + free(efn); + return fail; +} + +int conf_export_to_file(const char *fn, conf_role_t role, const char *conf_path) +{ + lht_node_t *at = conf_lht_get_at(role, conf_path, 0); + lht_err_t r; + FILE *f; + + if (at == NULL) + return -1; + + f = pcb_fopen(fn, "w"); + if (f == NULL) + return -1; + + r = lht_dom_export(at, f, ""); + fclose(f); + return r; +} + + +conf_listitem_t *conf_list_first_str(conflist_t *list, const char **item_str, int *idx) +{ + conf_listitem_t *item_li; + item_li = conflist_first(list); + if (item_li == NULL) + return NULL; + if (item_li->type == CFN_STRING) { + *item_str = item_li->val.string[0]; + return item_li; + } + return conf_list_next_str(item_li, item_str, idx); +} + +conf_listitem_t *conf_list_next_str(conf_listitem_t *item_li, const char **item_str, int *idx) +{ + while((item_li = conflist_next(item_li)) != NULL) { + (*idx)++; + if (item_li->type != CFN_STRING) + continue; + /* found next string */ + *item_str = item_li->val.string[0]; + return item_li; + } + /* found end of the list */ + (*idx)++; + *item_str = NULL; + return item_li; +} + +const char *conf_concat_strlist(const conflist_t *lst, gds_t *buff, int *inited, char sep) +{ + int n; + conf_listitem_t *ci; + + if ((inited == NULL) || (!*inited)) { + gds_init(buff); + if (inited != NULL) + *inited = 1; + } + else + gds_truncate(buff, 0); + + for (n = 0, ci = conflist_first((conflist_t *)lst); ci != NULL; ci = conflist_next(ci), n++) { + const char *p = ci->val.string[0]; + if (ci->type != CFN_STRING) + continue; + if (n > 0) + gds_append(buff, sep); + gds_append_str(buff, p); + } + return buff->array; +} + +void conf_lock(conf_role_t target) +{ + conf_main_root_lock[target] = 1; +} + +void conf_unlock(conf_role_t target) +{ + conf_main_root_lock[target] = 0; +} + +int conf_islocked(conf_role_t target) +{ + return conf_main_root_lock[target]; +} + +int conf_isdirty(conf_role_t target) +{ + return conf_lht_dirty[target]; +} + +void conf_makedirty(conf_role_t target) +{ + conf_lht_dirty[target]++; +} +conf_role_t conf_lookup_role(const lht_node_t *nd) +{ + conf_role_t r; + for(r = 0; r < CFR_max_real; r++) + if (conf_main_root[r] == nd->doc) + return r; + + return CFR_invalid; +} + +void conf_reset(conf_role_t target, const char *source_fn) +{ + lht_node_t *n; + + if (conf_main_root[target] != NULL) + lht_dom_uninit(conf_main_root[target]); + + conf_main_root[target] = lht_dom_init(); + lht_dom_loc_newfile(conf_main_root[target], source_fn); + conf_main_root[target]->root = lht_dom_node_alloc(LHT_LIST, conf_list_name); + conf_main_root[target]->root->doc = conf_main_root[target]; + n = lht_dom_node_alloc(LHT_HASH, "overwrite"); + lht_dom_list_insert(conf_main_root[target]->root, n); +} + +/*****************/ +static int needs_braces(const char *s) +{ + for(; *s != '\0'; s++) + if (!isalnum(*s) && (*s != '_') && (*s != '-') && (*s != '+') && (*s != '/') + && (*s != ':') && (*s != '.') && (*s != ',') && (*s != '$') + && (*s != '(') && (*s != ')') && (*s != '~') && (*s != '#')) + return 1; + return 0; +} + +#define print_str_or_null(pfn, ctx, verbose, chk, out) \ + do { \ + if (chk == NULL) { \ + if (verbose) \ + ret += pfn(ctx, "");\ + } \ + else {\ + if (needs_braces(out)) \ + ret += pfn(ctx, "{%s}", out); \ + else \ + ret += pfn(ctx, "%s", out); \ + } \ + } while(0) + +int conf_print_native_field(conf_pfn pfn, void *ctx, int verbose, confitem_t *val, conf_native_type_t type, confprop_t *prop, int idx) +{ + int ret = 0; + switch(type) { + case CFN_STRING: print_str_or_null(pfn, ctx, verbose, val->string[idx], val->string[idx]); break; + case CFN_BOOLEAN: ret += pfn(ctx, "%d", val->boolean[idx]); break; + case CFN_INTEGER: ret += pfn(ctx, "%ld", val->integer[idx]); break; + case CFN_REAL: ret += pfn(ctx, "%f", val->real[idx]); break; + case CFN_COORD: ret += pfn(ctx, "%$mS", val->coord[idx]); break; + case CFN_UNIT: print_str_or_null(pfn, ctx, verbose, val->unit[idx], val->unit[idx]->suffix); break; + case CFN_COLOR: print_str_or_null(pfn, ctx, verbose, val->color[idx].str, val->color[idx].str); break; + case CFN_LIST: + { + conf_listitem_t *n; + if (conflist_length(val->list) > 0) { + ret += pfn(ctx, "{"); + for(n = conflist_first(val->list); n != NULL; n = conflist_next(n)) { + conf_print_native_field(pfn, ctx, verbose, &n->val, n->type, &n->prop, 0); + ret += pfn(ctx, ";"); + } + ret += pfn(ctx, "}"); + } + else { + if (verbose) + ret += pfn(ctx, ""); + else + ret += pfn(ctx, "{}"); + } + } + break; + case CFN_max: break; + } + if (verbose) { + ret += pfn(ctx, " <file_name, prop[idx].src->line); + } + ret += pfn(ctx, ">>"); + } + return ret; +} + +int conf_print_native(conf_pfn pfn, void *ctx, const char * prefix, int verbose, conf_native_t *node) +{ + int ret = 0; + if ((node->used <= 0) && (!verbose)) + return 0; + if (node->array_size > 1) { + int n; + if (!verbose) + ret += pfn(ctx, "{"); + for(n = 0; n < node->used; n++) { + if (verbose) + ret += pfn(ctx, "%s I %s[%d] = ", prefix, node->hash_path, n); + ret += conf_print_native_field(pfn, ctx, verbose, &node->val, node->type, node->prop, n); + if (verbose) + ret += pfn(ctx, " conf_rev=%d\n", node->conf_rev); + else + ret += pfn(ctx, ";"); + } + if (verbose) { + if (node->used == 0) + ret += pfn(ctx, "%s I %s[] = \n", prefix, node->hash_path); + } + else + ret += pfn(ctx, "}"); + } + else { + if (verbose) + ret += pfn(ctx, "%s I %s = ", prefix, node->hash_path); + ret += conf_print_native_field(pfn, ctx, verbose, &node->val, node->type, node->prop, 0); + if (verbose) + ret += pfn(ctx, " conf_rev=%d\n", node->conf_rev); + } + return ret; +} + + +/****************/ + +void conf_init(void) +{ + conf_reset(CFR_ENV, ""); + conf_reset(CFR_CLI, ""); + conf_reset(CFR_DESIGN, ""); + + conf_reset(CFR_file, ""); + conf_reset(CFR_binary, ""); +} + +void conf_uninit(void) +{ + int n; + htsp_entry_t *e; + + conf_fields_foreach(e) { + if (strncmp(e->key, "plugins/", 8) == 0) + fprintf(stderr, "pcb-rnd conf ERROR: conf node '%s' is not unregistered\n", e->key); + } + + conf_pcb_hid_uninit(); + + for(n = 0; n < CFR_max_alloc; n++) { + if (conf_main_root[n] != NULL) + lht_dom_uninit(conf_main_root[n]); + if (conf_plug_root[n] != NULL) + lht_dom_uninit(conf_plug_root[n]); + } + + conf_fields_foreach(e) { + conf_free_native(e->value); + htsp_delentry(conf_fields, e); + } + htsp_free(conf_fields); + + vmst_uninit(&merge_subtree); + pcb_conf_files_uninit(); +} + +void conf_setf(conf_role_t role, const char *path, int idx, const char *fmt, ...) +{ + char *tmp; + va_list ap; + + va_start(ap, fmt); + tmp = pcb_strdup_vprintf(fmt, ap); + va_end(ap); + + conf_set(role, path, idx, tmp, POL_OVERWRITE); + + free(tmp); +} + +#include "conf_regfile.c" Index: tags/2.1.2/src/conf.h =================================================================== --- tags/2.1.2/src/conf.h (nonexistent) +++ tags/2.1.2/src/conf.h (revision 24813) @@ -0,0 +1,395 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2016 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#ifndef PCB_CONF_H +#define PCB_CONF_H +#include "config.h" +#include "global_typedefs.h" +#include "pcb-printf.h" +#include +#include +#include +#include "unit.h" + +typedef union confitem_u confitem_t ; +typedef struct conf_listitem_s conf_listitem_t; + +#include "list_conf.h" + +extern int conf_rev; /* increased by one each time there's a change in any of the config binaries */ + +typedef enum { + POL_PREPEND, + POL_APPEND, + POL_OVERWRITE, + POL_DISABLE, + POL_invalid +} conf_policy_t; + +typedef enum { /* bitfield */ + CFF_USAGE = 1 /* settings should be printed in usage help */ +} conf_flag_t; + + +typedef const char * CFT_STRING; +typedef int CFT_BOOLEAN; +typedef long CFT_INTEGER; +typedef double CFT_REAL; +typedef pcb_coord_t CFT_COORD; +typedef pcb_unit_t * CFT_UNIT; +typedef pcb_color_t CFT_COLOR; +typedef conflist_t CFT_LIST; + +typedef enum { + CFN_STRING, + CFN_BOOLEAN, + CFN_INTEGER, /* signed long */ + CFN_REAL, /* double */ + CFN_COORD, + CFN_UNIT, + CFN_COLOR, + CFN_LIST, + CFN_max +} conf_native_type_t; + +union confitem_u { + const char **string; + int *boolean; + long *integer; + double *real; + pcb_coord_t *coord; + const pcb_unit_t **unit; + pcb_color_t *color; + conflist_t *list; + void *any; +}; + +typedef struct { + int prio; + lht_node_t *src; +} confprop_t; + +typedef struct { + /* static fields defined by the macros */ + const char *description; + const char *hash_path; /* points to the hash key once its added in the hash (else: NULL) */ + int array_size; + conf_native_type_t type; + conf_flag_t flags; + struct { + unsigned io_pcb_no_attrib:1; + unsigned read_only:1; /* set by conf_core, has no lihata, should not be overwritten */ + } random_flags; /* hack... persistent flags attached by various plugins */ + + /* dynamic fields loaded from lihata */ + confitem_t val; /* value is always an array (len 1 for the common case) */ + confprop_t *prop; /* an array of properties allocated as big as val's array */ + int used; /* number of items actually used in the arrays */ + int conf_rev; /* last changed rev */ + + /* dynamic fields for HIDs storing their data */ + vtp0_t hid_data; + vtp0_t hid_callbacks; /* vector of (const conf_hid_callbacks_t *) */ +} conf_native_t; + + +struct conf_listitem_s { + conf_native_type_t type; + confitem_t val; /* value is always an array (len 1 for the common case) */ + confprop_t prop; /* an array of properties allocated as big as val's array */ + const char *name; + const char *payload; + gdl_elem_t link; +}; + + +typedef enum { + CFR_INTERNAL, + CFR_SYSTEM, + CFR_DEFAULTPCB, /* default.pcb */ + CFR_USER, + CFR_ENV, /* env vars */ + CFR_PROJECT, /* project specific, from a local file */ + CFR_DESIGN, /* from the design file */ + CFR_CLI, /* from the command line */ + CFR_max_real, /* all the above are real files and should be merged */ + /* these ones are not real roles and are used in internal communication in the GUI HIDs */ + CFR_file, /* custom file */ + CFR_binary, /* the in-memory binary representation */ + CFR_max_alloc, /* all the above should have a root */ + + CFR_invalid +} conf_role_t; + +extern const int conf_default_prio[]; + +void conf_init(void); +void conf_uninit(void); + +/* Load all config files from disk into memory-lht and run conf_update to + get the binary representation updated. Called only once, from main.c. + Switches the conf system into production mode - new plugins registering new + internal files will get special treat after this. */ +void conf_load_all(const char *project_fn, const char *pcb_fn); + +/* Set to 1 after conf_load_all() to indicate that the in-memory conf + system is complete; any new plugin registering new conf will need to + trigger a refresh */ +extern int conf_in_production; + +/* Load a file or a string as a role */ +int conf_load_as(conf_role_t role, const char *fn, int fn_is_text); + +/* copy root to be the new config of role; root must be a li:pcb-rnd-conf-v1 + return 0 on success and removes/invalidates root */ +int conf_insert_tree_as(conf_role_t role, lht_node_t *root); + +/* Load a project file into CFR_PROJECT. Both project_fn and pcb_fn can't be NULL. + Leaves an initialized but empty CFR_PROJECT root if no project file was + found. Runs conf_update(NULL); */ +void conf_load_project(const char *project_fn, const char *pcb_fn); + +void conf_load_extra(const char *project_fn, const char *pcb_fn); + +/* Update the binary representation from the memory-lht representation */ +void conf_update(const char *path, int arr_idx); + +conf_native_t *conf_get_field(const char *path); +void conf_reg_field_(void *value, int array_size, conf_native_type_t type, const char *path, const char *desc, conf_flag_t flags); + +void conf_unreg_fields(const char *prefix); + +/* Set the value of path[arr_idx] in memory-lht role target to new_val using + policy pol. Only lists should be indexed. Indexing can be a [n] suffix on + path or a non-negative arr_idx. Updates the in-memory binary as well. If + new_val is NULL, the selected subtree is removed from the lihata document. */ +int conf_set(conf_role_t target, const char *path, int arr_idx, const char *new_val, conf_policy_t pol); + +/* Remove the subtree of path[arr_idx] in memory-lht role target. Same + considerations as in conf_set. */ +int conf_del(conf_role_t target, const char *path, int arr_idx); + +/* Same as conf_set, but without updating the binary - useful for multiple + conf_set_dry calls and a single all-tree conf_udpate(NULL) for transactions. + If mkdirp is non-zero, automatically create the policy subtree if it doesn't exist. */ +int conf_set_dry(conf_role_t target, const char *path_, int arr_idx, const char *new_val, conf_policy_t pol, int mkdirp); + +/* Same as conf_set, but doesn't look up where to set things: change the value of + the lihata node backing the native field */ +int conf_set_native(conf_native_t *field, int arr_idx, const char *new_val); + +/* Process a command line argument arg_ (if val == NULL) or a pair of command line + arguments arg_ and val. In the first case assume arg_ has both a config path + and a value (may be implicit true for a boolean). In the second case val + is always the value. If prefix is not NULL, the path is prefixed with it. + On error always set *why to a const string reason. + Returns 0 on success. */ +int conf_set_from_cli(const char *prefix, const char *arg_, const char *val, const char **why); + +/* Attempt to consume argv[] using conf_set_from_cli */ +int conf_parse_arguments(const char *prefix, int *argc, char ***argv); + +#define conf_reg_field_array(globvar, field, type_name, path, desc, flags) \ + conf_reg_field_((void *)&globvar.field, (sizeof(globvar.field) / sizeof(globvar.field[0])), type_name, path, desc, flags) + +#define conf_reg_field_scalar(globvar, field, type_name, path, desc, flags) \ + conf_reg_field_((void *)&globvar.field, 1, type_name, path, desc, flags) + +/* register a config field, array or scalar, selecting the right macro */ +#define conf_reg_field(globvar, field,isarray,type_name,cpath,cname, desc, flags) \ + conf_reg_field_ ## isarray(globvar, field,type_name,cpath "/" cname, desc, flags) + +/* convert a policy text to policy value - return POL_invalid on error */ +conf_policy_t conf_policy_parse(const char *s); + +/* Return the name of the policy - always a static string, even for invalid roles */ +const char *conf_policy_name(conf_policy_t p); + +/* convert a role text to role value - return CFR_invalid on error */ +conf_role_t conf_role_parse(const char *s); + +/* Return the name of the role - always a static string, even for invalid roles */ +const char *conf_role_name(conf_role_t r); + +/* Lock/unlock the structure of a role. In a locked role value of existing + fields may be modified but the structure of the tree is static (can't + create or remove nodes). This is useful when an io_ file format supports + only a subset of settings: it can build the CFR_DESIGN tree, lock it so + settings that it wouldn't know how to save won't appear. NOTE: io_pcb + supports all settings via attributes so does not lock. */ +void conf_lock(conf_role_t target); +void conf_unlock(conf_role_t target); + + +/* replace dst_role:dst_path with a copy of src_role:src_path */ +int conf_replace_subtree(conf_role_t dst_role, const char *dst_path, conf_role_t src_role, const char *src_path); + +/* Throw out a subtree (remove all nodes from the lihata representation). + Useful for io_ plugins, on CFR_DESIGN, before loading a new file. */ +void conf_reset(conf_role_t target, const char *source_fn); + +/* Save an in-memory lihata representation to the disk */ +int conf_save_file(const char *project_fn, const char *pcb_fn, conf_role_t role, const char *fn); + +/* Returns whether a given lihata tree is locked */ +int conf_islocked(conf_role_t target); + +/* Returns whether a given lihata tree has changed since load or last save */ +int conf_isdirty(conf_role_t target); +void conf_makedirty(conf_role_t target); + +/* all configuration fields ever seen */ +extern htsp_t *conf_fields; + +/***** print fields from binary to lihata/text *****/ + +typedef int (*conf_pfn)(void *ctx, const char *fmt, ...); + +/* Prints the value of a node in a form that is suitable for lihata. Prints + a single element of an array, but prints lists as lists. Returns + the sum of conf_pfn call return values - this is usually the number of + bytes printed. */ +int conf_print_native_field(conf_pfn pfn, void *ctx, int verbose, confitem_t *val, conf_native_type_t type, confprop_t *prop, int idx); + +/* Prints the value of a node in a form that is suitable for lihata. Prints + full arrays. Returns the sum of conf_pfn call return values - this is + usually the number of bytes printed. */ +int conf_print_native(conf_pfn pfn, void *ctx, const char * prefix, int verbose, conf_native_t *node); + + +/****** utility ******/ + +void conf_setf(conf_role_t role, const char *path, int idx, const char *fmt, ...); + +#define conf_list_foreach_path_first(res, conf_list, call) \ +do { \ + conf_listitem_t *__n__; \ + const conflist_t *__lst1__ = (conf_list); \ + conflist_t *__lst__ = (conflist_t *)(__lst1__); \ + if (__lst__ != NULL) { \ + for(__n__ = conflist_first(__lst__); __n__ != NULL; __n__ = conflist_next(__n__)) { \ + char *__path__; \ + const char **__in__ = __n__->val.string; \ + if (__in__ == NULL) \ + continue; \ + pcb_path_resolve(*__in__, &__path__, 0, pcb_false); \ + res = call; \ + free(__path__); \ + if (res == 0) \ + break; \ + } \ + } \ +} while(0) + +/* printf("conf_list_foreach_path_first: %s using %s\n", # call, # conf_list); \*/ + +/* htsp_entry_t *e; */ +#define conf_fields_foreach(e) \ + for (e = htsp_first(conf_fields); e; e = htsp_next(conf_fields, e)) + +/* helpers to make the code shorter */ +#define conf_set_design(path, fmt, new_val) \ + conf_setf(CFR_DESIGN, path, -1, fmt, new_val) + +#define conf_set_editor(field, val) \ + conf_set(CFR_DESIGN, "editor/" #field, -1, val ? "1" : "0", POL_OVERWRITE) + +#define conf_set_editor_(sfield, val) \ + conf_set(CFR_DESIGN, sfield, -1, val ? "1" : "0", POL_OVERWRITE) + +#define conf_toggle_editor(field) \ + conf_set_editor(field, !conf_core.editor.field) + +#define conf_toggle_editor_(sfield, field) \ + conf_set_editor_("editor/" sfield, !conf_core.editor.field) + +/* For temporary modification/restoration of variables (hack) */ +#define conf_force_set_bool(var, val) *((CFT_BOOLEAN *)(&var)) = val +#define conf_force_set_str(var, val) *((CFT_STRING *)(&var)) = val + +/* get the first config subtree node (it's a hash and its children + are "design", "rc", ...); if create is 1, and the subtree doesn't + exist, create an "overwrite". */ +lht_node_t *conf_lht_get_first(conf_role_t target, int create); + +/* loop helper */ +conf_listitem_t *conf_list_first_str(conflist_t *list, const char **item_str, int *idx); +conf_listitem_t *conf_list_next_str(conf_listitem_t *item_li, const char **item_str, int *idx); + +/*conf_listitem_t *item;*/ +#define conf_loop_list(list, item, idx) \ + for (idx = 0, item = conflist_first((conflist_t *)list); item != NULL; item = conflist_next(item), idx++) + +/*conf_listitem_t *item; const char *item_str; */ +#define conf_loop_list_str(list, item_li, item_str, idx) \ + for (idx = 0, item_li = conf_list_first_str((conflist_t *)list, &item_str, &idx); \ + item_li != NULL;\ + item_li = conf_list_next_str(item_li, &item_str, &idx)) + +const char *conf_concat_strlist(const conflist_t *lst, gds_t *buff, int *inited, char sep); + +/* Print usage help for all nodes that have the CFF_USAGE flag and whose + path starts with prefix (if prefix != NULL) */ +void conf_usage(const char *prefix, void (*print)(const char *name, const char *help)); + +/* Determine under which role a node is */ +conf_role_t conf_lookup_role(const lht_node_t *nd); + +/* Return the lihata node of a path in target, optionally creating it with the right type */ +lht_node_t *conf_lht_get_at(conf_role_t target, const char *path, int create); + +/* Write an existing conf subtree to a file */ +int conf_export_to_file(const char *fn, conf_role_t role, const char *conf_path); + +/* Determine the policy and priority of a config lihata node; + returns 0 on success but may not fill in both values, caller is + responsible for initializing them before the call. */ +int conf_get_policy_prio(lht_node_t *node, conf_policy_t *gpolicy, long *gprio); + +/* Parse text and convert the value into native form and store in one of dst + fields depending on type */ +int conf_parse_text(confitem_t *dst, int idx, conf_native_type_t type, const char *text, lht_node_t *err_node); + +/* Returns the user configuration file name */ +const char *conf_get_user_conf_name(); + +/* Determine the file name of the project file - project_fn and pcb_fn can be NULL */ +const char *conf_get_project_conf_name(const char *project_fn, const char *pcb_fn, const char **out_project_fn); + +/* Get the first subtree that matches pol within target; allocate new + subtree if needed */ +lht_node_t *conf_lht_get_first_pol(conf_role_t target, conf_policy_t pol, int create); + +/* (un)register a custom config file name (not path, just file name); + if intern is not NULL, it is the internal (executable-embedded) + version; it's not strdup'd, the caller needs to keep the string available + until conf_unreg_file(). path is strdup'd */ +void conf_reg_file(const char *path, const char *intern); +void conf_unreg_file(const char *path, const char *intern); + +void pcb_conf_files_uninit(void); + +#endif Index: tags/2.1.2/src/conf_act.c =================================================================== --- tags/2.1.2/src/conf_act.c (nonexistent) +++ tags/2.1.2/src/conf_act.c (revision 24813) @@ -0,0 +1,341 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2016 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "config.h" +#include "board.h" +#include "actions.h" +#include "conf_core.h" +#include "funchash_core.h" +#include "route_style.h" +#include "error.h" +#include "tool.h" +#include "macro.h" + +static const char pcb_acts_Conf[] = + "conf(set, path, value, [role], [policy]) - change a config setting to an absolute value\n" + "conf(delta, path, value, [role], [policy]) - change a config setting by a delta value (numerics-only)\n" + "conf(toggle, path, [role]) - invert boolean value of a flag; if no role given, overwrite the highest prio config\n" + "conf(reset, role) - reset the in-memory lihata of a role\n" + "conf(iseq, path, value) - returns whether the value of a conf item matches value (for menu checked's)\n" + ; +static const char pcb_acth_Conf[] = "Perform various operations on the configuration tree."; + +extern lht_doc_t *conf_root[]; +static inline int conf_iseq_pf(void *ctx, const char *fmt, ...) +{ + int res; + va_list ap; + va_start(ap, fmt); + res = pcb_append_vprintf((gds_t *)ctx, fmt, ap); + va_end(ap); + return res; +} + +static fgw_error_t pcb_act_Conf(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + int op; + const char *a1, *a2, *a3, *a4; + + PCB_ACT_CONVARG(1, FGW_KEYWORD, Conf, op = fgw_keyword(&argv[1])); + PCB_ACT_MAY_CONVARG(2, FGW_STR, Conf, a1 = argv[2].val.str); + PCB_ACT_MAY_CONVARG(3, FGW_STR, Conf, a2 = argv[3].val.str); + PCB_ACT_MAY_CONVARG(4, FGW_STR, Conf, a3 = argv[4].val.str); + PCB_ACT_MAY_CONVARG(5, FGW_STR, Conf, a4 = argv[5].val.str); + + if ((op == F_Set) || (op == F_Delta)) { + const char *path, *val; + char valbuff[128]; + conf_policy_t pol = POL_OVERWRITE; + conf_role_t role = CFR_invalid; + int rs; + + if (argc < 4) { + pcb_message(PCB_MSG_ERROR, "conf(set) needs at least two arguments"); + return FGW_ERR_ARGC; + } + if (argc > 4) { + role = conf_role_parse(a3); + if (role == CFR_invalid) { + pcb_message(PCB_MSG_ERROR, "Invalid role: '%s'", a3); + return FGW_ERR_ARG_CONV; + } + } + if (argc > 5) { + pol = conf_policy_parse(a4); + if (pol == POL_invalid) { + pcb_message(PCB_MSG_ERROR, "Invalid policy: '%s'", a4); + return FGW_ERR_ARG_CONV; + } + } + path = a1; + val = a2; + + if (op == F_Delta) { + double d; + char *end; + conf_native_t *n = conf_get_field(a1); + + if (n == 0) { + pcb_message(PCB_MSG_ERROR, "Can't delta-set '%s': no such path\n", argv[1]); + return FGW_ERR_ARG_CONV; + } + + switch(n->type) { + case CFN_REAL: + d = strtod(val, &end); + if (*end != '\0') { + pcb_message(PCB_MSG_ERROR, "Can't delta-set '%s': invalid delta value\n", a1); + return FGW_ERR_ARG_CONV; + } + d += *n->val.real; + sprintf(valbuff, "%f", d); + val = valbuff; + break; + case CFN_COORD: + case CFN_INTEGER: + default: + pcb_message(PCB_MSG_ERROR, "Can't delta-set '%s': not a numeric item\n", a1); + return FGW_ERR_ARG_CONV; + } + } + + if (role == CFR_invalid) { + conf_native_t *n = conf_get_field(a1); + if (n == NULL) { + pcb_message(PCB_MSG_ERROR, "Invalid conf field '%s': no such path\n", a1); + return FGW_ERR_ARG_CONV; + } + rs = conf_set_native(n, 0, val); + conf_update(a1, 0); + } + else + rs = conf_set(role, path, -1, val, pol); + + if (rs != 0) { + pcb_message(PCB_MSG_ERROR, "conf(set) failed.\n"); + return FGW_ERR_UNKNOWN; + } + } + + else if (op == F_Iseq) { + const char *path, *val; + int rs; + gds_t nval; + conf_native_t *n; + + if (argc != 4) { + pcb_message(PCB_MSG_ERROR, "conf(iseq) needs two arguments"); + return FGW_ERR_ARGC; + } + path = a1; + val = a2; + + n = conf_get_field(a1); + if (n == NULL) { + if (conf_core.rc.verbose) + pcb_message(PCB_MSG_ERROR, "Invalid conf field '%s' in iseq: no such path\n", path); + return FGW_ERR_ARG_CONV; + } + + gds_init(&nval); + conf_print_native_field(conf_iseq_pf, &nval, 0, &n->val, n->type, NULL, 0); + rs = !strcmp(nval.array, val); +/* printf("iseq: %s %s==%s %d\n", path, nval.array, val, rs);*/ + gds_uninit(&nval); + + PCB_ACT_IRES(rs); + return 0; + } + + else if (op == F_Toggle) { + conf_native_t *n = conf_get_field(a1); + const char *new_value; + conf_role_t role = CFR_invalid; + int res; + + if (n == NULL) { + pcb_message(PCB_MSG_ERROR, "Invalid conf field '%s': no such path\n", a1); + return FGW_ERR_UNKNOWN; + } + if (n->type != CFN_BOOLEAN) { + pcb_message(PCB_MSG_ERROR, "Can not toggle '%s': not a boolean\n", a1); + return FGW_ERR_UNKNOWN; + } + if (n->used != 1) { + pcb_message(PCB_MSG_ERROR, "Can not toggle '%s': array size should be 1, not %d\n", a1, n->used); + return FGW_ERR_UNKNOWN; + } + if (argc > 3) { + role = conf_role_parse(a2); + if (role == CFR_invalid) { + pcb_message(PCB_MSG_ERROR, "Invalid role: '%s'", a2); + return FGW_ERR_ARG_CONV; + } + } + if (n->val.boolean[0]) + new_value = "false"; + else + new_value = "true"; + if (role == CFR_invalid) + res = conf_set_native(n, 0, new_value); + else + res = conf_set(role, a1, -1, new_value, POL_OVERWRITE); + + if (res != 0) { + pcb_message(PCB_MSG_ERROR, "Can not toggle '%s': failed to set new value\n", a1); + return FGW_ERR_UNKNOWN; + } + conf_update(a1, -1); + } + + else if (op == F_Reset) { + conf_role_t role; + role = conf_role_parse(a1); + if (role == CFR_invalid) { + pcb_message(PCB_MSG_ERROR, "Invalid role: '%s'", a1); + return FGW_ERR_ARG_CONV; + } + conf_reset(role, ""); + conf_update(a1, -1); + } + + else { + pcb_message(PCB_MSG_ERROR, "Invalid conf command\n"); + return FGW_ERR_ARG_CONV; + } + + PCB_ACT_IRES(0); + return 0; +} + +/*------------ get/chk (check flag actions for menus) ------------------*/ +static const char pcb_acts_GetStyle[] = "GetStyle()" ; +static const char pcb_acth_GetStyle[] = "Return integer index (>=0) of the currently active style or -1 if no style is selected (== custom style)"; +fgw_error_t pcb_act_GetStyle(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + PCB_ACT_IRES(pcb_route_style_lookup(&PCB->RouteStyle, conf_core.design.line_thickness, conf_core.design.via_thickness, conf_core.design.via_drilling_hole, conf_core.design.clearance, NULL)); + return 0; +} + +static const char pcb_acts_ChkMode[] = "ChkMode(expected_mode)" ; +static const char pcb_acth_ChkMode[] = "Return 1 if the currently selected mode is the expected_mode"; +static fgw_error_t pcb_act_ChkMode(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + const char *dst; + pcb_toolid_t id; + + PCB_ACT_CONVARG(1, FGW_STR, ChkMode, dst = argv[1].val.str); + + id = pcb_tool_lookup(dst); + if (id >= 0) { + PCB_ACT_IRES(conf_core.editor.mode == id); + return 0; + } + PCB_ACT_IRES(-1); + return 0; +} + + +static const char pcb_acts_ChkGridSize[] = + "ChkGridSize(expected_size)\n" + "ChkGridSize(none)\n" + ; +static const char pcb_acth_ChkGridSize[] = "Return 1 if the currently selected grid matches the expected_size. If argument is \"none\" return 1 if there is no grid."; +static fgw_error_t pcb_act_ChkGridSize(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + const char *dst; + + PCB_ACT_CONVARG(1, FGW_STR, ChkGridSize, dst = argv[1].val.str); + + if (strcmp(dst, "none") == 0) { + PCB_ACT_IRES(PCB->Grid <= 300); + return 0; + } + + PCB_ACT_IRES(PCB->Grid == pcb_get_value_ex(dst, NULL, NULL, NULL, NULL, NULL)); + return 0; +} + +static const char pcb_acts_ChkSubcID[] = "ChkSubcID(pattern)\n"; +static const char pcb_acth_ChkSubcID[] = "Return 1 if currently shown subc ID matches the requested pattern"; +static fgw_error_t pcb_act_ChkSubcID(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + const char *have = conf_core.editor.subc_id, *expected = ""; + + if (have == NULL) have = ""; + + PCB_ACT_MAY_CONVARG(1, FGW_STR, ChkSubcID, expected = argv[1].val.str); + + PCB_ACT_IRES(strcmp(expected, have) == 0); + return 0; +} + +static const char pcb_acts_ChkTermID[] = "ChkTermID(pattern)\n"; +static const char pcb_acth_ChkTermID[] = "Return 1 if currently shown term ID matches the requested pattern"; +static fgw_error_t pcb_act_ChkTermID(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + const char *have = conf_core.editor.term_id, *expected = ""; + + if (have == NULL) have = ""; + + PCB_ACT_MAY_CONVARG(1, FGW_STR, ChkTermID, expected = argv[1].val.str); + + PCB_ACT_IRES(strcmp(expected, have) == 0); + return 0; +} + +static const char pcb_acts_ChkGridUnits[] = "ChkGridUnits(expected)"; +static const char pcb_acth_ChkGridUnits[] = "Return 1 if currently selected grid unit matches the expected (normally mm or mil)"; +static fgw_error_t pcb_act_ChkGridUnits(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + const char *expected; + PCB_ACT_CONVARG(1, FGW_STR, ChkGridUnits, expected = argv[1].val.str); + PCB_ACT_IRES(strcmp(conf_core.editor.grid_unit->suffix, expected) == 0); + return 0; +} + +static const char pcb_acts_ChkBuffer[] = "ChkBuffer(idx)"; +static const char pcb_acth_ChkBuffer[] = "Return 1 if currently selected buffer's index matches idx"; +static fgw_error_t pcb_act_ChkBuffer(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + int expected; + PCB_ACT_CONVARG(1, FGW_INT, ChkBuffer, expected = argv[1].val.nat_int); + PCB_ACT_IRES((conf_core.editor.buffer_number + 1) == expected); + return 0; +} + +pcb_action_t conf_action_list[] = { + {"conf", pcb_act_Conf, pcb_acth_Conf, pcb_acts_Conf}, + {"GetStyle", pcb_act_GetStyle, pcb_acth_GetStyle, pcb_acts_GetStyle}, + {"ChkMode", pcb_act_ChkMode, pcb_acth_ChkMode, pcb_acts_ChkMode}, + {"ChkGridSize", pcb_act_ChkGridSize, pcb_acth_ChkGridSize, pcb_acts_ChkGridSize}, + {"ChkSubcID", pcb_act_ChkSubcID, pcb_acth_ChkSubcID, pcb_acts_ChkSubcID}, + {"ChkTermID", pcb_act_ChkTermID, pcb_acth_ChkTermID, pcb_acts_ChkTermID}, + {"ChkGridUnits", pcb_act_ChkGridUnits, pcb_acth_ChkGridUnits, pcb_acts_ChkGridUnits}, + {"ChkBuffer", pcb_act_ChkBuffer, pcb_acth_ChkBuffer, pcb_acts_ChkBuffer} +}; + +PCB_REGISTER_ACTIONS(conf_action_list, NULL) Index: tags/2.1.2/src/conf_core.c =================================================================== --- tags/2.1.2/src/conf_core.c (nonexistent) +++ tags/2.1.2/src/conf_core.c (revision 24813) @@ -0,0 +1,57 @@ +#include "config.h" +#include "conf.h" +#include "conf_core.h" +conf_core_t conf_core; + +void conf_core_init() +{ +#define conf_reg(field,isarray,type_name,cpath,cname,desc,flags) \ + conf_reg_field(conf_core, field,isarray,type_name,cpath,cname,desc,flags); +#include "conf_core_fields.h" +} + +#define conf_clamp_to(type, var, min, max, safe_val) \ +do { \ + if ((var < min) || (var > max)) \ + *((type *)(&var)) = safe_val; \ +} while(0) + +#define conf_clamp(type, var, min, max) \ +do { \ + if (var < min) \ + *((type *)(&var)) = min; \ + else if (var > max) \ + *((type *)(&var)) = max; \ +} while(0) + +static char *get_homedir(void) +{ + char *homedir = getenv("HOME"); + if (homedir == NULL) + homedir = getenv("USERPROFILE"); + return homedir; +} + +void pcb_conf_ro(const char *path) +{ + conf_native_t *n = conf_get_field(path); + if (n != NULL) { + n->used = 1; + n->random_flags.read_only = 1; + } +} + +void conf_core_postproc() +{ + conf_clamp_to(CFT_COORD, conf_core.design.line_thickness, PCB_MIN_LINESIZE, PCB_MAX_LINESIZE, PCB_MIL_TO_COORD(10)); + conf_clamp_to(CFT_COORD, conf_core.design.via_thickness, PCB_MIN_PINORVIASIZE, PCB_MAX_PINORVIASIZE, PCB_MIL_TO_COORD(40)); + conf_clamp_to(CFT_COORD, conf_core.design.via_drilling_hole, 0, PCB_MAX_COORD, PCB_DEFAULT_DRILLINGHOLE * conf_core.design.via_thickness / 100); + conf_force_set_bool(conf_core.rc.have_regex, 1); + pcb_conf_ro("rc/have_regex"); + + conf_force_set_str(conf_core.rc.path.prefix, PCB_PREFIX); pcb_conf_ro("rc/path/prefix"); + conf_force_set_str(conf_core.rc.path.lib, PCBLIBDIR); pcb_conf_ro("rc/path/lib"); + conf_force_set_str(conf_core.rc.path.bin, BINDIR); pcb_conf_ro("rc/path/bin"); + conf_force_set_str(conf_core.rc.path.share, PCBSHAREDIR); pcb_conf_ro("rc/path/share"); + conf_force_set_str(conf_core.rc.path.home, get_homedir()); pcb_conf_ro("rc/path/home"); +} Index: tags/2.1.2/src/conf_core.h =================================================================== --- tags/2.1.2/src/conf_core.h (nonexistent) +++ tags/2.1.2/src/conf_core.h (revision 24813) @@ -0,0 +1,242 @@ +#ifndef PCB_CONF_CORE_H +#define PCB_CONF_CORE_H + +#include "conf.h" +#include "globalconst.h" +#include "color.h" + +/* NOTE: this struct has a strict format because a code generator needs to + read it. Please always keep the format (preferably even whitespace style). + Use only the CFT_* prefixed types declared in conf.h. + */ + +typedef struct { + + struct temp { + CFT_BOOLEAN rat_warn; /* rats nest has set warnings */ + CFT_BOOLEAN clip_inhibit_chg; /* dummy node to inform the menu about clip inhibit change */ + } temp; + + const struct editor { + CFT_UNIT grid_unit; /* select whether you draw in mm or mil */ + CFT_COORD grid; /* grid in pcb-units */ + CFT_LIST grids; /* grid in grid-string format */ + CFT_INTEGER grids_idx; /* the index of the currently active grid from grids */ + CFT_REAL zoom; /* default zoom */ + CFT_INTEGER mode; /* currently active mode */ + CFT_INTEGER buffer_number; /* number of the current buffer */ + CFT_BOOLEAN clear_line; /* new lines/arc clear polygons. */ + CFT_BOOLEAN clear_polypoly; /* new polygons clear polygons. */ + CFT_BOOLEAN full_poly; /* new polygons are full polygons. */ + CFT_BOOLEAN unique_names; /* OBSOLETE: force unique names */ + CFT_BOOLEAN snap_pin; /* snap to pins and pads */ + CFT_BOOLEAN snap_offgrid_line; /* Snap to certain off-grid points along a line. */ + CFT_BOOLEAN marker_snaps; /* marker snaps to grid or snap points, as any other click */ + CFT_BOOLEAN highlight_on_point; /* Highlight if crosshair is on endpoints. */ + CFT_BOOLEAN show_solder_side; /* mirror output */ + CFT_BOOLEAN save_last_command; /* the command entry editline always starts with the last command entered by user in the current session */ + CFT_INTEGER line_refraction; /* value for line lookahead setting */ + CFT_BOOLEAN save_in_tmp; /* emergency save unsaved PCB data (despite the user clicks don't save) when: user starts a new PCB; user quits pcb-rnd. Does not affect the on-crash emergency save. */ + CFT_BOOLEAN draw_grid; /* draw grid points */ + CFT_BOOLEAN all_direction_lines; /* enable lines to all directions */ + CFT_BOOLEAN rubber_band_mode; /* move, rotate use rubberband connections */ + CFT_BOOLEAN rubber_band_keep_midlinedir; /* keep line direction when a middle line is moved */ + CFT_BOOLEAN swap_start_direction; /* change starting direction after each click */ + CFT_BOOLEAN show_drc; /* show drc region on crosshair */ + CFT_BOOLEAN auto_drc; /* when set, PCB doesn't let you place copper that violates DRC. */ + CFT_BOOLEAN conn_find_rat; /* connection find includes rats; when off, only existing galvanic connections are mapped */ + CFT_BOOLEAN show_number; /* OBSOLETE: pinout shows number */ + CFT_BOOLEAN orthogonal_moves; /* move items orthogonally. */ + CFT_BOOLEAN reset_after_element; /* OBSOLETE: reset connections after each element while saving all connections */ + CFT_BOOLEAN auto_place; /* force placement of GUI windows (dialogs), trying to override the window manager */ + CFT_BOOLEAN lock_names; /* lock down text so they can not be moved or selected */ + CFT_BOOLEAN only_names; /* lock down everything else but text so only text objects can be moved or selected */ + CFT_BOOLEAN thin_draw; /* if set, objects on the screen are drawn as outlines (lines are drawn as center-lines). This lets you see line endpoints hidden under pins, for example. */ + CFT_BOOLEAN thin_draw_poly; /* if set, polygons on the screen are drawn as outlines. */ + CFT_BOOLEAN as_drawn_poly; /* if set, also draw the as-drawn outline of polygons */ + CFT_BOOLEAN wireframe_draw; /* if set, lines and arcs on the screen are drawn as outlines. */ + CFT_BOOLEAN local_ref; /* use local reference for moves, by setting the mark at the beginning of each move. */ + CFT_BOOLEAN check_planes; /* when set, only polygons and their clearances are drawn, to see if polygons have isolated regions. */ + CFT_BOOLEAN hide_names; /* when set, subc floater text objects (typical use case: refdes text) are not drawn. */ + CFT_BOOLEAN description; /* obsolete - DO NOT USE - kept for compatibility */ + CFT_BOOLEAN name_on_pcb; /* obsolete - DO NOT USE - kept for compatibility */ + CFT_STRING subc_id; /* subcircuit ID template for diplaying the subcircuit label on the subcircuit layer; default to displaying the refes, if empty; syntax if the same as for DYNTEXT */ + CFT_STRING term_id; /* terminal ID template for diplaying the subcircuit label on the subcircuit layer; default to displaying termid[intconn], if empty; syntax if the same as for DYNTEXT */ + CFT_BOOLEAN fullscreen; /* hide widgets to make more room for the drawing */ + CFT_BOOLEAN move_linepoint_uses_route; /* Moving a line point calculates a new line route. This allows 45/90 line modes when editing lines. */ + CFT_BOOLEAN auto_via; /* when drawing traces and switching layers or when moving an object from one layer to another, try to keep connections by automatically inserting vias. */ + CFT_REAL route_radius; /* temporary: route draw helper's arc radius at corners (factor of the trace thickness) */ + + CFT_BOOLEAN io_incomp_popup; /* wether to enable popping up the io incompatibility list dialog on save incompatibility errors */ + CFT_STRING io_incomp_style; /* view listing style (list or simple), when io_incomp_popup is true */ + + CFT_INTEGER click_time; /* default time for click expiration, in ms */ + + struct view { + CFT_BOOLEAN flip_x; /* view: flip the board along the X (horizontal) axis */ + CFT_BOOLEAN flip_y; /* view: flip the board along the Y (vertical) axis */ + } view; + + struct selection { + CFT_BOOLEAN disable_negative; /* selection box behaviour: disable the negative-direction selection - any selection box will select only what's fully within the box */ + CFT_BOOLEAN symmetric_negative; /* selection box behaviour: when set, the selection direction is considered negative only if the box has negative size in the X direction */ + } selection; + + /* these two would need to be moved in the router plugin.... There are two + reasons to keep them here: + - the original pcb and pcb-rnd file formats already have named/numbered flags for these, so io_pcb needs these + - more than one router plugin may share these */ + CFT_BOOLEAN enable_stroke; /* Enable libstroke gestures on middle mouse button when non-zero */ + CFT_BOOLEAN live_routing; /* autorouter shows tracks in progress */ + + /* Keep it here instead of the router plugin: more than one router plugin may share these */ + CFT_BOOLEAN beep_when_finished; /* flag if a signal should be produced when searching of connections is done */ + + CFT_INTEGER undo_warning_size; /* warn the user when undo list exceeds this amount of kilobytes in memory */ + + CFT_STRING subc_conv_refdes; /* automatic refdes value assigned to new subcircuits on conversion from objects - if empty, no refdes text or attribute is added; if the value is , the refdes text object is added but no refdes attribute is created */ + } editor; + + const struct rc { + CFT_INTEGER verbose; + CFT_INTEGER quiet; /* print only errors on stderr */ + CFT_BOOLEAN dup_log_to_stderr; /* copy log messages to stderr even if there is a HID that can show them */ + CFT_INTEGER backup_interval; /* time between two backups in seconds; 0 means disabled (no backups) */ + CFT_BOOLEAN hid_fallback; /* if there is no explicitly specified HID (--gui) and the preferred GUI fails, automatically fall back on other HIDs, eventually running in batch mode */ + CFT_STRING brave; /* brave mode flags: when non-empty, enable various experimental (unstable) features - useful for testers */ + CFT_STRING font_command; /* file name template; if not empty, run this command and read its output for loading the font; %f is the file name */ + CFT_STRING file_command; /* file name template; if not empty, run this command and read its output for loading a pcb file; %f is the file name, %p is the conf setting rc.file_path */ + CFT_STRING file_path; + CFT_STRING library_shell; + CFT_LIST library_search_paths; + CFT_STRING menu_file; /* where to load the default menu file from. If empty/unset, fall back to the legacy 'per hid ow menu file' setup. If contains slash, take it as a full path, if no slash, do a normal menu search for pcb-menu-NAME.lht */ + CFT_BOOLEAN export_basename; /* if an exported file contains the source file name, remove path from it, keeping the basename only */ + + CFT_STRING emergency_name; /* file name template for emergency save anonymous .pcb files (when pcb-rnd crashes); optional field: %ld --> pid; must be shorter than 240 characters. Don't do emergency save if this item is empty. */ + CFT_STRING emergency_format; /* if set, use this format for the backups; if unset, use the default format */ + CFT_STRING backup_name; /* file name template for periodic backup of board files; optional fields (the usual % substitutions work) */ + CFT_STRING backup_format; /* if set, use this format for the backups; if unset or set to 'original', use the original format */ + + CFT_STRING save_command; /* command to pipe the pcb, footprint or buffer file into, when saving (makes lihata persist impossible) */ + CFT_BOOLEAN keep_save_backups; /* a copy is made before a save operation overwrites an existing file; if this setting is true, keep the copy even after a successful save */ + CFT_LIST default_font_file; /* name of default font file (list of names to search) */ + CFT_LIST default_pcb_file; + + CFT_STRING script_filename; /* PCB Actions script to execute on startup */ + CFT_STRING action_string; /* PCB Actions string to execute on startup */ + CFT_STRING rat_path; + CFT_STRING rat_command; /* file name template; if not empty, run this command and read its output for loading a rats; %f is the file name, %p is the rc.rat_path conf setting */ + + CFT_LIST preferred_gui; /* if set, try GUI HIDs in this order when no GUI is explicitly selected */ + + CFT_STRING save_final_fallback_fmt;/* when a new file is created (by running pcb-rnd with the file name) there won't be a known format; pcb-rnd will guess from the file name (extension) but eventhat may fail. This format is the final fallback that'll be used if no other guessing mechanism worked. The user can override this by save as. */ + CFT_STRING save_fp_fmt; /* when saving a buffer element/subcircuit, prefer this format by default */ + + CFT_STRING cli_prompt; /* plain text prompt to prefix the command entry */ + CFT_STRING cli_backend; /* command parser action */ + + /***** automatically set (in postproc) *****/ + CFT_BOOLEAN have_regex; /* whether we have regex compiled in */ + struct path { + CFT_STRING prefix; /* e.g. /usr/local */ + CFT_STRING lib; /* e.g. /usr/lib/pcb-rnd */ + CFT_STRING bin; /* e.g. /usr/bin */ + CFT_STRING share; /* e.g. /usr/share/pcb-rnd */ + CFT_STRING home; /* user's home dir, determined run-time */ + + CFT_STRING exec_prefix; /* exec prefix path (extracted from argv[0]) */ + + CFT_STRING design; /* directory path of the current design, or if the current design doesn't have a file name yet */ + } path; + } rc; + + const struct design { /* defaults of a new layout */ + CFT_COORD via_thickness; + CFT_COORD via_drilling_hole; + CFT_COORD line_thickness; + CFT_COORD clearance; + + CFT_COORD bloat; /* minimum space between copper features on different networks */ + CFT_COORD shrink; /* minimum overlap between connected copper features */ + CFT_COORD min_wid; /* minimum copper width */ + CFT_COORD min_slk; /* minimum silk width */ + CFT_COORD min_drill; /* minimum drill diameter */ + CFT_COORD min_ring; /* minimum annular ring */ + CFT_INTEGER text_scale; /* text scaling in % */ + CFT_COORD text_thickness; /* override stroke font text thickness */ + CFT_INTEGER text_font_id; + CFT_REAL poly_isle_area; /* polygon min area */ + CFT_STRING fab_author; /* Full name of author for FAB drawings */ + CFT_STRING initial_layer_stack; /* deprecated. */ + + CFT_COORD paste_adjust; /* Adjust paste thickness */ + } design; + +/* @path appearance/color */ + const struct appearance { + CFT_BOOLEAN compact; /* when set: optimize GUI widget arrangement for small screen; may be wasting some screen space on large screen */ + CFT_COORD rat_thickness; + CFT_COORD mark_size; /* relative marker size */ + CFT_REAL layer_alpha; /* alpha value for layer drawing */ + CFT_REAL drill_alpha; /* alpha value for drill drawing */ + CFT_BOOLEAN text_host_bbox; /* when moving a text object, the outline thin-draw should also include the bounding box */ + CFT_REAL term_label_size; /* size of terminal labels, in pcb font scale (100 is for the normal size) */ + CFT_BOOLEAN subc_layer_per_side; /* hide top or bottom placed subcircuit annotations if the view is showing the other side */ + CFT_BOOLEAN invis_other_groups; /* render non-current group layers with the inivisble color */ + CFT_BOOLEAN black_current_group; /* render all layers of the current group black, for maximum contrast */ + struct loglevels { + CFT_STRING debug_tag; /* log style tag of debug messages */ + CFT_BOOLEAN debug_popup; /* whether a debug line should pop up the log window */ + CFT_STRING info_tag; /* log style tag of info messages */ + CFT_BOOLEAN info_popup; /* whether an info line should pop up the log window */ + CFT_STRING warning_tag; /* log style tag of warnings */ + CFT_BOOLEAN warning_popup; /* whether a warning should pop up the log window */ + CFT_STRING error_tag; /* log style tag of errors */ + CFT_BOOLEAN error_popup; /* whether an error should pop up the log window */ + } loglevels; + struct color { + CFT_COLOR background; /* background and cursor color ... */ + CFT_COLOR crosshair; /* different object colors */ + CFT_COLOR cross; /* crosshair, drc outline color */ + CFT_COLOR selected; /* generic object selection color */ + CFT_COLOR via; /* non-terminal padstack shape on current layer */ + CFT_COLOR via_far; /* non-terminal padstack shape on non-current ('far side') layer */ + CFT_COLOR pin; /* terminal padstack shape on current layer */ + CFT_COLOR pin_far; /* terminal padstack shape on non-current ('far side') layer */ + CFT_COLOR pin_name; /* on-screen terminal number/name labels */ + CFT_COLOR subc; /* on-screen subcircuit marks */ + CFT_COLOR subc_nonetlist; /* on-screen subcircuit marks for subcircuits with the nonetlist flag */ + CFT_COLOR padstackmark; /* on-screen center mark cross for padstacks */ + CFT_COLOR rat; /* on-screen rat lines */ + CFT_COLOR invisible_objects; /* other-side objects and padstack shapes on non-current layer */ + CFT_COLOR connected; /* 'connected' highlight (galvanic connections found) */ + CFT_COLOR warn; /* warning highlight (e.g. object found to cause a short) */ + CFT_COLOR off_limit; /* on-screen background beyond the configured drawing area */ + CFT_COLOR grid; /* on-screen grid */ + CFT_COLOR layer[PCB_MAX_LAYER]; /* default layer colors; when a new layer is created, a color from this list is assigned initially */ + CFT_COLOR mask; /* default mask layer color (when a new mask layer is created) */ + CFT_COLOR paste; /* default paste layer color (when a new paste layer is created) */ + CFT_COLOR element; /* default silk layer color (when a new silk layer is created) */ + } color; + struct padstack { + CFT_INTEGER cross_thick; /* cross thickness in pixels - 0 means disable crosses */ + CFT_COORD cross_size; /* cross size in word coords - size of one arm of the cross (minus the hole radius) */ + } padstack; + struct subc { + CFT_INTEGER dash_freq; /* how dense the dashed outline should be; -1 means do not display the dashed outline; 0 means solid outline; 1..32 means dashed outline */ + } subc; + struct messages { + CFT_INTEGER char_per_line; /* width of an output line in characters (used by separator drawing in find.c) */ + } messages; + struct misc { + CFT_INTEGER volume; /* the speakers volume -100..100 */ + } misc; + } appearance; + +} conf_core_t; + +extern conf_core_t conf_core; +void conf_core_init(); +void conf_core_postproc(); +void pcb_conf_ro(const char *path); +#endif Index: tags/2.1.2/src/conf_hid.c =================================================================== --- tags/2.1.2/src/conf_hid.c (nonexistent) +++ tags/2.1.2/src/conf_hid.c (revision 24813) @@ -0,0 +1,148 @@ +#include "config.h" +#include "conf_hid.h" +#include +#include +#include "error.h" +#include "conf_core.h" + +typedef struct { + const conf_hid_callbacks_t *cb; + conf_hid_id_t id; +} conf_hid_t; + +void *conf_hid_set_data(conf_native_t *cfg, conf_hid_id_t id, void *data) +{ + void **old = vtp0_get(&cfg->hid_data, id, 0); + vtp0_set(&cfg->hid_data, id, data); + return old == NULL ? NULL : *old; +} + +void *conf_hid_get_data(conf_native_t *cfg, conf_hid_id_t id) +{ + void **old = vtp0_get(&cfg->hid_data, id, 0); + return old == NULL ? NULL : *old; +} + +const conf_hid_callbacks_t *conf_hid_set_cb(conf_native_t *cfg, conf_hid_id_t id, const conf_hid_callbacks_t *cbs) +{ + void **old; + assert(id >= 0); + old = vtp0_get(&cfg->hid_callbacks, id, 0); + vtp0_set(&cfg->hid_callbacks, id, (void *)cbs); + return (const conf_hid_callbacks_t *)(old == NULL ? NULL : *old); +} + + +static int conf_hid_id_next = 0; +static htpp_t *conf_hid_ids = NULL; + +static void conf_pcb_hid_init(void) +{ + if (conf_hid_ids == NULL) + conf_hid_ids = htpp_alloc(ptrhash, ptrkeyeq); +} + +void conf_pcb_hid_uninit(void) +{ +#ifndef NDEBUG + if (conf_hid_ids != NULL) { + htpp_entry_t *e; + for(e = htpp_first(conf_hid_ids); e != NULL; e = htpp_next(conf_hid_ids, e)) + fprintf(stderr, "ERROR: conf_hid id left registered: '%s'\n", (char *)e->key); + } +#endif + + if (conf_hid_ids != NULL) { + htpp_free(conf_hid_ids); + conf_hid_ids = NULL; + } +} + +conf_hid_id_t conf_hid_reg(const char *cookie, const conf_hid_callbacks_t *cb) +{ + conf_hid_t *h; + + if (cookie == NULL) + return -1; + + conf_pcb_hid_init(); + if (htpp_getentry(conf_hid_ids, (void *)cookie) != NULL) + return -1; /* already registered */ + + h = malloc(sizeof(conf_hid_t)); + h->cb = cb; + h->id = conf_hid_id_next++; + htpp_set(conf_hid_ids, (void *)cookie, h); + return h->id; +} + +void conf_hid_unreg(const char *cookie) +{ + htsp_entry_t *e; + conf_hid_t *h = htpp_pop(conf_hid_ids, (void *)cookie); + + if (h == NULL) + return; + + /* remove local callbacks */ + conf_fields_foreach(e) { + int len; + conf_native_t *cfg = e->value; + len = vtp0_len(&cfg->hid_callbacks); + + conf_hid_local_cb(cfg, -1, unreg_item); + + /* truncate the list if there are empty items at the end */ + if (len > h->id) { + int last; + cfg->hid_callbacks.array[h->id] = NULL; + for(last = len-1; last >= 0; last--) + if (cfg->hid_callbacks.array[last] != NULL) + break; + if (last < len) + vtp0_truncate(&cfg->hid_callbacks, last+1); + } + } + + if ((h->cb != NULL) && (h->cb->unreg_item != NULL)) { + conf_fields_foreach(e) { + conf_native_t *cfg = e->value; + h->cb->unreg_item(cfg, -1); + } + } + + free(h); +} + +typedef void (*cb_t)(conf_native_t *cfg, int arr_idx); +void conf_hid_global_cb_(conf_native_t *item, int arr_idx, int offs) +{ + htpp_entry_t *e; + if (conf_hid_ids == NULL) + return; + for (e = htpp_first(conf_hid_ids); e; e = htpp_next(conf_hid_ids, e)) { + conf_hid_t *h = e->value; + const conf_hid_callbacks_t *cbs = h->cb; + if (cbs != NULL) { + char *s = (char *)&cbs->val_change_pre; + cb_t *cb = (cb_t *)(s + offs); + if ((*cb) != NULL) + (*cb)(item, arr_idx); + } + } +} + + +void conf_loglevel_props(enum pcb_message_level level, const char **tag, int *popup) +{ + *tag = NULL; + *popup = 0; + switch(level) { + case PCB_MSG_DEBUG: *tag = conf_core.appearance.loglevels.debug_tag; *popup = conf_core.appearance.loglevels.debug_popup; break; + case PCB_MSG_INFO: *tag = conf_core.appearance.loglevels.info_tag; *popup = conf_core.appearance.loglevels.info_popup; break; + case PCB_MSG_WARNING: *tag = conf_core.appearance.loglevels.warning_tag; *popup = conf_core.appearance.loglevels.warning_popup; break; + case PCB_MSG_ERROR: *tag = conf_core.appearance.loglevels.error_tag; *popup = conf_core.appearance.loglevels.error_popup; break; + break; + } +} + Index: tags/2.1.2/src/conf_hid.h =================================================================== --- tags/2.1.2/src/conf_hid.h (nonexistent) +++ tags/2.1.2/src/conf_hid.h (revision 24813) @@ -0,0 +1,74 @@ +#ifndef PCB_CONF_HID_H +#define PCB_CONF_HID_H + +#include "conf.h" +#include "error.h" + +typedef struct conf_hid_callbacks_s { + /* Called before/after a value of a config item is updated - this doesn't necessarily mean the value actually changes */ + void (*val_change_pre)(conf_native_t *cfg, int arr_idx); + void (*val_change_post)(conf_native_t *cfg, int arr_idx); + + /* Called when a new config item is added to the database; global-only */ + void (*new_item_post)(conf_native_t *cfg, int arr_idx); + + /* Called during conf_hid_unreg to get hid-data cleaned up */ + void (*unreg_item)(conf_native_t *cfg, int arr_idx); +} conf_hid_callbacks_t; + +typedef int conf_hid_id_t; + +/* Set local hid data in a native item; returns the previous value set or NULL */ +void *conf_hid_set_data(conf_native_t *cfg, conf_hid_id_t id, void *data); + +/* Returns local hid data in a native item */ +void *conf_hid_get_data(conf_native_t *cfg, conf_hid_id_t id); + +/* Set local callbacks in a native item; returns the previous callbacks set or NULL */ +const conf_hid_callbacks_t *conf_hid_set_cb(conf_native_t *cfg, conf_hid_id_t id, const conf_hid_callbacks_t *cbs); + + +/* register a hid with a cookie; this is necessary only if: + - the HID wants to store per-config-item hid_data with the above calls + - the HID wants to get notified about changes in the config tree using callback functions + NOTE: cookie is taken by pointer, the string value does not matter. One pointer + can be registered only once. + cb holds the global notification callbacks - called when anything changed; it can be NULL. + Returns a new HID id that can be used to access hid data, or -1 on error. +*/ +conf_hid_id_t conf_hid_reg(const char *cookie, const conf_hid_callbacks_t *cb); + +/* Unregister a hid; if unreg_item cb is specified, call it on each config item */ +void conf_hid_unreg(const char *cookie); + +void conf_pcb_hid_uninit(void); + + +/* Call the local callback of a native item */ +#define conf_hid_local_cb(native, arr_idx, cb) \ +do { \ + unsigned int __n__; \ + for(__n__ = 0; __n__ < vtp0_len(&((native)->hid_callbacks)); __n__++) { \ + const conf_hid_callbacks_t *cbs = (native)->hid_callbacks.array[__n__]; \ + if ((cbs != NULL) && (cbs->cb != NULL)) \ + cbs->cb(native, arr_idx); \ + } \ +} while(0) + +/* Call the global callback of a native item */ +#define conf_hid_global_cb(native, arr_idx, cb) \ +do { \ + conf_hid_callbacks_t __cbs__; \ + int __offs__ = ((char *)&(__cbs__.cb)) - ((char *)&(__cbs__)); \ + conf_hid_global_cb_(native, arr_idx, __offs__); \ +} while(0) + +/****** Utility/helper functions ******/ +/* Looking at the log level, return a log format tag and whether the window + should pop up. */ +void conf_loglevel_props(enum pcb_message_level level, const char **tag, int *popup); + +/****** Internal ******/ +void conf_hid_global_cb_(conf_native_t *item, int arr_idx, int offs); + +#endif Index: tags/2.1.2/src/conf_regfile.c =================================================================== --- tags/2.1.2/src/conf_regfile.c (nonexistent) +++ tags/2.1.2/src/conf_regfile.c (revision 24813) @@ -0,0 +1,94 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2018 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +/* Register custom (plugin) config file names, reference counted. These files + are loaded from system and user config paths */ + +#include + +static void conf_files_init(void) +{ + htsi_init(&conf_files, strhash, strkeyeq); + htsi_init(&conf_interns, strhash, strkeyeq); + conf_files_inited = 1; +} + +void pcb_conf_files_uninit(void) +{ + htsi_entry_t *e; + for (e = htsi_first(&conf_files); e; e = htsi_next(&conf_files, e)) + free(e->key); + htsi_uninit(&conf_files); + htsi_uninit(&conf_interns); + conf_files_inited = 0; +} + +void conf_reg_file(const char *path, const char *intern) +{ + htsi_entry_t *e; + if (!conf_files_inited) conf_files_init(); + e = htsi_getentry(&conf_files, path); + if (e == NULL) + htsi_set(&conf_files, pcb_strdup(path), 1); + else + e->value++; + e = htsi_getentry(&conf_interns, intern); + if (e == NULL) + htsi_set(&conf_interns, (char *)intern, 1); + else + e->value++; + + if (conf_in_production) { + if (conf_load_plug_interns(CFR_INTERNAL)) + conf_merge_all(NULL); + } +} + +static void conf_unreg_any(htsi_t *ht, const char *key, int free_key) +{ + htsi_entry_t *e; + + e = htsi_getentry(ht, key); + assert(e != NULL); + if (e == NULL) return; + + e->value--; + if (e->value == 0) { + htsi_delentry(ht, e); + if (free_key) + free(e->key); + } +} + +void conf_unreg_file(const char *path, const char *intern) +{ + assert(conf_files_inited); + if (!conf_files_inited) return; + + conf_unreg_any(&conf_files, path, 1); + conf_unreg_any(&conf_interns, intern, 0); +} + Index: tags/2.1.2/src/crosshair.c =================================================================== --- tags/2.1.2/src/crosshair.c (nonexistent) +++ tags/2.1.2/src/crosshair.c (revision 24813) @@ -0,0 +1,1133 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * 15 Oct 2008 Ineiev: add different crosshair shapes + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +#include "config.h" +#include "conf_core.h" + +#include "board.h" +#include "crosshair.h" +#include "data.h" +#include "draw.h" +#include "draw_wireframe.h" +#include "search.h" +#include "polygon.h" +#include "actions.h" +#include "hid_inlines.h" +#include "compat_misc.h" +#include "vtonpoint.h" +#include "find.h" +#include "undo.h" +#include "event.h" +#include "macro.h" +#include "grid.h" +#include "stub_stroke.h" + +#include "obj_line_draw.h" +#include "obj_arc_draw.h" +#include "obj_text_draw.h" +#include "obj_pstk_draw.h" +#include "route_draw.h" +#include "obj_arc_ui.h" +#include "obj_subc_parent.h" + +#include "tool.h" + +typedef struct { + int x, y; +} point; + +pcb_crosshair_t pcb_crosshair; /* information about cursor settings */ +pcb_mark_t pcb_marked; /* a cross-hair mark */ + +static void thindraw_moved_ps(pcb_pstk_t *ps, pcb_coord_t x, pcb_coord_t y) +{ + /* Make a copy of the pin structure, moved to the correct position */ + pcb_pstk_t moved_ps = *ps; + moved_ps.x += x; + moved_ps.y += y; + + pcb_pstk_thindraw(NULL, pcb_crosshair.GC, &moved_ps); +} + +/* --------------------------------------------------------------------------- + * creates a tmp polygon with coordinates converted to screen system + */ +void pcb_xordraw_poly(pcb_poly_t *polygon, pcb_coord_t dx, pcb_coord_t dy, int dash_last) +{ + pcb_cardinal_t i; + for (i = 0; i < polygon->PointN; i++) { + pcb_cardinal_t next = pcb_poly_contour_next_point(polygon, i); + + if (next == 0) { /* last line: sometimes the implicit closing line */ + if (i == 1) /* corner case: don't draw two lines on top of each other - with XOR it looks bad */ + continue; + + if (dash_last) { + pcb_draw_dashed_line(NULL, pcb_crosshair.GC, + polygon->Points[i].X + dx, + polygon->Points[i].Y + dy, polygon->Points[next].X + dx, polygon->Points[next].Y + dy, 5, pcb_false); + break; /* skip normal line draw below */ + } + } + + /* normal contour line */ + pcb_gui->draw_line(pcb_crosshair.GC, + polygon->Points[i].X + dx, + polygon->Points[i].Y + dy, polygon->Points[next].X + dx, polygon->Points[next].Y + dy); + } +} + +/* --------------------------------------------------------------------------- + * creates a tmp polygon with coordinates converted to screen system, designed + * for subc paste xor-draw + */ +void pcb_xordraw_poly_subc(pcb_poly_t *polygon, pcb_coord_t dx, pcb_coord_t dy, pcb_coord_t w, pcb_coord_t h, int mirr) +{ + pcb_cardinal_t i; + for (i = 0; i < polygon->PointN; i++) { + pcb_cardinal_t next = pcb_poly_contour_next_point(polygon, i); + + if (next == 0) { /* last line: sometimes the implicit closing line */ + if (i == 1) /* corner case: don't draw two lines on top of each other - with XOR it looks bad */ + continue; + } + + /* normal contour line */ + pcb_gui->draw_line(pcb_crosshair.GC, + PCB_CSWAP_X(polygon->Points[i].X, w, mirr) + dx, + PCB_CSWAP_Y(polygon->Points[i].Y, h, mirr) + dy, + PCB_CSWAP_X(polygon->Points[next].X, w, mirr) + dx, + PCB_CSWAP_Y(polygon->Points[next].Y, h, mirr) + dy); + } +} + +void pcb_xordraw_attached_arc(pcb_coord_t thick) +{ + pcb_arc_t arc; + pcb_coord_t wx, wy; + pcb_angle_t sa, dir; + + wx = pcb_crosshair.X - pcb_crosshair.AttachedBox.Point1.X; + wy = pcb_crosshair.Y - pcb_crosshair.AttachedBox.Point1.Y; + if (wx == 0 && wy == 0) + return; + arc.X = pcb_crosshair.AttachedBox.Point1.X; + arc.Y = pcb_crosshair.AttachedBox.Point1.Y; + if (PCB_XOR(pcb_crosshair.AttachedBox.otherway, coord_abs(wy) > coord_abs(wx))) { + arc.X = pcb_crosshair.AttachedBox.Point1.X + coord_abs(wy) * PCB_SGNZ(wx); + sa = (wx >= 0) ? 0 : 180; + dir = (PCB_SGNZ(wx) == PCB_SGNZ(wy)) ? 90 : -90; + } + else { + arc.Y = pcb_crosshair.AttachedBox.Point1.Y + coord_abs(wx) * PCB_SGNZ(wy); + sa = (wy >= 0) ? -90 : 90; + dir = (PCB_SGNZ(wx) == PCB_SGNZ(wy)) ? -90 : 90; + wy = wx; + } + wy = coord_abs(wy); + arc.StartAngle = sa; + arc.Delta = dir; + arc.Width = arc.Height = wy; + arc.Thickness = thick; + + pcb_draw_wireframe_arc(pcb_crosshair.GC, &arc, thick); +} + +/* --------------------------------------------------------------------------- + * draws all visible and attached objects of the pastebuffer + */ +void pcb_xordraw_buffer(pcb_buffer_t *Buffer) +{ + pcb_cardinal_t i; + pcb_coord_t x, y; + + /* set offset */ + x = pcb_crosshair.AttachedObject.tx - Buffer->X; + y = pcb_crosshair.AttachedObject.ty - Buffer->Y; + + /* draw all visible layers */ + for (i = 0; i < pcb_max_layer; i++) + if (PCB->Data->Layer[i].meta.real.vis) { + pcb_layer_t *layer = &Buffer->Data->Layer[i]; + + PCB_LINE_LOOP(layer); + { + pcb_draw_wireframe_line( pcb_crosshair.GC, + x + line->Point1.X, y + line->Point1.Y, + x + line->Point2.X, y + line->Point2.Y, + line->Thickness,0 ); + } + PCB_END_LOOP; + PCB_ARC_LOOP(layer); + { + pcb_arc_t translated_arc = *arc; + translated_arc.X += x; + translated_arc.Y += y; + pcb_draw_wireframe_arc(pcb_crosshair.GC, &translated_arc, arc->Thickness); + } + PCB_END_LOOP; + PCB_TEXT_LOOP(layer); + { + pcb_text_draw_xor(text, x, y); + } + PCB_END_LOOP; + /* the tmp polygon has n+1 points because the first + * and the last one are set to the same coordinates + */ + PCB_POLY_LOOP(layer); + { + pcb_xordraw_poly(polygon, x, y, 0); + } + PCB_END_LOOP; + } + + /* draw subcircuit */ + PCB_SUBC_LOOP(Buffer->Data); + { + pcb_xordraw_subc(subc, x, y, Buffer->from_outside); + } + PCB_END_LOOP; + + /* and the padstacks */ + if (PCB->pstk_on) + PCB_PADSTACK_LOOP(Buffer->Data); + { + thindraw_moved_ps(padstack, x, y); + } + PCB_END_LOOP; +} + +/* --------------------------------------------------------------------------- + * draws the rubberband to insert points into polygons/lines/... + */ +void pcb_xordraw_insert_pt_obj(void) +{ + pcb_line_t *line = (pcb_line_t *) pcb_crosshair.AttachedObject.Ptr2; + pcb_point_t *point = (pcb_point_t *) pcb_crosshair.AttachedObject.Ptr3; + + if (pcb_crosshair.AttachedObject.Type != PCB_OBJ_VOID) { + pcb_gui->draw_line(pcb_crosshair.GC, point->X, point->Y, line->Point1.X, line->Point1.Y); + pcb_gui->draw_line(pcb_crosshair.GC, point->X, point->Y, line->Point2.X, line->Point2.Y); + } +} + +/* --------------------------------------------------------------------------- + * draws the attached object while in PCB_MODE_MOVE or PCB_MODE_COPY + */ +void pcb_xordraw_movecopy(void) +{ + pcb_coord_t dx = pcb_crosshair.AttachedObject.tx - pcb_crosshair.AttachedObject.X; + pcb_coord_t dy = pcb_crosshair.AttachedObject.ty - pcb_crosshair.AttachedObject.Y; + int event_sent = 0; + + switch (pcb_crosshair.AttachedObject.Type) { + + case PCB_OBJ_PSTK: + { + pcb_pstk_t *ps = (pcb_pstk_t *) pcb_crosshair.AttachedObject.Ptr1; + thindraw_moved_ps(ps, dx, dy); + break; + } + + case PCB_OBJ_LINE: + { + /* We move a local copy of the line -the real line hasn't moved, + * only the preview. + */ + int constrained = 0; + pcb_line_t line; + + pcb_coord_t dx1 = dx, dx2 = dx; + pcb_coord_t dy1 = dy, dy2 = dy; + + memcpy(&line, (pcb_line_t *) pcb_crosshair.AttachedObject.Ptr2, sizeof(line)); + + if(conf_core.editor.rubber_band_keep_midlinedir) + pcb_event(PCB_EVENT_RUBBER_CONSTRAIN_MAIN_LINE, "pppppp", &line, &constrained, &dx1, &dy1, &dx2, &dy2); + pcb_event(PCB_EVENT_RUBBER_MOVE_DRAW, "icccc", constrained, dx1, dy1, dx2, dy2); + + event_sent = 1; + + line.Point1.X += dx1; + line.Point1.Y += dy1; + line.Point2.X += dx2; + line.Point2.Y += dy2; + + pcb_draw_wireframe_line(pcb_crosshair.GC, + line.Point1.X, line.Point1.Y, + line.Point2.X, line.Point2.Y, + line.Thickness, 0); + + /* Draw the DRC outline if it is enabled */ + if (conf_core.editor.show_drc) { + pcb_gui->set_color(pcb_crosshair.GC, &conf_core.appearance.color.cross); + pcb_draw_wireframe_line(pcb_crosshair.GC,line.Point1.X, line.Point1.Y, + line.Point2.X, line.Point2.Y, + line.Thickness + 2 * (conf_core.design.bloat + 1), 0); + pcb_gui->set_color(pcb_crosshair.GC, &conf_core.appearance.color.crosshair); + } + break; + } + + case PCB_OBJ_ARC: + { + /* Make a temporary arc and move it by dx,dy */ + pcb_arc_t arc = *((pcb_arc_t *) pcb_crosshair.AttachedObject.Ptr2); + pcb_event(PCB_EVENT_RUBBER_MOVE_DRAW, "icccc", 0, dx, dy, dx, dy); + event_sent = 1; + + arc.X += dx; + arc.Y += dy; + + pcb_draw_wireframe_arc(pcb_crosshair.GC, &arc, arc.Thickness); + + /* Draw the DRC outline if it is enabled */ + if (conf_core.editor.show_drc) { + pcb_gui->set_color(pcb_crosshair.GC, &conf_core.appearance.color.cross); + arc.Thickness += 2 * (conf_core.design.bloat + 1); + pcb_draw_wireframe_arc(pcb_crosshair.GC, &arc, arc.Thickness); + pcb_gui->set_color(pcb_crosshair.GC, &conf_core.appearance.color.crosshair); + } + break; + } + + case PCB_OBJ_POLY: + { + pcb_poly_t *polygon = (pcb_poly_t *) pcb_crosshair.AttachedObject.Ptr2; + + /* the tmp polygon has n+1 points because the first + * and the last one are set to the same coordinates + */ + pcb_xordraw_poly(polygon, dx, dy, 0); + break; + } + + case PCB_OBJ_TEXT: + { + pcb_text_t *text = (pcb_text_t *)pcb_crosshair.AttachedObject.Ptr2; + pcb_text_draw_xor(text, dx, dy); + break; + } + + case PCB_OBJ_LINE_POINT: + { + pcb_line_t *line; + pcb_point_t *point,*point1,point2; + + line = (pcb_line_t *) pcb_crosshair.AttachedObject.Ptr2; + point = (pcb_point_t *) pcb_crosshair.AttachedObject.Ptr3; + point1 = (point == &line->Point1 ? &line->Point2 : &line->Point1); + point2 = *point; + point2.X += dx; + point2.Y += dy; + + if(conf_core.editor.move_linepoint_uses_route == 0) {/* config setting for selecting new 45/90 method */ + pcb_draw_wireframe_line(pcb_crosshair.GC,point1->X, point1->Y, point2.X, point2.Y, line->Thickness, 0); + + /* Draw the DRC outline if it is enabled */ + if (conf_core.editor.show_drc) { + pcb_gui->set_color(pcb_crosshair.GC, &conf_core.appearance.color.cross); + pcb_draw_wireframe_line(pcb_crosshair.GC,point1->X, point1->Y, point2.X, + point2.Y,line->Thickness + 2 * (conf_core.design.bloat + 1), 0); + pcb_gui->set_color(pcb_crosshair.GC, &conf_core.appearance.color.crosshair); + } + } + else { + pcb_route_t route; + pcb_route_init(&route); + pcb_route_calculate( PCB, + &route, + point1, + &point2, + pcb_layer_id(PCB->Data,(pcb_layer_t *)pcb_crosshair.AttachedObject.Ptr1), + line->Thickness, + line->Clearance, + line->Flags, + pcb_gui->shift_is_pressed(), + pcb_gui->control_is_pressed() ); + pcb_route_draw(&route,pcb_crosshair.GC); + if (conf_core.editor.show_drc) + pcb_route_draw_drc(&route,pcb_crosshair.GC); + pcb_route_destroy(&route); + } + + break; + } + + case PCB_OBJ_ARC_POINT: + { + pcb_arc_t arc = *((pcb_arc_t *)pcb_crosshair.AttachedObject.Ptr2); + pcb_coord_t ox1,ox2,oy1,oy2; + pcb_coord_t nx1,nx2,ny1,ny2; + + /* Get the initial position of the arc point */ + pcb_arc_get_end(&arc,0, &ox1, &oy1); + pcb_arc_get_end(&arc,1, &ox2, &oy2); + + /* Update the attached arc point */ + pcb_arc_ui_move_or_copy(&pcb_crosshair); + + /* Update our local arc copy from the attached object */ + if(pcb_crosshair.AttachedObject.radius != 0) { + arc.Width = pcb_crosshair.AttachedObject.radius; + arc.Height = pcb_crosshair.AttachedObject.radius; + } + else { + arc.StartAngle = pcb_crosshair.AttachedObject.start_angle; + arc.Delta = pcb_crosshair.AttachedObject.delta_angle; + } + + pcb_draw_wireframe_arc(pcb_crosshair.GC, &arc, arc.Thickness); + + /* Draw the DRC outline if it is enabled */ + if (conf_core.editor.show_drc) { + pcb_gui->set_color(pcb_crosshair.GC, &conf_core.appearance.color.cross); + arc.Thickness += 2 * (conf_core.design.bloat + 1); + pcb_draw_wireframe_arc(pcb_crosshair.GC, &arc, arc.Thickness); + pcb_gui->set_color(pcb_crosshair.GC, &conf_core.appearance.color.crosshair); + } + + /* Get the new arc point positions, calculate the movement deltas and send them + * in a rubber_move_draw event */ + pcb_arc_get_end(&arc,0, &nx1, &ny1); + pcb_arc_get_end(&arc,1, &nx2, &ny2); + + pcb_event(PCB_EVENT_RUBBER_MOVE_DRAW, "icccc", 0, nx1-ox1,ny1-oy1,nx2-ox2,ny2-oy2); + event_sent = 1; + break; + } + + case PCB_OBJ_POLY_POINT: + { + pcb_poly_t *polygon; + pcb_point_t *point; + pcb_cardinal_t point_idx, prev, next; + + polygon = (pcb_poly_t *) pcb_crosshair.AttachedObject.Ptr2; + point = (pcb_point_t *) pcb_crosshair.AttachedObject.Ptr3; + point_idx = pcb_poly_point_idx(polygon, point); + + /* get previous and following point */ + prev = pcb_poly_contour_prev_point(polygon, point_idx); + next = pcb_poly_contour_next_point(polygon, point_idx); + + /* draw the two segments */ + pcb_gui->draw_line(pcb_crosshair.GC, polygon->Points[prev].X, polygon->Points[prev].Y, point->X + dx, point->Y + dy); + pcb_gui->draw_line(pcb_crosshair.GC, point->X + dx, point->Y + dy, polygon->Points[next].X, polygon->Points[next].Y); + break; + } + + case PCB_OBJ_SUBC: + pcb_xordraw_subc((pcb_subc_t *) pcb_crosshair.AttachedObject.Ptr2, dx, dy, 0); + break; + } + + /* floaters have a link back to their parent subc */ + if (pcb_crosshair.AttachedObject.Ptr2 != NULL + && PCB_FLAG_TEST(PCB_FLAG_FLOATER, (pcb_any_obj_t *)pcb_crosshair.AttachedObject.Ptr2)) { + pcb_any_obj_t *obj = pcb_crosshair.AttachedObject.Ptr2; + if (obj->parent_type == PCB_PARENT_LAYER) { + pcb_data_t *data = obj->parent.layer->parent.data; + if ((data != NULL) && (data->parent_type == PCB_PARENT_SUBC)) { + pcb_subc_t *sc = data->parent.subc; + pcb_coord_t ox, oy; + if (pcb_subc_get_origin(sc, &ox, &oy) == 0) + pcb_gui->draw_line(pcb_crosshair.GC, ox, oy, pcb_crosshair.X, pcb_crosshair.Y); + } + } + } + + if(!event_sent) + pcb_event(PCB_EVENT_RUBBER_MOVE_DRAW, "icc", 0, dx, dy ); +} + +/* --------------------------------------------------------------------------- + * draws additional stuff that follows the crosshair + */ +void pcb_draw_attached(pcb_bool inhibit_drawing_mode) +{ + if (!inhibit_drawing_mode) { + pcb_gui->set_drawing_mode(PCB_HID_COMP_RESET, 1, NULL); + pcb_gui->set_drawing_mode(PCB_HID_COMP_POSITIVE_XOR, 1, NULL); + } + + pcb_tool_draw_attached(); + + /* an attached box does not depend on a special mode */ + if (pcb_crosshair.AttachedBox.State == PCB_CH_STATE_SECOND || pcb_crosshair.AttachedBox.State == PCB_CH_STATE_THIRD) { + pcb_coord_t x1, y1, x2, y2; + + x1 = pcb_crosshair.AttachedBox.Point1.X; + y1 = pcb_crosshair.AttachedBox.Point1.Y; + x2 = pcb_crosshair.AttachedBox.Point2.X; + y2 = pcb_crosshair.AttachedBox.Point2.Y; + pcb_gui->draw_rect(pcb_crosshair.GC, x1, y1, x2, y2); + } + + if (!inhibit_drawing_mode) + pcb_gui->set_drawing_mode(PCB_HID_COMP_FLUSH, 1, NULL); +} + + +void pcb_draw_mark(pcb_bool inhibit_drawing_mode) +{ + pcb_coord_t ms = conf_core.appearance.mark_size; + + /* Mark is not drawn when it is not set */ + if (!pcb_marked.status) + return; + + if (!inhibit_drawing_mode) { + pcb_gui->set_drawing_mode(PCB_HID_COMP_RESET, 1, NULL); + pcb_gui->set_drawing_mode(PCB_HID_COMP_POSITIVE, 1, NULL); + } + + pcb_gui->draw_line(pcb_crosshair.GC, pcb_marked.X - ms, pcb_marked.Y - ms, pcb_marked.X + ms, pcb_marked.Y + ms); + pcb_gui->draw_line(pcb_crosshair.GC, pcb_marked.X + ms, pcb_marked.Y - ms, pcb_marked.X - ms, pcb_marked.Y + ms); + + if (!inhibit_drawing_mode) + pcb_gui->set_drawing_mode(PCB_HID_COMP_FLUSH, 1, NULL); +} + +/* --------------------------------------------------------------------------- + * notify the GUI that data relating to the crosshair is being changed. + * + * The argument passed is pcb_false to notify "changes are about to happen", + * and pcb_true to notify "changes have finished". + * + * Each call with a 'pcb_false' parameter must be matched with a following one + * with a 'pcb_true' parameter. Unmatched 'pcb_true' calls are currently not permitted, + * but might be allowed in the future. + * + * GUIs should not complain if they receive extra calls with 'pcb_true' as parameter. + * They should initiate a redraw of the crosshair attached objects - which may + * (if necessary) mean repainting the whole screen if the GUI hasn't tracked the + * location of existing attached drawing. + */ +void pcb_notify_crosshair_change(pcb_bool changes_complete) +{ + if (pcb_gui->notify_crosshair_change) + pcb_gui->notify_crosshair_change(changes_complete); +} + + +/* --------------------------------------------------------------------------- + * notify the GUI that data relating to the mark is being changed. + * + * The argument passed is pcb_false to notify "changes are about to happen", + * and pcb_true to notify "changes have finished". + * + * Each call with a 'pcb_false' parameter must be matched with a following one + * with a 'pcb_true' parameter. Unmatched 'pcb_true' calls are currently not permitted, + * but might be allowed in the future. + * + * GUIs should not complain if they receive extra calls with 'pcb_true' as parameter. + * They should initiate a redraw of the mark - which may (if necessary) mean + * repainting the whole screen if the GUI hasn't tracked the mark's location. + */ +void pcb_notify_mark_change(pcb_bool changes_complete) +{ + if (pcb_gui->notify_mark_change) + pcb_gui->notify_mark_change(changes_complete); +} + + +/* + * Below is the implementation of the "highlight on endpoint" functionality. + * This highlights lines and arcs when the crosshair is on of their (two) + * endpoints. + */ +struct onpoint_search_info { + pcb_crosshair_t *crosshair; + pcb_coord_t X; + pcb_coord_t Y; +}; + +static pcb_r_dir_t onpoint_line_callback(const pcb_box_t * box, void *cl) +{ + struct onpoint_search_info *info = (struct onpoint_search_info *) cl; + pcb_crosshair_t *crosshair = info->crosshair; + pcb_line_t *line = (pcb_line_t *) box; + +#ifdef DEBUG_ONPOINT + printf("X=%ld Y=%ld X1=%ld Y1=%ld X2=%ld Y2=%ld\n", info->X, info->Y, + line->Point1.X, line->Point1.Y, line->Point2.X, line->Point2.Y); +#endif + if ((line->Point1.X == info->X && line->Point1.Y == info->Y) || (line->Point2.X == info->X && line->Point2.Y == info->Y)) { + pcb_onpoint_t op; + op.type = PCB_OBJ_LINE; + op.obj.line = line; + vtop_append(&crosshair->onpoint_objs, op); + PCB_FLAG_SET(PCB_FLAG_ONPOINT, (pcb_any_obj_t *) line); + pcb_line_invalidate_draw(NULL, line); + return PCB_R_DIR_FOUND_CONTINUE; + } + else { + return PCB_R_DIR_NOT_FOUND; + } +} + +#define close_enough(v1, v2) (coord_abs((v1)-(v2)) < 10) + +static pcb_r_dir_t onpoint_arc_callback(const pcb_box_t * box, void *cl) +{ + struct onpoint_search_info *info = (struct onpoint_search_info *) cl; + pcb_crosshair_t *crosshair = info->crosshair; + pcb_arc_t *arc = (pcb_arc_t *) box; + pcb_coord_t p1x, p1y, p2x, p2y; + + p1x = arc->X - arc->Width * cos(PCB_TO_RADIANS(arc->StartAngle)); + p1y = arc->Y + arc->Height * sin(PCB_TO_RADIANS(arc->StartAngle)); + p2x = arc->X - arc->Width * cos(PCB_TO_RADIANS(arc->StartAngle + arc->Delta)); + p2y = arc->Y + arc->Height * sin(PCB_TO_RADIANS(arc->StartAngle + arc->Delta)); + + /* printf("p1=%ld;%ld p2=%ld;%ld info=%ld;%ld\n", p1x, p1y, p2x, p2y, info->X, info->Y); */ + + if ((close_enough(p1x, info->X) && close_enough(p1y, info->Y)) || (close_enough(p2x, info->X) && close_enough(p2y, info->Y))) { + pcb_onpoint_t op; + op.type = PCB_OBJ_ARC; + op.obj.arc = arc; + vtop_append(&crosshair->onpoint_objs, op); + PCB_FLAG_SET(PCB_FLAG_ONPOINT, (pcb_any_obj_t *) arc); + pcb_arc_invalidate_draw(NULL, arc); + return PCB_R_DIR_FOUND_CONTINUE; + } + else { + return PCB_R_DIR_NOT_FOUND; + } +} + +void DrawLineOrArc(int type, void *obj) +{ + switch (type) { + case PCB_OBJ_LINE_POINT: + /* Attention: We can use a NULL pointer here for the layer, + * because it is not used in the pcb_line_invalidate_draw() function anyways. + * ATM pcb_line_invalidate_draw() only calls AddPart() internally, which invalidates + * the area specified by the line's bounding box. + */ + pcb_line_invalidate_draw(NULL, (pcb_line_t *) obj); + break; + case PCB_OBJ_ARC_POINT: + /* See comment above */ + pcb_arc_invalidate_draw(NULL, (pcb_arc_t *) obj); + break; + } +} + + +#define op_swap(crosshair) \ +do { \ + vtop_t __tmp__ = crosshair->onpoint_objs; \ + crosshair->onpoint_objs = crosshair->old_onpoint_objs; \ + crosshair->old_onpoint_objs = __tmp__; \ +} while(0) + +static void *onpoint_find(vtop_t *vect, void *obj_ptr) +{ + int i; + + for (i = 0; i < vect->used; i++) { + pcb_onpoint_t *op = &(vect->array[i]); + if (op->obj.any == obj_ptr) + return op; + } + return NULL; +} + +/* + * Searches for lines or arcs which have points that are exactly + * at the given coordinates and adds them to the crosshair's + * object list along with their respective type. + */ +static void onpoint_work(pcb_crosshair_t * crosshair, pcb_coord_t X, pcb_coord_t Y) +{ + pcb_box_t SearchBox = pcb_point_box(X, Y); + struct onpoint_search_info info; + int i; + pcb_bool redraw = pcb_false; + + op_swap(crosshair); + + /* Do not truncate to 0 because that may free the array */ + vtop_truncate(&crosshair->onpoint_objs, 1); + crosshair->onpoint_objs.used = 0; + + + info.crosshair = crosshair; + info.X = X; + info.Y = Y; + + for (i = 0; i < pcb_max_layer; i++) { + pcb_layer_t *layer = &PCB->Data->Layer[i]; + /* Only find points of arcs and lines on currently visible layers. */ + if (!layer->meta.real.vis) + continue; + pcb_r_search(layer->line_tree, &SearchBox, NULL, onpoint_line_callback, &info, NULL); + pcb_r_search(layer->arc_tree, &SearchBox, NULL, onpoint_arc_callback, &info, NULL); + } + + /* Undraw the old objects */ + for (i = 0; i < crosshair->old_onpoint_objs.used; i++) { + pcb_onpoint_t *op = &crosshair->old_onpoint_objs.array[i]; + + /* only remove and redraw those which aren't in the new list */ + if (onpoint_find(&crosshair->onpoint_objs, op->obj.any) != NULL) + continue; + + PCB_FLAG_CLEAR(PCB_FLAG_ONPOINT, (pcb_any_obj_t *) op->obj.any); + DrawLineOrArc(op->type, op->obj.any); + redraw = pcb_true; + } + + /* draw the new objects */ + for (i = 0; i < crosshair->onpoint_objs.used; i++) { + pcb_onpoint_t *op = &crosshair->onpoint_objs.array[i]; + + /* only draw those which aren't in the old list */ + if (onpoint_find(&crosshair->old_onpoint_objs, op->obj.any) != NULL) + continue; + DrawLineOrArc(op->type, op->obj.any); + redraw = pcb_true; + } + + if (redraw) { + pcb_redraw(); + } +} + +static double square(double x) +{ + return x * x; +} + +static double crosshair_sq_dist(pcb_crosshair_t * crosshair, pcb_coord_t x, pcb_coord_t y) +{ + return square(x - crosshair->X) + square(y - crosshair->Y); +} + +struct snap_data { + pcb_crosshair_t *crosshair; + double nearest_sq_dist; + pcb_bool nearest_is_grid; + pcb_coord_t x, y; +}; + +/* Snap to a given location if it is the closest thing we found so far. + * If "prefer_to_grid" is set, the passed location will take preference + * over a closer grid points we already snapped to UNLESS the user is + * pressing the SHIFT key. If the SHIFT key is pressed, the closest object + * (including grid points), is always preferred. + */ +static void check_snap_object(struct snap_data *snap_data, pcb_coord_t x, pcb_coord_t y, pcb_bool prefer_to_grid, pcb_any_obj_t *snapo) +{ + double sq_dist; + + /* avoid snapping to an object if it is in the same subc */ + if ((snapo != NULL) && (conf_core.editor.mode == PCB_MODE_MOVE) && (pcb_crosshair.AttachedObject.Type == PCB_OBJ_SUBC)) { + pcb_any_obj_t *parent = (pcb_any_obj_t *)pcb_obj_parent_subc(snapo); + int n; + pcb_cardinal_t parent_id = snapo->ID; + if (parent != NULL) + parent_id = parent->ID; + for(n = 0; n < pcb_crosshair.drags_len; n++) { + if ((snapo->ID == pcb_crosshair.drags[n]) || (parent_id == pcb_crosshair.drags[n])) + return; + } + } + + sq_dist = crosshair_sq_dist(snap_data->crosshair, x, y); + if (sq_dist < snap_data->nearest_sq_dist || (prefer_to_grid && snap_data->nearest_is_grid && !pcb_gui->shift_is_pressed())) { + snap_data->x = x; + snap_data->y = y; + snap_data->nearest_sq_dist = sq_dist; + snap_data->nearest_is_grid = pcb_false; + } +} + +static void check_snap_offgrid_line(struct snap_data *snap_data, pcb_coord_t nearest_grid_x, pcb_coord_t nearest_grid_y) +{ + void *ptr1, *ptr2, *ptr3; + int ans; + pcb_line_t *line; + pcb_coord_t try_x, try_y; + double dx, dy; + double dist; + + if (!conf_core.editor.snap_pin) + return; + + /* Code to snap at some sensible point along a line */ + /* Pick the nearest grid-point in the x or y direction + * to align with, then adjust until we hit the line + */ + ans = pcb_search_grid_slop(pcb_crosshair.X, pcb_crosshair.Y, PCB_OBJ_LINE, &ptr1, &ptr2, &ptr3); + + if (ans == PCB_OBJ_VOID) + return; + + line = (pcb_line_t *) ptr2; + + if (!pcb_tool_should_snap_offgrid_line(ptr1, line)) + return; + + dx = line->Point2.X - line->Point1.X; + dy = line->Point2.Y - line->Point1.Y; + + /* Try snapping along the X axis */ + if (dy != 0.) { + /* Move in the X direction until we hit the line */ + try_x = (nearest_grid_y - line->Point1.Y) / dy * dx + line->Point1.X; + try_y = nearest_grid_y; + check_snap_object(snap_data, try_x, try_y, pcb_true, (pcb_any_obj_t *)line); + } + + /* Try snapping along the Y axis */ + if (dx != 0.) { + try_x = nearest_grid_x; + try_y = (nearest_grid_x - line->Point1.X) / dx * dy + line->Point1.Y; + check_snap_object(snap_data, try_x, try_y, pcb_true, (pcb_any_obj_t *)line); + } + + if (dx != dy) { /* If line not parallel with dX = dY direction.. */ + /* Try snapping diagonally towards the line in the dX = dY direction */ + + if (dy == 0) + dist = line->Point1.Y - nearest_grid_y; + else + dist = ((line->Point1.X - nearest_grid_x) - (line->Point1.Y - nearest_grid_y) * dx / dy) / (1 - dx / dy); + + try_x = nearest_grid_x + dist; + try_y = nearest_grid_y + dist; + + check_snap_object(snap_data, try_x, try_y, pcb_true, (pcb_any_obj_t *)line); + } + + if (dx != -dy) { /* If line not parallel with dX = -dY direction.. */ + /* Try snapping diagonally towards the line in the dX = -dY direction */ + + if (dy == 0) + dist = nearest_grid_y - line->Point1.Y; + else + dist = ((line->Point1.X - nearest_grid_x) - (line->Point1.Y - nearest_grid_y) * dx / dy) / (1 + dx / dy); + + try_x = nearest_grid_x + dist; + try_y = nearest_grid_y - dist; + + check_snap_object(snap_data, try_x, try_y, pcb_true, (pcb_any_obj_t *)line); + } +} + +/* --------------------------------------------------------------------------- + * recalculates the passed coordinates to fit the current grid setting + */ +void pcb_crosshair_grid_fit(pcb_coord_t X, pcb_coord_t Y) +{ + pcb_coord_t nearest_grid_x, nearest_grid_y; + void *ptr1, *ptr2, *ptr3; + struct snap_data snap_data; + int ans; + + pcb_crosshair.X = PCB_CLAMP(X, pcb_crosshair.MinX, pcb_crosshair.MaxX); + pcb_crosshair.Y = PCB_CLAMP(Y, pcb_crosshair.MinY, pcb_crosshair.MaxY); + + if (PCB->RatDraw) { + nearest_grid_x = -PCB_MIL_TO_COORD(6); + nearest_grid_y = -PCB_MIL_TO_COORD(6); + } + else { + nearest_grid_x = pcb_grid_fit(pcb_crosshair.X, PCB->Grid, PCB->GridOffsetX); + nearest_grid_y = pcb_grid_fit(pcb_crosshair.Y, PCB->Grid, PCB->GridOffsetY); + + if (pcb_marked.status && conf_core.editor.orthogonal_moves) { + pcb_coord_t dx = pcb_crosshair.X - pcb_marked.X; + pcb_coord_t dy = pcb_crosshair.Y - pcb_marked.Y; + if (PCB_ABS(dx) > PCB_ABS(dy)) + nearest_grid_y = pcb_marked.Y; + else + nearest_grid_x = pcb_marked.X; + } + + } + + snap_data.crosshair = &pcb_crosshair; + snap_data.nearest_sq_dist = crosshair_sq_dist(&pcb_crosshair, nearest_grid_x, nearest_grid_y); + snap_data.nearest_is_grid = pcb_true; + snap_data.x = nearest_grid_x; + snap_data.y = nearest_grid_y; + + ans = PCB_OBJ_VOID; + if (!PCB->RatDraw) + ans = pcb_search_grid_slop(pcb_crosshair.X, pcb_crosshair.Y, PCB_OBJ_SUBC, &ptr1, &ptr2, &ptr3); + + if (ans & PCB_OBJ_SUBC) { + pcb_subc_t *sc = (pcb_subc_t *) ptr1; + pcb_coord_t ox, oy; + if (pcb_subc_get_origin(sc, &ox, &oy) == 0) + check_snap_object(&snap_data, ox, oy, pcb_false, (pcb_any_obj_t *)sc); + } + + /*** padstack center ***/ + ans = PCB_OBJ_VOID; + if (conf_core.editor.snap_pin) + ans = pcb_search_grid_slop(pcb_crosshair.X, pcb_crosshair.Y, PCB_OBJ_PSTK | PCB_OBJ_SUBC_PART, &ptr1, &ptr2, &ptr3); + + /* Avoid snapping padstack to any other padstack */ + if (conf_core.editor.mode == PCB_MODE_MOVE && pcb_crosshair.AttachedObject.Type == PCB_OBJ_PSTK && (ans & PCB_OBJ_PSTK)) + ans = PCB_OBJ_VOID; + + if (ans != PCB_OBJ_VOID) { + pcb_pstk_t *ps = (pcb_pstk_t *) ptr2; + check_snap_object(&snap_data, ps->x, ps->y, pcb_true, (pcb_any_obj_t *)ps); + pcb_crosshair.snapped_pstk = ps; + } + + /*** arc ***/ + ans = PCB_OBJ_VOID; + if (conf_core.editor.snap_pin) + ans = pcb_search_grid_slop(pcb_crosshair.X, pcb_crosshair.Y, PCB_OBJ_LINE_POINT | PCB_OBJ_ARC_POINT | PCB_OBJ_SUBC_PART, &ptr1, &ptr2, &ptr3); + + if (ans == PCB_OBJ_ARC_POINT) { + /* Arc point needs special handling as it's not a real point but has to be calculated */ + pcb_coord_t ex, ey; + pcb_arc_get_end((pcb_arc_t *)ptr2, (ptr3 != pcb_arc_start_ptr), &ex, &ey); + check_snap_object(&snap_data, ex, ey, pcb_true, (pcb_any_obj_t *)ptr2); + } + else if (ans != PCB_OBJ_VOID) { + pcb_point_t *pnt = (pcb_point_t *) ptr3; + check_snap_object(&snap_data, pnt->X, pnt->Y, pcb_true, (pcb_any_obj_t *)ptr2); + } + + /*** polygon terminal: center ***/ + ans = PCB_OBJ_VOID; + if (conf_core.editor.snap_pin) + ans = pcb_search_grid_slop(pcb_crosshair.X, pcb_crosshair.Y, PCB_OBJ_POLY | PCB_OBJ_SUBC_PART, &ptr1, &ptr2, &ptr3); + + if (ans == PCB_OBJ_POLY) { + pcb_poly_t *p = ptr2; + if (p->term != NULL) { + pcb_coord_t cx, cy; + cx = (p->BoundingBox.X1 + p->BoundingBox.X2)/2; + cy = (p->BoundingBox.Y1 + p->BoundingBox.Y2)/2; + if (pcb_poly_is_point_in_p(cx, cy, 1, p)) + check_snap_object(&snap_data, cx, cy, pcb_true, (pcb_any_obj_t *)p); + } + } + + /* + * Snap to offgrid points on lines. + */ + if (conf_core.editor.snap_offgrid_line) + check_snap_offgrid_line(&snap_data, nearest_grid_x, nearest_grid_y); + + ans = PCB_OBJ_VOID; + if (conf_core.editor.snap_pin) + ans = pcb_search_grid_slop(pcb_crosshair.X, pcb_crosshair.Y, PCB_OBJ_POLY_POINT, &ptr1, &ptr2, &ptr3); + + if (ans != PCB_OBJ_VOID) { + pcb_point_t *pnt = (pcb_point_t *) ptr3; + check_snap_object(&snap_data, pnt->X, pnt->Y, pcb_true, NULL); + } + + if (snap_data.x >= 0 && snap_data.y >= 0) { + pcb_crosshair.X = snap_data.x; + pcb_crosshair.Y = snap_data.y; + } + + if (conf_core.editor.highlight_on_point) + onpoint_work(&pcb_crosshair, pcb_crosshair.X, pcb_crosshair.Y); + + if (conf_core.editor.mode == PCB_MODE_ARROW) { + ans = pcb_search_grid_slop(pcb_crosshair.X, pcb_crosshair.Y, PCB_OBJ_LINE_POINT, &ptr1, &ptr2, &ptr3); + if (ans == PCB_OBJ_VOID) { + if ((pcb_gui != NULL) && (pcb_gui->point_cursor != NULL)) + pcb_gui->point_cursor(pcb_false); + } + else if (!PCB_FLAG_TEST(PCB_FLAG_SELECTED, (pcb_line_t *) ptr2)) { + if ((pcb_gui != NULL) && (pcb_gui->point_cursor != NULL)) + pcb_gui->point_cursor(pcb_true); + } + } + + if (conf_core.editor.mode == PCB_MODE_LINE && pcb_crosshair.AttachedLine.State != PCB_CH_STATE_FIRST && conf_core.editor.auto_drc) + pcb_line_enforce_drc(); + + pcb_gui->set_crosshair(pcb_crosshair.X, pcb_crosshair.Y, HID_SC_DO_NOTHING); +} + +/* --------------------------------------------------------------------------- + * move crosshair relative (has to be switched off) + */ +void pcb_crosshair_move_relative(pcb_coord_t DeltaX, pcb_coord_t DeltaY) +{ + pcb_crosshair_grid_fit(pcb_crosshair.X + DeltaX, pcb_crosshair.Y + DeltaY); +} + +/* --------------------------------------------------------------------------- + * move crosshair absolute + * return pcb_true if the crosshair was moved from its existing position + */ +pcb_bool pcb_crosshair_move_absolute(pcb_coord_t X, pcb_coord_t Y) +{ + pcb_coord_t x, y, z; + pcb_crosshair.ptr_x = X; + pcb_crosshair.ptr_y = Y; + x = pcb_crosshair.X; + y = pcb_crosshair.Y; + pcb_crosshair_grid_fit(X, Y); + if (pcb_crosshair.X != x || pcb_crosshair.Y != y) { + /* back up to old position to notify the GUI + * (which might want to erase the old crosshair) */ + z = pcb_crosshair.X; + pcb_crosshair.X = x; + x = z; + z = pcb_crosshair.Y; + pcb_crosshair.Y = y; + pcb_notify_crosshair_change(pcb_false); /* Our caller notifies when it has done */ + /* now move forward again */ + pcb_crosshair.X = x; + pcb_crosshair.Y = z; + return pcb_true; + } + return pcb_false; +} + +void pcb_crosshair_set_range(pcb_coord_t MinX, pcb_coord_t MinY, pcb_coord_t MaxX, pcb_coord_t MaxY) +{ + pcb_crosshair.MinX = MAX(0, MinX); + pcb_crosshair.MinY = MAX(0, MinY); + pcb_crosshair.MaxX = MIN(PCB->MaxWidth, MaxX); + pcb_crosshair.MaxY = MIN(PCB->MaxHeight, MaxY); + + /* force update of position */ + pcb_crosshair_move_relative(0, 0); +} + +/* --------------------------------------------------------------------------- + * centers the displayed PCB around the specified point (X,Y) + */ +void pcb_center_display(pcb_coord_t X, pcb_coord_t Y) +{ + pcb_coord_t save_grid = PCB->Grid; + PCB->Grid = 1; + if (pcb_crosshair_move_absolute(X, Y)) + pcb_notify_crosshair_change(pcb_true); + pcb_gui->set_crosshair(pcb_crosshair.X, pcb_crosshair.Y, HID_SC_WARP_POINTER); + PCB->Grid = save_grid; +} + +/* --------------------------------------------------------------------------- + * initializes crosshair stuff + * clears the struct, allocates to graphical contexts + */ +void pcb_crosshair_init(void) +{ + pcb_crosshair.GC = pcb_hid_make_gc(); + + pcb_gui->set_color(pcb_crosshair.GC, &conf_core.appearance.color.crosshair); + pcb_hid_set_draw_xor(pcb_crosshair.GC, 1); + pcb_hid_set_line_cap(pcb_crosshair.GC, pcb_cap_round); + pcb_hid_set_line_width(pcb_crosshair.GC, 1); + + /* set initial shape */ + pcb_crosshair.shape = pcb_ch_shape_basic; + + /* set default limits */ + pcb_crosshair.MinX = pcb_crosshair.MinY = 0; + pcb_crosshair.MaxX = PCB->MaxWidth; + pcb_crosshair.MaxY = PCB->MaxHeight; + + /* Initialize the onpoint data. */ + memset(&pcb_crosshair.onpoint_objs, 0, sizeof(vtop_t)); + memset(&pcb_crosshair.old_onpoint_objs, 0, sizeof(vtop_t)); + + /* clear the mark */ + pcb_marked.status = pcb_false; + + /* Initialise Line Route */ + pcb_route_init(&pcb_crosshair.Route); + +} + +void pcb_crosshair_uninit(void) +{ + pcb_poly_free_fields(&pcb_crosshair.AttachedPolygon); + pcb_route_destroy(&pcb_crosshair.Route); + pcb_hid_destroy_gc(pcb_crosshair.GC); +} + +void pcb_crosshair_range_to_buffer(void) +{ + if (conf_core.editor.mode == PCB_MODE_PASTE_BUFFER) { + if (pcb_set_buffer_bbox(PCB_PASTEBUFFER) == 0) { + pcb_crosshair_set_range(PCB_PASTEBUFFER->X - PCB_PASTEBUFFER->bbox_naked.X1, + PCB_PASTEBUFFER->Y - PCB_PASTEBUFFER->bbox_naked.Y1, + PCB->MaxWidth - + (PCB_PASTEBUFFER->bbox_naked.X2 - PCB_PASTEBUFFER->X), + PCB->MaxHeight - (PCB_PASTEBUFFER->bbox_naked.Y2 - PCB_PASTEBUFFER->Y)); + } + else /* failed to calculate the bounding box of the buffer, it's probably a single-object move, allow the whole page */ + pcb_crosshair_set_range(0, 0, PCB->MaxWidth, PCB->MaxHeight); + } +} + +void pcb_crosshair_set_local_ref(pcb_coord_t X, pcb_coord_t Y, pcb_bool Showing) +{ + static pcb_mark_t old; + static int count = 0; + + if (Showing) { + pcb_notify_mark_change(pcb_false); + if (count == 0) + old = pcb_marked; + pcb_marked.X = X; + pcb_marked.Y = Y; + pcb_marked.status = pcb_true; + count++; + pcb_notify_mark_change(pcb_true); + } + else if (count > 0) { + pcb_notify_mark_change(pcb_false); + count = 0; + pcb_marked = old; + pcb_notify_mark_change(pcb_true); + } +} + +void pcb_event_move_crosshair(pcb_coord_t ev_x, pcb_coord_t ev_y) +{ + if (pcb_mid_stroke) + pcb_stub_stroke_record(ev_x, ev_y); + if (pcb_crosshair_move_absolute(ev_x, ev_y)) { + /* update object position and cursor location */ + pcb_tool_adjust_attached_objects(); + pcb_event(PCB_EVENT_DRAW_CROSSHAIR_CHATT, NULL); + pcb_notify_crosshair_change(pcb_true); + } +} Index: tags/2.1.2/src/crosshair.h =================================================================== --- tags/2.1.2/src/crosshair.h (nonexistent) +++ tags/2.1.2/src/crosshair.h (revision 24813) @@ -0,0 +1,136 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +#ifndef PCB_CROSSHAIR_H +#define PCB_CROSSHAIR_H + +#include "config.h" +#include "vtonpoint.h" +#include "hid.h" +#include "obj_line.h" +#include "obj_poly.h" +#include "route.h" + +typedef struct { /* currently marked block */ + pcb_point_t Point1, Point2; /* start- and end-position */ + long int State; + pcb_bool otherway; +} pcb_attached_box_t; + +typedef struct { /* currently attached object */ + pcb_coord_t X, Y; /* saved position when PCB_MODE_MOVE */ + pcb_coord_t tx, ty; /* target position when PCB_MODE_MOVE */ + pcb_box_t BoundingBox; + long int Type; /* object type */ + long int State; + void *Ptr1, *Ptr2, *Ptr3; /* three pointers to data, see search.c */ + pcb_angle_t start_angle, delta_angle; + pcb_coord_t radius; +} pcb_attached_object_t; + +typedef struct { + pcb_bool status; + pcb_coord_t X, Y; +} pcb_mark_t; + +enum pcb_crosshair_shape_e { + pcb_ch_shape_basic = 0, /* 4-ray */ + pcb_ch_shape_union_jack, /* 8-ray */ + pcb_ch_shape_dozen, /* 12-ray */ + pcb_ch_shape_NUM +}; + +typedef struct { /* holds crosshair, cursor and crosshair-attachment information */ + pcb_hid_gc_t GC; /* GC for cursor drawing */ + pcb_hid_gc_t AttachGC; /* and for displaying buffer contents */ + pcb_coord_t ptr_x, ptr_y; /* last seen raw mouse pointer x;y coords */ + pcb_coord_t X, Y; /* (snapped) crosshair position */ + pcb_coord_t MinX, MinY, MaxX, MaxY; /* lowest and highest coordinates */ + pcb_attached_line_t AttachedLine; /* data of new lines... */ + pcb_attached_box_t AttachedBox; + pcb_poly_t AttachedPolygon; + int AttachedPolygon_pts; /* number of valid points ever seen for this poly */ + pcb_attached_object_t AttachedObject; /* data of attached objects */ + pcb_route_t Route; /* Calculated line route in LINE or MOVE(LINE) mode */ + enum pcb_crosshair_shape_e shape; /* shape of crosshair */ + vtop_t onpoint_objs; + vtop_t old_onpoint_objs; + pcb_pstk_t *snapped_pstk; + + /* list of object IDs that could have been dragged so that they can be cycled */ + long int *drags; + int drags_len, drags_current; + pcb_coord_t dragx, dragy; /* the point where drag started */ + + unsigned click_cmd_entry_active:1; /* true if the command entry was active during a mosue click while actions are executed */ +} pcb_crosshair_t; + + +/* --------------------------------------------------------------------------- + * all possible states of an attached object + */ +#define PCB_CH_STATE_FIRST 0 /* initial state */ +#define PCB_CH_STATE_SECOND 1 +#define PCB_CH_STATE_THIRD 2 + +extern pcb_crosshair_t pcb_crosshair; +extern pcb_mark_t pcb_marked; + +void pcb_notify_crosshair_change(pcb_bool changes_complete); +void pcb_notify_mark_change(pcb_bool changes_complete); +void pcb_draw_attached(pcb_bool inhibit_drawing_mode); +void pcb_draw_mark(pcb_bool inhibit_drawing_mode); +void pcb_crosshair_move_relative(pcb_coord_t, pcb_coord_t); +pcb_bool pcb_crosshair_move_absolute(pcb_coord_t, pcb_coord_t); +void pcb_crosshair_set_range(pcb_coord_t, pcb_coord_t, pcb_coord_t, pcb_coord_t); +void pcb_crosshair_init(void); +void pcb_crosshair_uninit(void); +void pcb_crosshair_grid_fit(pcb_coord_t, pcb_coord_t); +void pcb_center_display(pcb_coord_t X, pcb_coord_t Y); + +/* sets the crosshair range to the current buffer extents */ +void pcb_crosshair_range_to_buffer(void); +void pcb_crosshair_set_local_ref(pcb_coord_t X, pcb_coord_t Y, pcb_bool Showing); + + +/* Event handler to set the cursor according to the X pointer position + called from inside main.c */ +void pcb_event_move_crosshair(pcb_coord_t ev_x, pcb_coord_t ev_y); + +/*** utility for plugins ***/ +void pcb_xordraw_attached_line(pcb_coord_t, pcb_coord_t, pcb_coord_t, pcb_coord_t, pcb_coord_t); +void pcb_xordraw_poly(pcb_poly_t *polygon, pcb_coord_t dx, pcb_coord_t dy, int dash_last); +void pcb_xordraw_poly_subc(pcb_poly_t *polygon, pcb_coord_t dx, pcb_coord_t dy, pcb_coord_t w, pcb_coord_t h, int mirr); +void pcb_xordraw_attached_arc(pcb_coord_t thick); +void pcb_xordraw_buffer(pcb_buffer_t *Buffer); +void pcb_xordraw_movecopy(void); +void pcb_xordraw_insert_pt_obj(void); + + + +#endif Index: tags/2.1.2/src/data.c =================================================================== --- tags/2.1.2/src/data.c (nonexistent) +++ tags/2.1.2/src/data.c (revision 24813) @@ -0,0 +1,924 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +/* just defines common identifiers + */ +#include "config.h" + +#include + +#include "board.h" +#include "data.h" +#include "data_list.h" +#include "data_it.h" +#include "rtree.h" +#include "list_common.h" +#include "compat_misc.h" +#include "layer_it.h" +#include "operation.h" +#include "flag.h" +#include "obj_arc.h" +#include "obj_line.h" +#include "obj_poly.h" +#include "obj_text.h" +#include "obj_pstk.h" +#include "obj_subc.h" + +int pcb_layer_stack[PCB_MAX_LAYER]; /* determines the layer draw order */ + +pcb_buffer_t pcb_buffers[PCB_MAX_BUFFER]; /* my buffers */ +pcb_bool pcb_bumped; /* if the undo serial number has changed */ + +int pcb_added_lines; + +static void pcb_loop_layer(pcb_board_t *pcb, pcb_layer_t *layer, void *ctx, pcb_layer_cb_t lacb, pcb_line_cb_t lcb, pcb_arc_cb_t acb, pcb_text_cb_t tcb, pcb_poly_cb_t pocb) +{ + if (lacb != NULL) + if (lacb(ctx, pcb, layer, 1)) + return; + + if (lcb != NULL) { + PCB_LINE_LOOP(layer); + { + lcb(ctx, pcb, layer, line); + } + PCB_END_LOOP; + } + + if (acb != NULL) { + PCB_ARC_LOOP(layer); + { + acb(ctx, pcb, layer, arc); + } + PCB_END_LOOP; + } + + if (tcb != NULL) { + PCB_TEXT_LOOP(layer); + { + tcb(ctx, pcb, layer, text); + } + PCB_END_LOOP; + } + + if (pocb != NULL) { + PCB_POLY_LOOP(layer); + { + pocb(ctx, pcb, layer, polygon); + } + PCB_END_LOOP; + } + if (lacb != NULL) + lacb(ctx, pcb, layer, 0); +} + +/* callback based loops */ +void pcb_loop_layers(pcb_board_t *pcb, void *ctx, pcb_layer_cb_t lacb, pcb_line_cb_t lcb, pcb_arc_cb_t acb, pcb_text_cb_t tcb, pcb_poly_cb_t pocb) +{ + if ((lacb != NULL) || (lcb != NULL) || (acb != NULL) || (tcb != NULL) || (pocb != NULL)) { + if (pcb->is_footprint) { + int n; + pcb_data_t *data = PCB_REAL_DATA(pcb); + for(n = 0; n < data->LayerN; n++) + pcb_loop_layer(pcb, &data->Layer[n], ctx, lacb, lcb, acb, tcb, pocb); + } + else { + pcb_layer_it_t it; + pcb_layer_id_t lid; + for(lid = pcb_layer_first_all(&pcb->LayerGroups, &it); lid != -1; lid = pcb_layer_next(&it)) { + pcb_layer_t *layer = pcb->Data->Layer + lid; + pcb_loop_layer(pcb, layer, ctx, lacb, lcb, acb, tcb, pocb); + } + } + } +} + +void pcb_loop_subc(pcb_board_t *pcb, void *ctx, pcb_subc_cb_t scb) +{ + if (scb != NULL) { + PCB_SUBC_LOOP(PCB_REAL_DATA(pcb)); + { + scb(ctx, pcb, subc, 1); + } + PCB_END_LOOP; + } +} + +void pcb_loop_pstk(pcb_board_t *pcb, void *ctx, pcb_pstk_cb_t pscb) +{ + if (pscb != NULL) { + PCB_PADSTACK_LOOP(PCB_REAL_DATA(pcb)); + { + pscb(ctx, pcb, padstack); + } + PCB_END_LOOP; + } +} + +void pcb_loop_all(pcb_board_t *pcb, void *ctx, + pcb_layer_cb_t lacb, pcb_line_cb_t lcb, pcb_arc_cb_t acb, pcb_text_cb_t tcb, pcb_poly_cb_t pocb, + pcb_subc_cb_t scb, + pcb_pstk_cb_t pscb + ) +{ + pcb_loop_layers(pcb, ctx, lacb, lcb, acb, tcb, pocb); + pcb_loop_subc(pcb, ctx, scb); + pcb_loop_pstk(pcb, ctx, pscb); +} + +void pcb_data_uninit(pcb_data_t *data) +{ + pcb_layer_t *layer; + int i, subc; + + subc = (data->parent_type == PCB_PARENT_SUBC); + + PCB_SUBC_LOOP(data); + { + pcb_subc_free(subc); + } + PCB_END_LOOP; + + list_map0(&data->Rat, pcb_rat_t, pcb_rat_free); + + for (layer = data->Layer, i = 0; i < data->LayerN; layer++, i++) + pcb_layer_free_fields(layer); + + if (!subc) { + if (data->subc_tree) + pcb_r_destroy_tree(&data->subc_tree); + if (data->padstack_tree) + pcb_r_destroy_tree(&data->padstack_tree); + if (data->rat_tree) + pcb_r_destroy_tree(&data->rat_tree); + } + + for (layer = data->Layer, i = 0; i < PCB_MAX_LAYER; layer++, i++) + free((char *)layer->name); + + htip_uninit(&data->id2obj); + + memset(data, 0, sizeof(pcb_data_t)); +} + +void pcb_data_free(pcb_data_t *data) +{ + if (data == NULL) + return; + + pcb_data_uninit(data); + free(data); +} + +pcb_bool pcb_data_is_empty(pcb_data_t *Data) +{ + pcb_cardinal_t i; + + if (padstacklist_length(&Data->padstack) != 0) return pcb_false; + if (pcb_subclist_length(&Data->subc) != 0) return pcb_false; + for (i = 0; i < Data->LayerN; i++) + if (!pcb_layer_is_pure_empty(&(Data->Layer[i]))) + return pcb_false; + + return pcb_true; +} + +pcb_box_t *pcb_data_bbox(pcb_box_t *out, pcb_data_t *Data, pcb_bool ignore_floaters) +{ + /* preset identifiers with highest and lowest possible values */ + out->X1 = out->Y1 = PCB_MAX_COORD; + out->X2 = out->Y2 = -PCB_MAX_COORD; + + /* now scan for the lowest/highest X and Y coordinate */ + PCB_PADSTACK_LOOP(Data); + { + pcb_pstk_bbox(padstack); + if (!ignore_floaters || !PCB_FLAG_TEST(PCB_FLAG_FLOATER, padstack)) + pcb_box_bump_box(out, &padstack->BoundingBox); + } + PCB_END_LOOP; + PCB_SUBC_LOOP(Data); + { + pcb_subc_bbox(subc); + if (!ignore_floaters || !PCB_FLAG_TEST(PCB_FLAG_FLOATER, subc)) + pcb_box_bump_box(out, &subc->BoundingBox); + } + PCB_END_LOOP; + PCB_LINE_ALL_LOOP(Data); + { + pcb_line_bbox(line); + if (!ignore_floaters || !PCB_FLAG_TEST(PCB_FLAG_FLOATER, line)) + pcb_box_bump_box(out, &line->BoundingBox); + } + PCB_ENDALL_LOOP; + PCB_ARC_ALL_LOOP(Data); + { + pcb_arc_bbox(arc); + if (!ignore_floaters || !PCB_FLAG_TEST(PCB_FLAG_FLOATER, arc)) + pcb_box_bump_box(out, &arc->BoundingBox); + } + PCB_ENDALL_LOOP; + PCB_TEXT_ALL_LOOP(Data); + { + pcb_text_bbox(pcb_font(PCB, text->fid, 1), text); + if (!ignore_floaters || !PCB_FLAG_TEST(PCB_FLAG_FLOATER, text)) + pcb_box_bump_box(out, &text->BoundingBox); + } + PCB_ENDALL_LOOP; + PCB_POLY_ALL_LOOP(Data); + { + pcb_poly_bbox(polygon); + if (!ignore_floaters || !PCB_FLAG_TEST(PCB_FLAG_FLOATER, polygon)) + pcb_box_bump_box(out, &polygon->BoundingBox); + } + PCB_ENDALL_LOOP; + return (pcb_data_is_empty(Data) ? NULL : out); +} + +pcb_box_t *pcb_data_bbox_naked(pcb_box_t *out, pcb_data_t *Data, pcb_bool ignore_floaters) +{ + /* preset identifiers with highest and lowest possible values */ + out->X1 = out->Y1 = PCB_MAX_COORD; + out->X2 = out->Y2 = -PCB_MAX_COORD; + + /* now scan for the lowest/highest X and Y coordinate */ + PCB_PADSTACK_LOOP(Data); + { + pcb_pstk_bbox(padstack); + if (!ignore_floaters || !PCB_FLAG_TEST(PCB_FLAG_FLOATER, padstack)) + pcb_box_bump_box(out, &padstack->bbox_naked); + } + PCB_END_LOOP; + PCB_SUBC_LOOP(Data); + { + pcb_subc_bbox(subc); + if (!ignore_floaters || !PCB_FLAG_TEST(PCB_FLAG_FLOATER, subc)) + pcb_box_bump_box(out, &subc->bbox_naked); + } + PCB_END_LOOP; + PCB_LINE_ALL_LOOP(Data); + { + pcb_line_bbox(line); + if (!ignore_floaters || !PCB_FLAG_TEST(PCB_FLAG_FLOATER, line)) + pcb_box_bump_box(out, &line->bbox_naked); + } + PCB_ENDALL_LOOP; + PCB_ARC_ALL_LOOP(Data); + { + pcb_arc_bbox(arc); + if (!ignore_floaters || !PCB_FLAG_TEST(PCB_FLAG_FLOATER, arc)) + pcb_box_bump_box(out, &arc->bbox_naked); + } + PCB_ENDALL_LOOP; + PCB_TEXT_ALL_LOOP(Data); + { + pcb_text_bbox(pcb_font(PCB, text->fid, 1), text); + if (!ignore_floaters || !PCB_FLAG_TEST(PCB_FLAG_FLOATER, text)) + pcb_box_bump_box(out, &text->bbox_naked); + } + PCB_ENDALL_LOOP; + PCB_POLY_ALL_LOOP(Data); + { + pcb_poly_bbox(polygon); + if (!ignore_floaters || !PCB_FLAG_TEST(PCB_FLAG_FLOATER, polygon)) + pcb_box_bump_box(out, &polygon->bbox_naked); + } + PCB_ENDALL_LOOP; + return (pcb_data_is_empty(Data) ? NULL : out); +} + +void pcb_data_set_layer_parents(pcb_data_t *data) +{ + pcb_layer_id_t n; + for(n = 0; n < PCB_MAX_LAYER; n++) { + data->Layer[n].parent.data = data; + data->Layer[n].parent_type = PCB_PARENT_DATA; + } +} + +void pcb_data_bind_board_layers(pcb_board_t *pcb, pcb_data_t *data, int share_rtrees) +{ + pcb_layer_id_t n; + for(n = 0; n < pcb->Data->LayerN; n++) { + pcb_layer_real2bound(&data->Layer[n], &pcb->Data->Layer[n], share_rtrees); + data->Layer[n].parent.data = data; + data->Layer[n].parent_type = PCB_PARENT_DATA; + data->Layer[n].type = PCB_OBJ_LAYER; + } + data->LayerN = pcb->Data->LayerN; +} + +void pcb_data_make_layers_bound(pcb_board_t *pcb4layer_groups, pcb_data_t *data) +{ + pcb_layer_id_t n; + for(n = 0; n < data->LayerN; n++) { + pcb_layer_type_t lyt = pcb_layergrp_flags(pcb4layer_groups, data->Layer[n].meta.real.grp); + memset(&data->Layer[n].meta.bound, 0, sizeof(data->Layer[n].meta.bound)); + pcb_layer_real2bound_offs(&data->Layer[n], pcb4layer_groups, &data->Layer[n]); + data->Layer[n].parent.data = data; + data->Layer[n].parent_type = PCB_PARENT_DATA; + data->Layer[n].type = PCB_OBJ_LAYER; + data->Layer[n].meta.bound.type = lyt; + } +} + +void pcb_data_unbind_layers(pcb_data_t *data) +{ + pcb_layer_id_t n; + for(n = 0; n < data->LayerN; n++) + data->Layer[n].meta.bound.real = NULL; +} + +void pcb_data_binding_update(pcb_board_t *pcb, pcb_data_t *data) +{ + int i; + for(i = 0; i < data->LayerN; i++) { + pcb_layer_t *sourcelayer = &data->Layer[i]; + pcb_layer_t *destlayer = pcb_layer_resolve_binding(pcb, sourcelayer); + sourcelayer->meta.bound.real = destlayer; + } +} + +void pcb_data_init(pcb_data_t *data) +{ + memset(data, 0, sizeof(pcb_data_t)); + htip_init(&data->id2obj, longhash, longkeyeq); +} + +pcb_data_t *pcb_data_new(pcb_board_t *parent) +{ + pcb_data_t *data; + data = malloc(sizeof(pcb_data_t)); + pcb_data_init(data); + if (parent != NULL) + PCB_SET_PARENT(data, board, parent); + pcb_data_set_layer_parents(data); + return data; +} + +pcb_board_t *pcb_data_get_top(pcb_data_t *data) +{ + while((data != NULL) && (data->parent_type == PCB_PARENT_SUBC)) + data = data->parent.subc->parent.data; + + if (data == NULL) + return NULL; + + if (data->parent_type == PCB_PARENT_BOARD) + return data->parent.board; + + return NULL; +} + +void pcb_data_mirror(pcb_data_t *data, pcb_coord_t y_offs, pcb_data_mirror_text_t mtxt, pcb_bool pstk_smirror) +{ + PCB_PADSTACK_LOOP(data); + { + pcb_pstk_mirror(padstack, y_offs, pstk_smirror, 0); + } + PCB_END_LOOP; + PCB_SUBC_LOOP(data); + { + pcb_subc_mirror(data, subc, y_offs, pstk_smirror); + } + PCB_END_LOOP; + PCB_LINE_ALL_LOOP(data); + { + pcb_line_mirror(layer, line, y_offs); + } + PCB_ENDALL_LOOP; + PCB_ARC_ALL_LOOP(data); + { + pcb_arc_mirror(layer, arc, y_offs); + } + PCB_ENDALL_LOOP; + PCB_POLY_ALL_LOOP(data); + { + pcb_poly_mirror(layer, polygon, y_offs); + } + PCB_ENDALL_LOOP; + + switch(mtxt) { + case PCB_TXM_NONE: + break; + case PCB_TXM_SIDE: + PCB_TEXT_ALL_LOOP(data); + { + pcb_text_flip_side(layer, text, y_offs); + } + PCB_ENDALL_LOOP; + break; + case PCB_TXM_COORD: + PCB_TEXT_ALL_LOOP(data); + { + pcb_text_mirror_coords(layer, text, y_offs); + } + PCB_ENDALL_LOOP; + break; + } +} + +void pcb_data_scale(pcb_data_t *data, double sx, double sy, double sth, int recurse) +{ + if ((sx == 1.0) && (sy == 1.0) && (sth == 1.0)) + return; + + PCB_PADSTACK_LOOP(data); + { + pcb_pstk_scale(padstack, sx, sy); + } + PCB_END_LOOP; + if (recurse) { + PCB_SUBC_LOOP(data); + { + pcb_subc_scale(data, subc, sx, sy, sth, 1); + } + PCB_END_LOOP; + } + else { + /* when not scaled recursively, position still needs to be scaled */ + PCB_SUBC_LOOP(data); + { + pcb_coord_t ox, oy, nx, ny; + if (pcb_subc_get_origin(subc, &ox, &oy) == 0) { + nx = pcb_round((double)ox * sx); + ny = pcb_round((double)oy * sy); + pcb_subc_move(subc, nx - ox, ny - oy, pcb_true); + } + } + PCB_END_LOOP; + } + PCB_LINE_ALL_LOOP(data); + { + pcb_line_scale(line, sx, sy, sth); + } + PCB_ENDALL_LOOP; + PCB_ARC_ALL_LOOP(data); + { + pcb_arc_scale(arc, sx, sy, sth); + } + PCB_ENDALL_LOOP; + PCB_POLY_ALL_LOOP(data); + { + pcb_poly_scale(polygon, sx, sy); + } + PCB_ENDALL_LOOP; + PCB_TEXT_ALL_LOOP(data); + { + pcb_text_scale(text, sx, sy, sth); + } + PCB_ENDALL_LOOP; +} + + +int pcb_data_normalize_(pcb_data_t *data, pcb_box_t *data_bbox) +{ + pcb_box_t tmp; + pcb_coord_t dx = 0, dy = 0; + + if (data_bbox == NULL) { + data_bbox = &tmp; + if (pcb_data_bbox(data_bbox, data, pcb_false) == NULL) + return -1; + } + + if (data_bbox->X1 < 0) + dx = -data_bbox->X1; + if (data_bbox->Y1 < 0) + dy = -data_bbox->Y1; + + if ((dx > 0) || (dy > 0)) { + pcb_data_move(data, dx, dy); + return 1; + } + + return 0; +} + +int pcb_data_normalize(pcb_data_t *data) +{ + return pcb_data_normalize_(data, NULL); +} + +void pcb_data_set_parent_globals(pcb_data_t *data, pcb_data_t *new_parent) +{ + pcb_pstk_t *ps; + pcb_subc_t *sc; + gdl_iterator_t it; + + padstacklist_foreach(&data->padstack, &it, ps) { + ps->parent_type = PCB_PARENT_DATA; + ps->parent.data = new_parent; + } + subclist_foreach(&data->subc, &it, sc) { + sc->parent_type = PCB_PARENT_DATA; + sc->parent.data = new_parent; + } +} + + +extern pcb_opfunc_t MoveFunctions; +void pcb_data_move(pcb_data_t *data, pcb_coord_t dx, pcb_coord_t dy) +{ + pcb_opctx_t ctx; + + ctx.move.pcb = pcb_data_get_top(data); + ctx.move.dx = dx; + ctx.move.dy = dy; + + PCB_PADSTACK_LOOP(data); + { + pcb_object_operation(&MoveFunctions, &ctx, PCB_OBJ_PSTK, padstack, padstack, padstack); + } + PCB_END_LOOP; + PCB_SUBC_LOOP(data); + { + pcb_object_operation(&MoveFunctions, &ctx, PCB_OBJ_SUBC, subc, subc, subc); + } + PCB_END_LOOP; + PCB_LINE_ALL_LOOP(data); + { + pcb_object_operation(&MoveFunctions, &ctx, PCB_OBJ_LINE, layer, line, line); + } + PCB_ENDALL_LOOP; + PCB_ARC_ALL_LOOP(data); + { + pcb_object_operation(&MoveFunctions, &ctx, PCB_OBJ_ARC, layer, arc, arc); + } + PCB_ENDALL_LOOP; + PCB_TEXT_ALL_LOOP(data); + { + pcb_object_operation(&MoveFunctions, &ctx, PCB_OBJ_TEXT, layer, text, text); + } + PCB_ENDALL_LOOP; + PCB_POLY_ALL_LOOP(data); + { + pcb_object_operation(&MoveFunctions, &ctx, PCB_OBJ_POLY, layer, polygon, polygon); + } + PCB_ENDALL_LOOP; +} + +void pcb_data_list_by_flag(pcb_data_t *data, vtp0_t *dst, pcb_objtype_t type, unsigned long mask) +{ + if (type & PCB_OBJ_PSTK) PCB_PADSTACK_LOOP(data); { + if ((mask == 0) || (PCB_FLAG_TEST(mask, padstack))) vtp0_append(dst, padstack); + } PCB_END_LOOP; + if (type & PCB_OBJ_SUBC) PCB_SUBC_LOOP(data); { + if ((mask == 0) || (PCB_FLAG_TEST(mask, subc))) vtp0_append(dst, subc); + } PCB_END_LOOP; + if (type & PCB_OBJ_LINE) PCB_LINE_ALL_LOOP(data); { + if ((mask == 0) || (PCB_FLAG_TEST(mask, line))) vtp0_append(dst, line); + } PCB_ENDALL_LOOP; + if (type & PCB_OBJ_ARC) PCB_ARC_ALL_LOOP(data); { + if ((mask == 0) || (PCB_FLAG_TEST(mask, arc))) vtp0_append(dst, arc); + } PCB_ENDALL_LOOP; + if (type & PCB_OBJ_TEXT) PCB_TEXT_ALL_LOOP(data); { + if ((mask == 0) || (PCB_FLAG_TEST(mask, text))) vtp0_append(dst, text); + } PCB_ENDALL_LOOP; + if (type & PCB_OBJ_POLY) PCB_POLY_ALL_LOOP(data); { + if ((mask == 0) || (PCB_FLAG_TEST(mask, polygon))) vtp0_append(dst, polygon); + } PCB_ENDALL_LOOP; +} + +void pcb_data_list_terms(pcb_data_t *data, vtp0_t *dst, pcb_objtype_t type) +{ +TODO("subc TODO: subc in subc") +/* if (type & PCB_OBJ_SUBC) PCB_SUBC_LOOP(data); { + if (subc->term != NULL) vtp0_append(dst, subc); + } PCB_END_LOOP;*/ + if (type & PCB_OBJ_LINE) PCB_LINE_ALL_LOOP(data); { + if ((line->term != NULL)) vtp0_append(dst, line); + } PCB_ENDALL_LOOP; + if (type & PCB_OBJ_ARC) PCB_ARC_ALL_LOOP(data); { + if (arc->term != NULL) vtp0_append(dst, arc); + } PCB_ENDALL_LOOP; + if (type & PCB_OBJ_TEXT) PCB_TEXT_ALL_LOOP(data); { + if (text->term != NULL) vtp0_append(dst, text); + } PCB_ENDALL_LOOP; + if (type & PCB_OBJ_POLY) PCB_POLY_ALL_LOOP(data); { + if (polygon->term != NULL) vtp0_append(dst, polygon); + } PCB_ENDALL_LOOP; +} + +void pcb_data_clip_polys(pcb_data_t *data) +{ + PCB_POLY_ALL_LOOP(data); + { + pcb_poly_init_clip(data, layer, polygon); + } + PCB_ENDALL_LOOP; +} + +#define rsearch(tree) \ + do { \ + pcb_r_dir_t tmp = pcb_r_search(tree, starting_region, region_in_search, rectangle_in_region, closure, num_found); \ + if (tmp == PCB_R_DIR_CANCEL) return tmp; \ + res |= tmp; \ + } while(0); + +pcb_r_dir_t pcb_data_r_search(pcb_data_t *data, pcb_objtype_t types, const pcb_box_t *starting_region, + pcb_r_dir_t (*region_in_search) (const pcb_box_t *region, void *cl), + pcb_r_dir_t (*rectangle_in_region) (const pcb_box_t *box, void *cl), + void *closure, int *num_found, pcb_bool vis_only) +{ + pcb_layer_id_t lid; + pcb_r_dir_t res = 0; + + if (!vis_only || PCB->RatOn) + if (types & PCB_OBJ_RAT) rsearch(data->rat_tree); + + if (!vis_only || PCB->pstk_on || PCB->hole_on) + if (types & PCB_OBJ_PSTK) rsearch(data->padstack_tree); + + if (!vis_only || PCB->SubcOn) + if (types & PCB_OBJ_SUBC) rsearch(data->subc_tree); + + for(lid = 0; lid < data->LayerN; lid++) { + pcb_layer_t *ly = data->Layer + lid; + + if (vis_only && (!ly->meta.real.vis)) + continue; + + if (types & PCB_OBJ_LINE) rsearch(ly->line_tree); + if (types & PCB_OBJ_TEXT) rsearch(ly->text_tree); + if (types & PCB_OBJ_POLY) rsearch(ly->polygon_tree); + if (types & PCB_OBJ_ARC) rsearch(ly->arc_tree); + } + + return res; +} + +/*** poly clip inhibit mechanism ***/ +void pcb_data_clip_inhibit_inc(pcb_data_t *data) +{ + int old = data->clip_inhibit; + data->clip_inhibit++; + + if (old > data->clip_inhibit) { + pcb_message(PCB_MSG_ERROR, "Internal error: overflow on poly clip inhibit\n"); + abort(); + } +} + +void pcb_data_clip_inhibit_dec(pcb_data_t *data, pcb_bool enable_progbar) +{ + if (data->clip_inhibit == 0) { + pcb_message(PCB_MSG_ERROR, "Internal error: overflow on poly clip inhibit\n"); + assert(!"clip_inhibit underflow"); + return; + } + data->clip_inhibit--; + + if (data->clip_inhibit == 0) + pcb_data_clip_dirty(data, enable_progbar); +} + +typedef struct { + pcb_data_t *data; + time_t nextt; + int inited, force_all; + pcb_cardinal_t at, total; +} data_clip_all_t; + +static void data_clip_all_cb(void *ctx_) +{ + data_clip_all_t *ctx = ctx_; + + ctx->at++; + if ((ctx->at % 8) == 0) { + time_t now = time(NULL); + if (now >= ctx->nextt) { + ctx->nextt = now+1; + if (!ctx->inited) { + ctx->total = 0; + PCB_POLY_ALL_LOOP(ctx->data); { + if (ctx->force_all || polygon->clip_dirty) + ctx->total += pcb_poly_num_clears(ctx->data, layer, polygon); + } PCB_ENDALL_LOOP; + ctx->inited = 1; + } + if (pcb_hid_progress(ctx->at, ctx->total, "Clipping polygons...") != 0) { + int rv = pcb_hid_message_box("warning", "Stop poly clipping", "The only way to cancel poly clipping is to quit pcb-rnd.\nAre you sure you want to quit?", "yes, quit pcb-rnd", 1, "no, continue clipping", 2, NULL); + if (rv == 1) { + exit(1); + } + else { + /* Have to recreate the dialog next time, that's the only way to get it out from the cancel state */ + pcb_hid_progress(0, 0, NULL); + } + } + } + } +} + +void pcb_data_clip_all_poly(pcb_data_t *data, pcb_bool enable_progbar, pcb_bool force_all) +{ + data_clip_all_t ctx; + + if (data->clip_inhibit != 0) + return; + + PCB_SUBC_LOOP(data); { + pcb_data_clip_dirty(subc->data, enable_progbar); + } PCB_END_LOOP; + + ctx.data = data; + ctx.force_all = force_all; + ctx.nextt = time(NULL) + 2; + ctx.total = ctx.at = 0; + ctx.inited = 0; + + /* have to go in two passes, to make sure that clearing polygons are done + before the polygons that are potentially being cleared - this way we + guarantee that by the time the poly-vs-poly clearance needs to be + calculated, the clearing poly has a contour */ + PCB_POLY_ALL_LOOP(data); { + if ((force_all || polygon->clip_dirty) && (PCB_FLAG_TEST(PCB_FLAG_CLEARPOLYPOLY, polygon))) + pcb_poly_init_clip_prog(data, layer, polygon, (enable_progbar ? data_clip_all_cb : NULL), &ctx); + } PCB_ENDALL_LOOP; + + PCB_POLY_ALL_LOOP(data); { + if ((force_all || polygon->clip_dirty) && (!PCB_FLAG_TEST(PCB_FLAG_CLEARPOLYPOLY, polygon))) + pcb_poly_init_clip_prog(data, layer, polygon, (enable_progbar ? data_clip_all_cb : NULL), &ctx); + } PCB_ENDALL_LOOP; + + if (enable_progbar) + pcb_hid_progress(0, 0, NULL); +} + +void pcb_data_clip_dirty(pcb_data_t *data, pcb_bool enable_progbar) +{ + pcb_data_clip_all_poly(data, enable_progbar, pcb_false); +} + +void pcb_data_clip_all(pcb_data_t *data, pcb_bool enable_progbar) +{ + pcb_data_clip_all_poly(data, enable_progbar, pcb_true); +} + + +void pcb_data_flag_change(pcb_data_t *data, pcb_objtype_t mask, int how, unsigned long flags) +{ + pcb_any_obj_t *o; + pcb_data_it_t it; + + for(o = pcb_data_first(&it, data, mask); o != NULL; o = pcb_data_next(&it)) { + PCB_FLAG_CHANGE(how, flags, o); + if (o->type == PCB_OBJ_SUBC) + pcb_data_flag_change(((pcb_subc_t *)o)->data, mask, how, flags); + } +} + +#include "obj_pstk_draw.h" +#include "obj_text_draw.h" +#include "obj_poly_draw.h" +#include "obj_arc_draw.h" +#include "obj_line_draw.h" +#include "conf_core.h" +#include "undo.h" + +/* Check if object n has flag set and if so, clear it and do all administration */ +#define CHK_CLEAR(n) \ +do { \ + if (PCB_FLAG_TEST(flag, (pcb_any_obj_t *)n)) { \ + if (undoable) \ + pcb_undo_add_obj_to_flag((pcb_any_obj_t *)n); \ + PCB_FLAG_CLEAR(flag, (pcb_any_obj_t *)n); \ + if (redraw) \ + pcb_pstk_invalidate_draw((pcb_pstk_t *)n); \ + cnt++; \ + } \ +} while(0) + +unsigned long pcb_data_clear_obj_flag(pcb_data_t *data, pcb_objtype_t tmask, unsigned long flag, int redraw, int undoable) +{ + pcb_rtree_it_t it; + pcb_box_t *n; + int li; + pcb_layer_t *l; + unsigned long cnt = 0; + + if (flag & PCB_FLAG_WARN) + conf_core.temp.rat_warn = pcb_false; + + if (tmask & PCB_OBJ_PSTK) { + for(n = pcb_r_first(data->padstack_tree, &it); n != NULL; n = pcb_r_next(&it)) + CHK_CLEAR(n); + pcb_r_end(&it); + } + + if (tmask & PCB_OBJ_RAT) { + for(n = pcb_r_first(data->rat_tree, &it); n != NULL; n = pcb_r_next(&it)) + CHK_CLEAR(n); + pcb_r_end(&it); + } + + if (tmask & PCB_OBJ_SUBC) { + for(n = pcb_r_first(data->subc_tree, &it); n != NULL; n = pcb_r_next(&it)) + CHK_CLEAR(n); + pcb_r_end(&it); + } + + if ((tmask & (PCB_OBJ_LINE | PCB_OBJ_ARC | PCB_OBJ_POLY | PCB_OBJ_TEXT)) == 0) + return cnt; /* do not run the layer loop if no layer object is requested */ + + for(li = 0, l = data->Layer; li < data->LayerN; li++,l++) { + if (tmask & PCB_OBJ_LINE) { + for(n = pcb_r_first(l->line_tree, &it); n != NULL; n = pcb_r_next(&it)) + CHK_CLEAR(n); + pcb_r_end(&it); + } + + if (tmask & PCB_OBJ_ARC) { + for(n = pcb_r_first(l->arc_tree, &it); n != NULL; n = pcb_r_next(&it)) + CHK_CLEAR(n); + pcb_r_end(&it); + } + + if (tmask & PCB_OBJ_POLY) { + for(n = pcb_r_first(l->polygon_tree, &it); n != NULL; n = pcb_r_next(&it)) + CHK_CLEAR(n); + pcb_r_end(&it); + } + + if (tmask & PCB_OBJ_TEXT) { + for(n = pcb_r_first(l->text_tree, &it); n != NULL; n = pcb_r_next(&it)) + CHK_CLEAR(n); + pcb_r_end(&it); + } + } + return cnt; +} +#undef CHK_CLEAR + +unsigned long pcb_data_clear_flag(pcb_data_t *data, unsigned long flag, int redraw, int undoable) +{ + return pcb_data_clear_obj_flag(data, PCB_OBJ_CLASS_REAL, flag, redraw, undoable); +} + + +void pcb_data_dynflag_clear(pcb_data_t *data, pcb_dynf_t dynf) +{ + pcb_rtree_it_t it; + pcb_box_t *n; + int li; + pcb_layer_t *l; + + for(n = pcb_r_first(data->padstack_tree, &it); n != NULL; n = pcb_r_next(&it)) + PCB_DFLAG_CLR(&((pcb_any_obj_t *)n)->Flags, dynf); + pcb_r_end(&it); + + for(n = pcb_r_first(data->subc_tree, &it); n != NULL; n = pcb_r_next(&it)) { + PCB_DFLAG_CLR(&((pcb_any_obj_t *)n)->Flags, dynf); + pcb_data_dynflag_clear(((pcb_subc_t *)n)->data, dynf); + } + pcb_r_end(&it); + + for(n = pcb_r_first(data->rat_tree, &it); n != NULL; n = pcb_r_next(&it)) + PCB_DFLAG_CLR(&((pcb_any_obj_t *)n)->Flags, dynf); + pcb_r_end(&it); + + for(li = 0, l = data->Layer; li < data->LayerN; li++,l++) { + for(n = pcb_r_first(l->line_tree, &it); n != NULL; n = pcb_r_next(&it)) + PCB_DFLAG_CLR(&((pcb_any_obj_t *)n)->Flags, dynf); + pcb_r_end(&it); + + for(n = pcb_r_first(l->arc_tree, &it); n != NULL; n = pcb_r_next(&it)) + PCB_DFLAG_CLR(&((pcb_any_obj_t *)n)->Flags, dynf); + pcb_r_end(&it); + + for(n = pcb_r_first(l->polygon_tree, &it); n != NULL; n = pcb_r_next(&it)) + PCB_DFLAG_CLR(&((pcb_any_obj_t *)n)->Flags, dynf); + pcb_r_end(&it); + + for(n = pcb_r_first(l->text_tree, &it); n != NULL; n = pcb_r_next(&it)) + PCB_DFLAG_CLR(&((pcb_any_obj_t *)n)->Flags, dynf); + pcb_r_end(&it); + } +} + Index: tags/2.1.2/src/data.h =================================================================== --- tags/2.1.2/src/data.h (nonexistent) +++ tags/2.1.2/src/data.h (revision 24813) @@ -0,0 +1,229 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +/* common identifiers */ + +#ifndef PCB_DATA_H +#define PCB_DATA_H + +#include "globalconst.h" +#include "global_typedefs.h" +#include "layer.h" +#include "crosshair.h" +#include "buffer.h" +#include "data_parent.h" +#include "obj_rat_list.h" +#include "obj_subc_list.h" +#include "obj_pstk_list.h" +#include "vtpadstack.h" +#include + +/* Generic container object that can hold subcircuits with layer-global + objects (e.g. vias and rats) and layer-locals (lines, arcs) */ +struct pcb_data_s { + htip_t id2obj; /* long object ID -> (pcb_any_obj_t *) */ + int LayerN; /* number of layers in this board */ + + pcb_vtpadstack_proto_t ps_protos; + + padstacklist_t padstack; + pcb_subclist_t subc; +/**/ + pcb_rtree_t *padstack_tree, *subc_tree, *rat_tree; + pcb_layer_t Layer[PCB_MAX_LAYER]; /* layer TODO: make this dynamic */ + pcb_plug_io_t *loader; + ratlist_t Rat; + +/**/ + pcb_parenttype_t parent_type; + pcb_parent_t parent; + +/* poly clip inhibit */ + int clip_inhibit; /* counter: >0 means we are in inhibit mode */ +}; + +#define pcb_max_group(pcb) ((pcb)->LayerGroups.len) + +/* DO NOT USE this macro, it is not PCB-safe */ +#define pcb_max_layer (PCB->Data->LayerN) + + + +extern pcb_buffer_t pcb_buffers[PCB_MAX_BUFFER]; +extern int pcb_added_lines; +extern int pcb_layer_stack[PCB_MAX_LAYER]; + +extern pcb_bool pcb_bumped; + +/****** callback based loops *****/ + +/* The functions returning int are called once when processing of a new layer + or element starts, with enter=1. If they return non-zero, the current layer + or element is skipped. If it is not skipped, the function is called once + at the end of processing the given layer or element, with enter=0 (and + return value ignored). + + Any of the callbacks for any loop function can be NULL. + */ + +/* layer object callbacks */ +typedef int (*pcb_layer_cb_t)(void *ctx, pcb_board_t *pcb, pcb_layer_t *layer, int enter); +typedef void (*pcb_line_cb_t)(void *ctx, pcb_board_t *pcb, pcb_layer_t *layer, pcb_line_t *line); +typedef void (*pcb_arc_cb_t)(void *ctx, pcb_board_t *pcb, pcb_layer_t *layer, pcb_arc_t *arc); +typedef void (*pcb_text_cb_t)(void *ctx, pcb_board_t *pcb, pcb_layer_t *layer, pcb_text_t *text); +typedef void (*pcb_poly_cb_t)(void *ctx, pcb_board_t *pcb, pcb_layer_t *layer, pcb_poly_t *poly); + +/* subc callbacks */ +typedef int (*pcb_subc_cb_t)(void *ctx, pcb_board_t *pcb, pcb_subc_t *subc, int enter); + +/* via and padstack callbacks */ +typedef void (*pcb_pstk_cb_t)(void *ctx, pcb_board_t *pcb, pcb_pstk_t *ps); + +/* Loop over all layer objects on each layer. Layer is the outer loop. */ +void pcb_loop_layers(pcb_board_t *pcb, void *ctx, pcb_layer_cb_t lacb, pcb_line_cb_t lcb, pcb_arc_cb_t acb, pcb_text_cb_t tcb, pcb_poly_cb_t pocb); + +/* Loop over all subcircuits. */ +void pcb_loop_subc(pcb_board_t *pcb, void *ctx, pcb_subc_cb_t scb); + +/* Loop over all design objects. (So all the above three in one call.) */ +void pcb_loop_all(pcb_board_t *pcb, void *ctx, + pcb_layer_cb_t lacb, pcb_line_cb_t lcb, pcb_arc_cb_t acb, pcb_text_cb_t tcb, pcb_poly_cb_t pocb, + pcb_subc_cb_t scb, + pcb_pstk_cb_t pscb +); + +/* Initialize the fields of data */ +void pcb_data_init(pcb_data_t *data); + +/* Allocate new data and initialize all fields */ +pcb_data_t *pcb_data_new(pcb_board_t *parent); + +/* Uninitialize and free the fields of data (doesn't free data) */ +void pcb_data_uninit(pcb_data_t *data); + +/* Calls pcb_data_uninit() and free data */ +void pcb_data_free(pcb_data_t *data); + +pcb_bool pcb_data_is_empty(pcb_data_t *); + +/* gets minimum and maximum coordinates + * returns NULL if layout is empty */ +pcb_box_t *pcb_data_bbox(pcb_box_t *out, pcb_data_t *Data, pcb_bool ignore_floaters); +pcb_box_t *pcb_data_bbox_naked(pcb_box_t *out, pcb_data_t *Data, pcb_bool ignore_floaters); + +/* Make sure all layers of data has their .parent field pointing to the data */ +void pcb_data_set_layer_parents(pcb_data_t *data); + +/* Set up all data layers as bound layers to pcb's Data */ +void pcb_data_bind_board_layers(pcb_board_t *pcb, pcb_data_t *data, int share_rtrees); + +/* redo all layers of data to be bound layers (layer recipes) using the stackup + from pcb4layer_groups. The new bound layers are not bound to any real layer. */ +void pcb_data_make_layers_bound(pcb_board_t *pcb4layer_groups, pcb_data_t *data); + +/* Recalculate the layer bindings updating meta.bound.real to new board layers */ +void pcb_data_binding_update(pcb_board_t *pcb, pcb_data_t *data); + +/* Break the binding in data bound layers (set htem all to NULL) */ +void pcb_data_unbind_layers(pcb_data_t *data); + +/* Make sure there are no negative coords in data, knowing the bbox of the data */ +int pcb_data_normalize_(pcb_data_t *data, pcb_box_t *data_bbox); + +/* Make sure there are no negative coords in data (calculates the bbox of the data) */ +int pcb_data_normalize(pcb_data_t *data); + +/* Returns the top level pcb related to a data, or NULL if the data is floating + (e.g. is a global buffer) */ +pcb_board_t *pcb_data_get_top(pcb_data_t *data); + +/* Force-set the parent.data field of each global object in data (but not + the layers!) */ +void pcb_data_set_parent_globals(pcb_data_t *data, pcb_data_t *new_parent); + +typedef enum pcb_data_mirror_text_e { + PCB_TXM_NONE = 0, /* do not mirror text */ + PCB_TXM_SIDE = 1, /* mirror text, changing side */ + PCB_TXM_COORD /* mirror text base coords only */ +} pcb_data_mirror_text_t; +void pcb_data_mirror(pcb_data_t *data, pcb_coord_t y_offs, pcb_data_mirror_text_t mtxt, pcb_bool pstk_smirror); + +void pcb_data_move(pcb_data_t *data, pcb_coord_t dx, pcb_coord_t dy); + +/* Multiply x and y coords by sx and sy and thickness by sth (where applicable). + If recurse is non-zero, also modify subcircuits */ +void pcb_data_scale(pcb_data_t *data, double sx, double sy, double sth, int recurse); + +/* run pcb_poly_init_clip() on all polygons in data */ +void pcb_data_clip_polys(pcb_data_t *data); + + +/* rsearch on all trees matching types of data */ +pcb_r_dir_t pcb_data_r_search(pcb_data_t *data, pcb_objtype_t types, const pcb_box_t *starting_region, + pcb_r_dir_t (*region_in_search) (const pcb_box_t *region, void *cl), + pcb_r_dir_t (*rectangle_in_region) (const pcb_box_t *box, void *cl), + void *closure, int *num_found, pcb_bool vis_only); + +/* Either pcb->data or the subcircuit's data if PCB is a subc (footprint edit mode) */ +#define PCB_REAL_DATA(pcb) \ + ((pcb)->is_footprint ? (pcb_subclist_first(&(pcb)->Data->subc)->data) : ((pcb)->Data)) + + +/*** Polygon clipping inhibit ***/ + +/* increase the inhibit counter (stop clipping polygons) */ +void pcb_data_clip_inhibit_inc(pcb_data_t *data); + +/* decrease the inhibit counter - if it's zero, reclip all dirty polygons; + enable_progbar controls whether a progress bar is drawn for reclips + that take longer than a few seconds. */ +void pcb_data_clip_inhibit_dec(pcb_data_t *data, pcb_bool enable_progbar); + +/* attempt to reclip all dirty polygons; normally called by + pcb_data_clip_inhibit_dec(). */ +void pcb_data_clip_dirty(pcb_data_t *data, pcb_bool enable_progbar); + +/* Force reclip all polygons; useful after a move-everything kind + of operation (e.g. autocrop()) */ +void pcb_data_clip_all(pcb_data_t *data, pcb_bool enable_progbar); + + +/* Recursively change flags of data; how is one of pcb_change_flag_t */ +void pcb_data_flag_change(pcb_data_t *data, pcb_objtype_t mask, int how, unsigned long flags); + +/* Clear specific static flag from all objects, optionally with matching + object types only. If redraw is not 0, issue an object redraw on change. + If undoable is not 0, add flag changes to the undo list. Returns number + of object changed. */ +unsigned long pcb_data_clear_obj_flag(pcb_data_t *data, pcb_objtype_t tmask, unsigned long flag, int redraw, int undoable); +unsigned long pcb_data_clear_flag(pcb_data_t *data, unsigned long flag, int redraw, int undoable); + +/* Clear the given dyflag bit from all objects under data */ +void pcb_data_dynflag_clear(pcb_data_t *data, pcb_dynf_t dynf); + +#endif Index: tags/2.1.2/src/data_it.h =================================================================== --- tags/2.1.2/src/data_it.h (nonexistent) +++ tags/2.1.2/src/data_it.h (revision 24813) @@ -0,0 +1,144 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2017 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +/* Flat, non-recursive iterator on pcb_data_t children objects */ + +#ifndef PCB_DATA_IT_H +#define PCB_DATA_IT_H + +#include "obj_common.h" +#include "data.h" + +typedef struct pcb_data_it_s { + /* config */ + pcb_data_t *data; + pcb_objtype_t mask; /* caller wants to see these types */ + + /* current state */ + pcb_objtype_t remaining; + pcb_objtype_t type; + pcb_cardinal_t ln; + pcb_any_obj_t *last; +} pcb_data_it_t; + +#define PCB_DATA_IT_TYPES \ + (PCB_OBJ_LINE | PCB_OBJ_TEXT | PCB_OBJ_POLY | PCB_OBJ_ARC | PCB_OBJ_PSTK | \ + PCB_OBJ_SUBC | PCB_OBJ_RAT) + +/* Start an iteration on data, looking for any object type listed in mask; + returns NULL if nothing is found. The iteration is non-recursive to subcircuits */ +PCB_INLINE pcb_any_obj_t *pcb_data_first(pcb_data_it_t *it, pcb_data_t *data, pcb_objtype_t mask); + +/* Return the next object or NULL on end of iteration */ +PCB_INLINE pcb_any_obj_t *pcb_data_next(pcb_data_it_t *it); + +/**** implementation (inlines) ****/ + +/* Skip to the next type; returns 0 on success, non-0 at the end of types */ +PCB_INLINE int pcb_data_it_next_type(pcb_data_it_t *it) +{ + if (it->remaining == 0) + return 1; + + if (it->type == 0) + it->type = 1; + else + it->type <<= 1; + + /* find and remove the next bit */ + while((it->remaining & it->type) == 0) it->type <<= 1; + it->remaining &= ~it->type; + + return 0; +} + +/* Take the next layer object, skip layer if there's no more */ +#define PCB_DATA_IT_LOBJ(it, otype, ltype, list) \ + do { \ + if (it->last == NULL) \ + it->last = (pcb_any_obj_t *)ltype ## _first(&(it->data->Layer[it->ln].list)); \ + else \ + it->last = (pcb_any_obj_t *)ltype ## _next((otype *)it->last); \ + if (it->last == NULL) \ + goto next_layer; \ + } while(0) + +/* Take the next global object, skip type if there's no more */ +#define PCB_DATA_IT_GOBJ(it, otype, ltype, list) \ + do { \ + if (it->last == NULL) \ + it->last = (pcb_any_obj_t *)ltype ## _first(&(it->data->list)); \ + else \ + it->last = (pcb_any_obj_t *)ltype ## _next((otype *)it->last); \ + if (it->last == NULL) \ + goto next_type; \ + } while(0) + + +PCB_INLINE pcb_any_obj_t *pcb_data_next(pcb_data_it_t *it) +{ + retry:; + + switch(it->type) { + case PCB_OBJ_LINE: PCB_DATA_IT_LOBJ(it, pcb_line_t, linelist, Line); break; + case PCB_OBJ_TEXT: PCB_DATA_IT_LOBJ(it, pcb_text_t, textlist, Text); break; + case PCB_OBJ_POLY: PCB_DATA_IT_LOBJ(it, pcb_poly_t, polylist, Polygon); break; + case PCB_OBJ_ARC: PCB_DATA_IT_LOBJ(it, pcb_arc_t, arclist, Arc); break; + case PCB_OBJ_PSTK: PCB_DATA_IT_GOBJ(it, pcb_pstk_t, padstacklist, padstack); break; + case PCB_OBJ_SUBC: PCB_DATA_IT_GOBJ(it, pcb_subc_t, pcb_subclist, subc); break; + case PCB_OBJ_RAT: PCB_DATA_IT_GOBJ(it, pcb_rat_t, ratlist, Rat); break; + default: + assert(!"iterating on invalid type"); + return NULL; + } + return it->last; + + /* skip to the next layer and retry unless ran out of types */ + next_layer:; + it->ln++; + if (it->ln >= it->data->LayerN) { /* checked all layers for this type, skip to next type */ + it->ln = 0; + next_type:; + if (pcb_data_it_next_type(it)) + return NULL; + } + + goto retry; /* ... on the new layer */ +} + +PCB_INLINE pcb_any_obj_t *pcb_data_first(pcb_data_it_t *it, pcb_data_t *data, pcb_objtype_t mask) +{ + it->data = data; + it->mask = it->remaining = mask & PCB_DATA_IT_TYPES; + it->type = 0; + it->ln = 0; + it->last = NULL; + if (pcb_data_it_next_type(it)) + return NULL; + return pcb_data_next(it); +} + +#endif Index: tags/2.1.2/src/data_list.h =================================================================== --- tags/2.1.2/src/data_list.h (nonexistent) +++ tags/2.1.2/src/data_list.h (revision 24813) @@ -0,0 +1,41 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2017 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#ifndef PCB_DATA_LIST_H +#define PCB_DATA_LIST_H + +#include +#include "data.h" + +/* append objects of type, with flags matching mask to dst; pointer are + valid only until the first change to data; if flags is 0, everything matches. */ +void pcb_data_list_by_flag(pcb_data_t *data, vtp0_t *dst, pcb_objtype_t type, unsigned long mask); + +/* append objects of type that are terminals; pointer are + valid only until the first change to data */ +void pcb_data_list_terms(pcb_data_t *data, vtp0_t *dst, pcb_objtype_t type); + +#endif Index: tags/2.1.2/src/data_parent.h =================================================================== --- tags/2.1.2/src/data_parent.h (nonexistent) +++ tags/2.1.2/src/data_parent.h (revision 24813) @@ -0,0 +1,72 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2016..2017 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#ifndef PCB_DATA_PARENT_H +#define PCB_DATA_PARENT_H + +#include "global_typedefs.h" + +/* which elem of the parent union is active */ +typedef enum pcb_parenttype_e { + PCB_PARENT_INVALID = 0, /* invalid or unknown */ + PCB_PARENT_LAYER, /* object is on a layer */ + PCB_PARENT_SUBC, /* object is part of a subcircuit */ + PCB_PARENT_DATA, /* global objects like via */ + PCB_PARENT_BOARD, /* directly under a board (typical for pcb_data_t of a board) */ + PCB_PARENT_NET, /* pcb_net_term_t's parent is a pcb_net_t */ + PCB_PARENT_UI /* parent of UI layers */ +} pcb_parenttype_t; + +/* class is e.g. PCB_OBJ_CLASS_OBJ */ +#define PCB_OBJ_IS_CLASS(type, class) (((type) & PCB_OBJ_CLASS_MASK) == (class)) + +union pcb_parent_s { + void *any; + pcb_layer_t *layer; + pcb_data_t *data; + pcb_subc_t *subc; + pcb_board_t *board; + pcb_net_t *net; +}; + +#define PCB_PARENT_TYPENAME_layer PCB_PARENT_LAYER +#define PCB_PARENT_TYPENAME_data PCB_PARENT_DATA +#define PCB_PARENT_TYPENAME_subc PCB_PARENT_SUBC +#define PCB_PARENT_TYPENAME_board PCB_PARENT_BOARD + +#define PCB_SET_PARENT(obj, ptype, parent_ptr) \ + do { \ + (obj)->parent_type = PCB_PARENT_TYPENAME_ ## ptype; \ + (obj)->parent.ptype = parent_ptr; \ + } while(0) + +#define PCB_CLEAR_PARENT(obj) \ + do { \ + (obj)->parent_type = PCB_PARENT_INVALID; \ + (obj)->parent.any = NULL; \ + } while(0) + +#endif Index: tags/2.1.2/src/default2.lht =================================================================== --- tags/2.1.2/src/default2.lht (nonexistent) +++ tags/2.1.2/src/default2.lht (revision 24813) @@ -0,0 +1,131 @@ +# pcb-rnd official 2-layer default board + +ha:pcb-rnd-board-v6 { + li:styles { + ha:Signal { + diameter = 2mm + thickness = 10.0mil + hole = 31.5mil + clearance = 20.0mil + } + ha:Power { + diameter = 2.2mm + thickness = 20.0mil + hole = 1mm + clearance = 20.0mil + } + ha:Fat { + diameter = 137.8mil + thickness = 80.0mil + hole = 47.24mil + clearance = 25.0mil + } + ha:Sig-tight { + diameter = 64.0mil + thickness = 10.0mil + hole = 31.5mil + clearance = 12.0mil + } + } + + ha:meta { + ha:size { + thermal_scale = 0.500000 + x = 127.0mm; y = 127.0mm + isle_area_nm2 = 200000000.0 + } + ha:grid { + spacing = 25.0mil + offs_x = 0.0 + offs_y = 0.0 + } + } + + ha:data { + li:layers { + ha:top-sig { lid=0; group=3; } + ha:bottom-sig { lid=1; group=6; } + ha:top-gnd { lid=2; group=3; } + ha:bottom-gnd { lid=3; group=6; } + ha:top-vcc { lid=4; group=3; } + ha:bottom-vcc { lid=5; group=6; } + ha:outline { lid=6; group=5; } + ha:bottom-silk { lid=7; group=8; ha:combining { auto=1; } } + ha:top-silk { lid=8; group=1; ha:combining { auto=1; } } + ha:top-paste { lid=9; group=0; ha:combining { auto=1; } } + ha:top-mask { lid=10; group=2; ha:combining { sub=1; auto=1; } } + ha:bottom-mask { lid=11; group=7; ha:combining { sub=1; auto=1; } } + ha:bottom-paste { lid=12; group=9; ha:combining { auto=1; } } + ha:slot-plated { lid=13; group=10; ha:combining { auto=1; } } + ha:slot-unplated { lid=14; group=11; ha:combining { auto=1; } } + } + } + + ha:layer_stack { + li:groups { + ha:0 { + name = top_paste + ha:type { top=1; paste=1; } + li:layers { 9; } + } + ha:1 { + name = top_silk + ha:type { silk=1; top=1; } + li:layers { 8; } + } + ha:2 { + name = top_mask + ha:type { top=1; mask=1; } + li:layers { 10; } + } + ha:3 { + name = top_copper + ha:type { copper=1; top=1; } + li:layers { 0; 2; 4; } + } + ha:4 { + ha:type { substrate=1; intern=1; } + li:layers { } + name = grp_4 + } + ha:5 { + name = global_outline + ha:type { boundary=1; } + purpose = uroute + li:layers { 6; } + } + ha:6 { + name = bottom_copper + ha:type { bottom=1; copper=1; } + li:layers { 1; 3; 5; } + } + ha:7 { + name = bottom_mask + ha:type { bottom=1; mask=1; } + li:layers { 11; } + } + ha:8 { + name = bottom_silk + ha:type { silk=1; bottom=1; } + li:layers { 7; } + } + ha:9 { + name = bottom_paste + ha:type { bottom=1; paste=1; } + li:layers { 12; } + } + ha:10 { + name = pmech + ha:type { mech=1; } + purpose = proute + li:layers { 13; } + } + ha:11 { + name = umech + ha:type { mech=1; } + purpose = uroute + li:layers { 14; } + } + } + } +} Index: tags/2.1.2/src/default4.lht =================================================================== --- tags/2.1.2/src/default4.lht (nonexistent) +++ tags/2.1.2/src/default4.lht (revision 24813) @@ -0,0 +1,151 @@ +# pcb-rnd official 4-layer default board + +ha:pcb-rnd-board-v6 { + li:styles { + ha:Signal { + diameter = 2mm + thickness = 10.0mil + hole = 31.5mil + clearance = 20.0mil + } + ha:Power { + diameter = 2.2mm + thickness = 20.0mil + hole = 1mm + clearance = 20.0mil + } + ha:Fat { + diameter = 137.8mil + thickness = 80.0mil + hole = 47.24mil + clearance = 25.0mil + } + ha:Sig-tight { + diameter = 64.0mil + thickness = 10.0mil + hole = 31.5mil + clearance = 12.0mil + } + } + + ha:meta { + ha:size { + thermal_scale = 0.500000 + x = 127.0mm; y = 127.0mm + isle_area_nm2 = 200000000.0 + } + ha:grid { + spacing = 25.0mil + offs_x = 0.0 + offs_y = 0.0 + } + } + + ha:data { + li:layers { + ha:top-sig { lid=0; group=3; } + ha:bottom-sig { lid=1; group=10; } + ha:top-gnd { lid=2; group=3; } + ha:bottom-gnd { lid=3; group=10; } + ha:int-sig2 { lid=4; group=7; } + ha:int-sig1 { lid=5; group=5; } + ha:outline { lid=6; group=9; } + ha:bottom-silk { lid=7; group=12; ha:combining { auto=1; } } + ha:top-silk { lid=8; group=1; ha:combining { auto=1; } } + ha:top-paste { lid=9; group=0; ha:combining { auto=1; } } + ha:top-mask { lid=10; group=2; ha:combining { sub=1; auto=1; } } + ha:bottom-mask { lid=11; group=11; ha:combining { sub=1; auto=1; } } + ha:bottom-paste { lid=12; group=13; ha:combining { auto=1; } } + ha:slot-plated { lid=13; group=14; ha:combining { auto=1; } } + ha:slot-unplated { lid=14; group=15; ha:combining { auto=1; } } + } + } + + ha:layer_stack { + li:groups { + ha:0 { + name = top_paste + ha:type { top=1; paste=1; } + li:layers { 9; } + } + ha:1 { + name = top_silk + ha:type { silk=1; top=1; } + li:layers { 8; } + } + ha:2 { + name = top_mask + ha:type { top=1; mask=1; } + li:layers { 10; } + } + ha:3 { + name = top_copper + ha:type { copper=1; top=1; } + li:layers { 0; 2; } + } + ha:4 { + ha:type { substrate=1; intern=1; } + li:layers { } + name = grp_4 + } + ha:5 { + name = Intern + ha:type { copper=1; intern=1; } + li:layers { 5; } + } + ha:6 { + ha:type { substrate=1; intern=1; } + li:layers { } + name = grp_6 + } + ha:7 { + name = Intern + ha:type { copper=1; intern=1; } + li:layers { 4; } + } + ha:8 { + ha:type { substrate=1; intern=1; } + li:layers { } + name = grp_8 + } + ha:9 { + name = global_outline + ha:type { boundary=1; } + purpose = uroute + li:layers { 6; } + } + ha:10 { + name = bottom_copper + ha:type { bottom=1; copper=1; } + li:layers { 1; 3; } + } + ha:11 { + name = bottom_mask + ha:type { bottom=1; mask=1; } + li:layers { 11; } + } + ha:12 { + name = bottom_silk + ha:type { silk=1; bottom=1; } + li:layers { 7; } + } + ha:13 { + name = bottom_paste + ha:type { bottom=1; paste=1; } + li:layers { 12; } + } + ha:14 { + name = pmech + ha:type { mech=1; } + purpose = proute + li:layers { 13; } + } + ha:15 { + name = umech + ha:type { mech=1; } + purpose = uroute + li:layers { 14; } + } + } + } +} Index: tags/2.1.2/src/default_font =================================================================== --- tags/2.1.2/src/default_font (nonexistent) +++ tags/2.1.2/src/default_font (revision 24813) @@ -0,0 +1,773 @@ +Symbol(' ' 18) +( +) +Symbol('!' 12) +( + SymbolLine(0 35 0 40 8) + SymbolLine(0 0 0 25 8) +) +Symbol('"' 12) +( + SymbolLine(0 0 0 10 8) + SymbolLine(10 0 10 10 8) +) +Symbol('#' 12) +( + SymbolLine(0 25 20 25 8) + SymbolLine(0 15 20 15 8) + SymbolLine(15 10 15 30 8) + SymbolLine(5 10 5 30 8) +) +Symbol('$' 12) +( + SymbolLine(15 5 20 10 8) + SymbolLine(5 5 15 5 8) + SymbolLine(0 10 5 5 8) + SymbolLine(0 10 0 15 8) + SymbolLine(0 15 5 20 8) + SymbolLine(5 20 15 20 8) + SymbolLine(15 20 20 25 8) + SymbolLine(20 25 20 30 8) + SymbolLine(15 35 20 30 8) + SymbolLine(5 35 15 35 8) + SymbolLine(0 30 5 35 8) + SymbolLine(10 0 10 40 8) +) +Symbol('%' 12) +( + SymbolLine(0 5 0 10 8) + SymbolLine(0 5 5 0 8) + SymbolLine(5 0 10 0 8) + SymbolLine(10 0 15 5 8) + SymbolLine(15 5 15 10 8) + SymbolLine(10 15 15 10 8) + SymbolLine(5 15 10 15 8) + SymbolLine(0 10 5 15 8) + SymbolLine(0 40 40 0 8) + SymbolLine(35 40 40 35 8) + SymbolLine(40 30 40 35 8) + SymbolLine(35 25 40 30 8) + SymbolLine(30 25 35 25 8) + SymbolLine(25 30 30 25 8) + SymbolLine(25 30 25 35 8) + SymbolLine(25 35 30 40 8) + SymbolLine(30 40 35 40 8) +) +Symbol('&' 12) +( + SymbolLine(0 35 5 40 8) + SymbolLine(0 5 0 15 8) + SymbolLine(0 5 5 0 8) + SymbolLine(0 25 15 10 8) + SymbolLine(5 40 10 40 8) + SymbolLine(10 40 20 30 8) + SymbolLine(0 15 25 40 8) + SymbolLine(5 0 10 0 8) + SymbolLine(10 0 15 5 8) + SymbolLine(15 5 15 10 8) + SymbolLine(0 25 0 35 8) +) +Symbol(''' 12) +( + SymbolLine(0 10 10 0 8) +) +Symbol('(' 12) +( + SymbolLine(0 35 5 40 8) + SymbolLine(0 5 5 0 8) + SymbolLine(0 5 0 35 8) +) +Symbol(')' 12) +( + SymbolLine(0 0 5 5 8) + SymbolLine(5 5 5 35 8) + SymbolLine(0 40 5 35 8) +) +Symbol('*' 12) +( + SymbolLine(0 10 20 30 8) + SymbolLine(0 30 20 10 8) + SymbolLine(0 20 20 20 8) + SymbolLine(10 10 10 30 8) +) +Symbol('+' 12) +( + SymbolLine(0 20 20 20 8) + SymbolLine(10 10 10 30 8) +) +Symbol(',' 12) +( + SymbolLine(0 50 10 40 8) +) +Symbol('-' 12) +( + SymbolLine(0 20 20 20 8) +) +Symbol('.' 12) +( + SymbolLine(0 40 5 40 8) +) +Symbol('/' 12) +( + SymbolLine(0 35 30 5 8) +) +Symbol('0' 12) +( + SymbolLine(0 35 5 40 8) + SymbolLine(0 5 0 35 8) + SymbolLine(0 5 5 0 8) + SymbolLine(5 0 15 0 8) + SymbolLine(15 0 20 5 8) + SymbolLine(20 5 20 35 8) + SymbolLine(15 40 20 35 8) + SymbolLine(5 40 15 40 8) + SymbolLine(0 30 20 10 8) +) +Symbol('1' 12) +( + SymbolLine( 0 8 8 0 8) + SymbolLine( 8 0 8 40 8) + SymbolLine( 0 40 15 40 8) +) +Symbol('2' 12) +( + SymbolLine(0 5 5 0 8) + SymbolLine(5 0 20 0 8) + SymbolLine(20 0 25 5 8) + SymbolLine(25 5 25 15 8) + SymbolLine(0 40 25 15 8) + SymbolLine(0 40 25 40 8) +) +Symbol('3' 12) +( + SymbolLine( 0 5 5 0 8) + SymbolLine( 5 0 15 0 8) + SymbolLine(15 0 20 5 8) + SymbolLine(15 40 20 35 8) + SymbolLine( 5 40 15 40 8) + SymbolLine( 0 35 5 40 8) + + SymbolLine( 5 18 15 18 8) + SymbolLine(20 5 20 13 8) + SymbolLine(20 23 20 35 8) + SymbolLine(20 23 15 18 8) + SymbolLine(20 13 15 18 8) +) +Symbol('4' 12) +( + SymbolLine(0 25 20 0 8) + SymbolLine(0 25 25 25 8) + SymbolLine(20 0 20 40 8) +) +Symbol('5' 12) +( + SymbolLine(0 0 20 0 8) + SymbolLine(0 0 0 20 8) + SymbolLine(0 20 5 15 8) + SymbolLine(5 15 15 15 8) + SymbolLine(15 15 20 20 8) + SymbolLine(20 20 20 35 8) + SymbolLine(15 40 20 35 8) + SymbolLine(5 40 15 40 8) + SymbolLine(0 35 5 40 8) +) +Symbol('6' 12) +( + SymbolLine(15 0 20 5 8) + SymbolLine( 5 0 15 0 8) + SymbolLine( 0 5 5 0 8) + SymbolLine( 0 5 0 35 8) + SymbolLine( 0 35 5 40 8) + SymbolLine(15 18 20 23 8) + SymbolLine( 0 18 15 18 8) + SymbolLine( 5 40 15 40 8) + SymbolLine(15 40 20 35 8) + SymbolLine(20 23 20 35 8) +) +Symbol('7' 12) +( + SymbolLine( 5 40 25 0 8) + SymbolLine( 0 0 25 0 8) +) +Symbol('8' 12) +( + SymbolLine( 0 35 5 40 8) + SymbolLine( 0 27 0 35 8) + SymbolLine( 0 27 7 20 8) + SymbolLine( 7 20 13 20 8) + SymbolLine(13 20 20 27 8) + SymbolLine(20 27 20 35 8) + SymbolLine(15 40 20 35 8) + SymbolLine( 5 40 15 40 8) + SymbolLine( 0 13 7 20 8) + SymbolLine( 0 5 0 13 8) + SymbolLine( 0 5 5 0 8) + SymbolLine( 5 0 15 0 8) + SymbolLine(15 0 20 5 8) + SymbolLine(20 5 20 13 8) + SymbolLine(13 20 20 13 8) +) +Symbol('9' 12) +( + SymbolLine(5 40 20 20 8) + SymbolLine(20 5 20 20 8) + SymbolLine(15 0 20 5 8) + SymbolLine(5 0 15 0 8) + SymbolLine(0 5 5 0 8) + SymbolLine(0 5 0 15 8) + SymbolLine(0 15 5 20 8) + SymbolLine(5 20 20 20 8) +) +Symbol(':' 12) +( + SymbolLine(0 15 5 15 8) + SymbolLine(0 25 5 25 8) +) +Symbol(';' 12) +( + SymbolLine(0 40 10 30 8) + SymbolLine(10 15 10 20 8) +) +Symbol('<' 12) +( + SymbolLine(0 20 10 10 8) + SymbolLine(0 20 10 30 8) +) +Symbol('=' 12) +( + SymbolLine(0 15 20 15 8) + SymbolLine(0 25 20 25 8) +) +Symbol('>' 12) +( + SymbolLine(0 10 10 20 8) + SymbolLine(0 30 10 20 8) +) +Symbol('?' 12) +( + SymbolLine(10 20 10 25 8) + SymbolLine(10 35 10 40 8) + SymbolLine(0 5 0 10 8) + SymbolLine(0 5 5 0 8) + SymbolLine(5 0 15 0 8) + SymbolLine(15 0 20 5 8) + SymbolLine(20 5 20 10 8) + SymbolLine(10 20 20 10 8) +) +Symbol('A' 12) +( + SymbolLine( 0 10 0 40 8) + SymbolLine( 0 10 7 0 8) + SymbolLine( 7 0 18 0 8) + SymbolLine(18 0 25 10 8) + SymbolLine(25 10 25 40 8) + SymbolLine( 0 20 25 20 8) +) +Symbol('B' 12) +( + SymbolLine( 0 40 20 40 8) + SymbolLine(20 40 25 35 8) + SymbolLine(25 23 25 35 8) + SymbolLine(20 18 25 23 8) + SymbolLine( 5 18 20 18 8) + SymbolLine( 5 0 5 40 8) + SymbolLine( 0 0 20 0 8) + SymbolLine(20 0 25 5 8) + SymbolLine(25 5 25 13 8) + SymbolLine(20 18 25 13 8) +) +Symbol('C' 12) +( + SymbolLine(7 40 20 40 8) + SymbolLine(0 33 7 40 8) + SymbolLine(0 7 0 33 8) + SymbolLine(0 7 7 0 8) + SymbolLine(7 0 20 0 8) +) +Symbol('D' 12) +( + SymbolLine( 5 0 5 40 8) + SymbolLine(18 0 25 7 8) + SymbolLine(25 7 25 33 8) + SymbolLine(18 40 25 33 8) + SymbolLine( 0 40 18 40 8) + SymbolLine( 0 0 18 0 8) +) +Symbol('E' 12) +( + SymbolLine(0 18 15 18 8) + SymbolLine(0 40 20 40 8) + SymbolLine(0 0 0 40 8) + SymbolLine(0 0 20 0 8) +) +Symbol('F' 12) +( + SymbolLine(0 0 0 40 8) + SymbolLine(0 0 20 0 8) + SymbolLine(0 18 15 18 8) +) +Symbol('G' 12) +( + SymbolLine(20 0 25 5 8) + SymbolLine(5 0 20 0 8) + SymbolLine(0 5 5 0 8) + SymbolLine(0 5 0 35 8) + SymbolLine(0 35 5 40 8) + SymbolLine(5 40 20 40 8) + SymbolLine(20 40 25 35 8) + SymbolLine(25 25 25 35 8) + SymbolLine(20 20 25 25 8) + SymbolLine(10 20 20 20 8) +) +Symbol('H' 12) +( + SymbolLine(0 0 0 40 8) + SymbolLine(25 0 25 40 8) + SymbolLine(0 20 25 20 8) +) +Symbol('I' 12) +( + SymbolLine(0 0 10 0 8) + SymbolLine(5 0 5 40 8) + SymbolLine(0 40 10 40 8) +) +Symbol('J' 12) +( + SymbolLine( 7 0 15 0 8) + SymbolLine(15 0 15 35 8) + SymbolLine(10 40 15 35 8) + SymbolLine( 5 40 10 40 8) + SymbolLine( 0 35 5 40 8) + SymbolLine( 0 35 0 30 8) +) +Symbol('K' 12) +( + SymbolLine(0 0 0 40 8) + SymbolLine(0 20 20 0 8) + SymbolLine(0 20 20 40 8) +) +Symbol('L' 12) +( + SymbolLine(0 0 0 40 8) + SymbolLine(0 40 20 40 8) +) +Symbol('M' 12) +( + SymbolLine(0 0 0 40 8) + SymbolLine(0 0 15 20 8) + SymbolLine(15 20 30 0 8) + SymbolLine(30 0 30 40 8) +) +Symbol('N' 12) +( + SymbolLine(0 0 0 40 8) + SymbolLine(0 0 25 40 8) + SymbolLine(25 0 25 40 8) +) +Symbol('O' 12) +( + SymbolLine(0 5 0 35 8) + SymbolLine(0 5 5 0 8) + SymbolLine(5 0 15 0 8) + SymbolLine(15 0 20 5 8) + SymbolLine(20 5 20 35 8) + SymbolLine(15 40 20 35 8) + SymbolLine(5 40 15 40 8) + SymbolLine(0 35 5 40 8) +) +Symbol('P' 12) +( + SymbolLine(5 0 5 40 8) + SymbolLine(0 0 20 0 8) + SymbolLine(20 0 25 5 8) + SymbolLine(25 5 25 15 8) + SymbolLine(20 20 25 15 8) + SymbolLine(5 20 20 20 8) +) +Symbol('Q' 12) +( + SymbolLine( 0 5 0 35 8) + SymbolLine( 0 5 5 0 8) + SymbolLine( 5 0 15 0 8) + SymbolLine(15 0 20 5 8) + SymbolLine(20 5 20 30 8) + SymbolLine(10 40 20 30 8) + SymbolLine( 5 40 10 40 8) + SymbolLine( 0 35 5 40 8) + SymbolLine(10 25 20 40 8) +) +Symbol('R' 12) +( + SymbolLine( 0 0 20 0 8) + SymbolLine(20 0 25 5 8) + SymbolLine(25 5 25 15 8) + SymbolLine(20 20 25 15 8) + SymbolLine( 5 20 20 20 8) + SymbolLine( 5 0 5 40 8) + SymbolLine(13 20 25 40 8) +) +Symbol('S' 12) +( + SymbolLine(20 0 25 5 8) + SymbolLine(5 0 20 0 8) + SymbolLine(0 5 5 0 8) + SymbolLine(0 5 0 15 8) + SymbolLine(0 15 5 20 8) + SymbolLine(5 20 20 20 8) + SymbolLine(20 20 25 25 8) + SymbolLine(25 25 25 35 8) + SymbolLine(20 40 25 35 8) + SymbolLine(5 40 20 40 8) + SymbolLine(0 35 5 40 8) +) +Symbol('T' 12) +( + SymbolLine(0 0 20 0 8) + SymbolLine(10 0 10 40 8) +) +Symbol('U' 12) +( + SymbolLine(0 0 0 35 8) + SymbolLine(0 35 5 40 8) + SymbolLine(5 40 15 40 8) + SymbolLine(15 40 20 35 8) + SymbolLine(20 0 20 35 8) +) +Symbol('V' 12) +( + SymbolLine( 0 0 10 40 8) + SymbolLine(10 40 20 0 8) +) +Symbol('W' 12) +( + SymbolLine( 0 0 0 20 8) + SymbolLine( 0 20 5 40 8) + SymbolLine( 5 40 15 20 8) + SymbolLine(15 20 25 40 8) + SymbolLine(25 40 30 20 8) + SymbolLine(30 20 30 0 8) +) +Symbol('X' 12) +( + SymbolLine( 0 40 25 0 8) + SymbolLine( 0 0 25 40 8) +) +Symbol('Y' 12) +( + SymbolLine( 0 0 10 20 8) + SymbolLine(10 20 20 0 8) + SymbolLine(10 20 10 40 8) +) +Symbol('Z' 12) +( + SymbolLine( 0 0 25 0 8) + SymbolLine( 0 40 25 0 8) + SymbolLine( 0 40 25 40 8) +) +Symbol('[' 12) +( + SymbolLine(0 0 5 0 8) + SymbolLine(0 0 0 40 8) + SymbolLine(0 40 5 40 8) +) +Symbol('\' 12) +( + SymbolLine(0 5 30 35 8) +) +Symbol(']' 12) +( + SymbolLine(0 0 5 0 8) + SymbolLine(5 0 5 40 8) + SymbolLine(0 40 5 40 8) +) +Symbol('^' 12) +( + SymbolLine(0 5 5 0 8) + SymbolLine(5 0 10 5 8) +) +Symbol('_' 12) +( + SymbolLine(0 40 20 40 8) +) +Symbol('a' 12) +( + SymbolLine(15 20 20 25 8) + SymbolLine(5 20 15 20 8) + SymbolLine(0 25 5 20 8) + SymbolLine(0 25 0 35 8) + SymbolLine(0 35 5 40 8) + SymbolLine(20 20 20 35 8) + SymbolLine(20 35 25 40 8) + SymbolLine(5 40 15 40 8) + SymbolLine(15 40 20 35 8) +) +Symbol('b' 12) +( + SymbolLine(0 0 0 40 8) + SymbolLine(0 35 5 40 8) + SymbolLine(5 40 15 40 8) + SymbolLine(15 40 20 35 8) + SymbolLine(20 25 20 35 8) + SymbolLine(15 20 20 25 8) + SymbolLine(5 20 15 20 8) + SymbolLine(0 25 5 20 8) +) +Symbol('c' 12) +( + SymbolLine(5 20 20 20 8) + SymbolLine(0 25 5 20 8) + SymbolLine(0 25 0 35 8) + SymbolLine(0 35 5 40 8) + SymbolLine(5 40 20 40 8) +) +Symbol('d' 12) +( + SymbolLine(20 0 20 40 8) + SymbolLine(15 40 20 35 8) + SymbolLine(5 40 15 40 8) + SymbolLine(0 35 5 40 8) + SymbolLine(0 25 0 35 8) + SymbolLine(0 25 5 20 8) + SymbolLine(5 20 15 20 8) + SymbolLine(15 20 20 25 8) +) +Symbol('e' 12) +( + SymbolLine(5 40 20 40 8) + SymbolLine(0 35 5 40 8) + SymbolLine(0 25 0 35 8) + SymbolLine(0 25 5 20 8) + SymbolLine(5 20 15 20 8) + SymbolLine(15 20 20 25 8) + SymbolLine(0 30 20 30 8) + SymbolLine(20 30 20 25 8) +) +Symbol('f' 10) +( + SymbolLine(5 5 5 40 8) + SymbolLine(5 5 10 0 8) + SymbolLine(10 0 15 0 8) + SymbolLine(0 20 10 20 8) +) +Symbol('g' 12) +( + SymbolLine(15 20 20 25 8) + SymbolLine(5 20 15 20 8) + SymbolLine(0 25 5 20 8) + SymbolLine(0 25 0 35 8) + SymbolLine(0 35 5 40 8) + SymbolLine(5 40 15 40 8) + SymbolLine(15 40 20 35 8) + SymbolLine(0 50 5 55 8) + SymbolLine(5 55 15 55 8) + SymbolLine(15 55 20 50 8) + SymbolLine(20 20 20 50 8) +) +Symbol('h' 12) +( + SymbolLine(0 0 0 40 8) + SymbolLine(0 25 5 20 8) + SymbolLine(5 20 15 20 8) + SymbolLine(15 20 20 25 8) + SymbolLine(20 25 20 40 8) +) +Symbol('i' 10) +( + SymbolLine(0 10 0 11 10) + SymbolLine(0 25 0 40 8) +) +Symbol('j' 10) +( + SymbolLine(5 10 5 11 10) + SymbolLine(5 25 5 50 8) + SymbolLine(0 55 5 50 8) +) +Symbol('k' 12) +( + SymbolLine(0 0 0 40 8) + SymbolLine(0 25 15 40 8) + SymbolLine(0 25 10 15 8) +) +Symbol('l' 10) +( + SymbolLine(0 0 0 35 8) + SymbolLine(0 35 5 40 8) +) +Symbol('m' 12) +( + SymbolLine(5 25 5 40 8) + SymbolLine(5 25 10 20 8) + SymbolLine(10 20 15 20 8) + SymbolLine(15 20 20 25 8) + SymbolLine(20 25 20 40 8) + SymbolLine(20 25 25 20 8) + SymbolLine(25 20 30 20 8) + SymbolLine(30 20 35 25 8) + SymbolLine(35 25 35 40 8) + SymbolLine(0 20 5 25 8) +) +Symbol('n' 12) +( + SymbolLine(5 25 5 40 8) + SymbolLine(5 25 10 20 8) + SymbolLine(10 20 15 20 8) + SymbolLine(15 20 20 25 8) + SymbolLine(20 25 20 40 8) + SymbolLine(0 20 5 25 8) +) +Symbol('o' 12) +( + SymbolLine(0 25 0 35 8) + SymbolLine(0 25 5 20 8) + SymbolLine(5 20 15 20 8) + SymbolLine(15 20 20 25 8) + SymbolLine(20 25 20 35 8) + SymbolLine(15 40 20 35 8) + SymbolLine(5 40 15 40 8) + SymbolLine(0 35 5 40 8) +) +Symbol('p' 12) +( + SymbolLine(5 25 5 55 8) + SymbolLine(0 20 5 25 8) + SymbolLine(5 25 10 20 8) + SymbolLine(10 20 20 20 8) + SymbolLine(20 20 25 25 8) + SymbolLine(25 25 25 35 8) + SymbolLine(20 40 25 35 8) + SymbolLine(10 40 20 40 8) + SymbolLine(5 35 10 40 8) +) +Symbol('q' 12) +( + SymbolLine(20 25 20 55 8) + SymbolLine(15 20 20 25 8) + SymbolLine(5 20 15 20 8) + SymbolLine(0 25 5 20 8) + SymbolLine(0 25 0 35 8) + SymbolLine(0 35 5 40 8) + SymbolLine(5 40 15 40 8) + SymbolLine(15 40 20 35 8) +) +Symbol('r' 12) +( + SymbolLine(5 25 5 40 8) + SymbolLine(5 25 10 20 8) + SymbolLine(10 20 20 20 8) + SymbolLine(0 20 5 25 8) +) +Symbol('s' 12) +( + SymbolLine(5 40 20 40 8) + SymbolLine(20 40 25 35 8) + SymbolLine(20 30 25 35 8) + SymbolLine(5 30 20 30 8) + SymbolLine(0 25 5 30 8) + SymbolLine(0 25 5 20 8) + SymbolLine(5 20 20 20 8) + SymbolLine(20 20 25 25 8) + SymbolLine(0 35 5 40 8) +) +Symbol('t' 10) +( + SymbolLine(5 0 5 35 8) + SymbolLine(5 35 10 40 8) + SymbolLine(0 15 10 15 8) +) +Symbol('u' 12) +( + SymbolLine(0 20 0 35 8) + SymbolLine(0 35 5 40 8) + SymbolLine(5 40 15 40 8) + SymbolLine(15 40 20 35 8) + SymbolLine(20 20 20 35 8) +) +Symbol('v' 12) +( + SymbolLine( 0 20 10 40 8) + SymbolLine(20 20 10 40 8) +) +Symbol('w' 12) +( + SymbolLine(0 20 0 35 8) + SymbolLine(0 35 5 40 8) + SymbolLine(5 40 10 40 8) + SymbolLine(10 40 15 35 8) + SymbolLine(15 20 15 35 8) + SymbolLine(15 35 20 40 8) + SymbolLine(20 40 25 40 8) + SymbolLine(25 40 30 35 8) + SymbolLine(30 20 30 35 8) +) +Symbol('x' 12) +( + SymbolLine(0 20 20 40 8) + SymbolLine(0 40 20 20 8) +) +Symbol('y' 12) +( + SymbolLine(0 20 0 35 8) + SymbolLine(0 35 5 40 8) + SymbolLine(20 20 20 50 8) + SymbolLine(15 55 20 50 8) + SymbolLine(5 55 15 55 8) + SymbolLine(0 50 5 55 8) + SymbolLine(5 40 15 40 8) + SymbolLine(15 40 20 35 8) +) +Symbol('z' 12) +( + SymbolLine(0 20 20 20 8) + SymbolLine(0 40 20 20 8) + SymbolLine(0 40 20 40 8) +) +Symbol('{' 12) +( + SymbolLine(5 5 10 0 8) + SymbolLine(5 5 5 15 8) + SymbolLine(0 20 5 15 8) + SymbolLine(0 20 5 25 8) + SymbolLine(5 25 5 35 8) + SymbolLine(5 35 10 40 8) +) +Symbol('|' 12) +( + SymbolLine(0 0 0 40 8) +) +Symbol('}' 12) +( + SymbolLine(0 0 5 5 8) + SymbolLine(5 5 5 15 8) + SymbolLine(5 15 10 20 8) + SymbolLine(5 25 10 20 8) + SymbolLine(5 25 5 35 8) + SymbolLine(0 40 5 35 8) +) +Symbol('~' 12) +( + SymbolLine(0 25 5 20 8) + SymbolLine(5 20 10 20 8) + SymbolLine(10 20 15 25 8) + SymbolLine(15 25 20 25 8) + SymbolLine(20 25 25 20 8) +) +Symbol('@' 12) +( + SymbolLine(0 0 0 30 8) + SymbolLine(0 30 10 40 8) + SymbolLine(10 40 40 40 8) + SymbolLine(50 25 50 0 8) + SymbolLine(50 0 40 -10 8) + SymbolLine(40 -10 10 -10 8) + SymbolLine(10 -10 0 0 8) + SymbolLine(15 10 15 20 8) + SymbolLine(15 20 20 25 8) + SymbolLine(20 25 30 25 8) + SymbolLine(30 25 35 20 8) + SymbolLine(35 20 40 25 8) + SymbolLine(35 20 35 5 8) + SymbolLine(35 10 30 5 8) + SymbolLine(20 5 30 5 8) + SymbolLine(20 5 15 10 8) + SymbolLine(40 25 50 25 8) +) Index: tags/2.1.2/src/dolists.h =================================================================== --- tags/2.1.2/src/dolists.h (nonexistent) +++ tags/2.1.2/src/dolists.h (revision 24813) @@ -0,0 +1,6 @@ +#undef PCB_REGISTER_ACTIONS +#undef PCB_REGISTER_ATTRIBUTES + +#define PCB_REGISTER_ACTIONS(a, cookie) {extern void PCB_HIDCONCAT(register_,a)();PCB_HIDCONCAT(register_,a)();} +#define PCB_REGISTER_ATTRIBUTES(a, cookie) {extern void PCB_HIDCONCAT(register_,a)();PCB_HIDCONCAT(register_,a)();} + Index: tags/2.1.2/src/draw.c =================================================================== --- tags/2.1.2/src/draw.c (nonexistent) +++ tags/2.1.2/src/draw.c (revision 24813) @@ -0,0 +1,1125 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996, 2003, 2004 Thomas Nau + * Copyright (C) 2017,2018 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +#include "config.h" + +#include "conf_core.h" +#include "math_helper.h" +#include "board.h" +#include "data.h" +#include "draw.h" +#include "event.h" +#include "rotate.h" +#include "rtree.h" +#include "stub_draw.h" +#include "layer_ui.h" +#include "hid_inlines.h" +#include "layer_inlines.h" +#include "funchash_core.h" + +#include "obj_pstk_draw.h" +#include "obj_line_draw.h" +#include "obj_arc_draw.h" +#include "obj_rat_draw.h" +#include "obj_poly_draw.h" +#include "obj_text_draw.h" +#include "obj_subc_parent.h" + +#undef NDEBUG +#include + +#define SMALL_SMALL_TEXT_SIZE 0 +#define SMALL_TEXT_SIZE 1 +#define NORMAL_TEXT_SIZE 2 +#define LARGE_TEXT_SIZE 3 +#define N_TEXT_SIZES 4 + +pcb_output_t pcb_draw_out; /* global context used for drawing */ + +pcb_box_t pcb_draw_invalidated = { COORD_MAX, COORD_MAX, -COORD_MAX, -COORD_MAX }; + +int pcb_draw_force_termlab = 0; +pcb_bool pcb_draw_doing_assy = pcb_false; +static vtp0_t delayed_labels, delayed_objs, annot_objs; +pcb_bool delayed_labels_enabled = pcb_false; +pcb_bool delayed_terms_enabled = pcb_false; + +static void draw_everything(pcb_draw_info_t *info); +static void pcb_draw_layer_grp(pcb_draw_info_t *info, int, int); +static void pcb_draw_obj_label(pcb_draw_info_t *info, pcb_layergrp_id_t gid, pcb_any_obj_t *obj); +static void pcb_draw_pstk_marks(pcb_draw_info_t *info); +static void pcb_draw_pstk_labels(pcb_draw_info_t *info); +static void pcb_draw_pstk_holes(pcb_draw_info_t *info, pcb_layergrp_id_t group, pcb_pstk_draw_hole_t holetype); +static void pcb_draw_ppv(pcb_draw_info_t *info, pcb_layergrp_id_t group); + +/* In draw_ly_spec.c: */ +static void pcb_draw_paste(pcb_draw_info_t *info, int side); +static void pcb_draw_mask(pcb_draw_info_t *info, int side); +static void pcb_draw_silk_doc(pcb_draw_info_t *info, pcb_layer_type_t lyt_side, pcb_layer_type_t lyt_type, int setgrp, int invis); +static void pcb_draw_boundary_mech(pcb_draw_info_t *info); +static void pcb_draw_rats(const pcb_box_t *); +static void pcb_draw_assembly(pcb_draw_info_t *info, pcb_layer_type_t lyt_side); + + +void pcb_draw_delay_label_add(pcb_any_obj_t *obj) +{ + if (delayed_labels_enabled) + vtp0_append(&delayed_labels, obj); +} + +void pcb_draw_delay_obj_add(pcb_any_obj_t *obj) +{ + vtp0_append(&delayed_objs, obj); +} + +void pcb_draw_annotation_add(pcb_any_obj_t *obj) +{ + vtp0_append(&annot_objs, obj); +} + + +TODO("cleanup: this should be cached") +void pcb_lighten_color(const pcb_color_t *orig, pcb_color_t *dst, double factor) +{ + pcb_color_load_int(dst, MIN(255, orig->r * factor), MIN(255, orig->g * factor), MIN(255, orig->b * factor), 255); +} + +void pcb_draw_dashed_line(pcb_draw_info_t *info, pcb_hid_gc_t GC, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2, unsigned int segs, pcb_bool_t cheap) +{ +/* TODO: we need a real geo lib... using double here is plain wrong */ + double dx = x2-x1, dy = y2-y1; + double len_mnt = PCB_ABS(dx) + PCB_ABS(dy); + int n; + pcb_coord_t minlen = pcb_gui->coord_per_pix * 8; + + /* Ignore info->xform->bloat because a dashed line is always thin */ + + if (len_mnt < minlen*2) { + /* line too short, just draw it */ + pcb_gui->draw_line(GC, x1, y1, x2, y2); + return; + } + + segs = (segs << 1) + 1; /* must be odd */ + + if (cheap) { + if ((segs > 3) && (len_mnt < minlen * segs)) + segs = 3; + else if ((segs > 5) && (len_mnt < minlen * 2 * segs)) + segs = 5; + } + + /* first seg is drawn from x1, y1 with no rounding error due to n-1 == 0 */ + for(n = 1; n < segs; n+=2) + pcb_gui->draw_line(GC, + x1 + (dx * (double)(n-1) / (double)segs), y1 + (dy * (double)(n-1) / (double)segs), + x1 + (dx * (double)n / (double)segs), y1 + (dy * (double)n / (double)segs)); + + + /* make sure the last segment is drawn properly to x2 and y2, don't leave + room for rounding errors */ + pcb_gui->draw_line(GC, + x2 - (dx / (double)segs), y2 - (dy / (double)segs), + x2, y2); +} + + +/* + * initiate the actual redrawing of the updated area + */ +pcb_cardinal_t pcb_draw_inhibit = 0; +void pcb_draw(void) +{ + if (pcb_draw_inhibit) + return; + if (pcb_draw_invalidated.X1 <= pcb_draw_invalidated.X2 && pcb_draw_invalidated.Y1 <= pcb_draw_invalidated.Y2) + pcb_gui->invalidate_lr(pcb_draw_invalidated.X1, pcb_draw_invalidated.X2, pcb_draw_invalidated.Y1, pcb_draw_invalidated.Y2); + + /* shrink the update block */ + pcb_draw_invalidated.X1 = pcb_draw_invalidated.Y1 = COORD_MAX; + pcb_draw_invalidated.X2 = pcb_draw_invalidated.Y2 = -COORD_MAX; +} + +/* ---------------------------------------------------------------------- + * redraws all the data by the event handlers + */ +void pcb_redraw(void) +{ + pcb_gui->invalidate_all(); +} + +static void draw_everything_holes(pcb_draw_info_t *info, pcb_layergrp_id_t gid) +{ + int plated, unplated; + pcb_board_count_holes(PCB, &plated, &unplated, info->drawn_area); + + if (plated && pcb_layer_gui_set_vlayer(PCB, PCB_VLY_PLATED_DRILL, 0, &info->xform_exporter)) { + pcb_draw_pstk_holes(info, gid, PCB_PHOLE_PLATED); + pcb_gui->end_layer(); + } + + if (unplated && pcb_layer_gui_set_vlayer(PCB, PCB_VLY_UNPLATED_DRILL, 0, &info->xform_exporter)) { + pcb_draw_pstk_holes(info, gid, PCB_PHOLE_UNPLATED); + pcb_gui->end_layer(); + } +} + +static void draw_virtual_layers(pcb_draw_info_t *info) +{ + pcb_hid_expose_ctx_t hid_exp; + + hid_exp.view = *info->drawn_area; + + if (pcb_layer_gui_set_vlayer(PCB, PCB_VLY_TOP_ASSY, 0, &info->xform_exporter)) { + pcb_draw_assembly(info, PCB_LYT_TOP); + pcb_gui->end_layer(); + } + + if (pcb_layer_gui_set_vlayer(PCB, PCB_VLY_BOTTOM_ASSY, 0, &info->xform_exporter)) { + pcb_draw_assembly(info, PCB_LYT_BOTTOM); + pcb_gui->end_layer(); + } + + if (pcb_layer_gui_set_vlayer(PCB, PCB_VLY_FAB, 0, &info->xform_exporter)) { + pcb_stub_draw_fab(info, pcb_draw_out.fgGC, &hid_exp); + pcb_gui->end_layer(); + } + + if (pcb_layer_gui_set_vlayer(PCB, PCB_VLY_CSECT, 0, &info->xform_exporter)) { + pcb_stub_draw_csect(pcb_draw_out.fgGC, &hid_exp); + pcb_gui->end_layer(); + } +} + +static void draw_ui_layers(pcb_draw_info_t *info) +{ + int i; + pcb_layer_t *first, *ly; + + /* find the first ui layer in use */ + first = NULL; + for(i = 0; i < vtp0_len(&pcb_uilayers); i++) { + if (pcb_uilayers.array[i] != NULL) { + first = pcb_uilayers.array[i]; + break; + } + } + + /* if there's any UI layer, try to draw them */ + if ((first != NULL) && pcb_layer_gui_set_g_ui(first, 0, &info->xform_exporter)) { + int have_canvas = 0; + for(i = 0; i < vtp0_len(&pcb_uilayers); i++) { + ly = pcb_uilayers.array[i]; + if ((ly != NULL) && (ly->meta.real.vis)) { + if (!have_canvas) { + pcb_gui->set_drawing_mode(PCB_HID_COMP_RESET, pcb_draw_out.direct, info->drawn_area); + pcb_gui->set_drawing_mode(PCB_HID_COMP_POSITIVE, pcb_draw_out.direct, info->drawn_area); + have_canvas = 1; + } + pcb_draw_layer(info, ly); + } + } + if (have_canvas) + pcb_gui->set_drawing_mode(PCB_HID_COMP_FLUSH, pcb_draw_out.direct, info->drawn_area); + pcb_gui->end_layer(); + } +} + +/* Draw subc and padstack marks in xor mode */ +static void draw_xor_marks(pcb_draw_info_t *info) +{ + int per_side = conf_core.appearance.subc_layer_per_side; + pcb_gui->set_drawing_mode(PCB_HID_COMP_RESET, pcb_draw_out.direct, info->drawn_area); + pcb_gui->set_drawing_mode(PCB_HID_COMP_POSITIVE_XOR, pcb_draw_out.direct, info->drawn_area); + + pcb_hid_set_line_cap(pcb_draw_out.fgGC, pcb_cap_round); + pcb_hid_set_line_width(pcb_draw_out.fgGC, 0); + pcb_hid_set_draw_xor(pcb_draw_out.fgGC, 1); + + if (PCB->SubcOn) { + info->objcb.subc.per_side = per_side; + pcb_r_search(PCB->Data->subc_tree, info->drawn_area, NULL, draw_subc_mark_callback, info, NULL); + } + + if ((PCB->padstack_mark_on) && (conf_core.appearance.padstack.cross_thick > 0)) { + pcb_hid_set_line_width(pcb_draw_out.fgGC, -conf_core.appearance.padstack.cross_thick); + pcb_draw_pstk_marks(info); + } + + pcb_event(PCB_EVENT_GUI_DRAW_OVERLAY_XOR, NULL); + + pcb_hid_set_draw_xor(pcb_draw_out.fgGC, 0); + pcb_gui->set_drawing_mode(PCB_HID_COMP_FLUSH, pcb_draw_out.direct, info->drawn_area); +} + +static void draw_rats(const pcb_box_t *drawn_area) +{ + if (pcb_layer_gui_set_vlayer(PCB, PCB_VLY_RATS, 0, NULL)) { + pcb_gui->set_drawing_mode(PCB_HID_COMP_RESET, pcb_draw_out.direct, drawn_area); + pcb_gui->set_drawing_mode(PCB_HID_COMP_POSITIVE, pcb_draw_out.direct, drawn_area); + pcb_draw_rats(drawn_area); + pcb_gui->set_drawing_mode(PCB_HID_COMP_FLUSH, pcb_draw_out.direct, drawn_area); + pcb_gui->end_layer(); + } +} + +static void draw_pins_and_pads(pcb_draw_info_t *info, pcb_layergrp_id_t component, pcb_layergrp_id_t solder) +{ + int per_side = conf_core.appearance.subc_layer_per_side; + + pcb_gui->set_drawing_mode(PCB_HID_COMP_RESET, pcb_draw_out.direct, info->drawn_area); + pcb_gui->set_drawing_mode(PCB_HID_COMP_POSITIVE, pcb_draw_out.direct, info->drawn_area); + + /* Draw pins' and pads' names */ + pcb_gui->set_drawing_mode(PCB_HID_COMP_RESET, pcb_draw_out.direct, info->drawn_area); + pcb_gui->set_drawing_mode(PCB_HID_COMP_POSITIVE, pcb_draw_out.direct, info->drawn_area); + pcb_hid_set_line_cap(pcb_draw_out.fgGC, pcb_cap_round); + pcb_hid_set_line_width(pcb_draw_out.fgGC, 0); + if (PCB->SubcOn) { + info->objcb.subc.per_side = per_side; + pcb_r_search(PCB->Data->subc_tree, info->drawn_area, NULL, draw_subc_label_callback, info, NULL); + } + if (PCB->padstack_mark_on) { + pcb_hid_set_line_width(pcb_draw_out.fgGC, -conf_core.appearance.padstack.cross_thick); + pcb_draw_pstk_labels(info); + } + pcb_draw_pstk_names(info, conf_core.editor.show_solder_side ? solder : component, info->drawn_area); + pcb_gui->set_drawing_mode(PCB_HID_COMP_FLUSH, pcb_draw_out.direct, info->drawn_area); +} + + +static void draw_everything(pcb_draw_info_t *info) +{ + pcb_layer_t *backsilk; + pcb_color_t old_silk_color; + int i, ngroups; + pcb_layergrp_id_t component, solder, gid, side_copper_grp; + /* This is the list of layer groups we will draw. */ + char do_group[PCB_MAX_LAYERGRP]; + /* This is the reverse of the order in which we draw them. */ + pcb_layergrp_id_t drawn_groups[PCB_MAX_LAYERGRP]; + pcb_bool paste_empty; + + backsilk = pcb_layer_silk_back(PCB); + if (backsilk != NULL) { + old_silk_color = backsilk->meta.real.color; + backsilk->meta.real.color = conf_core.appearance.color.invisible_objects; + } + + pcb_gui->render_burst(PCB_HID_BURST_START, info->drawn_area); + + memset(do_group, 0, sizeof(do_group)); + for (ngroups = 0, i = 0; i < pcb_max_layer; i++) { + pcb_layer_t *l = LAYER_ON_STACK(i); + pcb_layergrp_id_t group = pcb_layer_get_group(PCB, pcb_layer_stack[i]); + unsigned int gflg = pcb_layergrp_flags(PCB, group); + + if ((gflg & PCB_LYT_SILK) || (gflg & PCB_LYT_DOC) || (gflg & PCB_LYT_MASK) || (gflg & PCB_LYT_PASTE) || (gflg & PCB_LYT_BOUNDARY) || (gflg & PCB_LYT_MECH)) /* do not draw silk, mask, paste and boundary here, they'll be drawn separately */ + continue; + + if (l->meta.real.vis && !do_group[group]) { + do_group[group] = 1; + drawn_groups[ngroups++] = group; + } + } + + solder = component = -1; + pcb_layergrp_list(PCB, PCB_LYT_BOTTOM | PCB_LYT_COPPER, &solder, 1); + pcb_layergrp_list(PCB, PCB_LYT_TOP | PCB_LYT_COPPER, &component, 1); + side_copper_grp = conf_core.editor.show_solder_side ? solder : component; + + + /* + * first draw all 'invisible' stuff + */ + if (!conf_core.editor.check_planes && pcb_layer_gui_set_vlayer(PCB, PCB_VLY_INVISIBLE, 0, &info->xform_exporter)) { + pcb_layer_type_t side = PCB_LYT_INVISIBLE_SIDE(); + pcb_draw_silk_doc(info, side, PCB_LYT_DOC, 0, 1); + pcb_draw_silk_doc(info, side, PCB_LYT_SILK, 0, 1); + + pcb_gui->set_drawing_mode(PCB_HID_COMP_RESET, pcb_draw_out.direct, info->drawn_area); + pcb_gui->set_drawing_mode(PCB_HID_COMP_POSITIVE, pcb_draw_out.direct, info->drawn_area); + pcb_gui->set_drawing_mode(PCB_HID_COMP_FLUSH, pcb_draw_out.direct, info->drawn_area); + pcb_gui->end_layer(); + } + + /* Draw far side doc and silks */ + { + pcb_layer_type_t ivside = PCB_LYT_INVISIBLE_SIDE(); + + pcb_draw_silk_doc(info, ivside, PCB_LYT_SILK, 1, 0); + pcb_draw_silk_doc(info, ivside, PCB_LYT_DOC, 1, 0); + } + + /* draw all layers in layerstack order */ + for (i = ngroups - 1; i >= 0; i--) { + pcb_layergrp_id_t group = drawn_groups[i]; + + if (pcb_layer_gui_set_glayer(PCB, group, 0, &info->xform_exporter)) { + int is_current = 0; + pcb_layergrp_id_t cgrp = CURRENT->meta.real.grp; + + if ((cgrp == solder) || (cgrp == component)) { + /* current group is top or bottom: visibility depends on side we are looking at */ + if (group == side_copper_grp) + is_current = 1; + } + else { + /* internal layer displayed on top: current group is solid, others are "invisible" */ + if (group == cgrp) + is_current = 1; + } + + pcb_draw_layer_grp(info, group, is_current); + pcb_gui->end_layer(); + } + } + + if (conf_core.editor.check_planes && pcb_gui->gui) + goto finish; + + /* Draw padstacks below silk */ + pcb_gui->set_drawing_mode(PCB_HID_COMP_RESET, pcb_draw_out.direct, info->drawn_area); + pcb_gui->set_drawing_mode(PCB_HID_COMP_POSITIVE, pcb_draw_out.direct, info->drawn_area); + if (pcb_gui->gui) + pcb_draw_ppv(info, conf_core.editor.show_solder_side ? solder : component); + pcb_gui->set_drawing_mode(PCB_HID_COMP_FLUSH, pcb_draw_out.direct, info->drawn_area); + + /* Draw the solder mask if turned on */ + gid = pcb_layergrp_get_top_mask(); + if ((gid >= 0) && (pcb_layer_gui_set_glayer(PCB, gid, 0, &info->xform_exporter))) { + pcb_draw_mask(info, PCB_COMPONENT_SIDE); + pcb_gui->end_layer(); + } + + gid = pcb_layergrp_get_bottom_mask(); + if ((gid >= 0) && (pcb_layer_gui_set_glayer(PCB, gid, 0, &info->xform_exporter))) { + pcb_draw_mask(info, PCB_SOLDER_SIDE); + pcb_gui->end_layer(); + } + + /* Draw doc and silks */ + { + pcb_layer_type_t vside = PCB_LYT_VISIBLE_SIDE(); + + pcb_draw_silk_doc(info, PCB_LYT_INTERN, PCB_LYT_SILK, 1, 0); + pcb_draw_silk_doc(info, PCB_LYT_INTERN, PCB_LYT_DOC, 1, 0); + pcb_draw_silk_doc(info, 0, PCB_LYT_DOC, 1, 0); + pcb_draw_silk_doc(info, vside, PCB_LYT_SILK, 1, 0); + pcb_draw_silk_doc(info, vside, PCB_LYT_DOC, 1, 0); + } + + { /* holes_after: draw holes after copper, silk and mask, to make sure it punches through everything. */ + pcb_gui->set_drawing_mode(PCB_HID_COMP_RESET, pcb_draw_out.direct, info->drawn_area); + pcb_gui->set_drawing_mode(PCB_HID_COMP_POSITIVE, pcb_draw_out.direct, info->drawn_area); + draw_everything_holes(info, side_copper_grp); + pcb_gui->set_drawing_mode(PCB_HID_COMP_FLUSH, pcb_draw_out.direct, info->drawn_area); + } + + gid = pcb_layergrp_get_top_paste(); + if (gid >= 0) + paste_empty = pcb_layergrp_is_empty(PCB, gid); + if ((gid >= 0) && (pcb_layer_gui_set_glayer(PCB, gid, paste_empty, &info->xform_exporter))) { + pcb_draw_paste(info, PCB_COMPONENT_SIDE); + pcb_gui->end_layer(); + } + + gid = pcb_layergrp_get_bottom_paste(); + if (gid >= 0) + paste_empty = pcb_layergrp_is_empty(PCB, gid); + if ((gid >= 0) && (pcb_layer_gui_set_glayer(PCB, gid, paste_empty, &info->xform_exporter))) { + pcb_draw_paste(info, PCB_SOLDER_SIDE); + pcb_gui->end_layer(); + } + + pcb_draw_boundary_mech(info); + + draw_virtual_layers(info); + if (pcb_gui->gui) { + draw_rats(info->drawn_area); + draw_pins_and_pads(info, component, solder); + } + draw_ui_layers(info); + + if (pcb_gui->gui) + draw_xor_marks(info); + + finish:; + pcb_gui->render_burst(PCB_HID_BURST_END, info->drawn_area); + if (backsilk != NULL) + backsilk->meta.real.color = old_silk_color; +} + +static void pcb_draw_pstks(pcb_draw_info_t *info, pcb_layergrp_id_t group, int is_current, pcb_layer_combining_t comb) +{ + pcb_layergrp_t *g = PCB->LayerGroups.grp + group; + + info->objcb.pstk.gid = group; + info->objcb.pstk.is_current = is_current; + info->objcb.pstk.comb = comb; + if (g->len > 0) + info->objcb.pstk.layer1 = pcb_get_layer(info->pcb->Data, g->lid[0]); + else + info->objcb.pstk.layer1 = NULL; + pcb_r_search(info->pcb->Data->padstack_tree, info->drawn_area, NULL, pcb_pstk_draw_callback, info, NULL); +} + +static void pcb_draw_pstk_marks(pcb_draw_info_t *info) +{ + pcb_r_search(PCB->Data->padstack_tree, info->drawn_area, NULL, pcb_pstk_draw_mark_callback, info, NULL); +} + +static void pcb_draw_pstk_labels(pcb_draw_info_t *info) +{ + pcb_r_search(PCB->Data->padstack_tree, info->drawn_area, NULL, pcb_pstk_draw_label_callback, info, NULL); +} + +static void pcb_draw_pstk_holes(pcb_draw_info_t *info, pcb_layergrp_id_t group, pcb_pstk_draw_hole_t holetype) +{ + if (!PCB->hole_on) + return; + + info->objcb.pstk.gid = group; + info->objcb.pstk.holetype = holetype; + pcb_r_search(PCB->Data->padstack_tree, info->drawn_area, NULL, pcb_pstk_draw_hole_callback, info, NULL); +} + +static void pcb_draw_pstk_slots(pcb_draw_info_t *info, pcb_layergrp_id_t group, pcb_pstk_draw_hole_t holetype) +{ + if (!PCB->hole_on) + return; + + info->objcb.pstk.gid = group; + info->objcb.pstk.holetype = holetype; + pcb_r_search(PCB->Data->padstack_tree, info->drawn_area, NULL, pcb_pstk_draw_slot_callback, info, NULL); +} + +/* --------------------------------------------------------------------------- + * Draws padstacks - Always draws for non-gui HIDs, + * otherwise drawing depends on PCB->pstk_on + */ +static void pcb_draw_ppv(pcb_draw_info_t *info, pcb_layergrp_id_t group) +{ + /* draw padstack holes - copper is drawn with each group */ + if (PCB->pstk_on || !pcb_gui->gui) { + pcb_draw_pstk_holes(info, group, PCB_PHOLE_PLATED | PCB_PHOLE_UNPLATED | PCB_PHOLE_BB); + } +} + +/* --------------------------------------------------------------------------- + * Draws padstacks' names - Always draws for non-gui HIDs, + * otherwise drawing depends on PCB->pstk_on + */ +void pcb_draw_pstk_names(pcb_draw_info_t *info, pcb_layergrp_id_t group, const pcb_box_t *drawn_area) +{ + if (PCB->pstk_on || !pcb_gui->gui) { + size_t n; + for(n = 0; n < delayed_labels.used; n++) + pcb_draw_obj_label(info, group, delayed_labels.array[n]); + } + delayed_labels.used = 0; +} + +static void pcb_draw_delayed_objs(pcb_draw_info_t *info) +{ + size_t n; + + for(n = 0; n < delayed_objs.used; n++) { + pcb_any_obj_t *o = delayed_objs.array[n]; + pcb_box_t *b = (pcb_box_t *)o; + switch(o->type) { + case PCB_OBJ_ARC: pcb_arc_draw_term_callback(b, info); break; + case PCB_OBJ_LINE: pcb_line_draw_term_callback(b, info); break; + case PCB_OBJ_TEXT: pcb_text_draw_term_callback(b, info); break; + case PCB_OBJ_POLY: pcb_poly_draw_term_callback(b, info); break; + default: + assert(!"Don't know how to draw delayed object"); + } + } + vtp0_truncate(&delayed_objs, 0); +} + +static void pcb_draw_annotations(pcb_draw_info_t *info) +{ + size_t n; + + for(n = 0; n < annot_objs.used; n++) { + pcb_any_obj_t *o = annot_objs.array[n]; + switch(o->type) { + case PCB_OBJ_POLY: pcb_poly_draw_annotation(info, (pcb_poly_t *)o); break; + default: + assert(!"Don't know how to draw annotation for object"); + } + } + vtp0_truncate(&annot_objs, 0); +} + +#include "draw_composite.c" +#include "draw_ly_spec.c" + +static void xform_setup(pcb_draw_info_t *info, pcb_xform_t *dst, const pcb_layer_t *Layer) +{ + info->layer = Layer; + if ((Layer != NULL) && (!pcb_xform_is_nop(&Layer->meta.real.xform))) { + pcb_xform_copy(dst, &Layer->meta.real.xform); + info->xform = dst; + } + if (info->xform_caller != NULL) { + if (info->xform == NULL) { + info->xform = dst; + pcb_xform_copy(dst, info->xform_caller); + } + else + pcb_xform_add(dst, info->xform_caller); + } + if (info->xform_exporter != NULL) { + if (info->xform == NULL) { + info->xform = dst; + pcb_xform_copy(dst, info->xform_exporter); + } + else + pcb_xform_add(dst, info->xform_exporter); + } +} + +void pcb_draw_layer(pcb_draw_info_t *info, const pcb_layer_t *Layer_) +{ + unsigned int lflg = 0; + int may_have_delayed = 0, restore_color = 0, current_grp; + pcb_xform_t xform; + pcb_color_t orig_color; + pcb_layer_t *Layer = (pcb_layer_t *)Layer_; /* ugly hack until layer color is moved into info */ + + xform_setup(info, &xform, Layer); + + current_grp = (Layer_->meta.real.grp == CURRENT->meta.real.grp); + + if ((info->xform != NULL) && (info->xform->layer_faded)) { + orig_color = Layer->meta.real.color; + pcb_lighten_color(&orig_color, &Layer->meta.real.color, 0.5); + restore_color = 1; + } + else if (conf_core.appearance.invis_other_groups && !current_grp) { + orig_color = Layer->meta.real.color; + Layer->meta.real.color = conf_core.appearance.color.invisible_objects; + restore_color = 1; + } + + if (conf_core.appearance.black_current_group && current_grp) { + if (!restore_color) { + orig_color = Layer->meta.real.color; + restore_color = 1; + Layer->meta.real.color = *pcb_color_black; + } + } + + lflg = pcb_layer_flags_(Layer); + if (PCB_LAYERFLG_ON_VISIBLE_SIDE(lflg)) + pcb_draw_out.active_padGC = pcb_draw_out.padGC; + else + pcb_draw_out.active_padGC = pcb_draw_out.backpadGC; + + /* print the non-clearing polys */ + if (lflg & PCB_LYT_COPPER) { + delayed_terms_enabled = pcb_true; + pcb_hid_set_line_width(pcb_draw_out.fgGC, 1); + pcb_hid_set_line_cap(pcb_draw_out.fgGC, pcb_cap_square); + pcb_r_search(Layer->polygon_tree, info->drawn_area, NULL, pcb_poly_draw_term_callback, info, NULL); + delayed_terms_enabled = pcb_false; + may_have_delayed = 1; + } + else { + pcb_r_search(Layer->polygon_tree, info->drawn_area, NULL, pcb_poly_draw_callback, info, NULL); + } + + if (conf_core.editor.check_planes) + goto out; + + /* draw all visible layer objects (with terminal gfx on copper) */ + if (lflg & PCB_LYT_COPPER) { + delayed_terms_enabled = pcb_true; + pcb_r_search(Layer->line_tree, info->drawn_area, NULL, pcb_line_draw_term_callback, info, NULL); + pcb_r_search(Layer->arc_tree, info->drawn_area, NULL, pcb_arc_draw_term_callback, info, NULL); + pcb_r_search(Layer->text_tree, info->drawn_area, NULL, pcb_text_draw_term_callback, info, NULL); + delayed_terms_enabled = pcb_false; + may_have_delayed = 1; + } + else { + pcb_r_search(Layer->line_tree, info->drawn_area, NULL, pcb_line_draw_callback, info, NULL); + pcb_r_search(Layer->arc_tree, info->drawn_area, NULL, pcb_arc_draw_callback, info, NULL); + pcb_r_search(Layer->text_tree, info->drawn_area, NULL, pcb_text_draw_callback, info, NULL); + } + + if (may_have_delayed) + pcb_draw_delayed_objs(info); + pcb_draw_annotations(info); + + out:; + pcb_draw_out.active_padGC = NULL; + + if (restore_color) + Layer->meta.real.color = orig_color; + + info->layer = NULL; + info->xform = NULL; +} + +void pcb_draw_layer_noxform(pcb_board_t *pcb, const pcb_layer_t *Layer, const pcb_box_t *screen) +{ + pcb_draw_info_t info; + pcb_box_t scr2; + + info.pcb = pcb; + info.drawn_area = screen; + info.xform_exporter = info.xform = NULL; + + /* fix screen coord order */ + if ((screen->X2 <= screen->X1) || (screen->Y2 <= screen->Y1)) { + scr2 = *screen; + info.drawn_area = &scr2; + if (scr2.X2 <= scr2.X1) + scr2.X2 = scr2.X1+1; + if (scr2.Y2 <= scr2.Y1) + scr2.Y2 = scr2.Y1+1; + } + + pcb_draw_layer(&info, Layer); +} + + +/* This version is about 1% slower and used rarely, thus it's all dupped + from pcb_draw_layer() to keep the original speed there */ +void pcb_draw_layer_under(pcb_board_t *pcb, const pcb_layer_t *Layer, const pcb_box_t *screen, pcb_data_t *data) +{ + pcb_draw_info_t info; + pcb_box_t scr2; + unsigned int lflg = 0; + pcb_rtree_it_t it; + pcb_any_obj_t *o; + pcb_xform_t tmp; + + if ((screen->X2 <= screen->X1) || (screen->Y2 <= screen->Y1)) { + scr2 = *screen; + screen = &scr2; + if (scr2.X2 <= scr2.X1) + scr2.X2 = scr2.X1+1; + if (scr2.Y2 <= scr2.Y1) + scr2.Y2 = scr2.Y1+1; + } + + info.pcb = pcb; + info.drawn_area = screen; + info.xform_exporter = info.xform_caller = info.xform = NULL; + + xform_setup(&info, &tmp, Layer); + + lflg = pcb_layer_flags_(Layer); + if (PCB_LAYERFLG_ON_VISIBLE_SIDE(lflg)) + pcb_draw_out.active_padGC = pcb_draw_out.padGC; + else + pcb_draw_out.active_padGC = pcb_draw_out.backpadGC; + + /* print the non-clearing polys */ + if (Layer->polygon_tree != NULL) { + if (lflg & PCB_LYT_COPPER) { + for(o = pcb_rtree_first(&it, Layer->polygon_tree, (pcb_rtree_box_t *)screen); o != NULL; o = pcb_rtree_next(&it)) + if (pcb_obj_is_under(o, data)) + pcb_poly_draw_term_callback((pcb_box_t *)o, &info); + } + else { + for(o = pcb_rtree_first(&it, Layer->polygon_tree, (pcb_rtree_box_t *)screen); o != NULL; o = pcb_rtree_next(&it)) + if (pcb_obj_is_under(o, data)) + pcb_poly_draw_callback((pcb_box_t *)o, &info); + } + } + + if (conf_core.editor.check_planes) + goto out; + + /* draw all visible layer objects (with terminal gfx on copper) */ + if (lflg & PCB_LYT_COPPER) { + if (Layer->line_tree != NULL) + for(o = pcb_rtree_first(&it, Layer->line_tree, (pcb_rtree_box_t *)screen); o != NULL; o = pcb_rtree_next(&it)) + if (pcb_obj_is_under(o, data)) + pcb_line_draw_term_callback((pcb_box_t *)o, &info); + if (Layer->arc_tree != NULL) + for(o = pcb_rtree_first(&it, Layer->arc_tree, (pcb_rtree_box_t *)screen); o != NULL; o = pcb_rtree_next(&it)) + if (pcb_obj_is_under(o, data)) + pcb_arc_draw_term_callback((pcb_box_t *)o, &info); + if (Layer->text_tree != NULL) + for(o = pcb_rtree_first(&it, Layer->text_tree, (pcb_rtree_box_t *)screen); o != NULL; o = pcb_rtree_next(&it)) + if (pcb_obj_is_under(o, data)) + pcb_text_draw_term_callback((pcb_box_t *)o, &info); + } + else { + if (Layer->line_tree != NULL) + for(o = pcb_rtree_first(&it, Layer->line_tree, (pcb_rtree_box_t *)screen); o != NULL; o = pcb_rtree_next(&it)) + if (pcb_obj_is_under(o, data)) + pcb_line_draw_callback((pcb_box_t *)o, &info); + if (Layer->arc_tree != NULL) + for(o = pcb_rtree_first(&it, Layer->arc_tree, (pcb_rtree_box_t *)screen); o != NULL; o = pcb_rtree_next(&it)) + if (pcb_obj_is_under(o, data)) + pcb_arc_draw_callback((pcb_box_t *)o, &info); + if (Layer->text_tree != NULL) + for(o = pcb_rtree_first(&it, Layer->text_tree, (pcb_rtree_box_t *)screen); o != NULL; o = pcb_rtree_next(&it)) + if (pcb_obj_is_under(o, data)) + pcb_text_draw_callback((pcb_box_t *)o, &info); + } + + out:; + pcb_draw_out.active_padGC = NULL; + + info.layer = NULL; + info.xform = NULL; +} + +/* --------------------------------------------------------------------------- + * draws one layer group. If the exporter is not a GUI, + * also draws the padstacks in this layer group. + */ +static void pcb_draw_layer_grp(pcb_draw_info_t *info, int group, int is_current) +{ + int i; + pcb_layer_id_t layernum; + pcb_layer_t *Layer; + pcb_cardinal_t n_entries = PCB->LayerGroups.grp[group].len; + pcb_layer_id_t *layers = PCB->LayerGroups.grp[group].lid; + pcb_layergrp_t *grp = pcb_get_layergrp(PCB, group); + unsigned int gflg = grp->ltype; + + pcb_gui->set_drawing_mode(PCB_HID_COMP_RESET, pcb_draw_out.direct, info->drawn_area); + pcb_gui->set_drawing_mode(PCB_HID_COMP_POSITIVE, pcb_draw_out.direct, info->drawn_area); + + for (i = n_entries - 1; i >= 0; i--) { + layernum = layers[i]; + Layer = info->pcb->Data->Layer + layernum; + if (!(gflg & PCB_LYT_SILK) && Layer->meta.real.vis) + pcb_draw_layer(info, Layer); + } + + if ((gflg & PCB_LYT_COPPER) && (PCB->pstk_on)) { + pcb_xform_t tmp; + const pcb_layer_t *ly1 = NULL; + + /* figure first layer to get the transformations from */ + if (n_entries > 0) + ly1 = info->pcb->Data->Layer + layers[0]; + + xform_setup(info, &tmp, ly1); + pcb_draw_pstks(info, group, (CURRENT->meta.real.grp == group), 0); + info->xform = NULL; + info->layer = NULL; + } + + /* this draws the holes - must be the last, so holes are drawn over everything else */ + if (!pcb_gui->gui) + pcb_draw_ppv(info, group); + + pcb_gui->set_drawing_mode(PCB_HID_COMP_FLUSH, pcb_draw_out.direct, info->drawn_area); +} + +void pcb_erase_obj(int type, void *lptr, void *ptr) +{ + if (pcb_hidden_floater((pcb_any_obj_t *)ptr)) + return; + + switch (type) { + case PCB_OBJ_PSTK: + pcb_pstk_invalidate_erase((pcb_pstk_t *) ptr); + break; + + case PCB_OBJ_TEXT: + pcb_text_invalidate_erase((pcb_layer_t *) lptr, (pcb_text_t *) ptr); + break; + case PCB_OBJ_POLY: + pcb_poly_invalidate_erase((pcb_poly_t *) ptr); + break; + case PCB_OBJ_SUBC: + EraseSubc((pcb_subc_t *)ptr); + break; + case PCB_OBJ_LINE: + case PCB_OBJ_RAT: + pcb_line_invalidate_erase((pcb_line_t *) ptr); + break; + case PCB_OBJ_ARC: + pcb_arc_invalidate_erase((pcb_arc_t *) ptr); + break; + default: + pcb_message(PCB_MSG_ERROR, "hace: Internal ERROR, trying to erase an unknown type\n"); + } +} + + +void pcb_draw_obj(pcb_any_obj_t *obj) +{ + if (pcb_hidden_floater(obj)) + return; + + switch (obj->type) { + case PCB_OBJ_PSTK: + if (PCB->pstk_on) + pcb_pstk_invalidate_draw((pcb_pstk_t *)obj); + break; + case PCB_OBJ_LINE: + if (obj->parent.layer->meta.real.vis) + pcb_line_invalidate_draw(obj->parent.layer, (pcb_line_t *)obj); + break; + case PCB_OBJ_ARC: + if (obj->parent.layer->meta.real.vis) + pcb_arc_invalidate_draw(obj->parent.layer, (pcb_arc_t *)obj); + break; + case PCB_OBJ_TEXT: + if (obj->parent.layer->meta.real.vis) + pcb_text_invalidate_draw(obj->parent.layer, (pcb_text_t *)obj); + break; + case PCB_OBJ_POLY: + if (obj->parent.layer->meta.real.vis) + pcb_poly_invalidate_draw(obj->parent.layer, (pcb_poly_t *)obj); + break; + case PCB_OBJ_RAT: + if (PCB->RatOn) + pcb_rat_invalidate_draw((pcb_rat_t *)obj); + break; + case PCB_OBJ_SUBC: + case PCB_OBJ_NET: + case PCB_OBJ_LAYER: + case PCB_OBJ_LAYERGRP: + case PCB_OBJ_VOID: + case PCB_OBJ_NET_TERM: + break; + } +} + +static void pcb_draw_obj_label(pcb_draw_info_t *info, pcb_layergrp_id_t gid, pcb_any_obj_t *obj) +{ + if (pcb_hidden_floater(obj)) + return; + + /* do not show layer-object labels of the other side on non-pinout views */ + if ((!pcb_draw_force_termlab) && (obj->parent_type == PCB_PARENT_LAYER)) { + pcb_layer_t *ly = pcb_layer_get_real(obj->parent.layer); + if ((ly != NULL) && (ly->meta.real.grp != gid)) + return; + } + + switch(obj->type) { + case PCB_OBJ_LINE: pcb_line_draw_label(info, (pcb_line_t *)obj); return; + case PCB_OBJ_ARC: pcb_arc_draw_label(info, (pcb_arc_t *)obj); return; + case PCB_OBJ_POLY: pcb_poly_draw_label(info, (pcb_poly_t *)obj); return; + case PCB_OBJ_TEXT: pcb_text_draw_label(info, (pcb_text_t *)obj); return; + case PCB_OBJ_PSTK: pcb_pstk_draw_label(info, (pcb_pstk_t *)obj); return; + default: break; + } +} + +/* --------------------------------------------------------------------------- + * HID drawing callback. + */ + +static void expose_begin(pcb_output_t *save, pcb_hid_t *hid) +{ + memcpy(save, &pcb_draw_out, sizeof(pcb_output_t)); + save->hid = pcb_gui; + + delayed_labels_enabled = pcb_true; + vtp0_truncate(&delayed_labels, 0); + vtp0_truncate(&delayed_objs, 0); + + pcb_gui = pcb_draw_out.hid = hid; + pcb_draw_out.fgGC = pcb_hid_make_gc(); + pcb_draw_out.padGC = pcb_hid_make_gc(); + pcb_draw_out.backpadGC = pcb_hid_make_gc(); + pcb_draw_out.padselGC = pcb_hid_make_gc(); + pcb_draw_out.drillGC = pcb_hid_make_gc(); + pcb_draw_out.pmGC = pcb_hid_make_gc(); + + if (hid->force_compositing) + pcb_draw_out.direct = 0; + else + pcb_draw_out.direct = 1; + + hid->set_color(pcb_draw_out.pmGC, pcb_color_cyan); + hid->set_color(pcb_draw_out.drillGC, pcb_color_drill); + hid->set_color(pcb_draw_out.padGC, &conf_core.appearance.color.pin); + hid->set_color(pcb_draw_out.backpadGC, &conf_core.appearance.color.invisible_objects); + hid->set_color(pcb_draw_out.padselGC, &conf_core.appearance.color.selected); + pcb_hid_set_line_width(pcb_draw_out.backpadGC, -1); + pcb_hid_set_line_cap(pcb_draw_out.backpadGC, pcb_cap_square); + pcb_hid_set_line_width(pcb_draw_out.padselGC, -1); + pcb_hid_set_line_cap(pcb_draw_out.padselGC, pcb_cap_square); + pcb_hid_set_line_width(pcb_draw_out.padGC, -1); + pcb_hid_set_line_cap(pcb_draw_out.padGC, pcb_cap_square); +} + +static void expose_end(pcb_output_t *save) +{ + pcb_hid_destroy_gc(pcb_draw_out.fgGC); + pcb_hid_destroy_gc(pcb_draw_out.padGC); + pcb_hid_destroy_gc(pcb_draw_out.backpadGC); + pcb_hid_destroy_gc(pcb_draw_out.padselGC); + pcb_hid_destroy_gc(pcb_draw_out.drillGC); + pcb_hid_destroy_gc(pcb_draw_out.pmGC); + + pcb_draw_out.fgGC = NULL; + + delayed_labels_enabled = pcb_false; + vtp0_truncate(&delayed_labels, 0); + vtp0_truncate(&delayed_objs, 0); + + memcpy(&pcb_draw_out, save, sizeof(pcb_output_t)); + pcb_gui = pcb_draw_out.hid; +} + +void pcb_hid_expose_all(pcb_hid_t * hid, const pcb_hid_expose_ctx_t *ctx, pcb_xform_t *xform_caller) +{ + if (!pcb_draw_inhibit) { + pcb_output_t save; + pcb_draw_info_t info; + + expose_begin(&save, hid); + info.pcb = PCB; + info.drawn_area = &ctx->view; + info.xform_caller = xform_caller; + info.xform = info.xform_exporter = NULL; + info.layer = NULL; + draw_everything(&info); + expose_end(&save); + } +} + +void pcb_hid_expose_generic(pcb_hid_t *hid, const pcb_hid_expose_ctx_t *e) +{ + pcb_output_t save; + expose_begin(&save, hid); + + pcb_gui->set_drawing_mode(PCB_HID_COMP_RESET, 1, &e->view); + pcb_gui->set_drawing_mode(PCB_HID_COMP_POSITIVE, 1, &e->view); + e->expose_cb(pcb_draw_out.fgGC, e); + pcb_gui->set_drawing_mode(PCB_HID_COMP_FLUSH, 1, &e->view); + pcb_gui->end_layer(); + + expose_end(&save); +} + +static const char *lab_with_intconn(const pcb_any_obj_t *term, int intconn, const char *lab, char *buff, int bufflen) +{ + if ((conf_core.editor.term_id != NULL) && (*conf_core.editor.term_id != '\0')) { + gds_t tmp; + if (pcb_append_dyntext(&tmp, term, conf_core.editor.term_id) == 0) { + int len = tmp.used < (bufflen-1) ? tmp.used : (bufflen-1); + memcpy(buff, tmp.array, len); + buff[len] = '\0'; + gds_uninit(&tmp); + return buff; + } + } + + /* fallback when template is not available or failed */ + if (intconn <= 0) + return lab; + pcb_snprintf(buff, bufflen, "%s[%d]", lab, intconn); + + return buff; +} + +/* vert flip magic: make sure the offset is in-line with the flip and our sick y coords for vertical */ +#define PCB_TERM_LABEL_SETUP(label) \ + pcb_bool flip_x = conf_core.editor.view.flip_x; \ + pcb_bool flip_y = conf_core.editor.view.flip_y; \ + pcb_font_t *font = pcb_font(PCB, 0, 0); \ + pcb_coord_t w, h, dx, dy; \ + if (vert) { \ + h = pcb_text_width(font, scale, label); \ + w = pcb_text_height(font, scale, label); \ + } \ + else { \ + w = pcb_text_width(font, scale, label); \ + h = pcb_text_height(font, scale, label); \ + } \ + dx = w / 2; \ + dy = h / 2; \ + if (flip_x) \ + dx = -dx; \ + if (flip_y) \ + dy = -dy; \ + if (vert) \ + dy = -dy; \ + if (centered) { \ + x -= dx; \ + y -= dy; \ + } + + +void pcb_label_draw(pcb_draw_info_t *info, pcb_coord_t x, pcb_coord_t y, double scale, pcb_bool vert, pcb_bool centered, const char *label) +{ + int mirror, direction; + PCB_TERM_LABEL_SETUP((const unsigned char *)label); + + mirror = (flip_x ^ flip_y); + direction = (vert ? 1 : 0) + (flip_x ? 2 : 0); + + pcb_gui->set_color(pcb_draw_out.fgGC, &conf_core.appearance.color.pin_name); + + if (pcb_gui->gui) + pcb_draw_force_termlab++; + pcb_text_draw_string(info, font, (unsigned const char *)label, x, y, scale, direction*90.0, mirror, 1, 0, 0, 0, 0, PCB_TXT_TINY_HIDE); + if (pcb_gui->gui) + pcb_draw_force_termlab--; +} + +void pcb_label_invalidate(pcb_coord_t x, pcb_coord_t y, double scale, pcb_bool vert, pcb_bool centered, const char *label) +{ + pcb_coord_t ox = x, oy = y, margin = 0; + pcb_box_t b; + PCB_TERM_LABEL_SETUP((const unsigned char *)label); + + dx = PCB_ABS(dx); + dy = PCB_ABS(dy); + b.X1 = ox - dx - margin; + b.X2 = ox + dx + margin; + b.Y1 = oy - dy - margin; + b.Y2 = oy + dy + margin; + + pcb_draw_invalidate(&b); +} + +void pcb_term_label_draw(pcb_draw_info_t *info, pcb_coord_t x, pcb_coord_t y, double scale, pcb_bool vert, pcb_bool centered, const pcb_any_obj_t *obj) +{ + char buff[128]; + const char *label = lab_with_intconn(obj, obj->intconn, obj->term, buff, sizeof(buff)); + pcb_label_draw(info, x, y, scale, vert, centered, label); +} + +void pcb_term_label_invalidate(pcb_coord_t x, pcb_coord_t y, double scale, pcb_bool vert, pcb_bool centered, const pcb_any_obj_t *obj) +{ + char buff[128]; + const char *label = lab_with_intconn(obj, obj->intconn, obj->term, buff, sizeof(buff)); + pcb_label_invalidate(x, y, scale, vert, centered, label); +} + Index: tags/2.1.2/src/draw.h =================================================================== --- tags/2.1.2/src/draw.h (nonexistent) +++ tags/2.1.2/src/draw.h (revision 24813) @@ -0,0 +1,188 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996, 2004 Thomas Nau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +#ifndef PCB_DRAW_H +#define PCB_DRAW_H + +#include "config.h" +#include "hid.h" + +/* holds information about output window */ +typedef struct { + pcb_hid_t *hid; + pcb_hid_gc_t drillGC, fgGC, pmGC; /* changed from some routines */ + pcb_hid_gc_t active_padGC, backpadGC, padGC, padselGC; /* pads are drawn with this gc */ + unsigned direct:1; /* starts as 1 and becomes 0 before the first compositing layer group is reset */ +} pcb_output_t; + +extern pcb_output_t pcb_draw_out; + +typedef enum { + PCB_PHOLE_PLATED = 1, + PCB_PHOLE_UNPLATED = 2, + PCB_PHOLE_BB = 4 +} pcb_pstk_draw_hole_t; + +/* Some low level draw callback depend on this in their void *cl */ +typedef struct pcb_draw_info_s { + pcb_board_t *pcb; + const pcb_box_t *drawn_area; + pcb_xform_t *xform_caller; /* the extra transformation the caller requested (the one who has initiated the rendering, e.g. throuh pcb_draw_everything()) */ + pcb_xform_t *xform_exporter; /* the extra transformation the exporter requested (e.g. because of cam) */ + pcb_xform_t *xform; /* the final transformation applied on objects */ + + const pcb_layer_t *layer; + + union { /* fields used for specific object callbacks */ + struct { + pcb_layergrp_id_t gid; + int is_current; + pcb_pstk_draw_hole_t holetype; + pcb_layer_combining_t comb; + const pcb_layer_t *layer1; /* first (real) layer in the target group */ + + pcb_layer_type_t shape_mask; /* when gid is invalid, use this for the shapes */ + } pstk; + struct { + int per_side; + } subc; + } objcb; +} pcb_draw_info_t; + +/* Temporarily inhibid drawing if this is non-zero. A function that calls a + lot of other functions that would call pcb_draw() a lot in turn may increase + this value before the calls, then decrease it at the end and call pcb_draw(). + This makes sure the whole block is redrawn only once at the end. */ +extern pcb_cardinal_t pcb_draw_inhibit; + +#define pcb_draw_inhibit_inc() pcb_draw_inhibit++ +#define pcb_draw_inhibit_dec() \ +do { \ + if (pcb_draw_inhibit > 0) \ + pcb_draw_inhibit--; \ +} while(0) \ + +/* When true, do not draw terminals but put them on the obj delay list + using pcb_draw_delay_obj_add() - used to delay heavy terminal drawing + to get proper overlaps */ +extern pcb_bool delayed_terms_enabled; +void pcb_draw_delay_obj_add(pcb_any_obj_t *obj); + +/* Append an object to the annotatation list; annotations are drawn at the + end, after labels */ +void pcb_draw_annotation_add(pcb_any_obj_t *obj); + +/* the minimum box that needs to be redrawn */ +extern pcb_box_t pcb_draw_invalidated; + +/* Adds the update rect to the invalidated region. This schedules the object + for redraw (by pcb_draw()). obj is anything that can be casted to pcb_box_t */ +#define pcb_draw_invalidate(obj) \ +do { \ + pcb_box_t *box = (pcb_box_t *)obj; \ + pcb_draw_invalidated.X1 = MIN(pcb_draw_invalidated.X1, box->X1); \ + pcb_draw_invalidated.X2 = MAX(pcb_draw_invalidated.X2, box->X2); \ + pcb_draw_invalidated.Y1 = MIN(pcb_draw_invalidated.Y1, box->Y1); \ + pcb_draw_invalidated.Y2 = MAX(pcb_draw_invalidated.Y2, box->Y2); \ +} while(0) + +extern int pcb_draw_force_termlab; /* force drawing terminal lables - useful for pinout previews */ +extern pcb_bool pcb_draw_doing_assy; + +void pcb_lighten_color(const pcb_color_t *orig, pcb_color_t *dst, double factor); + +/* Draw a series of short line segments emulating a dashed line. segs is + the number of on/off segment pairs. It is guaranteed that the line starts + and ends with an "on" line segment. If cheap is true, allow drawing less + segments if the line is short */ +void pcb_draw_dashed_line(pcb_draw_info_t *info, pcb_hid_gc_t GC, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2, unsigned int segs, pcb_bool_t cheap); + + +void pcb_draw(void); +void pcb_redraw(void); +void pcb_draw_obj(pcb_any_obj_t *obj); +void pcb_draw_layer(pcb_draw_info_t *info, const pcb_layer_t *ly); +void pcb_draw_layer_noxform(pcb_board_t *pcb, const pcb_layer_t *ly, const pcb_box_t *screen); + +/* Same as pcb_draw_layer(), but never draws an implicit outline and ignores + objects that are not in the subtree of data - useful for drawing a subtree, + e.g. a subc only */ +void pcb_draw_layer_under(pcb_board_t *pcb, const pcb_layer_t *Layer, const pcb_box_t *screen, pcb_data_t *data); + +/* Composite draw all layer groups matching lyt/purpi/purpose */ +void pcb_draw_groups(pcb_board_t *pcb, pcb_layer_type_t lyt, int purpi, char *purpose, const pcb_box_t *screen, const pcb_color_t *default_color, pcb_layer_type_t pstk_lyt_match, int thin_draw, int invert); + + +void pcb_erase_obj(int, void *, void *); +void pcb_draw_pstk_names(pcb_draw_info_t *info, pcb_layergrp_id_t group, const pcb_box_t *drawn_area); + +/*#define PCB_BBOX_DEBUG*/ + +#ifdef PCB_BBOX_DEBUG +#define PCB_DRAW_BBOX(obj) \ + do { \ + pcb_hid_set_line_width(pcb_draw_out.fgGC, 0); \ + pcb_gui->draw_rect(pcb_draw_out.fgGC, obj->BoundingBox.X1, obj->BoundingBox.Y1, obj->BoundingBox.X2, obj->BoundingBox.Y2); \ + } while(0) +#else +#define PCB_DRAW_BBOX(obj) +#endif + + +/* Returns whether lay_id is part of a group that is composite-drawn */ +int pcb_draw_layer_is_comp(pcb_layer_id_t lay_id); + +/* Returns whether a group is composite-drawn */ +int pcb_draw_layergrp_is_comp(const pcb_layergrp_t *g); + +/* Draw (render) or invalidate a terminal label */ +void pcb_term_label_draw(pcb_draw_info_t *info, pcb_coord_t x, pcb_coord_t y, double scale, pcb_bool vert, pcb_bool centered, const pcb_any_obj_t *obj); +void pcb_term_label_invalidate(pcb_coord_t x, pcb_coord_t y, double scale, pcb_bool vert, pcb_bool centered, const pcb_any_obj_t *obj); +void pcb_label_draw(pcb_draw_info_t *info, pcb_coord_t x, pcb_coord_t y, double scale, pcb_bool vert, pcb_bool centered, const char *label); +void pcb_label_invalidate(pcb_coord_t x, pcb_coord_t y, double scale, pcb_bool vert, pcb_bool centered, const char *label); + + +/* Schedule an object to be called again at the end for drawing its labels + on top of everything. */ +void pcb_draw_delay_label_add(pcb_any_obj_t *obj); + +/* Return non-zero if extra terminal graphics should be drawn */ +#define pcb_draw_term_need_gfx(obj) \ + (((obj)->term != NULL) && !PCB_FLAG_TEST(PCB_FLAG_FOUND, (obj)) && !PCB_FLAG_TEST(PCB_FLAG_WARN, (obj)) && !PCB_FLAG_TEST(PCB_FLAG_SELECTED, (obj))) + +#define pcb_draw_term_hid_permission() (pcb_gui->heavy_term_layer_ind) + +#define PCB_DRAW_TERM_GFX_WIDTH (-3) + +/* Normal expose: draw all layers with all flags (no .content is used) */ +void pcb_hid_expose_all(pcb_hid_t *hid, const pcb_hid_expose_ctx_t *region, pcb_xform_t *xform_caller); + +/* generic, dialog/callbakc based preview expose */ +void pcb_hid_expose_generic(pcb_hid_t *hid, const pcb_hid_expose_ctx_t *e); + +#endif Index: tags/2.1.2/src/draw_composite.c =================================================================== --- tags/2.1.2/src/draw_composite.c (nonexistent) +++ tags/2.1.2/src/draw_composite.c (revision 24813) @@ -0,0 +1,227 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996, 2003, 2004 Thomas Nau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +/* Local functions to draw a layer group as a composite of logical layers + using positive and negative draw operations. Included from draw.c. */ + +typedef struct comp_ctx_s { + pcb_draw_info_t *info; + const pcb_layergrp_t *grp; + pcb_layergrp_id_t gid; + const pcb_color_t *color; + + unsigned thin:1; + unsigned invert:1; +} comp_ctx_t; + +static void comp_fill_board(comp_ctx_t *ctx) +{ + pcb_gui->set_color(pcb_draw_out.fgGC, ctx->color); + if (ctx->info->drawn_area == NULL) + pcb_gui->fill_rect(pcb_draw_out.fgGC, 0, 0, ctx->info->pcb->MaxWidth, ctx->info->pcb->MaxHeight); + else + pcb_gui->fill_rect(pcb_draw_out.fgGC, ctx->info->drawn_area->X1, ctx->info->drawn_area->Y1, ctx->info->drawn_area->X2, ctx->info->drawn_area->Y2); +} + +static void comp_start_sub_(comp_ctx_t *ctx) +{ + pcb_gui->set_drawing_mode(PCB_HID_COMP_NEGATIVE, pcb_draw_out.direct, ctx->info->drawn_area); +} + +static void comp_start_add_(comp_ctx_t *ctx) +{ + pcb_gui->set_drawing_mode(PCB_HID_COMP_POSITIVE, pcb_draw_out.direct, ctx->info->drawn_area); +} + +static void comp_start_sub(comp_ctx_t *ctx) +{ + if (ctx->thin) { + pcb_gui->set_drawing_mode(PCB_HID_COMP_POSITIVE, pcb_draw_out.direct, ctx->info->drawn_area); + pcb_gui->set_color(pcb_draw_out.pmGC, ctx->color); + return; + } + + if (ctx->invert) + comp_start_add_(ctx); + else + comp_start_sub_(ctx); +} + +static void comp_start_add(comp_ctx_t *ctx) +{ + if (ctx->thin) { + pcb_gui->set_drawing_mode(PCB_HID_COMP_POSITIVE, pcb_draw_out.direct, ctx->info->drawn_area); + return; + } + + if (ctx->invert) + comp_start_sub_(ctx); + else + comp_start_add_(ctx); +} + +static void comp_finish(comp_ctx_t *ctx) +{ + if (ctx->thin) { + pcb_gui->set_drawing_mode(PCB_HID_COMP_FLUSH, pcb_draw_out.direct, ctx->info->drawn_area); + return; + } + + pcb_gui->set_drawing_mode(PCB_HID_COMP_FLUSH, pcb_draw_out.direct, ctx->info->drawn_area); +} + +static void comp_init(comp_ctx_t *ctx, int negative) +{ + pcb_gui->set_drawing_mode(PCB_HID_COMP_RESET, pcb_draw_out.direct, ctx->info->drawn_area); + + if (ctx->thin) + return; + + if (ctx->invert) + negative = !negative; + + if ((!ctx->thin) && (negative)) { + /* drawing the big poly for the negative */ + pcb_gui->set_drawing_mode(PCB_HID_COMP_POSITIVE, pcb_draw_out.direct, ctx->info->drawn_area); + comp_fill_board(ctx); + } +} + +/* Real composite draw: if any layer is negative, we have to use the HID API's + composite layer draw mechanism */ +static void comp_draw_layer_real(comp_ctx_t *ctx, void (*draw_auto)(comp_ctx_t *ctx, void *data), void *auto_data) +{ /* generic multi-layer rendering */ + int n, adding = -1; + pcb_layer_t *l = pcb_get_layer(PCB->Data, ctx->grp->lid[0]); + comp_init(ctx, (l->comb & PCB_LYC_SUB)); + + for(n = 0; n < ctx->grp->len; n++) { + int want_add; + l = pcb_get_layer(PCB->Data, ctx->grp->lid[n]); + + want_add = ctx->thin || !(l->comb & PCB_LYC_SUB); + if (want_add != adding) { + if (want_add) + comp_start_add(ctx); + else + comp_start_sub(ctx); + adding = want_add; + } + + { + pcb_hid_gc_t old_fg = pcb_draw_out.fgGC; + pcb_draw_out.fgGC = pcb_draw_out.pmGC; + if ((l->comb & PCB_LYC_AUTO) && (draw_auto != NULL)) + draw_auto(ctx, auto_data); + pcb_draw_layer(ctx->info, l); + pcb_draw_out.fgGC = old_fg; + } + } + if (!adding) + comp_start_add(ctx); +} + +int pcb_draw_layergrp_is_comp(const pcb_layergrp_t *g) +{ + int n; + + /* as long as we are doing only positive compositing, we can go without compositing */ + for(n = 0; n < g->len; n++) + if (PCB->Data->Layer[g->lid[n]].comb & (PCB_LYC_SUB)) + return 1; + + return 0; +} + +int pcb_draw_layer_is_comp(pcb_layer_id_t id) +{ + pcb_layergrp_t *g = pcb_get_layergrp(PCB, PCB->Data->Layer[id].meta.real.grp); + if (g == NULL) return 0; + return pcb_draw_layergrp_is_comp(g); +} + +/* Draw a layer group with fake or real compositing */ +static void comp_draw_layer(comp_ctx_t *ctx, void (*draw_auto)(comp_ctx_t *ctx, void *data), void *auto_data) +{ + int is_comp = pcb_draw_layergrp_is_comp(ctx->grp); + + if (is_comp) + pcb_draw_out.direct = 0; + + comp_draw_layer_real(ctx, draw_auto, auto_data); +} + +/******** generic group draws ********/ + +static void pcb_draw_groups_auto(comp_ctx_t *ctx, void *lym) +{ + pcb_layer_type_t *pstk_lyt_match = (pcb_layer_type_t *)lym; + if ((ctx->info->pcb->pstk_on) && (*pstk_lyt_match != 0)) + pcb_draw_pstks(ctx->info, ctx->gid, 0, *pstk_lyt_match); +} + +void pcb_draw_groups(pcb_board_t *pcb, pcb_layer_type_t lyt, int purpi, char *purpose, const pcb_box_t *screen, const pcb_color_t *default_color, pcb_layer_type_t pstk_lyt_match, int thin_draw, int invert) +{ + pcb_draw_info_t info; + pcb_layergrp_id_t gid; + pcb_layergrp_t *g; + comp_ctx_t cctx; + + memset(&info, 0, sizeof(info)); + info.pcb = pcb; + info.drawn_area = screen; + + for(gid = 0, g = pcb->LayerGroups.grp; gid < pcb->LayerGroups.len; gid++,g++) { + pcb_layer_t *ly = NULL; + + if ((g->ltype & lyt) != lyt) + continue; + + if ((purpi != -1) && (g->purpi != purpi)) + continue; + + if ((purpose != NULL) && (strcmp(g->purpose, purpose) != 0)) + continue; + + if (g->len > 0) + ly = pcb_get_layer(PCB->Data, g->lid[0]); + info.layer = ly; + cctx.grp = g; + cctx.info = &info; + cctx.gid = gid; + cctx.color = ly != NULL ? &ly->meta.real.color : default_color; + cctx.thin = thin_draw; + cctx.invert = invert; + + if (!cctx.invert) + pcb_draw_out.direct = 0; + + comp_draw_layer(&cctx, pcb_draw_groups_auto, &pstk_lyt_match); + comp_finish(&cctx); + } +} Index: tags/2.1.2/src/draw_ly_spec.c =================================================================== --- tags/2.1.2/src/draw_ly_spec.c (nonexistent) +++ tags/2.1.2/src/draw_ly_spec.c (revision 24813) @@ -0,0 +1,331 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996, 2003, 2004 Thomas Nau + * Copyright (C) 2017,2018 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +/* Local functions for special layer draw logics. This code is not generic; + instead it collects all the hardwired heuristics for the special layers. + Included from draw.c. */ + +/******** paste ********/ + +static void pcb_draw_paste_auto_(comp_ctx_t *ctx, void *side) +{ + if (PCB->pstk_on) + pcb_draw_pstks(ctx->info, ctx->gid, 0, PCB_LYC_AUTO); +} + +static void pcb_draw_paste(pcb_draw_info_t *info, int side) +{ + unsigned long side_lyt = side ? PCB_LYT_TOP : PCB_LYT_BOTTOM; + pcb_layergrp_id_t gid = -1; + comp_ctx_t cctx; + pcb_layer_t *ly = NULL; + + pcb_layergrp_list(info->pcb, PCB_LYT_PASTE | side_lyt, &gid, 1); + + cctx.grp = pcb_get_layergrp((pcb_board_t *)info->pcb, gid); + + if (cctx.grp->len > 0) + ly = pcb_get_layer(info->pcb->Data, cctx.grp->lid[0]); + + cctx.info = info; + cctx.gid = gid; + cctx.color = ly != NULL ? &ly->meta.real.color : &conf_core.appearance.color.paste; + cctx.thin = conf_core.editor.thin_draw || conf_core.editor.thin_draw_poly || conf_core.editor.wireframe_draw; + cctx.invert = 0; + + if ((cctx.grp == NULL) || (cctx.grp->len == 0)) { /* fallback: no layers -> original code: draw a single auto-add */ + pcb_gui->set_drawing_mode(PCB_HID_COMP_RESET, pcb_draw_out.direct, info->drawn_area); + pcb_gui->set_drawing_mode(PCB_HID_COMP_POSITIVE, pcb_draw_out.direct, info->drawn_area); + pcb_gui->set_drawing_mode(PCB_HID_COMP_FLUSH, pcb_draw_out.direct, info->drawn_area); + } + else { + comp_draw_layer(&cctx, pcb_draw_paste_auto_, &side); + comp_finish(&cctx); + } +} + +/******** mask ********/ +static void pcb_draw_mask_auto(comp_ctx_t *ctx, void *side) +{ + if (PCB->pstk_on) + pcb_draw_pstks(ctx->info, ctx->gid, 0, PCB_LYC_SUB | PCB_LYC_AUTO); +} + +static void pcb_draw_mask(pcb_draw_info_t *info, int side) +{ + unsigned long side_lyt = side ? PCB_LYT_TOP : PCB_LYT_BOTTOM; + pcb_layergrp_id_t gid = -1; + comp_ctx_t cctx; + pcb_layer_t *ly = NULL; + + pcb_layergrp_list(PCB, PCB_LYT_MASK | side_lyt, &gid, 1); + + cctx.grp = pcb_get_layergrp(PCB, gid); + + if (cctx.grp->len > 0) + ly = pcb_get_layer(PCB->Data, cctx.grp->lid[0]); + + cctx.info = info; + cctx.gid = gid; + cctx.color = ly != NULL ? &ly->meta.real.color : &conf_core.appearance.color.mask; + cctx.thin = conf_core.editor.thin_draw || conf_core.editor.thin_draw_poly || conf_core.editor.wireframe_draw; + cctx.invert = pcb_gui->mask_invert; + + if (!cctx.invert) + pcb_draw_out.direct = 0; + + if ((cctx.grp == NULL) || (cctx.grp->len == 0)) { /* fallback: no layers -> original code: draw a single auto-sub */ + comp_init(&cctx, 1); + comp_start_sub(&cctx); + pcb_draw_mask_auto(&cctx, &side); + comp_start_add(&cctx); + } + else + comp_draw_layer(&cctx, pcb_draw_mask_auto, &side); + comp_finish(&cctx); +} + +/******** silk ********/ + +static void pcb_draw_silk_auto(comp_ctx_t *ctx, void *lyt_side) +{ + if (PCB->pstk_on) + pcb_draw_pstks(ctx->info, ctx->gid, 0, PCB_LYC_AUTO); +} + +static int pcb_is_silk_old_style(comp_ctx_t *cctx, pcb_layer_id_t lid) +{ + if (cctx->grp == NULL) + return 1; /* no group means no silk -> fall back to implicit */ + + if ((cctx->grp->len == 1) && ((PCB->Data->Layer[lid].comb & (PCB_LYC_AUTO | PCB_LYC_SUB)) == PCB_LYC_AUTO)) + return 1; /* A single auto-positive layer -> original code: draw auto+manual */ + + return 0; +} + +static void pcb_draw_silk_doc(pcb_draw_info_t *info, pcb_layer_type_t lyt_side, pcb_layer_type_t lyt_type, int setgrp, int invis) +{ + pcb_layer_id_t lid; + pcb_layergrp_id_t gid[PCB_MAX_LAYERGRP]; + comp_ctx_t cctx; + int len, n; + + len = pcb_layergrp_list(info->pcb, lyt_type | lyt_side, gid, PCB_MAX_LAYERGRP); + if (len < 1) + return; + + for(n = 0; n < len; n++) { + if (!info->pcb->LayerGroups.grp[gid[n]].vis) + continue; + + if (setgrp) + if (!pcb_layer_gui_set_glayer(info->pcb, gid[n], 0, &info->xform_exporter)) + continue; + + cctx.info = info; + cctx.gid = gid[n]; + cctx.grp = pcb_get_layergrp((pcb_board_t *)info->pcb, gid[n]); + if ((lyt_side == 0) && (cctx.grp->ltype & PCB_LYT_ANYWHERE) != 0) /* special case for global */ + continue; + if (cctx.grp->len == 0) + continue; + lid = cctx.grp->lid[0]; + cctx.color = invis ? &conf_core.appearance.color.invisible_objects : &info->pcb->Data->Layer[lid].meta.real.color; + cctx.thin = conf_core.editor.thin_draw || conf_core.editor.thin_draw_poly || conf_core.editor.wireframe_draw; + cctx.invert = 0; + + if ((lyt_type & PCB_LYT_SILK) && (pcb_is_silk_old_style(&cctx, lid))) { + /* fallback: implicit layer -> original code: draw auto+manual */ + pcb_gui->set_drawing_mode(PCB_HID_COMP_RESET, pcb_draw_out.direct, info->drawn_area); + pcb_gui->set_drawing_mode(PCB_HID_COMP_POSITIVE, pcb_draw_out.direct, info->drawn_area); + pcb_draw_layer(info, LAYER_PTR(lid)); + pcb_draw_silk_auto(&cctx, &lyt_side); + pcb_gui->set_drawing_mode(PCB_HID_COMP_FLUSH, pcb_draw_out.direct, info->drawn_area); + } + else { + comp_draw_layer(&cctx, pcb_draw_silk_auto, &lyt_side); + comp_finish(&cctx); + } + if (setgrp) + pcb_gui->end_layer(); + } +} + +static void remember_slot(pcb_layer_t **uslot, pcb_layer_t **pslot, int *uscore, int *pscore, const pcb_layergrp_t *g, pcb_layer_t *ly) +{ + int score; + pcb_layer_t **dslot; + int *dscore; + + if (!(ly->comb & PCB_LYC_AUTO)) + return; + + if (g->purpi == F_uroute) { + dslot = uslot; + dscore = uscore; + } + else if (g->purpi == F_proute) { + dslot = pslot; + dscore = pscore; + } + else + return; + + if (g->ltype & PCB_LYT_BOUNDARY) score = 1; + if (g->ltype & PCB_LYT_MECH) score = 2; + + if (score > *dscore) { + *dscore = score; + *dslot = ly; + } +} + +static void pcb_draw_boundary_mech(pcb_draw_info_t *info) +{ + int count = 0; + pcb_layergrp_id_t gid, goutid; + const pcb_layergrp_t *g, *goutl = NULL; + pcb_layer_t *uslot = NULL, *pslot = NULL; + int uscore = 0, pscore = 0; + int plated, unplated; + + for(gid = 0, g = info->pcb->LayerGroups.grp; gid < info->pcb->LayerGroups.len; gid++,g++) { + int n, numobj; + + if ((g->ltype & PCB_LYT_BOUNDARY) && (g->purpi == F_uroute)) { + goutl = g; + goutid = gid; + } + + if (!(g->ltype & (PCB_LYT_BOUNDARY | PCB_LYT_MECH)) || (g->len < 1)) + continue; + + /* Count whether there are objects on any boundary layer: + don't count the objects drawn, but the objects the layer has; + zooming in the middle doesn't mean we need to have the implicit + outline */ + numobj = 0; + for(n = 0; n < g->len; n++) { + pcb_layer_t *ly = LAYER_PTR(g->lid[n]); + if (ly->line_tree != NULL) + numobj += ly->line_tree->size; + if (ly->arc_tree != NULL) + numobj += ly->arc_tree->size; + if (ly->text_tree != NULL) + numobj += ly->text_tree->size; + if (ly->polygon_tree != NULL) + numobj += ly->polygon_tree->size; + remember_slot(&uslot, &pslot, &uscore, &pscore, g, ly); + } + count += numobj; + + if (pcb_layer_gui_set_layer(gid, g, (numobj == 0), &info->xform_exporter)) { + /* boundary does NOT support compisiting, everything is drawn in positive */ + pcb_gui->set_drawing_mode(PCB_HID_COMP_RESET, pcb_draw_out.direct, info->drawn_area); + pcb_gui->set_drawing_mode(PCB_HID_COMP_POSITIVE, pcb_draw_out.direct, info->drawn_area); + for(n = 0; n < g->len; n++) { + pcb_layer_t *ly = LAYER_PTR(g->lid[n]); + pcb_draw_layer(info, ly); + } + pcb_gui->set_drawing_mode(PCB_HID_COMP_FLUSH, pcb_draw_out.direct, info->drawn_area); + pcb_gui->end_layer(); + } + } + + if ((count == 0) && (goutl != NULL) && (pcb_layer_gui_set_layer(goutid, goutl, 0, &info->xform))) { + /* The implicit outline rectangle (or automatic outline rectanlge). + We should check for pcb_gui->gui here, but it's kinda cool seeing the + auto-outline magically disappear when you first add something to + the outline layer. */ + pcb_gui->set_drawing_mode(PCB_HID_COMP_RESET, pcb_draw_out.direct, info->drawn_area); + pcb_gui->set_drawing_mode(PCB_HID_COMP_POSITIVE, pcb_draw_out.direct, info->drawn_area); + + pcb_gui->set_color(pcb_draw_out.fgGC, &PCB->Data->Layer[goutl->lid[0]].meta.real.color); + pcb_hid_set_line_cap(pcb_draw_out.fgGC, pcb_cap_round); + pcb_hid_set_line_width(pcb_draw_out.fgGC, conf_core.design.min_wid); + pcb_gui->draw_rect(pcb_draw_out.fgGC, 0, 0, PCB->MaxWidth, PCB->MaxHeight); + + pcb_gui->set_drawing_mode(PCB_HID_COMP_FLUSH, pcb_draw_out.direct, info->drawn_area); + pcb_gui->end_layer(); + } + + /* draw slots */ + if (((uslot == NULL) || (!uslot->meta.real.vis)) && ((pslot == NULL) || (!pslot->meta.real.vis))) + return; + + pcb_board_count_slots(PCB, &plated, &unplated, info->drawn_area); + + if ((uslot != NULL) && (uslot->meta.real.vis)) { + if (pcb_layer_gui_set_glayer(PCB, uslot->meta.real.grp, unplated > 0, &info->xform)) { + pcb_gui->set_drawing_mode(PCB_HID_COMP_RESET, pcb_draw_out.direct, info->drawn_area); + pcb_gui->set_drawing_mode(PCB_HID_COMP_POSITIVE, pcb_draw_out.direct, info->drawn_area); + pcb_draw_pstk_slots(info, uslot->meta.real.grp, PCB_PHOLE_UNPLATED | PCB_PHOLE_BB); + pcb_gui->set_drawing_mode(PCB_HID_COMP_FLUSH, pcb_draw_out.direct, info->drawn_area); + pcb_gui->end_layer(); + } + } + if ((pslot != NULL) && (pslot->meta.real.vis)) { + if (pcb_layer_gui_set_glayer(PCB, pslot->meta.real.grp, plated > 0, &info->xform)) { + pcb_gui->set_drawing_mode(PCB_HID_COMP_RESET, pcb_draw_out.direct, info->drawn_area); + pcb_gui->set_drawing_mode(PCB_HID_COMP_POSITIVE, pcb_draw_out.direct, info->drawn_area); + pcb_draw_pstk_slots(info, pslot->meta.real.grp, PCB_PHOLE_PLATED | PCB_PHOLE_BB); + pcb_gui->set_drawing_mode(PCB_HID_COMP_FLUSH, pcb_draw_out.direct, info->drawn_area); + pcb_gui->end_layer(); + } + } +} + + +/******** misc ********/ + +static void pcb_draw_rats(const pcb_box_t *drawn_area) +{ + pcb_gui->set_drawing_mode(PCB_HID_COMP_RESET, pcb_draw_out.direct, drawn_area); + pcb_gui->set_drawing_mode(PCB_HID_COMP_POSITIVE, pcb_draw_out.direct, drawn_area); + pcb_r_search(PCB->Data->rat_tree, drawn_area, NULL, pcb_rat_draw_callback, NULL, NULL); + pcb_gui->set_drawing_mode(PCB_HID_COMP_FLUSH, pcb_draw_out.direct, drawn_area); +} + +static void pcb_draw_assembly(pcb_draw_info_t *info, pcb_layer_type_t lyt_side) +{ + pcb_layergrp_id_t side_group; + + if (pcb_layergrp_list(PCB, PCB_LYT_COPPER | lyt_side, &side_group, 1) != 1) + return; + + pcb_draw_doing_assy = pcb_true; + pcb_hid_set_draw_faded(pcb_draw_out.fgGC, 1); + pcb_draw_layer_grp(info, side_group, 0); + pcb_hid_set_draw_faded(pcb_draw_out.fgGC, 0); + + /* draw package */ + pcb_draw_silk_doc(info, lyt_side, PCB_LYT_SILK, 0, 0); + pcb_draw_doing_assy = pcb_false; +} Index: tags/2.1.2/src/draw_wireframe.h =================================================================== --- tags/2.1.2/src/draw_wireframe.h (nonexistent) +++ tags/2.1.2/src/draw_wireframe.h (revision 24813) @@ -0,0 +1,104 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ +#ifndef PCB_DRAW_WIREFRAME_H +#define PCB_DRAW_WIREFRAME_H + +#include "config.h" +#include "hid.h" + +/*----------------------------------------------------------- + * Draws the outline of an arc + */ +PCB_INLINE void pcb_draw_wireframe_arc(pcb_hid_gc_t gc, pcb_arc_t *arc, pcb_coord_t thick) +{ + pcb_coord_t wid = thick / 2; + pcb_coord_t x1, y1, x2, y2; + + pcb_arc_get_end(arc, 0, &x1, &y1); + pcb_arc_get_end(arc, 1, &x2, &y2); + + pcb_gui->draw_arc(gc, arc->X, arc->Y, arc->Width + wid, arc->Height + wid, arc->StartAngle, arc->Delta); + if (wid > pcb_pixel_slop) { + pcb_gui->draw_arc(gc, arc->X, arc->Y, arc->Width - wid, arc->Height - wid, arc->StartAngle, arc->Delta); + pcb_gui->draw_arc(gc, x1, y1, wid, wid, arc->StartAngle, -180 * SGN(arc->Delta)); + pcb_gui->draw_arc(gc, x2, y2, wid, wid, arc->StartAngle + arc->Delta, 180 * SGN(arc->Delta)); + } +} + +/*----------------------------------------------------------- + * Draws the outline of a line + */ +PCB_INLINE void pcb_draw_wireframe_line(pcb_hid_gc_t gc, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2, pcb_coord_t thick, int square) +{ + if((x1 != x2) || (y1 != y2)) { + double dx = x2 - x1; + double dy = y2 - y1; + double h = 0.5 * thick / sqrt(PCB_SQUARE(dx) + PCB_SQUARE(dy)); + pcb_coord_t ox = dy * h + 0.5 * SGN(dy); + pcb_coord_t oy = -(dx * h + 0.5 * SGN(dx)); + if (square) { + /* make the line longer by cap */ + x1 -= dx * h; + x2 += dx * h; + y1 -= dy * h; + y2 += dy * h; + } + if ((coord_abs(ox) >= pcb_pixel_slop) || (coord_abs(oy) >= pcb_pixel_slop)) { + pcb_gui->draw_line(gc, x1 + ox, y1 + oy, x2 + ox, y2 + oy); + pcb_gui->draw_line(gc, x1 - ox, y1 - oy, x2 - ox, y2 - oy); + + /* draw caps */ + if (!square) { + pcb_angle_t angle = atan2(dx, dy) * 57.295779; + pcb_gui->draw_arc(gc, x1, y1, thick / 2, thick / 2, angle - 180, 180); + pcb_gui->draw_arc(gc, x2, y2, thick / 2, thick / 2, angle, 180); + } + else { + pcb_gui->draw_line(gc, x1 + ox, y1 + oy, x1 - ox, y1 - oy); + pcb_gui->draw_line(gc, x2 + ox, y2 + oy, x2 - ox, y2 - oy); + } + } + else + pcb_gui->draw_line(gc, x1, y1, x2, y2); + } + else { + if (square) { + /* square cap 0 long line does not have an angle -> always draw it axis aligned */ + pcb_coord_t cx1 = x1 - thick/2, cx2 = x1 + thick/2, cy1 = y1 - thick/2, cy2 = y1 + thick/2; + pcb_gui->draw_line(gc, cx1, cy1, cx2, cy1); + pcb_gui->draw_line(gc, cx2, cy1, cx2, cy2); + pcb_gui->draw_line(gc, cx2, cy2, cx1, cy2); + pcb_gui->draw_line(gc, cx1, cy2, cx1, cy1); + } + else + pcb_gui->draw_arc(gc, x1, y1, thick/2, thick/2, 0, 360); + } +} + +#endif /* ! defined PCB_DRAW_WIREFRAME_H */ + Index: tags/2.1.2/src/drc.c =================================================================== --- tags/2.1.2/src/drc.c (nonexistent) +++ tags/2.1.2/src/drc.c (revision 24813) @@ -0,0 +1,178 @@ +/* + * + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2018 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ +#include "config.h" + +#include "actions.h" +#include "drc.h" +#include "conf_core.h" +#include "compat_misc.h" +#include "event.h" + + +pcb_view_list_t pcb_drc_lst; + +void pcb_drc_set_data(pcb_view_t *violation, const pcb_coord_t *measured_value, pcb_coord_t required_value) +{ + violation->data_type = PCB_VIEW_DRC; + violation->data.drc.required_value = required_value; + if (measured_value != NULL) { + violation->data.drc.have_measured = 1; + violation->data.drc.measured_value = *measured_value; + } + else + violation->data.drc.have_measured = 0; +} + + +static fgw_error_t view_dlg(fgw_arg_t *res, int argc, fgw_arg_t *argv, const char *dlg_type, const char *dlgact, pcb_view_list_t *lst, void (*refresh)()) +{ + fgw_arg_t args[2]; + + args[1].type = FGW_STR; + + if (pcb_strcasecmp(dlg_type, "list") == 0) { + if (PCB_HAVE_GUI_ATTR_DLG) { + args[1].val.str = "list"; + return pcb_actionv_bin(dlgact, res, 2, args); + } + dlg_type = "print"; + } + + if (pcb_strcasecmp(dlg_type, "simple") == 0) { + if (PCB_HAVE_GUI_ATTR_DLG) { + args[1].val.str = "simple"; + return pcb_actionv_bin(dlgact, res, 2, args); + } + dlg_type = "print"; + } + + + PCB_ACT_IRES(-1); + if (refresh != NULL) + refresh(); + + if (pcb_strcasecmp(dlg_type, "print") == 0) { + pcb_view_t *v; + for(v = pcb_view_list_first(lst); v != NULL; v = pcb_view_list_next(v)) { + printf("%ld: %s: %s\n", v->uid, v->type, v->title); + if (v->have_bbox) + pcb_printf("%m+within %$m4\n", conf_core.editor.grid_unit->allow, v->bbox.X1, v->bbox.Y1, v->bbox.X2, v->bbox.Y2); + if (v->have_xy) + pcb_printf("%m+at %$m2\n", conf_core.editor.grid_unit->allow, v->x, v->y); + pcb_printf("%m+required value %$mS\n", conf_core.editor.grid_unit->allow, v->data.drc.required_value); + if (v->data.drc.have_measured) + pcb_printf("%m+measured value %$mS\n", conf_core.editor.grid_unit->allow, v->data.drc.measured_value); + printf("%s\n\n", v->description); + } + } + else if (pcb_strcasecmp(dlg_type, "log") == 0) { + pcb_view_t *v; + for(v = pcb_view_list_first(lst); v != NULL; v = pcb_view_list_next(v)) { + pcb_message(PCB_MSG_INFO, "%ld: %s: %s\n", v->uid, v->type, v->title); + if (v->have_bbox) + pcb_message(PCB_MSG_INFO, "%m+within %$m4\n", conf_core.editor.grid_unit->allow, v->bbox.X1, v->bbox.Y1, v->bbox.X2, v->bbox.Y2); + if (v->have_xy) + pcb_message(PCB_MSG_INFO, "%m+at %$m2\n", conf_core.editor.grid_unit->allow, v->x, v->y); + pcb_printf("%m+required value %$mS\n", conf_core.editor.grid_unit->allow, v->data.drc.required_value); + if (v->data.drc.have_measured) + pcb_message(PCB_MSG_INFO, "%m+measured value %$mS\n", conf_core.editor.grid_unit->allow, v->data.drc.measured_value); + pcb_message(PCB_MSG_INFO, "%s\n\n", v->description); + } + } + if (pcb_strcasecmp(dlg_type, "dump") == 0) { + pcb_view_t *v; + char *s; + for(v = pcb_view_list_first(lst); v != NULL; v = pcb_view_list_next(v)) { + printf("V%ld\n", v->uid); + printf("T%s\n", v->type); + printf("t%s\n", v->title); + if (v->have_bbox) + pcb_printf("B%mm %mm %mm %mm mm\n", v->bbox.X1, v->bbox.Y1, v->bbox.X2, v->bbox.Y2); + if (v->have_xy) + pcb_printf("A%mm %mm mm\n", v->x, v->y); + pcb_printf("R%$mm\n", v->data.drc.required_value); + if (v->data.drc.have_measured) + pcb_printf("M%$mm\n", v->data.drc.measured_value); + for(s = v->description; *s != '\0'; s++) + if (*s == '\n') + *s = ' '; + printf("E%s\n\n", v->description); + } + } + else if (pcb_strcasecmp(dlg_type, "count") == 0) + PCB_ACT_IRES(pcb_view_list_length(lst)); + + + if (refresh != NULL) + pcb_view_list_free_fields(lst); + + return 0; +} + +void pcb_drc_all(void) +{ + pcb_event(PCB_EVENT_DRC_RUN, NULL); +} + +static const char pcb_acts_DRC[] = "DRC([list|simple|print|log|dump])"; +static const char pcb_acth_DRC[] = "Invoke the DRC check. Results are presented as the argument requests."; +/* DOC: drc.html */ +static fgw_error_t pcb_act_DRC(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + const char *dlg_type = "list"; + PCB_ACT_MAY_CONVARG(1, FGW_STR, DRC, dlg_type = argv[1].val.str); + return view_dlg(res, argc, argv, dlg_type, "drcdialog", &pcb_drc_lst, pcb_drc_all); +} + +const char pcb_acts_IOIncompatList[] = "IOIncompatList([list|simple])\n"; +const char pcb_acth_IOIncompatList[] = "Present the format incompatibilities of the last save to file operation."; +fgw_error_t pcb_act_IOIncompatList(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + const char *dlg_type = "list"; + const char *aauto = NULL; + + PCB_ACT_MAY_CONVARG(1, FGW_STR, IOIncompatList, dlg_type = argv[1].val.str); + PCB_ACT_MAY_CONVARG(2, FGW_STR, IOIncompatList, aauto = argv[2].val.str); + + if ((aauto != NULL) && (strcmp(aauto, "auto") == 0)) { + if (conf_core.rc.quiet && !PCB_HAVE_GUI_ATTR_DLG) { + /* if not explicitly asked for a listing style and we are on CLI and quiet is set, don't print anything */ + PCB_ACT_IRES(0); + return 0; + } + } + + return view_dlg(res, argc, argv, dlg_type, "ioincompatlistdialog", &pcb_drc_lst, pcb_drc_all); +} + +pcb_action_t find_action_list[] = { + {"DRC", pcb_act_DRC, pcb_acth_DRC, pcb_acts_DRC}, + {"IOIncompatList", pcb_act_IOIncompatList, pcb_acth_IOIncompatList, pcb_acts_IOIncompatList}, +}; + +PCB_REGISTER_ACTIONS(find_action_list, NULL) Index: tags/2.1.2/src/drc.h =================================================================== --- tags/2.1.2/src/drc.h (nonexistent) +++ tags/2.1.2/src/drc.h (revision 24813) @@ -0,0 +1,46 @@ +/* + * + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2018 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +#ifndef PCB_DRC_H +#define PCB_DRC_H + +/* Generic DRC infra: helper functions for keeping track of a list of views + for drc violations (without any actual checking logics) */ + +#include "view.h" + +/* Load drc-specific fields of a view; if measured_value is NULL, it is not available */ +void pcb_drc_set_data(pcb_view_t *violation, const pcb_coord_t *measured_value, pcb_coord_t required_value); + +extern pcb_view_list_t pcb_drc_lst; + +/* run all configured DRCs */ +void pcb_drc_all(void); + +#endif + Index: tags/2.1.2/src/error.c =================================================================== --- tags/2.1.2/src/error.c (nonexistent) +++ tags/2.1.2/src/error.c (revision 24813) @@ -0,0 +1,258 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2019 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "config.h" + +#include +#include + +#include "actions.h" +#include "data.h" +#include "error.h" +#include "event.h" +#include "hid_dad.h" +#include "safe_fs.h" +#include "funchash_core.h" +#include "conf_core.h" +#include "genvector/gds_char.h" + +void pcb_trace(const char *Format, ...) +{ +#ifndef NDEBUG + va_list args; + va_start(args, Format); + pcb_vfprintf(stderr, Format, args); + va_end(args); +#endif +} + +unsigned long pcb_log_next_ID = 0; +pcb_logline_t *pcb_log_first, *pcb_log_last; + +void pcb_message(enum pcb_message_level level, const char *Format, ...) +{ + va_list args; + pcb_message_level_t min_level = PCB_MSG_INFO; + gds_t tmp; + pcb_logline_t *line; + + if ((pcb_gui == NULL) || (conf_core.rc.dup_log_to_stderr)) { + if (conf_core.rc.quiet) + min_level = PCB_MSG_ERROR; + + if ((level >= min_level) || (conf_core.rc.verbose)) { + va_start(args, Format); + pcb_vfprintf(stderr, Format, args); + va_end(args); + } + } + + /* allocate a new log line; for efficiency pretend it is a string during + the allocation */ + gds_init(&tmp); + gds_enlarge(&tmp, sizeof(pcb_logline_t)); + tmp.used = offsetof(pcb_logline_t, str); + va_start(args, Format); + pcb_append_vprintf(&tmp, Format, args); + va_end(args); + + /* add the header and link in */ + line = (pcb_logline_t *)tmp.array; + line->stamp = time(NULL); + line->ID = pcb_log_next_ID++; + line->level = level; + line->seen = 0; + line->next = NULL; + line->prev = pcb_log_last; + if (pcb_log_first == NULL) + pcb_log_first = line; + if (pcb_log_last != NULL) + pcb_log_last->next = line; + pcb_log_last = line; + line->len = tmp.used - offsetof(pcb_logline_t, str); + + pcb_event(PCB_EVENT_LOG_APPEND, "p", line); +} + +pcb_logline_t *pcb_log_find_min_(pcb_logline_t *from, unsigned long ID) +{ + pcb_logline_t *n; + if (ID == -1) + return from; + for(n = from; n != NULL; n = n->next) + if (n->ID >= ID) + return n; + return NULL; +} + +pcb_logline_t *pcb_log_find_min(unsigned long ID) +{ + return pcb_log_find_min_(pcb_log_first, ID); +} + +pcb_logline_t *pcb_log_find_first_unseen(void) +{ + pcb_logline_t *n; + for(n = pcb_log_last; n != NULL; n = n->prev) + if (n->seen) + return n->next; + return pcb_log_first; +} + +void pcb_log_del_range(unsigned long from, unsigned long to) +{ + pcb_logline_t *start = pcb_log_find_min(from), *end = NULL; + pcb_logline_t *next, *n, *start_prev, *end_next; + + if (start == NULL) + return; /* start is beyond the end of the list - do not delete anything */ + + if (to != -1) + end = pcb_log_find_min_(start, to); + if (end == NULL) + end = pcb_log_last; + + /* remember boundary elems near the range */ + start_prev = start->prev; + end_next = end->next; + + /* free all elems of the range */ + n = start; + for(;;) { + next = n->next; + free(n); + if (n == end) + break; + n = next; + } + + /* unlink the whole range at once */ + if (start_prev != NULL) + start_prev->next = end_next; + else + pcb_log_first = end_next; + + if (end_next != NULL) + end_next->prev = start_prev; + else + pcb_log_last = start_prev; +} + + + +int pcb_log_export(const char *fn, int fmt_lihata) +{ + FILE *f; + pcb_logline_t *n; + + f = pcb_fopen(fn, "w"); + if (f == NULL) + return -1; + + if (fmt_lihata) { + fprintf(f, "ha:pcb-rnd-log-v1 {\n"); + fprintf(f, " li:entries {\n"); + } + + for(n = pcb_log_first; n != NULL; n = n->next) { + if (fmt_lihata) { + fprintf(f, " ha:%lu {", n->ID); + fprintf(f, "stamp=%ld; level=%d; seen=%d; ", (long int)n->stamp, n->level, n->seen); + fprintf(f, "str={%s}}\n", n->str); + } + else + fprintf(f, "%s", n->str); + } + + if (fmt_lihata) + fprintf(f, " }\n}\n"); + + fclose(f); + return 0; +} + +void pcb_log_uninit(void) +{ + pcb_log_del_range(-1, -1); +} + + +static const char pcb_acts_Log[] = + "Log(clear, [fromID, [toID])\n" + "Log(export, [filename, [text|lihata])\n"; +static const char pcb_acth_Log[] = "Manages the central, in-memory log."; +static fgw_error_t pcb_act_Log(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + int ret, op = -1; + + PCB_ACT_MAY_CONVARG(1, FGW_KEYWORD, Log, op = fgw_keyword(&argv[1])); + + switch(op) { + case F_Clear: + { + unsigned long from = -1, to = -1; + PCB_ACT_MAY_CONVARG(2, FGW_ULONG, Log, from = fgw_keyword(&argv[2])); + PCB_ACT_MAY_CONVARG(3, FGW_ULONG, Log, from = fgw_keyword(&argv[3])); + pcb_log_del_range(from, to); + pcb_event(PCB_EVENT_LOG_CLEAR, "pp", &from, &to); + ret = 0; + } + break; + case F_Export: + { + const char *fmts[] = { "text", "lihata", NULL }; + pcb_hid_dad_subdialog_t fmtsub; + char *fn; + int wfmt; + + memset(&fmtsub, 0, sizeof(fmtsub)); + PCB_DAD_ENUM(fmtsub.dlg, fmts); + wfmt = PCB_DAD_CURRENT(fmtsub.dlg); + fn = pcb_gui->fileselect("Export log", NULL, "log.txt", NULL, NULL, "log", PCB_HID_FSD_MAY_NOT_EXIST, &fmtsub); + if (fn != NULL) { + ret = pcb_log_export(fn, (fmtsub.dlg[wfmt].default_val.int_value == 1)); + if (ret != 0) + pcb_message(PCB_MSG_ERROR, "Failed to export log to '%s'\n", fn); + free(fn); + } + else + ret = 0; + } + break; + default: + PCB_ACT_FAIL(Log); + ret = -1; + } + + PCB_ACT_IRES(ret); + return 0; +} + +pcb_action_t log_action_list[] = { + {"Log", pcb_act_Log, pcb_acth_Log, pcb_acts_Log} +}; + +PCB_REGISTER_ACTIONS(log_action_list, NULL) Index: tags/2.1.2/src/error.h =================================================================== --- tags/2.1.2/src/error.h (nonexistent) +++ tags/2.1.2/src/error.h (revision 24813) @@ -0,0 +1,94 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2019 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +/* Messages, error reporting, debug and logging */ + +#ifndef PCB_ERROR_H +#define PCB_ERROR_H + +#include + +/* pcb_printf()-like call to print temporary trace messages to stderr; + disabled in non-debug compilation */ +void pcb_trace(const char *Format, ...); + +typedef enum pcb_message_level { + PCB_MSG_DEBUG = 0, /* Debug message. Should probably not be shown in regular operation. */ + PCB_MSG_INFO, /* Info message. FYI for the user, no action needed. */ + PCB_MSG_WARNING, /* Something the user should probably take note */ + PCB_MSG_ERROR /* Couldn't finish an action, needs user attention. */ +} pcb_message_level_t; + +/*** central log write API ***/ + +/* printf-like logger to the log dialog and stderr */ +void pcb_message(enum pcb_message_level level, const char *Format, ...); + +/* shorthands for indicating common errors using pcb_message() */ +#define pcb_FS_error_message(filename, func) pcb_message(PCB_MSG_ERROR, "Can't open file\n '%s'\n" func "() returned: '%s'\n", filename, strerror(errno)) + +#define pcb_open_error_message(filename) pcb_FS_error_message(filename, "open") +#define pcb_popen_error_message(filename) pcb_FS_error_message(filename, "popen") +#define pcb_opendir_error_message(filename) pcb_FS_error_message(filename, "opendir") +#define pcb_chdir_error_message(filename) pcb_FS_error_message(filename, "chdir") + +/*** central log storage and read API ***/ + +typedef struct pcb_logline_s pcb_logline_t; + +struct pcb_logline_s { + time_t stamp; + unsigned long ID; + pcb_message_level_t level; + unsigned seen:1; /* message ever shown to the user - set by the code that presented the message */ + pcb_logline_t *prev, *next; + size_t len; + char str[1]; +}; + +extern unsigned long pcb_log_next_ID; + +/* Return the first log line that has at least the specified value in its ID. */ +pcb_logline_t *pcb_log_find_min(unsigned long ID); +pcb_logline_t *pcb_log_find_min_(pcb_logline_t *from, unsigned long ID); + +/* Search back from the bottom of the log and return the oldest unseen entry + (or NULL if all entries have been shown) */ +pcb_logline_t *pcb_log_find_first_unseen(void); + +/* Remove log lines between ID from and to, inclusive; -1 in these fields + mean begin or end of the list. */ +void pcb_log_del_range(unsigned long from, unsigned long to); + +/* Export the whole log list to a file, in lihata or plain text */ +int pcb_log_export(const char *fn, int fmt_lihata); + +/* Free all memory and reset the log system */ +void pcb_log_uninit(void); + +extern pcb_logline_t *pcb_log_first, *pcb_log_last; + +#endif Index: tags/2.1.2/src/event.c =================================================================== --- tags/2.1.2/src/event.c (nonexistent) +++ tags/2.1.2/src/event.c (revision 24813) @@ -0,0 +1,256 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2016, 2018 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include +#include +#include +#include "config.h" +#include "event.h" +#include "error.h" +#include "actions.h" +#include "fptr_cast.h" + +static const char *pcb_fgw_evnames[] = { + "pcbev_gui_init", + "pcbev_cli_enter", + "pcbev_save_pre", + "pcbev_save_post", + "pcbev_load_pre", + "pcbev_load_post", + "pcbev_board_changed", + "pcbev_board_meta_changed", + "pcbev_route_styles_changed", + "pcbev_netlist_changed", + "pcbev_layers_changed", + "pcbev_layer_changed_grp", + "pcbev_layervis_changed", + "pcbev_library_changed", + "pcbev_font_changed", + "pcbev_undo_post", + "pcbev_new_pstk", + "pcbev_busy", + "pcbev_log_append", + "pcbev_log_clear", + "pcbev_rubber_reset", + "pcbev_rubber_move", + "pcbev_rubber_move_draw", + "pcbev_rubber_rotate90", + "pcbev_rubber_rotate", + "pcbev_rubber_lookup_lines", + "pcbev_rubber_lookup_rats", + "pcbev_rubber_constrain_main_line", + "pcbev_gui_sync", + "pcbev_gui_sync_status", + "pcbev_gui_lead_user", + "pcbev_gui_draw_overlay_xor", + "pcbev_user_input_post", + "pcbev_draw_crosshair_chatt", + "pcbev_drc_run", + "pcbev_dad_new_dialog", + "pcbev_dad_new_geo", + "pcbev_net_indicate_short" +}; + +typedef struct event_s event_t; + +struct event_s { + pcb_event_handler_t *handler; + void *user_data; + const char *cookie; + event_t *next; +}; + +event_t *events[PCB_EVENT_last]; + +#define event_valid(ev) (((ev) >= 0) && ((ev) < PCB_EVENT_last)) + +void pcb_event_bind(pcb_event_id_t ev, pcb_event_handler_t * handler, void *user_data, const char *cookie) +{ + event_t *e; + + if (!(event_valid(ev))) + return; + + e = malloc(sizeof(event_t)); + e->handler = handler; + e->cookie = cookie; + e->user_data = user_data; + + /* insert the new event in front of the list */ + e->next = events[ev]; + events[ev] = e; +} + +static void event_destroy(event_t * ev) +{ + free(ev); +} + +void pcb_event_unbind(pcb_event_id_t ev, pcb_event_handler_t * handler) +{ + event_t *prev = NULL, *e, *next; + if (!(event_valid(ev))) + return; + for (e = events[ev]; e != NULL; e = next) { + next = e->next; + if (e->handler == handler) { + event_destroy(e); + if (prev == NULL) + events[ev] = next; + else + prev->next = next; + } + else + prev = e; + } +} + +void pcb_event_unbind_cookie(pcb_event_id_t ev, const char *cookie) +{ + event_t *prev = NULL, *e, *next; + if (!(event_valid(ev))) + return; + for (e = events[ev]; e != NULL; e = next) { + next = e->next; + if (e->cookie == cookie) { + event_destroy(e); + if (prev == NULL) + events[ev] = next; + else + prev->next = next; + } + else + prev = e; + } +} + + +void pcb_event_unbind_allcookie(const char *cookie) +{ + pcb_event_id_t n; + for (n = 0; n < PCB_EVENT_last; n++) + pcb_event_unbind_cookie(n, cookie); +} + +void pcb_event(pcb_event_id_t ev, const char *fmt, ...) +{ + va_list ap; + pcb_event_arg_t argv[EVENT_MAX_ARG], *a; + fgw_arg_t fargv[EVENT_MAX_ARG+1], *fa; + event_t *e; + int argc; + + if (ev >= PCB_EVENT_last) + return; + + a = argv; + a->type = PCB_EVARG_INT; + a->d.i = ev; + + fa = fargv; + fa->type = FGW_INVALID; /* first argument will be the function, as filed in by fungw; we are not passing the event number as it is impossible to bind multiple events to the same function this way */ + + argc = 1; + + if (fmt != NULL) { + va_start(ap, fmt); + for (a++, fa++; *fmt != '\0'; fmt++, a++, fa++, argc++) { + if (argc >= EVENT_MAX_ARG) { + pcb_message(PCB_MSG_ERROR, "pcb_event(): too many arguments\n"); + break; + } + switch (*fmt) { + case 'i': + a->type = PCB_EVARG_INT; + fa->type = FGW_INT; + fa->val.nat_int = a->d.i = va_arg(ap, int); + break; + case 'd': + a->type = PCB_EVARG_DOUBLE; + fa->type = FGW_DOUBLE; + fa->val.nat_double = a->d.d = va_arg(ap, double); + break; + case 's': + a->type = PCB_EVARG_STR; + fa->type = FGW_STR; + a->d.s = va_arg(ap, const char *); + fa->val.str = (char *)a->d.s; + break; + case 'p': + a->type = PCB_EVARG_PTR; + fa->type = FGW_PTR; + fa->val.ptr_void = a->d.p = va_arg(ap, void *); + break; + case 'c': + a->type = PCB_EVARG_COORD; + a->d.c = va_arg(ap, pcb_coord_t); + fa->type = FGW_LONG; + fa->val.nat_long = a->d.c; + fgw_arg_conv(&pcb_fgw, fa, FGW_COORD_); + break; + case 'a': + a->type = PCB_EVARG_ANGLE; + fa->type = FGW_DOUBLE; + fa->val.nat_double = a->d.a = va_arg(ap, pcb_angle_t); + break; + default: + a->type = PCB_EVARG_INT; + a->d.i = 0; + fa->type = FGW_INVALID; + pcb_message(PCB_MSG_ERROR, "pcb_event(): invalid argument type '%c'\n", *fmt); + break; + } + } + va_end(ap); + } + + for (e = events[ev]; e != NULL; e = e->next) + e->handler(e->user_data, argc, argv); + + fgw_call_all(&pcb_fgw, pcb_fgw_evnames[ev], argc, fargv); +} + +void pcb_events_init(void) +{ + if ((sizeof(pcb_fgw_evnames) / sizeof(pcb_fgw_evnames[0])) != PCB_EVENT_last) { + fprintf(stderr, "INTERNAL ERROR: event.c: pcb_fgw_evnames and pcb_event_id_t are out of sync\n"); + exit(1); + } +} + +void pcb_events_uninit(void) +{ + int ev; + for(ev = 0; ev < PCB_EVENT_last; ev++) { + event_t *e, *next; + for(e = events[ev]; e != NULL; e = next) { + next = e->next; + fprintf(stderr, "WARNING: events_uninit: event %d still has %p registered for cookie %p (%s)\n", ev, pcb_cast_f2d(e->handler), (void *)e->cookie, e->cookie); + free(e); + } + } +} + Index: tags/2.1.2/src/event.h =================================================================== --- tags/2.1.2/src/event.h (nonexistent) +++ tags/2.1.2/src/event.h (revision 24813) @@ -0,0 +1,138 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2016 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#ifndef PCB_EVENT_H +#define PCB_EVENT_H +#include "config.h" +#include "unit.h" +#include "global_typedefs.h" + +typedef enum { + PCB_EVENT_GUI_INIT, /* finished initializing the GUI called right before the main loop of the GUI; args: (void) */ + PCB_EVENT_CLI_ENTER, /* the user pressed enter on a CLI command - called before parsing the line for actions; args: (str commandline) */ + PCB_EVENT_SAVE_PRE, /* called before saving the design */ + PCB_EVENT_SAVE_POST, /* called after saving the design */ + PCB_EVENT_LOAD_PRE, /* called before loading a new design */ + PCB_EVENT_LOAD_POST, /* called after loading a new design, whether it was successful or not */ + + PCB_EVENT_BOARD_CHANGED, /* called after the board being edited got _replaced_ (used to be the PCBChanged action) */ + PCB_EVENT_BOARD_META_CHANGED, /* called if the metadata of the board has changed */ + PCB_EVENT_ROUTE_STYLES_CHANGED, /* called after any route style change (used to be the RouteStylesChanged action) */ + PCB_EVENT_NETLIST_CHANGED, /* called after any netlist change (used to be the NetlistChanged action) */ + PCB_EVENT_LAYERS_CHANGED, /* called after layers or layer groups change (used to be the LayersChanged action) */ + PCB_EVENT_LAYER_CHANGED_GRP, /* called after a layer changed its group; argument: layer pointer */ + PCB_EVENT_LAYERVIS_CHANGED, /* called after the visibility of layers has changed */ + PCB_EVENT_LIBRARY_CHANGED, /* called after a change in the footprint lib (used to be the LibraryChanged action) */ + PCB_EVENT_FONT_CHANGED, /* called when a font has changed; argument is the font ID */ + + PCB_EVENT_UNDO_POST, /* called after an undo/redo operation; argument is an integer pcb_undo_ev_t */ + + PCB_EVENT_NEW_PSTK, /* called when a new padstack is created */ + + PCB_EVENT_BUSY, /* called before CPU-intensive task begins */ + PCB_EVENT_LOG_APPEND, /* called after a new log line is appended; arg is a pointer to the log line */ + PCB_EVENT_LOG_CLEAR, /* called after a clear; args: two pointers; unsigned long "from" and "to" */ + + PCB_EVENT_RUBBER_RESET, /* rubber band: reset attached */ + PCB_EVENT_RUBBER_MOVE, /* rubber band: object moved */ + PCB_EVENT_RUBBER_MOVE_DRAW, /* rubber band: draw crosshair-attached rubber band objects after a move or copy */ + PCB_EVENT_RUBBER_ROTATE90, /* rubber band: crosshair object rotated by 90 degrees */ + PCB_EVENT_RUBBER_ROTATE, /* rubber band: crosshair object rotated by arbitrary angle */ + PCB_EVENT_RUBBER_LOOKUP_LINES, /* rubber band: attach rubber banded line objects to crosshair */ + PCB_EVENT_RUBBER_LOOKUP_RATS, /* rubber band: attach rubber banded rat lines objects to crosshair */ + PCB_EVENT_RUBBER_CONSTRAIN_MAIN_LINE, /* rubber band: adapt main line to keep rubberband lines direction */ + + PCB_EVENT_GUI_SYNC, /* sync full GUI state (e.g. after a menu clicked) */ + PCB_EVENT_GUI_SYNC_STATUS, /* sync partial GUI state (status line update - do not update menus and do not redraw) */ + PCB_EVENT_GUI_LEAD_USER, /* GUI aid to lead the user attention to a specific location on the board in the main drawing area; args: (coord x, coord y, int enabled) */ + PCB_EVENT_GUI_DRAW_OVERLAY_XOR, /* called in board draw after finished drawing the xor marks, still in xor draw mode */ + PCB_EVENT_USER_INPUT_POST, /* generated any time any user input reaches core, after processing it */ + + PCB_EVENT_DRAW_CROSSHAIR_CHATT, /* called from crosshair code upon attached object recalculation; event handlers can use this hook to enforce various geometric restrictions */ + + PCB_EVENT_DRC_RUN, /* called from core to run all configured DRCs (implemented in plugins) */ + PCB_EVENT_DAD_NEW_DIALOG, /* called by the GUI after a new DAD dialog is open; args are pointer hid_ctx, string dialog id and a pointer to int[4] for getting back preferre {x,y,w,h} (-1 means unknown) */ + PCB_EVENT_DAD_NEW_GEO, /* called by the GUI after the window geometry got reconfigured; args are: void *hid_ctx, const char *dialog id, int x1, int y1, int width, int height */ + + PCB_EVENT_NET_INDICATE_SHORT, /* called by core to get a shortcircuit indicated (e.g. by mincut). Args: (pcb_net_t *net, pcb_any_obj_t *offending_term, pcb_net_t *offending_net, int *handled) - if *handled is non-zero, the short is already indicated */ + + PCB_EVENT_last /* not a real event */ +} pcb_event_id_t; + +/* Maximum number of arguments for an event handler, auto-set argv[0] included */ +#define EVENT_MAX_ARG 16 + +/* Argument types in event's argv[] */ +typedef enum { + PCB_EVARG_INT, /* format char: i */ + PCB_EVARG_DOUBLE, /* format char: d */ + PCB_EVARG_STR, /* format char: s */ + PCB_EVARG_PTR, /* format char: p */ + PCB_EVARG_COORD, /* format char: c */ + PCB_EVARG_ANGLE /* format char: a */ +} pcb_event_argtype_t; + +/* An argument is its type and value */ +struct pcb_event_arg_s { + pcb_event_argtype_t type; + union { + int i; + double d; + const char *s; + void *p; + pcb_coord_t c; + pcb_angle_t a; + } d; +}; + +/* Initialize the event system */ +void pcb_events_init(void); + +/* Uninitialize the event system and remove all events */ +void pcb_events_uninit(void); + + +/* Event callback prototype; user_data is the same as in pcb_event_bind(). + argv[0] is always an PCB_EVARG_INT with the event id that triggered the event. */ +typedef void (pcb_event_handler_t) (void *user_data, int argc, pcb_event_arg_t argv[]); + +/* Bind: add a handler to the call-list of an event; the cookie is also remembered + so that mass-unbind is easier later. user_data is passed to the handler. */ +void pcb_event_bind(pcb_event_id_t ev, pcb_event_handler_t * handler, void *user_data, const char *cookie); + +/* Unbind: remove a handler from an event */ +void pcb_event_unbind(pcb_event_id_t ev, pcb_event_handler_t * handler); + +/* Unbind by cookie: remove all handlers from an event matching the cookie */ +void pcb_event_unbind_cookie(pcb_event_id_t ev, const char *cookie); + +/* Unbind all by cookie: remove all handlers from all events matching the cookie */ +void pcb_event_unbind_allcookie(const char *cookie); + +/* Event trigger: call all handlers for an event. Fmt is a list of + format characters (e.g. i for PCB_EVARG_INT). */ +void pcb_event(pcb_event_id_t ev, const char *fmt, ...); +#endif Index: tags/2.1.2/src/file_act.c =================================================================== --- tags/2.1.2/src/file_act.c (nonexistent) +++ tags/2.1.2/src/file_act.c (revision 24813) @@ -0,0 +1,322 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * Copyright (C) 1997, 1998, 1999, 2000, 2001 Harry Eaton + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + * + * Old contact info: + * Harry Eaton, 6697 Buttonhole Ct, Columbia, MD 21044, USA + * haceaton@aplcomm.jhuapl.edu + * + */ +#include "config.h" +#include "board.h" +#include "build_run.h" +#include "conf_core.h" +#include "funchash_core.h" +#include "data.h" +#include "buffer.h" + +#include "plug_io.h" +#include "plug_import.h" +#include "remove.h" +#include "draw.h" +#include "find.h" +#include "search.h" +#include "actions.h" +#include "compat_misc.h" +#include "hid_init.h" +#include "layer_vis.h" +#include "safe_fs.h" +#include "tool.h" +#include "netlist2.h" + + +static const char pcb_acts_LoadFrom[] = "LoadFrom(Layout|LayoutToBuffer|SubcToBuffer|Netlist|Revert,filename[,format])"; +static const char pcb_acth_LoadFrom[] = "Load layout data from a file."; +/* DOC: loadfrom.html */ +fgw_error_t pcb_act_LoadFrom(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + const char *name, *format = NULL; + int op; + + PCB_ACT_CONVARG(1, FGW_KEYWORD, LoadFrom, op = fgw_keyword(&argv[1])); + PCB_ACT_CONVARG(2, FGW_STR, LoadFrom, name = argv[2].val.str); + PCB_ACT_MAY_CONVARG(3, FGW_STR, LoadFrom, format = argv[3].val.str); + + switch(op) { + case F_ElementToBuffer: + case F_FootprintToBuffer: + case F_Element: + case F_SubcToBuffer: + case F_Subcircuit: + case F_Footprint: + pcb_notify_crosshair_change(pcb_false); + if (pcb_buffer_load_footprint(PCB_PASTEBUFFER, name, format)) + pcb_tool_select_by_id(PCB_MODE_PASTE_BUFFER); + pcb_notify_crosshair_change(pcb_true); + break; + + case F_LayoutToBuffer: + pcb_notify_crosshair_change(pcb_false); + if (pcb_buffer_load_layout(PCB, PCB_PASTEBUFFER, name, format)) + pcb_tool_select_by_id(PCB_MODE_PASTE_BUFFER); + pcb_notify_crosshair_change(pcb_true); + break; + + case F_Layout: + if (!PCB->Changed || pcb_hid_message_box("warning", "File overwrite", "OK to override layout data?", "cancel", 0, "ok", 1, NULL)) + pcb_load_pcb(name, format, pcb_true, 0); + break; + + case F_Netlist: + if (PCB->Netlistname) + free(PCB->Netlistname); + PCB->Netlistname = pcb_strdup_strip_wspace(name); + { + int i; + for (i = 0; i < PCB_NUM_NETLISTS; i++) { + pcb_netlist_uninit(&(PCB->netlist[i])); + pcb_netlist_init(&(PCB->netlist[i])); + } + } + if (!pcb_import_netlist(PCB->Netlistname)) + pcb_netlist_changed(1); + break; + + case F_Revert: + if (PCB->Filename && (!PCB->Changed || (pcb_hid_message_box("warning", "Revert: lose data", "Really revert all modifications?", "no", 0, "yes", 1, NULL) == 1))) + pcb_revert_pcb(); + break; + + default: + pcb_message(PCB_MSG_ERROR, "LoadFrom(): invalid command (first arg)\n"); + PCB_ACT_IRES(1); + return 0; + } + + PCB_ACT_IRES(0); + return 0; +} + +static const char pcb_acts_New[] = "New([name])"; +static const char pcb_acth_New[] = "Starts a new layout."; +/* DOC: new.html */ +static fgw_error_t pcb_act_New(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + const char *argument_name = NULL; + char *name = NULL; + + PCB_ACT_MAY_CONVARG(1, FGW_STR, New, argument_name = argv[1].val.str); + + if (!PCB->Changed || (pcb_hid_message_box("warning", "New pcb", "OK to clear layout data?", "cancel", 0, "yes", 1, NULL) == 1)) { + if (argument_name) + name = pcb_strdup(argument_name); + else + name = pcb_hid_prompt_for("Enter the layout name:", "", "Layout name"); + + if (!name) + return 1; + + pcb_notify_crosshair_change(pcb_false); + /* do emergency saving + * clear the old struct and allocate memory for the new one + */ + if (PCB->Changed && conf_core.editor.save_in_tmp) + pcb_save_in_tmp(); + pcb_board_remove(PCB); + PCB = pcb_board_new(1); + pcb_board_new_postproc(PCB, 1); + pcb_set_design_dir(NULL); + conf_set(CFR_DESIGN, "design/text_font_id", 0, "0", POL_OVERWRITE); /* we have only one font now, make sure it is selected */ + + /* setup the new name and reset some values to default */ + free(PCB->Name); + PCB->Name = name; + + pcb_layervis_reset_stack(); + pcb_crosshair_set_range(0, 0, PCB->MaxWidth, PCB->MaxHeight); + pcb_center_display(PCB->MaxWidth / 2, PCB->MaxHeight / 2); + pcb_redraw(); + pcb_board_changed(0); + pcb_notify_crosshair_change(pcb_true); + PCB_ACT_IRES(0); + return 0; + } + PCB_ACT_IRES(-1); + return 0; +} + +/* --------------------------------------------------------------------------- */ +static const char pcb_acts_normalize[] = "Normalize()"; +static const char pcb_acth_normalize[] = "Move all objects within the drawing area, align the drawing to 0;0"; +static fgw_error_t pcb_act_normalize(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + PCB_ACT_IRES(pcb_board_normalize(PCB)); + return 0; +} + + +static const char pcb_acts_SaveTo[] = + "SaveTo(Layout|LayoutAs,filename,[fmt])\n" + "SaveTo(PasteBuffer,filename,[fmt])"; +static const char pcb_acth_SaveTo[] = "Saves data to a file."; +/* DOC: saveto.html */ +fgw_error_t pcb_act_SaveTo(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + int op; + const char *name = NULL; + const char *fmt = NULL; + + PCB_ACT_CONVARG(1, FGW_KEYWORD, SaveTo, op = fgw_keyword(&argv[1])); + PCB_ACT_MAY_CONVARG(2, FGW_STR, SaveTo, name = argv[2].val.str); + PCB_ACT_MAY_CONVARG(3, FGW_STR, SaveTo, fmt = argv[3].val.str); + PCB_ACT_IRES(0); + + if ((op != F_Layout) && (name == NULL)) + PCB_ACT_FAIL(SaveTo); + + switch(op) { + case F_Layout: + if (argc != 2) { + pcb_message(PCB_MSG_ERROR, "SaveTo(Layout) doesn't take file name or format - did you mean SaveTo(LayoutAs)?\n"); + return FGW_ERR_ARGC; + } + if (pcb_save_pcb(PCB->Filename, NULL) == 0) + pcb_board_set_changed_flag(pcb_false); + if (pcb_gui->notify_filename_changed != NULL) + pcb_gui->notify_filename_changed(); + return 0; + + case F_LayoutAs: + if (pcb_save_pcb(name, fmt) == 0) { + pcb_board_set_changed_flag(pcb_false); + free(PCB->Filename); + PCB->Filename = pcb_strdup(name); + if (pcb_gui->notify_filename_changed != NULL) + pcb_gui->notify_filename_changed(); + } + return 0; + + + case F_PasteBuffer: + PCB_ACT_IRES(pcb_save_buffer_elements(name, fmt)); + return 0; + + /* shorthand kept only for compatibility reasons - do not use */ + case F_AllConnections: + pcb_message(PCB_MSG_WARNING, "Please use action ExportOldConn() instead of SaveTo() for connections.\n"); + return pcb_actionl("ExportOldConn", "AllConnections", name, NULL); + case F_AllUnusedPins: + pcb_message(PCB_MSG_WARNING, "Please use action ExportOldConn() instead of SaveTo() for connections.\n"); + return pcb_actionl("ExportOldConn", "AllUnusedPins", name, NULL); + case F_ElementConnections: + case F_SubcConnections: + pcb_message(PCB_MSG_WARNING, "Please use action ExportOldConn() instead of SaveTo() for connections.\n"); + return pcb_actionl("ExportOldConn", "SubcConnections", name, NULL); + } + + PCB_ACT_FAIL(SaveTo); +} + +static const char pcb_acts_Quit[] = "Quit()"; +static const char pcb_acth_Quit[] = "Quits the application after confirming."; +/* DOC: quit.html */ +static fgw_error_t pcb_act_Quit(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + const char *force = NULL; + PCB_ACT_MAY_CONVARG(1, FGW_STR, Quit, force = argv[1].val.str); + + if ((force != NULL) && (pcb_strcasecmp(force, "force") == 0)) + exit(0); + if (!PCB->Changed || (pcb_hid_message_box("warning", "Close: lose data", "OK to lose data?", "cancel", 0, "ok", 1, NULL) == 1)) + pcb_quit_app(); + PCB_ACT_IRES(-1); + return 0; +} + + +static const char pcb_acts_Export[] = "Export(exporter, [exporter-args])"; +static const char pcb_acth_Export[] = "Export the current layout, e.g. Export(png, --dpi, 600)"; +static fgw_error_t pcb_act_Export(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + char *args[128]; + char **a; + int n; + + if (argc < 1) { + pcb_message(PCB_MSG_ERROR, "Export() needs at least one argument, the name of the export plugin\n"); + return 1; + } + + if (argc > sizeof(args)/sizeof(args[0])) { + pcb_message(PCB_MSG_ERROR, "Export(): too many arguments\n"); + return 1; + } + + args[0] = NULL; + for(n = 1; n < argc; n++) + PCB_ACT_CONVARG(n, FGW_STR, Export, args[n-1] = argv[n].val.str); + + pcb_exporter = pcb_hid_find_exporter(args[0]); + if (pcb_exporter == NULL) { + pcb_message(PCB_MSG_ERROR, "Export plugin %s not found. Was it enabled in ./configure?\n", args[0]); + return 1; + } + + /* remove the name of the exporter */ + argc-=2; + + /* call the exporter */ + a = args; + a++; + pcb_exporter->parse_arguments(&argc, &a); + pcb_exporter->do_export(NULL); + + pcb_exporter = NULL; + PCB_ACT_IRES(0); + return 0; +} + +static const char pcb_acts_Backup[] = "Backup()"; +static const char pcb_acth_Backup[] = "Backup the current layout - save using the same method that the timed backup function uses"; +static fgw_error_t pcb_act_Backup(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + pcb_backup(); + PCB_ACT_IRES(0); + return 0; +} + +pcb_action_t file_action_list[] = { + {"Backup", pcb_act_Backup, pcb_acth_Backup, pcb_acts_Backup}, + {"Export", pcb_act_Export, pcb_acth_Export, pcb_acts_Export}, + {"LoadFrom", pcb_act_LoadFrom, pcb_acth_LoadFrom, pcb_acts_LoadFrom}, + {"New", pcb_act_New, pcb_acth_New, pcb_acts_New}, + {"Normalize", pcb_act_normalize, pcb_acth_normalize, pcb_acts_normalize}, + {"SaveTo", pcb_act_SaveTo, pcb_acth_SaveTo, pcb_acts_SaveTo}, + {"Quit", pcb_act_Quit, pcb_acth_Quit, pcb_acts_Quit} +}; + +PCB_REGISTER_ACTIONS(file_action_list, NULL) Index: tags/2.1.2/src/file_loaded.c =================================================================== --- tags/2.1.2/src/file_loaded.c (nonexistent) +++ tags/2.1.2/src/file_loaded.c (revision 24813) @@ -0,0 +1,155 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * pcb-rnd Copyright (C) 2018 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +#include "config.h" +#include +#include +#include "file_loaded.h" +#include "compat_misc.h" + +htsp_t pcb_file_loaded; + +pcb_file_loaded_t *pcb_file_loaded_category(const char *name, int alloc) +{ + pcb_file_loaded_t *cat = htsp_get(&pcb_file_loaded, name); + + if ((cat == NULL) && (alloc)) { + cat = calloc(sizeof(pcb_file_loaded_t), 1); + cat->type = PCB_FLT_CATEGORY; + cat->name = pcb_strdup(name); + htsp_init(&cat->data.category.children, strhash, strkeyeq); + htsp_set(&pcb_file_loaded, cat->name, cat); + } + return cat; +} + +int pcb_file_loaded_file_free(pcb_file_loaded_t *file) +{ + free(file->data.file.path); + free(file->data.file.desc); + free(file->name); + free(file); + return 0; +} + +int pcb_file_loaded_clear(pcb_file_loaded_t *cat) +{ + htsp_entry_t *e; + + assert(cat->type == PCB_FLT_CATEGORY); + + for (e = htsp_first(&cat->data.category.children); e; e = htsp_next(&cat->data.category.children, e)) { + pcb_file_loaded_file_free(e->value); + htsp_delentry(&cat->data.category.children, e); + } + return 0; +} + +int pcb_file_loaded_clear_at(const char *catname) +{ + pcb_file_loaded_t *cat = pcb_file_loaded_category(catname, 0); + if (cat != NULL) + return pcb_file_loaded_clear(cat); + return 0; +} + +int pcb_file_loaded_set(pcb_file_loaded_t *cat, const char *name, const char *path, const char *desc) +{ + pcb_file_loaded_t *file; + + assert(cat->type == PCB_FLT_CATEGORY); + file = htsp_get(&cat->data.category.children, name); + if (file != NULL) { + free(file->data.file.path); + free(file->data.file.desc); + } + else { + file = malloc(sizeof(pcb_file_loaded_t)); + file->type = PCB_FLT_FILE; + file->name = pcb_strdup(name); + htsp_set(&cat->data.category.children, file->name, file); + } + if (path != NULL) + file->data.file.path = pcb_strdup(path); + else + file->data.file.path = NULL; + + if (desc != NULL) + file->data.file.desc = pcb_strdup(desc); + else + file->data.file.desc = NULL; + return 0; +} + +int pcb_file_loaded_set_at(const char *catnam, const char *name, const char *path, const char *desc) +{ + pcb_file_loaded_t *cat = pcb_file_loaded_category(catnam, 1); + return pcb_file_loaded_set(cat, name, path, desc); +} + +int pcb_file_loaded_del(pcb_file_loaded_t *cat, const char *name) +{ + pcb_file_loaded_t *file; + assert(cat->type == PCB_FLT_CATEGORY); + file = htsp_pop(&cat->data.category.children, name); + if (file != NULL) { + if (file->type != PCB_FLT_FILE) + return -1; + pcb_file_loaded_file_free(file); + } + return 0; +} + +int pcb_file_loaded_del_at(const char *catname, const char *name) +{ + pcb_file_loaded_t *cat = pcb_file_loaded_category(catname, 1); + return pcb_file_loaded_del(cat, name); +} + +void pcb_file_loaded_init(void) +{ + htsp_init(&pcb_file_loaded, strhash, strkeyeq); +} + +void pcb_file_loaded_uninit(void) +{ + htsp_entry_t *e; + + for (e = htsp_first(&pcb_file_loaded); e; e = htsp_next(&pcb_file_loaded, e)) { + pcb_file_loaded_t *cat = e->value; + pcb_file_loaded_clear(cat); + free(cat->name); + htsp_uninit(&cat->data.category.children); + free(cat); + htsp_delentry(&pcb_file_loaded, e); + } + + htsp_uninit(&pcb_file_loaded); +} + + Index: tags/2.1.2/src/file_loaded.h =================================================================== --- tags/2.1.2/src/file_loaded.h (nonexistent) +++ tags/2.1.2/src/file_loaded.h (revision 24813) @@ -0,0 +1,82 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 2018 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +/* info on where files are loaded from */ + +#ifndef PCB_FILE_LOADED_H +#define PCB_FILE_LOADED_H + +#include + +/* Hash-in-hash tree with the top tree being categories. */ + +typedef enum pcb_file_loaded_type_e { + PCB_FLT_CATEGORY, + PCB_FLT_FILE +} pcb_file_loaded_type_t; + +typedef struct pcb_file_loaded_s pcb_file_loaded_t; + +struct pcb_file_loaded_s { + char *name; /* same as the hash key; strdup'd */ + pcb_file_loaded_type_t type; + union { + struct { + htsp_t children; + } category; + struct { + char *path; + char *desc; + } file; + } data; +}; + +extern htsp_t pcb_file_loaded; + +/* Return the category called name; if doesn't exist and alloc is 1, + allocate it it (else return NULL) */ +pcb_file_loaded_t *pcb_file_loaded_category(const char *name, int alloc); + +/* clear the subtree of a category, keeping the category; return 0 on success */ +int pcb_file_loaded_clear(pcb_file_loaded_t *cat); +int pcb_file_loaded_clear_at(const char *catname); + +/* clear the subtree of a category, keeping the category; return 0 on success */ +int pcb_file_loaded_set(pcb_file_loaded_t *cat, const char *name, const char *path, const char *desc); +int pcb_file_loaded_set_at(const char *catname, const char *name, const char *path, const char *desc); + +/* remove an entry */ +int pcb_file_loaded_del(pcb_file_loaded_t *cat, const char *name); +int pcb_file_loaded_del_at(const char *catname, const char *name); + + +/* called once, from main */ +void pcb_file_loaded_init(void); +void pcb_file_loaded_uninit(void); + +#endif Index: tags/2.1.2/src/find.c =================================================================== --- tags/2.1.2/src/find.c (nonexistent) +++ tags/2.1.2/src/find.c (revision 24813) @@ -0,0 +1,383 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2018 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +/* Follow galvanic connections through overlapping objects */ + +#include "config.h" +#include "find.h" +#include "undo.h" +#include "obj_subc_parent.h" + +TODO("find: this is the only non-reentrant part - pass it on!") +pcb_coord_t Bloat = 0; + +#include "find_geo.c" +#include "find_any_isect.c" + +/* trickery: keeping vtp0 is reentrant and is cheaper than keeping lists, + at least for appending. But as long as only the last item is removed, + it's also cheap on remove! */ + +/* Do everything that needs to be done for an object found */ +static int pcb_find_found(pcb_find_t *ctx, pcb_any_obj_t *obj, pcb_any_obj_t *arrived_from, pcb_found_conn_type_t ctype) +{ + if (ctx->list_found) + vtp0_append(&ctx->found, obj); + + if ((ctx->flag_set != 0) || (ctx->flag_clr != 0)) { + if (ctx->flag_chg_undoable) + pcb_undo_add_obj_to_flag(obj); + if (ctx->flag_set != 0) + PCB_FLAG_SET(ctx->flag_set, obj); + if (ctx->flag_clr != 0) + PCB_FLAG_CLEAR(ctx->flag_clr, obj); + } + + ctx->nfound++; + + if ((ctx->found_cb != NULL) && (ctx->found_cb(ctx, obj, arrived_from, ctype) != 0)) { + ctx->aborted = 1; + return 1; + } + + return 0; +} + + +static int pcb_find_addobj(pcb_find_t *ctx, pcb_any_obj_t *obj, pcb_any_obj_t *arrived_from, pcb_found_conn_type_t ctype, int jump) +{ + PCB_DFLAG_SET(&obj->Flags, ctx->mark); + if (jump) + vtp0_append(&ctx->open, obj); + + if (pcb_find_found(ctx, obj, arrived_from, ctype) != 0) { + ctx->aborted = 1; + return 1; + } + return 0; +} + +static void find_int_conn(pcb_find_t *ctx, pcb_any_obj_t *from_) +{ + void *from = from_; /* for warningless comparison */ + pcb_subc_t *s; + int ic; + + s = pcb_obj_parent_subc(from_); + if (s == NULL) + return; + + ic = from_->intconn; + + PCB_PADSTACK_LOOP(s->data); + { + if ((padstack != from) && (padstack->term != NULL) && (padstack->intconn == ic) && (!(PCB_DFLAG_TEST(&(padstack->Flags), ctx->mark)))) + if (pcb_find_addobj(ctx, (pcb_any_obj_t *)padstack, from_, PCB_FCT_INTCONN, 1) != 0) + return; + } + PCB_END_LOOP; + + PCB_LINE_COPPER_LOOP(s->data); + { + if ((line != from) && (line->term != NULL) && (line->intconn == ic) && (!(PCB_DFLAG_TEST(&(line->Flags), ctx->mark)))) + if (pcb_find_addobj(ctx, (pcb_any_obj_t *)line, from_, PCB_FCT_INTCONN, 1) != 0) + return; + } + PCB_ENDALL_LOOP; + + PCB_ARC_COPPER_LOOP(s->data); + { + if ((arc != from) && (arc->term != NULL) && (arc->intconn == ic) && (!(PCB_DFLAG_TEST(&(arc->Flags), ctx->mark)))) + if (pcb_find_addobj(ctx, (pcb_any_obj_t *)arc, from_, PCB_FCT_INTCONN, 1) != 0) + return; + } + PCB_ENDALL_LOOP; + + PCB_POLY_COPPER_LOOP(s->data); + { + if ((polygon != from) && (polygon->term != NULL) && (polygon->intconn == ic) && (!(PCB_DFLAG_TEST(&(polygon->Flags), ctx->mark)))) + if (pcb_find_addobj(ctx, (pcb_any_obj_t *)polygon, from_, PCB_FCT_INTCONN, 1) != 0) + return; + } + PCB_ENDALL_LOOP; + +TODO("find: no find through text yet") +#if 0 + PCB_TEXT_COPPER_LOOP(s->data); + { + if ((text != from) && (text->term != NULL) && (text->intconn == ic) && (!(PCB_DFLAG_TEST(&(text->Flags), ctx->mark)))) + if (pcb_find_addobj(ctx, (pcb_any_obj_t *)text, from_, PCB_FCT_INTCONN, 1) != 0) + return; + } + PCB_ENDALL_LOOP; +#endif +} + +/* return whether a and b are in the same internal-no-connection group */ +static pcb_bool int_noconn(pcb_any_obj_t *a, pcb_any_obj_t *b) +{ + pcb_subc_t *pa, *pb; + + /* cheap test: they need to have valid and matching intnoconn */ + if ((a->intnoconn == 0) || (a->intnoconn != b->intnoconn)) + return pcb_false; + + /* expensive tests: they need to be in the same subc */ + pa = pcb_obj_parent_subc(a); + if (pa == NULL) + return pcb_false; + + pb = pcb_obj_parent_subc(b); + + return (pa == pb); +} + +#define INOCONN(a,b) int_noconn((pcb_any_obj_t *)a, (pcb_any_obj_t *)b) + +#define PCB_FIND_CHECK(ctx, curr, obj, ctype, retstmt) \ + do { \ + pcb_any_obj_t *__obj__ = (pcb_any_obj_t *)obj; \ + if (!(PCB_DFLAG_TEST(&(__obj__->Flags), ctx->mark))) { \ + if (!INOCONN(curr, obj) && (pcb_intersect_obj_obj(curr, __obj__))) {\ + if (pcb_find_addobj(ctx, __obj__, curr, ctype, 1) != 0) { retstmt; } \ + if ((__obj__->term != NULL) && (!ctx->ignore_intconn) && (__obj__->intconn > 0)) \ + find_int_conn(ctx, __obj__); \ + } \ + } \ + } while(0) + +#define PCB_FIND_CHECK_RAT(ctx, curr, obj, ctype, retstmt) \ + do { \ + pcb_any_obj_t *__obj__ = (pcb_any_obj_t *)obj; \ + if (!(PCB_DFLAG_TEST(&(__obj__->Flags), ctx->mark))) { \ + if (!INOCONN(curr, obj) && (pcb_intersect_obj_obj(curr, __obj__))) {\ + if (pcb_find_addobj(ctx, __obj__, curr, ctype, ctx->consider_rats) != 0) { retstmt; } \ + if ((__obj__->term != NULL) && (!ctx->ignore_intconn) && (__obj__->intconn > 0)) \ + find_int_conn(ctx, __obj__); \ + } \ + } \ + } while(0) + +void pcb_find_on_layer(pcb_find_t *ctx, pcb_layer_t *l, pcb_any_obj_t *curr, pcb_rtree_box_t *sb, pcb_found_conn_type_t ctype) +{ + pcb_rtree_it_t it; + pcb_box_t *n; + + if (l->line_tree != NULL) { + for(n = pcb_rtree_first(&it, l->line_tree, sb); n != NULL; n = pcb_rtree_next(&it)) + PCB_FIND_CHECK(ctx, curr, n, ctype, return); + pcb_r_end(&it); + } + + if (l->arc_tree != NULL) { + for(n = pcb_rtree_first(&it, l->arc_tree, sb); n != NULL; n = pcb_rtree_next(&it)) + PCB_FIND_CHECK(ctx, curr, n, ctype, return); + pcb_r_end(&it); + } + + if (l->polygon_tree != NULL) { + for(n = pcb_rtree_first(&it, l->polygon_tree, sb); n != NULL; n = pcb_rtree_next(&it)) + PCB_FIND_CHECK(ctx, curr, n, ctype, return); + pcb_r_end(&it); + } + + if (l->text_tree != NULL) { + for(n = pcb_rtree_first(&it, l->text_tree, sb); n != NULL; n = pcb_rtree_next(&it)) + PCB_FIND_CHECK(ctx, curr, n, ctype, return); + pcb_r_end(&it); + } +} + +void pcb_find_on_layergrp(pcb_find_t *ctx, pcb_layergrp_t *g, pcb_any_obj_t *curr, pcb_rtree_box_t *sb, pcb_found_conn_type_t ctype) +{ + int n; + if (g == NULL) + return; + for(n = 0; n < g->len; n++) + pcb_find_on_layer(ctx, &ctx->data->Layer[g->lid[n]], curr, sb, ctype); +} + +static void pcb_find_rat(pcb_find_t *ctx, pcb_rat_t *rat) +{ + pcb_rtree_box_t sb; + + sb.x1 = rat->Point1.X; sb.x2 = rat->Point1.X+1; + sb.y1 = rat->Point1.Y; sb.y2 = rat->Point1.Y+1; + pcb_find_on_layergrp(ctx, pcb_get_layergrp(ctx->pcb, rat->group1), (pcb_any_obj_t *)rat, &sb, PCB_FCT_RAT); + + sb.x1 = rat->Point2.X; sb.x2 = rat->Point2.X+1; + sb.y1 = rat->Point2.Y; sb.y2 = rat->Point2.Y+1; + pcb_find_on_layergrp(ctx, pcb_get_layergrp(ctx->pcb, rat->group2), (pcb_any_obj_t *)rat, &sb, PCB_FCT_RAT); +} + +static unsigned long pcb_find_exec(pcb_find_t *ctx) +{ + pcb_any_obj_t *curr; + pcb_found_conn_type_t ctype; + + if ((ctx->start_layergrp == NULL) && (ctx->open.used > 0) && (ctx->pcb != NULL)) { + curr = ctx->open.array[0]; + if ((curr != NULL) && (curr->parent_type == PCB_PARENT_LAYER)) { + pcb_layergrp_id_t gid = pcb_layer_get_group_(curr->parent.layer); + ctx->start_layergrp = pcb_get_layergrp(ctx->pcb, gid); + if (!ctx->allow_noncopper) { + TODO("find.c: implement this; special case: starting layer object on non-copper can still jump on padstack!"); + } + } + } + + while((ctx->open.used > 0) && (!ctx->aborted)) { + /* pop the last object, without reallocating to smaller, mark it found */ + ctx->open.used--; + curr = ctx->open.array[ctx->open.used]; + ctype = curr->type == PCB_OBJ_RAT ? PCB_FCT_RAT : PCB_FCT_COPPER; + + { /* search unmkared connections: iterative approach */ + pcb_rtree_it_t it; + pcb_box_t *n; + pcb_rtree_box_t *sb = (pcb_rtree_box_t *)&curr->bbox_naked; + + if (PCB->Data->padstack_tree != NULL) { + for(n = pcb_rtree_first(&it, PCB->Data->padstack_tree, sb); n != NULL; n = pcb_rtree_next(&it)) + PCB_FIND_CHECK(ctx, curr, n, ctype, return ctx->nfound); + pcb_r_end(&it); + } + + if ((ctx->consider_rats || ctx->only_mark_rats) && (PCB->Data->rat_tree != NULL)) { + if (PCB->Data->padstack_tree != NULL) { + for(n = pcb_rtree_first(&it, PCB->Data->rat_tree, sb); n != NULL; n = pcb_rtree_next(&it)) + PCB_FIND_CHECK_RAT(ctx, curr, n, PCB_FCT_RAT, return ctx->nfound); + pcb_r_end(&it); + } + } + + if (curr->type == PCB_OBJ_PSTK) { + int li; + pcb_layer_t *l; + if ((!ctx->stay_layergrp) || (ctx->start_layergrp == NULL)) { + for(li = 0, l = ctx->data->Layer; li < ctx->data->LayerN; li++,l++) { + if (!ctx->allow_noncopper) { + /* skip anything that's not on a copper layer */ + pcb_layer_type_t lyt = pcb_layer_flags_(l); + if (!(lyt & PCB_LYT_COPPER)) + continue; + } + if (pcb_pstk_shape_at_(ctx->pcb, (pcb_pstk_t *)curr, l, 0)) + pcb_find_on_layer(ctx, l, curr, sb, ctype); + } + } + else { + for(li = 0; li < ctx->start_layergrp->len; li++) { + l = pcb_get_layer(ctx->data, ctx->start_layergrp->lid[li]); + if (l != NULL) + pcb_find_on_layer(ctx, l, curr, sb, ctype); + } + } + } + else if (curr->type == PCB_OBJ_RAT) { + pcb_find_rat(ctx, (pcb_rat_t *)curr); + } + else { + /* layer objects need to be checked against same layer objects only */ + assert(curr->parent_type == PCB_PARENT_LAYER); + pcb_find_on_layer(ctx, curr->parent.layer, curr, sb, ctype); + } + } + } + + if (ctx->flag_chg_undoable) + pcb_undo_inc_serial(); + + return ctx->nfound; +} + +static int pcb_find_init_(pcb_find_t *ctx, pcb_data_t *data) +{ + if (ctx->in_use) + return -1; + ctx->in_use = 1; + ctx->aborted = 0; + ctx->mark = pcb_dynflag_alloc("pcb_find_from_obj"); + ctx->data = data; + ctx->nfound = 0; + ctx->start_layergrp = NULL; + ctx->pcb = pcb_data_get_top(data); + + if (ctx->list_found) + vtp0_init(&ctx->found); + vtp0_init(&ctx->open); + return 0; +} + +unsigned long pcb_find_from_obj(pcb_find_t *ctx, pcb_data_t *data, pcb_any_obj_t *from) +{ + if (pcb_find_init_(ctx, data) < 0) + return -1; + + pcb_data_dynflag_clear(data, ctx->mark); + pcb_find_addobj(ctx, from, NULL, PCB_FCT_START, 1); /* add the starting object with no 'arrived_from' */ + return pcb_find_exec(ctx); +} + +unsigned long pcb_find_from_obj_next(pcb_find_t *ctx, pcb_data_t *data, pcb_any_obj_t *from) +{ + pcb_find_addobj(ctx, from, NULL, PCB_FCT_START, 1); /* add the starting object with no 'arrived_from' */ + return pcb_find_exec(ctx); +} + + +unsigned long pcb_find_from_xy(pcb_find_t *ctx, pcb_data_t *data, pcb_coord_t x, pcb_coord_t y) +{ + void *ptr1, *ptr2, *ptr3; + pcb_any_obj_t *obj; + int type; + + type = pcb_search_obj_by_location(PCB_LOOKUP_FIRST, &ptr1, &ptr2, &ptr3, x, y, PCB_SLOP * pcb_pixel_slop); + if (type == PCB_OBJ_VOID) + type = pcb_search_obj_by_location(PCB_LOOKUP_MORE, &ptr1, &ptr2, &ptr3, x, y, PCB_SLOP * pcb_pixel_slop); + + if (type == PCB_OBJ_VOID) + return -1; + + obj = ptr2; + if ((obj->parent_type == PCB_PARENT_LAYER) && ((pcb_layer_flags_(obj->parent.layer) & PCB_LYT_COPPER) == 0)) + return -1; /* non-conductive object */ + + return pcb_find_from_obj(ctx, data, obj); +} + + +void pcb_find_free(pcb_find_t *ctx) +{ + if (!ctx->in_use) + return; + if (ctx->list_found) + vtp0_uninit(&ctx->found); + vtp0_uninit(&ctx->open); + pcb_dynflag_free(ctx->mark); + ctx->in_use = 0; +} + Index: tags/2.1.2/src/find.h =================================================================== --- tags/2.1.2/src/find.h (nonexistent) +++ tags/2.1.2/src/find.h (revision 24813) @@ -0,0 +1,110 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2018 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +/* Follow galvanic connections through overlapping objects */ + +#ifndef PCB_FIND2_H +#define PCB_FIND2_H + +#include +#include "global_typedefs.h" +#include "flag.h" + +typedef enum { + PCB_FCT_COPPER = 1, /* copper connection */ + PCB_FCT_INTCONN = 2, /* subc internal connection, using the intconn attrib */ + PCB_FCT_RAT = 4, /* connected between a rat line and anything else */ + PCB_FCT_START = 8 /* starting object of a query */ +} pcb_found_conn_type_t; + +typedef struct pcb_find_s pcb_find_t; +struct pcb_find_s { + /* public config - all-zero uses the original method, except for flag set */ + unsigned stay_layergrp:1; /* do not leave the layer (no padstack hop) */ + unsigned allow_noncopper:1; /* also run on non-copper objects */ + unsigned list_found:1; /* allow adding objects in the ->found vector */ + unsigned ignore_intconn:1; /* do not jump terminals on subc intconn */ + unsigned consider_rats:1; /* don't ignore rat lines, don't consider physical objects only */ + unsigned only_mark_rats:1; /* don't ignore rat lines, find them, but do not jump over them */ + unsigned flag_chg_undoable:1; /* when set, and flag_set or flag_clr is non-zero, put all found objects on the flag-undo before the flag change */ + unsigned long flag_set; /* when non-zero, set the static flag bits on objects found */ + unsigned long flag_clr; /* when non-zero, remove the static flag bits on objects found */ + + /* if non-NULL, call after an object is found; if returns non-zero, + set ->aborted and stop the search. When search started from an object, + it is called for the starting object as well. All object data and ctx + fields are updated for new_obj before the call. arrived_from is + the previous object (that already triggered a callback) from which + new_obj was first found; can be NULL for the starting object. ctype + describes the relation between arrived_from and new_obj. */ + int (*found_cb)(pcb_find_t *ctx, pcb_any_obj_t *new_obj, pcb_any_obj_t *arrived_from, pcb_found_conn_type_t ctype); + + /* public state/result */ + vtp0_t found; /* objects found, when list_found is 1 - of (pcb_any_obj_t *) */ + void *user_data; /* filled in by caller, not read or modified by find code */ + + /* private */ + vtp0_t open; /* objects already found but need checking for conns of (pcb_any_obj_t *) */ + pcb_data_t *data; + pcb_board_t *pcb; + pcb_layergrp_t *start_layergrp; + pcb_dynf_t mark; + unsigned long nfound; + unsigned in_use:1; + unsigned aborted:1; +}; + + +unsigned long pcb_find_from_obj(pcb_find_t *ctx, pcb_data_t *data, pcb_any_obj_t *from); +unsigned long pcb_find_from_xy(pcb_find_t *ctx, pcb_data_t *data, pcb_coord_t x, pcb_coord_t y); + +/* Same as pcb_find_from_obj but assumes ctx already seen a pcb_find_from_obj() + and continues from that state */ +unsigned long pcb_find_from_obj_next(pcb_find_t *ctx, pcb_data_t *data, pcb_any_obj_t *from); + +void pcb_find_free(pcb_find_t *ctx); + +/* High level intersection function: returns if a and b intersect (overlap) */ +pcb_bool pcb_intersect_obj_obj(pcb_any_obj_t *a, pcb_any_obj_t *b); + +/* Low level intersection functions: */ +pcb_bool pcb_isc_line_line(pcb_line_t *Line1, pcb_line_t *Line2); +pcb_bool pcb_isc_line_arc(pcb_line_t *Line, pcb_arc_t *Arc); +pcb_bool pcb_isc_arc_poly(pcb_arc_t *Arc, pcb_poly_t *Polygon); +pcb_bool pcb_isc_arc_polyarea(pcb_arc_t *Arc, pcb_polyarea_t *pa); +pcb_bool pcb_isc_line_poly(pcb_line_t *Line, pcb_poly_t *Polygon); +pcb_bool pcb_isc_poly_poly(pcb_poly_t *P1, pcb_poly_t *P2); +pcb_bool_t pcb_isc_pstk_line(pcb_pstk_t *ps, pcb_line_t *line); + +/* Return whether obj is marked as already visited by the current search context */ +#define PCB_FIND_IS_MARKED(ctx, obj) PCB_DFLAG_TEST(&((obj)->Flags), (ctx)->mark) + +#define PCB_LOOKUP_FIRST \ + (PCB_OBJ_PSTK | PCB_OBJ_SUBC_PART) +#define PCB_LOOKUP_MORE \ + (PCB_OBJ_LINE | PCB_OBJ_RAT | PCB_OBJ_POLY | PCB_OBJ_ARC | PCB_OBJ_SUBC_PART) + +#endif Index: tags/2.1.2/src/find_any_isect.c =================================================================== --- tags/2.1.2/src/find_any_isect.c (nonexistent) +++ tags/2.1.2/src/find_any_isect.c (revision 24813) @@ -0,0 +1,127 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2018 Tibor 'Igor2' Palinkas + * + * This module, diag, was written and is Copyright (C) 2016 by Tibor Palinkas + * this module is also subject to the GNU GPL as described below + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + + +TODO(": implement text intersections") +pcb_bool pcb_isc_text_line(pcb_text_t *a, pcb_line_t *b) { return pcb_false; } +pcb_bool pcb_isc_text_text(pcb_text_t *a, pcb_text_t *b) { return pcb_false; } +pcb_bool pcb_isc_text_poly(pcb_text_t *a, pcb_poly_t *b) { return pcb_false; } +pcb_bool pcb_isc_text_arc(pcb_text_t *a, pcb_arc_t *b) { return pcb_false; } +pcb_bool pcb_isc_text_pstk(pcb_text_t *a, pcb_pstk_t *b) { return pcb_false; } + +pcb_bool pcb_intersect_obj_obj(pcb_any_obj_t *a, pcb_any_obj_t *b) +{ + /* produce the clopped version for polygons to compare */ + if ((a->type == PCB_OBJ_POLY) && (((pcb_poly_t *)a)->Clipped == NULL)) + pcb_poly_init_clip(a->parent.layer->parent.data, a->parent.layer, (pcb_poly_t *)a); + if ((b->type == PCB_OBJ_POLY) && (((pcb_poly_t *)b)->Clipped == NULL)) + pcb_poly_init_clip(b->parent.layer->parent.data, b->parent.layer, (pcb_poly_t *)b); + + switch(a->type) { + case PCB_OBJ_VOID: return pcb_false; + case PCB_OBJ_LINE: + switch(b->type) { + case PCB_OBJ_VOID: return pcb_false; + case PCB_OBJ_LINE: return pcb_isc_line_line((pcb_line_t *)a, (pcb_line_t *)b); + case PCB_OBJ_TEXT: return pcb_isc_text_line((pcb_text_t *)b, (pcb_line_t *)a); + case PCB_OBJ_POLY: return pcb_isc_line_poly((pcb_line_t *)a, (pcb_poly_t *)b); + case PCB_OBJ_ARC: return pcb_isc_line_arc((pcb_line_t *)a, (pcb_arc_t *)b); + case PCB_OBJ_PSTK: return pcb_isc_pstk_line((pcb_pstk_t *)b, (pcb_line_t *)a); + case PCB_OBJ_RAT: return pcb_isc_rat_line((pcb_rat_t *)b, (pcb_line_t *)a); + default:; + } + break; + case PCB_OBJ_TEXT: + switch(b->type) { + case PCB_OBJ_VOID: return pcb_false; + case PCB_OBJ_LINE: return pcb_isc_text_line((pcb_text_t *)a, (pcb_line_t *)b); + case PCB_OBJ_TEXT: return pcb_isc_text_text((pcb_text_t *)a, (pcb_text_t *)b); + case PCB_OBJ_POLY: return pcb_isc_text_poly((pcb_text_t *)a, (pcb_poly_t *)b); + case PCB_OBJ_ARC: return pcb_isc_text_arc((pcb_text_t *)a, (pcb_arc_t *)b); + case PCB_OBJ_PSTK: return pcb_isc_text_pstk((pcb_text_t *)a, (pcb_pstk_t *)b); + case PCB_OBJ_RAT: return pcb_false; /* text is invisible to find for now */ + default:; + } + break; + + case PCB_OBJ_POLY: + switch(b->type) { + case PCB_OBJ_VOID: return pcb_false; + case PCB_OBJ_LINE: return pcb_isc_line_poly((pcb_line_t *)b, (pcb_poly_t *)a); + case PCB_OBJ_TEXT: return pcb_isc_text_poly((pcb_text_t *)b, (pcb_poly_t *)a); + case PCB_OBJ_POLY: return pcb_isc_poly_poly((pcb_poly_t *)a, (pcb_poly_t *)b); + case PCB_OBJ_ARC: return pcb_isc_arc_poly((pcb_arc_t *)b, (pcb_poly_t *)a); + case PCB_OBJ_PSTK: return pcb_isc_pstk_poly((pcb_pstk_t *)b, (pcb_poly_t *)a); + case PCB_OBJ_RAT: return pcb_isc_rat_poly((pcb_rat_t *)b, (pcb_poly_t *)a); + default:; + } + break; + case PCB_OBJ_ARC: + switch(b->type) { + case PCB_OBJ_VOID: return pcb_false; + case PCB_OBJ_LINE: return pcb_isc_line_arc((pcb_line_t *)b, (pcb_arc_t *)a); + case PCB_OBJ_TEXT: return pcb_isc_text_arc((pcb_text_t *)b, (pcb_arc_t *)a); + case PCB_OBJ_POLY: return pcb_isc_arc_poly((pcb_arc_t *)a, (pcb_poly_t *)b); + case PCB_OBJ_ARC: return pcb_isc_arc_arc((pcb_arc_t *)a, (pcb_arc_t *)b); + case PCB_OBJ_PSTK: return pcb_isc_pstk_arc((pcb_pstk_t *)b, (pcb_arc_t *)a); + case PCB_OBJ_RAT: return pcb_isc_rat_arc((pcb_rat_t *)b, (pcb_arc_t *)a); + default:; + } + break; + case PCB_OBJ_PSTK: + switch(b->type) { + case PCB_OBJ_VOID: return pcb_false; + case PCB_OBJ_LINE: return pcb_isc_pstk_line((pcb_pstk_t *)a, (pcb_line_t *)b); + case PCB_OBJ_TEXT: return pcb_isc_text_pstk((pcb_text_t *)b, (pcb_pstk_t *)a); + case PCB_OBJ_POLY: return pcb_isc_pstk_poly((pcb_pstk_t *)a, (pcb_poly_t *)b); + case PCB_OBJ_ARC: return pcb_isc_pstk_arc((pcb_pstk_t *)a, (pcb_arc_t *)b); + case PCB_OBJ_PSTK: return pcb_isc_pstk_pstk((pcb_pstk_t *)a, (pcb_pstk_t *)b); + case PCB_OBJ_RAT: return pcb_isc_pstk_rat((pcb_pstk_t *)a, (pcb_rat_t *)b); + default:; + } + break; + case PCB_OBJ_RAT: + switch(b->type) { + case PCB_OBJ_VOID: return pcb_false; + case PCB_OBJ_LINE: return pcb_isc_rat_line((pcb_rat_t *)a, (pcb_line_t *)b); + case PCB_OBJ_TEXT: return pcb_false; /* text is invisible to find for now */ + case PCB_OBJ_POLY: return pcb_isc_rat_poly((pcb_rat_t *)a, (pcb_poly_t *)b); + case PCB_OBJ_ARC: return pcb_isc_rat_arc((pcb_rat_t *)a, (pcb_arc_t *)b); + case PCB_OBJ_PSTK: return pcb_isc_pstk_rat((pcb_pstk_t *)b, (pcb_rat_t *)a); + case PCB_OBJ_RAT: return pcb_isc_rat_rat((pcb_rat_t *)a, (pcb_rat_t *)b); + default:; + } + break; + default:; + } + assert(!"Don't know how to check intersection of these objet types"); + return pcb_false; +} + + Index: tags/2.1.2/src/find_geo.c =================================================================== --- tags/2.1.2/src/find_geo.c (nonexistent) +++ tags/2.1.2/src/find_geo.c (revision 24813) @@ -0,0 +1,1051 @@ +/* + * + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996, 2005 Thomas Nau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +/* Generic geometric functions used by find.c lookup */ + +/* + * Intersection of line <--> circle: + * - calculate the signed distance from the line to the center, + * return false if abs(distance) > R + * - get the distance from the line <--> distancevector intersection to + * (X1,Y1) in range [0,1], return pcb_true if 0 <= distance <= 1 + * - depending on (r > 1.0 or r < 0.0) check the distance of X2,Y2 or X1,Y1 + * to X,Y + * + * Intersection of line <--> line: + * - see the description of 'pcb_isc_line_line()' + */ + +#include "macro.h" +#include "obj_arc_ui.h" +#include "obj_pstk_inlines.h" +#include "search.h" + +#define EXPAND_BOUNDS(p) if (Bloat > 0) {\ + (p)->BoundingBox.X1 -= Bloat; \ + (p)->BoundingBox.X2 += Bloat; \ + (p)->BoundingBox.Y1 -= Bloat; \ + (p)->BoundingBox.Y2 += Bloat;} + +/* reduce arc start angle and delta to 0..360 */ +static void normalize_angles(pcb_angle_t * sa, pcb_angle_t * d) +{ + if (*d < 0) { + *sa += *d; + *d = -*d; + } + if (*d > 360) /* full circle */ + *d = 360; + *sa = pcb_normalize_angle(*sa); +} + +static int radius_crosses_arc(double x, double y, pcb_arc_t *arc) +{ + double alpha = atan2(y - arc->Y, -x + arc->X) * PCB_RAD_TO_DEG; + pcb_angle_t sa = arc->StartAngle, d = arc->Delta; + + normalize_angles(&sa, &d); + if (alpha < 0) + alpha += 360; + if (sa <= alpha) + return (sa + d) >= alpha; + return (sa + d - 360) >= alpha; +} + +static void get_arc_ends(pcb_coord_t * box, pcb_arc_t *arc) +{ + box[0] = arc->X - arc->Width * cos(PCB_M180 * arc->StartAngle); + box[1] = arc->Y + arc->Height * sin(PCB_M180 * arc->StartAngle); + box[2] = arc->X - arc->Width * cos(PCB_M180 * (arc->StartAngle + arc->Delta)); + box[3] = arc->Y + arc->Height * sin(PCB_M180 * (arc->StartAngle + arc->Delta)); +} + +/* --------------------------------------------------------------------------- + * check if two arcs intersect + * first we check for circle intersections, + * then find the actual points of intersection + * and test them to see if they are on arcs + * + * consider a, the distance from the center of arc 1 + * to the point perpendicular to the intersecting points. + * + * a = (r1^2 - r2^2 + l^2)/(2l) + * + * the perpendicular distance to the point of intersection + * is then + * + * d = sqrt(r1^2 - a^2) + * + * the points of intersection would then be + * + * x = X1 + a/l dx +- d/l dy + * y = Y1 + a/l dy -+ d/l dx + * + * where dx = X2 - X1 and dy = Y2 - Y1 + * + * + */ +static pcb_bool pcb_isc_arc_arc(pcb_arc_t *Arc1, pcb_arc_t *Arc2) +{ + double x, y, dx, dy, r1, r2, a, d, l, t, t1, t2, dl; + pcb_coord_t pdx, pdy; + pcb_coord_t box[8]; + + t = 0.5 * Arc1->Thickness + Bloat; + t2 = 0.5 * Arc2->Thickness; + t1 = t2 + Bloat; + + /* too thin arc */ + if (t < 0 || t1 < 0) + return pcb_false; + + /* try the end points first */ + get_arc_ends(&box[0], Arc1); + get_arc_ends(&box[4], Arc2); + if (pcb_is_point_on_arc(box[0], box[1], t, Arc2) + || pcb_is_point_on_arc(box[2], box[3], t, Arc2) + || pcb_is_point_on_arc(box[4], box[5], t, Arc1) + || pcb_is_point_on_arc(box[6], box[7], t, Arc1)) + return pcb_true; + + pdx = Arc2->X - Arc1->X; + pdy = Arc2->Y - Arc1->Y; + dl = pcb_distance(Arc1->X, Arc1->Y, Arc2->X, Arc2->Y); + /* concentric arcs, simpler intersection conditions */ + if (dl < 0.5) { + if ((Arc1->Width - t >= Arc2->Width - t2 && Arc1->Width - t <= Arc2->Width + t2) + || (Arc1->Width + t >= Arc2->Width - t2 && Arc1->Width + t <= Arc2->Width + t2)) { + pcb_angle_t sa1 = Arc1->StartAngle, d1 = Arc1->Delta; + pcb_angle_t sa2 = Arc2->StartAngle, d2 = Arc2->Delta; + /* NB the endpoints have already been checked, + so we just compare the angles */ + + normalize_angles(&sa1, &d1); + normalize_angles(&sa2, &d2); + /* sa1 == sa2 was caught when checking endpoints */ + if (sa1 > sa2) + if (sa1 < sa2 + d2 || sa1 + d1 - 360 > sa2) + return pcb_true; + if (sa2 > sa1) + if (sa2 < sa1 + d1 || sa2 + d2 - 360 > sa1) + return pcb_true; + } + return pcb_false; + } + r1 = Arc1->Width; + r2 = Arc2->Width; + /* arcs centerlines are too far or too near */ + if (dl > r1 + r2 || dl + r1 < r2 || dl + r2 < r1) { + /* check the nearest to the other arc's center point */ + dx = pdx * r1 / dl; + dy = pdy * r1 / dl; + if (dl + r1 < r2) { /* Arc1 inside Arc2 */ + dx = -dx; + dy = -dy; + } + + if (radius_crosses_arc(Arc1->X + dx, Arc1->Y + dy, Arc1) + && pcb_is_point_on_arc(Arc1->X + dx, Arc1->Y + dy, t, Arc2)) + return pcb_true; + + dx = -pdx * r2 / dl; + dy = -pdy * r2 / dl; + if (dl + r2 < r1) { /* Arc2 inside Arc1 */ + dx = -dx; + dy = -dy; + } + + if (radius_crosses_arc(Arc2->X + dx, Arc2->Y + dy, Arc2) + && pcb_is_point_on_arc(Arc2->X + dx, Arc2->Y + dy, t1, Arc1)) + return pcb_true; + return pcb_false; + } + + l = dl * dl; + r1 *= r1; + r2 *= r2; + a = 0.5 * (r1 - r2 + l) / l; + r1 = r1 / l; + d = r1 - a * a; + /* the circles are too far apart to touch or probably just touch: + check the nearest point */ + if (d < 0) + d = 0; + else + d = sqrt(d); + x = Arc1->X + a * pdx; + y = Arc1->Y + a * pdy; + dx = d * pdx; + dy = d * pdy; + if (radius_crosses_arc(x + dy, y - dx, Arc1) + && pcb_is_point_on_arc(x + dy, y - dx, t, Arc2)) + return pcb_true; + if (radius_crosses_arc(x + dy, y - dx, Arc2) + && pcb_is_point_on_arc(x + dy, y - dx, t1, Arc1)) + return pcb_true; + + if (radius_crosses_arc(x - dy, y + dx, Arc1) + && pcb_is_point_on_arc(x - dy, y + dx, t, Arc2)) + return pcb_true; + if (radius_crosses_arc(x - dy, y + dx, Arc2) + && pcb_is_point_on_arc(x - dy, y + dx, t1, Arc1)) + return pcb_true; + return pcb_false; +} + +/* --------------------------------------------------------------------------- + * Tests if point is same as line end point or center point + */ +static pcb_bool pcb_isc_ratp_line(pcb_point_t *Point, pcb_line_t *Line) +{ + pcb_coord_t cx, cy; + + /* either end */ + if ((Point->X == Line->Point1.X && Point->Y == Line->Point1.Y) + || (Point->X == Line->Point2.X && Point->Y == Line->Point2.Y)) + return pcb_true; + + /* middle point */ + pcb_obj_center((pcb_any_obj_t *)Line, &cx, &cy); + if ((Point->X == cx) && (Point->Y == cy)) + return pcb_true; + + return pcb_false; +} + +/* Tests any end of a rat line is on the line */ +static pcb_bool pcb_isc_rat_line(pcb_rat_t *rat, pcb_line_t *line) +{ + pcb_layergrp_id_t gid = pcb_layer_get_group_(line->parent.layer); + + if ((rat->group1 == gid) && pcb_isc_ratp_line(&rat->Point1, line)) + return pcb_true; + if ((rat->group2 == gid) && pcb_isc_ratp_line(&rat->Point2, line)) + return pcb_true; + + return pcb_false; +} + +/* --------------------------------------------------------------------------- + * Tests if point is same as arc end point or center point + */ +static pcb_bool pcb_isc_ratp_arc(pcb_point_t *Point, pcb_arc_t *arc) +{ + pcb_coord_t cx, cy; + + /* either end */ + pcb_arc_get_end(arc, 0, &cx, &cy); + if ((Point->X == cx) && (Point->Y == cy)) + return pcb_true; + + pcb_arc_get_end(arc, 1, &cx, &cy); + if ((Point->X == cx) && (Point->Y == cy)) + return pcb_true; + + /* middle point */ + pcb_arc_middle(arc, &cx, &cy); + if ((Point->X == cx) && (Point->Y == cy)) + return pcb_true; + + return pcb_false; +} + +/* Tests any end of a rat line is on the arc */ +static pcb_bool pcb_isc_rat_arc(pcb_rat_t *rat, pcb_arc_t *arc) +{ + pcb_layergrp_id_t gid = pcb_layer_get_group_(arc->parent.layer); + + if ((rat->group1 == gid) && pcb_isc_ratp_arc(&rat->Point1, arc)) + return pcb_true; + if ((rat->group2 == gid) && pcb_isc_ratp_arc(&rat->Point2, arc)) + return pcb_true; + + return pcb_false; +} + +/* --------------------------------------------------------------------------- + * Tests if rat line point is connected to a polygon + */ +static pcb_bool pcb_isc_ratp_poly(pcb_point_t *Point, pcb_poly_t *polygon) +{ + pcb_coord_t cx, cy; + + /* canonical point */ + cx = polygon->Clipped->contours->head.point[0]; + cy = polygon->Clipped->contours->head.point[1]; + if ((Point->X == cx) && (Point->Y == cy)) + return pcb_true; + + /* middle point */ + pcb_obj_center((pcb_any_obj_t *)polygon, &cx, &cy); + if ((Point->X == cx) && (Point->Y == cy)) + return pcb_true; + + return pcb_false; +} + +/* Tests any end of a rat line is on the poly */ +static pcb_bool pcb_isc_rat_poly(pcb_rat_t *rat, pcb_poly_t *poly) +{ + pcb_layergrp_id_t gid = pcb_layer_get_group_(poly->parent.layer); + + if ((rat->group1 == gid) && pcb_isc_ratp_poly(&rat->Point1, poly)) + return pcb_true; + if ((rat->group2 == gid) && pcb_isc_ratp_poly(&rat->Point2, poly)) + return pcb_true; + + return pcb_false; +} + +/* Tests any end of a rat line is on the other rat */ +static pcb_bool pcb_isc_rat_rat(pcb_rat_t *r1, pcb_rat_t *r2) +{ + if ((r1->group1 == r2->group1) && (r1->Point1.X == r2->Point1.X) && (r1->Point1.Y == r2->Point1.Y)) + return pcb_true; + if ((r1->group2 == r2->group2) && (r1->Point2.X == r2->Point2.X) && (r1->Point2.Y == r2->Point2.Y)) + return pcb_true; + if ((r1->group1 == r2->group2) && (r1->Point1.X == r2->Point2.X) && (r1->Point1.Y == r2->Point2.Y)) + return pcb_true; + if ((r1->group2 == r2->group1) && (r1->Point2.X == r2->Point1.X) && (r1->Point2.Y == r2->Point1.Y)) + return pcb_true; + return pcb_false; +} + +static void form_slanted_rectangle(pcb_point_t p[4], pcb_line_t *l) +/* writes vertices of a squared line */ +{ + double dwx = 0, dwy = 0; + if (l->Point1.Y == l->Point2.Y) + dwx = l->Thickness / 2.0; + else if (l->Point1.X == l->Point2.X) + dwy = l->Thickness / 2.0; + else { + pcb_coord_t dX = l->Point2.X - l->Point1.X; + pcb_coord_t dY = l->Point2.Y - l->Point1.Y; + double r = pcb_distance(l->Point1.X, l->Point1.Y, l->Point2.X, l->Point2.Y); + dwx = l->Thickness / 2.0 / r * dX; + dwy = l->Thickness / 2.0 / r * dY; + } + p[0].X = l->Point1.X - dwx + dwy; + p[0].Y = l->Point1.Y - dwy - dwx; + p[1].X = l->Point1.X - dwx - dwy; + p[1].Y = l->Point1.Y - dwy + dwx; + p[2].X = l->Point2.X + dwx - dwy; + p[2].Y = l->Point2.Y + dwy + dwx; + p[3].X = l->Point2.X + dwx + dwy; + p[3].Y = l->Point2.Y + dwy - dwx; +} + +/* --------------------------------------------------------------------------- + * checks if two lines intersect + * from news FAQ: + * + * Let A,B,C,D be 2-space position vectors. Then the directed line + * segments AB & CD are given by: + * + * AB=A+r(B-A), r in [0,1] + * CD=C+s(D-C), s in [0,1] + * + * If AB & CD intersect, then + * + * A+r(B-A)=C+s(D-C), or + * + * XA+r(XB-XA)=XC+s(XD-XC) + * YA+r(YB-YA)=YC+s(YD-YC) for some r,s in [0,1] + * + * Solving the above for r and s yields + * + * (YA-YC)(XD-XC)-(XA-XC)(YD-YC) + * r = ----------------------------- (eqn 1) + * (XB-XA)(YD-YC)-(YB-YA)(XD-XC) + * + * (YA-YC)(XB-XA)-(XA-XC)(YB-YA) + * s = ----------------------------- (eqn 2) + * (XB-XA)(YD-YC)-(YB-YA)(XD-XC) + * + * Let I be the position vector of the intersection point, then + * + * I=A+r(B-A) or + * + * XI=XA+r(XB-XA) + * YI=YA+r(YB-YA) + * + * By examining the values of r & s, you can also determine some + * other limiting conditions: + * + * If 0<=r<=1 & 0<=s<=1, intersection exists + * r<0 or r>1 or s<0 or s>1 line segments do not intersect + * + * If the denominator in eqn 1 is zero, AB & CD are parallel + * If the numerator in eqn 1 is also zero, AB & CD are coincident + * + * If the intersection point of the 2 lines are needed (lines in this + * context mean infinite lines) regardless whether the two line + * segments intersect, then + * + * If r>1, I is located on extension of AB + * If r<0, I is located on extension of BA + * If s>1, I is located on extension of CD + * If s<0, I is located on extension of DC + * + * Also note that the denominators of eqn 1 & 2 are identical. + * + */ +pcb_bool pcb_isc_line_line(pcb_line_t *Line1, pcb_line_t *Line2) +{ + double s, r; + double line1_dx, line1_dy, line2_dx, line2_dy, point1_dx, point1_dy; + if (PCB_FLAG_TEST(PCB_FLAG_SQUARE, Line1)) { /* pretty reckless recursion */ + pcb_point_t p[4]; + form_slanted_rectangle(p, Line1); + return pcb_is_line_in_quadrangle(p, Line2); + } + /* here come only round Line1 because pcb_is_line_in_quadrangle() + calls pcb_isc_line_line() with first argument rounded */ + if (PCB_FLAG_TEST(PCB_FLAG_SQUARE, Line2)) { + pcb_point_t p[4]; + form_slanted_rectangle(p, Line2); + return pcb_is_line_in_quadrangle(p, Line1); + } + /* now all lines are round */ + + /* Check endpoints: this provides a quick exit, catches + * cases where the "real" lines don't intersect but the + * thick lines touch, and ensures that the dx/dy business + * below does not cause a divide-by-zero. */ + if (pcb_is_point_in_line(Line2->Point1.X, Line2->Point1.Y, MAX(Line2->Thickness / 2 + Bloat, 0), (pcb_any_line_t *) Line1) + || pcb_is_point_in_line(Line2->Point2.X, Line2->Point2.Y, MAX(Line2->Thickness / 2 + Bloat, 0), (pcb_any_line_t *) Line1) + || pcb_is_point_in_line(Line1->Point1.X, Line1->Point1.Y, MAX(Line1->Thickness / 2 + Bloat, 0), (pcb_any_line_t *) Line2) + || pcb_is_point_in_line(Line1->Point2.X, Line1->Point2.Y, MAX(Line1->Thickness / 2 + Bloat, 0), (pcb_any_line_t *) Line2)) + return pcb_true; + + /* setup some constants */ + line1_dx = Line1->Point2.X - Line1->Point1.X; + line1_dy = Line1->Point2.Y - Line1->Point1.Y; + line2_dx = Line2->Point2.X - Line2->Point1.X; + line2_dy = Line2->Point2.Y - Line2->Point1.Y; + point1_dx = Line1->Point1.X - Line2->Point1.X; + point1_dy = Line1->Point1.Y - Line2->Point1.Y; + + /* If either line is a point, we have failed already, since the + * endpoint check above will have caught an "intersection". */ + if ((line1_dx == 0 && line1_dy == 0) + || (line2_dx == 0 && line2_dy == 0)) + return pcb_false; + + /* set s to cross product of Line1 and the line + * Line1.Point1--Line2.Point1 (as vectors) */ + s = point1_dy * line1_dx - point1_dx * line1_dy; + + /* set r to cross product of both lines (as vectors) */ + r = line1_dx * line2_dy - line1_dy * line2_dx; + + /* No cross product means parallel lines, or maybe Line2 is + * zero-length. In either case, since we did a bounding-box + * check before getting here, the above pcb_is_point_in_line() checks + * will have caught any intersections. */ + if (r == 0.0) + return pcb_false; + + s /= r; + r = (point1_dy * line2_dx - point1_dx * line2_dy) / r; + + /* intersection is at least on AB */ + if (r >= 0.0 && r <= 1.0) + return (s >= 0.0 && s <= 1.0); + + /* intersection is at least on CD */ + /* [removed this case since it always returns pcb_false --asp] */ + return pcb_false; +} + +/*--------------------------------------------------- + * + * Check for line intersection with an arc + * + * Mostly this is like the circle/line intersection + * found in pcb_is_point_on_line(search.c) see the detailed + * discussion for the basics there. + * + * Since this is only an arc, not a full circle we need + * to find the actual points of intersection with the + * circle, and see if they are on the arc. + * + * To do this, we translate along the line from the point Q + * plus or minus a distance delta = sqrt(Radius^2 - d^2) + * but it's handy to normalize with respect to l, the line + * length so a single projection is done (e.g. we don't first + * find the point Q + * + * The projection is now of the form + * + * Px = X1 + (r +- r2)(X2 - X1) + * Py = Y1 + (r +- r2)(Y2 - Y1) + * + * Where r2 sqrt(Radius^2 l^2 - d^2)/l^2 + * note that this is the variable d, not the symbol d described in IsPointOnLine + * (variable d = symbol d * l) + * + * The end points are hell so they are checked individually + */ +pcb_bool pcb_isc_line_arc(pcb_line_t *Line, pcb_arc_t *Arc) +{ + double dx, dy, dx1, dy1, l, d, r, r2, Radius; + pcb_coord_t ex, ey; + + dx = Line->Point2.X - Line->Point1.X; + dy = Line->Point2.Y - Line->Point1.Y; + dx1 = Line->Point1.X - Arc->X; + dy1 = Line->Point1.Y - Arc->Y; + l = dx * dx + dy * dy; + d = dx * dy1 - dy * dx1; + d *= d; + + /* use the larger diameter circle first */ + Radius = Arc->Width + MAX(0.5 * (Arc->Thickness + Line->Thickness) + Bloat, 0.0); + Radius *= Radius; + r2 = Radius * l - d; + /* projection doesn't even intersect circle when r2 < 0 */ + if (r2 < 0) + return pcb_false; + /* check the ends of the line in case the projected point */ + /* of intersection is beyond the line end */ + if (pcb_is_point_on_arc(Line->Point1.X, Line->Point1.Y, MAX(0.5 * Line->Thickness + Bloat, 0.0), Arc)) + return pcb_true; + if (pcb_is_point_on_arc(Line->Point2.X, Line->Point2.Y, MAX(0.5 * Line->Thickness + Bloat, 0.0), Arc)) + return pcb_true; + if (l == 0.0) + return pcb_false; + r2 = sqrt(r2); + Radius = -(dx * dx1 + dy * dy1); + r = (Radius + r2) / l; + if (r >= 0 && r <= 1 + && pcb_is_point_on_arc(Line->Point1.X + r * dx, Line->Point1.Y + r * dy, MAX(0.5 * Line->Thickness + Bloat, 0.0) + 1, Arc)) + return pcb_true; + r = (Radius - r2) / l; + if (r >= 0 && r <= 1 + && pcb_is_point_on_arc(Line->Point1.X + r * dx, Line->Point1.Y + r * dy, MAX(0.5 * Line->Thickness + Bloat, 0.0) + 1, Arc)) + return pcb_true; + + /* check arc end points */ + pcb_arc_get_end(Arc, 0, &ex, &ey); + if (pcb_is_point_in_line(ex, ey, Arc->Thickness * 0.5 + Bloat, (pcb_any_line_t *) Line)) + return pcb_true; + + pcb_arc_get_end(Arc, 1, &ex, &ey); + if (pcb_is_point_in_line(ex, ey, Arc->Thickness * 0.5 + Bloat, (pcb_any_line_t *) Line)) + return pcb_true; + return pcb_false; +} + +/* --------------------------------------------------------------------------- + * checks if an arc has a connection to a polygon + * + * - first check if the arc can intersect with the polygon by + * evaluating the bounding boxes + * - check the two end points of the arc. If none of them matches + * - check all segments of the polygon against the arc. + */ +pcb_bool pcb_isc_arc_poly(pcb_arc_t *Arc, pcb_poly_t *Polygon) +{ + pcb_box_t *Box = (pcb_box_t *) Arc; + + /* arcs with clearance never touch polys */ + if (PCB_FLAG_TEST(PCB_FLAG_CLEARPOLY, Polygon) && PCB_OBJ_HAS_CLEARANCE(Arc)) + return pcb_false; + if (!Polygon->Clipped) + return pcb_false; + if (Box->X1 <= Polygon->Clipped->contours->xmax + Bloat + && Box->X2 >= Polygon->Clipped->contours->xmin - Bloat + && Box->Y1 <= Polygon->Clipped->contours->ymax + Bloat && Box->Y2 >= Polygon->Clipped->contours->ymin - Bloat) { + pcb_polyarea_t *ap; + + if (!(ap = pcb_poly_from_arc(Arc, Arc->Thickness + Bloat))) + return pcb_false; /* error */ + return pcb_poly_isects_poly(ap, Polygon, pcb_true); + } + return pcb_false; +} + +pcb_bool pcb_isc_arc_polyarea(pcb_arc_t *Arc, pcb_polyarea_t *pa) +{ + pcb_box_t *Box = (pcb_box_t *) Arc; + pcb_bool res = pcb_false; + + /* arcs with clearance never touch polys */ + if ((Box->X1 <= pa->contours->xmax + Bloat) && (Box->X2 >= pa->contours->xmin - Bloat) + && (Box->Y1 <= pa->contours->ymax + Bloat) && (Box->Y2 >= pa->contours->ymin - Bloat)) { + pcb_polyarea_t *arcp; + + if (!(arcp = pcb_poly_from_arc(Arc, Arc->Thickness + Bloat))) + return pcb_false; /* error */ + res = pcb_polyarea_touching(arcp, pa); + pcb_polyarea_free(&arcp); + } + return res; +} + + +/* --------------------------------------------------------------------------- + * checks if a line has a connection to a polygon + * + * - first check if the line can intersect with the polygon by + * evaluating the bounding boxes + * - check the two end points of the line. If none of them matches + * - check all segments of the polygon against the line. + */ +pcb_bool pcb_isc_line_poly(pcb_line_t *Line, pcb_poly_t *Polygon) +{ + pcb_box_t *Box = (pcb_box_t *) Line; + pcb_polyarea_t *lp; + + /* lines with clearance never touch polygons */ + if (PCB_FLAG_TEST(PCB_FLAG_CLEARPOLY, Polygon) && PCB_OBJ_HAS_CLEARANCE(Line)) + return pcb_false; + if (!Polygon->Clipped) + return pcb_false; + if (PCB_FLAG_TEST(PCB_FLAG_SQUARE, Line) && (Line->Point1.X == Line->Point2.X || Line->Point1.Y == Line->Point2.Y)) { + pcb_coord_t wid = (Line->Thickness + Bloat + 1) / 2; + pcb_coord_t x1, x2, y1, y2; + + x1 = MIN(Line->Point1.X, Line->Point2.X) - wid; + y1 = MIN(Line->Point1.Y, Line->Point2.Y) - wid; + x2 = MAX(Line->Point1.X, Line->Point2.X) + wid; + y2 = MAX(Line->Point1.Y, Line->Point2.Y) + wid; + return pcb_poly_is_rect_in_p(x1, y1, x2, y2, Polygon); + } + if (Box->X1 <= Polygon->Clipped->contours->xmax + Bloat + && Box->X2 >= Polygon->Clipped->contours->xmin - Bloat + && Box->Y1 <= Polygon->Clipped->contours->ymax + Bloat && Box->Y2 >= Polygon->Clipped->contours->ymin - Bloat) { + if (!(lp = pcb_poly_from_line(Line, Line->Thickness + Bloat))) + return pcb_false; /* error */ + return pcb_poly_isects_poly(lp, Polygon, pcb_true); + } + return pcb_false; +} + +/* --------------------------------------------------------------------------- + * checks if a polygon has a connection to a second one + * + * First check all points out of P1 against P2 and vice versa. + * If both fail check all lines of P1 against the ones of P2 + */ +pcb_bool pcb_isc_poly_poly(pcb_poly_t *P1, pcb_poly_t *P2) +{ + int pcp_cnt = 0; + pcb_coord_t pcp_gap; + + if (!P1->Clipped || !P2->Clipped) + return pcb_false; + assert(P1->Clipped->contours); + assert(P2->Clipped->contours); + + + /* first check if both bounding boxes intersect. If not, return quickly */ + if (P1->Clipped->contours->xmin - Bloat > P2->Clipped->contours->xmax || + P1->Clipped->contours->xmax + Bloat < P2->Clipped->contours->xmin || + P1->Clipped->contours->ymin - Bloat > P2->Clipped->contours->ymax || + P1->Clipped->contours->ymax + Bloat < P2->Clipped->contours->ymin) + return pcb_false; + + /* cheat: poly-clear-poly means we did generate the clearance; this + shall happen only if there's exactly one poly that is clearing the other */ + if (PCB_FLAG_TEST(PCB_FLAG_CLEARPOLYPOLY, P1)) { + pcp_cnt++; + pcp_gap = P1->Clearance / 2.0; + } + if (PCB_FLAG_TEST(PCB_FLAG_CLEARPOLYPOLY, P2)) { + pcp_cnt++; + pcp_gap = P2->Clearance / 2.0; + } + if (pcp_cnt == 1) { + if (pcp_gap >= Bloat) + return pcb_false; + return pcb_true; + } + + /* first check un-bloated case */ + if (pcb_poly_isects_poly(P1->Clipped, P2, pcb_false)) + return pcb_true; + + /* now the difficult case of bloated */ + if (Bloat > 0) { + pcb_pline_t *c; + for (c = P1->Clipped->contours; c; c = c->next) { + pcb_line_t line; + pcb_vnode_t *v = &c->head; + if (c->xmin - Bloat <= P2->Clipped->contours->xmax && + c->xmax + Bloat >= P2->Clipped->contours->xmin && + c->ymin - Bloat <= P2->Clipped->contours->ymax && c->ymax + Bloat >= P2->Clipped->contours->ymin) { + + line.Point1.X = v->point[0]; + line.Point1.Y = v->point[1]; + line.Thickness = 2 * Bloat; + line.Clearance = 0; + line.Flags = pcb_no_flags(); + for (v = v->next; v != &c->head; v = v->next) { + line.Point2.X = v->point[0]; + line.Point2.Y = v->point[1]; + pcb_line_bbox(&line); + if (pcb_isc_line_poly(&line, P2)) + return pcb_true; + line.Point1.X = line.Point2.X; + line.Point1.Y = line.Point2.Y; + } + } + } + } + + return pcb_false; +} + +/* returns whether a round-cap pcb line touches a polygon; assumes bounding + boxes do touch */ +PCB_INLINE pcb_bool_t pcb_isc_line_polyline(pcb_pline_t *pl, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2, pcb_coord_t thick) +{ + pcb_coord_t ox, oy, vx, vy; + double dx, dy, h, l; + + thick += Bloat*2; + if (thick < 0) thick = 0; + + /* single-point line - check only one circle*/ + if ((x1 == x2) && (y1 == y2)) + return pcb_pline_overlaps_circ(pl, x1, y1, thick/2); + + /* long line - check ends */ + if (pcb_pline_overlaps_circ(pl, x1, y1, thick/2)) return pcb_true; + if (pcb_pline_overlaps_circ(pl, x2, y2, thick/2)) return pcb_true; + + dx = x2 - x1; + dy = y2 - y1; + l = sqrt(PCB_SQUARE(dx) + PCB_SQUARE(dy)); + h = 0.5 * thick / l; + ox = dy * h + 0.5 * SGN(dy); + oy = -(dx * h + 0.5 * SGN(dx)); + vx = (double)dx / -l * ((double)Bloat/2.0); + vy = (double)dy / -l * ((double)Bloat/2.0); + + /* long line - consider edge intersection */ + if (pcb_pline_isect_line(pl, x1 + ox + vx, y1 + oy + vy, x2 + ox - vx, y2 + oy - vy, NULL, NULL)) return pcb_true; + if (pcb_pline_isect_line(pl, x1 - ox + vx, y1 - oy + vy, x2 - ox - vx, y2 - oy - vy, NULL, NULL)) return pcb_true; + + /* A corner case is when the polyline is fully within the line. By now we + are sure there's no contour intersection, so if any of the polyline points + is in, the whole polyline is in. */ + { + pcb_vector_t q[4]; + + q[0][0] = x1 + ox; q[0][1] = y1 + oy; + q[1][0] = x2 + ox; q[1][1] = y2 + oy; + q[2][0] = x1 - ox; q[2][1] = y1 - oy; + q[3][0] = x2 - ox; q[3][1] = y2 - oy; + + return pcb_is_point_in_convex_quad(pl->head.point, q); + } +} + +#define shape_line_to_pcb_line(ps, shape_line, pcb_line) \ + do { \ + pcb_line.Point1.X = shape_line.x1 + ps->x; \ + pcb_line.Point1.Y = shape_line.y1 + ps->y; \ + pcb_line.Point2.X = shape_line.x2 + ps->x; \ + pcb_line.Point2.Y = shape_line.y2 + ps->y; \ + pcb_line.Clearance = 0; \ + pcb_line.Thickness = shape_line.thickness; \ + pcb_line.Flags = shape_line.square ? pcb_flag_make(PCB_FLAG_SQUARE) : pcb_no_flags(); \ + } while(0) + +pcb_bool_t pcb_isc_pstk_line(pcb_pstk_t *ps, pcb_line_t *line) +{ + pcb_pstk_shape_t *shape = pcb_pstk_shape_at(PCB, ps, line->parent.layer); + if (shape == NULL) return pcb_false; + switch(shape->shape) { + case PCB_PSSH_POLY: + if (shape->data.poly.pa == NULL) + pcb_pstk_shape_update_pa(&shape->data.poly); + return pcb_isc_line_polyline(shape->data.poly.pa->contours, line->Point1.X - ps->x, line->Point1.Y - ps->y, line->Point2.X - ps->x, line->Point2.Y - ps->y, line->Thickness); + case PCB_PSSH_LINE: + { + pcb_line_t tmp; + shape_line_to_pcb_line(ps, shape->data.line, tmp); + return pcb_isc_line_line(line, &tmp); + } + case PCB_PSSH_CIRC: + { + pcb_any_line_t tmp; + tmp.Point1.X = line->Point1.X; + tmp.Point1.Y = line->Point1.Y; + tmp.Point2.X = line->Point2.X; + tmp.Point2.Y = line->Point2.Y; + tmp.Thickness = line->Thickness; + tmp.Flags = pcb_no_flags(); + return pcb_is_point_in_line(shape->data.circ.x + ps->x, shape->data.circ.y + ps->y, shape->data.circ.dia/2, &tmp); + } + case PCB_PSSH_HSHADOW: + return 0; /* non-object won't intersect */ + } + return pcb_false; +} + + +PCB_INLINE pcb_bool_t pcb_isc_pstk_arc(pcb_pstk_t *ps, pcb_arc_t *arc) +{ + pcb_pstk_shape_t *shape = pcb_pstk_shape_at(PCB, ps, arc->parent.layer); + if (shape == NULL) return pcb_false; + switch(shape->shape) { + case PCB_PSSH_POLY: + { + pcb_arc_t tmp; + + /* transform the arc back to 0;0 of the padstack */ + tmp = *arc; + tmp.X -= ps->x; + tmp.Y -= ps->y; + tmp.BoundingBox.X1 -= ps->x; + tmp.BoundingBox.Y1 -= ps->y; + tmp.BoundingBox.X2 -= ps->x; + tmp.BoundingBox.Y2 -= ps->y; + + if (shape->data.poly.pa == NULL) + pcb_pstk_shape_update_pa(&shape->data.poly); + + return pcb_isc_arc_polyarea(&tmp, shape->data.poly.pa); + } + + case PCB_PSSH_LINE: + { + pcb_line_t tmp; + shape_line_to_pcb_line(ps, shape->data.line, tmp); + return pcb_isc_line_arc(&tmp, arc); + } + case PCB_PSSH_CIRC: + return pcb_is_point_on_arc(shape->data.circ.x + ps->x, shape->data.circ.y + ps->y, shape->data.circ.dia/2, arc); + break; + case PCB_PSSH_HSHADOW: + return 0; /* non-object won't intersect */ + } + return pcb_false; +} + +PCB_INLINE pcb_polyarea_t *pcb_pstk_shp_poly2area(pcb_pstk_t *ps, pcb_pstk_shape_t *shape) +{ + int n; + pcb_pline_t *pl; + pcb_vector_t v; + pcb_polyarea_t *shp = pcb_polyarea_create(); + + v[0] = shape->data.poly.x[0] + ps->x; v[1] = shape->data.poly.y[0] + ps->y; + pl = pcb_poly_contour_new(v); + for(n = 1; n < shape->data.poly.len; n++) { + v[0] = shape->data.poly.x[n] + ps->x; v[1] = shape->data.poly.y[n] + ps->y; + pcb_poly_vertex_include(pl->head.prev, pcb_poly_node_create(v)); + } + pcb_poly_contour_pre(pl, 1); + pcb_polyarea_contour_include(shp, pl); + + if (!pcb_poly_valid(shp)) { +/* pcb_polyarea_free(&shp); shp = pcb_polyarea_create();*/ + pcb_poly_contour_inv(pl); + pcb_polyarea_contour_include(shp, pl); + } + + return shp; +} + +PCB_INLINE pcb_bool_t pcb_isc_pstk_poly(pcb_pstk_t *ps, pcb_poly_t *poly) +{ + pcb_pstk_shape_t *shape = pcb_pstk_shape_at(PCB, ps, poly->parent.layer); + if (shape == NULL) return pcb_false; + + switch(shape->shape) { + case PCB_PSSH_POLY: + { + /* convert the shape poly to a new poly so that it can be intersected */ + pcb_bool res; + pcb_polyarea_t *shp = pcb_pstk_shp_poly2area(ps, shape); + res = pcb_polyarea_touching(shp, poly->Clipped); + pcb_polyarea_free(&shp); + return res; + } + case PCB_PSSH_LINE: + { + pcb_line_t tmp; + shape_line_to_pcb_line(ps, shape->data.line, tmp); + pcb_line_bbox(&tmp); + return pcb_isc_line_poly(&tmp, poly); + } + case PCB_PSSH_CIRC: + { + pcb_line_t tmp; + tmp.Point1.X = tmp.Point2.X = shape->data.circ.x + ps->x; + tmp.Point1.Y = tmp.Point2.Y = shape->data.circ.y + ps->y; + tmp.Clearance = 0; + tmp.Thickness = shape->data.circ.dia; + tmp.Flags = pcb_no_flags(); + pcb_line_bbox(&tmp); + return pcb_isc_line_poly(&tmp, poly); + } + case PCB_PSSH_HSHADOW: + return 0; /* non-object won't intersect */ + } + return pcb_false; +} + +PCB_INLINE pcb_bool_t pstk_shape_isc_circ_poly(pcb_pstk_t *p, pcb_pstk_shape_t *sp, pcb_pstk_t *c, pcb_pstk_shape_t *sc) +{ + pcb_coord_t px = sc->data.circ.x + c->x - p->x; + pcb_coord_t py = sc->data.circ.y + c->y - p->y; + return pcb_isc_line_polyline(sp->data.poly.pa->contours, px, py, px, py, sc->data.circ.dia); +} + +PCB_INLINE pcb_bool_t pstk_shape_isc_circ_line(pcb_pstk_t *l, pcb_pstk_shape_t *sl, pcb_pstk_t *c, pcb_pstk_shape_t *sc) +{ + pcb_any_line_t tmp; + tmp.Point1.X = sl->data.line.x1 + l->x; + tmp.Point1.Y = sl->data.line.y1 + l->y; + tmp.Point2.X = sl->data.line.x2 + l->x; + tmp.Point2.Y = sl->data.line.y2 + l->y; + tmp.Thickness = sl->data.line.thickness; + tmp.Flags = pcb_no_flags(); + return pcb_is_point_in_line(sc->data.circ.x + c->x, sc->data.circ.y + c->y, sc->data.circ.dia/2, &tmp); +} + +PCB_INLINE pcb_bool_t pcb_pstk_shape_intersect(pcb_pstk_t *ps1, pcb_pstk_shape_t *shape1, pcb_pstk_t *ps2, pcb_pstk_shape_t *shape2) +{ + if ((shape1->shape == PCB_PSSH_POLY) && (shape1->data.poly.pa == NULL)) + pcb_pstk_shape_update_pa(&shape1->data.poly); + if ((shape2->shape == PCB_PSSH_POLY) && (shape2->data.poly.pa == NULL)) + pcb_pstk_shape_update_pa(&shape2->data.poly); + + switch(shape1->shape) { + case PCB_PSSH_POLY: + switch(shape2->shape) { + case PCB_PSSH_POLY: + { + pcb_bool res; + pcb_polyarea_t *shp1 = pcb_pstk_shp_poly2area(ps1, shape1); + pcb_polyarea_t *shp2 = pcb_pstk_shp_poly2area(ps2, shape2); + res = pcb_polyarea_touching(shp1, shp2); + pcb_polyarea_free(&shp1); + pcb_polyarea_free(&shp2); + return res; + } + case PCB_PSSH_LINE: + return pcb_isc_line_polyline(shape1->data.poly.pa->contours, shape2->data.line.x1 + ps2->x - ps1->x, shape2->data.line.y1 + ps2->y - ps1->y, shape2->data.line.x2 + ps2->x - ps1->x, shape2->data.line.y2 + ps2->y - ps1->y, shape2->data.line.thickness); + case PCB_PSSH_CIRC: + return pstk_shape_isc_circ_poly(ps1, shape1, ps2, shape2); + case PCB_PSSH_HSHADOW: + return 0; /* non-object won't intersect */ + } + break; + + case PCB_PSSH_LINE: + switch(shape2->shape) { + case PCB_PSSH_POLY: + return pcb_isc_line_polyline(shape2->data.poly.pa->contours, shape1->data.line.x1 + ps1->x - ps2->x, shape1->data.line.y1 + ps1->y - ps2->y, shape1->data.line.x2 + ps1->x - ps2->x, shape1->data.line.y2 + ps1->y - ps2->y, shape1->data.line.thickness); + case PCB_PSSH_LINE: + { + pcb_line_t tmp1, tmp2; + shape_line_to_pcb_line(ps1, shape1->data.line, tmp1); + shape_line_to_pcb_line(ps2, shape2->data.line, tmp2); + return pcb_isc_line_line(&tmp1, &tmp2); + } + case PCB_PSSH_CIRC: + return pstk_shape_isc_circ_line(ps1, shape1, ps2, shape2); + case PCB_PSSH_HSHADOW: + return 0; /* non-object won't intersect */ + } + break; + + case PCB_PSSH_CIRC: + switch(shape2->shape) { + case PCB_PSSH_POLY: + return pstk_shape_isc_circ_poly(ps2, shape2, ps1, shape1); + case PCB_PSSH_LINE: + return pstk_shape_isc_circ_line(ps2, shape2, ps1, shape1); + case PCB_PSSH_CIRC: + { + double cdist2 = pcb_distance2(ps1->x + shape1->data.circ.x, ps1->y + shape1->data.circ.y, ps2->x + shape2->data.circ.x, ps2->y + shape2->data.circ.y); + double dia = ((double)shape1->data.circ.dia + (double)shape2->data.circ.dia)/2.0; + return cdist2 <= dia*dia; + } + case PCB_PSSH_HSHADOW: + return 0; /* non-object won't intersect */ + } + break; + + case PCB_PSSH_HSHADOW: + return 0; /* non-object won't intersect */ + } + return pcb_false; +} + +PCB_INLINE pcb_bool_t pcb_isc_pstk_pstk(pcb_pstk_t *ps1, pcb_pstk_t *ps2) +{ + pcb_layer_t *ly; + int n; + + for(n = 0, ly = PCB->Data->Layer; n < PCB->Data->LayerN; n++,ly++) { + pcb_pstk_shape_t *shape1; + pcb_pstk_shape_t *shape2; + pcb_layer_type_t lyt = pcb_layer_flags_(ly); + + if (!(lyt & PCB_LYT_COPPER)) /* consider only copper for connections */ + continue; + + shape1 = pcb_pstk_shape_at(PCB, ps1, ly); + if (shape1 == NULL) continue; + shape2 = pcb_pstk_shape_at(PCB, ps2, ly); + if (shape2 == NULL) continue; + + if (pcb_pstk_shape_intersect(ps1, shape1, ps2, shape2)) return pcb_true; + } + return pcb_false; +} + + +PCB_INLINE pcb_bool_t pcb_isc_pstk_rat(pcb_pstk_t *ps, pcb_rat_t *rat) +{ + pcb_board_t *pcb = PCB; + + if ((rat->Point1.X == ps->x) && (rat->Point1.Y == ps->y)) { + pcb_layer_t *layer = pcb_get_layer(pcb->Data, pcb->LayerGroups.grp[rat->group1].lid[0]); + if ((layer != NULL) && (pcb_pstk_shape_at(pcb, ps, layer) != NULL)) + return pcb_true; + } + + if ((rat->Point2.X == ps->x) && (rat->Point2.Y == ps->y)) { + pcb_layer_t *layer = pcb_get_layer(pcb->Data, pcb->LayerGroups.grp[rat->group2].lid[0]); + if ((layer != NULL) && (pcb_pstk_shape_at(pcb, ps, layer) != NULL)) + return pcb_true; + } + + return pcb_false; +} Index: tags/2.1.2/src/flag.c =================================================================== --- tags/2.1.2/src/flag.c (nonexistent) +++ tags/2.1.2/src/flag.c (revision 24813) @@ -0,0 +1,117 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996,2004,2006 Thomas Nau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +#include +#include +#include +#include "config.h" +#include "flag.h" +#include "operation.h" + +/* This just fills in a pcb_flag_t with current flags. */ +pcb_flag_t pcb_flag_make(unsigned int flags) +{ + pcb_flag_t rv; + memset(&rv, 0, sizeof(rv)); + rv.f = flags; + return rv; +} + +pcb_flag_t pcb_flag_add(pcb_flag_t flag, unsigned int flags) +{ + flag.f |= flags; + return flag; +} + +pcb_flag_t pcb_flag_mask(pcb_flag_t flag, unsigned int flags) +{ + flag.f &= ~flags; + return flag; +} + +int pcb_mem_any_set(unsigned char *ptr, int bytes) +{ + while (bytes--) + if (*ptr++) + return 1; + return 0; +} + +void pcb_flag_erase(pcb_flag_t * f) +{ + pcb_unknown_flag_t *u, *next; + for (u = f->unknowns; u != NULL; u = next) { + free(u->str); + next = u->next; + free(u); + } + f->unknowns = NULL; +} + +int pcb_flag_eq(pcb_flag_t *f1, pcb_flag_t *f2) +{ + if (f1->f != f2->f) + return 0; + + if (f1->q != f2->q) + return 0; + + /* WARNING: ignore unknowns for now: the only place where we use this function, + undo.c, won't care */ + + return (memcmp(f1->t, &f2->t, sizeof(f1->t)) == 0); +} + +const char *pcb_dynflag_cookie[PCB_DYNFLAG_BLEN]; + +pcb_dynf_t pcb_dynflag_alloc(const char *cookie) +{ + pcb_dynf_t n; + for(n = 0; n < PCB_DYNFLAG_BLEN; n++) { + if (pcb_dynflag_cookie[n] == NULL) { + pcb_dynflag_cookie[n] = cookie; + return n; + } + } + return PCB_DYNF_INVALID; +} + +void pcb_dynflag_free(pcb_dynf_t dynf) +{ + if ((dynf >= 0) && (dynf < PCB_DYNFLAG_BLEN)) + pcb_dynflag_cookie[dynf] = NULL; +} + + +void pcb_dynflag_uninit(void) +{ + pcb_dynf_t n; + for(n = 0; n < PCB_DYNFLAG_BLEN; n++) + if (pcb_dynflag_cookie[n] != NULL) + fprintf(stderr, "pcb-rnd: Internal error: dynamic flag %d (%s) not unregistered\n", n, pcb_dynflag_cookie[n]); +} Index: tags/2.1.2/src/flag.h =================================================================== --- tags/2.1.2/src/flag.h (nonexistent) +++ tags/2.1.2/src/flag.h (revision 24813) @@ -0,0 +1,199 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996,2006 Thomas Nau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +#ifndef PCB_FLAG_H +#define PCB_FLAG_H + +#include "globalconst.h" + +/* Nobody should know about the internals of this except the macros in + macros.h that access it. This structure must be simple-assignable + for now. */ +typedef struct pcb_unknown_flag_s pcb_unknown_flag_t; +struct pcb_unknown_flag_s { + char *str; + pcb_unknown_flag_t *next; +}; + +#define PCB_DYNFLAG_WORD unsigned long +#define PCB_DYNFLAG_WLEN ((PCB_DYNFLAG_BLEN-1) / sizeof(PCB_DYNFLAG_WORD)+1) +typedef PCB_DYNFLAG_WORD pcb_dynflag_t[PCB_DYNFLAG_WLEN]; + +typedef struct { + unsigned long f; /* generic statically assigned flag bits */ + pcb_dynflag_t df; /* dynamically allocated flag bits */ + unsigned char t[(PCB_MAX_LAYER + 1) / 2]; /* thermals */ + unsigned char q; /* square geometry flag - need to keep only for .pcb compatibility */ + pcb_unknown_flag_t *unknowns; +} pcb_flag_t; + +extern pcb_flag_t no_flags; + +/*** object flags ***/ +typedef enum { + PCB_FLAG_NO = 0x00000, + PCB_FLAG_PIN = 0x00001, + PCB_FLAG_VIA = 0x00002, + PCB_FLAG_FOUND = 0x00004, + PCB_FLAG_HOLE = 0x00008, + PCB_FLAG_NOPASTE = 0x00008, + PCB_FLAG_RAT = 0x00010, + PCB_FLAG_PININPOLY = 0x00010, + PCB_FLAG_CLEARPOLY = 0x00010, + PCB_FLAG_HIDENAME = 0x00010, + PCB_FLAG_DISPLAYNAME = 0x00020, + PCB_FLAG_CLEARLINE = 0x00020, + PCB_FLAG_FULLPOLY = 0x00020, + PCB_FLAG_SELECTED = 0x00040, + PCB_FLAG_ONSOLDER = 0x00080, + PCB_FLAG_AUTO = 0x00080, + PCB_FLAG_SQUARE = 0x00100, + PCB_FLAG_RUBBEREND = 0x00200, + PCB_FLAG_WARN = 0x00200, + PCB_FLAG_USETHERMAL = 0x00400, + PCB_FLAG_ONSILK = 0x00400, /* Obsolete, old files used this to indicate lines drawn on silk. (Used by io_pcb for compatibility.) */ + PCB_FLAG_OCTAGON = 0x00800, + PCB_FLAG_DRC = 0x01000, + PCB_FLAG_LOCK = 0x02000, + PCB_FLAG_EDGE2 = 0x04000, + PCB_FLAG_VISIT = 0x08000, /* marker to avoid re-visiting an object */ + PCB_FLAG_NONETLIST = 0x10000, + PCB_FLAG_MINCUT = 0x20000, /* used by the mincut short find code */ + PCB_FLAG_ONPOINT = 0x40000, /* crosshair is on line point or arc point */ + PCB_FLAG_TERMNAME = 0x80000, + PCB_FLAG_DRC_INTCONN = 0x100000,/* Set for objects are put on the DRC mark because of an intconn */ + PCB_FLAG_CLEARPOLYPOLY= 0x200000, + PCB_FLAG_DYNTEXT = 0x400000, + PCB_FLAG_FLOATER = 0x800000 +/* PCB_FLAG_NOCOPY = (PCB_FLAG_FOUND | CONNECTEDFLAG | PCB_FLAG_ONPOINT)*/ +} pcb_flag_values_t; + +#define PCB_FLAGS 0x01ffffff /* all used flags */ + +#define PCB_SHOWNUMBERFLAG 0x00000001 +#define PCB_LOCALREFFLAG 0x00000002 +#define PCB_CHECKPLANESFLAG 0x00000004 +#define PCB_SHOWPCB_FLAG_DRC 0x00000008 +#define PCB_RUBBERBANDFLAG 0x00000010 +#define PCB_DESCRIPTIONFLAG 0x00000020 +#define PCB_NAMEONPCBFLAG 0x00000040 +#define PCB_AUTOPCB_FLAG_DRC 0x00000080 +#define PCB_ALLDIRECTIONFLAG 0x00000100 +#define PCB_SWAPSTARTDIRFLAG 0x00000200 +#define PCB_UNIQUENAMEFLAG 0x00000400 +#define PCB_CLEARNEWFLAG 0x00000800 +#define PCB_SNAPPCB_FLAG_PIN 0x00001000 +#define PCB_SHOWMASKFLAG 0x00002000 +#define PCB_THINDRAWFLAG 0x00004000 +#define PCB_ORTHOMOVEFLAG 0x00008000 +#define PCB_LIVEROUTEFLAG 0x00010000 +#define PCB_THINDRAWPOLYFLAG 0x00020000 +#define PCB_LOCKNAMESFLAG 0x00040000 +#define PCB_ONLYNAMESFLAG 0x00080000 +#define PCB_NEWPCB_FLAG_FULLPOLY 0x00100000 +#define PCB_HIDENAMESFLAG 0x00200000 +#define PCB_ENABLEPCB_FLAG_MINCUT 0x00400000 + + + +/* Convert flags to flags, set everything else to 0 */ +pcb_flag_t pcb_flag_make(unsigned int src); + +/* set bits of src in dst */ +pcb_flag_t pcb_flag_add(pcb_flag_t dst, unsigned int src); + +/* clear (unset) bits of src in dst */ +pcb_flag_t pcb_flag_mask(pcb_flag_t dst, unsigned int src); + +/* destroy flags: clear all bits and free fields */ +void pcb_flag_erase(pcb_flag_t *f); + +#define pcb_no_flags() pcb_flag_make(0) + +/* --------------------------------------------------------------------------- + * some routines for flag setting, clearing, changing and testing + */ +#define PCB_FLAG_SET(F,P) ((P)->Flags.f |= (F)) +#define PCB_FLAG_CLEAR(F,P) ((P)->Flags.f &= (~(F))) +#define PCB_FLAG_TEST(F,P) ((P)->Flags.f & (F) ? 1 : 0) +#define PCB_FLAG_TOGGLE(F,P) ((P)->Flags.f ^= (F)) +#define PCB_FLAG_ASSIGN(F,V,P) ((P)->Flags.f = ((P)->Flags.f & (~(F))) | ((V) ? (F) : 0)) +#define PCB_FLAGS_TEST(F,P) (((P)->Flags.f & (F)) == (F) ? 1 : 0) + +typedef enum { + PCB_CHGFLG_CLEAR, + PCB_CHGFLG_SET, + PCB_CHGFLG_TOGGLE +} pcb_change_flag_t; + +#define PCB_FLAG_CHANGE(how, F, P) \ +do { \ + switch(how) { \ + case PCB_CHGFLG_CLEAR: PCB_FLAG_CLEAR(F, P); break; \ + case PCB_CHGFLG_SET: PCB_FLAG_SET(F, P); break; \ + case PCB_CHGFLG_TOGGLE: PCB_FLAG_TOGGLE(F, P); break; \ + } \ +} while(0) + +/* Ignores dynamic flags and thermals */ +int pcb_flag_eq(pcb_flag_t *f1, pcb_flag_t *f2); +#define PCB_FLAG_EQ(F1,F2) pcb_flag_eq(&(F1), &(F2)) + +#define PCB_FLAG_THERM(L) (0xf << (4 *((L) % 2))) + +#define PCB_FLAG_THERM_TEST(L,P) ((P)->Flags.t[(L)/2] & PCB_FLAG_THERM(L) ? 1 : 0) +#define PCB_FLAG_THERM_GET(L,P) (((P)->Flags.t[(L)/2] >> (4 * ((L) % 2))) & 0xf) +#define PCB_FLAG_THERM_CLEAR(L,P) (P)->Flags.t[(L)/2] &= ~PCB_FLAG_THERM(L) +#define PCB_FLAG_THERM_ASSIGN(L,V,P) (P)->Flags.t[(L)/2] = ((P)->Flags.t[(L)/2] & ~PCB_FLAG_THERM(L)) | ((V) << (4 * ((L) % 2))) +#define PCB_FLAG_THERM_ASSIGN_(L,V,F) (F).t[(L)/2] = (((F).t[(L)/2] & ~PCB_FLAG_THERM(L)) | ((V) << (4 * ((L) % 2)))) + + +#define PCB_FLAG_SQUARE_GET(P) ((P)->Flags.q) +#define PCB_FLAG_SQUARE_CLEAR(P) (P)->Flags.q = 0 +#define PCB_FLAG_SQUARE_ASSIGN(V,P) (P)->Flags.q = V + +/* Returns 1 if any of the bytes in arr is non-zero */ +int pcb_mem_any_set(unsigned char *arr, int arr_len); +#define PCB_FLAG_THERM_TEST_ANY(P) pcb_mem_any_set((P)->Flags.t, sizeof((P)->Flags.t)) + +/*** Dynamic flags ***/ +#define PCB_DFLAG_SET(flg, dynf) (flg)->df[(dynf) / sizeof(PCB_DYNFLAG_WORD)] |= (1 << (dynf) % sizeof(PCB_DYNFLAG_WORD)) +#define PCB_DFLAG_CLR(flg, dynf) (flg)->df[(dynf) / sizeof(PCB_DYNFLAG_WORD)] &= ~(1 << (dynf) % sizeof(PCB_DYNFLAG_WORD)) +#define PCB_DFLAG_TEST(flg, dynf) (!!((flg)->df[(dynf) / sizeof(PCB_DYNFLAG_WORD)] & (1 << (dynf) % sizeof(PCB_DYNFLAG_WORD)))) +#define PCB_DFLAG_PUT(flg, dynf, val) ((val) ? PCB_DFLAG_SET((flg), (dynf)) : PCB_DFLAG_CLR((flg), (dynf))) + +extern const char *pcb_dynflag_cookie[PCB_DYNFLAG_BLEN]; + +typedef int pcb_dynf_t; +#define PCB_DYNF_INVALID (-1) +pcb_dynf_t pcb_dynflag_alloc(const char *cookie); +void pcb_dynflag_free(pcb_dynf_t dynf); + +void pcb_dynflag_uninit(void); + +#endif Index: tags/2.1.2/src/flag_str.c =================================================================== --- tags/2.1.2/src/flag_str.c (nonexistent) +++ tags/2.1.2/src/flag_str.c (revision 24813) @@ -0,0 +1,623 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 2005 DJ Delorie + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + * + * Old contact info: + * DJ Delorie, 334 North Road, Deerfield NH 03037-1110, USA + * dj@delorie.com + * + */ + +#include "config.h" + +#include +#include +#include +#include + +#include "flag_str.h" +#include "compat_misc.h" +#include "obj_common.h" +#include "macro.h" + +/* Because the common flag access macros expect an object struct to work on. */ +typedef struct { + pcb_flag_t Flags; +} FlagHolder; + +/* Be careful to list more specific flags first, followed by general + * flags, when two flags use the same bit. For example, "onsolder" is + * for elements only, while "auto" is for everything else. They use + * the same bit, but onsolder is listed first so that elements will + * use it and not auto. + * + * Thermals are handled separately, as they're layer-selective. + */ + +#define N(x) x, sizeof(x)-1 +#define FN(x) x, #x +pcb_flag_bits_t pcb_object_flagbits[] = { + {FN(PCB_FLAG_PIN), N("pin"), PCB_OBJ_ANY, "If set, this object is a pin. This flag is for internal use only.", 0, 1}, + {FN(PCB_FLAG_VIA), N("via"), PCB_OBJ_ANY, "If set, this object is a via. This flag is for internal use only.", 0, 1}, + {FN(PCB_FLAG_FOUND), N("found"), PCB_OBJ_ANY, "If set, this object has been found by FindConnection()", 0, 0}, + {FN(PCB_FLAG_HOLE), N("hole"), PCB_OBJ_CLASS_PIN, "For pins and vias, this flag means that the pin or via is a hole without a copper annulus.", 0, 0}, + {FN(PCB_FLAG_RAT), N("rat"), PCB_OBJ_RAT, "If set for a line, indicates that this line is a rat line instead of a copper trace.", 0, 0}, + {FN(PCB_FLAG_PININPOLY), N("pininpoly"), 0, "For pins and pads, this flag is used internally to indicate that the pin or pad overlaps a polygon on some layer.", 0, 0}, + {FN(PCB_FLAG_CLEARPOLY), N("clearpoly"), PCB_OBJ_POLY, "For polygons, this flag means that pins and vias will normally clear these polygons (thus, thermals are required for electrical connection). When clear, polygons will solidly connect to pins and vias. ", 0, 0}, + {FN(PCB_FLAG_HIDENAME), N("hidename"), 0, "For elements, when set the name of the element is hidden.", PCB_OBJ_SUBC, 0}, + {FN(PCB_FLAG_DISPLAYNAME), N("showname"), 0, "OBSOLETE: For elements, when set the names of pins are shown.", 0, 0}, + {FN(PCB_FLAG_CLEARLINE), N("clearline"), PCB_OBJ_LINE | PCB_OBJ_ARC | PCB_OBJ_TEXT | PCB_OBJ_PSTK, "For lines and arcs, the line/arc will clear polygons instead of connecting to them.", 0, 0 }, + {FN(PCB_FLAG_SELECTED), N("selected"), PCB_OBJ_ANY, "Set when the object is selected.", 0, 0}, + {FN(PCB_FLAG_ONSOLDER), N("onsolder"), PCB_OBJ_TEXT, "For text, indicates that it is on the solder side.", PCB_OBJ_SUBC | PCB_OBJ_PSTK, 0}, + {FN(PCB_FLAG_AUTO), N("auto"), PCB_OBJ_LINE|PCB_OBJ_ARC|PCB_OBJ_PSTK, "For lines and vias, indicates that these were created by the autorouter.", 0, 0}, + {FN(PCB_FLAG_SQUARE), N("square"), 0, "For pins and pads, indicates a square (vs round) pin/pad.", PCB_OBJ_PSTK, 0}, + {FN(PCB_FLAG_RUBBEREND), N("rubberend"), PCB_OBJ_LINE | PCB_OBJ_ARC, "For lines, used internally for rubber band moves: indicates one end already rubber banding.", 0, 0}, + {FN(PCB_FLAG_WARN), N("warn"), PCB_OBJ_CLASS_PIN, "For pins, vias, and pads, set to indicate a warning.", 0, 0}, + {FN(PCB_FLAG_USETHERMAL), N("usetherm"), PCB_OBJ_CLASS_PIN | PCB_OBJ_LINE | PCB_OBJ_ARC, "Obsolete, indicates that pins/vias should be drawn with thermal fingers.", 0, 1}, + {FN(PCB_FLAG_OCTAGON), N("octagon"), 0, "Draw pins and vias as octagons.", 0, 0}, + {FN(PCB_FLAG_DRC), N("drc"), PCB_OBJ_ANY, "Set for objects that fail DRC: flag like FOUND flag for DRC checking.", 0}, + {FN(PCB_FLAG_LOCK), N("lock"), PCB_OBJ_ANY, "Set for locked objects.", 0, 0}, + {FN(PCB_FLAG_EDGE2), N("edge2"), PCB_OBJ_ANY, "For pads, indicates that the second point is closer to the edge. For pins, indicates that the pin is closer to a horizontal edge and thus pinout text should be vertical. (Padr.Point2 is closer to outside edge also pinout text for pins is vertical)", 0, 1}, + {FN(PCB_FLAG_FULLPOLY), N("fullpoly"), PCB_OBJ_POLY, "For polygons, the full polygon is drawn (i.e. all parts instead of only the biggest one).", 0, 0}, + {FN(PCB_FLAG_NOPASTE), N("nopaste"), 0, "Pad should not receive solderpaste. This is to support fiducials", 0, 0}, + {FN(PCB_FLAG_NONETLIST), N("nonetlist"), PCB_OBJ_SUBC, "subcircuit is not on the netlist and should not interfere with the netlist ", 0, 0}, + {FN(PCB_FLAG_TERMNAME), N("termname"), PCB_OBJ_LINE | PCB_OBJ_ARC | PCB_OBJ_POLY | PCB_OBJ_TEXT | PCB_OBJ_PSTK | PCB_OBJ_SUBC, "when set the names of pins are shown.", 0, 0}, + {FN(PCB_FLAG_CLEARPOLYPOLY), N("clearpolypoly"), PCB_OBJ_POLY, "For polygons, apply clearance to nearby polygons", 0, 0}, + {FN(PCB_FLAG_DYNTEXT), N("dyntext"), PCB_OBJ_TEXT, "For text: dynamic string (substitute %patterns%)", 0, 0}, + {FN(PCB_FLAG_FLOATER), N("floater"), PCB_OBJ_ANY, "subc part can be moved after subc placing", 0, 0} +}; +#undef N +#undef FN + +const int pcb_object_flagbits_len = PCB_ENTRIES(pcb_object_flagbits); + +/* List of old/obsolete flags to silently ignore on load */ +static const char *old_flag_ignore[] = { "connected", NULL }; + +/* + * This helper function maintains a small list of buffers which are + * used by pcb_strflg_f2s(). Each buffer is allocated from the heap, + * but the caller must not free them (they get realloced when they're + * reused, but never completely freed). + */ + +static struct { + char *ptr; + int len; +} buffers[10]; +static int bufptr = 0; +static char *alloc_buf(int len) +{ +#define B buffers[bufptr] + len++; + bufptr = (bufptr + 1) % 10; + if (B.len < len) { + if (B.ptr) + B.ptr = (char *) realloc(B.ptr, len); + else + B.ptr = (char *) malloc(len); + B.len = len; + } + return B.ptr; +#undef B +} + +void pcb_strflg_uninit_buf(void) +{ + int n; + for(n = 0; n < 10; n++) { + if (buffers[n].ptr != NULL) { + free(buffers[n].ptr); + buffers[n].ptr = NULL; + } + } +} + +/* + * This set of routines manages a list of layer-specific flags. + * Callers should call grow_layer_list(0) to reset the list, and + * set_layer_list(layer,1) to set bits in the layer list. The results + * are stored in layers[], which has num_layers valid entries. + */ + +static char *layers = 0; +static int max_layers = 0, num_layers = 0; + +static void grow_layer_list(int num) +{ + if (layers == 0) { + layers = (char *) calloc(num > 0 ? num : 1, 1); + max_layers = num; + } + else if (num > max_layers) { + max_layers = num; + layers = (char *) realloc(layers, max_layers); + } + if (num > num_layers) + memset(layers + num_layers, 0, num - num_layers - 1); + num_layers = num; + return; +} + +void pcb_strflg_uninit_layerlist(void) +{ + if (layers != NULL) { + free(layers); + layers = NULL; + num_layers = max_layers = 0; + } +} + +static inline void set_layer_list(int layer, int v) +{ + if (layer >= num_layers) + grow_layer_list(layer + 1); + layers[layer] = v; +} + +/* + * These next two convert between layer lists and strings. + * parse_layer_list() is passed a pointer to a string, and parses a + * list of integer which reflect layers to be flagged. It returns a + * pointer to the first character following the list. The syntax of + * the list is a paren-surrounded, comma-separated list of integers + * and/or pairs of integers separated by a dash (like "(1,2,3-7)"). + * Spaces and other punctuation are not allowed. The results are + * stored in layers[] defined above. + * + * print_layer_list() does the opposite - it uses the flags set in + * layers[] to build a string that represents them, using the syntax + * above. + * + */ + +/* Returns a pointer to the first character past the list. */ +static const char *parse_layer_list(const char *bp, int (*error) (const char *)) +{ + const char *orig_bp = bp; + int l = 0, range = -1; + int value = 1; + + grow_layer_list(0); + while (*bp) { + if (*bp == '+') + value = 2; + else if (*bp == 'S') + value = 3; + else if (*bp == 'X') + value = 4; + else if (*bp == 't') + value = 5; + else if (*bp == ')' || *bp == ',' || *bp == '-') { + if (range == -1) + range = l; + while (range <= l) + set_layer_list(range++, value); + if (*bp == '-') + range = l; + else + range = -1; + value = 1; + l = 0; + } + + else if (isdigit((int) *bp)) + l = l * 10 + (*bp - '0'); + + else if (error) { + const char *fmt = "Syntax error parsing layer list \"%.*s\" at %c"; + char *msg = alloc_buf(strlen(fmt) + strlen(orig_bp)); + sprintf(msg, fmt, bp - orig_bp + 5, orig_bp, *bp); + error(msg); + error = NULL; + } + + if (*bp == ')') + return bp + 1; + + bp++; + } + return bp; +} + +/* Number of character the value "i" requires when printed. */ +static int printed_int_length(int i, int j) +{ + int rv; + + if (i < 10) + return 1 + (j ? 1 : 0); + if (i < 100) + return 2 + (j ? 1 : 0); + + for (rv = 1; i >= 10; rv++) + i /= 10; + return rv + (j ? 1 : 0); +} + +/* Returns a pointer to an internal buffer which is overwritten with + each new call. */ +static char *print_layer_list() +{ + static char *buf = 0; + static int buflen = 0; + int len, i, j; + char *bp; + + len = 2; + for (i = 0; i < num_layers; i++) + if (layers[i]) + len += 1 + printed_int_length(i, layers[i]); + if (buflen < len) { + if (buf) + buf = (char *) realloc(buf, len); + else + buf = (char *) malloc(len); + buflen = len; + } + + bp = buf; + *bp++ = '('; + + for (i = 0; i < num_layers; i++) + if (layers[i]) { + /* 0 0 1 1 1 0 0 */ + /* i j */ + for (j = i + 1; j < num_layers && layers[j] == 1; j++); + if (j > i + 2) { + sprintf(bp, "%d-%d,", i, j - 1); + i = j - 1; + } + else + switch (layers[i]) { + case 1: + sprintf(bp, "%d,", i); + break; + case 2: + sprintf(bp, "%d+,", i); + break; + case 3: + sprintf(bp, "%dS,", i); + break; + case 4: + sprintf(bp, "%dX,", i); + break; + case 5: + default: + sprintf(bp, "%dt,", i); + break; + } + bp += strlen(bp); + } + bp[-1] = ')'; + *bp = 0; + return buf; +} + +static int error_ignore(const char *msg) +{ + return 0; +} + +static pcb_flag_t empty_flags; + +pcb_flag_t pcb_strflg_common_s2f(const char *flagstring, int (*error) (const char *msg), pcb_flag_bits_t * flagbits, int n_flagbits, unsigned char *intconn, int compat) +{ + const char *fp, *ep; + int flen; + FlagHolder rv; + int i; + + if (intconn != NULL) + *intconn = 0; + rv.Flags = empty_flags; + + if (error == 0) + error = error_ignore; + + if (flagstring == NULL) + return empty_flags; + + fp = ep = flagstring; + + if (*fp == '"') + ep = ++fp; + + while (*ep && *ep != '"') { + int found = 0; + + while (*fp == ',') + fp++; + + for (ep = fp; *ep && *ep != ',' && *ep != '"' && *ep != '('; ep++); + flen = ep - fp; + if (*ep == '(') + ep = parse_layer_list(ep + 1, error); + + if (flen == 7 && memcmp(fp, "thermal", 7) == 0) { + for (i = 0; i < PCB_MAX_LAYER && i < num_layers; i++) + if (layers[i]) + PCB_FLAG_THERM_ASSIGN(i, layers[i], &rv); + } + else if (flen == 5 && memcmp(fp, "shape", 5) == 0) { + rv.Flags.q = atoi(fp + 6); + } + else if (intconn != NULL && flen == 7 && memcmp(fp, "intconn", 7) == 0) { + *intconn = atoi(fp + 8); + } + else { + for (i = 0; i < n_flagbits; i++) + if (flagbits[i].nlen == flen && memcmp(flagbits[i].name, fp, flen) == 0) { + found = 1; + PCB_FLAG_SET(flagbits[i].mask, &rv); + break; + } + if (!found) { + const char **ign; + for(ign = old_flag_ignore; *ign != NULL; ign++) { + if (memcmp(*ign, fp, flen) == 0) { + found = 1; + break; + } + } + } + if (!found) { + const char *fmt = "Unknown flag: \"%.*s\" ignored"; + pcb_unknown_flag_t *u; + char *msg; + const char *s; + + /* include () */ + s = fp + flen; + if (*s == '(') { + while (*s != ')') { + flen++; + s++; + } + } + if (*s == ')') + flen++; + + msg = alloc_buf(strlen(fmt) + flen); + sprintf(msg, fmt, flen, fp); + error(msg); + + u = malloc(sizeof(pcb_unknown_flag_t)); + u->str = pcb_strndup(fp, flen); + u->next = NULL; + /* need to append, to keep order of flags */ + if (rv.Flags.unknowns != NULL) { + pcb_unknown_flag_t *n; + for (n = rv.Flags.unknowns; n->next != NULL; n = n->next); + n->next = u; + } + else + rv.Flags.unknowns = u; + } + } + fp = ep + 1; + } + return rv.Flags; +} + +pcb_flag_t pcb_strflg_s2f(const char *flagstring, int (*error) (const char *msg), unsigned char *intconn, int compat) +{ + return pcb_strflg_common_s2f(flagstring, error, pcb_object_flagbits, PCB_ENTRIES(pcb_object_flagbits), intconn, compat); +} + +char *pcb_strflg_common_f2s(pcb_flag_t flags, int object_type, pcb_flag_bits_t * flagbits, int n_flagbits, unsigned char *intconn, int compat) +{ + int len; + int i; + FlagHolder fh, savef; + char *buf, *bp; + pcb_unknown_flag_t *u; + + fh.Flags = flags; + +#ifndef FLAG_TEST + switch (object_type) { + case PCB_OBJ_RAT: + PCB_FLAG_CLEAR(PCB_FLAG_RAT, &fh); + break; + } +#endif + + savef = fh; + + len = 3; /* for "()\0" */ + + for (i = 0; i < n_flagbits; i++) { + long my_obj_typs = flagbits[i].object_types | (compat ? flagbits[i].compat_types : 0); + if ((my_obj_typs & object_type) && (PCB_FLAG_TEST(flagbits[i].mask, &fh))) { + len += flagbits[i].nlen + 1; + PCB_FLAG_CLEAR(flagbits[i].mask, &fh); + } + } + + if (PCB_FLAG_THERM_TEST_ANY(&fh)) { + len += sizeof("thermal()"); + for (i = 0; i < PCB_MAX_LAYER; i++) + if (PCB_FLAG_THERM_TEST(i, &fh)) + len += printed_int_length(i, PCB_FLAG_THERM_GET(i, &fh)) + 1; + } + + if (flags.q > 0) { + len += sizeof("shape(.)"); + if (flags.q > 9) + len += 2; + } + + if ((intconn != NULL) && (*intconn > 0)) { + len += sizeof("intconn(.)"); + if (*intconn > 9) + len++; + if (*intconn > 99) + len++; + } + + for (u = flags.unknowns; u != NULL; u = u->next) + len += strlen(u->str) + 1; + + bp = buf = alloc_buf(len + 2); + + *bp++ = '"'; + + fh = savef; + for (i = 0; i < n_flagbits; i++) { + long my_obj_typs = flagbits[i].object_types | (compat ? flagbits[i].compat_types : 0); + if ((my_obj_typs & object_type) && (PCB_FLAG_TEST(flagbits[i].mask, &fh))) { + if (bp != buf + 1) + *bp++ = ','; + strcpy(bp, flagbits[i].name); + bp += flagbits[i].nlen; + PCB_FLAG_CLEAR(flagbits[i].mask, &fh); + } + } + + if (PCB_FLAG_THERM_TEST_ANY(&fh)) { + if (bp != buf + 1) + *bp++ = ','; + strcpy(bp, "thermal"); + bp += strlen("thermal"); + grow_layer_list(0); + for (i = 0; i < PCB_MAX_LAYER; i++) + if (PCB_FLAG_THERM_TEST(i, &fh)) + set_layer_list(i, PCB_FLAG_THERM_GET(i, &fh)); + strcpy(bp, print_layer_list()); + bp += strlen(bp); + } + + if (flags.q > 0) { + if (bp != buf + 1) + *bp++ = ','; + bp += sprintf(bp, "shape(%d)", flags.q); + } + + if ((intconn != NULL) && (*intconn > 0)) { + if (bp != buf + 1) + *bp++ = ','; + bp += sprintf(bp, "intconn(%d)", *intconn); + } + + for (u = flags.unknowns; u != NULL; u = u->next) { + int len; + len = strlen(u->str); + if (bp != buf + 1) + *bp++ = ','; + memcpy(bp, u->str, len); + bp += len; + } + + *bp++ = '"'; + *bp = 0; + return buf; +} + +char *pcb_strflg_f2s(pcb_flag_t flags, int object_type, unsigned char *intconn, int compat) +{ + return pcb_strflg_common_f2s(flags, object_type, pcb_object_flagbits, PCB_ENTRIES(pcb_object_flagbits), intconn, compat); +} + +const pcb_flag_bits_t *pcb_strflg_1bit(unsigned long bit, int object_type) +{ + int i, n_flagbits = PCB_ENTRIES(pcb_object_flagbits);; + for (i = 0; i < n_flagbits; i++) { + unsigned long my_obj_typs = pcb_object_flagbits[i].object_types; + if ((my_obj_typs & object_type) && (!pcb_object_flagbits[i].omit_list) && (pcb_object_flagbits[i].mask & bit)) + return &pcb_object_flagbits[i]; + } + return NULL; +} + +const pcb_flag_bits_t *pcb_strflg_name(const char *name, int object_type) +{ + int i, n_flagbits = PCB_ENTRIES(pcb_object_flagbits);; + for (i = 0; i < n_flagbits; i++) { + unsigned long my_obj_typs = pcb_object_flagbits[i].object_types; + if ((my_obj_typs & object_type) && (!pcb_object_flagbits[i].omit_list) && (strcmp(pcb_object_flagbits[i].name, name) == 0)) + return &pcb_object_flagbits[i]; + } + return NULL; +} + +void pcb_strflg_map(unsigned long fbits, int object_type, void *ctx, void (*cb)(void *ctx, unsigned long flg, const pcb_flag_bits_t *fb)) +{ + int n, i, n_flagbits = PCB_ENTRIES(pcb_object_flagbits); + for(n = 0; n < 32; n++) { + unsigned long bit = 1 << n; + if (!(fbits & bit)) + continue; + + for (i = 0; i < n_flagbits; i++) { + unsigned long my_obj_typs = pcb_object_flagbits[i].object_types /*| pcb_object_flagbits[i].compat_types*/; + if ((my_obj_typs & object_type) && (!pcb_object_flagbits[i].omit_list) && (pcb_object_flagbits[i].mask & bit)) { + cb(ctx, bit, &pcb_object_flagbits[i]); + } + } + } +} + + +#define N(x) x, sizeof(x)-1 +#define FN(x) x, #x +static pcb_flag_bits_t pcb_flagbits[] = { + {FN(PCB_SHOWNUMBERFLAG), N("shownumber"), 1, "Pinout displays pin numbers instead of pin names." }, + {FN(PCB_LOCALREFFLAG), N("localref"), 1, "Use local reference for moves, by setting the mark at the beginning of each move." }, + {FN(PCB_CHECKPLANESFLAG), N("checkplanes"), 1, "When set, only polygons and their clearances are drawn, to see if polygons have isolated regions." }, + {FN(PCB_SHOWPCB_FLAG_DRC), N("showdrc"), 1, "Display DRC region on crosshair." }, + {FN(PCB_RUBBERBANDFLAG), N("rubberband"), 1, "Do all move, mirror, rotate with rubberband connections." }, + {FN(PCB_DESCRIPTIONFLAG), N("description"), 1, "Display descriptions of elements, instead of refdes." }, + {FN(PCB_NAMEONPCBFLAG), N("nameonpcb"), 1, "Display names of elements, instead of refdes." }, + {FN(PCB_AUTOPCB_FLAG_DRC), N("autodrc"), 1, "Auto-DRC flag. When set, PCB doesn't let you place copper that violates DRC." }, + {FN(PCB_ALLDIRECTIONFLAG), N("alldirection"), 1, "Enable 'all-direction' lines." }, + {FN(PCB_SWAPSTARTDIRFLAG), N("swapstartdir"), 1, "Switch starting angle after each click." }, + {FN(PCB_UNIQUENAMEFLAG), N("uniquename"), 1, "Force unique names on board." }, + {FN(PCB_CLEARNEWFLAG), N("clearnew"), 1, "New lines/arc clear polygons." }, + {FN(PCB_SNAPPCB_FLAG_PIN), N("snappin"), 1, "pcb_crosshair snaps to pins and pads." }, + {FN(PCB_SHOWMASKFLAG), N("showmask"), 1, "Show the solder mask layer." }, + {FN(PCB_THINDRAWFLAG), N("thindraw"), 1, "Draw with thin lines." }, + {FN(PCB_ORTHOMOVEFLAG), N("orthomove"), 1, "Move items orthogonally." }, + {FN(PCB_LIVEROUTEFLAG), N("liveroute"), 1, "Draw autoroute paths real-time." }, + {FN(PCB_NEWPCB_FLAG_FULLPOLY), N("newfullpoly"), 1, "New polygons are full ones." }, + {FN(PCB_THINDRAWPOLYFLAG), N("thindrawpoly"), 1, "Thin draw polygon contours instead of filling polygons." }, + {FN(PCB_LOCKNAMESFLAG), N("locknames"), 1, "Names are locked, the mouse cannot select them." }, + {FN(PCB_ONLYNAMESFLAG), N("onlynames"), 1, "Everything but names are locked, the mouse cannot select anything else." }, + {FN(PCB_HIDENAMESFLAG), N("hidenames"), 1, "When set, element names are not drawn." }, + {FN(PCB_ENABLEPCB_FLAG_MINCUT), N("enablemincut"), 1, "Use the mincut algorithm for finding shorts." }, +}; +#undef N +#undef FN + +char *pcb_strflg_board_f2s(pcb_flag_t flags) +{ + return pcb_strflg_common_f2s(flags, PCB_OBJ_ANY, pcb_flagbits, PCB_ENTRIES(pcb_flagbits), NULL, 0); +} + +pcb_flag_t pcb_strflg_board_s2f(const char *flagstring, int (*error) (const char *msg)) +{ + return pcb_strflg_common_s2f(flagstring, error, pcb_flagbits, PCB_ENTRIES(pcb_flagbits), NULL, 0); +} Index: tags/2.1.2/src/flag_str.h =================================================================== --- tags/2.1.2/src/flag_str.h (nonexistent) +++ tags/2.1.2/src/flag_str.h (revision 24813) @@ -0,0 +1,104 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 2005 DJ Delorie + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + * + * Old contact info: + * DJ Delorie, 334 North Road, Deerfield NH 03037-1110, USA + * dj@delorie.com + * + */ + +#ifndef PCB_STRFLAGS_H +#define PCB_STRFLAGS_H + +#include "flag.h" + +typedef struct { + + /* This is the bit that we're setting. */ + pcb_flag_values_t mask; + const char *mask_name; + + /* The name used in the output file. */ + const char *name; + int nlen; + + /* The entry won't be output unless the object type is one of these. */ + int object_types; + + char *help; + + /* in compatibility mode also accept these object types to have the flag */ + int compat_types; + + /* when non-zero, omit from all-flag listings */ + int omit_list; +} pcb_flag_bits_t; + +/* All flags natively known by the core */ +extern pcb_flag_bits_t pcb_object_flagbits[]; +extern const int pcb_object_flagbits_len; + +/* The purpose of this interface is to make the file format able to + handle more than 32 flags, and to hide the internal details of + flags from the file format. In compat mode, compat_types are + also considered (so an old PCB PAD (padstack now) can have + a square flag). */ + +/* When passed a string, parse it and return an appropriate set of + flags. Errors cause error() to be called with a suitable message; + if error is NULL, errors are ignored. */ +pcb_flag_t pcb_strflg_s2f(const char *flagstring, int (*error) (const char *msg), unsigned char *intconn, int compat); + +/* Given a set of flags for a given object type, return a string which + can be output to a file. The returned pointer must not be + freed. If compat is set, allow some old flags set on new object types + which normally won't handle them - this is only for io_pcb, for the + transitional period */ +char *pcb_strflg_f2s(pcb_flag_t flags, int object_type, unsigned char *intconn, int compat); + + +/* Call cb for each flag bit for a given object type */ +void pcb_strflg_map(unsigned long fbits, int object_type, void *ctx, void (*cb)(void *ctx, unsigned long flg, const pcb_flag_bits_t *fb)); + +/* Return flag bit info for a single bit for an object type, or NULL is not available - slow linear search */ +const pcb_flag_bits_t *pcb_strflg_1bit(unsigned long bit, int object_type); + +/* Return flag bit info by flag name for an object type, or NULL is not available - slow linear search */ +const pcb_flag_bits_t *pcb_strflg_name(const char *name, int object_type); + +/* same as above, for pcb level flags */ +char *pcb_strflg_board_f2s(pcb_flag_t flags); +pcb_flag_t pcb_strflg_board_s2f(const char *flagstring, int (*error) (const char *msg)); + +void pcb_strflg_uninit_buf(void); +void pcb_strflg_uninit_layerlist(void); + +/* low level */ +pcb_flag_t pcb_strflg_common_s2f(const char *flagstring, int (*error) (const char *msg), pcb_flag_bits_t * flagbits, int n_flagbits, unsigned char *intconn, int compat); +char *pcb_strflg_common_f2s(pcb_flag_t flags, int object_type, pcb_flag_bits_t * flagbits, int n_flagbits, unsigned char *intconn, int compat); + +#endif Index: tags/2.1.2/src/font.c =================================================================== --- tags/2.1.2/src/font.c (nonexistent) +++ tags/2.1.2/src/font.c (revision 24813) @@ -0,0 +1,474 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996, 2005 Thomas Nau + * pcb-rnd Copyright (C) 2017 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +/* font support. Note: glyphs are called symbols here */ + +#include "config.h" + +#include +#include + +#include "font.h" +#include "board.h" +#include "conf_core.h" +#include "error.h" +#include "plug_io.h" +#include "paths.h" +#include "compat_misc.h" +#include "event.h" +#include "file_loaded.h" + +#define STEP_SYMBOLLINE 10 + +typedef struct embf_line_s { + int x1, y1, x2, y2, th; +} embf_line_t; + +typedef struct embf_font_s { + int delta; + embf_line_t *lines; + int num_lines; +} embf_font_t; + +#include "font_internal.c" + +static void pcb_font_load_internal(pcb_font_t *font) +{ + int n, l; + memset(font, 0, sizeof(pcb_font_t)); + font->MaxWidth = embf_maxx - embf_minx; + font->MaxHeight = embf_maxy - embf_miny; + for(n = 0; n < sizeof(embf_font) / sizeof(embf_font[0]); n++) { + if (embf_font[n].delta != 0) { + pcb_symbol_t *s = font->Symbol + n; + embf_line_t *lines = embf_font[n].lines; + + for(l = 0; l < embf_font[n].num_lines; l++) { + pcb_coord_t x1 = PCB_MIL_TO_COORD(lines[l].x1); + pcb_coord_t y1 = PCB_MIL_TO_COORD(lines[l].y1); + pcb_coord_t x2 = PCB_MIL_TO_COORD(lines[l].x2); + pcb_coord_t y2 = PCB_MIL_TO_COORD(lines[l].y2); + pcb_coord_t th = PCB_MIL_TO_COORD(lines[l].th); + pcb_font_new_line_in_sym(s, x1, y1, x2, y2, th); + } + + s->Valid = 1; + s->Delta = PCB_MIL_TO_COORD(embf_font[n].delta); + } + } + pcb_font_set_info(font); +} + +static int pcb_parse_font_default(pcb_font_t *ptr, const char *filename) +{ + int res = pcb_parse_font(ptr, filename); + if (res == 0) + pcb_file_loaded_set_at("font", "default", filename, "original default font"); + return res; +} + +/* parses a file with font information and installs it into the provided PCB + * checks directories given as colon separated list by resource fontPath + * if the fonts filename doesn't contain a directory component */ +void pcb_font_create_default(pcb_board_t *pcb) +{ + int res = -1; + pcb_io_err_inhibit_inc(); + conf_list_foreach_path_first(res, &conf_core.rc.default_font_file, pcb_parse_font_default(&pcb->fontkit.dflt, __path__)); + pcb_io_err_inhibit_dec(); + + if (res != 0) { + const char *s; + gds_t buff; + s = conf_concat_strlist(&conf_core.rc.default_font_file, &buff, NULL, ':'); + pcb_message(PCB_MSG_WARNING, "Can't find font-symbol-file. Searched: '%s'; falling back to the embedded default font\n", s); + pcb_font_load_internal(&pcb->fontkit.dflt); + pcb_file_loaded_set_at("font", "default", "", "original default font"); + gds_uninit(&buff); + } +} + +/* transforms symbol coordinates so that the left edge of each symbol + * is at the zero position. The y coordinates are moved so that min(y) = 0 */ +void pcb_font_set_info(pcb_font_t *Ptr) +{ + pcb_cardinal_t i, j; + pcb_symbol_t *symbol; + pcb_line_t *line; + pcb_arc_t *arc; + pcb_poly_t *poly; + pcb_coord_t totalminy = PCB_MAX_COORD; + + /* calculate cell with and height (is at least PCB_DEFAULT_CELLSIZE) + * maximum cell width and height + * minimum x and y position of all lines + */ + Ptr->MaxWidth = PCB_DEFAULT_CELLSIZE; + Ptr->MaxHeight = PCB_DEFAULT_CELLSIZE; + for (i = 0, symbol = Ptr->Symbol; i <= PCB_MAX_FONTPOSITION; i++, symbol++) { + pcb_coord_t minx, miny, maxx, maxy; + + /* next one if the index isn't used or symbol is empty (SPACE) */ + if (!symbol->Valid || !symbol->LineN) + continue; + + minx = miny = PCB_MAX_COORD; + maxx = maxy = 0; + for (line = symbol->Line, j = symbol->LineN; j; j--, line++) { + minx = MIN(minx, line->Point1.X); + miny = MIN(miny, line->Point1.Y); + minx = MIN(minx, line->Point2.X); + miny = MIN(miny, line->Point2.Y); + maxx = MAX(maxx, line->Point1.X); + maxy = MAX(maxy, line->Point1.Y); + maxx = MAX(maxx, line->Point2.X); + maxy = MAX(maxy, line->Point2.Y); + } + + for(arc = arclist_first(&symbol->arcs); arc != NULL; arc = arclist_next(arc)) { + pcb_arc_bbox(arc); + minx = MIN(minx, arc->BoundingBox.X1); + miny = MIN(miny, arc->BoundingBox.Y1); + maxx = MAX(maxx, arc->BoundingBox.X2); + maxy = MAX(maxy, arc->BoundingBox.Y2); + } + + for(poly = polylist_first(&symbol->polys); poly != NULL; poly = polylist_next(poly)) { + pcb_poly_bbox(poly); + minx = MIN(minx, poly->BoundingBox.X1); + miny = MIN(miny, poly->BoundingBox.Y1); + maxx = MAX(maxx, poly->BoundingBox.X2); + maxy = MAX(maxy, poly->BoundingBox.Y2); + } + + + /* move symbol to left edge */ + for (line = symbol->Line, j = symbol->LineN; j; j--, line++) + pcb_line_move(line, -minx, 0); + + for(arc = arclist_first(&symbol->arcs); arc != NULL; arc = arclist_next(arc)) + pcb_arc_move(arc, -minx, 0); + + for(poly = polylist_first(&symbol->polys); poly != NULL; poly = polylist_next(poly)) + pcb_poly_move(poly, -minx, 0); + + /* set symbol bounding box with a minimum cell size of (1,1) */ + symbol->Width = maxx - minx + 1; + symbol->Height = maxy + 1; + + /* check total min/max */ + Ptr->MaxWidth = MAX(Ptr->MaxWidth, symbol->Width); + Ptr->MaxHeight = MAX(Ptr->MaxHeight, symbol->Height); + totalminy = MIN(totalminy, miny); + } + + /* move coordinate system to the upper edge (lowest y on screen) */ + for (i = 0, symbol = Ptr->Symbol; i <= PCB_MAX_FONTPOSITION; i++, symbol++) { + if (symbol->Valid) { + symbol->Height -= totalminy; + for (line = symbol->Line, j = symbol->LineN; j; j--, line++) + pcb_line_move(line, 0, -totalminy); + + for(arc = arclist_first(&symbol->arcs); arc != NULL; arc = arclist_next(arc)) + pcb_arc_move(arc, 0, -totalminy); + + for(poly = polylist_first(&symbol->polys); poly != NULL; poly = polylist_next(poly)) + pcb_poly_move(poly, 0, -totalminy); + } + } + + /* setup the box for the default symbol */ + Ptr->DefaultSymbol.X1 = Ptr->DefaultSymbol.Y1 = 0; + Ptr->DefaultSymbol.X2 = Ptr->DefaultSymbol.X1 + Ptr->MaxWidth; + Ptr->DefaultSymbol.Y2 = Ptr->DefaultSymbol.Y1 + Ptr->MaxHeight; +} + +/* creates a new line in a symbol */ +pcb_line_t *pcb_font_new_line_in_sym(pcb_symbol_t *Symbol, pcb_coord_t X1, pcb_coord_t Y1, pcb_coord_t X2, pcb_coord_t Y2, pcb_coord_t Thickness) +{ + pcb_line_t *line = Symbol->Line; + + /* realloc new memory if necessary and clear it */ + if (Symbol->LineN >= Symbol->LineMax) { + Symbol->LineMax += STEP_SYMBOLLINE; + line = (pcb_line_t *) realloc(line, Symbol->LineMax * sizeof(pcb_line_t)); + Symbol->Line = line; + memset(line + Symbol->LineN, 0, STEP_SYMBOLLINE * sizeof(pcb_line_t)); + } + + /* copy values */ + line = line + Symbol->LineN++; + line->Point1.X = X1; + line->Point1.Y = Y1; + line->Point2.X = X2; + line->Point2.Y = Y2; + line->Thickness = Thickness; + return line; +} + +pcb_poly_t *pcb_font_new_poly_in_sym(pcb_symbol_t *Symbol, int num_points) +{ + pcb_poly_t *p = calloc(sizeof(pcb_poly_t), 1); + if (num_points > 0) { + p->PointN = p->PointMax = num_points; + p->Points = malloc(sizeof(pcb_point_t) * num_points); + } + polylist_insert(&Symbol->polys, p); + return p; +} + +pcb_arc_t *pcb_font_new_arc_in_sym(pcb_symbol_t *Symbol, pcb_coord_t cx, pcb_coord_t cy, pcb_coord_t r, pcb_angle_t start, pcb_angle_t delta, pcb_coord_t thickness) +{ + pcb_arc_t *a = calloc(sizeof(pcb_arc_t), 1); + a->X = cx; + a->Y = cy; + a->Height = a->Width = r; + a->StartAngle = start; + a->Delta = delta; + a->Thickness = thickness; + arclist_insert(&Symbol->arcs, a); + return a; +} + + +static pcb_font_t *pcb_font_(pcb_board_t *pcb, pcb_font_id_t id, int fallback, int unlink) +{ + if (id <= 0) { + do_default:; + if (unlink) { + pcb_font_t *f = malloc(sizeof(pcb_font_t)); + memcpy(f, &pcb->fontkit.dflt, sizeof(pcb_font_t)); + memset(&pcb->fontkit.dflt, 0, sizeof(pcb_font_t)); + return f; + } + else + return &pcb->fontkit.dflt; + } + + if (pcb->fontkit.hash_inited) { + pcb_font_t *f = htip_get(&pcb->fontkit.fonts, id); + if (f != NULL) { + if (unlink) + htip_popentry(&pcb->fontkit.fonts, id); + return f; + } + } + + if (fallback) + goto do_default; + + return NULL; +} + +pcb_font_t *pcb_font(pcb_board_t *pcb, pcb_font_id_t id, int fallback) +{ + return pcb_font_(pcb, id, fallback, 0); +} + +pcb_font_t *pcb_font_unlink(pcb_board_t *pcb, pcb_font_id_t id) +{ + return pcb_font_(pcb, id, 0, 1); +} + + +static void hash_setup(pcb_fontkit_t *fk) +{ + if (fk->hash_inited) + return; + + htip_init(&fk->fonts, longhash, longkeyeq); + fk->hash_inited = 1; +} + +pcb_font_t *pcb_new_font(pcb_fontkit_t *fk, pcb_font_id_t id, const char *name) +{ + pcb_font_t *f; + + if (id == 0) + return NULL; + + if (id < 0) + id = fk->last_id + 1; + + hash_setup(fk); + + /* do not attempt to overwrite/reuse existing font of the same ID, rather report error */ + f = htip_get(&fk->fonts, id); + if (f != NULL) + return NULL; + + f = calloc(sizeof(pcb_font_t), 1); + htip_set(&fk->fonts, id, f); + if (name != NULL) + f->name = pcb_strdup(name); + f->id = id; + + if (f->id > fk->last_id) + fk->last_id = f->id; + + return f; +} + +void pcb_font_free(pcb_font_t *f) +{ + int i; + for (i = 0; i <= PCB_MAX_FONTPOSITION; i++) { + pcb_poly_t *p; + pcb_arc_t *a; + + free(f->Symbol[i].Line); + + for(p = polylist_first(&f->Symbol[i].polys); p != NULL; p = polylist_first(&f->Symbol[i].polys)) { + polylist_remove(p); + pcb_poly_free_fields(p); + free(p); + } + + for(a = arclist_first(&f->Symbol[i].arcs); a != NULL; a = arclist_first(&f->Symbol[i].arcs)) { + arclist_remove(a); + free(a); + } + + memset (&f->Symbol[i], 0, sizeof(f->Symbol[0])); + } + free(f->name); + f->name = NULL; + f->id = -1; +} + +void pcb_fontkit_free(pcb_fontkit_t *fk) +{ + pcb_font_free(&fk->dflt); + if (fk->hash_inited) { + htip_entry_t *e; + for (e = htip_first(&fk->fonts); e; e = htip_next(&fk->fonts, e)) + pcb_font_free(e->value); + htip_uninit(&fk->fonts); + fk->hash_inited = 0; + } + fk->last_id = 0; +} + +void pcb_fontkit_reset(pcb_fontkit_t *fk) +{ + if (fk->hash_inited) { + htip_entry_t *e; + for (e = htip_first(&fk->fonts); e; e = htip_first(&fk->fonts)) { + pcb_font_free(e->value); + htip_delentry(&fk->fonts, e); + } + } + fk->last_id = 0; +} + +static void update_last_id(pcb_fontkit_t *fk) +{ + pcb_font_id_t id; + for (id = fk->last_id; id > 0; id--) { + if (htip_has(&fk->fonts, id)) + break; + } + fk->last_id = id; +} + +int pcb_del_font(pcb_fontkit_t *fk, pcb_font_id_t id) +{ + htip_entry_t *e; + + if ((id == 0) || (!fk->hash_inited) || (htip_get(&fk->fonts, id) == NULL)) + return -1; + + e = htip_popentry(&fk->fonts, id); + pcb_font_free(e->value); + pcb_event(PCB_EVENT_FONT_CHANGED, "i", id); + if (id == fk->last_id) + update_last_id(fk); + return 0; +} + +static void copy_font(pcb_font_t *dst, pcb_font_t *src) +{ + int i; + + memcpy(dst, src, sizeof(pcb_font_t)); + for (i = 0; i <= PCB_MAX_FONTPOSITION; i++) { + pcb_poly_t *p_src; + pcb_arc_t *a_src; + + if (src->Symbol[i].Line) { + dst->Symbol[i].Line = malloc(sizeof(pcb_line_t) * src->Symbol[i].LineMax); + memcpy(dst->Symbol[i].Line, src->Symbol[i].Line, sizeof(pcb_line_t) * src->Symbol[i].LineN); + } + + memset(&dst->Symbol[i].polys, 0, sizeof(polylist_t)); + for(p_src = polylist_first(&src->Symbol[i].polys); p_src != NULL; p_src = polylist_next(p_src)) { + pcb_poly_t *p_dst = pcb_font_new_poly_in_sym(&dst->Symbol[i], p_src->PointN); + memcpy(p_dst->Points, p_src->Points, p_src->PointN * sizeof(pcb_point_t)); + } + + memset(&dst->Symbol[i].arcs, 0, sizeof(arclist_t)); + for(a_src = arclist_first(&src->Symbol[i].arcs); a_src != NULL; a_src = arclist_next(a_src)) { + pcb_font_new_arc_in_sym(&dst->Symbol[i], a_src->X, a_src->Y, a_src->Width, + a_src->StartAngle, a_src->Delta, a_src->Thickness); + } + } + if (src->name != NULL) + dst->name = pcb_strdup(src->name); +} + +int pcb_move_font(pcb_fontkit_t *fk, pcb_font_id_t src, pcb_font_id_t dst) +{ + htip_entry_t *e; + pcb_font_t *src_font; + + if ((!fk->hash_inited) || (htip_get(&fk->fonts, src) == NULL)) + return -1; + + pcb_del_font(fk, dst); + + e = htip_popentry(&fk->fonts, src); + src_font = e->value; + if (dst == 0) { + pcb_font_free (&fk->dflt); + copy_font (&fk->dflt, src_font); + pcb_font_free (src_font); + fk->dflt.id = 0; + } else { + htip_set(&fk->fonts, dst, src_font); + src_font->id = dst; + } + if (src == fk->last_id) + update_last_id (fk); + fk->last_id = MAX(fk->last_id, dst); + pcb_event(PCB_EVENT_FONT_CHANGED, "i", src); + pcb_event(PCB_EVENT_FONT_CHANGED, "i", dst); + + return 0; +} + Index: tags/2.1.2/src/font.h =================================================================== --- tags/2.1.2/src/font.h (nonexistent) +++ tags/2.1.2/src/font.h (revision 24813) @@ -0,0 +1,98 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * pcb-rnd Copyright (C) 2017 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +#ifndef PCB_FONT_H +#define PCB_FONT_H + +#include +#include "global_typedefs.h" +#include "obj_poly.h" +#include "obj_poly_list.h" +#include "obj_arc.h" +#include "obj_arc_list.h" +#include "box.h" + +/* --------------------------------------------------------------------------- + * symbol and font related stuff + */ +typedef struct symbol_s { /* a single symbol */ + pcb_line_t *Line; + pcb_bool Valid; + pcb_cardinal_t LineN; /* number of lines */ + pcb_cardinal_t LineMax; /* lines allocated */ + pcb_coord_t Width, Height, Delta; /* size of cell, distance to next symbol */ + polylist_t polys; /* simple (non-clipped) polygons */ + arclist_t arcs; +} pcb_symbol_t; + +typedef long int pcb_font_id_t; /* a font is referenced by a pcb_board_t:pcb_font_id_t pair */ + +struct pcb_font_s { /* complete set of symbols */ + pcb_coord_t MaxHeight, MaxWidth; /* maximum cell width and height */ + pcb_box_t DefaultSymbol; /* the default symbol is a filled box */ + pcb_symbol_t Symbol[PCB_MAX_FONTPOSITION + 1]; + char *name; + pcb_font_id_t id; +}; + +struct pcb_fontkit_s { /* a set of unrelated fonts */ + pcb_font_t dflt; /* default, fallback font, also the sysfont */ + htip_t fonts; + pcb_bool valid, hash_inited; + pcb_font_id_t last_id; /* highest font id ever seen in this kit */ +}; + +/* Look up font. If not found: return NULL (fallback=0), or return the + default font (fallback=1) */ +pcb_font_t *pcb_font(pcb_board_t *pcb, pcb_font_id_t id, int fallback); + +void pcb_font_create_default(pcb_board_t *pcb); +void pcb_font_set_info(pcb_font_t *Ptr); + +pcb_line_t *pcb_font_new_line_in_sym(pcb_symbol_t *Symbol, pcb_coord_t X1, pcb_coord_t Y1, pcb_coord_t X2, pcb_coord_t Y2, pcb_coord_t Thickness); +pcb_arc_t *pcb_font_new_arc_in_sym(pcb_symbol_t *Symbol, pcb_coord_t cx, pcb_coord_t cy, pcb_coord_t r, pcb_angle_t start, pcb_angle_t delta, pcb_coord_t thickness); +pcb_poly_t *pcb_font_new_poly_in_sym(pcb_symbol_t *Symbol, int num_points); + +void pcb_font_free(pcb_font_t *f); + +/*** font kit handling ***/ +void pcb_fontkit_free(pcb_fontkit_t *fk); +pcb_font_t *pcb_new_font(pcb_fontkit_t *fk, pcb_font_id_t id, const char *name); +int pcb_del_font(pcb_fontkit_t *fk, pcb_font_id_t id); +int pcb_move_font(pcb_fontkit_t *fk, pcb_font_id_t src, pcb_font_id_t dst); + +/* Reset the fontkit so that only the default font is kept and all extra fonts are purged */ +void pcb_fontkit_reset(pcb_fontkit_t *fk); + +/* Unlink the font from pcb, but do not free anything but return the font */ +pcb_font_t *pcb_font_unlink(pcb_board_t *pcb, pcb_font_id_t id); + + +#endif + Index: tags/2.1.2/src/font_act.c =================================================================== --- tags/2.1.2/src/font_act.c (nonexistent) +++ tags/2.1.2/src/font_act.c (revision 24813) @@ -0,0 +1,166 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2017 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ +#include "config.h" +#include +#include "board.h" +#include "actions.h" +#include "error.h" +#include "font.h" +#include "conf_core.h" +#include "plug_io.h" +#include "event.h" + + +static const char pcb_acts_load_font_from[] = "LoadFontFrom([file, id])"; +static const char pcb_acth_load_font_from[] = "Load PCB font from a file"; + +fgw_error_t pcb_act_load_font_from(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + const char *fname = NULL, *sid = NULL; + static char *default_file = NULL; + pcb_font_id_t fid, dst_fid = -1; + pcb_font_t *fnt; + int r; + + PCB_ACT_MAY_CONVARG(1, FGW_STR, load_font_from, fname = argv[1].val.str); + PCB_ACT_MAY_CONVARG(2, FGW_STR, load_font_from, sid = argv[2].val.str); + + if (sid != NULL) { + char *end; + fid = strtol(sid, &end, 10); + if (*end != '\0') { + pcb_message(PCB_MSG_ERROR, "LoadFontFrom(): when second argument is present, it must be an integer\n"); + return 1; + } + if (pcb_font(PCB, fid, 0) != NULL) { /* font already exists */ + dst_fid = fid; + fid = -1; /* allocate a new id, which will be later moved to dst_fid */ + } + } + else + fid = -1; /* auto-allocate a new ID */ + + if (!fname || !*fname) { + fname = pcb_gui->fileselect("Load PCB font file...", + "Picks a PCB font file to load.\n", + default_file, ".font", NULL, "pcbfont", PCB_HID_FSD_READ, NULL); + if (fname == NULL) + return 0; /* cancel */ + if (default_file != NULL) { + free(default_file); + default_file = NULL; + } + } + + fnt = pcb_new_font(&PCB->fontkit, fid, NULL); + if (fnt == NULL) { + pcb_message(PCB_MSG_ERROR, "LoadFontFrom(): unable to allocate font\n"); + return 1; + } + + r = pcb_parse_font(fnt, fname); + pcb_event(PCB_EVENT_FONT_CHANGED, "i", fnt->id); + if (r != 0) { + pcb_message(PCB_MSG_ERROR, "LoadFontFrom(): failed to load font from %s\n", fname); + pcb_del_font(&PCB->fontkit, fnt->id); + return 1; + } + + if (dst_fid != -1) { + pcb_move_font(&PCB->fontkit, fnt->id, dst_fid); + } + + fid = dst_fid == 0 ? 0 : fnt->id; + pcb_message(PCB_MSG_INFO, "LoadFontFrom(): new font (ID %d) successfully loaded from file %s\n", fid, fname); + PCB_ACT_IRES(0); + return 0; +} + + +static const char pcb_acts_save_font_to[] = "SaveFontTo([file, id])"; +static const char pcb_acth_save_font_to[] = "Save PCB font to a file"; + +fgw_error_t pcb_act_save_font_to(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + const char *fname = NULL, *sid = NULL; + static char *default_file = NULL; + pcb_font_id_t fid; + pcb_font_t *fnt; + int r; + + PCB_ACT_MAY_CONVARG(1, FGW_STR, load_font_from, fname = argv[1].val.str); + PCB_ACT_MAY_CONVARG(2, FGW_STR, load_font_from, sid = argv[1].val.str); + + if (sid != NULL) { + char *end; + fid = strtol(sid, &end, 10); + if (*end != '\0') { + pcb_message(PCB_MSG_ERROR, "SaveFontTo(): when second argument is present, it must be an integer\n"); + return 1; + } + if (pcb_font(PCB, fid, 0) == NULL) { + pcb_message(PCB_MSG_ERROR, "SaveFontTo(): can not fetch font ID %d\n", fid); + return 1; + } + } + else + fid = conf_core.design.text_font_id; + + fnt = pcb_font(PCB, fid, 0); + if (fnt == NULL) { + pcb_message(PCB_MSG_ERROR, "SaveFontTo(): failed to fetch font %d\n", fid); + return 1; + } + + if (!fname || !*fname) { + fname = pcb_gui->fileselect("Save PCB font file...", + "Picks a PCB font file to save.\n", + default_file, ".font", NULL, "pcbfont", PCB_HID_FSD_MAY_NOT_EXIST, NULL); + if (fname == NULL) + PCB_ACT_FAIL(save_font_to); + if (default_file != NULL) { + free(default_file); + default_file = NULL; + } + } + + r = pcb_write_font(fnt, fname, "lihata"); + if (r != 0) { + pcb_message(PCB_MSG_ERROR, "SaveFontTo(): failed to save font to %s\n", fname); + return 1; + } + + PCB_ACT_IRES(0); + return 0; +} + + +pcb_action_t font_action_list[] = { + {"LoadFontFrom", pcb_act_load_font_from, pcb_acth_load_font_from, pcb_acts_load_font_from}, + {"SaveFontTo", pcb_act_save_font_to, pcb_acth_save_font_to, pcb_acts_save_font_to} +}; + +PCB_REGISTER_ACTIONS(font_action_list, NULL) Index: tags/2.1.2/src/font_internal.c =================================================================== --- tags/2.1.2/src/font_internal.c (nonexistent) +++ tags/2.1.2/src/font_internal.c (revision 24813) @@ -0,0 +1,818 @@ +/* This file is autogenerated by font2c.sh - DO NOT EDIT */ + +/* Internal copy of the default font; used when no font file is found */ + +static embf_line_t embf_line_32[] = { + {0,0,0,0} +}; +static embf_line_t embf_line_33[] = { /* ! */ + {0, 35, 0, 40, 8}, + {0, 0, 0, 25, 8} +}; +static embf_line_t embf_line_34[] = { /* " */ + {0, 0, 0, 10, 8}, + {10, 0, 10, 10, 8} +}; +static embf_line_t embf_line_35[] = { /* # */ + {0, 25, 20, 25, 8}, + {0, 15, 20, 15, 8}, + {15, 10, 15, 30, 8}, + {5, 10, 5, 30, 8} +}; +static embf_line_t embf_line_36[] = { /* $ */ + {15, 5, 20, 10, 8}, + {5, 5, 15, 5, 8}, + {0, 10, 5, 5, 8}, + {0, 10, 0, 15, 8}, + {0, 15, 5, 20, 8}, + {5, 20, 15, 20, 8}, + {15, 20, 20, 25, 8}, + {20, 25, 20, 30, 8}, + {15, 35, 20, 30, 8}, + {5, 35, 15, 35, 8}, + {0, 30, 5, 35, 8}, + {10, 0, 10, 40, 8} +}; +static embf_line_t embf_line_37[] = { /* % */ + {0, 5, 0, 10, 8}, + {0, 5, 5, 0, 8}, + {5, 0, 10, 0, 8}, + {10, 0, 15, 5, 8}, + {15, 5, 15, 10, 8}, + {10, 15, 15, 10, 8}, + {5, 15, 10, 15, 8}, + {0, 10, 5, 15, 8}, + {0, 40, 40, 0, 8}, + {35, 40, 40, 35, 8}, + {40, 30, 40, 35, 8}, + {35, 25, 40, 30, 8}, + {30, 25, 35, 25, 8}, + {25, 30, 30, 25, 8}, + {25, 30, 25, 35, 8}, + {25, 35, 30, 40, 8}, + {30, 40, 35, 40, 8} +}; +static embf_line_t embf_line_38[] = { /* & */ + {0, 35, 5, 40, 8}, + {0, 5, 0, 15, 8}, + {0, 5, 5, 0, 8}, + {0, 25, 15, 10, 8}, + {5, 40, 10, 40, 8}, + {10, 40, 20, 30, 8}, + {0, 15, 25, 40, 8}, + {5, 0, 10, 0, 8}, + {10, 0, 15, 5, 8}, + {15, 5, 15, 10, 8}, + {0, 25, 0, 35, 8} +}; +static embf_line_t embf_line_39[] = { /* ' */ + {0, 10, 10, 0, 8} +}; +static embf_line_t embf_line_40[] = { + {0, 35, 5, 40, 8}, + {0, 5, 5, 0, 8}, + {0, 5, 0, 35, 8} +}; +static embf_line_t embf_line_41[] = { + {0, 0, 5, 5, 8}, + {5, 5, 5, 35, 8}, + {0, 40, 5, 35, 8} +}; +static embf_line_t embf_line_42[] = { /* * */ + {0, 10, 20, 30, 8}, + {0, 30, 20, 10, 8}, + {0, 20, 20, 20, 8}, + {10, 10, 10, 30, 8} +}; +static embf_line_t embf_line_43[] = { /* + */ + {0, 20, 20, 20, 8}, + {10, 10, 10, 30, 8} +}; +static embf_line_t embf_line_44[] = { /* , */ + {0, 50, 10, 40, 8} +}; +static embf_line_t embf_line_45[] = { /* - */ + {0, 20, 20, 20, 8} +}; +static embf_line_t embf_line_46[] = { /* . */ + {0, 40, 5, 40, 8} +}; +static embf_line_t embf_line_47[] = { /* / */ + {0, 35, 30, 5, 8} +}; +static embf_line_t embf_line_48[] = { /* 0 */ + {0, 35, 5, 40, 8}, + {0, 5, 0, 35, 8}, + {0, 5, 5, 0, 8}, + {5, 0, 15, 0, 8}, + {15, 0, 20, 5, 8}, + {20, 5, 20, 35, 8}, + {15, 40, 20, 35, 8}, + {5, 40, 15, 40, 8}, + {0, 30, 20, 10, 8} +}; +static embf_line_t embf_line_49[] = { /* 1 */ + {0, 8, 8, 0, 8}, + {8, 0, 8, 40, 8}, + {0, 40, 15, 40, 8} +}; +static embf_line_t embf_line_50[] = { /* 2 */ + {0, 5, 5, 0, 8}, + {5, 0, 20, 0, 8}, + {20, 0, 25, 5, 8}, + {25, 5, 25, 15, 8}, + {0, 40, 25, 15, 8}, + {0, 40, 25, 40, 8} +}; +static embf_line_t embf_line_51[] = { /* 3 */ + {0, 5, 5, 0, 8}, + {5, 0, 15, 0, 8}, + {15, 0, 20, 5, 8}, + {15, 40, 20, 35, 8}, + {5, 40, 15, 40, 8}, + {0, 35, 5, 40, 8}, + {5, 18, 15, 18, 8}, + {20, 5, 20, 13, 8}, + {20, 23, 20, 35, 8}, + {20, 23, 15, 18, 8}, + {20, 13, 15, 18, 8} +}; +static embf_line_t embf_line_52[] = { /* 4 */ + {0, 25, 20, 0, 8}, + {0, 25, 25, 25, 8}, + {20, 0, 20, 40, 8} +}; +static embf_line_t embf_line_53[] = { /* 5 */ + {0, 0, 20, 0, 8}, + {0, 0, 0, 20, 8}, + {0, 20, 5, 15, 8}, + {5, 15, 15, 15, 8}, + {15, 15, 20, 20, 8}, + {20, 20, 20, 35, 8}, + {15, 40, 20, 35, 8}, + {5, 40, 15, 40, 8}, + {0, 35, 5, 40, 8} +}; +static embf_line_t embf_line_54[] = { /* 6 */ + {15, 0, 20, 5, 8}, + {5, 0, 15, 0, 8}, + {0, 5, 5, 0, 8}, + {0, 5, 0, 35, 8}, + {0, 35, 5, 40, 8}, + {15, 18, 20, 23, 8}, + {0, 18, 15, 18, 8}, + {5, 40, 15, 40, 8}, + {15, 40, 20, 35, 8}, + {20, 23, 20, 35, 8} +}; +static embf_line_t embf_line_55[] = { /* 7 */ + {5, 40, 25, 0, 8}, + {0, 0, 25, 0, 8} +}; +static embf_line_t embf_line_56[] = { /* 8 */ + {0, 35, 5, 40, 8}, + {0, 27, 0, 35, 8}, + {0, 27, 7, 20, 8}, + {7, 20, 13, 20, 8}, + {13, 20, 20, 27, 8}, + {20, 27, 20, 35, 8}, + {15, 40, 20, 35, 8}, + {5, 40, 15, 40, 8}, + {0, 13, 7, 20, 8}, + {0, 5, 0, 13, 8}, + {0, 5, 5, 0, 8}, + {5, 0, 15, 0, 8}, + {15, 0, 20, 5, 8}, + {20, 5, 20, 13, 8}, + {13, 20, 20, 13, 8} +}; +static embf_line_t embf_line_57[] = { /* 9 */ + {5, 40, 20, 20, 8}, + {20, 5, 20, 20, 8}, + {15, 0, 20, 5, 8}, + {5, 0, 15, 0, 8}, + {0, 5, 5, 0, 8}, + {0, 5, 0, 15, 8}, + {0, 15, 5, 20, 8}, + {5, 20, 20, 20, 8} +}; +static embf_line_t embf_line_58[] = { /* : */ + {0, 15, 5, 15, 8}, + {0, 25, 5, 25, 8} +}; +static embf_line_t embf_line_59[] = { /* ; */ + {0, 40, 10, 30, 8}, + {10, 15, 10, 20, 8} +}; +static embf_line_t embf_line_60[] = { /* < */ + {0, 20, 10, 10, 8}, + {0, 20, 10, 30, 8} +}; +static embf_line_t embf_line_61[] = { /* = */ + {0, 15, 20, 15, 8}, + {0, 25, 20, 25, 8} +}; +static embf_line_t embf_line_62[] = { /* > */ + {0, 10, 10, 20, 8}, + {0, 30, 10, 20, 8} +}; +static embf_line_t embf_line_63[] = { /* ? */ + {10, 20, 10, 25, 8}, + {10, 35, 10, 40, 8}, + {0, 5, 0, 10, 8}, + {0, 5, 5, 0, 8}, + {5, 0, 15, 0, 8}, + {15, 0, 20, 5, 8}, + {20, 5, 20, 10, 8}, + {10, 20, 20, 10, 8} +}; +static embf_line_t embf_line_64[] = { /* @ */ + {0, 0, 0, 30, 8}, + {0, 30, 10, 40, 8}, + {10, 40, 40, 40, 8}, + {50, 25, 50, 0, 8}, + {50, 0, 40, -10, 8}, + {40, -10, 10, -10, 8}, + {10, -10, 0, 0, 8}, + {15, 10, 15, 20, 8}, + {15, 20, 20, 25, 8}, + {20, 25, 30, 25, 8}, + {30, 25, 35, 20, 8}, + {35, 20, 40, 25, 8}, + {35, 20, 35, 5, 8}, + {35, 10, 30, 5, 8}, + {20, 5, 30, 5, 8}, + {20, 5, 15, 10, 8}, + {40, 25, 50, 25, 8} +}; +static embf_line_t embf_line_65[] = { /* A */ + {0, 10, 0, 40, 8}, + {0, 10, 7, 0, 8}, + {7, 0, 18, 0, 8}, + {18, 0, 25, 10, 8}, + {25, 10, 25, 40, 8}, + {0, 20, 25, 20, 8} +}; +static embf_line_t embf_line_66[] = { /* B */ + {0, 40, 20, 40, 8}, + {20, 40, 25, 35, 8}, + {25, 23, 25, 35, 8}, + {20, 18, 25, 23, 8}, + {5, 18, 20, 18, 8}, + {5, 0, 5, 40, 8}, + {0, 0, 20, 0, 8}, + {20, 0, 25, 5, 8}, + {25, 5, 25, 13, 8}, + {20, 18, 25, 13, 8} +}; +static embf_line_t embf_line_67[] = { /* C */ + {7, 40, 20, 40, 8}, + {0, 33, 7, 40, 8}, + {0, 7, 0, 33, 8}, + {0, 7, 7, 0, 8}, + {7, 0, 20, 0, 8} +}; +static embf_line_t embf_line_68[] = { /* D */ + {5, 0, 5, 40, 8}, + {18, 0, 25, 7, 8}, + {25, 7, 25, 33, 8}, + {18, 40, 25, 33, 8}, + {0, 40, 18, 40, 8}, + {0, 0, 18, 0, 8} +}; +static embf_line_t embf_line_69[] = { /* E */ + {0, 18, 15, 18, 8}, + {0, 40, 20, 40, 8}, + {0, 0, 0, 40, 8}, + {0, 0, 20, 0, 8} +}; +static embf_line_t embf_line_70[] = { /* F */ + {0, 0, 0, 40, 8}, + {0, 0, 20, 0, 8}, + {0, 18, 15, 18, 8} +}; +static embf_line_t embf_line_71[] = { /* G */ + {20, 0, 25, 5, 8}, + {5, 0, 20, 0, 8}, + {0, 5, 5, 0, 8}, + {0, 5, 0, 35, 8}, + {0, 35, 5, 40, 8}, + {5, 40, 20, 40, 8}, + {20, 40, 25, 35, 8}, + {25, 25, 25, 35, 8}, + {20, 20, 25, 25, 8}, + {10, 20, 20, 20, 8} +}; +static embf_line_t embf_line_72[] = { /* H */ + {0, 0, 0, 40, 8}, + {25, 0, 25, 40, 8}, + {0, 20, 25, 20, 8} +}; +static embf_line_t embf_line_73[] = { /* I */ + {0, 0, 10, 0, 8}, + {5, 0, 5, 40, 8}, + {0, 40, 10, 40, 8} +}; +static embf_line_t embf_line_74[] = { /* J */ + {7, 0, 15, 0, 8}, + {15, 0, 15, 35, 8}, + {10, 40, 15, 35, 8}, + {5, 40, 10, 40, 8}, + {0, 35, 5, 40, 8}, + {0, 35, 0, 30, 8} +}; +static embf_line_t embf_line_75[] = { /* K */ + {0, 0, 0, 40, 8}, + {0, 20, 20, 0, 8}, + {0, 20, 20, 40, 8} +}; +static embf_line_t embf_line_76[] = { /* L */ + {0, 0, 0, 40, 8}, + {0, 40, 20, 40, 8} +}; +static embf_line_t embf_line_77[] = { /* M */ + {0, 0, 0, 40, 8}, + {0, 0, 15, 20, 8}, + {15, 20, 30, 0, 8}, + {30, 0, 30, 40, 8} +}; +static embf_line_t embf_line_78[] = { /* N */ + {0, 0, 0, 40, 8}, + {0, 0, 25, 40, 8}, + {25, 0, 25, 40, 8} +}; +static embf_line_t embf_line_79[] = { /* O */ + {0, 5, 0, 35, 8}, + {0, 5, 5, 0, 8}, + {5, 0, 15, 0, 8}, + {15, 0, 20, 5, 8}, + {20, 5, 20, 35, 8}, + {15, 40, 20, 35, 8}, + {5, 40, 15, 40, 8}, + {0, 35, 5, 40, 8} +}; +static embf_line_t embf_line_80[] = { /* P */ + {5, 0, 5, 40, 8}, + {0, 0, 20, 0, 8}, + {20, 0, 25, 5, 8}, + {25, 5, 25, 15, 8}, + {20, 20, 25, 15, 8}, + {5, 20, 20, 20, 8} +}; +static embf_line_t embf_line_81[] = { /* Q */ + {0, 5, 0, 35, 8}, + {0, 5, 5, 0, 8}, + {5, 0, 15, 0, 8}, + {15, 0, 20, 5, 8}, + {20, 5, 20, 30, 8}, + {10, 40, 20, 30, 8}, + {5, 40, 10, 40, 8}, + {0, 35, 5, 40, 8}, + {10, 25, 20, 40, 8} +}; +static embf_line_t embf_line_82[] = { /* R */ + {0, 0, 20, 0, 8}, + {20, 0, 25, 5, 8}, + {25, 5, 25, 15, 8}, + {20, 20, 25, 15, 8}, + {5, 20, 20, 20, 8}, + {5, 0, 5, 40, 8}, + {13, 20, 25, 40, 8} +}; +static embf_line_t embf_line_83[] = { /* S */ + {20, 0, 25, 5, 8}, + {5, 0, 20, 0, 8}, + {0, 5, 5, 0, 8}, + {0, 5, 0, 15, 8}, + {0, 15, 5, 20, 8}, + {5, 20, 20, 20, 8}, + {20, 20, 25, 25, 8}, + {25, 25, 25, 35, 8}, + {20, 40, 25, 35, 8}, + {5, 40, 20, 40, 8}, + {0, 35, 5, 40, 8} +}; +static embf_line_t embf_line_84[] = { /* T */ + {0, 0, 20, 0, 8}, + {10, 0, 10, 40, 8} +}; +static embf_line_t embf_line_85[] = { /* U */ + {0, 0, 0, 35, 8}, + {0, 35, 5, 40, 8}, + {5, 40, 15, 40, 8}, + {15, 40, 20, 35, 8}, + {20, 0, 20, 35, 8} +}; +static embf_line_t embf_line_86[] = { /* V */ + {0, 0, 10, 40, 8}, + {10, 40, 20, 0, 8} +}; +static embf_line_t embf_line_87[] = { /* W */ + {0, 0, 0, 20, 8}, + {0, 20, 5, 40, 8}, + {5, 40, 15, 20, 8}, + {15, 20, 25, 40, 8}, + {25, 40, 30, 20, 8}, + {30, 20, 30, 0, 8} +}; +static embf_line_t embf_line_88[] = { /* X */ + {0, 40, 25, 0, 8}, + {0, 0, 25, 40, 8} +}; +static embf_line_t embf_line_89[] = { /* Y */ + {0, 0, 10, 20, 8}, + {10, 20, 20, 0, 8}, + {10, 20, 10, 40, 8} +}; +static embf_line_t embf_line_90[] = { /* Z */ + {0, 0, 25, 0, 8}, + {0, 40, 25, 0, 8}, + {0, 40, 25, 40, 8} +}; +static embf_line_t embf_line_91[] = { /* [ */ + {0, 0, 5, 0, 8}, + {0, 0, 0, 40, 8}, + {0, 40, 5, 40, 8} +}; +static embf_line_t embf_line_92[] = { /* \ */ + {0, 5, 30, 35, 8} +}; +static embf_line_t embf_line_93[] = { /* ] */ + {0, 0, 5, 0, 8}, + {5, 0, 5, 40, 8}, + {0, 40, 5, 40, 8} +}; +static embf_line_t embf_line_94[] = { /* ^ */ + {0, 5, 5, 0, 8}, + {5, 0, 10, 5, 8} +}; +static embf_line_t embf_line_95[] = { /* _ */ + {0, 40, 20, 40, 8} +}; +static embf_line_t embf_line_97[] = { /* a */ + {15, 20, 20, 25, 8}, + {5, 20, 15, 20, 8}, + {0, 25, 5, 20, 8}, + {0, 25, 0, 35, 8}, + {0, 35, 5, 40, 8}, + {20, 20, 20, 35, 8}, + {20, 35, 25, 40, 8}, + {5, 40, 15, 40, 8}, + {15, 40, 20, 35, 8} +}; +static embf_line_t embf_line_98[] = { /* b */ + {0, 0, 0, 40, 8}, + {0, 35, 5, 40, 8}, + {5, 40, 15, 40, 8}, + {15, 40, 20, 35, 8}, + {20, 25, 20, 35, 8}, + {15, 20, 20, 25, 8}, + {5, 20, 15, 20, 8}, + {0, 25, 5, 20, 8} +}; +static embf_line_t embf_line_99[] = { /* c */ + {5, 20, 20, 20, 8}, + {0, 25, 5, 20, 8}, + {0, 25, 0, 35, 8}, + {0, 35, 5, 40, 8}, + {5, 40, 20, 40, 8} +}; +static embf_line_t embf_line_100[] = { /* d */ + {20, 0, 20, 40, 8}, + {15, 40, 20, 35, 8}, + {5, 40, 15, 40, 8}, + {0, 35, 5, 40, 8}, + {0, 25, 0, 35, 8}, + {0, 25, 5, 20, 8}, + {5, 20, 15, 20, 8}, + {15, 20, 20, 25, 8} +}; +static embf_line_t embf_line_101[] = { /* e */ + {5, 40, 20, 40, 8}, + {0, 35, 5, 40, 8}, + {0, 25, 0, 35, 8}, + {0, 25, 5, 20, 8}, + {5, 20, 15, 20, 8}, + {15, 20, 20, 25, 8}, + {0, 30, 20, 30, 8}, + {20, 30, 20, 25, 8} +}; +static embf_line_t embf_line_102[] = { /* f */ + {5, 5, 5, 40, 8}, + {5, 5, 10, 0, 8}, + {10, 0, 15, 0, 8}, + {0, 20, 10, 20, 8} +}; +static embf_line_t embf_line_103[] = { /* g */ + {15, 20, 20, 25, 8}, + {5, 20, 15, 20, 8}, + {0, 25, 5, 20, 8}, + {0, 25, 0, 35, 8}, + {0, 35, 5, 40, 8}, + {5, 40, 15, 40, 8}, + {15, 40, 20, 35, 8}, + {0, 50, 5, 55, 8}, + {5, 55, 15, 55, 8}, + {15, 55, 20, 50, 8}, + {20, 20, 20, 50, 8} +}; +static embf_line_t embf_line_104[] = { /* h */ + {0, 0, 0, 40, 8}, + {0, 25, 5, 20, 8}, + {5, 20, 15, 20, 8}, + {15, 20, 20, 25, 8}, + {20, 25, 20, 40, 8} +}; +static embf_line_t embf_line_105[] = { /* i */ + {0, 10, 0, 11, 10}, + {0, 25, 0, 40, 8} +}; +static embf_line_t embf_line_106[] = { /* j */ + {5, 10, 5, 11, 10}, + {5, 25, 5, 50, 8}, + {0, 55, 5, 50, 8} +}; +static embf_line_t embf_line_107[] = { /* k */ + {0, 0, 0, 40, 8}, + {0, 25, 15, 40, 8}, + {0, 25, 10, 15, 8} +}; +static embf_line_t embf_line_108[] = { /* l */ + {0, 0, 0, 35, 8}, + {0, 35, 5, 40, 8} +}; +static embf_line_t embf_line_109[] = { /* m */ + {5, 25, 5, 40, 8}, + {5, 25, 10, 20, 8}, + {10, 20, 15, 20, 8}, + {15, 20, 20, 25, 8}, + {20, 25, 20, 40, 8}, + {20, 25, 25, 20, 8}, + {25, 20, 30, 20, 8}, + {30, 20, 35, 25, 8}, + {35, 25, 35, 40, 8}, + {0, 20, 5, 25, 8} +}; +static embf_line_t embf_line_110[] = { /* n */ + {5, 25, 5, 40, 8}, + {5, 25, 10, 20, 8}, + {10, 20, 15, 20, 8}, + {15, 20, 20, 25, 8}, + {20, 25, 20, 40, 8}, + {0, 20, 5, 25, 8} +}; +static embf_line_t embf_line_111[] = { /* o */ + {0, 25, 0, 35, 8}, + {0, 25, 5, 20, 8}, + {5, 20, 15, 20, 8}, + {15, 20, 20, 25, 8}, + {20, 25, 20, 35, 8}, + {15, 40, 20, 35, 8}, + {5, 40, 15, 40, 8}, + {0, 35, 5, 40, 8} +}; +static embf_line_t embf_line_112[] = { /* p */ + {5, 25, 5, 55, 8}, + {0, 20, 5, 25, 8}, + {5, 25, 10, 20, 8}, + {10, 20, 20, 20, 8}, + {20, 20, 25, 25, 8}, + {25, 25, 25, 35, 8}, + {20, 40, 25, 35, 8}, + {10, 40, 20, 40, 8}, + {5, 35, 10, 40, 8} +}; +static embf_line_t embf_line_113[] = { /* q */ + {20, 25, 20, 55, 8}, + {15, 20, 20, 25, 8}, + {5, 20, 15, 20, 8}, + {0, 25, 5, 20, 8}, + {0, 25, 0, 35, 8}, + {0, 35, 5, 40, 8}, + {5, 40, 15, 40, 8}, + {15, 40, 20, 35, 8} +}; +static embf_line_t embf_line_114[] = { /* r */ + {5, 25, 5, 40, 8}, + {5, 25, 10, 20, 8}, + {10, 20, 20, 20, 8}, + {0, 20, 5, 25, 8} +}; +static embf_line_t embf_line_115[] = { /* s */ + {5, 40, 20, 40, 8}, + {20, 40, 25, 35, 8}, + {20, 30, 25, 35, 8}, + {5, 30, 20, 30, 8}, + {0, 25, 5, 30, 8}, + {0, 25, 5, 20, 8}, + {5, 20, 20, 20, 8}, + {20, 20, 25, 25, 8}, + {0, 35, 5, 40, 8} +}; +static embf_line_t embf_line_116[] = { /* t */ + {5, 0, 5, 35, 8}, + {5, 35, 10, 40, 8}, + {0, 15, 10, 15, 8} +}; +static embf_line_t embf_line_117[] = { /* u */ + {0, 20, 0, 35, 8}, + {0, 35, 5, 40, 8}, + {5, 40, 15, 40, 8}, + {15, 40, 20, 35, 8}, + {20, 20, 20, 35, 8} +}; +static embf_line_t embf_line_118[] = { /* v */ + {0, 20, 10, 40, 8}, + {20, 20, 10, 40, 8} +}; +static embf_line_t embf_line_119[] = { /* w */ + {0, 20, 0, 35, 8}, + {0, 35, 5, 40, 8}, + {5, 40, 10, 40, 8}, + {10, 40, 15, 35, 8}, + {15, 20, 15, 35, 8}, + {15, 35, 20, 40, 8}, + {20, 40, 25, 40, 8}, + {25, 40, 30, 35, 8}, + {30, 20, 30, 35, 8} +}; +static embf_line_t embf_line_120[] = { /* x */ + {0, 20, 20, 40, 8}, + {0, 40, 20, 20, 8} +}; +static embf_line_t embf_line_121[] = { /* y */ + {0, 20, 0, 35, 8}, + {0, 35, 5, 40, 8}, + {20, 20, 20, 50, 8}, + {15, 55, 20, 50, 8}, + {5, 55, 15, 55, 8}, + {0, 50, 5, 55, 8}, + {5, 40, 15, 40, 8}, + {15, 40, 20, 35, 8} +}; +static embf_line_t embf_line_122[] = { /* z */ + {0, 20, 20, 20, 8}, + {0, 40, 20, 20, 8}, + {0, 40, 20, 40, 8} +}; +static embf_line_t embf_line_123[] = { + {5, 5, 10, 0, 8}, + {5, 5, 5, 15, 8}, + {0, 20, 5, 15, 8}, + {0, 20, 5, 25, 8}, + {5, 25, 5, 35, 8}, + {5, 35, 10, 40, 8} +}; +static embf_line_t embf_line_124[] = { /* | */ + {0, 0, 0, 40, 8} +}; +static embf_line_t embf_line_125[] = { + {0, 0, 5, 5, 8}, + {5, 5, 5, 15, 8}, + {5, 15, 10, 20, 8}, + {5, 25, 10, 20, 8}, + {5, 25, 5, 35, 8}, + {0, 40, 5, 35, 8} +}; +static embf_line_t embf_line_126[] = { /* ~ */ + {0, 25, 5, 20, 8}, + {5, 20, 10, 20, 8}, + {10, 20, 15, 25, 8}, + {15, 25, 20, 25, 8}, + {20, 25, 25, 20, 8} +}; +/***************************************************************/ +static int embf_minx = 0; +static int embf_miny = -10; +static int embf_maxx = 50; +static int embf_maxy = 55; +static embf_font_t embf_font[] = { + {0, NULL, 0}, + {0, NULL, 0}, + {0, NULL, 0}, + {0, NULL, 0}, + {0, NULL, 0}, + {0, NULL, 0}, + {0, NULL, 0}, + {0, NULL, 0}, + {0, NULL, 0}, + {0, NULL, 0}, + {0, NULL, 0}, + {0, NULL, 0}, + {0, NULL, 0}, + {0, NULL, 0}, + {0, NULL, 0}, + {0, NULL, 0}, + {0, NULL, 0}, + {0, NULL, 0}, + {0, NULL, 0}, + {0, NULL, 0}, + {0, NULL, 0}, + {0, NULL, 0}, + {0, NULL, 0}, + {0, NULL, 0}, + {0, NULL, 0}, + {0, NULL, 0}, + {0, NULL, 0}, + {0, NULL, 0}, + {0, NULL, 0}, + {0, NULL, 0}, + {0, NULL, 0}, + {0, NULL, 0}, + {18, embf_line_32, 0}, + {12, embf_line_33, 2}, + {12, embf_line_34, 2}, + {12, embf_line_35, 4}, + {12, embf_line_36, 12}, + {12, embf_line_37, 17}, + {12, embf_line_38, 11}, + {12, embf_line_39, 1}, + {12, embf_line_40, 3}, + {12, embf_line_41, 3}, + {12, embf_line_42, 4}, + {12, embf_line_43, 2}, + {12, embf_line_44, 1}, + {12, embf_line_45, 1}, + {12, embf_line_46, 1}, + {12, embf_line_47, 1}, + {12, embf_line_48, 9}, + {12, embf_line_49, 3}, + {12, embf_line_50, 6}, + {12, embf_line_51, 11}, + {12, embf_line_52, 3}, + {12, embf_line_53, 9}, + {12, embf_line_54, 10}, + {12, embf_line_55, 2}, + {12, embf_line_56, 15}, + {12, embf_line_57, 8}, + {12, embf_line_58, 2}, + {12, embf_line_59, 2}, + {12, embf_line_60, 2}, + {12, embf_line_61, 2}, + {12, embf_line_62, 2}, + {12, embf_line_63, 8}, + {12, embf_line_64, 17}, + {12, embf_line_65, 6}, + {12, embf_line_66, 10}, + {12, embf_line_67, 5}, + {12, embf_line_68, 6}, + {12, embf_line_69, 4}, + {12, embf_line_70, 3}, + {12, embf_line_71, 10}, + {12, embf_line_72, 3}, + {12, embf_line_73, 3}, + {12, embf_line_74, 6}, + {12, embf_line_75, 3}, + {12, embf_line_76, 2}, + {12, embf_line_77, 4}, + {12, embf_line_78, 3}, + {12, embf_line_79, 8}, + {12, embf_line_80, 6}, + {12, embf_line_81, 9}, + {12, embf_line_82, 7}, + {12, embf_line_83, 11}, + {12, embf_line_84, 2}, + {12, embf_line_85, 5}, + {12, embf_line_86, 2}, + {12, embf_line_87, 6}, + {12, embf_line_88, 2}, + {12, embf_line_89, 3}, + {12, embf_line_90, 3}, + {12, embf_line_91, 3}, + {12, embf_line_92, 1}, + {12, embf_line_93, 3}, + {12, embf_line_94, 2}, + {12, embf_line_95, 1}, + {0, NULL, 0}, + {12, embf_line_97, 9}, + {12, embf_line_98, 8}, + {12, embf_line_99, 5}, + {12, embf_line_100, 8}, + {12, embf_line_101, 8}, + {10, embf_line_102, 4}, + {12, embf_line_103, 11}, + {12, embf_line_104, 5}, + {10, embf_line_105, 2}, + {10, embf_line_106, 3}, + {12, embf_line_107, 3}, + {10, embf_line_108, 2}, + {12, embf_line_109, 10}, + {12, embf_line_110, 6}, + {12, embf_line_111, 8}, + {12, embf_line_112, 9}, + {12, embf_line_113, 8}, + {12, embf_line_114, 4}, + {12, embf_line_115, 9}, + {10, embf_line_116, 3}, + {12, embf_line_117, 5}, + {12, embf_line_118, 2}, + {12, embf_line_119, 9}, + {12, embf_line_120, 2}, + {12, embf_line_121, 8}, + {12, embf_line_122, 3}, + {12, embf_line_123, 6}, + {12, embf_line_124, 1}, + {12, embf_line_125, 6}, + {12, embf_line_126, 5}, + {0, NULL, 0} +}; Index: tags/2.1.2/src/fptr_cast.c =================================================================== --- tags/2.1.2/src/fptr_cast.c (nonexistent) +++ tags/2.1.2/src/fptr_cast.c (revision 24813) @@ -0,0 +1,42 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2016 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include +#include "config.h" +#include "fptr_cast.h" + +void *pcb_cast_f2d(pcb_fptr_t f) +{ + assert(sizeof(void *) == sizeof(pcb_fptr_t)); + return (void *)f; +} + +pcb_fptr_t pcb_cast_d2f(void *d) +{ + assert(sizeof(void *) == sizeof(pcb_fptr_t)); + return (pcb_fptr_t)d; +} + Index: tags/2.1.2/src/fptr_cast.h =================================================================== --- tags/2.1.2/src/fptr_cast.h (nonexistent) +++ tags/2.1.2/src/fptr_cast.h (revision 24813) @@ -0,0 +1,38 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2016 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +/* Function pointer <-> data pointer casts with assert on size match. C89 + does not permit these casts but they practically work on any platform + pcb-rnd has the chance to run on. Hide the ugliness behind this API. */ + +#ifndef PCB_FPTRCAST_H +#define PCB_FPTRCAST_H +typedef void (*pcb_fptr_t)(); + +void *pcb_cast_f2d(pcb_fptr_t f); +pcb_fptr_t pcb_cast_d2f(void *d); + +#endif Index: tags/2.1.2/src/funchash.c =================================================================== --- tags/2.1.2/src/funchash.c (nonexistent) +++ tags/2.1.2/src/funchash.c (revision 24813) @@ -0,0 +1,155 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2016 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include +#include +#include +#include +#include +#include "funchash_core.h" +#include "config.h" +#include "macro.h" +#include "compat_misc.h" + +#define action_entry(x) { #x, F_ ## x}, +static pcb_funchash_table_t Functions[] = { +#include "funchash_core_list.h" + {"F_END", F_END} +}; + +typedef struct { + const char *cookie; + const char *key; + char key_buff[1]; +} fh_key_t; + +static htpi_t *funchash; + +static int keyeq(const void *a_, const void *b_) +{ + const fh_key_t *a = a_, *b = b_; + if (a->cookie != b->cookie) + return 1; + return !pcb_strcasecmp(a->key, b->key); +} + +static unsigned fh_hash(const void *key) +{ + const fh_key_t *k = key; + return strhash_case((char *)k->key) ^ ptrhash((void *)k->cookie); +} + +void pcb_funchash_init(void) +{ + funchash = htpi_alloc(fh_hash, keyeq); + pcb_funchash_set_table(Functions, PCB_ENTRIES(Functions), NULL); +} + +void pcb_funchash_uninit(void) +{ + htpi_entry_t *e; + + for (e = htpi_first(funchash); e; e = htpi_next(funchash, e)) { + fh_key_t *k = e->key; + if (k->cookie != NULL) + fprintf(stderr, "WARNING: function not removed: %s::%s\n", k->cookie, k->key); + htpi_pop(funchash, e->key); + free(e->key); + } + htpi_free(funchash); + funchash = NULL; +} + +void pcb_funchash_remove_cookie(const char *cookie) +{ + htpi_entry_t *e; + + /* Slow linear search - probably OK, this will run only on uninit */ + for (e = htpi_first(funchash); e; e = htpi_next(funchash, e)) { + fh_key_t *k = e->key; + if (k->cookie == cookie) { + htpi_pop(funchash, e->key); + free(e->key); + } + } +} + +int pcb_funchash_get(const char *key, const char *cookie) +{ + fh_key_t new_key; + htpi_entry_t *e; + + if (key == NULL) + return -1; + + new_key.cookie = cookie; + new_key.key = key; + + e = htpi_getentry(funchash, &new_key); + if (e == NULL) + return -1; + return e->value; +} + +int pcb_funchash_set(const char *key, int val, const char *cookie) +{ + fh_key_t *new_key; + int kl; + + if (pcb_funchash_get(key, cookie) >= 0) + return -1; + + kl = strlen(key); + new_key = malloc(sizeof(fh_key_t) + kl); + new_key->cookie = cookie; + new_key->key = new_key->key_buff; + strcpy(new_key->key_buff, key); + htpi_set(funchash, new_key, val); + return 0; +} + +int pcb_funchash_set_table(pcb_funchash_table_t *table, int numelem, const char *cookie) +{ + int i, rv = 0; + + for (i = 0; i < numelem; i++) + rv |= pcb_funchash_set(table[i].key, table[i].val, cookie); + + return rv; +} + +const char *pcb_funchash_reverse(int id) +{ + htpi_entry_t *e; + + for (e = htpi_first(funchash); e; e = htpi_next(funchash, e)) { + if (e->value == id) { + fh_key_t *k = e->key; + return k->key; + } + } + return NULL; +} Index: tags/2.1.2/src/funchash.h =================================================================== --- tags/2.1.2/src/funchash.h (nonexistent) +++ tags/2.1.2/src/funchash.h (revision 24813) @@ -0,0 +1,60 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2016 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#ifndef PCB_FUNCHASH_H +#define PCB_FUNCHASH_H + +/* Table entry format for pcb_funchash_set_table() */ +typedef struct { + const char *key; + int val; +} pcb_funchash_table_t; + +/* Cookie is the namespace so that different modules can use the same + function names with different integer IDs without interference. Core + should use cookie==NULL. */ + +/* Resolve a key string into an integer ID */ +int pcb_funchash_get(const char *key, const char *cookie); + +/* Store key string - integer ID pair */ +int pcb_funchash_set(const char *key, int val, const char *cookie); + +/* Store multiple key strings - integer ID pairs using a table */ +int pcb_funchash_set_table(pcb_funchash_table_t *table, int numelem, const char *cookie); + +/* Remove all keys inserted for a cookie */ +void pcb_funchash_remove_cookie(const char *cookie); + +/* Slow linear search to look up the key text for an ID (for debugging) */ +const char *pcb_funchash_reverse(int id); + + +/* Init-uninit the hash */ +void pcb_funchash_init(void); +void pcb_funchash_uninit(void); + +#endif Index: tags/2.1.2/src/funchash_core.h =================================================================== --- tags/2.1.2/src/funchash_core.h (nonexistent) +++ tags/2.1.2/src/funchash_core.h (revision 24813) @@ -0,0 +1,10 @@ +/* central, auto-generated enum of core function IDs */ + +#include "funchash.h" + +#define action_entry(x) F_ ## x, +typedef enum { +#include "funchash_core_list.h" +F_END +} pcb_function_id_t; +#undef action_entry Index: tags/2.1.2/src/funchash_core_list.h =================================================================== --- tags/2.1.2/src/funchash_core_list.h (nonexistent) +++ tags/2.1.2/src/funchash_core_list.h (revision 24813) @@ -0,0 +1,182 @@ +/* + Central list of function IDs + The core and core plugins use these from a single, central hash + This list is used to cpp-generate the F_* constants in enum pcb_function_id_t +*/ + +/* layer purpose */ +action_entry(user) +action_entry(fab) +action_entry(assy) +action_entry(csect) +action_entry(pdrill) +action_entry(udrill) +action_entry(proute) +action_entry(uroute) + +/* Keywords for actions */ +action_entry(Add) +action_entry(AddSelected) +action_entry(AddRats) +action_entry(All) +action_entry(AllConnections) +action_entry(AllRats) +action_entry(AllUnusedPins) +action_entry(Arc) +action_entry(Arrow) +action_entry(Block) +action_entry(Buffer) +action_entry(Cancel) +action_entry(Center) +action_entry(Check) +action_entry(Clear) +action_entry(ClearAndRedraw) +action_entry(ClearList) +action_entry(Close) +action_entry(CloseHole) +action_entry(Connection) +action_entry(Convert) +action_entry(ConvertSubc) +action_entry(Copy) +action_entry(CycleClip) +action_entry(CycleCrosshair) +action_entry(DeleteRats) +action_entry(Delta) +action_entry(Done) +action_entry(Drag) +action_entry(DrillReport) +action_entry(Element) +action_entry(ElementConnections) +action_entry(ElementToBuffer) +action_entry(Escape) +action_entry(Eq) +action_entry(Export) +action_entry(Find) +action_entry(FlipElement) +action_entry(Found) +action_entry(FoundPins) +action_entry(Footprint) +action_entry(FootprintToBuffer) +action_entry(ForceThaw) +action_entry(Freeze) +action_entry(Grid) +action_entry(Hash) +action_entry(InsertPoint) +action_entry(Invert) +action_entry(Iseq) +action_entry(Layer) +action_entry(Layout) +action_entry(LayoutAs) +action_entry(LayoutToBuffer) +action_entry(Lihata) +action_entry(Line) +action_entry(LineSize) +action_entry(Lock) +action_entry(Loose) +action_entry(Merge) +action_entry(Mirror) +action_entry(Move) +action_entry(MoveSelected) +action_entry(Native) +action_entry(Netlist) +action_entry(Need) +action_entry(None) +action_entry(Normalize) +action_entry(Notify) +action_entry(NoRats) +action_entry(Object) +action_entry(Off) +action_entry(On) +action_entry(Pan) +action_entry(PasteBuffer) +action_entry(PinOrPadName) +action_entry(Pinout) +action_entry(Polygon) +action_entry(PolygonHole) +action_entry(Pop) +action_entry(PreviousPoint) +action_entry(Push) +action_entry(Rats) +action_entry(RatsNest) +action_entry(Rectangle) +action_entry(Redraw) +action_entry(Refdes) +action_entry(Release) +action_entry(Revert) +action_entry(Remove) +action_entry(RemoveSelected) +action_entry(Rename) +action_entry(Report) +action_entry(Reset) +action_entry(ResetLayerObjects) +action_entry(ResetLinesAndPolygons) +action_entry(ResetPadstacks) +action_entry(ResetPinsViasAndPads) +action_entry(Restore) +action_entry(Ripup) +action_entry(Rotate) +action_entry(Save) +action_entry(Select) +action_entry(Selected) +action_entry(SelectedArcs) +action_entry(SelectedElements) +action_entry(SelectedLines) +action_entry(SelectedNames) +action_entry(SelectedObjects) +action_entry(SelectedPads) +action_entry(SelectedPins) +action_entry(SelectedPadstacks) +action_entry(SelectedTexts) +action_entry(SelectedVias) +action_entry(SelectedRats) +action_entry(Set) +action_entry(Sides) +action_entry(Sort) +action_entry(Start) +action_entry(Stroke) +action_entry(Style) +action_entry(Subc) +action_entry(Subcircuit) +action_entry(SubcConnections) +action_entry(SubcToBuffer) +action_entry(SubcID) +action_entry(Swap) +action_entry(TermID) +action_entry(Text) +action_entry(TextScale) +action_entry(Thaw) +action_entry(Thermal) +action_entry(ToLayout) +action_entry(Toggle) +action_entry(ToggleAllDirections) +action_entry(ToggleAutoDRC) +action_entry(ToggleClearLine) +action_entry(ToggleFullPoly) +action_entry(ToggleGrid) +action_entry(ToggleHideNames) +action_entry(ToggleMinCut) +action_entry(ToggleMask) +action_entry(TogglePaste) +action_entry(ToggleName) +action_entry(ToggleObject) +action_entry(ToggleShowDRC) +action_entry(ToggleLiveRoute) +action_entry(ToggleRubberBandMode) +action_entry(ToggleStartDirection) +action_entry(ToggleSnapPin) +action_entry(ToggleSnapOffGridLine) +action_entry(ToggleHighlightOnPoint) +action_entry(ToggleThindraw) +action_entry(ToggleLockNames) +action_entry(ToggleOnlyNames) +action_entry(ToggleThindrawPoly) +action_entry(ToggleOrthoMove) +action_entry(ToggleLocalRef) +action_entry(ToggleCheckPlanes) +action_entry(ToggleUniqueNames) +action_entry(ToggleStroke) +action_entry(Unselect) +action_entry(Via) +action_entry(Warp) +action_entry(Zoom) + Index: tags/2.1.2/src/global_typedefs.h =================================================================== --- tags/2.1.2/src/global_typedefs.h (nonexistent) +++ tags/2.1.2/src/global_typedefs.h (revision 24813) @@ -0,0 +1,87 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 2016 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#ifndef GLOBAL_TYPEDEFS_H +#define GLOBAL_TYPEDEFS_H +#include "config.h" + +typedef struct pcb_board_s pcb_board_t; +typedef struct pcb_data_s pcb_data_t; +typedef struct pcb_layer_stack_s pcb_layer_stack_t; +typedef struct pcb_layer_s pcb_layer_t; +typedef struct pcb_layergrp_s pcb_layergrp_t; +typedef long int pcb_layer_id_t; +typedef long int pcb_layergrp_id_t; +typedef struct pcb_polyarea_s pcb_polyarea_t; +typedef struct pcb_buffer_s pcb_buffer_t; +typedef struct pcb_net_s pcb_net_t; +typedef struct pcb_net_term_s pcb_net_term_t; +typedef struct pcb_oldnet_s pcb_oldnet_t; +typedef struct pcb_connection_s pcb_connection_t; +typedef struct pcb_box_s pcb_box_t; +typedef struct pcb_box_list_s pcb_box_list_t; +typedef struct pcb_font_s pcb_font_t; +typedef struct pcb_fontkit_s pcb_fontkit_t; +typedef struct pcb_line_s pcb_line_t; +typedef struct pcb_arc_s pcb_arc_t; +typedef struct pcb_point_s pcb_point_t; +typedef struct pcb_rat_line_s pcb_rat_t; + +typedef struct pcb_poly_s pcb_poly_t; +typedef struct pcb_pstk_s pcb_pstk_t; +typedef struct pcb_rtree_s pcb_rtree_t; +typedef struct pcb_rtree_it_s pcb_rtree_it_t; +typedef struct pcb_ratspatch_line_s pcb_ratspatch_line_t; +typedef struct pcb_subc_s pcb_subc_t; +typedef struct pcb_text_s pcb_text_t; + +typedef struct pcb_any_obj_s pcb_any_obj_t; +typedef struct pcb_any_line_s pcb_any_line_t; + +typedef union pcb_parent_s pcb_parent_t; + +typedef struct pcb_plug_io_s pcb_plug_io_t; + +typedef struct pcb_hid_cfg_s pcb_hid_cfg_t; + +typedef unsigned int pcb_cardinal_t; +typedef struct pcb_color_s pcb_color_t; +typedef struct pcb_clrcache_s pcb_clrcache_t; + +typedef struct pcb_action_s pcb_action_t; + +typedef struct pcb_view_s pcb_view_t; + +typedef struct pcb_hid_dad_subdialog_s pcb_hid_dad_subdialog_t; + +typedef struct pcb_event_arg_s pcb_event_arg_t; + +#include "pcb_bool.h" + +#include "unit.h" + +#endif Index: tags/2.1.2/src/globalconst.h =================================================================== --- tags/2.1.2/src/globalconst.h (nonexistent) +++ tags/2.1.2/src/globalconst.h (revision 24813) @@ -0,0 +1,88 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +#ifndef PCB_GLOBALCONST_H +#define PCB_GLOBALCONST_H + +#include "config.h" + +#define PCB_LARGE_VALUE (COORD_MAX / 2 - 1) /* maximum extent of board and elements */ + +#define PCB_MAX_LAYER 38 /* max number of layer, check source code for more changes, a *lot* more changes */ +/* new array size that allows substrate layers */ +#define PCB_MAX_LAYERGRP ((PCB_MAX_LAYER+8)*2) /* max number of layer groups, a.k.a. physical layers: a few extra outer layers per side, pluse one substrate per real layer */ +#define PCB_MIN_LINESIZE PCB_MIL_TO_COORD(0.01) /* thickness of lines */ +#define PCB_MAX_LINESIZE ((pcb_coord_t)PCB_LARGE_VALUE) +#define PCB_MIN_ARCSIZE PCB_MIL_TO_COORD(0.01) +#define PCB_MAX_ARCSIZE ((pcb_coord_t)PCB_LARGE_VALUE) +#define PCB_MIN_TEXTSCALE 10 /* scaling of text objects in percent */ +#define PCB_MAX_TEXTSCALE 10000 +#define PCB_MIN_PINORVIASIZE PCB_MIL_TO_COORD(20) /* size of a pin or via */ +#define PCB_MIN_PINORVIAHOLE PCB_MIL_TO_COORD(4) /* size of a pins or vias drilling hole */ +#define PCB_MAX_PINORVIASIZE ((pcb_coord_t)PCB_LARGE_VALUE) +#define PCB_MIN_PINORVIACOPPER PCB_MIL_TO_COORD(4) /* min difference outer-inner diameter */ +#define PCB_MIN_GRID 1 +#define PCB_MAX_GRID PCB_MIL_TO_COORD(1000) +#define PCB_MAX_FONTPOSITION 255 /* upper limit of characters in my font */ + +#define PCB_MAX_COORD ((pcb_coord_t)PCB_LARGE_VALUE) /* coordinate limits */ +#define PCB_MIN_SIZE PCB_MIL_TO_COORD(10) /* lowest width and height of the board */ +#define PCB_MAX_BUFFER 5 /* number of pastebuffers additional changes in menu.c are also required to select more buffers */ + +#define PCB_DEFAULT_DRILLINGHOLE 40 /* default inner/outer ratio for pins/vias in percent */ + +#define PCB_MAX_SIZE ((pcb_coord_t)PCB_LARGE_VALUE) + +#ifndef PCB_PATH_MAX /* maximum path length */ +#ifdef PATH_MAX +#define PCB_PATH_MAX PATH_MAX +#else +#define PCB_PATH_MAX 2048 +#endif +#endif + +/* number of dynamic flag bits that can be allocated at once; should be n*64 for + memory efficiency */ +#define PCB_DYNFLAG_BLEN 64 + +#define PCB_MAX_LINE_POINT_DISTANCE 0 /* maximum distance when searching line points; same for arc point */ +#define PCB_MAX_POLYGON_POINT_DISTANCE 0 /* maximum distance when searching polygon points */ +#define PCB_MAX_NETLIST_LINE_LENGTH 255 /* maximum line length for netlist files */ +#define PCB_MAX_MODESTACK_DEPTH 16 /* maximum depth of mode stack */ +#define PCB_MIN_GRID_DISTANCE 4 /* minimum distance between point to enable grid drawing */ +#define PCB_EMARK_SIZE PCB_MIL_TO_COORD(10) /* size of diamond element mark */ + + +/**** Font ***/ +/* These are used in debug draw font rendering (e.g. pin names) and reverse + scale calculations (e.g. when report is trying to figure how the font + is scaled. Changing these values is not really supported. */ +#define PCB_FONT_CAPHEIGHT PCB_MIL_TO_COORD (45) /* (Approximate) capheight size of the default PCB font */ +#define PCB_DEFAULT_CELLSIZE 50 /* default cell size for symbols */ + +#endif Index: tags/2.1.2/src/grid.c =================================================================== --- tags/2.1.2/src/grid.c (nonexistent) +++ tags/2.1.2/src/grid.c (revision 24813) @@ -0,0 +1,223 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * 15 Oct 2008 Ineiev: add different crosshair shapes + * Copyright (C) 2018 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +#include "config.h" + +#include +#include +#include +#include + +#include "unit.h" +#include "grid.h" +#include "board.h" +#include "conf.h" +#include "conf_core.h" +#include "conf_hid.h" +#include "compat_misc.h" +#include "misc_util.h" +#include "pcb_bool.h" +#include "pcb-printf.h" + +pcb_coord_t pcb_grid_fit(pcb_coord_t x, pcb_coord_t grid_spacing, pcb_coord_t grid_offset) +{ + x -= grid_offset; + x = grid_spacing * pcb_round((double) x / grid_spacing); + x += grid_offset; + return x; +} + +pcb_bool_t pcb_grid_parse(pcb_grid_t *dst, const char *src) +{ + const char *nsep; + char *sep3, *sep2, *sep, *tmp, *size, *ox = NULL, *oy = NULL, *unit = NULL; + pcb_bool succ; + + nsep = strchr(src, ':'); + if (nsep != NULL) + src = nsep+1; + else + dst->name = NULL; + + /* remember where size starts */ + while(isspace(*src)) src++; + sep = size = tmp = pcb_strdup(src); + + /* find optional offs */ + sep2 = strchr(sep, '@'); + if (sep2 != NULL) { + sep = sep2; + *sep = '\0'; + sep++; + ox = sep; + sep3 = strchr(sep, ','); + if (sep3 != NULL) { + *sep3 = '\0'; + sep3++; + oy = sep; + } + } + + /* find optional unit switch */ + sep2 = strchr(sep, '!'); + if (sep2 != NULL) { + sep = sep2; + *sep = '\0'; + sep++; + unit = sep; + } + + /* convert */ + dst->size = pcb_get_value(size, NULL, NULL, &succ); + if ((!succ) || (dst->size < 0)) + goto error; + + if (ox != NULL) { + dst->ox = pcb_get_value(ox, NULL, NULL, &succ); + if (!succ) + goto error; + } + else + dst->ox = 0; + + if (oy != NULL) { + dst->oy = pcb_get_value(oy, NULL, NULL, &succ); + if (!succ) + goto error; + } + else + dst->oy = 0; + + if (unit != NULL) { + dst->unit = get_unit_struct(unit); + if (dst->unit == NULL) + goto error; + } + else + dst->unit = NULL; + + /* success */ + free(tmp); + + if (nsep != NULL) + dst->name = pcb_strndup(src, nsep-src-1); + else + dst->name = NULL; + return pcb_true; + + error:; + free(tmp); + return pcb_false; +} + +pcb_bool_t pcb_grid_append_print(gds_t *dst, const pcb_grid_t *src) +{ + if (src->size <= 0) + return pcb_false; + if (src->name != NULL) { + gds_append_str(dst, src->name); + gds_append(dst, ':'); + } + pcb_append_printf(dst, "%$.08mH", src->size); + if ((src->ox != 0) || (src->oy != 0)) + pcb_append_printf(dst, "@%$.08mH,%$.08mH", src->ox, src->oy); + if (src->unit != NULL) { + gds_append(dst, '!'); + gds_append_str(dst, src->unit->suffix); + } + return pcb_true; +} + +char *pcb_grid_print(const pcb_grid_t *src) +{ + gds_t tmp; + gds_init(&tmp); + if (!pcb_grid_append_print(&tmp, src)) { + gds_uninit(&tmp); + return NULL; + } + return tmp.array; /* do not uninit tmp */ +} + +void pcb_grid_set(pcb_board_t *pcb, const pcb_grid_t *src) +{ + pcb_board_set_grid(src->size, pcb_true, src->ox, src->oy); + if (src->unit != NULL) + pcb_board_set_unit(pcb, src->unit); +} + +void pcb_grid_free(pcb_grid_t *dst) +{ + free(dst->name); + dst->name = NULL; +} + +pcb_bool_t pcb_grid_list_jump(int dst) +{ + const conf_listitem_t *li; + pcb_grid_t g; + int max = conflist_length((conflist_t *)&conf_core.editor.grids); + + if (dst < 0) + dst = 0; + if (dst >= max) + dst = max - 1; + if (dst < 0) + return pcb_false; + + conf_setf(CFR_DESIGN, "editor/grids_idx", -1, "%d", dst); + + li = conflist_nth((conflist_t *)&conf_core.editor.grids, dst); + /* clamp */ + if (li == NULL) + return pcb_false; + + if (!pcb_grid_parse(&g, li->payload)) + return pcb_false; + pcb_grid_set(PCB, &g); + pcb_grid_free(&g); + + return pcb_true; +} + +pcb_bool_t pcb_grid_list_step(int stp) +{ + int dst = conf_core.editor.grids_idx; + if (dst < 0) + dst = -dst-1; + return pcb_grid_list_jump(dst + stp); +} + +void pcb_grid_inval(void) +{ + if (conf_core.editor.grids_idx > 0) + conf_setf(CFR_DESIGN, "editor/grids_idx", -1, "%d", -1 - conf_core.editor.grids_idx); +} + Index: tags/2.1.2/src/grid.h =================================================================== --- tags/2.1.2/src/grid.h (nonexistent) +++ tags/2.1.2/src/grid.h (revision 24813) @@ -0,0 +1,78 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * Copyright (C) 2018 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +#ifndef PCB_GRID_H +#define PCB_GRID_H + +#include +#include "pcb_bool.h" +#include "board.h" +#include "unit.h" + +/* String packed syntax (bracket means optional): + + [name:]size[@offs][!unit] + + "!" means to switch the UI to the unit specified. */ +typedef struct { + char *name; + pcb_coord_t size; + pcb_coord_t ox, oy; + const pcb_unit_t *unit; /* force switching to unit if not NULL */ +} pcb_grid_t; + +/* Returns the nearest grid-point to the given coord x */ +pcb_coord_t pcb_grid_fit(pcb_coord_t x, pcb_coord_t grid_spacing, pcb_coord_t grid_offset); + +/* Parse packed string format src into dst; allocat dst->name on success */ +pcb_bool_t pcb_grid_parse(pcb_grid_t *dst, const char *src); + +/* Free all allocated fields of a grid struct */ +void pcb_grid_free(pcb_grid_t *dst); + +/* Convert src into packed string format */ +pcb_bool_t pcb_grid_append_print(gds_t *dst, const pcb_grid_t *src); +char *pcb_grid_print(const pcb_grid_t *src); + +/* Apply grid settings from src to the pcb */ +void pcb_grid_set(pcb_board_t *pcb, const pcb_grid_t *src); + +/* Jump to grid index dst (clamped); absolute set */ +pcb_bool_t pcb_grid_list_jump(int dst); + +/* Step stp steps (can be 0) on the grids list and set the resulting grid; relative set */ +pcb_bool_t pcb_grid_list_step(int stp); + +/* invalidate the grid index; call this when changing the grid settings */ +void pcb_grid_inval(void); + +/* Reinstall grid menus */ +void pcb_grid_install_menu(void); + +#endif Index: tags/2.1.2/src/gui_act.c =================================================================== --- tags/2.1.2/src/gui_act.c (nonexistent) +++ tags/2.1.2/src/gui_act.c (revision 24813) @@ -0,0 +1,1823 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * Copyright (C) 1997, 1998, 1999, 2000, 2001 Harry Eaton + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + * + * Old contact info: + * Harry Eaton, 6697 Buttonhole Ct, Columbia, MD 21044, USA + * haceaton@aplcomm.jhuapl.edu + * + */ +#include "config.h" +#include "board.h" +#include "build_run.h" +#include "conf_core.h" +#include "data.h" +#include "tool.h" +#include "grid.h" +#include "error.h" +#include "undo.h" +#include "funchash_core.h" +#include "change.h" + +#include "draw.h" +#include "search.h" +#include "find.h" +#include "stub_stroke.h" +#include "actions.h" +#include "hid_init.h" +#include "compat_misc.h" +#include "event.h" +#include "layer.h" +#include "layer_ui.h" +#include "layer_grp.h" +#include "layer_vis.h" +#include "attrib.h" +#include "hid_attrib.h" +#include "operation.h" +#include "obj_subc_op.h" +#include "tool.h" +#include "route_style.h" + +#define CLONE_TYPES PCB_OBJ_LINE | PCB_OBJ_ARC | PCB_OBJ_POLY + +/* --------------------------------------------------------------------------- */ +/* Toggle actions are kept for compatibility; new code should use the conf system instead */ +static const char pcb_acts_Display[] = + "Display(SubcID, template)\n" + "Display(Grid|Redraw|Pinout|PinOrPadName)\n" + "Display(CycleClip|CycleCrosshair|ToggleAllDirections|ToggleStartDirection)\n" + "Display(ToggleGrid|ToggleRubberBandMode|ToggleUniqueNames)\n" + "Display(ToggleName|ToggleClearLine|ToggleFullPoly|ToggleSnapPin)\n" + "Display(ToggleSnapOffGridLine|ToggleHighlightOnPoint|ToggleCheckPlanes)\n" + "Display(ToggleThindraw|ToggleThindrawPoly|ToggleOrthoMove|ToggleLocalRef)\n" + "Display(ToggleLiveRoute|ToggleShowDRC|ToggleAutoDRC|LockNames|OnlyNames)"; + +static const char pcb_acth_Display[] = "Several display-related actions."; +/* DOC: display.html */ +static enum pcb_crosshair_shape_e CrosshairShapeIncrement(enum pcb_crosshair_shape_e shape) +{ + switch (shape) { + case pcb_ch_shape_basic: + shape = pcb_ch_shape_union_jack; + break; + case pcb_ch_shape_union_jack: + shape = pcb_ch_shape_dozen; + break; + case pcb_ch_shape_dozen: + shape = pcb_ch_shape_NUM; + break; + case pcb_ch_shape_NUM: + shape = pcb_ch_shape_basic; + break; + } + return shape; +} + +extern pcb_opfunc_t ChgFlagFunctions; +static fgw_error_t pcb_act_Display(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + const char *str_dir = NULL; + int id; + int err = 0; + + PCB_ACT_IRES(0); + PCB_ACT_CONVARG(1, FGW_KEYWORD, Display, id = fgw_keyword(&argv[1])); + PCB_ACT_MAY_CONVARG(2, FGW_STR, Display, str_dir = argv[2].val.str); + + if (id == F_SubcID) { /* change the displayed name of subcircuits */ + if (argc > 1) + conf_set(CFR_DESIGN, "editor/subc_id", -1, str_dir, POL_OVERWRITE); + else + conf_set(CFR_DESIGN, "editor/subc_id", -1, "", POL_OVERWRITE); + + pcb_gui->invalidate_all(); /* doesn't change too often, isn't worth anything more complicated */ + pcb_draw(); + return 0; + } + + if (id == F_TermID) { /* change the displayed name of terminals */ + if (argc > 1) + conf_set(CFR_DESIGN, "editor/term_id", -1, str_dir, POL_OVERWRITE); + else + conf_set(CFR_DESIGN, "editor/term_id", -1, "", POL_OVERWRITE); + + pcb_gui->invalidate_all(); /* doesn't change too often, isn't worth anything more complicated */ + pcb_draw(); + return 0; + } + + if (!str_dir || !*str_dir) { + switch (id) { + + /* redraw layout */ + case F_ClearAndRedraw: + case F_Redraw: + pcb_redraw(); + break; + + /* toggle line-adjust flag */ + case F_ToggleAllDirections: + conf_toggle_editor(all_direction_lines); + pcb_tool_adjust_attached_objects(); + break; + + case F_CycleClip: + pcb_notify_crosshair_change(pcb_false); + if (conf_core.editor.all_direction_lines) { + conf_toggle_editor(all_direction_lines); + conf_setf(CFR_DESIGN,"editor/line_refraction",-1,"%d",0); + } + else { + conf_setf(CFR_DESIGN,"editor/line_refraction",-1,"%d",(conf_core.editor.line_refraction +1) % 3); + } + pcb_tool_adjust_attached_objects(); + pcb_notify_crosshair_change(pcb_true); + break; + + case F_CycleCrosshair: + pcb_notify_crosshair_change(pcb_false); + pcb_crosshair.shape = CrosshairShapeIncrement(pcb_crosshair.shape); + if (pcb_ch_shape_NUM == pcb_crosshair.shape) + pcb_crosshair.shape = pcb_ch_shape_basic; + pcb_notify_crosshair_change(pcb_true); + break; + + case F_ToggleRubberBandMode: + pcb_notify_crosshair_change(pcb_false); + conf_toggle_editor(rubber_band_mode); + pcb_notify_crosshair_change(pcb_true); + break; + + case F_ToggleStartDirection: + pcb_notify_crosshair_change(pcb_false); + conf_toggle_editor(swap_start_direction); + pcb_notify_crosshair_change(pcb_true); + break; + + case F_ToggleUniqueNames: + pcb_message(PCB_MSG_ERROR, "Unique names/refdes is not supported any more - please use the renumber plugin\n"); + break; + + case F_ToggleSnapPin: + pcb_notify_crosshair_change(pcb_false); + conf_toggle_editor(snap_pin); + pcb_notify_crosshair_change(pcb_true); + break; + + case F_ToggleSnapOffGridLine: + pcb_notify_crosshair_change(pcb_false); + conf_toggle_editor(snap_offgrid_line); + pcb_notify_crosshair_change(pcb_true); + break; + + case F_ToggleHighlightOnPoint: + pcb_notify_crosshair_change(pcb_false); + conf_toggle_editor(highlight_on_point); + pcb_notify_crosshair_change(pcb_true); + break; + + case F_ToggleLocalRef: + conf_toggle_editor(local_ref); + break; + + case F_ToggleThindraw: + conf_toggle_editor(thin_draw); + pcb_redraw(); + break; + + case F_ToggleThindrawPoly: + conf_toggle_editor(thin_draw_poly); + pcb_redraw(); + break; + + case F_ToggleLockNames: + conf_toggle_editor(lock_names); + conf_set_editor(only_names, 0); + break; + + case F_ToggleOnlyNames: + conf_toggle_editor(only_names); + conf_set_editor(lock_names, 0); + break; + + case F_ToggleHideNames: + conf_toggle_editor(hide_names); + pcb_redraw(); + break; + + case F_ToggleStroke: + conf_toggle_editor(enable_stroke); + break; + + case F_ToggleShowDRC: + conf_toggle_editor(show_drc); + break; + + case F_ToggleLiveRoute: + conf_toggle_editor(live_routing); + break; + + case F_ToggleAutoDRC: + pcb_notify_crosshair_change(pcb_false); + conf_toggle_editor(auto_drc); + if (conf_core.editor.auto_drc && conf_core.editor.mode == PCB_MODE_LINE) { + if (pcb_data_clear_flag(PCB->Data, PCB_FLAG_FOUND, 1, 1) > 0) { + pcb_undo_inc_serial(); + pcb_draw(); + } + if (pcb_crosshair.AttachedLine.State != PCB_CH_STATE_FIRST) { + pcb_find_t fctx; + memset(&fctx, 0, sizeof(fctx)); + fctx.flag_set = PCB_FLAG_FOUND; + fctx.flag_chg_undoable = 1; + pcb_find_from_xy(&fctx, PCB->Data, pcb_crosshair.X, pcb_crosshair.Y); + pcb_find_free(&fctx); + } + } + pcb_notify_crosshair_change(pcb_true); + break; + + case F_ToggleCheckPlanes: + conf_toggle_editor(check_planes); + pcb_redraw(); + break; + + case F_ToggleOrthoMove: + conf_toggle_editor(orthogonal_moves); + break; + + case F_ToggleName: + conf_toggle_editor(show_number); + pcb_redraw(); + break; + + case F_ToggleClearLine: + conf_toggle_editor(clear_line); + break; + + case F_ToggleFullPoly: + conf_toggle_editor(full_poly); + break; + + /* shift grid alignment */ + case F_ToggleGrid: + { + pcb_coord_t oldGrid = PCB->Grid; + + PCB->Grid = 1; + if (pcb_crosshair_move_absolute(pcb_crosshair.X, pcb_crosshair.Y)) + pcb_notify_crosshair_change(pcb_true); /* first notify was in MoveCrosshairAbs */ + pcb_board_set_grid(oldGrid, pcb_true, pcb_crosshair.X, pcb_crosshair.Y); + pcb_grid_inval(); + } + break; + + /* toggle displaying of the grid */ + case F_Grid: + conf_toggle_editor(draw_grid); + pcb_redraw(); + break; + + /* display the pinout of a subcircuit */ + case F_Pinout: + return pcb_actionl("pinout", NULL); + + /* toggle displaying of terminal names */ + case F_PinOrPadName: + { + int type; + void *ptr1, *ptr2, *ptr3; + pcb_coord_t x, y; + pcb_hid_get_coords("Click on a subcircuit", &x, &y, 0); + + /* toggle terminal ID print for subcircuit parts */ + type = pcb_search_screen(x, y, PCB_OBJ_SUBC | PCB_OBJ_SUBC_PART | PCB_OBJ_PSTK | PCB_OBJ_LINE | PCB_OBJ_ARC | PCB_OBJ_POLY | PCB_OBJ_TEXT, (void **)&ptr1, (void **)&ptr2, (void **)&ptr3); + if (type) { + pcb_any_obj_t *obj = ptr2; + pcb_opctx_t opctx; + + switch(type) { + case PCB_OBJ_SUBC: + opctx.chgflag.pcb = PCB; + opctx.chgflag.how = PCB_CHGFLG_TOGGLE; + opctx.chgflag.flag = PCB_FLAG_TERMNAME; + pcb_subc_op(PCB->Data, (pcb_subc_t *)obj, &ChgFlagFunctions, &opctx, 0); + pcb_undo_inc_serial(); + return 0; + break; + case PCB_OBJ_LINE: + case PCB_OBJ_ARC: + case PCB_OBJ_POLY: + case PCB_OBJ_TEXT: + case PCB_OBJ_PSTK: + pcb_obj_invalidate_label(type, ptr1, ptr2, ptr3); + break; + default: + return 0; /* nothing else can have a displayed name */ + } + + pcb_undo_add_obj_to_flag(ptr2); + PCB_FLAG_TOGGLE(PCB_FLAG_TERMNAME, obj); + pcb_board_set_changed_flag(pcb_true); + pcb_undo_inc_serial(); + pcb_draw(); + } + break; + } + default: + err = 1; + } + } + else if (str_dir) { + switch(id) { + case F_ToggleGrid: + if (argc > 3) { + if (fgw_arg_conv(&pcb_fgw, &argv[3], FGW_KEYWORD) != 0) { + PCB_ACT_FAIL(Display); + return FGW_ERR_ARG_CONV; + } + PCB->GridOffsetX = pcb_get_value(argv[2].val.str, NULL, NULL, NULL); + PCB->GridOffsetY = pcb_get_value(argv[3].val.str, NULL, NULL, NULL); + if (conf_core.editor.draw_grid) + pcb_redraw(); + } + break; + + default: + err = 1; + break; + } + } + + if (!err) + return 0; + + PCB_ACT_FAIL(Display); +} +/* --------------------------------------------------------------------------- */ + +static const char pcb_acts_Mode[] = + "Mode(Arc|Arrow|Copy|InsertPoint|Line|Lock|Move|None|PasteBuffer)\n" + "Mode(Polygon|Rectangle|Remove|Rotate|Text|Thermal|Via)\n" "Mode(Notify|Release|Cancel|Stroke)\n" "Mode(Save|Restore)"; + +static const char pcb_acth_Mode[] = "Change or use the tool mode."; +/* DOC: mode.html */ +static fgw_error_t pcb_act_Mode(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + PCB_ACT_IRES(0); + PCB_ACT_CONVARG(1, FGW_KEYWORD, Display, ;); + + /* it is okay to use crosshair directly here, the mode command is called from a click when it needs coords */ + pcb_tool_note.X = pcb_crosshair.X; + pcb_tool_note.Y = pcb_crosshair.Y; + pcb_notify_crosshair_change(pcb_false); + switch(fgw_keyword(&argv[1])) { + case F_Arc: + pcb_tool_select_by_id(PCB_MODE_ARC); + break; + case F_Arrow: + pcb_tool_select_by_id(PCB_MODE_ARROW); + break; + case F_Copy: + pcb_tool_select_by_id(PCB_MODE_COPY); + break; + case F_InsertPoint: + pcb_tool_select_by_id(PCB_MODE_INSERT_POINT); + break; + case F_Line: + pcb_tool_select_by_id(PCB_MODE_LINE); + break; + case F_Lock: + pcb_tool_select_by_id(PCB_MODE_LOCK); + break; + case F_Move: + pcb_tool_select_by_id(PCB_MODE_MOVE); + break; + case F_None: + pcb_tool_select_by_id(PCB_MODE_NO); + break; + case F_Cancel: + { + int saved_mode = conf_core.editor.mode; + pcb_tool_select_by_id(PCB_MODE_NO); + pcb_tool_select_by_id(saved_mode); + } + break; + case F_Escape: + { + switch (conf_core.editor.mode) { + case PCB_MODE_VIA: + case PCB_MODE_PASTE_BUFFER: + case PCB_MODE_TEXT: + case PCB_MODE_ROTATE: + case PCB_MODE_REMOVE: + case PCB_MODE_MOVE: + case PCB_MODE_COPY: + case PCB_MODE_INSERT_POINT: + case PCB_MODE_RUBBERBAND_MOVE: + case PCB_MODE_THERMAL: + case PCB_MODE_LOCK: + pcb_tool_select_by_id(PCB_MODE_NO); + pcb_tool_select_by_id(PCB_MODE_ARROW); + pcb_tool_note.Hit = pcb_tool_note.Click = 0; /* if the mouse button is still pressed, don't start selecting a box */ + break; + + case PCB_MODE_LINE: + if (pcb_crosshair.AttachedLine.State == PCB_CH_STATE_FIRST) { + pcb_tool_select_by_id(PCB_MODE_ARROW); + } + else { + pcb_tool_select_by_id(PCB_MODE_NO); + pcb_tool_select_by_id(PCB_MODE_LINE); + } + break; + + case PCB_MODE_RECTANGLE: + if (pcb_crosshair.AttachedBox.State == PCB_CH_STATE_FIRST) + pcb_tool_select_by_id(PCB_MODE_ARROW); + else { + pcb_tool_select_by_id(PCB_MODE_NO); + pcb_tool_select_by_id(PCB_MODE_RECTANGLE); + } + break; + + case PCB_MODE_POLYGON: + if (pcb_crosshair.AttachedLine.State == PCB_CH_STATE_FIRST) + pcb_tool_select_by_id(PCB_MODE_ARROW); + else { + pcb_tool_select_by_id(PCB_MODE_NO); + pcb_tool_select_by_id(PCB_MODE_POLYGON); + } + break; + + case PCB_MODE_POLYGON_HOLE: + if (pcb_crosshair.AttachedLine.State == PCB_CH_STATE_FIRST) + pcb_tool_select_by_id(PCB_MODE_ARROW); + else { + pcb_tool_select_by_id(PCB_MODE_NO); + pcb_tool_select_by_id(PCB_MODE_POLYGON_HOLE); + } + break; + + case PCB_MODE_ARC: + if (pcb_crosshair.AttachedBox.State == PCB_CH_STATE_FIRST) + pcb_tool_select_by_id(PCB_MODE_ARROW); + else { + pcb_tool_select_by_id(PCB_MODE_NO); + pcb_tool_select_by_id(PCB_MODE_ARC); + } + break; + + case PCB_MODE_ARROW: + break; + + default: + break; + } + } + break; + + case F_Notify: + pcb_notify_mode(); + break; + case F_PasteBuffer: + pcb_tool_select_by_id(PCB_MODE_PASTE_BUFFER); + break; + case F_Polygon: + pcb_tool_select_by_id(PCB_MODE_POLYGON); + break; + case F_PolygonHole: + pcb_tool_select_by_id(PCB_MODE_POLYGON_HOLE); + break; + case F_Release: + if ((pcb_mid_stroke) && (conf_core.editor.enable_stroke) && (pcb_stub_stroke_finish() == 0)) { + /* Ugly hack: returning 1 here will break execution of the + action script, so actions after this one could do things + that would be executed only after non-recognized gestures */ + pcb_release_mode(); + return 1; + } + pcb_release_mode(); + break; + case F_Remove: + pcb_tool_select_by_id(PCB_MODE_REMOVE); + break; + case F_Rectangle: + pcb_tool_select_by_id(PCB_MODE_RECTANGLE); + break; + case F_Rotate: + pcb_tool_select_by_id(PCB_MODE_ROTATE); + break; + case F_Stroke: + if (conf_core.editor.enable_stroke) { + pcb_stub_stroke_start(); + break; + } + /* Handle middle mouse button restarts of drawing mode. + If not in a drawing mode, middle mouse button will select objects. */ + if (conf_core.editor.mode == PCB_MODE_LINE && pcb_crosshair.AttachedLine.State != PCB_CH_STATE_FIRST) + pcb_tool_select_by_id(PCB_MODE_LINE); + else if (conf_core.editor.mode == PCB_MODE_ARC && pcb_crosshair.AttachedBox.State != PCB_CH_STATE_FIRST) + pcb_tool_select_by_id(PCB_MODE_ARC); + else if (conf_core.editor.mode == PCB_MODE_RECTANGLE && pcb_crosshair.AttachedBox.State != PCB_CH_STATE_FIRST) + pcb_tool_select_by_id(PCB_MODE_RECTANGLE); + else if (conf_core.editor.mode == PCB_MODE_POLYGON && pcb_crosshair.AttachedLine.State != PCB_CH_STATE_FIRST) + pcb_tool_select_by_id(PCB_MODE_POLYGON); + else { + pcb_tool_save(); + pcb_tool_is_saved = pcb_true; + pcb_tool_select_by_id(PCB_MODE_ARROW); + pcb_notify_mode(); + } + break; + case F_Text: + pcb_tool_select_by_id(PCB_MODE_TEXT); + break; + case F_Thermal: + pcb_tool_select_by_id(PCB_MODE_THERMAL); + break; + case F_Via: + pcb_tool_select_by_id(PCB_MODE_VIA); + break; + + case F_Restore: /* restore the last saved tool */ + pcb_tool_restore(); + break; + + case F_Save: /* save currently selected tool */ + pcb_tool_save(); + break; + } + pcb_notify_crosshair_change(pcb_true); + return 0; +} + +/* ---------------------------------------------------------------- */ +static const char pcb_acts_CycleDrag[] = "CycleDrag()\n"; +static const char pcb_acth_CycleDrag[] = "Cycle through which object is being dragged"; +/* DOC: cycledrag.html */ +#define close_enough(a, b) ((((a)-(b)) > 0) ? ((a)-(b) < (PCB_SLOP * pcb_pixel_slop)) : ((a)-(b) > -(PCB_SLOP * pcb_pixel_slop))) +static fgw_error_t pcb_act_CycleDrag(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + void *ptr1, *ptr2, *ptr3; + int over = 0; + + PCB_ACT_IRES(0); + if (pcb_crosshair.drags == NULL) + return 0; + + do { + pcb_crosshair.drags_current++; + if (pcb_crosshair.drags_current >= pcb_crosshair.drags_len) { + pcb_crosshair.drags_current = 0; + over++; + } + + if (pcb_search_obj_by_id(PCB->Data, &ptr1, &ptr2, &ptr3, pcb_crosshair.drags[pcb_crosshair.drags_current], PCB_OBJ_LINE) != PCB_OBJ_VOID) { + /* line has two endpoints, check which one is close to the original x;y */ + pcb_line_t *l = ptr2; + if (close_enough(pcb_tool_note.X, l->Point1.X) && close_enough(pcb_tool_note.Y, l->Point1.Y)) { + pcb_crosshair.AttachedObject.Type = PCB_OBJ_LINE_POINT; + pcb_crosshair.AttachedObject.Ptr1 = ptr1; + pcb_crosshair.AttachedObject.Ptr2 = ptr2; + pcb_crosshair.AttachedObject.Ptr3 = &l->Point1; + goto switched; + } + if (close_enough(pcb_tool_note.X, l->Point2.X) && close_enough(pcb_tool_note.Y, l->Point2.Y)) { + pcb_crosshair.AttachedObject.Type = PCB_OBJ_LINE_POINT; + pcb_crosshair.AttachedObject.Ptr1 = ptr1; + pcb_crosshair.AttachedObject.Ptr2 = ptr2; + pcb_crosshair.AttachedObject.Ptr3 = &l->Point2; + goto switched; + } + } + else if (pcb_search_obj_by_id(PCB->Data, &ptr1, &ptr2, &ptr3, pcb_crosshair.drags[pcb_crosshair.drags_current], PCB_OBJ_ARC_POINT) != PCB_OBJ_VOID) { + pcb_coord_t ex, ey; + pcb_arc_get_end((pcb_arc_t *)ptr2, 0, &ex, &ey); + if (close_enough(pcb_tool_note.X, ex) && close_enough(pcb_tool_note.Y, ey)) { + pcb_crosshair.AttachedObject.Type = PCB_OBJ_ARC_POINT; + pcb_crosshair.AttachedObject.Ptr1 = ptr1; + pcb_crosshair.AttachedObject.Ptr2 = ptr2; + pcb_crosshair.AttachedObject.Ptr3 = pcb_arc_start_ptr; + goto switched; + } + pcb_arc_get_end((pcb_arc_t *)ptr2, 1, &ex, &ey); + if (close_enough(pcb_tool_note.X, ex) && close_enough(pcb_tool_note.Y, ey)) { + pcb_crosshair.AttachedObject.Type = PCB_OBJ_ARC_POINT; + pcb_crosshair.AttachedObject.Ptr1 = ptr1; + pcb_crosshair.AttachedObject.Ptr2 = ptr2; + pcb_crosshair.AttachedObject.Ptr3 = pcb_arc_end_ptr; + goto switched; + } + } + else if (pcb_search_obj_by_id(PCB->Data, &ptr1, &ptr2, &ptr3, pcb_crosshair.drags[pcb_crosshair.drags_current], PCB_OBJ_ARC) != PCB_OBJ_VOID) { + pcb_crosshair.AttachedObject.Type = PCB_OBJ_ARC; + pcb_crosshair.AttachedObject.Ptr1 = ptr1; + pcb_crosshair.AttachedObject.Ptr2 = ptr2; + pcb_crosshair.AttachedObject.Ptr3 = ptr3; + goto switched; + } + + } while (over <= 1); + + PCB_ACT_IRES(-1); + return 0; + switched:; + pcb_event(PCB_EVENT_RUBBER_RESET, NULL); + pcb_event(PCB_EVENT_RUBBER_LOOKUP_LINES, "ippp", pcb_crosshair.AttachedObject.Type, pcb_crosshair.AttachedObject.Ptr1, pcb_crosshair.AttachedObject.Ptr2, pcb_crosshair.AttachedObject.Ptr3); + return 0; +} + +#undef close_enough + +/* -------------------------------------------------------------------------- */ + +static const char pcb_acts_Message[] = "message(message)"; +static const char pcb_acth_Message[] = "Writes a message to the log window."; +/* DOC: message.html */ +static fgw_error_t pcb_act_Message(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + int i; + + if (argc < 2) + PCB_ACT_FAIL(Message); + + PCB_ACT_IRES(0); + for (i = 1; i < argc; i++) { + PCB_ACT_MAY_CONVARG(i, FGW_STR, Message, ;); + pcb_message(PCB_MSG_INFO, argv[i].val.str); + pcb_message(PCB_MSG_INFO, "\n"); + } + + return 0; +} + +/* --------------------------------------------------------------------------- */ + +static const char pcb_acts_MarkCrosshair[] = "MarkCrosshair()\n" "MarkCrosshair(Center)"; +static const char pcb_acth_MarkCrosshair[] = "Set/Reset the pcb_crosshair mark."; +/* DOC: markcrosshair.html */ +static fgw_error_t pcb_act_MarkCrosshair(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + int id = -2; + + PCB_ACT_IRES(0); + PCB_ACT_MAY_CONVARG(1, FGW_KEYWORD, Display, id = fgw_keyword(&argv[1])); + + if (id == -1) { /* invalid */ + PCB_ACT_FAIL(MarkCrosshair); + return FGW_ERR_ARGV_TYPE; + } + else if (id == -2) { /* empty */ + if (pcb_marked.status) { + pcb_notify_mark_change(pcb_false); + pcb_marked.status = pcb_false; + pcb_notify_mark_change(pcb_true); + } + else { + pcb_notify_mark_change(pcb_false); + pcb_marked.status = pcb_true; + if (conf_core.editor.marker_snaps) { + pcb_marked.X = pcb_crosshair.X; + pcb_marked.Y = pcb_crosshair.Y; + } + else + pcb_hid_get_coords("Click on new mark", &pcb_marked.X, &pcb_marked.Y, 0); + pcb_notify_mark_change(pcb_true); + } + } + else if (id == F_Center) { + pcb_notify_mark_change(pcb_false); + pcb_marked.status = pcb_true; + if (conf_core.editor.marker_snaps) { + pcb_marked.X = pcb_crosshair.X; + pcb_marked.Y = pcb_crosshair.Y; + } + else + pcb_hid_get_coords("Click on new mark", &pcb_marked.X, &pcb_marked.Y, 0); + pcb_notify_mark_change(pcb_true); + } + return 0; +} + +/* --------------------------------------------------------------------------- */ + +static const char pcb_acts_RouteStyle[] = "RouteStyle(style_id|style_name)"; +static const char pcb_acth_RouteStyle[] = "Copies the indicated routing style into the current pen."; +static fgw_error_t pcb_act_RouteStyle(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + char *end; + const char *str = NULL; + pcb_route_style_t *rts; + int number; + + PCB_ACT_IRES(0); + PCB_ACT_CONVARG(1, FGW_STR, RouteStyle, str = argv[1].val.str); + + number = strtol(str, &end, 10); + + if (*end != '\0') { /* if not an integer, find by name */ + int n; + number = -1; + for(n = 0; n < vtroutestyle_len(&PCB->RouteStyle); n++) { + rts = &PCB->RouteStyle.array[n]; + if (pcb_strcasecmp(rts->name, str) == 0) { + number = n + 1; + break; + } + } + } + + if (number > 0 && number <= vtroutestyle_len(&PCB->RouteStyle)) { + rts = &PCB->RouteStyle.array[number - 1]; + pcb_board_set_line_width(rts->Thick); + pcb_board_set_via_size(rts->Diameter, pcb_true); + pcb_board_set_via_drilling_hole(rts->Hole, pcb_true); + pcb_board_set_clearance(rts->Clearance); + } + else { + PCB_ACT_IRES(-1); + pcb_message(PCB_MSG_ERROR, "Error: invalid route style name or index\n"); + } + return 0; +} + +/* --------------------------------------------------------------------------- */ + +static const char pcb_acts_CreateMenu[] = "CreateMenu(path)\nCreateMenu(path, action, tooltip, cookie)"; +static const char pcb_acth_CreateMenu[] = "Creates a new menu, popup (only path specified) or submenu (at least path and action are specified)"; +static fgw_error_t pcb_act_CreateMenu(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + if (pcb_gui == NULL) { + pcb_message(PCB_MSG_ERROR, "Error: can't create menu, there's no GUI hid loaded\n"); + PCB_ACT_IRES(-1); + return 0; + } + + PCB_ACT_CONVARG(1, FGW_STR, CreateMenu, ;); + PCB_ACT_MAY_CONVARG(2, FGW_STR, CreateMenu, ;); + PCB_ACT_MAY_CONVARG(3, FGW_STR, CreateMenu, ;); + PCB_ACT_MAY_CONVARG(4, FGW_STR, CreateMenu, ;); + + if (argc > 1) { + pcb_menu_prop_t props; + + memset(&props, 0, sizeof(props)); + props.action = (argc > 2) ? argv[2].val.str : NULL; + props.tip = (argc > 3) ? argv[3].val.str : NULL; + props.cookie = (argc > 4) ? argv[4].val.str : NULL; + + pcb_gui->create_menu(argv[1].val.str, &props); + + PCB_ACT_IRES(0); + return 0; + } + + PCB_ACT_FAIL(CreateMenu); +} + +/* --------------------------------------------------------------------------- */ + +static const char pcb_acts_RemoveMenu[] = "RemoveMenu(path|cookie)"; +static const char pcb_acth_RemoveMenu[] = "Recursively removes a new menu, popup (only path specified) or submenu. "; +static fgw_error_t pcb_act_RemoveMenu(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + if (pcb_gui == NULL) { + pcb_message(PCB_MSG_ERROR, "can't remove menu, there's no GUI hid loaded\n"); + PCB_ACT_IRES(-1); + return 0; + } + + if (pcb_gui->remove_menu == NULL) { + pcb_message(PCB_MSG_ERROR, "can't remove menu, the GUI doesn't support it\n"); + PCB_ACT_IRES(-1); + return 0; + } + + PCB_ACT_CONVARG(1, FGW_STR, RemoveMenu, ;); + if (pcb_gui->remove_menu(argv[1].val.str) != 0) { + pcb_message(PCB_MSG_ERROR, "failed to remove some of the menu items\n"); + PCB_ACT_IRES(-1); + } + else + PCB_ACT_IRES(0); + return 0; +} + +/* --------------------------------------------------------------------------- */ + +static const char pcb_acts_SetSame[] = "SetSame()"; +static const char pcb_acth_SetSame[] = "Sets current layer and sizes to match indicated item."; +/* DOC: setsame.html */ +static void set_same_(pcb_coord_t Thick, pcb_coord_t Diameter, pcb_coord_t Hole, pcb_coord_t Clearance, char *Name) +{ + int known; + known = pcb_route_style_lookup(&PCB->RouteStyle, Thick, Diameter, Hole, Clearance, Name); + if (known < 0) { + /* unknown style, set properties */ + if (Thick != -1) { pcb_custom_route_style.Thick = Thick; conf_set_design("design/line_thickness", "%$mS", Thick); } + if (Clearance != -1) { pcb_custom_route_style.Clearance = Clearance; conf_set_design("design/clearance", "%$mS", Clearance); } + if (Diameter != -1) { pcb_custom_route_style.Diameter = Diameter; conf_set_design("design/via_thickness", "%$mS", Diameter); } + if (Hole != -1) { pcb_custom_route_style.Hole = Hole; conf_set_design("design/via_drilling_hole", "%$mS", Hole); } + PCB->pen_attr = NULL; + } + else + pcb_use_route_style_idx(&PCB->RouteStyle, known); +} + +static fgw_error_t pcb_act_SetSame(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + pcb_coord_t x, y; + void *ptr1, *ptr2, *ptr3; + int type; + pcb_layer_t *layer = CURRENT; + + pcb_hid_get_coords("Select item to use properties from", &x, &y, 0); + + type = pcb_search_screen(x, y, CLONE_TYPES, &ptr1, &ptr2, &ptr3); +/* set layer current and size from line or arc */ + switch (type) { + case PCB_OBJ_LINE: + pcb_notify_crosshair_change(pcb_false); + set_same_(((pcb_line_t *) ptr2)->Thickness, -1, -1, ((pcb_line_t *) ptr2)->Clearance / 2, NULL); + layer = (pcb_layer_t *) ptr1; + if (conf_core.editor.mode != PCB_MODE_LINE) + pcb_tool_select_by_id(PCB_MODE_LINE); + pcb_notify_crosshair_change(pcb_true); + pcb_event(PCB_EVENT_ROUTE_STYLES_CHANGED, NULL); + break; + + case PCB_OBJ_ARC: + pcb_notify_crosshair_change(pcb_false); + set_same_(((pcb_arc_t *) ptr2)->Thickness, -1, -1, ((pcb_arc_t *) ptr2)->Clearance / 2, NULL); + layer = (pcb_layer_t *) ptr1; + if (conf_core.editor.mode != PCB_MODE_ARC) + pcb_tool_select_by_id(PCB_MODE_ARC); + pcb_notify_crosshair_change(pcb_true); + pcb_event(PCB_EVENT_ROUTE_STYLES_CHANGED, NULL); + break; + + case PCB_OBJ_POLY: + layer = (pcb_layer_t *) ptr1; + break; + + default: + PCB_ACT_IRES(-1); + return 0; + } + if (layer != CURRENT) { + pcb_layervis_change_group_vis(pcb_layer_id(PCB->Data, layer), pcb_true, pcb_true); + pcb_redraw(); + } + PCB_ACT_IRES(0); + return 0; +} + +/* --------------------------------------------------------------------------- */ + +static const char pcb_acts_SwitchHID[] = "SwitchHID(lesstif|gtk|batch)"; +static const char pcb_acth_SwitchHID[] = "Switch to another HID."; +static fgw_error_t pcb_act_SwitchHID(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + pcb_hid_t *ng; + int chg; + + PCB_ACT_CONVARG(1, FGW_STR, SwitchHID, ;); + ng = pcb_hid_find_gui(argv[1].val.str); + if (ng == NULL) { + pcb_message(PCB_MSG_ERROR, "No such HID."); + PCB_ACT_IRES(-1); + return 0; + } + + pcb_next_gui = ng; + chg = PCB->Changed; + pcb_quit_app(); + PCB->Changed = chg; + + PCB_ACT_IRES(0); + return 0; +} + + +/* --------------------------------------------------------------------------- */ + +/* This action is provided for CLI convenience */ +static const char pcb_acts_FullScreen[] = "FullScreen(on|off|toggle)\n"; +static const char pcb_acth_FullScreen[] = "Hide widgets to get edit area full screen"; + +static fgw_error_t pcb_act_FullScreen(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + int id = -2; + PCB_ACT_MAY_CONVARG(1, FGW_KEYWORD, FullScreen, id = fgw_keyword(&argv[1])); + + PCB_ACT_IRES(0); + switch(id) { + case -2: + case F_Toggle: + conf_setf(CFR_DESIGN, "editor/fullscreen", -1, "%d", !conf_core.editor.fullscreen, POL_OVERWRITE); + break; + case F_On: + conf_set(CFR_DESIGN, "editor/fullscreen", -1, "1", POL_OVERWRITE); + break; + case F_Off: + conf_set(CFR_DESIGN, "editor/fullscreen", -1, "0", POL_OVERWRITE); + break; + default: + PCB_ACT_FAIL(FullScreen); + } + return 0; +} + +static const char pcb_acts_Cursor[] = "Cursor(Type,DeltaUp,DeltaRight,Units)"; +static const char pcb_acth_Cursor[] = "Move the cursor."; +/* DOC: cursor.html */ +static fgw_error_t pcb_act_Cursor(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + pcb_unit_list_t extra_units_x = { + {"grid", 0, 0}, + {"view", 0, PCB_UNIT_PERCENT}, + {"board", 0, PCB_UNIT_PERCENT}, + {"", 0, 0} + }; + pcb_unit_list_t extra_units_y = { + {"grid", 0, 0}, + {"view", 0, PCB_UNIT_PERCENT}, + {"board", 0, PCB_UNIT_PERCENT}, + {"", 0, 0} + }; + int op, pan_warp = HID_SC_DO_NOTHING; + double dx, dy; + pcb_coord_t view_width, view_height; + const char *a1, *a2, *a3; + + extra_units_x[0].scale = PCB->Grid; + extra_units_x[2].scale = PCB->MaxWidth; + + extra_units_y[0].scale = PCB->Grid; + extra_units_y[2].scale = PCB->MaxHeight; + + pcb_gui->get_view_size(&view_width, &view_height); + + extra_units_x[1].scale = view_width; + extra_units_y[1].scale = view_height; + + PCB_ACT_CONVARG(1, FGW_KEYWORD, Cursor, op = fgw_keyword(&argv[1])); + PCB_ACT_CONVARG(2, FGW_STR, Cursor, a1 = argv[2].val.str); + PCB_ACT_CONVARG(3, FGW_STR, Cursor, a2 = argv[3].val.str); + PCB_ACT_CONVARG(4, FGW_STR, Cursor, a3 = argv[4].val.str); + + if (op == F_Pan) + pan_warp = HID_SC_PAN_VIEWPORT; + else if (op == F_Warp) + pan_warp = HID_SC_WARP_POINTER; + else + PCB_ACT_FAIL(Cursor); + + dx = pcb_get_value_ex(a1, a3, NULL, extra_units_x, "", NULL); + if (conf_core.editor.view.flip_x) + dx = -dx; + dy = pcb_get_value_ex(a2, a3, NULL, extra_units_y, "", NULL); + if (!conf_core.editor.view.flip_y) + dy = -dy; + + /* Allow leaving snapped pin/pad/padstack */ + if (pcb_crosshair.snapped_pstk) { + pcb_pstk_t *ps = pcb_crosshair.snapped_pstk; + pcb_coord_t radius = ((ps->BoundingBox.X2 - ps->BoundingBox.X1) + (ps->BoundingBox.Y2 - ps->BoundingBox.Y1))/2; + if (dx < 0) + dx -= radius; + else if (dx > 0) + dx += radius; + if (dy < 0) + dy -= radius; + else if (dy > 0) + dy += radius; + } + + pcb_event_move_crosshair(pcb_crosshair.X + dx, pcb_crosshair.Y + dy); + pcb_gui->set_crosshair(pcb_crosshair.X, pcb_crosshair.Y, pan_warp); + + PCB_ACT_IRES(0); + return 0; +} + + +#define istrue(s) ((*(s) == '1') || (*(s) == 'y') || (*(s) == 'Y') || (*(s) == 't') || (*(s) == 'T')) + +static const char pcb_acts_EditLayer[] = "Editlayer([@layer], [name=text|auto=[0|1]|sub=[0|1])]\nEditlayer([@layer], attrib, key=value)"; +static const char pcb_acth_EditLayer[] = "Change a property or attribute of a layer. If the first argument starts with @, it is taken as the layer name to manipulate, else the action uses the current layer. Without arguments or if only a layer name is specified, interactive runs editing."; +static fgw_error_t pcb_act_EditLayer(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + int ret = 0, n, interactive = 1, explicit = 0; + pcb_layer_t *ly = CURRENT; + + for(n = 1; n < argc; n++) { + const char *arg; + PCB_ACT_CONVARG(n, FGW_STR, EditLayer, arg = argv[n].val.str); + if (!explicit && (*arg == '@')) { + pcb_layer_id_t lid = pcb_layer_by_name(PCB->Data, arg+1); + if (lid < 0) { + pcb_message(PCB_MSG_ERROR, "Can't find layer named %s\n", arg+1); + return 1; + } + ly = pcb_get_layer(PCB->Data, lid); + explicit = 1; + } + else if (strncmp(arg, "name=", 5) == 0) { + interactive = 0; + ret |= pcb_layer_rename_(ly, pcb_strdup(arg+5)); + pcb_board_set_changed_flag(pcb_true); + } + else if (strncmp(arg, "auto=", 5) == 0) { + interactive = 0; + if (istrue(arg+5)) + ly->comb |= PCB_LYC_AUTO; + else + ly->comb &= ~PCB_LYC_AUTO; + pcb_board_set_changed_flag(pcb_true); + } + else if (strncmp(arg, "sub=", 4) == 0) { + interactive = 0; + if (istrue(arg+4)) + ly->comb |= PCB_LYC_SUB; + else + ly->comb &= ~PCB_LYC_SUB; + pcb_board_set_changed_flag(pcb_true); + } + else if (strncmp(arg, "attrib", 6) == 0) { + char *key, *val; + interactive = 0; + n++; + if (n >= argc) { + pcb_message(PCB_MSG_ERROR, "Need an attribute name=value\n", arg+1); + return 1; + } + key = pcb_strdup(arg); + val = strchr(key, '='); + if (val != NULL) { + *val = '\0'; + val++; + if (*val == '\0') + val = NULL; + } + if (val == NULL) + ret |= pcb_attribute_remove(&ly->Attributes, key); + else + ret |= pcb_attribute_put(&ly->Attributes, key, val); + free(key); + pcb_board_set_changed_flag(pcb_true); + } + else { + pcb_message(PCB_MSG_ERROR, "Invalid EditLayer() command: %s\n", arg); + PCB_ACT_FAIL(EditLayer); + } + } + + if (interactive) { + char fn[PCB_ACTION_NAME_MAX]; + fgw_arg_t args[2]; + args[0].type = FGW_FUNC; + args[0].val.func = fgw_func_lookup(&pcb_fgw, pcb_aname(fn, "LayerPropGui")); + if (args[0].val.func != NULL) { + args[1].type = FGW_LONG; + args[1].val.nat_long = pcb_layer_id(PCB->Data, ly); + ret = pcb_actionv_(args[0].val.func, res, 2, args); + pcb_event(PCB_EVENT_LAYERS_CHANGED, NULL); + } + else + return FGW_ERR_NOT_FOUND; + return ret; + } + + pcb_event(PCB_EVENT_LAYERS_CHANGED, NULL); + PCB_ACT_IRES(0); + return ret; +} + +pcb_layergrp_id_t pcb_actd_EditGroup_gid = -1; +static const char pcb_acts_EditGroup[] = "Editgroup([@group], [name=text|type=+bit|type=-bit])]\nEditlayer([@layer], attrib, key=value)"; +static const char pcb_acth_EditGroup[] = "Change a property or attribute of a layer group. If the first argument starts with @, it is taken as the group name to manipulate, else the action uses the current layer's group. Without arguments or if only a layer name is specified, interactive runs editing."; +static fgw_error_t pcb_act_EditGroup(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + int ret = 0, n, interactive = 1, explicit = 0; + pcb_layergrp_t *g = NULL; + + if (CURRENT->is_bound) { + pcb_message(PCB_MSG_ERROR, "Can't edit bound layers yet\n"); + PCB_ACT_IRES(1); + return 0; + } + + if (CURRENT != NULL) + g = pcb_get_layergrp(PCB, CURRENT->meta.real.grp); + + for(n = 1; n < argc; n++) { + const char *arg; + PCB_ACT_CONVARG(n, FGW_STR, EditLayer, arg = argv[n].val.str); + if (!explicit && (*arg == '@')) { + pcb_layergrp_id_t gid; + if (arg[1] == '\0') + gid = pcb_actd_EditGroup_gid; + else + gid = pcb_layergrp_by_name(PCB, arg+1); + if (gid < 0) { + pcb_message(PCB_MSG_ERROR, "Can't find layer group named %s\n", arg+1); + PCB_ACT_IRES(1); + return 0; + } + g = pcb_get_layergrp(PCB, gid); + explicit = 1; + } + else if (strncmp(arg, "name=", 5) == 0) { + interactive = 0; + ret |= pcb_layergrp_rename_(g, pcb_strdup(arg+5)); + pcb_board_set_changed_flag(pcb_true); + } + else if (strncmp(arg, "type=", 5) == 0) { + const char *sbit = arg+5; + pcb_layer_type_t bit = pcb_layer_type_str2bit(sbit+1); + if (bit == 0) { + if (strcmp(sbit+1, "anything") == 0) bit = PCB_LYT_ANYTHING; + else if (strcmp(sbit+1, "anywhere") == 0) bit = PCB_LYT_ANYWHERE; + } + if (bit == 0) { + pcb_message(PCB_MSG_ERROR, "Unknown type bit %s\n", sbit+1); + PCB_ACT_IRES(1); + return 0; + } + switch(*sbit) { + case '+': g->ltype |= bit; break; + case '-': g->ltype &= ~bit; break; + } + interactive = 0; + pcb_board_set_changed_flag(pcb_true); + } + else if (strncmp(arg, "attrib", 6) == 0) { + char *key, *val; + interactive = 0; + n++; + if (n >= argc) { + pcb_message(PCB_MSG_ERROR, "Need an attribute name=value\n", arg+1); + PCB_ACT_IRES(1); + return 0; + } + key = pcb_strdup(arg); + val = strchr(key, '='); + if (val != NULL) { + *val = '\0'; + val++; + if (*val == '\0') + val = NULL; + } + if (val == NULL) + ret |= pcb_attribute_remove(&g->Attributes, key); + else + ret |= pcb_attribute_put(&g->Attributes, key, val); + free(key); + } + else { + pcb_message(PCB_MSG_ERROR, "Invalid EditGroup() command: %s\n", arg); + PCB_ACT_FAIL(EditLayer); + } + } + + if (interactive) { + char fn[PCB_ACTION_NAME_MAX]; + fgw_arg_t args[2]; + args[0].type = FGW_FUNC; + args[0].val.func = fgw_func_lookup(&pcb_fgw, pcb_aname(fn, "GroupPropGui")); + if (args[0].val.func != NULL) { + args[1].type = FGW_LONG; + args[1].val.nat_long = pcb_layergrp_id(PCB, g); + ret = pcb_actionv_(args[0].val.func, res, 2, args); + pcb_event(PCB_EVENT_LAYERS_CHANGED, NULL); + } + else + return FGW_ERR_NOT_FOUND; + return ret; + + } + + pcb_event(PCB_EVENT_LAYERS_CHANGED, NULL); + PCB_ACT_IRES(0); + return ret; +} + +static const char pcb_acts_DelGroup[] = "DelGroup([@group])"; +static const char pcb_acth_DelGroup[] = "Remove a layer group; if the first argument is not specified, the current group is removed"; +static fgw_error_t pcb_act_DelGroup(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + const char *name = NULL; + pcb_layergrp_t *g = NULL; + pcb_layergrp_id_t gid; + + if (CURRENT != NULL) + g = pcb_get_layergrp(PCB, CURRENT->meta.real.grp); + + PCB_ACT_MAY_CONVARG(1, FGW_STR, DelGroup, name = argv[1].val.str); + if (*name == '@') { + gid = pcb_actd_EditGroup_gid; + if (name[1] != '\0') + gid = pcb_layergrp_by_name(PCB, name+1); + if (gid < 0) { + pcb_message(PCB_MSG_ERROR, "Can't find layer group named %s\n", name+1); + PCB_ACT_IRES(1); + return 0; + } + } + else { + if (g == NULL) { + pcb_message(PCB_MSG_ERROR, "Can't find layer group\n"); + PCB_ACT_IRES(1); + return 0; + } + gid = pcb_layergrp_id(PCB, g); + } + + PCB_ACT_IRES(pcb_layergrp_del(PCB, gid, 1)); + return 0; +} + +static const char pcb_acts_NewGroup[] = "NewGroup(type [,location [, purpose[, auto|sub]]])"; +static const char pcb_acth_NewGroup[] = "Create a new layer group with a single, positive drawn layer in it"; +static fgw_error_t pcb_act_NewGroup(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + const char *stype = NULL, *sloc = NULL, *spurp = NULL, *scomb = NULL; + pcb_layergrp_t *g = NULL; + pcb_layer_type_t ltype = 0, lloc = 0; + + PCB_ACT_CONVARG(1, FGW_STR, NewGroup, stype = argv[1].val.str); + PCB_ACT_MAY_CONVARG(2, FGW_STR, NewGroup, sloc = argv[2].val.str); + PCB_ACT_MAY_CONVARG(3, FGW_STR, NewGroup, spurp = argv[3].val.str); + PCB_ACT_MAY_CONVARG(4, FGW_STR, NewGroup, scomb = argv[4].val.str); + + ltype = pcb_layer_type_str2bit(stype) & PCB_LYT_ANYTHING; + if (ltype == 0) { + pcb_message(PCB_MSG_ERROR, "Invalid type: '%s'\n", sloc); + PCB_ACT_IRES(-1); + return 0; + } + + if ((ltype == PCB_LYT_COPPER) || (ltype == PCB_LYT_SUBSTRATE)) { + pcb_message(PCB_MSG_ERROR, "Can not create this type of layer group: '%s'\n", sloc); + PCB_ACT_IRES(-1); + return 0; + } + + if (sloc != NULL) { + if (strcmp(sloc, "global") != 0) { + lloc = pcb_layer_type_str2bit(sloc) & PCB_LYT_ANYWHERE; + if (lloc == 0) { + pcb_message(PCB_MSG_ERROR, "Invalid location: '%s'\n", sloc); + PCB_ACT_IRES(-1); + return 0; + } + } + } + + pcb_layergrp_inhibit_inc(); + g = pcb_get_grp_new_misc(PCB); + if (g != NULL) { + pcb_layer_id_t lid; + + if (spurp != NULL) + pcb_layergrp_set_purpose__(g, pcb_strdup(spurp)); + + free(g->name); + g->name = pcb_strdup_printf("%s%s%s", sloc == NULL ? "" : sloc, sloc == NULL ? "" : "-", stype); + g->ltype = ltype | lloc; + g->vis = 1; + g->open = 1; + lid = pcb_layer_create(PCB, g - PCB->LayerGroups.grp, stype); + if (lid >= 0) { + pcb_layer_t *ly; + PCB_ACT_IRES(0); + ly = &PCB->Data->Layer[lid]; + ly->meta.real.vis = 1; + if (scomb != NULL) { + if (strstr(scomb, "auto") != NULL) ly->comb |= PCB_LYC_AUTO; + if (strstr(scomb, "sub") != NULL) ly->comb |= PCB_LYC_SUB; + } + } + else + PCB_ACT_IRES(-1); + + } + else + PCB_ACT_IRES(-1); + pcb_layergrp_inhibit_dec(); + + pcb_event(PCB_EVENT_LAYERS_CHANGED, NULL); + if ((pcb_gui != NULL) && (pcb_exporter == NULL)) + pcb_gui->invalidate_all(); + + return 0; +} + +static const char pcb_acts_DupGroup[] = "DupGroup([@group])"; +static const char pcb_acth_DupGroup[] = "Duplicate a layer group; if the first argument is not specified, the current group is duplicated"; +static fgw_error_t pcb_act_DupGroup(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + const char *name = NULL; + pcb_layergrp_t *g = NULL; + pcb_layergrp_id_t gid, ng; + + if (CURRENT != NULL) + g = pcb_get_layergrp(PCB, CURRENT->meta.real.grp); + + PCB_ACT_MAY_CONVARG(1, FGW_STR, DupGroup, name = argv[1].val.str); + if (*name == '@') { + gid = pcb_actd_EditGroup_gid; + if (name[1] != '\0') + gid = pcb_layergrp_by_name(PCB, name+1); + if (gid < 0) { + pcb_message(PCB_MSG_ERROR, "Can't find layer group named %s\n", name+1); + PCB_ACT_IRES(1); + return 0; + } + } + else { + if (g == NULL) { + pcb_message(PCB_MSG_ERROR, "Can't find layer group\n"); + PCB_ACT_IRES(1); + return 0; + } + gid = pcb_layergrp_id(PCB, g); + } + + pcb_layergrp_inhibit_inc(); + ng = pcb_layergrp_dup(PCB, gid, 1); + if (ng >= 0) { + pcb_layer_id_t lid = pcb_layer_create(PCB, ng, g->name); + if (lid >= 0) { + PCB_ACT_IRES(0); + PCB->Data->Layer[lid].meta.real.vis = 1; + } + else + PCB_ACT_IRES(-1); + } + else + PCB_ACT_IRES(-1); + pcb_layergrp_inhibit_dec(); + + pcb_event(PCB_EVENT_LAYERS_CHANGED, NULL); + if ((pcb_gui != NULL) && (pcb_exporter == NULL)) + pcb_gui->invalidate_all(); + + return 0; +} + +const char pcb_acts_selectlayer[] = "SelectLayer(1..MAXLAYER|Silk|Rats)"; +const char pcb_acth_selectlayer[] = "Select which layer is the current layer."; +/* DOC: selectlayer.html */ +static fgw_error_t pcb_act_SelectLayer(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + pcb_layer_id_t lid; + const pcb_menu_layers_t *ml; + char *name; + + PCB_ACT_IRES(0); + PCB_ACT_CONVARG(1, FGW_STR, selectlayer, name = argv[1].val.str); + + if (pcb_strcasecmp(name, "silk") == 0) { + PCB->RatDraw = 0; + if (pcb_layer_list(PCB, PCB_LYT_VISIBLE_SIDE() | PCB_LYT_SILK, &lid, 1) > 0) { + pcb_layervis_change_group_vis(lid, 1, 1); + } + else { + pcb_message(PCB_MSG_ERROR, "Can't find this-side silk layer\n"); + PCB_ACT_IRES(-1); + } + return 0; + } + + ml = pcb_menu_layer_find(name); + if (ml != NULL) { + pcb_bool *v = (pcb_bool *)((char *)PCB + ml->vis_offs); + pcb_bool *s = (pcb_bool *)((char *)PCB + ml->sel_offs); + if (ml->sel_offs == 0) { + pcb_message(PCB_MSG_ERROR, "Virtual layer '%s' (%s) can not be selected\n", ml->name, ml->abbrev); + PCB_ACT_IRES(-1); + return 0; + } + *s = *v = 1; + pcb_event(PCB_EVENT_LAYERVIS_CHANGED, NULL); + return 0; + } + + PCB->RatDraw = 0; + pcb_layervis_change_group_vis(atoi(name)-1, 1, 1); + pcb_gui->invalidate_all(); + pcb_event(PCB_EVENT_LAYERVIS_CHANGED, NULL); + return 0; +} + +const char pcb_acts_chklayer[] = "ChkLayer(layerid)"; +const char pcb_acth_chklayer[] = "Returns 1 if the specified layer is the active layer"; +/* DOC: chklayer.html */ +static fgw_error_t pcb_act_ChkLayer(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + pcb_layer_id_t lid; + pcb_layer_t *ly; + char *end; + const char *name; + const pcb_menu_layers_t *ml; + + PCB_ACT_CONVARG(1, FGW_STR, chklayer, name = argv[1].val.str); + + lid = strtol(name, &end, 10); + if (*end != '\0') { + ml = pcb_menu_layer_find(name); + if (ml != NULL) { + if (ml->sel_offs != 0) { + pcb_bool *s = (pcb_bool *)((char *)PCB + ml->sel_offs); + PCB_ACT_IRES(*s); + } + else + PCB_ACT_IRES(-1); + return 0; + } + pcb_message(PCB_MSG_ERROR, "pcb_act_ChkLayer: '%s' is not a valid layer ID - check your menu file!\n", argv[0]); + PCB_ACT_IRES(-1); + return 0; + } + + /* if any virtual is selected, do not accept CURRENT as selected */ + for(ml = pcb_menu_layers; ml->name != NULL; ml++) { + pcb_bool *s = (pcb_bool *)((char *)PCB + ml->sel_offs); + if ((ml->sel_offs != 0) && (*s)) { + PCB_ACT_IRES(0); + return 0; + } + } + + lid--; + ly = pcb_get_layer(PCB->Data, lid); + if (ly == NULL) + PCB_ACT_IRES(-1); + else + PCB_ACT_IRES(ly == CURRENT); + return 0; +} + + +const char pcb_acts_toggleview[] = "ToggleView(1..MAXLAYER)\n" "ToggleView(layername)\n" "ToggleView(Silk|Rats|Pins|Vias|BackSide)\n" "ToggleView(All, Open|Vis, Set|Clear|Toggle)"; +const char pcb_acth_toggleview[] = "Toggle the visibility of the specified layer or layer group."; +/* DOC: toggleview.html */ +static fgw_error_t pcb_act_ToggleView(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + pcb_layer_id_t lid; + const char *name; + + PCB_ACT_CONVARG(1, FGW_STR, toggleview, name = argv[1].val.str); + PCB_ACT_IRES(0); + + if (pcb_strcasecmp(name, "all") == 0) { + pcb_bool_op_t open = PCB_BOOL_PRESERVE, vis = PCB_BOOL_PRESERVE, user = PCB_BOOL_PRESERVE; + const char *cmd, *suser; + PCB_ACT_CONVARG(2, FGW_STR, toggleview, cmd = argv[2].val.str); + PCB_ACT_CONVARG(3, FGW_STR, toggleview, suser = argv[3].val.str); + + user = pcb_str2boolop(suser); + if (user == PCB_BOOL_INVALID) + PCB_ACT_FAIL(toggleview); + if (pcb_strcasecmp(cmd, "open") == 0) + open = user; + else if (pcb_strcasecmp(cmd, "vis") == 0) + vis = user; + else + PCB_ACT_FAIL(toggleview); + pcb_layer_vis_change_all(PCB, open, vis); + pcb_gui->invalidate_all(); + pcb_event(PCB_EVENT_LAYERVIS_CHANGED, NULL); + return 0; + } + else if (pcb_strcasecmp(name, "silk") == 0) { + if (pcb_layer_list(PCB, PCB_LYT_VISIBLE_SIDE() | PCB_LYT_SILK, &lid, 1) > 0) + pcb_layervis_change_group_vis(lid, -1, 0); + else + pcb_message(PCB_MSG_ERROR, "Can't find this-side silk layer\n"); + } + else if ((pcb_strcasecmp(name, "padstacks") == 0) || (pcb_strcasecmp(name, "vias") == 0) || (pcb_strcasecmp(name, "pins") == 0) || (pcb_strcasecmp(name, "pads") == 0)) { + PCB->pstk_on = !PCB->pstk_on; + pcb_gui->invalidate_all(); + pcb_event(PCB_EVENT_LAYERVIS_CHANGED, NULL); + } + else if (pcb_strcasecmp(name, "BackSide") == 0) { + PCB->InvisibleObjectsOn = !PCB->InvisibleObjectsOn; + pcb_gui->invalidate_all(); + pcb_event(PCB_EVENT_LAYERVIS_CHANGED, NULL); + } + else if (strncmp(name, "ui:", 3) == 0) { + pcb_layer_t *ly = pcb_uilayer_get(atoi(name+3)); + if (ly == NULL) { + pcb_message(PCB_MSG_ERROR, "Invalid ui layer id: '%s'\n", name); + PCB_ACT_IRES(-1); + return 0; + } + ly->meta.real.vis = !ly->meta.real.vis; + pcb_gui->invalidate_all(); + pcb_event(PCB_EVENT_LAYERVIS_CHANGED, NULL); + } + else { + char *end; + int id = strtol(name, &end, 10) - 1; + if (*end == '\0') { /* integer layer */ + pcb_layervis_change_group_vis(id, -1, 0); + pcb_gui->invalidate_all(); + pcb_event(PCB_EVENT_LAYERVIS_CHANGED, NULL); + return 0; + } + else { /* virtual menu layer */ + const pcb_menu_layers_t *ml = pcb_menu_layer_find(name); + if (ml != NULL) { + pcb_bool *v = (pcb_bool *)((char *)PCB + ml->vis_offs); + *v = !(*v); + pcb_gui->invalidate_all(); + pcb_event(PCB_EVENT_LAYERVIS_CHANGED, NULL); + return 0; + } + pcb_message(PCB_MSG_ERROR, "Invalid layer id: '%s'\n", name); + } + } + + PCB_ACT_IRES(1); + return 0; +} + +const char pcb_acts_chkview[] = "ChkView(layerid)\n"; +const char pcb_acth_chkview[] = "Return 1 if layerid is visible."; +/* DOC: chkview.html */ +static fgw_error_t pcb_act_ChkView(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + pcb_layer_id_t lid; + pcb_layer_t *ly; + char *end; + const char *name; + + PCB_ACT_CONVARG(1, FGW_STR, chkview, name = argv[1].val.str); + + if (strncmp(name, "ui:", 3) == 0) { + pcb_layer_t *ly = pcb_uilayer_get(atoi(name+3)); + if (ly == NULL) { + PCB_ACT_IRES(-1); + return 0; + } + PCB_ACT_IRES(ly->meta.real.vis); + return 0; + } + + lid = strtol(name, &end, 10); + + if (*end != '\0') { + const pcb_menu_layers_t *ml = pcb_menu_layer_find(name); + + if (ml != NULL) { + pcb_bool *v = (pcb_bool *)((char *)PCB + ml->vis_offs); + PCB_ACT_IRES(*v); + return 0; + } + + pcb_message(PCB_MSG_ERROR, "pcb_act_ChkView: '%s' is not a valid layer ID - check your menu file!\n", name); + return FGW_ERR_ARGV_TYPE; + } + + lid--; + ly = pcb_get_layer(PCB->Data, lid); + if (ly == NULL) { + PCB_ACT_IRES(-1); + return 0; + } + + PCB_ACT_IRES(ly->meta.real.vis); + return 0; +} + + +static const char pcb_acts_setunits[] = "SetUnits(mm|mil)"; +static const char pcb_acth_setunits[] = "Set the default measurement units."; +/* DOC: setunits.html */ +static fgw_error_t pcb_act_SetUnits(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + const pcb_unit_t *new_unit; + const char *name; + + PCB_ACT_CONVARG(1, FGW_STR, setunits, name = argv[1].val.str); + PCB_ACT_IRES(0); + + new_unit = get_unit_struct(name); + pcb_board_set_unit(PCB, new_unit); + + return 0; +} + +static const char pcb_acts_grid[] = + "grid(set, [name:]size[@offs][!unit])\n" + "grid(+|up)\n" "grid(-|down)\n" "grid(#N)\n" "grid(idx, N)\n"; +static const char pcb_acth_grid[] = "Set the grid."; +static fgw_error_t pcb_act_grid(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + const char *op, *a; + + PCB_ACT_CONVARG(1, FGW_STR, grid, op = argv[1].val.str); + PCB_ACT_IRES(0); + + if (strcmp(op, "set") == 0) { + pcb_grid_t dst; + PCB_ACT_CONVARG(2, FGW_STR, grid, a = argv[2].val.str); + if (!pcb_grid_parse(&dst, a)) + PCB_ACT_FAIL(grid); + pcb_grid_set(PCB, &dst); + pcb_grid_free(&dst); + } + else if ((strcmp(op, "up") == 0) || (strcmp(op, "+") == 0)) + pcb_grid_list_step(+1); + else if ((strcmp(op, "down") == 0) || (strcmp(op, "-") == 0)) + pcb_grid_list_step(-1); + else if (strcmp(op, "idx") == 0) { + PCB_ACT_CONVARG(2, FGW_STR, grid, a = argv[2].val.str); + pcb_grid_list_jump(atoi(a)); + } + else if (op[0] == '#') { + pcb_grid_list_jump(atoi(op+1)); + } + else + PCB_ACT_FAIL(grid); + + return 0; +} + +const char pcb_acts_chkrst[] = "ChkRst(route_style_id)\n"; +const char pcb_acth_chkrst[] = "Return 1 if route_style_id matches pen."; +/* DOC: chkrst.html */ +static fgw_error_t pcb_act_ChkRst(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + int rid; + pcb_route_style_t *rst; + + PCB_ACT_CONVARG(1, FGW_INT, chkrst, rid = argv[1].val.nat_int); + + rst = vtroutestyle_get(&PCB->RouteStyle, rid, 0); + if (rst == NULL) + PCB_ACT_IRES(-1); + else + PCB_ACT_IRES(pcb_route_style_match(rst, conf_core.design.line_thickness, conf_core.design.via_thickness, conf_core.design.via_drilling_hole, conf_core.design.clearance, NULL)); + return 0; +} + +static const char pcb_acts_GetXY[] = "GetXY()"; +static const char pcb_acth_GetXY[] = "Get a coordinate."; +/* DOC: getxy.html */ +static fgw_error_t pcb_act_GetXY(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + pcb_coord_t x, y; + const char *msg = "Click to enter a coordinate."; + PCB_ACT_MAY_CONVARG(1, FGW_STR, GetXY, msg = argv[1].val.str); + PCB_ACT_IRES(0); + pcb_hid_get_coords(msg, &x, &y, 0); + return 0; +} + +static const char pcb_acts_boardflip[] = "BoardFlip([sides])"; +static const char pcb_acth_boardflip[] = "Mirror the board over the x axis, optionally mirroring sides as well."; +/* DOC: boardflip.html */ +static fgw_error_t pcb_act_boardflip(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + int op = -2; + pcb_bool smirror; + + PCB_ACT_MAY_CONVARG(1, FGW_KEYWORD, boardflip, op = fgw_keyword(&argv[1])); + + smirror = (op == F_Sides); + pcb_data_mirror(PCB->Data, 0, smirror ? PCB_TXM_SIDE : PCB_TXM_COORD, smirror); + + PCB_ACT_IRES(0); + return 0; +} + +static const char pcb_acts_ClipInhibit[] = "ClipInhibit([on|off|check])"; +static const char pcb_acth_ClipInhibit[] = "ClipInhibit Feature Template."; +static fgw_error_t pcb_act_ClipInhibit(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + static int is_on = 0; + int target; + const char *op; + char tmp[2]; + + PCB_ACT_CONVARG(1, FGW_STR, ClipInhibit, op = argv[1].val.str); + + if (strcmp(op, "check") == 0) { + PCB_ACT_IRES(is_on); + return 0; + } + + + if (strcmp(op, "toggle") == 0) { + target = !is_on; + } + else { + if (op[0] != 'o') + PCB_ACT_FAIL(ClipInhibit); + + switch(op[1]) { + case 'n': target = 1; break; + case 'f': target = 0; break; + default: PCB_ACT_FAIL(ClipInhibit); + } + } + + if (is_on == target) { + PCB_ACT_IRES(0); + return 0; + } + + is_on = target; + if (is_on) + pcb_data_clip_inhibit_inc(PCB->Data); + else + pcb_data_clip_inhibit_dec(PCB->Data, 1); + + tmp[0] = '0' + !conf_core.temp.clip_inhibit_chg; + tmp[1] = '\0'; + conf_set(CFR_CLI, "temp/clip_inhibit_chg", 0, tmp, POL_OVERWRITE); + + + PCB_ACT_IRES(0); + return 0; +} + +static const char pcb_acts_Benchmark[] = "Benchmark()"; +static const char pcb_acth_Benchmark[] = "Benchmark the GUI speed."; +/* DOC: benchmark.html */ +static fgw_error_t pcb_act_Benchmark(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + double fps = 0; + + if ((pcb_gui != NULL) && (pcb_gui->benchmark != NULL)) { + fps = pcb_gui->benchmark(); + pcb_message(PCB_MSG_INFO, "%f redraws per second\n", fps); + } + else + pcb_message(PCB_MSG_ERROR, "benchmark is not available in the current HID\n"); + + PCB_ACT_DRES(fps); + return 0; +} + +pcb_action_t gui_action_list[] = { + {"Display", pcb_act_Display, pcb_acth_Display, pcb_acts_Display}, + {"CycleDrag", pcb_act_CycleDrag, pcb_acth_CycleDrag, pcb_acts_CycleDrag}, + {"FullScreen", pcb_act_FullScreen, pcb_acth_FullScreen, pcb_acts_FullScreen}, + {"MarkCrosshair", pcb_act_MarkCrosshair, pcb_acth_MarkCrosshair, pcb_acts_MarkCrosshair}, + {"Message", pcb_act_Message, pcb_acth_Message, pcb_acts_Message}, + {"Mode", pcb_act_Mode, pcb_acth_Mode, pcb_acts_Mode}, + {"SetSame", pcb_act_SetSame, pcb_acth_SetSame, pcb_acts_SetSame}, + {"RouteStyle", pcb_act_RouteStyle, pcb_acth_RouteStyle, pcb_acts_RouteStyle}, + {"CreateMenu", pcb_act_CreateMenu, pcb_acth_CreateMenu, pcb_acts_CreateMenu}, + {"RemoveMenu", pcb_act_RemoveMenu, pcb_acth_RemoveMenu, pcb_acts_RemoveMenu}, + {"SelectLayer", pcb_act_SelectLayer, pcb_acth_selectlayer, pcb_acts_selectlayer}, + {"ChkLayer", pcb_act_ChkLayer, pcb_acth_chklayer, pcb_acts_chklayer}, + {"SwitchHID", pcb_act_SwitchHID, pcb_acth_SwitchHID, pcb_acts_SwitchHID}, + {"ToggleView", pcb_act_ToggleView, pcb_acth_toggleview, pcb_acts_toggleview}, + {"ChkView", pcb_act_ChkView, pcb_acth_chkview, pcb_acts_chkview}, + {"Cursor", pcb_act_Cursor, pcb_acth_Cursor, pcb_acts_Cursor}, + {"EditLayer", pcb_act_EditLayer, pcb_acth_EditLayer, pcb_acts_EditLayer}, + {"EditGroup", pcb_act_EditGroup, pcb_acth_EditGroup, pcb_acts_EditGroup}, + {"DelGroup", pcb_act_DelGroup, pcb_acth_DelGroup, pcb_acts_DelGroup}, + {"DupGroup", pcb_act_DupGroup, pcb_acth_DupGroup, pcb_acts_DupGroup}, + {"NewGroup", pcb_act_NewGroup, pcb_acth_NewGroup, pcb_acts_NewGroup}, + {"Grid", pcb_act_grid, pcb_acth_grid, pcb_acts_grid}, + {"SetUnits", pcb_act_SetUnits, pcb_acth_setunits, pcb_acts_setunits}, + {"ChkRst", pcb_act_ChkRst, pcb_acth_chkrst, pcb_acts_chkrst}, + {"GetXY", pcb_act_GetXY, pcb_acth_GetXY, pcb_acts_GetXY}, + {"BoardFlip", pcb_act_boardflip, pcb_acth_boardflip, pcb_acts_boardflip}, + {"ClipInhibit", pcb_act_ClipInhibit, pcb_acth_ClipInhibit, pcb_acts_ClipInhibit}, + {"Benchmark", pcb_act_Benchmark, pcb_acth_Benchmark, pcb_acts_Benchmark} +}; + +PCB_REGISTER_ACTIONS(gui_action_list, NULL) Index: tags/2.1.2/src/heap.c =================================================================== --- tags/2.1.2/src/heap.c (nonexistent) +++ tags/2.1.2/src/heap.c (revision 24813) @@ -0,0 +1,233 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * Copyright (C) 1998,1999,2000,2001 harry eaton + * + * this file, heap.c, was written and is + * Copyright (c) 2001 C. Scott Ananian. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + * + * Old contact info: + * harry eaton, 6697 Buttonhole Ct, Columbia, MD 21044 USA + * haceaton@aplcomm.jhuapl.edu + * + */ + + +/* operations on heaps. */ + +#include +#include +#include "config.h" +#include "heap.h" + +/* define this for more thorough self-checking of data structures */ +#undef SLOW_ASSERTIONS + +struct heap_element { + pcb_cost_t cost; + void *data; +}; +struct pcb_heap_s { + struct heap_element *element; + int size, max; +}; + +static pcb_cost_t MIN_COST = 0; + +/* --------------------------------------------------------------------------- + * functions. + */ +/* helper functions for assertions */ +#ifndef NDEBUG +#ifdef SLOW_ASSERTIONS +static int __heap_is_good_slow(pcb_heap_t * heap) +{ + int i; + /* heap condition: key in each node should be smaller than in its children */ + /* alternatively (and this is what we check): key in each node should be + * larger than (or equal to) key of its parent. */ + /* note that array element[0] is not used (except as a sentinel) */ + for (i = 2; i < heap->size; i++) + if (heap->element[i].cost < heap->element[i / 2].cost) + return 0; + return 1; +} +#endif /* SLOW_ASSERTIONS */ +static int __heap_is_good(pcb_heap_t * heap) +{ + return heap && (heap->max == 0 || heap->element) && + (heap->max >= 0) && (heap->size >= 0) && (heap->max == 0 || heap->size < heap->max) && +#ifdef SLOW_ASSERTIONS + __heap_is_good_slow(heap) && +#endif + 1; +} +#endif /* ! NDEBUG */ + +/* create an empty heap */ +pcb_heap_t *pcb_heap_create() +{ + pcb_heap_t *heap; + /* initialize MIN_COST if necessary */ + if (MIN_COST == 0) + MIN_COST = -1e23; + assert(MIN_COST < 0); + /* okay, create empty heap */ + heap = (pcb_heap_t *) calloc(1, sizeof(*heap)); + assert(heap); + assert(__heap_is_good(heap)); + return heap; +} + +/* destroy a heap */ +void pcb_heap_destroy(pcb_heap_t ** heap) +{ + assert(heap && *heap); + assert(__heap_is_good(*heap)); + if ((*heap)->element) + free((*heap)->element); + free(*heap); + *heap = NULL; +} + +/* free all elements in the heap */ +void pcb_heap_free(pcb_heap_t * heap, void (*freefunc) (void *)) +{ + assert(heap); + assert(__heap_is_good(heap)); + for (; heap->size; heap->size--) { + if (heap->element[heap->size].data) + freefunc(heap->element[heap->size].data); + } +} + +/* -- mutation -- */ +static void __upheap(pcb_heap_t * heap, int k) +{ + struct heap_element v; + + assert(heap && heap->size < heap->max); + assert(k <= heap->size); + + v = heap->element[k]; + heap->element[0].cost = MIN_COST; + for (v = heap->element[k]; heap->element[k / 2].cost > v.cost; k = k / 2) + heap->element[k] = heap->element[k / 2]; + heap->element[k] = v; +} + +void pcb_heap_insert(pcb_heap_t * heap, pcb_cost_t cost, void *data) +{ + assert(heap && __heap_is_good(heap)); + assert(cost >= MIN_COST); + + /* determine whether we need to grow the heap */ + if (heap->size + 1 >= heap->max) { + heap->max *= 2; + if (heap->max == 0) + heap->max = 256; /* default initial heap size */ + heap->element = (struct heap_element *) realloc(heap->element, heap->max * sizeof(*heap->element)); + } + heap->size++; + assert(heap->size < heap->max); + heap->element[heap->size].cost = cost; + heap->element[heap->size].data = data; + __upheap(heap, heap->size); /* fix heap condition violation */ + assert(__heap_is_good(heap)); + return; +} + +/* this procedure moves down the heap, exchanging the node at position + * k with the smaller of its two children as necessary and stopping when + * the node at k is smaller than both children or the bottom is reached. + */ +static void __downheap(pcb_heap_t * heap, int k) +{ + struct heap_element v; + + assert(heap && heap->size < heap->max); + assert(k <= heap->size); + + v = heap->element[k]; + while (k <= heap->size / 2) { + int j = k + k; + if (j < heap->size && heap->element[j].cost > heap->element[j + 1].cost) + j++; + if (v.cost < heap->element[j].cost) + break; + heap->element[k] = heap->element[j]; + k = j; + } + heap->element[k] = v; +} + +void *pcb_heap_remove_smallest(pcb_heap_t * heap) +{ + struct heap_element v; + assert(heap && __heap_is_good(heap)); + assert(heap->size > 0); + assert(heap->max > 1); + + v = heap->element[1]; + heap->element[1] = heap->element[heap->size--]; + if (heap->size > 0) + __downheap(heap, 1); + + assert(__heap_is_good(heap)); + return v.data; +} + +void *pcb_heap_replace(pcb_heap_t * heap, pcb_cost_t cost, void *data) +{ + assert(heap && __heap_is_good(heap)); + + if (pcb_heap_is_empty(heap)) + return data; + + assert(heap->size > 0); + assert(heap->max > 1); + + heap->element[0].cost = cost; + heap->element[0].data = data; + __downheap(heap, 0); /* ooh, tricky! */ + + assert(__heap_is_good(heap)); + return heap->element[0].data; +} + +/* -- interrogation -- */ +int pcb_heap_is_empty(pcb_heap_t * heap) +{ + assert(__heap_is_good(heap)); + return heap->size == 0; +} + +/* -- size -- */ +int pcb_heap_size(pcb_heap_t * heap) +{ + assert(__heap_is_good(heap)); + return heap->size; +} Index: tags/2.1.2/src/heap.h =================================================================== --- tags/2.1.2/src/heap.h (nonexistent) +++ tags/2.1.2/src/heap.h (revision 24813) @@ -0,0 +1,68 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * Copyright (C) 1998,1999,2000,2001 harry eaton + * + * this file, heap.h, was written and is + * Copyright (c) 2001 C. Scott Ananian. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + * + * Old contact info: + * harry eaton, 6697 Buttonhole Ct, Columbia, MD 21044 USA + * haceaton@aplcomm.jhuapl.edu + * + */ + +/* Heap used by the polygon code and autoroute */ + +#ifndef PCB_HEAP_H +#define PCB_HEAP_H + +#include "config.h" + +/* type of heap costs */ +typedef double pcb_cost_t; +/* what a heap looks like */ +typedef struct pcb_heap_s pcb_heap_t; + +/* create an empty heap */ +pcb_heap_t *pcb_heap_create(); +/* destroy a heap */ +void pcb_heap_destroy(pcb_heap_t ** heap); +/* free all elements in a heap */ +void pcb_heap_free(pcb_heap_t * heap, void (*funcfree) (void *)); + +/* -- mutation -- */ +void pcb_heap_insert(pcb_heap_t * heap, pcb_cost_t cost, void *data); +void *pcb_heap_remove_smallest(pcb_heap_t * heap); +/* replace the smallest item with a new item and return the smallest item. + * (if the new item is the smallest, than return it, instead.) */ +void *pcb_heap_replace(pcb_heap_t * heap, pcb_cost_t cost, void *data); + +/* -- interrogation -- */ +int pcb_heap_is_empty(pcb_heap_t * heap); +int pcb_heap_size(pcb_heap_t * heap); + +#endif /* PCB_HEAP_H */ Index: tags/2.1.2/src/hid.h =================================================================== --- tags/2.1.2/src/hid.h (nonexistent) +++ tags/2.1.2/src/hid.h (revision 24813) @@ -0,0 +1,581 @@ +#ifndef PCB_HID_H +#define PCB_HID_H + +#include +#include + +#include "config.h" +#include "error.h" +#include "global_typedefs.h" +#include "attrib.h" +#include "layer.h" + +/* attribute dialog properties */ +typedef enum pcb_hat_property_e { + PCB_HATP_GLOBAL_CALLBACK, + PCB_HATP_max +} pcb_hat_property_t; + + +typedef enum { + PCB_HID_MOUSE_PRESS, + PCB_HID_MOUSE_RELEASE, + PCB_HID_MOUSE_MOTION, + PCB_HID_MOUSE_POPUP /* "right click", open context-specific popup */ +} pcb_hid_mouse_ev_t; + + +typedef struct pcb_hid_attr_val_s pcb_hid_attr_val_t; +typedef struct pcb_hid_attribute_s pcb_hid_attribute_t; + +/* Human Interface Device */ + +/* + +The way the HID layer works is that you instantiate a HID device +structure, and invoke functions through its members. Code in the +common part of PCB may *not* rely on *anything* other than what's +defined in this file. Code in the HID layers *may* rely on data and +functions in the common code (like, board size and such) but it's +considered bad form to do so when not needed. + +Coordinates are ALWAYS in pcb's internal units (nanometer at the +moment). Positive X is right, positive Y is down. Angles are +degrees, with 0 being right (positive X) and 90 being up (negative Y). +All zoom, scaling, panning, and conversions are hidden inside the HID +layers. + +The main structure is at the end of this file. + +Data structures passed to the HIDs will be copied if the HID needs to +save them. Data structures returned from the HIDs must not be freed, +and may be changed by the HID in response to new information. + +*/ + +/* Line end cap styles. The cap *always* extends beyond the + coordinates given, by half the width of the line. */ +typedef enum { + pcb_cap_invalid = -1, + pcb_cap_square, /* square pins or pads when drawn using a line */ + pcb_cap_round /* for normal traces, round pins */ +} pcb_cap_style_t; + +/* The HID may need something more than an "int" for colors, timers, + etc. So it passes/returns one of these, which is castable to a + variety of things. */ +typedef union { + long lval; + void *ptr; +} pcb_hidval_t; + +typedef struct { + pcb_coord_t width; /* as set by set_line_width */ + pcb_cap_style_t cap; /* as set by set_line_cap */ + int xor; /* as set by set_draw_xor */ + int faded; /* as set by set_draw_faded */ +} pcb_core_gc_t; + +/* This graphics context is an opaque pointer defined by the HID. GCs + are HID-specific; attempts to use one HID's GC for a different HID + will result in a fatal error. The first field must be: + pcb_core_gc_t core_gc; */ +typedef struct hid_gc_s *pcb_hid_gc_t; + + +#define PCB_HIDCONCAT(a,b) a##b + +/* File Watch flags */ +/* Based upon those in dbus/dbus-connection.h */ +typedef enum { + PCB_WATCH_READABLE = 1 << 0, /* As in POLLIN */ + PCB_WATCH_WRITABLE = 1 << 1, /* As in POLLOUT */ + PCB_WATCH_ERROR = 1 << 2, /* As in POLLERR */ + PCB_WATCH_HANGUP = 1 << 3 /* As in POLLHUP */ +} pcb_watch_flags_t; + +typedef enum pcb_composite_op_s { + PCB_HID_COMP_RESET, /* reset (allocate and clear) the sketch canvas */ + PCB_HID_COMP_POSITIVE, /* draw subsequent objects in positive, with color, no XOR allowed */ + PCB_HID_COMP_POSITIVE_XOR, /* draw subsequent objects in positive, with color, XOR allowed */ + PCB_HID_COMP_NEGATIVE, /* draw subsequent objects in negative, ignore color */ + PCB_HID_COMP_FLUSH /* combine the sketch canvas onto the output buffer and discard the sketch canvas */ +} pcb_composite_op_t; + +typedef enum pcb_burst_op_s { + PCB_HID_BURST_START, + PCB_HID_BURST_END +} pcb_burst_op_t; + +typedef enum pcb_hid_attr_ev_e { + PCB_HID_ATTR_EV_WINCLOSE = 2, /* window closed (window manager close) */ + PCB_HID_ATTR_EV_CODECLOSE /* closed by the code, including standard close buttons */ +} pcb_hid_attr_ev_t; + +typedef enum pcb_hid_fsd_flags_e { + /* Prompts the user for a filename or directory name. For GUI + HID's this would mean a file select dialog box. The 'flags' + argument is the bitwise OR of the following values. */ + PCB_HID_FSD_READ = 1, + + /* The function calling hid->fileselect will deal with the case + where the selected file already exists. If not given, then the + GUI will prompt with an "overwrite?" prompt. Only used when + writing. + */ + PCB_HID_FSD_MAY_NOT_EXIST = 2, + + /* The call is supposed to return a file template (for gerber + output for example) instead of an actual file. Only used when + writing. + */ + PCB_HID_FSD_IS_TEMPLATE = 4 +} pcb_hid_fsd_flags_t; + +typedef struct { + const char *name; + const char *mime; + const char **pat; /* NULL terminated array of file name patterns */ +} pcb_hid_fsd_filter_t; + +extern const pcb_hid_fsd_filter_t pcb_hid_fsd_filter_any[]; + +/* Optional fields of a menu item; all non-NULL fields are strdup'd in the HID. */ +typedef struct pcb_menu_prop_s { + const char *action; + const char *accel; + const char *tip; /* tooltip */ + const char *checked; + const char *update_on; + const pcb_color_t *foreground; + const pcb_color_t *background; + const char *cookie; /* used for cookie based removal */ +} pcb_menu_prop_t; + +typedef enum pcb_hid_clipfmt_e { + PCB_HID_CLIPFMT_TEXT /* plain text (c string with the \0 included) */ +} pcb_hid_clipfmt_t; + +typedef struct pcb_hid_s pcb_hid_t; + +/* This is the main HID structure. */ +struct pcb_hid_s { + /* The size of this structure. We use this as a compatibility + check; a HID built with a different hid.h than we're expecting + should have a different size here. */ + int struct_size; + + /* The name of this HID. This should be suitable for + command line options, multi-selection menus, file names, + etc. */ + const char *name; + + /* Likewise, but allowed to be longer and more descriptive. */ + const char *description; + + /* The hid may use this field to store its context. */ + void *user_context; + + /* If set, this is the GUI HID. Exactly one of these three flags + must be set; setting "gui" lets the expose callback optimize and + coordinate itself. */ + unsigned gui:1; + + /* If set, this is the printer-class HID. The common part of PCB + may use this to do command-line printing, without having + instantiated any GUI HIDs. Only one printer HID is normally + defined at a time. */ + unsigned printer:1; + + /* If set, this HID provides an export option, and should be used as + part of the File->Export menu option. Examples are PNG, Gerber, + and EPS exporters. */ + unsigned exporter:1; + + /* Export plugin should not be listed in the export dialog */ + unsigned hide_from_gui:1; + + /* If set, draw the mask layer inverted. Normally the mask is a filled + rectangle over the board with cutouts at pins/pads. The HIDs + use render in normal mode, gerber renders in inverse mode. */ + unsigned mask_invert:1; + + /* Always draw layers in compositing mode - no base layer */ + unsigned force_compositing:1; + + /* When enabled, indicate layer of heavy terminals graphically */ + unsigned heavy_term_layer_ind:1; + + /* When 1, HID supports markup (e.g. color) in DAD text widgets */ + unsigned supports_dad_text_markup:1; + + /* it is possible to create DAD dialogs before the GUI_INIT event is emitted + (e.g. draw progress bar while loading a command line file) */ + unsigned allow_dad_before_init:1; + + /* Returns a set of resources describing options the export or print + HID supports. In GUI mode, the print/export dialogs use this to + set up the selectable options. In command line mode, these are + used to interpret command line options. If n_ret_ is non-NULL, + the number of attributes is stored there. */ + pcb_hid_attribute_t *(*get_export_options)(int *n_ret); + + /* Exports (or print) the current PCB. The options given represent + the choices made from the options returned from + get_export_options. Call with options_ == NULL to start the + primary GUI (create a main window, print, export, etc) */ + void (*do_export)(pcb_hid_attr_val_t *options); + + /* uninit a GUI hid */ + void (*uninit)(pcb_hid_t *hid); + + /* uninit a GUI hid */ + void (*do_exit)(pcb_hid_t *hid); + + /* Process pending events, flush output, but never block. Called from busy + loops from time to time. */ + void (*iterate)(pcb_hid_t *hid); + + /* Parses the command line. Call this early for whatever HID will be + the primary HID, as it will set all the registered attributes. + The HID should remove all arguments, leaving any possible file + names behind. Returns 0 on success, positive for recoverable errors + (no change in argc or argv) and negative for unrecoverable errors. */ + int (*parse_arguments)(int *argc, char ***argv); + + /* This may be called to ask the GUI to force a redraw of a given area */ + void (*invalidate_lr)(pcb_coord_t left, pcb_coord_t right, pcb_coord_t top, pcb_coord_t bottom); + void (*invalidate_all)(void); + void (*notify_crosshair_change)(pcb_bool changes_complete); + void (*notify_mark_change)(pcb_bool changes_complete); + + /* During redraw or print/export cycles, this is called once per layer group + (physical layer); pusrpose/purpi are the extracted purpose field and its + keyword/function version; layer is the first layer in the group. + TODO: The group may be -1 until the layer rewrite is finished. + If it returns false (zero), the HID does not want that layer, and none of + the drawing functions should be called. If it returns pcb_true (nonzero), + the items in that layer [group] should be drawn using the various drawing + functions. In addition to the copper layer groups, you may select virtual + layers. The is_empty argument is a hint - if set, the layer is empty, if + zero it may be non-empty. */ + int (*set_layer_group)(pcb_layergrp_id_t group, const char *purpose, int purpi, pcb_layer_id_t layer, unsigned int flags, int is_empty, pcb_xform_t **xform); + + /* Tell the GUI the layer last selected has been finished with. */ + void (*end_layer)(void); + + /*** Drawing Functions. ***/ + + /* Make an empty graphics context. */ + pcb_hid_gc_t (*make_gc)(void); + void (*destroy_gc)(pcb_hid_gc_t gc); + + /* Composite layer drawing: manipulate the sketch canvas and set + positive or negative drawing mode. The canvas covers the screen box. */ + void (*set_drawing_mode)(pcb_composite_op_t op, pcb_bool direct, const pcb_box_t *screen); + + /* Announce start/end of a render burst for a specific screen screen box; + A GUI hid should set the coord_per_pix value here for proper optimization. */ + void (*render_burst)(pcb_burst_op_t op, const pcb_box_t *screen); + + /* Sets a color. Can be one of the special colors like pcb_color_drill. + (Always use the drill color to draw holes and slots). + You may assume this is cheap enough to call inside the redraw + callback, but not cheap enough to call for each item drawn. */ + void (*set_color)(pcb_hid_gc_t gc, const pcb_color_t *color); + + /* Sets the line style. While calling this is cheap, calling it with + different values each time may be expensive, so grouping items by + line style is helpful. */ + void (*set_line_cap)(pcb_hid_gc_t gc, pcb_cap_style_t style); + void (*set_line_width)(pcb_hid_gc_t gc, pcb_coord_t width); + void (*set_draw_xor)(pcb_hid_gc_t gc, int xor); + /* Blends 20% or so color with 80% background. Only used for + assembly drawings so far. */ + void (*set_draw_faded)(pcb_hid_gc_t gc, int faded); + + /* The usual drawing functions. "draw" means to use segments of the + given width, whereas "fill" means to fill to a zero-width + outline. */ + void (*draw_line)(pcb_hid_gc_t gc, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2); + void (*draw_arc)(pcb_hid_gc_t gc, pcb_coord_t cx, pcb_coord_t cy, pcb_coord_t xradius, pcb_coord_t yradius, pcb_angle_t start_angle, pcb_angle_t delta_angle); + void (*draw_rect)(pcb_hid_gc_t gc, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2); + void (*fill_circle)(pcb_hid_gc_t gc, pcb_coord_t cx, pcb_coord_t cy, pcb_coord_t radius); + void (*fill_polygon)(pcb_hid_gc_t gc, int n_coords, pcb_coord_t *x, pcb_coord_t *y); + void (*fill_polygon_offs)(pcb_hid_gc_t gc, int n_coords, pcb_coord_t *x, pcb_coord_t *y, pcb_coord_t dx, pcb_coord_t dy); + void (*fill_pcb_polygon)(pcb_hid_gc_t gc, pcb_poly_t *poly, const pcb_box_t *clip_box); + void (*thindraw_pcb_polygon)(pcb_hid_gc_t gc, pcb_poly_t *poly, const pcb_box_t *clip_box); + void (*fill_rect)(pcb_hid_gc_t gc, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2); + + + /* This is for the printer. If you call this for the GUI, xval_ and + yval_ are ignored, and a dialog pops up to lead you through the + calibration procedure. For the printer, if xval_ and yval_ are + zero, a calibration page is printed with instructions for + calibrating your printer. After calibrating, nonzero xval_ and + yval_ are passed according to the instructions. Metric is nonzero + if the user prefers metric units, else inches are used. */ + void (*calibrate)(double xval, double yval); + + + /* GUI layout functions. Not used or defined for print/export + HIDs. */ + + /* Temporary */ + int (*shift_is_pressed)(void); + int (*control_is_pressed)(void); + int (*mod1_is_pressed)(void); + + void (*get_coords)(const char *msg, pcb_coord_t *x, pcb_coord_t *y, int force); + + /* Fill in width and height with the sizes of the current view in + pcb coordinates. used by action "Cursor" to determine max cursor pos. + Width and height are never NULL. */ + void (*get_view_size)(pcb_coord_t *width, pcb_coord_t *height); + + /* Sets the crosshair, which may differ from the pointer depending + on grid and pad snap. Note that the HID is responsible for + hiding, showing, redrawing, etc. The core just tells it what + coordinates it's actually using. Note that this routine may + need to know what "pcb units" are so it can display them in mm + or mils accordingly. If cursor_action_ is set, the cursor or + screen may be adjusted so that the cursor and the crosshair are + at the same point on the screen. */ + void (*set_crosshair)(pcb_coord_t x, pcb_coord_t y, int cursor_action); +#define HID_SC_DO_NOTHING 0 +#define HID_SC_WARP_POINTER 1 +#define HID_SC_PAN_VIEWPORT 2 + + /* Causes func to be called at some point in the future. Timers are + only good for *one* call; if you want it to repeat, add another + timer during the callback for the first. user_data_ can be + anything, it's just passed to func. Times are not guaranteed to + be accurate. */ + pcb_hidval_t (*add_timer) (void (*func)(pcb_hidval_t user_data), unsigned long milliseconds, pcb_hidval_t user_data); + /* Use this to stop a timer that hasn't triggered yet. */ + void (*stop_timer) (pcb_hidval_t timer); + + /* Causes func_ to be called when some condition occurs on the file + descriptor passed. Conditions include data for reading, writing, + hangup, and errors. user_data_ can be anything, it's just passed + to func. If the watch function returns pcb_true, the watch is kept, else + it is removed. */ + pcb_hidval_t (*watch_file)(int fd, unsigned int condition, pcb_bool (*func)(pcb_hidval_t watch, int fd, unsigned int condition, pcb_hidval_t user_data), pcb_hidval_t user_data); + + /* Use this to stop a file watch; must not be called from within a GUI callback! */ + void (*unwatch_file) (pcb_hidval_t watch); + + /* title may be used as a dialog box title. Ignored if NULL. + * + * descr is a longer help string. Ignored if NULL. + * + * default_file is the default file name. Ignored if NULL. + * + * default_ext is the default file extension, like ".pdf". + * Ignored if NULL. + * + * flt is a {NULL} terminated array of file filters; HID support is optional. + * Ignored if NULL. If NULL and default_ext is not NULL, the HID may make + * up a minimalistic filter from the default_ext also allowing *.*. + * + * history_tag may be used by the GUI to keep track of file + * history. Examples would be "board", "vendor", "renumber", + * etc. If NULL, no specific history is kept. + * + * flags_ are the bitwise OR + * + * sub is an optional DAD sub-dialog, can be NULL; its parent_poke commands: + * close close the dialog + * get_path returns the current full paht in res as string + * set_file_name replaces the file name portion of the current path from arg[0].d.s + */ + char *(*fileselect)(const char *title, const char *descr, const char *default_file, const char *default_ext, const pcb_hid_fsd_filter_t *flt, const char *history_tag, pcb_hid_fsd_flags_t flags, pcb_hid_dad_subdialog_t *sub); + + /* A generic dialog to ask for a set of attributes. If n_attrs_ is + zero, attrs_(.name) must be NULL terminated. attr_dlg_run returns + non-zero if an error occurred (usually, this means the user cancelled + the dialog or something). title is the title of the dialog box + The HID may choose to ignore it or it may use it for a tooltip or + text in a dialog box, or a help string. Id is used in some events (e.g. + for window placement) and is strdup'd. If defx and defy are larger than 0, + they are hints for the default (starting) window size - can be overridden + by window placement. Returns opaque hid_ctx. */ + void *(*attr_dlg_new)(const char *id, pcb_hid_attribute_t *attrs, int n_attrs, pcb_hid_attr_val_t *results, const char *title, void *caller_data, pcb_bool modal, void (*button_cb)(void *caller_data, pcb_hid_attr_ev_t ev), int defx, int defy); + int (*attr_dlg_run)(void *hid_ctx); + void (*attr_dlg_raise)(void *hid_ctx); /* raise the window to top */ + void (*attr_dlg_free)(void *hid_ctx); /* results_ is avalibale after this call */ + + /* Set a property of an attribute dialog (typical call is between + attr_dlg_new() and attr_dlg_run()) */ + void (*attr_dlg_property)(void *hid_ctx, pcb_hat_property_t prop, const pcb_hid_attr_val_t *val); + + + /* Disable or enable a widget of an active attribute dialog */ + int (*attr_dlg_widget_state)(void *hid_ctx, int idx, pcb_bool enabled); + + /* hide or show a widget of an active attribute dialog */ + int (*attr_dlg_widget_hide)(void *hid_ctx, int idx, pcb_bool hide); + + /* Change the current value of a widget; same as if the user chaged it, + except the value-changed callback is inhibited */ + int (*attr_dlg_set_value)(void *hid_ctx, int idx, const pcb_hid_attr_val_t *val); + + /* Change the help text (tooltip) string of a widget; NULL means remove it. + NOTE: does _not_ change the help_text field of the attribute. */ + void (*attr_dlg_set_help)(void *hid_ctx, int idx, const char *val); + + /* Something to alert the user. */ + void (*beep)(void); + + void (*edit_attributes)(const char *owner, pcb_attribute_list_t *attrlist); + + /* Notification to the GUI around saving the PCB file. + * + * Called with a false parameter before the save, called again + * with pcb_true after the save. + * + * Allows GUIs which watch for file-changes on disk to ignore + * our deliberate changes. + */ + void (*notify_save_pcb)(const char *filename, pcb_bool done); + + /* Notification to the GUI that the PCB file has been renamed. */ + void (*notify_filename_changed)(void); + + /* Creates a new menu and/or submenus + * menu_path is a / separated path to the new menu (parents are silently created). + * The last non-NULL item is the new menu item. + * action, accel and tip affect the new menu item. + * Cookie is strdup()'d into the lihata tree and can be used later to search + * and remove menu items that are no longer needed. + * If action is NULL, the menu may get submenus. + */ + void (*create_menu)(const char *menu_path, const pcb_menu_prop_t *props); + + /* Removes a menu recursively */ + int (*remove_menu)(const char *menu_path); + int (*remove_menu_node)(lht_node_t *nd); + + /* Update the state of all checkboxed menus whose luhata + node cookie matches cookie (or all checkboxed menus globally if cookie + is NULL) */ + void (*update_menu_checkbox)(const char *cookie); + + /* Pointer to the hid's configuration - useful for plugins and core wanting to install menus at anchors */ + pcb_hid_cfg_t *hid_cfg; + + + /* Optional: print usage string (if accepts command line arguments) + Subtopic: + NULL print generic help + string print summary for the topic in string + Return 0 on success. + */ + int (*usage)(const char *subtopic); + + + /* Optional: change cursor to indicate if an object is grabbed (or not) */ + void (*point_cursor)(pcb_bool grabbed); + + /* Optional: when non-zero, the core renderer may decide to draw cheaper + (simplified) approximation of some objects that would end up being too + small. For a GUI, this should depend on the zoom level */ + pcb_coord_t coord_per_pix; + + /* If ovr is not NULL: + - overwrite the command etry with ovr + - if cursor is not NULL, set the cursor after the overwrite + If ovr is NULL: + - if cursor is not NULL, load the value with the cursor (or -1 if not supported) + Return the current command entry content in a read-only string */ + const char *(*command_entry)(const char *ovr, int *cursor); + + /*** clipboard handling for GUI HIDs ***/ + /* Place format/data/len on the clipboard; return 0 on success */ + int (*clip_set)(pcb_hid_clipfmt_t format, const void *data, size_t len); + + /* retrieve format/data/len from the clipboard; return 0 on success; + data is a copy of the data, modifiable by the caller */ + int (*clip_get)(pcb_hid_clipfmt_t *format, void **data, size_t *len); + + /* release the data from the last clip_get(); clip_get() and clip_free() should + be called in pair */ + void (*clip_free)(pcb_hid_clipfmt_t format, void *data, size_t len); + + /* run redraw-benchmark and return an FPS value (optional) */ + double (*benchmark)(void); +}; + +/* One of these functions (in the common code) will be called whenever the GUI + needs to redraw the screen, print the board, or export a layer. + + Each time func is called, it should do the following: + + * allocate any colors needed, via get_color. + + * cycle through the layers, calling set_layer for each layer to be + drawn, and only drawing objects (all or specified) of desired + layers. + + Do *not* assume that the hid that is passed is the GUI hid. This + callback is also used for printing and exporting. */ + +typedef struct pcb_hid_expose_ctx_s pcb_hid_expose_ctx_t; + +typedef void (*pcb_hid_expose_cb_t)(pcb_hid_gc_t gc, const pcb_hid_expose_ctx_t *e); + +struct pcb_hid_expose_ctx_s { + pcb_box_t view; + pcb_hid_expose_cb_t expose_cb; /* function that is called on expose to get things drawn */ + void *draw_data; /* user data for the expose function */ +}; + +typedef void (*pcb_hid_expose_t)(pcb_hid_t *hid, const pcb_hid_expose_ctx_t *ctx); + +/* This is initially set to a "no-gui" GUI, and later reset by + main. hid_expose_callback also temporarily set it for drawing. */ +extern pcb_hid_t *pcb_gui; + +/* When not NULL, auto-start the next GUI after the current one quits */ +extern pcb_hid_t *pcb_next_gui; + +/* This is either NULL or points to the current HID that is being called to + do the exporting. The GUI HIDs set and unset this var.*/ +extern pcb_hid_t *pcb_exporter; + +/* This is either NULL or points to the current pcb_action_t that is being + called. The action launcher sets and unsets this variable. */ +extern const pcb_action_t *pcb_current_action; + +/* The GUI may set this to be approximately the PCB size of a pixel, + to allow for near-misses in selection and changes in drawing items + smaller than a screen pixel. */ +extern int pcb_pixel_slop; + +/*** Glue for GUI/CLI dialogs: wrappers around actions */ + +/* Prompts the user to enter a string, returns the string. If + default_string isn't NULL, the form is pre-filled with this + value. "msg" is printed above the query. The optional title + is the window title. + Returns NULL on cancel. The caller needs to free the returned string */ +char *pcb_hid_prompt_for(const char *msg, const char *default_string, const char *title); + +/* Present a dialog box with a message and variable number of buttons. If icon + is not NULL, attempt to draw the named icon on the left. The vararg part is + one or more buttons, as a list of "char *label, int retval", terminated with + NULL. */ +int pcb_hid_message_box(const char *icon, const char *title, const char *label, ...); + +/* Show modal progressbar to the user, offering cancel long running processes. + Pass all zeros to flush display and remove the dialog. + Returns nonzero if the user wishes to cancel the operation. */ +int pcb_hid_progress(long so_far, long total, const char *message); + +/* non-zero if DAD dialogs are available currently */ +#define PCB_HAVE_GUI_ATTR_DLG \ + ((pcb_gui != NULL) && (pcb_gui->gui) && (pcb_gui->attr_dlg_new != NULL) && (pcb_gui->attr_dlg_new != pcb_nogui_attr_dlg_new)) +void *pcb_nogui_attr_dlg_new(const char *id, pcb_hid_attribute_t *attrs_, int n_attrs_, pcb_hid_attr_val_t * results_, const char *title_, void *caller_data, pcb_bool modal, void (*button_cb)(void *caller_data, pcb_hid_attr_ev_t ev), int defx, int defy); + + +#endif Index: tags/2.1.2/src/hid_attrib.c =================================================================== --- tags/2.1.2/src/hid_attrib.c (nonexistent) +++ tags/2.1.2/src/hid_attrib.c (revision 24813) @@ -0,0 +1,351 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * Copyright (C) 2004 harry eaton + * Copyright (C) 2016..2018 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +#include "config.h" +#include "hid_attrib.h" +#include "misc_util.h" +#include "compat_misc.h" +#include "pcb-printf.h" +#include "macro.h" + +pcb_hid_attr_node_t *hid_attr_nodes = 0; + +typedef struct { + pcb_hatt_compflags_t flag; + const char *name; +} comflag_name_t; + +static comflag_name_t compflag_names[] = { + {PCB_HATF_FRAME, "frame"}, + {PCB_HATF_SCROLL, "scroll"}, + {PCB_HATF_HIDE_TABLAB, "hide_tablab"}, + {PCB_HATF_LEFT_TAB, "left_tab"}, + {PCB_HATF_TREE_COL, "tree_col"}, + {PCB_HATF_EXPFILL, "expfill"}, + {0, NULL} +}; + +const char *pcb_hid_compflag_bit2name(pcb_hatt_compflags_t bit) +{ + comflag_name_t *n; + for(n = compflag_names; n->flag != 0; n++) + if (n->flag == bit) + return n->name; + return NULL; +} + +pcb_hatt_compflags_t pcb_hid_compflag_name2bit(const char *name) +{ + comflag_name_t *n; + for(n = compflag_names; n->flag != 0; n++) + if (strcmp(n->name, name) == 0) + return n->flag; + return 0; +} + +void pcb_hid_register_attributes(pcb_hid_attribute_t * a, int n, const char *cookie, int copy) +{ + pcb_hid_attr_node_t *ha; + + /* printf("%d attributes registered\n", n); */ + ha = malloc(sizeof(pcb_hid_attr_node_t)); + ha->next = hid_attr_nodes; + hid_attr_nodes = ha; + ha->attributes = a; + ha->n = n; + ha->cookie = cookie; +} + +void pcb_hid_attributes_uninit(void) +{ + pcb_hid_attr_node_t *ha, *next; + for (ha = hid_attr_nodes; ha; ha = next) { + next = ha->next; + if (ha->cookie != NULL) + fprintf(stderr, "WARNING: attribute %s by %s is not uninited, check your plugins' uninit!\n", ha->attributes->name, ha->cookie); + free(ha); + } + hid_attr_nodes = NULL; +} + +void pcb_hid_remove_attributes_by_cookie(const char *cookie) +{ + pcb_hid_attr_node_t *ha, *next, *prev = NULL; + for (ha = hid_attr_nodes; ha; ha = next) { + next = ha->next; + if (ha->cookie == cookie) { + if (prev == NULL) + hid_attr_nodes = next; + else + prev->next = next; + free(ha); + } + else + prev = ha; + } +} + +int pcb_hid_parse_command_line(int *argc, char ***argv) +{ + pcb_hid_attr_node_t *ha; + int i, e, ok; + char *filename = NULL; + + for (ha = hid_attr_nodes; ha; ha = ha->next) + for (i = 0; i < ha->n; i++) { + pcb_hid_attribute_t *a = ha->attributes + i; + switch (a->type) { + case PCB_HATT_LABEL: + break; + case PCB_HATT_INTEGER: + if (a->value) + *(int *) a->value = a->default_val.int_value; + break; + case PCB_HATT_COORD: + if (a->value) + *(pcb_coord_t *) a->value = a->default_val.coord_value; + break; + case PCB_HATT_BOOL: + if (a->value) + *(char *) a->value = a->default_val.int_value; + break; + case PCB_HATT_REAL: + if (a->value) + *(double *) a->value = a->default_val.real_value; + break; + case PCB_HATT_STRING: + if (a->value) + *(const char **) a->value = pcb_strdup(PCB_EMPTY(a->default_val.str_value)); + break; + case PCB_HATT_ENUM: + if (a->value) + *(int *) a->value = a->default_val.int_value; + break; + case PCB_HATT_UNIT: + if (a->value) + *(int *) a->value = a->default_val.int_value; + break; + default: + pcb_message(PCB_MSG_ERROR, "Invalid attribute type %d for attribute %s\n", a->type, a->name); + abort(); + } + } + + while(*argc > 0) + if (*argc && (*argv)[0][0] == '-' && (*argv)[0][1] == '-') { + int bool_val; + int arg_ofs; + + bool_val = 1; + arg_ofs = 2; + try_no_arg: + for (ha = hid_attr_nodes; ha; ha = ha->next) + for (i = 0; i < ha->n; i++) + if (strcmp((*argv)[0] + arg_ofs, ha->attributes[i].name) == 0) { + pcb_hid_attribute_t *a = ha->attributes + i; + char *ep; + const pcb_unit_t *unit; + switch (ha->attributes[i].type) { + case PCB_HATT_LABEL: + break; + case PCB_HATT_INTEGER: + if (a->value) + *(int *) a->value = strtol((*argv)[1], 0, 0); + else + a->default_val.int_value = strtol((*argv)[1], 0, 0); + (*argc)--; + (*argv)++; + break; + case PCB_HATT_COORD: + if (a->value) + *(pcb_coord_t *) a->value = pcb_get_value((*argv)[1], NULL, NULL, NULL); + else + a->default_val.coord_value = pcb_get_value((*argv)[1], NULL, NULL, NULL); + (*argc)--; + (*argv)++; + break; + case PCB_HATT_REAL: + if (a->value) + *(double *) a->value = strtod((*argv)[1], 0); + else + a->default_val.real_value = strtod((*argv)[1], 0); + (*argc)--; + (*argv)++; + break; + case PCB_HATT_STRING: + if (a->value) + *(char **) a->value = pcb_strdup(PCB_EMPTY((*argv)[1])); + else + a->default_val.str_value = pcb_strdup(PCB_EMPTY((*argv)[1])); + (*argc)--; + (*argv)++; + break; + case PCB_HATT_BOOL: + if (a->value) + *(char *) a->value = bool_val; + else + a->default_val.int_value = bool_val; + break; + case PCB_HATT_ENUM: + ep = (*argv)[1]; + ok = 0; + for (e = 0; a->enumerations[e]; e++) + if (strcmp(a->enumerations[e], ep) == 0) { + ok = 1; + a->default_val.int_value = e; + a->default_val.str_value = ep; + break; + } + if (!ok) { + fprintf(stderr, "ERROR: \"%s\" is an unknown value for the --%s option\n", (*argv)[1], a->name); + exit(1); + } + (*argc)--; + (*argv)++; + break; + case PCB_HATT_PATH: + abort(); + a->default_val.str_value = pcb_strdup(PCB_EMPTY((*argv)[1])); + (*argc)--; + (*argv)++; + break; + case PCB_HATT_UNIT: + unit = get_unit_struct((*argv)[1]); + if (unit == NULL) { + fprintf(stderr, "ERROR: unit \"%s\" is unknown to pcb (option --%s)\n", (*argv)[1], a->name); + exit(1); + } + a->default_val.int_value = unit->index; + a->default_val.str_value = unit->suffix; + (*argc)--; + (*argv)++; + break; + default: + break; + } + (*argc)--; + (*argv)++; + ha = 0; + goto got_match; + } + if (bool_val == 1 && strncmp((*argv)[0], "--no-", 5) == 0) { + bool_val = 0; + arg_ofs = 5; + goto try_no_arg; + } + fprintf(stderr, "unrecognized option: %s\n", (*argv)[0]); + return -1; + got_match:; + } + else { + /* Any argument without the "--" is considered a filename. Take only + one filename for now */ + if (filename == NULL) { + filename = (*argv)[0]; + (*argc)--; + (*argv)++; + } + else { + pcb_message(PCB_MSG_ERROR, "Multiple filenames not supported. First filename was: %s; offending second filename: %s\n", filename, (*argv)[0]); + return -1; + } + } + + /* restore filename to the first argument */ + if (filename != NULL) { + (*argv)[0] = filename; + (*argc) = 1; + } + return 0; +} + +void pcb_hid_usage_option(const char *name, const char *help) +{ + fprintf(stderr, "%-20s %s\n", name, help); +} + +void pcb_hid_usage(pcb_hid_attribute_t * a, int numa) +{ + for (; numa > 0; numa--,a++) { + const char *help; + if (a->help_text == NULL) help = ""; + else if (a->help_text == ATTR_UNDOCUMENTED) help = ""; + else help = a->help_text; + pcb_hid_usage_option(a->name, help); + } +} + +int pcb_hid_attrdlg_num_children(pcb_hid_attribute_t *attrs, int start_from, int n_attrs) +{ + int n, level = 1, cnt = 0; + + for(n = start_from; n < n_attrs; n++) { + if ((level == 1) && (attrs[n].type != PCB_HATT_END)) + cnt++; + switch(attrs[n].type) { + case PCB_HATT_END: + level--; + if (level == 0) + return cnt; + break; + case PCB_HATT_BEGIN_TABLE: + case PCB_HATT_BEGIN_HBOX: + case PCB_HATT_BEGIN_VBOX: + level++; + break; + default: + break; + } + } + return cnt; +} + +int pcb_attribute_dialog_(const char *id, pcb_hid_attribute_t *attrs, int n_attrs, pcb_hid_attr_val_t *results, const char *title, void *caller_data, void **retovr, int defx, int defy, void **hid_ctx_out) +{ + int rv; + void *hid_ctx; + + if ((pcb_gui == NULL) || (pcb_gui->attr_dlg_new == NULL)) + return -1; + + hid_ctx = pcb_gui->attr_dlg_new(id, attrs, n_attrs, results, title, caller_data, pcb_true, NULL, 0, 0); + if (hid_ctx_out != NULL) + *hid_ctx_out = hid_ctx; + rv = pcb_gui->attr_dlg_run(hid_ctx); + if ((retovr == NULL) || (*retovr != 0)) + pcb_gui->attr_dlg_free(hid_ctx); + + return rv ? 0 : 1; +} + +int pcb_attribute_dialog(const char *id, pcb_hid_attribute_t *attrs, int n_attrs, pcb_hid_attr_val_t *results, const char *title, void *caller_data) +{ + return pcb_attribute_dialog_(id, attrs, n_attrs, results, title, caller_data, NULL, 0, 0, NULL); +} Index: tags/2.1.2/src/hid_attrib.h =================================================================== --- tags/2.1.2/src/hid_attrib.h (nonexistent) +++ tags/2.1.2/src/hid_attrib.h (revision 24813) @@ -0,0 +1,243 @@ +#ifndef PCB_HID_ATTRIB_H +#define PCB_HID_ATTRIB_H + +#include "hid.h" +#include "color.h" + +/* Used for HID attributes (exporting and printing, mostly). + HA_boolean uses int_value, HA_enum sets int_value to the index and + str_value to the enumeration string. PCB_HATT_LABEL just shows the + default str_value. */ +struct pcb_hid_attr_val_s { + int int_value; + const char *str_value; + double real_value; + pcb_coord_t coord_value; + pcb_color_t clr_value; + void (*func)(); +}; + +typedef enum pcb_hatt_compflags_e { + PCB_HATF_FRAME = 1, /* box/table has a visible frame around it */ + PCB_HATF_TIGHT = 2, /* box/table/button has minimal padding and spacing */ + PCB_HATF_SCROLL = 4, /* box/table is scrollable */ + PCB_HATF_HIDE_TABLAB = 8, /* hide tab labes of a TABBED - the tab mechanism works, but tab names are not displayed and are not clickable */ + PCB_HATF_CLR_STATIC = 8, /* color that can not be changed */ + PCB_HATF_LEFT_TAB = 16, /* display tab labels of TABBED on the left instead of on top (default) */ + PCB_HATF_TREE_COL = 32, /* first column of a PCB_HATT_TREE is a tree */ + PCB_HATF_EXPFILL = 64, /* for hbox and vbox: expand and fill */ + PCB_HATF_HIDE = 128 /* widget is initially hidden */ +} pcb_hatt_compflags_t; + +typedef enum pcb_hids_e { + /* atomic entry types */ + PCB_HATT_LABEL, + PCB_HATT_INTEGER, + PCB_HATT_REAL, + PCB_HATT_STRING, /* WARNING: string, must be malloc()'d, can't be a (const char *) */ + PCB_HATT_BOOL, + PCB_HATT_ENUM, + PCB_HATT_PATH, /* WARNING: string, must be malloc()'d, can't be a (const char *) */ + PCB_HATT_UNIT, + PCB_HATT_COORD, + PCB_HATT_BUTTON, /* push button; default value is the label */ + PCB_HATT_TREE, /* tree/list/table view; number of columns: pcb_hatt_table_cols; data is in field 'enumerations' */ + PCB_HATT_PROGRESS, /* progress bar; displays real_value between 0 and 1 */ + PCB_HATT_PREVIEW, /* preview/render widget; callbacks in 'enumerations' */ + PCB_HATT_PICTURE, /* static picture from xpm - picture data in enumerations */ + PCB_HATT_PICBUTTON, /* button with static picture from xpm - picture data in enumerations */ + PCB_HATT_COLOR, /* color pick (user input: select a color) */ + PCB_HATT_TEXT, /* plain text editor; data is in 'enumerations' as pcb_hid_text_t */ + + /* groups (e.g. boxes) */ + PCB_HATT_BEGIN_HBOX, /* NOTE: PCB_HATT_IS_COMPOSITE() depends on it */ + PCB_HATT_BEGIN_VBOX, + PCB_HATT_BEGIN_HPANE, /* horizontal split and offer two vboxes; the split ratio is real_value between 0 and 1, that describes the left side's size */ + PCB_HATT_BEGIN_VPANE, /* vertical split and offer two vboxes; the split ratio is real_value between 0 and 1, that describes the left side's size */ + PCB_HATT_BEGIN_TABLE, /* min_val is the number of columns */ + PCB_HATT_BEGIN_TABBED, /* tabbed view (e.g. notebook); ->enumerations stores the tab names and a NULL; default_val's integer value is the index of the current tab */ + PCB_HATT_BEGIN_COMPOUND, /* subtree emulating a single widget; (pcb_hid_compound_t *) stored in END's enumerations */ + PCB_HATT_END /* close one level of PCB_HATT_* */ +} pcb_hids_t; + +#define PCB_HATT_IS_COMPOSITE(type) \ + (((type) >= PCB_HATT_BEGIN_HBOX) && ((type) < PCB_HATT_END)) + +#define PCB_HAT_IS_STR(type) \ + ((type == PCB_HATT_STRING) || (type == PCB_HATT_PATH)) + +/* alternative field names in struct pcb_hid_attribute_s */ +#define pcb_hatt_flags hatt_flags +#define pcb_hatt_table_cols min_val + +typedef enum { + PCB_HID_TEXT_INSERT, /* insert at cursor or replace selection */ + PCB_HID_TEXT_REPLACE, /* replace the entire text */ + PCB_HID_TEXT_APPEND, /* append to the end of the text */ + + /* modifiers (bitfield) */ + PCB_HID_TEXT_MARKUP = 0x0010 /* interpret minimal html-like markup - some HIDs may ignore these */ +} pcb_hid_text_set_t; + +typedef struct { + /* cursor manipulation callbacks */ + void (*hid_get_xy)(pcb_hid_attribute_t *attrib, void *hid_ctx, long *x, long *y); /* can be very slow */ + long (*hid_get_offs)(pcb_hid_attribute_t *attrib, void *hid_ctx); + void (*hid_set_xy)(pcb_hid_attribute_t *attrib, void *hid_ctx, long x, long y); /* can be very slow */ + void (*hid_set_offs)(pcb_hid_attribute_t *attrib, void *hid_ctx, long offs); + void (*hid_scroll_to_bottom)(pcb_hid_attribute_t *attrib, void *hid_ctx); + void (*hid_set_text)(pcb_hid_attribute_t *attrib, void *hid_ctx, pcb_hid_text_set_t how, const char *txt); + char *(*hid_get_text)(pcb_hid_attribute_t *attrib, void *hid_ctx); /* caller needs to free the result */ + void (*hid_set_readonly)(pcb_hid_attribute_t *attrib, void *hid_ctx, pcb_bool readonly); /* by default text views are not read-only */ + + /* optional callbacks the user set after widget creation */ + void *user_ctx; + void (*user_free_cb)(pcb_hid_attribute_t *attrib, void *user_ctx, void *hid_ctx); + + /* optional callbacks HIDs may set after widget creation */ + void *hid_wdata; + void (*hid_free_cb)(pcb_hid_attribute_t *attrib, void *hid_wdata); +} pcb_hid_text_t; + + +typedef struct { + int cols; /* number of columns used by this node (allocation size) */ + void *hid_data; /* the hid running the widget can use this field to store a custom pointer per row */ + gdl_list_t children; + gdl_elem_t link; + char *path; /* full path of the node; allocated/free'd by DAD (/ is the root, every entry is specified from the root, but the leading / is omitted; in non-tree case, this only points to the first col data) */ + unsigned hide:1; /* if non-zero, the row is not visible (e.g. filtered out) */ + + /* caller/user data */ + void *user_data; + union { + void *ptr; + long lng; + double dbl; + } user_data2; + char *cell[1]; /* each cell is a char *; the true length of the array is the value of the len field; the array is allocated together with the struct */ +} pcb_hid_row_t; + +typedef struct { + gdl_list_t rows; /* ordered list of first level rows (tree root) */ + htsp_t paths; /* translate first column paths iinto (pcb_hid_row_t *) */ + pcb_hid_attribute_t *attrib; + const char **hdr; /* optional column headers (NULL means disable header) */ + + /* optional callbacks the user set after widget creation */ + void *user_ctx; + void (*user_free_cb)(pcb_hid_attribute_t *attrib, void *hid_ctx, pcb_hid_row_t *row); + void (*user_selected_cb)(pcb_hid_attribute_t *attrib, void *hid_ctx, pcb_hid_row_t *row); + int (*user_browse_activate_cb)(pcb_hid_attribute_t *attrib, void *hid_ctx, pcb_hid_row_t *row); /* returns non-zero if the row should auto-activate while browsing (e.g. stepping with arrow keys) */ + const char *(*user_copy_to_clip_cb)(pcb_hid_attribute_t *attrib, void *hid_ctx, pcb_hid_row_t *row); /* returns the string to copy to clipboard for the given row (if unset, first column text is used) */ + + /* optional callbacks HIDs may set after widget creation */ + void *hid_wdata; + void (*hid_insert_cb)(pcb_hid_attribute_t *attrib, void *hid_wdata, pcb_hid_row_t *new_row); + void (*hid_modify_cb)(pcb_hid_attribute_t *attrib, void *hid_wdata, pcb_hid_row_t *row, int col); /* if col is negative, all columns have changed */ + void (*hid_remove_cb)(pcb_hid_attribute_t *attrib, void *hid_wdata, pcb_hid_row_t *row); + void (*hid_free_cb)(pcb_hid_attribute_t *attrib, void *hid_wdata, pcb_hid_row_t *row); + pcb_hid_row_t *(*hid_get_selected_cb)(pcb_hid_attribute_t *attrib, void *hid_wdata); + void (*hid_jumpto_cb)(pcb_hid_attribute_t *attrib, void *hid_wdata, pcb_hid_row_t *row); /* row = NULL means deselect all */ + void (*hid_expcoll_cb)(pcb_hid_attribute_t *attrib, void *hid_wdata, pcb_hid_row_t *row, int expanded); /* sets whether a row is expanded or collapsed */ + void (*hid_update_hide_cb)(pcb_hid_attribute_t *attrib, void *hid_wdata); +} pcb_hid_tree_t; + +typedef struct pcb_hid_preview_s pcb_hid_preview_t; +struct pcb_hid_preview_s { + pcb_hid_attribute_t *attrib; + + pcb_box_t initial_view; + unsigned initial_view_valid:1; + + int min_sizex_px, min_sizey_px; /* hint: widget minimum size in pixels */ + + /* optional callbacks the user set after widget creation */ + void *user_ctx; + void (*user_free_cb)(pcb_hid_attribute_t *attrib, void *user_ctx, void *hid_ctx); + void (*user_expose_cb)(pcb_hid_attribute_t *attrib, pcb_hid_preview_t *prv, pcb_hid_gc_t gc, const pcb_hid_expose_ctx_t *e); + pcb_bool (*user_mouse_cb)(pcb_hid_attribute_t *attrib, pcb_hid_preview_t *prv, pcb_hid_mouse_ev_t kind, pcb_coord_t x, pcb_coord_t y); /* returns true if redraw is needed */ + + /* optional callbacks HIDs may set after widget creation */ + void *hid_wdata; + void (*hid_zoomto_cb)(pcb_hid_attribute_t *attrib, void *hid_wdata, const pcb_box_t *view); + void (*hid_free_cb)(pcb_hid_attribute_t *attrib, void *hid_wdata); +}; + +typedef struct { + int wbegin, wend; /* widget index to the correspoding PCB_HATT_BEGIN_COMPOUND and PCB_HATT_END */ + + /* compound implementation callbacks */ + int (*widget_state)(pcb_hid_attribute_t *end, void *hid_ctx, int idx, pcb_bool enabled); + int (*widget_hide)(pcb_hid_attribute_t *end, void *hid_ctx, int idx, pcb_bool hide); + int (*set_value)(pcb_hid_attribute_t *end, void *hid_ctx, int idx, const pcb_hid_attr_val_t *val); /* set value runtime */ + void (*set_val_num)(pcb_hid_attribute_t *attr, long l, double d, pcb_coord_t c); /* set value during creation; attr is the END */ + void (*set_val_ptr)(pcb_hid_attribute_t *attr, void *ptr); /* set value during creation; attr is the END */ + void (*set_field_num)(pcb_hid_attribute_t *attr, const char *fieldname, long l, double d, pcb_coord_t c); /* set value during creation; attr is the END */ + void (*set_field_ptr)(pcb_hid_attribute_t *attr, const char *fieldname, void *ptr); /* set value during creation; attr is the END */ + void (*free)(pcb_hid_attribute_t *attrib); /* called by DAD on free'ing the PCB_HATT_BEGIN_COMPOUND and PCB_HATT_END_COMPOUND widget */ +} pcb_hid_compound_t; + + + +struct pcb_hid_attribute_s { + const char *name; + /* If the help_text is this, usage() won't show this option */ +#define ATTR_UNDOCUMENTED ((char *)(1)) + const char *help_text; + pcb_hids_t type; + int min_val, max_val; /* for integer and real */ + pcb_hid_attr_val_t default_val; /* Also actual value for global attributes. */ + + /* NULL terminated list of values for a PCB_HATT_ENUM; + Also (ab)used as (pcb_hid_tree_t *) for a PCB_HATT_TREE and for PCB_HATT_PICTURE & PCB_HATT_PICBUTTON */ + const char **enumerations; + + /* If set, this is used for global attributes (i.e. those set + statically with REGISTER_ATTRIBUTES below) instead of changing + the default_val. */ + void *value; + + /* dynamic API */ + int changed; /* 0 for initial values, 1 on user change */ + void (*change_cb)(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr); /* called upon value change by the user */ + void (*enter_cb)(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr); /* called upon the user pressed enter in a widget that handles keys */ + void *user_data; /* ignored; the caller is free to use it */ + unsigned int hatt_flags; +}; + +extern void pcb_hid_register_attributes(pcb_hid_attribute_t *, int, const char *cookie, int copy); +#define PCB_REGISTER_ATTRIBUTES(a, cookie) PCB_HIDCONCAT(void register_,a) ()\ +{ pcb_hid_register_attributes(a, sizeof(a)/sizeof(a[0]), cookie, 0); } + +/* Remove all attributes registered with the given cookie */ +void pcb_hid_remove_attributes_by_cookie(const char *cookie); + +/* remove all attributes and free the list */ +void pcb_hid_attributes_uninit(void); + +typedef struct pcb_hid_attr_node_s { + struct pcb_hid_attr_node_s *next; + pcb_hid_attribute_t *attributes; + int n; + const char *cookie; +} pcb_hid_attr_node_t; + +extern pcb_hid_attr_node_t *hid_attr_nodes; + +void pcb_hid_usage(pcb_hid_attribute_t * a, int numa); +void pcb_hid_usage_option(const char *name, const char *help); + +/* Count the number of direct children, start_from the first children */ +int pcb_hid_attrdlg_num_children(pcb_hid_attribute_t *attrs, int start_from, int n_attrs); + +/* Invoke a simple modal attribute dialog if GUI is available */ +int pcb_attribute_dialog_(const char *id, pcb_hid_attribute_t *attrs, int n_attrs, pcb_hid_attr_val_t *results, const char *title, void *caller_data, void **retovr, int defx, int defy, void **hid_ctx_out); +int pcb_attribute_dialog(const char *id, pcb_hid_attribute_t *attrs, int n_attrs, pcb_hid_attr_val_t *results, const char *title, void *caller_data); + + +/* Convert between compflag bit value and name */ +const char *pcb_hid_compflag_bit2name(pcb_hatt_compflags_t bit); +pcb_hatt_compflags_t pcb_hid_compflag_name2bit(const char *name); + +#endif Index: tags/2.1.2/src/hid_cam.c =================================================================== --- tags/2.1.2/src/hid_cam.c (nonexistent) +++ tags/2.1.2/src/hid_cam.c (revision 24813) @@ -0,0 +1,655 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * Copyright (C) 2004 harry eaton + * Copyright (C) 2019 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +#include "config.h" + +#include +#include + +#include "board.h" +#include "data.h" +#include "hid_cam.h" +#include "hid_attrib.h" +#include "compat_misc.h" +#include "layer_vis.h" +#include "plug_io.h" + +htsp_t *pcb_cam_vars = NULL; /* substitute %% variables from this hash */ + +char *pcb_layer_to_file_name(char *dest, pcb_layer_id_t lid, unsigned int flags, const char *purpose, int purpi, pcb_file_name_style_t style) +{ + const pcb_virt_layer_t *v; + pcb_layergrp_id_t group; + int nlayers; + const char *single_name, *res = NULL; + + if (flags == 0) + flags = pcb_layer_flags(PCB, lid); + + if (style == PCB_FNS_pcb_rnd) { + const char *sloc, *styp; + group = pcb_layer_get_group(PCB, lid); + sloc = pcb_layer_type_bit2str(flags & PCB_LYT_ANYWHERE); + styp = pcb_layer_type_bit2str(flags & (PCB_LYT_ANYTHING | PCB_LYT_VIRTUAL)); + if (sloc == NULL) sloc = "global"; + if (styp == NULL) styp = "none"; + if (purpose == NULL) purpose = "none"; + if (group < 0) { + sprintf(dest, "%s.%s.%s.none", sloc, styp, purpose); + } + else + sprintf(dest, "%s.%s.%s.%ld", sloc, styp, purpose, group); + return dest; + } + + if (flags & PCB_LYT_BOUNDARY) { + strcpy(dest, "outline"); + return dest; + } + + /* NOTE: long term only PCB_FNS_pcb_rnd will be supported and the rest, + below, will be removed */ + v = pcb_vlayer_get_first(flags, purpose, purpi); + if (v != NULL) { + strcpy(dest, v->name); + return dest; + } + + + group = pcb_layer_get_group(PCB, lid); + nlayers = PCB->LayerGroups.grp[group].len; + single_name = pcb_layer_name(PCB->Data, lid); + + if (flags & PCB_LYT_TOP) { + if (style == PCB_FNS_first || (style == PCB_FNS_single && nlayers == 2)) + res = single_name; + if (flags & PCB_LYT_SILK) + res = "topsilk"; + else if (flags & PCB_LYT_MASK) + res = "topmask"; + else if (flags & PCB_LYT_PASTE) + res = "toppaste"; + else + res = "top"; + } + else if (flags & PCB_LYT_BOTTOM) { + if (style == PCB_FNS_first || (style == PCB_FNS_single && nlayers == 2)) + res = single_name; + if (flags & PCB_LYT_SILK) + res = "bottomsilk"; + else if (flags & PCB_LYT_MASK) + res = "bottommask"; + else if (flags & PCB_LYT_PASTE) + res = "bottompaste"; + else + res = "bottom"; + } + else { + static char buf[PCB_DERIVE_FN_SUFF_LEN]; + if (style == PCB_FNS_first || (style == PCB_FNS_single && nlayers == 1)) + res = single_name; + sprintf(buf, "group%ld", group); + res = buf; + } + + assert(res != NULL); + strcpy(dest, res); + return dest; +} + + +char *pcb_derive_default_filename_(const char *pcbfile, const char *suffix) +{ + char *buf; + const char *pf; + + if (pcbfile == NULL) + pf = "unknown.pcb"; + else + pf = pcbfile; + + buf = (char *) malloc(strlen(pf) + strlen(suffix) + 1); + if (buf) { + size_t bl; + pcb_plug_io_t *i; + strcpy(buf, pf); + bl = strlen(buf); + for(i = pcb_plug_io_chain; i != NULL; i = i->next) { + if (i->default_extension != NULL) { + int slen = strlen(i->default_extension); + if (bl > slen && strcmp(buf + bl - slen, i->default_extension) == 0) { + buf[bl - slen] = 0; + break; + } + } + } + strcat(buf, suffix); + } + + return buf; +} + +void pcb_derive_default_filename(const char *pcbfile, pcb_hid_attribute_t * filename_attrib, const char *suffix) +{ + if (filename_attrib->default_val.str_value) + free((char *)filename_attrib->default_val.str_value); + filename_attrib->default_val.str_value = pcb_derive_default_filename_(pcbfile, suffix); +} + +/* remove leading and trailing whitespace */ +static char *strip(char *s) +{ + char *end; + while(isspace(*s)) s++; + end = s + strlen(s) - 1; + while((end >= s) && (isspace(*end))) { + *end = '\0'; + end--; + } + return s; +} + +static void layervis_save_and_reset(pcb_cam_t *cam) +{ + pcb_layer_id_t n; + for(n = 0; n < cam->pcb->Data->LayerN; n++) { + cam->orig_vis[n] = cam->pcb->Data->Layer[n].meta.real.vis; + cam->pcb->Data->Layer[n].meta.real.vis = 0; + } +} + +static void layervis_restore(pcb_cam_t *cam) +{ + pcb_layer_id_t n; + for(n = 0; n < cam->pcb->Data->LayerN; n++) + cam->pcb->Data->Layer[n].meta.real.vis = cam->orig_vis[n]; +} + +static int parse_layer_type(char *type, pcb_layer_type_t *lyt, int *offs, int *has_offs) +{ + char *soffs, *end, *nxt, *cur; + pcb_layer_type_t l; + + *lyt = 0; + *offs = *has_offs = 0; + + soffs = strchr(type, ':'); + if (soffs != NULL) { + *soffs = '\0'; + *offs = strtol(soffs+1, &end, 10); + if (*end != '\0') { + pcb_message(PCB_MSG_ERROR, "CAM rule: invalid offset '%s'\n", soffs); + return 1; + } + *has_offs = 1; + } + + for(cur = type; cur != NULL; cur = nxt) { + nxt = strchr(cur, '-'); + if (nxt != NULL) { + *nxt = '\0'; + nxt++; + } + l = pcb_layer_type_str2bit(cur); + if (l == 0) { + pcb_message(PCB_MSG_ERROR, "CAM rule: invalid layer type '%s'\n", cur); + return 1; + } + (*lyt) |= l; + } + return 0; +} + +static char *lp_err = ""; + +/* Parse a layer directive: split at comma, curr will end up holding the + layer name. If there were transformations in (), they are split and + listed in tr up to at most *spc entries. Returns NULL on error or + pointer to the next layer directive. */ +static char *parse_layer(char *curr, char **spk, char **spv, int *spc) +{ + char *s, *lasta, *eq; + int level = 0, trmax = *spc; + *spc = 0; + + for(s = curr; *s != '\0'; s++) { + switch(*s) { + case '(': + if (level == 0) { + *s = '\0'; + lasta = s+1; + } + level++; + break; + case ')': + if (level > 0) + level--; + if (level == 0) + goto append; + break; + case ',': + if (level == 0) + goto out; + append:; + if (*spc >= trmax) + return lp_err; + lasta = strip(lasta); + spk[*spc] = lasta; + eq = strchr(lasta, '='); + if (eq != NULL) { + *eq = '\0'; + eq++; + } + spv[*spc] = eq; + (*spc)++; + *s = '\0'; + lasta = s+1; + } + } + + if (level > 0) + return lp_err; + + out:; + + if (*s != '\0') { + *s = '\0'; + s++; + return s; + } + + return NULL; /* no more layers */ +} + + +static void parse_layer_supplements(char **spk, char **spv, int spc, char **purpose, pcb_xform_t **xf, pcb_xform_t *xf_) +{ + int n; + + *purpose = NULL; + memset(xf_, 0, sizeof(pcb_xform_t)); + + for(n = 0; n < spc; n++) { + char *key = spk[n], *val = spv[n]; + + if (strcmp(key, "purpose") == 0) + *purpose = val; + else if (strcmp(key, "bloat") == 0) { + pcb_bool succ; + double v = pcb_get_value(val, NULL, NULL, &succ); + if (succ) { + xf_->bloat = v; + *xf = xf_; + } + else + pcb_message(PCB_MSG_ERROR, "CAM: ignoring invalid layer supplement value '%s' for bloat\n", val); + } + else + pcb_message(PCB_MSG_ERROR, "CAM: ignoring unknown layer supplement key '%s'\n", key); + } +} + +int pcb_cam_begin(pcb_board_t *pcb, pcb_cam_t *dst, const char *src, const pcb_hid_attribute_t *attr_tbl, int numa, pcb_hid_attr_val_t *options) +{ + char *curr, *next, *purpose; + + memset(dst, 0, sizeof(pcb_cam_t)); + + if ((src == NULL) || (*src == '\0')) + return 0; + + dst->pcb = pcb; + dst->inst = pcb_strdup(src); + layervis_save_and_reset(dst); + + + /* Syntax: fn=layergrp,layergrp,layergrp;--opt=val;--opt=val */ + /* parse: get file name name */ + next = strchr(dst->inst, '='); + if (next == NULL) { + pcb_message(PCB_MSG_ERROR, "CAM rule missing '='\n"); + goto err; + } + *next = '\0'; + next++; + dst->fn = strip(dst->inst); + + if (strchr(dst->fn, '%') != NULL) { + dst->fn_template = dst->fn; + dst->fn = NULL; + } + + while(isspace(*next)) + next++; + + /* parse layers */ + for(curr = next; curr != NULL; curr = next) { + char *spk[64], *spv[64]; + int spc = sizeof(spk) / sizeof(spk[0]); + next = parse_layer(curr, spk, spv, &spc); + if (next == lp_err) { + pcb_message(PCB_MSG_ERROR, "CAM rule: invalid layer transformation\n"); + goto err; + } + +{ +} + + curr = strip(curr); + if (*curr == '@') { + /* named layer group */ + pcb_xform_t *xf, xf_; + pcb_layergrp_id_t gid; + curr++; + gid = pcb_layergrp_by_name(pcb, curr); + if (gid < 0) { + const pcb_virt_layer_t *v; + int n, vid = -1; + for(n = 0, v = pcb_virt_layers; v->name != NULL; n++,v++) { + if (strcmp(v->name, curr) == 0) { + vid = n; + break; + } + } + if (vid != -1) { + dst->vgrp_vis[vid] = 1; + continue; + } + } + if (gid < 0) { + pcb_message(PCB_MSG_ERROR, "CAM rule: no such layer group '%s'\n", curr); + goto err; + } + if (pcb->LayerGroups.grp[gid].len <= 0) + continue; + pcb_layervis_change_group_vis(pcb->LayerGroups.grp[gid].lid[0], 1, 0); + dst->grp_vis[gid] = 1; + + parse_layer_supplements(spk, spv, spc, &purpose, &xf, &xf_); + + dst->xform[gid] = &dst->xform_[gid]; + memcpy(&dst->xform_[gid], &xf_, sizeof(pcb_xform_t)); + } + else { + /* by layer type */ + int offs, has_offs; + pcb_layer_type_t lyt; + const pcb_virt_layer_t *vl; + pcb_xform_t *xf = NULL, xf_; + + if (parse_layer_type(curr, &lyt, &offs, &has_offs) != 0) + goto err; + + parse_layer_supplements(spk, spv, spc, &purpose, &xf, &xf_); + + vl = pcb_vlayer_get_first(lyt, purpose, -1); + if (vl == NULL) { + pcb_layergrp_id_t gids[PCB_MAX_LAYERGRP]; + int n, len = pcb_layergrp_listp(dst->pcb, lyt, gids, sizeof(gids)/sizeof(gids[0]), -1, purpose); + if (has_offs) { + if (offs < 0) + offs = len - offs; + else + offs--; + if ((offs >= 0) && (offs < len)) { + pcb_layergrp_id_t gid = gids[offs]; + pcb_layervis_change_group_vis(pcb->LayerGroups.grp[gid].lid[0], 1, 0); + dst->grp_vis[gid] = 1; + if (xf != NULL) { + dst->xform[gid] = &dst->xform_[gid]; + memcpy(&dst->xform_[gid], &xf_, sizeof(pcb_xform_t)); + } + } + } + else { + for(n = 0; n < len; n++) { + pcb_layergrp_id_t gid = gids[n]; + pcb_layervis_change_group_vis(pcb->LayerGroups.grp[gid].lid[0], 1, 0); + dst->grp_vis[gid] = 1; + if (xf != NULL) { + dst->xform[gid] = &dst->xform_[gid]; + memcpy(&dst->xform_[gid], &xf_, sizeof(pcb_xform_t)); + } + } + } + + } + else { + int vid = vl->new_id - PCB_LYT_VIRTUAL - 1; + dst->vgrp_vis[vid] = 1; + if (xf != NULL) { + dst->vxform[vid] = &dst->vxform_[vid]; + memcpy(&dst->vxform_[vid], &xf_, sizeof(pcb_xform_t)); + } + + } + } + } + + dst->active = 1; + return 0; + err:; + layervis_restore(dst); + free(dst->inst); + dst->inst = NULL; + return -1; +} + +int pcb_cam_end(pcb_cam_t *dst) +{ + free(dst->inst); + if (dst->fn_template != NULL) { + free(dst->fn); + free(dst->fn_last); + } + dst->inst = NULL; + if (!dst->active) + return -1; + layervis_restore(dst); + dst->active = 0; + return dst->exported_grps; +} + + +typedef struct { + pcb_cam_t *cam; + const pcb_layergrp_t *grp; + const pcb_virt_layer_t *vl; + htsp_t *vars; +} cam_name_ctx_t; + +/* convert string to integer, step input beyond the terminating % */ +static int get_tune(const char **input) +{ + char *end; + int res; + + if (**input == '%') { + (*input)++; + return 0; + } + res = atoi(*input); + end = strchr(*input, '%'); + *input = end+1; + return res; +} + +static int cam_update_name_cb(void *ctx_, gds_t *s, const char **input) +{ + cam_name_ctx_t *ctx = ctx_; + if (strncmp(*input, "name%", 5) == 0) { + (*input) += 5; + if (ctx->grp != NULL) { + if (ctx->grp->name != NULL) + gds_append_str(s, ctx->grp->name); + } + else if (ctx->vl != NULL) + gds_append_str(s, ctx->vl->name); + } + else if (strncmp(*input, "top_offs", 8) == 0) { + int tune, from_top = -1; + pcb_layergrp_t *tcop = pcb_get_grp(&PCB->LayerGroups, PCB_LYT_TOP, PCB_LYT_COPPER); + pcb_layergrp_id_t tcop_id = pcb_layergrp_id(PCB, tcop); + + (*input) += 8; + tune = get_tune(input); + + pcb_layergrp_dist(PCB, pcb_layergrp_id(PCB, ctx->grp), tcop_id, PCB_LYT_COPPER, &from_top); + pcb_append_printf(s, "%d", from_top+tune); + } + else if (strncmp(*input, "bot_offs", 8) == 0) { + int tune, from_bot = -1; + pcb_layergrp_t *bcop = pcb_get_grp(&PCB->LayerGroups, PCB_LYT_BOTTOM, PCB_LYT_COPPER); + pcb_layergrp_id_t bcop_id = pcb_layergrp_id(PCB, bcop); + + (*input) += 8; + tune = get_tune(input); + + pcb_layergrp_dist(PCB, pcb_layergrp_id(PCB, ctx->grp), bcop_id, PCB_LYT_COPPER, &from_bot); + pcb_append_printf(s, "%d", from_bot+tune); + } + else { + char *end = strchr(*input, '%'); + char varname[128]; + int len; + + if (end == NULL) { + gds_append_str(s, *input); + return 0; + } + + if (ctx->vars != NULL) { + len = end - *input; + if (len < sizeof(varname)-1) { + const char *val; + strncpy(varname, *input, len); + varname[len] = 0; + val = htsp_get(ctx->vars, varname); + if (val != NULL) + gds_append_str(s, val); + } + else + pcb_message(PCB_MSG_ERROR, "cam job error: %%%% variable name too long at: '%%%s' - did not substitute\n", *input); + } + + *input = end+1; + } + + return 0; +} + +static int cam_update_name(pcb_cam_t *cam, pcb_layergrp_id_t gid, const pcb_virt_layer_t *vl) +{ + cam_name_ctx_t ctx; + if (cam->fn_template == NULL) + return 0; /* not templated */ + + free(cam->fn); + ctx.cam = cam; + ctx.grp = pcb_get_layergrp(cam->pcb, gid); + ctx.vl = vl; + ctx.vars = pcb_cam_vars; + cam->fn = pcb_strdup_subst(cam->fn_template, cam_update_name_cb, &ctx, PCB_SUBST_HOME | PCB_SUBST_PERCENT | PCB_SUBST_CONF); + if ((cam->fn_last == NULL) || (strcmp(cam->fn, cam->fn_last) != 0)) { + cam->fn_changed = 1; + free(cam->fn_last); + cam->fn_last = pcb_strdup(cam->fn); + } + else + cam->fn_changed = 0; + return 0; +} + +int pcb_cam_set_layer_group_(pcb_cam_t *cam, pcb_layergrp_id_t group, const char *purpose, int purpi, unsigned int flags, pcb_xform_t **xform) +{ + const pcb_virt_layer_t *vl; + + if (!cam->active) + return 0; + + vl = pcb_vlayer_get_first(flags, purpose, purpi); + if (vl == NULL) { + if (group == -1) + return 1; + + if (!cam->grp_vis[group]) + return 1; + + if (cam->xform[group] != NULL) + *xform = cam->xform[group]; + } + else { + int vid = vl->new_id - PCB_LYT_VIRTUAL - 1; + if (!cam->vgrp_vis[vid]) + return 1; + + if (cam->vxform[vid] != NULL) + *xform = cam->xform[vid]; + } + + cam->exported_grps++; + return cam_update_name(cam, group, NULL);; +} + + +void *pcb_cam_vars_alloc(void) +{ + return htsp_alloc(strhash, strkeyeq); +} + +void pcb_cam_vars_free(void *ctx) +{ + htsp_t *vars = ctx; + htsp_entry_t *e; + + for(e = htsp_first(vars); e != NULL; e = htsp_next(vars, e)) { + free(e->key); + free(e->value); + } + htsp_free(vars); +} + +void *pcb_cam_vars_use(void *new_vars) +{ + void *old = pcb_cam_vars; + pcb_cam_vars = new_vars; + return old; +} + +void pcb_cam_set_var(void *ctx, char *key, char *val) +{ + htsp_t *vars = ctx; + htsp_entry_t *e = htsp_popentry(vars, key); + if (e != NULL) { + free(e->key); + free(e->value); + } + htsp_set(vars, key, val); +} Index: tags/2.1.2/src/hid_cam.h =================================================================== --- tags/2.1.2/src/hid_cam.h (nonexistent) +++ tags/2.1.2/src/hid_cam.h (revision 24813) @@ -0,0 +1,93 @@ +#ifndef PCB_HID_HELPER_H +#define PCB_HID_HELPER_H + +#include "layer.h" +#include "hid_attrib.h" + +/*** CAM plugin side API ***/ +typedef struct pcb_cam_s { + /* public */ + char *fn; + pcb_bool fn_changed; /* true if last call changed the ->fn field */ + pcb_bool active; + int grp_vis[PCB_MAX_LAYERGRP]; /* whether a real layer group should be rendered */ + int vgrp_vis[PCB_VLY_end]; /* whether a virtual layer group should be rendered */ + + pcb_xform_t *xform[PCB_MAX_LAYERGRP]; + pcb_xform_t xform_[PCB_MAX_LAYERGRP]; + pcb_xform_t *vxform[PCB_VLY_end]; + pcb_xform_t vxform_[PCB_VLY_end]; + + /* private/internal/cache */ + const char *fn_template; + char *fn_last; + char *inst; + pcb_board_t *pcb; + int orig_vis[PCB_MAX_LAYER]; /* backup of the original layer visibility */ + int exported_grps; +} pcb_cam_t; + +int pcb_cam_begin(pcb_board_t *pcb, pcb_cam_t *dst, const char *src, const pcb_hid_attribute_t *attr_tbl, int numa, pcb_hid_attr_val_t *options); + +/* Finish cam export, free all memory, mark cam export inactive and report + the number of layer groups exported */ +int pcb_cam_end(pcb_cam_t *dst); + + +/* Shall be the first rule in a cam capable exporter's set_layer_group() + callback: decides not to draw a layer group in cam mode if the + group is not scheduled for export */ +#define pcb_cam_set_layer_group(cam, group, purpose, purpi, flags, xform) \ +do { \ + if (pcb_cam_set_layer_group_(cam, group, purpose, purpi, flags, xform)) \ + return 0; \ +} while(0) + +/* the logics behind pcb_cam_set_layer_group(); returns non-zero if the macro + should return (and skip the current group) */ +int pcb_cam_set_layer_group_(pcb_cam_t *cam, pcb_layergrp_id_t group, const char *purpose, int purpi, unsigned int flags, pcb_xform_t **xform); + +/*** CAM caller side API for global export ***/ + +/* Allocate or free a var context, in which pcb_cam_set_var() operates and + which then can be 'used' for exporting. */ +void *pcb_cam_vars_alloc(void); +void pcb_cam_vars_free(void *ctx); + +/* Use new_vars for the next export; returns the old var context that the + caller needs to restore (with another call to this function) after the export. */ +void *pcb_cam_vars_use(void *new_vars); + +/* Overwrite a CAM variable in the currently active context; both key + and val must be strdup'd on caller side (they are free'd by the CAM code) */ +void pcb_cam_set_var(void *ctx, char *key, char *val); + + +/*** Obsolete file suffix API - new plugins should not use this ***/ +/* maximum size of a derived suffix */ +#define PCB_DERIVE_FN_SUFF_LEN 20 + +typedef enum pcb_file_name_style_e { + /* The only style that will be available long term: native */ + PCB_FNS_pcb_rnd, + /* Files for copper layers are named top, groupN, bottom. */ + PCB_FNS_fixed, + /* Groups with multiple layers are named as above, else the single + layer name is used. */ + PCB_FNS_single, + /* The name of the first layer in each group is used. */ + PCB_FNS_first +} pcb_file_name_style_t; + +/* Returns a filename base that can be used to output the layer. */ +char *pcb_layer_to_file_name(char *dest, pcb_layer_id_t lid, unsigned int flags, const char *purpose, int purpi, pcb_file_name_style_t style); + +/* Returns a filename base that can be used to output the layer; if flags is 0, + look it up. Copies result in dest (which should be at least PCB_DERIVE_FN_SUFF_LEN bytes wide). */ +void pcb_derive_default_filename(const char *pcbfile, pcb_hid_attribute_t * filename_attrib, const char *suffix); + +/* Same as pcb_derive_default_filename() but returns an allocated string + directly, instead of manipulating an attribute */ +char *pcb_derive_default_filename_(const char *pcbfile, const char *suffix); + +#endif Index: tags/2.1.2/src/hid_cfg.c =================================================================== --- tags/2.1.2/src/hid_cfg.c (nonexistent) +++ tags/2.1.2/src/hid_cfg.c (revision 24813) @@ -0,0 +1,679 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2016 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include +#include +#include +#include +#include +#include + +#include "config.h" +#include "hid.h" +#include "hid_cfg.h" +#include "error.h" +#include "paths.h" +#include "safe_fs.h" +#include "compat_misc.h" +#include "file_loaded.h" +#include "conf_core.h" + +char hid_cfg_error_shared[1024]; + +typedef struct { + pcb_hid_cfg_t *hr; + pcb_create_menu_widget_t cb; + void *cb_ctx; + lht_node_t *parent; + const pcb_menu_prop_t *props; + int target_level; + int err; + lht_node_t *after; +} create_menu_ctx_t; + +static lht_node_t *create_menu_cb(void *ctx, lht_node_t *node, const char *path, int rel_level) +{ + create_menu_ctx_t *cmc = ctx; + lht_node_t *psub, *after; + +/* printf(" CB: '%s' %p at %d->%d\n", path, node, rel_level, cmc->target_level);*/ + if (node == NULL) { /* level does not exist, create it */ + const char *name; + name = strrchr(path, '/'); + if (name != NULL) + name++; + else + name = path; + + if (rel_level <= 1) { + /* creating a main menu */ + char *end, *name = pcb_strdup(path); + for(end = name; *end == '/'; end++) ; + end = strchr(end, '/'); + *end = '\0'; + psub = cmc->parent = pcb_hid_cfg_get_menu(cmc->hr, name); + free(name); + } + else + psub = pcb_hid_cfg_menu_field(cmc->parent, PCB_MF_SUBMENU, NULL); + + if (rel_level == cmc->target_level) { + node = pcb_hid_cfg_create_hash_node(psub, cmc->after, name, "dyn", "1", "cookie", cmc->props->cookie, "a", cmc->props->accel, "tip", cmc->props->tip, "action", cmc->props->action, "checked", cmc->props->checked, "update_on", cmc->props->update_on, "foreground", cmc->props->foreground, "background", cmc->props->background, NULL); + if (node != NULL) + cmc->err = 0; + } + else + node = pcb_hid_cfg_create_hash_node(psub, cmc->after, name, "dyn", "1", "cookie", cmc->props->cookie, NULL); + + if (node == NULL) + return NULL; + + if ((rel_level != cmc->target_level) || (cmc->props->action == NULL)) + lht_dom_hash_put(node, lht_dom_node_alloc(LHT_LIST, "submenu")); + + if (node->parent == NULL) { + lht_dom_list_append(psub, node); + } + else { + assert(node->parent == psub); + } + + if ((cmc->after != NULL) && (cmc->after->parent->parent == cmc->parent)) + after = cmc->after; + else + after = NULL; + + if (cmc->cb(cmc->cb_ctx, path, name, (rel_level == 1), cmc->parent, after, node) != 0) { + cmc->err = -1; + return NULL; + } + } + else { + /* existing level */ + if ((node->type == LHT_TEXT) && (node->data.text.value[0] == '@')) { + cmc->after = node; + goto skip_parent; + } + } + cmc->parent = node; + + skip_parent:; + return node; +} + +int pcb_hid_cfg_create_menu(pcb_hid_cfg_t *hr, const char *path, const pcb_menu_prop_t *props, pcb_create_menu_widget_t cb, void *cb_ctx) +{ + const char *name; + create_menu_ctx_t cmc; + + cmc.hr = hr; + cmc.cb = cb; + cmc.cb_ctx = cb_ctx; + cmc.parent = NULL; + cmc.props = props; + cmc.err = -1; + cmc.after = NULL; + + /* Allow creating new nodes only under certain main paths that correspond to menus */ + name = path; + while(*name == '/') name++; + + if ((strncmp(name, "main_menu/", 10) == 0) || (strncmp(name, "popups/", 7) == 0)) { + /* calculate target level */ + for(cmc.target_level = 0; *name != '\0'; name++) { + if (*name == '/') { + cmc.target_level++; + while(*name == '/') name++; + name--; + } + } + + /* descend and visit each level, create missing levels */ + pcb_hid_cfg_get_menu_at(hr, NULL, path, create_menu_cb, &cmc); + } + + return cmc.err; +} + +static int hid_cfg_remove_item(pcb_hid_cfg_t *hr, lht_node_t *item, int (*gui_remove)(void *ctx, lht_node_t *nd), void *ctx) +{ + if (gui_remove(ctx, item) != 0) + return -1; + lht_tree_del(item); + return 0; +} + +int pcb_hid_cfg_remove_menu_node(pcb_hid_cfg_t *hr, lht_node_t *root, int (*gui_remove)(void *ctx, lht_node_t *nd), void *ctx) +{ + if (root == NULL) + return -1; + + if (root->type == LHT_HASH) { + lht_node_t *psub, *n, *next; + psub = pcb_hid_cfg_menu_field(root, PCB_MF_SUBMENU, NULL); + if (psub != NULL) { /* remove a whole submenu with all children */ + int res = 0; + for(n = psub->data.list.first; n != NULL; n = next) { + next = n->next; + if (pcb_hid_cfg_remove_menu_node(hr, n, gui_remove, ctx) != 0) + res = -1; + } + if (res == 0) + res = hid_cfg_remove_item(hr, root, gui_remove, ctx); + return res; + } + } + + if ((root->type != LHT_TEXT) && (root->type != LHT_HASH)) /* allow text for the sep */ + return -1; + + /* remove a simple menu item */ + return hid_cfg_remove_item(hr, root, gui_remove, ctx); +} + +int pcb_hid_cfg_remove_menu_cookie(pcb_hid_cfg_t *hr, const char *cookie, int (*gui_remove)(void *ctx, lht_node_t *nd), void *ctx, int level, lht_node_t *curr) +{ + lht_err_t err; + lht_dom_iterator_t it; + + if ((curr != hr->doc->root) && (level > 1)) { + curr = lht_tree_path_(hr->doc, curr, "submenu", 1, 0, &err); + if (curr == NULL) + return 0; + } + + for(curr = lht_dom_first(&it, curr); curr != NULL; curr = lht_dom_next(&it)) { + lht_node_t *nck = lht_tree_path_(hr->doc, curr, "cookie", 1, 0, &err); + + if ((nck != NULL) && (strcmp(nck->data.text.value, cookie) == 0)) + pcb_hid_cfg_remove_menu_node(hr, curr, gui_remove, ctx); + else + pcb_hid_cfg_remove_menu_cookie(hr, cookie, gui_remove, ctx, level+1, curr); + } + + /* always success: not finding any menu is not considered an error */ + return 0; +} + +int pcb_hid_cfg_remove_menu(pcb_hid_cfg_t *hr, const char *path, int (*gui_remove)(void *ctx, lht_node_t *nd), void *ctx) +{ + lht_node_t *nd = pcb_hid_cfg_get_menu_at(hr, NULL, path, NULL, NULL); + + if (nd == NULL) + return pcb_hid_cfg_remove_menu_cookie(hr, path, gui_remove, ctx, 0, hr->doc->root); + else + return pcb_hid_cfg_remove_menu_node(hr, nd, gui_remove, ctx); +} + +static int hid_cfg_load_error(lht_doc_t *doc, const char *filename, lht_err_t err) +{ + const char *fn; + int line, col; + lht_dom_loc_active(doc, &fn, &line, &col); + pcb_message(PCB_MSG_ERROR, "Resource error: %s (%s:%d.%d)*\n", lht_err_str(err), filename, line+1, col+1); + return 1; +} + +lht_doc_t *pcb_hid_cfg_load_lht(const char *filename) +{ + FILE *f; + lht_doc_t *doc; + int error = 0; + + f = pcb_fopen(filename, "r"); + if (f == NULL) + return NULL; + + doc = lht_dom_init(); + lht_dom_loc_newfile(doc, filename); + + while(!(feof(f))) { + lht_err_t err; + int c = fgetc(f); + err = lht_dom_parser_char(doc, c); + if (err != LHTE_SUCCESS) { + if (err != LHTE_STOP) { + error = hid_cfg_load_error(doc, filename, err); + break; + } + break; /* error or stop, do not read anymore (would get LHTE_STOP without any processing all the time) */ + } + } + + if (error) { + lht_dom_uninit(doc); + doc = NULL; + } + fclose(f); + + return doc; +} + +lht_doc_t *pcb_hid_cfg_load_str(const char *text) +{ + lht_doc_t *doc; + int error = 0; + + doc = lht_dom_init(); + lht_dom_loc_newfile(doc, "embedded"); + + while(*text != '\0') { + lht_err_t err; + int c = *text++; + err = lht_dom_parser_char(doc, c); + if (err != LHTE_SUCCESS) { + if (err != LHTE_STOP) { + error = hid_cfg_load_error(doc, "internal", err); + break; + } + break; /* error or stop, do not read anymore (would get LHTE_STOP without any processing all the time) */ + } + } + + if (error) { + lht_dom_uninit(doc); + doc = NULL; + } + + return doc; +} + +const char *pcb_hid_cfg_text_value(lht_doc_t *doc, const char *path) +{ + lht_node_t *n = lht_tree_path(doc, "/", path, 1, NULL); + if (n == NULL) + return NULL; + if (n->type != LHT_TEXT) { + pcb_hid_cfg_error(n, "Error: node %s should be a text node\n", path); + return NULL; + } + return n->data.text.value; +} + +pcb_hid_cfg_t *pcb_hid_cfg_load(const char *fn, int exact_fn, const char *embedded_fallback) +{ + lht_doc_t *doc; + pcb_hid_cfg_t *hr; + + /* override HID defaults with the configured path */ + if ((conf_core.rc.menu_file != NULL) && (*conf_core.rc.menu_file != '\0')) { + fn = conf_core.rc.menu_file; + exact_fn = (strchr(conf_core.rc.menu_file, '/') != NULL); + } + + if (!exact_fn) { + /* try different paths to find the menu file inventing its exact name */ + static const char *hid_cfg_paths_in[] = { "./", "~/.pcb-rnd/", PCBSHAREDIR "/", NULL }; + char **paths = NULL, **p; + int fn_len = strlen(fn); + + doc = NULL; + pcb_paths_resolve_all(hid_cfg_paths_in, paths, fn_len+32, pcb_false); + for(p = paths; *p != NULL; p++) { + if (doc == NULL) { + char *end = *p + strlen(*p); + sprintf(end, "pcb-menu-%s.lht", fn); + doc = pcb_hid_cfg_load_lht(*p); + if (doc != NULL) + pcb_file_loaded_set_at("menu", "HID main", *p, "main menu system"); + } + free(*p); + } + free(paths); + } + else + doc = pcb_hid_cfg_load_lht(fn); + + if (doc == NULL) { + doc = pcb_hid_cfg_load_str(embedded_fallback); + pcb_file_loaded_set_at("menu", "HID main", "", "main menu system"); + } + if (doc == NULL) + return NULL; + + hr = calloc(sizeof(pcb_hid_cfg_t), 1); /* make sure the cache is cleared */ + hr->doc = doc; + + return hr; +} + +/************* "parsing" **************/ + +lht_node_t *pcb_hid_cfg_get_menu_at(pcb_hid_cfg_t *hr, lht_node_t *at, const char *menu_path, lht_node_t *(*cb)(void *ctx, lht_node_t *node, const char *path, int rel_level), void *ctx) +{ + lht_err_t err; + lht_node_t *curr; + int level = 0, len = strlen(menu_path), iafter = 0; + char *next_seg, *path; + + path = malloc(len+4); /* need a few bytes after the end for the ':' */ + strcpy(path, menu_path); + + next_seg = path; + curr = (at == NULL) ? hr->doc->root : at; + + /* Have to descend manually because of the submenu nodes */ + for(;;) { + char *next, *end; + lht_dom_iterator_t it; + + while(*next_seg == '/') next_seg++; + + if (curr != hr->doc->root) { + if (level > 1) { + curr = lht_tree_path_(hr->doc, curr, "submenu", 1, 0, &err); + if (curr == NULL) + break; + } + } + next = end = strchr(next_seg, '/'); + if (end == NULL) + end = next_seg + strlen(next_seg); + + *end = '\0'; + + /* find next_seg in the current level */ + for(curr = lht_dom_first(&it, curr); curr != NULL; curr = lht_dom_next(&it)) { + if (*next_seg == '@') { + /* looking for an anon text node with the value matching the anchor name */ + if ((curr->type == LHT_TEXT) && (strcmp(curr->data.text.value, next_seg) == 0)) { + iafter = 1; + break; + } + } + else { + /* looking for a hash node */ + if (strcmp(curr->name, next_seg) == 0) + break; + } + } + + if (cb != NULL) + curr = cb(ctx, curr, path, level); + + if (next != NULL) /* restore previous / so that path is a full path */ + *next = '/'; + next_seg = next; + if ((curr == NULL) || (next_seg == NULL)) + break; + next_seg++; + level++; + if (iafter) { + /* special case: insert after an @anchor and exit */ + if (cb != NULL) + curr = cb(ctx, NULL, path, level); + break; + } + } + + free(path); + return curr; +} + +lht_node_t *pcb_hid_cfg_get_menu(pcb_hid_cfg_t *hr, const char *menu_path) +{ + return pcb_hid_cfg_get_menu_at(hr, NULL, menu_path, NULL, NULL); +} + +lht_node_t *pcb_hid_cfg_menu_field(const lht_node_t *submenu, pcb_hid_cfg_menufield_t field, const char **field_name) +{ + lht_err_t err; + const char *fieldstr = NULL; + + switch(field) { + case PCB_MF_ACCELERATOR: fieldstr = "a"; break; + case PCB_MF_SUBMENU: fieldstr = "submenu"; break; + case PCB_MF_CHECKED: fieldstr = "checked"; break; + case PCB_MF_UPDATE_ON: fieldstr = "update_on"; break; + case PCB_MF_SENSITIVE: fieldstr = "sensitive"; break; + case PCB_MF_TIP: fieldstr = "tip"; break; + case PCB_MF_ACTIVE: fieldstr = "active"; break; + case PCB_MF_ACTION: fieldstr = "action"; break; + case PCB_MF_FOREGROUND: fieldstr = "foreground"; break; + case PCB_MF_BACKGROUND: fieldstr = "background"; break; + case PCB_MF_FONT: fieldstr = "font"; break; + } + if (field_name != NULL) + *field_name = fieldstr; + + if (fieldstr == NULL) + return NULL; + + return lht_tree_path_(submenu->doc, submenu, fieldstr, 1, 0, &err); +} + +const char *pcb_hid_cfg_menu_field_str(const lht_node_t *submenu, pcb_hid_cfg_menufield_t field) +{ + const char *fldname; + lht_node_t *n = pcb_hid_cfg_menu_field(submenu, field, &fldname); + + if (n == NULL) + return NULL; + if (n->type != LHT_TEXT) { + pcb_hid_cfg_error(submenu, "Error: field %s should be a text node\n", fldname); + return NULL; + } + return n->data.text.value; +} + +int pcb_hid_cfg_has_submenus(const lht_node_t *submenu) +{ + const char *fldname; + lht_node_t *n = pcb_hid_cfg_menu_field(submenu, PCB_MF_SUBMENU, &fldname); + if (n == NULL) + return 0; + if (n->type != LHT_LIST) { + pcb_hid_cfg_error(submenu, "Error: field %s should be a list (of submenus)\n", fldname); + return 0; + } + return 1; +} + + +void pcb_hid_cfg_extend_hash_nodev(lht_node_t *node, va_list ap) +{ + for(;;) { + char *cname, *cval; + lht_node_t *t; + + cname = va_arg(ap, char *); + if (cname == NULL) + break; + cval = va_arg(ap, char *); + + if (cval != NULL) { + t = lht_dom_node_alloc(LHT_TEXT, cname); + t->data.text.value = pcb_strdup(cval); + lht_dom_hash_put(node, t); + } + } +} + +void pcb_hid_cfg_extend_hash_node(lht_node_t *node, ...) +{ + va_list ap; + va_start(ap, node); + pcb_hid_cfg_extend_hash_nodev(node, ap); + va_end(ap); +} + +lht_node_t *pcb_hid_cfg_create_hash_node(lht_node_t *parent, lht_node_t *ins_after, const char *name, ...) +{ + lht_node_t *n; + va_list ap; + + if ((parent != NULL) && (parent->type != LHT_LIST)) + return NULL; + + /* ignore ins_after if we are already deeper in the tree */ + if ((ins_after != NULL) && (ins_after->parent != parent)) + ins_after = NULL; + + n = lht_dom_node_alloc(LHT_HASH, name); + if (ins_after != NULL) { + /* insert as next sibling below a @anchor */ + lht_dom_list_insert_after(ins_after, n); + } + else if (parent != NULL) { + /* insert as last item under a parent node */ + lht_dom_list_append(parent, n); + } + + va_start(ap, name); + pcb_hid_cfg_extend_hash_nodev(n, ap); + va_end(ap); + + return n; +} + +lht_node_t *pcb_hid_cfg_menu_field_path(const lht_node_t *parent, const char *path) +{ + return lht_tree_path_(parent->doc, parent, path, 1, 0, NULL); +} + +int pcb_hid_cfg_dfs(lht_node_t *parent, int (*cb)(void *ctx, lht_node_t *n), void *ctx) +{ + lht_dom_iterator_t it; + lht_node_t *n; + + for(n = lht_dom_first(&it, parent); n != NULL; n = lht_dom_next(&it)) { + int ret; + ret = cb(ctx, n); + if (ret != 0) + return ret; + if (n->type != LHT_TEXT) { + ret = pcb_hid_cfg_dfs(n, cb, ctx); + if (ret != 0) + return ret; + } + } + return 0; +} + +void pcb_hid_cfg_error(const lht_node_t *node, const char *fmt, ...) +{ + char *end; + va_list ap; + int len, maxlen = sizeof(hid_cfg_error_shared); + + len = pcb_snprintf(hid_cfg_error_shared, maxlen, "Error in lihata node %s:%d.%d:", node->file_name, node->line, node->col); + end = hid_cfg_error_shared + len; + maxlen -= len; + va_start(ap, fmt); + end += pcb_vsnprintf(end, maxlen, fmt, ap); + va_end(ap); + pcb_message(PCB_MSG_ERROR, hid_cfg_error_shared); +} + +static void map_anchor_menus(vtp0_t *dst, lht_node_t *node, const char *name) +{ + lht_dom_iterator_t it; + + switch(node->type) { + case LHT_HASH: + case LHT_LIST: + for(node = lht_dom_first(&it, node); node != NULL; node = lht_dom_next(&it)) + map_anchor_menus(dst, node, name); + break; + case LHT_TEXT: + if ((node->parent != NULL) && (node->parent->type == LHT_LIST) && (strcmp(node->data.text.value, name) == 0)) + vtp0_append(dst, node); + break; + default: + break; + } +} + +void pcb_hid_cfg_map_anchor_menus(const char *name, void (*cb)(void *ctx, pcb_hid_cfg_t *cfg, lht_node_t *n, char *path), void *ctx) +{ + vtp0_t anchors; + + if ((pcb_gui == NULL) || (pcb_gui->hid_cfg == NULL) || (pcb_gui->hid_cfg->doc == NULL) || (pcb_gui->hid_cfg->doc->root == NULL)) + return; + + /* extract anchors; don't do the callbacks from there because the tree + is going to be changed from the callbacks. It is however guaranteed + that anchors are not removed. */ + vtp0_init(&anchors); + map_anchor_menus(&anchors, pcb_gui->hid_cfg->doc->root, name); + + /* iterate over all anchors extracted and call the callback */ + { + char *path = NULL; + int used = 0, alloced = 0, l0 = strlen(name) + 128; + size_t an; + + for(an = 0; an < vtp0_len(&anchors); an++) { + lht_node_t *n, *node = anchors.array[an]; + + for(n = node->parent; n != NULL; n = n->parent) { + int len; + if (strcmp(n->name, "submenu") == 0) + continue; + len = strlen(n->name); + if (used+len+2+l0 >= alloced) { + alloced = used+len+2+l0 + 128; + path = realloc(path, alloced); + } + memmove(path+len+1, path, used); + memcpy(path, n->name, len); + path[len] = '/'; + used += len+1; + } + memcpy(path+used, name, l0+1); +/* pcb_trace("path='%s' used=%d\n", path, used);*/ + cb(ctx, pcb_gui->hid_cfg, node, path); + used = 0; + } + free(path); + } + + vtp0_uninit(&anchors); +} + +int pcb_hid_cfg_del_anchor_menus(lht_node_t *node, const char *cookie) +{ + lht_node_t *nxt; + + if ((node->type != LHT_TEXT) || (node->data.text.value == NULL) || (node->data.text.value[0] != '@')) + return -1; + + for(node = node->next; node != NULL; node = nxt) { + lht_node_t *ncookie; + + if (node->type != LHT_HASH) + break; + ncookie = lht_dom_hash_get(node, "cookie"); + +/* pcb_trace(" '%s' cookie='%s'\n", node->name, ncookie == NULL ? "NULL":ncookie->data.text.value );*/ + if ((ncookie == NULL) || (ncookie->type != LHT_TEXT) || (strcmp(ncookie->data.text.value, cookie) != 0)) + break; + + nxt = node->next; + pcb_gui->remove_menu_node(node); + } + return 0; +} Index: tags/2.1.2/src/hid_cfg.h =================================================================== --- tags/2.1.2/src/hid_cfg.h (nonexistent) +++ tags/2.1.2/src/hid_cfg.h (revision 24813) @@ -0,0 +1,128 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2016 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +/* Helpers for loading and handling lihata HID config files */ + +#ifndef PCB_HID_CFG_H +#define PCB_HID_CFG_H + +#include +#include +#include "global_typedefs.h" +#include "hid.h" + +struct pcb_hid_cfg_s { + lht_doc_t *doc; +}; + +/* Create a set of resources representing a single menu item + If action is NULL, it's a drop-down item that has submenus. + The callback is called after the new lihata node is created. + NOTE: unlike other cookies, this cookie is strdup()'d. + */ +typedef int (*pcb_create_menu_widget_t)(void *ctx, const char *path, const char *name, int is_main, lht_node_t *parent, lht_node_t *ins_after, lht_node_t *menu_item); +int pcb_hid_cfg_create_menu(pcb_hid_cfg_t *hr, const char *path, const pcb_menu_prop_t *props, pcb_create_menu_widget_t cb, void *cb_ctx); + +/* Remove a path recursively; call gui_remove() on leaf paths until the subtree + is consumed (should return 0 on success) */ +int pcb_hid_cfg_remove_menu(pcb_hid_cfg_t *hr, const char *path, int (*gui_remove)(void *ctx, lht_node_t *nd), void *ctx); +int pcb_hid_cfg_remove_menu_node(pcb_hid_cfg_t *hr, lht_node_t *root, int (*gui_remove)(void *ctx, lht_node_t *nd), void *ctx); + +/* Search and load the menu res for hidname; if not found, and embedded_fallback + is not NULL, parse that string instead. Returns NULL on error */ +pcb_hid_cfg_t *pcb_hid_cfg_load(const char *fn, int exact_fn, const char *embedded_fallback); + +/* Generic, low level lihata loader */ +lht_doc_t *pcb_hid_cfg_load_lht(const char *filename); +lht_doc_t *pcb_hid_cfg_load_str(const char *text); + +/* Generic, low level lihata text value fetch */ +const char *pcb_hid_cfg_text_value(lht_doc_t *doc, const char *path); + +lht_node_t *pcb_hid_cfg_get_menu(pcb_hid_cfg_t *hr, const char *menu_path); +lht_node_t *pcb_hid_cfg_get_menu_at(pcb_hid_cfg_t *hr, lht_node_t *at, const char *menu_path, lht_node_t *(*cb)(void *ctx, lht_node_t *node, const char *path, int rel_level), void *ctx); + +/* search all instances of an @anchor menu in the currently active GUI and + call cb on the lihata node; path has 128 extra bytes available at the end */ +void pcb_hid_cfg_map_anchor_menus(const char *name, void (*cb)(void *ctx, pcb_hid_cfg_t *cfg, lht_node_t *n, char *path), void *ctx); + +/* remove all adjacent anchor menus with matching cookie below anode, the + anchor node */ +int pcb_hid_cfg_del_anchor_menus(lht_node_t *anode, const char *cookie); + + +/* Fields are retrieved using this enum so that HIDs don't need to hardwire + lihata node names */ +typedef enum { + PCB_MF_ACCELERATOR, + PCB_MF_SUBMENU, + PCB_MF_CHECKED, + PCB_MF_UPDATE_ON, + PCB_MF_SENSITIVE, + PCB_MF_TIP, + PCB_MF_ACTIVE, + PCB_MF_ACTION, + PCB_MF_FOREGROUND, + PCB_MF_BACKGROUND, + PCB_MF_FONT +} pcb_hid_cfg_menufield_t; + +/* Return a field of a submenu and optionally fill in field_name with the + field name expected in the lihata document (useful for error messages) */ +lht_node_t *pcb_hid_cfg_menu_field(const lht_node_t *submenu, pcb_hid_cfg_menufield_t field, const char **field_name); + +/* Return a lihata node using a relative lihata path from parent - this is + just a wrapper around lht_tree_path_ */ +lht_node_t *pcb_hid_cfg_menu_field_path(const lht_node_t *parent, const char *path); + +/* Return a text field of a submenu; return NULL and generate a pcb_message(PCB_MSG_ERROR, ) if + the given field is not text */ +const char *pcb_hid_cfg_menu_field_str(const lht_node_t *submenu, pcb_hid_cfg_menufield_t field); + +/* Return non-zero if submenu has further submenus; generate pcb_message(PCB_MSG_ERROR, ) if + there is a submenu field with the wrong lihata type */ +int pcb_hid_cfg_has_submenus(const lht_node_t *submenu); + +/* Create a new hash node under parent (optional) and create a flat subtree of + text nodes from name,value varargs (NULL terminated). This is a shorthand + for creating a menu item in a subtree list. If ins_after is not NULL and + is under the same parent, the new menu is inserted after ins_after. */ +lht_node_t *pcb_hid_cfg_create_hash_node(lht_node_t *parent, lht_node_t *ins_after, const char *name, ...); + +/* Create a flat subtree of text nodes from name,value varargs (NULL + terminated). This is a shorthand for creating a menu item in a + subtree list. */ +void pcb_hid_cfg_extend_hash_node(lht_node_t *node, ...); +void pcb_hid_cfg_extend_hash_nodev(lht_node_t *node, va_list ap); + +/* Search a subtree in depth-first-search manner. Call cb on each node as + descending. If cb returns non-zero, stop the search and return that value. + Do all this recursively. */ +int pcb_hid_cfg_dfs(lht_node_t *parent, int (*cb)(void *ctx, lht_node_t *n), void *ctx); + +/* Report an error about a node */ +void pcb_hid_cfg_error(const lht_node_t *node, const char *fmt, ...); +#endif Index: tags/2.1.2/src/hid_cfg_action.c =================================================================== --- tags/2.1.2/src/hid_cfg_action.c (nonexistent) +++ tags/2.1.2/src/hid_cfg_action.c (revision 24813) @@ -0,0 +1,51 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2016 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "config.h" +#include "hid_cfg_action.h" +#include "actions.h" + +int pcb_hid_cfg_action(const lht_node_t *node) +{ + if (node == NULL) + return -1; + switch(node->type) { + case LHT_TEXT: + return pcb_parse_actions(node->data.text.value); + case LHT_LIST: + for(node = node->data.list.first; node != NULL; node = node->next) { + if (node->type == LHT_TEXT) { + if (pcb_parse_actions(node->data.text.value) != 0) + return -1; + } + else + return -1; + } + return 0; + default: ; /* suppress compiler warning: can't handle any other type */ + } + return -1; +} Index: tags/2.1.2/src/hid_cfg_action.h =================================================================== --- tags/2.1.2/src/hid_cfg_action.h (nonexistent) +++ tags/2.1.2/src/hid_cfg_action.h (revision 24813) @@ -0,0 +1,31 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2016 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + + +#include "hid_cfg.h" +/* Run an action node. The node is either a list of text nodes or a text node; + returns non-zero on error, the first action that fails in a chain breaks the chain */ +int pcb_hid_cfg_action(const lht_node_t *node); Index: tags/2.1.2/src/hid_cfg_input.c =================================================================== --- tags/2.1.2/src/hid_cfg_input.c (nonexistent) +++ tags/2.1.2/src/hid_cfg_input.c (revision 24813) @@ -0,0 +1,631 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2016 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "config.h" +#include "hid_cfg_input.h" +#include "hid_cfg_action.h" +#include "error.h" +#include "compat_misc.h" +#include "event.h" +#include "crosshair.h" + +/* split value into a list of '-' separated words; examine each word + and set the bitmask of modifiers */ +static pcb_hid_cfg_mod_t parse_mods(const char *value, const char **last, unsigned int vlen) +{ + pcb_hid_cfg_mod_t m = 0; + int press = 0; + const char *next; + + while(isspace(*value)) value++; + + if (*value != '<') { + for(;;) { + if ((vlen >= 5) && (pcb_strncasecmp(value, "shift", 5) == 0)) m |= PCB_M_Shift; + else if ((vlen >= 4) && (pcb_strncasecmp(value, "ctrl", 4) == 0)) m |= PCB_M_Ctrl; + else if ((vlen >= 3) && (pcb_strncasecmp(value, "alt", 3) == 0)) m |= PCB_M_Alt; + else if ((vlen >= 7) && (pcb_strncasecmp(value, "release", 7) == 0)) m |= PCB_M_Release; + else if ((vlen >= 5) && (pcb_strncasecmp(value, "press", 5) == 0)) press = 1; + else + pcb_message(PCB_MSG_ERROR, "Unknown modifier: %s\n", value); + /* skip to next word */ + next = strpbrk(value, "<- \t"); + if (next == NULL) + break; + if (*next == '<') + break; + vlen -= (next - value); + value = next+1; + } + } + + if (last != NULL) + *last = value; + + if (press && (m & PCB_M_Release)) + pcb_message(PCB_MSG_ERROR, "Bogus modifier: both press and release\n"); + + return m; +} + +static pcb_hid_cfg_mod_t button_name2mask(const char *name) +{ + /* All mouse-related resources must be named. The name is the + mouse button number. */ + if (!name) + return 0; + else if (pcb_strcasecmp(name, "left") == 0) return PCB_MB_LEFT; + else if (pcb_strcasecmp(name, "middle") == 0) return PCB_MB_MIDDLE; + else if (pcb_strcasecmp(name, "right") == 0) return PCB_MB_RIGHT; + + else if (pcb_strcasecmp(name, "scroll-up") == 0) return PCB_MB_SCROLL_UP; + else if (pcb_strcasecmp(name, "scroll-down") == 0) return PCB_MB_SCROLL_DOWN; + else if (pcb_strcasecmp(name, "scroll-left") == 0) return PCB_MB_SCROLL_UP; + else if (pcb_strcasecmp(name, "scroll-right") == 0) return PCB_MB_SCROLL_DOWN; + else { + pcb_message(PCB_MSG_ERROR, "Error: unknown mouse button: %s\n", name); + return 0; + } +} + +static unsigned int keyhash_int(htip_key_t a) { return murmurhash32(a & 0xFFFF); } + +static unsigned int keyb_hash(const void *key_) +{ + const hid_cfg_keyhash_t *key = key_; + unsigned int i = 0; + i += key->key_raw; i <<= 8; + i += ((unsigned int)key->key_tr) << 4; + i += key->mods; + return murmurhash32(i); +} + +static int keyb_eq(const void *keya_, const void *keyb_) +{ + const hid_cfg_keyhash_t *keya = keya_, *keyb = keyb_; + return (keya->key_raw == keyb->key_raw) && (keya->key_tr == keyb->key_tr) && (keya->mods == keyb->mods); +} + +/************************** MOUSE ***************************/ + +int hid_cfg_mouse_init(pcb_hid_cfg_t *hr, pcb_hid_cfg_mouse_t *mouse) +{ + lht_node_t *btn, *m; + + mouse->mouse = pcb_hid_cfg_get_menu(hr, "/mouse"); + + if (mouse->mouse == NULL) { + pcb_message(PCB_MSG_ERROR, "Warning: no /mouse section in the resource file - mouse is disabled\n"); + return -1; + } + + if (mouse->mouse->type != LHT_LIST) { + pcb_hid_cfg_error(mouse->mouse, "Warning: should be a list - mouse is disabled\n"); + return -1; + } + + if (mouse->mouse_mask == NULL) + mouse->mouse_mask = htip_alloc(keyhash_int, htip_keyeq); + else + htip_clear(mouse->mouse_mask); + + for(btn = mouse->mouse->data.list.first; btn != NULL; btn = btn->next) { + pcb_hid_cfg_mod_t btn_mask = button_name2mask(btn->name); + if (btn_mask == 0) { + pcb_hid_cfg_error(btn, "unknown mouse button"); + continue; + } + if (btn->type != LHT_LIST) { + pcb_hid_cfg_error(btn, "needs to be a list"); + continue; + } + for(m = btn->data.list.first; m != NULL; m = m->next) { + pcb_hid_cfg_mod_t mod_mask = parse_mods(m->name, NULL, -1); + htip_set(mouse->mouse_mask, btn_mask|mod_mask, m); + } + } + return 0; +} + +static lht_node_t *find_best_action(pcb_hid_cfg_mouse_t *mouse, pcb_hid_cfg_mod_t button_and_mask) +{ + lht_node_t *n; + + if (mouse->mouse_mask == NULL) + return NULL; + + /* look for exact mod match */ + n = htip_get(mouse->mouse_mask, button_and_mask); + if (n != NULL) + return n; + + if (button_and_mask & PCB_M_Release) { + /* look for plain release for the given button */ + n = htip_get(mouse->mouse_mask, (button_and_mask & PCB_M_ANY) | PCB_M_Release); + if (n != NULL) + return n; + } + + return NULL; +} + +void hid_cfg_mouse_action(pcb_hid_cfg_mouse_t *mouse, pcb_hid_cfg_mod_t button_and_mask, pcb_bool cmd_entry_active) +{ + pcb_crosshair.click_cmd_entry_active = cmd_entry_active; + pcb_hid_cfg_action(find_best_action(mouse, button_and_mask)); + pcb_event(PCB_EVENT_USER_INPUT_POST, NULL); + pcb_crosshair.click_cmd_entry_active = 0; +} + + +/************************** KEYBOARD ***************************/ +int pcb_hid_cfg_keys_init(pcb_hid_cfg_keys_t *km) +{ + htpp_init(&km->keys, keyb_hash, keyb_eq); + return 0; +} + +int pcb_hid_cfg_keys_uninit(pcb_hid_cfg_keys_t *km) +{ +TODO(": recursive free of nodes") + htpp_uninit(&km->keys); + return 0; +} + +pcb_hid_cfg_keyseq_t *pcb_hid_cfg_keys_add_under(pcb_hid_cfg_keys_t *km, pcb_hid_cfg_keyseq_t *parent, pcb_hid_cfg_mod_t mods, unsigned short int key_raw, unsigned short int key_tr, int terminal, const char **errmsg) +{ + pcb_hid_cfg_keyseq_t *ns; + hid_cfg_keyhash_t addr; + htpp_t *phash = (parent == NULL) ? &km->keys : &parent->seq_next; + + /* do not grow the tree under actions */ + if ((parent != NULL) && (parent->action_node != NULL)) { + if (*errmsg != NULL) + *errmsg = "unreachable multikey combo: prefix of the multikey stroke already has an action"; + return NULL; + } + + addr.mods = mods; + addr.key_raw = key_raw; + addr.key_tr = key_tr; + + /* already in the tree */ + ns = htpp_get(phash, &addr); + if (ns != NULL) { + if (terminal) { + if (*errmsg != NULL) + *errmsg = "duplicate: already registered"; + return NULL; /* full-path-match is collision */ + } + return ns; + } + + /* new node on this level */ + ns = calloc(sizeof(pcb_hid_cfg_keyseq_t), 1); + if (!terminal) + htpp_init(&ns->seq_next, keyb_hash, keyb_eq); + + ns->addr.mods = mods; + ns->addr.key_raw = key_raw; + ns->addr.key_tr = key_tr; + + htpp_set(phash, &ns->addr, ns); + return ns; +} + +const pcb_hid_cfg_keytrans_t hid_cfg_key_default_trans[] = { + { "semicolon", ';' }, + { NULL, 0 }, +}; + +static unsigned short int translate_key(pcb_hid_cfg_keys_t *km, const char *desc, int len) +{ + char tmp[256]; + + if ((km->auto_chr) && (len == 1)) + return *desc; + + if (len > sizeof(tmp)-1) { + pcb_message(PCB_MSG_ERROR, "key sym name too long\n"); + return 0; + } + strncpy(tmp, desc, len); + tmp[len] = '\0'; + + if (km->auto_tr != NULL) { + const pcb_hid_cfg_keytrans_t *t; + for(t = km->auto_tr; t->name != NULL; t++) { + if (pcb_strcasecmp(tmp, t->name) == 0) { + tmp[0] = t->sym; + tmp[1] = '\0'; + len = 1; + break; + } + } + } + + return km->translate_key(tmp, len); +} + +static int parse_keydesc(pcb_hid_cfg_keys_t *km, const char *keydesc, pcb_hid_cfg_mod_t *mods, unsigned short int *key_raws, unsigned short int *key_trs, int arr_len, const lht_node_t *loc) +{ + const char *curr, *next, *last, *k; + int slen, len; + + slen = 0; + curr = keydesc; + do { + if (slen >= arr_len) + return -1; + while(isspace(*curr)) curr++; + if (*curr == '\0') + break; + next = strchr(curr, ';'); + if (next != NULL) { + len = next - curr; + while(*next == ';') next++; + } + else + len = strlen(curr); + + mods[slen] = parse_mods(curr, &last, len); + + k = strchr(last, '<'); + if (k == NULL) { + pcb_message(PCB_MSG_ERROR, "Missing in the key description: '%s' at %s:%ld\n", keydesc, loc->file_name, loc->line+1); + return -1; + } + len -= k-last; + k++; len--; + if (pcb_strncasecmp(k, "key>", 4) == 0) { + k+=4; len-=4; + key_raws[slen] = translate_key(km, k, len); + key_trs[slen] = 0; + } + else if (pcb_strncasecmp(k, "char>", 5) == 0) { + k+=5; len-=5; + key_raws[slen] = 0; + if (!isalnum(*k)) + key_trs[slen] = *k; + else + key_trs[slen] = 0; + k++; len--; + } + else { + pcb_message(PCB_MSG_ERROR, "Missing or in the key description starting at %s at %s:%ld\n", k-1, loc->file_name, loc->line+1); + return -1; + } + + if ((key_raws[slen] == 0) && (key_trs[slen] == 0)) { + char *s; + s = malloc(len+1); + memcpy(s, k, len); + s[len] = '\0'; + pcb_message(PCB_MSG_ERROR, "Unrecognised key symbol in key description: %s at %s:%ld\n", s, loc->file_name, loc->line+1); + free(s); + return -1; + } + + slen++; + curr = next; + } while(curr != NULL); + return slen; +} + +int pcb_hid_cfg_keys_add_by_strdesc_(pcb_hid_cfg_keys_t *km, const char *keydesc, const lht_node_t *action_node, pcb_hid_cfg_keyseq_t **out_seq, int out_seq_len) +{ + pcb_hid_cfg_mod_t mods[HIDCFG_MAX_KEYSEQ_LEN]; + unsigned short int key_raws[HIDCFG_MAX_KEYSEQ_LEN]; + unsigned short int key_trs[HIDCFG_MAX_KEYSEQ_LEN]; + pcb_hid_cfg_keyseq_t *lasts; + int slen, n; + const char *errmsg; + + slen = parse_keydesc(km, keydesc, mods, key_raws, key_trs, HIDCFG_MAX_KEYSEQ_LEN, action_node); + if (slen <= 0) + return slen; + + if ((out_seq != NULL) && (slen >= out_seq_len)) + return -1; + +/* printf("KEY insert\n");*/ + + lasts = NULL; + for(n = 0; n < slen; n++) { + pcb_hid_cfg_keyseq_t *s; + int terminal = (n == slen-1); + +/* printf(" mods=%x sym=%x\n", mods[n], key_chars[n]);*/ + + s = pcb_hid_cfg_keys_add_under(km, lasts, mods[n], key_raws[n], key_trs[n], terminal, &errmsg); + if (s == NULL) { + pcb_message(PCB_MSG_ERROR, "Failed to add hotkey binding: %s: %s\n", keydesc, errmsg); +TODO(": free stuff?") + return -1; + } + if (terminal) + s->action_node = action_node; + + if (out_seq != NULL) + out_seq[n] = s; + lasts = s; + } + + return slen; +} + +int pcb_hid_cfg_keys_add_by_strdesc(pcb_hid_cfg_keys_t *km, const char *keydesc, const lht_node_t *action_node) +{ + return pcb_hid_cfg_keys_add_by_strdesc_(km, keydesc, action_node, NULL, 0); +} + +int pcb_hid_cfg_keys_add_by_desc_(pcb_hid_cfg_keys_t *km, const lht_node_t *keydescn, const lht_node_t *action_node, pcb_hid_cfg_keyseq_t **out_seq, int out_seq_len) +{ + switch(keydescn->type) { + case LHT_TEXT: return pcb_hid_cfg_keys_add_by_strdesc_(km, keydescn->data.text.value, action_node, out_seq, out_seq_len); + case LHT_LIST: + { + int ret = -1, cnt; + lht_node_t *n; + for(n = keydescn->data.list.first, cnt = 0; n != NULL; n = n->next, cnt++) { + if (n->type != LHT_TEXT) + break; + if (cnt == 0) + ret = pcb_hid_cfg_keys_add_by_strdesc_(km, n->data.text.value, action_node, out_seq, out_seq_len); + else + pcb_hid_cfg_keys_add_by_strdesc_(km, n->data.text.value, action_node, NULL, 0); + } + return ret; + } + default:; + } + return -1; +} + +int pcb_hid_cfg_keys_add_by_desc(pcb_hid_cfg_keys_t *km, const lht_node_t *keydescn, const lht_node_t *action_node) +{ + return pcb_hid_cfg_keys_add_by_desc_(km, keydescn, action_node, NULL, 0); +} + +static void gen_accel(gds_t *s, pcb_hid_cfg_keys_t *km, const char *keydesc, int *cnt, const char *sep, const lht_node_t *loc) +{ + pcb_hid_cfg_mod_t mods[HIDCFG_MAX_KEYSEQ_LEN]; + unsigned short int key_raws[HIDCFG_MAX_KEYSEQ_LEN]; + unsigned short int key_trs[HIDCFG_MAX_KEYSEQ_LEN]; + int slen, n; + + slen = parse_keydesc(km, keydesc, mods, key_raws, key_trs, HIDCFG_MAX_KEYSEQ_LEN, loc); + if (slen <= 0) + return; + + if (*cnt > 0) + gds_append_str(s, sep); + + for(n = 0; n < slen; n++) { + char buff[64]; + + if (n > 0) + gds_append(s, ' '); + + + if (key_raws[n]) { + if (km->key_name(key_raws[n], buff, sizeof(buff)) != 0) + strcpy(buff, ""); + } + else if (key_trs[n] != 0) { + buff[0] = key_trs[n]; + buff[1] ='\0'; + } + else + strcpy(buff, ""); + + if (mods[n] & PCB_M_Alt) gds_append_str(s, "Alt-"); + if (mods[n] & PCB_M_Ctrl) gds_append_str(s, "Ctrl-"); + if (mods[n] & PCB_M_Shift) gds_append_str(s, "Shift-"); + gds_append_str(s, buff); + } +} + +char *pcb_hid_cfg_keys_gen_accel(pcb_hid_cfg_keys_t *km, const lht_node_t *keydescn, unsigned long mask, const char *sep) +{ + gds_t s; + int cnt = 0; + + memset(&s, 0, sizeof(s)); + + switch(keydescn->type) { + case LHT_TEXT: + if (mask & 1) + gen_accel(&s, km, keydescn->data.text.value, &cnt, sep, keydescn); + break; + case LHT_LIST: + { + int cnt; + lht_node_t *n; + for(n = keydescn->data.list.first, cnt = 0; n != NULL; n = n->next, cnt++, mask >>= 1) { + if (n->type != LHT_TEXT) + break; + if (!(mask & 1)) + continue; + gen_accel(&s, km, n->data.text.value, &cnt, sep, keydescn); + } + } + default:; + } + return s.array; +} + + +int pcb_hid_cfg_keys_input_(pcb_hid_cfg_keys_t *km, pcb_hid_cfg_mod_t mods, unsigned short int key_raw, unsigned short int key_tr, pcb_hid_cfg_keyseq_t **seq, int *seq_len) +{ + pcb_hid_cfg_keyseq_t *ns; + hid_cfg_keyhash_t addr; + htpp_t *phash = (*seq_len == 0) ? &km->keys : &((seq[(*seq_len)-1])->seq_next); + + if (key_raw == 0) { + static int warned = 0; + if (!warned) { + pcb_message(PCB_MSG_ERROR, "Keyboard translation error: probably the US layout is not enabled. Some hotkeys may not work properly\n"); + warned = 1; + } + /* happens if only the translated version is available. Try to reverse + engineer it as good as we can. */ + if (isalpha(key_tr)) { + if (isupper(key_tr)) { + key_raw = tolower(key_tr); + mods |= PCB_M_Shift; + } + else + key_raw = key_tr; + } + else if (isdigit(key_tr)) + key_raw = key_tr; + /* the rest: punctuations should be handled by key_tr; special keys: well... */ + } + + /* first check for base key + mods */ + addr.mods = mods; + addr.key_raw = key_raw; + addr.key_tr = 0; + + ns = htpp_get(phash, &addr); + + /* if not found, try with translated key + limited mods */ + if (ns == NULL) { + addr.mods = mods & PCB_M_Ctrl; + addr.key_raw = 0; + addr.key_tr = key_tr; + ns = htpp_get(phash, &addr); + } + + /* already in the tree */ + if (ns == NULL) { + (*seq_len) = 0; + return -1; + } + + seq[*seq_len] = ns; + (*seq_len)++; + + /* found a terminal node with an action */ + if (ns->action_node != NULL) { + km->seq_len_action = *seq_len; + (*seq_len) = 0; + return km->seq_len_action; + } + + return 0; +} + +int pcb_hid_cfg_keys_input(pcb_hid_cfg_keys_t *km, pcb_hid_cfg_mod_t mods, unsigned short int key_raw, unsigned short int key_tr) +{ + return pcb_hid_cfg_keys_input_(km, mods, key_raw, key_tr, km->seq, &km->seq_len); +} + +int pcb_hid_cfg_keys_action_(pcb_hid_cfg_keyseq_t **seq, int seq_len) +{ + int res; + + if (seq_len < 1) + return -1; + + res = pcb_hid_cfg_action(seq[seq_len-1]->action_node); + pcb_event(PCB_EVENT_USER_INPUT_POST, NULL); + return res; +} + +int pcb_hid_cfg_keys_action(pcb_hid_cfg_keys_t *km) +{ + int ret = pcb_hid_cfg_keys_action_(km->seq, km->seq_len_action); + km->seq_len_action = 0; + return ret; +} + +int pcb_hid_cfg_keys_seq_(pcb_hid_cfg_keys_t *km, pcb_hid_cfg_keyseq_t **seq, int seq_len, char *dst, int dst_len) +{ + int n, sum = 0; + char *end = dst; + + dst_len -= 25; /* make room for a full key with modifiers, the \0 and the potential ellipsis */ + + for(n = 0; n < seq_len; n++) { + int k = seq[n]->addr.key_raw, mods = seq[n]->addr.mods, ll = 0, l; + + if (n != 0) { + *end = ' '; + end++; + ll = 1; + } + + if (mods & PCB_M_Alt) { strncpy(end, "Alt-", dst_len); end += 4; ll += 4; } + if (mods & PCB_M_Ctrl) { strncpy(end, "Ctrl-", dst_len); end += 5; ll += 5; } + if (mods & PCB_M_Shift) { strncpy(end, "Shift-", dst_len); end += 6; ll += 6; } + + if (k == 0) + k = seq[n]->addr.key_tr; + + if (km->key_name(k, end, dst_len) == 0) { + l = strlen(end); + } + else { + strncpy(end, "", dst_len); + l = 9; + } + + ll += l; + + sum += ll; + dst_len -= ll; + end += l; + + if (dst_len <= 1) { + strcpy(dst, " ..."); + sum += 4; + dst_len -= 4; + end += 4; + break; + } + } + *end = '\0'; + return sum; +} + +int pcb_hid_cfg_keys_seq(pcb_hid_cfg_keys_t *km, char *dst, int dst_len) +{ + if (km->seq_len_action > 0) + return pcb_hid_cfg_keys_seq_(km, km->seq, km->seq_len_action, dst, dst_len); + else + return pcb_hid_cfg_keys_seq_(km, km->seq, km->seq_len, dst, dst_len); +} Index: tags/2.1.2/src/hid_cfg_input.h =================================================================== --- tags/2.1.2/src/hid_cfg_input.h (nonexistent) +++ tags/2.1.2/src/hid_cfg_input.h (revision 24813) @@ -0,0 +1,161 @@ +#ifndef PCB_HID_CFG_INPUT_H +#define PCB_HID_CFG_INPUT_H + +#include +#include +#include +#include "hid_cfg.h" + +#define PCB_M_Mod0(n) (1u<<(n)) +typedef enum { + PCB_M_Shift = PCB_M_Mod0(0), + PCB_M_Ctrl = PCB_M_Mod0(1), + PCB_M_Alt = PCB_M_Mod0(2), + PCB_M_Mod1 = PCB_M_Alt, + /* PCB_M_Mod(3) is PCB_M_Mod0(4) */ + /* PCB_M_Mod(4) is PCB_M_Mod0(5) */ + PCB_M_Release = PCB_M_Mod0(6), /* there might be a random number of modkeys, but hopefully not this many */ + + PCB_MB_LEFT = PCB_M_Mod0(7), + PCB_MB_MIDDLE = PCB_M_Mod0(8), + PCB_MB_RIGHT = PCB_M_Mod0(9), + +/* scroll wheel */ + PCB_MB_SCROLL_UP = PCB_M_Mod0(10), + PCB_MB_SCROLL_DOWN = PCB_M_Mod0(11), + PCB_MB_SCROLL_LEFT = PCB_M_Mod0(12), + PCB_MB_SCROLL_RIGHT = PCB_M_Mod0(13) +} pcb_hid_cfg_mod_t; +#undef PCB_M_Mod0 + +#define PCB_MB_ANY (PCB_MB_LEFT | PCB_MB_MIDDLE | PCB_MB_RIGHT | PCB_MB_SCROLL_UP | PCB_MB_SCROLL_DOWN | PCB_MB_SCROLL_LEFT | PCB_MB_SCROLL_RIGHT) +#define PCB_M_ANY (PCB_M_Release-1) + +/************************** MOUSE ***************************/ + +typedef struct { + lht_node_t *mouse; + htip_t *mouse_mask; +} pcb_hid_cfg_mouse_t; + +int hid_cfg_mouse_init(pcb_hid_cfg_t *hr, pcb_hid_cfg_mouse_t *mouse); +void hid_cfg_mouse_action(pcb_hid_cfg_mouse_t *mouse, pcb_hid_cfg_mod_t button_and_mask, pcb_bool cmd_entry_active); + + +/************************** KEYBOARD ***************************/ +#define HIDCFG_MAX_KEYSEQ_LEN 32 +typedef struct hid_cfg_keyhash_s { + unsigned short int mods; /* of pcb_hid_cfg_mod_t */ + unsigned short int key_raw; + unsigned short int key_tr; +} hid_cfg_keyhash_t; + + +typedef struct pcb_hid_cfg_keyseq_s pcb_hid_cfg_keyseq_t; +struct pcb_hid_cfg_keyseq_s { + hid_cfg_keyhash_t addr; + + unsigned long int keysym; /* optional 32 bit long storage the GUI hid should cast to whatever the GUI backend supports */ + + const lht_node_t *action_node; /* terminal node: end of sequence, run actions */ + + htpp_t seq_next; /* ... or if node is NULL, a hash for each key that may follow the current one */ + pcb_hid_cfg_keyseq_t *parent; +}; + +/* Translate symbolic name to single-char keysym before processing; useful + for shortcuts like "Return -> '\r'" which are otherwise hard to describe + in text format */ +typedef struct pcb_hid_cfg_keytrans_s { + const char *name; + char sym; +} pcb_hid_cfg_keytrans_t; + +extern const pcb_hid_cfg_keytrans_t hid_cfg_key_default_trans[]; + +/* A complete tree of keyboard shortcuts/hotkeys */ +typedef struct pcb_hid_cfg_keys_s { + htpp_t keys; + + /* translate key sym description (the portion after ) to key_char; + desc is a \0 terminated string, len is only a hint. Should return 0 + on error. */ + unsigned short int (*translate_key)(const char *desc, int len); + + /* convert a key_char to human readable name, copy the string to out/out_len. + Return 0 on success. */ + int (*key_name)(unsigned short int key_char, char *out, int out_len); + + + int auto_chr; /* if non-zero: don't call translate_key() for 1-char symbols, handle the default way */ + const pcb_hid_cfg_keytrans_t *auto_tr; /* apply this table before calling translate_key() */ + + /* current sequence state */ + pcb_hid_cfg_keyseq_t *seq[HIDCFG_MAX_KEYSEQ_LEN]; + int seq_len; + int seq_len_action; /* when an action node is hit, save sequence length for executing the action while seq_len is reset */ +} pcb_hid_cfg_keys_t; + + +/* Initialize a new keyboard context + Returns 0 on success. +*/ +int pcb_hid_cfg_keys_init(pcb_hid_cfg_keys_t *km); + +/* Free km's fields recursively */ +int pcb_hid_cfg_keys_uninit(pcb_hid_cfg_keys_t *km); + +/* Add the next key of a key sequence; key sequences form a tree. A key starting + a new key sequence should have parent set NULL, subsequent calls should have + parent set to the previously returned keyseq value. Terminal is non-zero if + this is the last key of the sequence. + Raw vs. translated keys are desribed at pcb_hid_cfg_keys_input(). + Returns NULL on error and loads errmsg if not NULL */ +pcb_hid_cfg_keyseq_t *pcb_hid_cfg_keys_add_under(pcb_hid_cfg_keys_t *km, pcb_hid_cfg_keyseq_t *parent, pcb_hid_cfg_mod_t mods, unsigned short int key_raw, unsigned short int key_tr, int terminal, const char **errmsg); + +/* Add a new key using a description (read from a lihata file usually) + If out_seq is not NULL, load the array with pointers pointing to each + key in the sequence, up to out_seq_len. + When key desc is a lihata node, it may be a list (multiple keys for the + same action). In this case return value and seq are set using the first key. + Returns -1 on failure or the length of the sequence. +*/ +int pcb_hid_cfg_keys_add_by_desc(pcb_hid_cfg_keys_t *km, const lht_node_t *keydesc, const lht_node_t *action_node); +int pcb_hid_cfg_keys_add_by_desc_(pcb_hid_cfg_keys_t *km, const lht_node_t *keydesc, const lht_node_t *action_node, pcb_hid_cfg_keyseq_t **out_seq, int out_seq_len); +int pcb_hid_cfg_keys_add_by_strdesc(pcb_hid_cfg_keys_t *km, const char *keydesc, const lht_node_t *action_node); +int pcb_hid_cfg_keys_add_by_strdesc_(pcb_hid_cfg_keys_t *km, const char *keydesc, const lht_node_t *action_node, pcb_hid_cfg_keyseq_t **out_seq, int out_seq_len); + + +/* Allocate a new string and generate a human readable accel-text; mask determines + which keys on the list are generated (when multiple key sequences are + specified for the same action; from LSB to MSB, at most 32 keys) + Caller needs to free the string; returns NULL on error. + */ +char *pcb_hid_cfg_keys_gen_accel(pcb_hid_cfg_keys_t *km, const lht_node_t *keydescn, unsigned long mask, const char *sep); + +/* Process next input key stroke. + Seq and seq_len must not be NULL as they are the internal state of multi-key + processing. Load seq array with pointers pointing to each key in the + sequence, up to seq_len. + Key_raw is the raw key code for base keys, without any translation, key_tr + is the translated character; e.g. shift+1 is always reported as key_raw=1 + and on US keyboard reported as key_tr=! + Returns: + -1 if the key stroke or sequence is invalid + 0 if more characters needed to complete the sequence + + a positive integer means the lookup succeeded and the return value + is the length of the resulting sequence. +*/ +int pcb_hid_cfg_keys_input(pcb_hid_cfg_keys_t *km, pcb_hid_cfg_mod_t mods, unsigned short int key_raw, unsigned short int key_tr); +int pcb_hid_cfg_keys_input_(pcb_hid_cfg_keys_t *km, pcb_hid_cfg_mod_t mods, unsigned short int key_raw, unsigned short int key_tr, pcb_hid_cfg_keyseq_t **seq, int *seq_len); + +/* Run the action for a key sequence looked up by pcb_hid_cfg_keys_input(). + Returns: the result of the action or -1 on error */ +int pcb_hid_cfg_keys_action(pcb_hid_cfg_keys_t *km); +int pcb_hid_cfg_keys_action_(pcb_hid_cfg_keyseq_t **seq, int seq_len); + +/* Print a squence into dst in human readable form; returns strlen(dst) */ +int pcb_hid_cfg_keys_seq(pcb_hid_cfg_keys_t *km, char *dst, int dst_len); +int pcb_hid_cfg_keys_seq_(pcb_hid_cfg_keys_t *km, pcb_hid_cfg_keyseq_t **seq, int seq_len, char *dst, int dst_len); + +#endif Index: tags/2.1.2/src/hid_color.c =================================================================== --- tags/2.1.2/src/hid_color.c (nonexistent) +++ tags/2.1.2/src/hid_color.c (revision 24813) @@ -0,0 +1,88 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * Copyright (C) 2004 harry eaton + * Copyright (C) 2016..2018 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +#include +#include "config.h" +#include "hid_color.h" +#include +#include "compat_misc.h" + +static pcb_hidval_t invalid_color = { 0 }; + +#define HT_HAS_CONST_KEY +typedef char *htsh_key_t; +typedef const char *htsh_const_key_t; +typedef pcb_hidval_t htsh_value_t; +#define HT_INVALID_VALUE invalid_color +#define HT(x) htsh_ ## x +#include +#include +#undef HT + + +int pcb_hid_cache_color(int set, const char *name, pcb_hidval_t * val, void **vcache) +{ + htsh_t *cache; + htsh_entry_t *e; + + cache = (htsh_t *) * vcache; + if (cache == 0) { + cache = htsh_alloc(strhash, strkeyeq); + *vcache = cache; + } + + if (!set) { /* read */ + e = htsh_getentry(cache, (char *)name); + if (e == NULL) /* not found */ + return 0; + memcpy(val, &e->value, sizeof(pcb_hidval_t)); + } + else + htsh_set(cache, pcb_strdup(name), *val); /* write */ + + return 1; +} + +void pcb_hid_cache_color_destroy(void **vcache, void (*user_free)(void **vcache, const char *name, pcb_hidval_t *val)) +{ + htsh_t *cache = (htsh_t *) * vcache; + htsh_entry_t *e; + + if (cache == 0) + return; + + for (e = htsh_first(cache); e; e = htsh_next(cache, e)) { + user_free(vcache, e->key, &e->value); + free(e->key); /* name allocated with pcb_strdup() */ + } + htsh_free(cache); + *vcache = NULL; +} + Index: tags/2.1.2/src/hid_color.h =================================================================== --- tags/2.1.2/src/hid_color.h (nonexistent) +++ tags/2.1.2/src/hid_color.h (revision 24813) @@ -0,0 +1,18 @@ +#ifndef PCB_HID_COLOR_H +#define PCB_HID_COLOR_H + +#include "hid.h" + +/* HID internal interfaces. These may ONLY be called from the HID + modules, not from the common PCB code. */ + +/* Used to cache color lookups. If set is zero, it looks up the name + and if found sets val and returns nonzero. If not found, it + returns zero. If set is nonzero, name/val is added to the + cache. */ +int pcb_hid_cache_color(int set, const char *name, pcb_hidval_t * val, void **cache); + +/* Call user_free() on each cache entry and then destroy the cache */ +void pcb_hid_cache_color_destroy(void **vcache, void (*user_free)(void **vcache, const char *name, pcb_hidval_t *val)); + +#endif Index: tags/2.1.2/src/hid_dad.h =================================================================== --- tags/2.1.2/src/hid_dad.h (nonexistent) +++ tags/2.1.2/src/hid_dad.h (revision 24813) @@ -0,0 +1,676 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2017,2018,2019 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#ifndef PCB_HID_DAD_H +#define PCB_HID_DAD_H + +#include +#include +#include "compat_misc.h" +#include "hid_attrib.h" +#include "pcb-printf.h" +#include "global_typedefs.h" + + +/*** Helpers for building dynamic attribute dialogs (DAD) ***/ +#define PCB_DAD_DECL(table) \ + pcb_hid_attribute_t *table = NULL; \ + pcb_hid_attr_val_t *table ## _result = NULL; \ + int table ## _append_lock = 0; \ + int table ## _len = 0; \ + int table ## _alloced = 0; \ + void *table ## _hid_ctx = NULL; \ + int table ## _defx = 0, table ## _defy = 0; \ + pcb_dad_retovr_t *table ## _ret_override; + +#define PCB_DAD_DECL_NOINIT(table) \ + pcb_hid_attribute_t *table; \ + pcb_hid_attr_val_t *table ## _result; \ + int table ## _append_lock; \ + int table ## _len; \ + int table ## _alloced; \ + void *table ## _hid_ctx; \ + int table ## _defx, table ## _defy; \ + pcb_dad_retovr_t *table ## _ret_override; + +/* Free all resources allocated by DAD macros for table */ +#define PCB_DAD_FREE(table) \ +do { \ + int __n__; \ + if ((table ## _hid_ctx != NULL) && (table ## _ret_override != NULL)) \ + pcb_gui->attr_dlg_free(table ## _hid_ctx); \ + for(__n__ = 0; __n__ < table ## _len; __n__++) { \ + PCB_DAD_FREE_FIELD(table, __n__); \ + } \ + free(table); \ + free(table ## _result); \ + table = NULL; \ + table ## _result = NULL; \ + table ## _hid_ctx = NULL; \ + table ## _len = 0; \ + table ## _alloced = 0; \ + table ## _append_lock = 0; \ + if ((table ## _ret_override != NULL) && (table ## _ret_override->dont_free == 0)) {\ + free(table ## _ret_override); \ + table ## _ret_override = NULL; \ + } \ +} while(0) + +#define PCB_DAD_NEW(id, table, title, caller_data, modal, ev_cb) \ +do { \ + if (table ## _result == NULL) \ + PCB_DAD_ALLOC_RESULT(table); \ + table ## _ret_override = calloc(sizeof(pcb_dad_retovr_t), 1); \ + table ## _append_lock = 1; \ + table ## _hid_ctx = pcb_gui->attr_dlg_new(id, table, table ## _len, table ## _result, title, caller_data, modal, ev_cb, table ## _defx, table ## _defy); \ +} while(0) + +/* Sets the default window size (that is only a hint) - NOTE: must be called + before PCB_DAD_NEW() */ +#define PCB_DAD_DEFSIZE(table, width, height) \ +do { \ + table ## _defx = width; \ + table ## _defy = height; \ +} while(0) + +#define PCB_DAD_RUN(table) pcb_hid_dad_run(table ## _hid_ctx, table ## _ret_override) + +/* failed is non-zero on cancel */ +#define PCB_DAD_AUTORUN(id, table, title, caller_data, failed) \ +do { \ + if (table ## _result == NULL) \ + PCB_DAD_ALLOC_RESULT(table); \ + table ## _ret_override = calloc(sizeof(pcb_dad_retovr_t), 1); \ + table ## _ret_override->dont_free++; \ + table ## _ret_override->valid = 0; \ + table ## _append_lock = 1; \ + failed = pcb_attribute_dialog_(id,table, table ## _len, table ## _result, title, caller_data, (void **)&(table ## _ret_override), table ## _defx, table ## _defy, &table ## _hid_ctx); \ + if (table ## _ret_override->valid) \ + failed = table ## _ret_override->value; \ + table ## _ret_override->dont_free--; \ +} while(0) + +/* Return the index of the item currenty being edited */ +#define PCB_DAD_CURRENT(table) (table ## _len - 1) + +/* Begin a new box or table */ +#define PCB_DAD_BEGIN(table, item_type) \ + PCB_DAD_ALLOC(table, item_type); + +#define PCB_DAD_BEGIN_TABLE(table, cols) \ +do { \ + PCB_DAD_BEGIN(table, PCB_HATT_BEGIN_TABLE); \ + PCB_DAD_SET_ATTR_FIELD(table, pcb_hatt_table_cols, cols); \ +} while(0) + +#define PCB_DAD_BEGIN_TABBED(table, tabs) \ +do { \ + PCB_DAD_BEGIN(table, PCB_HATT_BEGIN_TABBED); \ + PCB_DAD_SET_ATTR_FIELD(table, enumerations, tabs); \ +} while(0) + +#define PCB_DAD_BEGIN_HBOX(table) PCB_DAD_BEGIN(table, PCB_HATT_BEGIN_HBOX) +#define PCB_DAD_BEGIN_VBOX(table) PCB_DAD_BEGIN(table, PCB_HATT_BEGIN_VBOX) +#define PCB_DAD_END(table) PCB_DAD_BEGIN(table, PCB_HATT_END) +#define PCB_DAD_COMPFLAG(table, val) PCB_DAD_SET_ATTR_FIELD(table, pcb_hatt_flags, val | (table[table ## _len-1].pcb_hatt_flags & PCB_HATF_TREE_COL)) + +#define PCB_DAD_LABEL(table, text) \ +do { \ + PCB_DAD_ALLOC(table, PCB_HATT_LABEL); \ + PCB_DAD_SET_ATTR_FIELD(table, name, pcb_strdup(text)); \ +} while(0) + +/* Add label usign printf formatting syntax: PCB_DAD_LABELF(tbl, ("a=%d", 12)); */ +#define PCB_DAD_LABELF(table, printf_args) \ +do { \ + PCB_DAD_ALLOC(table, PCB_HATT_LABEL); \ + PCB_DAD_SET_ATTR_FIELD(table, name, pcb_strdup_printf printf_args); \ +} while(0) + +#define PCB_DAD_ENUM(table, choices) \ +do { \ + PCB_DAD_ALLOC(table, PCB_HATT_ENUM); \ + PCB_DAD_SET_ATTR_FIELD(table, enumerations, choices); \ +} while(0) + +#define PCB_DAD_BOOL(table, label) \ +do { \ + PCB_DAD_ALLOC(table, PCB_HATT_BOOL); \ + PCB_DAD_SET_ATTR_FIELD(table, name, pcb_strdup(label)); \ +} while(0) + +#define PCB_DAD_INTEGER(table, label) \ +do { \ + PCB_DAD_ALLOC(table, PCB_HATT_INTEGER); \ + PCB_DAD_SET_ATTR_FIELD(table, name, label); \ +} while(0) + +#define PCB_DAD_REAL(table, label) \ +do { \ + PCB_DAD_ALLOC(table, PCB_HATT_REAL); \ + PCB_DAD_SET_ATTR_FIELD(table, name, label); \ +} while(0) + +#define PCB_DAD_UNIT(table) \ +do { \ + PCB_DAD_ALLOC(table, PCB_HATT_UNIT); \ +} while(0) + +#define PCB_DAD_COORD(table, label) \ +do { \ + PCB_DAD_ALLOC(table, PCB_HATT_COORD); \ + PCB_DAD_SET_ATTR_FIELD(table, name, label); \ +} while(0) + +#define PCB_DAD_STRING(table) \ + PCB_DAD_ALLOC(table, PCB_HATT_STRING); \ + +#define PCB_DAD_TEXT(table, user_ctx_) \ +do { \ + pcb_hid_text_t *txt = calloc(sizeof(pcb_hid_text_t), 1); \ + txt->user_ctx = user_ctx_; \ + PCB_DAD_ALLOC(table, PCB_HATT_TEXT); \ + PCB_DAD_SET_ATTR_FIELD(table, enumerations, (const char **)txt); \ +} while(0) + +#define PCB_DAD_BUTTON(table, text) \ +do { \ + PCB_DAD_ALLOC(table, PCB_HATT_BUTTON); \ + table[table ## _len - 1].default_val.str_value = text; \ +} while(0) + +#define PCB_DAD_BUTTON_CLOSE(table, text, retval) \ +do { \ + PCB_DAD_ALLOC(table, PCB_HATT_BUTTON); \ + table[table ## _len - 1].default_val.str_value = text; \ + table[table ## _len - 1].default_val.int_value = retval; \ + table[table ## _len - 1].enumerations = (const char **)(&table ## _ret_override); \ + PCB_DAD_CHANGE_CB(table, pcb_hid_dad_close_cb); \ +} while(0) + +/* Draw a set of close buttons without trying to fill a while hbox row */ +#define PCB_DAD_BUTTON_CLOSES_NAKED(table, buttons) \ +do { \ + pcb_hid_dad_buttons_t *__n__; \ + PCB_DAD_BEGIN_HBOX(table); \ + PCB_DAD_COMPFLAG(table, PCB_HATF_EXPFILL); \ + PCB_DAD_END(table); \ + for(__n__ = buttons; __n__->label != NULL; __n__++) { \ + PCB_DAD_BUTTON_CLOSE(table, __n__->label, __n__->retval); \ + } \ +} while(0) + +/* Draw a set of close buttons, adding a new hbox that tries to fill a whole row */ +#define PCB_DAD_BUTTON_CLOSES(table, buttons) \ +do { \ + PCB_DAD_BEGIN_HBOX(table); \ + PCB_DAD_BUTTON_CLOSES_NAKED(table, buttons); \ + PCB_DAD_END(table); \ +} while(0) + + +#define PCB_DAD_PROGRESS(table) \ +do { \ + PCB_DAD_ALLOC(table, PCB_HATT_PROGRESS); \ +} while(0) + +#define PCB_DAD_PREVIEW(table, expose_cb, mouse_cb, free_cb, initial_view_box, min_sizex_px_, min_sizey_px_, user_ctx_) \ +do { \ + pcb_hid_preview_t *prv = calloc(sizeof(pcb_hid_preview_t), 1); \ + prv->user_ctx = user_ctx_; \ + prv->user_expose_cb = expose_cb; \ + prv->user_mouse_cb = mouse_cb; \ + prv->user_free_cb = free_cb; \ + prv->min_sizex_px = min_sizex_px_; \ + prv->min_sizey_px = min_sizey_px_; \ + if ((initial_view_box) != NULL) { \ + prv->initial_view.X1 = ((pcb_box_t *)(initial_view_box))->X1; \ + prv->initial_view.Y1 = ((pcb_box_t *)(initial_view_box))->Y1; \ + prv->initial_view.X2 = ((pcb_box_t *)(initial_view_box))->X2; \ + prv->initial_view.Y2 = ((pcb_box_t *)(initial_view_box))->Y2; \ + prv->initial_view_valid = 1; \ + } \ + PCB_DAD_ALLOC(table, PCB_HATT_PREVIEW); \ + prv->attrib = &table[table ## _len-1]; \ + PCB_DAD_SET_ATTR_FIELD(table, enumerations, (const char **)prv); \ +} while(0) + +#define pcb_dad_preview_zoomto(attr, view) \ +do { \ + pcb_hid_preview_t *prv = (pcb_hid_preview_t *)((attr)->enumerations); \ + if (prv->hid_zoomto_cb != NULL) \ + prv->hid_zoomto_cb((attr), prv->hid_wdata, view); \ +} while(0) + + +#define PCB_DAD_PICTURE(table, xpm) \ +do { \ + PCB_DAD_ALLOC(table, PCB_HATT_PICTURE); \ + table[table ## _len - 1].enumerations = xpm; \ +} while(0) + +#define PCB_DAD_PICBUTTON(table, xpm) \ +do { \ + PCB_DAD_ALLOC(table, PCB_HATT_PICBUTTON); \ + table[table ## _len - 1].enumerations = xpm; \ +} while(0) + + +#define PCB_DAD_COLOR(table) \ +do { \ + PCB_DAD_ALLOC(table, PCB_HATT_COLOR); \ +} while(0) + +#define PCB_DAD_BEGIN_HPANE(table) \ +do { \ + PCB_DAD_BEGIN(table, PCB_HATT_BEGIN_HPANE); \ + table[table ## _len - 1].default_val.real_value = 0.5; \ +} while(0) + +#define PCB_DAD_BEGIN_VPANE(table) \ +do { \ + PCB_DAD_BEGIN(table, PCB_HATT_BEGIN_VPANE); \ + table[table ## _len - 1].default_val.real_value = 0.5; \ +} while(0) + +#define PCB_DAD_TREE(table, cols, first_col_is_tree, opt_header) \ +do { \ + pcb_hid_tree_t *tree = calloc(sizeof(pcb_hid_tree_t), 1); \ + htsp_init(&tree->paths, strhash, strkeyeq); \ + PCB_DAD_ALLOC(table, PCB_HATT_TREE); \ + tree->attrib = &table[table ## _len-1]; \ + tree->hdr = opt_header; \ + PCB_DAD_SET_ATTR_FIELD(table, pcb_hatt_table_cols, cols); \ + PCB_DAD_SET_ATTR_FIELD(table, pcb_hatt_flags, first_col_is_tree ? PCB_HATF_TREE_COL : 0); \ + PCB_DAD_SET_ATTR_FIELD(table, enumerations, (const char **)tree); \ +} while(0) + +#define PCB_DAD_TREE_APPEND(table, row_after, cells) \ + pcb_dad_tree_append(&table[table ## _len-1], row_after, cells) + +#define PCB_DAD_TREE_APPEND_UNDER(table, parent_row, cells) \ + pcb_dad_tree_append_under(&table[table ## _len-1], parent_row, cells) + +#define PCB_DAD_TREE_INSERT(table, row_before, cells) \ + pcb_dad_tree_insert(&table[table ## _len-1], row_before, cells) + +/* set the named tree user callback to func_or_data; name is automatically + appended with user_, any field prefixed with user_ in pcb_hid_tree_t + can be set */ +#define PCB_DAD_TREE_SET_CB(table, name, func_or_data) \ +do { \ + pcb_hid_tree_t *__tree__ = (pcb_hid_tree_t *)table[table ## _len-1].enumerations; \ + __tree__->user_ ## name = func_or_data; \ +} while(0) + +#define PCB_DAD_DUP_ATTR(table, attr) \ +do { \ + PCB_DAD_ALLOC(table, 0); \ + memcpy(&table[table ## _len-1], (attr), sizeof(pcb_hid_attribute_t)); \ + PCB_DAD_UPDATE_INTERNAL(table, table ## _len-1); \ +} while(0) + + +/* Set properties of the current item */ +#define PCB_DAD_MINVAL(table, val) PCB_DAD_SET_ATTR_FIELD(table, min_val, val) +#define PCB_DAD_MAXVAL(table, val) PCB_DAD_SET_ATTR_FIELD(table, max_val, val) +#define PCB_DAD_MINMAX(table, min, max) (PCB_DAD_SET_ATTR_FIELD(table, min_val, min),PCB_DAD_SET_ATTR_FIELD(table, max_val, max)) +#define PCB_DAD_CHANGE_CB(table, cb) PCB_DAD_SET_ATTR_FIELD(table, change_cb, cb) +#define PCB_DAD_ENTER_CB(table, cb) PCB_DAD_SET_ATTR_FIELD(table, enter_cb, cb) +#define PCB_DAD_HELP(table, val) PCB_DAD_SET_ATTR_FIELD(table, help_text, val) + +#define PCB_DAD_DEFAULT_PTR(table, val) \ + do {\ + switch(table[table ## _len - 1].type) { \ + case PCB_HATT_BEGIN_COMPOUND: \ + case PCB_HATT_END: \ + { \ + pcb_hid_compound_t *cmp = (pcb_hid_compound_t *)table[table ## _len - 1].enumerations; \ + if ((cmp != NULL) && (cmp->set_val_ptr != NULL)) \ + cmp->set_val_ptr(&table[table ## _len - 1], (void *)(val)); \ + else \ + assert(0); \ + } \ + break; \ + default: \ + PCB_DAD_SET_ATTR_FIELD_PTR(table, default_val, val); \ + } \ + } while(0) + +#define PCB_DAD_DEFAULT_NUM(table, val) \ + do {\ + switch(table[table ## _len - 1].type) { \ + case PCB_HATT_BEGIN_COMPOUND: \ + case PCB_HATT_END: \ + { \ + pcb_hid_compound_t *cmp = (pcb_hid_compound_t *)table[table ## _len - 1].enumerations; \ + if ((cmp != NULL) && (cmp->set_val_num != NULL)) \ + cmp->set_val_num(&table[table ## _len - 1], (long)(val), (double)(val), (pcb_coord_t)(val)); \ + else \ + assert(0); \ + } \ + break; \ + default: \ + PCB_DAD_SET_ATTR_FIELD_NUM(table, default_val, val); \ + } \ + } while(0); + +/* safe way to call gui->attr_dlg_set_value() - resets the unused fields */ +#define PCB_DAD_SET_VALUE(hid_ctx, wid, field, val) \ + do { \ + pcb_hid_attr_val_t __val__; \ + memset(&__val__, 0, sizeof(__val__)); \ + __val__.field = val; \ + pcb_gui->attr_dlg_set_value(hid_ctx, wid, &__val__); \ + } while(0) + +/*** DAD internals (do not use directly) ***/ + +/* Update widget internals after a potential attr pointer change */ +#define PCB_DAD_UPDATE_INTERNAL(table, widx) \ + do { \ + pcb_hid_preview_t *__prv__; \ + pcb_hid_tree_t *__tree__; \ + switch(table[(widx)].type) { \ + case PCB_HATT_PREVIEW: \ + __prv__ = (pcb_hid_preview_t *)table[(widx)].enumerations; \ + __prv__->attrib = &table[(widx)]; \ + break; \ + case PCB_HATT_TREE: \ + __tree__ = (pcb_hid_tree_t *)table[(widx)].enumerations; \ + __tree__->attrib = &table[(widx)]; \ + break; \ + default: break; \ + } \ + } while(0) + +/* Allocate a new item at the end of the attribute table; updates stored + attribute pointers of existing items (e.g. previews, trees) as the base + address of the table may have changed. */ +#define PCB_DAD_ALLOC(table, item_type) \ + do { \ + assert(table ## _append_lock == 0); \ + if (table ## _len >= table ## _alloced) { \ + int __n__; \ + table ## _alloced += 16; \ + table = realloc(table, sizeof(table[0]) * table ## _alloced); \ + for(__n__ = 0; __n__ < table ## _len; __n__++) { \ + PCB_DAD_UPDATE_INTERNAL(table, __n__); \ + } \ + } \ + memset(&table[table ## _len], 0, sizeof(table[0])); \ + table[table ## _len].type = item_type; \ + table ## _len++; \ + } while(0) + +#define PCB_DAD_SET_ATTR_FIELD(table, field, value) \ + table[table ## _len - 1].field = (value) + +#define PCB_DAD_SET_ATTR_FIELD_VAL(table, field, val) \ +do { \ + switch(table[table ## _len - 1].type) { \ + case PCB_HATT_LABEL: \ + assert(0); \ + break; \ + case PCB_HATT_INTEGER: \ + case PCB_HATT_BOOL: \ + case PCB_HATT_ENUM: \ + case PCB_HATT_UNIT: \ + case PCB_HATT_BEGIN_TABBED: \ + table[table ## _len - 1].field.int_value = (int)val; \ + break; \ + case PCB_HATT_COORD: \ + table[table ## _len - 1].field.coord_value = (pcb_coord_t)val; \ + break; \ + case PCB_HATT_REAL: \ + case PCB_HATT_PROGRESS: \ + case PCB_HATT_BEGIN_HPANE: \ + case PCB_HATT_BEGIN_VPANE: \ + table[table ## _len - 1].field.real_value = (double)val; \ + break; \ + case PCB_HATT_STRING: \ + case PCB_HATT_TEXT: \ + case PCB_HATT_PATH: \ + case PCB_HATT_BUTTON: \ + case PCB_HATT_TREE: \ + table[table ## _len - 1].field.str_value = (char *)val; \ + break; \ + case PCB_HATT_COLOR: \ + table[table ## _len - 1].field.clr_value = *(pcb_color_t *)val; \ + break; \ + case PCB_HATT_BEGIN_HBOX: \ + case PCB_HATT_BEGIN_VBOX: \ + case PCB_HATT_BEGIN_TABLE: \ + case PCB_HATT_BEGIN_COMPOUND: \ + case PCB_HATT_END: \ + case PCB_HATT_PREVIEW: \ + case PCB_HATT_PICTURE: \ + case PCB_HATT_PICBUTTON: \ + assert(0); \ + } \ +} while(0) + +#define PCB_DAD_SET_ATTR_FIELD_NUM(table, field, val) \ +do { \ + switch(table[table ## _len - 1].type) { \ + case PCB_HATT_LABEL: \ + assert(0); \ + break; \ + case PCB_HATT_INTEGER: \ + case PCB_HATT_BOOL: \ + case PCB_HATT_ENUM: \ + case PCB_HATT_UNIT: \ + case PCB_HATT_BEGIN_TABBED: \ + table[table ## _len - 1].field.int_value = (int)val; \ + break; \ + case PCB_HATT_COORD: \ + table[table ## _len - 1].field.coord_value = (pcb_coord_t)val; \ + break; \ + case PCB_HATT_REAL: \ + case PCB_HATT_PROGRESS: \ + case PCB_HATT_BEGIN_HPANE: \ + case PCB_HATT_BEGIN_VPANE: \ + table[table ## _len - 1].field.real_value = (double)val; \ + break; \ + case PCB_HATT_STRING: \ + case PCB_HATT_TEXT: \ + case PCB_HATT_PATH: \ + case PCB_HATT_BUTTON: \ + case PCB_HATT_TREE: \ + case PCB_HATT_COLOR: \ + assert(!"please use the _PTR() variant instead of the _NUM() variant"); \ + break; \ + case PCB_HATT_BEGIN_HBOX: \ + case PCB_HATT_BEGIN_VBOX: \ + case PCB_HATT_BEGIN_TABLE: \ + case PCB_HATT_PREVIEW: \ + case PCB_HATT_PICTURE: \ + case PCB_HATT_PICBUTTON: \ + assert(0); \ + case PCB_HATT_BEGIN_COMPOUND: \ + case PCB_HATT_END: \ + { \ + pcb_hid_compound_t *cmp = (pcb_hid_compound_t *)table[table ## _len - 1].enumerations; \ + if ((cmp != NULL) && (cmp->set_field_num != NULL)) \ + cmp->set_field_num(&table[table ## _len - 1], #field, (long)(val), (double)(val), (pcb_coord_t)(val)); \ + else \ + assert(0); \ + } \ + break; \ + } \ +} while(0) + +#define PCB_DAD_SET_ATTR_FIELD_PTR(table, field, val) \ +do { \ + switch(table[table ## _len - 1].type) { \ + case PCB_HATT_LABEL: \ + assert(0); \ + break; \ + case PCB_HATT_INTEGER: \ + case PCB_HATT_BOOL: \ + case PCB_HATT_ENUM: \ + case PCB_HATT_UNIT: \ + case PCB_HATT_BEGIN_TABBED: \ + case PCB_HATT_COORD: \ + case PCB_HATT_REAL: \ + case PCB_HATT_PROGRESS: \ + case PCB_HATT_BEGIN_HPANE: \ + case PCB_HATT_BEGIN_VPANE: \ + assert(!"please use the _PTR() variant instead of the _NUM() variant"); \ + break; \ + case PCB_HATT_STRING: \ + case PCB_HATT_TEXT: \ + case PCB_HATT_PATH: \ + case PCB_HATT_BUTTON: \ + case PCB_HATT_TREE: \ + table[table ## _len - 1].field.str_value = (char *)val; \ + break; \ + case PCB_HATT_COLOR: \ + table[table ## _len - 1].field.clr_value = *((pcb_color_t *)val); \ + break; \ + case PCB_HATT_BEGIN_HBOX: \ + case PCB_HATT_BEGIN_VBOX: \ + case PCB_HATT_BEGIN_TABLE: \ + case PCB_HATT_PREVIEW: \ + case PCB_HATT_PICTURE: \ + case PCB_HATT_PICBUTTON: \ + assert(0); \ + case PCB_HATT_BEGIN_COMPOUND: \ + case PCB_HATT_END: \ + { \ + pcb_hid_compound_t *cmp = (pcb_hid_compound_t *)table[table ## _len - 1].enumerations; \ + if ((cmp != NULL) && (cmp->set_field_ptr != NULL)) \ + cmp->set_field_ptr(&table[table ## _len - 1], #field, (void *)(val)); \ + else \ + assert(0); \ + } \ + break; \ + } \ +} while(0) + +#define PCB_DAD_FREE_FIELD(table, field) \ +do { \ + switch(table[field].type) { \ + case PCB_HATT_LABEL: \ + free((char *)table[field].name); \ + break; \ + case PCB_HATT_INTEGER: \ + case PCB_HATT_BOOL: \ + case PCB_HATT_ENUM: \ + case PCB_HATT_COORD: \ + case PCB_HATT_UNIT: \ + case PCB_HATT_REAL: \ + case PCB_HATT_PROGRESS: \ + case PCB_HATT_STRING: \ + case PCB_HATT_PATH: \ + case PCB_HATT_BUTTON: \ + case PCB_HATT_PICTURE: \ + case PCB_HATT_PICBUTTON: \ + case PCB_HATT_COLOR: \ + break; \ + case PCB_HATT_TREE: \ + pcb_dad_tree_free(&table[field]); \ + break; \ + case PCB_HATT_PREVIEW: \ + { \ + pcb_hid_preview_t *prv = (pcb_hid_preview_t *)table[field].enumerations; \ + if (prv->user_free_cb != NULL) \ + prv->user_free_cb(&table[field], prv->user_ctx, prv->hid_wdata); \ + if (prv->hid_free_cb != NULL) \ + prv->hid_free_cb(&table[field], prv->hid_wdata); \ + free(prv); \ + } \ + break; \ + case PCB_HATT_TEXT: \ + { \ + pcb_hid_text_t *txt = (pcb_hid_text_t *)table[field].enumerations; \ + if (txt->user_free_cb != NULL) \ + txt->user_free_cb(&table[field], txt->user_ctx, txt->hid_wdata); \ + if (txt->hid_free_cb != NULL) \ + txt->hid_free_cb(&table[field], txt->hid_wdata); \ + free(txt); \ + } \ + break; \ + case PCB_HATT_BEGIN_COMPOUND: \ + case PCB_HATT_END: \ + { \ + pcb_hid_compound_t *cmp = (pcb_hid_compound_t *)table[field].enumerations; \ + if ((cmp != NULL) && (cmp->free != NULL)) \ + cmp->free(&table[field]); \ + } \ + case PCB_HATT_BEGIN_HBOX: \ + case PCB_HATT_BEGIN_VBOX: \ + case PCB_HATT_BEGIN_HPANE: \ + case PCB_HATT_BEGIN_VPANE: \ + case PCB_HATT_BEGIN_TABLE: \ + case PCB_HATT_BEGIN_TABBED: \ + break; \ + } \ +} while(0) + +#define PCB_DAD_ALLOC_RESULT(table) \ +do { \ + free(table ## _result); \ + table ## _result = calloc(PCB_DAD_CURRENT(table)+1, sizeof(pcb_hid_attr_val_t)); \ +} while(0) + +/* Internal: free all rows and caches and the tree itself */ +void pcb_dad_tree_free(pcb_hid_attribute_t *attr); + +/* internal: retval override for the auto-close buttons */ +typedef struct { + int dont_free; + int valid; + int value; +} pcb_dad_retovr_t; + +typedef struct { + const char *label; + int retval; +} pcb_hid_dad_buttons_t; + +void pcb_hid_dad_close(void *hid_ctx, pcb_dad_retovr_t *retovr, int retval); +void pcb_hid_dad_close_cb(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr); +int pcb_hid_dad_run(void *hid_ctx, pcb_dad_retovr_t *retovr); +void pcb_hid_iterate(pcb_hid_t *hid); + +/* sub-dialogs e.g. for the file selector dialog */ +struct pcb_hid_dad_subdialog_s { + /* filled in by the sub-dialog's creator */ + PCB_DAD_DECL_NOINIT(dlg) + + /* filled in by the parent dialog's code, the subdialog's code should + call this to query/change properties of the parent dialog. cmd and + argc/argv are all specific to the given dialog. Returns 0 on success, + return payload may be placed in res (if it is not NULL). Parent poke: + close() - cancel/close the dialog */ + int (*parent_poke)(pcb_hid_dad_subdialog_t *sub, const char *cmd, pcb_event_arg_t *res, int argc, pcb_event_arg_t *argv); + + void *parent_ctx; /* used by the parent dialog code */ + void *sub_ctx; /* used by the sub-dialog's creator */ +}; + +#endif Index: tags/2.1.2/src/hid_dad_spin.c =================================================================== --- tags/2.1.2/src/hid_dad_spin.c (nonexistent) +++ tags/2.1.2/src/hid_dad_spin.c (revision 24813) @@ -0,0 +1,450 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2019 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +/* Compound DAD widget for numeric value entry, creating a spinbox */ + +#include "config.h" +#include "hid_attrib.h" +#include "hid_dad.h" +#include "hid_dad_spin.h" +#include "pcb-printf.h" +#include "compat_misc.h" +#include "conf_core.h" + +gdl_list_t pcb_dad_coord_spins; + +const char *pcb_hid_dad_spin_up[] = { +"5 3 2 1", +" c None", +"+ c #000000", +" + ", +" +++ ", +"+++++", +}; + +const char *pcb_hid_dad_spin_down[] = { +"5 3 2 1", +" c None", +"+ c #000000", +"+++++", +" +++ ", +" + ", +}; + +const char *pcb_hid_dad_spin_unit[] = { +"4 4 2 1", +" c None", +"+ c #000000", +"+ +", +"+ +", +"+ +", +" ++ ", +}; + +const char *pcb_hid_dad_spin_warn[] = { +"9 9 3 1", +" c None", +"+ c #000000", +"* c #FF0000", +" ******* ", +"** **", +"* + + *", +"* + + *", +"* + + + *", +"* + + + *", +"* +++++ *", +"** **", +" ******* ", +}; + +static void spin_changed(void *hid_ctx, void *caller_data, pcb_hid_dad_spin_t *spin, pcb_hid_attribute_t *end) +{ + if (end->change_cb != NULL) + end->change_cb(hid_ctx, caller_data, end); +} + +static void spin_warn(void *hid_ctx, pcb_hid_dad_spin_t *spin, pcb_hid_attribute_t *end, const char *msg) +{ + pcb_gui->attr_dlg_widget_hide(hid_ctx, spin->wwarn, (msg == NULL)); + if (pcb_gui->attr_dlg_set_help != NULL) + pcb_gui->attr_dlg_set_help(hid_ctx, spin->wwarn, msg); +} + +static char *gen_str_coord(pcb_hid_dad_spin_t *spin, pcb_coord_t c, char *buf, int buflen) +{ + const pcb_unit_t *unit; + if (spin->unit != NULL) + unit = spin->unit; + else + unit = conf_core.editor.grid_unit; + if (buf != NULL) { + pcb_snprintf(buf, buflen, "%$m*", unit->suffix, c); + return buf; + } + return pcb_strdup_printf("%$m*", unit->suffix, c); +} + +typedef struct { + PCB_DAD_DECL_NOINIT(dlg) + pcb_hid_attribute_t *end; + int wout, wunit, wstick, wglob, valid; + char buf[128]; +} spin_unit_t; + +static void spin_unit_chg_cb(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + pcb_hid_attr_val_t hv; + spin_unit_t *su = (spin_unit_t *)caller_data; + const pcb_unit_t *unit; + int unum = su->dlg[su->wunit].default_val.int_value; + + if ((!su->dlg[su->wglob].default_val.int_value) && (unum >= 0) && (unum < pcb_get_n_units())) + unit = &pcb_units[unum]; + else + unit = conf_core.editor.grid_unit; + + pcb_snprintf(su->buf, sizeof(su->buf), "%$m*", unit->suffix, su->end->default_val.coord_value); + hv.str_value = su->buf; + pcb_gui->attr_dlg_set_value(hid_ctx, su->wout, &hv); + su->valid = 1; +} + +static void spin_unit_dialog(void *spin_hid_ctx, pcb_hid_dad_spin_t *spin, pcb_hid_attribute_t *end, pcb_hid_attribute_t *str) +{ + pcb_hid_dad_buttons_t clbtn[] = {{"Cancel", -1}, {"ok", 0}, {NULL, 0}}; + spin_unit_t ctx; + int dlgres; + + memset(&ctx, 0, sizeof(ctx)); + ctx.end = end; + + PCB_DAD_BEGIN_VBOX(ctx.dlg); + PCB_DAD_COMPFLAG(ctx.dlg, PCB_HATF_EXPFILL); + PCB_DAD_BEGIN_TABLE(ctx.dlg, 2); + PCB_DAD_COMPFLAG(ctx.dlg, PCB_HATF_FRAME); + PCB_DAD_LABEL(ctx.dlg, "Original:"); + PCB_DAD_LABEL(ctx.dlg, str->default_val.str_value); + PCB_DAD_LABEL(ctx.dlg, "With new unit:"); + PCB_DAD_LABEL(ctx.dlg, ""); + ctx.wout = PCB_DAD_CURRENT(ctx.dlg); + PCB_DAD_END(ctx.dlg); + + + PCB_DAD_BEGIN_TABLE(ctx.dlg, 2); + PCB_DAD_LABEL(ctx.dlg, "Preferred unit"); + PCB_DAD_UNIT(ctx.dlg); + ctx.wunit = PCB_DAD_CURRENT(ctx.dlg); + PCB_DAD_HELP(ctx.dlg, "Convert value to this unit and rewrite\nthe text entry field with the converted value."); + PCB_DAD_CHANGE_CB(ctx.dlg, spin_unit_chg_cb); + + PCB_DAD_LABEL(ctx.dlg, "Use the global"); + PCB_DAD_BOOL(ctx.dlg, ""); + PCB_DAD_HELP(ctx.dlg, "Ignore the above unit selection,\nuse the global unit (grid unit) in this spinbox,\nfollow changes of the global unit"); + ctx.wglob = PCB_DAD_CURRENT(ctx.dlg); + PCB_DAD_DEFAULT_NUM(ctx.dlg, (spin->unit == NULL)); + PCB_DAD_CHANGE_CB(ctx.dlg, spin_unit_chg_cb); + + PCB_DAD_LABEL(ctx.dlg, "Stick to unit"); + PCB_DAD_BOOL(ctx.dlg, ""); + PCB_DAD_HELP(ctx.dlg, "Upon any update from software, switch back to\the selected unit even if the user specified\na different unit in the text field."); + ctx.wstick = PCB_DAD_CURRENT(ctx.dlg); + PCB_DAD_DEFAULT_NUM(ctx.dlg, spin->no_unit_chg); + PCB_DAD_CHANGE_CB(ctx.dlg, spin_unit_chg_cb); + PCB_DAD_END(ctx.dlg); + + PCB_DAD_BEGIN_HBOX(ctx.dlg); + PCB_DAD_COMPFLAG(ctx.dlg, PCB_HATF_EXPFILL); + PCB_DAD_BEGIN_HBOX(ctx.dlg); + PCB_DAD_COMPFLAG(ctx.dlg, PCB_HATF_EXPFILL); + PCB_DAD_END(ctx.dlg); + PCB_DAD_BUTTON_CLOSES(ctx.dlg, clbtn); + PCB_DAD_END(ctx.dlg); + PCB_DAD_END(ctx.dlg); + + PCB_DAD_AUTORUN("unit", ctx.dlg, "spinbox coord unit change", &ctx, dlgres); + if ((dlgres == 0) && (ctx.valid)) { + pcb_hid_attr_val_t hv; + int unum = ctx.dlg[ctx.wunit].default_val.int_value; + + if ((!ctx.dlg[ctx.wglob].default_val.int_value) && (unum >= 0) && (unum < pcb_get_n_units())) + spin->unit = &pcb_units[unum]; + else + spin->unit = NULL; + + spin->no_unit_chg = ctx.dlg[ctx.wstick].default_val.int_value; + hv.str_value = pcb_strdup(ctx.buf); + pcb_gui->attr_dlg_set_value(spin_hid_ctx, spin->wstr, &hv); + } + + PCB_DAD_FREE(ctx.dlg); +} + +static double get_step(pcb_hid_dad_spin_t *spin, pcb_hid_attribute_t *end, pcb_hid_attribute_t *str) +{ + double v, step; + const pcb_unit_t *unit; + + if (spin->step > 0) + return spin->step; + + switch(spin->type) { + case PCB_DAD_SPIN_INT: + step = pow(10, floor(log10(fabs(end->default_val.int_value)) - 1.0)); + if (step < 1) + step = 1; + break; + case PCB_DAD_SPIN_DOUBLE: + step = pow(10, floor(log10(fabs(end->default_val.real_value)) - 1.0)); + break; + case PCB_DAD_SPIN_COORD: + if (spin->unit == NULL) { + pcb_bool succ = pcb_get_value_unit(str->default_val.str_value, NULL, 0, &v, &unit); + if (!succ) { + v = end->default_val.coord_value; + unit = conf_core.editor.grid_unit; + } + } + else + unit = spin->unit; + v = pcb_coord_to_unit(unit, end->default_val.coord_value); + step = pow(10, floor(log10(fabs(v)) - 1.0)); + if (step <= 0.0) + step = 1; + step = pcb_unit_to_coord(unit, step); + break; + } + return step; +} + +#define SPIN_CLAMP(dst) \ + do { \ + if ((spin->vmin_valid) && (dst < spin->vmin)) { \ + dst = spin->vmin; \ + warn = "Value already at the minimum"; \ + } \ + if ((spin->vmax_valid) && (dst > spin->vmax)) { \ + dst = spin->vmax; \ + warn = "Value already at the maximum"; \ + } \ + } while(0) + +static void do_step(void *hid_ctx, pcb_hid_dad_spin_t *spin, pcb_hid_attribute_t *str, pcb_hid_attribute_t *end, double step) +{ + pcb_hid_attr_val_t hv; + const char *warn = NULL; + char buf[128]; + + switch(spin->type) { + case PCB_DAD_SPIN_INT: + end->default_val.int_value += step; + SPIN_CLAMP(end->default_val.int_value); + sprintf(buf, "%d", end->default_val.int_value); + break; + case PCB_DAD_SPIN_DOUBLE: + end->default_val.real_value += step; + SPIN_CLAMP(end->default_val.real_value); + sprintf(buf, "%f", end->default_val.real_value); + break; + case PCB_DAD_SPIN_COORD: + end->default_val.coord_value += step; + SPIN_CLAMP(end->default_val.coord_value); + gen_str_coord(spin, end->default_val.coord_value, buf, sizeof(buf)); + break; + } + + spin_warn(hid_ctx, spin, end, warn); + hv.str_value = pcb_strdup(buf); + spin->set_writeback_lock++; + pcb_gui->attr_dlg_set_value(hid_ctx, spin->wstr, &hv); + spin->set_writeback_lock--; +} + +void pcb_dad_spin_up_cb(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + pcb_hid_dad_spin_t *spin = (pcb_hid_dad_spin_t *)attr->user_data; + pcb_hid_attribute_t *str = attr - spin->wup + spin->wstr; + pcb_hid_attribute_t *end = attr - spin->wup + spin->cmp.wend; + + do_step(hid_ctx, spin, str, end, get_step(spin, end, str)); + spin_changed(hid_ctx, caller_data, spin, end); +} + +void pcb_dad_spin_down_cb(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + pcb_hid_dad_spin_t *spin = (pcb_hid_dad_spin_t *)attr->user_data; + pcb_hid_attribute_t *str = attr - spin->wdown + spin->wstr; + pcb_hid_attribute_t *end = attr - spin->wdown + spin->cmp.wend; + + do_step(hid_ctx, spin, str, end, -get_step(spin, end, str)); + spin_changed(hid_ctx, caller_data, spin, end); +} + +void pcb_dad_spin_txt_cb(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + pcb_hid_dad_spin_t *spin = (pcb_hid_dad_spin_t *)attr->user_data; + pcb_hid_attribute_t *str = attr; + pcb_hid_attribute_t *end = attr - spin->wstr + spin->cmp.wend; + char *ends, *warn = NULL; + long l; + double d; + pcb_bool succ, absolute; + const pcb_unit_t *unit; + + if (spin->set_writeback_lock) + return; + + switch(spin->type) { + case PCB_DAD_SPIN_INT: + l = strtol(str->default_val.str_value, &ends, 10); + SPIN_CLAMP(l); + if (*ends != '\0') + warn = "Invalid integer - result is truncated"; + end->default_val.int_value = l; + break; + case PCB_DAD_SPIN_DOUBLE: + d = strtod(str->default_val.str_value, &ends); + SPIN_CLAMP(d); + if (*ends != '\0') + warn = "Invalid numeric - result is truncated"; + end->default_val.real_value = d; + break; + case PCB_DAD_SPIN_COORD: + succ = pcb_get_value_unit(str->default_val.str_value, &absolute, 0, &d, &unit); + if (succ) + SPIN_CLAMP(d); + else + warn = "Invalid coord value or unit - result is truncated"; + if (!spin->no_unit_chg) + spin->unit = unit; + end->default_val.coord_value = d; + break; + default: pcb_trace("INTERNAL ERROR: spin_set_num\n"); + } + + spin_warn(hid_ctx, spin, end, warn); + spin_changed(hid_ctx, caller_data, spin, end); +} + +void pcb_dad_spin_unit_cb(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + pcb_hid_dad_spin_t *spin = (pcb_hid_dad_spin_t *)attr->user_data; + pcb_hid_attribute_t *str = attr - spin->wunit + spin->wstr; + pcb_hid_attribute_t *end = attr - spin->wunit + spin->cmp.wend; + spin_unit_dialog(hid_ctx, spin, end, str); +} + +void pcb_dad_spin_set_num(pcb_hid_attribute_t *attr, long l, double d, pcb_coord_t c) +{ + pcb_hid_dad_spin_t *spin = (pcb_hid_dad_spin_t *)attr->enumerations; + pcb_hid_attribute_t *str = attr - spin->cmp.wend + spin->wstr; + + switch(spin->type) { + case PCB_DAD_SPIN_INT: + attr->default_val.int_value = l; + free((char *)str->default_val.str_value); + str->default_val.str_value = pcb_strdup_printf("%ld", l); + break; + case PCB_DAD_SPIN_DOUBLE: + attr->default_val.real_value = d; + free((char *)str->default_val.str_value); + str->default_val.str_value = pcb_strdup_printf("%f", d); + break; + case PCB_DAD_SPIN_COORD: + attr->default_val.coord_value = c; + spin->unit = NULL; + free((char *)str->default_val.str_value); + str->default_val.str_value = gen_str_coord(spin, c, NULL, 0); + break; + default: pcb_trace("INTERNAL ERROR: spin_set_num\n"); + } +} + +void pcb_dad_spin_free(pcb_hid_attribute_t *attr) +{ + if (attr->type == PCB_HATT_END) { + pcb_hid_dad_spin_t *spin = (pcb_hid_dad_spin_t *)attr->enumerations; + if (spin->type == PCB_DAD_SPIN_COORD) + gdl_remove(&pcb_dad_coord_spins, spin, link); + free(spin); + } +} + +int pcb_dad_spin_widget_state(pcb_hid_attribute_t *end, void *hid_ctx, int idx, pcb_bool enabled) +{ + pcb_hid_dad_spin_t *spin = (pcb_hid_dad_spin_t *)end->enumerations; + return pcb_gui->attr_dlg_widget_state(hid_ctx, spin->wall, enabled); +} + +int pcb_dad_spin_widget_hide(pcb_hid_attribute_t *end, void *hid_ctx, int idx, pcb_bool hide) +{ + pcb_hid_dad_spin_t *spin = (pcb_hid_dad_spin_t *)end->enumerations; + return pcb_gui->attr_dlg_widget_hide(hid_ctx, spin->wall, hide); +} + +int pcb_dad_spin_set_value(pcb_hid_attribute_t *end, void *hid_ctx, int idx, const pcb_hid_attr_val_t *val) +{ + pcb_hid_dad_spin_t *spin = (pcb_hid_dad_spin_t *)end->enumerations; + pcb_hid_attribute_t *str = end - spin->cmp.wend + spin->wstr; + + /* do not modify the text field if the value is the same */ + switch(spin->type) { + case PCB_DAD_SPIN_INT: + if (val->int_value == end->default_val.int_value) + return 0; + end->default_val.int_value = val->int_value; + break; + case PCB_DAD_SPIN_DOUBLE: + if (val->real_value == end->default_val.real_value) + return 0; + end->default_val.real_value = val->real_value; + break; + case PCB_DAD_SPIN_COORD: + if (val->coord_value == end->default_val.coord_value) + return 0; + end->default_val.coord_value = val->coord_value; + break; + } + do_step(hid_ctx, spin, str, end, 0); /* cheap conversion + error checks */ + return 0; +} + +void pcb_dad_spin_update_global_coords(void) +{ + pcb_hid_dad_spin_t *spin; + + + for(spin = gdl_first(&pcb_dad_coord_spins); spin != NULL; spin = gdl_next(&pcb_dad_coord_spins, spin)) { + pcb_hid_attribute_t *dlg; + void *hid_ctx; + + if ((spin->unit != NULL) || (spin->attrs == NULL) || (*spin->attrs == NULL) || (spin->hid_ctx == NULL) || (*spin->hid_ctx == NULL)) + continue; + + dlg = *spin->attrs; + hid_ctx = *spin->hid_ctx; + do_step(hid_ctx, spin, &dlg[spin->wstr], &dlg[spin->cmp.wend], 0); /* cheap conversion*/ + } +} Index: tags/2.1.2/src/hid_dad_spin.h =================================================================== --- tags/2.1.2/src/hid_dad_spin.h (nonexistent) +++ tags/2.1.2/src/hid_dad_spin.h (revision 24813) @@ -0,0 +1,129 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2019 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +/* Compound DAD widget for numeric value entry, creating a spinbox */ + +#include + +typedef struct { + pcb_hid_compound_t cmp; + double step; /* how much an up/down step modifies; 0 means automatic */ + double vmin, vmax; + unsigned vmin_valid:1; + unsigned vmax_valid:1; + unsigned no_unit_chg:1; + int wall, wstr, wup, wdown, wunit, wwarn; + const pcb_unit_t *unit; /* for PCB_DAD_SPIN_COORD only: current unit */ + pcb_hid_attribute_t **attrs; + void **hid_ctx; + int set_writeback_lock; + enum { + PCB_DAD_SPIN_INT, + PCB_DAD_SPIN_DOUBLE, + PCB_DAD_SPIN_COORD + } type; + gdl_elem_t link; +} pcb_hid_dad_spin_t; + +#define PCB_DAD_SPIN_INT(table) PCB_DAD_SPIN_ANY(table, PCB_DAD_SPIN_INT, 0) +#define PCB_DAD_SPIN_DOUBLE(table) PCB_DAD_SPIN_ANY(table, PCB_DAD_SPIN_DOUBLE, 0) +#define PCB_DAD_SPIN_COORD(table) PCB_DAD_SPIN_ANY(table, PCB_DAD_SPIN_COORD, 1) + +/*** implementation ***/ + +#define PCB_DAD_SPIN_ANY(table, typ, has_unit) \ +do { \ + pcb_hid_dad_spin_t *spin = calloc(sizeof(pcb_hid_dad_spin_t), 1); \ + PCB_DAD_BEGIN(table, PCB_HATT_BEGIN_COMPOUND); \ + spin->cmp.wbegin = PCB_DAD_CURRENT(table); \ + PCB_DAD_SET_ATTR_FIELD(table, enumerations, (const char **)spin); \ + PCB_DAD_BEGIN_HBOX(table); \ + spin->wall = PCB_DAD_CURRENT(table); \ + PCB_DAD_COMPFLAG(table, PCB_HATF_TIGHT); \ + PCB_DAD_STRING(table); \ + PCB_DAD_CHANGE_CB(table, pcb_dad_spin_txt_cb); \ + PCB_DAD_SET_ATTR_FIELD(table, user_data, (const char **)spin); \ + spin->wstr = PCB_DAD_CURRENT(table); \ + PCB_DAD_BEGIN_VBOX(table); \ + PCB_DAD_COMPFLAG(table, PCB_HATF_TIGHT); \ + PCB_DAD_PICBUTTON(table, pcb_hid_dad_spin_up); \ + PCB_DAD_CHANGE_CB(table, pcb_dad_spin_up_cb); \ + PCB_DAD_SET_ATTR_FIELD(table, user_data, (const char **)spin); \ + spin->wup = PCB_DAD_CURRENT(table); \ + PCB_DAD_PICBUTTON(table, pcb_hid_dad_spin_down); \ + PCB_DAD_CHANGE_CB(table, pcb_dad_spin_down_cb); \ + PCB_DAD_SET_ATTR_FIELD(table, user_data, (const char **)spin); \ + spin->wdown = PCB_DAD_CURRENT(table); \ + PCB_DAD_END(table); \ + PCB_DAD_BEGIN_VBOX(table); \ + PCB_DAD_COMPFLAG(table, PCB_HATF_TIGHT); \ + if (has_unit) { \ + PCB_DAD_PICBUTTON(table, pcb_hid_dad_spin_unit); \ + PCB_DAD_CHANGE_CB(table, pcb_dad_spin_unit_cb); \ + PCB_DAD_SET_ATTR_FIELD(table, user_data, (const char **)spin); \ + spin->wunit = PCB_DAD_CURRENT(table); \ + } \ + PCB_DAD_PICTURE(table, pcb_hid_dad_spin_warn); \ + PCB_DAD_COMPFLAG(table, PCB_HATF_HIDE); \ + PCB_DAD_SET_ATTR_FIELD(table, user_data, (const char **)spin); \ + spin->wwarn = PCB_DAD_CURRENT(table); \ + PCB_DAD_END(table); \ + PCB_DAD_END(table); \ + PCB_DAD_END(table); \ + PCB_DAD_SET_ATTR_FIELD(table, enumerations, (const char **)spin); \ + spin->cmp.wend = PCB_DAD_CURRENT(table); \ + \ + spin->cmp.free = pcb_dad_spin_free; \ + spin->cmp.set_val_num = pcb_dad_spin_set_num; \ + spin->cmp.widget_state = pcb_dad_spin_widget_state; \ + spin->cmp.widget_hide = pcb_dad_spin_widget_hide; \ + spin->cmp.set_value = pcb_dad_spin_set_value; \ + spin->type = typ; \ + spin->attrs = &table; \ + spin->hid_ctx = &table ## _hid_ctx; \ + \ + if (typ == PCB_DAD_SPIN_COORD) \ + gdl_append(&pcb_dad_coord_spins, spin, link); \ +} while(0) + +extern const char *pcb_hid_dad_spin_up[]; +extern const char *pcb_hid_dad_spin_down[]; +extern const char *pcb_hid_dad_spin_unit[]; +extern const char *pcb_hid_dad_spin_unit[]; +extern const char *pcb_hid_dad_spin_warn[]; + +void pcb_dad_spin_up_cb(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr); +void pcb_dad_spin_down_cb(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr); +void pcb_dad_spin_txt_cb(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr); +void pcb_dad_spin_unit_cb(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr); + +void pcb_dad_spin_free(pcb_hid_attribute_t *attrib); +void pcb_dad_spin_set_num(pcb_hid_attribute_t *attr, long l, double d, pcb_coord_t c); +int pcb_dad_spin_widget_state(pcb_hid_attribute_t *end, void *hid_ctx, int idx, pcb_bool enabled); +int pcb_dad_spin_widget_hide(pcb_hid_attribute_t *end, void *hid_ctx, int idx, pcb_bool hide); +int pcb_dad_spin_set_value(pcb_hid_attribute_t *end, void *hid_ctx, int idx, const pcb_hid_attr_val_t *val); + +extern gdl_list_t pcb_dad_coord_spins; /* list of all active coord spinboxes */ Index: tags/2.1.2/src/hid_dad_tree.c =================================================================== --- tags/2.1.2/src/hid_dad_tree.c (nonexistent) +++ tags/2.1.2/src/hid_dad_tree.c (revision 24813) @@ -0,0 +1,151 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2018,2019 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +/* Non-inline utility functions for the DAD tree widget */ + +#include "config.h" +#include "hid_dad_tree.h" + +/* recursively free a row list subtree */ +static void pcb_dad_tree_free_rowlist(pcb_hid_attribute_t *attr, gdl_list_t *list) +{ + pcb_hid_tree_t *tree = (pcb_hid_tree_t *)attr->enumerations; + pcb_hid_row_t *r; + + while((r = gdl_first(list)) != NULL) { + gdl_remove(list, r, link); + pcb_dad_tree_free_rowlist(attr, &r->children); + + if (tree->hid_free_cb != NULL) + tree->hid_free_cb(tree->attrib, tree->hid_wdata, r); + + if (tree->user_free_cb != NULL) + tree->user_free_cb(tree->attrib, tree->hid_wdata, r); + + if (attr->pcb_hatt_flags & PCB_HATF_TREE_COL) + free(r->path); + + free(r); + } +} + +/* Internal: free all rows and caches and the tree itself */ +void pcb_dad_tree_free(pcb_hid_attribute_t *attr) +{ + pcb_hid_tree_t *tree = (pcb_hid_tree_t *)attr->enumerations; + htsp_uninit(&tree->paths); + pcb_dad_tree_free_rowlist(attr, &tree->rows); + free(tree); +} + +void pcb_dad_tree_hide_all(pcb_hid_tree_t *tree, gdl_list_t *rowlist, int val) +{ + pcb_hid_row_t *r; + for(r = gdl_first(rowlist); r != NULL; r = gdl_next(rowlist, r)) { + r->hide = val; + pcb_dad_tree_hide_all(tree, &r->children, val); + } +} + +void pcb_dad_tree_unhide_filter(pcb_hid_tree_t *tree, gdl_list_t *rowlist, int col, const char *text) +{ + pcb_hid_row_t *r, *pr; + + for(r = gdl_first(rowlist); r != NULL; r = gdl_next(rowlist, r)) { + if (strstr(r->cell[col], text) != NULL) { + pcb_dad_tree_hide_all(tree, &r->children, 0); /* if this is a node with children, show all children */ + for(pr = r; pr != NULL; pr = pcb_dad_tree_parent_row(tree, pr)) /* also show all parents so it is visible */ + pr->hide = 0; + } + pcb_dad_tree_unhide_filter(tree, &r->children, col, text); + } +} + + +/*** these shouldn't be in pcb_dad_tree.c, but they are so short that a new + file would be overkill ***/ +void pcb_hid_dad_close(void *hid_ctx, pcb_dad_retovr_t *retovr, int retval) +{ + retovr->valid = 1; + retovr->value = retval; + pcb_gui->attr_dlg_free(hid_ctx); +} + +void pcb_hid_dad_close_cb(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + pcb_dad_retovr_t **retovr = (pcb_dad_retovr_t **)attr->enumerations; + pcb_hid_dad_close(hid_ctx, *retovr, attr->default_val.int_value); +} + +int pcb_hid_dad_run(void *hid_ctx, pcb_dad_retovr_t *retovr) +{ + int ret; + + retovr->valid = 0; + retovr->dont_free++; + ret = pcb_gui->attr_dlg_run(hid_ctx); + if (retovr->valid) + ret = retovr->value; + retovr->dont_free--; + return ret; +} + +pcb_hid_row_t *pcb_dad_tree_mkdirp(pcb_hid_tree_t *tree, char *path, char **cells) +{ + char *cell[2] = {NULL}; + pcb_hid_row_t *parent; + char *last, *old; + + parent = htsp_get(&tree->paths, path); + if (parent != NULL) + return parent; + + last = strrchr(path, '/'); + + if (last == NULL) { + /* root dir */ + parent = htsp_get(&tree->paths, path); + if (parent != NULL) + return parent; + cell[0] = pcb_strdup(path); + return pcb_dad_tree_append(tree->attrib, NULL, cell); + } + +/* non-root-dir: get or create parent */ + *last = '\0'; + last++; + parent = pcb_dad_tree_mkdirp(tree, path, NULL); + + if (cells == NULL) { + cell[0] = pcb_strdup(last); + return pcb_dad_tree_append_under(tree->attrib, parent, cell); + } + + old = cell[0]; + cells[0] = pcb_strdup(last); + free(old); + return pcb_dad_tree_append_under(tree->attrib, parent, cells); +} Index: tags/2.1.2/src/hid_dad_tree.h =================================================================== --- tags/2.1.2/src/hid_dad_tree.h (nonexistent) +++ tags/2.1.2/src/hid_dad_tree.h (revision 24813) @@ -0,0 +1,322 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2018 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +/* Inline helpers called by the DAD macros for the tree-table widget */ + +#ifndef PCB_HID_DAD_TREE_H +#define PCB_HID_DAD_TREE_H + +#include "hid_attrib.h" +#include "hid_dad.h" +#include +#include +#include +#include + +/* recursively sets the hide flag on all nodes to val */ +void pcb_dad_tree_hide_all(pcb_hid_tree_t *tree, gdl_list_t *rowlist, int val); + +/* recursively unhide items that match text in the given column; parents are unhidden too */ +void pcb_dad_tree_unhide_filter(pcb_hid_tree_t *tree, gdl_list_t *rowlist, int col, const char *text); + +/* Recursively create the node and all parents in a tree. If cells is not NULL, + the target path row is created with these cells, else only the first col + is filled in. Temporarily modifies path (but changes it back) */ +pcb_hid_row_t *pcb_dad_tree_mkdirp(pcb_hid_tree_t *tree, char *path, char **cells); + +/* Internal: Allocate a new row and load the cells (but do not insert it anywhere) */ +PCB_INLINE pcb_hid_row_t *pcb_dad_tree_new_row(char **cols) +{ + int num_cols; + pcb_hid_row_t *nrow; + char **s, **o; + for(s = cols, num_cols = 0; *s != NULL; s++, num_cols++); + + nrow = calloc(sizeof(pcb_hid_row_t) + sizeof(char *) * num_cols, 1); + nrow->cols = num_cols; + for(s = cols, o = nrow->cell; *s != NULL; s++, o++) + *o = *s; + + return nrow; +} + +PCB_INLINE void pcb_dad_tree_free_row(pcb_hid_tree_t *tree, pcb_hid_row_t *row) +{ + int do_free_path = 0; + /* do this before the user callback just in case row->path == row->cell[0] + and the user callback free's it */ + if (row->path != NULL) { + htsp_pop(&tree->paths, row->path); + do_free_path = (row->path != row->cell[0]); /* user_free_cb may set row->cell[0] to NULL */ + } + + if (tree->user_free_cb != NULL) + tree->user_free_cb(tree->attrib, tree->hid_wdata, row); + + if (do_free_path) + free(row->path); + + free(row); +} + + +PCB_INLINE pcb_hid_row_t *pcb_dad_tree_parent_row(pcb_hid_tree_t *tree, pcb_hid_row_t *row) +{ + char *ptr = (char *)row->link.parent; + if ((ptr == NULL) || ((gdl_list_t *)ptr == &tree->rows)) + return NULL; + + ptr -= offsetof(gdl_elem_t, parent); + ptr -= offsetof(pcb_hid_row_t, children); + return (pcb_hid_row_t *)ptr; +} + +PCB_INLINE pcb_hid_row_t *pcb_dad_tree_prev_row(pcb_hid_tree_t *tree, pcb_hid_row_t *row) +{ + return row->link.prev; +} + +PCB_INLINE pcb_hid_row_t *pcb_dad_tree_next_row(pcb_hid_tree_t *tree, pcb_hid_row_t *row) +{ + return row->link.next; +} + +/* recursively build a full path of a tree node in path */ +PCB_INLINE void pcb_dad_tree_build_path(pcb_hid_tree_t *tree, gds_t *path, pcb_hid_row_t *row) +{ + pcb_hid_row_t *par = pcb_dad_tree_parent_row(tree, row); + if (par != NULL) + pcb_dad_tree_build_path(tree, path, par); + if (path->used > 0) + gds_append(path, '/'); + gds_append_str(path, row->cell[0]); +} + +/* calculate path of a row and insert it in the tree hash */ +PCB_INLINE void pcb_dad_tree_set_hash(pcb_hid_attribute_t *attr, pcb_hid_row_t *row) +{ + pcb_hid_tree_t *tree = (pcb_hid_tree_t *)attr->enumerations; + if (attr->pcb_hatt_flags & PCB_HATF_TREE_COL) { + gds_t path; + gds_init(&path); + pcb_dad_tree_build_path(tree, &path, row); + row->path = path.array; + } + else + row->path = row->cell[0]; + htsp_set(&tree->paths, row->path, row); +} + +/* allocate a new row and append it after aft; if aft is NULL, the new row is appended at the + end of the list of entries in the root (== at the bottom of the list) */ +PCB_INLINE pcb_hid_row_t *pcb_dad_tree_append(pcb_hid_attribute_t *attr, pcb_hid_row_t *aft, char **cols) +{ + pcb_hid_tree_t *tree = (pcb_hid_tree_t *)attr->enumerations; + pcb_hid_row_t *nrow = pcb_dad_tree_new_row(cols); + gdl_list_t *par; /* the list that is the common parent of aft and the new row */ + + assert(attr == tree->attrib); + + if (aft == NULL) { + par = &tree->rows; + aft = gdl_last(par); + } + else + par = aft->link.parent; + + gdl_insert_after(par, aft, nrow, link); + pcb_dad_tree_set_hash(attr, nrow); + if (tree->hid_insert_cb != NULL) + tree->hid_insert_cb(tree->attrib, tree->hid_wdata, nrow); + return nrow; +} + +/* allocate a new row and inert it before bfr; if bfr is NULL, the new row is inserted at the + beginning of the list of entries in the root (== at the top of the list) */ +PCB_INLINE pcb_hid_row_t *pcb_dad_tree_insert(pcb_hid_attribute_t *attr, pcb_hid_row_t *bfr, char **cols) +{ + pcb_hid_tree_t *tree = (pcb_hid_tree_t *)attr->enumerations; + pcb_hid_row_t *nrow = pcb_dad_tree_new_row(cols); + gdl_list_t *par; /* the list that is the common parent of bfr and the new row */ + + assert(attr == tree->attrib); + + if (bfr == NULL) { + par = &tree->rows; + bfr = gdl_first(par); + } + else + par = bfr->link.parent; + + gdl_insert_before(par, bfr, nrow, link); + pcb_dad_tree_set_hash(attr, nrow); + if (tree->hid_insert_cb != NULL) + tree->hid_insert_cb(tree->attrib, tree->hid_wdata, nrow); + return nrow; +} + +/* allocate a new row and append it under prn; if aft is NULL, the new row is appended at the + end of the list of entries in the root (== at the bottom of the list) */ +PCB_INLINE pcb_hid_row_t *pcb_dad_tree_append_under(pcb_hid_attribute_t *attr, pcb_hid_row_t *prn, char **cols) +{ + pcb_hid_tree_t *tree = (pcb_hid_tree_t *)attr->enumerations; + pcb_hid_row_t *nrow = pcb_dad_tree_new_row(cols); + gdl_list_t *par; /* the list that is the common parent of aft and the new row */ + + assert(attr == tree->attrib); + + if (prn == NULL) + par = &tree->rows; + else + par = &prn->children; + + gdl_append(par, nrow, link); + pcb_dad_tree_set_hash(attr, nrow); + if (tree->hid_insert_cb != NULL) + tree->hid_insert_cb(tree->attrib, tree->hid_wdata, nrow); + return nrow; +} + +PCB_INLINE int pcb_dad_tree_remove(pcb_hid_attribute_t *attr, pcb_hid_row_t *row) +{ + pcb_hid_tree_t *tree = (pcb_hid_tree_t *)attr->enumerations; + pcb_hid_row_t *r, *rn, *par = pcb_dad_tree_parent_row(tree, row); + gdl_list_t *lst = (par == NULL) ? &tree->rows : &par->children; + int res = 0; + + assert(attr == tree->attrib); + + /* recursively remove all children */ + for(r = gdl_first(&row->children); r != NULL; r = rn) { + rn = gdl_next(&row->children, r); + res |= pcb_dad_tree_remove(attr, r); + } + + /* remove from gui */ + if (tree->hid_remove_cb != NULL) + tree->hid_remove_cb(tree->attrib, tree->hid_wdata, row); + else + res = -1; + + /* remove from dad */ + gdl_remove(lst, row, link); + pcb_dad_tree_free_row(tree, row); + return res; +} + +PCB_INLINE void pcb_dad_tree_clear(pcb_hid_tree_t *tree) +{ + pcb_hid_row_t *r; + for(r = gdl_first(&tree->rows); r != NULL; r = gdl_first(&tree->rows)) + pcb_dad_tree_remove(tree->attrib, r); +} + +PCB_INLINE pcb_hid_row_t *pcb_dad_tree_get_selected(pcb_hid_attribute_t *attr) +{ + pcb_hid_tree_t *tree = (pcb_hid_tree_t *)attr->enumerations; + + assert(attr == tree->attrib); + + if (tree->hid_get_selected_cb == NULL) + return NULL; + + return tree->hid_get_selected_cb(tree->attrib, tree->hid_wdata); +} + +PCB_INLINE void pcb_dad_tree_update_hide(pcb_hid_attribute_t *attr) +{ + pcb_hid_tree_t *tree = (pcb_hid_tree_t *)attr->enumerations; + + assert(attr == tree->attrib); + + if (tree->hid_update_hide_cb != NULL) + tree->hid_update_hide_cb(tree->attrib, tree->hid_wdata); +} + +PCB_INLINE int pcb_dad_tree_modify_cell(pcb_hid_attribute_t *attr, pcb_hid_row_t *row, int col, char *new_val) +{ + pcb_hid_tree_t *tree = (pcb_hid_tree_t *)attr->enumerations; + + assert(attr == tree->attrib); + + if ((col < 0) || (col >= row->cols)) + return 0; + + if (col == 0) { + htsp_pop(&tree->paths, row->path); + free(row->path); + row->path = NULL; + } + + row->cell[col] = new_val; + + if (col == 0) + pcb_dad_tree_set_hash(attr, row); + + if (tree->hid_modify_cb != NULL) + tree->hid_modify_cb(tree->attrib, tree->hid_wdata, row, col); + + return 0; +} + +PCB_INLINE void pcb_dad_tree_jumpto(pcb_hid_attribute_t *attr, pcb_hid_row_t *row) +{ + pcb_hid_tree_t *tree = (pcb_hid_tree_t *)attr->enumerations; + + assert(attr == tree->attrib); + + if (tree->hid_jumpto_cb != NULL) + tree->hid_jumpto_cb(tree->attrib, tree->hid_wdata, row); +} + +PCB_INLINE void pcb_dad_tree_expcoll_(pcb_hid_tree_t *tree, pcb_hid_row_t *row, pcb_bool expanded, pcb_bool recursive) +{ + if (recursive) { + pcb_hid_row_t *r; + for(r = gdl_first(&row->children); r != NULL; r = gdl_next(&row->children, r)) + pcb_dad_tree_expcoll_(tree, r, expanded, recursive); + } + if (gdl_first(&row->children) != NULL) + tree->hid_expcoll_cb(tree->attrib, tree->hid_wdata, row, expanded); +} + +PCB_INLINE void pcb_dad_tree_expcoll(pcb_hid_attribute_t *attr, pcb_hid_row_t *row, pcb_bool expanded, pcb_bool recursive) +{ + pcb_hid_tree_t *tree = (pcb_hid_tree_t *)attr->enumerations; + + assert(attr == tree->attrib); + + if (tree->hid_expcoll_cb != NULL) { + if (row == NULL) { + for(row = gdl_first(&tree->rows); row != NULL; row = gdl_next(&tree->rows, row)) + pcb_dad_tree_expcoll_(tree, row, expanded, recursive); + } + else + pcb_dad_tree_expcoll_(tree, row, expanded, recursive); + } +} + +#endif Index: tags/2.1.2/src/hid_dlg.c =================================================================== --- tags/2.1.2/src/hid_dlg.c (nonexistent) +++ tags/2.1.2/src/hid_dlg.c (revision 24813) @@ -0,0 +1,294 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * Copyright (C) 2004 harry eaton + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +#include "config.h" + +#include "actions.h" +#include "event.h" +#include "hid.h" +#include "hid_dad.h" +#include "hid_nogui.h" + +static int hid_dlg_gui_inited = 0; + +/* Action and wrapper implementation for dialogs. If GUI is available, the + gui_ prefixed action is executed, else the cli_ prefixed one is used. If + nothing is available, the effect is equivalent to cancel. */ + +/* Call the gui_ or the cli_ action; act_name must be all lowercase! */ +static fgw_error_t call_dialog(const char *act_name, fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + char tmp[128]; + + strcpy(tmp, "gui_"); + strncpy(tmp+4, act_name, sizeof(tmp)-5); + if (PCB_HAVE_GUI_ATTR_DLG && (fgw_func_lookup(&pcb_fgw, tmp) != NULL)) + return pcb_actionv_bin(tmp, res, argc, argv); + + tmp[0] = 'c'; tmp[1] = 'l'; + if (fgw_func_lookup(&pcb_fgw, tmp) != NULL) + return pcb_actionv_bin(tmp, res, argc, argv); + + return FGW_ERR_NOT_FOUND; +} + +static const char pcb_acts_PromptFor[] = "PromptFor([message[,default[,title]]])"; +static const char pcb_acth_PromptFor[] = "Prompt for a string. Returns the string (or NULL on cancel)"; +/* DOC: promptfor.html */ +static fgw_error_t pcb_act_PromptFor(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + return call_dialog("promptfor", res, argc, argv); +} + +char *pcb_hid_prompt_for(const char *msg, const char *default_string, const char *title) +{ + fgw_arg_t res, argv[4]; + + argv[1].type = FGW_STR; argv[1].val.cstr = msg; + argv[2].type = FGW_STR; argv[2].val.cstr = default_string; + argv[3].type = FGW_STR; argv[3].val.cstr = title; + + if (pcb_actionv_bin("PromptFor", &res, 4, argv) != 0) + return NULL; + + if (res.type == (FGW_STR | FGW_DYN)) + return res.val.str; + + fgw_arg_free(&pcb_fgw, &res); + return NULL; +} + +static const char pcb_acts_MessageBox[] = "MessageBox(icon, title, label, button_txt, button_retval, ...)"; +static const char pcb_acth_MessageBox[] = "Open a modal message dialog box with title and label. If icon string is not empty, display the named icon on the left. Present one or more window close buttons with different text and return value."; +/* DOC: messagebox.html */ +static fgw_error_t pcb_act_MessageBox(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + return call_dialog("messagebox", res, argc, argv); +} + +int pcb_hid_message_box(const char *icon, const char *title, const char *label, ...) +{ + fgw_arg_t res, argv[128]; + int argc; + va_list ap; + + argv[1].type = FGW_STR; argv[1].val.cstr = icon; + argv[2].type = FGW_STR; argv[2].val.cstr = title; + argv[3].type = FGW_STR; argv[3].val.cstr = label; + argc = 4; + + va_start(ap, label); + for(;argc < 126;) { + argv[argc].type = FGW_STR; + argv[argc].val.cstr = va_arg(ap, const char *); + if (argv[argc].val.cstr == NULL) + break; + argc++; + argv[argc].type = FGW_INT; + argv[argc].val.nat_int = va_arg(ap, int); + argc++; + } + va_end(ap); + + if (pcb_actionv_bin("MessageBox", &res, argc, argv) != 0) + return -1; + + if (fgw_arg_conv(&pcb_fgw, &res, FGW_INT) == 0) + return res.val.nat_int; + + fgw_arg_free(&pcb_fgw, &res); + return -1; +} + +void pcb_hid_iterate(pcb_hid_t *hid) +{ + if (hid->iterate != NULL) + hid->iterate(hid); +} + +static const char *refresh = "progress refresh"; +static const char *cancel = "progress cancel"; +#define REFRESH_RATE 100 + +static void progress_close_cb(void *caller_data, pcb_hid_attr_ev_t ev) +{ + pcb_hid_progress(0, 0, NULL); +} + +static void progress_close_btn_cb(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + pcb_hid_progress(0, 0, cancel); +} + +static void progress_refresh_cb(pcb_hidval_t user_data) +{ + pcb_hid_progress(0, 0, refresh); +} + +static int pcb_gui_progress(long so_far, long total, const char *message) +{ + double now; + static pcb_hidval_t timer; + static int active = 0, cancelled = 0; + static int wp, have_timer = 0; + static pcb_hid_attr_val_t val; + static double last = 0; + static int closing = 0; + static struct { + PCB_DAD_DECL_NOINIT(dlg) + } ctx; + + if (message == refresh) { + if (active) + last = pcb_dtime(); + have_timer = 0; + refresh_now:; + if (active) { + pcb_gui->attr_dlg_set_value(ctx.dlg_hid_ctx, wp, &val); + if (!have_timer) { + timer = pcb_gui->add_timer(progress_refresh_cb, REFRESH_RATE, timer); + have_timer = 1; + } + pcb_hid_iterate(pcb_gui); + } + return 0; + } + + + if (message == cancel) { + cancelled = 1; + message = NULL; + } + + + /* If we are finished, destroy any dialog */ + if (so_far == 0 && total == 0 && message == NULL) { + if (active) { + if (have_timer) { + pcb_gui->stop_timer(timer); + have_timer = 0; + } + if (!closing) { + closing = 1; + PCB_DAD_FREE(ctx.dlg); + } + active = 0; + } + return 1; + } + + if (cancelled) { + cancelled = 0; + return 1; + } + + if (!active) { + PCB_DAD_BEGIN_VBOX(ctx.dlg); + PCB_DAD_LABEL(ctx.dlg, message); + PCB_DAD_PROGRESS(ctx.dlg); + wp = PCB_DAD_CURRENT(ctx.dlg); + + /* need to have a manual cancel button as it needs to call the close cb before really closing the window */ + PCB_DAD_BEGIN_HBOX(ctx.dlg); + PCB_DAD_BEGIN_HBOX(ctx.dlg); + PCB_DAD_COMPFLAG(ctx.dlg, PCB_HATF_EXPFILL); + PCB_DAD_END(ctx.dlg); + PCB_DAD_BUTTON(ctx.dlg, "cancel"); + PCB_DAD_CHANGE_CB(ctx.dlg, progress_close_btn_cb); + PCB_DAD_END(ctx.dlg); + PCB_DAD_END(ctx.dlg); + + PCB_DAD_NEW("progress", ctx.dlg, "pcb-rnd progress", &ctx, pcb_false, progress_close_cb); + active = 1; + cancelled = 0; + + timer = pcb_gui->add_timer(progress_refresh_cb, REFRESH_RATE, timer); + have_timer = 1; + closing = 0; + } + + val.real_value = (double)so_far / (double)total; + + now = pcb_dtime(); + if (now >= (last + (REFRESH_RATE / 1000.0))) { + last = now; + goto refresh_now; + } + return 0; +} + + +int pcb_hid_progress(long so_far, long total, const char *message) +{ + if (pcb_gui == NULL) + return 0; + if ((pcb_gui->gui) && (PCB_HAVE_GUI_ATTR_DLG) && (hid_dlg_gui_inited || pcb_gui->allow_dad_before_init)) + return pcb_gui_progress(so_far, total, message); + + return pcb_nogui_progress(so_far, total, message); +} + +static const char pcb_acts_Print[] = "Print()"; +static const char pcb_acth_Print[] = "Present the print export dialog for printing the layout from the GUI."; +/* DOC: print.html */ +static fgw_error_t pcb_act_Print(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + if (PCB_HAVE_GUI_ATTR_DLG && (fgw_func_lookup(&pcb_fgw, "printgui") != NULL)) + return pcb_actionv_bin("printgui", res, argc, argv); + pcb_message(PCB_MSG_ERROR, "action Print() is available only under a GUI HID. Please use the lpr exporter instead.\n"); + return FGW_ERR_NOT_FOUND; +} + + +static pcb_action_t hid_dlg_action_list[] = { + {"PromptFor", pcb_act_PromptFor, pcb_acth_PromptFor, pcb_acts_PromptFor}, + {"MessageBox", pcb_act_MessageBox, pcb_acth_MessageBox, pcb_acts_MessageBox}, + {"Print", pcb_act_Print, pcb_acth_Print, pcb_acts_Print} +}; + +PCB_REGISTER_ACTIONS(hid_dlg_action_list, NULL) + + +static const char *event_dlg_cookie = "hid_dlg"; + +static void hid_dlg_log_gui_init_ev(void *user_data, int argc, pcb_event_arg_t argv[]) +{ + hid_dlg_gui_inited = 1; +} + +void pcb_hid_dlg_uninit(void) +{ + pcb_event_unbind_allcookie(event_dlg_cookie); +} + +void pcb_hid_dlg_init(void) +{ + pcb_event_bind(PCB_EVENT_GUI_INIT, hid_dlg_log_gui_init_ev, NULL, event_dlg_cookie); +} + Index: tags/2.1.2/src/hid_draw_helpers.c =================================================================== --- tags/2.1.2/src/hid_draw_helpers.c (nonexistent) +++ tags/2.1.2/src/hid_draw_helpers.c (revision 24813) @@ -0,0 +1,229 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * Copyright (C) 2004 harry eaton + * Copyright (C) 2016..2018 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +#include "config.h" +#include "hid.h" +#include "polygon.h" +#include "obj_poly.h" +#include "hid_inlines.h" + +static void fill_contour(pcb_hid_gc_t gc, pcb_pline_t * pl) +{ + pcb_coord_t *x, *y, n, i = 0; + pcb_vnode_t *v; + + n = pl->Count; + x = (pcb_coord_t *) malloc(n * sizeof(*x)); + y = (pcb_coord_t *) malloc(n * sizeof(*y)); + + for (v = &pl->head; i < n; v = v->next) { + x[i] = v->point[0]; + y[i++] = v->point[1]; + } + + pcb_gui->fill_polygon(gc, n, x, y); + + free(x); + free(y); +} + +static void thindraw_contour(pcb_hid_gc_t gc, pcb_pline_t * pl) +{ + pcb_vnode_t *v; + pcb_coord_t last_x, last_y, this_x, this_y, next_x, next_y, mindist; + + + pcb_hid_set_line_width(gc, 0); + pcb_hid_set_line_cap(gc, pcb_cap_round); + + /* If the contour is round, use an arc drawing routine. */ + if (pl->is_round) { + pcb_gui->draw_arc(gc, pl->cx, pl->cy, pl->radius, pl->radius, 0, 360); + return; + } + + /* Need at least two points in the contour */ + if (pl->head.next == NULL) + return; + + last_x = pl->head.point[0]; + last_y = pl->head.point[1]; + v = pl->head.next; + mindist = pcb_gui->coord_per_pix * 2; + + do { + this_x = v->point[0]; + this_y = v->point[1]; + + if ((PCB_ABS(this_x - last_x) < mindist) && (PCB_ABS(this_y - last_y) < mindist)) { + next_x = v->next->point[0]; + next_y = v->next->point[1]; + if ((PCB_ABS(this_x - next_x) < mindist) && (PCB_ABS(this_y - next_y) < mindist)) + continue; + } + + pcb_gui->draw_line(gc, last_x, last_y, this_x, this_y); + /* pcb_gui->fill_circle (gc, this_x, this_y, 30); */ + + last_x = this_x; + last_y = this_y; + } + while ((v = v->next) != pl->head.next); +} + +static void fill_contour_cb(pcb_pline_t * pl, void *user_data) +{ + pcb_hid_gc_t gc = (pcb_hid_gc_t) user_data; + pcb_pline_t *local_pl = pl; + + fill_contour(gc, pl); + pcb_poly_contours_free(&local_pl); +} + +static void fill_clipped_contour(pcb_hid_gc_t gc, pcb_pline_t * pl, const pcb_box_t * clip_box) +{ + pcb_pline_t *pl_copy; + pcb_polyarea_t *clip_poly; + pcb_polyarea_t *piece_poly; + pcb_polyarea_t *clipped_pieces; + pcb_polyarea_t *draw_piece; + int x; + + /* Optimization: the polygon has no holes; if it is smaller the clip_box, + it is safe to draw directly */ + if ((clip_box->X1 <= pl->xmin) && (clip_box->X2 >= pl->xmax) && (clip_box->Y1 <= pl->ymin) && (clip_box->Y2 >= pl->ymax)) { + fill_contour(gc, pl); + return; + } + + clip_poly = pcb_poly_from_rect(clip_box->X1, clip_box->X2, clip_box->Y1, clip_box->Y2); + pcb_poly_contour_copy(&pl_copy, pl); + piece_poly = pcb_polyarea_create(); + pcb_polyarea_contour_include(piece_poly, pl_copy); + x = pcb_polyarea_boolean_free(piece_poly, clip_poly, &clipped_pieces, PCB_PBO_ISECT); + if (x != pcb_err_ok || clipped_pieces == NULL) + return; + + draw_piece = clipped_pieces; + do { + /* NB: The polygon won't have any holes in it */ + fill_contour(gc, draw_piece->contours); + } + while ((draw_piece = draw_piece->f) != clipped_pieces); + pcb_polyarea_free(&clipped_pieces); +} + +/* If at least 50% of the bounding box of the polygon is on the screen, + * lets compute the complete no-holes polygon. + */ +#define BOUNDS_INSIDE_CLIP_THRESHOLD 0.5 +static int should_compute_no_holes(pcb_poly_t * poly, const pcb_box_t * clip_box) +{ + pcb_coord_t x1, x2, y1, y2; + double poly_bounding_area; + double clipped_poly_area; + + /* If there is no passed clip box, compute the whole thing */ + if (clip_box == NULL) + return 1; + + x1 = MAX(poly->BoundingBox.X1, clip_box->X1); + x2 = MIN(poly->BoundingBox.X2, clip_box->X2); + y1 = MAX(poly->BoundingBox.Y1, clip_box->Y1); + y2 = MIN(poly->BoundingBox.Y2, clip_box->Y2); + + /* Check if the polygon is outside the clip box */ + if ((x2 <= x1) || (y2 <= y1)) + return 0; + + poly_bounding_area = (double) (poly->BoundingBox.X2 - poly->BoundingBox.X1) * + (double) (poly->BoundingBox.Y2 - poly->BoundingBox.Y1); + + clipped_poly_area = (double) (x2 - x1) * (double) (y2 - y1); + + if (clipped_poly_area / poly_bounding_area >= BOUNDS_INSIDE_CLIP_THRESHOLD) + return 1; + + return 0; +} + +#undef BOUNDS_INSIDE_CLIP_THRESHOLD + +void pcb_dhlp_fill_pcb_polygon(pcb_hid_gc_t gc, pcb_poly_t * poly, const pcb_box_t * clip_box) +{ + if (!poly->NoHolesValid) { + /* If enough of the polygon is on-screen, compute the entire + * NoHoles version and cache it for later rendering, otherwise + * just compute what we need to render now. + */ + if (should_compute_no_holes(poly, clip_box)) + pcb_poly_compute_no_holes(poly); + else + pcb_poly_no_holes_dicer(poly, clip_box, fill_contour_cb, gc); + } + if (poly->NoHolesValid && poly->NoHoles) { + pcb_pline_t *pl; + + for (pl = poly->NoHoles; pl != NULL; pl = pl->next) { + if (clip_box == NULL) + fill_contour(gc, pl); + else + fill_clipped_contour(gc, pl, clip_box); + } + } + + /* Draw other parts of the polygon if fullpoly flag is set */ + /* NB: No "NoHoles" cache for these */ + if (PCB_FLAG_TEST(PCB_FLAG_FULLPOLY, poly)) { + pcb_poly_t p = *poly; + + for (p.Clipped = poly->Clipped->f; p.Clipped != poly->Clipped; p.Clipped = p.Clipped->f) + pcb_poly_no_holes_dicer(&p, clip_box, fill_contour_cb, gc); + } +} + +static int thindraw_hole_cb(pcb_pline_t * pl, void *user_data) +{ + pcb_hid_gc_t gc = (pcb_hid_gc_t) user_data; + thindraw_contour(gc, pl); + return 0; +} + +void pcb_dhlp_thindraw_pcb_polygon(pcb_hid_gc_t gc, pcb_poly_t * poly, const pcb_box_t * clip_box) +{ + thindraw_contour(gc, poly->Clipped->contours); + pcb_poly_holes(poly, clip_box, thindraw_hole_cb, gc); +} + +void pcb_dhlp_draw_helpers_init(pcb_hid_t * hid) +{ + hid->fill_pcb_polygon = pcb_dhlp_fill_pcb_polygon; + hid->thindraw_pcb_polygon = pcb_dhlp_thindraw_pcb_polygon; +} Index: tags/2.1.2/src/hid_draw_helpers.h =================================================================== --- tags/2.1.2/src/hid_draw_helpers.h (nonexistent) +++ tags/2.1.2/src/hid_draw_helpers.h (revision 24813) @@ -0,0 +1,6 @@ +#ifndef PCB_HID_DRAW_HELPERS_H +#define PCB_HID_DRAW_HELPERS_H +void pcb_dhlp_fill_pcb_polygon(pcb_hid_gc_t gc, pcb_poly_t * poly, const pcb_box_t * clip_box); +void pcb_dhlp_thindraw_pcb_polygon(pcb_hid_gc_t gc, pcb_poly_t * poly, const pcb_box_t * clip_box); +void pcb_dhlp_draw_helpers_init(pcb_hid_t * hid); +#endif Index: tags/2.1.2/src/hid_flags.c =================================================================== --- tags/2.1.2/src/hid_flags.c (nonexistent) +++ tags/2.1.2/src/hid_flags.c (revision 24813) @@ -0,0 +1,119 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * Copyright (C) 2004 harry eaton + * Copyright (C) 2016..2018 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +#include "config.h" +#include "data.h" +#include "board.h" +#include "conf.h" + +#include "hid_flags.h" +#include "genht/hash.h" +#include "genht/htsp.h" +#include "error.h" +#include "actions.h" + +int pcb_hid_get_flag(const char *name) +{ + const char *cp; + + if (name == NULL) + return -1; + + cp = strchr(name, '('); + if (cp == NULL) { + conf_native_t *n = conf_get_field(name); + if (n == NULL) + return -1; + if ((n->type != CFN_BOOLEAN) || (n->used != 1)) + return -1; + return n->val.boolean[0]; + } + else { + const char *end, *s; + fgw_arg_t res, argv[2]; + if (cp != NULL) { + const pcb_action_t *a; + fgw_func_t *f; + char buff[256]; + int len, multiarg; + len = cp - name; + if (len > sizeof(buff)-1) { + pcb_message(PCB_MSG_ERROR, "hid_get_flag: action name too long: %s()\n", name); + return -1; + } + memcpy(buff, name, len); + buff[len] = '\0'; + a = pcb_find_action(buff, &f); + if (!a) { + pcb_message(PCB_MSG_ERROR, "hid_get_flag: no action %s\n", name); + return -1; + } + cp++; + len = strlen(cp); + end = NULL; + multiarg = 0; + for(s = cp; *s != '\0'; s++) { + if (*s == ')') { + end = s; + break; + } + if (*s == ',') + multiarg = 1; + } + if (!multiarg) { + /* faster but limited way for a single arg */ + if ((len > sizeof(buff)-1) || (end == NULL)) { + pcb_message(PCB_MSG_ERROR, "hid_get_flag: action arg too long or unterminated: %s\n", name); + return -1; + } + len = end - cp; + memcpy(buff, cp, len); + buff[len] = '\0'; + argv[0].type = FGW_FUNC; + argv[0].val.func = f; + argv[1].type = FGW_STR; + argv[1].val.str = buff; + res.type = FGW_INVALID; + if (pcb_actionv_(f, &res, (len > 0) ? 2 : 1, argv) != 0) + return -1; + fgw_arg_conv(&pcb_fgw, &res, FGW_INT); + return res.val.nat_int; + } + else { + /* slower but more generic way */ + return pcb_parse_command(name, pcb_true); + } + } + else { + fprintf(stderr, "ERROR: pcb_hid_get_flag(%s) - not a path or an action\n", name); + } + } + return -1; +} Index: tags/2.1.2/src/hid_flags.h =================================================================== --- tags/2.1.2/src/hid_flags.h (nonexistent) +++ tags/2.1.2/src/hid_flags.h (revision 24813) @@ -0,0 +1,11 @@ +#ifndef PCB_HID_FLAGS_H +#define PCB_HID_FLAGS_H + + +/* Looks up an integer (usually boolean) value by conf path or by running + an action (if name has a parenthesis). When an action is run, it has 0 + or 1 argument only and the return value of the action is returned. + On error, returns -1. */ +int pcb_hid_get_flag(const char *name); + +#endif Index: tags/2.1.2/src/hid_init.c =================================================================== --- tags/2.1.2/src/hid_init.c (nonexistent) +++ tags/2.1.2/src/hid_init.c (revision 24813) @@ -0,0 +1,314 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * Copyright (C) 2004 harry eaton + * Copyright (C) 2016..2018 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +#include "config.h" + +#include "hid.h" +#include "hid_nogui.h" +#include "event.h" + +/* for dlopen() and friends; will also solve all system-dependent includes + and provides a dl-compat layer on windows. Also solves the opendir related + includes. */ +#include "plugins.h" +#include "actions.h" +#include "hid_attrib.h" +#include "hid_init.h" +#include "misc_util.h" +#include "conf_core.h" +#include "compat_misc.h" +#include "compat_inc.h" +#include "file_loaded.h" + +static const char *flt_any[] = {"*", "*.*", NULL}; + +const pcb_hid_fsd_filter_t pcb_hid_fsd_filter_any[] = { + { "all", NULL, flt_any }, + { NULL, NULL, NULL } +}; + +pcb_hid_t **pcb_hid_list = 0; +int pcb_hid_num_hids = 0; + +pcb_hid_t *pcb_gui = NULL; +pcb_hid_t *pcb_next_gui = NULL; +pcb_hid_t *pcb_exporter = NULL; + +int pcb_pixel_slop = 1; + +pcb_plugin_dir_t *pcb_plugin_dir_first = NULL, *pcb_plugin_dir_last = NULL; + +void pcb_hid_init() +{ + char *tmp; + + /* Setup a "nogui" default HID */ + pcb_gui = pcb_hid_nogui_get_hid(); + +TODO("make this configurable - add to conf_board_ignores avoid plugin injection") + tmp = pcb_concat(conf_core.rc.path.exec_prefix, PCB_DIR_SEPARATOR_S, "lib", PCB_DIR_SEPARATOR_S, "pcb-rnd", PCB_DIR_SEPARATOR_S, "plugins", PCB_DIR_SEPARATOR_S, HOST, NULL); + pcb_plugin_add_dir(tmp); + free(tmp); + + tmp = pcb_concat(conf_core.rc.path.exec_prefix, PCB_DIR_SEPARATOR_S, "lib", PCB_DIR_SEPARATOR_S, "pcb-rnd", PCB_DIR_SEPARATOR_S, "plugins", NULL); + pcb_plugin_add_dir(tmp); + free(tmp); + + /* hardwired libdir, just in case exec-prefix goes wrong (e.g. linstall) */ + tmp = pcb_concat(PCBLIBDIR, PCB_DIR_SEPARATOR_S, "plugins", PCB_DIR_SEPARATOR_S, HOST, NULL); + pcb_plugin_add_dir(tmp); + free(tmp); + tmp = pcb_concat(PCBLIBDIR, PCB_DIR_SEPARATOR_S, "plugins", NULL); + pcb_plugin_add_dir(tmp); + free(tmp); + + /* conf_core.rc.path.home is set by the conf_core immediately on startup */ + if (conf_core.rc.path.home != NULL) { + tmp = pcb_concat(conf_core.rc.path.home, PCB_DIR_SEPARATOR_S, DOT_PCB_RND, PCB_DIR_SEPARATOR_S, "plugins", PCB_DIR_SEPARATOR_S, HOST, NULL); + pcb_plugin_add_dir(tmp); + free(tmp); + + tmp = pcb_concat(conf_core.rc.path.home, PCB_DIR_SEPARATOR_S, DOT_PCB_RND, PCB_DIR_SEPARATOR_S, "plugins", NULL); + pcb_plugin_add_dir(tmp); + free(tmp); + } + + tmp = pcb_concat("plugins", PCB_DIR_SEPARATOR_S, HOST, NULL); + pcb_plugin_add_dir(tmp); + free(tmp); + + pcb_plugin_add_dir("plugins"); +} + +void pcb_hid_uninit(void) +{ + pcb_plugin_dir_t *pd, *next; + + if (pcb_hid_num_hids > 0) { + int i; + for (i = pcb_hid_num_hids-1; i >= 0; i--) { + if (pcb_hid_list[i]->uninit != NULL) + pcb_hid_list[i]->uninit(pcb_hid_list[i]); + } + } + free(pcb_hid_list); + + pup_uninit(&pcb_pup); + + pcb_hid_attributes_uninit(); + + for(pd = pcb_plugin_dir_first; pd != NULL; pd = next) { + next = pd->next; + free(pd->path); + free(pd); + } + pcb_plugin_dir_first = pcb_plugin_dir_last = NULL; +} + +void pcb_hid_register_hid(pcb_hid_t * hid) +{ + int i; + int sz = (pcb_hid_num_hids + 2) * sizeof(pcb_hid_t *); + + if (hid->struct_size != sizeof(pcb_hid_t)) { + fprintf(stderr, "Warning: hid \"%s\" has an incompatible ABI.\n", hid->name); + return; + } + + for (i = 0; i < pcb_hid_num_hids; i++) + if (hid == pcb_hid_list[i]) + return; + + pcb_hid_num_hids++; + if (pcb_hid_list) + pcb_hid_list = (pcb_hid_t **) realloc(pcb_hid_list, sz); + else + pcb_hid_list = (pcb_hid_t **) malloc(sz); + + pcb_hid_list[pcb_hid_num_hids - 1] = hid; + pcb_hid_list[pcb_hid_num_hids] = 0; +} + +void pcb_hid_remove_hid(pcb_hid_t * hid) +{ + int i; + + for (i = 0; i < pcb_hid_num_hids; i++) { + if (hid == pcb_hid_list[i]) { + pcb_hid_list[i] = pcb_hid_list[pcb_hid_num_hids - 1]; + pcb_hid_list[pcb_hid_num_hids - 1] = 0; + pcb_hid_num_hids--; + return; + } + } +} + + +pcb_hid_t *pcb_hid_find_gui(const char *preference) +{ + int i; + + /* ugly hack for historical reasons: some old configs and veteran users are used to the --gui gtk option */ + if ((preference != NULL) && (strcmp(preference, "gtk") == 0)) { + pcb_hid_t *g; + + g = pcb_hid_find_gui("gtk2_gl"); + if (g != NULL) + return g; + + g = pcb_hid_find_gui("gtk2_gdk"); + if (g != NULL) + return g; + + return NULL; + } + + /* normal search */ + if (preference != NULL) { + for (i = 0; i < pcb_hid_num_hids; i++) + if (!pcb_hid_list[i]->printer && !pcb_hid_list[i]->exporter && !strcmp(pcb_hid_list[i]->name, preference)) + return pcb_hid_list[i]; + return NULL; + } + + for (i = 0; i < pcb_hid_num_hids; i++) + if (!pcb_hid_list[i]->printer && !pcb_hid_list[i]->exporter) + return pcb_hid_list[i]; + + fprintf(stderr, "Error: No GUI available.\n"); + exit(1); +} + +pcb_hid_t *pcb_hid_find_printer() +{ + int i; + + for (i = 0; i < pcb_hid_num_hids; i++) + if (pcb_hid_list[i]->printer) + return pcb_hid_list[i]; + + return 0; +} + +void pcb_hid_print_exporter_list(FILE *f, const char *prefix, const char *suffix) +{ + int i; + for (i = 0; i < pcb_hid_num_hids; i++) + if (pcb_hid_list[i]->exporter) + fprintf(f, "%s%s%s", prefix, pcb_hid_list[i]->name, suffix); +} + +pcb_hid_t *pcb_hid_find_exporter(const char *which) +{ + int i; + + if (which == NULL) { + fprintf(stderr, "Invalid exporter: need an exporter name, one of:"); + goto list; + } + + if (strcmp(which, "-list-") == 0) { + pcb_hid_print_exporter_list(stdout, "", "\n"); + return 0; + } + + for (i = 0; i < pcb_hid_num_hids; i++) + if (pcb_hid_list[i]->exporter && strcmp(which, pcb_hid_list[i]->name) == 0) + return pcb_hid_list[i]; + + fprintf(stderr, "Invalid exporter %s, available ones:", which); + + list:; + pcb_hid_print_exporter_list(stderr, " ", ""); + fprintf(stderr, "\n"); + + return 0; +} + +pcb_hid_t **pcb_hid_enumerate() +{ + return pcb_hid_list; +} + +const char *pcb_hid_export_fn(const char *filename) +{ + if (conf_core.rc.export_basename) { + const char *outfn = strrchr(filename, PCB_DIR_SEPARATOR_C); + if (outfn == NULL) + return filename; + return outfn + 1; + } + else + return filename; +} + +extern void pcb_hid_dlg_uninit(void); +extern void pcb_hid_dlg_init(void); + +void pcb_hidlib_init1(void) +{ + pcb_events_init(); + pcb_file_loaded_init(); + conf_init(); + conf_core_init(); + conf_core_postproc(); /* to get all the paths initialized */ + pcb_hid_dlg_init(); + pcb_hid_init(); +} + +void pcb_hidlib_init2(const pup_buildin_t *buildins) +{ + pcb_actions_init(); + + conf_load_all(NULL, NULL); + + pup_init(&pcb_pup); + pcb_pup.error_stack_enable = 1; + pup_buildin_load(&pcb_pup, buildins); + pup_autoload_dir(&pcb_pup, NULL, NULL); + + conf_load_extra(NULL, NULL); + pcb_units_init(); +} + + +void pcb_hidlib_uninit(void) +{ + pcb_hid_dlg_uninit(); + + if (conf_isdirty(CFR_USER)) + conf_save_file(NULL, NULL, CFR_USER, NULL); + + pcb_hid_uninit(); + pcb_events_uninit(); + conf_uninit(); + pcb_plugin_uninit(); + pcb_actions_uninit(); +} Index: tags/2.1.2/src/hid_init.h =================================================================== --- tags/2.1.2/src/hid_init.h (nonexistent) +++ tags/2.1.2/src/hid_init.h (revision 24813) @@ -0,0 +1,69 @@ +#ifndef PCB_HID_INIT_H +#define PCB_HID_INIT_H + +#include +#include "hid.h" + +/* NULL terminated list of all static HID structures. Built by + hid_register_hid, used by hid_find_*() and pcb_hid_enumerate(). The + order in this list is the same as the order of hid_register_hid + calls. */ +extern pcb_hid_t **pcb_hid_list; + +/* Count of entries in the above. */ +extern int pcb_hid_num_hids; + +/* Call this as soon as possible from main(). No other HID calls are + valid until this is called. */ +void pcb_hid_init(void); + +/* Call this at exit */ +void pcb_hid_uninit(void); + +/* When PCB runs in interactive mode, this is called to instantiate + one GUI HID which happens to be the GUI. This HID is the one that + interacts with the mouse and keyboard. */ +pcb_hid_t *pcb_hid_find_gui(const char *preference); + +/* Finds the one printer HID and instantiates it. */ +pcb_hid_t *pcb_hid_find_printer(void); + +/* Finds the indicated exporter HID and instantiates it. */ +pcb_hid_t *pcb_hid_find_exporter(const char *); + +/* This returns a NULL-terminated array of available HIDs. The only + real reason to use this is to locate all the export-style HIDs. */ +pcb_hid_t **pcb_hid_enumerate(void); + +/* HID internal interfaces. These may ONLY be called from the HID + modules, not from the common PCB code. */ + +/* A HID may use this if it does not need command line arguments in + any special format; for example, the Lesstif HID needs to use the + Xt parser, but the Postscript HID can use this function. */ +int pcb_hid_parse_command_line(int *argc, char ***argv); + +/* Called by the init funcs, used to set up pcb_hid_list. */ +extern void pcb_hid_register_hid(pcb_hid_t * hid); +void pcb_hid_remove_hid(pcb_hid_t * hid); + +typedef struct pcb_plugin_dir_s pcb_plugin_dir_t; +struct pcb_plugin_dir_s { + char *path; + int num_plugins; + pcb_plugin_dir_t *next; +}; + +extern pcb_plugin_dir_t *pcb_plugin_dir_first, *pcb_plugin_dir_last; + +/* Safe file name for inclusion in export file comments/headers; if the + user requested in the config, this becomes the basename of filename, + else it is the full file name */ +const char *pcb_hid_export_fn(const char *filename); + + +void pcb_hidlib_init1(void); /* before CLI argument parsing */ +void pcb_hidlib_init2(const pup_buildin_t *buildins); /* after CLI argument parsing */ +void pcb_hidlib_uninit(void); + +#endif Index: tags/2.1.2/src/hid_inlines.h =================================================================== --- tags/2.1.2/src/hid_inlines.h (nonexistent) +++ tags/2.1.2/src/hid_inlines.h (revision 24813) @@ -0,0 +1,97 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2018 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#ifndef PCB_HID_INLINES +#define PCB_HID_INLINES + +#include "hid.h" + +PCB_INLINE pcb_hid_gc_t pcb_hid_make_gc(void) +{ + pcb_hid_gc_t res; + pcb_core_gc_t *hc; + res = pcb_gui->make_gc(); + hc = (pcb_core_gc_t *)res; /* assumes first field is pcb_core_gc_t */ + hc->width = PCB_MAX_COORD; + hc->cap = pcb_cap_invalid; + hc->xor = 0; + hc->faded = 0; + return res; +} + +PCB_INLINE void pcb_hid_destroy_gc(pcb_hid_gc_t gc) +{ + pcb_gui->destroy_gc(gc); +} + +PCB_INLINE void pcb_hid_set_line_cap(pcb_hid_gc_t gc, pcb_cap_style_t style) +{ + pcb_core_gc_t *hc = (pcb_core_gc_t *)gc; + if (hc->cap != style) { + hc->cap = style; + pcb_gui->set_line_cap(gc, style); + } +} + +PCB_INLINE void pcb_hid_set_line_width(pcb_hid_gc_t gc, pcb_coord_t width) +{ + pcb_core_gc_t *hc = (pcb_core_gc_t *)gc; + if (hc->width != width) { + hc->width = width; + pcb_gui->set_line_width(gc, width); + } +} + +PCB_INLINE void pcb_hid_set_draw_xor(pcb_hid_gc_t gc, int xor) +{ + pcb_core_gc_t *hc = (pcb_core_gc_t *)gc; + if (hc->xor != xor) { + hc->xor = xor; + pcb_gui->set_draw_xor(gc, xor); + } +} + +PCB_INLINE void pcb_hid_set_draw_faded(pcb_hid_gc_t gc, int faded) +{ + pcb_core_gc_t *hc = (pcb_core_gc_t *)gc; + if (hc->faded != faded) { + hc->faded = faded; + pcb_gui->set_draw_faded(gc, faded); + } +} + +PCB_INLINE const char *pcb_hid_command_entry(const char *ovr, int *cursor) +{ + if ((pcb_gui == NULL) || (pcb_gui->command_entry == NULL)) { + if (cursor != NULL) + *cursor = -1; + return NULL; + } + return pcb_gui->command_entry(ovr, cursor); +} + + +#endif Index: tags/2.1.2/src/hid_nogui.c =================================================================== --- tags/2.1.2/src/hid_nogui.c (nonexistent) +++ tags/2.1.2/src/hid_nogui.c (revision 24813) @@ -0,0 +1,534 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * Copyright (C) 2004 harry eaton + * Copyright (C) 2016..2018 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +#include "config.h" + +#include +#include +#include + +#include "actions.h" +#include "hid.h" +#include "compat_misc.h" +#include "conf_core.h" + +/* This is the "gui" that is installed at startup, and is used when + there is no other real GUI to use. For the most part, it just + stops the application from (1) crashing randomly, and (2) doing + gui-specific things when it shouldn't. */ + +#define CRASH(func) fprintf(stderr, "HID error: pcb called GUI function %s without having a GUI available.\n", func); abort() + +static const char pcb_acth_cli[] = "Intenal: CLI frontend action. Do not use directly."; + +static pcb_hid_t nogui_hid; + +typedef struct hid_gc_s { + int nothing_interesting_here; +} hid_gc_s; + +static pcb_hid_attribute_t *nogui_get_export_options(int *n_ret) +{ + if (n_ret != NULL) + *n_ret = 0; + return NULL; +} + +static void nogui_do_export(pcb_hid_attr_val_t * options) +{ + CRASH("do_export"); +} + +static int nogui_parse_arguments(int *argc, char ***argv) +{ + CRASH("parse_arguments"); +} + +static void nogui_invalidate_lr(pcb_coord_t l, pcb_coord_t r, pcb_coord_t t, pcb_coord_t b) +{ + CRASH("invalidate_lr"); +} + +static void nogui_invalidate_all(void) +{ + CRASH("invalidate_all"); +} + +static int nogui_set_layer_group(pcb_layergrp_id_t group, const char *purpose, int purpi, pcb_layer_id_t layer, unsigned int flags, int is_empty, pcb_xform_t **xform) +{ + CRASH("set_layer_group"); + return 0; +} + +static void nogui_end_layer(void) +{ +} + +static pcb_hid_gc_t nogui_make_gc(void) +{ + return 0; +} + +static void nogui_destroy_gc(pcb_hid_gc_t gc) +{ +} + +static void nogui_set_drawing_mode(pcb_composite_op_t op, pcb_bool direct, const pcb_box_t *screen) +{ + CRASH("set_drawing_mode"); +} + +static void nogui_render_burst(pcb_burst_op_t op, const pcb_box_t *screen) +{ + /* the HID may decide to ignore this hook */ +} + +static void nogui_set_color(pcb_hid_gc_t gc, const pcb_color_t *name) +{ + CRASH("set_color"); +} + +static void nogui_set_line_cap(pcb_hid_gc_t gc, pcb_cap_style_t style) +{ + CRASH("set_line_cap"); +} + +static void nogui_set_line_width(pcb_hid_gc_t gc, pcb_coord_t width) +{ + CRASH("set_line_width"); +} + +static void nogui_set_draw_xor(pcb_hid_gc_t gc, int xor_) +{ + CRASH("set_draw_xor"); +} + +static void nogui_set_draw_faded(pcb_hid_gc_t gc, int faded) +{ +} + +static void nogui_draw_line(pcb_hid_gc_t gc, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2) +{ + CRASH("draw_line"); +} + +static void nogui_draw_arc(pcb_hid_gc_t gc, pcb_coord_t cx, pcb_coord_t cy, pcb_coord_t width, pcb_coord_t height, pcb_angle_t start_angle, pcb_angle_t end_angle) +{ + CRASH("draw_arc"); +} + +static void nogui_draw_rect(pcb_hid_gc_t gc, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2) +{ + CRASH("draw_rect"); +} + +static void nogui_fill_circle(pcb_hid_gc_t gc, pcb_coord_t cx, pcb_coord_t cy, pcb_coord_t radius) +{ + CRASH("fill_circle"); +} + +static void nogui_fill_polygon(pcb_hid_gc_t gc, int n_coords, pcb_coord_t * x, pcb_coord_t * y) +{ + CRASH("fill_polygon"); +} + +static void nogui_fill_pcb_polygon(pcb_hid_gc_t gc, pcb_poly_t * poly, const pcb_box_t * clip_box) +{ + CRASH("fill_pcb_polygon"); +} + +static void nogui_fill_rect(pcb_hid_gc_t gc, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2) +{ + CRASH("fill_rect"); +} + +static void nogui_calibrate(double xval, double yval) +{ + CRASH("calibrate"); +} + +static int nogui_shift_is_pressed(void) +{ + /* This is called from pcb_crosshair_grid_fit() when the board is loaded. */ + return 0; +} + +static int nogui_control_is_pressed(void) +{ + CRASH("control_is_pressed"); + return 0; +} + +static int nogui_mod1_is_pressed(void) +{ + CRASH("mod1_is_pressed"); + return 0; +} + +static void nogui_get_coords(const char *msg, pcb_coord_t *x, pcb_coord_t *y, int force) +{ + CRASH("get_coords"); +} + +static void nogui_set_crosshair(pcb_coord_t x, pcb_coord_t y, int action) +{ +} + +static pcb_hidval_t nogui_add_timer(void (*func) (pcb_hidval_t user_data), unsigned long milliseconds, pcb_hidval_t user_data) +{ + pcb_hidval_t rv; + CRASH("add_timer"); + rv.lval = 0; + return rv; +} + +static void nogui_stop_timer(pcb_hidval_t timer) +{ + CRASH("stop_timer"); +} + +static pcb_hidval_t nogui_watch_file(int fd, unsigned int condition, pcb_bool (*func) (pcb_hidval_t watch, int fd, unsigned int condition, pcb_hidval_t user_data), pcb_hidval_t user_data) +{ + pcb_hidval_t rv; + CRASH("watch_file"); + rv.lval = 0; + return rv; +} + +static void nogui_unwatch_file(pcb_hidval_t watch) +{ + CRASH("unwatch_file"); +} + +/* Return a line of user input text, stripped of any newline characters. + * Returns NULL if the user simply presses enter, or otherwise gives no input. + */ +#define MAX_LINE_LENGTH 1024 +static const char *CANCEL = "CANCEL"; +static char *read_stdin_line(void) +{ + static char buf[MAX_LINE_LENGTH]; + char *s; + int i; + + s = fgets(buf, MAX_LINE_LENGTH, stdin); + if (s == NULL) { + printf("\n"); + return pcb_strdup(CANCEL); + } + + /* Strip any trailing newline characters */ + for (i = strlen(s) - 1; i >= 0; i--) + if (s[i] == '\r' || s[i] == '\n') + s[i] = '\0'; + + if (s[0] == '\0') + return NULL; + + return pcb_strdup(s); +} + +#undef MAX_LINE_LENGTH + +static fgw_error_t pcb_act_cli_PromptFor(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + char *answer; + const char *label, *default_str = "", *title = NULL; + const char *pcb_acts_cli_PromptFor = pcb_acth_cli; + + PCB_ACT_CONVARG(1, FGW_STR, cli_PromptFor, label = argv[1].val.str); + PCB_ACT_MAY_CONVARG(2, FGW_STR, cli_PromptFor, default_str = argv[2].val.str); + PCB_ACT_MAY_CONVARG(3, FGW_STR, cli_PromptFor, title = argv[3].val.str); + + if (!conf_core.rc.quiet) { + char *tmp; + if (title != NULL) + printf("*** %s ***\n", title); + if (default_str) + printf("%s [%s] : ", label, default_str); + else + printf("%s : ", label); + + tmp = read_stdin_line(); + if (tmp == NULL) + answer = pcb_strdup((default_str != NULL) ? default_str : ""); + else + answer = tmp; /* always allocated */ + } + else + answer = pcb_strdup(""); + + res->type = FGW_STR | FGW_DYN; + res->val.str = answer; + return 0; +} + +static fgw_error_t pcb_act_cli_MessageBox(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + const char *pcb_acts_cli_MessageBox = pcb_acth_cli; + const char *icon, *title, *label, *txt, *answer; + char *end; + int n, ret; + + res->type = FGW_INT; + if (conf_core.rc.quiet) { + cancel:; + res->val.nat_int = -1; + return 0; + } + + PCB_ACT_CONVARG(1, FGW_STR, cli_MessageBox, icon = argv[1].val.str); + PCB_ACT_CONVARG(2, FGW_STR, cli_MessageBox, title = argv[2].val.str); + PCB_ACT_CONVARG(3, FGW_STR, cli_MessageBox, label = argv[3].val.str); + + printf("[%s] *** %s ***\n", icon, title); + + retry:; + printf("%s:\n", label); + for(n = 4; n < argc; n+=2) { + PCB_ACT_CONVARG(n+0, FGW_STR, cli_MessageBox, txt = argv[n+0].val.str); + printf(" %d = %s\n", (n - 4)/2+1, txt); + } + printf("\nChose a number from above: "); + fflush(stdout); + answer = read_stdin_line(); + if ((answer == CANCEL) || (strcmp(answer, "cancel") == 0)) + goto cancel; + if (answer == NULL) + goto retry; + ret = strtol(answer, &end, 10); + if (((*end != '\0') && (*end != '\n') && (*end != '\r')) || (ret < 1) || (ret > (argc - 3) / 2)) { + printf("\nERROR: please type a number between 1 and %d\n", (argc - 4)/2+1); + goto retry; + } + n = (ret-1)*2+5; + PCB_ACT_CONVARG(n, FGW_INT, cli_MessageBox, res->val.nat_int = argv[n].val.nat_int); + return 0; +} + +/* FIXME - this could use some enhancement to actually use the other + args */ +static char *nogui_fileselect(const char *title, const char *descr, + const char *default_file, const char *default_ext, const pcb_hid_fsd_filter_t *flt, const char *history_tag, pcb_hid_fsd_flags_t flags, pcb_hid_dad_subdialog_t *sub) +{ + char *answer; + + if (conf_core.rc.quiet) + return pcb_strdup(""); + + if (default_file) + printf("%s [%s] : ", title, default_file); + else + printf("%s : ", title); + + answer = read_stdin_line(); + if (answer == NULL) + return (default_file != NULL) ? pcb_strdup(default_file) : NULL; + else + return pcb_strdup(answer); +} + +void *pcb_nogui_attr_dlg_new(const char *id, pcb_hid_attribute_t *attrs_, int n_attrs_, pcb_hid_attr_val_t * results_, const char *title_, void *caller_data, pcb_bool modal, void (*button_cb)(void *caller_data, pcb_hid_attr_ev_t ev), int defx, int defy) +{ + CRASH("attr_dlg_new"); +} + +static int nogui_attr_dlg_run(void *hid_ctx) +{ + CRASH("attr_dlg_run"); +} + +static void nogui_attr_dlg_free(void *hid_ctx) +{ + CRASH("attr_dlg_free"); +} + +static void nogui_attr_dlg_property(void *hid_ctx, pcb_hat_property_t prop, const pcb_hid_attr_val_t *val) +{ + CRASH("attr_dlg_dlg_property"); +} + +static void nogui_beep(void) +{ + putchar(7); + fflush(stdout); +} + +int pcb_nogui_progress(long so_far, long total, const char *message) +{ + static int on = 0; + static double nextt; + double now; + + if (conf_core.rc.quiet) + return 0; + if (message == NULL) { + if ((on) && (conf_core.rc.verbose >= PCB_MSG_INFO)) + fprintf(stderr, "progress: finished\n"); + on = 0; + } + else { + if ((conf_core.rc.verbose >= PCB_MSG_INFO) || (pcb_gui != &nogui_hid)) { + now = pcb_dtime(); + if (now >= nextt) { + fprintf(stderr, "progress: %ld/%ld %s\n", so_far, total, message); + nextt = now + 0.2; + } + } + on = 1; + } + return 0; +} + +static void nogui_create_menu(const char *menu_path, const pcb_menu_prop_t *props) +{ +} + +static int clip_warn(void) +{ + static int warned = 0; + if (!warned) { + pcb_message(PCB_MSG_ERROR, "The current GUI HID does not support clipboard.\nClipboard is emulated, not shared withother programs\n"); + warned = 1; + } + return 0; +} + +static void *clip_data = NULL; +static size_t clip_len; +static pcb_hid_clipfmt_t clip_format; + +static int nogui_clip_set(pcb_hid_clipfmt_t format, const void *data, size_t len) +{ + free(clip_data); + clip_data = malloc(len); + if (clip_data != NULL) { + memcpy(clip_data, data, len); + clip_len = len; + clip_format = format; + } + else + clip_data = NULL; + return clip_warn(); +} + +static int nogui_clip_get(pcb_hid_clipfmt_t *format, void **data, size_t *len) +{ + if (clip_data == NULL) { + *data = NULL; + clip_warn(); + return -1; + } + *data = malloc(clip_len); + if (*data == NULL) { + *data = NULL; + return -1; + } + + memcpy(*data, clip_data, clip_len); + *format = clip_format; + *len = clip_len; + return clip_warn(); +} + +static void nogui_clip_free(pcb_hid_clipfmt_t format, void *data, size_t len) +{ + free(data); +} + + +void pcb_hid_nogui_init(pcb_hid_t * hid) +{ + hid->get_export_options = nogui_get_export_options; + hid->do_export = nogui_do_export; + hid->parse_arguments = nogui_parse_arguments; + hid->invalidate_lr = nogui_invalidate_lr; + hid->invalidate_all = nogui_invalidate_all; + hid->set_layer_group = nogui_set_layer_group; + hid->end_layer = nogui_end_layer; + hid->make_gc = nogui_make_gc; + hid->destroy_gc = nogui_destroy_gc; + hid->set_drawing_mode = nogui_set_drawing_mode; + hid->render_burst = nogui_render_burst; + hid->set_color = nogui_set_color; + hid->set_line_cap = nogui_set_line_cap; + hid->set_line_width = nogui_set_line_width; + hid->set_draw_xor = nogui_set_draw_xor; + hid->set_draw_faded = nogui_set_draw_faded; + hid->draw_line = nogui_draw_line; + hid->draw_arc = nogui_draw_arc; + hid->draw_rect = nogui_draw_rect; + hid->fill_circle = nogui_fill_circle; + hid->fill_polygon = nogui_fill_polygon; + hid->fill_pcb_polygon = nogui_fill_pcb_polygon; + hid->fill_rect = nogui_fill_rect; + hid->calibrate = nogui_calibrate; + hid->shift_is_pressed = nogui_shift_is_pressed; + hid->control_is_pressed = nogui_control_is_pressed; + hid->mod1_is_pressed = nogui_mod1_is_pressed; + hid->get_coords = nogui_get_coords; + hid->set_crosshair = nogui_set_crosshair; + hid->add_timer = nogui_add_timer; + hid->stop_timer = nogui_stop_timer; + hid->watch_file = nogui_watch_file; + hid->unwatch_file = nogui_unwatch_file; + hid->fileselect = nogui_fileselect; + hid->attr_dlg_new = pcb_nogui_attr_dlg_new; + hid->attr_dlg_run = nogui_attr_dlg_run; + hid->attr_dlg_free = nogui_attr_dlg_free; + hid->attr_dlg_property = nogui_attr_dlg_property; + hid->beep = nogui_beep; + hid->create_menu = nogui_create_menu; + hid->clip_set = nogui_clip_set; + hid->clip_get = nogui_clip_get; + hid->clip_free = nogui_clip_free; +} + + +pcb_hid_t *pcb_hid_nogui_get_hid(void) +{ + memset(&nogui_hid, 0, sizeof(pcb_hid_t)); + + nogui_hid.struct_size = sizeof(pcb_hid_t); + nogui_hid.name = "nogui"; + nogui_hid.description = "Default GUI when no other GUI is present. " "Does nothing."; + + pcb_hid_nogui_init(&nogui_hid); + + return &nogui_hid; +} + + +static pcb_action_t cli_dlg_action_list[] = { + {"cli_PromptFor", pcb_act_cli_PromptFor, pcb_acth_cli, NULL}, + {"cli_MessageBox", pcb_act_cli_MessageBox, pcb_acth_cli, NULL} +}; + +PCB_REGISTER_ACTIONS(cli_dlg_action_list, NULL) Index: tags/2.1.2/src/hid_nogui.h =================================================================== --- tags/2.1.2/src/hid_nogui.h (nonexistent) +++ tags/2.1.2/src/hid_nogui.h (revision 24813) @@ -0,0 +1,12 @@ +#ifndef PCB_HID_COMMON_HIDNOGUI_H +#define PCB_HID_COMMON_HIDNOGUI_H + +void pcb_hid_nogui_init(pcb_hid_t * hid); +pcb_hid_t *pcb_hid_nogui_get_hid(void); + +/* For checking if attr dialogs are not available: */ +void *pcb_nogui_attr_dlg_new(const char *id, pcb_hid_attribute_t *attrs_, int n_attrs_, pcb_hid_attr_val_t * results_, const char *title_, void *caller_data, pcb_bool modal, void (*button_cb)(void *caller_data, pcb_hid_attr_ev_t ev), int defx, int defy); + +int pcb_nogui_progress(long so_far, long total, const char *message); + +#endif Index: tags/2.1.2/src/hidlib.c =================================================================== --- tags/2.1.2/src/hidlib.c (nonexistent) +++ tags/2.1.2/src/hidlib.c (revision 24813) @@ -0,0 +1,47 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2019 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "config.h" + +#include + +const char *(*pcb_hidlib_get_filename)(void); +const char *(*pcb_hidlib_get_name)(void); + +const char *pcb_board_get_filename(void) +{ + if (pcb_hidlib_get_filename != NULL) + return pcb_hidlib_get_filename(); + return NULL; +} + +const char *pcb_board_get_name(void) +{ + if (pcb_hidlib_get_name != NULL) + return pcb_hidlib_get_name(); + return NULL; +} + Index: tags/2.1.2/src/hidlib.h =================================================================== --- tags/2.1.2/src/hidlib.h (nonexistent) +++ tags/2.1.2/src/hidlib.h (revision 24813) @@ -0,0 +1,32 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2019 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "config.h" + +/* optional: if non-NULL, called back to determine the file name or project + name of the current design */ +const char *(*pcb_hidlib_get_filename)(void); +const char *(*pcb_hidlib_get_name)(void); Index: tags/2.1.2/src/ht_subc.c =================================================================== --- tags/2.1.2/src/ht_subc.c (nonexistent) +++ tags/2.1.2/src/ht_subc.c (revision 24813) @@ -0,0 +1,9 @@ +#include +#include "config.h" +#include "obj_subc_list.h" + +#define HT(x) htscp_ ## x +#include +#undef HT + + Index: tags/2.1.2/src/ht_subc.h =================================================================== --- tags/2.1.2/src/ht_subc.h (nonexistent) +++ tags/2.1.2/src/ht_subc.h (revision 24813) @@ -0,0 +1,13 @@ +#ifndef PCB_HT_SUBC_H +#define PCB_HT_SUBC_H + +/* Hash: subcircuit -> pointer */ + +/* hash instance */ +typedef pcb_subc_t *htscp_key_t; +typedef void * htscp_value_t; +#define HT(x) htscp_ ## x +#include +#undef HT + +#endif Index: tags/2.1.2/src/icons/Makefile.am =================================================================== --- tags/2.1.2/src/icons/Makefile.am (nonexistent) +++ tags/2.1.2/src/icons/Makefile.am (revision 24813) @@ -0,0 +1,4 @@ +## $Id$ + +EXTRA_DIST= hand.dat hcurs.dat lcurs.dat lock.dat + Index: tags/2.1.2/src/icons/hand.dat =================================================================== --- tags/2.1.2/src/icons/hand.dat (nonexistent) +++ tags/2.1.2/src/icons/hand.dat (revision 24813) @@ -0,0 +1,9 @@ +#define hand_width 21 +#define hand_height 21 +static unsigned char hand_bits[] = { + 0x00, 0x02, 0x00, 0x20, 0x25, 0x00, 0x50, 0x55, 0x02, 0x50, 0x55, 0x05, + 0x50, 0x55, 0x05, 0xd3, 0xd4, 0x06, 0x95, 0x48, 0x02, 0x19, 0x40, 0x01, + 0x12, 0x00, 0x01, 0x04, 0x80, 0x00, 0x08, 0x80, 0x00, 0x10, 0x80, 0x00, + 0xe0, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x38, 0x26, 0x02, 0x48, 0x69, 0x02, + 0x48, 0xe9, 0x02, 0x38, 0xaf, 0x02, 0x08, 0xa9, 0x03, 0x08, 0x29, 0x03, + 0x08, 0x29, 0x02}; Index: tags/2.1.2/src/icons/hcurs.dat =================================================================== --- tags/2.1.2/src/icons/hcurs.dat (nonexistent) +++ tags/2.1.2/src/icons/hcurs.dat (revision 24813) @@ -0,0 +1,8 @@ +#define hcurs_width 16 +#define hcurs_height 16 +#define hcurs_x_hot 7 +#define hcurs_y_hot 9 +static unsigned char hcurs_bits[] = { + 0x80, 0x00, 0xc8, 0x09, 0xdc, 0x1d, 0xdc, 0x1d, 0xdc, 0x1d, 0xfc, 0xcf, + 0x38, 0xee, 0x1f, 0x78, 0x0f, 0x78, 0x07, 0x30, 0x07, 0x30, 0x0e, 0x38, + 0x1e, 0x3c, 0x3c, 0x1e, 0xf8, 0x0f, 0xf0, 0x0f}; Index: tags/2.1.2/src/icons/lcurs.dat =================================================================== --- tags/2.1.2/src/icons/lcurs.dat (nonexistent) +++ tags/2.1.2/src/icons/lcurs.dat (revision 24813) @@ -0,0 +1,6 @@ +#define lcurs_width 16 +#define lcurs_height 16 +static unsigned char lcurs_bits[] = { + 0xf0, 0x0f, 0xf0, 0x0f, 0xf8, 0x1f, 0x38, 0x1c, 0x1c, 0x3c, 0x1c, 0x38, + 0x1c, 0x30, 0xfe, 0x7f, 0xfe, 0x7f, 0xfe, 0x7f, 0xfe, 0x7f, 0xfe, 0x7f, + 0xfe, 0x7f, 0xfe, 0x7f, 0xfe, 0x7f, 0xfe, 0x7f}; Index: tags/2.1.2/src/icons/lock.dat =================================================================== --- tags/2.1.2/src/icons/lock.dat (nonexistent) +++ tags/2.1.2/src/icons/lock.dat (revision 24813) @@ -0,0 +1,9 @@ +#define lock_width 21 +#define lock_height 21 +static unsigned char lock_bits[] = { + 0x00, 0x1f, 0x00, 0x80, 0x31, 0x00, 0x80, 0x20, 0x00, 0xc0, 0x60, 0x00, + 0x40, 0x40, 0x00, 0x40, 0x40, 0x00, 0xf0, 0xff, 0x01, 0x10, 0x00, 0x01, + 0xf0, 0xff, 0x01, 0x10, 0x00, 0x01, 0xf0, 0xff, 0x01, 0x10, 0x00, 0x01, + 0xf0, 0xff, 0x01, 0x00, 0x00, 0x00, 0x84, 0xb1, 0x04, 0x44, 0x8a, 0x04, + 0x44, 0x8a, 0x02, 0x44, 0x8a, 0x01, 0x44, 0x8a, 0x02, 0x44, 0x8a, 0x04, + 0x9c, 0xb1, 0x04}; Index: tags/2.1.2/src/idpath.c =================================================================== --- tags/2.1.2/src/idpath.c (nonexistent) +++ tags/2.1.2/src/idpath.c (revision 24813) @@ -0,0 +1,186 @@ +/* + * + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2018 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +#include "config.h" + +#define TDL_DONT_UNDEF +#include "idpath.h" +#include +#undef TDL_DONT_UNDEF +#include + +#include + +#include "data.h" +#include "layer.h" + +static int idpath_map(pcb_idpath_t *idp, pcb_any_obj_t *obj, int level, int *numlevels) +{ + pcb_data_t *data; + + if (numlevels != 0) + (*numlevels)++; + + if (idp != NULL) { + if (level < 0) + return -1; + idp->id[level] = obj->ID; + } + + switch(obj->parent_type) { + case PCB_PARENT_INVALID: + case PCB_PARENT_UI: + case PCB_PARENT_SUBC: + case PCB_PARENT_BOARD: + case PCB_PARENT_NET: + return -1; + case PCB_PARENT_LAYER: + assert(obj->parent.layer->parent_type = PCB_PARENT_DATA); + data = obj->parent.layer->parent.data; + goto recurse; + + case PCB_PARENT_DATA: + data = obj->parent.data; + recurse:; + switch(data->parent_type) { + case PCB_PARENT_INVALID: + case PCB_PARENT_UI: + case PCB_PARENT_LAYER: + case PCB_PARENT_DATA: + case PCB_PARENT_NET: + return -1; + case PCB_PARENT_BOARD: + return 0; + case PCB_PARENT_SUBC: /* recurse */ + return idpath_map(idp, (pcb_any_obj_t *)data->parent.subc, level-1, numlevels); + } + break; + } + return -1; +} + +pcb_idpath_t *pcb_idpath_alloc(int len) +{ + pcb_idpath_t *idp; + idp = calloc(1, sizeof(pcb_idpath_t) + (sizeof(long int) * (len-1))); + idp->len = len; + return idp; +} + +pcb_idpath_t *pcb_obj2idpath(pcb_any_obj_t *obj) +{ + pcb_idpath_t *idp; + int len = 0; + + /* determine the length first */ + if (idpath_map(NULL, obj, 0, &len) != 0) + return NULL; + + idp = pcb_idpath_alloc(len); + if (idpath_map(idp, obj, len-1, NULL) != 0) { + free(idp); + return NULL; + } + + return idp; +} + +pcb_idpath_t *pcb_str2idpath(const char *str) +{ + const char *s; + char *next; + int n, len = 1; + pcb_idpath_t *idp; + + for(s = str; *s == '/'; s++) + for(; *s != '\0'; s++) { + if ((s[0] == '/') && (s[1] != '/') && (s[1] != '\0')) + len++; + } + + idp = pcb_idpath_alloc(len); + + for(s = str, n = 0; *s != '\0'; s++,n++) { + while(*s == '/') s++; + if (*s == '\0') + break; + idp->id[n] = strtol(s, &next, 10); + s = (const char *)next; + } + return idp; +} + +static pcb_any_obj_t *idpath2obj(pcb_data_t *data, const pcb_idpath_t *path, int level) +{ + + for(;;) { + pcb_any_obj_t *obj = htip_get(&data->id2obj, path->id[level]); + pcb_subc_t *sc = (pcb_subc_t *)obj; + + if (obj == NULL) + return NULL; + + level++; + if (level == path->len) + return obj; + + if (obj->type != PCB_OBJ_SUBC) /* can descend only in subcircuits */ + return NULL; + + data = sc->data; + } +} + +pcb_any_obj_t *pcb_idpath2obj(pcb_data_t *data, const pcb_idpath_t *path) +{ + return idpath2obj(data, path, 0); +} + +void pcb_idpath_destroy(pcb_idpath_t *path) +{ + pcb_idpath_list_remove(path); + free(path); +} + +void pcb_idpath_list_clear(pcb_idpath_list_t *lst) +{ + pcb_idpath_t *i, *next; + for(i = pcb_idpath_list_first(lst); i != NULL; i = next) { + next = pcb_idpath_list_next(i); + pcb_idpath_destroy(i); + } +} + +pcb_idpath_t *pcb_idpath_dup(const pcb_idpath_t *path) +{ + pcb_idpath_t *res = pcb_idpath_alloc(path->len); + memcpy(res->id, path->id, (sizeof(long int) * path->len)); + return res; +} + + Index: tags/2.1.2/src/idpath.h =================================================================== --- tags/2.1.2/src/idpath.h (nonexistent) +++ tags/2.1.2/src/idpath.h (revision 24813) @@ -0,0 +1,67 @@ +/* + * + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2018 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +#ifndef PCB_IDPATH_H +#define PCB_IDPATH_H + +#include + +typedef struct pcb_idpath_s { + int len; + gdl_elem_t link; /* may be part of an idpath list */ + long int id[1]; /* the struct is allocated to be sizeof(long int) * len */ +} pcb_idpath_t; + +/* List of id paths */ +#define TDL(x) pcb_idpath_list_ ## x +#define TDL_LIST_T pcb_idpath_list_t +#define TDL_ITEM_T pcb_idpath_t +#define TDL_FIELD link +#define TDL_SIZE_T size_t +#define TDL_FUNC + +#define pcb_idpath_list_foreach(list, iterator, loop_elem) \ + gdl_foreach_((&((list)->lst)), (iterator), (loop_elem)) + +#include +#include + +#include "obj_common.h" + +/* Allocate an idpath of a given length with all id's set to 0 */ +pcb_idpath_t *pcb_idpath_alloc(int len); + +pcb_idpath_t *pcb_obj2idpath(pcb_any_obj_t *obj); +pcb_idpath_t *pcb_str2idpath(const char *str); /* slash separated list of ids */ +pcb_any_obj_t *pcb_idpath2obj(pcb_data_t *data, const pcb_idpath_t *path); +pcb_idpath_t *pcb_idpath_dup(const pcb_idpath_t *path); +void pcb_idpath_destroy(pcb_idpath_t *path); + +void pcb_idpath_list_clear(pcb_idpath_list_t *lst); + +#endif Index: tags/2.1.2/src/insert.c =================================================================== --- tags/2.1.2/src/insert.c (nonexistent) +++ tags/2.1.2/src/insert.c (revision 24813) @@ -0,0 +1,146 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + + +/* functions used to insert points into objects + */ + +#include "config.h" +#include "conf_core.h" + +#include "board.h" +#include "data.h" +#include "select.h" +#include "undo.h" + +#include "obj_line_op.h" +#include "obj_arc_op.h" +#include "obj_rat_op.h" +#include "obj_poly_op.h" + +static pcb_opfunc_t InsertFunctions = { + pcb_lineop_insert_point, + NULL, + pcb_polyop_insert_point, + NULL, + NULL, + pcb_arc_insert_point, + pcb_ratop_insert_point, + NULL, + NULL, /* subc */ + NULL /* padstack */ +}; + +void *pcb_insert_point_in_object(int Type, void *Ptr1, void *Ptr2, pcb_cardinal_t * Ptr3, pcb_coord_t DX, pcb_coord_t DY, pcb_bool Force, pcb_bool insert_last) +{ + void *ptr; + pcb_opctx_t ctx; + + ctx.insert.pcb = PCB; + ctx.insert.x = DX; + ctx.insert.y = DY; + ctx.insert.idx = *Ptr3; + ctx.insert.last = insert_last; + ctx.insert.forcible = Force; + + /* the operation insert the points to the undo-list */ + ptr = pcb_object_operation(&InsertFunctions, &ctx, Type, Ptr1, Ptr2, Ptr3); + if (ptr != NULL) + pcb_undo_inc_serial(); + return ptr; +} + +pcb_point_t *pcb_adjust_insert_point(void) +{ + static pcb_point_t InsertedPoint; + double m; + pcb_coord_t x, y, m1, m2; + pcb_line_t *line = (pcb_line_t *) pcb_crosshair.AttachedObject.Ptr2; + + if (pcb_crosshair.AttachedObject.State == PCB_CH_STATE_FIRST) + return NULL; + pcb_crosshair.AttachedObject.Ptr3 = &InsertedPoint; + if (pcb_gui->shift_is_pressed()) { + pcb_attached_line_t myline; + /* only force 45 degree for nearest point */ + if (pcb_distance(pcb_crosshair.X, pcb_crosshair.Y, line->Point1.X, line->Point1.Y) < + pcb_distance(pcb_crosshair.X, pcb_crosshair.Y, line->Point2.X, line->Point2.Y)) + myline.Point1 = myline.Point2 = line->Point1; + else + myline.Point1 = myline.Point2 = line->Point2; + pcb_line_45(&myline); + InsertedPoint.X = myline.Point2.X; + InsertedPoint.Y = myline.Point2.Y; + return &InsertedPoint; + } + if (PCB->RatDraw || conf_core.editor.all_direction_lines) { + InsertedPoint.X = pcb_crosshair.X; + InsertedPoint.Y = pcb_crosshair.Y; + return &InsertedPoint; + } + if (pcb_crosshair.X == line->Point1.X) + m1 = 2; /* 2 signals infinite slope */ + else { + m = (double) (pcb_crosshair.Y - line->Point1.Y) / (pcb_crosshair.X - line->Point1.X); + m1 = 0; + if (m > PCB_TAN_30_DEGREE) + m1 = (m > PCB_TAN_60_DEGREE) ? 2 : 1; + else if (m < -PCB_TAN_30_DEGREE) + m1 = (m < -PCB_TAN_60_DEGREE) ? 2 : -1; + } + if (pcb_crosshair.X == line->Point2.X) + m2 = 2; /* 2 signals infinite slope */ + else { + m = (double) (pcb_crosshair.Y - line->Point2.Y) / (pcb_crosshair.X - line->Point2.X); + m2 = 0; + if (m > PCB_TAN_30_DEGREE) + m2 = (m > PCB_TAN_60_DEGREE) ? 2 : 1; + else if (m < -PCB_TAN_30_DEGREE) + m2 = (m < -PCB_TAN_60_DEGREE) ? 2 : -1; + } + if (m1 == m2) { + InsertedPoint.X = line->Point1.X; + InsertedPoint.Y = line->Point1.Y; + return &InsertedPoint; + } + if (m1 == 2) { + x = line->Point1.X; + y = line->Point2.Y + m2 * (line->Point1.X - line->Point2.X); + } + else if (m2 == 2) { + x = line->Point2.X; + y = line->Point1.Y + m1 * (line->Point2.X - line->Point1.X); + } + else { + x = (line->Point2.Y - line->Point1.Y + m1 * line->Point1.X - m2 * line->Point2.X) / (m1 - m2); + y = (m1 * line->Point2.Y - m1 * m2 * line->Point2.X - m2 * line->Point1.Y + m1 * m2 * line->Point1.X) / (m1 - m2); + } + InsertedPoint.X = x; + InsertedPoint.Y = y; + return &InsertedPoint; +} Index: tags/2.1.2/src/insert.h =================================================================== --- tags/2.1.2/src/insert.h (nonexistent) +++ tags/2.1.2/src/insert.h (revision 24813) @@ -0,0 +1,43 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +/* Inserting points into objects */ + +#ifndef PCB_INSERT_H +#define PCB_INSERT_H + +#include "config.h" + +#define PCB_INSERT_TYPES (PCB_OBJ_POLY | PCB_OBJ_LINE | PCB_OBJ_ARC | PCB_OBJ_RAT) + +void *pcb_insert_point_in_object(int Type, void *Ptr1, void *Ptr2, pcb_cardinal_t * Ptr3, pcb_coord_t DX, pcb_coord_t DY, pcb_bool Force, pcb_bool insert_last); + +/* adjusts the insert point to make 45 degree lines as necessary */ +pcb_point_t *pcb_adjust_insert_point(void); + +#endif Index: tags/2.1.2/src/intersect.c =================================================================== --- tags/2.1.2/src/intersect.c (nonexistent) +++ tags/2.1.2/src/intersect.c (revision 24813) @@ -0,0 +1,270 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * Copyright (C) 1998,1999,2000,2001 harry eaton + * + * this file, intersect.c, was written and is + * Copyright (c) 2001 C. Scott Ananian + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + * + * Old contact info: + * harry eaton, 6697 Buttonhole Ct, Columbia, MD 21044 USA + * haceaton@aplcomm.jhuapl.edu + * + */ + +/* rectangle intersection/union routines. */ + +#include "config.h" + +#include +#include + +#include "intersect.h" +#include "box.h" + +static int compareleft(const void *ptr1, const void *ptr2); +static int compareright(const void *ptr1, const void *ptr2); +static int comparepos(const void *ptr1, const void *ptr2); +static int nextpwrof2(int i); + +typedef struct { + pcb_coord_t left, right; + int covered; + pcb_coord_t area; +} SegmentTreeNode; + +typedef struct { + SegmentTreeNode *nodes; + int size; +} SegmentTree; + +typedef struct { + pcb_coord_t *p; + int size; +} LocationList; + +/* --------------------------------------------------------------------------- + * Create a sorted list of unique y coords from a BoxList. + */ +static LocationList createSortedYList(pcb_box_list_t *boxlist) +{ + LocationList yCoords; + pcb_coord_t last; + int i, n; + /* create sorted list of Y coordinates */ + yCoords.size = 2 * boxlist->BoxN; + yCoords.p = (pcb_coord_t *) calloc(yCoords.size, sizeof(*yCoords.p)); + for (i = 0; i < boxlist->BoxN; i++) { + yCoords.p[2 * i] = boxlist->Box[i].Y1; + yCoords.p[2 * i + 1] = boxlist->Box[i].Y2; + } + qsort(yCoords.p, yCoords.size, sizeof(*yCoords.p), comparepos); + /* count uniq y coords */ + last = 0; + for (n = 0, i = 0; i < yCoords.size; i++) + if (i == 0 || yCoords.p[i] != last) + yCoords.p[n++] = last = yCoords.p[i]; + yCoords.size = n; + return yCoords; +} + +/* --------------------------------------------------------------------------- + * Create an empty segment tree from the given sorted list of uniq y coords. + */ +static SegmentTree createSegmentTree(pcb_coord_t * yCoords, int N) +{ + SegmentTree st; + int i; + /* size is twice the nearest larger power of 2 */ + st.size = 2 * nextpwrof2(N); + st.nodes = (SegmentTreeNode *) calloc(st.size, sizeof(*st.nodes)); + /* initialize the rightmost leaf node */ + st.nodes[st.size - 1].left = (N > 0) ? yCoords[--N] : 10; + st.nodes[st.size - 1].right = st.nodes[st.size - 1].left + 1; + /* initialize the rest of the leaf nodes */ + for (i = st.size - 2; i >= st.size / 2; i--) { + st.nodes[i].right = st.nodes[i + 1].left; + st.nodes[i].left = (N > 0) ? yCoords[--N] : st.nodes[i].right - 1; + } + /* initialize the internal nodes */ + for (; i > 0; i--) { /* node 0 is not used */ + st.nodes[i].right = st.nodes[2 * i + 1].right; + st.nodes[i].left = st.nodes[2 * i].left; + } + /* done! */ + return st; +} + +void insertSegment(SegmentTree * st, int n, pcb_coord_t Y1, pcb_coord_t Y2) +{ + pcb_coord_t discriminant; + if (st->nodes[n].left >= Y1 && st->nodes[n].right <= Y2) { + st->nodes[n].covered++; + } + else { + assert(n < st->size / 2); + discriminant = st->nodes[n * 2 + 1 /*right */ ].left; + if (Y1 < discriminant) + insertSegment(st, n * 2, Y1, Y2); + if (discriminant < Y2) + insertSegment(st, n * 2 + 1, Y1, Y2); + } + /* fixup area */ + st->nodes[n].area = (st->nodes[n].covered > 0) ? + (st->nodes[n].right - st->nodes[n].left) : (n >= st->size / 2) ? 0 : st->nodes[n * 2].area + st->nodes[n * 2 + 1].area; +} + +void deleteSegment(SegmentTree * st, int n, pcb_coord_t Y1, pcb_coord_t Y2) +{ + pcb_coord_t discriminant; + if (st->nodes[n].left >= Y1 && st->nodes[n].right <= Y2) { + assert(st->nodes[n].covered); + --st->nodes[n].covered; + } + else { + assert(n < st->size / 2); + discriminant = st->nodes[n * 2 + 1 /*right */ ].left; + if (Y1 < discriminant) + deleteSegment(st, n * 2, Y1, Y2); + if (discriminant < Y2) + deleteSegment(st, n * 2 + 1, Y1, Y2); + } + /* fixup area */ + st->nodes[n].area = (st->nodes[n].covered > 0) ? + (st->nodes[n].right - st->nodes[n].left) : (n >= st->size / 2) ? 0 : st->nodes[n * 2].area + st->nodes[n * 2 + 1].area; +} + +/* --------------------------------------------------------------------------- + * Compute the area of the intersection of the given rectangles; that is, + * the area covered by more than one rectangle (counted twice if the area is + * covered by three rectangles, three times if covered by four rectangles, + * etc.). + * Runs in O(N ln N) time. + */ +double pcb_intersect_box_box(pcb_box_list_t *boxlist) +{ + pcb_cardinal_t i; + double area = 0.0; + /* first get the aggregate area. */ + for (i = 0; i < boxlist->BoxN; i++) + area += (double) (boxlist->Box[i].X2 - boxlist->Box[i].X1) * (double) (boxlist->Box[i].Y2 - boxlist->Box[i].Y1); + /* intersection area is aggregate - union. */ + return area * 0.0001 - pcb_union_box_box(boxlist); +} + +/* --------------------------------------------------------------------------- + * Compute the area of the union of the given rectangles. + * O(N ln N) time. + */ +double pcb_union_box_box(pcb_box_list_t *boxlist) +{ + pcb_box_t **rectLeft, **rectRight; + pcb_cardinal_t i, j; + LocationList yCoords; + SegmentTree segtree; + pcb_coord_t lastX; + double area = 0.0; + + if (boxlist->BoxN == 0) + return 0.0; + /* create sorted list of Y coordinates */ + yCoords = createSortedYList(boxlist); + /* now create empty segment tree */ + segtree = createSegmentTree(yCoords.p, yCoords.size); + free(yCoords.p); + /* create sorted list of left and right X coordinates of rectangles */ + rectLeft = (pcb_box_t **) calloc(boxlist->BoxN, sizeof(*rectLeft)); + rectRight = (pcb_box_t **) calloc(boxlist->BoxN, sizeof(*rectRight)); + for (i = 0; i < boxlist->BoxN; i++) { + assert(boxlist->Box[i].X1 <= boxlist->Box[i].X2); + assert(boxlist->Box[i].Y1 <= boxlist->Box[i].Y2); + rectLeft[i] = rectRight[i] = &boxlist->Box[i]; + } + qsort(rectLeft, boxlist->BoxN, sizeof(*rectLeft), compareleft); + qsort(rectRight, boxlist->BoxN, sizeof(*rectRight), compareright); + /* sweep through x segments from left to right */ + i = j = 0; + lastX = rectLeft[0]->X1; + while (j < boxlist->BoxN) { + assert(i <= boxlist->BoxN); + /* i will step through rectLeft, j will through rectRight */ + if (i == boxlist->BoxN || rectRight[j]->X2 < rectLeft[i]->X1) { + /* right edge of rectangle */ + pcb_box_t *b = rectRight[j++]; + /* check lastX */ + if (b->X2 != lastX) { + assert(lastX < b->X2); + area += (double) (b->X2 - lastX) * segtree.nodes[1].area; + lastX = b->X2; + } + /* remove a segment from the segment tree. */ + deleteSegment(&segtree, 1, b->Y1, b->Y2); + } + else { + /* left edge of rectangle */ + pcb_box_t *b = rectLeft[i++]; + /* check lastX */ + if (b->X1 != lastX) { + assert(lastX < b->X1); + area += (double) (b->X1 - lastX) * segtree.nodes[1].area; + lastX = b->X1; + } + /* add a segment from the segment tree. */ + insertSegment(&segtree, 1, b->Y1, b->Y2); + } + } + free(rectLeft); + free(rectRight); + free(segtree.nodes); + return area * 0.0001; +} + +static int compareleft(const void *ptr1, const void *ptr2) +{ + pcb_box_t **b1 = (pcb_box_t **) ptr1, **b2 = (pcb_box_t **) ptr2; + return (*b1)->X1 - (*b2)->X1; +} + +static int compareright(const void *ptr1, const void *ptr2) +{ + pcb_box_t **b1 = (pcb_box_t **) ptr1, **b2 = (pcb_box_t **) ptr2; + return (*b1)->X2 - (*b2)->X2; +} + +static int comparepos(const void *ptr1, const void *ptr2) +{ + return *((pcb_coord_t *) ptr1) - *((pcb_coord_t *) ptr2); +} + +static int nextpwrof2(int n) +{ + int r = 1; + while (n != 0) { + n /= 2; + r *= 2; + } + return r; +} Index: tags/2.1.2/src/intersect.h =================================================================== --- tags/2.1.2/src/intersect.h (nonexistent) +++ tags/2.1.2/src/intersect.h (revision 24813) @@ -0,0 +1,49 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * Copyright (C) 1998,1999,2000,2001 harry eaton + * + * this file, intersect.h, was written and is + * Copyright (c) 2001 C. Scott Ananian. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + * + * Old contact info: + * harry eaton, 6697 Buttonhole Ct, Columbia, MD 21044 USA + * haceaton@aplcomm.jhuapl.edu + * + */ + + +/* Box (rectangle) intersection/union routines. */ + +#ifndef PCB_INTERSECT_H +#define PCB_INTERSECT_H + +#include "global_typedefs.h" + +double pcb_intersect_box_box(pcb_box_list_t *boxlist); /* will sort boxlist */ +double pcb_union_box_box(pcb_box_list_t *boxlist); + +#endif Index: tags/2.1.2/src/layer.c =================================================================== --- tags/2.1.2/src/layer.c (nonexistent) +++ tags/2.1.2/src/layer.c (revision 24813) @@ -0,0 +1,1165 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996,2004,2006 Thomas Nau + * Copyright (C) 2016, 2017 Tibor 'Igor2' Palinkas (pcb-rnd extensions) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +#include "config.h" +#include "board.h" +#include "data.h" +#include "conf_core.h" +#include "layer.h" +#include "compat_misc.h" +#include "undo.h" +#include "event.h" +#include "layer_ui.h" +#include "layer_vis.h" +#include "funchash_core.h" +#include "rtree.h" +#include "obj_pstk_inlines.h" +#include "list_common.h" + +pcb_virt_layer_t pcb_virt_layers[] = { + {"invisible", PCB_LYT_VIRTUAL + 1, PCB_LYT_VIRTUAL | PCB_LYT_INVIS, NULL, -1 }, + {"rats", PCB_LYT_VIRTUAL + 2, PCB_LYT_VIRTUAL | PCB_LYT_RAT, NULL, -1 }, + {"topassembly", PCB_LYT_VIRTUAL + 3, PCB_LYT_VIRTUAL | PCB_LYT_TOP, "assy", F_assy }, + {"bottomassembly", PCB_LYT_VIRTUAL + 4, PCB_LYT_VIRTUAL | PCB_LYT_BOTTOM, "assy", F_assy }, + {"fab", PCB_LYT_VIRTUAL + 5, PCB_LYT_VIRTUAL | PCB_LYT_LOGICAL, "fab", F_fab }, + {"plated-drill", PCB_LYT_VIRTUAL + 6, PCB_LYT_VIRTUAL, "pdrill", F_pdrill }, + {"unplated-drill", PCB_LYT_VIRTUAL + 7, PCB_LYT_VIRTUAL, "udrill", F_udrill }, + {"csect", PCB_LYT_VIRTUAL + 8, PCB_LYT_VIRTUAL | PCB_LYT_LOGICAL, "csect", F_csect }, + {"dialog", PCB_LYT_VIRTUAL + 9, PCB_LYT_VIRTUAL | PCB_LYT_DIALOG | PCB_LYT_LOGICAL | PCB_LYT_NOEXPORT, NULL, -1 }, + { NULL, 0 }, +}; + +const pcb_menu_layers_t pcb_menu_layers[] = { + { "Subcircuits", "subc", &conf_core.appearance.color.subc, NULL, offsetof(pcb_board_t, SubcOn), 0 }, + { "Subc. parts", "subcpart", &conf_core.appearance.color.subc, NULL, offsetof(pcb_board_t, SubcPartsOn), 0 }, + { "Padstacks", "padstacks",&conf_core.appearance.color.pin, NULL, offsetof(pcb_board_t, pstk_on), 0 }, + { "Holes", "holes", &conf_core.appearance.color.pin, NULL, offsetof(pcb_board_t, hole_on), 0 }, + { "Pstk. marks", "pstkmark", &conf_core.appearance.color.padstackmark, NULL, offsetof(pcb_board_t, padstack_mark_on), 0 }, + { "Far side", "farside", &conf_core.appearance.color.invisible_objects, NULL, offsetof(pcb_board_t, InvisibleObjectsOn), 0 }, + { "Rats", "rats", &conf_core.appearance.color.rat, "rats", offsetof(pcb_board_t, RatOn), offsetof(pcb_board_t, RatDraw) }, + { NULL, NULL, NULL, NULL, 0} +}; + + +typedef struct { + pcb_layer_type_t type; + int class; + const char *name; +} pcb_layer_type_name_t; + +/* update docs: lihata format tree */ +static const pcb_layer_type_name_t pcb_layer_type_names[] = { + { PCB_LYT_TOP, 1, "top" }, + { PCB_LYT_BOTTOM, 1, "bottom" }, + { PCB_LYT_INTERN, 1, "intern" }, + { PCB_LYT_LOGICAL, 1, "logical" }, + { PCB_LYT_COPPER, 2, "copper" }, + { PCB_LYT_SILK, 2, "silk" }, + { PCB_LYT_MASK, 2, "mask" }, + { PCB_LYT_PASTE, 2, "paste" }, + { PCB_LYT_BOUNDARY,2, "boundary" }, + { PCB_LYT_RAT, 2, "rat" }, + { PCB_LYT_INVIS, 2, "invis" }, + { PCB_LYT_SUBSTRATE,2,"substrate" }, + { PCB_LYT_MISC, 2, "misc" }, + { PCB_LYT_DOC, 2, "doc" }, + { PCB_LYT_MECH, 2, "mech" }, + { PCB_LYT_UI, 2, "userinterface" }, + { PCB_LYT_VIRTUAL, 3, "virtual" }, + { 0, 0, NULL } +}; + +static const char *pcb_layer_type_class_names[] = { + "INVALID", "location", "purpose", "property" +}; + +static const pcb_layer_type_name_t pcb_layer_comb_names[] = { + { PCB_LYC_SUB, 0, "sub"}, + { PCB_LYC_AUTO, 0, "auto"}, + { 0, 0, NULL } +}; + + +#define PCB_LAYER_VIRT_MIN (PCB_LYT_VIRTUAL + PCB_VLY_first + 1) +#define PCB_LAYER_VIRT_MAX (PCB_LYT_VIRTUAL + PCB_VLY_end) + +#define layer_if_too_many(pcb, fail_cmd) \ +do { \ + if (pcb->Data->LayerN >= PCB_MAX_LAYER) { \ + pcb_message(PCB_MSG_ERROR, "Too many layers - can't have more than %d\n", PCB_MAX_LAYER); \ + fail_cmd; \ + } \ +} while(0) + +#define PURP_MATCH(ps, pi) (((purpi == -1) || (purpi == pi)) && ((purpose == NULL) || ((ps != NULL) && (strcmp(purpose, ps) == 0)))) + +void pcb_layer_free_fields(pcb_layer_t *layer) +{ + if (!layer->is_bound) + pcb_attribute_free(&layer->Attributes); + PCB_TEXT_LOOP(layer); + { + free(text->TextString); + } + PCB_END_LOOP; + + list_map0(&layer->Line, pcb_line_t, pcb_line_free); + list_map0(&layer->Arc, pcb_arc_t, pcb_arc_free); + list_map0(&layer->Text, pcb_text_t, pcb_text_free); + PCB_POLY_LOOP(layer); + { + pcb_poly_free_fields(polygon); + } + PCB_END_LOOP; + list_map0(&layer->Polygon, pcb_poly_t, pcb_poly_free); + if (!layer->is_bound) { + if (layer->line_tree) + pcb_r_destroy_tree(&layer->line_tree); + if (layer->arc_tree) + pcb_r_destroy_tree(&layer->arc_tree); + if (layer->text_tree) + pcb_r_destroy_tree(&layer->text_tree); + if (layer->polygon_tree) + pcb_r_destroy_tree(&layer->polygon_tree); + } + free((char *)layer->name); + memset(layer, 0, sizeof(pcb_layer_t)); +} + +pcb_bool pcb_layer_is_pure_empty(pcb_layer_t *layer) +{ + /* if any local list is non-empty, the layer is non-empty */ + if (layer->Line.lst.length > 0) return pcb_false; + if (layer->Arc.lst.length > 0) return pcb_false; + if (layer->Polygon.lst.length > 0) return pcb_false; + if (layer->Text.lst.length > 0) return pcb_false; + + /* if the layer is locally empty, it might be a board layer that has + objects from subcircuits so also check the rtrees */ + return + PCB_RTREE_EMPTY(layer->line_tree) && + PCB_RTREE_EMPTY(layer->arc_tree) && + PCB_RTREE_EMPTY(layer->polygon_tree) && + PCB_RTREE_EMPTY(layer->text_tree); +} + +static pcb_bool pcb_layer_is_empty_glob(pcb_board_t *pcb, pcb_data_t *data, pcb_layer_t *layer) +{ + /* if any padstack has a shape on this layer, it is not empty */ + PCB_PADSTACK_LOOP(data); + { + if (pcb_pstk_shape_at(pcb, padstack, layer) != NULL) + return 0; + } + PCB_END_LOOP; + + /* need to recurse to subc */ + PCB_SUBC_LOOP(data); + { + pcb_layer_id_t n; + pcb_layer_t *sl; + + for(sl = subc->data->Layer, n = 0; n < subc->data->LayerN; sl++,n++) { + if (sl->meta.bound.real == layer) { + if (!pcb_layer_is_empty_(pcb, sl)) + return 0; + /* can't break here: multiple bound layers may point to the same real layer! */ + } + } + + if (!pcb_layer_is_empty_glob(pcb, subc->data, layer)) + return 0; + } + PCB_END_LOOP; + + return 1; +} + +pcb_bool pcb_layer_is_empty_(pcb_board_t *pcb, pcb_layer_t *layer) +{ + pcb_layer_type_t flags = pcb_layer_flags_(layer); + if (flags == 0) + return 1; + + /* fast check: direct object */ + if (!pcb_layer_is_pure_empty(layer)) + return 0; + + if (!pcb_layer_is_empty_glob(pcb, pcb->Data, layer)) + return 0; + + /* found nothing: layer is empty */ + return 1; +} + +pcb_bool pcb_layer_is_empty(pcb_board_t *pcb, pcb_layer_id_t num) +{ + if ((num >= 0) && (num < pcb->Data->LayerN)) + return pcb_layer_is_empty_(pcb, pcb->Data->Layer + num); + return pcb_false; +} + +pcb_layer_id_t pcb_layer_id(const pcb_data_t *Data, const pcb_layer_t *Layer) +{ + if (Layer->parent_type == PCB_PARENT_UI) + return pcb_uilayer_get_id(Layer); + + if (Layer->parent.data != Data) { + /* the only case this makes sense is when we are resolving a bound layer */ + if ((Layer->is_bound) && (Layer->meta.bound.real != NULL)) + return pcb_layer_id(Data, Layer->meta.bound.real); + /* failed binding, ignore the layer */ + return -1; + } + if ((Layer >= Data->Layer) && (Layer < (Data->Layer + PCB_MAX_LAYER))) + return Layer - Data->Layer; + + return -1; +} + +unsigned int pcb_layer_flags(const pcb_board_t *pcb, pcb_layer_id_t layer_idx) +{ + pcb_layer_t *l; + + if (layer_idx & PCB_LYT_UI) + return PCB_LYT_UI | PCB_LYT_VIRTUAL; + + if ((layer_idx >= PCB_LAYER_VIRT_MIN) && (layer_idx <= PCB_LAYER_VIRT_MAX)) + return pcb_virt_layers[layer_idx - PCB_LAYER_VIRT_MIN].type; + + if ((layer_idx < 0) || (layer_idx >= pcb->Data->LayerN)) + return 0; + + l = &pcb->Data->Layer[layer_idx]; + return pcb_layergrp_flags(pcb, l->meta.real.grp); +} + +unsigned int pcb_layer_flags_(const pcb_layer_t *layer) +{ + + /* real layer: have to do a layer stack based lookup; but at least we have a real layer ID */ + if (!layer->is_bound) { + pcb_data_t *data = layer->parent.data; + pcb_layer_id_t lid; + + if (data == NULL) + return 0; + + lid = pcb_layer_id(data, layer);; + if (lid < 0) + return 0; + + assert(data->parent_type == PCB_PARENT_BOARD); + return pcb_layer_flags(data->parent.board, lid); + } + + /* bound layer: if it is already bound to a real layer, use that, whatever it is (manual binding may override our local type match pattern) */ + if (layer->meta.bound.real != NULL) { + layer = pcb_layer_get_real(layer); + if (layer == NULL) + return 0; + return pcb_layer_flags_(layer); /* tail recursion */ + } + + /* bound layer without a real layer binding: use the type match */ + return layer->meta.bound.type; +} + +int pcb_layer_purpose(const pcb_board_t *pcb, pcb_layer_id_t layer_idx, const char **out) +{ + pcb_layergrp_t *grp; + + if (layer_idx & PCB_LYT_UI) + return PCB_LYT_UI | PCB_LYT_VIRTUAL; + + if ((layer_idx >= PCB_LAYER_VIRT_MIN) && (layer_idx <= PCB_LAYER_VIRT_MAX)) { + if (out != NULL) + *out = pcb_virt_layers[layer_idx - PCB_LAYER_VIRT_MIN].purpose; + return pcb_virt_layers[layer_idx - PCB_LAYER_VIRT_MIN].purpi; + } + + if ((layer_idx < 0) || (layer_idx >= pcb->Data->LayerN)) { + if (out != NULL) + *out = NULL; + return -1; + } + + grp = pcb_get_layergrp((pcb_board_t *)pcb, pcb->Data->Layer[layer_idx].meta.real.grp); + + if (out != NULL) { + if (grp == NULL) { + *out = NULL; + return -1; + } + *out = grp->purpose; + return grp->purpi; + } + + if (grp == NULL) + return -1; + + return grp->purpi; +} + +int pcb_layer_purpose_(const pcb_layer_t *layer, const char **out) +{ + /* real layer: have to do a layer stack based lookup; but at least we have a real layer ID */ + if (!layer->is_bound) { + pcb_data_t *data = layer->parent.data; + pcb_layer_id_t lid; + + if (data == NULL) + return 0; + + lid = pcb_layer_id(data, layer);; + if (lid < 0) + return 0; + + assert(data->parent_type == PCB_PARENT_BOARD); + return pcb_layer_purpose(data->parent.board, lid, out); + } + + /* bound layer: if it is already bound to a real layer, use that, whatever it is (manual binding may override our local type match pattern) */ + if (layer->meta.bound.real != NULL) { + layer = pcb_layer_get_real(layer); + if (layer == NULL) + return 0; + return pcb_layer_purpose_(layer, out); /* tail recursion */ + } + + /* bound layer without a real layer binding: use the type match */ + if (out != NULL) + *out = layer->meta.bound.purpose; + return pcb_funchash_get(layer->meta.bound.purpose, NULL); +} + +#define APPEND(n) \ + do { \ + if (res != NULL) { \ + if (used < res_len) { \ + res[used] = n; \ + used++; \ + } \ + } \ + else \ + used++; \ + } while(0) + +#define APPEND_VIRT(v) \ +do { \ + APPEND(v->new_id); \ +} while(0) + +const pcb_virt_layer_t *pcb_vlayer_get_first(pcb_layer_type_t mask, const char *purpose, int purpi) +{ + const pcb_virt_layer_t *v; + mask &= (~PCB_LYT_VIRTUAL); + for(v = pcb_virt_layers; v->name != NULL; v++) + if ((((v->type & (~PCB_LYT_VIRTUAL)) & mask) == mask) && PURP_MATCH(v->purpose, v->purpi)) + return v; + return NULL; +} + + + +int pcb_layer_list(const pcb_board_t *pcb, pcb_layer_type_t mask, pcb_layer_id_t *res, int res_len) +{ + int n, used = 0; + pcb_virt_layer_t *v; + + for(v = pcb_virt_layers; v->name != NULL; v++) + if ((v->type & mask) == mask) + APPEND_VIRT(v); + + for (n = 0; n < PCB_MAX_LAYER; n++) + if ((pcb_layer_flags(pcb, n) & mask) == mask) + APPEND(n); + + if (mask == PCB_LYT_UI) + for (n = 0; n < vtp0_len(&pcb_uilayers); n++) + if (pcb_uilayers.array[n] != NULL) + APPEND(n | PCB_LYT_UI | PCB_LYT_VIRTUAL); + + return used; +} + +/* optimization: code dup for speed */ +int pcb_layer_listp(const pcb_board_t *pcb, pcb_layer_type_t mask, pcb_layer_id_t *res, int res_len, int purpi, const char *purpose) +{ + int n, used = 0; + pcb_virt_layer_t *v; + + + for(v = pcb_virt_layers; v->name != NULL; v++) + if (((v->type & mask) == mask) && (PURP_MATCH(v->purpose, v->purpi))) + APPEND_VIRT(v); + + for (n = 0; n < PCB_MAX_LAYER; n++) { + if ((pcb_layer_flags(pcb, n) & mask) == mask) { + const char *lpurp; + int lpurpi = pcb_layer_purpose(pcb, n, &lpurp); + if (PURP_MATCH(lpurp, lpurpi)) + APPEND(n); + } + } + + if (mask == PCB_LYT_UI) + for (n = 0; n < vtp0_len(&pcb_uilayers); n++) + if ((pcb_uilayers.array[n] != NULL)) + APPEND(n | PCB_LYT_UI | PCB_LYT_VIRTUAL); + + return used; +} + + +int pcb_layer_list_any(const pcb_board_t *pcb, pcb_layer_type_t mask, pcb_layer_id_t *res, int res_len) +{ + int n, used = 0; + pcb_virt_layer_t *v; + + for(v = pcb_virt_layers; v->name != NULL; v++) + if ((v->type & mask)) + APPEND_VIRT(v); + + for (n = 0; n < PCB_MAX_LAYER; n++) + if ((pcb_layer_flags(pcb, n) & mask)) + APPEND(n); + + if (mask & PCB_LYT_UI) + for (n = 0; n < vtp0_len(&pcb_uilayers); n++) + if (pcb_uilayers.array[n] != NULL) + APPEND(n | PCB_LYT_UI | PCB_LYT_VIRTUAL); + + return used; +} + +pcb_layer_id_t pcb_layer_by_name(pcb_data_t *data, const char *name) +{ + pcb_layer_id_t n; + for (n = 0; n < data->LayerN; n++) + if (strcmp(data->Layer[n].name, name) == 0) + return n; + return -1; +} + +void pcb_layers_reset(pcb_board_t *pcb) +{ + pcb_layer_id_t n; + + /* reset everything to empty, even if that's invalid (no top/bottom copper) + for the rest of the code: the (embedded) default design will overwrite this. */ + /* reset layers */ + for(n = 0; n < PCB_MAX_LAYER; n++) { + if (pcb->Data->Layer[n].name != NULL) + free((char *)pcb->Data->Layer[n].name); + pcb->Data->Layer[n].name = pcb_strdup(""); + pcb->Data->Layer[n].meta.real.grp = -1; + } + + /* reset layer groups */ + for(n = 0; n < PCB_MAX_LAYERGRP; n++) { + pcb->LayerGroups.grp[n].len = 0; + pcb->LayerGroups.grp[n].ltype = 0; + pcb->LayerGroups.grp[n].valid = 0; + } + pcb->LayerGroups.len = 0; + pcb->Data->LayerN = 0; +} + +/* empty and detach a layer - must be initialized or another layer moved over it later */ +static void layer_clear(pcb_layer_t *dst) +{ + memset(dst, 0, sizeof(pcb_layer_t)); + dst->meta.real.grp = -1; +} + +pcb_layer_id_t pcb_layer_create(pcb_board_t *pcb, pcb_layergrp_id_t grp, const char *lname) +{ + pcb_layer_id_t id; + + layer_if_too_many(pcb, return -1); + + id = pcb->Data->LayerN++; + + if (lname != NULL) { + if (pcb->Data->Layer[id].name != NULL) + free((char *)pcb->Data->Layer[id].name); + } + + layer_clear(&pcb->Data->Layer[id]); + pcb->Data->Layer[id].name = pcb_strdup(lname); + + /* add layer to group */ + if (grp >= 0) { + pcb->LayerGroups.grp[grp].lid[pcb->LayerGroups.grp[grp].len] = id; + pcb->LayerGroups.grp[grp].len++; + pcb->Data->Layer[id].meta.real.vis = pcb->Data->Layer[pcb->LayerGroups.grp[grp].lid[0]].meta.real.vis; + } + pcb->Data->Layer[id].meta.real.grp = grp; + pcb->Data->Layer[id].meta.real.color = *pcb_layer_default_color(id, (grp < 0) ? 0 : pcb->LayerGroups.grp[grp].ltype); + + pcb->Data->Layer[id].parent_type = PCB_PARENT_DATA; + pcb->Data->Layer[id].parent.data = pcb->Data; + pcb->Data->Layer[id].type = PCB_OBJ_LAYER; + + if (pcb == PCB) + pcb_board_set_changed_flag(1); + + return id; +} + +int pcb_layer_rename_(pcb_layer_t *Layer, char *Name) +{ + free((char*)Layer->name); + Layer->name = Name; + pcb_event(PCB_EVENT_LAYERS_CHANGED, NULL); + return 0; +} + +int pcb_layer_rename(pcb_data_t *data, pcb_layer_id_t layer, const char *lname) +{ + return pcb_layer_rename_(&data->Layer[layer], pcb_strdup(lname)); +} + +int pcb_layer_recolor_(pcb_layer_t *Layer, const pcb_color_t *color) +{ + if (Layer->is_bound) + return -1; + Layer->meta.real.color = *color; + pcb_event(PCB_EVENT_LAYERS_CHANGED, NULL); + return 0; +} + +int pcb_layer_recolor(pcb_data_t *data, pcb_layer_id_t layer, const char *color) +{ + pcb_color_t clr; + pcb_color_load_str(&clr, color); + return pcb_layer_recolor_(&data->Layer[layer], &clr); +} + +#undef APPEND + +static int is_last_top_copper_layer(pcb_board_t *pcb, int layer) +{ + pcb_layergrp_id_t cgroup = pcb_layer_get_group(pcb, pcb->LayerGroups.len + PCB_COMPONENT_SIDE); + pcb_layergrp_id_t lgroup = pcb_layer_get_group(pcb, layer); + if (cgroup == lgroup && pcb->LayerGroups.grp[lgroup].len == 1) + return 1; + return 0; +} + +static int is_last_bottom_copper_layer(pcb_board_t *pcb, int layer) +{ + int sgroup = pcb_layer_get_group(pcb, pcb->LayerGroups.len + PCB_SOLDER_SIDE); + int lgroup = pcb_layer_get_group(pcb, layer); + if (sgroup == lgroup && pcb->LayerGroups.grp[lgroup].len == 1) + return 1; + return 0; +} + +/* Safe move of a layer within a layer array, updaging all fields (list->parents) */ +void pcb_layer_move_(pcb_layer_t *dst, pcb_layer_t *src) +{ + pcb_line_t *li; + pcb_text_t *te; + pcb_poly_t *po; + pcb_arc_t *ar; + + memcpy(dst, src, sizeof(pcb_layer_t)); + + /* reparent all the lists: each list item has a ->parent pointer that needs to point to the new place */ + for(li = linelist_first(&dst->Line); li != NULL; li = linelist_next(li)) + li->link.parent = &dst->Line.lst; + for(te = textlist_first(&dst->Text); te != NULL; te = textlist_next(te)) + te->link.parent = &dst->Text.lst; + for(po = polylist_first(&dst->Polygon); po != NULL; po = polylist_next(po)) + po->link.parent = &dst->Polygon.lst; + for(ar = arclist_first(&dst->Arc); ar != NULL; ar = arclist_next(ar)) + ar->link.parent = &dst->Arc.lst; +} + +const pcb_color_t *pcb_layer_default_color(int idx, pcb_layer_type_t lyt) +{ + const int clrs = sizeof(conf_core.appearance.color.layer) / sizeof(conf_core.appearance.color.layer[0]); + + if (lyt & PCB_LYT_MASK) + return &conf_core.appearance.color.mask; + if (lyt & PCB_LYT_PASTE) + return &conf_core.appearance.color.paste; + if (lyt & PCB_LYT_SILK) + return &conf_core.appearance.color.element; + + return &conf_core.appearance.color.layer[idx % clrs]; +} + +/* Initialize a new layer with safe initial values */ +static void layer_init(pcb_board_t *pcb, pcb_layer_t *lp, pcb_layer_id_t idx, pcb_layergrp_id_t gid, pcb_data_t *parent) +{ + memset(lp, 0, sizeof(pcb_layer_t)); + lp->meta.real.grp = gid; + lp->meta.real.vis = 1; + lp->name = pcb_strdup("New Layer"); + lp->meta.real.color = *pcb_layer_default_color(idx, (gid >= 0) ? pcb->LayerGroups.grp[gid].ltype : 0); + if ((gid >= 0) && (pcb->LayerGroups.grp[gid].len == 0)) { /*When adding the first layer in a group, set up comb flags automatically */ + switch((pcb->LayerGroups.grp[gid].ltype) & PCB_LYT_ANYTHING) { + case PCB_LYT_MASK: lp->comb = PCB_LYC_AUTO | PCB_LYC_SUB; break; + case PCB_LYT_SILK: lp->comb = PCB_LYC_AUTO; + case PCB_LYT_PASTE: lp->comb = PCB_LYC_AUTO; + default: break; + } + } + lp->parent.data = parent; + lp->parent_type = PCB_PARENT_DATA; + lp->type = PCB_OBJ_LAYER; +} + +int pcb_layer_move(pcb_board_t *pcb, pcb_layer_id_t old_index, pcb_layer_id_t new_index, pcb_layergrp_id_t new_in_grp) +{ + pcb_layer_id_t l, at = -1; + + /* sanity checks */ + if (old_index < -1 || old_index >= pcb->Data->LayerN) { + pcb_message(PCB_MSG_ERROR, "Invalid old layer %d for move: must be -1..%d\n", old_index, pcb->Data->LayerN - 1); + return 1; + } + + if (new_index < -1 || new_index > pcb->Data->LayerN || new_index >= PCB_MAX_LAYER) { + pcb_message(PCB_MSG_ERROR, "Invalid new layer %d for move: must be -1..%d\n", new_index, pcb->Data->LayerN); + return 1; + } + + if (new_index == -1 && is_last_top_copper_layer(pcb, old_index)) { + pcb_hid_message_box("warning", "Layer delete", "You can't delete the last top-side layer\n", "cancel", 0, NULL); + return 1; + } + + if (new_index == -1 && is_last_bottom_copper_layer(pcb, old_index)) { + pcb_hid_message_box("warning", "Layer delete", "You can't delete the last bottom-side layer\n", "cancel", 0, NULL); + return 1; + } + + + if (old_index == -1) { /* append new layer at the end of the logical layer list, put it in the current group */ + pcb_layergrp_t *g; + pcb_layer_t *lp; + pcb_layer_id_t new_lid = pcb->Data->LayerN++; + int grp_idx; + + lp = &pcb->Data->Layer[new_lid]; + if (new_in_grp >= 0) + layer_init(pcb, lp, new_lid, new_in_grp, pcb->Data); + else + layer_init(pcb, lp, new_lid, pcb->Data->Layer[new_index].meta.real.grp, pcb->Data); + + g = pcb_get_layergrp(pcb, lp->meta.real.grp); + + if (new_in_grp >= 0) { + if (new_index == 0) + grp_idx = 0; + else + grp_idx = g->len; + } + else + grp_idx = pcb_layergrp_index_in_grp(g, new_index); + + /* shift group members up and insert the new group */ + if ((g->len > grp_idx) && (grp_idx >= 0)) + memmove(g->lid+grp_idx+1, g->lid+grp_idx, (g->len - grp_idx) * sizeof(pcb_layer_id_t)); + if (grp_idx < 0) + grp_idx = 0; + g->lid[grp_idx] = new_lid; + g->len++; + pcb_event(PCB_EVENT_LAYERS_CHANGED, NULL); + pcb_layervis_change_group_vis(new_lid, 1, 1); + pcb_event(PCB_EVENT_LAYERVIS_CHANGED, NULL); + at = new_lid; + } + else if (new_index == -1) { /* Delete the layer at old_index */ + pcb_layergrp_id_t gid; + pcb_layergrp_t *g; + int grp_idx, remaining; + + /* remove the current lid from its group */ + g = pcb_get_layergrp(pcb, pcb->Data->Layer[old_index].meta.real.grp); + grp_idx = pcb_layergrp_index_in_grp(g, old_index); + if (grp_idx < 0) { + pcb_message(PCB_MSG_ERROR, "Internal error; layer not in group\n"); + return -1; + } + + pcb_layer_free_fields(&pcb->Data->Layer[old_index]); + + remaining = (g->len - grp_idx - 1); + if (remaining > 0) + memmove(g->lid+grp_idx, g->lid+grp_idx+1, remaining * sizeof(pcb_layer_id_t)); + g->len--; + + /* update lids in all groups (shifting down idx) */ + for(gid = 0; gid < pcb_max_group(pcb); gid++) { + int n; + g = &pcb->LayerGroups.grp[gid]; + for(n = 0; n < g->len; n++) + if (g->lid[n] > old_index) + g->lid[n]--; + } + + /* update visibility */ + for(l = old_index; l < pcb->Data->LayerN-1; l++) { + pcb_layer_move_(&pcb->Data->Layer[l], &pcb->Data->Layer[l+1]); + layer_clear(&pcb->Data->Layer[l+1]); + } + + for (l = 0; l < pcb->Data->LayerN; l++) + if (pcb_layer_stack[l] == old_index) + memmove(pcb_layer_stack + l, pcb_layer_stack + l + 1, (pcb->Data->LayerN - l - 1) * sizeof(pcb_layer_stack[0])); + + /* remove layer from the logical layer array */ + pcb_max_layer--; + for (l = 0; l < pcb->Data->LayerN; l++) + if (pcb_layer_stack[l] > old_index) + pcb_layer_stack[l]--; + + pcb_event(PCB_EVENT_LAYERS_CHANGED, NULL); + } + else { + pcb_message(PCB_MSG_ERROR, "Logical layer move is not supported any more. This function should have not been called. Please report this error.\n"); + /* Removed r8686: + The new layer design presents the layers by groups to preserve physical + order. In this system the index of the logical layer on the logical + layer list is insignificant, thus we shouldn't try to change it. */ + } + + if (at >= 0) { + pcb_undo_add_layer_move(old_index, new_index, at); + pcb_undo_inc_serial(); + } + else + pcb_message(PCB_MSG_WARNING, "this operation is not undoable.\n"); + + return 0; +} + +const char *pcb_layer_name(pcb_data_t *data, pcb_layer_id_t id) +{ + if (id < 0) + return NULL; + if (id < data->LayerN) + return data->Layer[id].name; + if ((id >= PCB_LAYER_VIRT_MIN) && (id <= PCB_LAYER_VIRT_MAX)) + return pcb_virt_layers[id-PCB_LAYER_VIRT_MIN].name; + return NULL; +} + +pcb_layer_t *pcb_get_layer(pcb_data_t *data, pcb_layer_id_t id) +{ + if ((id >= 0) && (id < data->LayerN)) + return &data->Layer[id]; + if (id & PCB_LYT_UI) + return pcb_uilayer_get(id); + return NULL; +} + +pcb_layer_id_t pcb_layer_str2id(pcb_data_t *data, const char *str) +{ + char *end; + pcb_layer_id_t id; + if (*str == '#') { + id = strtol(str+1, &end, 10); + if ((*end == '\0') && (id >= 0) && (id < data->LayerN)) + return id; + } +TODO("layer: do the same that cam does; test with propedit"); + return -1; +} + + +void pcb_layer_link_trees(pcb_layer_t *dst, pcb_layer_t *src) +{ + /* we can't link non-existing trees - make sure src does have the trees initialized */ + if (src->line_tree == NULL) src->line_tree = pcb_r_create_tree(); + if (src->arc_tree == NULL) src->arc_tree = pcb_r_create_tree(); + if (src->text_tree == NULL) src->text_tree = pcb_r_create_tree(); + if (src->polygon_tree == NULL) src->polygon_tree = pcb_r_create_tree(); + + dst->line_tree = src->line_tree; + dst->arc_tree = src->arc_tree; + dst->text_tree = src->text_tree; + dst->polygon_tree = src->polygon_tree; +} + + +void pcb_layer_real2bound_offs(pcb_layer_t *dst, pcb_board_t *src_pcb, pcb_layer_t *src) +{ + dst->meta.bound.real = NULL; + dst->is_bound = 1; + if ((dst->meta.bound.type & PCB_LYT_INTERN) && (dst->meta.bound.type & PCB_LYT_COPPER)) { + int from_top, from_bottom, res; + pcb_layergrp_t *tcop = pcb_get_grp(&src_pcb->LayerGroups, PCB_LYT_TOP, PCB_LYT_COPPER); + pcb_layergrp_t *bcop = pcb_get_grp(&src_pcb->LayerGroups, PCB_LYT_BOTTOM, PCB_LYT_COPPER); + pcb_layergrp_id_t tcop_id = pcb_layergrp_id(src_pcb, tcop); + pcb_layergrp_id_t bcop_id = pcb_layergrp_id(src_pcb, bcop); + + res = pcb_layergrp_dist(src_pcb, src->meta.real.grp, tcop_id, PCB_LYT_COPPER, &from_top); + res |= pcb_layergrp_dist(src_pcb, src->meta.real.grp, bcop_id, PCB_LYT_COPPER, &from_bottom); + if (res == 0) { + if (from_top <= from_bottom) + dst->meta.bound.stack_offs = from_top; + else + dst->meta.bound.stack_offs = -from_bottom; + } + else + pcb_message(PCB_MSG_ERROR, "Internal error: can't figure the inter copper\nlayer offset for %s\n", src->name); + } + else + dst->meta.bound.stack_offs = 0; +} + +void pcb_layer_real2bound(pcb_layer_t *dst, pcb_layer_t *src, int share_rtrees) +{ + pcb_board_t *pcb; + pcb_layergrp_t *grp; + + assert(!src->is_bound); + + pcb = pcb_layer_get_top(src); + grp = pcb_get_layergrp(pcb, src->meta.real.grp); + dst->comb = src->comb; + + dst->meta.bound.type = pcb_layergrp_flags(pcb, src->meta.real.grp); + if (src->name != NULL) + dst->name = pcb_strdup(src->name); + else + dst->name = NULL; + + if ((grp != NULL) && (grp->purpose != NULL)) + dst->meta.bound.purpose = pcb_strdup(grp->purpose); + else + dst->meta.bound.purpose = NULL; + + pcb_layer_real2bound_offs(dst, pcb, src); + + if (!src->is_bound) { + dst->meta.bound.real = src; + if (share_rtrees) + pcb_layer_link_trees(dst, src); + } +} + +static int strcmp_score(const char *s1, const char *s2) +{ + int score = 0; + + if (s1 == s2) /* mainly for NULL = NULL */ + score += 4; + + if ((s1 != NULL) && (s2 != NULL)) { + if (strcmp(s1, s2) == 0) + score += 4; + else if (pcb_strcasecmp(s1, s2) == 0) + score += 2; + } + + return score; +} + +void pcb_layer_resolve_best(pcb_board_t *pcb, pcb_layergrp_t *grp, pcb_layer_t *src, int *best_score, pcb_layer_t **best) +{ + int l, score; + + for(l = 0; l < grp->len; l++) { + pcb_layer_t *ly = pcb_get_layer(pcb->Data, grp->lid[l]); + if ((ly->comb & PCB_LYC_SUB) == (src->comb & PCB_LYC_SUB)) { + score = 1; + if (ly->comb == src->comb) + score++; + + score += strcmp_score(ly->name, src->name); + score += strcmp_score(grp->purpose, src->meta.bound.purpose); + + if (score > *best_score) { + *best = ly; + *best_score = score; + } + } + } +} + +pcb_layer_t *pcb_layer_resolve_binding(pcb_board_t *pcb, pcb_layer_t *src) +{ + pcb_layergrp_id_t gid; + pcb_layergrp_t *grp; + int best_score = 0; + pcb_layer_t *best = NULL; + + + assert(src->is_bound); + + /* look up the layer group; for internal copper this means counting the offset */ + if ((src->meta.bound.type & PCB_LYT_INTERN) && (src->meta.bound.type & PCB_LYT_COPPER) && (src->meta.bound.stack_offs != 0)) { + if (src->meta.bound.stack_offs < 0) + gid = pcb_layergrp_get_bottom_copper(); + else + gid = pcb_layergrp_get_top_copper(); + gid = pcb_layergrp_step(pcb, gid, src->meta.bound.stack_offs, PCB_LYT_COPPER | PCB_LYT_INTERN); + /* target group identified; pick the closest match layer within that group */ + grp = pcb->LayerGroups.grp+gid; + pcb_layer_resolve_best(pcb, grp, src, &best_score, &best); + } + else { + pcb_layer_type_t lyt = src->meta.bound.type; + if ((lyt & PCB_LYT_BOUNDARY) && (lyt & PCB_LYT_ANYWHERE)) { + lyt = PCB_LYT_BOUNDARY; + pcb_message(PCB_MSG_WARNING, "Ignoring invalid layer flag combination for %s: boundary layer must be global\n(fixed up by removing location specifier bits)\n", src->name); + } + for(gid = 0, grp = pcb->LayerGroups.grp; gid < pcb->LayerGroups.len; gid++,grp++) + if ((grp->ltype & lyt) == lyt) + pcb_layer_resolve_best(pcb, grp, src, &best_score, &best); + } + + return best; +} + +pcb_layer_t *pcb_layer_new_bound(pcb_data_t *data, pcb_layer_type_t type, const char *name, const char *purpose) +{ + pcb_layer_t *lay = &data->Layer[data->LayerN++]; + + memset(lay, 0, sizeof(pcb_layer_t)); + lay->is_bound = 1; + lay->name = pcb_strdup(name); + lay->meta.bound.type = type; + if (purpose == NULL) + lay->meta.bound.purpose = NULL; + else + lay->meta.bound.purpose = pcb_strdup(purpose); + lay->parent.data = data; + lay->parent_type = PCB_PARENT_DATA; + lay->type = PCB_OBJ_LAYER; + return lay; +} + +unsigned int pcb_layer_hash_bound(pcb_layer_t *ly, pcb_bool smirror) +{ + unsigned int hash; + pcb_layer_type_t lyt; + int offs; + + assert(ly->is_bound); + + lyt = ly->meta.bound.type; + offs = ly->meta.bound.stack_offs; + + if (smirror) { + lyt = pcb_layer_mirror_type(lyt); + offs = -offs; + } + + hash = (unsigned long)arclist_length(&ly->Arc); + hash ^= (unsigned long)linelist_length(&ly->Line); + hash ^= (unsigned long)textlist_length(&ly->Text); + hash ^= (unsigned long)polylist_length(&ly->Polygon); + hash ^= (unsigned long)ly->comb ^ (unsigned long)lyt; + + if (ly->meta.bound.type & PCB_LYT_INTERN) + hash ^= (unsigned int)offs; + + return hash; +} + +pcb_layer_type_t pcb_layer_mirror_type(pcb_layer_type_t lyt) +{ + if (lyt & PCB_LYT_TOP) + return (lyt & ~PCB_LYT_TOP) | PCB_LYT_BOTTOM; + else if (lyt & PCB_LYT_BOTTOM) + return (lyt & ~PCB_LYT_BOTTOM) | PCB_LYT_TOP; + return lyt; +} + +int pcb_layer_type_map(pcb_layer_type_t type, void *ctx, void (*cb)(void *ctx, pcb_layer_type_t bit, const char *name, int class, const char *class_name)) +{ + const pcb_layer_type_name_t *n; + int found = 0; + for(n = pcb_layer_type_names; n->name != NULL; n++) { + if (type & n->type) { + cb(ctx, n->type, n->name, n->class, pcb_layer_type_class_names[n->class]); + found++; + } + } + return found; +} + +int pcb_layer_comb_map(pcb_layer_combining_t type, void *ctx, void (*cb)(void *ctx, pcb_layer_combining_t bit, const char *name)) +{ + const pcb_layer_type_name_t *n; + int found = 0; + for(n = pcb_layer_comb_names; n->name != NULL; n++) { + if (type & n->type) { + cb(ctx, n->type, n->name); + found++; + } + } + return found; +} + + +pcb_layer_type_t pcb_layer_type_str2bit(const char *name) +{ + const pcb_layer_type_name_t *n; + for(n = pcb_layer_type_names; n->name != NULL; n++) + if (strcmp(n->name, name) == 0) + return n->type; + return 0; +} + +const char *pcb_layer_type_bit2str(pcb_layer_type_t type) +{ + const pcb_layer_type_name_t *n; + for(n = pcb_layer_type_names; n->name != NULL; n++) + if (type & n->type) + return n->name; + return 0; +} + +pcb_layer_combining_t pcb_layer_comb_str2bit(const char *name) +{ + const pcb_layer_type_name_t *n; + for(n = pcb_layer_comb_names; n->name != NULL; n++) + if (strcmp(n->name, name) == 0) + return n->type; + return 0; +} + +void pcb_layer_auto_fixup(pcb_board_t *pcb) +{ + pcb_layer_id_t n; + + /* old silk layers are always auto */ + for(n = 0; n < pcb->Data->LayerN; n++) + if (pcb_layer_flags(pcb, n) & PCB_LYT_SILK) + pcb->Data->Layer[n].comb |= PCB_LYC_AUTO; +} + +int pcb_layer_gui_set_vlayer(pcb_board_t *pcb, pcb_virtual_layer_t vid, int is_empty, pcb_xform_t **xform) +{ + pcb_virt_layer_t *v = &pcb_virt_layers[vid]; + assert((vid >= 0) && (vid < PCB_VLY_end)); + + /* if there's no GUI, that means no draw should be done */ + if (pcb_gui == NULL) + return 0; + + if (xform != NULL) + *xform = NULL; + +TODO("layer: need to pass the flags of the group, not the flags of the layer once we have a group for each layer") + if (pcb_gui->set_layer_group != NULL) { + pcb_layergrp_id_t grp; + pcb_layer_id_t lid = v->new_id; + grp = pcb_layer_get_group(pcb, lid); + return pcb_gui->set_layer_group(grp, v->purpose, v->purpi, lid, v->type, is_empty, xform); + } + + /* if the GUI doesn't have a set_layer, assume it wants to draw all layers */ + return 1; +} + +int pcb_layer_gui_set_g_ui(pcb_layer_t *first, int is_empty, pcb_xform_t **xform) +{ + /* if there's no GUI, that means no draw should be done */ + if (pcb_gui == NULL) + return 0; + + if (xform != NULL) + *xform = NULL; + + if (pcb_gui->set_layer_group != NULL) + return pcb_gui->set_layer_group(-1, NULL, -1, pcb_layer_id(first->parent.data, first), PCB_LYT_VIRTUAL | PCB_LYT_UI, is_empty, xform); + + /* if the GUI doesn't have a set_layer, assume it wants to draw all layers */ + return 1; +} + +void pcb_layer_edit_attrib(pcb_layer_t *layer) +{ + char *buf = pcb_strdup_printf("Layer %s Attributes", layer->name); + pcb_gui->edit_attributes(buf, &(layer->Attributes)); + free(buf); +} + +const pcb_menu_layers_t *pcb_menu_layer_find(const char *name_or_abbrev) +{ + const pcb_menu_layers_t *ml; + + for(ml = pcb_menu_layers; ml->name != NULL; ml++) + if (pcb_strcasecmp(name_or_abbrev, ml->abbrev) == 0) + return ml; + + for(ml = pcb_menu_layers; ml->name != NULL; ml++) + if (pcb_strcasecmp(name_or_abbrev, ml->name) == 0) + return ml; + + return NULL; +} + + +static pcb_layer_id_t pcb_layer_get_cached(pcb_board_t *pcb, pcb_layer_id_t *cache, unsigned int loc, unsigned int typ) +{ + pcb_layergrp_t *g; + + if (*cache < pcb->Data->LayerN) { /* check if the cache is still pointing to the right layer */ + pcb_layergrp_id_t gid = pcb->Data->Layer[*cache].meta.real.grp; + if ((gid >= 0) && (gid < pcb->LayerGroups.len)) { + g = &(pcb->LayerGroups.grp[gid]); + if ((g->ltype & loc) && (g->ltype & typ) && (g->lid[0] == *cache)) + return *cache; + } + } + + /* nope: need to resolve it again */ + g = pcb_get_grp(&pcb->LayerGroups, loc, typ); + if ((g == NULL) || (g->len == 0)) { + *cache = -1; + return -1; + } + *cache = g->lid[0]; + return *cache; +} + +pcb_layer_id_t pcb_layer_get_bottom_silk(void) +{ + static pcb_layer_id_t cache = -1; + pcb_layer_id_t id = pcb_layer_get_cached(PCB, &cache, PCB_LYT_BOTTOM, PCB_LYT_SILK); + return id; +} + +pcb_layer_id_t pcb_layer_get_top_silk(void) +{ + static pcb_layer_id_t cache = -1; + pcb_layer_id_t id = pcb_layer_get_cached(PCB, &cache, PCB_LYT_TOP, PCB_LYT_SILK); + return id; +} Index: tags/2.1.2/src/layer.h =================================================================== --- tags/2.1.2/src/layer.h (nonexistent) +++ tags/2.1.2/src/layer.h (revision 24813) @@ -0,0 +1,373 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996,2006 Thomas Nau + * Copyright (C) 2016 Tibor 'Igor2' Palinkas (pcb-rnd extensions) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +#ifndef PCB_LAYER_H +#define PCB_LAYER_H + +/* Layer type bitfield */ +typedef enum { + /* Stack-up (vertical position): */ + PCB_LYT_TOP = 0x00000001, /* layer is on the top side of the board */ + PCB_LYT_BOTTOM = 0x00000002, /* layer is on the bottom side of the board */ + PCB_LYT_INTERN = 0x00000004, /* layer is internal */ + PCB_LYT_LOGICAL = 0x00000008, /* does not depend on the layer stackup (typically aux drawing layer) */ + PCB_LYT_ANYWHERE = 0x000000FF, /* MASK: layer is anywhere on the stack */ + + /* What the layer consists of (main type) */ + PCB_LYT_COPPER = 0x00000100, /* copper objects */ + PCB_LYT_SILK = 0x00000200, /* silk objects */ + PCB_LYT_MASK = 0x00000400, /* solder mask */ + PCB_LYT_PASTE = 0x00000800, /* paste */ + PCB_LYT_RAT = 0x00002000, /* (virtual) rats nest (one, not in the stackup) */ + PCB_LYT_INVIS = 0x00004000, /* (virtual) layer is invisible (one, not in the stackup) */ + PCB_LYT_BOUNDARY = 0x00008000, /* physical boundaries of the board (inner and outer): route, cuts, slots, drills */ + PCB_LYT_UI = 0x00080000, /* (virtual) user interface drawings (feature plugins use this for displaying states or debug info) */ + PCB_LYT_SUBSTRATE= 0x00200000, /* substrate / insulator */ + PCB_LYT_MISC = 0x00400000, /* misc (for internal use) */ + PCB_LYT_DIALOG = 0x00800000, /* (virtual) dialog box drawings (e.g. font selector) - not to be interpreted in the board space */ + PCB_LYT_DOC = 0x01000000, /* misc documentation layers - user allocated, largely ignored by the code */ + PCB_LYT_MECH = 0x02000000, /* misc mechanical/physical layers (e.g. adhesive, keepouts) */ + PCB_LYT_ANYTHING = 0x0FFFFF00, /* MASK: layers consist anything */ + + /* misc properties */ + PCB_LYT_VIRTUAL = 0x10000000, /* the layer is not in the layer array (generated layer) */ + PCB_LYT_NOEXPORT = 0x20000000, /* should not show up in any of the exports */ + PCB_LYT_ANYPROP = 0x70000000 /* MASK: misc layer properties */ +} pcb_layer_type_t; + + +typedef enum { + PCB_VLY_INVISIBLE, + PCB_VLY_RATS, + PCB_VLY_TOP_ASSY, + PCB_VLY_BOTTOM_ASSY, + PCB_VLY_FAB, + PCB_VLY_PLATED_DRILL, + PCB_VLY_UNPLATED_DRILL, + PCB_VLY_CSECT, + + /* for determining the range, do not use */ + PCB_VLY_end, + PCB_VLY_first = PCB_VLY_INVISIBLE +} pcb_virtual_layer_t; + +typedef enum { /* bitfield */ + PCB_LYC_SUB = 1, /* bit 0 is 0 for add or 1 for sub */ + PCB_LYC_AUTO = 2 /* bit 1 is 0 for manual drawn layer or 1 for side-effect objects from padstacks; this is how the user controls on which composite mask/paste layer padstack side effects should appear */ +} pcb_layer_combining_t; + +#define PCB_LAYER_IN_STACK(lyt) (((lyt) & PCB_LYT_COPPER) || ((lyt) & PCB_LYT_SILK) || ((lyt) & PCB_LYT_MASK) || ((lyt) & PCB_LYT_PASTE) || ((lyt) & PCB_LYT_SUBSTRATE)) +#define PCB_LAYER_SIDED(lyt) (((lyt) & PCB_LYT_COPPER) || ((lyt) & PCB_LYT_SILK) || ((lyt) & PCB_LYT_MASK) || ((lyt) & PCB_LYT_PASTE) || ((lyt) & PCB_LYT_DOC)) + +#define PCB_LAYER_IS_ASSY(lyt, purpi) (((lyt) & PCB_LYT_VIRTUAL) && ((purpi) == F_assy)) +#define PCB_LAYER_IS_FAB(lyt, purpi) (((lyt) & PCB_LYT_VIRTUAL) && ((purpi) == F_fab)) +#define PCB_LAYER_IS_CSECT(lyt, purpi) (((lyt) & PCB_LYT_VIRTUAL) && ((purpi) == F_csect)) +#define PCB_LAYER_IS_PDRILL(lyt, purpi) (((lyt) & PCB_LYT_VIRTUAL) && ((purpi) == F_pdrill)) +#define PCB_LAYER_IS_UDRILL(lyt, purpi) (((lyt) & PCB_LYT_VIRTUAL) && ((purpi) == F_udrill)) +#define PCB_LAYER_IS_DRILL(lyt, purpi) (((lyt) & PCB_LYT_VIRTUAL) && (((purpi) == F_pdrill) || ((purpi) == F_udrill))) + +/* Route must be on a mech or boundary layer */ +#define PCB_LAYER_IS_UROUTE(lyt, purpi) (((lyt) & (PCB_LYT_BOUNDARY | PCB_LYT_MECH)) && ((((purpi) == F_uroute)))) +#define PCB_LAYER_IS_PROUTE(lyt, purpi) (((lyt) & (PCB_LYT_BOUNDARY | PCB_LYT_MECH)) && (((purpi) == F_proute))) +#define PCB_LAYER_IS_ROUTE(lyt, purpi) (((lyt) & (PCB_LYT_BOUNDARY | PCB_LYT_MECH)) && (((purpi) == F_proute) || ((purpi) == F_uroute))) + +/* Outline is a route in a boundary group; outline in this sense + means the "perimeter of the board", but could include largish internal + cutout - the user needs to be explicit about this. Mech layers are NOT + included, that's the difference compared to routed layers */ +#define PCB_LAYER_IS_OUTLINE(lyt, purpi) (((lyt) & PCB_LYT_BOUNDARY) && (((purpi) == F_proute) || ((purpi) == F_uroute))) + +#include "globalconst.h" +#include "global_typedefs.h" +#include "attrib.h" +#include "color.h" +#include "obj_common.h" +#include "obj_arc_list.h" +#include "obj_line_list.h" +#include "obj_poly_list.h" +#include "obj_text_list.h" + +struct pcb_layer_s { /* holds information about one layer */ + PCB_ANY_OBJ_FIELDS; + + linelist_t Line; + textlist_t Text; + polylist_t Polygon; + arclist_t Arc; + + const char *name; /* layer name */ + + pcb_layer_combining_t comb; /* how to combine this layer with other layers in the group */ + + /* for bound layers these point to the board layer's*/ + pcb_rtree_t *line_tree, *text_tree, *polygon_tree, *arc_tree; + + union { + struct { /* A real board layer */ + pcb_layergrp_id_t grp; /* the group this layer is in (cross-reference) */ + pcb_bool vis; /* visible flag */ + pcb_color_t color; /* copied */ + int no_drc; /* whether to ignore the layer when checking the design rules */ + const char *cookie; /* for UI layers: registration cookie; NULL for unused UI layers */ + pcb_xform_t xform; /* layer specified rendering transformation */ + } real; + struct { /* A subcircuit layer binding; list data are local but everything else is coming from board layers */ + pcb_layer_t *real; /* NULL if unbound */ + + /* matching rules */ + pcb_layer_type_t type; + /* for comb, use the ->comb from the common part */ + int stack_offs; /* offset in the stack for PCB_LYT_INNER: positive is counted from primary side, negative from the opposite side */ + char *purpose; /* what the target doc/mech layer is used for */ + + unsigned user_specified:1; /* 1 if the user forced the binding */ + pcb_layer_id_t user_lid; + } bound; + } meta; + + unsigned is_bound:1; +}; + +/* returns the layer number for the passed copper or silk layer pointer */ +pcb_layer_id_t pcb_layer_id(const pcb_data_t *Data, const pcb_layer_t *Layer); + + +/* the offsets of the two additional special layers (e.g. silk) for 'component' + and 'solder'. The offset of PCB_MAX_LAYER is not added here. Also can be + used to address side of the board without referencing to groups or layers. */ +typedef enum { + PCB_SOLDER_SIDE = 0, + PCB_COMPONENT_SIDE = 1 +} pcb_side_t; + +/* Cached lookup of the first silk layer in the bottom or top group */ +pcb_layer_id_t pcb_layer_get_bottom_silk(void); +pcb_layer_id_t pcb_layer_get_top_silk(void); + +/* Return the board the layer is under */ +#define pcb_layer_get_top(layer) pcb_data_get_top((layer)->parent.data) + +typedef struct { + const char *name, *abbrev; + pcb_color_t const *force_color; + const char *select_name; + int vis_offs, sel_offs; +} pcb_menu_layers_t; + +extern const pcb_menu_layers_t pcb_menu_layers[]; + +const pcb_menu_layers_t *pcb_menu_layer_find(const char *name_or_abbrev); + +/************ OLD API - new code should not use these **************/ + +#define LAYER_ON_STACK(n) (&PCB->Data->Layer[pcb_layer_stack[(n)]]) +#define LAYER_PTR(n) (&PCB->Data->Layer[(n)]) +#define CURRENT (LAYER_ON_STACK(0)) +#define INDEXOFCURRENT (pcb_layer_stack[0]) + +#define LAYER_LOOP(data, ml) do { \ + pcb_cardinal_t n; \ + for (n = 0; n < ml; n++) \ + { \ + pcb_layer_t *layer = (&data->Layer[(n)]); + +/************ NEW API - new code should use these **************/ + +/* Free all metadata and objects of a layer; does not free(layer) */ +void pcb_layer_free_fields(pcb_layer_t *layer); + +/* Return the layer pointer (or NULL on invalid or virtual layers) for an id */ +pcb_layer_t *pcb_get_layer(pcb_data_t *data, pcb_layer_id_t id); + +/* Return the name of a layer (real or virtual) or NULL on error + NOTE: layer names may not be unique; returns the first case sensitive hit; + slow linear search */ +pcb_layer_id_t pcb_layer_by_name(pcb_data_t *data, const char *name); + +/* Returns pcb_true if the given layer is empty (there are no objects on the layer) */ +pcb_bool pcb_layer_is_empty_(pcb_board_t *pcb, pcb_layer_t *ly); +pcb_bool pcb_layer_is_empty(pcb_board_t *pcb, pcb_layer_id_t ly); + +/* Returns pcb_true if the given layer is empty - non-recursive variant (doesn't deal with side effects) */ +pcb_bool pcb_layer_is_pure_empty(pcb_layer_t *layer); + + +/* call the gui to set a virtual layer or the UI layer group */ +int pcb_layer_gui_set_vlayer(pcb_board_t *pcb, pcb_virtual_layer_t vid, int is_empty, pcb_xform_t **xform); +int pcb_layer_gui_set_g_ui(pcb_layer_t *first, int is_empty, pcb_xform_t **xform); + + +/* returns a bitfield of pcb_layer_type_t; returns 0 if layer_idx or layer is invalid. */ +unsigned int pcb_layer_flags(const pcb_board_t *pcb, pcb_layer_id_t layer_idx); +unsigned int pcb_layer_flags_(const pcb_layer_t *layer); + +/* Return the purpi of the group of a layer; if out is not NULL, also copy + a pointer to the purpose string there (valid until a layer change) */ +int pcb_layer_purpose(const pcb_board_t *pcb, pcb_layer_id_t layer_idx, const char **out); +int pcb_layer_purpose_(const pcb_layer_t *layer, const char **out); + + +/* map bits of a layer type (call cb for each bit set); return number of bits + found. */ +int pcb_layer_type_map(pcb_layer_type_t type, void *ctx, void (*cb)(void *ctx, pcb_layer_type_t bit, const char *name, int class, const char *class_name)); +int pcb_layer_comb_map(pcb_layer_combining_t type, void *ctx, void (*cb)(void *ctx, pcb_layer_combining_t bit, const char *name)); + +/* return 0 or the flag value correspoding to name (linear search) */ +pcb_layer_type_t pcb_layer_type_str2bit(const char *name); +pcb_layer_combining_t pcb_layer_comb_str2bit(const char *name); + +/* return the name of a type bit; type should have only one bit set */ +const char *pcb_layer_type_bit2str(pcb_layer_type_t type); + +/* Various fixes for old/plain/flat layer stack imports vs. composite layers */ +void pcb_layer_auto_fixup(pcb_board_t *pcb); + +/* List layer IDs that matches mask - write the first res_len items in res, + if res is not NULL. Returns: + - the total number of layers matching the query, if res is NULL + - the number of layers copied into res if res is not NULL + The plain version require exact match (look for a specific layer), + the _any version allows partial match so work with PCB_LYT_ANY*. + The version that ends in 'p' also matches purpose if purpi is not -1 + and/or purpose is not NULL. +*/ +int pcb_layer_list(const pcb_board_t *pcb, pcb_layer_type_t mask, pcb_layer_id_t *res, int res_len); +int pcb_layer_list_any(const pcb_board_t *pcb, pcb_layer_type_t mask, pcb_layer_id_t *res, int res_len); +int pcb_layer_listp(const pcb_board_t *pcb, pcb_layer_type_t mask, pcb_layer_id_t *res, int res_len, int purpi, const char *purpose); + + +/**** layer creation (for load/import code) ****/ + +/* Reset layers and layer groups to empty */ +void pcb_layers_reset(pcb_board_t *pcb); + +/* Create a new layer and put it in an existing group (if grp is not -1). */ +pcb_layer_id_t pcb_layer_create(pcb_board_t *pcb, pcb_layergrp_id_t grp, const char *lname); + +/* Return the name of a layer (resolving the true name of virtual layers too) */ +const char *pcb_layer_name(pcb_data_t *data, pcb_layer_id_t id); + +/* Return the default color for a new layer from the config */ +const pcb_color_t *pcb_layer_default_color(int idx, pcb_layer_type_t lyt); + +/* Rename/recolor an existing layer by idx */ +int pcb_layer_rename(pcb_data_t *data, pcb_layer_id_t layer, const char *lname); +int pcb_layer_recolor(pcb_data_t *data, pcb_layer_id_t layer, const char *lcolor); + +/* changes the color of a layer; string has to be allocated by the caller (pcb_strdup) */ +int pcb_layer_rename_(pcb_layer_t *Layer, char *Name); + +/* Low level layer color change, parsed color must be available */ +int pcb_layer_recolor_(pcb_layer_t *Layer, const pcb_color_t *color); + +/* index is 0..PCB_MAX_LAYER-1. If old_index is -1, a new layer is + inserted at that index. If new_index is -1, the specified layer is + deleted. Returns non-zero on error, zero if OK. */ +int pcb_layer_move(pcb_board_t *pcb, pcb_layer_id_t old_index, pcb_layer_id_t new_index, pcb_layergrp_id_t new_in_grp); + + +/* set up dst to be a bound layer with the right offset in the stack; src_pcb + is used for the layer stack of src. Assumes other fields of dst, e.g. name, + are all set up. */ +void pcb_layer_real2bound_offs(pcb_layer_t *dst, pcb_board_t *src_pcb, pcb_layer_t *src); + +/* Set up dst so that it's a non-real layer bound to src */ +void pcb_layer_real2bound(pcb_layer_t *dst, pcb_layer_t *src, int share_rtrees); + +/* Assume src is a bound layer; find the closest match in pcb's layer stack */ +pcb_layer_t *pcb_layer_resolve_binding(pcb_board_t *pcb, pcb_layer_t *src); + +/* Allocate a new bound layer within data, set it up, but do not do the binding */ +pcb_layer_t *pcb_layer_new_bound(pcb_data_t *data, pcb_layer_type_t type, const char *name, const char *purpose); + +/* Calculate a hash of a bound layer (ingoring its name) */ +unsigned int pcb_layer_hash_bound(pcb_layer_t *ly, pcb_bool smirror); + +/* Calculate mirrored version of some (bound) layer properties */ +pcb_layer_type_t pcb_layer_mirror_type(pcb_layer_type_t lyt); + + +/* Modify tree pointers in dst to point to src's; allocates trees for src if they are not yet allocated */ +void pcb_layer_link_trees(pcb_layer_t *dst, pcb_layer_t *src); + +/* Open the attribute editor for a layer */ +void pcb_layer_edit_attrib(pcb_layer_t *layer); + +/* Convert a textual layer reference into a layer ID. The text is either + #id or a layer name. */ +pcb_layer_id_t pcb_layer_str2id(pcb_data_t *data, const char *str); + +/* How deep subcs can be nested */ +#define PCB_MAX_BOUND_LAYER_RECURSION 128 + +/* Return the real layer, resolving layer bindings. Returns NULL on + error (e.g. binding loop) */ +PCB_INLINE pcb_layer_t *pcb_layer_get_real(const pcb_layer_t *layer) +{ + int rec = 0; + + while(layer->is_bound) { + layer = layer->meta.bound.real; + rec++; + if ((rec > PCB_MAX_BOUND_LAYER_RECURSION) || (layer == NULL)) + return NULL; + } + return (pcb_layer_t *)layer; +} + +/* list of virtual layers: these are generated by the draw code but do not + have a real layer in the array */ +typedef struct pcb_virt_layer_s { + char *name; + pcb_layer_id_t new_id; + pcb_layer_type_t type; + const char *purpose; + int purpi; +} pcb_virt_layer_t; + +extern pcb_virt_layer_t pcb_virt_layers[]; + +/* Return the first virtual layer that fully matches mask */ +const pcb_virt_layer_t *pcb_vlayer_get_first(pcb_layer_type_t mask, const char *purpose, int purpi); + +/* Returns whether the given unsigned int layer flags corresponds to a layer + that's on the visible side of the board at the moment. */ +#define PCB_LAYERFLG_ON_VISIBLE_SIDE(uint_flags) \ + (!!(conf_core.editor.show_solder_side ? ((uint_flags) & PCB_LYT_BOTTOM) : ((uint_flags) & PCB_LYT_TOP))) + +#define PCB_LYT_VISIBLE_SIDE() \ + ((conf_core.editor.show_solder_side ? PCB_LYT_BOTTOM : PCB_LYT_TOP)) + +#define PCB_LYT_INVISIBLE_SIDE() \ + ((conf_core.editor.show_solder_side ? PCB_LYT_TOP : PCB_LYT_BOTTOM)) + +/*** For internal use ***/ +void pcb_layer_move_(pcb_layer_t *dst, pcb_layer_t *src); + +#endif Index: tags/2.1.2/src/layer_grp.c =================================================================== --- tags/2.1.2/src/layer_grp.c (nonexistent) +++ tags/2.1.2/src/layer_grp.c (revision 24813) @@ -0,0 +1,1283 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996,2004,2006 Thomas Nau + * Copyright (C) 2016 Tibor 'Igor2' Palinkas (pcb-rnd extensions) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +#include "config.h" +#include "board.h" +#include "data.h" +#include "layer_grp.h" +#include "compat_misc.h" +#include "event.h" +#include "funchash.h" +#include "funchash_core.h" + +/* notify the rest of the code after layer group changes so that the GUI + and other parts sync up */ +static int inhibit_notify = 0; +#define NOTIFY(pcb) \ +do { \ + pcb->LayerGroups.cache.copper_valid = 0; \ + if (!inhibit_notify) { \ + pcb_event(PCB_EVENT_LAYERS_CHANGED, NULL); \ + if ((pcb_gui != NULL) && (pcb_exporter == NULL)) \ + pcb_gui->invalidate_all(); \ + pcb_board_set_changed_flag(pcb_true); \ + } \ +} while(0) + +void pcb_layergrp_inhibit_inc(void) +{ + inhibit_notify++; +} + +void pcb_layergrp_inhibit_dec(void) +{ + inhibit_notify--; +} + +void pcb_layergrp_notify(pcb_board_t *pcb) +{ + NOTIFY(pcb); +} + +pcb_layergrp_id_t pcb_layergrp_id(const pcb_board_t *pcb, const pcb_layergrp_t *grp) +{ + if ((grp >= &pcb->LayerGroups.grp[0]) && (grp < &pcb->LayerGroups.grp[pcb->LayerGroups.len])) + return grp - &pcb->LayerGroups.grp[0]; + return -1; +} + +pcb_layergrp_id_t pcb_layer_get_group_(pcb_layer_t *Layer) +{ + if (!Layer->is_bound) + return Layer->meta.real.grp; + + if (Layer->meta.bound.real == NULL) /* bound layer without a binding */ + return -1; + + return Layer->meta.bound.real->meta.real.grp; +} + +pcb_layergrp_t *pcb_get_layergrp(pcb_board_t *pcb, pcb_layergrp_id_t gid) +{ + if ((gid < 0) || (gid >= pcb->LayerGroups.len)) + return NULL; + return pcb->LayerGroups.grp + gid; +} + + +pcb_layergrp_id_t pcb_layer_get_group(pcb_board_t *pcb, pcb_layer_id_t lid) +{ + if ((lid < 0) || (lid >= pcb->Data->LayerN)) + return -1; + + return pcb_layer_get_group_(&pcb->Data->Layer[lid]); +} + +int pcb_layergrp_del_layer(pcb_board_t *pcb, pcb_layergrp_id_t gid, pcb_layer_id_t lid) +{ + int n; + pcb_layergrp_t *grp; + pcb_layer_t *layer; + + if ((lid < 0) || (lid >= pcb->Data->LayerN)) + return -1; + + layer = pcb->Data->Layer + lid; + if (gid < 0) { + gid = layer->meta.real.grp; + if (gid == -1) + return 0; /* already deleted from groups */ + } + if (gid >= pcb->LayerGroups.len) + return -1; + + grp = &pcb->LayerGroups.grp[gid]; + + if (layer->meta.real.grp != gid) + return -1; + + for(n = 0; n < grp->len; n++) { + if (grp->lid[n] == lid) { + int remain = grp->len - n - 1; + if (remain > 0) + memmove(&grp->lid[n], &grp->lid[n+1], remain * sizeof(pcb_layer_id_t)); + grp->len--; + layer->meta.real.grp = -1; + NOTIFY(pcb); + return 0; + } + } + + + /* also: broken layer group list */ + return -1; +} + +static void make_substrate(pcb_board_t *pcb, pcb_layergrp_t *g) +{ + g->ltype = PCB_LYT_INTERN | PCB_LYT_SUBSTRATE; + g->valid = 1; + g->parent_type = PCB_PARENT_BOARD; + g->parent.board = pcb; + g->type = PCB_OBJ_LAYERGRP; +} + +pcb_layergrp_id_t pcb_layergrp_dup(pcb_board_t *pcb, pcb_layergrp_id_t gid, int auto_substrate) +{ + pcb_layergrp_t *ng, *og = pcb_get_layergrp(pcb, gid); + pcb_layergrp_id_t after; + + if (og == NULL) + return -1; + + inhibit_notify++; + if (auto_substrate && (og->ltype & PCB_LYT_COPPER)&& !(og->ltype & PCB_LYT_BOTTOM)) { + ng = pcb_layergrp_insert_after(pcb, gid); + make_substrate(pcb, ng); + after = ng - pcb->LayerGroups.grp; + } + else + after = gid; + + ng = pcb_layergrp_insert_after(pcb, after); + if (og->name != NULL) + ng->name = pcb_strdup(og->name); + ng->ltype = og->ltype; + if (og->purpose != NULL) + ng->purpose = pcb_strdup(og->purpose); + ng->purpi = og->purpi; + ng->valid = ng->open = ng->vis = 1; + ng->parent_type = PCB_PARENT_BOARD; + ng->parent.board = pcb; + ng->type = PCB_OBJ_LAYERGRP; + + inhibit_notify--; + NOTIFY(pcb); + return ng - pcb->LayerGroups.grp; +} + + +pcb_layergrp_id_t pcb_layer_move_to_group(pcb_board_t *pcb, pcb_layer_id_t lid, pcb_layergrp_id_t gid) +{ + if (pcb_layergrp_del_layer(pcb, -1, lid) != 0) + return -1; + pcb_layer_add_in_group(pcb, lid, gid); + pcb_event(PCB_EVENT_LAYER_CHANGED_GRP, "p", &pcb->Data->Layer[lid]); + NOTIFY(pcb); + return gid; +} + +unsigned int pcb_layergrp_flags(const pcb_board_t *pcb, pcb_layergrp_id_t gid) +{ + + if ((gid < 0) || (gid >= pcb->LayerGroups.len)) + return 0; + + return pcb->LayerGroups.grp[gid].ltype; +} + +const char *pcb_layergrp_name(pcb_board_t *pcb, pcb_layergrp_id_t gid) +{ + + if ((gid < 0) || (gid >= pcb->LayerGroups.len)) + return 0; + + return pcb->LayerGroups.grp[gid].name; +} + +pcb_bool pcb_layergrp_is_empty(pcb_board_t *pcb, pcb_layergrp_id_t num) +{ + int i; + pcb_layergrp_t *g = &pcb->LayerGroups.grp[num]; + + /* some layers are never empty */ + if (g->ltype & PCB_LYT_MASK) + return pcb_false; + + if (!pcb_pstk_is_group_empty(pcb, num)) + return pcb_false; + + for (i = 0; i < g->len; i++) + if (!pcb_layer_is_empty(pcb, g->lid[i])) + return pcb_false; + return pcb_true; +} + +pcb_bool pcb_layergrp_is_pure_empty(pcb_board_t *pcb, pcb_layergrp_id_t num) +{ + int i; + pcb_layergrp_t *g = &pcb->LayerGroups.grp[num]; + + for (i = 0; i < g->len; i++) + if (!pcb_layer_is_pure_empty(pcb_get_layer(pcb->Data, g->lid[i]))) + return pcb_false; + return pcb_true; +} + +static void pcb_layergrp_free_fields(pcb_layergrp_t *g) +{ + free(g->name); + free(g->purpose); + g->name = g->purpose = NULL; + g->purpi = -1; +} + + +int pcb_layergrp_free(pcb_board_t *pcb, pcb_layergrp_id_t id) +{ + pcb_layer_stack_t *stack = &pcb->LayerGroups; + if ((id >= 0) && (id < stack->len)) { + int n; + pcb_layergrp_t *g = stack->grp + id; + for(n = 0; n < g->len; n++) { + pcb_layer_t *layer = pcb->Data->Layer + g->lid[n]; + layer->meta.real.grp = -1; + } + pcb_layergrp_free_fields(g); + memset(g, 0, sizeof(pcb_layergrp_t)); + return 0; + } + return -1; +} + +int pcb_layergrp_move_onto(pcb_board_t *pcb, pcb_layergrp_id_t dst, pcb_layergrp_id_t src) +{ + pcb_layer_stack_t *stack = &pcb->LayerGroups; + pcb_layergrp_t *d, *s; + int n; + + if ((src < 0) || (src >= stack->len)) + return -1; + if ((dst < stack->len) && (pcb_layergrp_free(pcb, dst) != 0)) + return -1; + d = stack->grp + dst; + s = stack->grp + src; + memcpy(d, s, sizeof(pcb_layergrp_t)); + + /* update layer's group refs to the new grp */ + for(n = 0; n < d->len; n++) { + pcb_layer_t *layer = pcb->Data->Layer + d->lid[n]; + layer->meta.real.grp = dst; + } + + memset(s, 0, sizeof(pcb_layergrp_t)); + NOTIFY(pcb); + return 0; +} + +static int flush_item(const char *s, const char *start, pcb_layer_id_t *lids, int *lids_len, pcb_layer_type_t *loc) +{ + char *end; + pcb_layer_id_t lid; + switch (*start) { + case 'c': case 'C': case 't': case 'T': *loc = PCB_LYT_TOP; break; + case 's': case 'S': case 'b': case 'B': *loc = PCB_LYT_BOTTOM; break; + default: + lid = strtol(start, &end, 10)-1; + if (end != s) + return -1; + if ((*lids_len) >= PCB_MAX_LAYER) + return -1; + lids[*lids_len] = lid; + (*lids_len)++; + } + return 0; +} + +pcb_layergrp_t *pcb_get_grp(pcb_layer_stack_t *stack, pcb_layer_type_t loc, pcb_layer_type_t typ) +{ + int n; + for(n = 0; n < stack->len; n++) + if ((stack->grp[n].ltype & loc) && (stack->grp[n].ltype & typ)) + return &(stack->grp[n]); + return NULL; +} + +pcb_layergrp_t *pcb_layergrp_insert_after(pcb_board_t *pcb, pcb_layergrp_id_t where) +{ + pcb_layer_stack_t *stack = &pcb->LayerGroups; + int n; + if ((where <= 0) || (where >= stack->len)) + return NULL; + + for(n = stack->len-1; n > where; n--) + pcb_layergrp_move_onto(pcb, n+1, n); + + stack->len++; + NOTIFY(pcb); + return stack->grp+where+1; +} + +static pcb_layergrp_t *pcb_get_grp_new_intern_insert(pcb_board_t *pcb, int room, int bl, int omit_substrate) +{ + pcb_layer_stack_t *stack = &pcb->LayerGroups; + + stack->len += room; + + stack->grp[bl].name = pcb_strdup("Intern"); + stack->grp[bl].ltype = PCB_LYT_INTERN | PCB_LYT_COPPER; + stack->grp[bl].valid = 1; + stack->grp[bl].parent_type = PCB_PARENT_BOARD; + stack->grp[bl].parent.board = pcb; + stack->grp[bl].type = PCB_OBJ_LAYERGRP; + bl++; + if (!omit_substrate) + make_substrate(pcb, &stack->grp[bl]); + return &stack->grp[bl-1]; +} + +static pcb_layergrp_t *pcb_get_grp_new_intern_(pcb_board_t *pcb, int omit_substrate, int force_end) +{ + pcb_layer_stack_t *stack = &pcb->LayerGroups; + int bl, n; + int room = omit_substrate ? 1 : 2; + + if ((stack->len + room) >= PCB_MAX_LAYERGRP) + return NULL; + + /* seek the bottom copper layer */ + if (!force_end) + for(bl = stack->len; bl >= 0; bl--) { + if ((stack->grp[bl].ltype & PCB_LYT_BOTTOM) && (stack->grp[bl].ltype & PCB_LYT_COPPER)) { + + /* insert a new internal layer: move existing layers to make room */ + for(n = stack->len-1; n >= bl; n--) + pcb_layergrp_move_onto(pcb, n+room, n); + + pcb_get_grp_new_intern_insert(pcb, room, bl, omit_substrate); + return &stack->grp[bl]; + } + } + + /* bottom copper did not exist - insert at the end */ + bl = stack->len; + pcb_get_grp_new_intern_insert(pcb, room, bl, omit_substrate); + return &stack->grp[bl]; +} + +pcb_layergrp_t *pcb_get_grp_new_intern(pcb_board_t *pcb, int intern_id) +{ + pcb_layer_stack_t *stack = &pcb->LayerGroups; + pcb_layergrp_t *g; + + if (intern_id > 0) { /* look for existing intern layer first */ + int n; + for(n = 0; n < stack->len; n++) + if (stack->grp[n].intern_id == intern_id) + return &stack->grp[n]; + } + + inhibit_notify++; + g = pcb_get_grp_new_intern_(pcb, 0, 0); + inhibit_notify--; + if (g != NULL) { + g->intern_id = intern_id; + NOTIFY(pcb); + } + return g; +} + +pcb_layergrp_t *pcb_get_grp_new_misc(pcb_board_t *pcb) +{ + pcb_layergrp_t *g; + inhibit_notify++; + g = pcb_get_grp_new_intern_(pcb, 1, 0); + inhibit_notify--; + NOTIFY(pcb); + return g; +} + +pcb_layergrp_t *pcb_get_grp_new_raw(pcb_board_t *pcb) +{ + pcb_layergrp_t *g; + inhibit_notify++; + g = pcb_get_grp_new_intern_insert(pcb, 1, pcb->LayerGroups.len, 1); + inhibit_notify--; + NOTIFY(pcb); + return g; +} + + +/* Move an inclusive block of groups [from..to] by delta on the stack, assuming + target is already cleared and the new hole will be cleared by the caller */ +static void move_grps(pcb_board_t *pcb, pcb_layer_stack_t *stk, pcb_layergrp_id_t from, pcb_layergrp_id_t to, int delta) +{ + int g, remaining, n; + + for(g = from; g <= to; g++) { + for(n = 0; n < stk->grp[g].len; n++) { + pcb_layer_id_t lid =stk->grp[g].lid[n]; + if ((lid >= 0) && (lid < pcb->Data->LayerN)) { + pcb_layer_t *l = &pcb->Data->Layer[lid]; + if (l->meta.real.grp > 0) + l->meta.real.grp += delta; + } + } + } + + remaining = to - from+1; + if (remaining > 0) + memmove(&stk->grp[from + delta], &stk->grp[from], sizeof(pcb_layergrp_t) * remaining); +} + +int pcb_layergrp_index_in_grp(pcb_layergrp_t *grp, pcb_layer_id_t lid) +{ + int idx; + for(idx = 0; idx < grp->len; idx++) + if (grp->lid[idx] == lid) + return idx; + return -1; +} + +int pcb_layergrp_step_layer(pcb_board_t *pcb, pcb_layergrp_t *grp, pcb_layer_id_t lid, int delta) +{ + int idx, idx2; + pcb_layer_id_t tmp; + + for(idx = 0; idx < grp->len; idx++) { + if (grp->lid[idx] == lid) { + if (delta > 0) { + if (idx == grp->len - 1) /* already the last */ + return 0; + idx2 = idx+1; + goto swap; + } + else if (delta < 0) { + if (idx == 0) /* already the last */ + return 0; + idx2 = idx-1; + goto swap; + } + else + return -1; + } + } + return -1; + + swap:; + tmp = grp->lid[idx]; + grp->lid[idx] =grp->lid[idx2]; + grp->lid[idx2] = tmp; + NOTIFY(pcb); + return 0; +} + +int pcb_layergrp_del(pcb_board_t *pcb, pcb_layergrp_id_t gid, int del_layers) +{ + int n; + pcb_layer_stack_t *stk = &pcb->LayerGroups; + + if ((gid < 0) || (gid >= stk->len)) + return -1; + + for(n = 0; n < stk->grp[gid].len; n++) { + pcb_layer_t *l = pcb_get_layer(pcb->Data, stk->grp[gid].lid[n]); + if (l != NULL) { + if (del_layers) { + pcb_layer_move(pcb, stk->grp[gid].lid[n], -1, -1); + n = -1; /* restart counting because the layer remove code may have changed the order */ + } + else { + /* detach only */ + l->meta.real.grp = -1; + } + } + } + + pcb_layergrp_free(pcb, gid); + move_grps(pcb, stk, gid+1, stk->len-1, -1); + stk->len--; + NOTIFY(pcb); + return 0; +} + +int pcb_layergrp_move(pcb_board_t *pcb, pcb_layergrp_id_t from, pcb_layergrp_id_t to_before) +{ + pcb_layer_stack_t *stk = &pcb->LayerGroups; + pcb_layergrp_t tmp; + int n; + + if ((from < 0) || (from >= stk->len)) + return -1; + + if ((to_before < 0) || (to_before >= stk->len)) + return -1; + + if ((to_before == from + 1) || (to_before == from)) + return 0; + + memcpy(&tmp, &stk->grp[from], sizeof(pcb_layergrp_t)); + memset(&stk->grp[from], 0, sizeof(pcb_layergrp_t)); + if (to_before < from + 1) { + move_grps(pcb, stk, to_before, from-1, +1); + memcpy(&stk->grp[to_before], &tmp, sizeof(pcb_layergrp_t)); + } + else { + move_grps(pcb, stk, from+1, to_before-1, -1); + memcpy(&stk->grp[to_before-1], &tmp, sizeof(pcb_layergrp_t)); + } + + /* fix up the group id for the layers of the group moved */ + for(n = 0; n < stk->grp[to_before].len; n++) { + pcb_layer_t *l = pcb_get_layer(pcb->Data, stk->grp[to_before].lid[n]); + if ((l != NULL) && (l->meta.real.grp > 0)) + l->meta.real.grp = to_before; + } + + NOTIFY(pcb); + return 0; +} + + + /* ugly hack: remove the extra substrate we added after the outline layer */ +void pcb_layergrp_fix_old_outline(pcb_board_t *pcb) +{ + pcb_layer_stack_t *LayerGroup = &pcb->LayerGroups; + pcb_layergrp_t *g = pcb_get_grp(LayerGroup, PCB_LYT_ANYWHERE, PCB_LYT_BOUNDARY); + if ((g != NULL) && (g[1].ltype & PCB_LYT_SUBSTRATE)) { + pcb_layergrp_id_t gid = g - LayerGroup->grp + 1; + pcb_layergrp_del(pcb, gid, 0); + } +} + +void pcb_layergrp_fix_turn_to_outline(pcb_layergrp_t *g) +{ + g->ltype |= PCB_LYT_BOUNDARY; + g->ltype &= ~PCB_LYT_COPPER; + g->ltype &= ~(PCB_LYT_ANYWHERE); + free(g->name); + g->name = pcb_strdup("global_outline"); + pcb_layergrp_set_purpose__(g, pcb_strdup("uroute")); +} + + +#define LAYER_IS_OUTLINE(idx) ((pcb->Data->Layer[idx].name != NULL) && ((strcmp(pcb->Data->Layer[idx].name, "route") == 0 || pcb_strcasecmp(pcb->Data->Layer[(idx)].name, "outline") == 0))) + +void pcb_layergrp_fix_old_outline_detect(pcb_board_t *pcb, pcb_layergrp_t *g) +{ + int n, converted = 0; + + for(n = 0; n < g->len; n++) { + if (g->lid[n] < 0) + continue; + if (LAYER_IS_OUTLINE(g->lid[n])) { + if (!converted) { + pcb_layergrp_fix_turn_to_outline(g); + converted = 1; + break; + } + } + } + + if (converted) { + for(n = 0; n < g->len; n++) + pcb->Data->Layer[g->lid[n]].comb = PCB_LYC_AUTO; + } +} + +int pcb_layer_parse_group_string(pcb_board_t *pcb, const char *grp_str, int LayerN, int oldfmt) +{ + const char *s, *start; + pcb_layer_id_t lids[PCB_MAX_LAYER]; + int lids_len = 0; + pcb_layer_type_t loc = PCB_LYT_INTERN; + pcb_layergrp_t *g; + int n; + pcb_layer_stack_t *LayerGroup = &pcb->LayerGroups; + + inhibit_notify++; + + /* clear struct */ + pcb_layer_group_setup_default(pcb); + + for(start = s = grp_str; ; s++) { + switch(*s) { + case ',': + if (flush_item(s, start, lids, &lids_len, &loc) != 0) + goto error; + start = s+1; + break; + case '\0': + case ':': + if (flush_item(s, start, lids, &lids_len, &loc) != 0) + goto error; + /* finalize group */ + if (loc & PCB_LYT_INTERN) + g = pcb_get_grp_new_intern(pcb, -1); + else + g = pcb_get_grp(LayerGroup, loc, PCB_LYT_COPPER); + + for(n = 0; n < lids_len; n++) { + if (lids[n] < 0) + continue; + if (LAYER_IS_OUTLINE(lids[n])) { + if (g->ltype & PCB_LYT_INTERN) { + pcb_layergrp_fix_turn_to_outline(g); + pcb->Data->Layer[lids[n]].comb |= PCB_LYC_AUTO; + } + else + pcb_message(PCB_MSG_ERROR, "outline layer can not be on the solder or component side - converting it into a copper layer\n"); + } + pcb_layer_add_in_group_(pcb, g, g - LayerGroup->grp, lids[n]); + } + + lids_len = 0; + + /* prepare for next iteration */ + loc = PCB_LYT_INTERN; + start = s+1; + break; + } + if (*s == '\0') + break; + } + + pcb_layergrp_fix_old_outline(pcb); + + /* set the two silks */ + g = pcb_get_grp(LayerGroup, PCB_LYT_BOTTOM, PCB_LYT_SILK); + pcb_layer_add_in_group_(pcb, g, g - LayerGroup->grp, LayerN-2); + + g = pcb_get_grp(LayerGroup, PCB_LYT_TOP, PCB_LYT_SILK); + pcb_layer_add_in_group_(pcb, g, g - LayerGroup->grp, LayerN-1); + + inhibit_notify--; + return 0; + + /* reset structure on error */ +error: + inhibit_notify--; + memset(LayerGroup, 0, sizeof(pcb_layer_stack_t)); + return 1; +} + +int pcb_layer_gui_set_layer(pcb_layergrp_id_t gid, const pcb_layergrp_t *grp, int is_empty, pcb_xform_t **xform) +{ + /* if there's no GUI, that means no draw should be done */ + if (pcb_gui == NULL) + return 0; + + if (xform != NULL) + *xform = NULL; + + if (pcb_gui->set_layer_group != NULL) + return pcb_gui->set_layer_group(gid, grp->purpose, grp->purpi, grp->lid[0], grp->ltype, is_empty, xform); + + /* if the GUI doesn't have a set_layer, assume it wants to draw all layers */ + return 1; +} + +int pcb_layer_gui_set_glayer(pcb_board_t *pcb, pcb_layergrp_id_t grp, int is_empty, pcb_xform_t **xform) +{ + return pcb_layer_gui_set_layer(grp, &pcb->LayerGroups.grp[grp], is_empty, xform); +} + +#define APPEND(n) \ + do { \ + if (res != NULL) { \ + if (used < res_len) { \ + res[used] = n; \ + used++; \ + } \ + } \ + else \ + used++; \ + } while(0) + +int pcb_layergrp_list(const pcb_board_t *pcb, pcb_layer_type_t mask, pcb_layergrp_id_t *res, int res_len) +{ + int group, used = 0; + for (group = 0; group < pcb->LayerGroups.len; group++) { + if ((pcb_layergrp_flags(pcb, group) & mask) == mask) + APPEND(group); + } + return used; +} + +int pcb_layergrp_listp(const pcb_board_t *pcb, pcb_layer_type_t mask, pcb_layergrp_id_t *res, int res_len, int purpi, const char *purpose) +{ + int group, used = 0; + const pcb_layergrp_t *g; + for (group = 0, g = pcb->LayerGroups.grp; group < pcb->LayerGroups.len; group++,g++) { + if ((pcb_layergrp_flags(pcb, group) & mask) == mask) { + if (((purpose == NULL) || ((g->purpose != NULL) && (strcmp(purpose, g->purpose) == 0))) && ((purpi == -1) || (purpi == g->purpi))) { + APPEND(group); + } + } + } + return used; +} + +int pcb_layergrp_list_any(const pcb_board_t *pcb, pcb_layer_type_t mask, pcb_layergrp_id_t *res, int res_len) +{ + int group, used = 0; + for (group = 0; group < pcb->LayerGroups.len; group++) { + if ((pcb_layergrp_flags(pcb, group) & mask)) + APPEND(group); + } + return used; +} + +int pcb_layer_add_in_group_(pcb_board_t *pcb, pcb_layergrp_t *grp, pcb_layergrp_id_t group_id, pcb_layer_id_t layer_id) +{ + if ((layer_id < 0) || (layer_id >= pcb->Data->LayerN)) + return -1; + + grp->lid[grp->len] = layer_id; + grp->len++; + pcb->Data->Layer[layer_id].meta.real.grp = group_id; + + return 0; +} + +int pcb_layer_add_in_group(pcb_board_t *pcb, pcb_layer_id_t layer_id, pcb_layergrp_id_t group_id) +{ + if ((group_id < 0) || (group_id >= pcb->LayerGroups.len)) + return -1; + + return pcb_layer_add_in_group_(pcb, &pcb->LayerGroups.grp[group_id], group_id, layer_id); +} + +#define NEWG(g, flags, gname, pcb) \ +do { \ + g = &(newg->grp[newg->len]); \ + g->parent_type = PCB_PARENT_BOARD; \ + g->parent.board = pcb; \ + g->type = PCB_OBJ_LAYERGRP; \ + g->valid = 1; \ + if (gname != NULL) \ + g->name = pcb_strdup(gname); \ + else \ + g->name = NULL; \ + g->ltype = flags; \ + newg->len++; \ +} while(0) + +void pcb_layer_group_setup_default(pcb_board_t *pcb) +{ + pcb_layer_stack_t *newg = &pcb->LayerGroups; + pcb_layergrp_t *g; + + memset(newg, 0, sizeof(pcb_layer_stack_t)); + + NEWG(g, PCB_LYT_TOP | PCB_LYT_PASTE, "top_paste", pcb); + NEWG(g, PCB_LYT_TOP | PCB_LYT_SILK, "top_silk", pcb); + NEWG(g, PCB_LYT_TOP | PCB_LYT_MASK, "top_mask", pcb); + NEWG(g, PCB_LYT_TOP | PCB_LYT_COPPER, "top_copper", pcb); + NEWG(g, PCB_LYT_INTERN | PCB_LYT_SUBSTRATE, NULL, pcb); + + NEWG(g, PCB_LYT_BOTTOM | PCB_LYT_COPPER, "bottom_copper", pcb); + NEWG(g, PCB_LYT_BOTTOM | PCB_LYT_MASK, "bottom_mask", pcb); + NEWG(g, PCB_LYT_BOTTOM | PCB_LYT_SILK, "bottom_silk", pcb); + NEWG(g, PCB_LYT_BOTTOM | PCB_LYT_PASTE, "bottom_paste", pcb); + +/* NEWG(g, PCB_LYT_INTERN | PCB_LYT_BOUNDARY, "outline");*/ +} + +void pcb_layer_group_setup_silks(pcb_board_t *pcb) +{ + pcb_layergrp_id_t gid; + for(gid = 0; gid < pcb->LayerGroups.len; gid++) + if ((pcb->LayerGroups.grp[gid].ltype & PCB_LYT_SILK) && (pcb->LayerGroups.grp[gid].len == 0)) + pcb_layer_create(pcb, gid, "silk"); +} + +int pcb_layergrp_rename_(pcb_layergrp_t *grp, char *name) +{ + free(grp->name); + grp->name = name; + pcb_event(PCB_EVENT_LAYERS_CHANGED, NULL); + return 0; +} + +int pcb_layergrp_rename(pcb_board_t *pcb, pcb_layergrp_id_t gid, const char *name) +{ + pcb_layergrp_t *grp = pcb_get_layergrp(pcb, gid); + if (grp == NULL) return -1; + return pcb_layergrp_rename_(grp, pcb_strdup(name)); +} + +int pcb_layergrp_set_purpose__(pcb_layergrp_t *lg, char *purpose) +{ + free(lg->purpose); + if (purpose == NULL) { + lg->purpose = NULL; + lg->purpi = F_user; + } + else { + lg->purpose = purpose; + lg->purpi = pcb_funchash_get(purpose, NULL); + if (lg->purpi < 0) + lg->purpi = F_user; + } + return 0; +} + +int pcb_layergrp_set_purpose_(pcb_layergrp_t *lg, char *purpose) +{ + int ret = pcb_layergrp_set_purpose__(lg, purpose); + pcb_event(PCB_EVENT_LAYERS_CHANGED, NULL); + return ret; +} + +int pcb_layergrp_set_purpose(pcb_layergrp_t *lg, const char *purpose) +{ + return pcb_layergrp_set_purpose_(lg, pcb_strdup(purpose)); +} + +pcb_layergrp_id_t pcb_layergrp_by_name(pcb_board_t *pcb, const char *name) +{ + pcb_layergrp_id_t n; + for (n = 0; n < pcb->LayerGroups.len; n++) + if ((pcb->LayerGroups.grp[n].name != NULL) && (strcmp(pcb->LayerGroups.grp[n].name, name) == 0)) + return n; + return -1; +} + +int pcb_layergrp_dist(pcb_board_t *pcb, pcb_layergrp_id_t gid1, pcb_layergrp_id_t gid2, pcb_layer_type_t mask, int *diff) +{ + int gid, d, cnt; + + if ((gid1 < 0) || (gid2 < 0)) + return -1; + if (gid1 == gid2) { + *diff = 0; + return 0; + } + + d = (gid1 < gid2) ? +1 : -1; + cnt = 0; + for(gid = gid1; gid != gid2; gid += d) { + if ((gid < 0) || (gid >= pcb->LayerGroups.len)) + return -1; + if ((pcb->LayerGroups.grp[gid].ltype & mask) == mask) + cnt++; + } + *diff = cnt; + return 0; +} + +pcb_layergrp_id_t pcb_layergrp_step(pcb_board_t *pcb, pcb_layergrp_id_t gid, int steps, pcb_layer_type_t mask) +{ + int d; + + if (gid < 0) + return -1; + + if (steps == 0) + return gid; + + if (steps < 0) { + d = -1; + steps = -steps; + } + else + d = 1; + + for(gid += d;; gid += d) { + if ((gid < 0) || (gid >= pcb->LayerGroups.len)) + return -1; + if ((pcb->LayerGroups.grp[gid].ltype & mask) == mask) { + steps--; + if (steps == 0) + return gid; + } + } + return -1; +} + +void pcb_layergrp_create_missing_substrate(pcb_board_t *pcb) +{ + pcb_layergrp_id_t g; + for(g = 0; g < pcb->LayerGroups.len-2; g++) { + pcb_layergrp_t *g0 = &pcb->LayerGroups.grp[g], *g1 = &pcb->LayerGroups.grp[g+1]; + if ((g < pcb->LayerGroups.len-3) && (g1->ltype & PCB_LYT_BOUNDARY)) g1++; + if ((g0->ltype & PCB_LYT_COPPER) && (g1->ltype & PCB_LYT_COPPER)) { + pcb_layergrp_t *ng = pcb_layergrp_insert_after(pcb, g); + ng->ltype = PCB_LYT_INTERN | PCB_LYT_SUBSTRATE; + ng->name = pcb_strdup("implicit_subst"); + ng->valid = 1; + ng->parent_type = PCB_PARENT_BOARD; + ng->parent.board = pcb; + ng->type = PCB_OBJ_LAYERGRP; + } + } +} + +int pcb_layer_create_all_for_recipe(pcb_board_t *pcb, pcb_layer_t *layer, int num_layer) +{ + int n, existing_intern = 0, want_intern = 0; + static char *anon = "anon"; + + for(n = 0; n < pcb->LayerGroups.len; n++) + if ((pcb->LayerGroups.grp[n].ltype & PCB_LYT_COPPER) && (pcb->LayerGroups.grp[n].ltype & PCB_LYT_INTERN)) + existing_intern++; + + for(n = 0; n < num_layer; n++) { + pcb_layer_t *ly = layer + n; + pcb_layer_t *dst = pcb_layer_resolve_binding(pcb, ly); + pcb_layergrp_t *grp; + + if ((ly->meta.bound.type & PCB_LYT_COPPER) && (ly->meta.bound.type & PCB_LYT_INTERN)) { + want_intern++; + continue; + } + + if (dst != NULL) + continue; + + if (ly->meta.bound.type & PCB_LYT_VIRTUAL) { + /* no chance to have this yet */ + continue; + } + + if (ly->meta.bound.type & PCB_LYT_BOUNDARY) { + pcb_layergrp_t *grp = pcb_get_grp_new_misc(pcb); + pcb_layer_id_t nlid; + pcb_layer_t *nly; + grp->ltype = PCB_LYT_BOUNDARY; + grp->name = pcb_strdup("outline"); + if (ly->meta.bound.purpose != NULL) + pcb_layergrp_set_purpose__(grp, pcb_strdup(ly->meta.bound.purpose)); + nlid = pcb_layer_create(pcb, pcb_layergrp_id(pcb, grp), ly->name); + nly = pcb_get_layer(pcb->Data, nlid); + if (nly != NULL) + nly->comb = ly->comb; + continue; + } + + + if (ly->meta.bound.type & PCB_LYT_COPPER) { /* top or bottom copper */ + grp = pcb_get_grp(&pcb->LayerGroups, ly->meta.bound.type & PCB_LYT_ANYWHERE, PCB_LYT_COPPER); + if (grp != NULL) { + pcb_layer_create(pcb, pcb_layergrp_id(pcb, grp), ly->name); + continue; + } + } + + grp = pcb_get_grp(&pcb->LayerGroups, ly->meta.bound.type & PCB_LYT_ANYWHERE, ly->meta.bound.type & PCB_LYT_ANYTHING); + if (grp != NULL) { + pcb_layer_id_t lid = pcb_layer_create(pcb, pcb_layergrp_id(pcb, grp), ly->name); + pcb_layer_t *nly = pcb_get_layer(pcb->Data, lid); + nly->comb = ly->comb; + continue; + } + + pcb_message(PCB_MSG_ERROR, "Failed to create layer from recipe %s\n", ly->name); + } + + if (want_intern > existing_intern) { + int int_ofs = 0; +/*pcb_trace("want: %d have: %d\n", want_intern, existing_intern);*/ + /* create enough dummy internal layers, mark them by name anon */ + while(want_intern > existing_intern) { + pcb_layergrp_t *grp = pcb_get_grp_new_intern(pcb, -1); + grp->name = anon; + existing_intern++; + } + /* rename new interns from the recipe layer names */ + for(n = 0; n < pcb->LayerGroups.len; n++) { + if (pcb->LayerGroups.grp[n].name == anon) { + int m; + int_ofs++; + for(m = 0; m < num_layer; m++) { + pcb_layer_t *ly = layer + m; + if ((ly->meta.bound.type & PCB_LYT_COPPER) && (ly->meta.bound.type & PCB_LYT_INTERN)) { + int offs = ly->meta.bound.stack_offs; +/*pcb_trace("offs: %d (%d) == %d\n", offs, existing_intern + offs + 1, int_ofs);*/ + if (offs < 0) + offs = existing_intern + offs + 1; + if ((offs == int_ofs) && (ly->name != NULL)) { + pcb->LayerGroups.grp[n].name = pcb_strdup("internal"); + pcb_layer_create(pcb, n, ly->name); + goto found; + } + } + } + pcb->LayerGroups.grp[n].name = pcb_strdup("anon-recipe"); + found:; + } + } + } + + + /* create doc and mech layers */ + for(n = 0; n < num_layer; n++) { + pcb_layer_t *ly = layer + n; + pcb_layer_t *dst = pcb_layer_resolve_binding(pcb, ly); + if ((ly->meta.bound.type & PCB_LYT_DOC) || (ly->meta.bound.type & PCB_LYT_MECH)) { + pcb_layergrp_t *grp = pcb_get_grp_new_misc(pcb); + if (grp != NULL) { + grp->ltype = ly->meta.bound.type; + grp->name = pcb_strdup(ly->name); + pcb_layer_create(pcb, pcb_layergrp_id(pcb, grp), ly->name); + pcb_layer_resolve_binding(pcb, ly); + } + } + } + return 0; +} + +void pcb_layergroup_free_stack(pcb_layer_stack_t *st) +{ + int n; + + for(n = 0; n < st->len; n++) + pcb_layergrp_free_fields(st->grp + n); + + free(st->cache.copper); + st->cache.copper = NULL; + st->cache.copper_len = st->cache.copper_alloced = 0; +} + +const pcb_dflgmap_t pcb_dflgmap[] = { + {"top_paste", PCB_LYT_TOP | PCB_LYT_PASTE, NULL, PCB_LYC_AUTO, 0}, + {"top_silk", PCB_LYT_TOP | PCB_LYT_SILK, NULL, PCB_LYC_AUTO, 0}, + {"top_mask", PCB_LYT_TOP | PCB_LYT_MASK, NULL, PCB_LYC_SUB | PCB_LYC_AUTO, 0}, + {"top_copper", PCB_LYT_TOP | PCB_LYT_COPPER, NULL, 0, 0}, + {"any_internal_copper", PCB_LYT_INTERN | PCB_LYT_COPPER, NULL, 0, 0}, + {"bottom_copper", PCB_LYT_BOTTOM | PCB_LYT_COPPER, NULL, 0, 0}, + {"bottom_mask", PCB_LYT_BOTTOM | PCB_LYT_MASK, NULL, PCB_LYC_SUB | PCB_LYC_AUTO, 1}, + {"bottom_silk", PCB_LYT_BOTTOM | PCB_LYT_SILK, NULL, PCB_LYC_AUTO, 1}, + {"bottom_paste", PCB_LYT_BOTTOM | PCB_LYT_PASTE, NULL, PCB_LYC_AUTO, 1}, + {NULL, 0} +}; + +const pcb_dflgmap_t *pcb_dflgmap_last_top_noncopper = pcb_dflgmap+2; +const pcb_dflgmap_t *pcb_dflgmap_first_bottom_noncopper = pcb_dflgmap+6; +const pcb_dflgmap_t pcb_dflg_top_copper = { + "top_copper", PCB_LYT_TOP | PCB_LYT_COPPER, NULL, 0, 0 +}; +const pcb_dflgmap_t pcb_dflg_int_copper = { + "int_copper", PCB_LYT_INTERN | PCB_LYT_COPPER, NULL, 0, 0 +}; +const pcb_dflgmap_t pcb_dflg_substrate = { + "substrate", PCB_LYT_INTERN | PCB_LYT_SUBSTRATE, NULL, 0, 0 +}; +const pcb_dflgmap_t pcb_dflg_bot_copper = { + "bot_copper", PCB_LYT_BOTTOM | PCB_LYT_COPPER, NULL, 0, 0 +}; + +const pcb_dflgmap_t pcb_dflg_outline = { + "outline", PCB_LYT_BOUNDARY, "uroute", 0, 0 +}; + +void pcb_layergrp_set_dflgly(pcb_board_t *pcb, pcb_layergrp_t *grp, const pcb_dflgmap_t *src, const char *grname, const char *lyname) +{ + pcb_layergrp_id_t gid = grp - pcb->LayerGroups.grp; + + if (grname == NULL) + grname = src->name; + if (lyname == NULL) + lyname = src->name; + + grp->name = pcb_strdup(grname); + grp->ltype = src->lyt; + + free(grp->purpose); + grp->purpose = NULL; + if (src->purpose != NULL) + pcb_layergrp_set_purpose__(grp, pcb_strdup(src->purpose)); + + if (grp->len == 0) { + pcb_layer_id_t lid = pcb_layer_create(pcb, gid, lyname); + if (lid >= 0) { + pcb->Data->Layer[lid].comb = src->comb; + } + } + grp->valid = 1; +} + +void pcb_layergrp_upgrade_to_pstk(pcb_board_t *pcb) +{ + const pcb_dflgmap_t *m; + pcb_layergrp_t *grp; + pcb_layergrp_id_t gid; + + inhibit_notify++; + for(m = pcb_dflgmap; m->name != NULL; m++) { + if (pcb_layergrp_list(pcb, m->lyt, &gid, 1) == 1) { + grp = &pcb->LayerGroups.grp[gid]; + free(grp->name); + } + else + grp = pcb_get_grp_new_intern_(pcb, 1, m->force_end); + pcb_layergrp_set_dflgly(pcb, grp, m, NULL, NULL); + } + inhibit_notify--; + NOTIFY(pcb); +} + + +static pcb_layergrp_id_t pcb_layergrp_get_cached(pcb_board_t *pcb, pcb_layer_id_t *cache, unsigned int loc, unsigned int typ) +{ + pcb_layergrp_t *g; + + /* check if the last known value is still accurate */ + if ((*cache >= 0) && (*cache < pcb->LayerGroups.len)) { + g = &(pcb->LayerGroups.grp[*cache]); + if ((g->ltype & loc) && (g->ltype & typ)) + return *cache; + } + + /* nope: need to resolve it again */ + g = pcb_get_grp(&pcb->LayerGroups, loc, typ); + if (g == NULL) + *cache = -1; + else + *cache = (g - pcb->LayerGroups.grp); + return *cache; +} + +pcb_layergrp_id_t pcb_layergrp_get_bottom_mask() +{ + static pcb_layer_id_t cache = -1; + return pcb_layergrp_get_cached(PCB, &cache, PCB_LYT_BOTTOM, PCB_LYT_MASK); +} + +pcb_layergrp_id_t pcb_layergrp_get_top_mask() +{ + static pcb_layer_id_t cache = -1; + return pcb_layergrp_get_cached(PCB, &cache, PCB_LYT_TOP, PCB_LYT_MASK); +} + +pcb_layergrp_id_t pcb_layergrp_get_bottom_paste() +{ + static pcb_layer_id_t cache = -1; + return pcb_layergrp_get_cached(PCB, &cache, PCB_LYT_BOTTOM, PCB_LYT_PASTE); +} + +pcb_layergrp_id_t pcb_layergrp_get_top_paste() +{ + static pcb_layer_id_t cache = -1; + return pcb_layergrp_get_cached(PCB, &cache, PCB_LYT_TOP, PCB_LYT_PASTE); +} + +pcb_layergrp_id_t pcb_layergrp_get_bottom_silk() +{ + static pcb_layer_id_t cache = -1; + return pcb_layergrp_get_cached(PCB, &cache, PCB_LYT_BOTTOM, PCB_LYT_SILK); +} + +pcb_layergrp_id_t pcb_layergrp_get_top_silk() +{ + static pcb_layer_id_t cache = -1; + return pcb_layergrp_get_cached(PCB, &cache, PCB_LYT_TOP, PCB_LYT_SILK); +} + +pcb_layergrp_id_t pcb_layergrp_get_bottom_copper() +{ + static pcb_layer_id_t cache = -1; + return pcb_layergrp_get_cached(PCB, &cache, PCB_LYT_BOTTOM, PCB_LYT_COPPER); +} + +pcb_layergrp_id_t pcb_layergrp_get_top_copper() +{ + static pcb_layer_id_t cache = -1; + return pcb_layergrp_get_cached(PCB, &cache, PCB_LYT_TOP, PCB_LYT_COPPER); +} + +/* Note: these function is in this file mainly to access the static inlines */ +int pcb_silk_on(pcb_board_t *pcb) +{ + static pcb_layer_id_t ts = -1, bs = -1; + pcb_layergrp_get_cached(pcb, &ts, PCB_LYT_TOP, PCB_LYT_SILK); + if ((ts >= 0) && (pcb->LayerGroups.grp[ts].vis)) + return 1; + pcb_layergrp_get_cached(pcb, &bs, PCB_LYT_BOTTOM, PCB_LYT_SILK); + if ((bs >= 0) && (pcb->LayerGroups.grp[bs].vis)) + return 1; + return 0; +} + +int pcb_mask_on(pcb_board_t *pcb) +{ + static pcb_layer_id_t tm = -1, bm = -1; + pcb_layergrp_get_cached(pcb, &tm, PCB_LYT_TOP, PCB_LYT_MASK); + if ((tm >= 0) && (pcb->LayerGroups.grp[tm].vis)) + return 1; + pcb_layergrp_get_cached(pcb, &bm, PCB_LYT_BOTTOM, PCB_LYT_MASK); + if ((bm >= 0) && (pcb->LayerGroups.grp[bm].vis)) + return 1; + return 0; +} + + +int pcb_paste_on(pcb_board_t *pcb) +{ + static pcb_layer_id_t tp = -1, bp = -1; + pcb_layergrp_get_cached(pcb, &tp, PCB_LYT_TOP, PCB_LYT_PASTE); + if ((tp >= 0) && (pcb->LayerGroups.grp[tp].vis)) + return 1; + pcb_layergrp_get_cached(pcb, &bp, PCB_LYT_BOTTOM, PCB_LYT_PASTE); + if ((bp >= 0) && (pcb->LayerGroups.grp[bp].vis)) + return 1; + return 0; +} + + +void pcb_layergrp_copper_cache_update(pcb_layer_stack_t *st) +{ + pcb_layergrp_id_t n; + if (st->len > st->cache.copper_alloced) { + st->cache.copper_alloced = st->len + 64; + st->cache.copper = realloc(st->cache.copper, sizeof(st->cache.copper[0]) * st->cache.copper_alloced); + } + + st->cache.copper_len = 0; + for(n = 0; n < st->len; n++) + if (st->grp[n].ltype & PCB_LYT_COPPER) + st->cache.copper[st->cache.copper_len++] = n; + + st->cache.copper_valid = 1; +} + + +pcb_layergrp_id_t pcb_layergrp_str2id(pcb_board_t *pcb, const char *str) +{ + char *end; + pcb_layer_id_t id; + if (*str == '#') { + id = strtol(str+1, &end, 10); + if ((*end == '\0') && (id >= 0) && (id < pcb->LayerGroups.len)) + return id; + } +TODO("layer: do the same that cam does; test with propedit"); + return -1; +} + +pcb_bool pcb_has_explicit_outline(pcb_board_t *pcb) +{ + int i; + pcb_layergrp_t *g; + for(i = 0, g = pcb->LayerGroups.grp; i < pcb->LayerGroups.len; i++,g++) + if (PCB_LAYER_IS_OUTLINE(g->ltype, g->purpi) && !pcb_layergrp_is_pure_empty(pcb, i)) + return 1; + return 0; +} Index: tags/2.1.2/src/layer_grp.h =================================================================== --- tags/2.1.2/src/layer_grp.h (nonexistent) +++ tags/2.1.2/src/layer_grp.h (revision 24813) @@ -0,0 +1,283 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996,2006 Thomas Nau + * Copyright (C) 2016, 2017 Tibor 'Igor2' Palinkas (pcb-rnd extensions) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +#ifndef PCB_LAYER_GRP_H +#define PCB_LAYER_GRP_H + +#include "layer.h" + +/* ---------------------------------------------------------------------- + * layer group. A layer group identifies layers which are always switched + * on/off together. + */ + +struct pcb_layergrp_s { + PCB_ANY_OBJ_FIELDS; + pcb_cardinal_t len; /* number of layer IDs in use */ + pcb_layer_id_t lid[PCB_MAX_LAYER]; /* lid=layer ID */ + char *name; /* name of the physical layer (independent of the name of the layer groups) */ + + pcb_layer_type_t ltype; + char *purpose; /* what a doc/mech layer is used for */ + int purpi; /* integer version of purpose from the funtion hash (cache) */ + + unsigned valid:1; /* 1 if it's a new-style, valid layer group; 0 after loading old files with no layer stackup info */ + unsigned vis:1; /* 1 if layer group is visible on the GUI */ + unsigned open:1; /* 1 if the group is open (expanded) on the GUI */ + + /* internal: temporary states */ + int intern_id; /* for the old layer import mechanism */ +}; + + +/* layer stack: an ordered list of layer groups (physical layers). */ +struct pcb_layer_stack_s { + pcb_cardinal_t len; + pcb_layergrp_t grp[PCB_MAX_LAYERGRP]; + struct { /* cache copper groups from top to bottom for fast padstack ("bbvia") lookup */ + int copper_len, copper_alloced; + pcb_layergrp_id_t *copper; + unsigned copper_valid:1; /* whether the cache is valid */ + } cache; +}; + +/* Free all fields of a layer stack */ +void pcb_layergroup_free_stack(pcb_layer_stack_t *st); + +/* Return the layer group for an id, or NULL on error (range check) */ +pcb_layergrp_t *pcb_get_layergrp(pcb_board_t *pcb, pcb_layergrp_id_t gid); + +/* Return the gid if grp is in the stackup of pcb (else return -1) */ +pcb_layergrp_id_t pcb_layergrp_id(const pcb_board_t *pcb, const pcb_layergrp_t *grp); + +/* Free a layer group (don't free the layers but detach them) */ +int pcb_layergrp_free(pcb_board_t *pcb, pcb_layergrp_id_t id); + +/* lookup the group to which a layer belongs to returns -1 if no group is found */ +pcb_layergrp_id_t pcb_layer_get_group(pcb_board_t *pcb, pcb_layer_id_t Layer); +pcb_layergrp_id_t pcb_layer_get_group_(pcb_layer_t *Layer); + +/* Returns group actually moved to (i.e. either group or previous) */ +pcb_layergrp_id_t pcb_layer_move_to_group(pcb_board_t *pcb, pcb_layer_id_t layer, pcb_layergrp_id_t group); + +/* Returns pcb_true if all layers in a group are empty */ +pcb_bool pcb_layergrp_is_empty(pcb_board_t *pcb, pcb_layergrp_id_t lgrp); +pcb_bool pcb_layergrp_is_pure_empty(pcb_board_t *pcb, pcb_layergrp_id_t num); + +/* call the gui to set a layer group */ +int pcb_layer_gui_set_layer(pcb_layergrp_id_t gid, const pcb_layergrp_t *grp, int is_empty, pcb_xform_t **xform); +int pcb_layer_gui_set_glayer(pcb_board_t *pcb, pcb_layergrp_id_t grp, int is_empty, pcb_xform_t **xform); + +/* returns a bitfield of pcb_layer_type_t; returns 0 if layer_idx is invalid. */ +unsigned int pcb_layergrp_flags(const pcb_board_t *pcb, pcb_layergrp_id_t group_idx); +const char *pcb_layergrp_name(pcb_board_t *pcb, pcb_layergrp_id_t gid); + +/* Same as pcb_layer_list but lists layer groups. A group is matching + if any layer in that group matches mask. */ +int pcb_layergrp_list(const pcb_board_t *pcb, pcb_layer_type_t mask, pcb_layergrp_id_t *res, int res_len); +int pcb_layergrp_listp(const pcb_board_t *pcb, pcb_layer_type_t mask, pcb_layergrp_id_t *res, int res_len, int purpi, const char *purpose); +int pcb_layergrp_list_any(const pcb_board_t *pcb, pcb_layer_type_t mask, pcb_layergrp_id_t *res, int res_len); + +/* Put a layer in a group (the layer should not be in any other group); + returns 0 on success */ +int pcb_layer_add_in_group(pcb_board_t *pcb, pcb_layer_id_t layer_id, pcb_layergrp_id_t group_id); +int pcb_layer_add_in_group_(pcb_board_t *pcb, pcb_layergrp_t *grp, pcb_layergrp_id_t group_id, pcb_layer_id_t layer_id); + +/* Remove a layer group; if del_layers is zero, layers are kept but detached + (.grp = -1), else layers are deleted too */ +int pcb_layergrp_del(pcb_board_t *pcb, pcb_layergrp_id_t gid, int del_layers); + +/* Remove a layer from a group */ +int pcb_layergrp_del_layer(pcb_board_t *pcb, pcb_layergrp_id_t gid, pcb_layer_id_t lid); + +/* Duplicate a layer group (with no layers); if auto_substrate is set, insert + a substrate layer automatically if needed */ +pcb_layergrp_id_t pcb_layergrp_dup(pcb_board_t *pcb, pcb_layergrp_id_t gid, int auto_substrate); + +/* Move gfrom to to_before and shift the stack as necessary. Return -1 on range error */ +int pcb_layergrp_move(pcb_board_t *pcb, pcb_layergrp_id_t gfrom, pcb_layergrp_id_t to_before); + +/* Move src onto dst, not shifting the stack, free()'ing and overwriting dst, leaving a gap (0'd slot) at src */ +int pcb_layergrp_move_onto(pcb_board_t *pcb, pcb_layergrp_id_t dst, pcb_layergrp_id_t src); + + +/* Insert a new layer group in the layer stack after the specified group */ +pcb_layergrp_t *pcb_layergrp_insert_after(pcb_board_t *pcb, pcb_layergrp_id_t where); + +/* Move lid 1 step towards the front (delta=-1) or end (delta=+1) of the + layer list of the group. Return 0 on success (even when already reached + the end of the list) or -1 on error */ +int pcb_layergrp_step_layer(pcb_board_t *pcb, pcb_layergrp_t *grp, pcb_layer_id_t lid, int delta); + +/* Return the array index of lid within the grp's lid list or -1 if not on the list */ +int pcb_layergrp_index_in_grp(pcb_layergrp_t *grp, pcb_layer_id_t lid); + +/* Calculate the distance between gid1 and gid2 in the stack, in number of + layer groups matching mask. The result is placed in *diff. Returns 0 on success. + Typical use case: gid1 is an internal copper layer, gid2 is the top copper layer, + mask is PCB_LYT_COPPER -> *diff is the copper index of the internal layer from top */ +int pcb_layergrp_dist(pcb_board_t *pcb, pcb_layergrp_id_t gid1, pcb_layergrp_id_t gid2, pcb_layer_type_t mask, int *diff); + +/* walk the given amount steps on the stack among layer groups matching mask. + A negative step goes upward. + Typical use: "return the 2nd copper layer below this one" */ +pcb_layergrp_id_t pcb_layergrp_step(pcb_board_t *pcb, pcb_layergrp_id_t gid, int steps, pcb_layer_type_t mask); + + +/* Enable/disable inhibition of layer changed events during layer group updates */ +void pcb_layergrp_inhibit_inc(void); +void pcb_layergrp_inhibit_dec(void); + +/* Send out a layer changed event if not inhibited */ +void pcb_layergrp_notify(pcb_board_t *pcb); + +/* Rename an existing layer by idx */ +int pcb_layergrp_rename(pcb_board_t *pcb, pcb_layergrp_id_t gid, const char *lname); + +/* changes the name of a layer; memory has to be already allocated */ +int pcb_layergrp_rename_(pcb_layergrp_t *grp, char *name); + +/* Change the purpose field and recalc purpi (not undoable) */ +int pcb_layergrp_set_purpose__(pcb_layergrp_t *lg, char *purpose); /* no strdup, no event */ +int pcb_layergrp_set_purpose_(pcb_layergrp_t *lg, char *purpose); /* no strdup, send layer change event */ +int pcb_layergrp_set_purpose(pcb_layergrp_t *lg, const char *purpose); /* strdup, send event */ + + +/* Slow linear search for a layer group by name */ +pcb_layergrp_id_t pcb_layergrp_by_name(pcb_board_t *pcb, const char *name); + +/* Create a layer for each unbindable layers from the layer array */ +int pcb_layer_create_all_for_recipe(pcb_board_t *pcb, pcb_layer_t *layer, int num_layer); + +/* Upgrade the current layer stack to incldue all layers for + fully representaing standard padstacks. This includes reusing or + creating layer groups and layers, altering layer group names (but + not removing layers or groups) */ +void pcb_layergrp_upgrade_to_pstk(pcb_board_t *pcb); + +/* Compatibility helper: insert a substrate group in between any two adjacent + copper groups. */ +void pcb_layergrp_create_missing_substrate(pcb_board_t *pcb); + + +/********* OBSOLETE functions, do not use in new code *********/ +/* parses the group definition string which is a colon separated list of + comma separated layer numbers (1,2,b:4,6,8,t); oldfmt is 0 or 1 + depending on PCB() or PCB[] in the file header. + + OBSOLETE, do not use in new code: only the conf system and io_pcb + may need this. */ +int pcb_layer_parse_group_string(pcb_board_t *pcb, const char *s, int LayerN, int oldfmt); + +#define PCB_COPPER_GROUP_LOOP(data, group) do { \ + pcb_cardinal_t entry; \ + pcb_board_t *cgl__pcb = pcb_data_get_top(data); \ + if (cgl__pcb == NULL) \ + cgl__pcb = PCB; \ + for (entry = 0; entry < ((pcb_board_t *)(cgl__pcb))->LayerGroups.grp[(group)].len; entry++) \ + { \ + pcb_layer_t *layer; \ + pcb_layer_id_t number; \ + number = ((pcb_board_t *)(cgl__pcb))->LayerGroups.grp[(group)].lid[entry]; \ + if (!(pcb_layer_flags(PCB, number) & PCB_LYT_COPPER)) \ + continue; \ + layer = &data->Layer[number]; + +/* for parsing old files with old layer descriptions, with no layer groups */ +void pcb_layer_group_setup_default(pcb_board_t *pcb); /* default layer groups, no layers */ +void pcb_layer_group_setup_silks(pcb_board_t *pcb); /* make sure we have two silk layers, add them if needed */ +pcb_layergrp_t *pcb_get_grp(pcb_layer_stack_t *stack, pcb_layer_type_t loc, pcb_layer_type_t typ); +pcb_layergrp_t *pcb_get_grp_new_intern(pcb_board_t *pcb, int intern_id); +pcb_layergrp_t *pcb_get_grp_new_misc(pcb_board_t *pcb); + +/* append a layer group without any smart side effects - use only from io loaders */ +pcb_layergrp_t *pcb_get_grp_new_raw(pcb_board_t *pcb); + +/* ugly hack: remove the extra substrate we added after the outline layer */ +void pcb_layergrp_fix_old_outline(pcb_board_t *pcb); + +/* ugly hack: turn an old intern layer group into an outline group after realizing it is really an outline (reading the old layers) */ +void pcb_layergrp_fix_turn_to_outline(pcb_layergrp_t *g); + +/* ugly hack: look at layers and convert g into an outline group if needed */ +void pcb_layergrp_fix_old_outline_detect(pcb_board_t *pcb, pcb_layergrp_t *g); + + +/* Cached layer group lookups foir a few common cases */ +pcb_layergrp_id_t pcb_layergrp_get_bottom_mask(); +pcb_layergrp_id_t pcb_layergrp_get_top_mask(); +pcb_layergrp_id_t pcb_layergrp_get_bottom_paste(); +pcb_layergrp_id_t pcb_layergrp_get_top_paste(); +pcb_layergrp_id_t pcb_layergrp_get_bottom_silk(); +pcb_layergrp_id_t pcb_layergrp_get_top_silk(); +pcb_layergrp_id_t pcb_layergrp_get_bottom_copper(); +pcb_layergrp_id_t pcb_layergrp_get_top_copper(); + + +/* return whether any silk or mask or paste layer group is visible */ +int pcb_silk_on(pcb_board_t *pcb); +int pcb_mask_on(pcb_board_t *pcb); +int pcb_paste_on(pcb_board_t *pcb); + +/* recalculate the copper cache */ +void pcb_layergrp_copper_cache_update(pcb_layer_stack_t *st); + +/* default layer group map */ +typedef struct pcb_dflgmap_s { + const char *name; + pcb_layer_type_t lyt; + const char *purpose; + pcb_layer_combining_t comb; + int force_end; +} pcb_dflgmap_t; + +extern const pcb_dflgmap_t pcb_dflgmap[]; /* the whole map */ + +/* pointers into the array marking boundaries */ +extern const pcb_dflgmap_t *pcb_dflgmap_last_top_noncopper; +extern const pcb_dflgmap_t *pcb_dflgmap_first_bottom_noncopper; + +/* predefined common default map entries for building a stack */ +extern const pcb_dflgmap_t pcb_dflg_top_copper; +extern const pcb_dflgmap_t pcb_dflg_int_copper; +extern const pcb_dflgmap_t pcb_dflg_substrate; +extern const pcb_dflgmap_t pcb_dflg_bot_copper; +extern const pcb_dflgmap_t pcb_dflg_outline; + + +/* Overwrite an existing group from a default layer group map entry and create + a layer in the group */ +void pcb_layergrp_set_dflgly(pcb_board_t *pcb, pcb_layergrp_t *grp, const pcb_dflgmap_t *src, const char *grname, const char *lyname); + +pcb_layergrp_id_t pcb_layergrp_str2id(pcb_board_t *pcb, const char *str); + +/* Return true if the board has an outline layer with at least one object on it */ +pcb_bool pcb_has_explicit_outline(pcb_board_t *pcb); + +#endif Index: tags/2.1.2/src/layer_inlines.h =================================================================== --- tags/2.1.2/src/layer_inlines.h (nonexistent) +++ tags/2.1.2/src/layer_inlines.h (revision 24813) @@ -0,0 +1,22 @@ +#ifndef PCB_LAYER_INLINES_H +#define PCB_LAYER_INLINES_H + +#include "layer.h" + +PCB_INLINE pcb_layer_t *pcb_layer_silk_front(pcb_board_t *pcb) +{ + pcb_layer_id_t lid = (conf_core.editor.show_solder_side ? pcb_layer_get_bottom_silk() : pcb_layer_get_top_silk()); + if (lid < 0) + return NULL; + return &pcb->Data->Layer[lid]; +} + +PCB_INLINE pcb_layer_t *pcb_layer_silk_back(pcb_board_t *pcb) +{ + pcb_layer_id_t lid = ((!conf_core.editor.show_solder_side) ? pcb_layer_get_bottom_silk() : pcb_layer_get_top_silk()); + if (lid < 0) + return NULL; + return &pcb->Data->Layer[lid]; +} + +#endif Index: tags/2.1.2/src/layer_it.h =================================================================== --- tags/2.1.2/src/layer_it.h (nonexistent) +++ tags/2.1.2/src/layer_it.h (revision 24813) @@ -0,0 +1,121 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2017 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +/* Layer and layer group iterators (static inline functions) */ + +#ifndef PCB_LAYER_IT_H +#define PCB_LAYER_IT_H + +#include "layer_grp.h" + +typedef struct pcb_layer_it_s pcb_layer_it_t; + +/* Start an iteration matching exact flags or any of the flags; returns -1 if over */ +PCB_INLINE pcb_layer_id_t pcb_layer_first(pcb_layer_stack_t *stack, pcb_layer_it_t *it, unsigned int exact_mask); +PCB_INLINE pcb_layer_id_t pcb_layer_first_any(pcb_layer_stack_t *stack, pcb_layer_it_t *it, unsigned int any_mask); + +/* next iteration; returns -1 if over */ +PCB_INLINE pcb_layer_id_t pcb_layer_next(pcb_layer_it_t *it); + + +/*************** inline implementation *************************/ +struct pcb_layer_it_s { + pcb_layer_stack_t *stack; + pcb_layergrp_id_t gid; + pcb_cardinal_t lidx; + unsigned int mask; + unsigned int exact:1; + unsigned int global:1; +}; + +PCB_INLINE pcb_layer_id_t pcb_layer_next(pcb_layer_it_t *it) +{ + if (it->global) { + /* over all layers, random order, without any checks - go the cheap way, bypassing groups */ + if (it->lidx < pcb_max_layer) + return it->lidx++; + return -1; + } + else for(;;) { + pcb_layergrp_t *g = &(it->stack->grp[it->gid]); + pcb_layer_id_t lid; + unsigned int hit; + if (it->lidx >= g->len) { /* layer list over in this group */ + it->gid++; + if (it->gid >= PCB_MAX_LAYERGRP) /* last group */ + return -1; + it->lidx = 0; + continue; /* skip to next group */ + } + /* TODO: check group flags against mask here for more efficiency */ + lid = g->lid[it->lidx]; + it->lidx++; + hit = pcb_layer_flags(PCB, lid) & it->mask; + if (it->exact) { + if (hit == it->mask) + return lid; + } + else { + if (hit) + return lid; + } + /* skip to next group */ + } +} + +PCB_INLINE pcb_layer_id_t pcb_layer_first(pcb_layer_stack_t *stack, pcb_layer_it_t *it, unsigned int exact_mask) +{ + it->stack = stack; + it->mask = exact_mask; + it->gid = 0; + it->lidx = 0; + it->exact = 1; + it->global = 0; + return pcb_layer_next(it); +} + +PCB_INLINE pcb_layer_id_t pcb_layer_first_any(pcb_layer_stack_t *stack, pcb_layer_it_t *it, unsigned int any_mask) +{ + it->stack = stack; + it->mask = any_mask; + it->gid = 0; + it->lidx = 0; + it->exact = 0; + it->global = 0; + return pcb_layer_next(it); +} + +PCB_INLINE pcb_layer_id_t pcb_layer_first_all(pcb_layer_stack_t *stack, pcb_layer_it_t *it) +{ + it->stack = stack; + it->lidx = 0; + it->global = 1; + return pcb_layer_next(it); +} + + +#endif Index: tags/2.1.2/src/layer_ui.c =================================================================== --- tags/2.1.2/src/layer_ui.c (nonexistent) +++ tags/2.1.2/src/layer_ui.c (revision 24813) @@ -0,0 +1,125 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2016 Tibor 'Igor2' Palinkas + * + * This module, layer_ui.c, was written and is Copyright (C) 2016 by + * Tibor 'Igor2' Palinkas. + * this module is also subject to the GNU GPL as described below + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +/* Virtual layers for UI and debug */ +#include "config.h" +#include "layer.h" +#include "event.h" +#include "compat_misc.h" +#include "genvector/vtp0.h" +#include "layer_ui.h" + +vtp0_t pcb_uilayers; + + +pcb_layer_t *pcb_uilayer_alloc(const char *cookie, const char *name, const pcb_color_t *color) +{ + int n; + pcb_layer_t *l; + void **p; + + if (cookie == NULL) + return NULL; + + for(n = 0; n < vtp0_len(&pcb_uilayers); n++) { + l = pcb_uilayers.array[n]; + if (l == NULL) { + l = calloc(sizeof(pcb_layer_t), 1); + pcb_uilayers.array[n] = l; + goto found; + } + } + + l = calloc(sizeof(pcb_layer_t), 1); + p = vtp0_alloc_append(&pcb_uilayers, 1); + *p = l; +found:; + l->meta.real.cookie = cookie; + l->meta.real.color = *color; + l->name = pcb_strdup(name); + l->meta.real.vis = 1; + l->parent_type = PCB_PARENT_UI; + l->parent.any = NULL; + pcb_event(PCB_EVENT_LAYERS_CHANGED, NULL); + return l; +} + +static void pcb_uilayer_free_(pcb_layer_t *l, long idx) +{ + pcb_layer_free_fields(l); + free(l); + pcb_uilayers.array[idx] = NULL; +} + +void pcb_uilayer_free(pcb_layer_t *ly) +{ + int n; + for(n = 0; n < vtp0_len(&pcb_uilayers); n++) { + pcb_layer_t *l = pcb_uilayers.array[n]; + if (l == ly) { + pcb_uilayer_free_(l, n); + break; + } + } + pcb_event(PCB_EVENT_LAYERS_CHANGED, NULL); +} + +void pcb_uilayer_free_all_cookie(const char *cookie) +{ + int n; + for(n = 0; n < vtp0_len(&pcb_uilayers); n++) { + pcb_layer_t *l = pcb_uilayers.array[n]; + if ((l != NULL) && (l->meta.real.cookie == cookie)) + pcb_uilayer_free_(l, n); + } + pcb_event(PCB_EVENT_LAYERS_CHANGED, NULL); +} + +void pcb_uilayer_uninit(void) +{ + vtp0_uninit(&pcb_uilayers); +} + +pcb_layer_t *pcb_uilayer_get(long ui_ly_id) +{ + void **p = vtp0_get(&pcb_uilayers, (ui_ly_id & (PCB_LYT_UI-1)), 0); + if (p == NULL) + return NULL; + return (pcb_layer_t *)(*p); +} + +long pcb_uilayer_get_id(const pcb_layer_t *ly) +{ + int n; + for(n = 0; n < vtp0_len(&pcb_uilayers); n++) + if (pcb_uilayers.array[n] == ly) + return (long)n | PCB_LYT_UI; + return -1; +} Index: tags/2.1.2/src/layer_ui.h =================================================================== --- tags/2.1.2/src/layer_ui.h (nonexistent) +++ tags/2.1.2/src/layer_ui.h (revision 24813) @@ -0,0 +1,50 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2016 Tibor 'Igor2' Palinkas + * + * This module, layer_ui.c, was written and is Copyright (C) 2016 by + * Tibor 'Igor2' Palinkas. + * this module is also subject to the GNU GPL as described below + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#ifndef PCB_LAYER_UI_H +#define PCB_LAYER_UI_H + +/* Virtual layers for UI and debug */ +#include "global_typedefs.h" + +#include "genvector/vtp0.h" + +/* list of all UI layers - each item is a persistent pointer to a layer struct */ +extern vtp0_t pcb_uilayers; + +pcb_layer_t *pcb_uilayer_alloc(const char *cookie, const char *name, const pcb_color_t *color); +void pcb_uilayer_free(pcb_layer_t *l); +void pcb_uilayer_free_all_cookie(const char *cookie); +void pcb_uilayer_uninit(void); + +pcb_layer_t *pcb_uilayer_get(long ui_ly_id); +long pcb_uilayer_get_id(const pcb_layer_t *ly); + +#endif Index: tags/2.1.2/src/layer_vis.c =================================================================== --- tags/2.1.2/src/layer_vis.c (nonexistent) +++ tags/2.1.2/src/layer_vis.c (revision 24813) @@ -0,0 +1,353 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996,2004,2006 Thomas Nau + * Copyright (C) 2016 Tibor 'Igor2' Palinkas (pcb-rnd extensions) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +/* Layer visibility logics (affects the GUI and some exporters) */ + +#include "config.h" +#include "board.h" +#include "data.h" +#include "conf_core.h" +#include "layer.h" +#include "layer_ui.h" +#include "layer_vis.h" +#include "event.h" +#include "compat_misc.h" +#include "conf_hid.h" + +/* + * Used by pcb_layervis_save_stack() and + * pcb_layervis_restore_stack() + */ +static struct { + pcb_bool ElementOn, InvisibleObjectsOn, pstk_on, RatOn; + int pcb_layer_stack[PCB_MAX_LAYER]; + pcb_bool LayerOn[PCB_MAX_LAYER]; + int cnt; +} SavedStack; + + +/* --------------------------------------------------------------------------- + * move layer (number is passed in) to top of layerstack + */ +static void PushOnTopOfLayerStack(int NewTop) +{ + int i; + + /* ignore silk layers */ + if (NewTop < pcb_max_layer) { + /* first find position of passed one */ + for (i = 0; i < pcb_max_layer; i++) + if (pcb_layer_stack[i] == NewTop) + break; + + /* bring this element to the top of the stack */ + for (; i; i--) + pcb_layer_stack[i] = pcb_layer_stack[i - 1]; + pcb_layer_stack[0] = NewTop; + } +} + + +/* ---------------------------------------------------------------------- + * changes the visibility of all layers in a group + * returns the number of changed layers + */ +int pcb_layervis_change_group_vis(pcb_layer_id_t Layer, int On, pcb_bool ChangeStackOrder) +{ + pcb_layergrp_id_t group; + int i, changed = 1; /* at least the current layer changes */ + + + if (Layer & PCB_LYT_UI) { + pcb_layer_t *ly = pcb_uilayer_get(Layer); + if (ly == NULL) + return 0; + if (On < 0) + On = !ly->meta.real.vis; + ly->meta.real.vis = On; + changed = 1; + goto done; + } + + if (On < 0) + On = !PCB->Data->Layer[Layer].meta.real.vis; + + /* decrement 'i' to keep stack in order of layergroup */ + if ((group = pcb_layer_get_group(PCB, Layer)) >= 0) { + for (i = PCB->LayerGroups.grp[group].len; i;) { + pcb_layer_id_t layer = PCB->LayerGroups.grp[group].lid[--i]; + + /* don't count the passed member of the group */ + if (layer != Layer && layer < pcb_max_layer) { + PCB->Data->Layer[layer].meta.real.vis = On; + + /* push layer on top of stack if switched on */ + if (On && ChangeStackOrder) + PushOnTopOfLayerStack(layer); + changed++; + } + } + PCB->LayerGroups.grp[group].vis = On; + } + + /* change at least the passed layer */ + PCB->Data->Layer[Layer].meta.real.vis = On; + if (On && ChangeStackOrder) + PushOnTopOfLayerStack(Layer); + + done:; + /* update control panel and exit */ + pcb_event(PCB_EVENT_LAYERVIS_CHANGED, NULL); + return changed; +} + +/* --------------------------------------------------------------------------- + * resets the layerstack setting + */ +void pcb_layervis_reset_stack(void) +{ + pcb_layer_id_t comp; + pcb_cardinal_t i; + + assert(PCB->Data->LayerN <= PCB_MAX_LAYER); + for (i = 0; i < pcb_max_layer; i++) { + if (!(pcb_layer_flags(PCB, i) & PCB_LYT_SILK)) + pcb_layer_stack[i] = i; + PCB->Data->Layer[i].meta.real.vis = pcb_true; + } + PCB->InvisibleObjectsOn = pcb_true; + PCB->pstk_on = pcb_true; + PCB->SubcOn = pcb_true; + PCB->SubcPartsOn = pcb_true; + PCB->RatOn = pcb_true; + PCB->padstack_mark_on = pcb_true; + PCB->hole_on = pcb_true; + + /* Bring the top copper group to the front and make it active. */ + if (pcb_layer_list(PCB, PCB_LYT_TOP | PCB_LYT_COPPER, &comp, 1) > 0) + pcb_layervis_change_group_vis(comp, 1, 1); +} + +/* --------------------------------------------------------------------------- + * saves the layerstack setting + */ +void pcb_layervis_save_stack(void) +{ + pcb_cardinal_t i; + static pcb_bool run = pcb_false; + + if (run == pcb_false) { + SavedStack.cnt = 0; + run = pcb_true; + } + + if (SavedStack.cnt != 0) + pcb_message(PCB_MSG_ERROR, "pcb_layervis_save_stack() layerstack was already saved and not yet restored. cnt = %d\n", SavedStack.cnt); + + for (i = 0; i < pcb_max_layer; i++) { + if (!(pcb_layer_flags(PCB, i) & PCB_LYT_SILK)) + SavedStack.pcb_layer_stack[i] = pcb_layer_stack[i]; + SavedStack.LayerOn[i] = PCB->Data->Layer[i].meta.real.vis; + } + SavedStack.ElementOn = pcb_silk_on(PCB); + SavedStack.InvisibleObjectsOn = PCB->InvisibleObjectsOn; + SavedStack.pstk_on = PCB->pstk_on; + SavedStack.RatOn = PCB->RatOn; + SavedStack.cnt++; +} + +/* --------------------------------------------------------------------------- + * restores the layerstack setting + */ +void pcb_layervis_restore_stack(void) +{ + pcb_cardinal_t i; + + if (SavedStack.cnt == 0) { + pcb_message(PCB_MSG_ERROR, "pcb_layervis_restore_stack() layerstack has not" " been saved. cnt = %d\n", SavedStack.cnt); + return; + } + else if (SavedStack.cnt != 1) { + pcb_message(PCB_MSG_ERROR, "pcb_layervis_restore_stack() layerstack save count is" " wrong. cnt = %d\n", SavedStack.cnt); + } + + for (i = 0; i < pcb_max_layer; i++) { + if (!(pcb_layer_flags(PCB, i) & PCB_LYT_SILK)) + pcb_layer_stack[i] = SavedStack.pcb_layer_stack[i]; + PCB->Data->Layer[i].meta.real.vis = SavedStack.LayerOn[i]; + } + PCB->InvisibleObjectsOn = SavedStack.InvisibleObjectsOn; + PCB->pstk_on = SavedStack.pstk_on; + PCB->RatOn = SavedStack.RatOn; + + SavedStack.cnt--; +} + +static conf_hid_id_t layer_vis_conf_id; + +void layer_vis_chg_mask(conf_native_t *cfg, int arr_idx) +{ + pcb_layer_id_t n; + int chg = 0; + static int in = 0; /* don't run when called from the PCB_EVENT_LAYERS_CHANGED triggered from this function */ + + if ((PCB == NULL) || (in)) + return; + + in = 1; + for(n = 0; n < pcb_max_layer; n++) { + if (pcb_layer_flags(PCB, n) & PCB_LYT_MASK) { + if (PCB->Data->Layer[n].meta.real.vis != *cfg->val.boolean) { + chg = 1; + PCB->Data->Layer[n].meta.real.vis = *cfg->val.boolean; + } + } + } + if (chg) + pcb_event(PCB_EVENT_LAYERVIS_CHANGED, NULL); + in = 0; +} + +void pcb_layer_vis_change_all(pcb_board_t *pcb, pcb_bool_op_t open, pcb_bool_op_t vis) +{ + pcb_layergrp_id_t gid; + int n; + + for(gid = 0; gid < pcb_max_group(pcb); gid++) { + pcb_layergrp_t *g = &pcb->LayerGroups.grp[gid]; + + pcb_bool_op(g->open, open); + + if (vis == PCB_BOOL_PRESERVE) { + /* the group is visible exactly if if any layer is visible */ + g->vis = 0; + for(n = 0; n < g->len; n++) { + pcb_layer_t *l = pcb_get_layer(pcb->Data, g->lid[n]); + if ((l != NULL) && (l->meta.real.vis)) { + g->vis = 1; + break; + } + } + } + else { + pcb_bool_op(g->vis, vis); + for(n = 0; n < g->len; n++) { + pcb_layer_t *l = pcb_get_layer(pcb->Data, g->lid[n]); + pcb_bool_op(l->meta.real.vis, vis); + } + } + } + /* do NOT generate an event: some callers want to handle that */ +} + +static void layer_vis_grp_defaults(void *user_data, int argc, pcb_event_arg_t argv[]) +{ + pcb_layergrp_id_t gid; + + pcb_layer_vis_change_all(PCB, PCB_BOOL_SET, PCB_BOOL_PRESERVE); + + /* do not show paste and mask by default - they are distractive */ + for(gid = 0; gid < pcb_max_group(PCB); gid++) { + pcb_layergrp_t *g = &PCB->LayerGroups.grp[gid]; + if ((g->ltype & PCB_LYT_MASK) || (g->ltype & PCB_LYT_PASTE)) { + int n; + g->vis = pcb_false; + for(n = 0; n < g->len; n++) { + pcb_layer_t *l = pcb_get_layer(PCB->Data, g->lid[n]); + if (l == NULL) + pcb_message(PCB_MSG_ERROR, "broken layer groups; layer group references to non-existing layer\n"); + else + l->meta.real.vis = 0; + } + } + } + + pcb_event(PCB_EVENT_LAYERS_CHANGED, NULL); /* Can't send LAYERVIS_CHANGED here: it's a race condition, the layer selector could still have the old widgets */ +} + +pcb_layer_id_t pcb_layer_vis_last_lyt(pcb_layer_type_t target) +{ + int n; + /* find the last used match on stack first */ + for(n = 0; n < PCB_MAX_LAYER; n++) { + pcb_layer_id_t lid = pcb_layer_stack[n]; + pcb_layer_type_t lyt = pcb_layer_flags(PCB, lid); + if ((lyt & target) == target) + return lid; + } + + /* if no match, find any matching layer */ + for(n = 0; n < PCB_MAX_LAYER; n++) { + pcb_layer_type_t lyt = pcb_layer_flags(PCB, n); + if ((lyt & target) == target) + return n; + } + + return -1; +} + +void pcb_hid_save_and_show_layer_ons(int *save_array) +{ + int i; + for (i = 0; i < pcb_max_layer; i++) { + save_array[i] = PCB->Data->Layer[i].meta.real.vis; + PCB->Data->Layer[i].meta.real.vis = 1; + } +} + +void pcb_hid_restore_layer_ons(int *save_array) +{ + int i; + for (i = 0; i < pcb_max_layer; i++) + PCB->Data->Layer[i].meta.real.vis = save_array[i]; +} + +static const char *layer_vis_cookie = "core_layer_vis"; + +void pcb_layer_vis_init(void) +{ + conf_native_t *n_mask = conf_get_field("editor/show_mask"); + static conf_hid_callbacks_t cbs_mask; + + layer_vis_conf_id = conf_hid_reg(layer_vis_cookie, NULL); + + if (n_mask != NULL) { + memset(&cbs_mask, 0, sizeof(conf_hid_callbacks_t)); + cbs_mask.val_change_post = layer_vis_chg_mask; + conf_hid_set_cb(n_mask, layer_vis_conf_id, &cbs_mask); + } + + pcb_event_bind(PCB_EVENT_BOARD_CHANGED, layer_vis_grp_defaults, NULL, layer_vis_cookie); +} + +void pcb_layer_vis_uninit(void) +{ + pcb_event_unbind_allcookie(layer_vis_cookie); + conf_hid_unreg(layer_vis_cookie); +} Index: tags/2.1.2/src/layer_vis.h =================================================================== --- tags/2.1.2/src/layer_vis.h (nonexistent) +++ tags/2.1.2/src/layer_vis.h (revision 24813) @@ -0,0 +1,68 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996,2004,2006 Thomas Nau + * Copyright (C) 2016 Tibor 'Igor2' Palinkas (pcb-rnd extensions) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +/* Layer visibility logics (affects the GUI and some exporters) */ + +#ifndef PCB_LAYER_VIS_H +#define PCB_LAYER_VIS_H + +#include "layer.h" + +/* changes the visibility of all layers in a group; returns the number of + changed layers; on should be 0 or 1 for setting the state or -1 for toggling it */ +int pcb_layervis_change_group_vis(pcb_layer_id_t Layer, int On, pcb_bool ChangeStackOrder); + +/* resets the layer visibility stack setting */ +void pcb_layervis_reset_stack(void); + +/* saves the layerstack setting */ +void pcb_layervis_save_stack(void); + +/* restores the layerstack setting */ +void pcb_layervis_restore_stack(void); + +/* Return the last used layer (or if none, any layer) that matches target type */ +pcb_layer_id_t pcb_layer_vis_last_lyt(pcb_layer_type_t target); + +/* Use this to temporarily enable all layers, so that they can be + exported even if they're not currently visible. save_array must be + PCB_MAX_LAYER+2 big. */ +void pcb_hid_save_and_show_layer_ons(int *save_array); + +/* Use this to restore them. */ +void pcb_hid_restore_layer_ons(int *save_array); + +/* (un)init config watches and events to keep layers in sync */ +void pcb_layer_vis_init(void); +void pcb_layer_vis_uninit(void); + +/* Open/close, on/off all layers and groups; does NOT generate an event */ +void pcb_layer_vis_change_all(pcb_board_t *pcb, pcb_bool_op_t open, pcb_bool_op_t vis); + +#endif Index: tags/2.1.2/src/list_common.h =================================================================== --- tags/2.1.2/src/list_common.h (nonexistent) +++ tags/2.1.2/src/list_common.h (revision 24813) @@ -0,0 +1,39 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2016 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#ifndef LIST_COMMON_H +#define LIST_COMMON_H + +/* iterate over all items of list and call func(item) */ +#define list_map0(list, itemtype, func) \ + do { \ + itemtype *__item__; \ + gdl_iterator_t it; \ + linelist_foreach((list), &it, __item__) \ + func(__item__); \ + } while(0) + +#endif Index: tags/2.1.2/src/list_conf.c =================================================================== --- tags/2.1.2/src/list_conf.c (nonexistent) +++ tags/2.1.2/src/list_conf.c (revision 24813) @@ -0,0 +1,30 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2016 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#define FROM_CONF_C +#include "conf.h" +#include "list_conf.h" +#include Index: tags/2.1.2/src/list_conf.h =================================================================== --- tags/2.1.2/src/list_conf.h (nonexistent) +++ tags/2.1.2/src/list_conf.h (revision 24813) @@ -0,0 +1,53 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2016 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#ifndef LIST_CONF_H +#define LIST_CONF_H + +#include "conf.h" + +#include + +#ifdef FROM_CONF_C +#define TDL_DONT_UNDEF +#endif + +#define TDL(x) conflist_ ## x +#define TDL_LIST_T conflist_t +#define TDL_LIST_U conflist_u +#define TDL_ITEM_T conf_listitem_t +#define TDL_FIELD link +#define TDL_SIZE_T size_t +#define TDL_FUNC + +#define conflist_foreach(list, iterator, loop_elem) \ + gdl_foreach_((&((list)->lst)), (iterator), (loop_elem)) + + +#include +#include + +#endif Index: tags/2.1.2/src/macro.h =================================================================== --- tags/2.1.2/src/macro.h (nonexistent) +++ tags/2.1.2/src/macro.h (revision 24813) @@ -0,0 +1,42 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +/* some commonly used macros not related to a special C-file + * the file is included by global.h after const.h */ + +#ifndef PCB_MACRO_H +#define PCB_MACRO_H + +#define PCB_ENTRIES(x) (sizeof((x))/sizeof((x)[0])) +#define PCB_UNKNOWN(a) ((a) && *(a) ? (a) : "(unknown)") +#define PCB_NSTRCMP(a, b) ((a) ? ((b) ? strcmp((a),(b)) : 1) : -1) +#define PCB_EMPTY(a) ((a) ? (a) : "") +#define PCB_EMPTY_STRING_P(a) ((a) ? (a)[0]==0 : 1) +#define PCB_XOR(a,b) (((a) && !(b)) || (!(a) && (b))) + +#endif Index: tags/2.1.2/src/main.c =================================================================== --- tags/2.1.2/src/main.c (nonexistent) +++ tags/2.1.2/src/main.c (revision 24813) @@ -0,0 +1,693 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996, 2004 Thomas Nau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + + +/* main program, initializes some stuff and handles user input + */ +#include "config.h" +#include + +static const char *EXPERIMENTAL = NULL; + +#include +#include +#include +#include /* Seed for srand() */ +#include +#include + +#include "board.h" +#include "brave.h" +#include "data.h" +#include "error.h" +#include "plug_io.h" +#include "buffer.h" +#include "crosshair.h" +#include "compat_lrealpath.h" +#include "polygon.h" +#include "buildin.h" +#include "build_run.h" +#include "file_loaded.h" +#include "flag.h" +#include "flag_str.h" +#include "plugins.h" +#include "plug_footprint.h" +#include "plug_import.h" +#include "event.h" +#include "funchash.h" +#include "conf.h" +#include "conf_core.h" +#include +#include "layer_vis.h" +#include "layer_ui.h" +#include "obj_text.h" +#include "pcb_minuid.h" +#include "tool.h" +#include "color.h" +#include "netlist2.h" + +#include "actions.h" +#include "actions_pcb.h" +#include "hid_init.h" +#include "compat_misc.h" + +/* ---------------------------------------------------------------------- + * initialize signal and error handlers + */ +static void InitHandler(void) +{ +#ifdef PCB_HAVE_SIGHUP + signal(SIGHUP, pcb_catch_signal); +#endif +#ifdef PCB_HAVE_SIGQUIT + signal(SIGQUIT, pcb_catch_signal); +#endif +#ifdef PCB_HAVE_SIGTERM + signal(SIGTERM, pcb_catch_signal); +#endif +#ifdef PCB_HAVE_SIGINT + signal(SIGINT, pcb_catch_signal); +#endif + +#ifdef NDEBUG +/* so that we get a core dump on segfault in debug mode */ +# ifdef PCB_HAVE_SIGABRT + signal(SIGABRT, pcb_catch_signal); +# endif +# ifdef PCB_HAVE_SIGSEGV + signal(SIGSEGV, pcb_catch_signal); +# endif +#endif + + /* calling external program by popen() may cause a PIPE signal, + so we ignore it */ +#ifdef PCB_HAVE_SIGPIPE + signal(SIGPIPE, SIG_IGN); +#endif +} + +/* ---------------------------------------------------------------------- + * Figure out the canonical name of the executed program + * and fix up the defaults for various paths + */ + +static void InitPaths(char *argv0) +{ + size_t l; + int haspath; + char *t1, *t2; + int found_bindir = 0, se = 0; + char *exec_prefix = NULL; + char *bindir = NULL; + + + /* see if argv0 has enough of a path to let lrealpath give the + * real path. This should be the case if you invoke pcb with + * something like /usr/local/bin/pcb or ./pcb or ./foo/pcb + * but if you just use pcb and it exists in your path, you'll + * just get back pcb again. + */ + +#ifndef NO_BINDIR_HEURISTICS + { + int i; + haspath = 0; + for (i = 0; i < strlen(argv0); i++) { + if (argv0[i] == PCB_DIR_SEPARATOR_C) + haspath = 1; + } + } +#endif + +#ifdef DEBUG + printf("InitPaths (%s): haspath = %d\n", argv0, haspath); +#endif + + if (haspath) { +#ifndef NO_BINDIR_HEURISTICS + bindir = pcb_lrealpath(argv0); +#endif + found_bindir = 1; + } + else { + char *path, *p, *tmps; + struct stat sb; + int r; + + tmps = getenv("PATH"); + + if (tmps != NULL) { + path = pcb_strdup(tmps); + + /* search through the font path for a font file */ + for (p = strtok(path, PCB_PATH_DELIMETER); p && *p; p = strtok(NULL, PCB_PATH_DELIMETER)) { +#ifdef DEBUG + printf("Looking for %s in %s\n", argv0, p); +#endif + if ((tmps = (char *) malloc((strlen(argv0) + strlen(p) + 2) * sizeof(char))) == NULL) { + fprintf(stderr, "InitPaths(): malloc failed\n"); + exit(1); + } + sprintf(tmps, "%s%s%s", p, PCB_DIR_SEPARATOR_S, argv0); + r = stat(tmps, &sb); + if (r == 0) { +#ifdef DEBUG + printf("Found it: \"%s\"\n", tmps); +#endif + bindir = pcb_lrealpath(tmps); + found_bindir = 1; + free(tmps); + break; + } + free(tmps); + } + free(path); + } + } + + if (found_bindir) { + /* strip off the executable name leaving only the path */ + t2 = NULL; + t1 = strchr(bindir, PCB_DIR_SEPARATOR_C); + while (t1 != NULL && *t1 != '\0') { + t2 = t1; + t1 = strchr(t2 + 1, PCB_DIR_SEPARATOR_C); + } + if (t2 != NULL) + *t2 = '\0'; + } + else { + /* we have failed to find out anything from argv[0] so fall back to the original + * install prefix + */ + bindir = pcb_strdup(BINDIR); + } + + /* now find the path to exec_prefix */ + l = strlen(bindir) + 1 + strlen(BINDIR_TO_EXECPREFIX) + 1; + if ((exec_prefix = (char *) malloc(l * sizeof(char))) == NULL) { + fprintf(stderr, "InitPaths(): malloc failed\n"); + exit(1); + } + sprintf(exec_prefix, "%s%s%s", bindir, PCB_DIR_SEPARATOR_S, BINDIR_TO_EXECPREFIX); + conf_set(CFR_INTERNAL, "rc/path/exec_prefix", -1, exec_prefix, POL_OVERWRITE); + + /* export the most important paths and data for child processes (e.g. parametric footprints) */ + se |= pcb_setenv("PCB_RND_VERSION", PCB_VERSION, 1); + se |= pcb_setenv("PCB_RND_REVISION", PCB_REVISION, 1); + se |= pcb_setenv("PCB_RND_PCBLIB", PCBSHAREDIR "/pcblib", 1); + se |= pcb_setenv("PCB_RND_SHARE", PCBSHAREDIR, 1); + se |= pcb_setenv("PCB_RND_LIB", PCBLIBDIR, 1); + se |= pcb_setenv("PCB_RND_EXEC_PREFIX", exec_prefix, 1); + + if (se != 0) + fprintf(stderr, "WARNING: setenv() failed - external commands such as parametric footprints may not have a proper environment\n"); + + free(exec_prefix); + free(bindir); +} + +/* ---------------------------------------------------------------------- + * main program + */ + +static const char *hid_name = NULL; +void pcb_set_hid_name(const char *new_hid_name) +{ + hid_name = new_hid_name; +} + + +#include "dolists.h" + +static char **hid_argv_orig; + +static void log_print_uninit_errs(const char *title) +{ + pcb_logline_t *n, *from = pcb_log_find_first_unseen(); + int printed = 0; + + for(n = from; n != NULL; n = n->next) { + if ((n->level >= PCB_MSG_INFO) || conf_core.rc.verbose) { + if (!printed) + fprintf(stderr, "*** %s:\n", title); + fprintf(stderr, "%s", n->str); + printed = 1; + } + } + if (printed) + fprintf(stderr, "\n\n"); +} + +void pcb_main_uninit(void) +{ + if (pcb_log_last != NULL) + pcb_log_last->seen = 1; /* ignore anything unseen before the uninit */ + + + pcb_brave_uninit(); + pcb_polygon_uninit(); + + if (PCB != NULL) { + pcb_uninit_buffers(PCB); + + /* Free up memory allocated to the PCB. Why bother when we're about to exit ? + * Because it removes some false positives from heap bug detectors such as + * valgrind. */ + pcb_board_free(PCB); + free(PCB); + } + PCB = NULL; + + pcb_text_uninit(); + pcb_layer_vis_uninit(); + + pcb_strflg_uninit_buf(); + pcb_strflg_uninit_layerlist(); + + pcb_hidlib_uninit(); /* plugin unload */ + + pcb_funchash_uninit(); + free(hid_argv_orig); + pcb_file_loaded_uninit(); + pcb_uilayer_uninit(); + pcb_cli_uninit(); + pcb_dynflag_uninit(); + + pcb_import_uninit(); + pcb_io_uninit(); + pcb_fp_uninit(); + pcb_fp_host_uninit(); + pcb_tool_uninit(); + + log_print_uninit_errs("Log produced during uninitialization"); + pcb_log_uninit(); +} + +static int arg_match(const char *in, const char *shrt, const char *lng) +{ + return ((shrt != NULL) && (strcmp(in, shrt) == 0)) || ((lng != NULL) && (strcmp(in, lng) == 0)); +} + +/* action table number of columns for a single action */ +const int PCB_ACTION_ARGS_WIDTH = 5; +const char *pcb_action_args[] = { +/*short, -long, action, help, hint-on-error */ + NULL, "-show-actions", "PrintActions()", "Print all available actions (human readable) and exit", NULL, + NULL, "-dump-actions", "DumpActions()", "Print all available actions (script readable) and exit", NULL, + NULL, "-dump-plugins", "DumpPlugins()", "Print all available plugins (script readable) and exit", NULL, + NULL, "-dump-plugindirs", "DumpPluginDirs()", "Print directories plugins might be loaded from and exit", NULL, + NULL, "-dump-oflags", "DumpObjFlags()", "Print object flags and exit", NULL, + NULL, "-show-paths", "PrintPaths()", "Print all configured paths and exit", NULL, + NULL, "-dump-config", "dumpconf(native,1)", "Print the config tree and exit", "Config dump not available - make sure you have configured pcb-rnd with --buildin-diag", + "V", "-version", "PrintVersion()", "Print version info and exit", NULL, + "V", "-dump-version", "DumpVersion()", "Print version info in script readable format and exit", NULL, + NULL, "-copyright", "PrintCopyright()", "Print copyright and exit", NULL, + NULL, NULL, NULL, NULL, NULL /* terminator */ +}; + +void print_pup_err(pup_err_stack_t *entry, char *string) +{ + pcb_message(PCB_MSG_ERROR, "puplug: %s\n", string); +} + +/* parse arguments using the gui; if fails and fallback is enabled, try the next gui */ +int gui_parse_arguments(int autopick_gui, int *hid_argc, char **hid_argv[]) +{ + conf_listitem_t *apg = NULL; + + if ((autopick_gui >= 0) && (conf_core.rc.hid_fallback)) { /* start from the GUI we are initializing first */ + int n; + const char *g; + + conf_loop_list_str(&conf_core.rc.preferred_gui, apg, g, n) { + if (n == autopick_gui) + break; + } + } + + for(;;) { + int res; + if (pcb_gui->get_export_options != NULL) + pcb_gui->get_export_options(NULL); + res = pcb_gui->parse_arguments(hid_argc, hid_argv); + if (res == 0) + break; /* HID accepted, don't try anything else */ + if (res < 0) { + pcb_message(PCB_MSG_ERROR, "Failed to initialize HID %s (unrecoverable, have to give up)\n", pcb_gui->name); + return -1; + } + fprintf(stderr, "Failed to initialize HID %s (recoverable)\n", pcb_gui->name); + if (apg == NULL) { + if (conf_core.rc.hid_fallback) { + ran_out_of_hids:; + pcb_message(PCB_MSG_ERROR, "Tried all available HIDs, all failed, giving up.\n"); + } + else + pcb_message(PCB_MSG_ERROR, "Not trying any other hid as fallback because rc/hid_fallback is disabled.\n"); + return -1; + } + + /* falling back to the next HID */ + do { + int n; + const char *g; + + apg = conf_list_next_str(apg, &g, &n); + if (apg == NULL) + goto ran_out_of_hids; + pcb_gui = pcb_hid_find_gui(g); + } while(pcb_gui == NULL); + } + return 0; +} + +#define we_are_exporting (pcb_gui->printer || pcb_gui->exporter) + +int main(int argc, char *argv[]) +{ + enum { + DO_SOMETHING, + DO_PRINT, + DO_EXPORT, + DO_GUI + } do_what = DO_SOMETHING; + int n, hid_argc = 0; + char *cmd, *arg, **hid_argv, **sp; + const char **cs; + const char *main_action = NULL, *main_action_hint = NULL; + char *command_line_pcb = NULL; + vtp0_t plugin_cli_conf; + int autopick_gui = -1; + + setlocale(LC_ALL, "C"); + + hid_argv_orig = hid_argv = calloc(sizeof(char *), argc); + /* init application: + * - make program name available for error handlers + * - initialize infrastructure (e.g. the conf system) + * - evaluate options + * - create an empty PCB with default symbols + * - register 'call on exit()' function + */ + + + /* Minimal conf setup before we do anything else */ + pcb_netlist_geo_init(); + pcb_minuid_init(); + pcb_hidlib_init1(); + pcb_color_init(); + pcb_layer_vis_init(); + pcb_brave_init(); + + vtp0_init(&plugin_cli_conf); + + /* process arguments */ + for(n = 1; n < argc; n++) { + cmd = argv[n]; + arg = argv[n+1]; + if (*cmd == '-') { + cmd++; + if ((strcmp(cmd, "?") == 0) || (strcmp(cmd, "h") == 0) || (strcmp(cmd, "-help") == 0)) { + if (arg != NULL) { + /* memory leak, but who cares for --help? */ + main_action = pcb_strdup_printf("PrintUsage(%s)", arg); + n++; + } + else + main_action = "PrintUsage()"; + goto next_arg; + } + if ((strcmp(cmd, "g") == 0) || (strcmp(cmd, "-gui") == 0) || (strcmp(cmd, "-hid") == 0)) { + do_what = DO_GUI; + hid_name = arg; + n++; + goto next_arg; + } + if ((strcmp(cmd, "x") == 0) || (strcmp(cmd, "-export") == 0)) { + do_what = DO_EXPORT; + hid_name = arg; + n++; + goto next_arg; + } + if ((strcmp(cmd, "p") == 0) || (strcmp(cmd, "-print") == 0)) { + do_what = DO_PRINT; + goto next_arg; + } + + for(cs = pcb_action_args; cs[2] != NULL; cs += PCB_ACTION_ARGS_WIDTH) { + if (arg_match(cmd, cs[0], cs[1])) { + if (main_action == NULL) { + main_action = cs[2]; + main_action_hint = cs[4]; + } + else + fprintf(stderr, "Warning: can't execute multiple command line actions, ignoring %s\n", argv[n]); + goto next_arg; + } + } + if (arg_match(cmd, "c", "-conf")) { + const char *why; + n++; /* eat up arg */ + if (strncmp(arg, "plugins/", 8) == 0) { + /* plugins are not yet loaded or initialized so their configs are + unavailable. Store these settings until plugins are up. This + should not happen to non-plugin config items as those might + affect how plugins are searched/loaded. */ + void **a = vtp0_alloc_append(&plugin_cli_conf, 1); + *a = arg; + } + else { + if (conf_set_from_cli(NULL, arg, NULL, &why) != 0) { + fprintf(stderr, "Error: failed to set config %s: %s\n", arg, why); + exit(1); + } + } + goto next_arg; + } + } + + /* didn't handle argument, save it for the HID */ + hid_argv[hid_argc++] = argv[n]; + + next_arg:; + } + pcb_hidlib_init2(pup_buildins); + pcb_actions_init_pcb_only(); + + setbuf(stdout, 0); + InitPaths(argv[0]); + + pcb_fp_init(); + + srand(time(NULL)); /* Set seed for rand() */ + + pcb_funchash_init(); + pcb_polygon_init(); + + /* Register a function to be called when the program terminates. + * This makes sure that data is saved even if LEX/YACC routines + * abort the program. + * If the OS doesn't have at least one of them, + * the critical sections will be handled by parse_l.l */ + atexit(pcb_emergency_save); + + pcb_text_init(); + pcb_tool_init(); + + if (pcb_pup.err_stack != NULL) { + pcb_message(PCB_MSG_ERROR, "Some of the static linked buildins could not be loaded:\n"); + pup_err_stack_process_str(&pcb_pup, print_pup_err); + } + + for(sp = pcb_pup_paths; *sp != NULL; sp++) { + pcb_message(PCB_MSG_DEBUG, "Loading plugins from '%s'\n", *sp); + pup_autoload_dir(&pcb_pup, *sp, (const char **)pcb_pup_paths); + } + if (pcb_pup.err_stack != NULL) { + pcb_message(PCB_MSG_ERROR, "Some of the dynamic linked plugins could not be loaded:\n"); + pup_err_stack_process_str(&pcb_pup, print_pup_err); + } + + { /* Now that plugins are already initialized, apply plugin config items */ + int n; + for(n = 0; n < vtp0_len(&plugin_cli_conf); n++) { + const char *why, *arg = plugin_cli_conf.array[n]; + if (conf_set_from_cli(NULL, arg, NULL, &why) != 0) { + fprintf(stderr, "Error: failed to set config %s: %s\n", arg, why); + exit(1); + } + } + vtp0_uninit(&plugin_cli_conf); + } + + /* Export pcb from command line if requested. */ + switch(do_what) { + case DO_PRINT: pcb_exporter = pcb_gui = pcb_hid_find_printer(); break; + case DO_EXPORT: pcb_exporter = pcb_gui = pcb_hid_find_exporter(hid_name); break; + case DO_GUI: + pcb_gui = pcb_hid_find_gui(hid_name); + if (pcb_gui == NULL) { + pcb_message(PCB_MSG_ERROR, "Can't find the gui (%s) requested.\n", hid_name); + exit(1); + } + break; + default: { + const char *g; + conf_listitem_t *i; + + pcb_gui = NULL; + conf_loop_list_str(&conf_core.rc.preferred_gui, i, g, autopick_gui) { + pcb_gui = pcb_hid_find_gui(g); + if (pcb_gui != NULL) + break; + } + + /* try anything */ + if (pcb_gui == NULL) { + pcb_message(PCB_MSG_WARNING, "Warning: can't find any of the preferred GUIs, falling back to anything available...\nYou may want to check if the plugin is loaded, try --dump-plugins and --dump-plugindirs\n"); + pcb_gui = pcb_hid_find_gui(NULL); + } + } + } + + /* Exit with error if GUI failed to start. */ + if (!pcb_gui) + exit(1); + +/* Initialize actions only when the gui is already known so only the right + one is registered (there can be only one GUI). */ +#include "generated_lists.h" + + /* plugins may have installed their new fields, reinterpret the config + (memory lht -> memory bin) to get the new fields */ + conf_update(NULL, -1); + + if (main_action != NULL) { + int res = pcb_parse_command(main_action, pcb_true); + if ((res != 0) && (main_action_hint != NULL)) + pcb_message(PCB_MSG_ERROR, "\nHint: %s\n", main_action_hint); + log_print_uninit_errs("main_action parse error"); + pcb_main_uninit(); + exit(res); + } + + if (gui_parse_arguments(autopick_gui, &hid_argc, &hid_argv) != 0) { + log_print_uninit_errs("Export plugin argument parse error"); + pcb_main_uninit(); + exit(1); + } + + /* Create a new PCB object in memory */ + PCB = pcb_board_new(0); + + if (PCB == NULL) { + pcb_message(PCB_MSG_ERROR, "Can't create an empty layout, exiting\n"); + log_print_uninit_errs("Initialization"); + exit(1); + } + + /* Add silk layers to newly created PCB */ + pcb_board_new_postproc(PCB, 1); + if (hid_argc > 0) + command_line_pcb = hid_argv[0]; + + pcb_layervis_reset_stack(); + + if (pcb_gui->gui) + pcb_crosshair_init(); + InitHandler(); + pcb_init_buffers(PCB); + + pcb_tool_select_by_id(PCB_MODE_ARROW); + + if (command_line_pcb) { + if (pcb_load_pcb(command_line_pcb, NULL, pcb_true, 0) != 0) { + if (we_are_exporting) { + pcb_message(PCB_MSG_ERROR, "Can not load file '%s' (specified on command line) for exporting or printing\n", command_line_pcb); + log_print_uninit_errs("Export load error"); + exit(1); + } + /* keep filename if load failed: file might not exist, save it by that name */ + PCB->Filename = pcb_strdup(command_line_pcb); + } + } + + if (conf_core.design.initial_layer_stack && conf_core.design.initial_layer_stack[0]) + pcb_message(PCB_MSG_ERROR, "Config setting desgin/initial_layer_stack is set but is deprecated and ignored. Please edit your config files to remove it.\n"); + + /* read the library file and display it if it's not empty */ + if (!pcb_fp_read_lib_all() && pcb_library.data.dir.children.used) + pcb_event(PCB_EVENT_LIBRARY_CHANGED, NULL); + + if (conf_core.rc.script_filename) { + pcb_message(PCB_MSG_INFO, "Executing startup script file %s\n", conf_core.rc.script_filename); + pcb_actionl("ExecuteFile", conf_core.rc.script_filename, NULL); + } + if (conf_core.rc.action_string) { + pcb_message(PCB_MSG_INFO, "Executing startup action %s\n", conf_core.rc.action_string); + pcb_parse_actions(conf_core.rc.action_string); + } + + if (we_are_exporting) { + if (pcb_data_is_empty(PCB->Data)) + pcb_message(PCB_MSG_WARNING, "Exporting empty board (nothing loaded or drawn).\n"); + pcb_gui->do_export(0); + log_print_uninit_errs("Exporting"); + pcb_main_uninit(); + exit(0); + } + + pcb_enable_autosave(); + + /* main loop */ + do { + if (EXPERIMENTAL != NULL) { + pcb_message(PCB_MSG_ERROR, "******************************** IMPORTANT ********************************\n"); + pcb_message(PCB_MSG_ERROR, "This revision of pcb-rnd is experimental, unstable, do NOT attempt to use\n"); + pcb_message(PCB_MSG_ERROR, "it for production. The reason for this state is:\n"); + pcb_message(PCB_MSG_ERROR, "%s\n", EXPERIMENTAL); + pcb_message(PCB_MSG_ERROR, "******************************** IMPORTANT ********************************\n"); + } + pcb_gui->do_export(0); + pcb_gui = pcb_next_gui; + pcb_next_gui = NULL; + if (pcb_gui != NULL) { + /* init the next GUI */ + pcb_gui->parse_arguments(&hid_argc, &hid_argv); + if (pcb_gui->gui) + pcb_crosshair_init(); + pcb_tool_select_by_id(PCB_MODE_ARROW); + pcb_event(PCB_EVENT_LIBRARY_CHANGED, NULL); + } + } while(pcb_gui != NULL); + + pcb_main_uninit(); + + return 0; +} Index: tags/2.1.2/src/main_act.c =================================================================== --- tags/2.1.2/src/main_act.c (nonexistent) +++ tags/2.1.2/src/main_act.c (revision 24813) @@ -0,0 +1,438 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * Copyright (C) 1997, 1998, 1999, 2000, 2001 Harry Eaton + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + * + * Old contact info: + * Harry Eaton, 6697 Buttonhole Ct, Columbia, MD 21044, USA + * haceaton@aplcomm.jhuapl.edu + * + */ + +#define Progname "pcb-rnd" + +#include "config.h" + +#include +#include "config.h" + +#include "undo.h" +#include "change.h" +#include "board.h" +#include "data.h" +#include "crosshair.h" +#include "compat_misc.h" +#include "layer.h" +#include "actions.h" +#include "hid_init.h" +#include "conf_core.h" +#include "plugins.h" +#include "build_run.h" +#include "file_loaded.h" +#include "safe_fs.h" +#include "flag_str.h" +#include "obj_common.h" + +static const char pcb_acts_PrintActions[] = "PrintActions()"; +static const char pcb_acth_PrintActions[] = "Print all actions available."; +fgw_error_t pcb_act_PrintActions(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + pcb_print_actions(); + PCB_ACT_IRES(0); + return 0; +} + +static const char pcb_acts_DumpActions[] = "DumpActions()"; +static const char pcb_acth_DumpActions[] = "Dump all actions available."; +fgw_error_t pcb_act_DumpActions(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + pcb_dump_actions(); + PCB_ACT_IRES(0); + return 0; +} + +/* print usage lines */ +static inline void u(const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + fputc('\n', stderr); + va_end(ap); +} + +static const char pcb_acts_PrintUsage[] = + "PrintUsage()\n" + "PrintUsage(plugin)"; + +static const char pcb_acth_PrintUsage[] = "Print command line arguments of pcb-rnd or a plugin loaded."; + +static int help0(void) +{ + pcb_hid_t **hl = pcb_hid_enumerate(); + int i; + + u("pcb-rnd Printed Circuit Board editing program, http://repo.hu/projects/pcb-rnd"); + u("For more information, please read the topic help pages:"); + u(" %s --help topic", Progname); + u("Topics are:"); + u(" invocation how to run pcb-rnd"); + u(" main main/misc flags (affecting none or all plugins)"); + for (i = 0; hl[i]; i++) + if (hl[i]->usage != NULL) + u(" %-20s %s", hl[i]->name, hl[i]->description); + return 0; +} + +extern const char *pcb_action_args[]; +extern const int PCB_ACTION_ARGS_WIDTH; +static int help_main(void) { + const char **cs; + for(cs = pcb_action_args; cs[2] != NULL; cs += PCB_ACTION_ARGS_WIDTH) { + fprintf(stderr, "%s [", Progname); + if (cs[0] != NULL) + fprintf(stderr, "-%s", cs[0]); + if ((cs[0] != NULL) && (cs[1] != NULL)) + fprintf(stderr, "|"); + if (cs[1] != NULL) + fprintf(stderr, "-%s", cs[1]); + fprintf(stderr, "] %s\n", cs[3]); + } + return 0; +} + +static int help_invoc(void) +{ + pcb_hid_t **hl = pcb_hid_enumerate(); + int i; + int n_printer = 0, n_gui = 0, n_exporter = 0; + + u("pcb-rnd invocation:"); + u(""); + u("%s [main options] See --help main", Progname); + u(""); + u("%s [generics] [--gui GUI] [gui options] interactive GUI", Progname); + + u("Available GUI hid%s:", n_gui == 1 ? "" : "s"); + for (i = 0; hl[i]; i++) + if (hl[i]->gui) + fprintf(stderr, "\t%-8s %s\n", hl[i]->name, hl[i]->description); + + u("\n%s [generics] -p [printing options] \tto print", Progname); + u("Available printing hid%s:", n_printer == 1 ? "" : "s"); + for (i = 0; hl[i]; i++) + if (hl[i]->printer) + fprintf(stderr, "\t%-8s %s\n", hl[i]->name, hl[i]->description); + + u("\n%s [generics] -x hid [export options] \tto export", Progname); + u("Available export hid%s:", n_exporter == 1 ? "" : "s"); + for (i = 0; hl[i]; i++) + if (hl[i]->exporter) + fprintf(stderr, "\t%-8s %s\n", hl[i]->name, hl[i]->description); + + + u("\nGenerics:"); + u("-c conf/path=value set the value of a configuration item (in CFR_CLI)"); + + return 0; +} + +fgw_error_t pcb_act_PrintUsage(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + const char *topic = NULL, *subt = NULL; + PCB_ACT_MAY_CONVARG(1, FGW_STR, PrintUsage, topic = argv[1].val.str); + PCB_ACT_IRES(0); + + u(""); + if (topic != NULL) { + pcb_hid_t **hl = pcb_hid_enumerate(); + int i; + + if (strcmp(topic, "invocation") == 0) return help_invoc(); + if (strcmp(topic, "main") == 0) return help_main(); + + for (i = 0; hl[i]; i++) { + if ((hl[i]->usage != NULL) && (strcmp(topic, hl[i]->name) == 0)) { + PCB_ACT_MAY_CONVARG(2, FGW_STR, PrintUsage, subt = argv[2].val.str); + PCB_ACT_IRES(hl[i]->usage(subt)); + return 0; + } + } + fprintf(stderr, "No help available for %s\n", topic); + PCB_ACT_IRES(-1); + return 0; + } + else + help0(); + return 0; +} + + +static const char pcb_acts_PrintVersion[] = "PrintVersion()"; +static const char pcb_acth_PrintVersion[] = "Print version."; +fgw_error_t pcb_act_PrintVersion(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + printf("%s\n", pcb_get_info_program()); + PCB_ACT_IRES(0); + return 0; +} + +static const char pcb_acts_DumpVersion[] = "DumpVersion()"; +static const char pcb_acth_DumpVersion[] = "Dump version in script readable format."; +fgw_error_t pcb_act_DumpVersion(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + printf("%s\n", PCB_VERSION); + printf("%s\n", PCB_REVISION); + PCB_ACT_IRES(0); + return 0; +} + +static const char pcb_acts_PrintCopyright[] = "PrintCopyright()"; +static const char pcb_acth_PrintCopyright[] = "Print copyright notice."; +fgw_error_t pcb_act_PrintCopyright(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + printf("%s\n", pcb_get_info_copyright()); + printf("%s\n", pcb_get_info_license()); + + printf(" This program is free software; you can redistribute it and/or modify\n" + " it under the terms of the GNU General Public License as published by\n" + " the Free Software Foundation; either version 2 of the License, or\n" + " (at your option) any later version.\n\n"); + printf(" This program is distributed in the hope that it will be useful,\n" + " but WITHOUT ANY WARRANTY; without even the implied warranty of\n" + " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" + " GNU General Public License for more details.\n\n"); + printf(" You should have received a copy of the GNU General Public License\n" + " along with this program; if not, write to the Free Software\n" + " Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n\n"); + PCB_ACT_IRES(0); + return 0; +} + +static const char pcb_acts_PrintPaths[] = "PrintPaths()"; +static const char pcb_acth_PrintPaths[] = "Print full paths and search paths."; +static void print_list(const conflist_t *cl) +{ + int n; + conf_listitem_t *ci; + const char *p; + + printf(" "); + conf_loop_list_str(cl, ci, p, n) { + printf("%c%s", (n == 0) ? '"' : ':', p); + } + printf("\"\n"); +} +fgw_error_t pcb_act_PrintPaths(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + htsp_entry_t *e; + conf_fields_foreach(e) { + conf_native_t *n = e->value; + if ((strncmp(n->hash_path, "rc/path/", 8) == 0) && (n->type == CFN_STRING) && (n->used == 1)) + printf("%-32s = %s\n", n->hash_path, n->val.string[0]); + } + printf("rc/default_font_file ="); print_list(&conf_core.rc.default_font_file); + printf("rc/library_search_paths ="); print_list(&conf_core.rc.library_search_paths); + printf("rc/library_shell = \"%s\"\n", conf_core.rc.library_shell); + PCB_ACT_IRES(0); + return 0; +} + + +static const char pcb_acts_PrintFiles[] = "PrintFiles()"; +static const char pcb_acth_PrintFiles[] = "Print files currently loaded."; +static void print_cat(pcb_file_loaded_t *cat) +{ + htsp_entry_t *e; + printf("%s\n", cat->name); + for (e = htsp_first(&cat->data.category.children); e; e = htsp_next(&cat->data.category.children, e)) { + pcb_file_loaded_t *file = e->value; + printf(" %s\t%s\t%s\n", file->name, file->data.file.path, file->data.file.desc); + } +} +fgw_error_t pcb_act_PrintFiles(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + htsp_entry_t *e; + printf("# Data files loaded\n"); + for (e = htsp_first(&pcb_file_loaded); e; e = htsp_next(&pcb_file_loaded, e)) + print_cat(e->value); + PCB_ACT_IRES(0); + return 0; +} + +static const char pcb_acts_DumpPlugins[] = "DumpPlugins()"; +static const char pcb_acth_DumpPlugins[] = "Print plugins loaded in a format digestable by scripts."; +fgw_error_t pcb_act_DumpPlugins(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + pup_plugin_t *p; + const pup_buildin_t **bu; + int n; + + printf("#state\tname\tbuildin\tautoload\trefco\tloaded_from\n"); + + for(p = pcb_pup.plugins; p != NULL; p = p->next) + printf("loaded\t%s\t%d\t%d\t%d\t%s\n", + p->name, + !!(p->flags & PUP_FLG_STATIC), !!(p->flags & PUP_FLG_AUTOLOAD), p->references, + (p->path == NULL ? "" : p->path)); + + for(n = 0, bu = pcb_pup.bu; n < pcb_pup.bu_used; n++, bu++) + if (pup_lookup(&pcb_pup, (*bu)->name) == NULL) + printf("unloaded buildin\t%s\t1\t0\t0\t\n", (*bu)->name); + + PCB_ACT_IRES(0); + return 0; +} + + +static const char pcb_acts_DumpPluginDirs[] = "DumpPluginDirs()"; +static const char pcb_acth_DumpPluginDirs[] = "Print plugins directories in a format digestable by scripts."; +fgw_error_t pcb_act_DumpPluginDirs(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + char **p; + for(p = pcb_pup_paths; *p != NULL; p++) + printf("%s\n", *p); + + PCB_ACT_IRES(0); + return 0; +} + +static const char pcb_acts_DumpObjFlags[] = "DumpObjFlags()"; +static const char pcb_acth_DumpObjFlags[] = "Print a script processable digest of all flags, per object type"; +static void dumpoflg(void *ctx, unsigned long flg, const pcb_flag_bits_t *fb) +{ + printf(" %lx %s %s\n", flg, fb->name, fb->help); +} +fgw_error_t pcb_act_DumpObjFlags(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + unsigned long ot, max = PCB_OBJ_CLASS_REAL + 1; + + for(ot = 1; ot < max; ot <<= 1) { + const char *name = pcb_obj_type_name(ot); + + if (*name == '<') + continue; + printf("%s\n", name); + pcb_strflg_map(0x7fffffff, ot, NULL, dumpoflg); + } + + PCB_ACT_IRES(0); + return 0; +} + +static const char pcb_acts_System[] = "System(shell_cmd)"; +static const char pcb_acth_System[] = "Run shell command"; +fgw_error_t pcb_act_System(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + char tmp[128]; + const char *cmd; + + PCB_ACT_CONVARG(1, FGW_STR, System, cmd = argv[1].val.str); + PCB_ACT_IRES(0); + + pcb_setenv("PCB_RND_BOARD_FILE_NAME", PCB->Filename == NULL ? "" : PCB->Filename, 1); + pcb_snprintf(tmp, sizeof(tmp), "%mm", pcb_crosshair.X); + pcb_setenv("PCB_RND_CROSSHAIR_X_MM", tmp, 1); + pcb_snprintf(tmp, sizeof(tmp), "%mm", pcb_crosshair.Y); + pcb_setenv("PCB_RND_CROSSHAIR_Y_MM", tmp, 1); + pcb_setenv("PCB_RND_CURRENT_LAYER_NAME", CURRENT->name, 1); + PCB_ACT_IRES(pcb_system(cmd)); + return 0; +} + +static const char pcb_acts_ExecuteFile[] = "ExecuteFile(filename)"; +static const char pcb_acth_ExecuteFile[] = "Run actions from the given file."; +/* DOC: executefile.html */ +fgw_error_t pcb_act_ExecuteFile(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + FILE *fp; + const char *fname; + char line[256]; + int n = 0; + char *sp; + + PCB_ACT_CONVARG(1, FGW_STR, ExecuteFile, fname = argv[1].val.str); + + if ((fp = pcb_fopen(fname, "r")) == NULL) { + fprintf(stderr, "Could not open actions file \"%s\".\n", fname); + return 1; + } + + defer_updates = 1; + defer_needs_update = 0; + while (fgets(line, sizeof(line), fp) != NULL) { + n++; + sp = line; + + /* eat the trailing newline */ + while (*sp && *sp != '\r' && *sp != '\n') + sp++; + *sp = '\0'; + + /* eat leading spaces and tabs */ + sp = line; + while (*sp && (*sp == ' ' || *sp == '\t')) + sp++; + + /* + * if we have anything left and its not a comment line + * then execute it + */ + + if (*sp && *sp != '#') { + /*pcb_message("%s : line %-3d : \"%s\"\n", fname, n, sp); */ + pcb_parse_actions(sp); + } + } + + defer_updates = 0; + if (defer_needs_update) { + pcb_undo_inc_serial(); + pcb_gui->invalidate_all(); + } + fclose(fp); + PCB_ACT_IRES(0); + return 0; +} + +pcb_action_t main_action_list[] = { + {"PrintActions", pcb_act_PrintActions, pcb_acth_PrintActions, pcb_acts_PrintActions}, + {"DumpActions", pcb_act_DumpActions, pcb_acth_DumpActions, pcb_acts_DumpActions}, + {"PrintUsage", pcb_act_PrintUsage, pcb_acth_PrintUsage, pcb_acts_PrintUsage}, + {"PrintVersion", pcb_act_PrintVersion, pcb_acth_PrintVersion, pcb_acts_PrintVersion}, + {"DumpVersion", pcb_act_DumpVersion, pcb_acth_DumpVersion, pcb_acts_DumpVersion}, + {"PrintCopyright", pcb_act_PrintCopyright, pcb_acth_PrintCopyright, pcb_acts_PrintCopyright}, + {"PrintPaths", pcb_act_PrintPaths, pcb_acth_PrintPaths, pcb_acts_PrintPaths}, + {"PrintFiles", pcb_act_PrintFiles, pcb_acth_PrintFiles, pcb_acts_PrintFiles}, + {"DumpPlugins", pcb_act_DumpPlugins, pcb_acth_DumpPlugins, pcb_acts_DumpPlugins}, + {"DumpPluginDirs", pcb_act_DumpPluginDirs, pcb_acth_DumpPluginDirs, pcb_acts_DumpPluginDirs}, + {"DumpObjFlags", pcb_act_DumpObjFlags, pcb_acth_DumpObjFlags, pcb_acts_DumpObjFlags}, + {"System", pcb_act_System, pcb_acth_System, pcb_acts_System}, + {"ExecCommand", pcb_act_System, pcb_acth_System, pcb_acts_System}, + {"ExecuteFile", pcb_act_ExecuteFile, pcb_acth_ExecuteFile, pcb_acts_ExecuteFile} +}; + +PCB_REGISTER_ACTIONS(main_action_list, NULL) Index: tags/2.1.2/src/math_helper.h =================================================================== --- tags/2.1.2/src/math_helper.h (nonexistent) +++ tags/2.1.2/src/math_helper.h (revision 24813) @@ -0,0 +1,70 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +#include + +/* --------------------------------------------------------------------------- + * some math constants + */ +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_SQRT1_2 +#define M_SQRT1_2 0.707106781 /* 1/sqrt(2) */ +#endif +#define PCB_M180 (M_PI/180.0) +#define PCB_RAD_TO_DEG (180.0/M_PI) +#define PCB_TAN_22_5_DEGREE_2 0.207106781 /* 0.5*tan(22.5) */ +#define PCB_COS_22_5_DEGREE 0.923879533 /* cos(22.5) */ +#define PCB_TAN_30_DEGREE 0.577350269 /* tan(30) */ +#define PCB_TAN_60_DEGREE 1.732050808 /* tan(60) */ +#define PCB_LN_2_OVER_2 0.346573590 +#define PCB_TO_RADIANS(degrees) (PCB_M180 * (degrees)) +#define PCB_SQRT2 1.41421356237309504880 /* sqrt(2) */ + +#define PCB_CLAMP(x, low, high) (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x))) +#define PCB_ABS(a) (((a) < 0) ? -(a) : (a)) +#define PCB_SQUARE(x) ((float) (x) * (float) (x)) + +/* --------------------------------------------------------------------------- + * misc macros, some might already be defined by + */ +#ifndef MIN +#define MIN(a,b) ((a) < (b) ? (a) : (b)) +#define MAX(a,b) ((a) > (b) ? (a) : (b)) +#endif +#ifndef SGN +#define SGN(a) ((a) >0 ? 1 : ((a) == 0 ? 0 : -1)) +#endif +#define PCB_SGNZ(a) ((a) >=0 ? 1 : -1) +#define PCB_MAKE_MIN(a,b) if ((b) < (a)) (a) = (b) +#define PCB_MAKE_MAX(a,b) if ((b) > (a)) (a) = (b) + + +#define PCB_SWAP_SIGN_X(x) (x) +#define PCB_SWAP_SIGN_Y(y) (-(y)) Index: tags/2.1.2/src/misc_util.c =================================================================== --- tags/2.1.2/src/misc_util.c (nonexistent) +++ tags/2.1.2/src/misc_util.c (revision 24813) @@ -0,0 +1,264 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996,2004,2006 Thomas Nau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +/* misc functions used by several modules + */ + +#include "config.h" +#include +#include +#include +#include +#include +#include +#include +#include "misc_util.h" +#include "unit.h" + +/* pcb_distance() should be used so that there is only one + * place to deal with overflow/precision errors + */ +double pcb_distance(double x1, double y1, double x2, double y2) +{ + double delta_x = (x2 - x1); + double delta_y = (y2 - y1); + return sqrt(delta_x * delta_x + delta_y * delta_y); +} + +/* pcb_distance2() should be used so that there is only one + * place to deal with overflow/precision errors + */ +double pcb_distance2(double x1, double y1, double x2, double y2) +{ + double delta_x = (x2 - x1); + double delta_y = (y2 - y1); + return delta_x * delta_x + delta_y * delta_y; +} + +double pcb_get_value(const char *val, const char *units, pcb_bool * absolute, pcb_bool *success) +{ + return pcb_get_value_ex(val, units, absolute, NULL, "cmil", success); +} + +pcb_bool pcb_get_value_unit(const char *val, pcb_bool *absolute, int unit_strict, double *val_out, const pcb_unit_t **unit_out) +{ + int ul, ulo = 0; + const char *start = val; + + if ((*start == '-') || (*start == '+')) { + start++; + ulo = 1; + if (absolute != NULL) + *absolute = pcb_false; + } + else if (absolute != NULL) + *absolute = pcb_true; + + ul = strspn(start, "0123456789."); + if (ul > 0) + ul += ulo; + if ((ul > 0) && (val[ul] != '\0')) { + const char *unit = val+ul; + const pcb_unit_t *u; + + while(isspace(*unit)) unit++; + if (*unit == '\0') + goto err; + else if ((unit[0] == 'm') && (unit[1] == '\0')) { + /* corner case: mil and mm starts with m, and we rarely want to specify anything in meter, so ignore it */ + goto err; + } + + u = get_unit_struct_(unit, unit_strict); + if (u != NULL) { + pcb_bool succ; + double crd; + + crd = pcb_get_value(val, unit, NULL, &succ); + if (succ) { + *val_out = crd; + *unit_out = u; + return pcb_true; + } + } + } + + err:; + *val_out = 0; + *unit_out = NULL; + return pcb_false; +} + + +double pcb_get_value_ex(const char *val, const char *units, pcb_bool * absolute, pcb_unit_list_t extra_units, const char *default_unit, pcb_bool *success) +{ + double value; + int n = -1; + pcb_bool scaled = 0; + pcb_bool dummy; + + /* Allow NULL to be passed for absolute */ + if (absolute == NULL) + absolute = &dummy; + + /* if the first character is a sign we have to add the + * value to the current one + */ + if (*val == '=') { + *absolute = pcb_true; + sscanf(val + 1, "%lf%n", &value, &n); + n++; + } + else { + if (isdigit((int) *val)) + *absolute = pcb_true; + else + *absolute = pcb_false; + sscanf(val, "%lf%n", &value, &n); + } + if (n <= 0) + goto fail; + + if (!units && n > 0) + units = val + n; + + while (units && isspace(*units)) + units++; + + if (units && *units) { + int i, unit_ok = 0; + const pcb_unit_t *unit = get_unit_struct(units); + if (unit != NULL) { + value = pcb_unit_to_coord(unit, value); + scaled = 1; + unit_ok = 1; + } + if (extra_units) { + for (i = 0; *extra_units[i].suffix; ++i) { + if (strncmp(units, extra_units[i].suffix, strlen(extra_units[i].suffix)) == 0) { + value *= extra_units[i].scale; + if (extra_units[i].flags & PCB_UNIT_PERCENT) + value /= 100.0; + scaled = 1; + unit_ok = 1; + } + } + } + if ((!unit_ok) && (success != NULL)) /* there was something after the number but it doesn't look like a valid unit */ + goto fail; + } + + /* Apply default unit */ + if (!scaled && default_unit && *default_unit) { + int i; + const pcb_unit_t *unit = get_unit_struct(default_unit); + if (extra_units) + for (i = 0; *extra_units[i].suffix; ++i) + if (strcmp(extra_units[i].suffix, default_unit) == 0) { + value *= extra_units[i].scale; + if (extra_units[i].flags & PCB_UNIT_PERCENT) + value /= 100.0; + scaled = 1; + } + if (!scaled && unit != NULL) + value = pcb_unit_to_coord(unit, value); + } + + if (success != NULL) + *success = 1; + return value; + + fail:; + if (success != NULL) + *success = 0; + return 0; +} + +char *pcb_concat(const char *first, ...) +{ + gds_t buf; + va_list a; + const char *s; + + gds_init(&buf); + va_start(a, first); + for(s = first; s != NULL; s = va_arg(a, const char *)) + gds_append_str(&buf, s); + va_end(a); + return buf.array; +} + +/* --------------------------------------------------------------------------- + * strips leading and trailing blanks from the passed string and + * returns a pointer to the new 'duped' one or NULL if the old one + * holds only white space characters + */ +char *pcb_strdup_strip_wspace(const char *S) +{ + const char *p1, *p2; + char *copy; + size_t length; + + if (!S || !*S) + return NULL; + + /* strip leading blanks */ + for (p1 = S; *p1 && isspace((int) *p1); p1++); + + /* strip trailing blanks and get string length */ + length = strlen(p1); + for (p2 = p1 + length - 1; length && isspace((int) *p2); p2--, length--); + + /* string is not empty -> allocate memory */ + if (length) { + copy = (char *) realloc(NULL, length + 1); + strncpy(copy, p1, length); + copy[length] = '\0'; + return copy; + } + else + return NULL; +} + +char *pcb_text_wrap(char *inp, int len, int sep, int nonsep) +{ + int cnt; + char *s, *lastspc = NULL; + for(s = inp, cnt = 0; *s != '\0'; s++,cnt++) { + if ((*s == sep) && (nonsep >= 0)) + *s = nonsep; + if ((cnt >= len) && (lastspc != NULL)) { + cnt = 0; + *lastspc = sep; + lastspc = NULL; + } + else if (isspace(*s)) + lastspc = s; + } + return inp; +} Index: tags/2.1.2/src/misc_util.h =================================================================== --- tags/2.1.2/src/misc_util.h (nonexistent) +++ tags/2.1.2/src/misc_util.h (revision 24813) @@ -0,0 +1,69 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996,2006 Thomas Nau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +/* misc - independent of PCB data types */ + +#ifndef PCB_MISC_UTIL_H +#define PCB_MISC_UTIL_H + +#include "unit.h" +#include "pcb_bool.h" + +double pcb_distance(double x1, double y1, double x2, double y2); +double pcb_distance2(double x1, double y1, double x2, double y2); /* distance square */ + +enum pcb_unit_flags_e { PCB_UNIT_PERCENT = 1 }; + +typedef struct { + const char *suffix; + double scale; + enum pcb_unit_flags_e flags; +} pcb_unit_list_t[]; + +/* Convert string to coords; if units is not NULL, it's the caller supplied unit + string; absolute is set to false if non-NULL and val starts with + or -. + success indicates whether the conversion was successful. */ +double pcb_get_value(const char *val, const char *units, pcb_bool *absolute, pcb_bool *success); +double pcb_get_value_ex(const char *val, const char *units, pcb_bool * absolute, pcb_unit_list_t extra_units, const char *default_unit, pcb_bool *success); + +/* Convert a string of value+unit to coords and unit struct. Absolute is the same + as above; if unit_strict is non-zero, require full unit name. Returns whether + the conversion is succesful. */ +pcb_bool pcb_get_value_unit(const char *val, pcb_bool *absolute, int unit_strict, double *val_out, const pcb_unit_t **unit_out); + +char *pcb_concat(const char *first, ...); /* end with NULL */ +int pcb_mem_any_set(unsigned char *ptr, int bytes); + +char *pcb_strdup_strip_wspace(const char *S); + +/* Wrap text so that each segment is at most len characters long. Insert + sep character to break the string into segments. If nonsep >= 0, replace + original sep chaarcters with nonsep. */ +char *pcb_text_wrap(char *inp, int len, int sep, int nonsep); + +#endif Index: tags/2.1.2/src/move.c =================================================================== --- tags/2.1.2/src/move.c (nonexistent) +++ tags/2.1.2/src/move.c (revision 24813) @@ -0,0 +1,282 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +#include "config.h" +#include "conf_core.h" + +#include + +#include "board.h" +#include "data.h" +#include "draw.h" +#include "error.h" +#include "move.h" +#include "select.h" +#include "undo.h" +#include "event.h" +#include "actions.h" +#include "compat_misc.h" +#include "obj_arc_op.h" +#include "obj_line_op.h" +#include "obj_text_op.h" +#include "obj_subc_op.h" +#include "obj_poly_op.h" +#include "obj_pstk_op.h" +#include "obj_rat_op.h" + +pcb_opfunc_t MoveFunctions = { + pcb_lineop_move, + pcb_textop_move, + pcb_polyop_move, + pcb_lineop_move_point, + pcb_polyop_move_point, + pcb_arcop_move, + NULL, + NULL, + pcb_subcop_move, + pcb_pstkop_move +}; + +pcb_opfunc_t MoveFunctions_noclip = { + pcb_lineop_move_noclip, + pcb_textop_move_noclip, + pcb_polyop_move_noclip, + NULL, + NULL, + pcb_arcop_move_noclip, + NULL, + NULL, + NULL, /* subc */ + pcb_pstkop_move_noclip +}; + +pcb_opfunc_t ClipFunctions = { + pcb_lineop_clip, + pcb_textop_clip, + pcb_polyop_clip, + NULL, + NULL, + pcb_arcop_clip, + NULL, + NULL, + NULL, /* subc */ + pcb_pstkop_clip +}; + +static pcb_opfunc_t MoveToLayerFunctions = { + pcb_lineop_move_to_layer, + pcb_textop_move_to_layer, + pcb_polyop_move_to_layer, + NULL, + NULL, + pcb_arcop_move_to_layer, + pcb_ratop_move_to_layer, + NULL, + NULL, /* subc */ + NULL /* padstack */ +}; + +static pcb_opfunc_t CopyFunctions = { + pcb_lineop_copy, + pcb_textop_copy, + pcb_polyop_copy, + NULL, + NULL, + pcb_arcop_copy, + NULL, + NULL, + pcb_subcop_copy, + pcb_pstkop_copy +}; + + +void *pcb_move_obj(int Type, void *Ptr1, void *Ptr2, void *Ptr3, pcb_coord_t DX, pcb_coord_t DY) +{ + void *result; + pcb_opctx_t ctx; + + ctx.move.pcb = PCB; + ctx.move.dx = DX; + ctx.move.dy = DY; + pcb_undo_add_obj_to_move(Type, Ptr1, Ptr2, Ptr3, DX, DY); + result = pcb_object_operation(&MoveFunctions, &ctx, Type, Ptr1, Ptr2, Ptr3); + return result; +} + +void *pcb_move_obj_and_rubberband(int Type, void *Ptr1, void *Ptr2, void *Ptr3, pcb_coord_t DX, pcb_coord_t DY) +{ + pcb_opctx_t ctx; + void *ptr2; + + if ((DX == 0) && (DY == 0) && (conf_core.editor.move_linepoint_uses_route == 0)) + return NULL; + + ctx.move.pcb = PCB; + ctx.move.dx = DX; + ctx.move.dy = DY; + + pcb_draw_inhibit_inc(); + + switch(Type) { + case PCB_OBJ_ARC_POINT: + { + /* Get the initial arc point positions */ + pcb_arc_t * p_arc = ((pcb_arc_t *)pcb_crosshair.AttachedObject.Ptr2); + pcb_coord_t ox1,ox2,oy1,oy2; + pcb_coord_t nx1,nx2,ny1,ny2; + + pcb_arc_get_end(p_arc,0, &ox1, &oy1); + pcb_arc_get_end(p_arc,1, &ox2, &oy2); + + /* moving the endpoint of an arc is not really a move, but a change of arc properties */ + if (pcb_crosshair.AttachedObject.radius == 0) + pcb_arc_set_angles((pcb_layer_t *)Ptr1, (pcb_arc_t *)Ptr2, + pcb_crosshair.AttachedObject.start_angle, + pcb_crosshair.AttachedObject.delta_angle); + else + pcb_arc_set_radii((pcb_layer_t *)Ptr1, (pcb_arc_t *)Ptr2, + pcb_crosshair.AttachedObject.radius, + pcb_crosshair.AttachedObject.radius); + pcb_crosshair.AttachedObject.radius = 0; + + /* Get the new arc point positions so that we can calculate the position deltas */ + pcb_arc_get_end(p_arc,0, &nx1, &ny1); + pcb_arc_get_end(p_arc,1, &nx2, &ny2); + pcb_event(PCB_EVENT_RUBBER_MOVE, "icccc", 0, nx1-ox1, ny1-oy1, nx2-ox2, ny2-oy2); + } + break; + + case PCB_OBJ_ARC: + pcb_event(PCB_EVENT_RUBBER_MOVE, "icccc", 0, DX, DY, DX, DY); + pcb_undo_add_obj_to_move(Type, Ptr1, Ptr2, Ptr3, DX, DY); + ptr2 = pcb_object_operation(&MoveFunctions, &ctx, Type, Ptr1, Ptr2, Ptr3); + break; + + case PCB_OBJ_LINE_POINT : + pcb_event(PCB_EVENT_RUBBER_MOVE, "icc", 0, DX, DY); + ptr2 = pcb_lineop_move_point_with_route(&ctx, Ptr1, Ptr2, Ptr3); + break; + + case PCB_OBJ_LINE: + { + pcb_coord_t dx1 = DX; + pcb_coord_t dy1 = DY; + pcb_coord_t dx2 = DX; + pcb_coord_t dy2 = DY; + pcb_line_t *line = (pcb_line_t*) Ptr2; + int constrained = 0; + + if(conf_core.editor.rubber_band_keep_midlinedir) + pcb_event(PCB_EVENT_RUBBER_CONSTRAIN_MAIN_LINE, "pppppp", line, &constrained, &dx1, &dy1, &dx2, &dy2); + pcb_event(PCB_EVENT_RUBBER_MOVE, "icccc", constrained, dx1, dy1, dx2, dy2); + + ctx.move.dx = dx1; + ctx.move.dy = dy1; + + /* If the line ends have moved indpendently then move the individual points */ + if((dx1 != dx2) || (dy1 != dy2)) { + /* Move point1 form line */ + pcb_undo_add_obj_to_move(PCB_OBJ_LINE_POINT, + Ptr1, line, &line->Point1, + dx1, dy1); + pcb_lineop_move_point(&ctx, Ptr1, line, &line->Point1); + + /* Move point2 form line */ + pcb_undo_add_obj_to_move(PCB_OBJ_LINE_POINT, + Ptr1, line, &line->Point2, + dx2, dy2); + ctx.move.dx = dx2; + ctx.move.dy = dy2; + ptr2 = pcb_lineop_move_point(&ctx, Ptr1, line, &line->Point2); + } + /* Otherwise make a normal move */ + else { + pcb_undo_add_obj_to_move(Type, Ptr1, Ptr2, Ptr3, dx1, dy1); + ptr2 = pcb_object_operation(&MoveFunctions, &ctx, Type, Ptr1, Ptr2, Ptr3); + } + } + break; + + default: + pcb_event(PCB_EVENT_RUBBER_MOVE, "icc", 0, DX, DY); + pcb_undo_add_obj_to_move(Type, Ptr1, Ptr2, Ptr3, DX, DY); + ptr2 = pcb_object_operation(&MoveFunctions, &ctx, Type, Ptr1, Ptr2, Ptr3); + break; + } + + pcb_undo_inc_serial(); + + pcb_draw_inhibit_dec(); + pcb_draw(); + + return ptr2; +} + +void *pcb_move_obj_to_layer(int Type, void *Ptr1, void *Ptr2, void *Ptr3, pcb_layer_t *Target, pcb_bool enmasse) +{ + void *result; + pcb_opctx_t ctx; + + ctx.move.pcb = PCB; + ctx.move.dst_layer = Target; + ctx.move.more_to_come = enmasse; + + result = pcb_object_operation(&MoveToLayerFunctions, &ctx, Type, Ptr1, Ptr2, Ptr3); + pcb_undo_inc_serial(); + return result; +} + +pcb_bool pcb_move_selected_objs_to_layer(pcb_layer_t *Target) +{ + pcb_bool changed; + pcb_opctx_t ctx; + + ctx.move.pcb = PCB; + ctx.move.dst_layer = Target; + ctx.move.more_to_come = pcb_true; + + changed = pcb_selected_operation(PCB, PCB->Data, &MoveToLayerFunctions, &ctx, pcb_true, PCB_OBJ_ANY, pcb_false); + /* passing pcb_true to above operation causes Undoserial to auto-increment */ + return changed; +} + +void *pcb_copy_obj(int Type, void *Ptr1, void *Ptr2, void *Ptr3, pcb_coord_t DX, pcb_coord_t DY) +{ + void *ptr; + pcb_opctx_t ctx; + + ctx.copy.pcb = PCB; + ctx.copy.DeltaX = DX; + ctx.copy.DeltaY = DY; + ctx.copy.from_outside = 0; + + /* the subroutines add the objects to the undo-list */ + ptr = pcb_object_operation(&CopyFunctions, &ctx, Type, Ptr1, Ptr2, Ptr3); + pcb_undo_inc_serial(); + return ptr; +} Index: tags/2.1.2/src/move.h =================================================================== --- tags/2.1.2/src/move.h (nonexistent) +++ tags/2.1.2/src/move.h (revision 24813) @@ -0,0 +1,63 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +#ifndef PCB_MOVE_H +#define PCB_MOVE_H + +#include "config.h" + +/*** move ***/ +#define PCB_MOVE_TYPES \ + (PCB_OBJ_PSTK | PCB_OBJ_LINE | PCB_OBJ_TEXT | PCB_OBJ_SUBC | \ + PCB_OBJ_POLY | PCB_OBJ_POLY_POINT | PCB_OBJ_LINE_POINT | PCB_OBJ_ARC | PCB_OBJ_ARC_POINT) +#define PCB_MOVETOLAYER_TYPES \ + (PCB_OBJ_LINE | PCB_OBJ_TEXT | PCB_OBJ_POLY | PCB_OBJ_RAT | PCB_OBJ_ARC) + + +/* undoably moves an object by relative DX and DY. Doesn't bump + the undo serial. Operation wrapper. The rubberband version also moves + or modifies connected objects. */ +void *pcb_move_obj(int Type, void *Ptr1, void *Ptr2, void *Ptr3, pcb_coord_t DX, pcb_coord_t DY); +void *pcb_move_obj_and_rubberband(int Type, void *Ptr1, void *Ptr2, void *Ptr3, pcb_coord_t DX, pcb_coord_t DY); + +/* undoably moves objects to a different layer. Doesn't bump + the undo serial. Operation wrapper. */ +void *pcb_move_obj_to_layer(int Type, void *Ptr1, void *Ptr2, void *Ptr3, pcb_layer_t *Target, pcb_bool enmasse); +pcb_bool pcb_move_selected_objs_to_layer(pcb_layer_t *Target); + + +/*** copy ***/ +#define PCB_COPY_TYPES \ + (PCB_OBJ_PSTK | PCB_OBJ_LINE | PCB_OBJ_TEXT | \ + PCB_OBJ_SUBC | PCB_OBJ_POLY | PCB_OBJ_ARC) + +/* Undoably copies (duplicates) an object; the new objects is moved by DX,DY + (operation wrapper) */ +void *pcb_copy_obj(int Type, void *Ptr1, void *Ptr2, void *Ptr3, pcb_coord_t DX, pcb_coord_t DY); + +#endif Index: tags/2.1.2/src/netlist2.c =================================================================== --- tags/2.1.2/src/netlist2.c (nonexistent) +++ tags/2.1.2/src/netlist2.c (revision 24813) @@ -0,0 +1,967 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2019 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "config.h" +#include +#include +#include +#include + +#include "board.h" +#include "data.h" +#include "data_it.h" +#include "event.h" +#include "compat_misc.h" +#include "layer_grp.h" +#include "find.h" +#include "obj_term.h" +#include "conf_core.h" +#include "undo.h" +#include "obj_rat_draw.h" +#include "obj_subc_parent.h" +#include "search.h" +#include "remove.h" +#include "draw.h" + +#define TDL_DONT_UNDEF +#include "netlist2.h" +#include + +void pcb_net_term_free_fields(pcb_net_term_t *term) +{ + pcb_attribute_free(&term->Attributes); + free(term->refdes); + free(term->term); +} + +void pcb_net_term_free(pcb_net_term_t *term) +{ + pcb_net_term_free_fields(term); + free(term); +} + +static pcb_net_term_t *pcb_net_term_alloc(pcb_net_t *net, const char *refdes, const char *term) +{ + pcb_net_term_t *t; + + t = calloc(sizeof(pcb_net_term_t), 1); + t->type = PCB_OBJ_NET_TERM; + t->parent_type = PCB_PARENT_NET; + t->parent.net = net; + t->refdes = pcb_strdup(refdes); + t->term = pcb_strdup(term); + pcb_termlist_append(&net->conns, t); + return t; +} + +pcb_net_term_t *pcb_net_term_get(pcb_net_t *net, const char *refdes, const char *term, pcb_bool alloc) +{ + pcb_net_term_t *t; + + /* for allocation this is slow, O(N^2) algorithm, but other than a few + biggish networks like GND, there won't be too many connections anyway) */ + for(t = pcb_termlist_first(&net->conns); t != NULL; t = pcb_termlist_next(t)) { + if ((strcmp(t->refdes, refdes) == 0) && (strcmp(t->term, term) == 0)) + return t; + } + + if (alloc) + return pcb_net_term_alloc(net, refdes, term); + return NULL; +} + +pcb_net_term_t *pcb_net_term_get_by_obj(pcb_net_t *net, const pcb_any_obj_t *obj) +{ + pcb_data_t *data; + pcb_subc_t *sc; + + if (obj->term == NULL) + return NULL; + + if (obj->parent_type == PCB_PARENT_LAYER) + data = obj->parent.layer->parent.data; + else if (obj->parent_type == PCB_PARENT_DATA) + data = obj->parent.data; + else + return NULL; + + if (data->parent_type != PCB_PARENT_SUBC) + return NULL; + + sc = data->parent.subc; + if (sc->refdes == NULL) + return NULL; + + return pcb_net_term_get(net, sc->refdes, obj->term, pcb_false); +} + +pcb_net_term_t *pcb_net_term_get_by_pinname(pcb_net_t *net, const char *pinname, pcb_bool alloc) +{ + char tmp[256]; + char *pn, *refdes, *term; + int len = strlen(pinname)+1; + pcb_net_term_t *t = NULL; + + if (len <= sizeof(tmp)) { + pn = tmp; + memcpy(pn, pinname, len); + } + else + pn = pcb_strdup(pinname); + + + refdes = pn; + term = strchr(refdes, '-'); + if (term != NULL) { + *term = '\0'; + term++; + t = pcb_net_term_get(net, refdes, term, alloc); + } + + if (pn != tmp) + free(pn); + return t; + +} + + +int pcb_net_term_del(pcb_net_t *net, pcb_net_term_t *term) +{ + pcb_termlist_remove(term); + pcb_net_term_free(term); + return 0; +} + + +int pcb_net_term_del_by_name(pcb_net_t *net, const char *refdes, const char *term) +{ + pcb_net_term_t *t; + + for(t = pcb_termlist_first(&net->conns); t != NULL; t = pcb_termlist_next(t)) + if ((strcmp(t->refdes, refdes) == 0) && (strcmp(t->term, term) == 0)) + return pcb_net_term_del(net, t); + + return -1; +} + +pcb_bool pcb_net_name_valid(const char *netname) +{ + for(;*netname != '\0'; netname++) { + if (isalnum(*netname)) continue; + switch(*netname) { + case '_': + break; + return pcb_false; + } + } + return pcb_true; +} + +static pcb_net_t *pcb_net_alloc(pcb_board_t *pcb, pcb_netlist_t *nl, const char *netname) +{ + pcb_net_t *net; + + net = calloc(sizeof(pcb_net_t), 1); + net->type = PCB_OBJ_NET; + net->parent_type = PCB_PARENT_BOARD; + net->parent.board = pcb; + net->name = pcb_strdup(netname); + htsp_set(nl, net->name, net); + return net; +} + +pcb_net_t *pcb_net_get(pcb_board_t *pcb, pcb_netlist_t *nl, const char *netname, pcb_bool alloc) +{ + pcb_net_t *net; + + if (nl == NULL) + return NULL; + + if (!pcb_net_name_valid(netname)) + return NULL; + + net = htsp_get(nl, netname); + if (net != NULL) + return net; + + if (alloc) + return pcb_net_alloc(pcb, nl, netname); + + return NULL; +} + +pcb_net_t *pcb_net_get_icase(pcb_board_t *pcb, pcb_netlist_t *nl, const char *name) +{ + htsp_entry_t *e; + + for(e = htsp_first(nl); e != NULL; e = htsp_next(nl, e)) { + pcb_net_t *net = e->value; + if (pcb_strcasecmp(name, net->name) == 0) + break; + } + + if (e == NULL) + return NULL; + return e->value; +} + +pcb_net_t *pcb_net_get_regex(pcb_board_t *pcb, pcb_netlist_t *nl, const char *rx) +{ + htsp_entry_t *e; + re_sei_t *regex; + + regex = re_sei_comp(rx); + if (re_sei_errno(regex) != 0) + return NULL; + + for(e = htsp_first(nl); e != NULL; e = htsp_next(nl, e)) { + pcb_net_t *net = e->value; + if (re_sei_exec(regex, net->name)) + break; + } + re_sei_free(regex); + + if (e == NULL) + return NULL; + return e->value; +} + +pcb_net_t *pcb_net_get_user(pcb_board_t *pcb, pcb_netlist_t *nl, const char *name_or_rx) +{ + pcb_net_t *net = pcb_net_get(pcb, nl, name_or_rx, 0); + if (net == NULL) + net = pcb_net_get_icase(pcb, nl, name_or_rx); + if (net == NULL) + net = pcb_net_get_regex(pcb, nl, name_or_rx); + return net; +} + +void pcb_net_free_fields(pcb_net_t *net) +{ + pcb_attribute_free(&net->Attributes); + free(net->name); + for(;;) { + pcb_net_term_t *term = pcb_termlist_first(&net->conns); + if (term == NULL) + break; + pcb_termlist_remove(term); + pcb_net_term_free(term); + } +} + +void pcb_net_free(pcb_net_t *net) +{ + pcb_net_free_fields(net); + free(net); +} + +int pcb_net_del(pcb_netlist_t *nl, const char *netname) +{ + htsp_entry_t *e; + + if (nl == NULL) + return -1; + + e = htsp_getentry(nl, netname); + if (e == NULL) + return -1; + + pcb_net_free(e->value); + + htsp_delentry(nl, e); + return 0; +} + +/* crawl from a single terminal; "first" sould be a pointer to an int + initialized to 0. Returns number of objects found. */ +static pcb_cardinal_t pcb_net_term_crawl(const pcb_board_t *pcb, pcb_net_term_t *term, pcb_find_t *fctx, int *first, pcb_cardinal_t *missing) +{ + pcb_any_obj_t *o; + +/* there can be multiple terminals with the same ID, but it is enough to run find from the first: find.c will consider them all */ + o = pcb_term_find_name(pcb, pcb->Data, PCB_LYT_COPPER, term->refdes, term->term, NULL, NULL); + if (o == NULL) { + if (missing != NULL) + (*missing)++; + return 0; + } + + if ((*first) == 0) { + *first = 1; + return pcb_find_from_obj(fctx, PCB->Data, o); + } + + if (PCB_FIND_IS_MARKED(fctx, o)) + return 0; /* already visited, no need to run 'find' again */ + + return pcb_find_from_obj_next(fctx, PCB->Data, o); +} + +void pcb_net_short_ctx_init(pcb_short_ctx_t *sctx, const pcb_board_t *pcb, pcb_net_t *net) +{ + sctx->pcb = pcb; + sctx->current_net = net; + sctx->changed = 0; + sctx->missing = 0; + sctx->num_shorts = 0; + htsp_init(&sctx->found, strhash, strkeyeq); +} + +void pcb_net_short_ctx_uninit(pcb_short_ctx_t *sctx) +{ + htsp_entry_t *e; + for(e = htsp_first(&sctx->found); e != NULL; e = htsp_next(&sctx->found, e)) + free(e->key); + htsp_uninit(&sctx->found); + if (sctx->changed) { + pcb_gui->invalidate_all(); + conf_core.temp.rat_warn = pcb_true; + } +} + +/* Return 1 if net1-net2 (or net2-net1) is already seen as a short, return 0 + else. Save net1-net2 as seen. */ +static int short_ctx_is_dup(pcb_short_ctx_t *sctx, pcb_net_t *net1, pcb_net_t *net2) +{ + char *key; + int order; + + order = strcmp(net1->name, net2->name); + + if (order == 0) { + pcb_message(PCB_MSG_ERROR, "netlist internal error: short_ctx_is_dup() net %s shorted with itself?!\n", net1->name); + return 1; + } + if (order > 0) + key = pcb_concat(net1->name, "-", net2->name, NULL); + else + key = pcb_concat(net2->name, "-", net1->name, NULL); + + if (htsp_has(&sctx->found, key)) { + free(key); + return 1; + } + + htsp_set(&sctx->found, key, net1); + return 0; +} + +/* Short circuit found between net and an offender object that should not + be part of the net but is connected to the net */ +static void net_found_short(pcb_short_ctx_t *sctx, pcb_any_obj_t *offender) +{ + pcb_subc_t *sc = pcb_obj_parent_subc(offender); + int handled = 0; + + pcb_net_term_t *offt = pcb_net_find_by_refdes_term(&sctx->pcb->netlist[PCB_NETLIST_EDITED], sc->refdes, offender->term); + pcb_net_t *offn = NULL; + const char *offnn = ""; + + if (offt != NULL) { + offn = offt->parent.net; + offnn = offn->name; + if (short_ctx_is_dup(sctx, sctx->current_net, offn)) + return; + } + + if (offnn != NULL) + pcb_message(PCB_MSG_WARNING, "SHORT: net \"%s\" is shorted to \"%s\" at terminal %s-%s\n", sctx->current_net->name, offnn, sc->refdes, offender->term); + else + pcb_message(PCB_MSG_WARNING, "SHORT: net \"%s\" is shorted to terminal %s-%s\n", sctx->current_net->name, sc->refdes, offender->term); + + pcb_event(PCB_EVENT_NET_INDICATE_SHORT, "pppp", sctx->current_net, offender, offn, &handled); + if (!handled) { + pcb_net_term_t *orig_t = pcb_termlist_first(&sctx->current_net->conns); + pcb_any_obj_t *orig_o = pcb_term_find_name(sctx->pcb, sctx->pcb->Data, PCB_LYT_COPPER, orig_t->refdes, orig_t->term, NULL, NULL); + + /* dummy fallback: warning-highlight the two terminals */ + PCB_FLAG_SET(PCB_FLAG_WARN, offender); + if (orig_o != NULL) + PCB_FLAG_SET(PCB_FLAG_WARN, orig_o); + } + sctx->changed++; + sctx->num_shorts++; +} + +static int net_short_check(pcb_find_t *fctx, pcb_any_obj_t *new_obj, pcb_any_obj_t *arrived_from, pcb_found_conn_type_t ctype) +{ + if (new_obj->term != NULL) { + pcb_net_term_t *t; + pcb_short_ctx_t *sctx = fctx->user_data; + pcb_subc_t *sc = pcb_obj_parent_subc(new_obj); + + if ((sc == NULL) || (sc->refdes == NULL)) + return 0; + + /* if new_obj is a terminal on our net, return */ + for(t = pcb_termlist_first(&sctx->current_net->conns); t != NULL; t = pcb_termlist_next(t)) + if ((strcmp(t->refdes, sc->refdes) == 0) && (strcmp(t->term, new_obj->term) == 0)) + return 0; + + /* new_obj is not on our net but has a refdes-term -> must be a short */ + net_found_short(fctx->user_data, new_obj); + } + + return 0; +} + +pcb_cardinal_t pcb_net_crawl_flag(pcb_board_t *pcb, pcb_net_t *net, unsigned long setf, unsigned long clrf) +{ + pcb_find_t fctx; + pcb_net_term_t *t; + pcb_cardinal_t res = 0, n; + pcb_short_ctx_t sctx; + int first = 0; + + pcb_net_short_ctx_init(&sctx, pcb, net); + + memset(&fctx, 0, sizeof(fctx)); + fctx.flag_set = setf; + fctx.flag_clr = clrf; + fctx.flag_chg_undoable = 1; + fctx.only_mark_rats = 1; /* do not trust rats, but do mark them */ + fctx.user_data = &sctx; + fctx.found_cb = net_short_check; + + for(t = pcb_termlist_first(&net->conns), n = 0; t != NULL; t = pcb_termlist_next(t), n++) { + res += pcb_net_term_crawl(pcb, t, &fctx, &first, NULL); + } + + pcb_find_free(&fctx); + pcb_net_short_ctx_uninit(&sctx); + return res; +} + +pcb_net_term_t *pcb_net_find_by_refdes_term(const pcb_netlist_t *nl, const char *refdes, const char *term) +{ + htsp_entry_t *e; + + for(e = htsp_first(nl); e != NULL; e = htsp_next(nl, e)) { + pcb_net_t *net = (pcb_net_t *)e->value; + pcb_net_term_t *t; + + for(t = pcb_termlist_first(&net->conns); t != NULL; t = pcb_termlist_next(t)) + if ((strcmp(t->refdes, refdes) == 0) && (strcmp(t->term, term) == 0)) + return t; + } + + return NULL; +} + +pcb_net_term_t *pcb_net_find_by_pinname(const pcb_netlist_t *nl, const char *pinname) +{ + char tmp[256]; + char *pn, *refdes, *term; + int len = strlen(pinname)+1; + pcb_net_term_t *t = NULL; + + if (len <= sizeof(tmp)) { + pn = tmp; + memcpy(pn, pinname, len); + } + else + pn = pcb_strdup(pinname); + + refdes = pn; + term = strchr(refdes, '-'); + if (term != NULL) { + *term = '\0'; + term++; + t = pcb_net_find_by_refdes_term(nl, refdes, term); + } + + if (pn != tmp) + free(pn); + return t; +} + +pcb_net_term_t *pcb_net_find_by_obj(const pcb_netlist_t *nl, const pcb_any_obj_t *obj) +{ + const pcb_subc_t *sc; + + if (obj->term == NULL) + return NULL; + + sc = pcb_obj_parent_subc(obj); + if (sc == NULL) + return NULL; + + return pcb_net_find_by_refdes_term(nl, sc->refdes, obj->term); +} + + + +static int netname_sort(const void *va, const void *vb) +{ + const pcb_net_t **a = (const pcb_net_t **)va; + const pcb_net_t **b = (const pcb_net_t **)vb; + return strcmp((*a)->name, (*b)->name); +} + +pcb_net_t **pcb_netlist_sort(pcb_netlist_t *nl) +{ + pcb_net_t **arr; + htsp_entry_t *e; + long n; + + if (nl->used == 0) + return NULL; + arr = malloc((nl->used+1) * sizeof(pcb_net_t)); + + for(e = htsp_first(nl), n = 0; e != NULL; e = htsp_next(nl, e), n++) + arr[n] = e->value; + qsort(arr, nl->used, sizeof(pcb_net_t *), netname_sort); + arr[nl->used] = NULL; + return arr; +} + +#include "netlist_geo.c" + +pcb_cardinal_t pcb_net_map_subnets(pcb_short_ctx_t *sctx, pcb_rat_accuracy_t acc, vtp0_t *subnets) +{ + pcb_find_t fctx; + pcb_net_term_t *t; + pcb_cardinal_t drawn = 0, r, n, s1, s2, su, sd; + pcb_subnet_dist_t *connmx; + char *done; + int left, first = 0; + pcb_rat_t *line; + + + memset(&fctx, 0, sizeof(fctx)); + fctx.consider_rats = 1; /* keep existing rats and their connections */ + fctx.list_found = 1; + fctx.user_data = sctx; + fctx.found_cb = net_short_check; + + /* each component of a desired network is called a subnet; already connected + objects of each subnet is collected on a vtp0_t; object-lists per submnet + is saved in variable "subnets" */ + for(t = pcb_termlist_first(&sctx->current_net->conns), n = 0; t != NULL; t = pcb_termlist_next(t), n++) { + r = pcb_net_term_crawl(sctx->pcb, t, &fctx, &first, &sctx->missing); + if (r > 0) { + vtp0_t *objs = malloc(sizeof(vtp0_t)); + memcpy(objs, &fctx.found, sizeof(vtp0_t)); + vtp0_append(subnets, objs); + memset(&fctx.found, 0, sizeof(vtp0_t)); + } + } + + /* find the shortest connection between any two subnets and save the info + in connmx */ + connmx = calloc(sizeof(pcb_subnet_dist_t), vtp0_len(subnets) * vtp0_len(subnets)); + for(s1 = 0; s1 < vtp0_len(subnets); s1++) { + for(s2 = s1+1; s2 < vtp0_len(subnets); s2++) { + connmx[s2 * vtp0_len(subnets) + s1] = connmx[s1 * vtp0_len(subnets) + s2] = pcb_subnet_dist(sctx->pcb, subnets->array[s1], subnets->array[s2], acc); + } + } + + /* Start collecting subnets into one bug snowball of newly connected + subnets. done[subnet] is 1 if a subnet is already in the snowball. + Use a greedy algorithm: mark the first subnet as dine, then always + add the shortest from any 'undone' subnet to any 'done' */ + done = calloc(vtp0_len(subnets), 1); + done[0] = 1; + for(left = vtp0_len(subnets)-1; left > 0; left--) { + double best_dist = HUGE_VAL; + int bestu; + pcb_subnet_dist_t *best = NULL, *curr; + + for(su = 1; su < vtp0_len(subnets); su++) { + if (done[su]) continue; + for(sd = 0; sd < vtp0_len(subnets); sd++) { + curr = &connmx[su * vtp0_len(subnets) + sd]; + if ((done[sd]) && (curr->dist2 < best_dist)) { + bestu = su; + best_dist = curr->dist2; + best = curr; + } + } + } + + if (best == NULL) { + /* Unlikely: if there are enough restrictions on the search, e.g. + PCB_RATACC_ONLY_MANHATTAN for the old autorouter is on and some + subnets have only heavy terminals made of non-manhattan-lines, + we will not find a connection. When best is NULL, that means + no connection found between any undone subnet to any done subnet + found, so some subnets will remain disconnected (there is no point + in looping more, this won't improve) */ + sctx->missing++; + break; + } + + /* best connection is 'best' between from 'undone' network bestu; draw the rat */ + line = pcb_rat_new(sctx->pcb->Data, -1, + best->o1x, best->o1y, best->o2x, best->o2y, best->o1g, best->o2g, + conf_core.appearance.rat_thickness, pcb_no_flags(), + best->o1, best->o2); + if (line != NULL) { + if (best->dist2 == 0) + PCB_FLAG_SET(PCB_FLAG_VIA, line); + pcb_undo_add_obj_to_create(PCB_OBJ_RAT, line, line, line); + pcb_rat_invalidate_draw(line); + drawn++; + } + else + sctx->missing++; + done[bestu] = 1; + } + + /* cleanup */ + free(connmx); + free(done); + pcb_find_free(&fctx); + return drawn; +} + +void pcb_net_reset_subnets(vtp0_t *subnets) +{ + pcb_cardinal_t n; + for(n = 0; n < vtp0_len(subnets); n++) + vtp0_uninit(subnets->array[n]); + subnets->used = 0; +} + +void pcb_net_free_subnets(vtp0_t *subnets) +{ + pcb_net_reset_subnets(subnets); + vtp0_uninit(subnets); +} + + +pcb_cardinal_t pcb_net_add_rats(const pcb_board_t *pcb, pcb_net_t *net, pcb_rat_accuracy_t acc) +{ + pcb_cardinal_t res; + pcb_short_ctx_t sctx; + vtp0_t subnets; + + vtp0_init(&subnets); + pcb_net_short_ctx_init(&sctx, pcb, net); + res = pcb_net_map_subnets(&sctx, acc, &subnets); + pcb_net_short_ctx_uninit(&sctx); + pcb_net_free_subnets(&subnets); + return res; +} + + +pcb_cardinal_t pcb_net_add_all_rats(const pcb_board_t *pcb, pcb_rat_accuracy_t acc) +{ + htsp_entry_t *e; + pcb_cardinal_t drawn = 0; + pcb_short_ctx_t sctx; + vtp0_t subnets; + + vtp0_init(&subnets); + + pcb_net_short_ctx_init(&sctx, pcb, NULL); + + for(e = htsp_first(&pcb->netlist[PCB_NETLIST_EDITED]); e != NULL; e = htsp_next(&pcb->netlist[PCB_NETLIST_EDITED], e)) { + pcb_net_t *net = e->value; + if (acc & PCB_RATACC_ONLY_SELECTED) { + pcb_net_term_t *t; + int has_selection = 0; + for(t = pcb_termlist_first(&net->conns); t != NULL; t = pcb_termlist_next(t)) { + pcb_any_obj_t *o = pcb_term_find_name(pcb, pcb->Data, PCB_LYT_COPPER, t->refdes, t->term, NULL, NULL); + if ((o != NULL) && (PCB_FLAG_TEST(PCB_FLAG_SELECTED, o))) { + has_selection = 1; + break; + } + } + if (!has_selection) + continue; + } + + sctx.current_net = net; + if (sctx.current_net->inhibit_rats) + continue; + drawn += pcb_net_map_subnets(&sctx, acc, &subnets); + pcb_net_reset_subnets(&subnets); + } + + if (acc & PCB_RATACC_INFO) { + long rem = ratlist_length(&pcb->Data->Rat); + if (rem > 0) + pcb_message(PCB_MSG_INFO, "%d rat line%s remaining\n", rem, rem > 1 ? "s" : ""); + else if (acc & PCB_RATACC_ONLY_SELECTED) + pcb_message(PCB_MSG_WARNING, "No rat for any network that has selected terminal\n"); + else if (sctx.missing > 0) + pcb_message(PCB_MSG_WARNING, "Nothing more to add, but there are\neither rat-lines in the layout, disabled nets\nin the net-list, or missing components\n"); + else if (sctx.num_shorts == 0) + pcb_message(PCB_MSG_INFO, "Congratulations!!\n" "The layout is complete and has no shorted nets.\n"); + } + + vtp0_uninit(&subnets); + pcb_net_short_ctx_uninit(&sctx); + return drawn; +} + +void pcb_netlist_changed(int force_unfreeze) +{ + if (force_unfreeze) + PCB->netlist_frozen = 0; + if (PCB->netlist_frozen) + PCB->netlist_needs_update = 1; + else { + PCB->netlist_needs_update = 0; + pcb_event(PCB_EVENT_NETLIST_CHANGED, NULL); + } +} + +void pcb_netlist_init(pcb_netlist_t *nl) +{ + htsp_init(nl, strhash, strkeyeq); +} + + +void pcb_netlist_uninit(pcb_netlist_t *nl) +{ + htsp_entry_t *e; + + for(e = htsp_first(nl); e != NULL; e = htsp_next(nl, e)) + pcb_net_free(e->value); + + htsp_uninit(nl); +} + +void pcb_netlist_copy(pcb_board_t *pcb, pcb_netlist_t *dst, pcb_netlist_t *src) +{ + htsp_entry_t *e; + + assert(dst->used == 0); + for(e = htsp_first(src); e != NULL; e = htsp_next(src, e)) { + pcb_net_t *src_net, *dst_net; + pcb_net_term_t *src_term, *dst_term; + + src_net = e->value; + dst_net = pcb_net_alloc(pcb, dst, src_net->name); + dst_net->export_tmp = src_net->export_tmp; + dst_net->inhibit_rats = src_net->inhibit_rats; + pcb_attribute_copy_all(&dst_net->Attributes, &src_net->Attributes); + + for(src_term = pcb_termlist_first(&src_net->conns); src_term != NULL; src_term = pcb_termlist_next(src_term)) { + dst_term = pcb_net_term_alloc(dst_net, src_term->refdes, src_term->term); + pcb_attribute_copy_all(&dst_term->Attributes, &src_term->Attributes); + } + } +} + +/* Return the (most natural) copper group the obj is in */ +static pcb_layergrp_id_t get_side_group(pcb_board_t *pcb, pcb_any_obj_t *obj) +{ + switch(obj->type) { + case PCB_OBJ_ARC: + case PCB_OBJ_LINE: + case PCB_OBJ_POLY: + case PCB_OBJ_TEXT: + return pcb_layer_get_group_(obj->parent.layer); + case PCB_OBJ_PSTK: + if (pcb_pstk_shape((pcb_pstk_t *)obj, PCB_LYT_COPPER | PCB_LYT_TOP, 0) != NULL) + return pcb_layergrp_get_top_copper(); + if (pcb_pstk_shape((pcb_pstk_t *)obj, PCB_LYT_COPPER | PCB_LYT_BOTTOM, 0) != NULL) + return pcb_layergrp_get_bottom_copper(); + default: return -1; + } +} + +static pcb_rat_t *pcb_net_create_by_rat_(pcb_board_t *pcb, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2, pcb_any_obj_t *o1, pcb_any_obj_t *o2, pcb_bool interactive) +{ + pcb_subc_t *sc1, *sc2, *sctmp; + pcb_net_t *net1 = NULL, *net2 = NULL, *ntmp, *target_net = NULL; + pcb_layergrp_id_t group1, group2; + pcb_rat_t *res; + static long netname_cnt = 0; + char ratname_[32], *ratname, *id; + long old_len, new_len; + + if ((o1 == o2) || (o1 == NULL) || (o2 == NULL)) { + pcb_message(PCB_MSG_ERROR, "Missing start or end terminal\n"); + return NULL; + } + + { /* make sure at least one of the terminals is not on a net */ + pcb_net_term_t *term1, *term2; + + sc1 = pcb_obj_parent_subc(o1); + sc2 = pcb_obj_parent_subc(o2); + if ((sc1 == NULL) || (sc2 == NULL) || (sc1->refdes == NULL) || (sc2->refdes == NULL)) { + pcb_message(PCB_MSG_ERROR, "Both start or end terminal must be in a subcircuit with refdes\n"); + return NULL; + } + + term1 = pcb_net_find_by_refdes_term(&pcb->netlist[PCB_NETLIST_EDITED], sc1->refdes, o1->term); + term2 = pcb_net_find_by_refdes_term(&pcb->netlist[PCB_NETLIST_EDITED], sc2->refdes, o2->term); + if (term1 != NULL) net1 = term1->parent.net; + if (term2 != NULL) net1 = term2->parent.net; + + if ((net1 == net2) && (net1 != NULL)) { + pcb_message(PCB_MSG_ERROR, "Those terminals are already on the same net (%s)\n", net1->name); + return NULL; + } + if ((net1 != NULL) && (net2 != NULL)) { + pcb_message(PCB_MSG_ERROR, "Can not connect two existing nets with a rat (%s and %s)\n", net1->name, net2->name); + return NULL; + } + } + + /* swap vars so it's always o1 is off-net (and o2 may be in a net) */ + if (net1 != NULL) { + pcb_any_obj_t *otmp; + otmp = o1; o1 = o2; o2 = otmp; + sctmp = sc1; sc1 = sc2; sc2 = sctmp; + ntmp = net1; net1 = net2; net2 = ntmp; + } + + group1 = get_side_group(pcb, o1); + group2 = get_side_group(pcb, o2); + if ((group1 == -1) && (group2 == -1)) { + pcb_message(PCB_MSG_ERROR, "Can not determine copper layer group of that terminal\n"); + return NULL; + } + + /* passed all sanity checks, o1 is off-net; figure the target_net (create it if needed) */ + if ((net1 == NULL) && (net2 == NULL)) { + do { + sprintf(ratname_, "pcbrnd%ld", ++netname_cnt); + } while(htsp_has(&pcb->netlist[PCB_NETLIST_EDITED], ratname_)); + if (interactive) { + ratname = pcb_hid_prompt_for("Name of the new net", ratname_, "rat net name"); + if (ratname == NULL) /* cancel */ + return NULL; + } + else + ratname = ratname_; + target_net = pcb_net_get(pcb, &pcb->netlist[PCB_NETLIST_EDITED], ratname, 1); + + assert(target_net != NULL); + if (ratname != ratname_) + free(ratname); + } + else + target_net = net2; + + /* create the rat and add terminals in the target_net */ + res = pcb_rat_new(pcb->Data, -1, x1, y1, x2, y2, group1, group2, conf_core.appearance.rat_thickness, pcb_no_flags(), o1, o2); + + old_len = pcb_termlist_length(&target_net->conns); + pcb_net_term_get(target_net, sc1->refdes, o1->term, 1); + new_len = pcb_termlist_length(&target_net->conns); + if (new_len != old_len) { + id = pcb_concat(sc1->refdes, "-", o1->term, NULL); + pcb_ratspatch_append(pcb, RATP_ADD_CONN, id, target_net->name, NULL); + free(id); + } + + old_len = new_len; + pcb_net_term_get(target_net, sc2->refdes, o2->term, 1); + new_len = pcb_termlist_length(&target_net->conns); + if (new_len != old_len) { + id = pcb_concat(sc2->refdes, "-", o2->term, NULL); + pcb_ratspatch_append(pcb, RATP_ADD_CONN, id, target_net->name, NULL); + free(id); + } + + pcb_netlist_changed(0); + return res; +} + +static pcb_any_obj_t *find_rat_end(pcb_board_t *pcb, pcb_coord_t x, pcb_coord_t y, const char *loc) +{ + void *ptr1, *ptr2, *ptr3; + pcb_any_obj_t *o; + pcb_objtype_t type = pcb_search_obj_by_location(PCB_OBJ_CLASS_TERM | PCB_OBJ_SUBC_PART, &ptr1, &ptr2, &ptr3, x, y, 5); + pcb_subc_t *sc; + + o = ptr2; + if ((type == PCB_OBJ_VOID) || (o->term == NULL)) { + pcb_message(PCB_MSG_ERROR, "Can't find a terminal at %s\n", loc); + return NULL; + } + + sc = pcb_obj_parent_subc(o); + if ((sc == NULL) || (sc->refdes == NULL)) { + pcb_message(PCB_MSG_ERROR, "The terminal terminal found at %s is not part of a subc with refdes\n", loc); + return NULL; + } + + return o; +} + +pcb_rat_t *pcb_net_create_by_rat_coords(pcb_board_t *pcb, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2, pcb_bool interactive) +{ + pcb_any_obj_t *os, *oe; + if ((x1 == x2) && (y1 == y2)) + return NULL; + + os = find_rat_end(pcb, x1, y1, "rat line start"); + oe = find_rat_end(pcb, x2, y2, "rat line end"); + + return pcb_net_create_by_rat_(pcb, x1, y1, x2, y2, os, oe, interactive); +} + + +pcb_cardinal_t pcb_net_ripup(pcb_board_t *pcb, pcb_net_t *net) +{ + pcb_find_t fctx; + pcb_net_term_t *t; + pcb_cardinal_t res, n; + pcb_any_obj_t *o, *lasto; + pcb_data_it_t it; + int first = 0; + + memset(&fctx, 0, sizeof(fctx)); + fctx.only_mark_rats = 1; /* do not trust rats, but do mark them */ + + for(t = pcb_termlist_first(&net->conns), n = 0; t != NULL; t = pcb_termlist_next(t), n++) + pcb_net_term_crawl(pcb, t, &fctx, &first, NULL); + + pcb_undo_save_serial(); + pcb_draw_inhibit_inc(); + + /* always remove the (n-1)th object; removing the current iterator object + confuses the iteration */ + res = 0; + lasto = NULL; + o = pcb_data_first(&it, pcb->Data, PCB_OBJ_CLASS_REAL & (~PCB_OBJ_SUBC)); + for(;;) { + if ((lasto != NULL) && (PCB_DFLAG_TEST(&lasto->Flags, fctx.mark))) { + pcb_remove_object(lasto->type, lasto->parent.any, lasto, lasto); + res++; + } + lasto = o; + if (lasto == NULL) + break; + o = pcb_data_next(&it); + } + + pcb_undo_restore_serial(); + if (res > 0) + pcb_undo_inc_serial(); + + pcb_draw_inhibit_dec(); + pcb_find_free(&fctx); + return res; +} Index: tags/2.1.2/src/netlist2.h =================================================================== --- tags/2.1.2/src/netlist2.h (nonexistent) +++ tags/2.1.2/src/netlist2.h (revision 24813) @@ -0,0 +1,191 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2019 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#ifndef PCB_NETLIST2_H +#define PCB_NETLIST2_H + +#include +#include +#include +#include "board.h" +#include "obj_common.h" + +struct pcb_net_term_s { + PCB_ANY_OBJ_FIELDS; + char *refdes; + char *term; + gdl_elem_t link; /* a net is mainly an ordered list of terminals */ +}; + +typedef enum { /* bitfield */ + PCB_RATACC_PRECISE = 1, /* find the shortest rats, precisely (expensive); if unset, use a simplified algo e.g. considering only endpoints of lines */ + PCB_RATACC_ONLY_MANHATTAN = 2, /* the old autorouter doesn't like non-manhattan lines and arcs */ + PCB_RATACC_ONLY_SELECTED = 4, + PCB_RATACC_INFO = 8 /* print INFO messages in the log about how many rats are to go */ +} pcb_rat_accuracy_t; + +/* List of refdes-terminals */ +#define TDL(x) pcb_termlist_ ## x +#define TDL_LIST_T pcb_termlist_t +#define TDL_ITEM_T pcb_net_term_t +#define TDL_FIELD link +#define TDL_SIZE_T size_t +#define TDL_FUNC + +#define pcb_termlist_foreach(list, iterator, loop_elem) \ + gdl_foreach_((&((list)->lst)), (iterator), (loop_elem)) + + +#include +#include + + +struct pcb_net_s { + PCB_ANY_OBJ_FIELDS; + char *name; + pcb_cardinal_t export_tmp; /* filled in and used by export code; valid only until the end of exporting */ + unsigned inhibit_rats:1; + pcb_termlist_t conns; +}; + + +/* Initialize an empty netlist */ +void pcb_netlist_init(pcb_netlist_t *nl); + +/* Free all memory (including nets and terminals) of a netlist */ +void pcb_netlist_uninit(pcb_netlist_t *nl); + +/* Copy all fields from src to dst, assuming dst is empty */ +void pcb_netlist_copy(pcb_board_t *pcb, pcb_netlist_t *dst, pcb_netlist_t *src); + +/* Look up (or allocate) a net by name within a netlist. Returns NULL on error */ +pcb_net_t *pcb_net_get(pcb_board_t *pcb, pcb_netlist_t *nl, const char *netname, pcb_bool alloc); +pcb_net_t *pcb_net_get_icase(pcb_board_t *pcb, pcb_netlist_t *nl, const char *name); /* read-only, case-insnensitive */ +pcb_net_t *pcb_net_get_regex(pcb_board_t *pcb, pcb_netlist_t *nl, const char *regex); +pcb_net_t *pcb_net_get_user(pcb_board_t *pcb, pcb_netlist_t *nl, const char *name_or_rx); /* run all three above in order, until one succeeds */ + + +/* Remove a net from a netlist by namel returns 0 on removal, -1 on error */ +int pcb_net_del(pcb_netlist_t *nl, const char *netname); + +/* Look up (or allocate) a terminal within a net. Pinname is "refdes-termid". + Returns NULL on error */ +pcb_net_term_t *pcb_net_term_get(pcb_net_t *net, const char *refdes, const char *term, pcb_bool alloc); +pcb_net_term_t *pcb_net_term_get_by_obj(pcb_net_t *net, const pcb_any_obj_t *obj); +pcb_net_term_t *pcb_net_term_get_by_pinname(pcb_net_t *net, const char *pinname, pcb_bool alloc); + +/* Remove term from its net and free all fields and term itself */ +int pcb_net_term_del(pcb_net_t *net, pcb_net_term_t *term); +int pcb_net_term_del_by_name(pcb_net_t *net, const char *refdes, const char *term); + + +/* Crawl a net and clear&set flags on each object belonging to the net + and. Return the number of objects found */ +pcb_cardinal_t pcb_net_crawl_flag(pcb_board_t *pcb, pcb_net_t *net, unsigned long setf, unsigned long clrf); + + +/* Slow, linear search for a terminal, by pinname ("refdes-pinnumber") or + separate refdes and terminal ID. */ +pcb_net_term_t *pcb_net_find_by_pinname(const pcb_netlist_t *nl, const char *pinname); +pcb_net_term_t *pcb_net_find_by_refdes_term(const pcb_netlist_t *nl, const char *refdes, const char *term); +pcb_net_term_t *pcb_net_find_by_obj(const pcb_netlist_t *nl, const pcb_any_obj_t *obj); + +/* Create an alphabetic sorted, NULL terminated array from the nets; + the return value is valid until any change to nl and should be free'd + by the caller. Pointers in the array are the same as in the has table, + should not be free'd. */ +pcb_net_t **pcb_netlist_sort(pcb_netlist_t *nl); + +/* Create missing rat lines */ +pcb_cardinal_t pcb_net_add_rats(const pcb_board_t *pcb, pcb_net_t *net, pcb_rat_accuracy_t acc); +pcb_cardinal_t pcb_net_add_all_rats(const pcb_board_t *pcb, pcb_rat_accuracy_t acc); + +/* Create a new network or a new net connection by drawing a rat line between two terminals */ +pcb_rat_t *pcb_net_create_by_rat_coords(pcb_board_t *pcb, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2, pcb_bool interactive); + +/* Undoably remove all non-subc-part copper objects that are connected to net. + Return the number of removals. */ +pcb_cardinal_t pcb_net_ripup(pcb_board_t *pcb, pcb_net_t *net); + +void pcb_netlist_changed(int force_unfreeze); + +pcb_bool pcb_net_name_valid(const char *netname); + +/*** subnet mapping ***/ + +typedef struct { + const pcb_board_t *pcb; + pcb_net_t *current_net; + htsp_t found; + pcb_cardinal_t changed, missing, num_shorts; +} pcb_short_ctx_t; + +void pcb_net_short_ctx_init(pcb_short_ctx_t *sctx, const pcb_board_t *pcb, pcb_net_t *net); +void pcb_net_short_ctx_uninit(pcb_short_ctx_t *sctx); + +/* Search and collect all subnets of a net, adding rat lines in between them. + Caller provided subnets is a vector of vtp0_t items that each contain + (pcb_any_obj_t *) pointers to subnet objects */ +pcb_cardinal_t pcb_net_map_subnets(pcb_short_ctx_t *sctx, pcb_rat_accuracy_t acc, vtp0_t *subnets); + +void pcb_net_reset_subnets(vtp0_t *subnets); /* clear the subnet list to zero items, but don't free the array ("malloc cache") */ +void pcb_net_free_subnets(vtp0_t *subnets); /* same as reset but also free the array */ + + + +/*** looping ***/ + +typedef struct pcb_net_it_s { + pcb_netlist_t *nl; + htsp_entry_t *next; +} pcb_net_it_t; + +PCB_INLINE pcb_net_t *pcb_net_next(pcb_net_it_t *it) +{ + pcb_net_t *res; + if (it->next == NULL) + return NULL; + res = it->next->value; + it->next = htsp_next(it->nl, it->next); + return res; +} + +PCB_INLINE pcb_net_t *pcb_net_first(pcb_net_it_t *it, pcb_netlist_t *nl) +{ + it->nl = nl; + it->next = htsp_first(nl); + return pcb_net_next(it); +} + +/*** Internal ***/ +void pcb_net_free_fields(pcb_net_t *net); +void pcb_net_free(pcb_net_t *net); +void pcb_net_term_free_fields(pcb_net_term_t *term); +void pcb_net_term_free(pcb_net_term_t *term); + +void pcb_netlist_geo_init(void); + +#endif Index: tags/2.1.2/src/netlist_act.c =================================================================== --- tags/2.1.2/src/netlist_act.c (nonexistent) +++ tags/2.1.2/src/netlist_act.c (revision 24813) @@ -0,0 +1,626 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996, 2005 Thomas Nau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +/* generic netlist operations + */ + +#include "config.h" + +#include +#include +#include +#include + +#include "funchash_core.h" +#include "data.h" +#include "data_it.h" +#include "board.h" +#include "error.h" +#include "plug_io.h" +#include "actions.h" +#include "compat_misc.h" +#include "netlist2.h" +#include "data_it.h" +#include "find.h" +#include "obj_term.h" +#include "search.h" +#include "obj_subc_parent.h" + +static int pcb_netlist_swap() +{ + char *pins[3] = { NULL, NULL, NULL }; + int next = 0, n; + int ret = -1; + pcb_net_term_t *t1, *t2; + pcb_net_t *n1, *n2; + + PCB_SUBC_LOOP(PCB->Data); + { + pcb_any_obj_t *o; + pcb_data_it_t it; + + for(o = pcb_data_first(&it, subc->data, PCB_OBJ_CLASS_REAL); o != NULL; o = pcb_data_next(&it)) { + if (PCB_FLAG_TEST(PCB_FLAG_SELECTED, o) && (o->term != NULL)) { + int le, lp; + + if (next > 2) { + pcb_message(PCB_MSG_ERROR, "Exactly two terminals should be selected for swap (more than 2 selected at the moment)\n"); + goto quit; + } + + le = strlen(subc->refdes); + lp = strlen(o->term); + pins[next] = malloc(le + lp + 2); + sprintf(pins[next], "%s-%s", subc->refdes, o->term); + next++; + } + } + } + PCB_END_LOOP; + + if (next < 2) { + pcb_message(PCB_MSG_ERROR, "Exactly two terminals should be selected for swap (less than 2 selected at the moment)\n"); + goto quit; + } + + + t1 = pcb_net_find_by_pinname(&PCB->netlist[PCB_NETLIST_EDITED], pins[0]); + t2 = pcb_net_find_by_pinname(&PCB->netlist[PCB_NETLIST_EDITED], pins[1]); + if ((t1 == NULL) || (t2 == NULL)) { + pcb_message(PCB_MSG_ERROR, "That terminal is not on a net.\n"); + goto quit; + } + + n1 = t1->parent.net; + n2 = t2->parent.net; + if (n1 == n2) { + pcb_message(PCB_MSG_ERROR, "Those two terminals are on the same net, can't swap them.\n"); + goto quit; + } + + + pcb_ratspatch_append_optimize(PCB, RATP_DEL_CONN, pins[0], n1->name, NULL); + pcb_ratspatch_append_optimize(PCB, RATP_DEL_CONN, pins[1], n2->name, NULL); + pcb_ratspatch_append_optimize(PCB, RATP_ADD_CONN, pins[0], n2->name, NULL); + pcb_ratspatch_append_optimize(PCB, RATP_ADD_CONN, pins[1], n1->name, NULL); + + /* TODO: not very efficient to regenerate the whole list... */ + pcb_ratspatch_make_edited(PCB); + ret = 0; + +quit:; + for (n = 0; n < 3; n++) + if (pins[n] != NULL) + free(pins[n]); + return ret; +} + +/* The primary purpose of this action is to rebuild a netlist from a + script, in conjunction with the clear action above. */ +static int pcb_netlist_add(int patch, const char *netname, const char *pinname) +{ + pcb_net_t *n; + pcb_net_term_t *t; + + if ((netname == NULL) || (pinname == NULL)) + return -1; + + if ((*netname == '\0') || (*pinname == '\0')) + return -1; + + n = pcb_net_get(PCB, &PCB->netlist[PCB_NETLIST_INPUT+(!!patch)], netname, 1); + t = pcb_net_term_get_by_pinname(n, pinname, 0); + if (t == NULL) { + if (!patch) { + t = pcb_net_term_get_by_pinname(n, pinname, 1); + PCB->netlist_needs_update=1; + } + else { + t = pcb_net_term_get_by_pinname(n, pinname, 1); + pcb_ratspatch_append_optimize(PCB, RATP_ADD_CONN, pinname, netname, NULL); + } + } + + pcb_netlist_changed(0); + return 0; +} + +static void pcb_netlist_find(pcb_net_t *new_net, pcb_net_term_t *term) +{ + pcb_net_crawl_flag(PCB, pcb_net_get(PCB, &PCB->netlist[PCB_NETLIST_EDITED], new_net->name, 0), PCB_FLAG_FOUND, 0); +} + +static void pcb_netlist_select(pcb_net_t *new_net, pcb_net_term_t *term) +{ + pcb_net_crawl_flag(PCB, pcb_net_get(PCB, &PCB->netlist[PCB_NETLIST_EDITED], new_net->name, 0), PCB_FLAG_SELECTED, 0); +} + +static void pcb_netlist_unselect(pcb_net_t *new_net, pcb_net_term_t *term) +{ + pcb_net_crawl_flag(PCB, pcb_net_get(PCB, &PCB->netlist[PCB_NETLIST_EDITED], new_net->name, 0), 0, PCB_FLAG_SELECTED); +} + +static void pcb_netlist_rats(pcb_net_t *new_net, pcb_net_term_t *term) +{ + pcb_net_t *n = pcb_net_get(PCB, &PCB->netlist[PCB_NETLIST_EDITED], new_net->name, 0); + if (n != NULL) + n->inhibit_rats = 0; + pcb_netlist_changed(0); +} + +static void pcb_netlist_norats(pcb_net_t *new_net, pcb_net_term_t *term) +{ + pcb_net_t *n = pcb_net_get(PCB, &PCB->netlist[PCB_NETLIST_EDITED], new_net->name, 0); + if (n != NULL) + n->inhibit_rats = 1; + pcb_netlist_changed(0); +} + +/* The primary purpose of this action is to remove the netlist + completely so that a new one can be loaded, usually via a gsch2pcb + style script. */ +static void pcb_netlist_clear(pcb_net_t *net, pcb_net_term_t *term) +{ + int ni; + + if (net == 0) { + /* Clear the entire netlist. */ + for (ni = 0; ni < PCB_NUM_NETLISTS; ni++) { + pcb_netlist_uninit(&PCB->netlist[ni]); + pcb_netlist_init(&PCB->netlist[ni]); + } + } + else if (term == NULL) { + /* Remove a net from the netlist. */ + pcb_net_del(&PCB->netlist[PCB_NETLIST_EDITED], net->name); + } + else { + /* Remove a pin from the given net. Note that this may leave an + empty net, which is different than removing the net + (above). */ + pcb_net_term_del(net, term); + } + pcb_netlist_changed(0); +} + +static void pcb_netlist_style(pcb_net_t *new_net, const char *style) +{ + pcb_attribute_put(&new_net->Attributes, "style", style); +} + +static void pcb_netlist_ripup(pcb_net_t *new_net, pcb_net_term_t *term) +{ + pcb_net_ripup(PCB, new_net); +} + +static void pcb_netlist_addrats(pcb_net_t *new_net, pcb_net_term_t *term) +{ + pcb_net_add_rats(PCB, new_net, PCB_RATACC_PRECISE); +} + + +static const char pcb_acts_Netlist[] = + "Net(find|select|rats|norats||ripup|addrats|clear[,net[,pin]])\n" + "Net(freeze|thaw|forcethaw)\n" + "Net(swap)\n" + "Net(add,net,pin)" + "Net([rename|merge],srcnet,dstnet)" + ; +static const char pcb_acth_Netlist[] = "Perform various actions on netlists."; + +/* DOC: netlist.html */ +static fgw_error_t pcb_act_Netlist(fgw_arg_t *res, int argc, fgw_arg_t *argv); + +typedef void (*NFunc)(pcb_net_t *net, pcb_net_term_t *term); + +static unsigned netlist_act_do(pcb_net_t *net, int argc, const char *a1, const char *a2, NFunc func) +{ + pcb_net_term_t *term = NULL; + int pin_found = 0; + + if (func == (NFunc)pcb_netlist_style) { + pcb_netlist_style(net, a2); + return 1; + } + + if (argc > 3) { + { + char *refdes, *termid; + refdes = pcb_strdup(a2); + termid = strchr(refdes, '-'); + if (termid != NULL) { + *termid = '\0'; + termid++; + } + else + termid = ""; + for(term = pcb_termlist_first(&net->conns); term != NULL; term = pcb_termlist_next(term)) { + if ((pcb_strcasecmp(refdes, term->refdes) == 0) && (pcb_strcasecmp(termid, term->term) == 0)) { + pin_found = 1; + func(net, term); + } + } + + free(refdes); + } + if (pcb_gui != NULL) + pcb_gui->invalidate_all(); + } + else if (argc > 2) { + pin_found = 1; + { + for(term = pcb_termlist_first(&net->conns); term != NULL; term = pcb_termlist_next(term)) + func(net, term); + } + if (pcb_gui != NULL) + pcb_gui->invalidate_all(); + } + else { + func(net, NULL); + if (pcb_gui != NULL) + pcb_gui->invalidate_all(); + } + + return pin_found; +} + +static void netlist_freeze(pcb_board_t *pcb) +{ + pcb->netlist_frozen++; +} + +static void netlist_unfreeze(pcb_board_t *pcb) +{ + if (pcb->netlist_frozen > 0) { + pcb->netlist_frozen--; + if (pcb->netlist_needs_update) + pcb_netlist_changed(0); + } +} + +/* Rename or merge networks: move all conns from 'from' to 'to'. If merge, + 'to' shall be an existing network, else it shall be a non-existing network. */ +static int netlist_merge(pcb_board_t *pcb, const char *from, const char *to, int merge) +{ + pcb_net_t *nfrom, *nto; + pcb_net_term_t *t, *tnext; + + nfrom = pcb_net_get(PCB, &PCB->netlist[PCB_NETLIST_EDITED], from, 0); + if (nfrom == NULL) { + pcb_message(PCB_MSG_ERROR, "No such net: '%s'\n", from); + return 1; + } + + nto = pcb_net_get(PCB, &PCB->netlist[PCB_NETLIST_EDITED], to, 0); + if (merge) { + if (nto == NULL) { + pcb_message(PCB_MSG_ERROR, "No such net: '%s'\n", to); + return 1; + } + } + else { + if (nto != NULL) { + pcb_message(PCB_MSG_ERROR, "Net name '%s' already in use\n", to); + return 1; + } + nto = pcb_net_get(PCB, &PCB->netlist[PCB_NETLIST_EDITED], to, 1); + } + + /* move over all terminals from nfrom to nto */ + for(t = pcb_termlist_first(&nfrom->conns); t != NULL; t = tnext) { + char *pinname = pcb_strdup_printf("%s-%s", t->refdes, t->term); + + tnext = pcb_termlist_next(t); + pcb_net_term_del(nfrom, t); + pcb_ratspatch_append_optimize(PCB, RATP_DEL_CONN, pinname, nfrom->name, NULL); + + pcb_net_term_get_by_pinname(nto, pinname, 1); + pcb_ratspatch_append_optimize(PCB, RATP_ADD_CONN, pinname, nto->name, NULL); + + free(pinname); + } + pcb_net_del(&PCB->netlist[PCB_NETLIST_EDITED], from); + pcb_netlist_changed(0); + return 0; +} + +static fgw_error_t pcb_act_Netlist(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + NFunc func; + const char *a1 = NULL, *a2 = NULL; + char *a2free = NULL; + int op; + pcb_net_t *net = NULL; + unsigned net_found = 0; + unsigned pin_found = 0; + + PCB_ACT_CONVARG(1, FGW_KEYWORD, Netlist, op = fgw_keyword(&argv[1])); + PCB_ACT_MAY_CONVARG(2, FGW_STR, Netlist, a1 = argv[2].val.str); + PCB_ACT_MAY_CONVARG(3, FGW_STR, Netlist, a2 = argv[3].val.str); + PCB_ACT_IRES(0); + + if (!PCB) + return 1; + + switch(op) { + case F_Rename: + if (a1 == NULL) + PCB_ACT_FAIL(Netlist); + if (a2 == NULL) { + a2 = a2free = pcb_hid_prompt_for("New name of the network", NULL, "net rename"); + if (a2 == NULL) { + PCB_ACT_IRES(1); + return 0; + } + } + PCB_ACT_IRES(netlist_merge(PCB, a1, a2, 0)); + free(a2free); + return 0; + case F_Merge: + if (a1 == NULL) + PCB_ACT_FAIL(Netlist); + if (a2 == NULL) { + a2 = a2free = pcb_hid_prompt_for("Network name to merge into", NULL, "net merge"); + if (a2 == NULL) { + PCB_ACT_IRES(1); + return 0; + } + } + PCB_ACT_IRES(netlist_merge(PCB, a1, a2, 1)); + free(a2free); + return 0; + case F_Find: func = pcb_netlist_find; break; + case F_Select: func = pcb_netlist_select; break; + case F_Unselect: func = pcb_netlist_unselect; break; + case F_Rats: func = pcb_netlist_rats; break; + case F_NoRats: func = pcb_netlist_norats; break; + case F_AddRats: func = pcb_netlist_addrats; break; + case F_Style: func = (NFunc) pcb_netlist_style; break; + case F_Ripup: func = pcb_netlist_ripup; break; + case F_Swap: return pcb_netlist_swap(); break; + case F_Clear: + func = pcb_netlist_clear; + if (argc == 2) { + pcb_netlist_clear(NULL, NULL); + return 0; + } + break; + case F_Add: + /* Add is different, because the net/pin won't already exist. */ + return pcb_netlist_add(0, a1, a2); + case F_Sort: + pcb_ratspatch_make_edited(PCB); + return 0; + case F_Freeze: + netlist_freeze(PCB); + return 0; + case F_Thaw: + netlist_unfreeze(PCB); + return 0; + case F_ForceThaw: + PCB->netlist_frozen = 0; + if (PCB->netlist_needs_update) + pcb_netlist_changed(0); + return 0; + default: + PCB_ACT_FAIL(Netlist); + } + + netlist_freeze(PCB); + { + pcb_netlist_t *nl = &PCB->netlist[PCB_NETLIST_EDITED]; + net = pcb_net_get(PCB, nl, a1, 0); + if (net == NULL) + net = pcb_net_get_icase(PCB, nl, a1); + if (net == NULL) { /* no direct match - have to go for the multi-net regex approach */ + re_sei_t *regex = re_sei_comp(a1); + if (re_sei_errno(regex) == 0) { + htsp_entry_t *e; + for(e = htsp_first(nl); e != NULL; e = htsp_next(nl, e)) { + pcb_net_t *net = e->value; + if (re_sei_exec(regex, net->name)) { + net_found = 1; + pin_found |= netlist_act_do(net, argc, a1, a2, func); + } + } + } + re_sei_free(regex); + } + else { + net_found = 1; + pin_found |= netlist_act_do(net, argc, a1, a2, func); + } + } + netlist_unfreeze(PCB); + + if (argc > 3 && !pin_found) { + pcb_message(PCB_MSG_ERROR, "Net %s has no pin %s\n", a1, a2); + return 1; + } + else if (!net_found) { + pcb_message(PCB_MSG_ERROR, "No net named %s\n", a1); + } + + + return 0; +} + +static void claim_import_by_flag(pcb_data_t *data, vtp0_t *termlist, unsigned long flg) +{ + pcb_any_obj_t *o; + pcb_data_it_t it; + + for(o = pcb_data_first(&it, data, PCB_OBJ_CLASS_REAL); o != NULL; o = pcb_data_next(&it)) { + pcb_subc_t *subc; + + if (o->type == PCB_OBJ_SUBC) + claim_import_by_flag(((pcb_subc_t *)o)->data, termlist, flg); + + if ((o->term == NULL) || (!PCB_FLAG_TEST(flg, o))) + continue; + + subc = pcb_obj_parent_subc(o); + if ((subc == NULL) || (subc->refdes == NULL)) + continue; + + vtp0_append(termlist, o); + } +} + +static int claim_net_cb(pcb_find_t *ctx, pcb_any_obj_t *new_obj, pcb_any_obj_t *arrived_from, pcb_found_conn_type_t ctype) +{ + pcb_subc_t *subc; + vtp0_t *termlist = ctx->user_data; + + if (new_obj->term == NULL) + return 0; + + subc = pcb_obj_parent_subc(new_obj); + if ((subc == NULL) || (subc->refdes == NULL)) + return 0; + + vtp0_append(termlist, new_obj); + return 0; +} + +static void pcb_net_claim_from_list(pcb_board_t *pcb, pcb_net_t *net, vtp0_t *termlist) +{ + size_t n; + + for(n = 0; n < vtp0_len(termlist); n++) { + pcb_any_obj_t *obj = termlist->array[n]; + pcb_subc_t *subc = pcb_obj_parent_subc(obj); + pcb_net_term_t *t = pcb_net_find_by_obj(&pcb->netlist[PCB_NETLIST_EDITED], obj); + char *pinname; + + if (t != NULL) { + /* remove term from its original net */ + pinname = pcb_strdup_printf("%s-%s", t->refdes, t->term); + pcb_ratspatch_append_optimize(PCB, RATP_DEL_CONN, pinname, net->name, NULL); + free(pinname); + } + + t = pcb_net_term_get(net, subc->refdes, obj->term, 1); + pinname = pcb_strdup_printf("%s-%s", t->refdes, t->term); + pcb_ratspatch_append_optimize(PCB, RATP_ADD_CONN, pinname, net->name, NULL); + free(pinname); + } +} + +static const char pcb_acts_ClaimNet[] = "ClaimNet(object|selected|found,[netname])\n"; +static const char pcb_acth_ClaimNet[] = "Claim existing connections and create a new net"; +/* DOC: claimnet.html */ +static fgw_error_t pcb_act_ClaimNet(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + pcb_find_t fctx; + int op; + vtp0_t termlist; + pcb_net_t *net; + char *netname = NULL, *free_netname = NULL; + + PCB_ACT_CONVARG(1, FGW_KEYWORD, Netlist, op = fgw_keyword(&argv[1])); + PCB_ACT_MAY_CONVARG(2, FGW_STR, Netlist, netname = argv[2].val.str); + PCB_ACT_IRES(0); + + vtp0_init(&termlist); + switch(op) { + case F_Object: + { + pcb_coord_t x, y; + void *r1, *r2, *r3; + + pcb_hid_get_coords("Select a an object to claim network from", &x, &y, 0); + if (pcb_search_screen(x, y, PCB_OBJ_LINE | PCB_OBJ_ARC | PCB_OBJ_POLY | PCB_OBJ_PSTK, &r1, &r2, &r3) <= 0) + return 0; + + memset(&fctx, 0, sizeof(fctx)); + fctx.consider_rats = 1; + fctx.found_cb = claim_net_cb; + fctx.user_data = &termlist; + pcb_find_from_obj(&fctx, PCB->Data, (pcb_any_obj_t *)r2); + } + break; + case F_Found: + claim_import_by_flag(PCB->Data, &termlist, PCB_FLAG_FOUND); + break; + case F_Selected: + claim_import_by_flag(PCB->Data, &termlist, PCB_FLAG_SELECTED); + break; + default: + vtp0_uninit(&termlist); + PCB_ACT_FAIL(ClaimNet); + } + + if (termlist.used < 1) { + vtp0_uninit(&termlist); + pcb_message(PCB_MSG_ERROR, "Can not claim network: no terminal found.\nPlease pick objects that have terminals with refdes-termID.\n"); + PCB_ACT_IRES(1); + return 0; + } + + if (netname == NULL) { + free_netname = netname = pcb_hid_prompt_for("Name of the new network", NULL, "net name"); + if (netname == NULL) { + vtp0_uninit(&termlist); + PCB_ACT_IRES(1); + return 0; + } + } + + if (pcb_net_get(PCB, &PCB->netlist[PCB_NETLIST_EDITED], netname, 0) != NULL) { + free(free_netname); + vtp0_uninit(&termlist); + pcb_message(PCB_MSG_ERROR, "Can not claim network: '%s' is an existing network\n", netname); + PCB_ACT_IRES(1); + return 0; + } + + net = pcb_net_get(PCB, &PCB->netlist[PCB_NETLIST_EDITED], netname, 1); + free(free_netname); + + if (net == NULL) { + vtp0_uninit(&termlist); + pcb_message(PCB_MSG_ERROR, "Can not claim network: failed to create net '%s'\n", netname); + PCB_ACT_IRES(1); + return 0; + } + + pcb_net_claim_from_list(PCB, net, &termlist); + pcb_netlist_changed(0); + vtp0_uninit(&termlist); + return 0; +} + + +pcb_action_t netlist_action_list[] = { + {"net", pcb_act_Netlist, pcb_acth_Netlist, pcb_acts_Netlist}, + {"netlist", pcb_act_Netlist, pcb_acth_Netlist, pcb_acts_Netlist}, + {"claimnet", pcb_act_ClaimNet, pcb_acth_ClaimNet, pcb_acts_ClaimNet} +}; + +PCB_REGISTER_ACTIONS(netlist_action_list, NULL) Index: tags/2.1.2/src/netlist_geo.c =================================================================== --- tags/2.1.2/src/netlist_geo.c (nonexistent) +++ tags/2.1.2/src/netlist_geo.c (revision 24813) @@ -0,0 +1,431 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2019 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include +#include "obj_pstk_inlines.h" + +typedef struct { + pcb_any_obj_t *o1, *o2; + pcb_coord_t o1x, o1y, o2x, o2y; + pcb_layergrp_id_t o1g, o2g; + double dist2; +} pcb_subnet_dist_t; + +static pcb_subnet_dist_t sdist_invalid = { NULL, NULL, 0, 0, 0, 0, -1, -1, 0 }; + +#define is_line_manhattan(l) (((l)->Point1.X == (l)->Point2.X) || ((l)->Point1.Y == (l)->Point2.Y)) + +#define dist_(o1_, o1x_, o1y_, o2_, o2x_, o2y_) \ +do { \ + double __dx__, __dy__; \ + curr.o1 = (pcb_any_obj_t *)o1_; \ + curr.o1x= o1x_; \ + curr.o1y= o1y_; \ + curr.o2 = (pcb_any_obj_t *)o2_; \ + curr.o2x= o2x_; \ + curr.o2y= o2y_; \ + __dx__ = o1x_ - o2x_; \ + __dy__ = o1y_ - o2y_; \ + curr.dist2 = __dx__ * __dx__ + __dy__ * __dy__; \ +} while(0) + + +#define dist2(o1, o1x, o1y, o2, o2x, o2y) \ +do { \ + dist_(o1, o1x, o1y, o2, o2x, o2y); \ + if (curr.dist2 < best.dist2) \ + best = curr; \ +} while(0) + +#define dist1(o1, o1x, o1y, o2, o2x, o2y) \ +do { \ + dist_(o1, o1x, o1y, o2, o2x, o2y); \ + best = curr; \ +} while(0) + +static pcb_subnet_dist_t pcb_dist_arc_arc(pcb_arc_t *o1, pcb_arc_t *o2, pcb_rat_accuracy_t acc) +{ + pcb_subnet_dist_t best, curr; + pcb_coord_t o1x1, o1y1, o1x2, o1y2, o2x1, o2y1, o2x2, o2y2; + + if (acc & PCB_RATACC_ONLY_MANHATTAN) + return sdist_invalid; + + pcb_arc_get_end(o1, 0, &o1x1, &o1y1); + pcb_arc_get_end(o1, 1, &o1x2, &o1y2); + pcb_arc_get_end(o2, 0, &o2x1, &o2y1); + pcb_arc_get_end(o2, 1, &o2x2, &o2y2); + + dist1(o1, o1x1, o1y1, o2, o2x1, o2y1); + dist2(o1, o1x1, o1y1, o2, o2x2, o2y2); + dist2(o1, o1x2, o1y2, o2, o2x1, o2y1); + dist2(o1, o1x2, o1y2, o2, o2x2, o2y2); + + return best; +} + +static pcb_subnet_dist_t pcb_dist_line_line(pcb_line_t *o1, pcb_line_t *o2, pcb_rat_accuracy_t acc) +{ + pcb_subnet_dist_t best, curr; + + if ((acc & PCB_RATACC_ONLY_MANHATTAN) && ((!is_line_manhattan(o1) || !is_line_manhattan(o2)))) + return sdist_invalid; + + dist1(o1, o1->Point1.X, o1->Point1.Y, o2, o2->Point1.X, o2->Point1.Y); + dist2(o1, o1->Point1.X, o1->Point1.Y, o2, o2->Point2.X, o2->Point2.Y); + dist2(o1, o1->Point2.X, o1->Point2.Y, o2, o2->Point1.X, o2->Point1.Y); + dist2(o1, o1->Point2.X, o1->Point2.Y, o2, o2->Point2.X, o2->Point2.Y); + + return best; +} + +static pcb_subnet_dist_t pcb_dist_line_arc(pcb_line_t *o1, pcb_arc_t *o2, pcb_rat_accuracy_t acc) +{ + pcb_subnet_dist_t best, curr; + pcb_coord_t o2x1, o2y1, o2x2, o2y2; + + if (acc & PCB_RATACC_ONLY_MANHATTAN) + return sdist_invalid; + if ((acc & PCB_RATACC_ONLY_MANHATTAN) && (!is_line_manhattan(o1))) + return sdist_invalid; + + pcb_arc_get_end(o2, 0, &o2x1, &o2y1); + pcb_arc_get_end(o2, 1, &o2x2, &o2y2); + + dist1(o1, o1->Point1.X, o1->Point1.Y, o2, o2x1, o2y1); + dist2(o1, o1->Point1.X, o1->Point1.Y, o2, o2x2, o2y2); + dist2(o1, o1->Point2.X, o1->Point2.Y, o2, o2x1, o2y1); + dist2(o1, o1->Point2.X, o1->Point2.Y, o2, o2x2, o2y2); + + return best; +} + +#define poly_dist_chk(x, y) \ +do { \ + double dx = o2x - x, dy = o2y - y, dist2 = dx*dx + dy*dy; \ + if (dist2 < best.dist2) { \ + best.dist2 = dist2; \ + best.o1x = x; \ + best.o1y = y; \ + } \ +} while(0) + +static pcb_subnet_dist_t dist_poly(pcb_poly_t *o1, pcb_any_obj_t *o2, pcb_coord_t o2x, pcb_coord_t o2y) +{ + pcb_subnet_dist_t best; + pcb_poly_it_t it; + pcb_polyarea_t *pa; + + best.dist2 = HUGE_VAL; + best.o1 = (pcb_any_obj_t *)o1; + best.o2 = o2; + best.o2x = o2x; + best.o2y = o2y; + + for(pa = pcb_poly_island_first(o1, &it); pa != NULL; pa = pcb_poly_island_next(&it)) { + pcb_coord_t x, y; + pcb_pline_t *pl; + int go; + + pl = pcb_poly_contour(&it); + if (pl != NULL) { + /* contour of the island */ + for(go = pcb_poly_vect_first(&it, &x, &y); go; go = pcb_poly_vect_next(&it, &x, &y)) + poly_dist_chk(x, y); + + /* iterate over all holes within this island */ + for(pl = pcb_poly_hole_first(&it); pl != NULL; pl = pcb_poly_hole_next(&it)) + for(go = pcb_poly_vect_first(&it, &x, &y); go; go = pcb_poly_vect_next(&it, &x, &y)) + poly_dist_chk(x, y); + } + } + return best; +} + +static pcb_subnet_dist_t pcb_dist_poly_arc(pcb_poly_t *o1, pcb_arc_t *o2, pcb_rat_accuracy_t acc) +{ + pcb_subnet_dist_t best, curr; + pcb_coord_t o2x1, o2y1, o2x2, o2y2; + + if (acc & PCB_RATACC_ONLY_MANHATTAN) + return sdist_invalid; + + pcb_arc_get_end(o2, 0, &o2x1, &o2y1); + pcb_arc_get_end(o2, 1, &o2x2, &o2y2); + + best = dist_poly(o1, (pcb_any_obj_t *)o2, o2x1, o2y1); + curr = dist_poly(o1, (pcb_any_obj_t *)o2, o2x2, o2y2); + if (curr.dist2 < best.dist2) + return curr; + + return best; +} + +static pcb_subnet_dist_t pcb_dist_poly_line(pcb_poly_t *o1, pcb_line_t *o2, pcb_rat_accuracy_t acc) +{ + pcb_subnet_dist_t best, curr; + + if (acc & PCB_RATACC_ONLY_MANHATTAN) + return sdist_invalid; + + best = dist_poly(o1, (pcb_any_obj_t *)o2, o2->Point1.X, o2->Point1.Y); + curr = dist_poly(o1, (pcb_any_obj_t *)o2, o2->Point2.X, o2->Point2.Y); + if (curr.dist2 < best.dist2) + return curr; + + return best; +} + +#define poly_pt_chk(x, y) \ +do { \ + pcb_subnet_dist_t curr = dist_poly(o1, (pcb_any_obj_t *)o2, x, y); \ + if (curr.dist2 < best.dist2) \ + best = curr; \ +} while(0) + +static pcb_subnet_dist_t pcb_dist_poly_poly(pcb_poly_t *o1, pcb_poly_t *o2, pcb_rat_accuracy_t acc) +{ + pcb_subnet_dist_t best; + pcb_poly_it_t it; + pcb_polyarea_t *pa; + + if (acc & PCB_RATACC_ONLY_MANHATTAN) + return sdist_invalid; + + if (!(acc & PCB_RATACC_PRECISE)) /* this is a slow, O(n^2) algo */ + return sdist_invalid; + + best.dist2 = HUGE_VAL; + + for(pa = pcb_poly_island_first(o2, &it); pa != NULL; pa = pcb_poly_island_next(&it)) { + pcb_coord_t x, y; + pcb_pline_t *pl; + int go; + + pl = pcb_poly_contour(&it); + if (pl != NULL) { + /* contour of the island */ + for(go = pcb_poly_vect_first(&it, &x, &y); go; go = pcb_poly_vect_next(&it, &x, &y)) + poly_pt_chk(x, y); + + /* iterate over all holes within this island */ + for(pl = pcb_poly_hole_first(&it); pl != NULL; pl = pcb_poly_hole_next(&it)) + for(go = pcb_poly_vect_first(&it, &x, &y); go; go = pcb_poly_vect_next(&it, &x, &y)) + poly_pt_chk(x, y); + } + } + return best; +} + + +static pcb_subnet_dist_t pcb_dist_pstk_arc(pcb_pstk_t *o1, pcb_arc_t *o2, pcb_rat_accuracy_t acc) +{ + pcb_subnet_dist_t best, curr; + pcb_coord_t o2x1, o2y1, o2x2, o2y2; + + if (acc & PCB_RATACC_ONLY_MANHATTAN) + return sdist_invalid; + + pcb_arc_get_end(o2, 0, &o2x1, &o2y1); + pcb_arc_get_end(o2, 1, &o2x2, &o2y2); + + dist1(o1, o1->x, o1->y, o2, o2x1, o2y1); + dist2(o1, o1->x, o1->y, o2, o2x2, o2y2); + + return best; +} + +static pcb_subnet_dist_t pcb_dist_pstk_line(pcb_pstk_t *o1, pcb_line_t *o2, pcb_rat_accuracy_t acc) +{ + pcb_subnet_dist_t best, curr; + + if ((acc & PCB_RATACC_ONLY_MANHATTAN) &&(!is_line_manhattan(o2))) + return sdist_invalid; + + dist1(o1, o1->x, o1->y, o2, o2->Point1.X, o2->Point1.Y); + dist2(o1, o1->x, o1->y, o2, o2->Point2.X, o2->Point2.Y); + + return best; +} + +static pcb_subnet_dist_t pcb_dist_pstk_poly(pcb_pstk_t *o1, pcb_poly_t *o2, pcb_rat_accuracy_t acc) +{ + if (acc & PCB_RATACC_ONLY_MANHATTAN) + return sdist_invalid; + + return dist_poly(o2, (pcb_any_obj_t *)o1, o1->x, o1->y); +} + +static pcb_subnet_dist_t pcb_dist_pstk_pstk(pcb_pstk_t *o1, pcb_pstk_t *o2, pcb_rat_accuracy_t acc) +{ + pcb_subnet_dist_t curr; + dist_(o1, o1->x, o1->y, o2, o2->x, o2->y); + return curr; +} + + +static pcb_subnet_dist_t pcb_obj_obj_distance(pcb_any_obj_t *o1, pcb_any_obj_t *o2, pcb_rat_accuracy_t acc) +{ + switch(o1->type) { + case PCB_OBJ_ARC: + switch(o2->type) { + case PCB_OBJ_ARC: return pcb_dist_arc_arc((pcb_arc_t *)o2, (pcb_arc_t *)o1, acc); + case PCB_OBJ_LINE: return pcb_dist_line_arc((pcb_line_t *)o2, (pcb_arc_t *)o1, acc); + case PCB_OBJ_POLY: return pcb_dist_poly_arc((pcb_poly_t *)o2, (pcb_arc_t *)o1, acc); + case PCB_OBJ_PSTK: return pcb_dist_pstk_arc((pcb_pstk_t *)o2, (pcb_arc_t *)o1, acc); + + case PCB_OBJ_RAT: case PCB_OBJ_TEXT: case PCB_OBJ_SUBC: + case PCB_OBJ_VOID: case PCB_OBJ_NET: case PCB_OBJ_NET_TERM: case PCB_OBJ_LAYER: case PCB_OBJ_LAYERGRP: goto wrongtype; + } + break; + case PCB_OBJ_LINE: + switch(o2->type) { + case PCB_OBJ_ARC: return pcb_dist_line_arc((pcb_line_t *)o1, (pcb_arc_t *)o2, acc); + case PCB_OBJ_LINE: return pcb_dist_line_line((pcb_line_t *)o1, (pcb_line_t *)o2, acc); + case PCB_OBJ_POLY: return pcb_dist_poly_line((pcb_poly_t *)o2, (pcb_line_t *)o1, acc); + case PCB_OBJ_PSTK: return pcb_dist_pstk_line((pcb_pstk_t *)o2, (pcb_line_t *)o1, acc); + + case PCB_OBJ_RAT: case PCB_OBJ_TEXT: case PCB_OBJ_SUBC: + case PCB_OBJ_VOID: case PCB_OBJ_NET: case PCB_OBJ_NET_TERM: case PCB_OBJ_LAYER: case PCB_OBJ_LAYERGRP: goto wrongtype; + } + break; + case PCB_OBJ_POLY: + switch(o2->type) { + case PCB_OBJ_ARC: return pcb_dist_poly_arc((pcb_poly_t *)o1, (pcb_arc_t *)o2, acc); + case PCB_OBJ_LINE: return pcb_dist_poly_line((pcb_poly_t *)o1, (pcb_line_t *)o2, acc); + case PCB_OBJ_POLY: return pcb_dist_poly_poly((pcb_poly_t *)o1, (pcb_poly_t *)o2, acc); + case PCB_OBJ_PSTK: return pcb_dist_pstk_poly((pcb_pstk_t *)o2, (pcb_poly_t *)o1, acc); + + case PCB_OBJ_RAT: case PCB_OBJ_TEXT: case PCB_OBJ_SUBC: + case PCB_OBJ_VOID: case PCB_OBJ_NET: case PCB_OBJ_NET_TERM: case PCB_OBJ_LAYER: case PCB_OBJ_LAYERGRP: goto wrongtype; + } + break; + + case PCB_OBJ_PSTK: + switch(o2->type) { + case PCB_OBJ_ARC: return pcb_dist_pstk_arc((pcb_pstk_t *)o1, (pcb_arc_t *)o2, acc); + case PCB_OBJ_LINE: return pcb_dist_pstk_line((pcb_pstk_t *)o1, (pcb_line_t *)o2, acc); + case PCB_OBJ_POLY: return pcb_dist_pstk_poly((pcb_pstk_t *)o1, (pcb_poly_t *)o2, acc); + case PCB_OBJ_PSTK: return pcb_dist_pstk_pstk((pcb_pstk_t *)o1, (pcb_pstk_t *)o2, acc); + + case PCB_OBJ_RAT: case PCB_OBJ_TEXT: case PCB_OBJ_SUBC: + case PCB_OBJ_VOID: case PCB_OBJ_NET: case PCB_OBJ_NET_TERM: case PCB_OBJ_LAYER: case PCB_OBJ_LAYERGRP: goto wrongtype; + } + break; + + case PCB_OBJ_RAT: case PCB_OBJ_TEXT: case PCB_OBJ_SUBC: + case PCB_OBJ_VOID: case PCB_OBJ_NET: case PCB_OBJ_NET_TERM: case PCB_OBJ_LAYER: case PCB_OBJ_LAYERGRP: goto wrongtype; + } + + wrongtype:; + return sdist_invalid; +} + +static pcb_layergrp_id_t get_obj_grp(const pcb_board_t *pcb, pcb_any_obj_t *obj) +{ + switch(obj->type) { + case PCB_OBJ_ARC: + case PCB_OBJ_LINE: + case PCB_OBJ_POLY: + return pcb_layer_get_group_(obj->parent.layer); + + case PCB_OBJ_PSTK: /* return the first copper layer's group */ + { + int n; + pcb_layergrp_id_t res; + pcb_pstk_tshape_t *ts = pcb_pstk_get_tshape((pcb_pstk_t *)obj); + for(n = 0; n < ts->len; n++) + if (ts->shape[n].layer_mask & PCB_LYT_COPPER) + if (pcb_layergrp_list(pcb, ts->shape[n].layer_mask, &res, 1) == 1) + return res; + } + return -1; + + case PCB_OBJ_RAT: case PCB_OBJ_TEXT: case PCB_OBJ_SUBC: + case PCB_OBJ_VOID: case PCB_OBJ_NET: case PCB_OBJ_NET_TERM: case PCB_OBJ_LAYER: case PCB_OBJ_LAYERGRP: + break; + } + return -1; +} + +static pcb_subnet_dist_t pcb_subnet_dist(const pcb_board_t *pcb, vtp0_t *objs1, vtp0_t *objs2, pcb_rat_accuracy_t acc) +{ + int i1, i2; + pcb_subnet_dist_t best, curr; + + memset(&best, 0, sizeof(best)); + best.dist2 = HUGE_VAL; + + for(i1 = 0; i1 < vtp0_len(objs1); i1++) { + for(i2 = 0; i2 < vtp0_len(objs2); i2++) { + pcb_any_obj_t *o1 = objs1->array[i1], *o2 = objs2->array[i2]; + + curr = pcb_obj_obj_distance(o1, o2, acc); + + if (curr.dist2 < HUGE_VAL) { + pcb_any_obj_t *o_in_poly = NULL, *poly; + pcb_coord_t x, y, farx, fary; + + /* if object needs to connect to sorrunding polygon, use a special rat + to indicate "in-place" connection */ + if ((curr.o1->type == PCB_OBJ_POLY) && (curr.o2->type != PCB_OBJ_POLY)) { + o_in_poly = curr.o2; + poly = curr.o1; + x = curr.o2x; + y = curr.o2y; + farx = curr.o1x; + fary = curr.o1y; + } + else if ((curr.o2->type == PCB_OBJ_POLY) && (curr.o1->type != PCB_OBJ_POLY)) { + o_in_poly = curr.o1; + poly = curr.o2; + x = curr.o1x; + y = curr.o1y; + farx = curr.o2x; + fary = curr.o2y; + } + if (o_in_poly && pcb_point_in_box(&o_in_poly->BoundingBox, farx, fary) && pcb_poly_is_point_in_p_ignore_holes(x, y, (pcb_poly_t *)poly)) { + curr.o1x = curr.o2x = x; + curr.o1y = curr.o2y = y; + curr.dist2 = 0; + } + + } + + if (curr.dist2 < best.dist2) + best = curr; + } + } + + best.o1g = get_obj_grp(pcb, best.o1); + best.o2g = get_obj_grp(pcb, best.o2); + return best; +} + +void pcb_netlist_geo_init(void) +{ + sdist_invalid.dist2 = HUGE_VAL; /* on some systems this is not constant and can be used as an initializer */ +} Index: tags/2.1.2/src/obj_arc.c =================================================================== --- tags/2.1.2/src/obj_arc.c (nonexistent) +++ tags/2.1.2/src/obj_arc.c (revision 24813) @@ -0,0 +1,1052 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +/* Drawing primitive: (elliptical) arc */ + + +#include "config.h" +#include "board.h" +#include "data.h" +#include "polygon.h" +#include "undo.h" +#include "rotate.h" +#include "move.h" +#include "conf_core.h" +#include "compat_misc.h" +#include "draw_wireframe.h" +#include "hid_inlines.h" + +#include "obj_arc.h" +#include "obj_arc_op.h" + +#include "obj_subc_parent.h" +#include "obj_hash.h" + +/* TODO: could be removed if draw.c could be split up */ +#include "draw.h" +#include "obj_arc_draw.h" + + +static int pcb_arc_end_addr = 1; +int *pcb_arc_start_ptr = NULL, *pcb_arc_end_ptr = &pcb_arc_end_addr; + +void pcb_arc_reg(pcb_layer_t *layer, pcb_arc_t *arc) +{ + arclist_append(&layer->Arc, arc); + PCB_SET_PARENT(arc, layer, layer); + + if (layer->parent_type == PCB_PARENT_UI) + return; + + assert(layer->parent_type == PCB_PARENT_DATA); + pcb_obj_id_reg(layer->parent.data, arc); +} + +void pcb_arc_unreg(pcb_arc_t *arc) +{ + pcb_layer_t *layer = arc->parent.layer; + assert(arc->parent_type == PCB_PARENT_LAYER); + arclist_remove(arc); + if (layer->parent_type != PCB_PARENT_UI) { + assert(layer->parent_type == PCB_PARENT_DATA); + pcb_obj_id_del(layer->parent.data, arc); + } + PCB_CLEAR_PARENT(arc); +} + +pcb_arc_t *pcb_arc_alloc_id(pcb_layer_t *layer, long int id) +{ + pcb_arc_t *new_obj; + + new_obj = calloc(sizeof(pcb_arc_t), 1); + new_obj->ID = id; + new_obj->type = PCB_OBJ_ARC; + new_obj->Attributes.post_change = pcb_obj_attrib_post_change; + + pcb_arc_reg(layer, new_obj); + + return new_obj; +} + +pcb_arc_t *pcb_arc_alloc(pcb_layer_t *layer) +{ + return pcb_arc_alloc_id(layer, pcb_create_ID_get()); +} + +/* computes the bounding box of an arc */ +static pcb_box_t pcb_arc_bbox_(const pcb_arc_t *Arc, int mini) +{ + double ca1, ca2, sa1, sa2; + double minx, maxx, miny, maxy, delta; + pcb_angle_t ang1, ang2; + pcb_coord_t width; + pcb_box_t res; + + /* first put angles into standard form: + * ang1 < ang2, both angles between 0 and 720 */ + delta = PCB_CLAMP(Arc->Delta, -360, 360); + + if (delta > 0) { + ang1 = pcb_normalize_angle(Arc->StartAngle); + ang2 = pcb_normalize_angle(Arc->StartAngle + delta); + } + else { + ang1 = pcb_normalize_angle(Arc->StartAngle + delta); + ang2 = pcb_normalize_angle(Arc->StartAngle); + } + if (ang1 > ang2) + ang2 += 360; + /* Make sure full circles aren't treated as zero-length arcs */ + if (delta == 360 || delta == -360) + ang2 = ang1 + 360; + + /* calculate sines, cosines */ + sa1 = sin(PCB_M180 * ang1); + ca1 = cos(PCB_M180 * ang1); + sa2 = sin(PCB_M180 * ang2); + ca2 = cos(PCB_M180 * ang2); + + minx = MIN(ca1, ca2); + maxx = MAX(ca1, ca2); + miny = MIN(sa1, sa2); + maxy = MAX(sa1, sa2); + + /* Check for extreme angles */ + if ((ang1 <= 0 && ang2 >= 0) || (ang1 <= 360 && ang2 >= 360)) + maxx = 1; + if ((ang1 <= 90 && ang2 >= 90) || (ang1 <= 450 && ang2 >= 450)) + maxy = 1; + if ((ang1 <= 180 && ang2 >= 180) || (ang1 <= 540 && ang2 >= 540)) + minx = -1; + if ((ang1 <= 270 && ang2 >= 270) || (ang1 <= 630 && ang2 >= 630)) + miny = -1; + + /* Finally, calculate bounds, converting sane geometry into pcb geometry */ + res.X1 = Arc->X - Arc->Width * maxx; + res.X2 = Arc->X - Arc->Width * minx; + res.Y1 = Arc->Y + Arc->Height * miny; + res.Y2 = Arc->Y + Arc->Height * maxy; + + if (!mini) { + width = (Arc->Thickness + Arc->Clearance) / 2; + /* Adjust for our discrete polygon approximation */ + width = (double) width *MAX(PCB_POLY_CIRC_RADIUS_ADJ, (1.0 + PCB_POLY_ARC_MAX_DEVIATION)) + 0.5; + } + else + width = Arc->Thickness / 2; + + res.X1 -= width; + res.X2 += width; + res.Y1 -= width; + res.Y2 += width; + pcb_close_box(&res); + return res; +} + + +void pcb_arc_bbox(pcb_arc_t *Arc) +{ + Arc->BoundingBox = pcb_arc_bbox_(Arc, 0); + Arc->bbox_naked = pcb_arc_bbox_(Arc, 1); +} + + +void pcb_arc_get_end(pcb_arc_t *Arc, int which, pcb_coord_t *x, pcb_coord_t *y) +{ + if (which == 0) { + *x = pcb_round((double)Arc->X - (double)Arc->Width * cos(Arc->StartAngle * PCB_M180)); + *y = pcb_round((double)Arc->Y + (double)Arc->Height * sin(Arc->StartAngle * PCB_M180)); + } + else { + *x = pcb_round((double)Arc->X - (double)Arc->Width * cos((Arc->StartAngle + Arc->Delta) * PCB_M180)); + *y = pcb_round((double)Arc->Y + (double)Arc->Height * sin((Arc->StartAngle + Arc->Delta) * PCB_M180)); + } +} + +void pcb_arc_set_angles(pcb_layer_t *Layer, pcb_arc_t *a, pcb_angle_t new_sa, pcb_angle_t new_da) +{ + if (new_da >= 360) { + new_da = 360; + new_sa = 0; + } + pcb_poly_restore_to_poly(PCB->Data, PCB_OBJ_ARC, Layer, a); + pcb_r_delete_entry(Layer->arc_tree, (pcb_box_t *) a); + pcb_undo_add_obj_to_change_angles(PCB_OBJ_ARC, a, a, a); + a->StartAngle = new_sa; + a->Delta = new_da; + pcb_arc_bbox(a); + pcb_r_insert_entry(Layer->arc_tree, (pcb_box_t *) a); + pcb_poly_clear_from_poly(PCB->Data, PCB_OBJ_ARC, Layer, a); +} + + +void pcb_arc_set_radii(pcb_layer_t *Layer, pcb_arc_t *a, pcb_coord_t new_width, pcb_coord_t new_height) +{ + pcb_poly_restore_to_poly(PCB->Data, PCB_OBJ_ARC, Layer, a); + pcb_r_delete_entry(Layer->arc_tree, (pcb_box_t *) a); + pcb_undo_add_obj_to_change_radii(PCB_OBJ_ARC, a, a, a); + a->Width = new_width; + a->Height = new_height; + pcb_arc_bbox(a); + pcb_r_insert_entry(Layer->arc_tree, (pcb_box_t *) a); + pcb_poly_clear_from_poly(PCB->Data, PCB_OBJ_ARC, Layer, a); +} + + +/* creates a new arc on a layer */ +pcb_arc_t *pcb_arc_new(pcb_layer_t *Layer, pcb_coord_t X1, pcb_coord_t Y1, pcb_coord_t width, pcb_coord_t height, pcb_angle_t sa, pcb_angle_t dir, pcb_coord_t Thickness, pcb_coord_t Clearance, pcb_flag_t Flags, pcb_bool prevent_dups) +{ + pcb_arc_t *Arc; + + if ((prevent_dups) && (Layer->arc_tree != NULL)) { + pcb_rtree_it_t it; + pcb_any_obj_t *o; + pcb_box_t b; + + b.X1 = X1 - width; + b.Y1 = Y1 - height; + b.X2 = X1 + width; + b.Y2 = Y1 + height; + + for(o = pcb_rtree_first(&it, Layer->arc_tree, (pcb_rtree_box_t *)&b); o != NULL; o = pcb_rtree_next(&it)) { + pcb_arc_t *arc = (pcb_arc_t *)o; +TODO(": this does not catch all cases; there are more ways two arcs can be the same because of the angles") + if (arc->X == X1 && arc->Y == Y1 && arc->Width == width && pcb_normalize_angle(arc->StartAngle) == pcb_normalize_angle(sa) && arc->Delta == dir) + return NULL; /* prevent stacked arcs */ + } + } + + Arc = pcb_arc_alloc(Layer); + if (!Arc) + return Arc; + + Arc->Flags = Flags; + Arc->Thickness = Thickness; + Arc->Clearance = Clearance; + Arc->X = X1; + Arc->Y = Y1; + Arc->Width = width; + Arc->Height = height; + Arc->StartAngle = sa; + Arc->Delta = dir; + pcb_add_arc_on_layer(Layer, Arc); + return Arc; +} + +static pcb_arc_t *pcb_arc_copy_meta(pcb_arc_t *dst, pcb_arc_t *src) +{ + if (dst == NULL) + return NULL; + pcb_attribute_copy_all(&dst->Attributes, &src->Attributes); + return dst; +} + + +pcb_arc_t *pcb_arc_dup(pcb_layer_t *dst, pcb_arc_t *src) +{ + pcb_arc_t *a = pcb_arc_new(dst, src->X, src->Y, src->Width, src->Height, src->StartAngle, src->Delta, src->Thickness, src->Clearance, src->Flags, pcb_false); + pcb_arc_copy_meta(a, src); + return a; +} + +pcb_arc_t *pcb_arc_dup_at(pcb_layer_t *dst, pcb_arc_t *src, pcb_coord_t dx, pcb_coord_t dy) +{ + pcb_arc_t *a = pcb_arc_new(dst, src->X+dx, src->Y+dy, src->Width, src->Height, src->StartAngle, src->Delta, src->Thickness, src->Clearance, src->Flags, pcb_false); + pcb_arc_copy_meta(a, src); + return a; +} + + +void pcb_add_arc_on_layer(pcb_layer_t *Layer, pcb_arc_t *Arc) +{ + pcb_arc_bbox(Arc); + if (!Layer->arc_tree) + Layer->arc_tree = pcb_r_create_tree(); + pcb_r_insert_entry(Layer->arc_tree, (pcb_box_t *) Arc); + Arc->type = PCB_OBJ_ARC; + PCB_SET_PARENT(Arc, layer, Layer); +} + + + +void pcb_arc_free(pcb_arc_t *arc) +{ + pcb_arc_unreg(arc); + free(arc); +} + + +int pcb_arc_eq(const pcb_host_trans_t *tr1, const pcb_arc_t *a1, const pcb_host_trans_t *tr2, const pcb_arc_t *a2) +{ + double sgn1 = tr1->on_bottom ? -1 : +1; + double sgn2 = tr2->on_bottom ? -1 : +1; + + if (pcb_field_neq(a1, a2, Thickness) || pcb_field_neq(a1, a2, Clearance)) return 0; + if (pcb_field_neq(a1, a2, Width) || pcb_field_neq(a1, a2, Height)) return 0; + + if (!PCB_FLAG_TEST(PCB_FLAG_FLOATER, a1) && !PCB_FLAG_TEST(PCB_FLAG_FLOATER, a2)) { + if (pcb_neq_tr_coords(tr1, a1->X, a1->Y, tr2, a2->X, a2->Y)) return 0; + if (pcb_normalize_angle(pcb_round(a1->StartAngle * sgn1 + tr1->rot * sgn1)) != pcb_normalize_angle(pcb_round(a2->StartAngle * sgn2 + tr2->rot * sgn2))) return 0; + if (pcb_round(a1->Delta * sgn1) != pcb_round(a2->Delta * sgn2)) return 0; + } + + return 1; +} + +unsigned int pcb_arc_hash(const pcb_host_trans_t *tr, const pcb_arc_t *a) +{ + unsigned int crd = 0; + double sgn = tr->on_bottom ? -1 : +1; + + if (!PCB_FLAG_TEST(PCB_FLAG_FLOATER, a)) { + pcb_coord_t x, y; + pcb_hash_tr_coords(tr, &x, &y, a->X, a->Y); + crd = pcb_hash_coord(x) ^ pcb_hash_coord(y) ^ + pcb_hash_coord(pcb_normalize_angle(pcb_round(a->StartAngle*sgn + tr->rot*sgn))) ^ pcb_hash_coord(pcb_round(a->Delta * sgn)); + } + + return + pcb_hash_coord(a->Thickness) ^ pcb_hash_coord(a->Clearance) ^ + pcb_hash_coord(a->Width) ^ pcb_hash_coord(a->Height) ^ crd; +} + +pcb_coord_t pcb_arc_length(const pcb_arc_t *arc) +{ + double da = arc->Delta; + double r = ((double)arc->Width + (double)arc->Height) / 2.0; /* TODO: lame approximation */ + if (da < 0) + da = -da; + while(da > 360.0) + da = 360.0; + return pcb_round(2.0*r*M_PI*da/360.0); +} + +double pcb_arc_area(const pcb_arc_t *arc) +{ + return + (pcb_arc_length(arc) * (double)arc->Thickness /* body */ + + (double)arc->Thickness * (double)arc->Thickness * (double)M_PI); /* cap circles */ +} + +pcb_box_t pcb_arc_mini_bbox(const pcb_arc_t *arc) +{ + return pcb_arc_bbox_(arc, 1); +} + +void pcb_arc_pre(pcb_arc_t *arc) +{ + pcb_layer_t *ly = pcb_layer_get_real(arc->parent.layer); + if (ly == NULL) + return; + if (ly->arc_tree != NULL) + pcb_r_delete_entry(ly->arc_tree, (pcb_box_t *)arc); + pcb_poly_restore_to_poly(ly->parent.data, PCB_OBJ_ARC, ly, arc); +} + +void pcb_arc_post(pcb_arc_t *arc) +{ + pcb_layer_t *ly = pcb_layer_get_real(arc->parent.layer); + if (ly == NULL) + return; + if (ly->arc_tree != NULL) + pcb_r_insert_entry(ly->arc_tree, (pcb_box_t *)arc); + pcb_poly_clear_from_poly(ly->parent.data, PCB_OBJ_ARC, ly, arc); +} + + +/***** operations *****/ + +/* copies an arc to buffer */ +void *pcb_arcop_add_to_buffer(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_arc_t *Arc) +{ + pcb_layer_t *layer = &ctx->buffer.dst->Layer[pcb_layer_id(ctx->buffer.src, Layer)]; + pcb_arc_t *a = pcb_arc_new(layer, Arc->X, Arc->Y, + Arc->Width, Arc->Height, Arc->StartAngle, Arc->Delta, + Arc->Thickness, Arc->Clearance, pcb_flag_mask(Arc->Flags, PCB_FLAG_FOUND | ctx->buffer.extraflg), pcb_false); + + pcb_arc_copy_meta(a, Arc); + return a; +} + +/* moves an arc between board and buffer */ +void *pcb_arcop_move_buffer(pcb_opctx_t *ctx, pcb_layer_t *dstly, pcb_arc_t *arc) +{ + pcb_layer_t *srcly = arc->parent.layer; + + assert(arc->parent_type == PCB_PARENT_LAYER); + if ((dstly == NULL) || (dstly == srcly)) /* auto layer in dst */ + dstly = &ctx->buffer.dst->Layer[pcb_layer_id(ctx->buffer.src, srcly)]; + + pcb_poly_restore_to_poly(ctx->buffer.src, PCB_OBJ_ARC, srcly, arc); + pcb_r_delete_entry(srcly->arc_tree, (pcb_box_t *) arc); + + pcb_arc_unreg(arc); + pcb_arc_reg(dstly, arc); + + PCB_FLAG_CLEAR(PCB_FLAG_FOUND, arc); + + if (!dstly->arc_tree) + dstly->arc_tree = pcb_r_create_tree(); + pcb_r_insert_entry(dstly->arc_tree, (pcb_box_t *) arc); + pcb_poly_clear_from_poly(ctx->buffer.dst, PCB_OBJ_ARC, dstly, arc); + + return arc; +} + +/* changes the size of an arc */ +void *pcb_arcop_change_size(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_arc_t *Arc) +{ + pcb_coord_t value = (ctx->chgsize.is_absolute) ? ctx->chgsize.value : Arc->Thickness + ctx->chgsize.value; + + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, Arc)) + return NULL; + if (value <= PCB_MAX_LINESIZE && value >= PCB_MIN_LINESIZE && value != Arc->Thickness) { + pcb_undo_add_obj_to_size(PCB_OBJ_ARC, Layer, Arc, Arc); + pcb_arc_invalidate_erase(Arc); + pcb_r_delete_entry(Layer->arc_tree, (pcb_box_t *) Arc); + pcb_poly_restore_to_poly(PCB->Data, PCB_OBJ_ARC, Layer, Arc); + Arc->Thickness = value; + pcb_arc_bbox(Arc); + pcb_r_insert_entry(Layer->arc_tree, (pcb_box_t *) Arc); + pcb_poly_clear_from_poly(PCB->Data, PCB_OBJ_ARC, Layer, Arc); + pcb_arc_invalidate_draw(Layer, Arc); + return Arc; + } + return NULL; +} + +/* changes the clearance size of an arc */ +void *pcb_arcop_change_clear_size(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_arc_t *Arc) +{ + pcb_coord_t value = (ctx->chgsize.is_absolute) ? ctx->chgsize.value : Arc->Clearance + ctx->chgsize.value; + + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, Arc) || !PCB_FLAG_TEST(PCB_FLAG_CLEARLINE, Arc)) + return NULL; + if (value < 0) + value = 0; + value = MIN(PCB_MAX_LINESIZE, value); + if (!ctx->chgsize.is_absolute && ctx->chgsize.value < 0 && value < conf_core.design.bloat * 2) + value = 0; + if (ctx->chgsize.value > 0 && value < conf_core.design.bloat * 2) + value = conf_core.design.bloat * 2 + 2; + if (value != Arc->Clearance) { + pcb_undo_add_obj_to_clear_size(PCB_OBJ_ARC, Layer, Arc, Arc); + pcb_arc_invalidate_erase(Arc); + pcb_r_delete_entry(Layer->arc_tree, (pcb_box_t *) Arc); + pcb_poly_restore_to_poly(PCB->Data, PCB_OBJ_ARC, Layer, Arc); + Arc->Clearance = value; + pcb_arc_bbox(Arc); + pcb_r_insert_entry(Layer->arc_tree, (pcb_box_t *) Arc); + pcb_poly_clear_from_poly(PCB->Data, PCB_OBJ_ARC, Layer, Arc); + pcb_arc_invalidate_draw(Layer, Arc); + return Arc; + } + return NULL; +} + +/* changes the radius of an arc (is_primary 0=width or 1=height or 2=both) */ +void *pcb_arcop_change_radius(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_arc_t *Arc) +{ + pcb_coord_t value, *dst; + void *a0, *a1; + + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, Arc)) + return NULL; + + switch(ctx->chgsize.is_primary) { + case 0: dst = &Arc->Width; break; + case 1: dst = &Arc->Height; break; + case 2: + ctx->chgsize.is_primary = 0; a0 = pcb_arcop_change_radius(ctx, Layer, Arc); + ctx->chgsize.is_primary = 1; a1 = pcb_arcop_change_radius(ctx, Layer, Arc); + if ((a0 != NULL) || (a1 != NULL)) + return Arc; + return NULL; + } + + value = (ctx->chgsize.is_absolute) ? ctx->chgsize.value : (*dst) + ctx->chgsize.value; + value = MIN(PCB_MAX_ARCSIZE, MAX(value, PCB_MIN_ARCSIZE)); + if (value != *dst) { + pcb_undo_add_obj_to_change_radii(PCB_OBJ_ARC, Layer, Arc, Arc); + pcb_arc_invalidate_erase(Arc); + pcb_r_delete_entry(Layer->arc_tree, (pcb_box_t *) Arc); + pcb_poly_restore_to_poly(PCB->Data, PCB_OBJ_ARC, Layer, Arc); + *dst = value; + pcb_arc_bbox(Arc); + pcb_r_insert_entry(Layer->arc_tree, (pcb_box_t *) Arc); + pcb_poly_clear_from_poly(PCB->Data, PCB_OBJ_ARC, Layer, Arc); + pcb_arc_invalidate_draw(Layer, Arc); + return Arc; + } + return NULL; +} + +/* changes the angle of an arc (is_primary 0=start or 1=end) */ +void *pcb_arcop_change_angle(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_arc_t *Arc) +{ + pcb_angle_t value, *dst; + void *a0, *a1; + + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, Arc)) + return NULL; + + switch(ctx->chgangle.is_primary) { + case 0: dst = &Arc->StartAngle; break; + case 1: dst = &Arc->Delta; break; + case 2: + ctx->chgangle.is_primary = 0; a0 = pcb_arcop_change_angle(ctx, Layer, Arc); + ctx->chgangle.is_primary = 1; a1 = pcb_arcop_change_angle(ctx, Layer, Arc); + if ((a0 != NULL) || (a1 != NULL)) + return Arc; + return NULL; + } + + value = (ctx->chgangle.is_absolute) ? ctx->chgangle.value : (*dst) + ctx->chgangle.value; + if ((value > 360.0) || (value < -360.0)) + value = fmod(value, 360.0); + + if (value != *dst) { + pcb_undo_add_obj_to_change_angles(PCB_OBJ_ARC, Layer, Arc, Arc); + pcb_arc_invalidate_erase(Arc); + pcb_r_delete_entry(Layer->arc_tree, (pcb_box_t *) Arc); + pcb_poly_restore_to_poly(PCB->Data, PCB_OBJ_ARC, Layer, Arc); + *dst = value; + pcb_arc_bbox(Arc); + pcb_r_insert_entry(Layer->arc_tree, (pcb_box_t *) Arc); + pcb_poly_clear_from_poly(PCB->Data, PCB_OBJ_ARC, Layer, Arc); + pcb_arc_invalidate_draw(Layer, Arc); + return Arc; + } + return NULL; +} + +/* changes the clearance flag of an arc */ +void *pcb_arcop_change_join(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_arc_t *Arc) +{ + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, Arc)) + return NULL; + pcb_arc_invalidate_erase(Arc); + if (PCB_FLAG_TEST(PCB_FLAG_CLEARLINE, Arc)) { + pcb_poly_restore_to_poly(PCB->Data, PCB_OBJ_ARC, Layer, Arc); + pcb_undo_add_obj_to_clear_poly(PCB_OBJ_ARC, Layer, Arc, Arc, pcb_false); + } + pcb_undo_add_obj_to_flag(Arc); + PCB_FLAG_TOGGLE(PCB_FLAG_CLEARLINE, Arc); + if (PCB_FLAG_TEST(PCB_FLAG_CLEARLINE, Arc)) { + pcb_poly_clear_from_poly(PCB->Data, PCB_OBJ_ARC, Layer, Arc); + pcb_undo_add_obj_to_clear_poly(PCB_OBJ_ARC, Layer, Arc, Arc, pcb_true); + } + pcb_arc_invalidate_draw(Layer, Arc); + return Arc; +} + +/* sets the clearance flag of an arc */ +void *pcb_arcop_set_join(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_arc_t *Arc) +{ + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, Arc) || PCB_FLAG_TEST(PCB_FLAG_CLEARLINE, Arc)) + return NULL; + return pcb_arcop_change_join(ctx, Layer, Arc); +} + +/* clears the clearance flag of an arc */ +void *pcb_arcop_clear_join(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_arc_t *Arc) +{ + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, Arc) || !PCB_FLAG_TEST(PCB_FLAG_CLEARLINE, Arc)) + return NULL; + return pcb_arcop_change_join(ctx, Layer, Arc); +} + +/* copies an arc */ +void *pcb_arcop_copy(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_arc_t *Arc) +{ + pcb_arc_t *arc; + + arc = pcb_arc_new(Layer, Arc->X + ctx->copy.DeltaX, + Arc->Y + ctx->copy.DeltaY, Arc->Width, Arc->Height, Arc->StartAngle, + Arc->Delta, Arc->Thickness, Arc->Clearance, pcb_flag_mask(Arc->Flags, PCB_FLAG_FOUND), pcb_true); + if (!arc) + return arc; + pcb_arc_copy_meta(arc, Arc); + pcb_arc_invalidate_draw(Layer, arc); + pcb_undo_add_obj_to_create(PCB_OBJ_ARC, Layer, arc, arc); + return arc; +} + +/* moves an arc */ +void *pcb_arcop_move_noclip(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_arc_t *Arc) +{ + if (Layer->meta.real.vis) { + pcb_arc_invalidate_erase(Arc); + pcb_arc_move(Arc, ctx->move.dx, ctx->move.dy); + pcb_arc_invalidate_draw(Layer, Arc); + } + else { + pcb_arc_move(Arc, ctx->move.dx, ctx->move.dy); + } + return Arc; +} + +void *pcb_arcop_move(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_arc_t *Arc) +{ + pcb_r_delete_entry(Layer->arc_tree, (pcb_box_t *) Arc); + pcb_poly_restore_to_poly(PCB->Data, PCB_OBJ_ARC, Layer, Arc); + pcb_arcop_move_noclip(ctx, Layer, Arc); + pcb_r_insert_entry(Layer->arc_tree, (pcb_box_t *) Arc); + pcb_poly_clear_from_poly(PCB->Data, PCB_OBJ_ARC, Layer, Arc); + return Arc; +} + +void *pcb_arcop_clip(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_arc_t *Arc) +{ + if (ctx->clip.restore) { + pcb_r_delete_entry(Layer->arc_tree, (pcb_box_t *) Arc); + pcb_poly_restore_to_poly(PCB->Data, PCB_OBJ_ARC, Layer, Arc); + } + if (ctx->clip.clear) { + pcb_r_insert_entry(Layer->arc_tree, (pcb_box_t *) Arc); + pcb_poly_clear_from_poly(PCB->Data, PCB_OBJ_ARC, Layer, Arc); + } + return Arc; +} + +/* moves an arc between layers; lowlevel routines */ +void *pcb_arcop_move_to_layer_low(pcb_opctx_t *ctx, pcb_layer_t * Source, pcb_arc_t * arc, pcb_layer_t * Destination) +{ + pcb_r_delete_entry(Source->arc_tree, (pcb_box_t *) arc); + + pcb_arc_unreg(arc); + pcb_arc_reg(Destination, arc); + + if (!Destination->arc_tree) + Destination->arc_tree = pcb_r_create_tree(); + pcb_r_insert_entry(Destination->arc_tree, (pcb_box_t *) arc); + + return arc; +} + + +/* moves an arc between layers */ +void *pcb_arcop_move_to_layer(pcb_opctx_t *ctx, pcb_layer_t * Layer, pcb_arc_t * Arc) +{ + pcb_arc_t *newone; + + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, Arc)) { + pcb_message(PCB_MSG_WARNING, "Sorry, arc object is locked\n"); + return NULL; + } + if (ctx->move.dst_layer == Layer && Layer->meta.real.vis) + pcb_arc_invalidate_draw(Layer, Arc); + if (ctx->move.dst_layer == Layer) + return Arc; + pcb_undo_add_obj_to_move_to_layer(PCB_OBJ_ARC, Layer, Arc, Arc); + pcb_poly_restore_to_poly(PCB->Data, PCB_OBJ_ARC, Layer, Arc); + if (Layer->meta.real.vis) + pcb_arc_invalidate_erase(Arc); + newone = (pcb_arc_t *) pcb_arcop_move_to_layer_low(ctx, Layer, Arc, ctx->move.dst_layer); + pcb_poly_clear_from_poly(PCB->Data, PCB_OBJ_ARC, ctx->move.dst_layer, Arc); + if (ctx->move.dst_layer->meta.real.vis) + pcb_arc_invalidate_draw(ctx->move.dst_layer, newone); + return newone; +} + +/* destroys an arc from a layer */ +void *pcb_arcop_destroy(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_arc_t *Arc) +{ + pcb_r_delete_entry(Layer->arc_tree, (pcb_box_t *) Arc); + + pcb_arc_free(Arc); + return NULL; +} + +/* removes an arc from a layer */ +void *pcb_arcop_remove(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_arc_t *Arc) +{ + /* erase from screen */ + if (Layer->meta.real.vis) + pcb_arc_invalidate_erase(Arc); + pcb_undo_move_obj_to_remove(PCB_OBJ_ARC, Layer, Arc, Arc); + return NULL; +} + +void *pcb_arcop_remove_point(pcb_opctx_t *ctx, pcb_layer_t *l, pcb_arc_t *a, int *end_id) +{ + return pcb_arcop_remove(ctx, l, a); +} + +void *pcb_arc_destroy(pcb_layer_t *Layer, pcb_arc_t *Arc) +{ + void *res; + pcb_opctx_t ctx; + + ctx.remove.pcb = PCB; + ctx.remove.destroy_target = NULL; + + res = pcb_arcop_remove(&ctx, Layer, Arc); + pcb_draw(); + return res; +} + +/* rotates an arc */ +void pcb_arc_rotate90(pcb_arc_t *Arc, pcb_coord_t X, pcb_coord_t Y, unsigned Number) +{ + pcb_coord_t save; + + /* add Number*90 degrees (i.e., Number quarter-turns) */ + Arc->StartAngle = pcb_normalize_angle(Arc->StartAngle + Number * 90); + PCB_COORD_ROTATE90(Arc->X, Arc->Y, X, Y, Number); + + /* now change width and height */ + if (Number == 1 || Number == 3) { + save = Arc->Width; + Arc->Width = Arc->Height; + Arc->Height = save; + } + + /* can't optimize with box rotation due to closed boxes */ + pcb_arc_bbox(Arc); +} + +void pcb_arc_rotate(pcb_layer_t *layer, pcb_arc_t *arc, pcb_coord_t X, pcb_coord_t Y, double cosa, double sina, pcb_angle_t angle) +{ + if (layer->arc_tree != NULL) + pcb_r_delete_entry(layer->arc_tree, (pcb_box_t *) arc); + pcb_rotate(&arc->X, &arc->Y, X, Y, cosa, sina); + arc->StartAngle = pcb_normalize_angle(arc->StartAngle + angle); + if (layer->arc_tree != NULL) + pcb_r_insert_entry(layer->arc_tree, (pcb_box_t *) arc); +} + +void pcb_arc_mirror(pcb_layer_t *layer, pcb_arc_t *arc, pcb_coord_t y_offs) +{ + if (layer->arc_tree != NULL) + pcb_r_delete_entry(layer->arc_tree, (pcb_box_t *) arc); + arc->X = PCB_SWAP_X(arc->X); + arc->Y = PCB_SWAP_Y(arc->Y) + y_offs; + arc->StartAngle = PCB_SWAP_ANGLE(arc->StartAngle); + arc->Delta = PCB_SWAP_DELTA(arc->Delta); + pcb_arc_bbox(arc); + if (layer->arc_tree != NULL) + pcb_r_insert_entry(layer->arc_tree, (pcb_box_t *) arc); +} + +void pcb_arc_flip_side(pcb_layer_t *layer, pcb_arc_t *arc) +{ + pcb_r_delete_entry(layer->arc_tree, (pcb_box_t *) arc); + arc->X = PCB_SWAP_X(arc->X); + arc->Y = PCB_SWAP_Y(arc->Y); + arc->StartAngle = PCB_SWAP_ANGLE(arc->StartAngle); + arc->Delta = PCB_SWAP_DELTA(arc->Delta); + pcb_arc_bbox(arc); + pcb_r_insert_entry(layer->arc_tree, (pcb_box_t *) arc); +} + +void pcb_arc_scale(pcb_arc_t *arc, double sx, double sy, double sth) +{ + int onbrd = (arc->parent.layer != NULL) && (!arc->parent.layer->is_bound); + + if (onbrd) + pcb_arc_pre(arc); + + if (sx != 1.0) { + arc->X = pcb_round((double)arc->X * sx); + arc->Width = pcb_round((double)arc->Width * sx); + } + + if (sy != 1.0) { + arc->Y = pcb_round((double)arc->Y * sy); + arc->Height = pcb_round((double)arc->Height * sy); + } + + if (sth != 1.0) + arc->Thickness = pcb_round((double)arc->Thickness * sth); + + pcb_arc_bbox(arc); + if (onbrd) + pcb_arc_post(arc); +} + +/* rotates an arc */ +void *pcb_arcop_rotate90(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_arc_t *Arc) +{ + pcb_arc_invalidate_erase(Arc); + pcb_poly_restore_to_poly(PCB->Data, PCB_OBJ_ARC, Layer, Arc); + if (Layer->arc_tree != NULL) + pcb_r_delete_entry(Layer->arc_tree, (pcb_box_t *) Arc); + pcb_arc_rotate90(Arc, ctx->rotate.center_x, ctx->rotate.center_y, ctx->rotate.number); + if (Layer->arc_tree != NULL) + pcb_r_insert_entry(Layer->arc_tree, (pcb_box_t *) Arc); + pcb_poly_clear_from_poly(PCB->Data, PCB_OBJ_ARC, Layer, Arc); + pcb_arc_invalidate_draw(Layer, Arc); + return Arc; +} + +void *pcb_arcop_rotate(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_arc_t *Arc) +{ + pcb_arc_invalidate_erase(Arc); + pcb_poly_restore_to_poly(PCB->Data, PCB_OBJ_ARC, Layer, Arc); + pcb_arc_rotate(Layer, Arc, ctx->rotate.center_x, ctx->rotate.center_y, ctx->rotate.cosa, ctx->rotate.sina, ctx->rotate.angle); + pcb_poly_clear_from_poly(PCB->Data, PCB_OBJ_ARC, Layer, Arc); + pcb_arc_invalidate_draw(Layer, Arc); + return Arc; +} + +void *pcb_arc_insert_point(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_arc_t *arc) +{ + pcb_angle_t end_ang = arc->StartAngle + arc->Delta; + pcb_coord_t x = pcb_crosshair.X, y = pcb_crosshair.Y; + pcb_angle_t angle = atan2(-(y - arc->Y), (x - arc->X)) * 180.0 / M_PI + 180.0; + pcb_arc_t *new_arc; + + if (end_ang > 360.0) + end_ang -= 360.0; + if (end_ang < -360.0) + end_ang += 360.0; + + if ((arc->Delta < 0) || (arc->Delta > 180)) + new_arc = pcb_arc_new(Layer, arc->X, arc->Y, arc->Width, arc->Height, angle, end_ang - angle + 360.0, arc->Thickness, arc->Clearance, arc->Flags, pcb_true); + else + new_arc = pcb_arc_new(Layer, arc->X, arc->Y, arc->Width, arc->Height, angle, end_ang - angle, arc->Thickness, arc->Clearance, arc->Flags, pcb_true); + + if (new_arc != NULL) { + pcb_arc_copy_meta(new_arc, arc); + PCB_FLAG_CHANGE(PCB_CHGFLG_SET, PCB_FLAG_FOUND, new_arc); + if (arc->Delta < 0) + pcb_arc_set_angles(Layer, arc, arc->StartAngle, angle - arc->StartAngle - 360.0); + else + pcb_arc_set_angles(Layer, arc, arc->StartAngle, angle - arc->StartAngle); + } + return new_arc; +} + +void *pcb_arcop_change_flag(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_arc_t *Arc) +{ + static pcb_flag_values_t pcb_arc_flags = 0; + if (pcb_arc_flags == 0) + pcb_arc_flags = pcb_obj_valid_flags(PCB_OBJ_ARC); + + if ((ctx->chgflag.flag & pcb_arc_flags) != ctx->chgflag.flag) + return NULL; + if ((ctx->chgflag.flag & PCB_FLAG_TERMNAME) && (Arc->term == NULL)) + return NULL; + pcb_undo_add_obj_to_flag(Arc); + + if (ctx->chgflag.flag & PCB_FLAG_CLEARLINE) + pcb_poly_restore_to_poly(ctx->chgflag.pcb->Data, PCB_OBJ_ARC, Arc->parent.layer, Arc); + + PCB_FLAG_CHANGE(ctx->chgflag.how, ctx->chgflag.flag, Arc); + + if (ctx->chgflag.flag & PCB_FLAG_CLEARLINE) + pcb_poly_clear_from_poly(ctx->chgflag.pcb->Data, PCB_OBJ_ARC, Arc->parent.layer, Arc); + + return Arc; +} + +void *pcb_arcop_invalidate_label(pcb_opctx_t *ctx, pcb_layer_t *layer, pcb_arc_t *arc) +{ + pcb_arc_name_invalidate_draw(arc); + return arc; +} + + +/*** draw ***/ + +static void arc_label_pos(const pcb_arc_t *arc, pcb_coord_t *x0, pcb_coord_t *y0, pcb_bool_t *vert) +{ + double da, ea, la; + + da = PCB_CLAMP(arc->Delta, -360, 360); + ea = arc->StartAngle + da; + while(ea < -360) ea += 360; + while(ea > +360) ea -= 360; + + la = (arc->StartAngle+ea)/2.0; + + *x0 = pcb_round((double)arc->X - (double)arc->Width * cos(la * PCB_M180)); + *y0 = pcb_round((double)arc->Y + (double)arc->Height * sin(la * PCB_M180)); + *vert = (((la < 45) && (la > -45)) || ((la > 135) && (la < 225))); +} + +void pcb_arc_middle(const pcb_arc_t *arc, pcb_coord_t *x, pcb_coord_t *y) +{ + pcb_bool_t waste; + arc_label_pos(arc, x, y, &waste); +} + +void pcb_arc_name_invalidate_draw(pcb_arc_t *arc) +{ + if (arc->term != NULL) { + pcb_text_t text; + pcb_coord_t x0, y0; + pcb_bool_t vert; + + arc_label_pos(arc, &x0, &y0, &vert); + pcb_term_label_invalidate(x0, y0, 100.0, vert, pcb_true, (pcb_any_obj_t *)arc); + } +} + +void pcb_arc_draw_label(pcb_draw_info_t *info, pcb_arc_t *arc) +{ + if (arc->term != NULL) { + pcb_coord_t x0, y0; + pcb_bool_t vert; + + arc_label_pos(arc, &x0, &y0, &vert); + pcb_term_label_draw(info, x0, y0, conf_core.appearance.term_label_size, vert, pcb_true, (pcb_any_obj_t *)arc); + } +} + +void pcb_arc_draw_(pcb_draw_info_t *info, pcb_arc_t *arc, int allow_term_gfx) +{ + pcb_coord_t thickness = arc->Thickness; + + if (!arc->Thickness) + return; + + if (delayed_terms_enabled && (arc->term != NULL)) { + pcb_draw_delay_obj_add((pcb_any_obj_t *)arc); + return; + } + + if ((info != NULL) && (info->xform != NULL) && (info->xform->bloat != 0)) { + thickness += info->xform->bloat; + if (thickness < 1) + thickness = 1; + } + + PCB_DRAW_BBOX(arc); + + if (!conf_core.editor.thin_draw && !conf_core.editor.wireframe_draw) + { + if ((allow_term_gfx) && pcb_draw_term_need_gfx(arc) && pcb_draw_term_hid_permission()) { + pcb_hid_set_line_cap(pcb_draw_out.active_padGC, pcb_cap_round); + pcb_hid_set_line_width(pcb_draw_out.active_padGC, thickness); + pcb_gui->draw_arc(pcb_draw_out.active_padGC, arc->X, arc->Y, arc->Width, arc->Height, arc->StartAngle, arc->Delta); + pcb_hid_set_line_width(pcb_draw_out.fgGC, PCB_DRAW_TERM_GFX_WIDTH); + } + else + pcb_hid_set_line_width(pcb_draw_out.fgGC, thickness); + pcb_hid_set_line_cap(pcb_draw_out.fgGC, pcb_cap_round); + pcb_gui->draw_arc(pcb_draw_out.fgGC, arc->X, arc->Y, arc->Width, arc->Height, arc->StartAngle, arc->Delta); + } + else + { + pcb_hid_set_line_width(pcb_draw_out.fgGC, 0); + pcb_hid_set_line_cap(pcb_draw_out.fgGC, pcb_cap_round); + + if(conf_core.editor.thin_draw) + pcb_gui->draw_arc(pcb_draw_out.fgGC, arc->X, arc->Y, arc->Width, arc->Height, arc->StartAngle, arc->Delta); + + if(conf_core.editor.wireframe_draw) + pcb_draw_wireframe_arc(pcb_draw_out.fgGC, arc, thickness); + } + if (arc->term != NULL) { + if ((pcb_draw_force_termlab) || PCB_FLAG_TEST(PCB_FLAG_TERMNAME, arc)) + pcb_draw_delay_label_add((pcb_any_obj_t *)arc); + } +} + +static void pcb_arc_draw(pcb_draw_info_t *info, pcb_arc_t *arc, int allow_term_gfx) +{ + const pcb_color_t *color; + pcb_color_t buf; + const pcb_layer_t *layer = info->layer != NULL ? info->layer : pcb_layer_get_real(arc->parent.layer); + + if (layer == NULL) /* if the layer is inbound, e.g. in preview, fall back using the layer recipe */ + layer = arc->parent.layer; + + if (PCB_FLAG_TEST(PCB_FLAG_WARN, arc)) + color = &conf_core.appearance.color.warn; + else if (PCB_FLAG_TEST(PCB_FLAG_SELECTED | PCB_FLAG_FOUND, arc)) { + if (PCB_FLAG_TEST(PCB_FLAG_SELECTED, arc)) { + if (layer->is_bound) + PCB_OBJ_COLOR_ON_BOUND_LAYER(color, layer, 1); + else + color = &conf_core.appearance.color.selected; + } + else + color = &conf_core.appearance.color.connected; + } + else if (PCB_HAS_COLOROVERRIDE(arc)) { + color = arc->override_color; + } + else if (layer->is_bound) + PCB_OBJ_COLOR_ON_BOUND_LAYER(color, layer, 0); + else + color = &layer->meta.real.color; + + if (PCB_FLAG_TEST(PCB_FLAG_ONPOINT, arc)) { + pcb_lighten_color(color, &buf, 1.75); + color = &buf; + } + pcb_gui->set_color(pcb_draw_out.fgGC, color); + pcb_arc_draw_(info, arc, allow_term_gfx); +} + +pcb_r_dir_t pcb_arc_draw_callback(const pcb_box_t * b, void *cl) +{ + pcb_arc_t *arc = (pcb_arc_t *)b; + pcb_draw_info_t *info = cl; + + if (pcb_hidden_floater((pcb_any_obj_t*)b)) + return PCB_R_DIR_FOUND_CONTINUE; + + if (!PCB->SubcPartsOn && pcb_lobj_parent_subc(arc->parent_type, &arc->parent)) + return PCB_R_DIR_NOT_FOUND; + + pcb_arc_draw(info, arc, 0); + return PCB_R_DIR_FOUND_CONTINUE; +} + +pcb_r_dir_t pcb_arc_draw_term_callback(const pcb_box_t * b, void *cl) +{ + pcb_arc_t *arc = (pcb_arc_t *)b; + pcb_draw_info_t *info = cl; + + if (pcb_hidden_floater((pcb_any_obj_t*)b)) + return PCB_R_DIR_FOUND_CONTINUE; + + if (!PCB->SubcPartsOn && pcb_lobj_parent_subc(arc->parent_type, &arc->parent)) + return PCB_R_DIR_NOT_FOUND; + + pcb_arc_draw(info, arc, 1); + return PCB_R_DIR_FOUND_CONTINUE; +} + +/* erases an arc on a layer */ +void pcb_arc_invalidate_erase(pcb_arc_t *Arc) +{ + if (!Arc->Thickness) + return; + pcb_draw_invalidate(Arc); + pcb_flag_erase(&Arc->Flags); +} + +void pcb_arc_invalidate_draw(pcb_layer_t *Layer, pcb_arc_t *Arc) +{ + pcb_draw_invalidate(Arc); +} Index: tags/2.1.2/src/obj_arc.h =================================================================== --- tags/2.1.2/src/obj_arc.h (nonexistent) +++ tags/2.1.2/src/obj_arc.h (revision 24813) @@ -0,0 +1,143 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +/* Drawing primitive: (elliptical) arc */ + +#ifndef PCB_OBJ_ARC_H +#define PCB_OBJ_ARC_H + +#include +#include "obj_common.h" + +struct pcb_arc_s { /* holds information about arcs */ + PCB_ANY_PRIMITIVE_FIELDS; + pcb_coord_t Thickness, Clearance; + pcb_coord_t Width, Height, /* length of axis */ + X, Y; /* center coordinates */ + pcb_angle_t StartAngle, Delta; /* the two limiting angles in degrees */ + gdl_elem_t link; /* an arc is in a list: either on a layer or in an element or in a font */ +}; + +/*** Memory ***/ +pcb_arc_t *pcb_arc_alloc(pcb_layer_t *); +pcb_arc_t *pcb_arc_alloc_id(pcb_layer_t *layer, long int id); +void pcb_arc_free(pcb_arc_t *data); + +pcb_arc_t *pcb_arc_new(pcb_layer_t *Layer, pcb_coord_t center_x, pcb_coord_t center_y, pcb_coord_t width_r, pcb_coord_t height_r, pcb_angle_t start_angle, pcb_angle_t delta_angle, pcb_coord_t Thickness, pcb_coord_t Clearance, pcb_flag_t Flags, pcb_bool prevent_dups); +pcb_arc_t *pcb_arc_dup(pcb_layer_t *dst, pcb_arc_t *src); +pcb_arc_t *pcb_arc_dup_at(pcb_layer_t *dst, pcb_arc_t *src, pcb_coord_t dx, pcb_coord_t dy); +void *pcb_arc_destroy(pcb_layer_t *Layer, pcb_arc_t *Arc); + +void pcb_arc_reg(pcb_layer_t *layer, pcb_arc_t *arc); +void pcb_arc_unreg(pcb_arc_t *arc); + +/* Add objects without creating them or making any "sanity modifications" to them */ +void pcb_add_arc_on_layer(pcb_layer_t *Layer, pcb_arc_t *Arc); + + +/*** Utility ***/ +void pcb_arc_bbox(pcb_arc_t *Arc); +void pcb_arc_rotate90(pcb_arc_t *Arc, pcb_coord_t X, pcb_coord_t Y, unsigned Number); +void pcb_arc_rotate(pcb_layer_t *layer, pcb_arc_t *arc, pcb_coord_t X, pcb_coord_t Y, double cosa, double sina, pcb_angle_t angle); +void pcb_arc_mirror(pcb_layer_t *layer, pcb_arc_t *arc, pcb_coord_t y_offs); +void pcb_arc_flip_side(pcb_layer_t *layer, pcb_arc_t *arc); +void pcb_arc_scale(pcb_arc_t *arc, double sx, double sy, double sth); +pcb_box_t pcb_arc_mini_bbox(const pcb_arc_t *arc); + + +/*** hash and eq ***/ +int pcb_arc_eq(const pcb_host_trans_t *tr1, const pcb_arc_t *a1, const pcb_host_trans_t *tr2, const pcb_arc_t *a2); +unsigned int pcb_arc_hash(const pcb_host_trans_t *tr, const pcb_arc_t *a); + + +/* Return the x;y coordinate of the endpoint of an arc; if which is 0, return + the endpoint that corresponds to StartAngle, else return the end angle's. */ +void pcb_arc_get_end(pcb_arc_t *Arc, int which, pcb_coord_t *x, pcb_coord_t *y); +void pcb_arc_middle(const pcb_arc_t *arc, pcb_coord_t *x, pcb_coord_t *y); + +void pcb_arc_set_angles(pcb_layer_t *Layer, pcb_arc_t *a, pcb_angle_t new_sa, pcb_angle_t new_da); +void pcb_arc_set_radii(pcb_layer_t *Layer, pcb_arc_t *a, pcb_coord_t new_width, pcb_coord_t new_height); + +pcb_coord_t pcb_arc_length(const pcb_arc_t *arc); +double pcb_arc_area(const pcb_arc_t *arc); + +/* ptr3 values for start and end point */ +extern int *pcb_arc_start_ptr, *pcb_arc_end_ptr; + +/* un-administrate a arc; call before changing geometry */ +void pcb_arc_pre(pcb_arc_t *arc); + +/* re-administrate a arc; call after changing geometry */ +void pcb_arc_post(pcb_arc_t *arc); + +#define pcb_arc_move(a,dx,dy) \ + do { \ + pcb_coord_t __dx__ = (dx), __dy__ = (dy); \ + pcb_arc_t *__a__ = (a); \ + PCB_MOVE_POINT((__a__)->X,(__a__)->Y,__dx__,__dy__); \ + PCB_BOX_MOVE_LOWLEVEL(&((__a__)->BoundingBox),__dx__,__dy__); \ + PCB_BOX_MOVE_LOWLEVEL(&((__a__)->bbox_naked),__dx__,__dy__); \ + } while(0) + +#define PCB_ARC_LOOP(element) do { \ + pcb_arc_t *arc; \ + gdl_iterator_t __it__; \ + linelist_foreach(&(element)->Arc, &__it__, arc) { + +#define PCB_ARC_ALL_LOOP(top) do { \ + pcb_cardinal_t l; \ + pcb_layer_t *layer = (top)->Layer; \ + for (l =0; l < ((top)->LayerN > 0 ? (top)->LayerN : PCB->Data->LayerN); l++, layer++) \ + { \ + PCB_ARC_LOOP(layer) + +#define PCB_ARC_COPPER_LOOP(top) do { \ + pcb_cardinal_t l; \ + pcb_layer_t *layer = (top)->Layer; \ + for (l =0; l < ((top)->LayerN > 0 ? (top)->LayerN : PCB->Data->LayerN); l++, layer++) \ + { \ + if (!(pcb_layer_flags(PCB, l) & PCB_LYT_COPPER)) continue; \ + PCB_ARC_LOOP(layer) + +#define PCB_ARC_SILK_LOOP(top) do { \ + pcb_cardinal_t l; \ + pcb_layer_t *layer = (top)->Layer; \ + for (l = 0; l < ((top)->LayerN > 0 ? (top)->LayerN : PCB->Data->LayerN); l++, layer++) \ + { \ + if (!(pcb_layer_flags(PCB, l) & PCB_LYT_SILK)) continue; \ + PCB_ARC_LOOP(layer) + +#define PCB_ARC_VISIBLE_LOOP(top) do { \ + pcb_cardinal_t l; \ + pcb_layer_t *layer = (top)->Layer; \ + for (l = 0; l < ((top)->LayerN > 0 ? (top)->LayerN : PCB->Data->LayerN); l++, layer++) \ + { \ + if (layer->meta.real.vis) \ + PCB_ARC_LOOP(layer) + +#endif Index: tags/2.1.2/src/obj_arc_draw.h =================================================================== --- tags/2.1.2/src/obj_arc_draw.h (nonexistent) +++ tags/2.1.2/src/obj_arc_draw.h (revision 24813) @@ -0,0 +1,44 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +/*** Standard draw of arcs ***/ + +#include "draw.h" + +/* Include rtree.h for this */ +#ifdef PCB_RTREE_H +pcb_r_dir_t pcb_arc_draw_callback(const pcb_box_t * b, void *cl); +pcb_r_dir_t pcb_arc_draw_term_callback(const pcb_box_t * b, void *cl); +#endif + +void pcb_arc_draw_(pcb_draw_info_t *info, pcb_arc_t *arc, int allow_term_gfx); +void pcb_arc_invalidate_erase(pcb_arc_t *Arc); +void pcb_arc_invalidate_draw(pcb_layer_t *Layer, pcb_arc_t *Arc); +void pcb_arc_name_invalidate_draw(pcb_arc_t *arc); +void pcb_arc_draw_label(pcb_draw_info_t *info, pcb_arc_t *arc); + Index: tags/2.1.2/src/obj_arc_list.c =================================================================== --- tags/2.1.2/src/obj_arc_list.c (nonexistent) +++ tags/2.1.2/src/obj_arc_list.c (revision 24813) @@ -0,0 +1,29 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2016 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#define TDL_DONT_UNDEF +#include "obj_arc_list.h" +#include Index: tags/2.1.2/src/obj_arc_list.h =================================================================== --- tags/2.1.2/src/obj_arc_list.h (nonexistent) +++ tags/2.1.2/src/obj_arc_list.h (revision 24813) @@ -0,0 +1,48 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2016 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#ifndef PCB_OBJ_ARC_LIST_H +#define PCB_OBJ_ARC_LIST_H + +#include "obj_common.h" +#include "obj_arc.h" + +/* List of Arcs */ +#define TDL(x) arclist_ ## x +#define TDL_LIST_T arclist_t +#define TDL_ITEM_T pcb_arc_t +#define TDL_FIELD link +#define TDL_SIZE_T size_t +#define TDL_FUNC + +#define arclist_foreach(list, iterator, loop_elem) \ + gdl_foreach_((&((list)->lst)), (iterator), (loop_elem)) + + +#include +#include + +#endif Index: tags/2.1.2/src/obj_arc_op.h =================================================================== --- tags/2.1.2/src/obj_arc_op.h (nonexistent) +++ tags/2.1.2/src/obj_arc_op.h (revision 24813) @@ -0,0 +1,59 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +/*** Standard operations on arc ***/ + +#include "operation.h" + +void *pcb_arcop_add_to_buffer(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_arc_t *Arc); +void *pcb_arcop_move_buffer(pcb_opctx_t *ctx, pcb_layer_t *layer, pcb_arc_t *arc); +void *pcb_arcop_change_size(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_arc_t *Arc); +void *pcb_arcop_change_clear_size(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_arc_t *Arc); +void *pcb_arcop_change_radius(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_arc_t *Arc); +void *pcb_arcop_change_angle(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_arc_t *Arc); +void *pcb_arcop_change_join(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_arc_t *Arc); +void *pcb_arcop_set_join(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_arc_t *Arc); +void *pcb_arcop_clear_join(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_arc_t *Arc); +void *pcb_arcop_copy(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_arc_t *Arc); +void *pcb_arcop_move(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_arc_t *Arc); +void *pcb_arcop_move_noclip(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_arc_t *Arc); +void *pcb_arcop_clip(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_arc_t *Arc); +void *pcb_arcop_move_to_layer_low(pcb_opctx_t *ctx, pcb_layer_t * Source, pcb_arc_t * arc, pcb_layer_t * Destination); +void *pcb_arcop_move_to_layer(pcb_opctx_t *ctx, pcb_layer_t * Layer, pcb_arc_t * Arc); +void *pcb_arcop_destroy(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_arc_t *Arc); +void *pcb_arcop_remove(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_arc_t *Arc); +void *pcb_arcop_remove_point(pcb_opctx_t *ctx, pcb_layer_t *l, pcb_arc_t *a, int *end_id); +void *pcb_arcop_rotate90(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_arc_t *Arc); +void *pcb_arcop_rotate(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_arc_t *Arc); +void *pcb_arcop_change_flag(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_arc_t *Arc); +void *pcb_arcop_invalidate_label(pcb_opctx_t *ctx, pcb_layer_t *layer, pcb_arc_t *arc); + + +void *pcb_arc_insert_point(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_arc_t *arc); + + Index: tags/2.1.2/src/obj_arc_ui.c =================================================================== --- tags/2.1.2/src/obj_arc_ui.c (nonexistent) +++ tags/2.1.2/src/obj_arc_ui.c (revision 24813) @@ -0,0 +1,140 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2016 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +/* Arc UI logics */ + +#include "config.h" +#include +#include "obj_arc_ui.h" +#include "obj_arc.h" +#include "box.h" + + +#include + +static void draw_mark(pcb_hid_gc_t gc, const pcb_arc_t *arc) +{ + const pcb_coord_t mark = PCB_MM_TO_COORD(0.2); + pcb_gui->draw_line(gc, arc->X-mark, arc->Y, arc->X+mark, arc->Y); + pcb_gui->draw_line(gc, arc->X, arc->Y-mark, arc->X, arc->Y+mark); +} + +static void pcb_arc_ui_move_or_copy_angle(pcb_crosshair_t *ch) +{ + int *end_pt = ch->AttachedObject.Ptr3; + pcb_arc_t *arc = (pcb_arc_t *) pcb_crosshair.AttachedObject.Ptr2; + pcb_angle_t start = arc->StartAngle, delta = arc->Delta; + + if (end_pt == pcb_arc_start_ptr) { + double end2, new_delta, new_start = atan2(-(ch->Y - arc->Y), (ch->X - arc->X)) * 180.0 / M_PI + 180.0; + + end2 = start + delta; + new_delta = end2 - new_start; + if (new_delta > 360.0) + new_delta -= 360.0; + if (new_delta < -360.0) + new_delta += 360.0; + +/* fprintf(stderr, "start: %f new_start: %f delta=%f new delta=%f\n", start, new_start, delta, new_delta);*/ + + if (delta > 0) { + if (new_delta < 0) + new_delta += 360.0; + } + else { + if (new_delta > 0) + new_delta -= 360.0; + } + + start = new_start; + delta = new_delta; + } + else { + double new_delta, new_end = atan2(-(ch->Y - arc->Y), (ch->X - arc->X)) * 180.0 / M_PI + 180.0; + if (delta < 0) + new_end -= 360.0; +/* fprintf(stderr, "delta: %f abs-end: %f new-abs: %f new-delta: %f\n", delta, start+delta, new_end, new_end-start);*/ + new_delta = new_end-start; + if (delta > 0) { + if (new_delta < 0) + new_delta += 360.0; + } + else { + if (new_delta > 0) + new_delta -= 360.0; + } + delta = new_delta; + } + + /* remember the result of the calculation so the actual move code can reuse them */ + ch->AttachedObject.start_angle = start; + ch->AttachedObject.delta_angle = delta; + ch->AttachedObject.radius = 0; + + pcb_gui->draw_arc(ch->GC, arc->X, arc->Y, arc->Width, arc->Height, start, delta); + draw_mark(ch->GC, arc); +} + +void pcb_arc_ui_move_or_copy_endp(pcb_crosshair_t *ch) +{ + int *end_pt = ch->AttachedObject.Ptr3; + pcb_arc_t arc2, *arc = (pcb_arc_t *) pcb_crosshair.AttachedObject.Ptr2; + pcb_coord_t ex, ey; + double dx, dy, d; + + pcb_arc_get_end(arc, (end_pt != NULL), &ex, &ey); + + dx = (arc->X - ch->X); + dy = (arc->Y - ch->Y); + d = sqrt(dx*dx+dy*dy); + + ch->AttachedObject.radius = d; + + pcb_gui->draw_arc(ch->GC, arc->X, arc->Y, ch->AttachedObject.radius, ch->AttachedObject.radius, arc->StartAngle, arc->Delta); + + draw_mark(ch->GC, &arc2); +} + + +void pcb_arc_ui_move_or_copy(pcb_crosshair_t *ch) +{ + if (pcb_gui->shift_is_pressed() || (ch->AttachedObject.radius != 0)) + pcb_arc_ui_move_or_copy_endp(ch); + else + pcb_arc_ui_move_or_copy_angle(ch); +} + + +int pcb_obj_ui_arc_point_bbox(int Type, void *Ptr1, void *Ptr2, void *Ptr3, pcb_box_t *res) +{ + pcb_arc_t *arc = Ptr2; + int *end_pt = Ptr3; + pcb_coord_t ex, ey; + pcb_arc_get_end(arc, (end_pt != pcb_arc_start_ptr), &ex, &ey); + *res = pcb_point_box(ex, ey); + return 0; +} + Index: tags/2.1.2/src/obj_arc_ui.h =================================================================== --- tags/2.1.2/src/obj_arc_ui.h (nonexistent) +++ tags/2.1.2/src/obj_arc_ui.h (revision 24813) @@ -0,0 +1,33 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2016 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ +/* Arc UI logics */ + +#include "crosshair.h" + +void pcb_arc_ui_move_or_copy(pcb_crosshair_t *ch); +int pcb_obj_ui_arc_point_bbox(int Type, void *Ptr1, void *Ptr2, void *Ptr3, pcb_box_t *res); +void pcb_arc_middle(const pcb_arc_t *arc, pcb_coord_t *x, pcb_coord_t *y); + Index: tags/2.1.2/src/obj_common.c =================================================================== --- tags/2.1.2/src/obj_common.c (nonexistent) +++ tags/2.1.2/src/obj_common.c (revision 24813) @@ -0,0 +1,350 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996, 2005 Thomas Nau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ +#include "config.h" + +#include +#include +#include "conf_core.h" +#include "flag_str.h" +#include "global_typedefs.h" +#include "error.h" +#include "obj_common.h" +#include "obj_arc_ui.h" +#include "obj_pstk.h" + +const char *pcb_obj_type_name(pcb_objtype_t type) +{ + switch(type) { + case PCB_OBJ_VOID: return "void"; + case PCB_OBJ_LINE: return "line"; + case PCB_OBJ_TEXT: return "text"; + case PCB_OBJ_POLY: return "polygon"; + case PCB_OBJ_ARC: return "arc"; + case PCB_OBJ_RAT: return "ratline"; + case PCB_OBJ_PSTK: return "padstack"; + case PCB_OBJ_SUBC: return "subcircuit"; + case PCB_OBJ_NET: return "net"; + case PCB_OBJ_NET_TERM: return "net_term"; + case PCB_OBJ_LAYER: return "layer"; + case PCB_OBJ_LAYERGRP: return "layer_group"; + } + switch((pcb_vobjtype_t)type) { + case PCB_OBJ_LINE_POINT: return "line_point"; + case PCB_OBJ_POLY_POINT: return "poly_point"; + case PCB_OBJ_ARC_POINT: return "arc_point"; + case PCB_OBJ_SUBC_PART: return "subc_part"; + case PCB_OBJ_LOCKED: return "locked"; + case PCB_OBJ_FLOATER: return "floater"; + } + return ""; +} + +/* returns a pointer to an objects bounding box; + * data is valid until the routine is called again + */ +int pcb_obj_get_bbox_naked(int Type, void *Ptr1, void *Ptr2, void *Ptr3, pcb_box_t *res) +{ + switch (Type) { + case PCB_OBJ_LINE: + case PCB_OBJ_ARC: + case PCB_OBJ_TEXT: + case PCB_OBJ_POLY: + case PCB_OBJ_PSTK: + *res = ((pcb_any_obj_t *)Ptr2)->bbox_naked; + return 0; + case PCB_OBJ_SUBC: + *res = ((pcb_any_obj_t *)Ptr1)->bbox_naked; + return 0; + case PCB_OBJ_POLY_POINT: + case PCB_OBJ_LINE_POINT: + *res = *(pcb_box_t *)Ptr3; + return 0; + case PCB_OBJ_ARC_POINT: + return pcb_obj_ui_arc_point_bbox(Type, Ptr1, Ptr2, Ptr3, res); + default: + pcb_message(PCB_MSG_ERROR, "Request for bounding box of unsupported type %d\n", Type); + *res = *(pcb_box_t *)Ptr2; + return -1; + } +} + + + +/* current object ID; incremented after each creation of an object */ +long int ID = 1; + +pcb_bool pcb_create_being_lenient = pcb_false; + +void pcb_create_be_lenient(pcb_bool v) +{ + pcb_create_being_lenient = v; +} + +void pcb_create_ID_bump(int min_id) +{ + if (ID < min_id) + ID = min_id; +} + +void pcb_create_ID_reset(void) +{ + ID = 1; +} + +long int pcb_create_ID_get(void) +{ + return ID++; +} + +void pcb_obj_add_attribs(void *obj, const pcb_attribute_list_t *src) +{ + pcb_any_obj_t *o = obj; + if (src == NULL) + return; + pcb_attribute_copy_all(&o->Attributes, src); +} + +void pcb_obj_center(const pcb_any_obj_t *obj, pcb_coord_t *x, pcb_coord_t *y) +{ + switch (obj->type) { + case PCB_OBJ_PSTK: + *x = ((const pcb_pstk_t *)(obj))->x; + *y = ((const pcb_pstk_t *)(obj))->y; + break; + case PCB_OBJ_ARC: + pcb_arc_middle((const pcb_arc_t *)obj, x, y); + break; + default: + *x = (obj->BoundingBox.X1 + obj->BoundingBox.X2) / 2; + *y = (obj->BoundingBox.Y1 + obj->BoundingBox.Y2) / 2; + } +} + +void pcb_obj_attrib_post_change(pcb_attribute_list_t *list, const char *name, const char *value) +{ + pcb_any_obj_t *obj = (pcb_any_obj_t *)(((char *)list) - offsetof(pcb_any_obj_t, Attributes)); + if (strcmp(name, "term") == 0) { + const char *inv; + obj->term = value; + inv = pcb_obj_id_invalid(obj->term); + if (inv != NULL) + pcb_message(PCB_MSG_ERROR, "Invalid character '%c' in terminal name (term attribute) '%s'\n", *inv, obj->term); + } + else if (strcmp(name, "intconn") == 0) { + long cid = 0; + if (value != NULL) { + char *end; + cid = strtol(value, &end, 10); + if (*end != '\0') + cid = 0; + } + obj->intconn = cid; + } + else if (strcmp(name, "intnoconn") == 0) { + long cid = 0; + if (value != NULL) { + char *end; + cid = strtol(value, &end, 10); + if (*end != '\0') + cid = 0; + } + obj->intnoconn = cid; + } +} + +const char *pcb_obj_id_invalid(const char *id) +{ + const char *s; + if (id != NULL) + for(s = id; *s != '\0'; s++) { + if (isalnum(*s)) + continue; + switch(*s) { + case '_': case '.': case '$': case '*': case ':': continue; + } + return s; + } + return NULL; +} + +char *pcb_obj_id_fix(char *id) +{ + char *s; + if (id == NULL) + return NULL; + + for(s = id; *s != '\0'; s++) { + if (isalnum(*s)) + continue; + switch(*s) { + case '_': case '.': case '$': case '*': case ':': continue; + default: *s = '_'; + } + } + + return id; +} + + +pcb_flag_values_t pcb_obj_valid_flags(unsigned long int objtype) +{ + pcb_flag_values_t res = 0; + int n; + + for(n = 0; n < pcb_object_flagbits_len; n++) + if (pcb_object_flagbits[n].object_types & objtype) + res |= pcb_object_flagbits[n].mask; + + return res; +} + +pcb_coord_t pcb_obj_clearance_at(pcb_board_t *pcb, const pcb_any_obj_t *o, pcb_layer_t *at) +{ + switch(o->type) { + case PCB_OBJ_POLY: + if (!(PCB_POLY_HAS_CLEARANCE((pcb_poly_t *)o))) + return 0; + return ((pcb_poly_t *)o)->Clearance; + case PCB_OBJ_LINE: + if (!(PCB_NONPOLY_HAS_CLEARANCE((pcb_line_t *)o))) + return 0; + return ((pcb_line_t *)o)->Clearance; + case PCB_OBJ_TEXT: + return 0; + case PCB_OBJ_ARC: + if (!(PCB_NONPOLY_HAS_CLEARANCE((pcb_arc_t *)o))) + return 0; + return ((pcb_arc_t *)o)->Clearance; + case PCB_OBJ_PSTK: + return obj_pstk_get_clearance(pcb, (pcb_pstk_t *)o, at); + default: + return 0; + } +} + +static void mmult(pcb_xform_mx_t dst, const pcb_xform_mx_t src) +{ + pcb_xform_mx_t tmp; + + tmp[0] = dst[0] * src[0] + dst[1] * src[3] + dst[2] * src[6]; + tmp[1] = dst[0] * src[1] + dst[1] * src[4] + dst[2] * src[7]; + tmp[2] = dst[0] * src[2] + dst[1] * src[5] + dst[2] * src[8]; + + tmp[3] = dst[3] * src[0] + dst[4] * src[3] + dst[5] * src[6]; + tmp[4] = dst[3] * src[1] + dst[4] * src[4] + dst[5] * src[7]; + tmp[5] = dst[3] * src[2] + dst[4] * src[5] + dst[5] * src[8]; + + tmp[6] = dst[6] * src[0] + dst[7] * src[3] + dst[8] * src[6]; + tmp[7] = dst[6] * src[1] + dst[7] * src[4] + dst[8] * src[7]; + tmp[8] = dst[6] * src[2] + dst[7] * src[5] + dst[8] * src[8]; + + memcpy(dst, tmp, sizeof(tmp)); +} + +void pcb_xform_mx_rotate(pcb_xform_mx_t mx, double deg) +{ + pcb_xform_mx_t tr; + + deg /= PCB_RAD_TO_DEG; + + tr[0] = cos(deg); + tr[1] = sin(deg); + tr[2] = 0; + + tr[3] = -sin(deg); + tr[4] = cos(deg); + tr[5] = 0; + + tr[6] = 0; + tr[7] = 0; + tr[8] = 1; + + mmult(mx, tr); +} + +void pcb_xform_mx_translate(pcb_xform_mx_t mx, double xt, double yt) +{ + pcb_xform_mx_t tr; + + tr[0] = 1; + tr[1] = 0; + tr[2] = xt; + + tr[3] = 0; + tr[4] = 1; + tr[5] = yt; + + tr[6] = 0; + tr[7] = 0; + tr[8] = 1; + + mmult(mx, tr); +} + +void pcb_xform_mx_scale(pcb_xform_mx_t mx, double sx, double sy) +{ + pcb_xform_mx_t tr; + + tr[0] = sx; + tr[1] = 0; + tr[2] = 0; + + tr[3] = 0; + tr[4] = sy; + tr[5] = 0; + + tr[6] = 0; + tr[7] = 0; + tr[8] = 1; + + mmult(mx, tr); +} + +void pcb_xform_mx_shear(pcb_xform_mx_t mx, double sx, double sy) +{ + pcb_xform_mx_t tr; + + tr[0] = 1; + tr[1] = sx; + tr[2] = 0; + + tr[3] = sy; + tr[4] = 1; + tr[5] = 0; + + tr[6] = 0; + tr[7] = 0; + tr[8] = 1; + + mmult(mx, tr); +} + +void pcb_xform_mx_mirrorx(pcb_xform_mx_t mx) +{ + pcb_xform_mx_scale(mx, 0, -1); +} Index: tags/2.1.2/src/obj_common.h =================================================================== --- tags/2.1.2/src/obj_common.h (nonexistent) +++ tags/2.1.2/src/obj_common.h (revision 24813) @@ -0,0 +1,321 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +#ifndef PCB_OBJ_COMMON_H +#define PCB_OBJ_COMMON_H + +#include +#include +#include "flag.h" +#include "attrib.h" +#include "global_typedefs.h" +#include "data_parent.h" + +/* Real objects that have actual struct; can be used as a bitfield */ +typedef enum pcb_objtype_e { + PCB_OBJ_VOID = 0x0000000, + + PCB_OBJ_ARC = 0x0000001, + PCB_OBJ_LINE = 0x0000002, + PCB_OBJ_POLY = 0x0000004, + PCB_OBJ_TEXT = 0x0000008, + PCB_OBJ_SUBC = 0x0000010, + PCB_OBJ_PSTK = 0x0000020, + PCB_OBJ_RAT = 0x0000040, + + + /* more abstract objects */ + PCB_OBJ_NET = 0x0001000, + PCB_OBJ_NET_TERM = 0x0002000, + PCB_OBJ_LAYER = 0x0004000, + PCB_OBJ_LAYERGRP = 0x0008000 +} pcb_objtype_t; + +/* Virtual objects for configuring searches; can be used as a bitfield with the above */ +typedef enum pcb_vobjtype_e { + PCB_OBJ_ARC_POINT = 0x0100000, + PCB_OBJ_LINE_POINT = 0x0200000, + PCB_OBJ_POLY_POINT = 0x0400000, + PCB_OBJ_SUBC_PART = 0x0800000, + PCB_OBJ_LOCKED = 0x1000000, + PCB_OBJ_FLOATER = 0x2000000 +} pcb_vobjtype_t; + + +/* combinations, groups, masks of pcb_objtype_t */ +typedef enum pcb_objmask_e { + /* lists */ + PCB_OBJ_CLASS_PIN = (PCB_OBJ_PSTK | PCB_OBJ_SUBC_PART), + PCB_OBJ_CLASS_TERM = (PCB_OBJ_CLASS_PIN | PCB_OBJ_SUBC_PART | PCB_OBJ_LINE | PCB_OBJ_ARC | PCB_OBJ_POLY | PCB_OBJ_TEXT), + + /* masks */ + PCB_OBJ_CLASS_REAL = 0x0000FFF, /* global and on-layer objects (but not abstract things like layers) */ + PCB_OBJ_CLASS_HOST = 0x00FF000, /* host types: layers, boards, nets */ + PCB_OBJ_CLASS_MASK = 0xFF00000, /* for virtual searches */ + PCB_OBJ_CLASS_OBJ = 0x0000000, /* anything with common object fields (pcb_any_obj_t) */ + PCB_OBJ_ANY = 0xFFFFFFF +} pcb_objmask_t; + + +/* point and box type - they are so common everything depends on them */ +struct pcb_point_s { /* a line/polygon point */ + pcb_coord_t X, Y, X2, Y2; /* so Point type can be cast as pcb_box_t */ + long int ID; +}; + +struct pcb_box_s { /* a bounding box */ + pcb_coord_t X1, Y1; /* upper left */ + pcb_coord_t X2, Y2; /* and lower right corner */ +}; + +typedef double pcb_xform_mx_t[9]; +#define PCB_XFORM_MX_IDENT {1,0,0, 0,1,0, 0,0,1} + +typedef struct pcb_xform_s { /* generic object transformation */ + pcb_coord_t bloat; /* if non-zero, bloat (positive) or shrink (negative) by this value */ + + unsigned layer_faded:1; /* draw layer colors faded */ + + /* WARNING: After adding new fields, make sure to update pcb_xform_add() and pcb_xform_is_nop() below */ +} pcb_xform_t; + +#define pcb_xform_clear(dst) memset(dst, 0, sizeof(pcb_xform_t)) +#define pcb_xform_copy(dst, src) memcpy(dst, src, sizeof(pcb_xform_t)) +#define pcb_xform_add(dst, src) \ + do { \ + pcb_xform_t *__dst__ = dst; \ + const pcb_xform_t *__src__ = src; \ + __dst__->bloat += __src__->bloat; \ + __dst__->layer_faded |= __src__->layer_faded; \ + } while(0) +#define pcb_xform_is_nop(src) (((src)->bloat == 0) && ((src)->layer_faded == 0)) + +/* Standard 2d matrix transformation using mx as pcb_xform_mx_t */ +#define pcb_xform_x(mx, x_in, y_in) ((double)(x_in) * mx[0] + (double)(y_in) * mx[1] + mx[2]) +#define pcb_xform_y(mx, x_in, y_in) ((double)(x_in) * mx[3] + (double)(y_in) * mx[4] + mx[5]) + +void pcb_xform_mx_rotate(pcb_xform_mx_t mx, double deg); +void pcb_xform_mx_translate(pcb_xform_mx_t mx, double xt, double yt); +void pcb_xform_mx_scale(pcb_xform_mx_t mx, double st, double sy); +void pcb_xform_mx_shear(pcb_xform_mx_t mx, double sx, double sy); +void pcb_xform_mx_mirrorx(pcb_xform_mx_t mx); /* mirror over the x axis (flip y coords) */ + +/* Return the user readable name of an object type in a string; never NULL */ +const char *pcb_obj_type_name(pcb_objtype_t type); + +/* returns a flag mask of all valid flags for an (old) object type */ +pcb_flag_values_t pcb_obj_valid_flags(unsigned long int objtype); + + +int pcb_obj_get_bbox_naked(int Type, void *Ptr1, void *Ptr2, void *Ptr3, pcb_box_t *res); + +/* Host transformations: typically the transformations an object of a subc + inherits from the subc */ +typedef struct pcb_host_trans_s { + pcb_coord_t ox, oy; + int on_bottom; + double rot; + double cosa, sina; /* rot angle cache */ +} pcb_host_trans_t; + +/* memset object to 0, but keep the link field */ +#define reset_obj_mem(type, obj) \ +do { \ + gdl_elem_t __lnk__ = obj->link; \ + memset(obj, 0, sizeof(type)); \ + obj->link = __lnk__; \ +} while(0) \ + + +/* pcb_true during file loads, for example to allow overlapping vias. + pcb_false otherwise, to stop the user from doing normally dangerous + things. */ +void pcb_create_be_lenient(pcb_bool); +extern pcb_bool pcb_create_being_lenient; + +void pcb_create_ID_bump(int min_id); +void pcb_create_ID_reset(void); +long int pcb_create_ID_get(void); + +void pcb_obj_add_attribs(void *obj, const pcb_attribute_list_t *src); + +/* --------------------------------------------------------------------------- + * Do not change the following definitions even if they're not very + * nice. It allows us to have functions act on these "base types" and + * not need to know what kind of actual object they're working on. + */ + +/* Any object that ends up in common use as pcb_any_obj_t, MUST be defined + using this as the first fieldsusing the following macros. */ +#define PCB_ANY_OBJ_FIELDS \ + pcb_box_t BoundingBox; \ + long int ID; \ + pcb_flag_t Flags; \ + pcb_objtype_t type; \ + pcb_parenttype_t parent_type; \ + pcb_parent_t parent; \ + pcb_box_t bbox_naked; \ + pcb_attribute_list_t Attributes \ + +#define PCB_ANY_PRIMITIVE_FIELDS \ + PCB_ANY_OBJ_FIELDS; \ + const char *term; \ + void *ratconn; \ + unsigned char thermal; \ + unsigned char intconn, intnoconn; \ + const pcb_color_t *override_color + +/* Lines, pads, and rats all use this so they can be cross-cast. */ +#define PCB_ANYLINEFIELDS \ + PCB_ANY_PRIMITIVE_FIELDS; \ + pcb_coord_t Thickness, Clearance; \ + pcb_point_t Point1, Point2 + +/* All on-pcb objects (elements, lines, pads, vias, rats, etc) are + based on this. */ +struct pcb_any_obj_s { + PCB_ANY_PRIMITIVE_FIELDS; +}; + +/* Lines, rats, pads, etc. */ +struct pcb_any_line_s { + PCB_ANYLINEFIELDS; +}; + +/* Return the geometric center of an object, as shown (center of bbox usually, + but not for an arc) */ +void pcb_obj_center(const pcb_any_obj_t *obj, pcb_coord_t *x, pcb_coord_t *y); + +/* Return the clearance value of object on the specified layer (in + case of padstack - in case of other objects layer is ignored) */ +pcb_coord_t pcb_obj_clearance_at(pcb_board_t *pcb, const pcb_any_obj_t *o, pcb_layer_t *at); + + +/* Update cached attributes (->term) */ +void pcb_obj_attrib_post_change(pcb_attribute_list_t *list, const char *name, const char *value); + +/* Returns the first invalid character of an ID (terminal, refdes) or NULL */ +const char *pcb_obj_id_invalid(const char *id); + +/* Fix an ID in place (replace anything invalid with '_'); returns id */ +char *pcb_obj_id_fix(char *id); + +#define pcb_obj_id_reg(data, obj) \ + do { \ + pcb_any_obj_t *__obj__ = (pcb_any_obj_t *)(obj); \ + htip_set(&(data)->id2obj, __obj__->ID, __obj__); \ + } while(0) + +#define pcb_obj_id_del(data, obj) \ + htip_pop(&(data)->id2obj, (obj)->ID) + +#define pcb_hidden_floater(obj) (conf_core.editor.hide_names && PCB_FLAG_TEST(PCB_FLAG_FLOATER, (obj))) + +/* Returns whether a subc part object is editable (not under the subc lock) */ +#define pcb_subc_part_editable(pcb, obj) \ + (((pcb)->loose_subc) || ((obj)->term != NULL) || PCB_FLAG_TEST(PCB_FLAG_FLOATER, (obj))) + +/* set const char *dst to a color, depending on the bound layer type: + top silk and copper get the color of the first crresponding layer + from current PCB, the rest get the far-side color; + set the selected color if sel is true */ +#define PCB_OBJ_COLOR_ON_BOUND_LAYER(dst, layer, sel) \ +do { \ + if (layer->meta.bound.type & PCB_LYT_TOP) { \ + pcb_layer_id_t lid = -1; \ + pcb_layergrp_t *g; \ + pcb_layergrp_id_t grp = -1; \ + if (layer->meta.bound.type & PCB_LYT_SILK) { \ + if (sel) {\ + dst = &conf_core.appearance.color.selected; \ + } \ + else {\ + if (layer != NULL) { \ + pcb_layer_t *ly = pcb_layer_get_real(layer); \ + if (ly != NULL) \ + dst = &ly->meta.real.color; \ + else \ + dst = &conf_core.appearance.color.element; \ + } \ + else \ + dst = &conf_core.appearance.color.element; \ + } \ + break; \ + } \ + else if (layer->meta.bound.type & PCB_LYT_COPPER) \ + grp = pcb_layergrp_get_top_copper(); \ + g = pcb_get_layergrp(PCB, grp); \ + if ((g != NULL) && (g->len > 0)) \ + lid = g->lid[0]; \ + if ((lid >= 0) && (lid <= PCB_MAX_LAYER)) { \ + if (sel) \ + dst = &conf_core.appearance.color.selected; \ + else {\ + if (layer != NULL) { \ + pcb_layer_t *ly = pcb_layer_get_real(layer); \ + if (ly != NULL) \ + dst = &ly->meta.real.color; \ + else \ + dst = &conf_core.appearance.color.layer[lid]; \ + } \ + else \ + dst = &conf_core.appearance.color.layer[lid]; \ + } \ + break; \ + } \ + } \ + if (sel) \ + dst = &conf_core.appearance.color.selected; \ + else \ + dst = &conf_core.appearance.color.invisible_objects; \ +} while(0) + +/* check if an object has clearance to polygon */ +#define PCB_POLY_HAS_CLEARANCE(ply) \ + (PCB_FLAG_TEST(PCB_FLAG_CLEARPOLYPOLY, (ply)) && ((ply)->Clearance != 0)) + +#define PCB_NONPOLY_HAS_CLEARANCE(obj) \ + (PCB_FLAG_TEST(PCB_FLAG_CLEARLINE, (obj)) && ((obj)->Clearance != 0)) + +#define PCB_OBJ_HAS_CLEARANCE(obj) \ + ( \ + ((obj)->type == PCB_OBJ_POLY) ? \ + PCB_POLY_HAS_CLEARANCE(obj) : PCB_NONPOLY_HAS_CLEARANCE(obj) \ + ) + +#define PCB_HAS_COLOROVERRIDE(obj) ((obj)->override_color != NULL) + +/* a pointer is created from index addressing because the base pointer + * may change when new memory is allocated; + * + * all data is relative to an objects name 'top' which can be either + * PCB or PasteBuffer */ +#define PCB_END_LOOP }} while (0) +#define PCB_ENDALL_LOOP }} while (0); }} while(0) + +#endif Index: tags/2.1.2/src/obj_hash.h =================================================================== --- tags/2.1.2/src/obj_hash.h (nonexistent) +++ tags/2.1.2/src/obj_hash.h (revision 24813) @@ -0,0 +1,97 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2017, 2018 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include +#include +#include "compat_misc.h" + +/* compare two strings and return 0 if they are equal. NULL == NULL means equal. */ +PCB_INLINE int pcb_neqs(const char *s1, const char *s2) +{ + if ((s1 == NULL) && (s2 == NULL)) return 0; + if ((s1 == NULL) || (s2 == NULL)) return 1; + return strcmp(s1, s2) != 0; +} + +PCB_INLINE unsigned pcb_hash_coord(pcb_coord_t c) +{ + return murmurhash(&(c), sizeof(pcb_coord_t)); +} + +/* cheat: round with a tolerance of a few nanometers to overcome the usual + +-1 nanometer rounding error */ +PCB_INLINE pcb_coord_t pcb_round_tol(double v, int tol) +{ + return pcb_round(v/(double)tol)*tol; +} + +PCB_INLINE void pcb_hash_tr_coords(const pcb_host_trans_t *tr, pcb_coord_t *dstx, pcb_coord_t *dsty, pcb_coord_t srcx, pcb_coord_t srcy) +{ + pcb_coord_t px, py; + + px = srcx + tr->ox; + py = srcy + tr->oy; + + if ((tr->rot == 0.0) && (!tr->on_bottom)) { + *dstx = px; + *dsty = py; + } + else { + double x, y; + x = (double)px * tr->cosa + (double)py * tr->sina; + y = (double)py * tr->cosa - (double)px * tr->sina; + if (tr->on_bottom) y = -(y); + + *dstx = pcb_round_tol(x, 4); + *dsty = pcb_round_tol(y, 4); + } +} + + +PCB_INLINE unsigned pcb_hash_angle(const pcb_host_trans_t *tr, pcb_angle_t ang) +{ + long l; + ang = fmod(ang + tr->rot, 360.0); + ang *= 10000; + l = floor(ang); + return murmurhash(&l, sizeof(l)); +} + +#define pcb_hash_str(s) ((s) == NULL ? 0 : strhash(s)) + +/* compare two fields and return 0 if they are equal */ +#define pcb_field_neq(s1, s2, f) ((s1)->f != (s2)->f) + +/* retruns if two sets of tr;x;y mismatches */ +PCB_INLINE pcb_bool pcb_neq_tr_coords(const pcb_host_trans_t *tr1, pcb_coord_t x1, pcb_coord_t y1, const pcb_host_trans_t *tr2, pcb_coord_t x2, pcb_coord_t y2) +{ + pcb_hash_tr_coords(tr1, &x1, &y1, x1, y1); + pcb_hash_tr_coords(tr2, &x2, &y2, x2, y2); + if (x1 != x2) return pcb_true; + if (y1 != y2) return pcb_true; + return pcb_false; +} + Index: tags/2.1.2/src/obj_line.c =================================================================== --- tags/2.1.2/src/obj_line.c (nonexistent) +++ tags/2.1.2/src/obj_line.c (revision 24813) @@ -0,0 +1,1196 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +/* Drawing primitive: line segment */ + +#include "config.h" +#include + +#include "undo.h" +#include "board.h" +#include "data.h" +#include "move.h" +#include "search.h" +#include "polygon.h" +#include "conf_core.h" +#include "compat_misc.h" +#include "rotate.h" +#include "hid_inlines.h" + +#include "obj_line.h" +#include "obj_line_op.h" + +#include "obj_subc_parent.h" +#include "obj_hash.h" + +/* TODO: maybe remove this and move lines from draw here? */ +#include "draw.h" +#include "draw_wireframe.h" +#include "obj_line_draw.h" +#include "obj_rat_draw.h" +#include "obj_pstk_draw.h" + +TODO("padstack: remove this when via is removed and the padstack is created from style directly") +#include "src_plugins/lib_compat_help/pstk_compat.h" + + +/**** allocation ****/ + +void pcb_line_reg(pcb_layer_t *layer, pcb_line_t *line) +{ + linelist_append(&layer->Line, line); + PCB_SET_PARENT(line, layer, layer); + + if (layer->parent_type == PCB_PARENT_UI) + return; + + assert(layer->parent_type == PCB_PARENT_DATA); + pcb_obj_id_reg(layer->parent.data, line); +} + +void pcb_line_unreg(pcb_line_t *line) +{ + pcb_layer_t *layer = line->parent.layer; + assert(line->parent_type == PCB_PARENT_LAYER); + linelist_remove(line); + if (layer->parent_type != PCB_PARENT_UI) { + assert(layer->parent_type == PCB_PARENT_DATA); + pcb_obj_id_del(layer->parent.data, line); + } + PCB_CLEAR_PARENT(line); +} + +pcb_line_t *pcb_line_alloc_id(pcb_layer_t *layer, long int id) +{ + pcb_line_t *new_obj; + + new_obj = calloc(sizeof(pcb_line_t), 1); + new_obj->ID = id; + new_obj->type = PCB_OBJ_LINE; + new_obj->Attributes.post_change = pcb_obj_attrib_post_change; + + pcb_line_reg(layer, new_obj); + + return new_obj; +} + +pcb_line_t *pcb_line_alloc(pcb_layer_t *layer) +{ + return pcb_line_alloc_id(layer, pcb_create_ID_get()); +} + +void pcb_line_free(pcb_line_t *line) +{ + pcb_line_unreg(line); + free(line); +} + + +/**** utility ****/ +struct line_info { + pcb_coord_t X1, X2, Y1, Y2; + pcb_coord_t Thickness, Clearance; + pcb_flag_t Flags; + pcb_line_t test, *ans; + jmp_buf env; +}; + +static pcb_r_dir_t line_callback(const pcb_box_t * b, void *cl) +{ + pcb_line_t *line = (pcb_line_t *) b; + struct line_info *i = (struct line_info *) cl; + + /* do not merge to subc parts or terminals */ + if ((pcb_obj_parent_subc((pcb_any_obj_t *)line) != NULL) || (line->term != NULL)) + return PCB_R_DIR_NOT_FOUND; + + if (line->Point1.X == i->X1 && line->Point2.X == i->X2 && line->Point1.Y == i->Y1 && line->Point2.Y == i->Y2) { + i->ans = (pcb_line_t *) (-1); + longjmp(i->env, 1); + } + /* check the other point order */ + if (line->Point1.X == i->X1 && line->Point2.X == i->X2 && line->Point1.Y == i->Y1 && line->Point2.Y == i->Y2) { + i->ans = (pcb_line_t *) (-1); + longjmp(i->env, 1); + } + if (line->Point2.X == i->X1 && line->Point1.X == i->X2 && line->Point2.Y == i->Y1 && line->Point1.Y == i->Y2) { + i->ans = (pcb_line_t *) - 1; + longjmp(i->env, 1); + } + /* remove unnecessary line points */ + if (line->Thickness == i->Thickness + /* don't merge lines if the clear flags or clearance differ */ + && PCB_FLAG_TEST(PCB_FLAG_CLEARLINE, line) == PCB_FLAG_TEST(PCB_FLAG_CLEARLINE, i) + && line->Clearance == i->Clearance) { + if (line->Point1.X == i->X1 && line->Point1.Y == i->Y1) { + i->test.Point1.X = line->Point2.X; + i->test.Point1.Y = line->Point2.Y; + i->test.Point2.X = i->X2; + i->test.Point2.Y = i->Y2; + if (pcb_is_point_on_line(i->X1, i->Y1, 1, &i->test)) { + i->ans = line; + longjmp(i->env, 1); + } + } + else if (line->Point2.X == i->X1 && line->Point2.Y == i->Y1) { + i->test.Point1.X = line->Point1.X; + i->test.Point1.Y = line->Point1.Y; + i->test.Point2.X = i->X2; + i->test.Point2.Y = i->Y2; + if (pcb_is_point_on_line(i->X1, i->Y1, 1, &i->test)) { + i->ans = line; + longjmp(i->env, 1); + } + } + else if (line->Point1.X == i->X2 && line->Point1.Y == i->Y2) { + i->test.Point1.X = line->Point2.X; + i->test.Point1.Y = line->Point2.Y; + i->test.Point2.X = i->X1; + i->test.Point2.Y = i->Y1; + if (pcb_is_point_on_line(i->X2, i->Y2, 1, &i->test)) { + i->ans = line; + longjmp(i->env, 1); + } + } + else if (line->Point2.X == i->X2 && line->Point2.Y == i->Y2) { + i->test.Point1.X = line->Point1.X; + i->test.Point1.Y = line->Point1.Y; + i->test.Point2.X = i->X1; + i->test.Point2.Y = i->Y1; + if (pcb_is_point_on_line(i->X2, i->Y2, 1, &i->test)) { + i->ans = line; + longjmp(i->env, 1); + } + } + } + return PCB_R_DIR_NOT_FOUND; +} + + +/* creates a new line on a layer and checks for overlap and extension */ +pcb_line_t *pcb_line_new_merge(pcb_layer_t *Layer, pcb_coord_t X1, pcb_coord_t Y1, pcb_coord_t X2, pcb_coord_t Y2, pcb_coord_t Thickness, pcb_coord_t Clearance, pcb_flag_t Flags) +{ + struct line_info info; + pcb_box_t search; + + search.X1 = MIN(X1, X2); + search.X2 = MAX(X1, X2); + search.Y1 = MIN(Y1, Y2); + search.Y2 = MAX(Y1, Y2); + if (search.Y2 == search.Y1) + search.Y2++; + if (search.X2 == search.X1) + search.X2++; + info.X1 = X1; + info.X2 = X2; + info.Y1 = Y1; + info.Y2 = Y2; + info.Thickness = Thickness; + info.Clearance = Clearance; + info.Flags = Flags; + info.test.Thickness = 0; + info.test.Flags = pcb_no_flags(); + info.ans = NULL; + /* prevent stacking of duplicate lines + * and remove needless intermediate points + * verify that the layer is on the board first! + */ + if (setjmp(info.env) == 0) { + pcb_r_search(Layer->line_tree, &search, NULL, line_callback, &info, NULL); + return pcb_line_new(Layer, X1, Y1, X2, Y2, Thickness, Clearance, Flags); + } + + if ((void *) info.ans == (void *) (-1)) + return NULL; /* stacked line */ + /* remove unnecessary points */ + if (info.ans) { + /* must do this BEFORE getting new line memory */ + pcb_undo_move_obj_to_remove(PCB_OBJ_LINE, Layer, info.ans, info.ans); + X1 = info.test.Point1.X; + X2 = info.test.Point2.X; + Y1 = info.test.Point1.Y; + Y2 = info.test.Point2.Y; + } + return pcb_line_new(Layer, X1, Y1, X2, Y2, Thickness, Clearance, Flags); +} + +pcb_line_t *pcb_line_new(pcb_layer_t *Layer, pcb_coord_t X1, pcb_coord_t Y1, pcb_coord_t X2, pcb_coord_t Y2, pcb_coord_t Thickness, pcb_coord_t Clearance, pcb_flag_t Flags) +{ + pcb_line_t *Line; + + Line = pcb_line_alloc(Layer); + if (!Line) + return Line; + Line->Flags = Flags; + PCB_FLAG_CLEAR(PCB_FLAG_RAT, Line); + Line->Thickness = Thickness; + Line->Clearance = Clearance; + Line->Point1.X = X1; + Line->Point1.Y = Y1; +TODO("ID: register points too") + Line->Point1.ID = pcb_create_ID_get(); + Line->Point2.X = X2; + Line->Point2.Y = Y2; + Line->Point2.ID = pcb_create_ID_get(); + pcb_add_line_on_layer(Layer, Line); + return Line; +} + +static pcb_line_t *pcb_line_copy_meta(pcb_line_t *dst, pcb_line_t *src) +{ + if (dst == NULL) + return NULL; + pcb_attribute_copy_all(&dst->Attributes, &src->Attributes); + return dst; +} + +pcb_line_t *pcb_line_dup(pcb_layer_t *dst, pcb_line_t *src) +{ + pcb_line_t *l = pcb_line_new(dst, src->Point1.X, src->Point1.Y, src->Point2.X, src->Point2.Y, src->Thickness, src->Clearance, src->Flags); + return pcb_line_copy_meta(l, src); +} + +pcb_line_t *pcb_line_dup_at(pcb_layer_t *dst, pcb_line_t *src, pcb_coord_t dx, pcb_coord_t dy) +{ + pcb_line_t *l = pcb_line_new(dst, src->Point1.X + dx, src->Point1.Y + dy, src->Point2.X + dx, src->Point2.Y + dy, src->Thickness, src->Clearance, src->Flags); + return pcb_line_copy_meta(l, src); +} + +void pcb_add_line_on_layer(pcb_layer_t *Layer, pcb_line_t *Line) +{ + pcb_line_bbox(Line); + if (!Layer->line_tree) + Layer->line_tree = pcb_r_create_tree(); + pcb_r_insert_entry(Layer->line_tree, (pcb_box_t *) Line); +} + +static void pcb_line_bbox_(const pcb_line_t *Line, pcb_box_t *dst, int mini) +{ + pcb_coord_t width = mini ? (Line->Thickness + 1) / 2 : (Line->Thickness + Line->Clearance + 1) / 2; + + /* Adjust for our discrete polygon approximation */ + width = (double) width *PCB_POLY_CIRC_RADIUS_ADJ + 0.5; + + dst->X1 = MIN(Line->Point1.X, Line->Point2.X) - width; + dst->X2 = MAX(Line->Point1.X, Line->Point2.X) + width; + dst->Y1 = MIN(Line->Point1.Y, Line->Point2.Y) - width; + dst->Y2 = MAX(Line->Point1.Y, Line->Point2.Y) + width; + pcb_close_box(dst); +} + +/* sets the bounding box of a line */ +void pcb_line_bbox(pcb_line_t *Line) +{ + pcb_line_bbox_(Line, &Line->BoundingBox, 0); + pcb_line_bbox_(Line, &Line->bbox_naked, 1); + pcb_set_point_bounding_box(&Line->Point1); + pcb_set_point_bounding_box(&Line->Point2); +} + +int pcb_line_eq(const pcb_host_trans_t *tr1, const pcb_line_t *l1, const pcb_host_trans_t *tr2, const pcb_line_t *l2) +{ + if (pcb_field_neq(l1, l2, Thickness) || pcb_field_neq(l1, l2, Clearance)) return 0; + if (pcb_neqs(l1->term, l2->term)) return 0; + if (!PCB_FLAG_TEST(PCB_FLAG_FLOATER, l1) && !PCB_FLAG_TEST(PCB_FLAG_FLOATER, l2)) { + if (pcb_neq_tr_coords(tr1, l1->Point1.X, l1->Point1.Y, tr2, l2->Point1.X, l2->Point1.Y)) goto swap; + if (pcb_neq_tr_coords(tr1, l1->Point2.X, l1->Point2.Y, tr2, l2->Point2.X, l2->Point2.Y)) return 0; + } + return 1; + + swap:; /* check the line with swapped endpoints */ + if (pcb_neq_tr_coords(tr1, l1->Point2.X, l1->Point2.Y, tr2, l2->Point1.X, l2->Point1.Y)) return 0; + if (pcb_neq_tr_coords(tr1, l1->Point1.X, l1->Point1.Y, tr2, l2->Point2.X, l2->Point2.Y)) return 0; + return 1; +} + + +unsigned int pcb_line_hash(const pcb_host_trans_t *tr, const pcb_line_t *l) +{ + unsigned int crd = 0; + + if (!PCB_FLAG_TEST(PCB_FLAG_FLOATER, l)) { + pcb_coord_t x1, y1, x2, y2; + pcb_hash_tr_coords(tr, &x1, &y1, l->Point1.X, l->Point1.Y); + pcb_hash_tr_coords(tr, &x2, &y2, l->Point2.X, l->Point2.Y); + crd = pcb_hash_coord(x1) ^ pcb_hash_coord(y1) ^ pcb_hash_coord(x2) ^ pcb_hash_coord(y2); + } + + return pcb_hash_coord(l->Thickness) ^ pcb_hash_coord(l->Clearance) ^ + pcb_hash_str(l->term) ^ crd; +} + + +pcb_coord_t pcb_line_length(const pcb_line_t *line) +{ + pcb_coord_t dx = line->Point1.X - line->Point2.X; + pcb_coord_t dy = line->Point1.Y - line->Point2.Y; +TODO(": use the distance func instead") + return pcb_round(sqrt((double)dx*(double)dx + (double)dy*(double)dy)); +} + +double pcb_line_area(const pcb_line_t *line) +{ + return + pcb_line_length(line) * (double)line->Thickness /* body */ + + (double)line->Thickness * (double)line->Thickness * M_PI; /* cap circles */ +} + +void pcb_sqline_to_rect(const pcb_line_t *line, pcb_coord_t *x, pcb_coord_t *y) +{ + double l, vx, vy, nx, ny, width, x1, y1, x2, y2, dx, dy; + + x1 = line->Point1.X; + y1 = line->Point1.Y; + x2 = line->Point2.X; + y2 = line->Point2.Y; + + width = (double)((line->Thickness + 1) / 2); + dx = x2-x1; + dy = y2-y1; + + if ((dx == 0) && (dy == 0)) + dx = 1; + + l = sqrt((double)dx*(double)dx + (double)dy*(double)dy); + + vx = dx / l; + vy = dy / l; + nx = -vy; + ny = vx; + + x[0] = (pcb_coord_t)pcb_round(x1 - vx * width + nx * width); + y[0] = (pcb_coord_t)pcb_round(y1 - vy * width + ny * width); + x[1] = (pcb_coord_t)pcb_round(x1 - vx * width - nx * width); + y[1] = (pcb_coord_t)pcb_round(y1 - vy * width - ny * width); + x[2] = (pcb_coord_t)pcb_round(x2 + vx * width - nx * width); + y[2] = (pcb_coord_t)pcb_round(y2 + vy * width - ny * width); + x[3] = (pcb_coord_t)pcb_round(x2 + vx * width + nx * width); + y[3] = (pcb_coord_t)pcb_round(y2 + vy * width + ny * width); +} + +void pcb_line_pre(pcb_line_t *line) +{ + pcb_layer_t *ly = pcb_layer_get_real(line->parent.layer); + if (ly == NULL) + return; + if (ly->line_tree != NULL) + pcb_r_delete_entry(ly->line_tree, (pcb_box_t *)line); + pcb_poly_restore_to_poly(ly->parent.data, PCB_OBJ_LINE, ly, line); +} + +void pcb_line_post(pcb_line_t *line) +{ + pcb_layer_t *ly = pcb_layer_get_real(line->parent.layer); + if (ly == NULL) + return; + if (ly->line_tree != NULL) + pcb_r_insert_entry(ly->line_tree, (pcb_box_t *)line); + pcb_poly_clear_from_poly(ly->parent.data, PCB_OBJ_LINE, ly, line); +} + +/*** ops ***/ +/* copies a line to buffer */ +void *pcb_lineop_add_to_buffer(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_line_t *Line) +{ + pcb_line_t *line; + pcb_layer_t *layer = &ctx->buffer.dst->Layer[pcb_layer_id(ctx->buffer.src, Layer)]; + line = pcb_line_new(layer, Line->Point1.X, Line->Point1.Y, + Line->Point2.X, Line->Point2.Y, + Line->Thickness, Line->Clearance, pcb_flag_mask(Line->Flags, PCB_FLAG_FOUND | ctx->buffer.extraflg)); + return pcb_line_copy_meta(line, Line); +} + +/* moves a line between board and buffer */ +void *pcb_lineop_move_buffer(pcb_opctx_t *ctx, pcb_layer_t *dstly, pcb_line_t *line) +{ + pcb_layer_t *srcly = line->parent.layer; + + assert(line->parent_type == PCB_PARENT_LAYER); + if ((dstly == NULL) || (dstly == srcly)) /* auto layer in dst */ + dstly = &ctx->buffer.dst->Layer[pcb_layer_id(ctx->buffer.src, srcly)]; + + pcb_poly_restore_to_poly(ctx->buffer.src, PCB_OBJ_LINE, srcly, line); + pcb_r_delete_entry(srcly->line_tree, (pcb_box_t *)line); + + pcb_line_unreg(line); + pcb_line_reg(dstly, line); + + PCB_FLAG_CLEAR(PCB_FLAG_FOUND, line); + + if (!dstly->line_tree) + dstly->line_tree = pcb_r_create_tree(); + pcb_r_insert_entry(dstly->line_tree, (pcb_box_t *)line); + pcb_poly_clear_from_poly(ctx->buffer.dst, PCB_OBJ_LINE, dstly, line); + + return line; +} + +/* changes the size of a line */ +void *pcb_lineop_change_size(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_line_t *Line) +{ + pcb_coord_t value = (ctx->chgsize.is_absolute) ? ctx->chgsize.value : Line->Thickness + ctx->chgsize.value; + + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, Line)) + return NULL; + if (value <= PCB_MAX_LINESIZE && value >= PCB_MIN_LINESIZE && value != Line->Thickness) { + pcb_undo_add_obj_to_size(PCB_OBJ_LINE, Layer, Line, Line); + pcb_line_invalidate_erase(Line); + pcb_r_delete_entry(Layer->line_tree, (pcb_box_t *) Line); + pcb_poly_restore_to_poly(ctx->chgsize.pcb->Data, PCB_OBJ_LINE, Layer, Line); + Line->Thickness = value; + pcb_line_bbox(Line); + pcb_r_insert_entry(Layer->line_tree, (pcb_box_t *) Line); + pcb_poly_clear_from_poly(ctx->chgsize.pcb->Data, PCB_OBJ_LINE, Layer, Line); + pcb_line_invalidate_draw(Layer, Line); + return Line; + } + return NULL; +} + +/*changes the clearance size of a line */ +void *pcb_lineop_change_clear_size(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_line_t *Line) +{ + pcb_coord_t value = (ctx->chgsize.is_absolute) ? ctx->chgsize.value : Line->Clearance + ctx->chgsize.value; + + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, Line) || !PCB_FLAG_TEST(PCB_FLAG_CLEARLINE, Line)) + return NULL; + if (value < 0) + value = 0; + value = MIN(PCB_MAX_LINESIZE, value); + if (!ctx->chgsize.is_absolute && ctx->chgsize.value < 0 && value < conf_core.design.bloat * 2) + value = 0; + if (ctx->chgsize.value > 0 && value < conf_core.design.bloat * 2) + value = conf_core.design.bloat * 2 + 2; + if (value != Line->Clearance) { + pcb_undo_add_obj_to_clear_size(PCB_OBJ_LINE, Layer, Line, Line); + pcb_poly_restore_to_poly(ctx->chgsize.pcb->Data, PCB_OBJ_LINE, Layer, Line); + pcb_line_invalidate_erase(Line); + pcb_r_delete_entry(Layer->line_tree, (pcb_box_t *) Line); + Line->Clearance = value; + pcb_line_bbox(Line); + pcb_r_insert_entry(Layer->line_tree, (pcb_box_t *) Line); + pcb_poly_clear_from_poly(ctx->chgsize.pcb->Data, PCB_OBJ_LINE, Layer, Line); + pcb_line_invalidate_draw(Layer, Line); + return Line; + } + return NULL; +} + +/* changes the clearance flag of a line */ +void *pcb_lineop_change_join(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_line_t *Line) +{ + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, Line)) + return NULL; + pcb_line_invalidate_erase(Line); + if (PCB_FLAG_TEST(PCB_FLAG_CLEARLINE, Line)) { + pcb_undo_add_obj_to_clear_poly(PCB_OBJ_LINE, Layer, Line, Line, pcb_false); + pcb_poly_restore_to_poly(ctx->chgsize.pcb->Data, PCB_OBJ_LINE, Layer, Line); + } + pcb_undo_add_obj_to_flag(Line); + PCB_FLAG_TOGGLE(PCB_FLAG_CLEARLINE, Line); + if (PCB_FLAG_TEST(PCB_FLAG_CLEARLINE, Line)) { + pcb_undo_add_obj_to_clear_poly(PCB_OBJ_LINE, Layer, Line, Line, pcb_true); + pcb_poly_clear_from_poly(ctx->chgsize.pcb->Data, PCB_OBJ_LINE, Layer, Line); + } + pcb_line_invalidate_draw(Layer, Line); + return Line; +} + +/* sets the clearance flag of a line */ +void *pcb_lineop_set_join(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_line_t *Line) +{ + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, Line) || PCB_FLAG_TEST(PCB_FLAG_CLEARLINE, Line)) + return NULL; + return pcb_lineop_change_join(ctx, Layer, Line); +} + +/* clears the clearance flag of a line */ +void *pcb_lineop_clear_join(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_line_t *Line) +{ + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, Line) || !PCB_FLAG_TEST(PCB_FLAG_CLEARLINE, Line)) + return NULL; + return pcb_lineop_change_join(ctx, Layer, Line); +} + +/* copies a line */ +void *pcb_lineop_copy(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_line_t *Line) +{ + pcb_line_t *line; + + line = pcb_line_new_merge(Layer, Line->Point1.X + ctx->copy.DeltaX, + Line->Point1.Y + ctx->copy.DeltaY, + Line->Point2.X + ctx->copy.DeltaX, + Line->Point2.Y + ctx->copy.DeltaY, Line->Thickness, Line->Clearance, pcb_flag_mask(Line->Flags, PCB_FLAG_FOUND)); + if (!line) + return line; + pcb_line_copy_meta(line, Line); + pcb_line_invalidate_draw(Layer, line); + pcb_undo_add_obj_to_create(PCB_OBJ_LINE, Layer, line, line); + return line; +} + +/* moves a line */ +void *pcb_lineop_move_noclip(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_line_t *Line) +{ + if (Layer->meta.real.vis) + pcb_line_invalidate_erase(Line); + pcb_line_move(Line, ctx->move.dx, ctx->move.dy); + if (Layer->meta.real.vis) + pcb_line_invalidate_draw(Layer, Line); + return Line; +} + +void *pcb_lineop_move(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_line_t *Line) +{ + if (Layer->line_tree != NULL) + pcb_r_delete_entry(Layer->line_tree, (pcb_box_t *) Line); + if (ctx->move.pcb != NULL) + pcb_poly_restore_to_poly(ctx->move.pcb->Data, PCB_OBJ_LINE, Layer, Line); + pcb_lineop_move_noclip(ctx, Layer, Line); + if (Layer->line_tree != NULL) + pcb_r_insert_entry(Layer->line_tree, (pcb_box_t *) Line); + if (ctx->move.pcb != NULL) + pcb_poly_clear_from_poly(ctx->move.pcb->Data, PCB_OBJ_LINE, Layer, Line); + return Line; +} + +void *pcb_lineop_clip(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_line_t *Line) +{ + if (ctx->clip.restore) { + pcb_r_delete_entry(Layer->line_tree, (pcb_box_t *) Line); + if (ctx->clip.pcb != NULL) + pcb_poly_restore_to_poly(ctx->clip.pcb->Data, PCB_OBJ_LINE, Layer, Line); + } + if (ctx->clip.clear) { + pcb_r_insert_entry(Layer->line_tree, (pcb_box_t *) Line); + if (ctx->clip.pcb != NULL) + pcb_poly_clear_from_poly(ctx->clip.pcb->Data, PCB_OBJ_LINE, Layer, Line); + } + return Line; +} + +/* moves one end of a line */ +void *pcb_lineop_move_point(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_line_t *Line, pcb_point_t *Point) +{ + if (Layer) { + if (Layer->meta.real.vis) + pcb_line_invalidate_erase(Line); + pcb_poly_restore_to_poly(ctx->move.pcb->Data, PCB_OBJ_LINE, Layer, Line); + pcb_r_delete_entry(Layer->line_tree, &Line->BoundingBox); + PCB_MOVE_POINT(Point->X, Point->Y, ctx->move.dx, ctx->move.dy); + pcb_line_bbox(Line); + pcb_r_insert_entry(Layer->line_tree, &Line->BoundingBox); + pcb_poly_clear_from_poly(ctx->move.pcb->Data, PCB_OBJ_LINE, Layer, Line); + if (Layer->meta.real.vis) + pcb_line_invalidate_draw(Layer, Line); + return Line; + } + else { /* must be a rat */ + + if (ctx->move.pcb->RatOn) + pcb_rat_invalidate_erase((pcb_rat_t *) Line); + pcb_r_delete_entry(ctx->move.pcb->Data->rat_tree, &Line->BoundingBox); + PCB_MOVE_POINT(Point->X, Point->Y, ctx->move.dx, ctx->move.dy); + pcb_line_bbox(Line); + pcb_r_insert_entry(ctx->move.pcb->Data->rat_tree, &Line->BoundingBox); + if (ctx->move.pcb->RatOn) + pcb_rat_invalidate_draw((pcb_rat_t *) Line); + return Line; + } +} + +/* moves one end of a line */ +void *pcb_lineop_move_point_with_route(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_line_t *Line, pcb_point_t *Point) +{ + if ((conf_core.editor.move_linepoint_uses_route == 0) || !Layer) { + pcb_undo_add_obj_to_move(PCB_OBJ_LINE_POINT, Layer, Line, Point, ctx->move.dx, ctx->move.dy); + return pcb_lineop_move_point(ctx, Layer, Line, Point); + } + else { + /* Move with Route Code */ + pcb_route_t route; + pcb_point_t point1 = (&Line->Point1 == Point ? Line->Point2 : Line->Point1); + pcb_point_t point2 = *Point; + + point2.X += ctx->move.dx; + point2.Y += ctx->move.dy; + + /* Calculate the new line route and add apply it */ + pcb_route_init(&route); + pcb_route_calculate(PCB, + &route, + &point1, + &point2, + pcb_layer_id(ctx->move.pcb->Data,Layer), + Line->Thickness, + Line->Clearance, + Line->Flags, + pcb_gui->shift_is_pressed(), + pcb_gui->control_is_pressed() ); + pcb_route_apply_to_line(&route,Layer,Line); + pcb_route_destroy(&route); + } + return NULL; +} + +/* moves a line between layers; lowlevel routines */ +void *pcb_lineop_move_to_layer_low(pcb_opctx_t *ctx, pcb_layer_t * Source, pcb_line_t * line, pcb_layer_t * Destination) +{ + pcb_r_delete_entry(Source->line_tree, (pcb_box_t *) line); + + pcb_line_unreg(line); + pcb_line_reg(Destination, line); + + if (!Destination->line_tree) + Destination->line_tree = pcb_r_create_tree(); + pcb_r_insert_entry(Destination->line_tree, (pcb_box_t *) line); + + return line; +} + +/* --------------------------------------------------------------------------- + * moves a line between layers + */ +struct via_info { + pcb_coord_t X, Y; + jmp_buf env; +}; + +static pcb_r_dir_t moveline_callback(const pcb_box_t * b, void *cl) +{ + struct via_info *i = (struct via_info *) cl; + pcb_pstk_t *ps; + +TODO("pdstk TODO #21: do not work in comp mode, use a pstk proto - scconfig also has TODO #21, fix it there too") + if ((ps = pcb_pstk_new_compat_via(PCB->Data, -1, i->X, i->Y, conf_core.design.via_drilling_hole, conf_core.design.via_thickness, conf_core.design.clearance, 0, PCB_PSTK_COMPAT_ROUND, pcb_true)) != NULL) { + pcb_undo_add_obj_to_create(PCB_OBJ_PSTK, ps, ps, ps); + pcb_pstk_invalidate_draw(ps); + } + longjmp(i->env, 1); +} + +void *pcb_lineop_move_to_layer(pcb_opctx_t *ctx, pcb_layer_t * Layer, pcb_line_t * Line) +{ + struct via_info info; + pcb_box_t sb; + pcb_line_t *newone; + void *ptr1, *ptr2, *ptr3; + + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, Line)) { + pcb_message(PCB_MSG_WARNING, "Sorry, line object is locked\n"); + return NULL; + } + if (ctx->move.dst_layer == Layer && Layer->meta.real.vis) + pcb_line_invalidate_draw(Layer, Line); + if (ctx->move.dst_layer == Layer) + return Line; + + pcb_undo_add_obj_to_move_to_layer(PCB_OBJ_LINE, Layer, Line, Line); + if (Layer->meta.real.vis) + pcb_line_invalidate_erase(Line); + pcb_poly_restore_to_poly(PCB->Data, PCB_OBJ_LINE, Layer, Line); + newone = (pcb_line_t *) pcb_lineop_move_to_layer_low(ctx, Layer, Line, ctx->move.dst_layer); + Line = NULL; + pcb_poly_clear_from_poly(PCB->Data, PCB_OBJ_LINE, ctx->move.dst_layer, newone); + if (ctx->move.dst_layer->meta.real.vis) + pcb_line_invalidate_draw(ctx->move.dst_layer, newone); + if (!conf_core.editor.auto_via || !PCB->pstk_on || ctx->move.more_to_come || + pcb_layer_get_group_(Layer) == + pcb_layer_get_group_(ctx->move.dst_layer) || !(pcb_layer_flags(PCB, pcb_layer_id(PCB->Data, Layer)) & PCB_LYT_COPPER) || !(pcb_layer_flags_(ctx->move.dst_layer) & PCB_LYT_COPPER)) + return newone; + /* consider via at Point1 */ + sb.X1 = newone->Point1.X - newone->Thickness / 2; + sb.X2 = newone->Point1.X + newone->Thickness / 2; + sb.Y1 = newone->Point1.Y - newone->Thickness / 2; + sb.Y2 = newone->Point1.Y + newone->Thickness / 2; + if ((pcb_search_obj_by_location(PCB_OBJ_CLASS_PIN, &ptr1, &ptr2, &ptr3, + newone->Point1.X, newone->Point1.Y, conf_core.design.via_thickness / 2) == PCB_OBJ_VOID)) { + info.X = newone->Point1.X; + info.Y = newone->Point1.Y; + if (setjmp(info.env) == 0) + pcb_r_search(Layer->line_tree, &sb, NULL, moveline_callback, &info, NULL); + } + /* consider via at Point2 */ + sb.X1 = newone->Point2.X - newone->Thickness / 2; + sb.X2 = newone->Point2.X + newone->Thickness / 2; + sb.Y1 = newone->Point2.Y - newone->Thickness / 2; + sb.Y2 = newone->Point2.Y + newone->Thickness / 2; + if ((pcb_search_obj_by_location(PCB_OBJ_CLASS_PIN, &ptr1, &ptr2, &ptr3, + newone->Point2.X, newone->Point2.Y, conf_core.design.via_thickness / 2) == PCB_OBJ_VOID)) { + info.X = newone->Point2.X; + info.Y = newone->Point2.Y; + if (setjmp(info.env) == 0) + pcb_r_search(Layer->line_tree, &sb, NULL, moveline_callback, &info, NULL); + } + return newone; +} + +/* destroys a line from a layer */ +void *pcb_lineop_destroy(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_line_t *Line) +{ + pcb_r_delete_entry(Layer->line_tree, (pcb_box_t *) Line); + + pcb_line_free(Line); + return NULL; +} + +/* remove point... */ +struct rlp_info { + jmp_buf env; + pcb_line_t *line; + pcb_point_t *point; +}; +static pcb_r_dir_t remove_point(const pcb_box_t * b, void *cl) +{ + pcb_line_t *line = (pcb_line_t *) b; + struct rlp_info *info = (struct rlp_info *) cl; + if (line == info->line) + return PCB_R_DIR_NOT_FOUND; + if ((line->Point1.X == info->point->X) + && (line->Point1.Y == info->point->Y)) { + info->line = line; + info->point = &line->Point1; + longjmp(info->env, 1); + } + else if ((line->Point2.X == info->point->X) + && (line->Point2.Y == info->point->Y)) { + info->line = line; + info->point = &line->Point2; + longjmp(info->env, 1); + } + return PCB_R_DIR_NOT_FOUND; +} + +/* removes a line point, or a line if the selected point is the end */ +void *pcb_lineop_remove_point(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_line_t *Line, pcb_point_t *Point) +{ + pcb_point_t other; + struct rlp_info info; + if (&Line->Point1 == Point) + other = Line->Point2; + else + other = Line->Point1; + info.line = Line; + info.point = Point; + if (setjmp(info.env) == 0) { + pcb_r_search(Layer->line_tree, (const pcb_box_t *) Point, NULL, remove_point, &info, NULL); + return pcb_lineop_remove(ctx, Layer, Line); + } + pcb_move_obj(PCB_OBJ_LINE_POINT, Layer, info.line, info.point, other.X - Point->X, other.Y - Point->Y); + return (pcb_lineop_remove(ctx, Layer, Line)); +} + +/* removes a line from a layer */ +void *pcb_lineop_remove(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_line_t *Line) +{ + /* erase from screen */ + if (Layer->meta.real.vis) + pcb_line_invalidate_erase(Line); + pcb_undo_move_obj_to_remove(PCB_OBJ_LINE, Layer, Line, Line); + return NULL; +} + +void *pcb_line_destroy(pcb_layer_t *Layer, pcb_line_t *Line) +{ + void *res; + pcb_opctx_t ctx; + + ctx.remove.pcb = PCB; + ctx.remove.destroy_target = NULL; + + res = pcb_lineop_remove(&ctx, Layer, Line); + pcb_draw(); + return res; +} + +/* rotates a line in 90 degree steps */ +void pcb_line_rotate90(pcb_line_t *Line, pcb_coord_t X, pcb_coord_t Y, unsigned Number) +{ + PCB_COORD_ROTATE90(Line->Point1.X, Line->Point1.Y, X, Y, Number); + PCB_COORD_ROTATE90(Line->Point2.X, Line->Point2.Y, X, Y, Number); + /* keep horizontal, vertical Point2 > Point1 */ + if (Line->Point1.X == Line->Point2.X) { + if (Line->Point1.Y > Line->Point2.Y) { + pcb_coord_t t; + t = Line->Point1.Y; + Line->Point1.Y = Line->Point2.Y; + Line->Point2.Y = t; + } + } + else if (Line->Point1.Y == Line->Point2.Y) { + if (Line->Point1.X > Line->Point2.X) { + pcb_coord_t t; + t = Line->Point1.X; + Line->Point1.X = Line->Point2.X; + Line->Point2.X = t; + } + } + /* instead of rotating the bounding box, the call updates both end points too */ + pcb_line_bbox(Line); +} + +void pcb_line_rotate(pcb_layer_t *layer, pcb_line_t *line, pcb_coord_t X, pcb_coord_t Y, double cosa, double sina) +{ + if (layer->line_tree != NULL) + pcb_r_delete_entry(layer->line_tree, (pcb_box_t *) line); + pcb_rotate(&line->Point1.X, &line->Point1.Y, X, Y, cosa, sina); + pcb_rotate(&line->Point2.X, &line->Point2.Y, X, Y, cosa, sina); + pcb_line_bbox(line); + if (layer->line_tree != NULL) + pcb_r_insert_entry(layer->line_tree, (pcb_box_t *) line); +} + +void pcb_line_mirror(pcb_layer_t *layer, pcb_line_t *line, pcb_coord_t y_offs) +{ + if (layer->line_tree != NULL) + pcb_r_delete_entry(layer->line_tree, (pcb_box_t *) line); + line->Point1.X = PCB_SWAP_X(line->Point1.X); + line->Point1.Y = PCB_SWAP_Y(line->Point1.Y) + y_offs; + line->Point2.X = PCB_SWAP_X(line->Point2.X); + line->Point2.Y = PCB_SWAP_Y(line->Point2.Y) + y_offs; + pcb_line_bbox(line); + if (layer->line_tree != NULL) + pcb_r_insert_entry(layer->line_tree, (pcb_box_t *) line); +} + +void pcb_line_scale(pcb_line_t *line, double sx, double sy, double sth) +{ + int onbrd = (line->parent.layer != NULL) && (!line->parent.layer->is_bound); + + if (onbrd) + pcb_line_pre(line); + + if (sx != 1.0) { + line->Point1.X = pcb_round((double)line->Point1.X * sx); + line->Point2.X = pcb_round((double)line->Point2.X * sx); + } + + if (sy != 1.0) { + line->Point1.Y = pcb_round((double)line->Point1.Y * sy); + line->Point2.Y = pcb_round((double)line->Point2.Y * sy); + } + + if (sth != 1.0) + line->Thickness = pcb_round((double)line->Thickness * sth); + + pcb_line_bbox(line); + + if (onbrd) + pcb_line_post(line); +} + +void pcb_line_flip_side(pcb_layer_t *layer, pcb_line_t *line) +{ + pcb_r_delete_entry(layer->line_tree, (pcb_box_t *) line); + line->Point1.X = PCB_SWAP_X(line->Point1.X); + line->Point1.Y = PCB_SWAP_Y(line->Point1.Y); + line->Point2.X = PCB_SWAP_X(line->Point2.X); + line->Point2.Y = PCB_SWAP_Y(line->Point2.Y); + pcb_line_bbox(line); + pcb_r_insert_entry(layer->line_tree, (pcb_box_t *) line); +} + +static void rotate_line1(pcb_layer_t *Layer, pcb_line_t *Line) +{ + pcb_line_invalidate_erase(Line); + if (Layer) { + if (!Layer->is_bound) + pcb_poly_restore_to_poly(PCB->Data, PCB_OBJ_LINE, Layer, Line); + if (Layer->line_tree != NULL) + pcb_r_delete_entry(Layer->line_tree, (pcb_box_t *) Line); + } + else + pcb_r_delete_entry(PCB->Data->rat_tree, (pcb_box_t *) Line); +} + +static void rotate_line2(pcb_layer_t *Layer, pcb_line_t *Line) +{ + pcb_line_bbox(Line); + if (Layer) { + if (Layer->line_tree != NULL) + pcb_r_insert_entry(Layer->line_tree, (pcb_box_t *) Line); + if (!Layer->is_bound) + pcb_poly_clear_from_poly(PCB->Data, PCB_OBJ_LINE, Layer, Line); + pcb_line_invalidate_draw(Layer, Line); + } + else { + pcb_r_insert_entry(PCB->Data->rat_tree, (pcb_box_t *) Line); + pcb_rat_invalidate_draw((pcb_rat_t *) Line); + } +} + +/* rotates a line's point */ +void *pcb_lineop_rotate90_point(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_line_t *Line, pcb_point_t *Point) +{ + rotate_line1(Layer, Line); + + pcb_point_rotate90(Point, ctx->rotate.center_x, ctx->rotate.center_y, ctx->rotate.number); + + rotate_line2(Layer, Line); + return Line; +} + +/* rotates a line */ +void *pcb_lineop_rotate90(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_line_t *Line) +{ + rotate_line1(Layer, Line); + pcb_point_rotate90(&Line->Point1, ctx->rotate.center_x, ctx->rotate.center_y, ctx->rotate.number); + pcb_point_rotate90(&Line->Point2, ctx->rotate.center_x, ctx->rotate.center_y, ctx->rotate.number); + rotate_line2(Layer, Line); + return Line; +} + +void *pcb_lineop_rotate(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_line_t *Line) +{ + pcb_line_rotate(Layer, Line, ctx->rotate.center_x, ctx->rotate.center_y, ctx->rotate.cosa, ctx->rotate.sina); + return Line; +} + +/* inserts a point into a line */ +void *pcb_lineop_insert_point(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_line_t *Line) +{ + pcb_line_t *line; + pcb_coord_t X, Y; + + if (((Line->Point1.X == ctx->insert.x) && (Line->Point1.Y == ctx->insert.y)) || + ((Line->Point2.X == ctx->insert.x) && (Line->Point2.Y == ctx->insert.y))) + return NULL; + X = Line->Point2.X; + Y = Line->Point2.Y; + pcb_undo_add_obj_to_move(PCB_OBJ_LINE_POINT, Layer, Line, &Line->Point2, ctx->insert.x - X, ctx->insert.y - Y); + pcb_line_invalidate_erase(Line); + pcb_r_delete_entry(Layer->line_tree, (pcb_box_t *) Line); + pcb_poly_restore_to_poly(PCB->Data, PCB_OBJ_LINE, Layer, Line); + Line->Point2.X = ctx->insert.x; + Line->Point2.Y = ctx->insert.y; + pcb_line_bbox(Line); + pcb_r_insert_entry(Layer->line_tree, (pcb_box_t *) Line); + pcb_poly_clear_from_poly(PCB->Data, PCB_OBJ_LINE, Layer, Line); + pcb_line_invalidate_draw(Layer, Line); + /* we must create after playing with Line since creation may + * invalidate the line pointer + */ + if ((line = pcb_line_new_merge(Layer, ctx->insert.x, ctx->insert.y, X, Y, Line->Thickness, Line->Clearance, Line->Flags))) { + pcb_line_copy_meta(line, Line); + pcb_undo_add_obj_to_create(PCB_OBJ_LINE, Layer, line, line); + pcb_line_invalidate_draw(Layer, line); + pcb_poly_clear_from_poly(PCB->Data, PCB_OBJ_LINE, Layer, line); + /* creation call adds it to the rtree */ + } + return line; +} + +void *pcb_lineop_change_flag(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_line_t *Line) +{ + static pcb_flag_values_t pcb_line_flags = 0; + if (pcb_line_flags == 0) + pcb_line_flags = pcb_obj_valid_flags(PCB_OBJ_LINE); + + if ((ctx->chgflag.flag & pcb_line_flags) != ctx->chgflag.flag) + return NULL; + if ((ctx->chgflag.flag & PCB_FLAG_TERMNAME) && (Line->term == NULL)) + return NULL; + pcb_undo_add_obj_to_flag(Line); + + if (ctx->chgflag.flag & PCB_FLAG_CLEARLINE) + pcb_poly_restore_to_poly(ctx->chgflag.pcb->Data, PCB_OBJ_LINE, Line->parent.layer, Line); + + PCB_FLAG_CHANGE(ctx->chgflag.how, ctx->chgflag.flag, Line); + + if (ctx->chgflag.flag & PCB_FLAG_CLEARLINE) + pcb_poly_clear_from_poly(ctx->chgflag.pcb->Data, PCB_OBJ_LINE, Line->parent.layer, Line); + + return Line; +} + +void *pcb_lineop_invalidate_label(pcb_opctx_t *ctx, pcb_layer_t *layer, pcb_line_t *line) +{ + pcb_line_name_invalidate_draw(line); + return line; +} + + +/*** draw ***/ + +static pcb_bool is_line_term_vert(const pcb_line_t *line) +{ + pcb_coord_t dx, dy; + + dx = line->Point1.X - line->Point2.X; + if (dx < 0) + dx = -dx; + + dy = line->Point1.Y - line->Point2.Y; + if (dy < 0) + dy = -dy; + + return dx < dy; +} + +void pcb_line_name_invalidate_draw(pcb_line_t *line) +{ + if (line->term != NULL) { + pcb_term_label_invalidate((line->Point1.X + line->Point2.X)/2, (line->Point1.Y + line->Point2.Y)/2, + 100.0, is_line_term_vert(line), pcb_true, (pcb_any_obj_t *)line); + } +} + +void pcb_line_draw_label(pcb_draw_info_t *info, pcb_line_t *line) +{ + if (line->term != NULL) + pcb_term_label_draw(info, (line->Point1.X + line->Point2.X)/2, (line->Point1.Y + line->Point2.Y)/2, + conf_core.appearance.term_label_size, is_line_term_vert(line), pcb_true, (pcb_any_obj_t *)line); +} + + +void pcb_line_draw_(pcb_draw_info_t *info, pcb_line_t *line, int allow_term_gfx) +{ + pcb_coord_t thickness = line->Thickness; + + if (delayed_terms_enabled && (line->term != NULL)) { + pcb_draw_delay_obj_add((pcb_any_obj_t *)line); + return; + } + + if ((info != NULL) && (info->xform != NULL) && (info->xform->bloat != 0)) { + thickness += info->xform->bloat; + if (thickness < 1) + thickness = 1; + } + + PCB_DRAW_BBOX(line); + pcb_hid_set_line_cap(pcb_draw_out.fgGC, pcb_cap_round); + if (!conf_core.editor.thin_draw && !conf_core.editor.wireframe_draw) { + if ((allow_term_gfx) && pcb_draw_term_need_gfx(line) && pcb_draw_term_hid_permission()) { + pcb_hid_set_line_cap(pcb_draw_out.active_padGC, pcb_cap_round); + pcb_hid_set_line_width(pcb_draw_out.active_padGC, thickness); + pcb_gui->draw_line(pcb_draw_out.active_padGC, line->Point1.X, line->Point1.Y, line->Point2.X, line->Point2.Y); + pcb_hid_set_line_width(pcb_draw_out.fgGC, PCB_DRAW_TERM_GFX_WIDTH); + } + else + pcb_hid_set_line_width(pcb_draw_out.fgGC, thickness); + pcb_gui->draw_line(pcb_draw_out.fgGC, line->Point1.X, line->Point1.Y, line->Point2.X, line->Point2.Y); + } + else { + if(conf_core.editor.thin_draw) { + pcb_hid_set_line_width(pcb_draw_out.fgGC, 0); + pcb_gui->draw_line(pcb_draw_out.fgGC, line->Point1.X, line->Point1.Y, line->Point2.X, line->Point2.Y); + } + + if(conf_core.editor.wireframe_draw) { + pcb_hid_set_line_width(pcb_draw_out.fgGC, 0); + pcb_draw_wireframe_line(pcb_draw_out.fgGC, line->Point1.X, line->Point1.Y, line->Point2.X, line->Point2.Y, thickness, 0); + } + } + + if (line->term != NULL) { + if ((pcb_draw_force_termlab) || PCB_FLAG_TEST(PCB_FLAG_TERMNAME, line)) + pcb_draw_delay_label_add((pcb_any_obj_t *)line); + } +} + +static void pcb_line_draw(pcb_draw_info_t *info, pcb_line_t *line, int allow_term_gfx) +{ + const pcb_color_t *color; + pcb_color_t buf; + const pcb_layer_t *layer = info->layer != NULL ? info->layer : pcb_layer_get_real(line->parent.layer); + + if (layer == NULL) /* if the layer is inbound, e.g. in preview, fall back using the layer recipe */ + layer = line->parent.layer; + + if (PCB_FLAG_TEST(PCB_FLAG_WARN, line)) + color = &conf_core.appearance.color.warn; + else if (PCB_FLAG_TEST(PCB_FLAG_SELECTED | PCB_FLAG_FOUND, line)) { + if (PCB_FLAG_TEST(PCB_FLAG_SELECTED, line)) { + if (layer->is_bound) + PCB_OBJ_COLOR_ON_BOUND_LAYER(color, layer, 1); + else + color = &conf_core.appearance.color.selected; + } + else + color = &conf_core.appearance.color.connected; + } + else if (PCB_HAS_COLOROVERRIDE(line)) { + color = line->override_color; + } + else if (layer->is_bound) + PCB_OBJ_COLOR_ON_BOUND_LAYER(color, layer, 0); + else + color = &layer->meta.real.color; + + if (PCB_FLAG_TEST(PCB_FLAG_ONPOINT, line)) { + pcb_lighten_color(color, &buf, 1.75); + color = &buf; + } + + pcb_gui->set_color(pcb_draw_out.fgGC, color); + pcb_line_draw_(info, line, allow_term_gfx); +} + +pcb_r_dir_t pcb_line_draw_callback(const pcb_box_t * b, void *cl) +{ + pcb_line_t *line = (pcb_line_t *)b; + pcb_draw_info_t *info = cl; + + if (pcb_hidden_floater((pcb_any_obj_t*)b)) + return PCB_R_DIR_FOUND_CONTINUE; + + if (!PCB->SubcPartsOn && pcb_lobj_parent_subc(line->parent_type, &line->parent)) + return PCB_R_DIR_NOT_FOUND; + + pcb_line_draw(info, line, 0); + return PCB_R_DIR_FOUND_CONTINUE; +} + +pcb_r_dir_t pcb_line_draw_term_callback(const pcb_box_t * b, void *cl) +{ + pcb_line_t *line = (pcb_line_t *)b; + pcb_draw_info_t *info = cl; + + if (pcb_hidden_floater((pcb_any_obj_t*)b)) + return PCB_R_DIR_FOUND_CONTINUE; + + if (!PCB->SubcPartsOn && pcb_lobj_parent_subc(line->parent_type, &line->parent)) + return PCB_R_DIR_NOT_FOUND; + + pcb_line_draw(info, line, 1); + return PCB_R_DIR_FOUND_CONTINUE; +} + +/* erases a line on a layer */ +void pcb_line_invalidate_erase(pcb_line_t *Line) +{ + pcb_draw_invalidate(Line); + pcb_flag_erase(&Line->Flags); +} + +void pcb_line_invalidate_draw(pcb_layer_t *Layer, pcb_line_t *Line) +{ + pcb_draw_invalidate(Line); +} + Index: tags/2.1.2/src/obj_line.h =================================================================== --- tags/2.1.2/src/obj_line.h (nonexistent) +++ tags/2.1.2/src/obj_line.h (revision 24813) @@ -0,0 +1,169 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +/* Drawing primitive: line segment */ + +#ifndef PCB_OBJ_LINE_H +#define PCB_OBJ_LINE_H + +#include +#include "obj_common.h" + +struct pcb_line_s { /* holds information about one line */ + PCB_ANYLINEFIELDS; + gdl_elem_t link; /* a line is in a list: either on a layer */ +}; + +/* crosshair: */ +typedef struct { /* current marked line */ + pcb_point_t Point1, /* start- and end-position */ + Point2; + long int State; + pcb_bool draw; +} pcb_attached_line_t; + + +pcb_line_t *pcb_line_alloc(pcb_layer_t * layer); +pcb_line_t *pcb_line_alloc_id(pcb_layer_t *layer, long int id); +void pcb_line_free(pcb_line_t * data); + +pcb_line_t *pcb_line_new_merge(pcb_layer_t *Layer, pcb_coord_t X1, pcb_coord_t Y1, pcb_coord_t X2, pcb_coord_t Y2, pcb_coord_t Thickness, pcb_coord_t Clearance, pcb_flag_t Flags); +pcb_line_t *pcb_line_new(pcb_layer_t *Layer, pcb_coord_t X1, pcb_coord_t Y1, pcb_coord_t X2, pcb_coord_t Y2, pcb_coord_t Thickness, pcb_coord_t Clearance, pcb_flag_t Flags); +pcb_line_t *pcb_line_dup(pcb_layer_t *Layer, pcb_line_t *src); +pcb_line_t *pcb_line_dup_at(pcb_layer_t *dst, pcb_line_t *src, pcb_coord_t dx, pcb_coord_t dy); +void *pcb_line_destroy(pcb_layer_t *dst, pcb_line_t *src); + +void pcb_line_reg(pcb_layer_t *layer, pcb_line_t *line); +void pcb_line_unreg(pcb_line_t *line); + +/* Add objects without creating them or making any "sanity modifications" to them */ +void pcb_add_line_on_layer(pcb_layer_t *Layer, pcb_line_t *Line); + +void pcb_line_bbox(pcb_line_t *Line); +void pcb_line_rotate90(pcb_line_t *Line, pcb_coord_t X, pcb_coord_t Y, unsigned Number); +void pcb_line_rotate(pcb_layer_t *layer, pcb_line_t *line, pcb_coord_t X, pcb_coord_t Y, double cosa, double sina); +void pcb_line_mirror(pcb_layer_t *layer, pcb_line_t *line, pcb_coord_t y_offs); +void pcb_line_flip_side(pcb_layer_t *layer, pcb_line_t *line); +void pcb_line_scale(pcb_line_t *line, double sx, double sy, double sth); + +pcb_coord_t pcb_line_length(const pcb_line_t *line); +double pcb_line_area(const pcb_line_t *line); + +/* Convert a square cap line (e.g. a gEDA/pcb pad) to 4 corner points of a rectangle */ +void pcb_sqline_to_rect(const pcb_line_t *line, pcb_coord_t *x, pcb_coord_t *y); + +/* hash and eq */ +int pcb_line_eq(const pcb_host_trans_t *tr1, const pcb_line_t *l1, const pcb_host_trans_t *tr2, const pcb_line_t *l2); +unsigned int pcb_line_hash(const pcb_host_trans_t *tr, const pcb_line_t *l); + +/* un-administrate a line; call before changing geometry */ +void pcb_line_pre(pcb_line_t *line); + +/* re-administrate a line; call after changing geometry */ +void pcb_line_post(pcb_line_t *line); + +/*** DRC enforcement (obj_line_drcenf.c) ***/ + +/* Adjust the attached line to 45 degrees if necessary */ +void pcb_line_adjust_attached(void); + +/* adjusts the insert lines to make them 45 degrees as necessary */ +void pcb_line_adjust_attached_2lines(pcb_bool); + +/* makes the attached line fit into a 45 degree direction */ +void pcb_line_45(pcb_attached_line_t *); + +void pcb_line_enforce_drc(void); + +/* Calculate a pair of refractioned (ortho-45) lines between 'start' and 'end'. + If 'mid_out' is not NULL, load it with the coords of the middle point. + If way is false it checks an ortho start line with one 45 refraction to + reach the endpoint, otherwise it checks a 45 start, with a ortho refraction + to reach endpoint. + + Checks for intersectors against two lines. + + If optimize is false, return straight-line distance between start and end + on success or -1 if the pair-of-lines has hit a blocker object. + + If optimize is true, keep on looking for a mid-way solution, adjusting + the fields of 'end' needed to find the closest point to the original target + that still won't hit any object. Returns the straigh-line distance between + start and the new end. */ +double pcb_drc_lines(const pcb_point_t *start, pcb_point_t *end, pcb_point_t *mid_out, pcb_bool way, pcb_bool optimize); + + +/* Rather than mode the line bounding box, we set it so the point bounding + * boxes are updated too. + */ +#define pcb_line_move(l,dx,dy) \ + do { \ + pcb_coord_t __dx__ = (dx), __dy__ = (dy); \ + pcb_line_t *__l__ = (l); \ + PCB_MOVE_POINT((__l__)->Point1.X,(__l__)->Point1.Y,(__dx__),(__dy__)); \ + PCB_MOVE_POINT((__l__)->Point2.X,(__l__)->Point2.Y,(__dx__),(__dy__)); \ + pcb_line_bbox(__l__); \ + } while(0) + +#define PCB_LINE_LOOP(layer) do { \ + pcb_line_t *line; \ + gdl_iterator_t __it__; \ + linelist_foreach(&(layer)->Line, &__it__, line) { + +#define PCB_LINE_ALL_LOOP(top) do { \ + pcb_cardinal_t l; \ + pcb_layer_t *layer = (top)->Layer; \ + for (l = 0; l < ((top)->LayerN > 0 ? (top)->LayerN : PCB->Data->LayerN); l++, layer++) \ + { \ + PCB_LINE_LOOP(layer) + +#define PCB_LINE_COPPER_LOOP(top) do { \ + pcb_cardinal_t l; \ + pcb_layer_t *layer = (top)->Layer; \ + for (l = 0; l < ((top)->LayerN > 0 ? (top)->LayerN : PCB->Data->LayerN); l++, layer++) \ + { \ + if (!(pcb_layer_flags(PCB, l) & PCB_LYT_COPPER)) continue; \ + PCB_LINE_LOOP(layer) + +#define PCB_LINE_SILK_LOOP(top) do { \ + pcb_cardinal_t l; \ + pcb_layer_t *layer = (top)->Layer; \ + for (l = 0; l < ((top)->LayerN > 0 ? (top)->LayerN : PCB->Data->LayerN); l++, layer++) \ + { \ + if (!(pcb_layer_flags(PCB, l) & PCB_LYT_SILK)) continue; \ + PCB_LINE_LOOP(layer) + +#define PCB_LINE_VISIBLE_LOOP(top) do { \ + pcb_cardinal_t l; \ + pcb_layer_t *layer = (top)->Layer; \ + for (l = 0; l < ((top)->LayerN > 0 ? (top)->LayerN : PCB->Data->LayerN); l++, layer++) \ + { \ + if (layer->meta.real.vis) \ + PCB_LINE_LOOP(layer) + +#endif Index: tags/2.1.2/src/obj_line_draw.h =================================================================== --- tags/2.1.2/src/obj_line_draw.h (nonexistent) +++ tags/2.1.2/src/obj_line_draw.h (revision 24813) @@ -0,0 +1,44 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +/*** Standard draw of lines ***/ + +#include "draw.h" + +/* Include rtree.h for this */ +#ifdef PCB_RTREE_H +pcb_r_dir_t pcb_line_draw_callback(const pcb_box_t * b, void *cl); +pcb_r_dir_t pcb_line_draw_term_callback(const pcb_box_t * b, void *cl); +#endif + +void pcb_line_draw_(pcb_draw_info_t *info, pcb_line_t *line, int allow_term_gfx); +void pcb_line_invalidate_erase(pcb_line_t *Line); +void pcb_line_invalidate_draw(pcb_layer_t *Layer, pcb_line_t *Line); +void pcb_line_draw_label(pcb_draw_info_t *info, pcb_line_t *line); +void pcb_line_name_invalidate_draw(pcb_line_t *line); + Index: tags/2.1.2/src/obj_line_drcenf.c =================================================================== --- tags/2.1.2/src/obj_line_drcenf.c (nonexistent) +++ tags/2.1.2/src/obj_line_drcenf.c (revision 24813) @@ -0,0 +1,526 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * Copyright (C) 2004 harry eaton + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +#include "config.h" +#include "conf_core.h" +#include "math_helper.h" + +#include +#include + +#include "board.h" +#include "data.h" +#include "find.h" +#include "rtree.h" +#include "macro.h" + +void pcb_line_adjust_attached(void) +{ + pcb_attached_line_t *line = &pcb_crosshair.AttachedLine; + int flags = conf_core.editor.clear_line ? PCB_FLAG_CLEARLINE : 0; + + if (conf_core.editor.auto_drc && (pcb_layer_flags_(CURRENT) & PCB_LYT_COPPER)) + flags |= PCB_FLAG_FOUND; + + /* I need at least one point */ + if (line->State == PCB_CH_STATE_FIRST) + return; + + line->Point2.X = pcb_crosshair.X; + line->Point2.Y = pcb_crosshair.Y; + + pcb_route_calculate(PCB, + &pcb_crosshair.Route, &line->Point1, &line->Point2, + pcb_layer_id(PCB->Data, CURRENT), + conf_core.design.line_thickness, conf_core.design.clearance * 2, + pcb_flag_make(flags), pcb_gui->shift_is_pressed(), + pcb_gui->control_is_pressed()); +} + +/* directions: + * + * 0 + * 7 1 + * 6 2 + * 5 3 + * 4 + */ +void pcb_line_45(pcb_attached_line_t *Line) +{ + pcb_coord_t dx, dy, min; + unsigned direction = 0; + double m; + + /* first calculate direction of line */ + dx = pcb_crosshair.X - Line->Point1.X; + dy = pcb_crosshair.Y - Line->Point1.Y; + + if (!dx) { + if (!dy) + /* zero length line, don't draw anything */ + return; + else + direction = dy > 0 ? 0 : 4; + } + else { + m = (double) dy / dx; + direction = 2; + if (m > PCB_TAN_30_DEGREE) + direction = m > PCB_TAN_60_DEGREE ? 0 : 1; + else if (m < -PCB_TAN_30_DEGREE) + direction = m < -PCB_TAN_60_DEGREE ? 0 : 3; + } + if (dx < 0) + direction += 4; + + dx = coord_abs(dx); + dy = coord_abs(dy); + min = MIN(dx, dy); + + /* now set up the second pair of coordinates */ + switch (direction) { + case 0: + case 4: + Line->Point2.X = Line->Point1.X; + Line->Point2.Y = pcb_crosshair.Y; + break; + + case 2: + case 6: + Line->Point2.X = pcb_crosshair.X; + Line->Point2.Y = Line->Point1.Y; + break; + + case 1: + Line->Point2.X = Line->Point1.X + min; + Line->Point2.Y = Line->Point1.Y + min; + break; + + case 3: + Line->Point2.X = Line->Point1.X + min; + Line->Point2.Y = Line->Point1.Y - min; + break; + + case 5: + Line->Point2.X = Line->Point1.X - min; + Line->Point2.Y = Line->Point1.Y - min; + break; + + case 7: + Line->Point2.X = Line->Point1.X - min; + Line->Point2.Y = Line->Point1.Y + min; + break; + } +} + +void pcb_line_adjust_attached_2lines(pcb_bool way) +{ + pcb_coord_t dx, dy; + pcb_attached_line_t *line = &pcb_crosshair.AttachedLine; + + if (pcb_crosshair.AttachedLine.State == PCB_CH_STATE_FIRST) + return; + + /* don't draw outline when ctrl key is pressed */ + if (pcb_gui->control_is_pressed()) { + line->draw = pcb_false; + return; + } + else + line->draw = pcb_true; + + if (conf_core.editor.all_direction_lines) { + line->Point2.X = pcb_crosshair.X; + line->Point2.Y = pcb_crosshair.Y; + return; + } + + /* swap the modes if shift is held down */ + if (pcb_gui->shift_is_pressed()) + way = !way; + + dx = pcb_crosshair.X - line->Point1.X; + dy = pcb_crosshair.Y - line->Point1.Y; + + if (!way) { + if (coord_abs(dx) > coord_abs(dy)) { + line->Point2.X = pcb_crosshair.X - SGN(dx) * coord_abs(dy); + line->Point2.Y = line->Point1.Y; + } + else { + line->Point2.X = line->Point1.X; + line->Point2.Y = pcb_crosshair.Y - SGN(dy) * coord_abs(dx); + } + } + else { + if (coord_abs(dx) > coord_abs(dy)) { + line->Point2.X = line->Point1.X + SGN(dx) * coord_abs(dy); + line->Point2.Y = pcb_crosshair.Y; + } + else { + line->Point2.X = pcb_crosshair.X; + line->Point2.Y = line->Point1.Y + SGN(dy) * coord_abs(dx); + } + } +} + +struct drc_info { + pcb_line_t *line; + pcb_bool solder; + jmp_buf env; +}; + +static pcb_r_dir_t drcPstk_callback(const pcb_box_t *b, void *cl) +{ + pcb_pstk_t *ps = (pcb_pstk_t *)b; + struct drc_info *i = (struct drc_info *)cl; + + if (!PCB_FLAG_TEST(PCB_FLAG_FOUND, ps) && pcb_isc_pstk_line(ps, i->line)) + longjmp(i->env, 1); + return PCB_R_DIR_FOUND_CONTINUE; +} + +static pcb_r_dir_t drcLine_callback(const pcb_box_t * b, void *cl) +{ + pcb_line_t *line = (pcb_line_t *) b; + struct drc_info *i = (struct drc_info *) cl; + + if (!PCB_FLAG_TEST(PCB_FLAG_FOUND, line) && pcb_isc_line_line(line, i->line)) + longjmp(i->env, 1); + return PCB_R_DIR_FOUND_CONTINUE; +} + +static pcb_r_dir_t drcArc_callback(const pcb_box_t * b, void *cl) +{ + pcb_arc_t *arc = (pcb_arc_t *) b; + struct drc_info *i = (struct drc_info *) cl; + + if (!PCB_FLAG_TEST(PCB_FLAG_FOUND, arc) && pcb_isc_line_arc(i->line, arc)) + longjmp(i->env, 1); + return PCB_R_DIR_FOUND_CONTINUE; +} + +double pcb_drc_lines(const pcb_point_t *start, pcb_point_t *end, pcb_point_t *mid_out, pcb_bool way, pcb_bool optimize) +{ + double f, s, f2, s2, len, best; + pcb_coord_t dx, dy, temp, last, length; + pcb_coord_t temp2, last2, length2; + pcb_line_t line1, line2; + pcb_layergrp_id_t group, comp; + struct drc_info info; + pcb_bool two_lines, x_is_long, blocker; + pcb_point_t ans; + + f = 1.0; + s = 0.5; + last = -1; + line1.type = line2.type = PCB_OBJ_LINE; + line1.Flags = line2.Flags = pcb_no_flags(); + line1.parent_type = line2.parent_type = PCB_PARENT_LAYER; + line1.parent.layer = line2.parent.layer = CURRENT; + line1.Thickness = conf_core.design.line_thickness + 2 * (conf_core.design.bloat + 1); + line2.Thickness = line1.Thickness; + line1.Clearance = line2.Clearance = 0; + line1.Point1.X = start->X; + line1.Point1.Y = start->Y; + dy = end->Y - line1.Point1.Y; + dx = end->X - line1.Point1.X; + + if (coord_abs(dx) > coord_abs(dy)) { + x_is_long = pcb_true; + length = coord_abs(dx); + } + else { + x_is_long = pcb_false; + length = coord_abs(dy); + } + + group = pcb_layer_get_group(PCB, INDEXOFCURRENT); + comp = PCB->LayerGroups.len + 10; /* this out-of-range group might save a call */ + + if (pcb_layergrp_flags(PCB, group) & PCB_LYT_BOTTOM) + info.solder = pcb_true; + else { + info.solder = pcb_false; + pcb_layer_list(PCB, PCB_LYT_TOP | PCB_LYT_SILK, &comp, 1); + } + temp = length; + + /* assume the worst */ + best = 0.0; + ans.X = line1.Point1.X; + ans.Y = line1.Point1.Y; + while (length != last) { + last = length; + if (x_is_long) { + dx = SGN(dx) * length; + dy = end->Y - line1.Point1.Y; + length2 = coord_abs(dy); + } + else { + dy = SGN(dy) * length; + dx = end->X - line1.Point1.X; + length2 = coord_abs(dx); + } + temp2 = length2; + f2 = 1.0; + s2 = 0.5; + last2 = -1; + blocker = pcb_true; + while (length2 != last2) { + if (x_is_long) + dy = SGN(dy) * length2; + else + dx = SGN(dx) * length2; + two_lines = pcb_true; + if (coord_abs(dx) > coord_abs(dy) && x_is_long) { + line1.Point2.X = line1.Point1.X + (way ? SGN(dx) * coord_abs(dy) : dx - SGN(dx) * coord_abs(dy)); + line1.Point2.Y = line1.Point1.Y + (way ? dy : 0); + } + else if (coord_abs(dy) >= coord_abs(dx) && !x_is_long) { + line1.Point2.X = line1.Point1.X + (way ? dx : 0); + line1.Point2.Y = line1.Point1.Y + (way ? SGN(dy) * coord_abs(dx) : dy - SGN(dy) * coord_abs(dx)); + } + else if (x_is_long) { + /* we've changed which axis is long, so only do one line */ + line1.Point2.X = line1.Point1.X + dx; + line1.Point2.Y = line1.Point1.Y + (way ? SGN(dy) * coord_abs(dx) : 0); + two_lines = pcb_false; + } + else { + /* we've changed which axis is long, so only do one line */ + line1.Point2.Y = line1.Point1.Y + dy; + line1.Point2.X = line1.Point1.X + (way ? SGN(dx) * coord_abs(dy) : 0); + two_lines = pcb_false; + } + line2.Point1.X = line1.Point2.X; + line2.Point1.Y = line1.Point2.Y; + if (!two_lines) { + line2.Point2.Y = line1.Point2.Y; + line2.Point2.X = line1.Point2.X; + } + else { + line2.Point2.X = line1.Point1.X + dx; + line2.Point2.Y = line1.Point1.Y + dy; + } + pcb_line_bbox(&line1); + pcb_line_bbox(&line2); + last2 = length2; + if (setjmp(info.env) == 0) { + info.line = &line1; + pcb_r_search(PCB->Data->padstack_tree, &line1.BoundingBox, NULL, drcPstk_callback, &info, NULL); + if (two_lines) { + info.line = &line2; + pcb_r_search(PCB->Data->padstack_tree, &line2.BoundingBox, NULL, drcPstk_callback, &info, NULL); + } + PCB_COPPER_GROUP_LOOP(PCB->Data, group); + { + info.line = &line1; + pcb_r_search(layer->line_tree, &line1.BoundingBox, NULL, drcLine_callback, &info, NULL); + pcb_r_search(layer->arc_tree, &line1.BoundingBox, NULL, drcArc_callback, &info, NULL); + if (two_lines) { + info.line = &line2; + pcb_r_search(layer->line_tree, &line2.BoundingBox, NULL, drcLine_callback, &info, NULL); + pcb_r_search(layer->arc_tree, &line2.BoundingBox, NULL, drcArc_callback, &info, NULL); + } + } + PCB_END_LOOP; + /* no intersector! */ + blocker = pcb_false; + f2 += s2; + len = (line2.Point2.X - line1.Point1.X); + len *= len; + len += (double) (line2.Point2.Y - line1.Point1.Y) * (line2.Point2.Y - line1.Point1.Y); + if (len > best) { + best = len; + ans.X = line2.Point2.X; + ans.Y = line2.Point2.Y; + } +#if 0 + if (f2 > 1.0) + f2 = 0.5; +#endif + } + else { + /* bumped into something, back off */ + f2 -= s2; + } + s2 *= 0.5; + length2 = MIN(f2 * temp2, temp2); + } + if (!blocker && ((x_is_long && line2.Point2.X - line1.Point1.X == dx) + || (!x_is_long && line2.Point2.Y - line1.Point1.Y == dy))) + f += s; + else + f -= s; + s *= 0.5; + length = MIN(f * temp, temp); + if (!optimize) { + if (blocker) + best = -1; + else + best = length; + break; + } + } + + end->X = ans.X; + end->Y = ans.Y; + if (mid_out != NULL) { + mid_out->X = line1.Point2.X; + mid_out->Y = line1.Point2.Y; + } + return best; +} + +static void drc_line(pcb_point_t *end) +{ + struct drc_info info; + pcb_layergrp_id_t group, comp; + pcb_line_t line; + pcb_attached_line_t aline; + static pcb_point_t last_good; /* internal state of last good endpoint - we can do this cheat, because... */ + + /* ... we hardwire the assumption on how a line is drawn: it starts out as a 0 long segment, which is valid: */ + if ((pcb_crosshair.AttachedLine.Point1.X == pcb_crosshair.X) && (pcb_crosshair.AttachedLine.Point1.Y == pcb_crosshair.Y)) { + line.Point1 = line.Point2 = pcb_crosshair.AttachedLine.Point1; + goto auto_good; + } + + memset(&line, 0, sizeof(line)); + + /* check where the line wants to end */ + aline.Point1.X = pcb_crosshair.AttachedLine.Point1.X; + aline.Point1.Y = pcb_crosshair.AttachedLine.Point1.Y; + pcb_line_45(&aline); + line.parent_type = PCB_PARENT_LAYER; + line.parent.layer = CURRENT; + line.type = PCB_OBJ_LINE; + line.Point1 = aline.Point1; + line.Point2 = aline.Point2; + + /* prepare for the intersection search */ + group = pcb_layer_get_group(PCB, INDEXOFCURRENT); + comp = PCB->LayerGroups.len + 10; /* this out-of-range group might save a call */ + if (pcb_layergrp_flags(PCB, group) & PCB_LYT_BOTTOM) + info.solder = pcb_true; + else { + info.solder = pcb_false; + pcb_layer_list(PCB, PCB_LYT_TOP | PCB_LYT_SILK, &comp, 1); + } + + /* search for intersection */ + pcb_line_bbox(&line); + if (setjmp(info.env) == 0) { + info.line = &line; + pcb_r_search(PCB->Data->padstack_tree, &line.BoundingBox, NULL, drcPstk_callback, &info, NULL); + PCB_COPPER_GROUP_LOOP(PCB->Data, group); + { + info.line = &line; + pcb_r_search(layer->line_tree, &line.BoundingBox, NULL, drcLine_callback, &info, NULL); + pcb_r_search(layer->arc_tree, &line.BoundingBox, NULL, drcArc_callback, &info, NULL); + } + PCB_END_LOOP; + /* no intersector! */ + auto_good:; + last_good.X = end->X = line.Point2.X; + last_good.Y = end->Y = line.Point2.Y; + return; + } + + /* bumped into ans */ + end->X = last_good.X; + end->Y = last_good.Y; +} + +void pcb_line_enforce_drc(void) +{ + pcb_point_t r45, rs, start; + pcb_bool shift; + double r1, r2; + + /* Silence a bogus compiler warning by storing this in a variable */ + pcb_layer_id_t layer_idx = INDEXOFCURRENT; + + if (pcb_gui->mod1_is_pressed() || pcb_gui->control_is_pressed() || PCB->RatDraw) + return; + + if (!(pcb_layer_flags(PCB, layer_idx) & PCB_LYT_COPPER)) + return; + + start.X = pcb_crosshair.AttachedLine.Point1.X; + start.Y = pcb_crosshair.AttachedLine.Point1.Y; + rs.X = r45.X = pcb_crosshair.X; + rs.Y = r45.Y = pcb_crosshair.Y; + + if (conf_core.editor.line_refraction != 0) { + /* first try starting straight */ + r1 = pcb_drc_lines(&start, &rs, NULL, pcb_false, pcb_true); + /* then try starting at 45 */ + r2 = pcb_drc_lines(&start, &r45, NULL, pcb_true, pcb_true); + } + else { + drc_line(&rs); + r45 = rs; +#define sqr(a) ((a) * (a)) + r1 = r2 = sqrt(sqr(rs.X - pcb_crosshair.AttachedLine.Point1.X) + sqr(rs.Y - pcb_crosshair.AttachedLine.Point1.Y)); +#undef sqr + } + /* shift forces the line lookahead path to refract the alternate way */ + shift = pcb_gui->shift_is_pressed(); + + if (PCB_XOR(r1 > r2, shift)) { + if (conf_core.editor.line_refraction != 0) { + if (shift) { + if (conf_core.editor.line_refraction !=2) + conf_setf(CFR_DESIGN, "editor/line_refraction", -1, "%d", 2); + } + else{ + if (conf_core.editor.line_refraction != 1) + conf_setf(CFR_DESIGN, "editor/line_refraction", -1, "%d", 1); + } + } + pcb_crosshair.X = rs.X; + pcb_crosshair.Y = rs.Y; + } + else { + if (conf_core.editor.line_refraction !=0) { + if (shift) { + if (conf_core.editor.line_refraction != 1) + conf_setf(CFR_DESIGN, "editor/line_refraction", -1, "%d", 1); + } + else { + if (conf_core.editor.line_refraction != 2) + conf_setf(CFR_DESIGN, "editor/line_refraction", -1, "%d", 2); + } + } + pcb_crosshair.X = r45.X; + pcb_crosshair.Y = r45.Y; + } +} Index: tags/2.1.2/src/obj_line_list.c =================================================================== --- tags/2.1.2/src/obj_line_list.c (nonexistent) +++ tags/2.1.2/src/obj_line_list.c (revision 24813) @@ -0,0 +1,29 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2016 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#define TDL_DONT_UNDEF +#include "obj_line_list.h" +#include Index: tags/2.1.2/src/obj_line_list.h =================================================================== --- tags/2.1.2/src/obj_line_list.h (nonexistent) +++ tags/2.1.2/src/obj_line_list.h (revision 24813) @@ -0,0 +1,47 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2016 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#ifndef PCB_OBJ_LINE_LIST_H +#define PCB_OBJ_LINE_LIST_H + +#include "obj_line.h" + +/* List of Lines */ +#define TDL(x) linelist_ ## x +#define TDL_LIST_T linelist_t +#define TDL_ITEM_T pcb_line_t +#define TDL_FIELD link +#define TDL_SIZE_T size_t +#define TDL_FUNC + +#define linelist_foreach(list, iterator, loop_elem) \ + gdl_foreach_((&((list)->lst)), (iterator), (loop_elem)) + + +#include +#include + +#endif Index: tags/2.1.2/src/obj_line_op.h =================================================================== --- tags/2.1.2/src/obj_line_op.h (nonexistent) +++ tags/2.1.2/src/obj_line_op.h (revision 24813) @@ -0,0 +1,59 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +/*** Standard operations on line segments ***/ + +#include "operation.h" + +void *pcb_lineop_add_to_buffer(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_line_t *Line); +void *pcb_lineop_change_size(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_line_t *Line); +void *pcb_lineop_change_clear_size(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_line_t *Line); +void *pcb_lineop_change_join(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_line_t *Line); +void *pcb_lineop_set_join(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_line_t *Line); +void *pcb_lineop_clear_join(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_line_t *Line); +void *pcb_lineop_insert_point(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_line_t *Line); +void *pcb_lineop_move_buffer(pcb_opctx_t *ctx, pcb_layer_t * layer, pcb_line_t * line); +void *pcb_lineop_copy(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_line_t *Line); +void *pcb_lineop_move(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_line_t *Line); +void *pcb_lineop_move_noclip(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_line_t *Line); +void *pcb_lineop_clip(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_line_t *Line); +void *pcb_lineop_move_point(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_line_t *Line, pcb_point_t *Point); +void *pcb_lineop_move_point_with_route(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_line_t *Line, pcb_point_t *Point); +void *pcb_lineop_move_to_layer_low(pcb_opctx_t *ctx, pcb_layer_t * Source, pcb_line_t * line, pcb_layer_t * Destination); +void *pcb_lineop_move_to_layer(pcb_opctx_t *ctx, pcb_layer_t * Layer, pcb_line_t * Line); +void *pcb_lineop_destroy(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_line_t *Line); +void *pcb_lineop_remove_point(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_line_t *Line, pcb_point_t *Point); +void *pcb_lineop_remove(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_line_t *Line); +void *pcb_lineop_rotate90_point(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_line_t *Line, pcb_point_t *Point); +void *pcb_lineop_rotate90(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_line_t *Line); +void *pcb_lineop_rotate(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_line_t *Line); +void *pcb_lineop_change_flag(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_line_t *Line); +void *pcb_lineop_invalidate_label(pcb_opctx_t *ctx, pcb_layer_t *layer, pcb_line_t *line); + + + Index: tags/2.1.2/src/obj_pinvia_therm.c =================================================================== --- tags/2.1.2/src/obj_pinvia_therm.c (nonexistent) +++ tags/2.1.2/src/obj_pinvia_therm.c (revision 24813) @@ -0,0 +1,156 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996,2004,2006 Thomas Nau + * + * this file, thermal.c was written by and is + * (C) Copyright 2006, harry eaton + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +/* negative thermal finger polygons */ + +#include "config.h" + +#include +#include + +#include "board.h" +#include "polygon.h" +#include "obj_pinvia_therm.h" + +static pcb_polyarea_t *pcb_pa_diag_line(pcb_coord_t X, pcb_coord_t Y, pcb_coord_t l, pcb_coord_t w, pcb_bool rt) +{ + pcb_pline_t *c; + pcb_vector_t v; + pcb_coord_t x1, x2, y1, y2; + + if (rt) { + x1 = (l - w) * M_SQRT1_2; + x2 = (l + w) * M_SQRT1_2; + y1 = x1; + y2 = x2; + } + else { + x2 = -(l - w) * M_SQRT1_2; + x1 = -(l + w) * M_SQRT1_2; + y1 = -x1; + y2 = -x2; + } + + v[0] = X + x1; + v[1] = Y + y2; + if ((c = pcb_poly_contour_new(v)) == NULL) + return NULL; + v[0] = X - x2; + v[1] = Y - y1; + pcb_poly_vertex_include(c->head.prev, pcb_poly_node_create(v)); + v[0] = X - x1; + v[1] = Y - y2; + pcb_poly_vertex_include(c->head.prev, pcb_poly_node_create(v)); + v[0] = X + x2; + v[1] = Y + y1; + pcb_poly_vertex_include(c->head.prev, pcb_poly_node_create(v)); + return pcb_poly_from_contour(c); +} + +/* ThermPoly returns a pcb_polyarea_t having all of the clearance that when + * subtracted from the plane create the desired thermal fingers. + * Usually this is 4 disjoint regions. + * + */ +pcb_polyarea_t *ThermPoly_(pcb_board_t *pcb, pcb_coord_t cx, pcb_coord_t cy, pcb_coord_t thickness, pcb_coord_t clearance, pcb_cardinal_t style) +{ + pcb_arc_t a; + pcb_polyarea_t *pa, *arc; + + /* must be circular */ + switch (style) { + case 1: + case 2: + { + pcb_polyarea_t *m; + pcb_coord_t t = (thickness + clearance) / 2; + pcb_coord_t w = 0.5 * pcb->ThermScale * clearance; + pa = pcb_poly_from_circle(cx, cy, t); + arc = pcb_poly_from_circle(cx, cy, thickness / 2); + /* create a thin ring */ + pcb_polyarea_boolean_free(pa, arc, &m, PCB_PBO_SUB); + /* fix me needs error checking */ + if (style == 2) { + /* t is the theoretically required length, but we use twice that + * to avoid discretisation errors in our circle approximation. + */ + pa = pcb_poly_from_rect(cx - t * 2, cx + t * 2, cy - w, cy + w); + pcb_polyarea_boolean_free(m, pa, &arc, PCB_PBO_SUB); + pa = pcb_poly_from_rect(cx - w, cx + w, cy - t * 2, cy + t * 2); + } + else { + /* t is the theoretically required length, but we use twice that + * to avoid discretisation errors in our circle approximation. + */ + pa = pcb_pa_diag_line(cx, cy, t * 2, w, pcb_true); + pcb_polyarea_boolean_free(m, pa, &arc, PCB_PBO_SUB); + pa = pcb_pa_diag_line(cx, cy, t * 2, w, pcb_false); + } + pcb_polyarea_boolean_free(arc, pa, &m, PCB_PBO_SUB); + return m; + } + + default: + a.X = cx; + a.Y = cy; + a.Height = a.Width = thickness / 2 + clearance / 4; + a.Thickness = 1; + a.Clearance = clearance / 2; + a.Flags = pcb_no_flags(); + a.Delta = 90 - (a.Clearance * (1. + 2. * pcb->ThermScale) * 180) / (M_PI * a.Width); + a.StartAngle = 90 - a.Delta / 2 + (style == 4 ? 0 : 45); + pa = pcb_poly_from_arc(&a, a.Clearance); + if (!pa) + return NULL; + a.StartAngle += 90; + arc = pcb_poly_from_arc(&a, a.Clearance); + if (!arc) + return NULL; + pa->f = arc; + arc->b = pa; + a.StartAngle += 90; + arc = pcb_poly_from_arc(&a, a.Clearance); + if (!arc) + return NULL; + pa->f->f = arc; + arc->b = pa->f; + a.StartAngle += 90; + arc = pcb_poly_from_arc(&a, a.Clearance); + if (!arc) + return NULL; + pa->b = arc; + pa->f->f->f = arc; + arc->b = pa->f->f; + arc->f = pa; + pa->b = arc; + return pa; + } +} Index: tags/2.1.2/src/obj_pinvia_therm.h =================================================================== --- tags/2.1.2/src/obj_pinvia_therm.h (nonexistent) +++ tags/2.1.2/src/obj_pinvia_therm.h (revision 24813) @@ -0,0 +1,39 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996,2006 Thomas Nau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +/* Thermal on padstacks are modified forms of the clearance cutout so that + the padstack has galvanic connection to the sorrunding polygon. */ +#ifndef PCB_PINVIA_THERMAL_H +#define PCB_PINVIA_THERMAL_H + +#include +#include "config.h" + +pcb_polyarea_t *ThermPoly_(pcb_board_t *p, pcb_coord_t cx, pcb_coord_t cy, pcb_coord_t thickness, pcb_coord_t clearance, pcb_cardinal_t style); + +#endif Index: tags/2.1.2/src/obj_poly.c =================================================================== --- tags/2.1.2/src/obj_poly.c (nonexistent) +++ tags/2.1.2/src/obj_poly.c (revision 24813) @@ -0,0 +1,1329 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +/* Drawing primitive: polygons */ + + +#include "config.h" + +#include "board.h" +#include "data.h" +#include "undo.h" +#include "polygon.h" +#include "polygon_offs.h" +#include "rotate.h" +#include "search.h" +#include "hid_inlines.h" + +#include "conf_core.h" + +#include "obj_poly.h" +#include "obj_poly_op.h" +#include "obj_poly_list.h" +#include "obj_poly_draw.h" + +#include "obj_subc_parent.h" +#include "obj_hash.h" + +/* TODO: get rid of these: */ +#include "draw.h" + +#define STEP_POLYGONPOINT 10 +#define STEP_POLYGONHOLEINDEX 10 + +/*** allocation ***/ + +void pcb_poly_reg(pcb_layer_t *layer, pcb_poly_t *poly) +{ + polylist_append(&layer->Polygon, poly); + PCB_SET_PARENT(poly, layer, layer); + + if (layer->parent_type == PCB_PARENT_UI) + return; + + assert(layer->parent_type == PCB_PARENT_DATA); + pcb_obj_id_reg(layer->parent.data, poly); +} + +void pcb_poly_unreg(pcb_poly_t *poly) +{ + pcb_layer_t *layer = poly->parent.layer; + assert(poly->parent_type == PCB_PARENT_LAYER); + polylist_remove(poly); + if (layer->parent_type != PCB_PARENT_UI) { + assert(layer->parent_type == PCB_PARENT_DATA); + pcb_obj_id_del(layer->parent.data, poly); + } + PCB_SET_PARENT(poly, layer, NULL); +} + +pcb_poly_t *pcb_poly_alloc_id(pcb_layer_t *layer, long int id) +{ + pcb_poly_t *new_obj; + + new_obj = calloc(sizeof(pcb_poly_t), 1); + new_obj->ID = id; + new_obj->type = PCB_OBJ_POLY; + new_obj->Attributes.post_change = pcb_obj_attrib_post_change; + + pcb_poly_reg(layer, new_obj); + + return new_obj; +} + +pcb_poly_t *pcb_poly_alloc(pcb_layer_t *layer) +{ + return pcb_poly_alloc_id(layer, pcb_create_ID_get()); +} + + +void pcb_poly_free(pcb_poly_t *poly) +{ + pcb_poly_unreg(poly); + free(poly); +} + +/* gets the next slot for a point in a polygon struct, allocates memory if necessary */ +pcb_point_t *pcb_poly_point_alloc(pcb_poly_t *Polygon) +{ + pcb_point_t *points = Polygon->Points; + + /* realloc new memory if necessary and clear it */ + if (Polygon->PointN >= Polygon->PointMax) { + Polygon->PointMax += STEP_POLYGONPOINT; + points = (pcb_point_t *) realloc(points, Polygon->PointMax * sizeof(pcb_point_t)); + Polygon->Points = points; + memset(points + Polygon->PointN, 0, STEP_POLYGONPOINT * sizeof(pcb_point_t)); + } + return (points + Polygon->PointN++); +} + +/* gets the next slot for a point in a polygon struct, allocates memory if necessary */ +pcb_cardinal_t *pcb_poly_holeidx_new(pcb_poly_t *Polygon) +{ + pcb_cardinal_t *holeindex = Polygon->HoleIndex; + + /* realloc new memory if necessary and clear it */ + if (Polygon->HoleIndexN >= Polygon->HoleIndexMax) { + Polygon->HoleIndexMax += STEP_POLYGONHOLEINDEX; + holeindex = (pcb_cardinal_t *) realloc(holeindex, Polygon->HoleIndexMax * sizeof(int)); + Polygon->HoleIndex = holeindex; + memset(holeindex + Polygon->HoleIndexN, 0, STEP_POLYGONHOLEINDEX * sizeof(int)); + } + return (holeindex + Polygon->HoleIndexN++); +} + +/* frees memory used by a polygon */ +void pcb_poly_free_fields(pcb_poly_t * polygon) +{ + pcb_parent_t parent; + pcb_parenttype_t parent_type; + + if (polygon == NULL) + return; + + free(polygon->Points); + free(polygon->HoleIndex); + + if (polygon->Clipped) + pcb_polyarea_free(&polygon->Clipped); + pcb_poly_contours_free(&polygon->NoHoles); + + /* have to preserve parent info for unreg */ + parent = polygon->parent; + parent_type = polygon->parent_type; + reset_obj_mem(pcb_poly_t, polygon); + polygon->parent = parent; + polygon->parent_type = parent_type; +} + +/*** utility ***/ + +/* rotates a polygon in 90 degree steps */ +void pcb_poly_rotate90(pcb_poly_t *Polygon, pcb_coord_t X, pcb_coord_t Y, unsigned Number) +{ + pcb_layer_t *layer = Polygon->parent.layer; + assert(Polygon->parent_type = PCB_PARENT_LAYER); + PCB_POLY_POINT_LOOP(Polygon); + { + PCB_COORD_ROTATE90(point->X, point->Y, X, Y, Number); + } + PCB_END_LOOP; + + if (layer->parent_type == PCB_PARENT_DATA) + pcb_poly_init_clip(layer->parent.data, layer, Polygon); + /* simply rotating the bounding box here won't work, because the box is 'closed' (increased by 1) */ + pcb_poly_bbox(Polygon); +} + +void pcb_poly_rotate(pcb_layer_t *layer, pcb_poly_t *polygon, pcb_coord_t X, pcb_coord_t Y, double cosa, double sina) +{ + if (layer->polygon_tree != NULL) + pcb_r_delete_entry(layer->polygon_tree, (pcb_box_t *) polygon); + PCB_POLY_POINT_LOOP(polygon); + { + pcb_rotate(&point->X, &point->Y, X, Y, cosa, sina); + } + PCB_END_LOOP; + if (layer->parent_type == PCB_PARENT_DATA) + pcb_poly_init_clip(layer->parent.data, layer, polygon); + pcb_poly_bbox(polygon); + if (layer->polygon_tree != NULL) + pcb_r_insert_entry(layer->polygon_tree, (pcb_box_t *) polygon); +} + +void pcb_poly_mirror(pcb_layer_t *layer, pcb_poly_t *polygon, pcb_coord_t y_offs) +{ + if (layer->polygon_tree != NULL) + pcb_r_delete_entry(layer->polygon_tree, (pcb_box_t *)polygon); + PCB_POLY_POINT_LOOP(polygon); + { + point->X = PCB_SWAP_X(point->X); + point->Y = PCB_SWAP_Y(point->Y) + y_offs; + } + PCB_END_LOOP; + if (layer->parent_type == PCB_PARENT_DATA) + pcb_poly_init_clip(layer->parent.data, layer, polygon); + pcb_poly_bbox(polygon); + if (layer->polygon_tree != NULL) + pcb_r_insert_entry(layer->polygon_tree, (pcb_box_t *)polygon); +} + +void pcb_poly_flip_side(pcb_layer_t *layer, pcb_poly_t *polygon) +{ + pcb_r_delete_entry(layer->polygon_tree, (pcb_box_t *) polygon); + PCB_POLY_POINT_LOOP(polygon); + { + point->X = PCB_SWAP_X(point->X); + point->Y = PCB_SWAP_Y(point->Y); + } + PCB_END_LOOP; + if (layer->parent_type == PCB_PARENT_DATA) + pcb_poly_init_clip(layer->parent.data, layer, polygon); + pcb_poly_bbox(polygon); + pcb_r_insert_entry(layer->polygon_tree, (pcb_box_t *) polygon); + /* hmmm, how to handle clip */ +} + +void pcb_poly_scale(pcb_poly_t *poly, double sx, double sy) +{ + int onbrd = (poly->parent.layer != NULL) && (!poly->parent.layer->is_bound); + + if (onbrd) + pcb_poly_pre(poly); + PCB_POLY_POINT_LOOP(poly); + { + point->X = pcb_round((double)point->X * sx); + point->Y = pcb_round((double)point->Y * sy); + } + PCB_END_LOOP; + pcb_poly_bbox(poly); + if (onbrd) + pcb_poly_post(poly); +} + + +/* sets the bounding box of a polygons */ +void pcb_poly_bbox(pcb_poly_t *Polygon) +{ + Polygon->bbox_naked.X1 = Polygon->bbox_naked.Y1 = PCB_MAX_COORD; + Polygon->bbox_naked.X2 = Polygon->bbox_naked.Y2 = -PCB_MAX_COORD; + + PCB_POLY_POINT_LOOP(Polygon); + { + PCB_MAKE_MIN(Polygon->bbox_naked.X1, point->X); + PCB_MAKE_MIN(Polygon->bbox_naked.Y1, point->Y); + PCB_MAKE_MAX(Polygon->bbox_naked.X2, point->X); + PCB_MAKE_MAX(Polygon->bbox_naked.Y2, point->Y); + } + PCB_END_LOOP; + + /* clearance is generally considered to be part of the bbox for all objects */ + { + pcb_coord_t clr = PCB_POLY_HAS_CLEARANCE(Polygon) ? Polygon->Clearance/2 : 0; + Polygon->BoundingBox.X1 = Polygon->bbox_naked.X1 - clr; + Polygon->BoundingBox.Y1 = Polygon->bbox_naked.Y1 - clr; + Polygon->BoundingBox.X2 = Polygon->bbox_naked.X2 + clr; + Polygon->BoundingBox.Y2 = Polygon->bbox_naked.Y2 + clr; + } + + /* boxes don't include the lower right corner */ + pcb_close_box(&Polygon->bbox_naked); + pcb_close_box(&Polygon->BoundingBox); +} + +int pcb_poly_eq(const pcb_host_trans_t *tr1, const pcb_poly_t *p1, const pcb_host_trans_t *tr2, const pcb_poly_t *p2) +{ + if (p1->PointN != p2->PointN) return 0; + if (pcb_field_neq(p1, p2, Clearance)) return 0; + if (pcb_neqs(p1->term, p2->term)) return 0; + + if (!PCB_FLAG_TEST(PCB_FLAG_FLOATER, p1) && !PCB_FLAG_TEST(PCB_FLAG_FLOATER, p2)) { + pcb_cardinal_t n; + for(n = 0; n < p1->PointN; n++) { + pcb_coord_t x1, y1, x2, y2; + pcb_hash_tr_coords(tr1, &x1, &y1, p1->Points[n].X, p1->Points[n].Y); + pcb_hash_tr_coords(tr2, &x2, &y2, p2->Points[n].X, p2->Points[n].Y); + if ((x1 != x2) || (y1 != y2)) return 0; + } + } + return 1; +} + +unsigned int pcb_poly_hash(const pcb_host_trans_t *tr, const pcb_poly_t *p) +{ + unsigned int crd = 0; + pcb_cardinal_t n; + + if (!PCB_FLAG_TEST(PCB_FLAG_FLOATER, p)) + for(n = 0; n < p->PointN; n++) { + pcb_coord_t x, y; + + pcb_hash_tr_coords(tr, &x, &y, p->Points[n].X, p->Points[n].Y); + crd ^= pcb_hash_coord(x) ^ pcb_hash_coord(y); + } + + return pcb_hash_coord(p->Clearance) ^ pcb_hash_str(p->term) ^ crd; +} + + +/* creates a new polygon from the old formats rectangle data */ +pcb_poly_t *pcb_poly_new_from_rectangle(pcb_layer_t *Layer, pcb_coord_t X1, pcb_coord_t Y1, pcb_coord_t X2, pcb_coord_t Y2, pcb_coord_t Clearance, pcb_flag_t Flags) +{ + pcb_poly_t *polygon = pcb_poly_new(Layer, Clearance, Flags); + if (!polygon) + return polygon; + + pcb_poly_point_new(polygon, X1, Y1); + pcb_poly_point_new(polygon, X2, Y1); + pcb_poly_point_new(polygon, X2, Y2); + pcb_poly_point_new(polygon, X1, Y2); + + pcb_add_poly_on_layer(Layer, polygon); + return polygon; +} + +pcb_poly_t *pcb_poly_new_from_poly(pcb_layer_t *Layer, pcb_poly_t *src, pcb_coord_t offs, pcb_coord_t Clearance, pcb_flag_t Flags) +{ + pcb_coord_t x, y; + pcb_poly_it_t it; + pcb_pline_t *pl; + int go; + pcb_poly_t *polygon = pcb_poly_new(Layer, Clearance, Flags); + + if (!polygon) + return polygon; + + it.pa = src->Clipped; + pcb_poly_island_first(src, &it); + pl = pcb_poly_contour(&it); + it.cntr = pcb_pline_dup_offset(pl, offs); + for(go = pcb_poly_vect_first(&it, &x, &y); go; go = pcb_poly_vect_next(&it, &x, &y)) + pcb_poly_point_new(polygon, x, y); + + pcb_poly_contours_free(&it.cntr); + + pcb_add_poly_on_layer(Layer, polygon); + return polygon; +} + + + +void pcb_add_poly_on_layer(pcb_layer_t *Layer, pcb_poly_t *polygon) +{ + pcb_poly_bbox(polygon); + if (!Layer->polygon_tree) + Layer->polygon_tree = pcb_r_create_tree(); + pcb_r_insert_entry(Layer->polygon_tree, (pcb_box_t *) polygon); + PCB_SET_PARENT(polygon, layer, Layer); + pcb_poly_clear_from_poly(Layer->parent.data, PCB_OBJ_POLY, Layer, polygon); +} + +/* creates a new polygon on a layer */ +pcb_poly_t *pcb_poly_new(pcb_layer_t *Layer, pcb_coord_t Clearance, pcb_flag_t Flags) +{ + pcb_poly_t *polygon = pcb_poly_alloc(Layer); + + /* copy values */ + polygon->Flags = Flags; + + polygon->Clearance = Clearance; + polygon->Clipped = NULL; + polygon->NoHoles = NULL; + polygon->NoHolesValid = 0; + return polygon; +} + +static pcb_poly_t *pcb_poly_copy_meta(pcb_poly_t *dst, pcb_poly_t *src) +{ + if (dst == NULL) + return NULL; + pcb_attribute_copy_all(&dst->Attributes, &src->Attributes); + return dst; +} + +pcb_poly_t *pcb_poly_dup(pcb_layer_t *dst, pcb_poly_t *src) +{ + pcb_board_t *pcb; + pcb_poly_t *p = pcb_poly_new(dst, src->Clearance, src->Flags); + pcb_poly_copy(p, src, 0, 0); + pcb_add_poly_on_layer(dst, p); + pcb_poly_copy_meta(p, src); + + pcb = pcb_data_get_top(dst->parent.data); + if (pcb != NULL) + pcb_poly_init_clip(pcb->Data, dst, p); + return p; +} + +pcb_poly_t *pcb_poly_dup_at(pcb_layer_t *dst, pcb_poly_t *src, pcb_coord_t dx, pcb_coord_t dy) +{ + pcb_board_t *pcb; + pcb_poly_t *p = pcb_poly_new(dst, src->Clearance, src->Flags); + pcb_poly_copy(p, src, dx, dy); + pcb_add_poly_on_layer(dst, p); + pcb_poly_copy_meta(p, src); + + pcb = pcb_data_get_top(dst->parent.data); + if (pcb != NULL) + pcb_poly_init_clip(pcb->Data, dst, p); + return p; +} + +/* creates a new point in a polygon */ +pcb_point_t *pcb_poly_point_new(pcb_poly_t *Polygon, pcb_coord_t X, pcb_coord_t Y) +{ + pcb_point_t *point = pcb_poly_point_alloc(Polygon); + + /* copy values */ + point->X = X; + point->Y = Y; +TODO("ID: register points too") + point->ID = pcb_create_ID_get(); + return point; +} + +/* creates a new hole in a polygon */ +pcb_poly_t *pcb_poly_hole_new(pcb_poly_t * Polygon) +{ + pcb_cardinal_t *holeindex = pcb_poly_holeidx_new(Polygon); + *holeindex = Polygon->PointN; + return Polygon; +} + +/* copies data from one polygon to another; 'Dest' has to exist */ +pcb_poly_t *pcb_poly_copy(pcb_poly_t *Dest, pcb_poly_t *Src, pcb_coord_t dx, pcb_coord_t dy) +{ + pcb_cardinal_t hole = 0; + pcb_cardinal_t n; + + for (n = 0; n < Src->PointN; n++) { + if (hole < Src->HoleIndexN && n == Src->HoleIndex[hole]) { + pcb_poly_hole_new(Dest); + hole++; + } + pcb_poly_point_new(Dest, Src->Points[n].X+dx, Src->Points[n].Y+dy); + } + pcb_poly_bbox(Dest); + Dest->Flags = Src->Flags; + PCB_FLAG_CLEAR(PCB_FLAG_FOUND, Dest); + return Dest; +} + +static double poly_area(pcb_point_t *points, pcb_cardinal_t n_points) +{ + double area = 0; + int n; + + for(n = 1; n < n_points; n++) + area += (double)(points[n-1].X - points[n].X) * (double)(points[n-1].Y + points[n].Y); + area +=(double)(points[n_points-1].X - points[0].X) * (double)(points[n_points-1].Y + points[0].Y); + + if (area > 0) + area /= 2.0; + else + area /= -2.0; + + return area; +} + +double pcb_poly_area(const pcb_poly_t *poly) +{ + double area; + + if (poly->HoleIndexN > 0) { + int h; + area = poly_area(poly->Points, poly->HoleIndex[0]); + for(h = 0; h < poly->HoleIndexN - 1; h++) + area -= poly_area(poly->Points + poly->HoleIndex[h], poly->HoleIndex[h+1] - poly->HoleIndex[h]); + area -= poly_area(poly->Points + poly->HoleIndex[h], poly->PointN - poly->HoleIndex[h]); + } + else + area = poly_area(poly->Points, poly->PointN); + + return area; +} + + + +/*** ops ***/ + +/* copies a polygon to buffer */ +void *pcb_polyop_add_to_buffer(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_poly_t *Polygon) +{ + pcb_layer_t *layer = &ctx->buffer.dst->Layer[pcb_layer_id(ctx->buffer.src, Layer)]; + pcb_poly_t *polygon; + + polygon = pcb_poly_new(layer, Polygon->Clearance, Polygon->Flags); + pcb_poly_copy(polygon, Polygon, 0, 0); + pcb_poly_copy_meta(polygon, Polygon); + + /* Update the polygon r-tree. Unlike similarly named functions for + * other objects, CreateNewPolygon does not do this as it creates a + * skeleton polygon object, which won't have correct bounds. + */ + if (!layer->polygon_tree) + layer->polygon_tree = pcb_r_create_tree(); + pcb_r_insert_entry(layer->polygon_tree, (pcb_box_t *) polygon); + + PCB_FLAG_CLEAR(PCB_FLAG_FOUND | ctx->buffer.extraflg, polygon); + return polygon; +} + + +/* moves a polygon between board and buffer. Doesn't allocate memory for the points */ +void *pcb_polyop_move_buffer(pcb_opctx_t *ctx, pcb_layer_t *dstly, pcb_poly_t *polygon) +{ + pcb_layer_t *srcly = polygon->parent.layer; + + assert(polygon->parent_type == PCB_PARENT_LAYER); + if ((dstly == NULL) || (dstly == srcly)) /* auto layer in dst */ + dstly = &ctx->buffer.dst->Layer[pcb_layer_id(ctx->buffer.src, srcly)]; + + pcb_poly_pprestore(polygon); + + pcb_r_delete_entry(srcly->polygon_tree, (pcb_box_t *)polygon); + + pcb_poly_unreg(polygon); + pcb_poly_reg(dstly, polygon); + + PCB_FLAG_CLEAR(PCB_FLAG_FOUND, polygon); + + if (!dstly->polygon_tree) + dstly->polygon_tree = pcb_r_create_tree(); + pcb_r_insert_entry(dstly->polygon_tree, (pcb_box_t *)polygon); + + pcb_poly_ppclear(polygon); + return polygon; +} + +/* Handle attempts to change the clearance of a polygon. */ +void *pcb_polyop_change_clear_size(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_poly_t *poly) +{ + if (PCB_FLAG_TEST(PCB_FLAG_CLEARPOLYPOLY, poly)) { + pcb_coord_t value = (ctx->chgsize.is_absolute) ? ctx->chgsize.value : poly->Clearance + ctx->chgsize.value; + + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, poly)) + return NULL; + + value = MIN(PCB_MAX_LINESIZE, value); + if (!ctx->chgsize.is_absolute && ctx->chgsize.value < 0 && value < conf_core.design.bloat * 2) + value = 0; + if (ctx->chgsize.value > 0 && value < conf_core.design.bloat * 2) + value = conf_core.design.bloat * 2 + 2; + if (value != poly->Clearance) { + pcb_undo_add_obj_to_clear_size(PCB_OBJ_POLY, Layer, poly, poly); + pcb_poly_restore_to_poly(ctx->chgsize.pcb->Data, PCB_OBJ_POLY, Layer, poly); + pcb_poly_invalidate_erase(poly); + pcb_r_delete_entry(Layer->polygon_tree, (pcb_box_t *)poly); + poly->Clearance = value; + pcb_poly_bbox(poly); + pcb_r_insert_entry(Layer->polygon_tree, (pcb_box_t *)poly); + pcb_poly_clear_from_poly(ctx->chgsize.pcb->Data, PCB_OBJ_POLY, Layer, poly); + pcb_poly_invalidate_draw(Layer, poly); + return poly; + } + + return poly; + } + + /* poly does not clear other polys */ + pcb_message(PCB_MSG_WARNING, + "To change the clearance of objects in a polygon, change \nthe objects, not the polygon.\n" + "Alternatively, set the clearpolypoly flag on the polygon to \nallow it to clear other polygons.\n" + "Hint: To set a minimum clearance for a group of objects, \nselect them all then :MinClearGap(Selected,=10,mil)\n", + "Ok", NULL); + + return NULL; +} + +/* changes the CLEARPOLY flag of a polygon */ +void *pcb_polyop_change_clear(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_poly_t *Polygon) +{ + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, Polygon)) + return NULL; + pcb_undo_add_obj_to_clear_poly(PCB_OBJ_POLY, Layer, Polygon, Polygon, pcb_true); + pcb_undo_add_obj_to_flag(Polygon); + PCB_FLAG_TOGGLE(PCB_FLAG_CLEARPOLY, Polygon); + pcb_poly_init_clip(PCB->Data, Layer, Polygon); + pcb_poly_invalidate_draw(Layer, Polygon); + return Polygon; +} + +/* inserts a point into a polygon */ +void *pcb_polyop_insert_point(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_poly_t *Polygon) +{ + pcb_point_t save; + pcb_cardinal_t n; + pcb_line_t line; + + pcb_poly_pprestore(Polygon); + + if (!ctx->insert.forcible) { + /* + * first make sure adding the point is sensible + */ + line.Thickness = 0; + line.Point1 = Polygon->Points[pcb_poly_contour_prev_point(Polygon, ctx->insert.idx)]; + line.Point2 = Polygon->Points[ctx->insert.idx]; + if (pcb_is_point_on_line((float) ctx->insert.x, (float) ctx->insert.y, 0.0, &line)) + return NULL; + } + /* + * second, shift the points up to make room for the new point + */ + pcb_poly_invalidate_erase(Polygon); + pcb_r_delete_entry(Layer->polygon_tree, (pcb_box_t *) Polygon); + save = *pcb_poly_point_new(Polygon, ctx->insert.x, ctx->insert.y); + for (n = Polygon->PointN - 1; n > ctx->insert.idx; n--) + Polygon->Points[n] = Polygon->Points[n - 1]; + + /* Shift up indices of any holes */ + for (n = 0; n < Polygon->HoleIndexN; n++) + if (Polygon->HoleIndex[n] > ctx->insert.idx || (ctx->insert.last && Polygon->HoleIndex[n] == ctx->insert.idx)) + Polygon->HoleIndex[n]++; + + Polygon->Points[ctx->insert.idx] = save; + pcb_board_set_changed_flag(pcb_true); + pcb_undo_add_obj_to_insert_point(PCB_OBJ_POLY_POINT, Layer, Polygon, &Polygon->Points[ctx->insert.idx]); + + pcb_poly_bbox(Polygon); + pcb_r_insert_entry(Layer->polygon_tree, (pcb_box_t *) Polygon); + pcb_poly_init_clip(PCB->Data, Layer, Polygon); + if (ctx->insert.forcible || !pcb_poly_remove_excess_points(Layer, Polygon)) + pcb_poly_invalidate_draw(Layer, Polygon); + + pcb_poly_ppclear(Polygon); + + return (&Polygon->Points[ctx->insert.idx]); +} + +/* changes the clearance flag of a polygon */ +void *pcb_polyop_change_join(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_poly_t *poly) +{ + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, poly)) + return NULL; + pcb_poly_invalidate_erase(poly); + if (PCB_FLAG_TEST(PCB_FLAG_CLEARPOLYPOLY, poly)) { + pcb_undo_add_obj_to_clear_poly(PCB_OBJ_POLY, Layer, poly, poly, pcb_false); + pcb_poly_restore_to_poly(PCB->Data, PCB_OBJ_POLY, Layer, poly); + } + pcb_undo_add_obj_to_flag(poly); + PCB_FLAG_TOGGLE(PCB_FLAG_CLEARPOLYPOLY, poly); + if (PCB_FLAG_TEST(PCB_FLAG_CLEARPOLYPOLY, poly)) { + pcb_undo_add_obj_to_clear_poly(PCB_OBJ_POLY, Layer, poly, poly, pcb_true); + pcb_poly_clear_from_poly(PCB->Data, PCB_OBJ_POLY, Layer, poly); + } + pcb_poly_invalidate_draw(Layer, poly); + return poly; +} + +/* low level routine to move a polygon */ +void pcb_poly_move(pcb_poly_t *Polygon, pcb_coord_t DX, pcb_coord_t DY) +{ + PCB_POLY_POINT_LOOP(Polygon); + { + PCB_MOVE_POINT(point->X, point->Y, DX, DY); + } + PCB_END_LOOP; + PCB_BOX_MOVE_LOWLEVEL(&Polygon->BoundingBox, DX, DY); + PCB_BOX_MOVE_LOWLEVEL(&Polygon->bbox_naked, DX, DY); +} + +/* moves a polygon */ +void *pcb_polyop_move_noclip(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_poly_t *Polygon) +{ + if (Layer->meta.real.vis) { + pcb_poly_invalidate_erase(Polygon); + } + pcb_poly_move(Polygon, ctx->move.dx, ctx->move.dy); + pcb_poly_init_clip(PCB->Data, Layer, Polygon); + if (Layer->meta.real.vis) + pcb_poly_invalidate_draw(Layer, Polygon); + return Polygon; +} + +void *pcb_polyop_move(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_poly_t *Polygon) +{ + pcb_r_delete_entry(Layer->polygon_tree, (pcb_box_t *) Polygon); + pcb_poly_pprestore(Polygon); + pcb_polyop_move_noclip(ctx, Layer, Polygon); + pcb_r_insert_entry(Layer->polygon_tree, (pcb_box_t *) Polygon); + pcb_poly_ppclear(Polygon); + return Polygon; +} + +void *pcb_polyop_clip(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_poly_t *Polygon) +{ + if (ctx->clip.restore) { + pcb_r_delete_entry(Layer->polygon_tree, (pcb_box_t *) Polygon); + pcb_poly_pprestore(Polygon); + } + if (ctx->clip.clear) { + pcb_r_insert_entry(Layer->polygon_tree, (pcb_box_t *) Polygon); + pcb_poly_ppclear(Polygon); + } + return Polygon; +} +/* moves a polygon-point */ +void *pcb_polyop_move_point(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_poly_t *Polygon, pcb_point_t *Point) +{ + pcb_poly_pprestore(Polygon); + if (Layer->meta.real.vis) { + pcb_poly_invalidate_erase(Polygon); + } + pcb_r_delete_entry(Layer->polygon_tree, (pcb_box_t *) Polygon); + PCB_MOVE_POINT(Point->X, Point->Y, ctx->move.dx, ctx->move.dy); + pcb_poly_bbox(Polygon); + pcb_r_insert_entry(Layer->polygon_tree, (pcb_box_t *) Polygon); + pcb_poly_remove_excess_points(Layer, Polygon); + pcb_poly_init_clip(PCB->Data, Layer, Polygon); + if (Layer->meta.real.vis) + pcb_poly_invalidate_draw(Layer, Polygon); + pcb_poly_ppclear(Polygon); + return Point; +} + +/* moves a polygon between layers; lowlevel routines */ +void *pcb_polyop_move_to_layer_low(pcb_opctx_t *ctx, pcb_layer_t * Source, pcb_poly_t * polygon, pcb_layer_t * Destination) +{ + pcb_r_delete_entry(Source->polygon_tree, (pcb_box_t *) polygon); + + pcb_poly_pprestore(polygon); + pcb_poly_unreg(polygon); + pcb_poly_reg(Destination, polygon); + + if (!Destination->polygon_tree) + Destination->polygon_tree = pcb_r_create_tree(); + pcb_r_insert_entry(Destination->polygon_tree, (pcb_box_t *) polygon); + + pcb_poly_ppclear(polygon); + return polygon; +} + +/* moves a polygon between layers */ +void *pcb_polyop_move_to_layer(pcb_opctx_t *ctx, pcb_layer_t * Layer, pcb_poly_t * Polygon) +{ + pcb_poly_t *newone; + + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, Polygon)) { + pcb_message(PCB_MSG_WARNING, "Sorry, polygon object is locked\n"); + return NULL; + } + if (Layer == ctx->move.dst_layer) + return Polygon; + pcb_undo_add_obj_to_move_to_layer(PCB_OBJ_POLY, Layer, Polygon, Polygon); + if (Layer->meta.real.vis) + pcb_poly_invalidate_erase(Polygon); + + newone = (struct pcb_poly_s *) pcb_polyop_move_to_layer_low(ctx, Layer, Polygon, ctx->move.dst_layer); + pcb_poly_init_clip(PCB->Data, ctx->move.dst_layer, newone); + if (ctx->move.dst_layer->meta.real.vis) + pcb_poly_invalidate_draw(ctx->move.dst_layer, newone); + return newone; +} + + +/* destroys a polygon from a layer */ +void *pcb_polyop_destroy(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_poly_t *Polygon) +{ + pcb_r_delete_entry(Layer->polygon_tree, (pcb_box_t *) Polygon); + pcb_poly_free_fields(Polygon); + + pcb_poly_free(Polygon); + + return NULL; +} + +/* removes a polygon-point from a polygon and destroys the data */ +void *pcb_polyop_destroy_point(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_poly_t *Polygon, pcb_point_t *Point) +{ + pcb_cardinal_t point_idx; + pcb_cardinal_t i; + pcb_cardinal_t contour; + pcb_cardinal_t contour_start, contour_end, contour_points; + + pcb_poly_pprestore(Polygon); + point_idx = pcb_poly_point_idx(Polygon, Point); + contour = pcb_poly_contour_point(Polygon, point_idx); + contour_start = (contour == 0) ? 0 : Polygon->HoleIndex[contour - 1]; + contour_end = (contour == Polygon->HoleIndexN) ? Polygon->PointN : Polygon->HoleIndex[contour]; + contour_points = contour_end - contour_start; + + if (contour_points <= 3) + return pcb_polyop_remove_counter(ctx, Layer, Polygon, contour); + + pcb_r_delete_entry(Layer->polygon_tree, (pcb_box_t *) Polygon); + + /* remove point from list, keep point order */ + for (i = point_idx; i < Polygon->PointN - 1; i++) + Polygon->Points[i] = Polygon->Points[i + 1]; + Polygon->PointN--; + + /* Shift down indices of any holes */ + for (i = 0; i < Polygon->HoleIndexN; i++) + if (Polygon->HoleIndex[i] > point_idx) + Polygon->HoleIndex[i]--; + + pcb_poly_bbox(Polygon); + pcb_r_insert_entry(Layer->polygon_tree, (pcb_box_t *) Polygon); + pcb_poly_init_clip(PCB->Data, Layer, Polygon); + pcb_poly_ppclear(Polygon); + return Polygon; +} + +/* removes a polygon from a layer */ +void *pcb_polyop_remove(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_poly_t *Polygon) +{ + /* erase from screen */ + pcb_poly_pprestore(Polygon); + if (Layer->meta.real.vis) + pcb_poly_invalidate_erase(Polygon); + pcb_undo_move_obj_to_remove(PCB_OBJ_POLY, Layer, Polygon, Polygon); + return NULL; +} + +void *pcb_poly_remove(pcb_layer_t *Layer, pcb_poly_t *Polygon) +{ + void *res; + pcb_opctx_t ctx; + + ctx.remove.pcb = PCB; + ctx.remove.destroy_target = NULL; + + res = pcb_polyop_remove(&ctx, Layer, Polygon); + pcb_draw(); + return res; +} + +/* Removes a contour from a polygon. + If removing the outer contour, it removes the whole polygon. */ +void *pcb_polyop_remove_counter(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_poly_t *Polygon, pcb_cardinal_t contour) +{ + pcb_cardinal_t contour_start, contour_end, contour_points; + pcb_cardinal_t i; + + if (contour == 0) + return pcb_poly_remove(Layer, Polygon); + + pcb_poly_pprestore(Polygon); + + if (Layer->meta.real.vis) + pcb_poly_invalidate_erase(Polygon); + + /* Copy the polygon to the undo list */ + pcb_undo_add_obj_to_remove_contour(PCB_OBJ_POLY, Layer, Polygon); + + contour_start = (contour == 0) ? 0 : Polygon->HoleIndex[contour - 1]; + contour_end = (contour == Polygon->HoleIndexN) ? Polygon->PointN : Polygon->HoleIndex[contour]; + contour_points = contour_end - contour_start; + + /* remove points from list, keep point order */ + for (i = contour_start; i < Polygon->PointN - contour_points; i++) + Polygon->Points[i] = Polygon->Points[i + contour_points]; + Polygon->PointN -= contour_points; + + /* remove hole from list and shift down remaining indices */ + for (i = contour; i < Polygon->HoleIndexN; i++) + Polygon->HoleIndex[i - 1] = Polygon->HoleIndex[i] - contour_points; + Polygon->HoleIndexN--; + + pcb_poly_init_clip(PCB->Data, Layer, Polygon); + + pcb_poly_ppclear(Polygon); + + /* redraw polygon if necessary */ + if (Layer->meta.real.vis) + pcb_poly_invalidate_draw(Layer, Polygon); + return NULL; +} + +/* removes a polygon-point from a polygon */ +void *pcb_polyop_remove_point(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_poly_t *Polygon, pcb_point_t *Point) +{ + pcb_cardinal_t point_idx; + pcb_cardinal_t i; + pcb_cardinal_t contour; + pcb_cardinal_t contour_start, contour_end, contour_points; + + pcb_poly_pprestore(Polygon); + + point_idx = pcb_poly_point_idx(Polygon, Point); + contour = pcb_poly_contour_point(Polygon, point_idx); + contour_start = (contour == 0) ? 0 : Polygon->HoleIndex[contour - 1]; + contour_end = (contour == Polygon->HoleIndexN) ? Polygon->PointN : Polygon->HoleIndex[contour]; + contour_points = contour_end - contour_start; + + if (contour_points <= 3) + return pcb_polyop_remove_counter(ctx, Layer, Polygon, contour); + + if (Layer->meta.real.vis) + pcb_poly_invalidate_erase(Polygon); + + /* insert the polygon-point into the undo list */ + pcb_undo_add_obj_to_remove_point(PCB_OBJ_POLY_POINT, Layer, Polygon, point_idx); + pcb_r_delete_entry(Layer->polygon_tree, (pcb_box_t *) Polygon); + + /* remove point from list, keep point order */ + for (i = point_idx; i < Polygon->PointN - 1; i++) + Polygon->Points[i] = Polygon->Points[i + 1]; + Polygon->PointN--; + + /* Shift down indices of any holes */ + for (i = 0; i < Polygon->HoleIndexN; i++) + if (Polygon->HoleIndex[i] > point_idx) + Polygon->HoleIndex[i]--; + + pcb_poly_bbox(Polygon); + pcb_r_insert_entry(Layer->polygon_tree, (pcb_box_t *) Polygon); + pcb_poly_remove_excess_points(Layer, Polygon); + pcb_poly_init_clip(PCB->Data, Layer, Polygon); + + /* redraw polygon if necessary */ + if (Layer->meta.real.vis) + pcb_poly_invalidate_draw(Layer, Polygon); + + pcb_poly_ppclear(Polygon); + return NULL; +} + +/* copies a polygon */ +void *pcb_polyop_copy(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_poly_t *Polygon) +{ + pcb_poly_t *polygon; + + polygon = pcb_poly_new(Layer, Polygon->Clearance, pcb_no_flags()); + pcb_poly_copy(polygon, Polygon, ctx->copy.DeltaX, ctx->copy.DeltaY); + pcb_poly_copy_meta(polygon, Polygon); + if (!Layer->polygon_tree) + Layer->polygon_tree = pcb_r_create_tree(); + pcb_r_insert_entry(Layer->polygon_tree, (pcb_box_t *) polygon); + pcb_poly_init_clip(PCB->Data, Layer, polygon); + pcb_poly_invalidate_draw(Layer, polygon); + pcb_undo_add_obj_to_create(PCB_OBJ_POLY, Layer, polygon, polygon); + pcb_poly_ppclear(polygon); + return polygon; +} + +void *pcb_polyop_rotate90(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_poly_t *Polygon) +{ + pcb_poly_pprestore(Polygon); + if (Layer->meta.real.vis) + pcb_poly_invalidate_erase(Polygon); + if (Layer->polygon_tree != NULL) + pcb_r_delete_entry(Layer->polygon_tree, (pcb_box_t *) Polygon); + pcb_poly_rotate90(Polygon, ctx->rotate.center_x, ctx->rotate.center_y, ctx->rotate.number); + if (Layer->polygon_tree != NULL) + pcb_r_insert_entry(Layer->polygon_tree, (pcb_box_t *) Polygon); + pcb_poly_init_clip(PCB->Data, Layer, Polygon); + if (Layer->meta.real.vis) + pcb_poly_invalidate_draw(Layer, Polygon); + pcb_poly_ppclear(Polygon); + return Polygon; +} + +void *pcb_polyop_rotate(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_poly_t *Polygon) +{ + pcb_poly_pprestore(Polygon); + if (Layer->meta.real.vis) + pcb_poly_invalidate_erase(Polygon); + pcb_poly_rotate(Layer, Polygon, ctx->rotate.center_x, ctx->rotate.center_y, ctx->rotate.cosa, ctx->rotate.sina); + pcb_poly_init_clip(PCB->Data, Layer, Polygon); + if (Layer->meta.real.vis) + pcb_poly_invalidate_draw(Layer, Polygon); + pcb_poly_ppclear(Polygon); + return Polygon; +} + +void *pcb_polyop_change_flag(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_poly_t *Polygon) +{ + static pcb_flag_values_t pcb_poly_flags = 0; + if (pcb_poly_flags == 0) + pcb_poly_flags = pcb_obj_valid_flags(PCB_OBJ_POLY); + + if ((ctx->chgflag.flag & pcb_poly_flags) != ctx->chgflag.flag) + return NULL; + if ((ctx->chgflag.flag & PCB_FLAG_TERMNAME) && (Polygon->term == NULL)) + return NULL; + pcb_undo_add_obj_to_flag(Polygon); + + + if (ctx->chgflag.flag & (PCB_FLAG_CLEARPOLY | PCB_FLAG_CLEARPOLYPOLY)) + pcb_poly_restore_to_poly(ctx->chgflag.pcb->Data, PCB_OBJ_POLY, Polygon->parent.layer, Polygon); + + PCB_FLAG_CHANGE(ctx->chgflag.how, ctx->chgflag.flag, Polygon); + + if (ctx->chgflag.flag & PCB_FLAG_FULLPOLY) + pcb_poly_init_clip(ctx->chgflag.pcb->Data, Polygon->parent.layer, Polygon); + + if (ctx->chgflag.flag & (PCB_FLAG_CLEARPOLY | PCB_FLAG_CLEARPOLYPOLY)) + pcb_poly_clear_from_poly(ctx->chgflag.pcb->Data, PCB_OBJ_POLY, Polygon->parent.layer, Polygon); + + return Polygon; +} + +void pcb_poly_pre(pcb_poly_t *poly) +{ + pcb_layer_t *ly = pcb_layer_get_real(poly->parent.layer); + if (ly == NULL) + return; + + pcb_poly_pprestore(poly); + if (ly->polygon_tree != NULL) + pcb_r_delete_entry(ly->polygon_tree, (pcb_box_t *)poly); +} + +void pcb_poly_post(pcb_poly_t *poly) +{ + pcb_layer_t *ly = pcb_layer_get_real(poly->parent.layer); + if (ly == NULL) + return; + + if (ly->polygon_tree != NULL) + pcb_r_insert_entry(ly->polygon_tree, (pcb_box_t *)poly); + pcb_poly_ppclear(poly); +} + + +/*** iteration helpers ***/ +void pcb_poly_map_contours(pcb_poly_t *p, void *ctx, pcb_poly_map_cb_t *cb) +{ + pcb_polyarea_t *pa; + pcb_pline_t *pl; + + pa = p->Clipped; + do { + int cidx; + for(cidx = 0, pl = pa->contours; pl != NULL; cidx++, pl = pl->next) { + pcb_vnode_t *v; + cb(p, ctx, (cidx == 0 ? PCB_POLYEV_ISLAND_START : PCB_POLYEV_HOLE_START), 0, 0); + v = pl->head.next; + do { + cb(p, ctx, (cidx == 0 ? PCB_POLYEV_ISLAND_POINT : PCB_POLYEV_HOLE_POINT), v->point[0], v->point[1]); + } while ((v = v->next) != pl->head.next); + + cb(p, ctx, (cidx == 0 ? PCB_POLYEV_ISLAND_END : PCB_POLYEV_HOLE_END), 0, 0); + } + pa = pa->f; + } while(pa != p->Clipped); +} + +void *pcb_polyop_invalidate_label(pcb_opctx_t *ctx, pcb_layer_t *layer, pcb_poly_t *poly) +{ + pcb_poly_name_invalidate_draw(poly); + return poly; +} + +/*** draw ***/ + +static pcb_bool is_poly_term_vert(const pcb_poly_t *poly) +{ + pcb_coord_t dx, dy; + + dx = poly->BoundingBox.X2 - poly->BoundingBox.X1; + if (dx < 0) + dx = -dx; + + dy = poly->BoundingBox.Y2 - poly->BoundingBox.Y1; + if (dy < 0) + dy = -dy; + + return dx < dy; +} + + +void pcb_poly_name_invalidate_draw(pcb_poly_t *poly) +{ + if (poly->term != NULL) { + pcb_term_label_invalidate((poly->BoundingBox.X1 + poly->BoundingBox.X2)/2, (poly->BoundingBox.Y1 + poly->BoundingBox.Y2)/2, + 100.0, is_poly_term_vert(poly), pcb_true, (pcb_any_obj_t *)poly); + } +} + +void pcb_poly_draw_label(pcb_draw_info_t *info, pcb_poly_t *poly) +{ + if (poly->term != NULL) + pcb_term_label_draw(info, (poly->BoundingBox.X1 + poly->BoundingBox.X2)/2, (poly->BoundingBox.Y1 + poly->BoundingBox.Y2)/2, + conf_core.appearance.term_label_size, is_poly_term_vert(poly), pcb_true, (pcb_any_obj_t *)poly); +} + +void pcb_poly_draw_annotation(pcb_draw_info_t *info, pcb_poly_t *poly) +{ + pcb_cardinal_t n, np; + + if (!conf_core.editor.as_drawn_poly) + return; + + if (PCB_FLAG_TEST(PCB_FLAG_SELECTED, poly)) + pcb_gui->set_color(pcb_draw_out.fgGC, &conf_core.appearance.color.selected); + else + pcb_gui->set_color(pcb_draw_out.fgGC, &conf_core.appearance.color.pin_name); + + pcb_hid_set_line_width(pcb_draw_out.fgGC, -1); + pcb_hid_set_line_cap(pcb_draw_out.fgGC, pcb_cap_round); + + if (poly->HoleIndexN > 0) + np = poly->HoleIndex[0]; + else + np = poly->PointN; + + for(n = 1; n < np; n++) + pcb_gui->draw_line(pcb_draw_out.fgGC, poly->Points[n-1].X, poly->Points[n-1].Y, poly->Points[n].X, poly->Points[n].Y); + pcb_gui->draw_line(pcb_draw_out.fgGC, poly->Points[n-1].X, poly->Points[n-1].Y, poly->Points[0].X, poly->Points[0].Y); +} + +static void pcb_poly_draw_tr_offs(pcb_poly_it_t *it, pcb_coord_t offs) +{ + int go; + long len, n; + pcb_coord_t x, y; + pcb_polo_t *p, p_st[256]; + + /* calculate length of the polyline */ + for(go = pcb_poly_vect_first(it, &x, &y), len = 0; go; go = pcb_poly_vect_next(it, &x, &y)) + len++; + + if (len >= sizeof(p_st) / sizeof(p_st[0])) + p = malloc(sizeof(pcb_polo_t) * len); + else + p = p_st; + + for(go = pcb_poly_vect_first(it, &x, &y), n = 0; go; go = pcb_poly_vect_next(it, &x, &y), n++) { + p[n].x = x; + p[n].y = y; + } + + pcb_polo_norms(p, len); + pcb_polo_offs(offs, p, len); + + + for(go = pcb_poly_vect_first(it, &x, &y), n = 0; go; go = pcb_poly_vect_next(it, &x, &y), n++) { + it->v->point[0] = pcb_round(p[n].x); + it->v->point[1] = pcb_round(p[n].y); + } + + if (p != p_st) + free(p); +} + +static pcb_poly_t *pcb_poly_draw_tr(pcb_draw_info_t *info, pcb_poly_t *polygon) +{ + pcb_poly_t *np = pcb_poly_alloc(polygon->parent.layer); + pcb_poly_it_t it; + pcb_polyarea_t *pa; + pcb_coord_t offs = info->xform->bloat / 2; + + pcb_poly_copy(np, polygon, 0, 0); + pcb_polyarea_copy0(&np->Clipped, polygon->Clipped); + + /* iterate over all islands of a polygon */ + for(pa = pcb_poly_island_first(np, &it); pa != NULL; pa = pcb_poly_island_next(&it)) { + pcb_pline_t *pl; + + /* check if we have a contour for the given island */ + pl = pcb_poly_contour(&it); + if (pl == NULL) + continue; + + /* iterate over the vectors of the contour */ + pcb_poly_draw_tr_offs(&it, offs); + + /* iterate over all holes within this island */ + for(pl = pcb_poly_hole_first(&it); pl != NULL; pl = pcb_poly_hole_next(&it)) + pcb_poly_draw_tr_offs(&it, offs); + } + + return np; +} + +void pcb_poly_draw_(pcb_draw_info_t *info, pcb_poly_t *polygon, int allow_term_gfx) +{ + pcb_poly_t *trpoly = NULL; + + if (delayed_terms_enabled && (polygon->term != NULL)) { + pcb_draw_delay_obj_add((pcb_any_obj_t *)polygon); + return; + } + + if (conf_core.editor.as_drawn_poly) + pcb_draw_annotation_add((pcb_any_obj_t *)polygon); + + if ((info != NULL) && (info->xform != NULL) && (info->xform->bloat != 0)) { + /* Slow dupping and recalculation every time; if we ever need this on-screen, we should cache */ + trpoly = pcb_poly_draw_tr(info, polygon); + polygon = trpoly; + } + + if ((pcb_gui->thindraw_pcb_polygon != NULL) && (conf_core.editor.thin_draw || conf_core.editor.thin_draw_poly || conf_core.editor.wireframe_draw)) + { + pcb_gui->thindraw_pcb_polygon(pcb_draw_out.fgGC, polygon, info->drawn_area); + } + else { + if ((allow_term_gfx) && pcb_draw_term_need_gfx(polygon) && pcb_draw_term_hid_permission()) { + pcb_vnode_t *n, *head; + int i; + pcb_gui->fill_pcb_polygon(pcb_draw_out.active_padGC, polygon, info->drawn_area); + head = &polygon->Clipped->contours->head; + pcb_hid_set_line_cap(pcb_draw_out.fgGC, pcb_cap_square); + for(n = head, i = 0; (n != head) || (i == 0); n = n->next, i++) { + pcb_coord_t x, y, r; + x = (n->prev->point[0] + n->point[0] + n->next->point[0]) / 3; + y = (n->prev->point[1] + n->point[1] + n->next->point[1]) / 3; + +TODO("subc: check if x;y is within the poly, but use a cheaper method than the official") + r = PCB_DRAW_TERM_GFX_WIDTH; + pcb_hid_set_line_width(pcb_draw_out.fgGC, r); + pcb_hid_set_line_cap(pcb_draw_out.fgGC, pcb_cap_square); + pcb_gui->draw_line(pcb_draw_out.fgGC, x, y, x, y); + } + } + else + pcb_gui->fill_pcb_polygon(pcb_draw_out.fgGC, polygon, info->drawn_area); + } + + /* If checking planes, thin-draw any pieces which have been clipped away */ + if (pcb_gui->thindraw_pcb_polygon != NULL && conf_core.editor.check_planes && !PCB_FLAG_TEST(PCB_FLAG_FULLPOLY, polygon)) { + pcb_poly_t poly = *polygon; + + for (poly.Clipped = polygon->Clipped->f; poly.Clipped != polygon->Clipped; poly.Clipped = poly.Clipped->f) + pcb_gui->thindraw_pcb_polygon(pcb_draw_out.fgGC, &poly, info->drawn_area); + } + + if (polygon->term != NULL) { + if ((pcb_draw_force_termlab) || PCB_FLAG_TEST(PCB_FLAG_TERMNAME, polygon)) + pcb_draw_delay_label_add((pcb_any_obj_t *)polygon); + } + + if (trpoly != NULL) + pcb_poly_free(trpoly); +} + +static void pcb_poly_draw(pcb_draw_info_t *info, pcb_poly_t *polygon, int allow_term_gfx) +{ + static const pcb_color_t *color; + pcb_color_t buf; + const pcb_layer_t *layer = info->layer != NULL ? info->layer : pcb_layer_get_real(polygon->parent.layer); + + if (layer == NULL) /* if the layer is inbound, e.g. in preview, fall back using the layer recipe */ + layer = polygon->parent.layer; + + if (PCB_FLAG_TEST(PCB_FLAG_WARN, polygon)) + color = &conf_core.appearance.color.warn; + else if (PCB_FLAG_TEST(PCB_FLAG_SELECTED, polygon)) { + if (layer->is_bound) + PCB_OBJ_COLOR_ON_BOUND_LAYER(color, layer, 1); + else + color = &conf_core.appearance.color.selected; + } + else if (PCB_FLAG_TEST(PCB_FLAG_FOUND, polygon)) + color = &conf_core.appearance.color.connected; + else if (PCB_FLAG_TEST(PCB_FLAG_ONPOINT, polygon)) { + pcb_lighten_color(color, &buf, 1.75); + color = &buf; + } + else if (PCB_HAS_COLOROVERRIDE(polygon)) { + color = polygon->override_color; + } + else if (layer->is_bound) + PCB_OBJ_COLOR_ON_BOUND_LAYER(color, layer, 0); + else + color = &layer->meta.real.color; + pcb_gui->set_color(pcb_draw_out.fgGC, color); + + pcb_poly_draw_(info, polygon, allow_term_gfx); +} + +pcb_r_dir_t pcb_poly_draw_callback(const pcb_box_t * b, void *cl) +{ + pcb_draw_info_t *i = cl; + pcb_poly_t *polygon = (pcb_poly_t *) b; + + if (pcb_hidden_floater((pcb_any_obj_t*)b)) + return PCB_R_DIR_FOUND_CONTINUE; + + if (!polygon->Clipped) + return PCB_R_DIR_NOT_FOUND; + + if (!PCB->SubcPartsOn && pcb_lobj_parent_subc(polygon->parent_type, &polygon->parent)) + return PCB_R_DIR_NOT_FOUND; + + pcb_poly_draw(i, polygon, 0); + + return PCB_R_DIR_FOUND_CONTINUE; +} + +pcb_r_dir_t pcb_poly_draw_term_callback(const pcb_box_t * b, void *cl) +{ + pcb_draw_info_t *i = cl; + pcb_poly_t *polygon = (pcb_poly_t *) b; + + if (pcb_hidden_floater((pcb_any_obj_t*)b)) + return PCB_R_DIR_FOUND_CONTINUE; + + if (!polygon->Clipped) + return PCB_R_DIR_NOT_FOUND; + + if (!PCB->SubcPartsOn && pcb_lobj_parent_subc(polygon->parent_type, &polygon->parent)) + return PCB_R_DIR_NOT_FOUND; + + pcb_poly_draw(i, polygon, 1); + + return PCB_R_DIR_FOUND_CONTINUE; +} + +/* erases a polygon on a layer */ +void pcb_poly_invalidate_erase(pcb_poly_t *Polygon) +{ + pcb_draw_invalidate(Polygon); + pcb_flag_erase(&Polygon->Flags); +} + +void pcb_poly_invalidate_draw(pcb_layer_t *Layer, pcb_poly_t *Polygon) +{ + pcb_draw_invalidate(Polygon); +} Index: tags/2.1.2/src/obj_poly.h =================================================================== --- tags/2.1.2/src/obj_poly.h (nonexistent) +++ tags/2.1.2/src/obj_poly.h (revision 24813) @@ -0,0 +1,298 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +/* Drawing primitive: polygons */ + +#ifndef PCB_OBJ_POLY_H +#define PCB_OBJ_POLY_H + +#include "config.h" +#include +#include "obj_common.h" +#include "polyarea.h" + +struct pcb_poly_s { /* holds information about a polygon */ + PCB_ANY_PRIMITIVE_FIELDS; + pcb_coord_t Clearance; + pcb_cardinal_t PointN; /* number of points in polygon */ + pcb_cardinal_t PointMax; /* max number from malloc() */ + pcb_polyarea_t *Clipped; /* the clipped region of this polygon */ + pcb_pline_t *NoHoles; /* the polygon broken into hole-less regions */ + int NoHolesValid; /* Is the NoHoles polygon up to date? */ + pcb_point_t *Points; /* data */ + pcb_cardinal_t *HoleIndex; /* Index of hole data within the Points array */ + pcb_cardinal_t HoleIndexN; /* number of holes in polygon */ + pcb_cardinal_t HoleIndexMax; /* max number from malloc() */ + unsigned clip_dirty:1; /* 1 if polygon should be reclipped after clipping inhibit is over */ + gdl_elem_t link; /* a poly is in a list of a layer */ +}; + + + +pcb_poly_t *pcb_poly_alloc(pcb_layer_t * layer); +pcb_poly_t *pcb_poly_alloc_id(pcb_layer_t *layer, long int id); +void pcb_poly_free(pcb_poly_t * data); +pcb_point_t *pcb_poly_point_alloc(pcb_poly_t *Polygon); +pcb_cardinal_t *pcb_poly_holeidx_new(pcb_poly_t *Polygon); +void pcb_poly_free_fields(pcb_poly_t * polygon); + +void pcb_poly_reg(pcb_layer_t *layer, pcb_poly_t *poly); +void pcb_poly_unreg(pcb_poly_t *poly); + +void pcb_poly_bbox(pcb_poly_t *Polygon); +pcb_poly_t *pcb_poly_new_from_rectangle(pcb_layer_t *Layer, pcb_coord_t X1, pcb_coord_t Y1, pcb_coord_t X2, pcb_coord_t Y2, pcb_coord_t Clearance, pcb_flag_t Flags); +pcb_poly_t *pcb_poly_new_from_poly(pcb_layer_t *Layer, pcb_poly_t *src, pcb_coord_t offs, pcb_coord_t Clearance, pcb_flag_t Flags); +pcb_poly_t *pcb_poly_new(pcb_layer_t *Layer, pcb_coord_t Clearance, pcb_flag_t Flags); +pcb_poly_t *pcb_poly_dup(pcb_layer_t *dst, pcb_poly_t *src); +pcb_poly_t *pcb_poly_dup_at(pcb_layer_t *dst, pcb_poly_t *src, pcb_coord_t dx, pcb_coord_t dy); +pcb_point_t *pcb_poly_point_new(pcb_poly_t *Polygon, pcb_coord_t X, pcb_coord_t Y); +pcb_poly_t *pcb_poly_hole_new(pcb_poly_t * Polygon); +void *pcb_poly_remove(pcb_layer_t *Layer, pcb_poly_t *Polygon); + +void pcb_poly_rotate90(pcb_poly_t *Polygon, pcb_coord_t X, pcb_coord_t Y, unsigned Number); +void pcb_poly_rotate(pcb_layer_t *layer, pcb_poly_t *poly, pcb_coord_t X, pcb_coord_t Y, double cosa, double sina); +void pcb_poly_mirror(pcb_layer_t *layer, pcb_poly_t *polygon, pcb_coord_t y_offs); +void pcb_poly_flip_side(pcb_layer_t *layer, pcb_poly_t *polygon); +void pcb_poly_scale(pcb_poly_t *poly, double sx, double sy); + +void pcb_poly_move(pcb_poly_t *Polygon, pcb_coord_t DX, pcb_coord_t DY); +pcb_poly_t *pcb_poly_copy(pcb_poly_t *Dest, pcb_poly_t *Src, pcb_coord_t dx, pcb_coord_t dy); + +void pcb_poly_pre(pcb_poly_t *poly); +void pcb_poly_post(pcb_poly_t *poly); + +/* hash and eq */ +int pcb_poly_eq(const pcb_host_trans_t *tr1, const pcb_poly_t *p1, const pcb_host_trans_t *tr2, const pcb_poly_t *p2); +unsigned int pcb_poly_hash(const pcb_host_trans_t *tr, const pcb_poly_t *p); + +/* Add objects without creating them or making any "sanity modifications" to them */ +void pcb_add_poly_on_layer(pcb_layer_t *Layer, pcb_poly_t *polygon); + +double pcb_poly_area(const pcb_poly_t *poly); + +/*** helpers for iterating over countours */ + +/*** Polygon helpers on the clopped polygon ***/ +typedef enum { + PCB_POLYEV_ISLAND_START, + PCB_POLYEV_ISLAND_POINT, + PCB_POLYEV_ISLAND_END, + PCB_POLYEV_HOLE_START, + PCB_POLYEV_HOLE_POINT, + PCB_POLYEV_HOLE_END +} pcb_poly_event_t; + +/* return non-zero to quit mapping immediatley */ +typedef int pcb_poly_map_cb_t(pcb_poly_t *p, void *ctx, pcb_poly_event_t ev, pcb_coord_t x, pcb_coord_t y); + +/* call cb for each point of each island and cutout */ +void pcb_poly_map_contours(pcb_poly_t *p, void *ctx, pcb_poly_map_cb_t *cb); + +typedef struct pcb_poly_it_s { + const pcb_poly_t *p; + pcb_polyarea_t *pa; + pcb_pline_t *cntr; + pcb_vnode_t *v; +} pcb_poly_it_t; + +/* Set the iterator to the first island of the polygon; returns NULL if no contour available */ +PCB_INLINE pcb_polyarea_t *pcb_poly_island_first(const pcb_poly_t *p, pcb_poly_it_t *it) +{ + it->p = p; + it->pa = p->Clipped; + it->cntr = NULL; + it->v = NULL; + return it->pa; +} + +/* Set the iterator to the next island of the polygon; returns NULL if no more */ +PCB_INLINE pcb_polyarea_t *pcb_poly_island_next(pcb_poly_it_t *it) +{ + if (it->pa->f == it->p->Clipped) + return NULL; + it->pa = it->pa->f; + it->cntr = NULL; + it->v = NULL; + return it->pa; +} + +/* Set the iterator to trace the outer contour of the current island */ +PCB_INLINE pcb_pline_t *pcb_poly_contour(pcb_poly_it_t *it) +{ + it->v = NULL; + return it->cntr = it->pa->contours; +} + +/* Set the iterator to trace the first hole of the current island; returns NULL if there are no holes */ +PCB_INLINE pcb_pline_t *pcb_poly_hole_first(pcb_poly_it_t *it) +{ + it->v = NULL; + return it->cntr = it->pa->contours->next; +} + +/* Set the iterator to trace the next hole of the current island; returns NULL if there are were more holes */ +PCB_INLINE pcb_pline_t *pcb_poly_hole_next(pcb_poly_it_t *it) +{ + it->v = NULL; + return it->cntr = it->cntr->next; +} + +/* Set the iterator to the first point of the last selected contour or hole; + read the coords into x,y; returns 1 on success, 0 if there are no points */ +PCB_INLINE int pcb_poly_vect_first(pcb_poly_it_t *it, pcb_coord_t *x, pcb_coord_t *y) +{ + it->v = it->cntr->head.next; + if (it->v == NULL) + return 0; + *x = it->v->point[0]; + *y = it->v->point[1]; + return 1; +} + + +/* Set the iterator to the next point of the last selected contour or hole; + read the coords into x,y; returns 1 on success, 0 if there are were more points */ +PCB_INLINE int pcb_poly_vect_next(pcb_poly_it_t *it, pcb_coord_t *x, pcb_coord_t *y) +{ + it->v = it->v->next; + if (it->v == it->cntr->head.next) + return 0; + *x = it->v->point[0]; + *y = it->v->point[1]; + return 1; +} + +/* read the previous contour/hole coords into x,y, without bumping the iterator */ +PCB_INLINE void pcb_poly_vect_peek_prev(pcb_poly_it_t *it, pcb_coord_t *x, pcb_coord_t *y) +{ + *x = it->v->prev->point[0]; + *y = it->v->prev->point[1]; +} + +/* read the next contour/hole coords into x,y, without bumping the iterator */ +PCB_INLINE void pcb_poly_vect_peek_next(pcb_poly_it_t *it, pcb_coord_t *x, pcb_coord_t *y) +{ + *x = it->v->next->point[0]; + *y = it->v->next->point[1]; +} + +/* Set the iterator to a polyarea*/ +PCB_INLINE pcb_polyarea_t *pcb_poly_iterate_polyarea(pcb_polyarea_t *pa, pcb_poly_it_t *it) +{ + it->p = NULL; + it->pa = pa; + it->cntr = NULL; + it->v = NULL; + return it->pa; +} + +/* construct the full poly clearance cutout for the pa in the iterator and add + it to dst - implemented in polygon.c */ +void pcb_poly_pa_clearance_construct(pcb_polyarea_t **dst, pcb_poly_it_t *it, pcb_coord_t clearance); + + +#define pcb_poly_ppclear_at(poly, layer) \ +do { \ + if (layer->is_bound) layer = layer->meta.bound.real; \ + if (PCB_POLY_HAS_CLEARANCE(poly) && (layer != NULL)) \ + pcb_poly_clear_from_poly(layer->parent.data, PCB_OBJ_POLY, layer, poly); \ +} while(0) + +/* Let the poly clear sorrunding polys in its layer */ +#define pcb_poly_ppclear(poly) \ +do { \ + if (poly->parent.layer != NULL) { \ + pcb_layer_t *layer = pcb_layer_get_real(poly->parent.layer); \ + if ((layer != NULL) && (layer->parent.data->parent_type == PCB_PARENT_BOARD)) { \ + pcb_poly_ppclear_at(poly, layer); \ + } \ + } \ +} while(0) + +/* Let the poly restore sorrunding polys in its layer */ +#define pcb_poly_pprestore(poly) \ +do { \ + if (poly->parent.layer != NULL) { \ + pcb_layer_t *layer = pcb_layer_get_real(poly->parent.layer); \ + if ((layer != NULL) && (layer->parent.data->parent_type == PCB_PARENT_BOARD)) { \ + if (layer->is_bound) layer = layer->meta.bound.real; \ + if (PCB_POLY_HAS_CLEARANCE(poly) && (layer != NULL)) \ + pcb_poly_restore_to_poly(layer->parent.data, PCB_OBJ_POLY, layer, poly); \ + } \ + } \ +} while(0) + + + +/*** loops ***/ + +#define PCB_POLY_LOOP(layer) do { \ + pcb_poly_t *polygon; \ + gdl_iterator_t __it__; \ + linelist_foreach(&(layer)->Polygon, &__it__, polygon) { + +#define PCB_POLY_POINT_LOOP(polygon) do { \ + pcb_cardinal_t n; \ + pcb_point_t *point; \ + for (n = (polygon)->PointN-1; n != -1; n--) \ + { \ + point = &(polygon)->Points[n] + +#define PCB_POLY_ALL_LOOP(top) do { \ + pcb_cardinal_t l; \ + pcb_layer_t *layer = (top)->Layer; \ + for (l = 0; l < ((top)->LayerN > 0 ? (top)->LayerN : PCB->Data->LayerN) ; l++, layer++) \ + { \ + PCB_POLY_LOOP(layer) + +#define PCB_POLY_COPPER_LOOP(top) do { \ + pcb_cardinal_t l; \ + pcb_layer_t *layer = (top)->Layer; \ + for (l = 0; l < ((top)->LayerN > 0 ? (top)->LayerN : PCB->Data->LayerN); l++, layer++) \ + { \ + if (!(pcb_layer_flags(PCB, l) & PCB_LYT_COPPER)) continue; \ + PCB_POLY_LOOP(layer) + +#define PCB_POLY_SILK_LOOP(top) do { \ + pcb_cardinal_t l; \ + pcb_layer_t *layer = (top)->Layer; \ + for (l = 0; l < ((top)->LayerN > 0 ? (top)->LayerN : PCB->Data->LayerN); l++, layer++) \ + { \ + if (!(pcb_layer_flags(PCB, l) & PCB_LYT_SILK)) continue; \ + PCB_POLY_LOOP(layer) + +#define PCB_POLY_VISIBLE_LOOP(top) do { \ + pcb_cardinal_t l; \ + pcb_layer_t *layer = (top)->Layer; \ + for (l = 0; l < ((top)->LayerN > 0 ? (top)->LayerN : PCB->Data->LayerN); l++, layer++) \ + { \ + if (layer->meta.real.vis) \ + PCB_POLY_LOOP(layer) + + +#endif Index: tags/2.1.2/src/obj_poly_draw.h =================================================================== --- tags/2.1.2/src/obj_poly_draw.h (nonexistent) +++ tags/2.1.2/src/obj_poly_draw.h (revision 24813) @@ -0,0 +1,45 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +/*** Standard draw of polygons ***/ + +#include "draw.h" + +/* Include rtree.h for these */ +#ifdef PCB_RTREE_H +pcb_r_dir_t pcb_poly_draw_callback(const pcb_box_t * b, void *cl); +pcb_r_dir_t pcb_poly_draw_term_callback(const pcb_box_t * b, void *cl); +#endif + +void pcb_poly_invalidate_erase(pcb_poly_t *Polygon); +void pcb_poly_invalidate_draw(pcb_layer_t *Layer, pcb_poly_t *Polygon); +void pcb_poly_name_invalidate_draw(pcb_poly_t *poly); +void pcb_poly_draw_label(pcb_draw_info_t *info, pcb_poly_t *poly); +void pcb_poly_draw_annotation(pcb_draw_info_t *info, pcb_poly_t *poly); + + Index: tags/2.1.2/src/obj_poly_list.c =================================================================== --- tags/2.1.2/src/obj_poly_list.c (nonexistent) +++ tags/2.1.2/src/obj_poly_list.c (revision 24813) @@ -0,0 +1,29 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2016 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#define TDL_DONT_UNDEF +#include "obj_poly_list.h" +#include Index: tags/2.1.2/src/obj_poly_list.h =================================================================== --- tags/2.1.2/src/obj_poly_list.h (nonexistent) +++ tags/2.1.2/src/obj_poly_list.h (revision 24813) @@ -0,0 +1,47 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2016 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#ifndef LIST_POLY_H +#define LIST_POLY_H + +#include "obj_poly.h" + +/* List of Lines */ +#define TDL(x) polylist_ ## x +#define TDL_LIST_T polylist_t +#define TDL_ITEM_T pcb_poly_t +#define TDL_FIELD link +#define TDL_SIZE_T size_t +#define TDL_FUNC + +#define polylist_foreach(list, iterator, loop_elem) \ + gdl_foreach_((&((list)->lst)), (iterator), (loop_elem)) + + +#include +#include + +#endif Index: tags/2.1.2/src/obj_poly_op.h =================================================================== --- tags/2.1.2/src/obj_poly_op.h (nonexistent) +++ tags/2.1.2/src/obj_poly_op.h (revision 24813) @@ -0,0 +1,56 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +/*** Standard operations on polygons ***/ + +#include "operation.h" + +void *pcb_polyop_add_to_buffer(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_poly_t *Polygon); +void *pcb_polyop_move_buffer(pcb_opctx_t *ctx, pcb_layer_t * layer, pcb_poly_t * polygon); +void *pcb_polyop_change_clear_size(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_poly_t *poly); +void *pcb_polyop_change_clear(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_poly_t *Polygon); +void *pcb_polyop_insert_point(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_poly_t *Polygon); +void *pcb_polyop_move(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_poly_t *Polygon); +void *pcb_polyop_move_noclip(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_poly_t *Polygon); +void *pcb_polyop_clip(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_poly_t *Polygon); +void *pcb_polyop_move_point(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_poly_t *Polygon, pcb_point_t *Point); +void *pcb_polyop_move_to_layer_low(pcb_opctx_t *ctx, pcb_layer_t * Source, pcb_poly_t * polygon, pcb_layer_t * Destination); +void *pcb_polyop_move_to_layer(pcb_opctx_t *ctx, pcb_layer_t * Layer, pcb_poly_t * Polygon); +void *pcb_polyop_destroy(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_poly_t *Polygon); +void *pcb_polyop_destroy_point(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_poly_t *Polygon, pcb_point_t *Point); +void *pcb_polyop_remove(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_poly_t *Polygon); +void *pcb_polyop_remove_counter(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_poly_t *Polygon, pcb_cardinal_t contour); +void *pcb_polyop_remove_point(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_poly_t *Polygon, pcb_point_t *Point); +void *pcb_polyop_copy(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_poly_t *Polygon); +void *pcb_polyop_rotate90(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_poly_t *Polygon); +void *pcb_polyop_rotate(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_poly_t *Polygon); +void *pcb_polyop_change_flag(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_poly_t *Polygon); +void *pcb_polyop_invalidate_label(pcb_opctx_t *ctx, pcb_layer_t *layer, pcb_poly_t *poly); +void *pcb_polyop_change_join(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_poly_t *poly); + + Index: tags/2.1.2/src/obj_pstk.c =================================================================== --- tags/2.1.2/src/obj_pstk.c (nonexistent) +++ tags/2.1.2/src/obj_pstk.c (revision 24813) @@ -0,0 +1,1457 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2017,2018 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "config.h" + +#include + +#include "board.h" +#include "conf_core.h" +#include "data.h" +#include "data_list.h" +#include "draw.h" +#include "draw_wireframe.h" +#include "flag.h" +#include "obj_pstk.h" +#include "obj_pstk_draw.h" +#include "obj_pstk_list.h" +#include "obj_pstk_inlines.h" +#include "obj_pstk_op.h" +#include "obj_subc_parent.h" +#include "obj_hash.h" +#include "operation.h" +#include "search.h" +#include "undo.h" +#include "vtpadstack.h" +#include "event.h" +#include "hid_inlines.h" +#include "polygon_offs.h" + +#define SQR(o) ((o)*(o)) + +static const char core_pstk_cookie[] = "padstack"; + +const pcb_proto_layer_t pcb_proto_layers[pcb_proto_num_layers] = { + {"top paste", PCB_LYT_TOP | PCB_LYT_PASTE, PCB_LYC_AUTO, {2,-1}, 0}, + {"top mask", PCB_LYT_TOP | PCB_LYT_MASK, PCB_LYC_SUB|PCB_LYC_AUTO, {2,-1}, PCB_PROTO_MASK_BLOAT}, + {"top copper", PCB_LYT_TOP | PCB_LYT_COPPER, 0, {4,3}, 0}, + {"any internal copper", PCB_LYT_INTERN | PCB_LYT_COPPER, 0, {2,4}, 0}, + {"bottom copper", PCB_LYT_BOTTOM | PCB_LYT_COPPER, 0, {2,3}, 0}, + {"bottom mask", PCB_LYT_BOTTOM | PCB_LYT_MASK, PCB_LYC_SUB|PCB_LYC_AUTO, {4,-1}, PCB_PROTO_MASK_BLOAT}, + {"bottom paste", PCB_LYT_BOTTOM | PCB_LYT_PASTE, PCB_LYC_AUTO, {4,-1}, 0}, + {"slot", PCB_LYT_MECH, PCB_LYC_AUTO, {-1,-1},0} +}; + + +void pcb_pstk_reg(pcb_data_t *data, pcb_pstk_t *pstk) +{ + padstacklist_append(&data->padstack, pstk); + pcb_obj_id_reg(data, pstk); + PCB_SET_PARENT(pstk, data, data); +} + +void pcb_pstk_unreg(pcb_pstk_t *pstk) +{ + pcb_data_t *data = pstk->parent.data; + assert(pstk->parent_type == PCB_PARENT_DATA); + padstacklist_remove(pstk); + pcb_obj_id_del(data, pstk); + PCB_CLEAR_PARENT(pstk); +} + +pcb_pstk_t *pcb_pstk_alloc_id(pcb_data_t *data, long int id) +{ + pcb_pstk_t *ps; + + ps = calloc(sizeof(pcb_pstk_t), 1); + ps->ID = id; + ps->protoi = -1; + ps->type = PCB_OBJ_PSTK; + ps->Attributes.post_change = pcb_obj_attrib_post_change; + + pcb_pstk_reg(data, ps); + + return ps; +} + +pcb_pstk_t *pcb_pstk_alloc(pcb_data_t *data) +{ + return pcb_pstk_alloc_id(data, pcb_create_ID_get()); +} + + +void pcb_pstk_free(pcb_pstk_t *ps) +{ + pcb_pstk_unreg(ps); + free(ps->thermals.shape); + free(ps); +} + +pcb_pstk_t *pcb_pstk_new_tr(pcb_data_t *data, long int id, pcb_cardinal_t proto, pcb_coord_t x, pcb_coord_t y, pcb_coord_t clearance, pcb_flag_t Flags, double rot, int xmirror, int smirror) +{ + pcb_pstk_t *ps; + + if (proto >= pcb_vtpadstack_proto_len(&data->ps_protos)) + return NULL; + + if (id <= 0) + id = pcb_create_ID_get(); + + ps = pcb_pstk_alloc_id(data, id); + + /* copy values */ + ps->proto = proto; + ps->x = x; + ps->y = y; + ps->Clearance = clearance; + ps->Flags = Flags; + ps->rot = rot; + ps->xmirror = xmirror; + ps->smirror = smirror; + pcb_pstk_add(data, ps); + pcb_event(PCB_EVENT_NEW_PSTK, "p", ps); + pcb_poly_clear_from_poly(data, PCB_OBJ_PSTK, NULL, ps); + return ps; +} + +pcb_pstk_t *pcb_pstk_new(pcb_data_t *data, long int id, pcb_cardinal_t proto, pcb_coord_t x, pcb_coord_t y, pcb_coord_t clearance, pcb_flag_t Flags) +{ + return pcb_pstk_new_tr(data, id, proto, x, y, clearance, Flags, 0, 0, 0); +} + + +void pcb_pstk_add(pcb_data_t *data, pcb_pstk_t *ps) +{ + pcb_pstk_bbox(ps); + if (!data->padstack_tree) + data->padstack_tree = pcb_r_create_tree(); + pcb_r_insert_entry(data->padstack_tree, (pcb_box_t *)ps); + PCB_SET_PARENT(ps, data, data); +} + +static void pcb_pstk_bbox_(pcb_box_t *dst, pcb_pstk_t *ps, pcb_bool copper_only) +{ + int n, sn; + pcb_line_t line; + pcb_pstk_proto_t *proto = pcb_pstk_get_proto(ps); + pcb_pstk_tshape_t *ts = pcb_pstk_get_tshape(ps); + assert(proto != NULL); + + dst->X1 = dst->X2 = ps->x; + dst->Y1 = dst->Y2 = ps->y; + + if (ts != NULL) + for(sn = 0; sn < ts->len; sn++) { + pcb_pstk_shape_t *shape = ts->shape + sn; + switch(shape->shape) { + case PCB_PSSH_POLY: + for(n = 0; n < shape->data.poly.len; n++) + pcb_box_bump_point(dst, shape->data.poly.x[n] + ps->x, shape->data.poly.y[n] + ps->y); + break; + case PCB_PSSH_LINE: + line.Point1.X = shape->data.line.x1 + ps->x; + line.Point1.Y = shape->data.line.y1 + ps->y; + line.Point2.X = shape->data.line.x2 + ps->x; + line.Point2.Y = shape->data.line.y2 + ps->y; + line.Thickness = shape->data.line.thickness; + line.Clearance = 0; + line.Flags = pcb_flag_make(shape->data.line.square ? PCB_FLAG_SQUARE : 0); + pcb_line_bbox(&line); + pcb_box_bump_box(dst, &line.BoundingBox); + break; + case PCB_PSSH_CIRC: + pcb_box_bump_point(dst, ps->x - shape->data.circ.dia/2, ps->y - shape->data.circ.dia/2); + pcb_box_bump_point(dst, ps->x + shape->data.circ.dia/2, ps->y + shape->data.circ.dia/2); + break; + case PCB_PSSH_HSHADOW: + break; + } + } + + if (!copper_only && PCB_NONPOLY_HAS_CLEARANCE(ps)) { + dst->X1 -= ps->Clearance; + dst->Y1 -= ps->Clearance; + dst->X2 += ps->Clearance; + dst->Y2 += ps->Clearance; + } + + if (proto->hdia != 0) { + /* corner case: no copper around the hole all 360 deg - let the hole stick out */ + pcb_box_bump_point(dst, ps->x - proto->hdia/2, ps->y - proto->hdia/2); + pcb_box_bump_point(dst, ps->x + proto->hdia/2, ps->y + proto->hdia/2); + } + + pcb_close_box(dst); +} + +void pcb_pstk_bbox(pcb_pstk_t *ps) +{ + pcb_pstk_bbox_(&ps->BoundingBox, ps, pcb_false); + pcb_pstk_bbox_(&ps->bbox_naked, ps, pcb_true); +} + +void pcb_pstk_copper_bbox(pcb_box_t *dst, pcb_pstk_t *ps) +{ + pcb_pstk_bbox_(dst, ps, pcb_true); +} + +/* hash */ +int pcb_pstk_eq(const pcb_host_trans_t *tr1, const pcb_pstk_t *p1, const pcb_host_trans_t *tr2, const pcb_pstk_t *p2) +{ + double rotdir1 = tr1->on_bottom ? -1.0 : 1.0, rotdir2 = tr2->on_bottom ? -1.0 : 1.0; + +TODO("padstack: should compare shape by shape: a 180 deg rotated or mirrored rectangle is still just the same rectangle!") + + if ((p1->smirror ^ tr1->on_bottom) != (p2->smirror ^ tr2->on_bottom)) return 0; + if ((p1->xmirror ^ tr1->on_bottom) != (p2->xmirror ^ tr2->on_bottom)) return 0; + if (floor(fmod((p1->rot * rotdir1) + tr1->rot, 360.0)*10000) != floor(fmod((p2->rot * rotdir2) + tr2->rot, 360.0)*10000)) return 0; + + if (!PCB_FLAG_TEST(PCB_FLAG_FLOATER, p1) && !PCB_FLAG_TEST(PCB_FLAG_FLOATER, p2)) { + pcb_coord_t x1, y1, x2, y2; + + pcb_hash_tr_coords(tr1, &x1, &y1, p1->x, p1->y); + pcb_hash_tr_coords(tr2, &x2, &y2, p2->x, p2->y); + if ((x1 != x2) || (y1 != y2)) return 0; + } + + if (pcb_neqs(p1->term, p2->term)) return 0; + return 1; +} + +unsigned int pcb_pstk_hash(const pcb_host_trans_t *tr, const pcb_pstk_t *p) +{ + unsigned int crd = 0; + double rotdir = tr->on_bottom ? -1.0 : 1.0; + + if (!PCB_FLAG_TEST(PCB_FLAG_FLOATER, p)) { + pcb_coord_t x, y; + + pcb_hash_tr_coords(tr, &x, &y, p->x, p->y); + crd = pcb_hash_coord(x) ^ pcb_hash_coord(y); + } + + return pcb_hash_angle(tr, p->rot * rotdir) ^ pcb_hash_coord(p->Clearance) ^ + pcb_hash_str(p->term) ^ crd ^ + murmurhash(&p->smirror, sizeof(p->smirror)) ^ + murmurhash(&p->xmirror, sizeof(p->xmirror)); +} + +/*** utils ***/ + +pcb_pstk_t *pcb_pstk_copy_meta(pcb_pstk_t *dst, pcb_pstk_t *src) +{ + if (dst == NULL) + return NULL; + pcb_attribute_copy_all(&dst->Attributes, &src->Attributes); + dst->thermals.used = src->thermals.used; + if (dst->thermals.used > 0) { + dst->thermals.shape = malloc(dst->thermals.used * sizeof(dst->thermals.shape[0])); + memcpy(dst->thermals.shape, src->thermals.shape, src->thermals.used * sizeof(src->thermals.shape[0])); + } + else + dst->thermals.shape = 0; + memcpy(&dst->Flags, &src->Flags, sizeof(dst->Flags)); + return dst; +} + +pcb_pstk_t *pcb_pstk_copy_orient(pcb_pstk_t *dst, pcb_pstk_t *src) +{ + if (dst == NULL) + return NULL; + dst->rot = src->rot; + dst->xmirror = src->xmirror; + dst->smirror = src->smirror; + dst->protoi = -1; /* invalidate the transformed index to get it recalculated */ + return dst; +} + +void pcb_pstk_move_(pcb_pstk_t *ps, pcb_coord_t dx, pcb_coord_t dy) +{ + ps->x += dx; + ps->y += dy; + ps->BoundingBox.X1 += dx; + ps->BoundingBox.Y1 += dy; + ps->BoundingBox.X2 += dx; + ps->BoundingBox.Y2 += dy; + ps->bbox_naked.X1 += dx; + ps->bbox_naked.Y1 += dy; + ps->bbox_naked.X2 += dx; + ps->bbox_naked.Y2 += dy; +} + +void pcb_pstk_move(pcb_pstk_t *ps, pcb_coord_t dx, pcb_coord_t dy, pcb_bool more_to_come) +{ + pcb_opctx_t ctx; + ctx.move.pcb = NULL; + ctx.move.dx = dx; + ctx.move.dy = dy; + ctx.move.more_to_come = more_to_come; + pcb_pstkop_move(&ctx, ps); +} + +pcb_pstk_t *pcb_pstk_by_id(pcb_data_t *base, long int ID) +{ + /* We can not have an rtree based search here: we are often called + in the middle of an operation, after the pstk got already removed + from the rtree. It happens in e.g. undoable padstack operations + where the padstack tries to look up its parent subc by ID, while + the subc is being sent to the other side. + + The solution will be the ID hash. */ + PCB_PADSTACK_LOOP(base); + { + if (padstack->ID == ID) + return padstack; + } + PCB_END_LOOP; + + return NULL; +} + +/*** draw ***/ + +static void set_ps_color(pcb_pstk_t *ps, int is_current, pcb_layer_type_t lyt, const pcb_layer_t *ly1) +{ + const pcb_color_t *color, *layer_color = NULL; + pcb_color_t buf; + + if ((lyt & PCB_LYT_PASTE) || (lyt & PCB_LYT_MASK) || (lyt & PCB_LYT_SILK)) { + if (ly1 == NULL) + layer_color = pcb_layer_default_color(0, lyt); + else + layer_color = &ly1->meta.real.color; + } + + if (conf_core.appearance.invis_other_groups && !is_current) { + color = &conf_core.appearance.color.invisible_objects; + } + else if (conf_core.appearance.black_current_group && is_current) { + color = pcb_color_black; + } + else if (ps->term == NULL) { + /* normal via, not a terminal */ + if (!pcb_draw_force_termlab && PCB_FLAG_TEST(PCB_FLAG_WARN | PCB_FLAG_SELECTED | PCB_FLAG_FOUND, ps)) { + if (PCB_FLAG_TEST(PCB_FLAG_WARN, ps)) + color = &conf_core.appearance.color.warn; + else if (PCB_FLAG_TEST(PCB_FLAG_SELECTED, ps)) + color = &conf_core.appearance.color.selected; + else + color = &conf_core.appearance.color.connected; + + if (PCB_FLAG_TEST(PCB_FLAG_ONPOINT, ps)) { + pcb_lighten_color(color, &buf, 1.75); + color = &buf; + } + } + else { + if (layer_color != NULL) + color = layer_color; + else if (PCB_HAS_COLOROVERRIDE(ps)) + color = ps->override_color; + else if (is_current) + color = &conf_core.appearance.color.via; + else + color = &conf_core.appearance.color.via_far; + } + } + else { + /* terminal */ + if (!pcb_draw_force_termlab && PCB_FLAG_TEST(PCB_FLAG_WARN | PCB_FLAG_SELECTED | PCB_FLAG_FOUND, ps)) { + if (PCB_FLAG_TEST(PCB_FLAG_WARN, ps)) + color = &conf_core.appearance.color.warn; + else if (PCB_FLAG_TEST(PCB_FLAG_SELECTED, ps)) + color = &conf_core.appearance.color.selected; + else + color = &conf_core.appearance.color.connected; + + if (PCB_FLAG_TEST(PCB_FLAG_ONPOINT, ps)) { + pcb_lighten_color(color, &buf, 1.75); + color = &buf; + } + } + else + if (layer_color != NULL) + color = layer_color; + else if (PCB_HAS_COLOROVERRIDE(ps)) + color = ps->override_color; + else if (is_current) + color = &conf_core.appearance.color.pin; + else + color = &conf_core.appearance.color.pin_far; + + } + + pcb_gui->set_color(pcb_draw_out.fgGC, color); +} + +static void set_ps_annot_color(pcb_hid_gc_t gc, pcb_pstk_t *ps) +{ + pcb_gui->set_color(pcb_draw_out.fgGC, PCB_FLAG_TEST(PCB_FLAG_SELECTED, ps) ? + &conf_core.appearance.color.selected : &conf_core.appearance.color.padstackmark); +} + +static void pcb_pstk_draw_poly(pcb_draw_info_t *info, pcb_hid_gc_t gc, pcb_pstk_t *ps, pcb_pstk_shape_t *shape, int fill, pcb_coord_t dthick) +{ + long n; + + if (shape->data.poly.pa == NULL) + pcb_pstk_shape_update_pa(&shape->data.poly); + pcb_hid_set_line_cap(gc, pcb_cap_round); + if (dthick != 0) { + /* slow - but would be used on export mostly, not on-screen drawing */ + pcb_polo_t *p, p_st[32]; + pcb_coord_t *x, *y, xy_st[64]; + double vl = pcb_round(-dthick/2); + long n; + + if (shape->data.poly.inverted) + dthick = -dthick; + vl = pcb_round(dthick/2); + + if (shape->data.poly.len >= sizeof(p_st) / sizeof(p_st[0])) { + p = malloc(sizeof(pcb_polo_t) * shape->data.poly.len); + x = malloc(sizeof(pcb_coord_t) * shape->data.poly.len); + } + else { + p = p_st; + x = xy_st; + } + y = x + sizeof(p_st) / sizeof(p_st[0]); + + /* relative: move each point radially */ + for(n = 0; n < shape->data.poly.len; n++) { + p[n].x = shape->data.poly.x[n]; + p[n].y = shape->data.poly.y[n]; + } + pcb_polo_norms(p, shape->data.poly.len); + pcb_polo_offs(vl, p, shape->data.poly.len); + for(n = 0; n < shape->data.poly.len; n++) { + x[n] = pcb_round(p[n].x); + y[n] = pcb_round(p[n].y); + } + + if (!fill) { + for(n = 1; n < shape->data.poly.len; n++) + pcb_gui->draw_line(gc, ps->x + x[n-1], ps->y + y[n-1], ps->x + x[n], ps->y + y[n]); + pcb_gui->draw_line(gc, ps->x + x[n-1], ps->y + y[n-1], ps->x + x[0], ps->y + y[0]); + } + else + pcb_gui->fill_polygon_offs(gc, shape->data.poly.len, x, y, ps->x, ps->y); + if (p != p_st) { + free(p); + free(x); + } + } + else { + if (!fill) { + for(n = 1; n < shape->data.poly.len; n++) + pcb_gui->draw_line(gc, ps->x + shape->data.poly.x[n-1], ps->y + shape->data.poly.y[n-1], ps->x + shape->data.poly.x[n], ps->y + shape->data.poly.y[n]); + pcb_gui->draw_line(gc, ps->x + shape->data.poly.x[n-1], ps->y + shape->data.poly.y[n-1], ps->x + shape->data.poly.x[0], ps->y + shape->data.poly.y[0]); + } + else + pcb_gui->fill_polygon_offs(gc, shape->data.poly.len, shape->data.poly.x, shape->data.poly.y, ps->x, ps->y); + } +} + +static void pcb_pstk_draw_shape_solid(pcb_draw_info_t *info, pcb_hid_gc_t gc, pcb_pstk_t *ps, pcb_pstk_shape_t *shape) +{ + pcb_coord_t r, dthick = 0; + if ((info != NULL) && (info->xform != NULL) && (info->xform->bloat != 0)) + dthick = info->xform->bloat; + + switch(shape->shape) { + case PCB_PSSH_POLY: + pcb_pstk_draw_poly(info, gc, ps, shape, 1, dthick); + break; + case PCB_PSSH_LINE: + pcb_hid_set_line_cap(gc, shape->data.line.square ? pcb_cap_square : pcb_cap_round); + pcb_hid_set_line_width(gc, MAX(shape->data.line.thickness + dthick, 1)); + pcb_gui->draw_line(gc, ps->x + shape->data.line.x1, ps->y + shape->data.line.y1, ps->x + shape->data.line.x2, ps->y + shape->data.line.y2); + break; + case PCB_PSSH_CIRC: + r = MAX(shape->data.circ.dia/2 + dthick/2, 1); + pcb_hid_set_line_cap(gc, pcb_cap_round); + pcb_gui->fill_circle(gc, ps->x + shape->data.circ.x, ps->y + shape->data.circ.y, r); + break; + case PCB_PSSH_HSHADOW: + break; + } +} + +static void pcb_pstk_draw_shape_thin(pcb_draw_info_t *info, pcb_hid_gc_t gc, pcb_pstk_t *ps, pcb_pstk_shape_t *shape) +{ + pcb_coord_t r, dthick = 0; + pcb_hid_set_line_cap(gc, pcb_cap_round); + + if ((info != NULL) && (info->xform != NULL) && (info->xform->bloat != 0)) + dthick = info->xform->bloat; + + switch(shape->shape) { + case PCB_PSSH_POLY: + pcb_pstk_draw_poly(info, gc, ps, shape, 0, dthick); + break; + case PCB_PSSH_LINE: + pcb_draw_wireframe_line(gc, ps->x + shape->data.line.x1, ps->y + shape->data.line.y1, ps->x + shape->data.line.x2, ps->y + shape->data.line.y2, MAX(shape->data.line.thickness + dthick, 1), shape->data.line.square); + break; + case PCB_PSSH_CIRC: + r = MAX(shape->data.circ.dia/2 + dthick/2, 1); + pcb_gui->draw_arc(gc, ps->x + shape->data.circ.x, ps->y + shape->data.circ.y, r, r, 0, 360); + break; + case PCB_PSSH_HSHADOW: + break; + } +} + +pcb_r_dir_t pcb_pstk_draw_callback(const pcb_box_t *b, void *cl) +{ + pcb_draw_info_t *info = cl; + pcb_pstk_t *ps = (pcb_pstk_t *)b; + pcb_pstk_shape_t *shape; + pcb_layergrp_t *grp = NULL; + + if (pcb_hidden_floater((pcb_any_obj_t*)b)) + return PCB_R_DIR_FOUND_CONTINUE; + + if (!PCB->SubcPartsOn && pcb_gobj_parent_subc(ps->parent_type, &ps->parent)) + return PCB_R_DIR_NOT_FOUND; + + if (info->objcb.pstk.gid < 0) { + if (info->objcb.pstk.shape_mask != 0) + shape = pcb_pstk_shape(ps, info->objcb.pstk.shape_mask, info->objcb.pstk.comb); + else + return PCB_R_DIR_NOT_FOUND; + } + else { + int n; + pcb_layer_id_t *lid; + shape = pcb_pstk_shape_gid(info->pcb, ps, info->objcb.pstk.gid, info->objcb.pstk.comb, &grp); + for(n = 0, lid = grp->lid; n < grp->len; n++,lid++) { + if (*lid < ps->thermals.used) { + if ((ps->thermals.shape[*lid] & PCB_THERMAL_ON) && ((ps->thermals.shape[*lid] & 3) == PCB_THERMAL_NOSHAPE)) + return PCB_R_DIR_NOT_FOUND; + } + } + } + + if (shape != NULL) { + if (grp == NULL) + set_ps_color(ps, info->objcb.pstk.is_current, info->objcb.pstk.shape_mask, info->objcb.pstk.layer1); + else + set_ps_color(ps, info->objcb.pstk.is_current, grp->ltype, info->objcb.pstk.layer1); + if (conf_core.editor.thin_draw || conf_core.editor.wireframe_draw) { + pcb_hid_set_line_width(pcb_draw_out.fgGC, 0); + pcb_pstk_draw_shape_thin(info, pcb_draw_out.fgGC, ps, shape); + } + else + pcb_pstk_draw_shape_solid(info, pcb_draw_out.fgGC, ps, shape); + } + + return PCB_R_DIR_FOUND_CONTINUE; +} + +pcb_r_dir_t pcb_pstk_draw_mark_callback(const pcb_box_t *b, void *cl) +{ + pcb_pstk_t *ps = (pcb_pstk_t *)b; + pcb_pstk_proto_t *proto; + pcb_coord_t mark, mark2; + + /* mark is a cross in the middle, right on the hole; + cross size should extend beyond the hole */ + pcb_hid_set_line_cap(pcb_draw_out.fgGC, pcb_cap_round); + mark = conf_core.appearance.padstack.cross_size; + proto = pcb_pstk_get_proto(ps); + if (proto != NULL) + mark += proto->hdia/2; + + mark2 = mark*2; + if (mark2 < pcb_gui->coord_per_pix) + return PCB_R_DIR_FOUND_CONTINUE; + + /* draw the cross using xor */ + set_ps_annot_color(pcb_draw_out.fgGC, ps); + pcb_hid_set_line_width(pcb_draw_out.fgGC, 0); + if (mark2 > pcb_gui->coord_per_pix*3) { + pcb_gui->draw_line(pcb_draw_out.fgGC, ps->x-mark, ps->y, ps->x+mark, ps->y); + pcb_gui->draw_line(pcb_draw_out.fgGC, ps->x, ps->y-mark, ps->x, ps->y+mark); + } + else + pcb_gui->draw_line(pcb_draw_out.fgGC, ps->x-pcb_gui->coord_per_pix, ps->y, ps->x+pcb_gui->coord_per_pix, ps->y); + + return PCB_R_DIR_FOUND_CONTINUE; +} + +pcb_r_dir_t pcb_pstk_draw_label_callback(const pcb_box_t *b, void *cl) +{ + pcb_draw_info_t *info = cl; + pcb_pstk_t *ps = (pcb_pstk_t *)b; + + /* draw the label if enabled, after everything else is drawn */ + if (ps->term != NULL) { + if ((pcb_draw_force_termlab) || PCB_FLAG_TEST(PCB_FLAG_TERMNAME, ps)) + pcb_pstk_draw_label(info, ps); + } + return PCB_R_DIR_FOUND_CONTINUE; +} + +pcb_r_dir_t pcb_pstk_draw_hole_callback(const pcb_box_t *b, void *cl) +{ + pcb_draw_info_t *info = cl; + pcb_pstk_t *ps = (pcb_pstk_t *)b; + pcb_pstk_proto_t *proto; + + /* hide subc parts if requested */ + if (!info->pcb->SubcPartsOn && pcb_gobj_parent_subc(ps->parent_type, &ps->parent)) + return PCB_R_DIR_NOT_FOUND; + + /* no hole in this layer group */ + if (info->objcb.pstk.gid >= 0) { + if (!pcb_pstk_bb_drills(info->pcb, ps, info->objcb.pstk.gid, &proto)) + return PCB_R_DIR_FOUND_CONTINUE; + } + else + proto = pcb_pstk_get_proto(ps); + + /* No hole at all */ + if ((proto == NULL) || (proto->hdia <= 0)) + return PCB_R_DIR_NOT_FOUND; + + /* hole is plated, but the caller doesn't want plated holes */ + if (proto->hplated && (!(info->objcb.pstk.holetype & PCB_PHOLE_PLATED))) + return PCB_R_DIR_NOT_FOUND; + + /* hole is unplated, but the caller doesn't want unplated holes */ + if (!proto->hplated && (!(info->objcb.pstk.holetype & PCB_PHOLE_UNPLATED))) + return PCB_R_DIR_NOT_FOUND; + + /* BBvia, but the caller doesn't want BBvias */ + if (((proto->htop != 0) || (proto->hbottom != 0)) && (!(info->objcb.pstk.holetype & PCB_PHOLE_BB))) + return PCB_R_DIR_NOT_FOUND; + + /* actual hole */ + pcb_hid_set_line_width(pcb_draw_out.drillGC, 0); + pcb_hid_set_line_cap(pcb_draw_out.drillGC, pcb_cap_round); + pcb_gui->fill_circle(pcb_draw_out.drillGC, ps->x, ps->y, proto->hdia / 2); + + /* indicate unplated holes with an arc; unplated holes are more rare + than plated holes, thus unplated holes are indicated */ + if (!proto->hplated) { + pcb_coord_t r = proto->hdia / 2; + r -= r/8; /* +12.5% */ + pcb_gui->set_color(pcb_draw_out.fgGC, PCB_FLAG_TEST(PCB_FLAG_SELECTED, ps) ? &conf_core.appearance.color.selected : &conf_core.appearance.color.subc); + pcb_hid_set_line_width(pcb_draw_out.fgGC, 0); + pcb_gui->draw_arc(pcb_draw_out.fgGC, ps->x, ps->y, r, r, 20, 290); + } + + return PCB_R_DIR_FOUND_CONTINUE; +} + +pcb_r_dir_t pcb_pstk_draw_slot_callback(const pcb_box_t *b, void *cl) +{ + pcb_draw_info_t *info = cl; + pcb_pstk_t *ps = (pcb_pstk_t *)b; + pcb_pstk_proto_t *proto; + pcb_pstk_shape_t *shape; + + /* hide subc parts if requested */ + if (!info->pcb->SubcPartsOn && pcb_gobj_parent_subc(ps->parent_type, &ps->parent)) + return PCB_R_DIR_NOT_FOUND; + + /* no slot in this layer group */ + if (info->objcb.pstk.gid >= 0) { + if (!pcb_pstk_bb_drills(info->pcb, ps, info->objcb.pstk.gid, &proto)) + return PCB_R_DIR_FOUND_CONTINUE; + } + else + proto = pcb_pstk_get_proto(ps); + + /* No slot at all */ + if (proto->mech_idx < 0) + return PCB_R_DIR_NOT_FOUND; + + /* hole is plated, but the caller doesn't want plated holes */ + if (proto->hplated && (!(info->objcb.pstk.holetype & PCB_PHOLE_PLATED))) + return PCB_R_DIR_NOT_FOUND; + + /* hole is unplated, but the caller doesn't want unplated holes */ + if (!proto->hplated && (!(info->objcb.pstk.holetype & PCB_PHOLE_UNPLATED))) + return PCB_R_DIR_NOT_FOUND; + + /* BBslot, but the caller doesn't want BBslot */ + if (((proto->htop != 0) || (proto->hbottom != 0)) && (!(info->objcb.pstk.holetype & PCB_PHOLE_BB))) + return PCB_R_DIR_NOT_FOUND; + + /* actual slot */ + shape = pcb_pstk_shape(ps, PCB_LYT_MECH, PCB_LYC_AUTO); + if (shape != NULL) { + if (conf_core.editor.thin_draw || conf_core.editor.wireframe_draw) { + pcb_hid_set_line_width(pcb_draw_out.drillGC, 0); + pcb_pstk_draw_shape_thin(info, pcb_draw_out.drillGC, ps, shape); + } + else + pcb_pstk_draw_shape_solid(info, pcb_draw_out.drillGC, ps, shape); + } + + return PCB_R_DIR_FOUND_CONTINUE; +} + +void pcb_pstk_thindraw(pcb_draw_info_t *info, pcb_hid_gc_t gc, pcb_pstk_t *ps) +{ + pcb_pstk_shape_t *shape = NULL; + pcb_board_t *pcb; + pcb_layergrp_id_t gid = CURRENT->meta.real.grp; + + pcb = pcb_data_get_top(ps->parent.data); + if (pcb != NULL) { + shape = pcb_pstk_shape_gid(pcb, ps, gid, 0, NULL); + if (shape == NULL) + shape = pcb_pstk_shape_gid(pcb, ps, gid, PCB_LYC_SUB, NULL); + } + else { /* no pcb means buffer - take the first shape, whichever layer it is for */ + pcb_pstk_tshape_t *ts = pcb_pstk_get_tshape(ps); + if ((ts != NULL) && (ts->len > 0)) + shape = ts->shape; + } + + if (shape != NULL) + pcb_pstk_draw_shape_thin(info, gc, ps, shape); +} + +void pcb_pstk_draw_label(pcb_draw_info_t *info, pcb_pstk_t *ps) +{ + pcb_bool vert; + pcb_coord_t dx, dy; + + if (ps->term == NULL) + return; + + dx = ps->BoundingBox.X2 - ps->BoundingBox.X1; + dy = ps->BoundingBox.Y2 - ps->BoundingBox.Y1; + if ((dx == 0) && (dy == 0)) { + pcb_pstk_bbox(ps); + dx = ps->BoundingBox.X2 - ps->BoundingBox.X1; + dy = ps->BoundingBox.Y2 - ps->BoundingBox.Y1; + } + + vert = dx < dy; +#ifdef PCB_PSTK_LABEL_OFFCENTER + pcb_coord_t offs = 0; + pcb_pstk_proto_t *proto; + proto = pcb_pstk_get_proto(ps); + if ((proto != NULL) && (proto->hdia > 0)) + offs = proto->hdia/2; + pcb_term_label_draw(info, ps->x + offs, ps->y, conf_core.appearance.term_label_size, vert, pcb_false, (pcb_any_obj_t *)ps); +#endif + pcb_term_label_draw(info, ps->x, ps->y, conf_core.appearance.term_label_size, vert, pcb_true, (pcb_any_obj_t *)ps); +} + +void pcb_pstk_draw_preview(pcb_board_t *pcb, const pcb_pstk_t *ps, char *layers, pcb_bool mark, pcb_bool label, const pcb_box_t *drawn_area) +{ + pcb_draw_info_t info; + int n, draw_hole = 0; + pcb_layer_id_t lid; + + info.pcb = pcb; + info.drawn_area = drawn_area; + info.xform_caller = info.xform_exporter = info.xform = NULL; + info.layer = NULL; + info.objcb.pstk.gid = -1; + info.objcb.pstk.holetype = PCB_PHOLE_UNPLATED | PCB_PHOLE_PLATED; + + /* draw non-currents */ + info.objcb.pstk.is_current = 0; + for(n = pcb_proto_num_layers-1; n >= 0; n--) { + if ((layers == NULL) || (layers[n] == 1)) { + info.objcb.pstk.shape_mask = pcb_proto_layers[n].mask; + info.objcb.pstk.comb = pcb_proto_layers[n].comb; + info.objcb.pstk.layer1 = info.layer = NULL; + if (!(info.objcb.pstk.shape_mask & PCB_LYT_COPPER)) { + if (pcb_layer_list(pcb, info.objcb.pstk.shape_mask, &lid, 1) == 1) + info.objcb.pstk.layer1 = info.layer = pcb_get_layer(pcb->Data, lid); + } + if (info.objcb.pstk.shape_mask == PCB_LYT_MECH) + draw_hole = 1; + else + pcb_pstk_draw_callback((pcb_box_t *)ps, &info); + } + } + + /* draw current with strong */ + info.objcb.pstk.is_current = 1; + for(n = pcb_proto_num_layers-1; n >= 0; n--) { + if ((layers == NULL) || (layers[n] > 1)) { + info.objcb.pstk.shape_mask = pcb_proto_layers[n].mask; + info.objcb.pstk.comb = pcb_proto_layers[n].comb; + info.objcb.pstk.layer1 = info.layer = NULL; + if (!(info.objcb.pstk.shape_mask & PCB_LYT_COPPER)) { + if (pcb_layer_list(pcb, info.objcb.pstk.shape_mask, &lid, 1) == 1) + info.objcb.pstk.layer1 = info.layer = pcb_get_layer(pcb->Data, lid); + } + if (info.objcb.pstk.shape_mask == PCB_LYT_MECH) + draw_hole = 2; + else + pcb_pstk_draw_callback((pcb_box_t *)ps, &info); + } + } + + if (draw_hole) { + info.objcb.pstk.shape_mask = PCB_LYT_MECH; + info.objcb.pstk.is_current = (draw_hole > 1); + pcb_pstk_draw_hole_callback((pcb_box_t *)ps, &info); + } + + if (mark) + pcb_pstk_draw_mark_callback((pcb_box_t *)ps, &info); + + if (label) + pcb_pstk_draw_label_callback((pcb_box_t *)ps, &info); +} + + + +void pcb_pstk_invalidate_erase(pcb_pstk_t *ps) +{ + pcb_draw_invalidate(ps); +} + +void pcb_pstk_invalidate_draw(pcb_pstk_t *ps) +{ + pcb_draw_invalidate(ps); +} + + +static int pcb_pstk_near_box_(pcb_pstk_t *ps, pcb_box_t *box, pcb_pstk_shape_t *shape) +{ + pcb_any_line_t pad; + pcb_vector_t v; + pcb_pstk_proto_t *proto = pcb_pstk_get_proto(ps); + int isneg = PCB_IS_BOX_NEGATIVE(box), is_in, n; + + /* cheap check: hole */ + if (proto->hdia > 0) { + /* in negative case, touching the hole means hit */ + if (isneg) + if (PCB_CIRCLE_TOUCHES_BOX(ps->x, ps->y, proto->hdia/2, box)) + return 1; + + /* in positive case, not including the hole means bad */ + if (!isneg) + if (!PCB_POINT_IN_BOX(ps->x-proto->hdia/2,ps->y-proto->hdia/2, box) || + !PCB_POINT_IN_BOX(ps->x+proto->hdia/2,ps->y+proto->hdia/2, box)) + return 0; + } + + switch(shape->shape) { + case PCB_PSSH_CIRC: + if (isneg) + return PCB_CIRCLE_TOUCHES_BOX(ps->x + shape->data.circ.x, ps->y + shape->data.circ.y, shape->data.circ.dia/2, box); + return + PCB_POINT_IN_BOX(ps->x+shape->data.circ.x-proto->hdia/2,ps->y+shape->data.circ.y-shape->data.circ.dia/2, box) && + PCB_POINT_IN_BOX(ps->x+shape->data.circ.x+proto->hdia/2,ps->y+shape->data.circ.y+shape->data.circ.dia/2, box); + case PCB_PSSH_LINE: + pad.Point1.X = shape->data.line.x1 + ps->x; + pad.Point1.Y = shape->data.line.y1 + ps->y; + pad.Point2.X = shape->data.line.x2 + ps->x; + pad.Point2.Y = shape->data.line.y2 + ps->y; + pad.Thickness = shape->data.line.thickness; + pad.Clearance = 0; + pad.Flags = pcb_flag_make(shape->data.line.square ? PCB_FLAG_SQUARE : 0); + return isneg ? PCB_PAD_TOUCHES_BOX(&pad, box) : PCB_PAD_IN_BOX(&pad, box); + + case PCB_PSSH_HSHADOW: + return 0; + + case PCB_PSSH_POLY: + if (shape->data.poly.pa == NULL) + pcb_pstk_shape_update_pa(&shape->data.poly); + + if (isneg) { + /* shortcut: if any point is in our box in negative, we are done */ + for(n = 0; n < shape->data.poly.len; n++) { + int pib = PCB_POINT_IN_BOX(ps->x + shape->data.poly.x[n], ps->y + shape->data.poly.y[n], box); + if (pib) + return 1; + } + } + + /* fully within */ + is_in = 1; + for(n = 0; n < shape->data.poly.len; n++) { + int pib = PCB_POINT_IN_BOX(ps->x + shape->data.poly.x[n], ps->y + shape->data.poly.y[n], box); + if (!pib) { + is_in = 0; + break; + } + } + + if (!isneg) /* normal box - accept only if we are in */ + return is_in; + + /* negative box, not fully within, no poly point in the box, check whether + the box is fully within the poly - if any of it's corners is in */ + v[0] = box->X1 - ps->x; + v[1] = box->Y1 - ps->y; + if (pcb_polyarea_contour_inside(shape->data.poly.pa, v)) + return 1; + + + /* negative box, not fully within, no poly point in the box, check whether + box lines intersect poly lines + We expect shapes to be simple so linear search is faster than + being clever */ + for(n = 1; n < shape->data.poly.len; n++) { + if (PCB_XYLINE_ISECTS_BOX(ps->x+shape->data.poly.x[n-1],ps->y+shape->data.poly.y[n-1],ps->x+shape->data.poly.x[n],ps->y+shape->data.poly.y[n], box)) + return 1; + } + + n = shape->data.poly.len-1; + if (PCB_XYLINE_ISECTS_BOX(ps->x+shape->data.poly.x[n-1],ps->y+shape->data.poly.y[n-1],ps->x+shape->data.poly.x[0],ps->y+shape->data.poly.y[0], box)) + return 1; + } + + return 0; +} + +#define HOLE_IN_BOX(ps, dia, b) \ + ( \ + PCB_POINT_IN_BOX((ps)->x - dia/2, (ps)->y - dia/2, (b)) && \ + PCB_POINT_IN_BOX((ps)->x + dia/2, (ps)->y + dia/2, (b)) \ + ) + +#define HOLE_TOUCHES_BOX(ps, dia, b) \ + PCB_CIRCLE_TOUCHES_BOX((ps)->x, (ps)->y, dia/2, (b)) + +int pcb_pstk_near_box(pcb_pstk_t *ps, pcb_box_t *box, pcb_layer_t *layer) +{ + pcb_pstk_shape_t *shp; + pcb_pstk_tshape_t *tshp = pcb_pstk_get_tshape(ps); + + /* special case: no-shape padstack is used for hole */ + if ((tshp == NULL) || (tshp->len == 0)) { + pcb_pstk_proto_t *proto = pcb_pstk_get_proto(ps); + if (proto->hdia <= 0) + return 0; + return (PCB_IS_BOX_NEGATIVE(box) ? HOLE_TOUCHES_BOX(ps, proto->hdia, box) : HOLE_IN_BOX(ps, proto->hdia, box)); + } + + /* no layer means: "is any shape near?" */ + if (layer == NULL) { + int n; + + if (tshp == NULL) + return 0; + + for(n = 0; n < tshp->len; n++) + if (pcb_pstk_near_box_(ps, box, &tshp->shape[n]) != 0) + return 1; + return 0; + } + + /* else check only on the specific layer */ + shp = pcb_pstk_shape(ps, pcb_layer_flags_(layer), layer->comb); + if (shp == NULL) + return 0; + return pcb_pstk_near_box_(ps, box, shp); +} + +static int pcb_is_point_in_pstk_(pcb_pstk_t *ps, pcb_coord_t x, pcb_coord_t y, pcb_coord_t radius, pcb_pstk_shape_t *shape) +{ + pcb_any_line_t pad; + pcb_vector_t v; + + switch(shape->shape) { + case PCB_PSSH_HSHADOW: + return 0; + case PCB_PSSH_CIRC: + return PCB_POINT_IN_CIRCLE(x, y, ps->x + shape->data.circ.x, ps->y + shape->data.circ.y, shape->data.circ.dia/2 + radius); + case PCB_PSSH_LINE: + pad.Point1.X = shape->data.line.x1 + ps->x; + pad.Point1.Y = shape->data.line.y1 + ps->y; + pad.Point2.X = shape->data.line.x2 + ps->x; + pad.Point2.Y = shape->data.line.y2 + ps->y; + pad.Thickness = shape->data.line.thickness; + pad.Clearance = 0; + pad.Flags = pcb_flag_make(shape->data.line.square ? PCB_FLAG_SQUARE : 0); + return pcb_is_point_in_line(x, y, radius, &pad); + case PCB_PSSH_POLY: + if (shape->data.poly.pa == NULL) + pcb_pstk_shape_update_pa(&shape->data.poly); + v[0] = x - ps->x; + v[1] = y - ps->y; + return pcb_polyarea_contour_inside(shape->data.poly.pa, v); + } + + return 0; +} + +int pcb_is_point_in_pstk(pcb_coord_t x, pcb_coord_t y, pcb_coord_t radius, pcb_pstk_t *ps, pcb_layer_t *layer) +{ + pcb_pstk_shape_t *shp; + pcb_pstk_proto_t *proto = pcb_pstk_get_proto(ps); + + /* cheap check: hole clicked (also necessary for a mounting hole too) */ + if (proto->hdia > 0) { + double dist2 = SQR((double)x - (double)ps->x) + SQR((double)y - (double)ps->y); + if (dist2 <= SQR((double)radius + (double)proto->hdia/2.0)) + return 1; + } + + /* no layer means: "is point in any shape?" */ + if (layer == NULL) { + int n; + pcb_pstk_tshape_t *tshp = pcb_pstk_get_tshape(ps); + + if (tshp == NULL) + return 0; + + for(n = 0; n < tshp->len; n++) + if (pcb_is_point_in_pstk_(ps, x, y, radius, &tshp->shape[n]) != 0) + return 1; + return 0; + } + + /* else check only on the specific layer */ + shp = pcb_pstk_shape(ps, pcb_layer_flags_(layer), layer->comb); + if (shp == NULL) + return 0; + return pcb_is_point_in_pstk_(ps, x, y, radius, shp); +} + +int pcb_pstk_drc_check_clearance(pcb_pstk_t *ps, pcb_poly_t *polygon, pcb_coord_t min_clr) +{ + int n; + pcb_pstk_tshape_t *ts; + + /* global clearance */ + if (ps->Clearance > 0) + return ps->Clearance < 2 * conf_core.design.bloat; + + /* else check each shape; it's safest to run this check on the canonical + transformed shape, that's always available */ + ts = pcb_pstk_get_tshape_(ps->parent.data, ps->proto, 0); + for(n = 0; n < ts->len; n++) + if ((ts->shape[n].clearance > 0) && (ts->shape[n].clearance < 2 * conf_core.design.bloat)) + return 1; + + return 0; +} + +/* Check the minimum distance between a hole's edge and a shape's edge and + indicate error if it's smaller than min */ +static pcb_bool pcb_pstk_shape_hole_break(pcb_pstk_shape_t *shp, pcb_coord_t hdia, pcb_coord_t min) +{ + double dist, neck, mindist2, dist2; + pcb_line_t line; + int n; + + switch(shp->shape) { + case PCB_PSSH_HSHADOW: + break; + case PCB_PSSH_CIRC: + dist = sqrt((double)shp->data.circ.x*(double)shp->data.circ.x + (double)shp->data.circ.y*(double)shp->data.circ.y); + neck = (double)(shp->data.circ.dia - hdia) / 2.0 - dist; + break; + case PCB_PSSH_LINE: + line.Point1.X = shp->data.line.x1; + line.Point1.Y = shp->data.line.y1; + line.Point2.X = shp->data.line.x2; + line.Point2.Y = shp->data.line.y2; + line.Thickness = shp->data.line.thickness; + dist = sqrt(pcb_point_line_dist2(0, 0, &line)); + neck = (double)(shp->data.line.thickness - hdia) / 2.0 - dist; + break; + case PCB_PSSH_POLY: + /* square of the minimal distance required for a neck */ + mindist2 = hdia/2 + min; + mindist2 *= mindist2; + + /* cheapest test: if any corner is closer to the hole than min, we are doomed */ + for(n = 0; n < shp->data.poly.len; n++) { + dist2 = (double)shp->data.poly.x[n] * (double)shp->data.poly.x[n] + (double)shp->data.poly.y[n] * (double)shp->data.poly.y[n]; + if (dist2 < mindist2) + return 1; + } + + /* more expensive: check each edge */ + line.Point1.X = shp->data.poly.x[shp->data.poly.len - 1]; + line.Point1.Y = shp->data.poly.y[shp->data.poly.len - 1]; + line.Thickness = 1; + + for(n = 0; n < shp->data.poly.len; n++) { + line.Point2.X = shp->data.poly.x[n]; + line.Point2.Y = shp->data.poly.y[n]; + + dist2 = pcb_point_line_dist2(0, 0, &line); + if (dist2 < mindist2) + return 1; + + /* shift coords for the next iteration */ + line.Point1.X = line.Point2.X; + line.Point1.Y = line.Point2.Y; + } + return 0; /* survived all tests: we are fine! */ + } + + return neck < min; +} + +void pcb_pstk_drc_check_and_warn(pcb_pstk_t *ps, pcb_coord_t *err_minring, pcb_coord_t *err_minhole) +{ + pcb_pstk_proto_t *proto = pcb_pstk_get_proto(ps); + + if (proto->hdia >= 0) { + int n; + pcb_pstk_tshape_t *ts = pcb_pstk_get_tshape_(ps->parent.data, ps->proto, 0); + + for(n = 0; n < ts->len; n++) { + if (!(ts->shape[n].layer_mask & PCB_LYT_COPPER)) + continue; /* only copper shapes can break */ + if (pcb_pstk_shape_hole_break(&ts->shape[n], proto->hdia, conf_core.design.min_ring)) { + (*err_minring)++; + break; + } + } + } + +TODO("slot: check if slot breaks other shapes") + + if ((proto->hdia > 0) && (proto->hdia < conf_core.design.min_drill)) + *err_minhole = proto->hdia; +} + +void pcb_pstk_mirror(pcb_pstk_t *ps, pcb_coord_t y_offs, int swap_side, int disable_xmirror) +{ + int xmirror = !ps->xmirror, smirror = (swap_side ? (!ps->smirror) : ps->smirror); + + + /* change the mirror flag - this will automatically cause mirroring in + every aspect */ + if (disable_xmirror) + pcb_pstk_change_instance(ps, NULL, NULL, NULL, NULL, &smirror); + else + pcb_pstk_change_instance(ps, NULL, NULL, NULL, &xmirror, &smirror); + + /* if mirror center is not 0, also move, to emulate that the mirror took + place around that point */ + if (((y_offs != 0) || (ps->y != 0)) && (y_offs != PCB_PSTK_DONT_MIRROR_COORDS)) { + pcb_poly_restore_to_poly(ps->parent.data, PCB_OBJ_PSTK, NULL, ps); + pcb_pstk_invalidate_erase(ps); + if (ps->parent.data->padstack_tree != NULL) + pcb_r_delete_entry(ps->parent.data->padstack_tree, (pcb_box_t *)ps); + + ps->y = PCB_SWAP_Y(ps->y) + y_offs; + pcb_pstk_bbox(ps); + + if (ps->parent.data->padstack_tree != NULL) + pcb_r_insert_entry(ps->parent.data->padstack_tree, (pcb_box_t *)ps); + pcb_poly_clear_from_poly(ps->parent.data, PCB_OBJ_PSTK, NULL, ps); + pcb_pstk_invalidate_draw(ps); + } +} + +void pcb_pstk_scale(pcb_pstk_t *ps, double sx, double sy) +{ + pcb_pstk_proto_t *prt; + pcb_pstk_tshape_t *tshp; + int n; + + if ((sx == 1.0) && (sy == 1.0)) + return; + + pcb_pstk_pre(ps); + + prt = malloc(sizeof(pcb_pstk_proto_t)); + pcb_pstk_proto_copy(prt, pcb_pstk_get_proto(ps)); + + /* after the copy we have the canonical transformed shape only; scale each shape in it */ + tshp = &prt->tr.array[0]; + for(n = 0; n < tshp->len; n++) + pcb_pstk_shape_scale(&tshp->shape[n], sx, sy); + + if (prt->hdia > 0.0) + prt->hdia = pcb_round((double)prt->hdia * ((sx+sy)/2.0)); + + pcb_pstk_proto_update(prt); + ps->proto = pcb_pstk_proto_insert_or_free(ps->parent.data, prt, 1); + + if (sx != 1.0) + ps->x = pcb_round((double)ps->x * sx); + + if (sy != 1.0) + ps->y = pcb_round((double)ps->y * sy); + + pcb_pstk_post(ps); +} + +unsigned char *pcb_pstk_get_thermal(pcb_pstk_t *ps, unsigned long lid, pcb_bool_t alloc) +{ + if (ps->thermals.used <= lid) { + unsigned long oldu = ps->thermals.used; + if (!alloc) + return NULL; + ps->thermals.used = lid+1; + ps->thermals.shape = realloc(ps->thermals.shape, ps->thermals.used); + memset(ps->thermals.shape + oldu, 0, ps->thermals.used - oldu); + } + return ps->thermals.shape + lid; +} + +void pcb_pstk_set_thermal(pcb_pstk_t *ps, unsigned long lid, unsigned char shape) +{ + unsigned char *th = pcb_pstk_get_thermal(ps, lid, 1); + if (th != NULL) + *th = shape; +} + +/*** Undoable instance parameter change ***/ + +typedef struct { + long int parent_ID; /* -1 for pcb, positive for a subc */ + long int ID; /* ID of the padstack */ + + pcb_cardinal_t proto; + pcb_coord_t clearance; + double rot; + int xmirror, smirror; +} padstack_change_instance_t; + +#define swap(a,b,type) \ + do { \ + type tmp = a; \ + a = b; \ + b = tmp; \ + } while(0) + +pcb_data_t *pcb_pstk_data_hack = NULL; + +static int undo_change_instance_swap(void *udata) +{ + padstack_change_instance_t *u = udata; + pcb_data_t *data; + pcb_pstk_t *ps; + + /* data is either parent subc's data or board's data */ + if (u->parent_ID != -1) { + pcb_subc_t *subc; + int n; + + /* Look up the parent subc by ID; on the board, in the hack-data and in all buffers */ + subc = pcb_subc_by_id(PCB->Data, u->parent_ID); + if ((subc == NULL) && (pcb_pstk_data_hack != NULL)) + subc = pcb_subc_by_id(pcb_pstk_data_hack, u->parent_ID); + for(n = 0; (subc == NULL) && (n < PCB_MAX_BUFFER); n++) + subc = pcb_subc_by_id(pcb_buffers[n].Data, u->parent_ID); + if (subc == NULL) { + pcb_message(PCB_MSG_ERROR, "Can't undo padstack change: parent subc #%ld is not found\n", u->parent_ID); + return -1; + } + data = subc->data; + } + else + data = PCB->Data; + + ps = pcb_pstk_by_id(data, u->ID); + if (ps == NULL) { + pcb_message(PCB_MSG_ERROR, "Can't undo padstack change: padstack ID #%ld is not available\n", u->ID); + return -1; + } + + pcb_poly_restore_to_poly(ps->parent.data, PCB_OBJ_PSTK, NULL, ps); + pcb_pstk_invalidate_erase(ps); + if (ps->parent.data->padstack_tree != NULL) + pcb_r_delete_entry(ps->parent.data->padstack_tree, (pcb_box_t *)ps); + + swap(ps->proto, u->proto, pcb_cardinal_t); + swap(ps->Clearance, u->clearance, pcb_coord_t); + swap(ps->rot, u->rot, double); + swap(ps->xmirror, u->xmirror, int); + swap(ps->smirror, u->smirror, int); + + /* force re-render the prototype */ + ps->protoi = -1; + pcb_pstk_get_tshape(ps); + + pcb_pstk_bbox(ps); + if (ps->parent.data->padstack_tree != NULL) + pcb_r_insert_entry(ps->parent.data->padstack_tree, (pcb_box_t *)ps); + pcb_poly_clear_from_poly(ps->parent.data, PCB_OBJ_PSTK, NULL, ps); + pcb_pstk_invalidate_draw(ps); + + return 0; +} + +static void undo_change_instance_print(void *udata, char *dst, size_t dst_len) +{ + padstack_change_instance_t *u = udata; + pcb_snprintf(dst, dst_len, "padstack change: clearance=%$mm rot=%.2f xmirror=%d smirror=%d\n", u->clearance, u->rot, u->xmirror, u->smirror); +} + +static const uundo_oper_t undo_pstk_change_instance = { + core_pstk_cookie, + NULL, /* free */ + undo_change_instance_swap, + undo_change_instance_swap, + undo_change_instance_print +}; + +int pcb_pstk_change_instance(pcb_pstk_t *ps, pcb_cardinal_t *proto, const pcb_coord_t *clearance, double *rot, int *xmirror, int *smirror) +{ + padstack_change_instance_t *u; + long int parent_ID; + pcb_opctx_t ctx; + + if (ps->ID <= 0) { /* off-board padstack: undo and clipping disabled */ + if (proto != NULL) ps->proto = *proto; + if (clearance != NULL) ps->Clearance = *clearance; + if (rot != NULL) ps->rot = *rot; + if (xmirror != NULL) ps->xmirror = *xmirror; + if (smirror != NULL) ps->xmirror = *smirror; + pcb_pstk_bbox(ps); + return 0; + } + + switch(ps->parent.data->parent_type) { + case PCB_PARENT_INVALID: + /* happens if parent is a buffer: do not undo operations done on the buffer */ + ps->proto = proto ? *proto : ps->proto; + ps->Clearance = clearance ? *clearance : ps->Clearance; + ps->rot = rot ? *rot : ps->rot; + ps->xmirror = xmirror ? *xmirror : ps->xmirror; + ps->smirror = smirror ? *smirror : ps->smirror; + + /* re-render the prototype so the new shape is generated and cached */ + ps->protoi = -1; + pcb_pstk_get_tshape(ps); + return 0; + case PCB_PARENT_BOARD: parent_ID = -1; break; + case PCB_PARENT_SUBC: parent_ID = ps->parent.data->parent.subc->ID; break; + default: return -1; + } + + ctx.clip.clear = 0; + ctx.clip.restore = 1; + pcb_pstkop_clip(&ctx, ps); + + u = pcb_undo_alloc(PCB, &undo_pstk_change_instance, sizeof(padstack_change_instance_t)); + u->parent_ID = parent_ID; + u->ID = ps->ID; + u->proto = proto ? *proto : ps->proto; + u->clearance = clearance ? *clearance : ps->Clearance; + u->rot = rot ? *rot : ps->rot; + u->xmirror = xmirror ? *xmirror : ps->xmirror; + u->smirror = smirror ? *smirror : ps->smirror; + + pcb_pstk_bbox(ps); + ctx.clip.clear = 1; + ctx.clip.restore = 0; + pcb_pstkop_clip(&ctx, ps); + + + undo_change_instance_swap(u); + + pcb_undo_inc_serial(); + return 0; +} + +pcb_bool pcb_pstk_is_group_empty(pcb_board_t *pcb, pcb_layergrp_id_t gid) +{ + pcb_layergrp_t *g = &pcb->LayerGroups.grp[gid]; + + PCB_PADSTACK_LOOP(pcb->Data); { + pcb_cardinal_t n; + for(n = 0; n < g->len; n++) + if (pcb_pstk_shape_at(pcb, padstack, &pcb->Data->Layer[g->lid[n]])) + return pcb_false; + } + PCB_END_LOOP; + return pcb_true; +} + + +#include "obj_pstk_op.c" + +void pcb_pstk_rotate90(pcb_pstk_t *pstk, pcb_coord_t cx, pcb_coord_t cy, int steps) +{ + pcb_opctx_t ctx; + + ctx.rotate.center_x = cx; + ctx.rotate.center_y = cy; + ctx.rotate.number = steps; + pcb_pstkop_rotate90(&ctx, pstk); +} + +void pcb_pstk_rotate(pcb_pstk_t *pstk, pcb_coord_t cx, pcb_coord_t cy, double cosa, double sina, double angle) +{ + pcb_opctx_t ctx; + + ctx.rotate.center_x = cx; + ctx.rotate.center_y = cy; + ctx.rotate.angle = angle; + ctx.rotate.cosa = cosa; + ctx.rotate.sina = sina; + pcb_pstkop_rotate(&ctx, pstk); +} + +pcb_coord_t obj_pstk_get_clearance(pcb_board_t *pcb, pcb_pstk_t *ps, pcb_layer_t *layer) +{ + pcb_pstk_shape_t *shp; + + if (!PCB_FLAG_TEST(PCB_FLAG_CLEARLINE, ps)) + return 0; + + if (ps->Clearance > 0) /* global clarance overrides */ + return ps->Clearance; + + shp = pcb_pstk_shape_at(pcb, ps, layer); + return shp->clearance; +} + +void pcb_pstk_pre(pcb_pstk_t *pstk) +{ + pcb_data_t *data = pstk->parent.data; + if (data->padstack_tree != NULL) + pcb_r_delete_entry(data->padstack_tree, (pcb_box_t *)pstk); + pcb_poly_restore_to_poly(data, PCB_OBJ_PSTK, NULL, pstk); +} + +void pcb_pstk_post(pcb_pstk_t *pstk) +{ + pcb_data_t *data = pstk->parent.data; + if (data->padstack_tree != NULL) + pcb_r_insert_entry(data->padstack_tree, (pcb_box_t *)pstk); + pcb_poly_clear_from_poly(data, PCB_OBJ_PSTK, NULL, pstk); +} + +pcb_layer_id_t pcb_proto_board_layer_for(const pcb_data_t *data, pcb_layer_type_t mask, pcb_layer_combining_t comb) +{ + pcb_layer_id_t lid; + const pcb_layer_t *ly; + for(lid = 0, ly = data->Layer; lid < data->LayerN; lid++,ly++) { + pcb_layer_type_t typ = pcb_layer_flags_(ly); + if ((typ == mask) && (ly->comb == comb)) + return lid; + } + return -1; +} Index: tags/2.1.2/src/obj_pstk.h =================================================================== --- tags/2.1.2/src/obj_pstk.h (nonexistent) +++ tags/2.1.2/src/obj_pstk.h (revision 24813) @@ -0,0 +1,303 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2017 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#ifndef PCB_OBJ_PSTK_STRUCT_DECLARED +#define PCB_OBJ_PSTK_STRUCT_DECLARED + +#include +#include +#include "obj_common.h" + +/* The actual padstack is just a reference to a padstack proto within the same data */ +struct pcb_pstk_s { +#define thermal thermal_dont_use + PCB_ANY_PRIMITIVE_FIELDS; +#undef thermal + pcb_cardinal_t proto; /* reference to a pcb_pstk_proto_t within pcb_data_t */ + int protoi; /* index of the transformed proto; -1 means invalid; local cache, not saved */ + pcb_coord_t x, y; + pcb_coord_t Clearance; + double rot; /* rotation angle */ + char xmirror, smirror; + struct { + unsigned long used; + unsigned char *shape; /* indexed by layer ID */ + } thermals; + gdl_elem_t link; /* a padstack is in a list in pcb_data_t as a global object */ +}; +#endif + +#ifndef PCB_PADSTACK_STRUCT_ONLY +#ifndef PCB_OBJ_PSTK_H +#define PCB_OBJ_PSTK_H + +#define PCB_PADSTACK_MAX_SHAPES 31 + +#define PCB_PADSTACK_INVALID ((pcb_cardinal_t)(-1)) + +#include "layer.h" +#include "obj_common.h" +#include "obj_pstk_shape.h" +#include "vtpadstack_t.h" + +typedef struct pcb_pstk_proto_s { + unsigned in_use:1; /* 1 if the slot is in use */ + + unsigned hplated:1; /* if > 0, whether the hole is plated */ + char *name; /* optional user assigned name (or NULL) */ + pcb_coord_t hdia; /* if > 0, diameter of the hole (else there's no hole) */ + int htop, hbottom; /* if hdia > 0, determine the hole's span, counted in copper layer groups from the top or bottom copper layer group */ + + pcb_vtpadstack_tshape_t tr; /* [0] is the canonical prototype with rot=0, xmirror=0 and smirror=0; the rest is an unordered list of transformed entries */ + + /* local cache - not saved */ + unsigned long hash; /* optimization: linear search compare speeded up: go into detailed match only if hash matches */ + pcb_data_t *parent; + int mech_idx; /* -1 or index to the first shape[] that is of PCB_LYT_MECH */ +} pcb_pstk_proto_t; + +/* Whether a proto cuts through board layers (has a hole or slot) */ +#define PCB_PSTK_PROTO_CUTS(proto) (((proto)->hdia > 0) || ((proto)->mech_idx >= 0)) + +/* Whether a proto cuts through board layers (has a hole or slot) and connects + layers with conductive material */ +#define PCB_PSTK_PROTO_PLATES(proto) (((proto)->hplated) && (((proto)->hdia > 0) || ((proto)->mech_idx >= 0))) + + +pcb_pstk_t *pcb_pstk_alloc(pcb_data_t *data); +pcb_pstk_t *pcb_pstk_alloc_id(pcb_data_t *data, long int id); +void pcb_pstk_free(pcb_pstk_t *ps); +pcb_pstk_t *pcb_pstk_new(pcb_data_t *data, long int id, pcb_cardinal_t proto, pcb_coord_t x, pcb_coord_t y, pcb_coord_t clearance, pcb_flag_t Flags); +pcb_pstk_t *pcb_pstk_new_tr(pcb_data_t *data, long int id, pcb_cardinal_t proto, pcb_coord_t x, pcb_coord_t y, pcb_coord_t clearance, pcb_flag_t Flags, double rot, int xmirror, int smirror); +void pcb_pstk_add(pcb_data_t *data, pcb_pstk_t *ps); +void pcb_pstk_bbox(pcb_pstk_t *ps); +void pcb_pstk_copper_bbox(pcb_box_t *dst, pcb_pstk_t *ps); + +void pcb_pstk_reg(pcb_data_t *data, pcb_pstk_t *pstk); +void pcb_pstk_unreg(pcb_pstk_t *pstk); + + +void pcb_pstk_pre(pcb_pstk_t *pstk); +void pcb_pstk_post(pcb_pstk_t *pstk); + +/* hash and eq */ +int pcb_pstk_eq(const pcb_host_trans_t *tr1, const pcb_pstk_t *p1, const pcb_host_trans_t *tr2, const pcb_pstk_t *p2); +unsigned int pcb_pstk_hash(const pcb_host_trans_t *tr, const pcb_pstk_t *p); + + +void pcb_pstk_set_thermal(pcb_pstk_t *ps, unsigned long lid, unsigned char shape); +unsigned char *pcb_pstk_get_thermal(pcb_pstk_t *ps, unsigned long lid, pcb_bool_t alloc); + +pcb_pstk_t *pcb_pstk_by_id(pcb_data_t *base, long int ID); + +/* Undoably change the instance parameters of a padstack ref */ +int pcb_pstk_change_instance(pcb_pstk_t *ps, pcb_cardinal_t *proto, const pcb_coord_t *clearance, double *rot, int *xmirror, int *smirror); + +/* Return whether a group is empty (free of padstack shapes) */ +pcb_bool pcb_pstk_is_group_empty(pcb_board_t *pcb, pcb_layergrp_id_t gid); + +/* Copy all metadata (attributes, thermals, etc.) */ +pcb_pstk_t *pcb_pstk_copy_meta(pcb_pstk_t *dst, pcb_pstk_t *src); + +/* Copy orientation information (rotatioin and mirror) of an instance */ +pcb_pstk_t *pcb_pstk_copy_orient(pcb_pstk_t *dst, pcb_pstk_t *src); + +/* Clearance of the padstack on a given layer */ +pcb_coord_t obj_pstk_get_clearance(pcb_board_t *pcb, pcb_pstk_t *ps, pcb_layer_t *layer); + +/*** proto ***/ + +/* Convert selection or current buffer to padstack; returns PCB_PADSTACK_INVALID + on error; looks for existing matching protos to avoid adding redundant + entries */ +pcb_cardinal_t pcb_pstk_conv_selection(pcb_board_t *pcb, int quiet, pcb_coord_t ox, pcb_coord_t oy); +pcb_cardinal_t pcb_pstk_conv_buffer(int quiet); + +/* Low level converter: take an array of (pcb_any_obj_t *) objs and convert + them into shapes of the dst proto. Does not remove input objects. */ +int pcb_pstk_proto_conv(pcb_data_t *data, pcb_pstk_proto_t *dst, int quiet, vtp0_t *objs, pcb_coord_t ox, pcb_coord_t oy); + +/* Break up src into discrete non-pstk objects placed in dst, one object + per layer type. The hole is ignored. If remove_src is true, also remove + src padstack. */ +int pcb_pstk_proto_breakup(pcb_data_t *dst, pcb_pstk_t *src, pcb_bool remove_src); + +/* free fields of a proto (not freeing the proto itself, not removing it from lists */ +void pcb_pstk_proto_free_fields(pcb_pstk_proto_t *dst); + +/* low level: allocate a new, uninitialized shape at the end of a transformed shape + WARNING: this should be done on all transformed shapes in parallel! */ +pcb_pstk_shape_t *pcb_pstk_alloc_append_shape(pcb_pstk_tshape_t *ts); + +/* allocate/free the point array of a poly shape (single allocation for x and y) */ +void pcb_pstk_shape_alloc_poly(pcb_pstk_poly_t *poly, int len); +void pcb_pstk_shape_free_poly(pcb_pstk_poly_t *poly); + +/* geometry for select.c and search.c; if layer is NULL, consider all shapes */ +int pcb_pstk_near_box(pcb_pstk_t *ps, pcb_box_t *box, pcb_layer_t *layer); +int pcb_is_point_in_pstk(pcb_coord_t x, pcb_coord_t y, pcb_coord_t radius, pcb_pstk_t *ps, pcb_layer_t *layer); + +/* Check if padstack has the proper clearance against polygon; returns 0 if everything's fine */ +int pcb_pstk_drc_check_clearance(pcb_pstk_t *ps, pcb_poly_t *polygon, pcb_coord_t min_clr); + +/* Check all possible local drc errors regarding to pad stacks - errors that + depend only on the padstack, not on other objects. load err_minring and + err_minhole with the relevant data for the report when ring or hole rules + are violated */ +void pcb_pstk_drc_check_and_warn(pcb_pstk_t *ps, pcb_coord_t *err_minring, pcb_coord_t *err_minhole); + +/* Generate poly->pa (which should be NULL at the time of call) */ +void pcb_pstk_shape_update_pa(pcb_pstk_poly_t *poly); + +/* Insert proto into the cache of data; if it's already in, return the existing + ID, else dup it and insert it. The forcedup variant always dups. + WARNING: make sure pcb_pstk_proto_update() was called on proto some point + in time before this call, esle the hash is invalid. */ +pcb_cardinal_t pcb_pstk_proto_insert_dup(pcb_data_t *data, const pcb_pstk_proto_t *proto, int quiet); +pcb_cardinal_t pcb_pstk_proto_insert_forcedup(pcb_data_t *data, const pcb_pstk_proto_t *proto, int quiet); + +/* Change the non-NULL hole properties of a padstack proto; undoable. + Returns 0 on success. */ +int pcb_pstk_proto_change_hole(pcb_pstk_proto_t *proto, const int *hplated, const pcb_coord_t *hdia, const int *htop, const int *hbottom); + +/* Change the name of a padstack proto; not yet undoable. + Returns 0 on success. */ +int pcb_pstk_proto_change_name(pcb_pstk_proto_t *proto, const char *new_name); + +/* Find or create a new transformed version of an existing proto */ +pcb_pstk_tshape_t *pcb_pstk_make_tshape(pcb_data_t *data, pcb_pstk_proto_t *proto, double rot, int xmirror, int smirror, int *out_protoi); + +/* Deep copy a prototype or shape */ +void pcb_pstk_proto_copy(pcb_pstk_proto_t *dst, const pcb_pstk_proto_t *src); +void pcb_pstk_shape_copy(pcb_pstk_shape_t *dst, pcb_pstk_shape_t *src); + +/* free all fields of a shape */ +void pcb_pstk_shape_free(pcb_pstk_shape_t *s); + +/* grow (or shrink) a prototype to or by val - change the proto in place */ +void pcb_pstk_proto_grow(pcb_pstk_proto_t *proto, pcb_bool is_absolute, pcb_coord_t val); +void pcb_pstk_shape_grow(pcb_pstk_shape_t *shp, pcb_bool is_absolute, pcb_coord_t val); +void pcb_pstk_shape_clr_grow(pcb_pstk_shape_t *shp, pcb_bool is_absolute, pcb_coord_t val); +void pcb_pstk_shape_scale(pcb_pstk_shape_t *shp, double sx, double sy); + +/* Derive (copy and bloat) the shape at dst_idx from src_idx; set the mask and comb + for the new shape. If dst_idx is -1, allocate the new shape */ +void pcb_pstk_shape_derive(pcb_pstk_proto_t *proto, int dst_idx, int src_idx, pcb_coord_t bloat, pcb_layer_type_t mask, pcb_layer_combining_t comb); + +/* Swap the layer definition of two shapes within a prototype; returns 0 on success */ +int pcb_pstk_shape_swap_layer(pcb_pstk_proto_t *proto, int idx1, int idx2); + +/* Create a new hshadow shape (in all transformed shape as well) */ +void pcb_pstk_shape_add_hshadow(pcb_pstk_proto_t *proto, pcb_layer_type_t mask, pcb_layer_combining_t comb); + + +/* Look up the shape index corresponding to a lty/comb; returns -1 if not found/empty */ +int pcb_pstk_get_shape_idx(pcb_pstk_tshape_t *ts, pcb_layer_type_t lyt, pcb_layer_combining_t comb); + +/* Remove a shape from the proto (either by layer or by idx) */ +void pcb_pstk_proto_del_shape(pcb_pstk_proto_t *proto, pcb_layer_type_t lyt, pcb_layer_combining_t comb); +void pcb_pstk_proto_del_shape_idx(pcb_pstk_proto_t *proto, int idx); + +#define PCB_PSTK_DONT_MIRROR_COORDS PCB_MAX_COORD +/* Mirror a padstack (useful for sending to the other side - set swap_side to 1 in that case) + Disabling xmirror is useful if side needs to be swapped but coordinates + are already mirrored so they represent the other-side geometry (e.g. when + importing from old pcb formats). If y_offs is PCB_PSTK_DONT_MIRROR_COORDS, + do not change the y coord */ +void pcb_pstk_mirror(pcb_pstk_t *ps, pcb_coord_t y_offs, int swap_side, int disable_xmirror); + +/* Create a new proto and scale it for the padstack; center x and y are scaled too */ +void pcb_pstk_scale(pcb_pstk_t *ps, double sx, double sy); + + +/* Rotate in place (op wrapper) */ +void pcb_pstk_rotate90(pcb_pstk_t *pstk, pcb_coord_t cx, pcb_coord_t cy, int steps); +void pcb_pstk_rotate(pcb_pstk_t *pstk, pcb_coord_t cx, pcb_coord_t cy, double cosa, double sina, double angle); + +/* High level move (op wrapper; no undo) */ +void pcb_pstk_move(pcb_pstk_t *ps, pcb_coord_t dx, pcb_coord_t dy, pcb_bool more_to_come); + +/* Low level move - updates only the coordinates and the bbox */ +void pcb_pstk_move_(pcb_pstk_t *ps, pcb_coord_t dx, pcb_coord_t dy); + +/* Temporary hack until we have a refcounted objects and ID->pcb_any_obj_t hash */ +extern pcb_data_t *pcb_pstk_data_hack; + +/* Insert a proto in data and return the proto-id. If the proto is already + in data, the fields of the caller's version are free'd, else they are + copied into data. In any case, the caller should not free proto. */ +pcb_cardinal_t pcb_pstk_proto_insert_or_free(pcb_data_t *data, pcb_pstk_proto_t *proto, int quiet); + +/* Update caches and hash - must be called after any change to the prototype */ +void pcb_pstk_proto_update(pcb_pstk_proto_t *dst); + +/* Overwrite all fields of a proto in-place; returns the id or INVALID on error */ +pcb_cardinal_t pcb_pstk_proto_replace(pcb_data_t *data, pcb_cardinal_t proto_id, const pcb_pstk_proto_t *src); + +/* Cycle through all (first level) padstacks of data and count how many times + each prototype is referenced by them. The result is returned as an array + of counts per prototype ID; the array is as large as data's prototype array. + len_out is always filled with the length of the array. If the length is 0, + NULL is returned. The caller needs to call free() on the returned array. */ +pcb_cardinal_t *pcb_pstk_proto_used_all(pcb_data_t *data, pcb_cardinal_t *len_out); + +/* Remove a prototype: free all fields and mark it unused */ +void pcb_pstk_proto_del(pcb_data_t *data, pcb_cardinal_t proto_id); + +/*** layer info ***/ +typedef struct pcb_proto_layer_s { + const char *name; + pcb_layer_type_t mask; + pcb_layer_combining_t comb; + + int auto_from[2]; + pcb_coord_t auto_bloat; +} pcb_proto_layer_t; + +#define PCB_PROTO_MASK_BLOAT PCB_MIL_TO_COORD(2*3) + +#define pcb_proto_num_layers 8 +const pcb_proto_layer_t pcb_proto_layers[pcb_proto_num_layers]; + + +/* Return the id of a board layer that matches a mask:comb pair or invalid if + nothing matched */ +pcb_layer_id_t pcb_proto_board_layer_for(const pcb_data_t *data, pcb_layer_type_t mask, pcb_layer_combining_t comb); + +/*** hash ***/ +unsigned int pcb_pstk_proto_hash(const pcb_pstk_proto_t *p); +int pcb_pstk_proto_eq(const pcb_pstk_proto_t *p1, const pcb_pstk_proto_t *p2); + +int pcb_pstk_shape_eq(const pcb_pstk_shape_t *sh1, const pcb_pstk_shape_t *sh2); + +/*** loops ***/ +#define PCB_PADSTACK_LOOP(top) do { \ + pcb_pstk_t *padstack; \ + gdl_iterator_t __it__; \ + padstacklist_foreach(&(top)->padstack, &__it__, padstack) { + +#endif +#endif Index: tags/2.1.2/src/obj_pstk_act.c =================================================================== --- tags/2.1.2/src/obj_pstk_act.c (nonexistent) +++ tags/2.1.2/src/obj_pstk_act.c (revision 24813) @@ -0,0 +1,221 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2017 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "config.h" + +#include "obj_pstk.h" +#include "obj_pstk_inlines.h" + +#include "funchash_core.h" +#include "board.h" +#include "conf_core.h" +#include "data.h" +#include "actions.h" +#include "search.h" +#include "data_list.h" + +static const char pcb_acts_padstackconvert[] = "PadstackConvert(buffer|selected, [originx, originy])"; +static const char pcb_acth_padstackconvert[] = "Convert selection or current buffer to padstack"; +fgw_error_t pcb_act_padstackconvert(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + int op; + pcb_coord_t x, y; + pcb_cardinal_t pid; + pcb_pstk_proto_t tmp, *p; + + PCB_ACT_CONVARG(1, FGW_KEYWORD, padstackconvert, op = fgw_keyword(&argv[1])); + + switch(op) { + case F_Selected: + if (argc > 3) { + PCB_ACT_CONVARG(2, FGW_COORD, padstackconvert, x = fgw_coord(&argv[2])); + PCB_ACT_CONVARG(3, FGW_COORD, padstackconvert, y = fgw_coord(&argv[3])); + } + else { + pcb_hid_get_coords("Click at padstack origin", &x, &y, 0); + /* rather use the snapped corsshair coords */ + x = pcb_crosshair.X; + y = pcb_crosshair.Y; + } + pid = pcb_pstk_conv_selection(PCB, 0, x, y); + + if (pid != PCB_PADSTACK_INVALID) { + pcb_buffer_clear(PCB, PCB_PASTEBUFFER); + p = pcb_vtpadstack_proto_alloc_append(&PCB_PASTEBUFFER->Data->ps_protos, 1); + pcb_pstk_proto_copy(p, &PCB->Data->ps_protos.array[pid]); + p->parent = PCB_PASTEBUFFER->Data; + pid = pcb_pstk_get_proto_id(p); /* should be 0 because of the clear, but just in case... */ + } + break; + case F_Buffer: + pid = pcb_pstk_conv_buffer(0); + + if (pid != PCB_PADSTACK_INVALID) { + /* have to save and restore the prototype around the buffer clear */ + tmp = PCB_PASTEBUFFER->Data->ps_protos.array[pid]; + memset(&PCB_PASTEBUFFER->Data->ps_protos.array[pid], 0, sizeof(PCB_PASTEBUFFER->Data->ps_protos.array[0])); + pcb_buffer_clear(PCB, PCB_PASTEBUFFER); + p = pcb_vtpadstack_proto_alloc_append(&PCB_PASTEBUFFER->Data->ps_protos, 1); + *p = tmp; + p->parent = PCB_PASTEBUFFER->Data; + pid = pcb_pstk_get_proto_id(p); /* should be 0 because of the clear, but just in case... */ + } + break; + default: + PCB_ACT_FAIL(padstackconvert); + } + + if (pid != PCB_PADSTACK_INVALID) { + pcb_message(PCB_MSG_INFO, "Pad stack registered with ID %d\n", pid); + pcb_pstk_new(PCB_PASTEBUFFER->Data, -1, pid, 0, 0, conf_core.design.clearance, pcb_flag_make(PCB_FLAG_CLEARLINE)); + pcb_set_buffer_bbox(PCB_PASTEBUFFER); + PCB_PASTEBUFFER->X = PCB_PASTEBUFFER->Y = 0; + } + else + pcb_message(PCB_MSG_ERROR, "(failed to convert to padstack)\n", pid); + + PCB_ACT_IRES(0); + return 0; +} + +static const char pcb_acts_padstackbreakup[] = "PadstackBreakup(buffer|selected|objet)"; +static const char pcb_acth_padstackbreakup[] = "Break up a padstack into one non-padstack object per layer type (the hole is ignored)"; +fgw_error_t pcb_act_padstackbreakup(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + int op; + PCB_ACT_CONVARG(1, FGW_KEYWORD, padstackconvert, op = fgw_keyword(&argv[1])); + PCB_ACT_IRES(-1); + + switch(op) { + case F_Object: + { + void *ptr1, *ptr2, *ptr3; + pcb_pstk_t *ps; + pcb_objtype_t type; + pcb_coord_t x, y; + + pcb_hid_get_coords("Select a padstack to break up", &x, &y, 0); + if ((type = pcb_search_screen(x, y, PCB_OBJ_PSTK, &ptr1, &ptr2, &ptr3)) != PCB_OBJ_PSTK) { + pcb_message(PCB_MSG_ERROR, "Need a padstack under the cursor\n"); + break; + } + ps = (pcb_pstk_t *)ptr2; + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, (pcb_any_obj_t *)ps)) { + pcb_message(PCB_MSG_ERROR, "Sorry, that padstack is locked\n"); + break; + } + PCB_ACT_IRES(pcb_pstk_proto_breakup(PCB->Data, ps, 1)); + } + break; + case F_Selected: + { + pcb_cardinal_t n; + int ret = 0; + vtp0_t objs; + pcb_any_obj_t **o; + + vtp0_init(&objs); + pcb_data_list_by_flag(PCB->Data, &objs, PCB_OBJ_PSTK, PCB_FLAG_SELECTED); + for(n = 0, o = (pcb_any_obj_t **)objs.array; n < vtp0_len(&objs); n++,o++) + ret |= pcb_pstk_proto_breakup(PCB->Data, (pcb_pstk_t *)*o, 1); + PCB_ACT_IRES(ret); + vtp0_uninit(&objs); + } + break; + case F_Buffer: + { + int ret = 0; + PCB_PADSTACK_LOOP(PCB_PASTEBUFFER->Data) { + ret |= pcb_pstk_proto_breakup(PCB_PASTEBUFFER->Data, padstack, 1); + } PCB_END_LOOP; + PCB_ACT_IRES(ret); + } + break; + default: + PCB_ACT_FAIL(padstackbreakup); + } + return 0; +} + +static const char pcb_acts_padstackplace[] = "PadstackPlace([proto_id|default], [x, y])"; +static const char pcb_acth_padstackplace[] = "Place a pad stack (either proto_id, or if not specified, the default for style)"; +fgw_error_t pcb_act_padstackplace(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + const char *pids = NULL; + pcb_cardinal_t pid; + pcb_pstk_t *ps; + pcb_coord_t x, y; + + PCB_ACT_MAY_CONVARG(1, FGW_STR, padstackplace, pids = argv[1].val.str); + + if (argc > 3) { + PCB_ACT_CONVARG(2, FGW_COORD, padstackconvert, x = fgw_coord(&argv[2])); + PCB_ACT_CONVARG(3, FGW_COORD, padstackconvert, y = fgw_coord(&argv[3])); + } + else { + pcb_hid_get_coords("Click at padstack origin", &x, &y, 0); + /* rather use the snapped corsshair coords */ + x = pcb_crosshair.X; + y = pcb_crosshair.Y; + } + + if ((pids == NULL) || (strcmp(pids, "default") == 0)) { +TODO("pstk: style default proto") + pid = 0; + } + else { + char *end; + pid = strtol(pids, &end, 10); + if (*end != '\0') { + pcb_message(PCB_MSG_ERROR, "Error in proto ID format: need an integer\n"); + return -1; + } + } + + if ((pid >= PCB->Data->ps_protos.used) || (PCB->Data->ps_protos.array[pid].in_use == 0)) { + pcb_message(PCB_MSG_ERROR, "Invalid padstack proto %ld\n", (long)pid); + return -1; + } + + ps = pcb_pstk_new(PCB->Data, -1, pid, x, y, conf_core.design.clearance, pcb_no_flags()); + if (ps == NULL) { + pcb_message(PCB_MSG_ERROR, "Failed to place padstack\n"); + return -1; + } + + PCB_ACT_IRES(0); + return 0; +} + +/* --------------------------------------------------------------------------- */ + +pcb_action_t padstack_action_list[] = { + {"PadstackConvert", pcb_act_padstackconvert, pcb_acth_padstackconvert, pcb_acts_padstackconvert}, + {"PadstackBreakup", pcb_act_padstackbreakup, pcb_acth_padstackbreakup, pcb_acts_padstackbreakup}, + {"PadstackPlace", pcb_act_padstackplace, pcb_acth_padstackplace, pcb_acts_padstackplace} +}; + +PCB_REGISTER_ACTIONS(padstack_action_list, NULL) Index: tags/2.1.2/src/obj_pstk_draw.h =================================================================== --- tags/2.1.2/src/obj_pstk_draw.h (nonexistent) +++ tags/2.1.2/src/obj_pstk_draw.h (revision 24813) @@ -0,0 +1,57 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2017 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "obj_pstk.h" + +#ifndef PCB_OBJ_PSTK_DRAW_H +#define PCB_OBJ_PSTK_DRAW_H + +/* Include rtree.h for these */ +#ifdef PCB_RTREE_H + +#include "board.h" +#include "draw.h" + +pcb_r_dir_t pcb_pstk_draw_callback(const pcb_box_t *b, void *cl); +pcb_r_dir_t pcb_pstk_draw_hole_callback(const pcb_box_t *b, void *cl); +pcb_r_dir_t pcb_pstk_draw_slot_callback(const pcb_box_t *b, void *cl); +pcb_r_dir_t pcb_pstk_clear_callback(const pcb_box_t *b, void *cl); +#endif + +pcb_r_dir_t pcb_pstk_draw_mark_callback(const pcb_box_t *b, void *cl); +pcb_r_dir_t pcb_pstk_draw_label_callback(const pcb_box_t *b, void *cl); +void pcb_pstk_draw_label(pcb_draw_info_t *info, pcb_pstk_t *ps); +void pcb_pstk_invalidate_erase(pcb_pstk_t *ps); +void pcb_pstk_invalidate_draw(pcb_pstk_t *ps); + +void pcb_pstk_thindraw(pcb_draw_info_t *info, pcb_hid_gc_t gc, pcb_pstk_t *ps); + +/* Draw a padstack for perview; if layers is NULL, draw all layers, else + draw the layers where it is not zero (layers are defined in pcb_proto_layers[]) */ +void pcb_pstk_draw_preview(pcb_board_t *pcb, const pcb_pstk_t *ps, char *layers, pcb_bool mark, pcb_bool label, const pcb_box_t *drawn_area); + + +#endif Index: tags/2.1.2/src/obj_pstk_inlines.h =================================================================== --- tags/2.1.2/src/obj_pstk_inlines.h (nonexistent) +++ tags/2.1.2/src/obj_pstk_inlines.h (revision 24813) @@ -0,0 +1,307 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2017 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#ifndef PCB_OBJ_PSTK_INLINES_H +#define PCB_OBJ_PSTK_INLINES_H + +#include "board.h" +#include "data.h" +#include "obj_pstk.h" +#include "vtpadstack.h" +#include "layer.h" +#include "thermal.h" + +typedef enum { + PCB_BB_NONE, /* no drill */ + PCB_BB_THRU, /* all way thru */ + PCB_BB_BB, + PCB_BB_INVALID +} pcb_bb_type_t; + +/* Returns the ID of a proto within its parent's cache */ +PCB_INLINE pcb_cardinal_t pcb_pstk_get_proto_id(const pcb_pstk_proto_t *proto) +{ + pcb_data_t *data = proto->parent; + if ((proto >= data->ps_protos.array) && (proto < data->ps_protos.array + data->ps_protos.used)) + return proto - data->ps_protos.array; + assert(!"padstack proto is not in its own parent!"); + return PCB_PADSTACK_INVALID; +} + +/* return the padstack prototype for a padstack reference - returns NULL if not found */ +PCB_INLINE pcb_pstk_proto_t *pcb_pstk_get_proto_(const pcb_data_t *data, pcb_cardinal_t proto) +{ + if (proto >= data->ps_protos.used) + return NULL; + if (data->ps_protos.array[proto].in_use == 0) + return NULL; + return data->ps_protos.array + proto; +} + +/* return the padstack prototype for a padstack reference - returns NULL if not found */ +PCB_INLINE pcb_pstk_proto_t *pcb_pstk_get_proto(const pcb_pstk_t *ps) +{ + return pcb_pstk_get_proto_(ps->parent.data, ps->proto); +} + +/* return the padstack transformed shape. Returns NULL if the proto or the + tshape is not. */ +PCB_INLINE pcb_pstk_tshape_t *pcb_pstk_get_tshape_(const pcb_data_t *data, pcb_cardinal_t proto, int protoi) +{ + pcb_pstk_proto_t *pr = pcb_pstk_get_proto_(data, proto); + if (protoi < 0) + return NULL; + if (pr == NULL) + return NULL; + if (protoi >= pr->tr.used) + return NULL; + return &pr->tr.array[protoi]; +} + +/* return the padstack prototype for a padstack reference - returns NULL if not found */ +PCB_INLINE pcb_pstk_tshape_t *pcb_pstk_get_tshape(pcb_pstk_t *ps) +{ + if (ps->protoi < 0) { /* need to update this */ + pcb_pstk_proto_t *pr = pcb_pstk_get_proto_(ps->parent.data, ps->proto); + if (pr == NULL) + return NULL; + return pcb_pstk_make_tshape(ps->parent.data, pr, ps->rot, ps->xmirror, ps->smirror, &ps->protoi); + } + return pcb_pstk_get_tshape_(ps->parent.data, ps->proto, ps->protoi); +} + +/* return the type of drill and optionally fill in group IDs of drill ends ; + if proto_out is not NULL, also load it with the proto */ +PCB_INLINE pcb_bb_type_t pcb_pstk_bbspan(pcb_board_t *pcb, const pcb_pstk_t *ps, pcb_layergrp_id_t *top, pcb_layergrp_id_t *bottom, pcb_pstk_proto_t **proto_out) +{ + pcb_bb_type_t res; + int topi, boti; + pcb_pstk_proto_t *proto = pcb_pstk_get_proto(ps); + + if (proto_out != NULL) + *proto_out = proto; + + if (proto == NULL) + return PCB_BB_INVALID; + + /* most common case should be quick */ + if (!PCB_PSTK_PROTO_CUTS(proto)) { + if (top != NULL) *top = -1; + if (bottom != NULL) *bottom = -1; + return PCB_BB_NONE; + } + + if ((proto->htop == 0) && (proto->hbottom == 0)) { + if ((top == NULL) && (bottom == NULL)) + return PCB_BB_THRU; + res = PCB_BB_THRU; + } + else + res = PCB_BB_BB; + + /* slower case: need to look up start and end */ + if (!pcb->LayerGroups.cache.copper_valid) + pcb_layergrp_copper_cache_update(&pcb->LayerGroups); + + if (proto->htop >= 0) { + /* positive: count from top copper down, bump at bottom */ + if (proto->htop < pcb->LayerGroups.cache.copper_len) + topi = proto->htop; + else + topi = pcb->LayerGroups.cache.copper_len - 1; + } + else { + /* negative: count from bottom copper up, bump at top */ + topi = pcb->LayerGroups.cache.copper_len - 1 - proto->htop; + if (topi < 0) + topi = 0; + } + + if (proto->hbottom >= 0) { + /* positive: count from bottom copper up, bump at top */ + if (proto->hbottom < pcb->LayerGroups.cache.copper_len-1) + boti = pcb->LayerGroups.cache.copper_len-1-proto->hbottom; + else + boti = 0; + } + else { + /* positive: count from top copper down, bump at bottom */ + boti = -proto->hbottom; + if (boti > pcb->LayerGroups.cache.copper_len - 1) + boti = pcb->LayerGroups.cache.copper_len - 1; + } + + if (boti <= topi) { + if (top != NULL) *top = -1; + if (bottom != NULL) *bottom = -1; + return PCB_BB_INVALID; + } + + if ((topi < 0) || (boti < 0)) { + /* special case: if there's no top or bottom copper, we do not know where to count from - do not support bbvias */ + return PCB_BB_THRU; + } + + if (top != NULL) *top = pcb->LayerGroups.cache.copper[topi]; + if (bottom != NULL) *bottom = pcb->LayerGroups.cache.copper[boti]; + + return res; +} + +/* return whether a given padstack drills a given group + (does not consider plating, only drill!) */ +PCB_INLINE pcb_bool_t pcb_pstk_bb_drills(pcb_board_t *pcb, const pcb_pstk_t *ps, pcb_layergrp_id_t grp, pcb_pstk_proto_t **proto_out) +{ + pcb_layergrp_id_t top, bot; + pcb_bb_type_t res = pcb_pstk_bbspan(pcb, ps, &top, &bot, proto_out); + switch(res) { + case PCB_BB_THRU: return pcb_true; + case PCB_BB_NONE: case PCB_BB_INVALID: return 0; + case PCB_BB_BB: return (grp <= bot) && (grp >= top); + } + return pcb_false; +} + +/* returns the shape the padstack has on the given layer group; + WARNING: does not respect the NOSHAPE thermal, should NOT be + called directly; use pcb_pstk_shape_*() instead. */ +PCB_INLINE pcb_pstk_shape_t *pcb_pstk_shape(pcb_pstk_t *ps, pcb_layer_type_t lyt, pcb_layer_combining_t comb) +{ + int n; + pcb_pstk_tshape_t *ts = pcb_pstk_get_tshape(ps); + if (ts == NULL) + return NULL; + + lyt &= (PCB_LYT_ANYTHING | PCB_LYT_ANYWHERE); + for(n = 0; n < ts->len; n++) + if ((lyt == ts->shape[n].layer_mask) && (comb == ts->shape[n].comb)) + return ts->shape+n; + + return 0; +} + +/* If force is non-zero, return the shape even if a thermal says no-shape */ +PCB_INLINE pcb_pstk_shape_t *pcb_pstk_shape_at_(pcb_board_t *pcb, pcb_pstk_t *ps, pcb_layer_t *layer, int force) +{ + unsigned int lyt = pcb_layer_flags_(layer); + pcb_layer_combining_t comb = layer->comb; + + if (lyt & PCB_LYT_COPPER) { + pcb_layer_id_t lid; + if (lyt & PCB_LYT_INTERN) { + /* apply internal only if that layer has drill */ + if (!pcb_pstk_bb_drills(pcb, ps, pcb_layer_get_group_(layer), NULL)) + return NULL; + } + + /* special case: if thermal says 'no shape' on this layer, omit the shape */ + if (!force) { + layer = pcb_layer_get_real(layer); + if ((layer != NULL) && (layer->parent.data != NULL)) { + lid = pcb_layer_id(layer->parent.data, layer); + if (lid < ps->thermals.used) { + if ((ps->thermals.shape[lid] & PCB_THERMAL_ON) && ((ps->thermals.shape[lid] & 3) == PCB_THERMAL_NOSHAPE)) + return NULL; + } + } + } + } + + /* combining is always 0 for copper */ + if (lyt & PCB_LYT_COPPER) + comb = 0; + else + comb = layer->comb; + + return pcb_pstk_shape(ps, lyt, comb); +} + +PCB_INLINE pcb_pstk_shape_t *pcb_pstk_shape_at(pcb_board_t *pcb, pcb_pstk_t *ps, pcb_layer_t *layer) +{ + return pcb_pstk_shape_at_(pcb, ps, layer, 0); +} + + +PCB_INLINE pcb_pstk_shape_t *pcb_pstk_shape_gid(pcb_board_t *pcb, pcb_pstk_t *ps, pcb_layergrp_id_t gid, pcb_layer_combining_t comb, pcb_layergrp_t **grp_out) +{ + pcb_layergrp_t *grp = pcb_get_layergrp(pcb, gid); + + if (grp_out != NULL) + *grp_out = grp; + + if ((grp == NULL) || (grp->len < 1)) + return NULL; + + if (grp->ltype & PCB_LYT_COPPER) { + int n, nosh; + + /* blind/buried: intern layer has no shape if no hole */ + if (grp->ltype & PCB_LYT_INTERN) { + /* apply internal only if that layer has drill */ + if (!pcb_pstk_bb_drills(pcb, ps, gid, NULL)) + return NULL; + } + + /* if all layers of the group says no-shape, don't have a shape */ + for(n = 0, nosh = 0; n < grp->len; n++) { + pcb_layer_id_t lid = grp->lid[n]; + if ((lid < ps->thermals.used) && (ps->thermals.shape[lid] & PCB_THERMAL_ON) && ((ps->thermals.shape[lid] & 3) == PCB_THERMAL_NOSHAPE)) + nosh++; + } + if (nosh == grp->len) + return NULL; + } + + /* normal procedure: go by group flags */ + return pcb_pstk_shape(ps, grp->ltype, comb); +} + +/* Return the shape of the hshadow, if it is not the same as the forbidden + shape. The forbidden shape should be the shape that triggers the lookup. + tmpshp should be a local temporary shape where the circular shape for a + hole can be built. */ +PCB_INLINE pcb_pstk_shape_t *pcb_pstk_hshadow_shape(pcb_pstk_t *ps, pcb_pstk_shape_t *forbidden, pcb_pstk_shape_t *tmpshp) +{ + pcb_pstk_proto_t *proto = pcb_pstk_get_proto(ps); + pcb_pstk_tshape_t *ts = pcb_pstk_get_tshape(ps); + + /* slot */ + if (proto->mech_idx >= 0) { + pcb_pstk_shape_t *s = ts->shape + proto->mech_idx; + if (s == forbidden) /* self-ref: hshadow in a mech layer type */ + return NULL; + return s; + } + + /* hole */ + tmpshp->shape = PCB_PSSH_CIRC; + tmpshp->data.circ.x = 0; + tmpshp->data.circ.y = 0; + tmpshp->data.circ.dia = proto->hdia; + return tmpshp; +} + +#endif Index: tags/2.1.2/src/obj_pstk_list.c =================================================================== --- tags/2.1.2/src/obj_pstk_list.c (nonexistent) +++ tags/2.1.2/src/obj_pstk_list.c (revision 24813) @@ -0,0 +1,29 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2017 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#define TDL_DONT_UNDEF +#include "obj_pstk_list.h" +#include Index: tags/2.1.2/src/obj_pstk_list.h =================================================================== --- tags/2.1.2/src/obj_pstk_list.h (nonexistent) +++ tags/2.1.2/src/obj_pstk_list.h (revision 24813) @@ -0,0 +1,51 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2017 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#ifndef PCB_OBJ_PSTK_LIST_H +#define PCB_OBJ_PSTK_LIST_H + +#define PCB_PADSTACK_STRUCT_ONLY +#include "obj_pstk.h" + + +/* List of padstatcks */ +#define TDL(x) padstacklist_ ## x +#define TDL_LIST_T padstacklist_t +#define TDL_ITEM_T pcb_pstk_t +#define TDL_FIELD link +#define TDL_SIZE_T size_t +#define TDL_FUNC + +#define padstacklist_foreach(list, iterator, loop_elem) \ + gdl_foreach_((&((list)->lst)), (iterator), (loop_elem)) + + +#include +#include + +#undef PCB_PADSTACK_STRUCT_ONLY + +#endif Index: tags/2.1.2/src/obj_pstk_op.c =================================================================== --- tags/2.1.2/src/obj_pstk_op.c (nonexistent) +++ tags/2.1.2/src/obj_pstk_op.c (revision 24813) @@ -0,0 +1,340 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2017 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "polygon.h" +#include "rotate.h" + +void *pcb_pstkop_add_to_buffer(pcb_opctx_t *ctx, pcb_pstk_t *ps) +{ + pcb_pstk_t *p; + pcb_cardinal_t npid; + pcb_pstk_proto_t *proto = pcb_pstk_get_proto(ps); + if (proto == NULL) + return NULL; + + npid = pcb_pstk_proto_insert_dup(ctx->buffer.dst, proto, 1); + p = pcb_pstk_new_tr(ctx->buffer.dst, -1, npid, ps->x, ps->y, ps->Clearance, pcb_flag_mask(ps->Flags, PCB_FLAG_FOUND | ctx->buffer.extraflg), ps->rot, ps->xmirror, ps->smirror); + return pcb_pstk_copy_meta(p, ps); +} + +/* Move between board and buffer */ +void *pcb_pstkop_move_buffer(pcb_opctx_t *ctx, pcb_pstk_t *ps) +{ + pcb_cardinal_t npid; + pcb_pstk_proto_t *proto = pcb_pstk_get_proto(ps); + if (proto == NULL) + return NULL; + + npid = pcb_pstk_proto_insert_dup(ctx->buffer.dst, proto, 1); + + pcb_poly_restore_to_poly(ctx->buffer.src, PCB_OBJ_PSTK, NULL, ps); + pcb_r_delete_entry(ctx->buffer.src->padstack_tree, (pcb_box_t *)ps); + + pcb_pstk_unreg(ps); + ps->proto = npid; + ps->protoi = -1; /* only the canonical trshape got copied, not the transofrmed ones */ + pcb_pstk_reg(ctx->buffer.dst, ps); + + PCB_FLAG_CLEAR(PCB_FLAG_WARN | PCB_FLAG_FOUND, ps); + + if (!ctx->buffer.dst->padstack_tree) + ctx->buffer.dst->padstack_tree = pcb_r_create_tree(); + + pcb_r_insert_entry(ctx->buffer.dst->padstack_tree, (pcb_box_t *)ps); + pcb_poly_clear_from_poly(ctx->buffer.dst, PCB_OBJ_PSTK, NULL, ps); + + return ps; +} + +void *pcb_pstkop_copy(pcb_opctx_t *ctx, pcb_pstk_t *ps) +{ + pcb_pstk_t *nps; + pcb_data_t *data = ctx->copy.pcb->Data; + pcb_cardinal_t npid; + pcb_pstk_proto_t *proto = pcb_pstk_get_proto(ps); + + if (proto == NULL) + return NULL; + npid = pcb_pstk_proto_insert_dup(data, proto, 1); + + nps = pcb_pstk_new_tr(data, -1, npid, ps->x + ctx->copy.DeltaX, ps->y + ctx->copy.DeltaY, ps->Clearance, pcb_flag_mask(ps->Flags, PCB_FLAG_FOUND), ps->rot, ps->xmirror, ps->smirror); + if (nps == NULL) + return NULL; + + pcb_pstk_copy_meta(nps, ps); + pcb_pstk_invalidate_draw(nps); + pcb_undo_add_obj_to_create(PCB_OBJ_PSTK, data, nps, nps); + return nps; +} + +void *pcb_pstkop_move_noclip(pcb_opctx_t *ctx, pcb_pstk_t *ps) +{ + pcb_pstk_invalidate_erase(ps); + pcb_pstk_move_(ps, ctx->move.dx, ctx->move.dy); + pcb_pstk_invalidate_draw(ps); + return ps; +} + +void *pcb_pstkop_move(pcb_opctx_t *ctx, pcb_pstk_t *ps) +{ + pcb_data_t *data = ps->parent.data; + assert(ps->parent_type = PCB_PARENT_DATA); + + pcb_r_delete_entry(data->padstack_tree, (pcb_box_t *)ps); + pcb_poly_restore_to_poly(data, PCB_OBJ_PSTK, NULL, ps); + pcb_pstkop_move_noclip(ctx, ps); + pcb_r_insert_entry(data->padstack_tree, (pcb_box_t *)ps); + pcb_poly_clear_from_poly(data, PCB_OBJ_PSTK, NULL, ps); + pcb_subc_part_changed(ps); + return ps; +} + +void *pcb_pstkop_clip(pcb_opctx_t *ctx, pcb_pstk_t *ps) +{ + pcb_data_t *data = ps->parent.data; + assert(ps->parent_type = PCB_PARENT_DATA); + + if (ctx->clip.restore) { + if (data->padstack_tree != NULL) + pcb_r_delete_entry(data->padstack_tree, (pcb_box_t *)ps); + pcb_poly_restore_to_poly(data, PCB_OBJ_PSTK, NULL, ps); + } + if (ctx->clip.clear) { + if (data->padstack_tree != NULL) + pcb_r_insert_entry(data->padstack_tree, (pcb_box_t *)ps); + pcb_poly_clear_from_poly(data, PCB_OBJ_PSTK, NULL, ps); + } + + return ps; +} + +void *pcb_pstkop_remove(pcb_opctx_t *ctx, pcb_pstk_t *ps) +{ + pcb_pstk_invalidate_erase(ps); + pcb_undo_move_obj_to_remove(PCB_OBJ_PSTK, ps, ps, ps); + pcb_subc_part_changed(ps); + return NULL; +} + +void *pcb_pstkop_destroy(pcb_opctx_t *ctx, pcb_pstk_t *ps) +{ + pcb_r_delete_entry(ctx->remove.destroy_target->padstack_tree, (pcb_box_t *)ps); + pcb_pstk_free(ps); + return NULL; +} + +void *pcb_pstkop_change_thermal(pcb_opctx_t *ctx, pcb_pstk_t *ps) +{ + pcb_board_t *pcb; + pcb_layer_t *layer; + + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, ps)) + return NULL; + + pcb = ctx->chgtherm.pcb; + layer = pcb_get_layer(pcb->Data, ctx->chgtherm.lid); + + pcb_undo_add_obj_to_clear_poly(PCB_OBJ_PSTK, ps, ps, ps, pcb_false); + pcb_poly_restore_to_poly(pcb->Data, PCB_OBJ_PSTK, layer, ps); + +TODO("undo") + pcb_pstk_set_thermal(ps, ctx->chgtherm.lid, ctx->chgtherm.style); + + pcb_undo_add_obj_to_clear_poly(PCB_OBJ_PSTK, ps, ps, ps, pcb_true); + pcb_poly_clear_from_poly(pcb->Data, PCB_OBJ_PSTK, layer, ps); + pcb_pstk_invalidate_draw(ps); + return ps; +} + +void *pcb_pstkop_change_flag(pcb_opctx_t *ctx, pcb_pstk_t *ps) +{ + static pcb_flag_values_t pcb_pstk_flags = 0; + + if (pcb_pstk_flags == 0) + pcb_pstk_flags = pcb_obj_valid_flags(PCB_OBJ_PSTK); + + if ((ctx->chgflag.flag & pcb_pstk_flags) != ctx->chgflag.flag) + return NULL; + if ((ctx->chgflag.flag & PCB_FLAG_TERMNAME) && (ps->term == NULL)) + return NULL; + pcb_undo_add_obj_to_flag(ps); + PCB_FLAG_CHANGE(ctx->chgflag.how, ctx->chgflag.flag, ps); + return ps; +} + + +void *pcb_pstkop_rotate(pcb_opctx_t *ctx, pcb_pstk_t *ps) +{ + double rot = ps->rot; + + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, ps)) + return NULL; + + if (ps->xmirror) + rot -= (double)ctx->rotate.angle; + else + rot += (double)ctx->rotate.angle; + + if ((rot > 360.0) || (rot < -360.0)) + rot = fmod(rot, 360.0); + + if ((rot == 360.0) || (rot == -360.0)) + rot = 0; + + if (pcb_pstk_change_instance(ps, NULL, NULL, &rot, NULL, NULL) == 0) { + pcb_coord_t nx = ps->x, ny = ps->y; + + + pcb_poly_restore_to_poly(ps->parent.data, PCB_OBJ_PSTK, NULL, ps); + pcb_pstk_invalidate_erase(ps); + if (ps->parent.data->padstack_tree != NULL) + pcb_r_delete_entry(ps->parent.data->padstack_tree, (pcb_box_t *)ps); + + pcb_rotate(&nx, &ny, ctx->rotate.center_x, ctx->rotate.center_y, ctx->rotate.cosa, ctx->rotate.sina); + if ((nx != ps->x) || (ny != ps->y)) + pcb_pstk_move_(ps, nx - ps->x, ny - ps->y); + + pcb_pstk_bbox(ps); + if (ps->parent.data->padstack_tree != NULL) + pcb_r_insert_entry(ps->parent.data->padstack_tree, (pcb_box_t *)ps); + pcb_poly_clear_from_poly(ps->parent.data, PCB_OBJ_PSTK, NULL, ps); + pcb_pstk_invalidate_draw(ps); + + pcb_subc_part_changed(ps); + return ps; + } + return NULL; +} + +void *pcb_pstkop_rotate90(pcb_opctx_t *ctx, pcb_pstk_t *ps) +{ + ctx->rotate.angle = (double)ctx->rotate.number * 90.0; + + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, ps)) + return NULL; + + switch(ctx->rotate.number) { + case 0: + ctx->rotate.sina = 0; + ctx->rotate.cosa = 1; + break; + case 1: + ctx->rotate.sina = 1; + ctx->rotate.cosa = 0; + break; + case 2: + ctx->rotate.sina = 0; + ctx->rotate.cosa = -1; + break; + case 3: + ctx->rotate.sina = -1; + ctx->rotate.cosa = 0; + break; + } + return pcb_pstkop_rotate(ctx, ps); +} + +void *pcb_pstkop_change_size(pcb_opctx_t *ctx, pcb_pstk_t *ps) +{ + pcb_pstk_proto_t proto; + pcb_cardinal_t nproto; + + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, ps)) + return NULL; + + /* create the new prototype and insert it */ + pcb_pstk_proto_copy(&proto, pcb_pstk_get_proto(ps)); + pcb_pstk_proto_grow(&proto, ctx->chgsize.is_absolute, ctx->chgsize.value); + nproto = pcb_pstk_proto_insert_dup(ps->parent.data, &proto, 1); + pcb_pstk_proto_free_fields(&proto); + + if (nproto == PCB_PADSTACK_INVALID) + return NULL; + + if (pcb_pstk_change_instance(ps, &nproto, NULL, NULL, NULL, NULL) == 0) { + pcb_subc_part_changed(ps); + return ps; + } + + return NULL; +} + +void *pcb_pstkop_change_clear_size(pcb_opctx_t *ctx, pcb_pstk_t *ps) +{ + pcb_coord_t value = (ctx->chgsize.is_absolute) ? ctx->chgsize.value / 2 : ps->Clearance + ctx->chgsize.value / 2; + + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, ps)) + return NULL; + if (value < 0) + value = 0; + value = MIN(PCB_MAX_LINESIZE, value); + if (!ctx->chgsize.is_absolute && (ctx->chgsize.value < 0) && (value < conf_core.design.bloat)) + value = 0; + if ((ctx->chgsize.value > 0) && (value < conf_core.design.bloat)) + value = conf_core.design.bloat + 1; + if (ps->Clearance == value) + return NULL; + + if (pcb_pstk_change_instance(ps, NULL, &value, NULL, NULL, NULL) == 0) { + pcb_subc_part_changed(ps); + return ps; + } + + return NULL; +} + + +void *pcb_pstkop_change_2nd_size(pcb_opctx_t *ctx, pcb_pstk_t *ps) +{ + pcb_pstk_proto_t proto; + pcb_cardinal_t nproto; + + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, ps)) + return NULL; + + /* create the new prototype and insert it */ + pcb_pstk_proto_copy(&proto, pcb_pstk_get_proto(ps)); + if (!ctx->chgsize.is_absolute) { + proto.hdia += ctx->chgsize.value; + if (proto.hdia < conf_core.design.min_drill) + proto.hdia = conf_core.design.min_drill; + } + else + proto.hdia = ctx->chgsize.value; + nproto = pcb_pstk_proto_insert_dup(ps->parent.data, &proto, 1); + pcb_pstk_proto_free_fields(&proto); + + if (nproto == PCB_PADSTACK_INVALID) + return NULL; + + if (pcb_pstk_change_instance(ps, &nproto, NULL, NULL, NULL, NULL) == 0) { + pcb_subc_part_changed(ps); + return ps; + } + + return NULL; +} + Index: tags/2.1.2/src/obj_pstk_op.h =================================================================== --- tags/2.1.2/src/obj_pstk_op.h (nonexistent) +++ tags/2.1.2/src/obj_pstk_op.h (revision 24813) @@ -0,0 +1,54 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2017 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +/*** Standard operations on padstacks ***/ + +#include "operation.h" + +void *pcb_pstkop_add_to_buffer(pcb_opctx_t *ctx, pcb_pstk_t *ps); +void *pcb_pstkop_move_buffer(pcb_opctx_t *ctx, pcb_pstk_t *ps); + +void *pcb_pstkop_copy(pcb_opctx_t *ctx, pcb_pstk_t *ps); +void *pcb_pstkop_move(pcb_opctx_t *ctx, pcb_pstk_t *ps); +void *pcb_pstkop_move_noclip(pcb_opctx_t *ctx, pcb_pstk_t *ps); +void *pcb_pstkop_clip(pcb_opctx_t *ctx, pcb_pstk_t *ps); +void *pcb_pstkop_remove(pcb_opctx_t *ctx, pcb_pstk_t *ps); +void *pcb_pstkop_destroy(pcb_opctx_t *ctx, pcb_pstk_t *ps); + +void *pcb_pstkop_change_thermal(pcb_opctx_t *ctx, pcb_pstk_t *ps); + +void *pcb_pstkop_change_flag(pcb_opctx_t *ctx, pcb_pstk_t *ps); + +void *pcb_pstkop_rotate90(pcb_opctx_t *ctx, pcb_pstk_t *ps); +void *pcb_pstkop_rotate(pcb_opctx_t *ctx, pcb_pstk_t *ps); + +void *pcb_pstkop_change_size(pcb_opctx_t *ctx, pcb_pstk_t *ps); +void *pcb_pstkop_change_clear_size(pcb_opctx_t *ctx, pcb_pstk_t *ps); /* changes the global clearance */ +void *pcb_pstkop_change_2nd_size(pcb_opctx_t *ctx, pcb_pstk_t *ps); + +/*** TODO: unimplemented ones ***/ + +void *pcb_pstkop_change_clear_size(pcb_opctx_t *ctx, pcb_pstk_t *ps); Index: tags/2.1.2/src/obj_pstk_proto.c =================================================================== --- tags/2.1.2/src/obj_pstk_proto.c (nonexistent) +++ tags/2.1.2/src/obj_pstk_proto.c (revision 24813) @@ -0,0 +1,1321 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2017 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "config.h" + +#include + +#include "board.h" +#include "buffer.h" +#include "compat_misc.h" +#include "conf_core.h" +#include "data.h" +#include "data_list.h" +#include "obj_pstk.h" +#include "obj_pstk_inlines.h" +#include "rotate.h" +#include "undo.h" +#include "vtpadstack_t.h" +#include "obj_hash.h" +#include "funchash_core.h" +#include "polygon_offs.h" + +static const char core_proto_cookie[] = "padstack prototypes"; + + +void pcb_pstk_proto_free_fields(pcb_pstk_proto_t *dst) +{ +TODO("do a full field free here") + dst->in_use = 0; +} + +void pcb_pstk_proto_update(pcb_pstk_proto_t *dst) +{ + pcb_pstk_tshape_t *ts = &dst->tr.array[0]; + unsigned int n; + + dst->hash = pcb_pstk_proto_hash(dst); + dst->mech_idx = -1; + + if (ts != NULL) { + for(n = 0; n < ts->len; n++) { + if (ts->shape[n].layer_mask & PCB_LYT_MECH) { + dst->mech_idx = n; + break; + } + } + } +} + +void pcb_pstk_shape_alloc_poly(pcb_pstk_poly_t *poly, int len) +{ + poly->x = malloc(sizeof(poly->x[0]) * len * 2); + poly->y = poly->x + len; + poly->len = len; + poly->pa = NULL; +} + +void pcb_pstk_shape_free_poly(pcb_pstk_poly_t *poly) +{ + if (poly->pa != NULL) + pcb_polyarea_free(&poly->pa); + free(poly->x); + poly->len = 0; +} + +void pcb_pstk_shape_copy_poly(pcb_pstk_poly_t *dst, const pcb_pstk_poly_t *src) +{ + memcpy(dst->x, src->x, sizeof(src->x[0]) * src->len * 2); + pcb_pstk_shape_update_pa(dst); +} + +int pcb_pstk_get_shape_idx(pcb_pstk_tshape_t *ts, pcb_layer_type_t lyt, pcb_layer_combining_t comb) +{ + int n; + for(n = 0; n < ts->len; n++) + if ((lyt == ts->shape[n].layer_mask) && (comb == ts->shape[n].comb)) + return n; + return -1; +} + +pcb_pstk_shape_t *pcb_pstk_alloc_append_shape(pcb_pstk_tshape_t *ts) +{ + int idx = ts->len; + + ts->len++; + ts->shape = realloc(ts->shape, ts->len * sizeof(pcb_pstk_shape_t)); + + return &ts->shape[idx]; +} + +static void append_circle(pcb_pstk_tshape_t *ts, pcb_layer_type_t lyt, pcb_layer_combining_t comb, pcb_coord_t dia) +{ + int idx = ts->len; + + ts->len++; + ts->shape = realloc(ts->shape, ts->len * sizeof(pcb_pstk_shape_t)); + + ts->shape[idx].shape = PCB_PSSH_CIRC; + ts->shape[idx].data.circ.x = ts->shape[idx].data.circ.y = 0; + ts->shape[idx].data.circ.dia = dia; + ts->shape[idx].layer_mask = lyt; + ts->shape[idx].comb = comb; +} + +static void append_tshape(pcb_pstk_tshape_t *ts, pcb_pstk_tshape_t *src, int srci) +{ + int idx = ts->len; + + ts->len++; + ts->shape = realloc(ts->shape, ts->len * sizeof(pcb_pstk_shape_t)); + memcpy(&ts->shape[idx], &src->shape[srci], sizeof(ts->shape[idx])); + switch(src->shape[srci].shape) { + case PCB_PSSH_LINE: + case PCB_PSSH_CIRC: + case PCB_PSSH_HSHADOW: + break; /* do nothing, all fields are copied already by the memcpy */ + case PCB_PSSH_POLY: + pcb_pstk_shape_alloc_poly(&ts->shape[idx].data.poly, src->shape[srci].data.poly.len); + pcb_pstk_shape_copy_poly(&ts->shape[idx].data.poly, &src->shape[srci].data.poly); + break; + } +} + +int pcb_pstk_proto_conv(pcb_data_t *data, pcb_pstk_proto_t *dst, int quiet, vtp0_t *objs, pcb_coord_t ox, pcb_coord_t oy) +{ + int ret = -1, n, m, i, extra_obj = 0, has_slot = 0, has_hole = 0; + pcb_any_obj_t **o; + pcb_pstk_tshape_t *ts, *ts_src; + pcb_pstk_t *pstk = NULL; + pcb_pstk_proto_t *prt; + + dst->in_use = 1; + dst->name = NULL; + pcb_vtpadstack_tshape_init(&dst->tr); + dst->hdia = 0; + dst->htop = dst->hbottom = 0; + + /* allocate shapes on the canonical tshape (tr[0]) */ + ts = pcb_vtpadstack_tshape_alloc_append(&dst->tr, 1); + ts->rot = 0.0; + ts->xmirror = 0; + ts->smirror = 0; + ts->len = 0; + for(n = 0, o = (pcb_any_obj_t **)objs->array; n < vtp0_len(objs); n++,o++) { + pcb_layer_t *ly = (*o)->parent.layer; + pcb_layer_type_t lyt = pcb_layer_flags_(ly); + + if (lyt & PCB_LYT_MECH) { + int purpi; + if (has_slot) { + if (!quiet) + pcb_message(PCB_MSG_ERROR, "Padstack conversion: multiple mechanical objects (slots) are not allowed\n"); + goto quit; + } + has_slot++; + purpi = pcb_layer_purpose_(ly, NULL); + dst->hplated = !!PCB_LAYER_IS_PROUTE(lyt, purpi); + } + + switch((*o)->type) { + case PCB_OBJ_LINE: + case PCB_OBJ_POLY: + ts->len++; + break; + case PCB_OBJ_PSTK: + if (pstk != NULL) { + if (!quiet) + pcb_message(PCB_MSG_ERROR, "Padstack conversion: multiple vias/padstacks\n"); + goto quit; + } + pstk = *(pcb_pstk_t **)o; + prt = pcb_pstk_get_proto(pstk); + if (prt == NULL) { + if (!quiet) + pcb_message(PCB_MSG_ERROR, "Padstack conversion: invalid input padstacks proto\n"); + goto quit; + } + if (prt->hdia > 0) + has_hole = 1; + dst->hdia = prt->hdia; + dst->hplated = prt->hplated; + if ((ox != pstk->x) || (oy != pstk->y)) { + pcb_message(PCB_MSG_INFO, "Padstack conversion: adjusting origin to padstack hole\n"); + ox = pstk->x; + oy = pstk->y; + } + extra_obj++; + break; + default:; + if (!quiet) + pcb_message(PCB_MSG_ERROR, "Padstack conversion: invalid object type (%x) selected; must be via, padstack, line or polygon\n", (*o)->type); + goto quit; + } + } + + if ((vtp0_len(objs) - extra_obj) > data->LayerN) { + if (!quiet) + pcb_message(PCB_MSG_ERROR, "Padstack conversion: too many objects selected\n"); + goto quit; + } + + if ((ts->len == 0) && (pstk == NULL)) { + if (!quiet) + pcb_message(PCB_MSG_ERROR, "Padstack conversion: there are no shapes and there is no via/padstack participating in the conversion; can not create empty padstack\n"); + goto quit; + } + + ts->shape = malloc(ts->len * sizeof(pcb_pstk_shape_t)); + + /* convert local (line/poly) objects */ + for(i = 0, n = -1, o = (pcb_any_obj_t **)objs->array; i < vtp0_len(objs); o++,i++) { + pcb_layer_t *ly; + switch((*o)->type) { + case PCB_OBJ_LINE: + { + pcb_line_t *line = (*(pcb_line_t **)o); + + n++; + if ((line->Point1.X != line->Point2.X) || (line->Point1.Y != line->Point2.Y)) { + ts->shape[n].shape = PCB_PSSH_LINE; + ts->shape[n].data.line.x1 = line->Point1.X - ox; + ts->shape[n].data.line.y1 = line->Point1.Y - oy; + ts->shape[n].data.line.x2 = line->Point2.X - ox; + ts->shape[n].data.line.y2 = line->Point2.Y - oy; + ts->shape[n].data.line.thickness = line->Thickness; + ts->shape[n].data.line.square = 0; + } + else { /* a zero-long line is really a circle - padstacks have a specific shape for that */ + ts->shape[n].shape = PCB_PSSH_CIRC; + ts->shape[n].data.circ.x = line->Point1.X - ox; + ts->shape[n].data.circ.y = line->Point1.Y - oy; + ts->shape[n].data.circ.dia = line->Thickness; + } + ts->shape[n].clearance = line->Clearance; + } + break; + case PCB_OBJ_POLY: + { + pcb_cardinal_t p, len, maxlen = (1L << ((sizeof(int)*8)-1)); + pcb_poly_t *poly = *(pcb_poly_t **)o; + + len = poly->PointN; + n++; + if (poly->HoleIndexN != 0) { + if (!quiet) + pcb_message(PCB_MSG_ERROR, "Padstack conversion: can not convert polygon with holes\n"); + goto quit; + } + if (len >= maxlen) { + if (!quiet) + pcb_message(PCB_MSG_ERROR, "Padstack conversion: polygon has too many points (%ld >= %ld)\n", (long)len, (long)maxlen); + goto quit; + } + pcb_pstk_shape_alloc_poly(&ts->shape[n].data.poly, len); + for(p = 0; p < len; p++) { + ts->shape[n].data.poly.x[p] = poly->Points[p].X - ox; + ts->shape[n].data.poly.y[p] = poly->Points[p].Y - oy; + } + pcb_pstk_shape_update_pa(&ts->shape[n].data.poly); + ts->shape[n].shape = PCB_PSSH_POLY; + ts->shape[n].clearance = (*(pcb_poly_t **)o)->Clearance; + } + break; + default: continue; + } + assert((*o)->parent_type == PCB_PARENT_LAYER); + ly = (*o)->parent.layer; + ts->shape[n].layer_mask = pcb_layer_flags_(ly); + ts->shape[n].comb = ly->comb; + + if (ts->shape[n].layer_mask & PCB_LYT_BOUNDARY) { + ts->shape[n].layer_mask &= ~PCB_LYT_BOUNDARY; + ts->shape[n].layer_mask |= PCB_LYT_MECH; + } + if (ts->shape[n].layer_mask & (PCB_LYT_PASTE | PCB_LYT_MASK | PCB_LYT_MECH)) + ts->shape[n].comb |= PCB_LYC_AUTO; + + for(m = 0; m < n; m++) { + if ((ts->shape[n].layer_mask == ts->shape[m].layer_mask) && (ts->shape[n].comb == ts->shape[m].comb)) { + if (!quiet) + pcb_message(PCB_MSG_ERROR, "Padstack conversion: multiple objects on the same layer\n"); + goto quit; + } + } + if ((ts->shape[n].layer_mask & PCB_LYT_COPPER) && (ts->shape[n].layer_mask & PCB_LYT_INTERN) && (has_hole) && (!has_slot)) { + if (!quiet) + pcb_message(PCB_MSG_ERROR, "Padstack conversion: can not have internal copper shape if there is no hole\n"); + goto quit; + } + } + + if (has_hole && has_slot) { + if (!quiet) + pcb_message(PCB_MSG_ERROR, "Padstack conversion: can not have both hole (padstack) and slot \n"); + goto quit; + } + + /* if there was a padstack, use the padstack's shape on layers that are not specified */ + if (pstk != NULL) { + int srci; + ts_src = pcb_pstk_get_tshape(pstk); + if (ts_src != NULL) { +# define MAYBE_COPY(mask, comb) \ + if ((pcb_pstk_get_shape_idx(ts, mask, comb) == -1) && ((srci = pcb_pstk_get_shape_idx(ts_src, mask, comb)) != -1)) \ + append_tshape(ts, ts_src, srci); + MAYBE_COPY(PCB_LYT_COPPER | PCB_LYT_TOP, 0); + MAYBE_COPY(PCB_LYT_COPPER | PCB_LYT_INTERN, 0); + MAYBE_COPY(PCB_LYT_COPPER | PCB_LYT_BOTTOM, 0); + MAYBE_COPY(PCB_LYT_MASK | PCB_LYT_BOTTOM, PCB_LYC_SUB | PCB_LYC_AUTO); + MAYBE_COPY(PCB_LYT_MASK | PCB_LYT_TOP, PCB_LYC_SUB | PCB_LYC_AUTO); + MAYBE_COPY(PCB_LYT_PASTE | PCB_LYT_BOTTOM, PCB_LYC_AUTO); + MAYBE_COPY(PCB_LYT_PASTE | PCB_LYT_TOP, PCB_LYC_AUTO); + MAYBE_COPY(PCB_LYT_MECH, PCB_LYC_AUTO); +# undef MAYBE_COPY + } + } + + /* all went fine */ + pcb_pstk_proto_update(dst); + ret = 0; + + quit:; + if (ret != 0) + pcb_pstk_proto_free_fields(dst); + return ret; +} + +int pcb_pstk_proto_breakup(pcb_data_t *dst, pcb_pstk_t *src, pcb_bool remove_src) +{ + pcb_pstk_tshape_t *ts = pcb_pstk_get_tshape(src); + int n, i; + pcb_layer_type_t lyt, filt = (PCB_LYT_ANYTHING | PCB_LYT_ANYWHERE); + pcb_any_obj_t *no; + pcb_pstk_proto_t *proto = pcb_pstk_get_proto(src); + + if (ts == NULL) + return -1; + + for(n = 0; n < ts->len; n++) { + pcb_pstk_shape_t *shp = &ts->shape[n]; + pcb_layer_id_t lid; + pcb_layer_t *ly, *ly1 = NULL, *ly2 = NULL, *ly3 = NULL; + pcb_coord_t clr; + pcb_poly_t *p; + + if ((shp->layer_mask & PCB_LYT_ANYTHING) == 0) + pcb_message(PCB_MSG_ERROR, "ERROR: breaking up padstack prototype: shape %d has invalid layer type, placing it on a random layer\nTHIS PADSTACK PROTOTYPE MUST BE FIXED.\n"); + + /* look up the best layer type */ + for(lid = 0; lid < dst->LayerN; lid++) { + ly = &dst->Layer[lid]; + lyt = pcb_layer_flags_(ly); + +TODO("layer: make a real scoring mechanism here instead of ly1, ly2, ly3") + /* cheat: pretend boundary layers are mech layers because padstack layer types are interested only in mech layers */ + if (lyt & PCB_LYT_BOUNDARY) { + lyt &= ~PCB_LYT_BOUNDARY; + lyt |= PCB_LYT_MECH; + } + + if ((lyt & shp->layer_mask) == shp->layer_mask) { + int comb_match = (shp->comb == ly->comb); + int plate_match = 1; + + if (lyt & PCB_LYT_MECH) { /* check plating only for mech layers */ + int purpi = pcb_layer_purpose_(ly, NULL); + int ly_plated = !!PCB_LAYER_IS_PROUTE(lyt, purpi); + plate_match = (ly_plated == proto->hplated); + } + + if (comb_match && plate_match) { + ly1 = ly; + break; + } + else + ly2 = ly; + } + else if ((lyt & shp->layer_mask & filt) == (shp->layer_mask & filt)) + ly3 = ly; + } + + ly = ly1; + if (ly == NULL) ly = ly2; + if (ly == NULL) ly = ly3; + if (ly == NULL) { + const char *locs, *mats; + locs = pcb_layer_type_bit2str(lyt & PCB_LYT_ANYWHERE); + mats = pcb_layer_type_bit2str(lyt & PCB_LYT_ANYTHING); + if (locs == NULL) locs = ""; + if (mats == NULL) mats = ""; + pcb_message(PCB_MSG_WARNING, "Can not create shape on %s %s\n", locs, mats); + continue; + } + + clr = src->Clearance == 0 ? shp->clearance : src->Clearance; + switch(shp->shape) { + case PCB_PSSH_CIRC: + no = (pcb_any_obj_t *)pcb_line_new(ly, + src->x + shp->data.circ.x, src->y + shp->data.circ.y, + src->x + shp->data.circ.x, src->y + shp->data.circ.y, + shp->data.circ.dia, clr, pcb_flag_make(PCB_FLAG_CLEARLINE)); + break; + case PCB_PSSH_LINE: + no = (pcb_any_obj_t *)pcb_line_new(ly, + src->x + shp->data.line.x1, src->y + shp->data.line.y1, + src->x + shp->data.line.x2, src->y + shp->data.line.y2, + shp->data.line.thickness, clr, pcb_flag_make(PCB_FLAG_CLEARLINE)); + break; + case PCB_PSSH_POLY: + p = pcb_poly_new(ly, clr, pcb_flag_make(PCB_FLAG_CLEARPOLYPOLY)); + for(i = 0; i < shp->data.poly.len; i++) + pcb_poly_point_new(p, src->x + shp->data.poly.x[i], src->y + shp->data.poly.y[i]); + pcb_add_poly_on_layer(ly, p); + no = (pcb_any_obj_t *)p; + break; + default: + assert(!"invalid shape"); + continue; + } + if (src->term != NULL) + pcb_attribute_put(&no->Attributes, "term", src->term); + } + + if (remove_src) { + if (src->parent.data->padstack_tree != NULL) + pcb_r_delete_entry(src->parent.data->padstack_tree, (pcb_box_t *)src); + pcb_pstk_free(src); + } + + return -1; +} + +int pcb_pstk_proto_conv_selection(pcb_board_t *pcb, pcb_pstk_proto_t *dst, int quiet, pcb_coord_t ox, pcb_coord_t oy) +{ + int ret; + vtp0_t objs; + + vtp0_init(&objs); + pcb_data_list_by_flag(pcb->Data, &objs, PCB_OBJ_CLASS_REAL, PCB_FLAG_SELECTED); + ret = pcb_pstk_proto_conv(pcb->Data, dst, quiet, &objs, ox, oy); + vtp0_uninit(&objs); + + return ret; +} + + +int pcb_pstk_proto_conv_buffer(pcb_pstk_proto_t *dst, int quiet) +{ + int ret; + vtp0_t objs; + pcb_coord_t ox, oy; + pcb_box_t bb; + + pcb_data_bbox(&bb, PCB_PASTEBUFFER->Data, 0); + + ox = (bb.X1 + bb.X2) / 2; + oy = (bb.Y1 + bb.Y2) / 2; + + vtp0_init(&objs); + pcb_data_list_by_flag(PCB_PASTEBUFFER->Data, &objs, PCB_OBJ_CLASS_REAL, 0); + ret = pcb_pstk_proto_conv(PCB_PASTEBUFFER->Data, dst, quiet, &objs, ox, oy); + vtp0_uninit(&objs); + + return ret; +} + +void pcb_pstk_shape_copy(pcb_pstk_shape_t *dst, pcb_pstk_shape_t *src) +{ + memcpy(dst, src, sizeof(pcb_pstk_shape_t)); + switch(src->shape) { + case PCB_PSSH_LINE: + case PCB_PSSH_CIRC: + case PCB_PSSH_HSHADOW: + break; /* do nothing, all fields are copied already by the memcpy */ + case PCB_PSSH_POLY: + pcb_pstk_shape_alloc_poly(&dst->data.poly, src->data.poly.len); + pcb_pstk_shape_copy_poly(&dst->data.poly, &src->data.poly); + break; + } +} + +void pcb_pstk_shape_free(pcb_pstk_shape_t *s) +{ + switch(s->shape) { + case PCB_PSSH_LINE: + case PCB_PSSH_CIRC: + case PCB_PSSH_HSHADOW: + break; /* no allocation */ + case PCB_PSSH_POLY: + pcb_pstk_shape_free_poly(&s->data.poly); + break; + } +} + +void pcb_pstk_tshape_copy(pcb_pstk_tshape_t *ts_dst, pcb_pstk_tshape_t *ts_src) +{ + int n; + + ts_dst->rot = ts_src->rot; + ts_dst->xmirror = ts_src->xmirror; + ts_dst->smirror = ts_src->smirror; + ts_dst->shape = malloc(sizeof(pcb_pstk_shape_t) * ts_src->len); + ts_dst->len = ts_src->len; + memcpy(ts_dst->shape, ts_src->shape, sizeof(pcb_pstk_shape_t) * ts_src->len); + for(n = 0; n < ts_src->len; n++) { + switch(ts_src->shape[n].shape) { + case PCB_PSSH_LINE: + case PCB_PSSH_CIRC: + case PCB_PSSH_HSHADOW: + break; /* do nothing, all fields are copied already by the memcpy */ + case PCB_PSSH_POLY: + pcb_pstk_shape_alloc_poly(&ts_dst->shape[n].data.poly, ts_src->shape[n].data.poly.len); + pcb_pstk_shape_copy_poly(&ts_dst->shape[n].data.poly, &ts_src->shape[n].data.poly); + break; + } + } +} + +void pcb_pstk_shape_rot(pcb_pstk_shape_t *sh, double sina, double cosa, double angle) +{ + int i; + + switch(sh->shape) { + case PCB_PSSH_LINE: + pcb_rotate(&sh->data.line.x1, &sh->data.line.y1, 0, 0, cosa, sina); + pcb_rotate(&sh->data.line.x2, &sh->data.line.y2, 0, 0, cosa, sina); + break; + case PCB_PSSH_CIRC: + pcb_rotate(&sh->data.circ.x, &sh->data.circ.y, 0, 0, cosa, sina); + break; + case PCB_PSSH_HSHADOW: + break; + case PCB_PSSH_POLY: + if (sh->data.poly.pa != NULL) + pcb_polyarea_free(&sh->data.poly.pa); + for(i = 0; i < sh->data.poly.len; i++) + pcb_rotate(&sh->data.poly.x[i], &sh->data.poly.y[i], 0, 0, cosa, sina); + pcb_pstk_shape_update_pa(&sh->data.poly); + break; + } +} + + +void pcb_pstk_tshape_rot(pcb_pstk_tshape_t *ts, double angle) +{ + int n; + double cosa = cos(angle / PCB_RAD_TO_DEG), sina = sin(angle / PCB_RAD_TO_DEG); + + for(n = 0; n < ts->len; n++) + pcb_pstk_shape_rot(&ts->shape[n], sina, cosa, angle); +} + +void pcb_pstk_tshape_xmirror(pcb_pstk_tshape_t *ts) +{ + int n, i; + + for(n = 0; n < ts->len; n++) { + pcb_pstk_shape_t *sh = &ts->shape[n]; + switch(sh->shape) { + case PCB_PSSH_LINE: + sh->data.line.y1 = -sh->data.line.y1; + sh->data.line.y2 = -sh->data.line.y2; + break; + case PCB_PSSH_CIRC: + sh->data.circ.y = -sh->data.circ.y; + break; + case PCB_PSSH_HSHADOW: + break; + case PCB_PSSH_POLY: + if (sh->data.poly.pa != NULL) + pcb_polyarea_free(&sh->data.poly.pa); + for(i = 0; i < sh->data.poly.len; i++) + sh->data.poly.y[i] = -sh->data.poly.y[i]; + pcb_pstk_shape_update_pa(&sh->data.poly); + break; + } + } +} + +void pcb_pstk_tshape_smirror(pcb_pstk_tshape_t *ts) +{ + int n; + + for(n = 0; n < ts->len; n++) { + pcb_pstk_shape_t *sh = &ts->shape[n]; + if (sh->layer_mask & PCB_LYT_TOP) { + sh->layer_mask &= ~PCB_LYT_TOP; + sh->layer_mask |= PCB_LYT_BOTTOM; + } + else if (sh->layer_mask & PCB_LYT_BOTTOM) { + sh->layer_mask &= ~PCB_LYT_BOTTOM; + sh->layer_mask |= PCB_LYT_TOP; + } + } +} + +void pcb_pstk_proto_copy(pcb_pstk_proto_t *dst, const pcb_pstk_proto_t *src) +{ + pcb_pstk_tshape_t *ts_dst, *ts_src; + + memcpy(dst, src, sizeof(pcb_pstk_proto_t)); + pcb_vtpadstack_tshape_init(&dst->tr); + + if (src->tr.used > 0) { + ts_src = &src->tr.array[0]; + + /* allocate shapes on the canonical tshape (tr[0]) */ + ts_dst = pcb_vtpadstack_tshape_alloc_append(&dst->tr, 1); + pcb_pstk_tshape_copy(ts_dst, ts_src); + + /* make sure it's the canonical form */ + ts_dst->rot = 0.0; + ts_dst->xmirror = 0; + ts_dst->smirror = 0; + } + + dst->in_use = 1; +} + + +/* Matches proto against all protos in data's cache; returns + PCB_PADSTACK_INVALID (and loads first_free_out) if not found */ +static pcb_cardinal_t pcb_pstk_proto_insert_try(pcb_data_t *data, const pcb_pstk_proto_t *proto, pcb_cardinal_t *first_free_out) +{ + pcb_cardinal_t n, first_free = PCB_PADSTACK_INVALID; + + /* look for the first existing padstack that matches */ + for(n = 0; n < pcb_vtpadstack_proto_len(&data->ps_protos); n++) { + if (!(data->ps_protos.array[n].in_use)) { + if (first_free == PCB_PADSTACK_INVALID) + first_free = n; + } + else if (data->ps_protos.array[n].hash == proto->hash) { + if (pcb_pstk_proto_eq(&data->ps_protos.array[n], proto)) + return n; + } + } + *first_free_out = first_free; + return PCB_PADSTACK_INVALID; +} + +pcb_cardinal_t pcb_pstk_proto_insert_or_free(pcb_data_t *data, pcb_pstk_proto_t *proto, int quiet) +{ + pcb_cardinal_t n, first_free; + + n = pcb_pstk_proto_insert_try(data, proto, &first_free); + if (n != PCB_PADSTACK_INVALID) { + pcb_pstk_proto_free_fields(proto); + return n; /* already in cache */ + } + + /* no match, have to register a new one */ + if (first_free == PCB_PADSTACK_INVALID) { + pcb_pstk_proto_t *np; + n = pcb_vtpadstack_proto_len(&data->ps_protos); + pcb_vtpadstack_proto_append(&data->ps_protos, *proto); + np = pcb_vtpadstack_proto_get(&data->ps_protos, n, 0); + np->parent = data; + pcb_pstk_proto_update(np); + } + else { + memcpy(data->ps_protos.array+first_free, proto, sizeof(pcb_pstk_proto_t)); + data->ps_protos.array[first_free].in_use = 1; + data->ps_protos.array[first_free].parent = data; + pcb_pstk_proto_update(data->ps_protos.array+first_free); + n = first_free; + } + memset(proto, 0, sizeof(pcb_pstk_proto_t)); /* make sure a subsequent free() won't do any harm */ + return n; +} + +static pcb_cardinal_t pcb_pstk_proto_insert_dup_(pcb_data_t *data, const pcb_pstk_proto_t *proto, int quiet, int forcedup) +{ + pcb_cardinal_t n, first_free = PCB_PADSTACK_INVALID; + + n = pcb_pstk_proto_insert_try(data, proto, &first_free); + if ((n != PCB_PADSTACK_INVALID) && (!forcedup)) + return n; /* already in cache */ + + /* no match, have to register a new one, which is a dup of the original */ + if (first_free == PCB_PADSTACK_INVALID) { + pcb_pstk_proto_t *nproto; + n = pcb_vtpadstack_proto_len(&data->ps_protos); + nproto = pcb_vtpadstack_proto_alloc_append(&data->ps_protos, 1); + pcb_pstk_proto_copy(nproto, proto); + nproto->parent = data; + pcb_pstk_proto_update(nproto); + } + else { + pcb_pstk_proto_copy(data->ps_protos.array+first_free, proto); + data->ps_protos.array[first_free].in_use = 1; + data->ps_protos.array[first_free].parent = data; + pcb_pstk_proto_update(data->ps_protos.array+first_free); + return first_free; + } + return n; +} + +pcb_cardinal_t pcb_pstk_proto_insert_dup(pcb_data_t *data, const pcb_pstk_proto_t *proto, int quiet) +{ + return pcb_pstk_proto_insert_dup_(data, proto, quiet, 0); +} + +pcb_cardinal_t pcb_pstk_proto_insert_forcedup(pcb_data_t *data, const pcb_pstk_proto_t *proto, int quiet) +{ + return pcb_pstk_proto_insert_dup_(data, proto, quiet, 1); +} + + +pcb_cardinal_t pcb_pstk_proto_replace(pcb_data_t *data, pcb_cardinal_t proto_id, const pcb_pstk_proto_t *src) +{ + pcb_pstk_proto_t *dst; + if ((proto_id < 0) || (proto_id >= pcb_vtpadstack_proto_len(&data->ps_protos))) + return PCB_PADSTACK_INVALID; + + dst = &data->ps_protos.array[proto_id]; + pcb_pstk_proto_free_fields(dst); + + pcb_pstk_proto_copy(dst, src); + dst->in_use = 1; + dst->parent = data; + pcb_pstk_proto_update(dst); + return proto_id; +} + + +pcb_cardinal_t pcb_pstk_conv_selection(pcb_board_t *pcb, int quiet, pcb_coord_t ox, pcb_coord_t oy) +{ + pcb_pstk_proto_t proto; + + if (pcb_pstk_proto_conv_selection(pcb, &proto, quiet, ox, oy) != 0) + return -1; + + return pcb_pstk_proto_insert_or_free(pcb->Data, &proto, quiet); +} + +pcb_cardinal_t pcb_pstk_conv_buffer(int quiet) +{ + pcb_pstk_proto_t proto; + + if (pcb_pstk_proto_conv_buffer(&proto, quiet) != 0) + return -1; + + return pcb_pstk_proto_insert_or_free(PCB_PASTEBUFFER->Data, &proto, quiet); +} + + +void pcb_pstk_shape_update_pa(pcb_pstk_poly_t *poly) +{ + int n; + pcb_vector_t v; + pcb_pline_t *pl; + + v[0] = poly->x[0]; v[1] = poly->y[0]; + pl = pcb_poly_contour_new(v); + for(n = 1; n < poly->len; n++) { + v[0] = poly->x[n]; v[1] = poly->y[n]; + pcb_poly_vertex_include(pl->head.prev, pcb_poly_node_create(v)); + } + pcb_poly_contour_pre(pl, 1); + + poly->pa = pcb_polyarea_create(); + pcb_polyarea_contour_include(poly->pa, pl); + + if (!pcb_poly_valid(poly->pa)) { + poly->pa->contours = NULL; /* keep pl safe from pcb_polyarea_free() */ + pcb_polyarea_free(&poly->pa); + + poly->pa = pcb_polyarea_create(); + pcb_poly_contour_inv(pl); + pcb_polyarea_contour_include(poly->pa, pl); + poly->inverted = 1; + } + else + poly->inverted = 0; +} + +/*** Undoable hole change ***/ + +typedef struct { + long int parent_ID; /* -1 for pcb, positive for a subc */ + pcb_cardinal_t proto; + + int hplated; + pcb_coord_t hdia; + int htop, hbottom; +} padstack_proto_change_hole_t; + +#define swap(a,b,type) \ + do { \ + type tmp = a; \ + a = b; \ + b = tmp; \ + } while(0) + +static int undo_change_hole_swap(void *udata) +{ + padstack_proto_change_hole_t *u = udata; + pcb_data_t *data; + pcb_pstk_proto_t *proto; + + if (u->parent_ID != -1) { + pcb_subc_t *subc = pcb_subc_by_id(PCB->Data, u->parent_ID); + if (subc == NULL) { + pcb_message(PCB_MSG_ERROR, "Can't undo padstack prototype hole change: parent subc #%ld is not found\n", u->parent_ID); + return -1; + } + data = subc->data; + } + else + data = PCB->Data; + + proto = pcb_pstk_get_proto_(data, u->proto); + if (proto == NULL) { + pcb_message(PCB_MSG_ERROR, "Can't undo padstack prototype hole change: proto ID #%ld is not available\n", u->parent_ID); + return -1; + } + + swap(proto->hplated, u->hplated, int); + swap(proto->hdia, u->hdia, pcb_coord_t); + swap(proto->htop, u->htop, int); + swap(proto->hbottom, u->hbottom, int); + return 0; +} + +static void undo_change_hole_print(void *udata, char *dst, size_t dst_len) +{ + padstack_proto_change_hole_t *u = udata; + pcb_snprintf(dst, dst_len, "padstack proto hole change: plated=%d dia=%$mm top=%d bottom=%d\n", u->hplated, u->hdia, u->htop, u->hbottom); +} + +static const uundo_oper_t undo_pstk_proto_change_hole = { + core_proto_cookie, + NULL, /* free */ + undo_change_hole_swap, + undo_change_hole_swap, + undo_change_hole_print +}; + +int pcb_pstk_proto_change_hole(pcb_pstk_proto_t *proto, const int *hplated, const pcb_coord_t *hdia, const int *htop, const int *hbottom) +{ + padstack_proto_change_hole_t *u; + long int parent_ID; + + switch(proto->parent->parent_type) { + case PCB_PARENT_BOARD: parent_ID = -1; break; + case PCB_PARENT_SUBC: parent_ID = proto->parent->parent.subc->ID; break; + default: return -1; + } + + u = pcb_undo_alloc(PCB, &undo_pstk_proto_change_hole, sizeof(padstack_proto_change_hole_t)); + u->parent_ID = parent_ID; + u->proto = pcb_pstk_get_proto_id(proto); + u->hplated = hplated ? *hplated : proto->hplated; + u->hdia = hdia ? *hdia : proto->hdia; + u->htop = htop ? *htop : proto->htop; + u->hbottom = hbottom ? *hbottom : proto->hbottom; + undo_change_hole_swap(u); + + pcb_undo_inc_serial(); + return 0; +} + +int pcb_pstk_proto_change_name(pcb_pstk_proto_t *proto, const char *new_name) +{ +TODO("undo: make this undoable (check how pcb_pstk_proto_change_hole() does it)") + free(proto->name); + if ((new_name == NULL) || (*new_name == '\0')) + proto->name = NULL; + else + proto->name = pcb_strdup(new_name); + return 0; +} + +#define TSHAPE_ANGLE_TOL 0.01 +#define tshape_angle_eq(a1, a2) (((a1 - a2) >= -TSHAPE_ANGLE_TOL) && ((a1 - a2) <= TSHAPE_ANGLE_TOL)) + +pcb_pstk_tshape_t *pcb_pstk_make_tshape(pcb_data_t *data, pcb_pstk_proto_t *proto, double rot, int xmirror, int smirror, int *out_protoi) +{ + size_t n; + pcb_pstk_tshape_t *ts; + + xmirror = !!xmirror; + smirror = !!smirror; + + /* cheap case: canonical */ + if (tshape_angle_eq(rot, 0.0) && (xmirror == 0) && (smirror == 0)) { + if (out_protoi != NULL) *out_protoi = 0; + return &proto->tr.array[0]; + } + + /* search for an existing version in the cache - we expect only a few + transformations per padstack, the result is cached -> linear search. */ + for(n = 0; n < proto->tr.used; n++) { + if (tshape_angle_eq(proto->tr.array[n].rot, rot) && (proto->tr.array[n].xmirror == xmirror) && (proto->tr.array[n].smirror == smirror)) { + if (out_protoi != NULL) *out_protoi = n; + return &proto->tr.array[n]; + } + } + + /* allocate and render the transformed version for the cache */ + if (out_protoi != NULL) *out_protoi = proto->tr.used; + ts = pcb_vtpadstack_tshape_alloc_append(&proto->tr, 1); + + /* first make a vanilla copy */ + pcb_pstk_tshape_copy(ts, &proto->tr.array[0]); + + if (!tshape_angle_eq(rot, 0.0)) + pcb_pstk_tshape_rot(ts, rot); + + if (xmirror) + pcb_pstk_tshape_xmirror(ts); + + if (smirror) + pcb_pstk_tshape_smirror(ts); + + ts->rot = rot; + ts->xmirror = xmirror; + ts->smirror = smirror; + return ts; +} + +static void pcb_pstk_poly_center(const pcb_pstk_poly_t *poly, pcb_coord_t *cx, pcb_coord_t *cy) +{ + double x = 0.0, y = 0.0; + int n; + + for(n = 0; n < poly->len; n++) { + x += (double)poly->x[n]; + y += (double)poly->y[n]; + } + x /= (double)poly->len; + y /= (double)poly->len; + *cx = pcb_round(x); + *cy = pcb_round(y); +} + +void pcb_pstk_shape_grow(pcb_pstk_shape_t *shp, pcb_bool is_absolute, pcb_coord_t val) +{ + pcb_coord_t cx, cy; + int n; + +TODO("padstack: undo") + + switch(shp->shape) { + case PCB_PSSH_LINE: + if (is_absolute) + shp->data.line.thickness = val; + else + shp->data.line.thickness += val; + if (shp->data.line.thickness < 1) + shp->data.line.thickness = 1; + break; + case PCB_PSSH_CIRC: + if (is_absolute) + shp->data.circ.dia = val; + else + shp->data.circ.dia += val; + if (shp->data.circ.dia < 1) + shp->data.circ.dia = 1; + break; + case PCB_PSSH_HSHADOW: + break; + case PCB_PSSH_POLY: + pcb_pstk_poly_center(&shp->data.poly, &cx, &cy); + pcb_polyarea_free(&shp->data.poly.pa); + if (is_absolute) { +TODO("TODO") + } + else { + pcb_polo_t *p, p_st[32]; + double vl = pcb_round(val/2); + + if (shp->data.poly.len >= sizeof(p_st) / sizeof(p_st[0])) + p = malloc(sizeof(pcb_polo_t) * shp->data.poly.len); + else + p = p_st; + + /* relative: move each point radially */ + for(n = 0; n < shp->data.poly.len; n++) { + p[n].x = shp->data.poly.x[n]; + p[n].y = shp->data.poly.y[n]; + } + pcb_polo_norms(p, shp->data.poly.len); + pcb_polo_offs(vl, p, shp->data.poly.len); + for(n = 0; n < shp->data.poly.len; n++) { + shp->data.poly.x[n] = p[n].x; + shp->data.poly.y[n] = p[n].y; + } + if (p != p_st) + free(p); + } + pcb_pstk_shape_update_pa(&shp->data.poly); + break; + } +} + +void pcb_pstk_shape_scale(pcb_pstk_shape_t *shp, double sx, double sy) +{ + pcb_coord_t cx, cy; + int n; + +TODO("padstack: undo") + + switch(shp->shape) { + case PCB_PSSH_LINE: + shp->data.line.thickness = pcb_round(shp->data.line.thickness * ((sx+sy)/2.0)); + if (shp->data.line.thickness < 1) + shp->data.line.thickness = 1; + shp->data.line.x1 = pcb_round((double)shp->data.line.x1 * sx); + shp->data.line.y1 = pcb_round((double)shp->data.line.y1 * sy); + shp->data.line.x2 = pcb_round((double)shp->data.line.x2 * sx); + shp->data.line.y2 = pcb_round((double)shp->data.line.y2 * sy); + break; + case PCB_PSSH_CIRC: + shp->data.circ.dia = pcb_round(shp->data.circ.dia * ((sx+sy)/2.0)); + if (shp->data.circ.dia < 1) + shp->data.circ.dia = 1; + shp->data.circ.x = pcb_round((double)shp->data.circ.x * sx); + shp->data.circ.y = pcb_round((double)shp->data.circ.y * sy); + break; + case PCB_PSSH_HSHADOW: + break; + case PCB_PSSH_POLY: + pcb_pstk_poly_center(&shp->data.poly, &cx, &cy); + pcb_polyarea_free(&shp->data.poly.pa); + + for(n = 0; n < shp->data.poly.len; n++) { + shp->data.poly.x[n] = pcb_round((double)shp->data.poly.x[n] * sx); + shp->data.poly.y[n] = pcb_round((double)shp->data.poly.y[n] * sy); + } + pcb_pstk_shape_update_pa(&shp->data.poly); + break; + } +} + +void pcb_pstk_shape_clr_grow(pcb_pstk_shape_t *shp, pcb_bool is_absolute, pcb_coord_t val) +{ +TODO("padstack: undo") + if (is_absolute) + shp->clearance = val; + else + shp->clearance += val; +} + +void pcb_pstk_proto_grow(pcb_pstk_proto_t *proto, pcb_bool is_absolute, pcb_coord_t val) +{ + int n, i; + + /* do the same growth on all shapes of all transformed variants */ + for(n = 0; n < proto->tr.used; n++) + for(i = 0; i < proto->tr.array[n].len; i++) + pcb_pstk_shape_grow(&proto->tr.array[n].shape[i], is_absolute, val); + pcb_pstk_proto_update(proto); +} + +void pcb_pstk_shape_derive(pcb_pstk_proto_t *proto, int dst_idx, int src_idx, pcb_coord_t bloat, pcb_layer_type_t mask, pcb_layer_combining_t comb) +{ + int n; + + /* do the same copy on all shapes of all transformed variants */ + for(n = 0; n < proto->tr.used; n++) { + int d = dst_idx; + if (d < 0) { + d = proto->tr.array[n].len; + proto->tr.array[n].len++; + proto->tr.array[n].shape = realloc(proto->tr.array[n].shape, proto->tr.array[n].len * sizeof(proto->tr.array[n].shape[0])); + + } + else + pcb_pstk_shape_free(&proto->tr.array[n].shape[d]); + pcb_pstk_shape_copy(&proto->tr.array[n].shape[d], &proto->tr.array[n].shape[src_idx]); + proto->tr.array[n].shape[d].layer_mask = mask; + proto->tr.array[n].shape[d].comb = comb; + if (bloat != 0) + pcb_pstk_shape_grow(&proto->tr.array[n].shape[d], pcb_false, bloat); + } + pcb_pstk_proto_update(proto); +} + +int pcb_pstk_shape_swap_layer(pcb_pstk_proto_t *proto, int idx1, int idx2) +{ + int n; + pcb_layer_type_t lm; + pcb_layer_combining_t lc; + + if ((idx1 < 0) || (idx1 > proto->tr.array[0].len)) + return -1; + if ((idx2 < 0) || (idx2 > proto->tr.array[0].len)) + return -1; + + for(n = 0; n < proto->tr.used; n++) { + lm = proto->tr.array[n].shape[idx1].layer_mask; + lc = proto->tr.array[n].shape[idx1].comb; + proto->tr.array[n].shape[idx1].layer_mask = proto->tr.array[n].shape[idx2].layer_mask; + proto->tr.array[n].shape[idx1].comb = proto->tr.array[n].shape[idx2].comb; + proto->tr.array[n].shape[idx2].layer_mask = lm; + proto->tr.array[n].shape[idx2].comb = lc; + } + return 0; +} + + +void pcb_pstk_shape_add_hshadow(pcb_pstk_proto_t *proto, pcb_layer_type_t mask, pcb_layer_combining_t comb) +{ + int n; + + /* do the same on all shapes of all transformed variants */ + for(n = 0; n < proto->tr.used; n++) { + int d = proto->tr.array[n].len; + proto->tr.array[n].len++; + proto->tr.array[n].shape = realloc(proto->tr.array[n].shape, proto->tr.array[n].len * sizeof(proto->tr.array[n].shape[0])); + proto->tr.array[n].shape[d].shape = PCB_PSSH_HSHADOW; + proto->tr.array[n].shape[d].layer_mask = mask; + proto->tr.array[n].shape[d].comb = comb; + } + pcb_pstk_proto_update(proto); +} + + +static void pcb_pstk_tshape_del_idx(pcb_pstk_tshape_t *shp, int idx) +{ + int n; + for(n = idx; n < shp->len-1; n++) + shp->shape[n] = shp->shape[n+1]; + shp->len--; +} + +void pcb_pstk_proto_del_shape_idx(pcb_pstk_proto_t *proto, int idx) +{ + int n; + + if ((proto->tr.used == 0) || (idx < 0) || (idx >= proto->tr.array[0].len)) + return; + + /* delete the shape from all transformed variants */ + for(n = 0; n < proto->tr.used; n++) + pcb_pstk_tshape_del_idx(&proto->tr.array[n], idx); + + pcb_pstk_proto_update(proto); +} + +void pcb_pstk_proto_del_shape(pcb_pstk_proto_t *proto, pcb_layer_type_t lyt, pcb_layer_combining_t comb) +{ + int idx; + + if (proto->tr.used == 0) + return; + + /* search the 0th transformed, all other tshapes are the same */ + idx = pcb_pstk_get_shape_idx(&proto->tr.array[0], lyt, comb); + pcb_pstk_proto_del_shape_idx(proto, idx); +} + +void pcb_pstk_proto_del(pcb_data_t *data, pcb_cardinal_t proto_id) +{ + pcb_pstk_proto_t *proto = pcb_vtpadstack_proto_get(&data->ps_protos, proto_id, 0); + if (proto == NULL) + return; + pcb_pstk_proto_free_fields(proto); +} + +pcb_cardinal_t *pcb_pstk_proto_used_all(pcb_data_t *data, pcb_cardinal_t *len_out) +{ + pcb_cardinal_t len, *res; + pcb_pstk_t *ps; + + len = data->ps_protos.used; + if (len == 0) { + *len_out = 0; + return NULL; + } + + res = calloc(sizeof(pcb_cardinal_t), len); + for(ps = padstacklist_first(&data->padstack); ps != NULL; ps = padstacklist_next(ps)) { + if ((ps->proto >= 0) && (ps->proto < len)) + res[ps->proto]++; + } + + /* routing styles may also reference to prototypes if we are on a board */ + if (data->parent_type == PCB_PARENT_BOARD) { + pcb_board_t *pcb = data->parent.board; + int n; + + for(n = 0; n < pcb->RouteStyle.used; n++) { + if (pcb->RouteStyle.array[n].via_proto_set) { + pcb_cardinal_t pid = pcb->RouteStyle.array[n].via_proto; + if ((pid >= 0) && (pid < len)) + res[pid]++; + } + } + } + + *len_out = len; + return res; +} + +/*** hash ***/ +static unsigned int pcb_pstk_shape_hash(const pcb_pstk_shape_t *sh) +{ + unsigned int n, ret = murmurhash32(sh->layer_mask) ^ murmurhash32(sh->comb) ^ pcb_hash_coord(sh->clearance); + + switch(sh->shape) { + case PCB_PSSH_POLY: + for(n = 0; n < sh->data.poly.len; n++) + ret ^= pcb_hash_coord(sh->data.poly.x[n]) ^ pcb_hash_coord(sh->data.poly.y[n]); + break; + case PCB_PSSH_LINE: + ret ^= pcb_hash_coord(sh->data.line.x1) ^ pcb_hash_coord(sh->data.line.x2) ^ pcb_hash_coord(sh->data.line.y1) ^ pcb_hash_coord(sh->data.line.y2); + ret ^= pcb_hash_coord(sh->data.line.thickness); + ret ^= sh->data.line.square; + break; + case PCB_PSSH_CIRC: + ret ^= pcb_hash_coord(sh->data.circ.x) ^ pcb_hash_coord(sh->data.circ.y); + ret ^= pcb_hash_coord(sh->data.circ.dia); + break; + case PCB_PSSH_HSHADOW: + break; + } + + return ret; +} + +unsigned int pcb_pstk_proto_hash(const pcb_pstk_proto_t *p) +{ + pcb_pstk_tshape_t *ts = &p->tr.array[0]; + unsigned int n, ret = pcb_hash_coord(p->hdia) ^ pcb_hash_coord(p->htop) ^ pcb_hash_coord(p->hbottom) ^ pcb_hash_coord(p->hplated); + if (ts != NULL) { + ret ^= pcb_hash_coord(ts->len); + for(n = 0; n < ts->len; n++) + ret ^= pcb_pstk_shape_hash(ts->shape + n); + } + return ret; +} + +int pcb_pstk_shape_eq(const pcb_pstk_shape_t *sh1, const pcb_pstk_shape_t *sh2) +{ + int n; + + if (sh1->layer_mask != sh2->layer_mask) return 0; + if (sh1->comb != sh2->comb) return 0; + if (sh1->clearance != sh2->clearance) return 0; + if (sh1->shape != sh2->shape) return 0; + + switch(sh1->shape) { + case PCB_PSSH_POLY: + if (sh1->data.poly.len != sh2->data.poly.len) return 0; + for(n = 0; n < sh1->data.poly.len; n++) { + if (sh1->data.poly.x[n] != sh2->data.poly.x[n]) return 0; + if (sh1->data.poly.y[n] != sh2->data.poly.y[n]) return 0; + } + break; + case PCB_PSSH_LINE: + if (sh1->data.line.x1 != sh2->data.line.x1) return 0; + if (sh1->data.line.x2 != sh2->data.line.x2) return 0; + if (sh1->data.line.y1 != sh2->data.line.y1) return 0; + if (sh1->data.line.y2 != sh2->data.line.y2) return 0; + if (sh1->data.line.thickness != sh2->data.line.thickness) return 0; + if (sh1->data.line.square != sh2->data.line.square) return 0; + break; + case PCB_PSSH_CIRC: + if (sh1->data.circ.x != sh2->data.circ.x) return 0; + if (sh1->data.circ.y != sh2->data.circ.y) return 0; + if (sh1->data.circ.dia != sh2->data.circ.dia) return 0; + break; + case PCB_PSSH_HSHADOW: + break; + } + + return 1; +} + +int pcb_pstk_proto_eq(const pcb_pstk_proto_t *p1, const pcb_pstk_proto_t *p2) +{ + pcb_pstk_tshape_t *ts1 = &p1->tr.array[0], *ts2 = &p2->tr.array[0]; + int n1, n2; + + if (p1->hdia != p2->hdia) return 0; + if (p1->htop != p2->htop) return 0; + if (p1->hbottom != p2->hbottom) return 0; + if (p1->hplated != p2->hplated) return 0; + if ((ts1 == NULL) && (ts2 != NULL)) return 0; + if ((ts2 == NULL) && (ts1 != NULL)) return 0; + + if (ts1 != NULL) { + if (ts1->len != ts2->len) return 0; + for(n1 = 0; n1 < ts1->len; n1++) { + for(n2 = 0; n2 < ts2->len; n2++) + if (pcb_pstk_shape_eq(ts1->shape + n1, ts2->shape + n2)) + goto found; + return 0; + found:; + } + } + + return 1; +} + Index: tags/2.1.2/src/obj_pstk_shape.h =================================================================== --- tags/2.1.2/src/obj_pstk_shape.h (nonexistent) +++ tags/2.1.2/src/obj_pstk_shape.h (revision 24813) @@ -0,0 +1,81 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2017 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#ifndef PCB_OBJ_PSTK_SHAPE_H +#define PCB_OBJ_PSTK_SHAPE_H + +#include "unit.h" +#include "polygon.h" +#include "layer.h" + +typedef struct pcb_pstk_poly_s { + unsigned int len; /* number of points in polygon */ + pcb_coord_t *x; /* ordered list of points, X coord */ + pcb_coord_t *y; /* ordered list of points, Y coord */ + pcb_polyarea_t *pa; /* cache for the poly code */ + char inverted; /* 1 if x;y has the opposite direction as pa */ +} pcb_pstk_poly_t; + +typedef struct pcb_pstk_line_s { + pcb_coord_t x1, y1, x2, y2, thickness; + unsigned square:1; +} pcb_pstk_line_t; + +typedef struct pcb_pstk_circ_s { + pcb_coord_t dia; /* diameter of the filled circle */ + pcb_coord_t x, y; /* assymetric pads */ +} pcb_pstk_circ_t; + +typedef struct pcb_pstk_shape_s { + pcb_layer_type_t layer_mask; + pcb_layer_combining_t comb; + union { + pcb_pstk_poly_t poly; + pcb_pstk_line_t line; + pcb_pstk_circ_t circ; + } data; + enum { + PCB_PSSH_POLY, + PCB_PSSH_LINE, + PCB_PSSH_CIRC, /* filled circle */ + PCB_PSSH_HSHADOW /* for clearance: pretend the shape is the same as the drill's or slot's; but do not add anything positive to the target layer */ + } shape; + pcb_coord_t clearance; /* per layer clearance: internal layer clearance is sometimes different for production or insulation reasons (IPC2221A) */ +} pcb_pstk_shape_t; + +/* transformed prototype */ +typedef struct pcb_pstk_tshape_s { + double rot; + unsigned xmirror:1; + unsigned smirror:1; + + unsigned char len; /* number of shapes (PCB_PADSTACK_MAX_SHAPES) */ + pcb_pstk_shape_t *shape; /* list of layer-shape pairs */ +} pcb_pstk_tshape_t; + +void pcb_pstk_shape_rot(pcb_pstk_shape_t *sh, double sina, double cosa, double angle); + +#endif Index: tags/2.1.2/src/obj_rat.c =================================================================== --- tags/2.1.2/src/obj_rat.c (nonexistent) +++ tags/2.1.2/src/obj_rat.c (revision 24813) @@ -0,0 +1,535 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ +#include "config.h" + +#include "board.h" +#include "data.h" +#include "data_it.h" +#include "conf_core.h" +#include "hid_inlines.h" +#include "undo.h" +#include "rtree.h" +#include "search.h" + +#include "obj_line_draw.h" + +#include "obj_rat.h" +#include "obj_rat_list.h" +#include "obj_rat_op.h" + +#include "obj_rat_draw.h" + +/*** allocation ***/ + +void pcb_rat_reg(pcb_data_t *data, pcb_rat_t *rat) +{ + ratlist_append(&data->Rat, rat); + pcb_obj_id_reg(data, rat); + PCB_SET_PARENT(rat, data, data); +} + +void pcb_rat_unreg(pcb_rat_t *rat) +{ + pcb_data_t *data = rat->parent.data; + assert(rat->parent_type == PCB_PARENT_DATA); + ratlist_remove(rat); + pcb_obj_id_del(data, rat); + PCB_CLEAR_PARENT(rat); +} + +pcb_rat_t *pcb_rat_alloc_id(pcb_data_t *data, long int id) +{ + pcb_rat_t *new_obj; + + new_obj = calloc(sizeof(pcb_rat_t), 1); + new_obj->ID = id; + new_obj->type = PCB_OBJ_RAT; + + pcb_rat_reg(data, new_obj); + + return new_obj; +} + +pcb_rat_t *pcb_rat_alloc(pcb_data_t *data) +{ + return pcb_rat_alloc_id(data, pcb_create_ID_get()); +} + +void pcb_rat_free(pcb_rat_t *rat) +{ + pcb_rat_unreg(rat); + free(rat->anchor[0]); + free(rat->anchor[1]); + free(rat); +} + +/*** utility ***/ +/* creates a new rat-line */ +pcb_rat_t *pcb_rat_new(pcb_data_t *Data, long int id, pcb_coord_t X1, pcb_coord_t Y1, pcb_coord_t X2, pcb_coord_t Y2, pcb_layergrp_id_t group1, pcb_layergrp_id_t group2, pcb_coord_t Thickness, pcb_flag_t Flags, pcb_any_obj_t *anchor1, pcb_any_obj_t *anchor2) +{ + pcb_rat_t *Line; + + if (id <= 0) + id = pcb_create_ID_get(); + + Line = pcb_rat_alloc_id(Data, id); + if (!Line) + return Line; + + Line->Flags = Flags; + PCB_FLAG_SET(PCB_FLAG_RAT, Line); + Line->Thickness = Thickness; + Line->Point1.X = X1; + Line->Point1.Y = Y1; + Line->Point1.ID = pcb_create_ID_get(); + Line->Point2.X = X2; + Line->Point2.Y = Y2; + Line->Point2.ID = pcb_create_ID_get(); + Line->group1 = group1; + Line->group2 = group2; + pcb_line_bbox((pcb_line_t *) Line); + if (!Data->rat_tree) + Data->rat_tree = pcb_r_create_tree(); + pcb_r_insert_entry(Data->rat_tree, &Line->BoundingBox); + + if (anchor1 != NULL) + Line->anchor[0] = pcb_obj2idpath(anchor1); + if (anchor2 != NULL) + Line->anchor[1] = pcb_obj2idpath(anchor2); + + return Line; +} + +/* DeleteRats - deletes rat lines only + * can delete all rat lines, or only selected one */ +pcb_bool pcb_rats_destroy(pcb_bool selected) +{ + pcb_opctx_t ctx; + pcb_bool changed = pcb_false; + + ctx.remove.pcb = PCB; + ctx.remove.destroy_target = NULL; + + PCB_RAT_LOOP(PCB->Data); + { + if ((!selected) || PCB_FLAG_TEST(PCB_FLAG_SELECTED, line)) { + changed = pcb_true; + pcb_ratop_remove(&ctx, line); + } + } + PCB_END_LOOP; + if (changed) + pcb_undo_inc_serial(); + return changed; +} + +/*** utility ***/ + +static pcb_bool rat_meets_line(pcb_line_t *line, pcb_coord_t x, pcb_coord_t y, pcb_layergrp_id_t gid) +{ + if (gid >= 0) { + pcb_layer_t *ly = pcb_layer_get_real(line->parent.layer); + if ((ly == NULL) || (ly->meta.real.grp != gid)) + return 0; + } + if ((line->Point1.X == x) && (line->Point1.Y == y)) return pcb_true; + if ((line->Point2.X == x) && (line->Point2.Y == y)) return pcb_true; + return pcb_is_point_on_line(x, y, 1, line); +} + + +static pcb_bool rat_meets_arc(pcb_arc_t *arc, pcb_coord_t x, pcb_coord_t y, pcb_layergrp_id_t gid) +{ + if (gid >= 0) { + pcb_layer_t *ly = pcb_layer_get_real(arc->parent.layer); + if ((ly == NULL) || (ly->meta.real.grp != gid)) + return 0; + } + return pcb_is_point_on_arc(x, y, 1, arc); +} + + +static pcb_bool rat_meets_poly(pcb_poly_t *poly, pcb_coord_t x, pcb_coord_t y, pcb_layergrp_id_t gid) +{ + if (gid >= 0) { + pcb_layer_t *ly = pcb_layer_get_real(poly->parent.layer); + if ((ly == NULL) || (ly->meta.real.grp != gid)) + return 0; + } + return pcb_poly_is_point_in_p(x, y, 1, poly); +} + +static pcb_bool rat_meets_pstk(pcb_data_t *data, pcb_pstk_t *pstk, pcb_coord_t x, pcb_coord_t y, pcb_layergrp_id_t gid) +{ + pcb_layergrp_t *g = pcb_get_layergrp(PCB, gid); + pcb_layer_t *ly; + if (g == NULL) + return pcb_false; + + ly = pcb_get_layer(data, g->lid[0]); + if (ly != NULL) + ly = pcb_layer_get_real(ly); + if (ly == NULL) + return pcb_false; + + if ((pstk->x == x) && (pstk->y == y)) + return pcb_true; + + return pcb_is_point_in_pstk(x, y, 1, pstk, ly); +} + + +/* return the first object (the type that is most likely an endpoint of a rat) + on a point on a layer */ +static pcb_any_obj_t *find_obj_on_layer(pcb_coord_t x, pcb_coord_t y, pcb_layer_t *l) +{ + pcb_rtree_it_t it; + pcb_box_t *n; + pcb_rtree_box_t sb; + + sb.x1 = x; sb.x2 = x+1; + sb.y1 = y; sb.y2 = y+1; + + if (l->line_tree != NULL) { + for(n = pcb_rtree_first(&it, l->line_tree, &sb); n != NULL; n = pcb_rtree_next(&it)) { + if (rat_meets_line((pcb_line_t *)n, x, y, -1)) { + pcb_r_end(&it); + return (pcb_any_obj_t *)n; + } + } + pcb_r_end(&it); + } + + if (l->arc_tree != NULL) { + for(n = pcb_rtree_first(&it, l->arc_tree, &sb); n != NULL; n = pcb_rtree_next(&it)) { + if (rat_meets_arc((pcb_arc_t *)n, x, y, -1)) { + pcb_r_end(&it); + return (pcb_any_obj_t *)n; + } + } + pcb_r_end(&it); + } + + if (l->polygon_tree != NULL) { + for(n = pcb_rtree_first(&it, l->polygon_tree, &sb); n != NULL; n = pcb_rtree_next(&it)) { + if (rat_meets_poly((pcb_poly_t *)n, x, y, -1)) { + pcb_r_end(&it); + return (pcb_any_obj_t *)n; + } + } + pcb_r_end(&it); + } + +TODO("find through text"); +#if 0 + if (l->text_tree != NULL) { + for(n = pcb_rtree_first(&it, l->text_tree, &sb); n != NULL; n = pcb_rtree_next(&it)) { + if (rat_meets_text((pcb_text_t *)n, x, y, -1)) { + pcb_r_end(&it); + return (pcb_any_obj_t *)n; + } + } + + pcb_r_end(&it); + } +#endif + return NULL; +} + +/* return the first object (the type that is most likely an endpoint of a rat) + on a point on a layer group */ +static pcb_any_obj_t *find_obj_on_grp(pcb_data_t *data, pcb_coord_t x, pcb_coord_t y, pcb_layergrp_id_t gid) +{ + int i; + pcb_rtree_box_t sb; + pcb_rtree_it_t it; + pcb_box_t *n; + pcb_layergrp_t *g = pcb_get_layergrp(PCB, gid); + + if (g == NULL) + return NULL; + + sb.x1 = x; sb.x2 = x+1; + sb.y1 = y; sb.y2 = y+1; + + if (PCB->Data->padstack_tree != NULL) { + for(n = pcb_rtree_first(&it, data->padstack_tree, &sb); n != NULL; n = pcb_rtree_next(&it)) { + if (rat_meets_pstk(data, (pcb_pstk_t *)n, x, y, gid)) { + pcb_r_end(&it); + return (pcb_any_obj_t *)n; + } + } + pcb_r_end(&it); + } + + for(i = 0; i < g->len; i++) { + pcb_any_obj_t *o = find_obj_on_layer(x, y, &data->Layer[g->lid[i]]); + if (o != NULL) + return o; + } + return NULL; +} + +pcb_any_obj_t *pcb_rat_anchor_guess(pcb_rat_t *rat, int end, pcb_bool update) +{ + pcb_data_t *data = rat->parent.data; + pcb_idpath_t **path = &rat->anchor[!!end]; + pcb_coord_t x = (end == 0) ? rat->Point1.X : rat->Point2.X; + pcb_coord_t y = (end == 0) ? rat->Point1.Y : rat->Point2.Y; + pcb_layergrp_id_t gid = (end == 0) ? rat->group1 : rat->group2; + pcb_any_obj_t *ao; + + /* (relatively) cheap thest if existing anchor is valid */ + if (*path != NULL) { + ao = pcb_idpath2obj(data, *path); + switch(ao->type) { + case PCB_OBJ_LINE: if (rat_meets_line((pcb_line_t *)ao, x, y, gid)) return ao; break; + case PCB_OBJ_ARC: if (rat_meets_arc((pcb_arc_t *)ao, x, y, gid)) return ao; break; + case PCB_OBJ_POLY: if (rat_meets_poly((pcb_poly_t *)ao, x, y, gid)) return ao; break; + case PCB_OBJ_PSTK: if (rat_meets_pstk(data, (pcb_pstk_t *)ao, x, y, gid)) return ao; break; + TODO("find through text") + default: break; + } + } + + /* if we got here, there was no anchor object set or it was outdated - find + the currently valid object by endpoint */ + ao = find_obj_on_grp(data, x, y, gid); + if (update) { + if (*path != NULL) + pcb_idpath_destroy(*path); + if (ao == NULL) + *path = NULL; + else + *path = pcb_obj2idpath(ao); + } + + return ao; +} + +void pcb_rat_all_anchor_guess(pcb_data_t *data) +{ + pcb_rat_t *rat; + gdl_iterator_t it; + ratlist_foreach(&data->Rat, &it, rat) { + pcb_rat_anchor_guess(rat, 0, pcb_true); + pcb_rat_anchor_guess(rat, 1, pcb_true); + } +} + + +/*** ops ***/ +/* copies a rat-line to paste buffer */ +void *pcb_ratop_add_to_buffer(pcb_opctx_t *ctx, pcb_rat_t *Rat) +{ + pcb_rat_t *res = pcb_rat_new(ctx->buffer.dst, -1, Rat->Point1.X, Rat->Point1.Y, + Rat->Point2.X, Rat->Point2.Y, Rat->group1, Rat->group2, Rat->Thickness, + pcb_flag_mask(Rat->Flags, PCB_FLAG_FOUND | ctx->buffer.extraflg), + NULL, NULL); + + res->anchor[0] = pcb_idpath_dup(Rat->anchor[0]); + res->anchor[1] = pcb_idpath_dup(Rat->anchor[1]); + return res; +} + +/* moves a rat-line between board and buffer */ +void *pcb_ratop_move_buffer(pcb_opctx_t *ctx, pcb_rat_t * rat) +{ + pcb_r_delete_entry(ctx->buffer.src->rat_tree, (pcb_box_t *) rat); + + pcb_rat_unreg(rat); + pcb_rat_reg(ctx->buffer.dst, rat); + + PCB_FLAG_CLEAR(PCB_FLAG_FOUND, rat); + + if (!ctx->buffer.dst->rat_tree) + ctx->buffer.dst->rat_tree = pcb_r_create_tree(); + pcb_r_insert_entry(ctx->buffer.dst->rat_tree, (pcb_box_t *) rat); + + return rat; +} + +/* inserts a point into a rat-line */ +void *pcb_ratop_insert_point(pcb_opctx_t *ctx, pcb_rat_t *Rat) +{ + pcb_line_t *newone; + + newone = pcb_line_new_merge(CURRENT, Rat->Point1.X, Rat->Point1.Y, + ctx->insert.x, ctx->insert.y, conf_core.design.line_thickness, 2 * conf_core.design.clearance, Rat->Flags); + if (!newone) + return newone; + pcb_undo_add_obj_to_create(PCB_OBJ_LINE, CURRENT, newone, newone); + pcb_rat_invalidate_erase(Rat); + pcb_line_invalidate_draw(CURRENT, newone); + newone = pcb_line_new_merge(CURRENT, Rat->Point2.X, Rat->Point2.Y, + ctx->insert.x, ctx->insert.y, conf_core.design.line_thickness, 2 * conf_core.design.clearance, Rat->Flags); + if (newone) { + pcb_undo_add_obj_to_create(PCB_OBJ_LINE, CURRENT, newone, newone); + pcb_line_invalidate_draw(CURRENT, newone); + } + pcb_undo_move_obj_to_remove(PCB_OBJ_RAT, Rat, Rat, Rat); + return newone; +} + +/* move a rat to a layer: convert it into a layer line */ +void *pcb_ratop_move_to_layer(pcb_opctx_t *ctx, pcb_rat_t * Rat) +{ + pcb_line_t *newone; + newone = pcb_line_new(ctx->move.dst_layer, Rat->Point1.X, Rat->Point1.Y, + Rat->Point2.X, Rat->Point2.Y, conf_core.design.line_thickness, 2 * conf_core.design.clearance, Rat->Flags); + if (conf_core.editor.clear_line) + conf_set_editor(clear_line, 1); + if (!newone) + return NULL; + pcb_undo_add_obj_to_create(PCB_OBJ_LINE, ctx->move.dst_layer, newone, newone); + if (PCB->RatOn) + pcb_rat_invalidate_erase(Rat); + pcb_undo_move_obj_to_remove(PCB_OBJ_RAT, Rat, Rat, Rat); + pcb_line_invalidate_draw(ctx->move.dst_layer, newone); + return newone; +} + +/* destroys a rat */ +void *pcb_ratop_destroy(pcb_opctx_t *ctx, pcb_rat_t *Rat) +{ + if (ctx->remove.destroy_target->rat_tree) + pcb_r_delete_entry(ctx->remove.destroy_target->rat_tree, &Rat->BoundingBox); + + pcb_rat_free(Rat); + return NULL; +} + +/* removes a rat */ +void *pcb_ratop_remove(pcb_opctx_t *ctx, pcb_rat_t *Rat) +{ + /* erase from screen and memory */ + if (PCB->RatOn) + pcb_rat_invalidate_erase(Rat); + pcb_undo_move_obj_to_remove(PCB_OBJ_RAT, Rat, Rat, Rat); + return NULL; +} + +/*** draw ***/ +pcb_r_dir_t pcb_rat_draw_callback(const pcb_box_t * b, void *cl) +{ + pcb_rat_t *rat = (pcb_rat_t *) b; + + if (PCB_FLAG_TEST(PCB_FLAG_SELECTED | PCB_FLAG_FOUND, rat)) { + if (PCB_FLAG_TEST(PCB_FLAG_SELECTED, rat)) + pcb_gui->set_color(pcb_draw_out.fgGC, &conf_core.appearance.color.selected); + else + pcb_gui->set_color(pcb_draw_out.fgGC, &conf_core.appearance.color.connected); + } + else if (PCB_HAS_COLOROVERRIDE(rat)) { + pcb_gui->set_color(pcb_draw_out.fgGC, rat->override_color); + } + else + pcb_gui->set_color(pcb_draw_out.fgGC, &conf_core.appearance.color.rat); + + if (conf_core.appearance.rat_thickness < 20) + rat->Thickness = pcb_pixel_slop * conf_core.appearance.rat_thickness; + /* rats.c set PCB_FLAG_VIA if this rat goes to a containing poly: draw a donut */ + if (PCB_FLAG_TEST(PCB_FLAG_VIA, rat)) { + int w = rat->Thickness; + + if (conf_core.editor.thin_draw || conf_core.editor.wireframe_draw) + pcb_hid_set_line_width(pcb_draw_out.fgGC, 0); + else + pcb_hid_set_line_width(pcb_draw_out.fgGC, w); + pcb_gui->draw_arc(pcb_draw_out.fgGC, rat->Point1.X, rat->Point1.Y, w * 2, w * 2, 0, 360); + } + else + pcb_line_draw_(NULL, (pcb_line_t *) rat, 0); + return PCB_R_DIR_FOUND_CONTINUE; +} + +void pcb_rat_invalidate_erase(pcb_rat_t *Rat) +{ + if (PCB_FLAG_TEST(PCB_FLAG_VIA, Rat)) { + pcb_coord_t w = Rat->Thickness; + + pcb_box_t b; + + b.X1 = Rat->Point1.X - w * 2 - w / 2; + b.X2 = Rat->Point1.X + w * 2 + w / 2; + b.Y1 = Rat->Point1.Y - w * 2 - w / 2; + b.Y2 = Rat->Point1.Y + w * 2 + w / 2; + pcb_draw_invalidate(&b); + } + else + pcb_line_invalidate_erase((pcb_line_t *) Rat); + pcb_flag_erase(&Rat->Flags); +} + +void pcb_rat_invalidate_draw(pcb_rat_t *Rat) +{ + if (conf_core.appearance.rat_thickness < 20) + Rat->Thickness = pcb_pixel_slop * conf_core.appearance.rat_thickness; + /* rats.c set PCB_FLAG_VIA if this rat goes to a containing poly: draw a donut */ + if (PCB_FLAG_TEST(PCB_FLAG_VIA, Rat)) { + pcb_coord_t w = Rat->Thickness; + + pcb_box_t b; + + b.X1 = Rat->Point1.X - w * 2 - w / 2; + b.X2 = Rat->Point1.X + w * 2 + w / 2; + b.Y1 = Rat->Point1.Y - w * 2 - w / 2; + b.Y2 = Rat->Point1.Y + w * 2 + w / 2; + pcb_draw_invalidate(&b); + } + else + pcb_line_invalidate_draw(NULL, (pcb_line_t *) Rat); +} + +void pcb_rat_update_obj_removed(pcb_board_t *pcb, pcb_any_obj_t *obj) +{ + pcb_rat_t *rat; + gdl_iterator_t it; + + if (obj->type == PCB_OBJ_SUBC) { + pcb_subc_t *subc = (pcb_subc_t *)obj; + pcb_any_obj_t *o; + pcb_data_it_t it2; + + /* subcircuit means checking against each part object; + this is O(R*P), where R is the number of rat lines and P is the + number of subc parts - maybe an rtree based approach would be better */ + for(o = pcb_data_first(&it2, subc->data, PCB_OBJ_CLASS_REAL); o != NULL; o = pcb_data_next(&it2)) + pcb_rat_update_obj_removed(pcb, o); + return; + } + + ratlist_foreach(&pcb->Data->Rat, &it, rat) { + if ((pcb_rat_anchor_guess(rat, 0, 1) == obj) || (pcb_rat_anchor_guess(rat, 1, 1) == obj)) { + if (PCB->RatOn) + pcb_rat_invalidate_erase(rat); + pcb_undo_move_obj_to_remove(PCB_OBJ_RAT, rat, rat, rat); + } + } +} + Index: tags/2.1.2/src/obj_rat.h =================================================================== --- tags/2.1.2/src/obj_rat.h (nonexistent) +++ tags/2.1.2/src/obj_rat.h (revision 24813) @@ -0,0 +1,73 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +/* Drawing primitive: rats */ + +#ifndef PCB_OBJ_RAT_H +#define PCB_OBJ_RAT_H + +#include +#include "obj_common.h" +#include "layer_grp.h" +#include "idpath.h" + +struct pcb_rat_line_s { /* a rat-line */ + PCB_ANYLINEFIELDS; + pcb_layergrp_id_t group1, group2; /* the layer group each point is on */ + pcb_idpath_t *anchor[2]; /* endpoint object that were originally connected */ + gdl_elem_t link; /* a rat line is in a list on a design */ +}; + + +pcb_rat_t *pcb_rat_alloc(pcb_data_t *data); +pcb_rat_t *pcb_rat_alloc_id(pcb_data_t *data, long int id); +void pcb_rat_free(pcb_rat_t *data); +void pcb_rat_reg(pcb_data_t *data, pcb_rat_t *rat); +void pcb_rat_unreg(pcb_rat_t *rat); + +/* if id is <= 0, allocate a new id */ +pcb_rat_t *pcb_rat_new(pcb_data_t *Data, long int id, pcb_coord_t X1, pcb_coord_t Y1, pcb_coord_t X2, pcb_coord_t Y2, pcb_layergrp_id_t group1, pcb_layergrp_id_t group2, pcb_coord_t Thickness, pcb_flag_t Flags, pcb_any_obj_t *anchor1, pcb_any_obj_t *anchor2); +pcb_bool pcb_rats_destroy(pcb_bool selected); + +/* Look up the anchor object (object the rat is connected to) for end 0 or + end 1. If update is true, also update rat's field */ +pcb_any_obj_t *pcb_rat_anchor_guess(pcb_rat_t *rat, int end, pcb_bool update); + +/* Call pcb_rat_anchor_guess() on all rats of data, with update=true */ +void pcb_rat_all_anchor_guess(pcb_data_t *data); + +/* Minimal update rats after object removal: remove connected rats */ +void pcb_rat_update_obj_removed(pcb_board_t *pcb, pcb_any_obj_t *obj); + + +#define PCB_RAT_LOOP(top) do { \ + pcb_rat_t *line; \ + gdl_iterator_t __it__; \ + ratlist_foreach(&(top)->Rat, &__it__, line) { + +#endif Index: tags/2.1.2/src/obj_rat_draw.h =================================================================== --- tags/2.1.2/src/obj_rat_draw.h (nonexistent) +++ tags/2.1.2/src/obj_rat_draw.h (revision 24813) @@ -0,0 +1,37 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +/*** Standard draw on rats ***/ + +/* Include rtree.h for these */ +#ifdef PCB_RTREE_H +pcb_r_dir_t pcb_rat_draw_callback(const pcb_box_t * b, void *cl); +#endif + +void pcb_rat_invalidate_erase(pcb_rat_t *Rat); +void pcb_rat_invalidate_draw(pcb_rat_t *Rat); Index: tags/2.1.2/src/obj_rat_list.c =================================================================== --- tags/2.1.2/src/obj_rat_list.c (nonexistent) +++ tags/2.1.2/src/obj_rat_list.c (revision 24813) @@ -0,0 +1,34 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2016 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "config.h" + +#include "layer_grp.h" +#include "obj_rat.h" + +#define TDL_DONT_UNDEF +#include "obj_rat_list.h" +#include Index: tags/2.1.2/src/obj_rat_list.h =================================================================== --- tags/2.1.2/src/obj_rat_list.h (nonexistent) +++ tags/2.1.2/src/obj_rat_list.h (revision 24813) @@ -0,0 +1,47 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2016 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#ifndef PCB_OBJ_RAT_LIST_H +#define PCB_OBJ_RAT_LIST_H + +#include "obj_rat.h" + +/* List of Rats */ +#define TDL(x) ratlist_ ## x +#define TDL_LIST_T ratlist_t +#define TDL_ITEM_T pcb_rat_t +#define TDL_FIELD link +#define TDL_SIZE_T size_t +#define TDL_FUNC + +#define ratlist_foreach(list, iterator, loop_elem) \ + gdl_foreach_((&((list)->lst)), (iterator), (loop_elem)) + + +#include +#include + +#endif Index: tags/2.1.2/src/obj_rat_op.h =================================================================== --- tags/2.1.2/src/obj_rat_op.h (nonexistent) +++ tags/2.1.2/src/obj_rat_op.h (revision 24813) @@ -0,0 +1,38 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +/*** Standard operations on rat lines ***/ + +#include "operation.h" + +void *pcb_ratop_add_to_buffer(pcb_opctx_t *ctx, pcb_rat_t *Rat); +void *pcb_ratop_move_buffer(pcb_opctx_t *ctx, pcb_rat_t * rat); +void *pcb_ratop_insert_point(pcb_opctx_t *ctx, pcb_rat_t *Rat); +void *pcb_ratop_move_to_layer(pcb_opctx_t *ctx, pcb_rat_t * Rat); +void *pcb_ratop_destroy(pcb_opctx_t *ctx, pcb_rat_t *Rat); +void *pcb_ratop_remove(pcb_opctx_t *ctx, pcb_rat_t *Rat); Index: tags/2.1.2/src/obj_subc.c =================================================================== --- tags/2.1.2/src/obj_subc.c (nonexistent) +++ tags/2.1.2/src/obj_subc.c (revision 24813) @@ -0,0 +1,1980 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2017..2019 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "config.h" + +#include + +#include "buffer.h" +#include "board.h" +#include "crosshair.h" +#include "brave.h" +#include "data.h" +#include "error.h" +#include "obj_subc.h" +#include "obj_subc_op.h" +#include "obj_subc_parent.h" +#include "obj_poly_op.h" +#include "obj_pstk.h" +#include "obj_pstk_inlines.h" +#include "obj_pstk_draw.h" +#include "obj_line_op.h" +#include "obj_term.h" +#include "obj_text_draw.h" +#include "rtree.h" +#include "draw.h" +#include "draw_wireframe.h" +#include "flag.h" +#include "polygon.h" +#include "operation.h" +#include "undo.h" +#include "macro.h" +#include "compat_misc.h" +#include "math_helper.h" +#include "pcb_minuid.h" +#include "conf_core.h" + +#define SUBC_AUX_NAME "subc-aux" + +void pcb_subc_reg(pcb_data_t *data, pcb_subc_t *subc) +{ + pcb_subclist_append(&data->subc, subc); + pcb_obj_id_reg(data, subc); + PCB_SET_PARENT(subc->data, subc, subc); + PCB_SET_PARENT(subc, data, data); +} + +void pcb_subc_unreg(pcb_subc_t *subc) +{ + pcb_data_t *data = subc->parent.data; + assert(subc->parent_type == PCB_PARENT_DATA); + pcb_subclist_remove(subc); + pcb_obj_id_del(data, subc); + PCB_CLEAR_PARENT(subc); +} + +/* Modify dst to include src, if src is not a floater */ +static void pcb_box_bump_box_noflt(pcb_box_t *dst, pcb_box_t *src) +{ + if (!PCB_FLAG_TEST(PCB_FLAG_FLOATER, ((pcb_any_obj_t *)(src)))) + pcb_box_bump_box(dst, src); +} + +/* update cached values: e.g. looking up refdes in attributes each time the + netlist code needs it would be too expensive. Instead, we maintain a + read-only ->refdes field and update it any time attributes change. */ +static void pcb_subc_attrib_post_change(pcb_attribute_list_t *list, const char *name, const char *value) +{ + pcb_subc_t *sc = (pcb_subc_t *)(((char *)list) - offsetof(pcb_subc_t, Attributes)); + if (strcmp(name, "refdes") == 0) { + const char *inv; + sc->refdes = value; + inv = pcb_obj_id_invalid(sc->refdes); + if (inv != NULL) + pcb_message(PCB_MSG_ERROR, "Invalid character '%c' in subc refdes '%s'\n", *inv, sc->refdes); + } + pcb_text_dyn_bbox_update(sc->data); +} + +pcb_subc_t *pcb_subc_alloc_id(long int id) +{ + pcb_subc_t *sc; + sc = calloc(sizeof(pcb_subc_t), 1); + sc->ID = id; + sc->Attributes.post_change = pcb_subc_attrib_post_change; + sc->data = pcb_data_new(NULL); + sc->type = PCB_OBJ_SUBC; + PCB_SET_PARENT(sc->data, subc, sc); + minuid_gen(&pcb_minuid, sc->uid); + pcb_term_init(&sc->terminals); + return sc; +} + +pcb_subc_t *pcb_subc_alloc(void) +{ + return pcb_subc_alloc_id(pcb_create_ID_get()); + +} + + +pcb_subc_t *pcb_subc_new(void) +{ + return pcb_subc_alloc(); +} + +void pcb_subc_free(pcb_subc_t *sc) +{ + pcb_term_uninit(&sc->terminals); + pcb_subc_unreg(sc); + pcb_data_free(sc->data); + free(sc); +} + +/* Create (and append) a new bound layer to a subc */ +static pcb_layer_t *pcb_subc_layer_create_buff(pcb_subc_t *sc, pcb_layer_t *src) +{ + pcb_layer_t *dst = &sc->data->Layer[sc->data->LayerN++]; + + memcpy(&dst->meta, &src->meta, sizeof(src->meta)); + dst->is_bound = 1; + dst->comb = src->comb; + dst->parent.data = sc->data; + dst->parent_type = PCB_PARENT_DATA; + dst->type = PCB_OBJ_LAYER; + dst->name = pcb_strdup(src->name); + return dst; +} + +static pcb_line_t *add_aux_line(pcb_layer_t *aux, const char *key, const char *val, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2) +{ + pcb_line_t *l = pcb_line_new(aux, x1, y1, x2, y2, PCB_MM_TO_COORD(0.1), 0, pcb_no_flags()); + pcb_attribute_put(&l->Attributes, key, val); + return l; +} + +static pcb_line_t *find_aux_line(pcb_layer_t *aux, const char *key) +{ + pcb_line_t *line; + gdl_iterator_t it; + linelist_foreach(&aux->Line, &it, line) { + const char *val = pcb_attribute_get(&line->Attributes, "subc-role"); + if ((val != NULL) && (strcmp(val, key) == 0)) + return line; + } + return NULL; +} + +/* Find and save the aux layer in the cache, of it exists */ +static void pcb_subc_cache_find_aux(pcb_subc_t *sc, int alloc) +{ + int n; + for(n = 0; n < sc->data->LayerN; n++) { + if (strcmp(sc->data->Layer[n].name, SUBC_AUX_NAME) == 0) { + sc->aux_layer = sc->data->Layer + n; + return; + } + } + + if (sc->aux_layer == NULL) + sc->aux_layer = pcb_layer_new_bound(sc->data, PCB_LYT_VIRTUAL | PCB_LYT_NOEXPORT | PCB_LYT_MISC | PCB_LYT_TOP, SUBC_AUX_NAME, NULL); +} + +/* Looking up aux objects for determining orientation/origin of a subc + is somewhat expensive. Instead of doing that every time, we just save + the pointer of those objects/layers. They don't change once the + subc is loaded into memory */ +static int pcb_subc_cache_update(pcb_subc_t *sc) +{ + if (sc->aux_layer == NULL) + pcb_subc_cache_find_aux(sc, 0); + + if (sc->aux_cache[0] != NULL) + return 0; + + if (sc->aux_layer == NULL) { + pcb_message(PCB_MSG_WARNING, "Can't find subc aux layer\n"); + return -1; + } + + sc->aux_cache[PCB_SUBCH_ORIGIN] = find_aux_line(sc->aux_layer, "origin"); + sc->aux_cache[PCB_SUBCH_X] = find_aux_line(sc->aux_layer, "x"); + sc->aux_cache[PCB_SUBCH_Y] = find_aux_line(sc->aux_layer, "y"); + + return 0; +} + +pcb_bool pcb_subc_find_aux_point(pcb_subc_t *sc, const char *role, pcb_coord_t *x, pcb_coord_t *y) +{ + pcb_line_t *l; + + if (sc->aux_layer == NULL) + pcb_subc_cache_update(sc); + if (sc->aux_layer == NULL) + return pcb_false; + + l = find_aux_line(sc->aux_layer, role); + if (l == NULL) + return pcb_false; + + *x = l->Point1.X; + *y = l->Point1.Y; + + return pcb_true; +} + +int pcb_subc_get_origin(pcb_subc_t *sc, pcb_coord_t *x, pcb_coord_t *y) +{ + if ((pcb_subc_cache_update(sc) != 0) || (sc->aux_cache[PCB_SUBCH_ORIGIN] == NULL)) + return -1; + + *x = sc->aux_cache[PCB_SUBCH_ORIGIN]->Point1.X; + *y = sc->aux_cache[PCB_SUBCH_ORIGIN]->Point1.Y; + return 0; +} + +int pcb_subc_get_rotation(pcb_subc_t *sc, double *rot) +{ + double r, rr; + if ((pcb_subc_cache_update(sc) != 0) || (sc->aux_cache[PCB_SUBCH_X] == NULL)) + return -1; + + r = -1 * PCB_RAD_TO_DEG * atan2(sc->aux_cache[PCB_SUBCH_X]->Point2.Y - sc->aux_cache[PCB_SUBCH_X]->Point1.Y, sc->aux_cache[PCB_SUBCH_X]->Point2.X - sc->aux_cache[PCB_SUBCH_X]->Point1.X); + + /* ugly hack to get round angles where possible: if error to a round angle + is less than 1/10000, it was meant to be round, just got ruined by + rounding errors */ + rr = pcb_round(r*10000.0) / 10000.0; + if (rr - r < 0.0001) + *rot = rr; + else + *rot = r; + return 0; +} + +/* The subc is originally drawn on the top side, and the aux layer gets + the PCB_LYT_TOP flag. If the subc is ever sent to the other side, the + aux layer changed side too. This is to be detected here. */ +int pcb_subc_get_side(pcb_subc_t *sc, int *on_bottom) +{ + if ((pcb_subc_cache_update(sc) != 0) || (sc->aux_layer == NULL)) + return -1; + if (!sc->aux_layer->is_bound) + return -1; + + if (sc->aux_layer->meta.bound.type & PCB_LYT_TOP) + *on_bottom = 0; + else if (sc->aux_layer->meta.bound.type & PCB_LYT_BOTTOM) + *on_bottom = 1; + else + return -1; + + return 0; +} + +int pcb_subc_get_host_trans(pcb_subc_t *sc, pcb_host_trans_t *tr, int neg) +{ + int res = 0; + double rr; + + if (pcb_subc_get_origin(sc, &tr->ox, &tr->oy) != 0) { + tr->ox = tr->oy = 0; + res = -1; + } + + if (pcb_subc_get_rotation(sc, &tr->rot) != 0) { + tr->rot = 0; + res = -1; + } + + if (pcb_subc_get_side(sc, &tr->on_bottom) != 0) { + tr->on_bottom = 0; + res = -1; + } + + rr = tr->rot / PCB_RAD_TO_DEG; + + if (neg) { + tr->rot = -tr->rot; + rr = -rr; + tr->ox = -tr->ox; + tr->oy = -tr->oy; + } + + tr->cosa = cos(rr); + tr->sina = sin(rr); + + return res; +} + +static void pcb_subc_cache_invalidate(pcb_subc_t *sc) +{ + sc->aux_cache[0] = NULL; +} + +/* Convert a square line into a polygon and add it to dst */ +static pcb_poly_t *sqline2term(pcb_layer_t *dst, pcb_line_t *line) +{ + pcb_poly_t *poly; + pcb_coord_t x[4], y[4]; + int n; + + pcb_sqline_to_rect(line, x, y); + + poly = pcb_poly_new(dst, line->Clearance, pcb_no_flags()); + for(n = 0; n < 4; n++) + pcb_poly_point_new(poly, x[n], y[n]); + PCB_FLAG_SET(PCB_FLAG_CLEARPOLYPOLY, poly); + pcb_attribute_copy_all(&poly->Attributes, &line->Attributes); + + pcb_poly_init_clip(dst->parent.data, dst, poly); + pcb_add_poly_on_layer(dst, poly); + + return poly; +} + +pcb_layer_t *pcb_loose_subc_layer(pcb_board_t *pcb, pcb_layer_t *layer, pcb_bool alloc) +{ + pcb_subc_t *sc; + int n; + + if (!pcb->is_footprint) + return layer; + + sc = pcb_subclist_first(&pcb->Data->subc); + if (sc == NULL) + return layer; + + for(n = 0; n < sc->data->LayerN; n++) { + pcb_layer_t *l = &sc->data->Layer[n]; + if (!l->is_bound) + continue; + if (l->meta.bound.real == layer) + return l; + } + + /* the subc does not have that layer */ + if (alloc) { + pcb_layer_t *nlayer = &sc->data->Layer[sc->data->LayerN]; + sc->data->LayerN++; + pcb_layer_real2bound(nlayer, layer, 1); + return nlayer; + } + + return layer; +} + +void pcb_subc_as_board_update(pcb_board_t *pcb) +{ + pcb_subc_t *sc; + + if (!pcb->is_footprint) + return; + sc = pcb_subclist_first(&pcb->Data->subc); + if (sc == NULL) + return; + + pcb_subc_bbox(sc); +} + +static pcb_coord_t read_mask(pcb_any_obj_t *obj) +{ + const char *smask = pcb_attribute_get(&obj->Attributes, "elem_smash_pad_mask"); + pcb_coord_t mask = 0; + + if (smask != NULL) { + pcb_bool success; + mask = pcb_get_value_ex(smask, NULL, NULL, NULL, "mm", &success); + if (!success) + mask = 0; + } + return mask; +} + +static void get_aux_layer(pcb_subc_t *sc, int alloc) +{ + if (sc->aux_layer == NULL) + pcb_subc_cache_find_aux(sc, 1); + pcb_subc_cache_update(sc); +} + +void pcb_subc_create_aux(pcb_subc_t *sc, pcb_coord_t ox, pcb_coord_t oy, double rot, pcb_bool bottom) +{ + double unit = PCB_MM_TO_COORD(1); + double cs, sn; + + get_aux_layer(sc, 1); + + if (rot == 0.0) { + cs = 1; + sn = 0; + } + else { + cs = cos(rot/PCB_RAD_TO_DEG); + sn = sin(rot/PCB_RAD_TO_DEG); + } + + if (bottom) { + assert(sc->aux_layer->is_bound); + sc->aux_layer->meta.bound.type &= ~PCB_LYT_TOP; + sc->aux_layer->meta.bound.type |= PCB_LYT_BOTTOM; + cs = -cs; + } + + add_aux_line(sc->aux_layer, "subc-role", "origin", ox, oy, ox, oy); + add_aux_line(sc->aux_layer, "subc-role", "x", ox, oy, pcb_round((double)ox + cs*unit), pcb_round((double)oy + sn*unit)); + add_aux_line(sc->aux_layer, "subc-role", "y", ox, oy, pcb_round((double)ox + sn*unit), pcb_round((double)oy + cs*unit)); +} + +void pcb_subc_create_aux_point(pcb_subc_t *sc, pcb_coord_t x, pcb_coord_t y, const char *role) +{ + get_aux_layer(sc, 1); + add_aux_line(sc->aux_layer, "subc-role", role, x, y, x, y); +} + +int pcb_subc_convert_from_buffer(pcb_buffer_t *buffer) +{ + pcb_subc_t *sc; + int n, top_pads = 0, bottom_pads = 0, has_refdes_text = 0; + pcb_layer_t *dst_top_mask = NULL, *dst_bottom_mask = NULL, *dst_top_paste = NULL, *dst_bottom_paste = NULL, *dst_top_silk = NULL; + vtp0_t mask_pads, paste_pads; + + vtp0_init(&mask_pads); + vtp0_init(&paste_pads); + + sc = pcb_subc_alloc(); + pcb_subc_reg(buffer->Data, sc); + + /* create layer matches and copy objects */ + for(n = 0; n < PCB_MAX_LAYER; n++) { + pcb_layer_t *dst, *src; + pcb_line_t *line; + pcb_text_t *text; + pcb_poly_t *poly; + pcb_arc_t *arc; + pcb_layer_type_t ltype; + + if (pcb_layer_is_pure_empty(&buffer->Data->Layer[n])) + continue; + + src = &buffer->Data->Layer[n]; + dst = pcb_subc_layer_create_buff(sc, src); + ltype = dst->meta.bound.type; + + if ((dst->comb & PCB_LYC_SUB) == 0) { + if ((ltype & PCB_LYT_PASTE) && (ltype & PCB_LYT_TOP)) + dst_top_paste = dst; + else if ((ltype & PCB_LYT_PASTE) && (ltype & PCB_LYT_BOTTOM)) + dst_bottom_paste = dst; + else if ((ltype & PCB_LYT_SILK) && (ltype & PCB_LYT_TOP)) + dst_top_silk = dst; + } + + if (dst->comb & PCB_LYC_SUB) { + if ((ltype & PCB_LYT_MASK) && (ltype & PCB_LYT_TOP)) + dst_top_mask = dst; + else if ((ltype & PCB_LYT_MASK) && (ltype & PCB_LYT_BOTTOM)) + dst_bottom_mask = dst; + } + + while((line = linelist_first(&src->Line)) != NULL) { + pcb_coord_t mask = 0; + char *np, *sq, *termpad; + const char *term; + + termpad = pcb_attribute_get(&line->Attributes, "elem_smash_pad"); + if (termpad != NULL) { + if (ltype & PCB_LYT_TOP) + top_pads++; + else if (ltype & PCB_LYT_BOTTOM) + bottom_pads++; + mask = read_mask((pcb_any_obj_t *)line); + } + term = pcb_attribute_get(&line->Attributes, "term"); + np = pcb_attribute_get(&line->Attributes, "elem_smash_nopaste"); + sq = pcb_attribute_get(&line->Attributes, "elem_smash_shape_square"); + if ((sq != NULL) && (*sq == '1')) { /* convert to polygon */ + poly = sqline2term(dst, line); + if (termpad != NULL) { + if ((np == NULL) || (*np != '1')) { + poly = sqline2term(dst, line); + vtp0_append(&paste_pads, poly); + } + if (mask > 0) { + line->Thickness = mask; + poly = sqline2term(dst, line); + if (term != NULL) + pcb_attribute_put(&poly->Attributes, "term", term); + vtp0_append(&mask_pads, poly); + } + } + + pcb_line_free(line); + } + else { + /* copy the line */ + pcb_line_unreg(line); + pcb_line_reg(dst, line); + PCB_FLAG_CLEAR(PCB_FLAG_WARN | PCB_FLAG_FOUND | PCB_FLAG_SELECTED, line); + + if (termpad != NULL) { + pcb_line_t *nl = pcb_line_dup(dst, line); + if ((np == NULL) || (*np != '1')) + vtp0_append(&paste_pads, nl); + if (mask > 0) { + nl = pcb_line_dup(dst, line); + nl->Thickness = mask; + if (term != NULL) + pcb_attribute_put(&nl->Attributes, "term", term); + vtp0_append(&mask_pads, nl); + } + } + } + } + + while((arc = arclist_first(&src->Arc)) != NULL) { + pcb_arc_unreg(arc); + pcb_arc_reg(dst, arc); + PCB_FLAG_CLEAR(PCB_FLAG_WARN | PCB_FLAG_FOUND | PCB_FLAG_SELECTED, arc); + } + + while((text = textlist_first(&src->Text)) != NULL) { + pcb_text_unreg(text); + pcb_text_reg(dst, text); + PCB_FLAG_CLEAR(PCB_FLAG_WARN | PCB_FLAG_FOUND | PCB_FLAG_SELECTED, text); + if (!has_refdes_text && (text->TextString != NULL) && (strstr(text->TextString, "%a.parent.refdes%") != NULL)) + has_refdes_text = 1; + } + + while((poly = polylist_first(&src->Polygon)) != NULL) { + pcb_poly_unreg(poly); + pcb_poly_reg(dst, poly); + + PCB_FLAG_CLEAR(PCB_FLAG_WARN | PCB_FLAG_FOUND | PCB_FLAG_SELECTED, poly); + } + } + + /* create paste and mask side effects - needed when importing from footprint */ + { + if (top_pads > 0) { + if (dst_top_paste == NULL) + dst_top_paste = pcb_layer_new_bound(sc->data, PCB_LYT_TOP | PCB_LYT_PASTE, "top paste", NULL); + if (dst_top_mask == NULL) { + dst_top_mask = pcb_layer_new_bound(sc->data, PCB_LYT_TOP | PCB_LYT_MASK, "top mask", NULL); + dst_top_mask->comb = PCB_LYC_SUB; + } + } + if (bottom_pads > 0) { + if (dst_bottom_paste == NULL) + dst_bottom_paste = pcb_layer_new_bound(sc->data, PCB_LYT_BOTTOM | PCB_LYT_PASTE, "bottom paste", NULL); + if (dst_bottom_mask == NULL) { + dst_bottom_mask = pcb_layer_new_bound(sc->data, PCB_LYT_BOTTOM | PCB_LYT_MASK, "bottom mask", NULL); + dst_bottom_mask->comb = PCB_LYC_SUB; + } + } + } + + { /* convert globals */ + pcb_pstk_t *ps; + + while((ps = padstacklist_first(&buffer->Data->padstack)) != NULL) { + const pcb_pstk_proto_t *proto = pcb_pstk_get_proto(ps); + pcb_pstk_unreg(ps); + pcb_pstk_reg(sc->data, ps); + PCB_FLAG_CLEAR(PCB_FLAG_WARN | PCB_FLAG_FOUND | PCB_FLAG_SELECTED, ps); + ps->proto = pcb_pstk_proto_insert_dup(sc->data, proto, 1); + ps->protoi = -1; + } + } + + vtp0_uninit(&mask_pads); + vtp0_uninit(&paste_pads); + + pcb_subc_create_aux(sc, buffer->X, buffer->Y, 0.0, pcb_false); + + /* Add refdes */ + if ((conf_core.editor.subc_conv_refdes != NULL) && (*conf_core.editor.subc_conv_refdes != '\0')) { + if (strcmp(conf_core.editor.subc_conv_refdes, "") != 0) + pcb_attribute_put(&sc->Attributes, "refdes", conf_core.editor.subc_conv_refdes); + if (!has_refdes_text) { + if (dst_top_silk == NULL) + dst_top_silk = pcb_layer_new_bound(sc->data, PCB_LYT_TOP | PCB_LYT_SILK, "top-silk", NULL); + if (dst_top_silk != NULL) + pcb_text_new(dst_top_silk, pcb_font(PCB, 0, 0), buffer->X, buffer->Y, 0, 100, 0, "%a.parent.refdes%", pcb_flag_make(PCB_FLAG_DYNTEXT | PCB_FLAG_FLOATER)); + else + pcb_message(PCB_MSG_ERROR, "Error: can't create top silk layer in subc for placing the refdes\n"); + } + } + + + return 0; +} + +static void pcb_subc_draw_origin(pcb_hid_gc_t GC, pcb_subc_t *sc, pcb_coord_t DX, pcb_coord_t DY) +{ + pcb_line_t *origin; + pcb_subc_cache_update(sc); + + origin = sc->aux_cache[PCB_SUBCH_ORIGIN]; + + if (origin == NULL) + return; + + DX += (origin->Point1.X + origin->Point2.X) / 2; + DY += (origin->Point1.Y + origin->Point2.Y) / 2; + + pcb_gui->draw_line(GC, DX - PCB_EMARK_SIZE, DY, DX, DY - PCB_EMARK_SIZE); + pcb_gui->draw_line(GC, DX + PCB_EMARK_SIZE, DY, DX, DY - PCB_EMARK_SIZE); + pcb_gui->draw_line(GC, DX - PCB_EMARK_SIZE, DY, DX, DY + PCB_EMARK_SIZE); + pcb_gui->draw_line(GC, DX + PCB_EMARK_SIZE, DY, DX, DY + PCB_EMARK_SIZE); +} + +void pcb_xordraw_subc(pcb_subc_t *sc, pcb_coord_t DX, pcb_coord_t DY, int use_curr_side) +{ + int n, mirr; + pcb_coord_t w = 0, h = 0; + + mirr = use_curr_side && conf_core.editor.show_solder_side; + + /* mirror center */ + if (mirr) { + pcb_subc_get_origin(sc, &w, &h); + w *= 2; + h *= 2; + } + + /* draw per layer objects */ + for(n = 0; n < sc->data->LayerN; n++) { + pcb_layer_t *ly = sc->data->Layer + n; + pcb_line_t *line; + pcb_text_t *text; + pcb_poly_t *poly; + pcb_arc_t *arc; + gdl_iterator_t it; + + linelist_foreach(&ly->Line, &it, line) + pcb_draw_wireframe_line(pcb_crosshair.GC, + DX + PCB_CSWAP_X(line->Point1.X, w, mirr), + DY + PCB_CSWAP_Y(line->Point1.Y, h, mirr), + DX + PCB_CSWAP_X(line->Point2.X, w, mirr), + DY + PCB_CSWAP_Y(line->Point2.Y, h, mirr), + line->Thickness, + 0 ); + + arclist_foreach(&ly->Arc, &it, arc) { + if(arc->Width != arc->Height) { +TODO(": The wireframe arc drawing code cannot draw ellipses yet so draw the elliptical arc with a thin line ") + double sa = mirr ? PCB_SWAP_ANGLE(arc->StartAngle) : arc->StartAngle; + double da = mirr ? PCB_SWAP_DELTA(arc->Delta) : arc->Delta; + pcb_gui->draw_arc(pcb_crosshair.GC, DX + PCB_CSWAP_X(arc->X, w, mirr), DY + PCB_CSWAP_Y(arc->Y, h, mirr), arc->Width, arc->Height, sa, da); + } + else { + pcb_arc_t temp_arc; + temp_arc.StartAngle = mirr ? PCB_SWAP_ANGLE(arc->StartAngle) : arc->StartAngle; + temp_arc.Delta = mirr ? PCB_SWAP_DELTA(arc->Delta) : arc->Delta; + temp_arc.X = DX + PCB_CSWAP_X(arc->X, w, mirr); + temp_arc.Y = DY + PCB_CSWAP_Y(arc->Y, h, mirr); + temp_arc.Width = arc->Width; + temp_arc.Height = arc->Height; + temp_arc.Thickness = arc->Thickness; + pcb_draw_wireframe_arc(pcb_crosshair.GC, &temp_arc, arc->Thickness); + } + } + + polylist_foreach(&ly->Polygon, &it, poly) + pcb_xordraw_poly_subc(poly, DX, DY, w, h, mirr); + + textlist_foreach(&ly->Text, &it, text) { + if (mirr) { + pcb_text_t t; + t = *text; + t.X = PCB_CSWAP_X(text->X, w, mirr); + t.Y = PCB_CSWAP_Y(text->Y, h, mirr); + t.BoundingBox.X1 = PCB_CSWAP_X(text->BoundingBox.X1, w, mirr); + t.BoundingBox.Y1 = PCB_CSWAP_Y(text->BoundingBox.Y1, h, mirr); + t.BoundingBox.X2 = PCB_CSWAP_X(text->BoundingBox.X2, w, mirr); + t.BoundingBox.Y2 = PCB_CSWAP_Y(text->BoundingBox.Y2, h, mirr); + PCB_FLAG_TOGGLE(PCB_FLAG_ONSOLDER, &t); + pcb_text_draw_xor(&t, DX, DY); + } + else + pcb_text_draw_xor(text, DX, DY); + } + } + + /* draw global objects */ + { + pcb_pstk_t *ps; + gdl_iterator_t it; + + padstacklist_foreach(&sc->data->padstack, &it, ps) { + pcb_coord_t ox, oy; + int oxm, pri; + ox = ps->x; + oy = ps->y; + oxm = ps->xmirror; + pri = ps->protoi; + ps->x = PCB_CSWAP_X(ps->x, w, mirr); + ps->y = PCB_CSWAP_Y(ps->y, h, mirr); + ps->x += DX; + ps->y += DY; + if (mirr) { + ps->xmirror = !ps->xmirror; + ps->protoi = -1; + } + pcb_pstk_thindraw(NULL, pcb_crosshair.GC, ps); + ps->x = ox; + ps->y = oy; + ps->xmirror = oxm; + ps->protoi = pri; + } + } + + pcb_subc_draw_origin(pcb_crosshair.GC, sc, DX, DY); +} + +#define MAYBE_KEEP_ID(dst, src) \ +do { \ + if ((keep_ids) && (dst != NULL)) \ + dst->ID = src->ID; \ +} while(0) + +static pcb_subc_t *pcb_subc_copy_meta(pcb_subc_t *dst, pcb_subc_t *src) +{ + if (dst == NULL) + return NULL; + pcb_attribute_copy_all(&dst->Attributes, &src->Attributes); + return dst; +} + + +pcb_subc_t *pcb_subc_dup_at(pcb_board_t *pcb, pcb_data_t *dst, pcb_subc_t *src, pcb_coord_t dx, pcb_coord_t dy, pcb_bool keep_ids) +{ + pcb_board_t *src_pcb; + int n; + pcb_subc_t *sc = pcb_subc_alloc(); + + if (keep_ids) + sc->ID = src->ID; + else + sc->ID = pcb_create_ID_get(); + + minuid_cpy(sc->uid, src->uid); + pcb_subc_reg(dst, sc); + + src_pcb = pcb_data_get_top(src->data); + + pcb_subc_copy_meta(sc, src); + + sc->BoundingBox.X1 = sc->BoundingBox.Y1 = PCB_MAX_COORD; + sc->BoundingBox.X2 = sc->BoundingBox.Y2 = -PCB_MAX_COORD; + sc->bbox_naked.X1 = sc->bbox_naked.Y1 = PCB_MAX_COORD; + sc->bbox_naked.X2 = sc->bbox_naked.Y2 = -PCB_MAX_COORD; + + /* make a copy of layer data */ + for(n = 0; n < src->data->LayerN; n++) { + pcb_layer_t *sl = src->data->Layer + n; + pcb_layer_t *dl = sc->data->Layer + n; + pcb_line_t *line, *nline; + pcb_text_t *text, *ntext; + pcb_arc_t *arc, *narc; + gdl_iterator_t it; + + /* bind layer/resolve layers */ + dl->is_bound = 1; + dl->type = PCB_OBJ_LAYER; + if ((pcb != NULL) && (pcb == src_pcb)) { + /* copy within the same board */ + memcpy(&dl->meta.bound, &sl->meta.bound, sizeof(sl->meta.bound)); + dl->name = pcb_strdup(sl->name); + dl->comb = sl->comb; + if (dl->meta.bound.real != NULL) + pcb_layer_link_trees(dl, dl->meta.bound.real); + } + else if (pcb != NULL) { + /* copying from buffer to board */ + memcpy(&dl->meta.bound, &sl->meta.bound, sizeof(sl->meta.bound)); + dl->name = pcb_strdup(sl->name); + dl->meta.bound.real = pcb_layer_resolve_binding(pcb, sl); + dl->comb = sl->comb; + + if (dl->meta.bound.real == NULL) { + if (!(dl->meta.bound.type & PCB_LYT_VIRTUAL)) { + const char *name = dl->name; + if (name == NULL) name = ""; + pcb_message(PCB_MSG_WARNING, "Couldn't bind a layer %s of subcircuit while placing it\n", name); + } + } + else + pcb_layer_link_trees(dl, dl->meta.bound.real); + } + else { + /* copying from board to buffer */ + memcpy(&dl->meta.bound, &sl->meta.bound, sizeof(sl->meta.bound)); + + dl->meta.bound.real = NULL; + dl->name = pcb_strdup(sl->name); + dl->comb = sl->comb; + } + + + linelist_foreach(&sl->Line, &it, line) { + nline = pcb_line_dup_at(dl, line, dx, dy); + MAYBE_KEEP_ID(nline, line); + if (nline != NULL) { + PCB_SET_PARENT(nline, layer, dl); + if (!PCB_FLAG_TEST(PCB_FLAG_FLOATER, nline)) { + pcb_box_bump_box_noflt(&sc->BoundingBox, &nline->BoundingBox); + pcb_box_bump_box_noflt(&sc->bbox_naked, &nline->bbox_naked); + } + } + } + + arclist_foreach(&sl->Arc, &it, arc) { + narc = pcb_arc_dup_at(dl, arc, dx, dy); + MAYBE_KEEP_ID(narc, arc); + if (narc != NULL) { + PCB_SET_PARENT(narc, layer, dl); + if (!PCB_FLAG_TEST(PCB_FLAG_FLOATER, narc)) { + pcb_box_bump_box_noflt(&sc->BoundingBox, &narc->BoundingBox); + pcb_box_bump_box_noflt(&sc->bbox_naked, &narc->bbox_naked); + } + } + } + + textlist_foreach(&sl->Text, &it, text) { + ntext = pcb_text_dup_at(dl, text, dx, dy); + MAYBE_KEEP_ID(ntext, text); + if (ntext != NULL) { + PCB_SET_PARENT(ntext, layer, dl); + if (!PCB_FLAG_TEST(PCB_FLAG_FLOATER, ntext)) { + pcb_box_bump_box_noflt(&sc->BoundingBox, &ntext->BoundingBox); + pcb_box_bump_box_noflt(&sc->bbox_naked, &ntext->bbox_naked); + } + } + } + + } + sc->data->LayerN = src->data->LayerN; + + /* bind the via rtree so that vias added in this subc show up on the board */ + if (pcb != NULL) { + if (pcb->Data->padstack_tree == NULL) + pcb->Data->padstack_tree = pcb_r_create_tree(); + sc->data->padstack_tree = pcb->Data->padstack_tree; + } + + { /* make a copy of global data */ + pcb_pstk_t *ps, *nps; + gdl_iterator_t it; + + padstacklist_foreach(&src->data->padstack, &it, ps) { + pcb_cardinal_t pid = pcb_pstk_proto_insert_dup(sc->data, pcb_pstk_get_proto(ps), 1); + nps = pcb_pstk_new_tr(sc->data, -1, pid, ps->x+dx, ps->y+dy, ps->Clearance, ps->Flags, ps->rot, ps->xmirror, ps->smirror); + pcb_pstk_copy_meta(nps, ps); + MAYBE_KEEP_ID(nps, ps); + if (nps != NULL) { + if (!PCB_FLAG_TEST(PCB_FLAG_FLOATER, nps)) { + pcb_box_bump_box_noflt(&sc->BoundingBox, &nps->BoundingBox); + pcb_box_bump_box_noflt(&sc->bbox_naked, &nps->bbox_naked); + } + } + } + } + + /* make a copy of polygons at the end so clipping caused by other objects are calculated only once */ + for(n = 0; n < src->data->LayerN; n++) { + pcb_layer_t *sl = src->data->Layer + n; + pcb_layer_t *dl = sc->data->Layer + n; + pcb_poly_t *poly, *npoly; + gdl_iterator_t it; + + polylist_foreach(&sl->Polygon, &it, poly) { + npoly = pcb_poly_dup_at(dl, poly, dx, dy); + MAYBE_KEEP_ID(npoly, poly); + if (npoly != NULL) { + PCB_SET_PARENT(npoly, layer, dl); + if (!PCB_FLAG_TEST(PCB_FLAG_FLOATER, npoly)) { + pcb_box_bump_box_noflt(&sc->BoundingBox, &npoly->BoundingBox); + pcb_box_bump_box_noflt(&sc->bbox_naked, &npoly->bbox_naked); + } + pcb_poly_ppclear(npoly); + } + } + } + + memcpy(&sc->Flags, &src->Flags, sizeof(sc->Flags)); + + pcb_close_box(&sc->BoundingBox); + pcb_close_box(&sc->bbox_naked); + + if (pcb != NULL) { + if (!dst->subc_tree) + dst->subc_tree = pcb_r_create_tree(); + pcb_r_insert_entry(dst->subc_tree, (pcb_box_t *)sc); + } + + return sc; +} + +pcb_subc_t *pcb_subc_dup(pcb_board_t *pcb, pcb_data_t *dst, pcb_subc_t *src) +{ + return pcb_subc_dup_at(pcb, dst, src, 0, 0, pcb_false); +} + +void pcb_subc_bbox(pcb_subc_t *sc) +{ + pcb_data_bbox(&sc->BoundingBox, sc->data, pcb_true); + pcb_data_bbox_naked(&sc->bbox_naked, sc->data, pcb_true); +} + + +/* erases a subc on a layer */ +void EraseSubc(pcb_subc_t *sc) +{ + pcb_draw_invalidate(sc); +/* pcb_flag_erase(&sc->Flags); ??? */ +} + +void DrawSubc(pcb_subc_t *sc) +{ + pcb_draw_invalidate(sc); +} + + +/* Execute an operation on all children on an sc and update the bbox of the sc */ +void *pcb_subc_op(pcb_data_t *Data, pcb_subc_t *sc, pcb_opfunc_t *opfunc, pcb_opctx_t *ctx, pcb_subc_op_undo_t batch_undo) +{ + int n; + + if ((pcb_brave & PCB_BRAVE_CLIPBATCH) && (Data != NULL)) + pcb_data_clip_inhibit_inc(Data); + + switch(batch_undo) { + case PCB_SUBCOP_UNDO_SUBC: + pcb_undo_freeze_serial(); + pcb_undo_freeze_add(); + break; + case PCB_SUBCOP_UNDO_BATCH: + pcb_undo_inc_serial(); + pcb_undo_save_serial(); + pcb_undo_freeze_serial(); + break; + case PCB_SUBCOP_UNDO_NORMAL: + break; + } + + EraseSubc(sc); + if (pcb_data_get_top(Data) != NULL) { + if (Data->subc_tree != NULL) + pcb_r_delete_entry(Data->subc_tree, (pcb_box_t *)sc); + else + Data->subc_tree = pcb_r_create_tree(); + } + + /* for calculating the new bounding box on the fly */ + sc->BoundingBox.X1 = sc->BoundingBox.Y1 = PCB_MAX_COORD; + sc->BoundingBox.X2 = sc->BoundingBox.Y2 = -PCB_MAX_COORD; + sc->bbox_naked.X1 = sc->bbox_naked.Y1 = PCB_MAX_COORD; + sc->bbox_naked.X2 = sc->bbox_naked.Y2 = -PCB_MAX_COORD; + + /* execute on layer locals */ + for(n = 0; n < sc->data->LayerN; n++) { + pcb_layer_t *sl = sc->data->Layer + n; + pcb_line_t *line; + pcb_text_t *text; + pcb_poly_t *poly; + pcb_arc_t *arc; + gdl_iterator_t it; + + + linelist_foreach(&sl->Line, &it, line) { + pcb_object_operation(opfunc, ctx, PCB_OBJ_LINE, sl, line, line); + if (!PCB_FLAG_TEST(PCB_FLAG_FLOATER, line)) { + pcb_box_bump_box_noflt(&sc->BoundingBox, &line->BoundingBox); + pcb_box_bump_box_noflt(&sc->bbox_naked, &line->bbox_naked); + } + } + + arclist_foreach(&sl->Arc, &it, arc) { + pcb_object_operation(opfunc, ctx, PCB_OBJ_ARC, sl, arc, arc); + if (!PCB_FLAG_TEST(PCB_FLAG_FLOATER, arc)) { + pcb_box_bump_box_noflt(&sc->BoundingBox, &arc->BoundingBox); + pcb_box_bump_box_noflt(&sc->bbox_naked, &arc->bbox_naked); + } + } + + textlist_foreach(&sl->Text, &it, text) { + pcb_object_operation(opfunc, ctx, PCB_OBJ_TEXT, sl, text, text); + if (!PCB_FLAG_TEST(PCB_FLAG_FLOATER, text)) { + pcb_box_bump_box_noflt(&sc->BoundingBox, &text->BoundingBox); + pcb_box_bump_box_noflt(&sc->bbox_naked, &text->bbox_naked); + } + } + + polylist_foreach(&sl->Polygon, &it, poly) { + pcb_object_operation(opfunc, ctx, PCB_OBJ_POLY, sl, poly, poly); + if (!PCB_FLAG_TEST(PCB_FLAG_FLOATER, poly)) { + pcb_box_bump_box_noflt(&sc->BoundingBox, &poly->BoundingBox); + pcb_box_bump_box_noflt(&sc->bbox_naked, &poly->bbox_naked); + } + } + + } + + + /* execute on globals */ + { + pcb_pstk_t *ps; + gdl_iterator_t it; + + padstacklist_foreach(&sc->data->padstack, &it, ps) { + pcb_object_operation(opfunc, ctx, PCB_OBJ_PSTK, ps, ps, ps); + if (!PCB_FLAG_TEST(PCB_FLAG_FLOATER, ps)) { + pcb_box_bump_box_noflt(&sc->BoundingBox, &ps->BoundingBox); + pcb_box_bump_box_noflt(&sc->bbox_naked, &ps->bbox_naked); + } + } + } + + pcb_close_box(&sc->BoundingBox); + pcb_close_box(&sc->bbox_naked); + if (pcb_data_get_top(Data) != NULL) + pcb_r_insert_entry(Data->subc_tree, (pcb_box_t *)sc); + DrawSubc(sc); + + switch(batch_undo) { + case PCB_SUBCOP_UNDO_SUBC: pcb_undo_unfreeze_add(); pcb_undo_unfreeze_serial(); break; + case PCB_SUBCOP_UNDO_BATCH: pcb_undo_unfreeze_serial(); break; + case PCB_SUBCOP_UNDO_NORMAL: break; + } + + if ((pcb_brave & PCB_BRAVE_CLIPBATCH) && (Data != NULL)) + pcb_data_clip_inhibit_dec(Data, 0); + + return sc; +} + + +/* copies a subcircuit onto the PCB (a.k.a "paste"). Then does a draw. */ +void *pcb_subcop_copy(pcb_opctx_t *ctx, pcb_subc_t *src) +{ + pcb_subc_t *sc; + + sc = pcb_subc_dup_at(PCB, PCB->Data, src, ctx->copy.DeltaX, ctx->copy.DeltaY, pcb_false); + + pcb_undo_add_obj_to_create(PCB_OBJ_SUBC, sc, sc, sc); + + if (ctx->copy.from_outside && conf_core.editor.show_solder_side) { + uundo_serial_t last; + + /* move-to-the-other-side is not undoable: it's part of the placement */ + pcb_undo_inc_serial(); + last = pcb_undo_serial(); +TODO("subc: should not depend on crosshair, because of automatic/scripted placement; test case 1: load subc footprint in buffer, swap side to bottom, place; test case 2: bug_files/cmd_element, execute the cmd while being on the bottom side, without crosshair set subcircuits catapult to negative y") + pcb_subc_change_side(sc, 2 * pcb_crosshair.Y - PCB->MaxHeight); + pcb_undo_truncate_from(last); + + } + + pcb_text_dyn_bbox_update(sc->data); + + return sc; +} + +extern pcb_opfunc_t ClipFunctions, MoveFunctions, MoveFunctions_noclip, Rotate90Functions, RotateFunctions, ChgFlagFunctions, ChangeSizeFunctions, ChangeClearSizeFunctions, Change1stSizeFunctions, Change2ndSizeFunctions; + +/* drag&drop move when not selected */ +void *pcb_subcop_move(pcb_opctx_t *ctx, pcb_subc_t *sc) +{ + pcb_board_t *pcb = pcb_data_get_top(sc->data); + pcb_data_t *data = (pcb != NULL ? pcb->Data : NULL); + pcb_opctx_t clip; + + /* restore all pins/pads at once, at the old location */ + clip.clip.restore = 1; clip.clip.clear = 0; + clip.clip.pcb = ctx->move.pcb; + pcb_subc_op(data, sc, &ClipFunctions, &clip, PCB_SUBCOP_UNDO_NORMAL); + + /* do the move without messing with the clipping */ + pcb_subc_op(data, sc, &MoveFunctions_noclip, ctx, PCB_SUBCOP_UNDO_NORMAL); + + /* clear all pins/pads at once, at the new location */ + clip.clip.restore = 0; clip.clip.clear = 1; + pcb_subc_op(data, sc, &ClipFunctions, &clip, PCB_SUBCOP_UNDO_NORMAL); + return sc; +} + +void *pcb_subcop_rotate90(pcb_opctx_t *ctx, pcb_subc_t *sc) +{ + pcb_board_t *pcb = pcb_data_get_top(sc->data); + return pcb_subc_op((pcb != NULL ? pcb->Data : NULL), sc, &Rotate90Functions, ctx, PCB_SUBCOP_UNDO_SUBC); +} + +void *pcb_subcop_rotate(pcb_opctx_t *ctx, pcb_subc_t *sc) +{ + pcb_data_t *data; + + ctx->rotate.pcb = pcb_data_get_top(sc->data); + data = (ctx->rotate.pcb != NULL ? ctx->rotate.pcb->Data : NULL); + + return pcb_subc_op(data, sc, &RotateFunctions, ctx, PCB_SUBCOP_UNDO_SUBC); +} + +void pcb_subc_rotate90(pcb_subc_t *subc, pcb_coord_t cx, pcb_coord_t cy, int steps) +{ + pcb_opctx_t ctx; + + ctx.rotate.center_x = cx; + ctx.rotate.center_y = cy; + ctx.rotate.number = steps; + pcb_subcop_rotate90(&ctx, subc); +} + +void pcb_subc_rotate(pcb_subc_t *subc, pcb_coord_t cx, pcb_coord_t cy, double cosa, double sina, double angle) +{ + pcb_opctx_t ctx; + + ctx.rotate.center_x = cx; + ctx.rotate.center_y = cy; + ctx.rotate.angle = angle; + ctx.rotate.cosa = cosa; + ctx.rotate.sina = sina; + pcb_subcop_rotate(&ctx, subc); +} + +void pcb_subc_move(pcb_subc_t *sc, pcb_coord_t dx, pcb_coord_t dy, pcb_bool more_to_come) +{ + pcb_opctx_t ctx; + ctx.move.pcb = NULL; + ctx.move.dx = dx; + ctx.move.dy = dy; + ctx.move.more_to_come = more_to_come; + pcb_subcop_move(&ctx, sc); +} + +pcb_bool pcb_selected_subc_change_side(void) +{ + pcb_bool change = pcb_false; + + if (PCB->pstk_on && pcb_silk_on(PCB)) { + PCB_SUBC_LOOP(PCB->Data); + { + if (PCB_FLAG_TEST(PCB_FLAG_SELECTED, subc)) { + change |= pcb_subc_change_side(subc, 2 * pcb_crosshair.Y - PCB->MaxHeight); + } + } + PCB_END_LOOP; + } + return change; +} + + +static int subc_relocate_layer_objs(pcb_layer_t *dl, pcb_data_t *src_data, pcb_layer_t *sl, int src_has_real_layer, int dst_is_pcb) +{ + pcb_line_t *line; + pcb_text_t *text; + pcb_poly_t *poly; + pcb_arc_t *arc; + gdl_iterator_t it; + int chg = 0; + pcb_data_t *dst_data = dl == NULL ? NULL : dl->parent.data; + + linelist_foreach(&sl->Line, &it, line) { + if (src_has_real_layer) { + pcb_poly_restore_to_poly(src_data, PCB_OBJ_LINE, sl, line); + pcb_r_delete_entry(sl->line_tree, (pcb_box_t *)line); + chg++; + } + PCB_FLAG_CLEAR(PCB_FLAG_WARN | PCB_FLAG_FOUND | PCB_FLAG_SELECTED, line); + if ((dl != NULL) && (dl->line_tree != NULL)) { + pcb_r_insert_entry(dl->line_tree, (pcb_box_t *)line); + chg++; + } + if (dst_is_pcb && (dl != NULL)) + pcb_poly_clear_from_poly(dst_data, PCB_OBJ_LINE, dl, line); + } + + arclist_foreach(&sl->Arc, &it, arc) { + if (src_has_real_layer) { + pcb_poly_restore_to_poly(src_data, PCB_OBJ_ARC, sl, arc); + pcb_r_delete_entry(sl->arc_tree, (pcb_box_t *)arc); + chg++; + } + PCB_FLAG_CLEAR(PCB_FLAG_WARN | PCB_FLAG_FOUND | PCB_FLAG_SELECTED, arc); + if ((dl != NULL) && (dl->arc_tree != NULL)) { + pcb_r_insert_entry(dl->arc_tree, (pcb_box_t *)arc); + chg++; + } + if (dst_is_pcb && (dl != NULL)) + pcb_poly_clear_from_poly(dst_data, PCB_OBJ_ARC, dl, arc); + } + + textlist_foreach(&sl->Text, &it, text) { + if (src_has_real_layer) { + pcb_poly_restore_to_poly(src_data, PCB_OBJ_LINE, sl, text); + pcb_r_delete_entry(sl->text_tree, (pcb_box_t *)text); + chg++; + } + PCB_FLAG_CLEAR(PCB_FLAG_WARN | PCB_FLAG_FOUND | PCB_FLAG_SELECTED, text); + if ((dl != NULL) && (dl->text_tree != NULL)) { + pcb_r_insert_entry(dl->text_tree, (pcb_box_t *)text); + chg++; + } + if (dst_is_pcb && (dl != NULL)) + pcb_poly_clear_from_poly(dst_data, PCB_OBJ_TEXT, dl, text); + } + + polylist_foreach(&sl->Polygon, &it, poly) { + pcb_poly_pprestore(poly); + if (src_has_real_layer) { + pcb_r_delete_entry(sl->polygon_tree, (pcb_box_t *)poly); + chg++; + } + PCB_FLAG_CLEAR(PCB_FLAG_WARN | PCB_FLAG_FOUND | PCB_FLAG_SELECTED, poly); + if ((dl != NULL) && (dl->polygon_tree != NULL)) { + pcb_r_insert_entry(dl->polygon_tree, (pcb_box_t *)poly); + chg++; + } + if (dst_is_pcb && (dl != NULL)) + pcb_poly_ppclear_at(poly, dl); + } + + if (!dst_is_pcb) { + /* keep only the layer binding match, unbound other aspects */ + sl->meta.bound.real = NULL; + sl->arc_tree = sl->line_tree = sl->text_tree = sl->polygon_tree = NULL; + chg++; + } + else { + sl->meta.bound.real = dl; + chg++; + } + return chg; +} + +static int subc_relocate_globals(pcb_data_t *dst, pcb_data_t *new_parent, pcb_subc_t *sc, int dst_is_pcb) +{ + pcb_pstk_t *ps; + gdl_iterator_t it; + int chg = 0; + + padstacklist_foreach(&sc->data->padstack, &it, ps) { + const pcb_pstk_proto_t *proto = pcb_pstk_get_proto(ps); + assert(proto != NULL); /* the prototype must be accessible at the source else we can't add it in the dest */ + pcb_poly_restore_to_poly(ps->parent.data, PCB_OBJ_PSTK, NULL, ps); + if (sc->data->padstack_tree != NULL) + pcb_r_delete_entry(sc->data->padstack_tree, (pcb_box_t *)ps); + PCB_FLAG_CLEAR(PCB_FLAG_WARN | PCB_FLAG_FOUND | PCB_FLAG_SELECTED, ps); + if ((dst != NULL) && (dst->padstack_tree != NULL)) + pcb_r_insert_entry(dst->padstack_tree, (pcb_box_t *)ps); + if (dst != NULL) + ps->proto = pcb_pstk_proto_insert_dup(ps->parent.data, proto, 1); + ps->protoi = -1; + ps->parent.data = new_parent; + if (dst_is_pcb) + pcb_poly_clear_from_poly(ps->parent.data, PCB_OBJ_PSTK, NULL, ps); + chg++; + } + + /* bind globals */ + if ((dst != NULL) && (dst_is_pcb)) { + if (dst->padstack_tree == NULL) + dst->padstack_tree = pcb_r_create_tree(); + sc->data->padstack_tree = dst->padstack_tree; + chg++; + } + else + sc->data->padstack_tree = NULL; + return chg; +} + +/* change the parent of all global objects to new_parent */ +static void subc_set_parent_globals(pcb_subc_t *sc, pcb_data_t *new_parent) +{ + pcb_data_set_parent_globals(sc->data, new_parent); +} + +void *pcb_subcop_move_buffer(pcb_opctx_t *ctx, pcb_subc_t *sc) +{ + int n; + pcb_board_t *dst_top = pcb_data_get_top(ctx->buffer.dst); + int dst_is_pcb = ((dst_top != NULL) && (dst_top->Data == ctx->buffer.dst)); + pcb_opctx_t clip; + + EraseSubc(sc); + + /* move the subc */ + if ((ctx->buffer.pcb != NULL) && (ctx->buffer.pcb->Data->subc_tree != NULL)) { + if (!dst_is_pcb) { + /* restore all pins/pads at once, at the old location */ + clip.clip.restore = 1; clip.clip.clear = 0; + clip.clip.pcb = ctx->buffer.pcb; + pcb_subc_op(ctx->buffer.pcb->Data, sc, &ClipFunctions, &clip, PCB_SUBCOP_UNDO_SUBC); + } + pcb_r_delete_entry(ctx->buffer.pcb->Data->subc_tree, (pcb_box_t *)sc); + } + + pcb_subc_unreg(sc); + pcb_subc_reg(ctx->buffer.dst, sc); + + if (dst_is_pcb) { + if (ctx->buffer.dst->subc_tree == NULL) + ctx->buffer.dst->subc_tree = pcb_r_create_tree(); + pcb_r_insert_entry(ctx->buffer.dst->subc_tree, (pcb_box_t *)sc); + } + + if (dst_is_pcb) + PCB_SET_PARENT(sc, data, ctx->buffer.dst); /* have to set sc parent before relocate globals so that poly clearings will work */ + + /* move layer local */ + for(n = 0; n < sc->data->LayerN; n++) { + pcb_layer_t *sl = sc->data->Layer + n; + pcb_layer_t *dl; + int src_has_real_layer = (sl->meta.bound.real != NULL); + + if (dst_is_pcb) { + dl = pcb_layer_resolve_binding(dst_top, sl); + if (dl != NULL) { + pcb_layer_link_trees(sl, dl); + } + else { + /* need to create the trees so that move and other ops work */ + if (sl->line_tree == NULL) sl->line_tree = pcb_r_create_tree(); + if (sl->arc_tree == NULL) sl->arc_tree = pcb_r_create_tree(); + if (sl->text_tree == NULL) sl->text_tree = pcb_r_create_tree(); + if (sl->polygon_tree == NULL) sl->polygon_tree = pcb_r_create_tree(); + if (!(sl->meta.bound.type & PCB_LYT_VIRTUAL)) + pcb_message(PCB_MSG_ERROR, "Couldn't bind subc layer %s on buffer move\n", sl->name == NULL ? "" : sl->name); + } + } + else + dl = ctx->buffer.dst->Layer + n; + + subc_relocate_layer_objs(dl, ctx->buffer.src, sl, src_has_real_layer, dst_is_pcb); + } + + subc_relocate_globals(ctx->buffer.dst, sc->data, sc, dst_is_pcb); + + if (dst_is_pcb) { + /* clear all pins/pads at once, at the new location */ + clip.clip.restore = 0; clip.clip.clear = 1; + clip.clip.pcb = ctx->buffer.pcb; + pcb_subc_op(ctx->buffer.dst, sc, &ClipFunctions, &clip, PCB_SUBCOP_UNDO_SUBC); + } + + PCB_FLAG_CLEAR(PCB_FLAG_WARN | PCB_FLAG_FOUND | PCB_FLAG_SELECTED, sc); + return sc; +} + +void *pcb_subcop_add_to_buffer(pcb_opctx_t *ctx, pcb_subc_t *sc) +{ + pcb_subc_t *nsc; + nsc = pcb_subc_dup_at(NULL, ctx->buffer.dst, sc, 0, 0, pcb_false); + + if (ctx->buffer.extraflg & PCB_FLAG_SELECTED) { + pcb_undo_freeze_serial(); + pcb_undo_freeze_add(); + pcb_subc_select(NULL, nsc, PCB_CHGFLG_CLEAR, 0); + pcb_undo_unfreeze_add(); + pcb_undo_unfreeze_serial(); + } + + return nsc; +} + +/* break buffer subc into pieces */ +pcb_bool pcb_subc_smash_buffer(pcb_buffer_t *buff) +{ + pcb_subc_t *subc; + int n; + + if (pcb_subclist_length(&buff->Data->subc) != 1) + return pcb_false; + + subc = pcb_subclist_first(&buff->Data->subc); + pcb_subc_unreg(subc); + + /* relocate to NULL to get trees detached */ + for(n = 0; n < subc->data->LayerN; n++) { + pcb_layer_t *sl = subc->data->Layer + n; + int src_has_real_layer = (sl->meta.bound.real != NULL); + subc_relocate_layer_objs(NULL, subc->data, sl, src_has_real_layer, 0); + } + subc_relocate_globals(NULL, NULL, subc, 0); + + pcb_data_free(buff->Data); + buff->Data = subc->data; + buff->Data->parent_type = PCB_PARENT_INVALID; + buff->Data->parent.data = NULL; + + subc_set_parent_globals(subc, buff->Data); + + return pcb_true; +} + +int pcb_subc_rebind(pcb_board_t *pcb, pcb_subc_t *sc) +{ + int n, chgly = 0; + pcb_board_t *dst_top = pcb_data_get_top(sc->data); + int dst_is_pcb = ((dst_top != NULL) && (dst_top->Data == pcb->Data)); + + if (!dst_is_pcb) + return -1; + + EraseSubc(sc); + +/* relocate bindings */ + for(n = 0; n < sc->data->LayerN; n++) { + pcb_layer_t *sl = sc->data->Layer + n; + pcb_layer_t *dl = pcb_layer_resolve_binding(dst_top, sl); + int src_has_real_layer = (sl->meta.bound.real != NULL); + + if (dl != NULL) { + if (sl->meta.bound.real == dl) + continue; + + /* make sure all trees exist on the dest layer - if these are the first objects there we may need to create them */ + if (dl->line_tree == NULL) dl->line_tree = pcb_r_create_tree(); + if (dl->arc_tree == NULL) dl->arc_tree = pcb_r_create_tree(); + if (dl->text_tree == NULL) dl->text_tree = pcb_r_create_tree(); + if (dl->polygon_tree == NULL) dl->polygon_tree = pcb_r_create_tree(); + } + + if (subc_relocate_layer_objs(dl, pcb->Data, sl, src_has_real_layer, 1) > 0) + chgly++; + + if (dl != NULL) + pcb_layer_link_trees(sl, dl); + } + + return chgly; +} + +void pcb_subc_bind_globals(pcb_board_t *pcb, pcb_subc_t *subc) +{ + if (pcb->Data->padstack_tree == NULL) + pcb->Data->padstack_tree = pcb_r_create_tree(); + subc->data->padstack_tree = pcb->Data->padstack_tree; +TODO("subc: subc-in-subc: bind subc rtree") +} + +void *pcb_subcop_change_size(pcb_opctx_t *ctx, pcb_subc_t *sc) +{ + pcb_subc_op(ctx->chgsize.pcb->Data, sc, &ChangeSizeFunctions, ctx, PCB_SUBCOP_UNDO_BATCH); + return sc; +} + +void *pcb_subcop_change_clear_size(pcb_opctx_t *ctx, pcb_subc_t *sc) +{ + pcb_subc_op(ctx->chgsize.pcb->Data, sc, &ChangeClearSizeFunctions, ctx, PCB_SUBCOP_UNDO_BATCH); + return sc; +} + +void *pcb_subcop_change_1st_size(pcb_opctx_t *ctx, pcb_subc_t *sc) +{ + pcb_subc_op(ctx->chgsize.pcb->Data, sc, &Change1stSizeFunctions, ctx, PCB_SUBCOP_UNDO_BATCH); + return sc; +} + +void *pcb_subcop_change_2nd_size(pcb_opctx_t *ctx, pcb_subc_t *sc) +{ + pcb_subc_op(ctx->chgsize.pcb->Data, sc, &Change2ndSizeFunctions, ctx, PCB_SUBCOP_UNDO_BATCH); + return sc; +} + +void *pcb_subcop_change_nonetlist(pcb_opctx_t *ctx, pcb_subc_t *sc) +{ +TODO("subc: add undo") + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, sc)) + return NULL; + PCB_FLAG_TOGGLE(PCB_FLAG_NONETLIST, sc); + return sc; +} + +void *pcb_subcop_change_name(pcb_opctx_t *ctx, pcb_subc_t *sc) +{ + void *old; + if (sc->refdes != NULL) + old = pcb_strdup(sc->refdes); /* strdup because the pcb_attribute_put() is going to free the original */ + else + old = NULL; + pcb_attribute_put(&sc->Attributes, "refdes", ctx->chgname.new_name); + return old; +} + +void *pcb_subcop_destroy(pcb_opctx_t *ctx, pcb_subc_t *sc) +{ + if (ctx->remove.pcb->Data->subc_tree != NULL) + pcb_r_delete_entry(ctx->remove.pcb->Data->subc_tree, (pcb_box_t *)sc); + + EraseSubc(sc); + pcb_subc_free(sc); + return NULL; +} + +void *pcb_subcop_remove(pcb_opctx_t *ctx, pcb_subc_t *sc) +{ + EraseSubc(sc); + pcb_undo_move_obj_to_remove(PCB_OBJ_SUBC, sc, sc, sc); + return NULL; +} + +void *pcb_subc_remove(pcb_subc_t *sc) +{ + void *res; + pcb_opctx_t ctx; + + ctx.remove.pcb = PCB; + ctx.remove.destroy_target = NULL; +/* PCB_CLEAR_PARENT(subc);*/ + + res = pcb_subcop_remove(&ctx, sc); + pcb_draw(); + return res; +} + +void *pcb_subcop_change_flag(pcb_opctx_t *ctx, pcb_subc_t *sc) +{ + static pcb_flag_values_t pcb_subc_flags = 0; + if (pcb_subc_flags == 0) + pcb_subc_flags = pcb_obj_valid_flags(PCB_OBJ_SUBC); + + if (ctx->chgflag.flag == PCB_FLAG_FLOATER) { +TODO("subc: subc-in-subc: can a whole subc be a floater? - add undo!") + PCB_FLAG_CHANGE(ctx->chgflag.how, ctx->chgflag.flag, sc); + return sc; + } + + pcb_subc_op(ctx->chgflag.pcb->Data, sc, &ChgFlagFunctions, ctx, PCB_SUBCOP_UNDO_NORMAL); + if ((ctx->chgflag.flag & pcb_subc_flags) == ctx->chgflag.flag) + PCB_FLAG_CHANGE(ctx->chgflag.how, ctx->chgflag.flag, sc); + return sc; +} + + +void pcb_subc_select(pcb_board_t *pcb, pcb_subc_t *sc, pcb_change_flag_t how, int redraw) +{ + pcb_opctx_t ctx; + + pcb_undo_add_obj_to_flag(sc); + + ctx.chgflag.pcb = pcb; + ctx.chgflag.how = how; + ctx.chgflag.flag = PCB_FLAG_SELECTED; + + pcb_subc_op((pcb == NULL ? NULL : pcb->Data), sc, &ChgFlagFunctions, &ctx, PCB_SUBCOP_UNDO_NORMAL); + PCB_FLAG_CHANGE(how, PCB_FLAG_SELECTED, sc); + if (redraw) + DrawSubc(sc); +} + +/* mirrors the coordinates of a subcircuit; an additional offset is passed */ +void pcb_subc_mirror(pcb_data_t *data, pcb_subc_t *subc, pcb_coord_t y_offs, pcb_bool smirror) +{ + if ((data != NULL) && (data->subc_tree != NULL)) + pcb_r_delete_entry(data->subc_tree, (pcb_box_t *)subc); + + pcb_undo_freeze_add(); + pcb_data_mirror(subc->data, y_offs, smirror ? PCB_TXM_SIDE : PCB_TXM_COORD, smirror); + pcb_undo_unfreeze_add(); + pcb_subc_bbox(subc); + + if ((data != NULL) && (data->subc_tree != NULL)) + pcb_r_insert_entry(data->subc_tree, (pcb_box_t *)subc); +} + +void pcb_subc_scale(pcb_data_t *data, pcb_subc_t *subc, double sx, double sy, double sth, int recurse) +{ + if ((data != NULL) && (data->subc_tree != NULL)) + pcb_r_delete_entry(data->subc_tree, (pcb_box_t *)subc); + + pcb_data_scale(subc->data, sx, sy, sth, recurse); + pcb_subc_bbox(subc); + + if ((data != NULL) && (data->subc_tree != NULL)) + pcb_r_insert_entry(data->subc_tree, (pcb_box_t *)subc); +} + + +pcb_bool pcb_subc_change_side(pcb_subc_t *subc, pcb_coord_t yoff) +{ + int n; + pcb_board_t *pcb; + pcb_data_t *data; + + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, subc)) + return pcb_false; + + assert(subc->parent_type = PCB_PARENT_DATA); + data = subc->parent.data; + pcb = pcb_data_get_top(data); + + /* mirror object geometry and stackup */ + + if ((data != NULL) && (data->subc_tree != NULL)) + pcb_r_delete_entry(data->subc_tree, (pcb_box_t *)subc); + + pcb_undo_freeze_add(); + pcb_data_mirror(subc->data, yoff, PCB_TXM_SIDE, 1); + pcb_undo_unfreeze_add(); + + for(n = 0; n < subc->data->LayerN; n++) { + pcb_layer_t *ly = subc->data->Layer + n; + ly->meta.bound.type = pcb_layer_mirror_type(ly->meta.bound.type); + ly->meta.bound.stack_offs = -ly->meta.bound.stack_offs; + } + pcb_subc_rebind(pcb, subc); + + pcb_subc_bbox(subc); + + if ((data != NULL) && (data->subc_tree != NULL)) + pcb_r_insert_entry(data->subc_tree, (pcb_box_t *)subc); + + pcb_undo_add_subc_to_otherside(PCB_OBJ_SUBC, subc, subc, subc, yoff); + + return pcb_true; +} + + + /* in per-side mode, do not show subc mark if it is on the other side */ +#define draw_subc_per_layer() \ +do { \ + int per_side = 0; \ + if (cl != NULL) \ + per_side = *(int *)cl; \ + if (per_side) { \ + int on_bottom; \ + if (pcb_subc_get_side(subc, &on_bottom) == 0) { \ + if ((!!on_bottom) != (!!conf_core.editor.show_solder_side)) \ + return PCB_R_DIR_FOUND_CONTINUE; \ + } \ + } \ +} while(0) + + +#include "conf_core.h" +#include "draw.h" +pcb_r_dir_t draw_subc_mark_callback(const pcb_box_t *b, void *cl) +{ + pcb_draw_info_t *info = cl; + pcb_subc_t *subc = (pcb_subc_t *) b; + pcb_box_t *bb = &subc->BoundingBox; + int selected = PCB_FLAG_TEST(PCB_FLAG_SELECTED, subc); + int freq = conf_core.appearance.subc.dash_freq; + const pcb_color_t *nnclr; + + draw_subc_per_layer(); + + if (freq > 32) + freq = 32; + + nnclr = (PCB_FLAG_TEST(PCB_FLAG_NONETLIST, subc)) ? &conf_core.appearance.color.subc_nonetlist : &conf_core.appearance.color.subc; + pcb_gui->set_color(pcb_draw_out.fgGC, selected ? &conf_core.appearance.color.selected : nnclr); + pcb_subc_draw_origin(pcb_draw_out.fgGC, subc, 0, 0); + + if (freq >= 0) { + pcb_draw_dashed_line(info, pcb_draw_out.fgGC, bb->X1, bb->Y1, bb->X2, bb->Y1, freq, pcb_true); + pcb_draw_dashed_line(info, pcb_draw_out.fgGC, bb->X1, bb->Y1, bb->X1, bb->Y2, freq, pcb_true); + pcb_draw_dashed_line(info, pcb_draw_out.fgGC, bb->X2, bb->Y2, bb->X2, bb->Y1, freq, pcb_true); + pcb_draw_dashed_line(info, pcb_draw_out.fgGC, bb->X2, bb->Y2, bb->X1, bb->Y2, freq, pcb_true); + } + + return PCB_R_DIR_FOUND_CONTINUE; +} + +pcb_r_dir_t draw_subc_label_callback(const pcb_box_t *b, void *cl) +{ + pcb_draw_info_t *info = cl; + pcb_subc_t *subc = (pcb_subc_t *) b; + pcb_box_t *bb = &subc->BoundingBox; + pcb_coord_t x0, y0, dx, dy; + pcb_font_t *font = &PCB->fontkit.dflt; + + /* do not display anyting from the other-side subcs */ + draw_subc_per_layer(); + + /* calculate where the label ends up - always top-right, even if board is flipped */ + dx = font->MaxWidth/2; + dy = font->MaxHeight/2; + + if (conf_core.editor.view.flip_x) { + x0 = bb->X2; + dx = -dx; + } + else + x0 = bb->X1; + + if (conf_core.editor.view.flip_y) { + y0 = bb->Y2; + dy = -dy; + } + else + y0 = bb->Y1; + + /* draw the label from template; if template is not available, draw the refdes */ + if ((conf_core.editor.subc_id != NULL) && (*conf_core.editor.subc_id != '\0')) { + static gds_t s; + + s.used = 0; + if (pcb_append_dyntext(&s, (pcb_any_obj_t *)subc, conf_core.editor.subc_id) == 0) { + char *curr, *next; + pcb_coord_t x = x0, y = y0; + + for(curr = s.array; curr != NULL; curr = next) { + int ctrl = 0; + next = strchr(curr, '\\'); + if (next != NULL) { + *next = '\0'; + next++; + ctrl = 1; + } + pcb_label_draw(info, x, y, conf_core.appearance.term_label_size/2, 0, 0, curr); + if (ctrl) { + switch(*next) { + case 'n': y += dy; x = x0; break; + } + next++; + } + } + } + else + pcb_label_draw(info, x0, y0, conf_core.appearance.term_label_size/2.0, 0, 0, ""); + } + else if (subc->refdes != NULL) + pcb_label_draw(info, x0, y0, conf_core.appearance.term_label_size/2.0, 0, 0, subc->refdes); + + return PCB_R_DIR_FOUND_CONTINUE; +} + +void pcb_subc_draw_preview(const pcb_subc_t *sc, const pcb_box_t *drawn_area) +{ + int n; + pcb_draw_info_t info; + pcb_rtree_it_t it; + pcb_any_obj_t *o; + + /* draw copper only first - order doesn't matter */ + for(n = 0; n < sc->data->LayerN; n++) { + pcb_layer_t *layer = &sc->data->Layer[n]; + if (layer->meta.bound.type & PCB_LYT_COPPER) + pcb_draw_layer_under(PCB, layer, drawn_area, sc->data); + } + + /* draw padstacks */ + info.pcb = PCB; + info.drawn_area = drawn_area; + info.xform_caller = info.xform_exporter = info.xform = NULL; + info.layer = NULL; + info.objcb.pstk.gid = -1; + info.objcb.pstk.is_current = 1; + info.objcb.pstk.comb = 0; + info.objcb.pstk.shape_mask = PCB_LYT_COPPER | PCB_LYT_TOP; + info.objcb.pstk.holetype = PCB_PHOLE_UNPLATED | PCB_PHOLE_PLATED; + + for(o = pcb_rtree_first(&it, sc->data->padstack_tree, (pcb_rtree_box_t *)drawn_area); o != NULL; o = pcb_rtree_next(&it)) { + if (pcb_obj_is_under(o, sc->data)) { + pcb_pstk_draw_callback((pcb_box_t *)o, &info); + if (PCB->hole_on) + pcb_pstk_draw_hole_callback((pcb_box_t *)o, &info); + } + } + + /* draw silk and mech and doc layers, above padstacks */ + for(n = 0; n < sc->data->LayerN; n++) { + pcb_layer_t *layer = &sc->data->Layer[n]; + if (layer->meta.bound.type & (PCB_LYT_SILK | PCB_LYT_BOUNDARY | PCB_LYT_MECH | PCB_LYT_DOC)) + pcb_draw_layer_under(PCB, layer, drawn_area, sc->data); + } + + /* padstack mark goes on top */ + for(o = pcb_rtree_first(&it, sc->data->padstack_tree, (pcb_rtree_box_t *)drawn_area); o != NULL; o = pcb_rtree_next(&it)) { + if (pcb_obj_is_under(o, sc->data)) { + pcb_pstk_draw_mark_callback((pcb_box_t *)o, &info); + pcb_pstk_draw_label_callback((pcb_box_t *)o, &info); + } + } +} + + +pcb_subc_t *pcb_subc_by_refdes(pcb_data_t *base, const char *name) +{ +TODO("subc: hierarchy") + PCB_SUBC_LOOP(base); + { + if ((subc->refdes != NULL) && (PCB_NSTRCMP(subc->refdes, name) == 0)) + return subc; + } + PCB_END_LOOP; + return NULL; +} + +pcb_subc_t *pcb_subc_by_id(pcb_data_t *base, long int ID) +{ + /* We can not have an rtree based search here: we are often called + in the middle of an operation, after the subc got already removed + from the rtree. It happens in e.g. undoable padstack operations + where the padstack tries to look up its parent subc by ID, while + the subc is being rotated. + + The solution will be the ID hash. */ +TODO("subc: hierarchy") + PCB_SUBC_LOOP(base); + { + if (subc->ID == ID) + return subc; + } + PCB_END_LOOP; + return NULL; +} + +pcb_bool pcb_subc_is_empty(pcb_subc_t *subc) +{ + return pcb_data_is_empty(subc->data); +} + +pcb_layer_t *pcb_subc_get_layer(pcb_subc_t *sc, pcb_layer_type_t lyt, pcb_layer_combining_t comb, pcb_bool_t alloc, const char *name, pcb_bool req_name_match) +{ + int n; + + /* look for an existing layer with matching lyt and comb first */ + for(n = 0; n < sc->data->LayerN; n++) { + if (sc->data->Layer[n].meta.bound.type != lyt) + continue; + if ((comb != -1) && (sc->data->Layer[n].comb != comb)) + continue; + if (req_name_match && (strcmp(sc->data->Layer[n].name, name) != 0)) + continue; + return &sc->data->Layer[n]; + } + + if (!alloc) + return NULL; + + if (sc->data->LayerN == PCB_MAX_LAYER) + return NULL; + + n = sc->data->LayerN++; + if (name == NULL) + name = ""; + + if (comb == -1) { + /* "any" means default, for the given layer type */ + if (lyt & PCB_LYT_MASK) + comb = PCB_LYC_SUB; + else + comb = 0; /* positive, manual */ + } + + memset(&sc->data->Layer[n], 0, sizeof(sc->data->Layer[n])); + sc->data->Layer[n].name = pcb_strdup(name); + sc->data->Layer[n].comb = comb; + sc->data->Layer[n].is_bound = 1; + sc->data->Layer[n].meta.bound.type = lyt; + sc->data->Layer[n].parent.data = sc->data; + sc->data->Layer[n].parent_type = PCB_PARENT_DATA; + sc->data->Layer[n].type = PCB_OBJ_LAYER; + return &sc->data->Layer[n]; +} + +void pcb_subc_part_changed_(pcb_any_obj_t *obj) +{ + pcb_subc_t *sc = pcb_obj_parent_subc(obj); + if (sc == NULL) + return; + + /* can't do this incrementally: if a boundary object is smaller than before + it has to make the subc bbox smaller too */ + pcb_subc_bbox(sc); +} + + +const char *pcb_subc_name(pcb_subc_t *subc, const char *local_name) +{ + const char *val; + + if (local_name != NULL) { + val = pcb_attribute_get(&subc->Attributes, local_name); + if (val != NULL) + return val; + } + val = pcb_attribute_get(&subc->Attributes, "visible_footprint"); + if (val != NULL) + return val; + val = pcb_attribute_get(&subc->Attributes, "footprint"); + return val; +} + + +pcb_subc_t *pcb_subc_replace(pcb_board_t *pcb, pcb_subc_t *dst, pcb_subc_t *src, pcb_bool add_undo, pcb_bool dumb) +{ + pcb_data_t *data = dst->parent.data; + pcb_subc_t *placed; + pcb_coord_t ox, oy; + double rot = 0; + long int target_id; + int dst_on_bottom = 0, src_on_bottom = 0; + static const pcb_flag_values_t fmask = PCB_FLAG_SELECTED | \ + PCB_FLAG_ONSOLDER | PCB_FLAG_AUTO | PCB_FLAG_NONETLIST; + pcb_flag_values_t flags; + + assert(dst->parent_type == PCB_PARENT_DATA); + assert(src != NULL); + + if (dumb) { + ox = pcb_crosshair.X; + oy = pcb_crosshair.Y; + } + else { + if (pcb_subc_get_origin(dst, &ox, &oy) != 0) { + ox = (dst->BoundingBox.X1 + dst->BoundingBox.X2) / 2; + oy = (dst->BoundingBox.Y1 + dst->BoundingBox.Y2) / 2; + } + pcb_subc_get_rotation(dst, &rot); + pcb_subc_get_side(dst, &dst_on_bottom); + } + + + placed = pcb_subc_dup_at(pcb, data, src, ox, oy, 0); + pcb_subc_get_side(placed, &src_on_bottom); + + { /* copy attributes */ + int n; + pcb_attribute_list_t *adst = &placed->Attributes, *asrc = &dst->Attributes; + for (n = 0; n < asrc->Number; n++) + if (strcmp(asrc->List[n].name, "footprint") != 0) + pcb_attribute_put(adst, asrc->List[n].name, asrc->List[n].value); + } + + flags = dst->Flags.f & fmask; + + target_id = dst->ID; + pcb_subc_remove(dst); + + pcb_obj_id_del(data, placed); + placed->ID = target_id; + pcb_obj_id_reg(data, placed); + placed->Flags.f &= ~fmask; + placed->Flags.f |= flags; + + if (rot != 0) { + if (dst_on_bottom != src_on_bottom) + rot = -rot; + pcb_subc_rotate(placed, ox, oy, cos(rot / PCB_RAD_TO_DEG), sin(rot / PCB_RAD_TO_DEG), rot); + } + + if (dst_on_bottom != src_on_bottom) + pcb_subc_change_side(placed, 2 * oy - PCB->MaxHeight); + + pcb_undo_freeze_add(); + pcb_subc_select(pcb, placed, (flags & PCB_FLAG_SELECTED) ? PCB_CHGFLG_SET : PCB_CHGFLG_CLEAR, 0); + pcb_undo_unfreeze_add(); + + if (add_undo) + pcb_undo_add_obj_to_create(PCB_OBJ_SUBC, placed, placed, placed); + + + return placed; +} Index: tags/2.1.2/src/obj_subc.h =================================================================== --- tags/2.1.2/src/obj_subc.h (nonexistent) +++ tags/2.1.2/src/obj_subc.h (revision 24813) @@ -0,0 +1,180 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2017..2019 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#ifndef PCB_OBJ_SUBC_H +#define PCB_OBJ_SUBC_H + +#include +#include +#include +#include "obj_common.h" +#include "layer.h" +#include "global_typedefs.h" + + +typedef enum pcb_subc_cached_s { + PCB_SUBCH_ORIGIN, + PCB_SUBCH_X, + PCB_SUBCH_Y, + PCB_SUBCH_max +} pcb_subc_cached_t; + +struct pcb_subc_s { + PCB_ANY_PRIMITIVE_FIELDS; + minuid_bin_t uid; + pcb_data_t *data; + htsp_t terminals; + pcb_line_t *aux_cache[PCB_SUBCH_max]; + pcb_layer_t *aux_layer; + const char *refdes; /* cached from attributes for fast lookup */ + gdl_elem_t link; +}; + +pcb_subc_t *pcb_subc_alloc(void); +pcb_subc_t *pcb_subc_alloc_id(long int id); +pcb_subc_t *pcb_subc_new(void); +void pcb_subc_free(pcb_subc_t *sc); + +void pcb_subc_reg(pcb_data_t *data, pcb_subc_t *subc); +void pcb_subc_unreg(pcb_subc_t *subc); + + +void pcb_subc_select(pcb_board_t *pcb, pcb_subc_t *sc, pcb_change_flag_t how, int redraw); + +void pcb_subc_bbox(pcb_subc_t *sc); + +/* convert buffer contents into a subcircuit, in-place; returns 0 on success */ +int pcb_subc_convert_from_buffer(pcb_buffer_t *buffer); +pcb_bool pcb_subc_smash_buffer(pcb_buffer_t *buff); + +void pcb_subc_mirror(pcb_data_t *data, pcb_subc_t *subc, pcb_coord_t y_offs, pcb_bool smirror); + +/* Scale coords/pos of a subc by sx,sy with thickness factor sth; + if recurse is non-zero, descend in subc-in-subc */ +void pcb_subc_scale(pcb_data_t *data, pcb_subc_t *subc, double sx, double sy, double sth, int recurse); + +/* changes the side of the board a subc is on; returns pcb_true if done */ +pcb_bool pcb_subc_change_side(pcb_subc_t *subc, pcb_coord_t yoff); + +void pcb_subc_rotate(pcb_subc_t *subc, pcb_coord_t cx, pcb_coord_t cy, double cosa, double sina, double angle); +void pcb_subc_rotate90(pcb_subc_t *subc, pcb_coord_t cx, pcb_coord_t cy, int steps); + +/* High level move (op wrapper; no undo) */ +void pcb_subc_move(pcb_subc_t *sc, pcb_coord_t dx, pcb_coord_t dy, pcb_bool more_to_come); + +/* changes the side of all selected and visible subcs; returns pcb_true if anything has changed */ +pcb_bool pcb_selected_subc_change_side(void); + +/* Draw a subcircuit for a preview (silk, copper and outline only) */ +void pcb_subc_draw_preview(const pcb_subc_t *sc, const pcb_box_t *drawn_area); + +void pcb_xordraw_subc(pcb_subc_t *sc, pcb_coord_t DX, pcb_coord_t DY, int use_curr_side); + +/* Redo the layer binding after the layer binding recipe changed in sc */ +int pcb_subc_rebind(pcb_board_t *pcb, pcb_subc_t *sc); + +/* Do the initial global bindings of subc to pcb (rtree links) */ +void pcb_subc_bind_globals(pcb_board_t *pcb, pcb_subc_t *subc); + +/* Look up a layer by lyt and comb (and name, if req_name_match is true); + if not found and alloc is true, allocate a new layer with the given name. + Return NULL on error. */ +pcb_layer_t *pcb_subc_get_layer(pcb_subc_t *sc, pcb_layer_type_t lyt, pcb_layer_combining_t comb, pcb_bool_t alloc, const char *name, pcb_bool req_name_match); + +#include "rtree.h" +pcb_r_dir_t draw_subc_mark_callback(const pcb_box_t *b, void *cl); +pcb_r_dir_t draw_subc_label_callback(const pcb_box_t *b, void *cl); +void DrawSubc(pcb_subc_t *sc); +void EraseSubc(pcb_subc_t *sc); + +/* calculate geometrical properties using the aux layer; return 0 on success */ +int pcb_subc_get_origin(pcb_subc_t *sc, pcb_coord_t *x, pcb_coord_t *y); +int pcb_subc_get_rotation(pcb_subc_t *sc, double *rot); +int pcb_subc_get_side(pcb_subc_t *sc, int *on_bottom); + +/* get all the above transformatoins at once. If neg is 0, these are the + raw transofrmations ("what happened to the subc from neutral state"), + if neg is non-zero, these are the transformations back to neutral state. */ +int pcb_subc_get_host_trans(pcb_subc_t *sc, pcb_host_trans_t *tr, int neg); + +/* Search for the named subc; name is relative path in hierarchy. Returns + NULL if not found */ +pcb_subc_t *pcb_subc_by_refdes(pcb_data_t *base, const char *name); + +/* Search subc, "recursively", by ID */ +pcb_subc_t *pcb_subc_by_id(pcb_data_t *base, long int ID); + +/* undoable remove */ +void *pcb_subc_remove(pcb_subc_t *sc); + +/* In board mode return brd_layer; in footprint edit mode, return the subcircuit + layer that matches brd_layer. If not found, either allocate it within + the subc (if alloc is true) or return the brd_layer. */ +pcb_layer_t *pcb_loose_subc_layer(pcb_board_t *pcb, pcb_layer_t *brd_layer, pcb_bool alloc); + +/* Returns whether there's no object in the subc */ +pcb_bool pcb_subc_is_empty(pcb_subc_t *subc); + +/* Return the footprint name; if local_name is not NULL, that attribute + is queried first; if that doesn't exist, "visible_footprint" and then + "footprint" is returned (or NULL if nothing is found) */ +const char *pcb_subc_name(pcb_subc_t *subc, const char *local_name); + + +/* Update the subcircuit (e.g. bbox) after a part of the subcircuit has changed */ +void pcb_subc_part_changed_(pcb_any_obj_t *obj); +#define pcb_subc_part_changed(obj) pcb_subc_part_changed_((pcb_any_obj_t *)obj) + +/*** subc creation helpers ***/ + +/* Create the aux layer for a subc, set origin to ox;oy and rotation to rot */ +void pcb_subc_create_aux(pcb_subc_t *sc, pcb_coord_t ox, pcb_coord_t oy, double rot, pcb_bool bottom); + +/* Create a new point on the aux layer using a given role string in attribute */ +void pcb_subc_create_aux_point(pcb_subc_t *sc, pcb_coord_t x, pcb_coord_t y, const char *role); + +/* Look up an aux point and return pcb_true if found; when found, load x and y + with the coords of the point. */ +pcb_bool pcb_subc_find_aux_point(pcb_subc_t *sc, const char *role, pcb_coord_t *x, pcb_coord_t *y); + + +pcb_subc_t *pcb_subc_dup_at(pcb_board_t *pcb, pcb_data_t *dst, pcb_subc_t *src, pcb_coord_t dx, pcb_coord_t dy, pcb_bool keep_ids); + +/* Replace dst with a copy of src in place (preserving location and orientation + and attributes. If add_undo is true, add the old subc del and the new subc + creation to the undo list. If dub is true, do not try to match rotation or + pick up coords, just use crosshair and current loc. */ +pcb_subc_t *pcb_subc_replace(pcb_board_t *pcb, pcb_subc_t *dst, pcb_subc_t *src, pcb_bool add_undo, pcb_bool dumb); + +/*** loops ***/ + +#define PCB_SUBC_LOOP(top) do { \ + pcb_subc_t *subc; \ + gdl_iterator_t __it__; \ + subclist_foreach(&(top)->subc, &__it__, subc) { + + +#endif Index: tags/2.1.2/src/obj_subc_hash.c =================================================================== --- tags/2.1.2/src/obj_subc_hash.c (nonexistent) +++ tags/2.1.2/src/obj_subc_hash.c (revision 24813) @@ -0,0 +1,166 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2018 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "config.h" + +#include "data.h" +#include "layer.h" +#include "obj_subc.h" +#include "obj_arc.h" +#include "obj_line.h" +#include "obj_text.h" +#include "obj_poly.h" +#include "obj_pstk.h" + +int pcb_subc_hash_ignore_uid = 0; + +int pcb_subc_eq(pcb_subc_t *sc1, pcb_subc_t *sc2) +{ + pcb_host_trans_t tr1, tr2; + int lid; + gdl_iterator_t it; + + /* optimization: cheap tests first */ + if (!pcb_subc_hash_ignore_uid && memcmp(&sc1->uid, &sc2->uid, sizeof(sc1->uid)) != 0) return 0; + if (sc1->data->LayerN != sc2->data->LayerN) return 0; + if (padstacklist_length(&sc1->data->padstack) != padstacklist_length(&sc2->data->padstack)) return 0; + if (pcb_subclist_length(&sc1->data->subc) != pcb_subclist_length(&sc2->data->subc)) return 0; + + for(lid = 0; lid < sc1->data->LayerN; lid++) { + pcb_layer_t *ly1 = &sc1->data->Layer[lid]; + pcb_layer_t *ly2 = &sc2->data->Layer[lid]; +TODO("todo") +/* if (!pcb_layer_eq_bound(ly1, tr1.on_bottom, ly2, tr2.on_bottom)) return 0;*/ + if (arclist_length(&ly1->Arc) != arclist_length(&ly2->Arc)) return 0; + } + + pcb_subc_get_host_trans(sc1, &tr1, 1); + pcb_subc_get_host_trans(sc2, &tr2, 1); + + for(lid = 0; lid < sc1->data->LayerN; lid++) { + pcb_line_t *l1, *l2; + pcb_arc_t *a1, *a2; + pcb_text_t *t1, *t2; + pcb_poly_t *p1, *p2; + pcb_layer_t *ly1 = &sc1->data->Layer[lid]; + pcb_layer_t *ly2 = &sc2->data->Layer[lid]; + + + /* assume order of children objects are the same */ + a2 = arclist_first(&ly2->Arc); + arclist_foreach(&ly1->Arc, &it, a1) { + if (!pcb_arc_eq(&tr1, a1, &tr2, a2)) return 0; + a2 = arclist_next(a2); + } + + l2 = linelist_first(&ly2->Line); + linelist_foreach(&ly1->Line, &it, l1) { + if (!pcb_line_eq(&tr1, l1, &tr2, l2)) return 0; + l2 = linelist_next(l2); + } + + t2 = textlist_first(&ly2->Text); + textlist_foreach(&ly1->Text, &it, t1) { + if (!pcb_text_eq(&tr1, t1, &tr2, t2)) return 0; + t2 = textlist_next(t2); + } + + p2 = polylist_first(&ly2->Polygon); + polylist_foreach(&ly1->Polygon, &it, p1) { + if (!pcb_poly_eq(&tr1, p1, &tr2, p2)) return 0; + p2 = polylist_next(p2); + } + } + + /* compare global objects */ + { + pcb_pstk_t *p1, *p2; + + p2 = padstacklist_first(&sc2->data->padstack); + padstacklist_foreach(&sc1->data->padstack, &it, p1) { + if (!pcb_pstk_eq(&tr1, p1, &tr2, p2)) return 0; + p2 = padstacklist_next(p2); + } +TODO("subc: subc-in-subc eq check") + } + + return 1; +} + +unsigned int pcb_subc_hash(pcb_subc_t *sc) +{ + unsigned int hash; + int lid; + pcb_host_trans_t tr; + gdl_iterator_t it; + + pcb_subc_get_host_trans(sc, &tr, 1); + + hash = sc->data->LayerN; + + if (!pcb_subc_hash_ignore_uid) + hash ^= murmurhash(&sc->uid, sizeof(sc->uid)); + + /* hash layers and layer objects */ + + for(lid = 0; lid < sc->data->LayerN; lid++) { + pcb_layer_t *ly = &sc->data->Layer[lid]; + + pcb_line_t *l; + pcb_arc_t *a; + pcb_text_t *t; + pcb_poly_t *p; + + hash ^= pcb_layer_hash_bound(ly, tr.on_bottom); + + arclist_foreach(&ly->Arc, &it, a) + hash ^= pcb_arc_hash(&tr, a); + + linelist_foreach(&ly->Line, &it, l) + hash ^= pcb_line_hash(&tr, l); + + textlist_foreach(&ly->Text, &it, t) + hash ^= pcb_text_hash(&tr, t); + + polylist_foreach(&ly->Polygon, &it, p) + hash ^= pcb_poly_hash(&tr, p); + } + + /* hash global objects */ + { + pcb_pstk_t *ps; +TODO("subc: subc in subc: trans in trans") +#if 0 + pcb_subc_t *s; + subclist_foreach(&sc->data->subc, &it, s) + hash ^= pcb_subc_hash_(&tr, p); +#endif + padstacklist_foreach(&sc->data->padstack, &it, ps) + hash ^= pcb_pstk_hash(&tr, ps); + } + return hash; +} + Index: tags/2.1.2/src/obj_subc_list.c =================================================================== --- tags/2.1.2/src/obj_subc_list.c (nonexistent) +++ tags/2.1.2/src/obj_subc_list.c (revision 24813) @@ -0,0 +1,36 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2017 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + + + +#include "config.h" + +/* include other lists before TDL_DONT_UNDEF makes them pollute the namespace */ +#include "obj_subc.h" + +#define TDL_DONT_UNDEF +#include "obj_subc_list.h" +#include Index: tags/2.1.2/src/obj_subc_list.h =================================================================== --- tags/2.1.2/src/obj_subc_list.h (nonexistent) +++ tags/2.1.2/src/obj_subc_list.h (revision 24813) @@ -0,0 +1,91 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2017 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#ifndef PCB_OBJ_SUBC_LIST_H +#define PCB_OBJ_SUBC_LIST_H + +#include "obj_subc.h" + +/* List of Elements */ +#define TDL(x) pcb_subclist_ ## x +#define TDL_LIST_T pcb_subclist_t +#define TDL_ITEM_T pcb_subc_t +#define TDL_FIELD link +#define TDL_SIZE_T size_t +#define TDL_FUNC + +#define subclist_foreach(list, iterator, loop_elem) \ + gdl_foreach_((&((list)->lst)), (iterator), (loop_elem)) + +#include "ht_subc.h" +#include + +/* When turned on, temporarily ignore the uid in hash()/eq() - useful for + imported subcircuits that may have random UIDs */ +extern int pcb_subc_hash_ignore_uid; + + +/* Calculate a hash value using the content of the subc. The hash value + represents the actual content of an subc */ +unsigned int pcb_subc_hash(pcb_subc_t *e); + +/* Compare two subcs and return 1 if they are qeual + (their uids match and they contain the same objects). */ +int pcb_subc_eq(pcb_subc_t *sc1, pcb_subc_t *sc2); + +/* Create a new local variable to be used for deduplication */ +#define pcb_subclist_dedup_initializer(state) htscp_t *state = NULL; + +/* Do a "continue" if an subc matching loop_elem has been seen already; + Typically this is invoked as the first statement of an subclist_foreach() + loop. */ +#define pcb_subclist_dedup_skip(state, loop_elem) \ +switch(1) { \ + case 1: { \ + if (state == NULL) \ + state = htscp_alloc(pcb_subc_hash, pcb_subc_eq); \ + if (htscp_has(state, loop_elem)) \ + continue; \ + htscp_set(state, loop_elem, loop_elem); \ + } \ +} + +/* use this after the loop to free all memory used by state */ +#define pcb_subclist_dedup_free(state) \ + do { \ + if (state != NULL) { \ + htscp_free(state); \ + state = NULL; \ + } \ + } while(0) + + +#ifndef LIST_SUBCENT_NOINSTANT +#include +#include +#endif + +#endif Index: tags/2.1.2/src/obj_subc_op.h =================================================================== --- tags/2.1.2/src/obj_subc_op.h (nonexistent) +++ tags/2.1.2/src/obj_subc_op.h (revision 24813) @@ -0,0 +1,57 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2017 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#ifndef PCB_OBJ_SUBC_OP_H +#define PCB_OBJ_SUBC_OP_H + +#include "operation.h" + +void *pcb_subcop_copy(pcb_opctx_t *ctx, pcb_subc_t *src); +void *pcb_subcop_move(pcb_opctx_t *ctx, pcb_subc_t *sc); +void *pcb_subcop_rotate90(pcb_opctx_t *ctx, pcb_subc_t *sc); +void *pcb_subcop_rotate(pcb_opctx_t *ctx, pcb_subc_t *sc); +void *pcb_subcop_move_buffer(pcb_opctx_t *ctx, pcb_subc_t *sc); +void *pcb_subcop_add_to_buffer(pcb_opctx_t *ctx, pcb_subc_t *sc); +void *pcb_subcop_change_size(pcb_opctx_t *ctx, pcb_subc_t *sc); +void *pcb_subcop_change_clear_size(pcb_opctx_t *ctx, pcb_subc_t *sc); +void *pcb_subcop_change_1st_size(pcb_opctx_t *ctx, pcb_subc_t *sc); +void *pcb_subcop_change_2nd_size(pcb_opctx_t *ctx, pcb_subc_t *sc); +void *pcb_subcop_change_nonetlist(pcb_opctx_t *ctx, pcb_subc_t *sc); +void *pcb_subcop_change_name(pcb_opctx_t *ctx, pcb_subc_t *sc); +void *pcb_subcop_destroy(pcb_opctx_t *ctx, pcb_subc_t *sc); +void *pcb_subcop_remove(pcb_opctx_t *ctx, pcb_subc_t *sc); + +void *pcb_subcop_change_flag(pcb_opctx_t *ctx, pcb_subc_t *sc); + +typedef enum pcb_subc_op_undo_e { + PCB_SUBCOP_UNDO_NORMAL, /* each part operation is undone separately */ + PCB_SUBCOP_UNDO_SUBC, /* the undo for the parent subcircuit will handle each part's undo */ + PCB_SUBCOP_UNDO_BATCH /* each part operation has its own undo, but with the same serial */ +} pcb_subc_op_undo_t; + +void *pcb_subc_op(pcb_data_t *Data, pcb_subc_t *sc, pcb_opfunc_t *opfunc, pcb_opctx_t *ctx, pcb_subc_op_undo_t batch_undo); + +#endif Index: tags/2.1.2/src/obj_subc_parent.h =================================================================== --- tags/2.1.2/src/obj_subc_parent.h (nonexistent) +++ tags/2.1.2/src/obj_subc_parent.h (revision 24813) @@ -0,0 +1,105 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2017 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#ifndef PCB_OBJ_SUBC_PARENT_H +#define PCB_OBJ_SUBC_PARENT_H + +#include "data.h" +#include "data_parent.h" +#include "layer.h" + +/* Returns the subc a global (on-data) object is part of (or NULL if not part of any subc) */ +PCB_INLINE pcb_subc_t *pcb_gobj_parent_subc(pcb_parenttype_t pt, const pcb_parent_t *p) +{ + if (pt != PCB_PARENT_DATA) + return NULL; + + if (p->data == NULL) + return NULL; + + if (p->data->parent_type == PCB_PARENT_SUBC) + return p->data->parent.subc; + return NULL; +} + +/* Returns the subc a layer object is part of (or NULL if not part of any subc) */ +PCB_INLINE pcb_subc_t *pcb_lobj_parent_subc(pcb_parenttype_t pt, const pcb_parent_t *p) +{ + if (pt != PCB_PARENT_LAYER) + return NULL; + + if (p->layer == NULL) + return NULL; + + if (p->layer->parent.data == NULL) + return NULL; + + if (p->layer->parent.data->parent_type == PCB_PARENT_SUBC) + return p->layer->parent.data->parent.subc; + return NULL; +} + +/* Returns the subc an object is part of (or NULL if not part of any subc) */ +PCB_INLINE pcb_subc_t *pcb_obj_parent_subc(const pcb_any_obj_t *obj) +{ + switch(obj->type) { + case PCB_OBJ_PSTK: + case PCB_OBJ_SUBC: + return pcb_gobj_parent_subc(obj->parent_type, &obj->parent); + + case PCB_OBJ_LINE: + case PCB_OBJ_POLY: + case PCB_OBJ_TEXT: + case PCB_OBJ_ARC: + return pcb_lobj_parent_subc(obj->parent_type, &obj->parent); + + default: + /* anything else: virtual */ + return 0; + } + return 0; +} + +PCB_INLINE pcb_bool_t pcb_obj_is_under(pcb_any_obj_t *obj, pcb_data_t *data) +{ + for(;;) { + switch(obj->parent_type) { + case PCB_PARENT_INVALID: return pcb_false; + case PCB_PARENT_BOARD: return pcb_false; + case PCB_PARENT_UI: return pcb_false; /* shouldn't happen */ + case PCB_PARENT_LAYER: if (obj->parent.layer->parent.data == data) return pcb_true; break; + case PCB_PARENT_SUBC: if (obj->parent.subc->data == data) return pcb_true; break; + case PCB_PARENT_DATA: if (obj->parent.data == data) return pcb_true; break; + case PCB_PARENT_NET: if (obj->parent.data == data) return pcb_true; break; + } + obj = (pcb_any_obj_t *)pcb_obj_parent_subc(obj); + if (obj == NULL) + return pcb_false; + } +} + + +#endif Index: tags/2.1.2/src/obj_term.c =================================================================== --- tags/2.1.2/src/obj_term.c (nonexistent) +++ tags/2.1.2/src/obj_term.c (revision 24813) @@ -0,0 +1,352 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2017 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "config.h" + +#include +#include +#include +#include + +#include "change.h" +#include "compat_misc.h" +#include "obj_common.h" +#include "obj_term.h" +#include "obj_subc_parent.h" +#include "pcb-printf.h" +#include "undo.h" +#include "macro.h" +#include "polygon.h" + +static const char core_term_cookie[] = "core-term"; + +static int term_name_invalid(const char *tname) +{ + if ((tname == NULL) || (*tname == '\0')) + return 1; + for(;*tname != '\0'; tname++) + if ((!isalnum(*tname)) && (*tname != '_') && (*tname != '-')) + return 1; + return 0; +} + +pcb_term_err_t pcb_term_name_is_valid(const char *tname) +{ + if (term_name_invalid(tname)) + return PCB_TERM_ERR_INVALID_NAME; + + return PCB_TERM_ERR_SUCCESS; +} + +pcb_term_err_t pcb_term_add(htsp_t *terminals, const char *tname, pcb_any_obj_t *obj) +{ + htsp_entry_t *e; + vtp0_t *v; + + if (obj->term != NULL) + return PCB_TERM_ERR_ALREADY_TERMINAL; + + if (term_name_invalid(tname)) + return PCB_TERM_ERR_INVALID_NAME; + + e = htsp_getentry(terminals, tname); + if (e == NULL) { + /* allocate new terminal */ + tname = pcb_strdup(tname); + v = malloc(sizeof(vtp0_t)); + vtp0_init(v); + htsp_set(terminals, (char *)tname, v); + } + else { + /* need to use the ones from the hash to avoid extra allocation/leak */ + v = e->value; + tname = e->key; + } + + obj->term = tname; + vtp0_append(v, obj); + + return PCB_TERM_ERR_SUCCESS; +} + +pcb_term_err_t pcb_term_del(htsp_t *terminals, pcb_any_obj_t *obj) +{ + vtp0_t *v; + size_t n; + + if (obj->term == NULL) + return PCB_TERM_ERR_NOT_IN_TERMINAL; + + v = htsp_get(terminals, obj->term); + if (v == NULL) + return PCB_TERM_ERR_TERM_NOT_FOUND; + + for(n = 0; n < v->used; n++) { + if (v->array[n] == obj) { + vtp0_remove(v, n, 1); + if (v->used == 0) + pcb_term_remove(terminals, obj->term); + obj->term = NULL; + return PCB_TERM_ERR_SUCCESS; + } + } + + return PCB_TERM_ERR_NOT_IN_TERMINAL; +} + +static pcb_term_err_t pcb_term_remove_entry(htsp_t *terminals, htsp_entry_t *e) +{ + vtp0_t *v = e->value; + char *name = e->key; + size_t n; + + /* unlink all objects from this terminal */ + for(n = 0; n < v->used; n++) { + pcb_any_obj_t *obj = v->array[n]; + obj->term = NULL; + } + + htsp_delentry(terminals, e); + free(name); + vtp0_uninit(v); + free(v); + + return PCB_TERM_ERR_SUCCESS; +} + +pcb_term_err_t pcb_term_remove(htsp_t *terminals, const char *tname) +{ + htsp_entry_t *e; + + e = htsp_getentry(terminals, tname); + if (e == NULL) + return PCB_TERM_ERR_TERM_NOT_FOUND; + + return pcb_term_remove_entry(terminals, e); +} + +pcb_term_err_t pcb_term_init(htsp_t *terminals) +{ + htsp_init(terminals, strhash, strkeyeq); + return PCB_TERM_ERR_SUCCESS; +} + +pcb_term_err_t pcb_term_uninit(htsp_t *terminals) +{ + htsp_entry_t *e; + + for (e = htsp_first(terminals); e; e = htsp_next(terminals, e)) + pcb_term_remove_entry(terminals, e); + htsp_uninit(terminals); + return PCB_TERM_ERR_SUCCESS; +} + +/*** undoable term rename ***/ + +typedef struct { + pcb_any_obj_t *obj; + pcb_flag_t Flags; + char str[1]; /* must be the last item, spans longer than 1 */ +} term_rename_t; + +static int undo_term_rename_swap(void *udata) +{ + char *old_term = NULL; + pcb_subc_t *subc; + term_rename_t *r = udata; + int res = 0; + pcb_flag_t ftmp; + + subc = pcb_obj_parent_subc(r->obj); + if (subc == NULL) { + pcb_message(PCB_MSG_ERROR, "Undo error: terminal rename: object %ld not part of a terminal\n", r->obj->ID); + return -1; + } + + /* remove from previous terminal */ + if (r->obj->term != NULL) { + old_term = pcb_strdup(r->obj->term); + res |= pcb_term_del(&subc->terminals, r->obj); + pcb_obj_invalidate_label(r->obj->type, r->obj->parent.any, r->obj, r->obj); + r->obj->term = NULL; + } + + /* add to new terminal */ + if (*r->str != '\0') { + res |= pcb_term_add(&subc->terminals, r->str, r->obj); + pcb_obj_invalidate_label(r->obj->type, r->obj->parent.any, r->obj, r->obj); + } + + /* swap name: redo & undo are symmetric; we made sure to have enough room for either old or new name */ + if (old_term == NULL) + *r->str = '\0'; + else + strcpy(r->str, old_term); + + free(old_term); + + /* swap flags: redo & undo are symmetric */ + ftmp = r->obj->Flags; + r->obj->Flags = r->Flags; + r->Flags = ftmp; + + /* Update the attributes */ + if (r->obj->term != NULL) + pcb_attribute_put(&r->obj->Attributes, "term", r->obj->term); + else + pcb_attribute_remove(&r->obj->Attributes, "term"); + + if (r->obj->type == PCB_OBJ_POLY) + pcb_poly_init_clip(r->obj->parent.layer->parent.data, r->obj->parent.layer, (pcb_poly_t *)r->obj); + + return res; +} + +static void undo_term_rename_print(void *udata, char *dst, size_t dst_len) +{ + term_rename_t *r = udata; + pcb_snprintf(dst, dst_len, "term_rename: %s #%ld to '%s'\n", + pcb_obj_type_name(r->obj->type), r->obj->ID, r->str); +} + +static const uundo_oper_t undo_term_rename = { + core_term_cookie, + NULL, /* free */ + undo_term_rename_swap, + undo_term_rename_swap, + undo_term_rename_print +}; + +pcb_term_err_t pcb_term_undoable_rename(pcb_board_t *pcb, pcb_any_obj_t *obj, const char *new_name) +{ + int nname_len = 0, oname_len = 0, len; + term_rename_t *r; + pcb_subc_t *subc; + + if ((new_name == NULL) && (obj->term == NULL)) + return PCB_TERM_ERR_NO_CHANGE; + + if (((new_name != NULL) && (obj->term != NULL)) && (strcmp(new_name, obj->term) == 0)) + return PCB_TERM_ERR_NO_CHANGE; + + subc = pcb_obj_parent_subc(obj); + if (subc == NULL) + return PCB_TERM_ERR_NOT_IN_SUBC; + + if (new_name != NULL) + nname_len = strlen(new_name); + + if (obj->term != NULL) + oname_len = strlen(obj->term); + + len = nname_len > oname_len ? nname_len : oname_len; /* +1 for the terminator is implied by sizeof(->str) */ + + r = pcb_undo_alloc(pcb, &undo_term_rename, sizeof(term_rename_t) + len); + r->obj = obj; + memcpy(r->str, new_name, nname_len+1); + r->Flags = obj->Flags; + PCB_FLAG_CLEAR(PCB_FLAG_CLEARPOLY, r); + undo_term_rename_swap(r); + + if (obj->type == PCB_OBJ_POLY) + pcb_poly_init_clip(obj->parent.layer->parent.data, obj->parent.layer, (pcb_poly_t *)obj); + + pcb_undo_inc_serial(); + return PCB_TERM_ERR_SUCCESS; +} + +#define CHECK_TERM_LY(ob) \ + do { \ + if (PCB_NSTRCMP(term_name, ob->term) == 0) { \ + if (parent_out != NULL) *parent_out = subc; \ + if (gid_out != NULL) *gid_out = pcb_layer_get_group_(layer); \ + return (pcb_any_obj_t *)ob; \ + } \ + } while(0) + +#define CHECK_TERM_GL(ob) \ + do { \ + if (PCB_NSTRCMP(term_name, ob->term) == 0) { \ + if (parent_out != NULL) *parent_out = subc; \ + if (gid_out != NULL) { \ + *gid_out = -1; \ + pcb_layergrp_list(pcb, lyt, gid_out, 1); \ + } \ + return (pcb_any_obj_t *)ob; \ + } \ + } while(0) + +pcb_any_obj_t *pcb_term_find_name(const pcb_board_t *pcb, pcb_data_t *data, pcb_layer_type_t lyt, const char *subc_name, const char *term_name, pcb_subc_t **parent_out, pcb_layergrp_id_t *gid_out) +{ + pcb_subc_t *subc; + pcb_layer_t *layer; + int l; + + if (lyt == 0) + return NULL; + + if ((subc = pcb_subc_by_refdes(data, subc_name)) == NULL) + return NULL; + + if (PCB_FLAG_TEST(PCB_FLAG_NONETLIST, subc)) + return NULL; + + /* search for global objects: padstack */ + if (lyt & (PCB_LYT_COPPER | PCB_LYT_MASK | PCB_LYT_MECH)) { + PCB_PADSTACK_LOOP(subc->data) { + CHECK_TERM_GL(padstack); + } PCB_END_LOOP; + } + + /* search for layer objects */ + layer = subc->data->Layer; + for (l = 0; l < subc->data->LayerN; l++, layer++) { + if ((pcb_layer_flags_(layer) & lyt) == 0) + continue; + PCB_LINE_LOOP(layer) { + CHECK_TERM_LY(line); + } PCB_END_LOOP; + + PCB_ARC_LOOP(layer) { + CHECK_TERM_LY(arc); + } PCB_END_LOOP; + + PCB_POLY_LOOP(layer) { + CHECK_TERM_LY(polygon); + } PCB_END_LOOP; + + + PCB_TEXT_LOOP(layer) { + CHECK_TERM_LY(text); + } PCB_END_LOOP; + } + + return NULL; +} + +#undef CHECK_TERM_LY +#undef CHECK_TERM_GL + Index: tags/2.1.2/src/obj_term.h =================================================================== --- tags/2.1.2/src/obj_term.h (nonexistent) +++ tags/2.1.2/src/obj_term.h (revision 24813) @@ -0,0 +1,91 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2017 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +/* Terminals: within a subcircuit, a terminal is a point of netlist connection. + Subcircuit objects can be tagged to belong to a terminal, by terminal ID + (similar tothe old pin number concept). + + A terminals is a str->ptr hash, keyed by terminal name. Each item is + a vtp0_t vector cotaining one or more pcb_any_obj_t * pointers to the + objects making up that terminal. +*/ + +#ifndef PCB_OBJ_TERM_H +#define PCB_OBJ_TERM_H + +#include +#include +#include "obj_common.h" +#include "layer.h" + +typedef enum pcb_term_err_e { + PCB_TERM_ERR_SUCCESS = 0, + PCB_TERM_ERR_ALREADY_TERMINAL, /* object is already in a terminal, can not be added in another */ + PCB_TERM_ERR_NOT_IN_TERMINAL, /* object is not part of any terminal */ + PCB_TERM_ERR_TERM_NOT_FOUND, + PCB_TERM_ERR_NOT_IN_SUBC, + PCB_TERM_ERR_NO_CHANGE, + PCB_TERM_ERR_INVALID_NAME +} pcb_term_err_t; + +/* any type that can be a temrinal */ +#define PCB_TERM_OBJ_TYPES \ + (PCB_OBJ_LINE | PCB_OBJ_TEXT | PCB_OBJ_POLY | PCB_OBJ_ARC | PCB_OBJ_PSTK | PCB_OBJ_SUBC) + +/* Initialize a clean hash of terminals for a subcircuit */ +pcb_term_err_t pcb_term_init(htsp_t *terminals); + +/* Remove all objects from all terminals and destroy the hash */ +pcb_term_err_t pcb_term_uninit(htsp_t *terminals); + +/* Determines if tname is a valid terminal name */ +pcb_term_err_t pcb_term_name_is_valid(const char *tname); + +/* Add obj to a list of terminals named tname. Sets the term field of obj if + it is unset (else fails). */ +pcb_term_err_t pcb_term_add(htsp_t *terminals, const char *tname, pcb_any_obj_t *obj); + +/* Remove obj from terminal tname. Sets obj's term to NULL. Removes + terminal if it becomes empty. */ +pcb_term_err_t pcb_term_del(htsp_t *terminals, pcb_any_obj_t *obj); + +/* Remove a terminal from, calling pcb_term_del() on all objects in it. */ +pcb_term_err_t pcb_term_remove(htsp_t *terminals, const char *tname); + +/* Returns a vector of (pcb_any_obj_t *) containing all objects for the named + termina. Returns NULL if tname doesn't exist in terminals. */ +#define pcb_term_get(terminals, tname) \ + (vtp0_t *)htsp_get(terminals, (char *)tname) + +/* Rename an object's ->term field in an undoable way */ +pcb_term_err_t pcb_term_undoable_rename(pcb_board_t *pcb, pcb_any_obj_t *obj, const char *new_name); + +/* Look up subc_name/term_name on layers matching lyt. Returns the object + or NULL if not found. If the *out parameters are non-NULL, load them. + Ignores subcircuits marked as nonetlist even if explicitly named. */ +pcb_any_obj_t *pcb_term_find_name(const pcb_board_t *pcb, pcb_data_t *data, pcb_layer_type_t lyt, const char *subc_name, const char *term_name, pcb_subc_t **parent_out, pcb_layergrp_id_t *gid_out); + +#endif Index: tags/2.1.2/src/obj_text.c =================================================================== --- tags/2.1.2/src/obj_text.c (nonexistent) +++ tags/2.1.2/src/obj_text.c (revision 24813) @@ -0,0 +1,1430 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * Copyright (C) 2018 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +/* Drawing primitive: text */ + +#include "config.h" + +#include "rotate.h" +#include "board.h" +#include "data.h" +#include "compat_misc.h" +#include "hid_inlines.h" +#include "undo.h" +#include "polygon.h" +#include "polygon_offs.h" +#include "event.h" +#include "layer.h" + +#include "obj_text.h" +#include "obj_text_op.h" +#include "obj_text_list.h" +#include "obj_poly_draw.h" +#include "obj_arc_draw.h" + +#include "obj_subc_parent.h" +#include "obj_hash.h" + +/* TODO: remove this if draw.c is moved here: */ +#include "draw.h" +#include "obj_line_draw.h" +#include "obj_text_draw.h" +#include "conf_core.h" + +/*** allocation ***/ + +void pcb_text_reg(pcb_layer_t *layer, pcb_text_t *text) +{ + textlist_append(&layer->Text, text); + PCB_SET_PARENT(text, layer, layer); + + if (layer->parent_type == PCB_PARENT_UI) + return; + + assert(layer->parent_type == PCB_PARENT_DATA); + pcb_obj_id_reg(layer->parent.data, text); +} + +void pcb_text_unreg(pcb_text_t *text) +{ + pcb_layer_t *layer = text->parent.layer; + assert(text->parent_type == PCB_PARENT_LAYER); + textlist_remove(text); + if (layer->parent_type != PCB_PARENT_UI) { + assert(layer->parent_type == PCB_PARENT_DATA); + pcb_obj_id_del(layer->parent.data, text); + } + PCB_CLEAR_PARENT(text); +} + +pcb_text_t *pcb_text_alloc_id(pcb_layer_t *layer, long int id) +{ + pcb_text_t *new_obj; + + new_obj = calloc(sizeof(pcb_text_t), 1); + new_obj->ID = id; + new_obj->type = PCB_OBJ_TEXT; + new_obj->Attributes.post_change = pcb_obj_attrib_post_change; + + pcb_text_reg(layer, new_obj); + + return new_obj; +} + +pcb_text_t *pcb_text_alloc(pcb_layer_t *layer) +{ + return pcb_text_alloc_id(layer, pcb_create_ID_get()); +} + +void pcb_text_free(pcb_text_t *text) +{ + pcb_text_unreg(text); + free(text); +} + +/*** utility ***/ + +/* creates a new text on a layer */ +pcb_text_t *pcb_text_new(pcb_layer_t *Layer, pcb_font_t *PCBFont, pcb_coord_t X, pcb_coord_t Y, double rot, int Scale, pcb_coord_t thickness, const char *TextString, pcb_flag_t Flags) +{ + pcb_text_t *text; + + if (TextString == NULL) + return NULL; + + text = pcb_text_alloc(Layer); + if (text == NULL) + return NULL; + + /* copy values, width and height are set by drawing routine + * because at this point we don't know which symbols are available + */ + text->X = X; + text->Y = Y; + text->rot = rot; + text->Flags = Flags; + text->Scale = Scale; + text->thickness = thickness; + text->TextString = pcb_strdup(TextString); + text->fid = PCBFont->id; + + pcb_add_text_on_layer(Layer, text, PCBFont); + + return text; +} + +static pcb_text_t *pcb_text_copy_meta(pcb_text_t *dst, pcb_text_t *src) +{ + if (dst == NULL) + return NULL; + pcb_attribute_copy_all(&dst->Attributes, &src->Attributes); + return dst; +} + +pcb_text_t *pcb_text_dup(pcb_layer_t *dst, pcb_text_t *src) +{ + pcb_text_t *t = pcb_text_new(dst, pcb_font(PCB, src->fid, 1), src->X, src->Y, src->rot, src->Scale, src->thickness, src->TextString, src->Flags); + pcb_text_copy_meta(t, src); + return t; +} + +pcb_text_t *pcb_text_dup_at(pcb_layer_t *dst, pcb_text_t *src, pcb_coord_t dx, pcb_coord_t dy) +{ + pcb_text_t *t = pcb_text_new(dst, pcb_font(PCB, src->fid, 1), src->X+dx, src->Y+dy, src->rot, src->Scale, src->thickness, src->TextString, src->Flags); + pcb_text_copy_meta(t, src); + return t; +} + +void pcb_add_text_on_layer(pcb_layer_t *Layer, pcb_text_t *text, pcb_font_t *PCBFont) +{ + /* calculate size of the bounding box */ + pcb_text_bbox(PCBFont, text); + if (!Layer->text_tree) + Layer->text_tree = pcb_r_create_tree(); + pcb_r_insert_entry(Layer->text_tree, (pcb_box_t *) text); +} + +static int pcb_text_render_str_cb(void *ctx, gds_t *s, const char **input) +{ + const pcb_text_t *text = ctx; + char *end, key[128], *path, *attrs; + size_t len; + + end = strchr(*input, '%'); + len = end - *input; + if (len > sizeof(key)-1) + return -1; + + strncpy(key, *input, len); + key[len] = '\0'; + *input += len+1; + + if ((key[0] == 'a') && (key[1] == '.')) { + const pcb_attribute_list_t *attr = &text->Attributes; + path = key+2; + if ((path[0] == 'p') && (memcmp(path, "parent.", 7) == 0)) { + pcb_data_t *par = text->parent.layer->parent.data; + + if (par == NULL) + attr = NULL; + else if (par->parent_type == PCB_PARENT_SUBC) + attr = &par->parent.subc->Attributes; + else if (par->parent_type == PCB_PARENT_BOARD) + attr = &par->parent.board->Attributes; + else + attr = NULL; + path+=7; + } + if (attr != NULL) { + attrs = pcb_attribute_get(attr, path); + if (attrs != NULL) + gds_append_str(s, attrs); + } + } + return 0; +} + +/* Render the string of a text, doing substitution if needed - don't allocate if there's no subst */ +static unsigned char *pcb_text_render_str(pcb_text_t *text) +{ + unsigned char *res; + + if (!PCB_FLAG_TEST(PCB_FLAG_DYNTEXT, text)) + return (unsigned char *)text->TextString; + + res = (unsigned char *)pcb_strdup_subst(text->TextString, pcb_text_render_str_cb, text, PCB_SUBST_PERCENT | PCB_SUBST_CONF); + if (res == NULL) { + res = (unsigned char *)pcb_strdup(""); + } + else if (*res == '\0') { + free(res); + res = (unsigned char *)pcb_strdup(""); + } + + return res; +} + +int pcb_append_dyntext(gds_t *dst, const pcb_any_obj_t *obj, const char *fmt) +{ + return pcb_subst_append(dst, fmt, pcb_text_render_str_cb, (void *)obj, PCB_SUBST_PERCENT | PCB_SUBST_CONF, 0); +} + +/* Free rendered if it was allocated */ +static void pcb_text_free_str(pcb_text_t *text, unsigned char *rendered) +{ + if ((unsigned char *)text->TextString != rendered) + free(rendered); +} + + +/* creates the bounding box of a text object */ +void pcb_text_bbox(pcb_font_t *FontPtr, pcb_text_t *Text) +{ + pcb_symbol_t *symbol; + unsigned char *s, *rendered = pcb_text_render_str(Text); + int i; + int space; + pcb_coord_t minx, miny, maxx, maxy, tx; + pcb_coord_t min_final_radius; + pcb_coord_t min_unscaled_radius; + pcb_bool first_time = pcb_true; + pcb_poly_t *poly; + double sc = (double)Text->Scale / 100.0; + pcb_xform_mx_t mx = PCB_XFORM_MX_IDENT; + pcb_coord_t cx[4], cy[4]; + + s = rendered; + + if (FontPtr == NULL) + FontPtr = pcb_font(PCB, Text->fid, 1); + + symbol = FontPtr->Symbol; + + minx = miny = maxx = maxy = tx = 0; + + /* Calculate the bounding box based on the larger of the thicknesses + * the text might clamped at on silk or copper layers. + */ + min_final_radius = MAX(conf_core.design.min_wid, conf_core.design.min_slk) / 2; + + /* Pre-adjust the line radius for the fact we are initially computing the + * bounds of the un-scaled text, and the thickness clamping applies to + * scaled text. + */ + min_unscaled_radius = PCB_UNPCB_SCALE_TEXT(min_final_radius, Text->Scale); + + /* calculate size of the bounding box */ + for (; s && *s; s++) { + if (*s <= PCB_MAX_FONTPOSITION && symbol[*s].Valid) { + pcb_line_t *line = symbol[*s].Line; + pcb_arc_t *arc; + for (i = 0; i < symbol[*s].LineN; line++, i++) { + /* Clamp the width of text lines at the minimum thickness. + * NB: Divide 4 in thickness calculation is comprised of a factor + * of 1/2 to get a radius from the center-line, and a factor + * of 1/2 because some stupid reason we render our glyphs + * at half their defined stroke-width. + */ + pcb_coord_t unscaled_radius = MAX(min_unscaled_radius, line->Thickness / 4); + + if (first_time) { + minx = maxx = line->Point1.X; + miny = maxy = line->Point1.Y; + first_time = pcb_false; + } + + minx = MIN(minx, line->Point1.X - unscaled_radius + tx); + miny = MIN(miny, line->Point1.Y - unscaled_radius); + minx = MIN(minx, line->Point2.X - unscaled_radius + tx); + miny = MIN(miny, line->Point2.Y - unscaled_radius); + maxx = MAX(maxx, line->Point1.X + unscaled_radius + tx); + maxy = MAX(maxy, line->Point1.Y + unscaled_radius); + maxx = MAX(maxx, line->Point2.X + unscaled_radius + tx); + maxy = MAX(maxy, line->Point2.Y + unscaled_radius); + } + + for(arc = arclist_first(&symbol[*s].arcs); arc != NULL; arc = arclist_next(arc)) { + pcb_arc_bbox(arc); + maxx = MAX(maxx, arc->bbox_naked.X2); + maxy = MAX(maxy, arc->bbox_naked.Y2); + } + + for(poly = polylist_first(&symbol[*s].polys); poly != NULL; poly = polylist_next(poly)) { + int n; + pcb_point_t *pnt; + for(n = 0, pnt = poly->Points; n < poly->PointN; n++,pnt++) { + maxx = MAX(maxx, pnt->X + tx); + maxy = MAX(maxy, pnt->Y); + } + } + + space = symbol[*s].Delta; + } + else { + pcb_box_t *ds = &FontPtr->DefaultSymbol; + pcb_coord_t w = ds->X2 - ds->X1; + + minx = MIN(minx, ds->X1 + tx); + miny = MIN(miny, ds->Y1); + minx = MIN(minx, ds->X2 + tx); + miny = MIN(miny, ds->Y2); + maxx = MAX(maxx, ds->X1 + tx); + maxy = MAX(maxy, ds->Y1); + maxx = MAX(maxx, ds->X2 + tx); + maxy = MAX(maxy, ds->Y2); + + space = w / 5; + } + tx += symbol[*s].Width + space; + } + + /* it is enough to do the transformations only once, on the raw bounding box */ + pcb_xform_mx_translate(mx, Text->X, Text->Y); + pcb_xform_mx_scale(mx, sc, sc); + if (PCB_FLAG_TEST(PCB_FLAG_ONSOLDER, Text)) + pcb_xform_mx_scale(mx, 1, -1); + pcb_xform_mx_rotate(mx, Text->rot); + + /* calculate the transformed coordinates of all 4 corners of the raw + (non-axis-aligned) bounding box */ + cx[0] = pcb_round(pcb_xform_x(mx, minx, miny)); + cy[0] = pcb_round(pcb_xform_y(mx, minx, miny)); + cx[1] = pcb_round(pcb_xform_x(mx, maxx, miny)); + cy[1] = pcb_round(pcb_xform_y(mx, maxx, miny)); + cx[2] = pcb_round(pcb_xform_x(mx, maxx, maxy)); + cy[2] = pcb_round(pcb_xform_y(mx, maxx, maxy)); + cx[3] = pcb_round(pcb_xform_x(mx, minx, maxy)); + cy[3] = pcb_round(pcb_xform_y(mx, minx, maxy)); + + /* calculate the axis-aligned version */ + Text->bbox_naked.X1 = Text->bbox_naked.X2 = cx[0]; + Text->bbox_naked.Y1 = Text->bbox_naked.Y2 = cy[0]; + pcb_box_bump_point(&Text->bbox_naked, cx[1], cy[1]); + pcb_box_bump_point(&Text->bbox_naked, cx[2], cy[2]); + pcb_box_bump_point(&Text->bbox_naked, cx[3], cy[3]); + + /* the bounding box covers the extent of influence + * so it must include the clearance values too + */ + Text->BoundingBox.X1 = Text->bbox_naked.X1 - conf_core.design.bloat; + Text->BoundingBox.Y1 = Text->bbox_naked.Y1 - conf_core.design.bloat; + Text->BoundingBox.X2 = Text->bbox_naked.X2 + conf_core.design.bloat; + Text->BoundingBox.Y2 = Text->bbox_naked.Y2 + conf_core.design.bloat; + pcb_close_box(&Text->bbox_naked); + pcb_close_box(&Text->BoundingBox); + pcb_text_free_str(Text, rendered); +} + +int pcb_text_eq(const pcb_host_trans_t *tr1, const pcb_text_t *t1, const pcb_host_trans_t *tr2, const pcb_text_t *t2) +{ + double rotdir1 = tr1->on_bottom ? -1.0 : 1.0, rotdir2 = tr2->on_bottom ? -1.0 : 1.0; + + if (pcb_neqs(t1->TextString, t2->TextString)) return 0; + if (pcb_neqs(t1->term, t2->term)) return 0; + if (pcb_field_neq(t1, t2, thickness)) return 0; + if (pcb_field_neq(t1, t2, fid)) return 0; + + if (!PCB_FLAG_TEST(PCB_FLAG_FLOATER, t1) && !PCB_FLAG_TEST(PCB_FLAG_FLOATER, t2)) { + if (pcb_field_neq(t1, t2, Scale)) return 0; + if (pcb_neq_tr_coords(tr1, t1->X, t1->Y, tr2, t2->X, t2->Y)) return 0; + if (floor(fmod((t1->rot * rotdir1) + tr1->rot, 360.0)*10000) != floor(fmod((t2->rot * rotdir2) + tr2->rot, 360.0)*10000)) return 0; + } + + return 1; +} + +unsigned int pcb_text_hash(const pcb_host_trans_t *tr, const pcb_text_t *t) +{ + unsigned int crd = 0; + + if (!PCB_FLAG_TEST(PCB_FLAG_FLOATER, t)) { + pcb_coord_t x, y; + double rotdir = tr->on_bottom ? -1.0 : 1.0; + + pcb_hash_tr_coords(tr, &x, &y, t->X, t->Y); + crd = pcb_hash_coord(x) ^ pcb_hash_coord(y) ^ pcb_hash_coord(t->Scale) ^ pcb_hash_angle(tr, t->rot * rotdir); + } + + return pcb_hash_str(t->TextString) ^ pcb_hash_str(t->term) ^ + pcb_hash_coord(t->thickness) ^ (unsigned)t->fid ^ crd; +} + + +/*** ops ***/ +/* copies a text to buffer */ +void *pcb_textop_add_to_buffer(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_text_t *Text) +{ + pcb_layer_t *layer = &ctx->buffer.dst->Layer[pcb_layer_id(ctx->buffer.src, Layer)]; + pcb_text_t *t = pcb_text_new(layer, pcb_font(PCB, Text->fid, 1), Text->X, Text->Y, Text->rot, Text->Scale, Text->thickness, Text->TextString, pcb_flag_mask(Text->Flags, ctx->buffer.extraflg)); + + pcb_text_copy_meta(t, Text); + return t; +} + +/* moves a text without allocating memory for the name between board and buffer */ +void *pcb_textop_move_buffer(pcb_opctx_t *ctx, pcb_layer_t *dstly, pcb_text_t *text) +{ + pcb_layer_t *srcly = text->parent.layer; + + assert(text->parent_type == PCB_PARENT_LAYER); + if ((dstly == NULL) || (dstly == srcly)) /* auto layer in dst */ + dstly = &ctx->buffer.dst->Layer[pcb_layer_id(ctx->buffer.src, srcly)]; + + pcb_r_delete_entry(srcly->text_tree, (pcb_box_t *) text); + pcb_poly_restore_to_poly(ctx->buffer.src, PCB_OBJ_TEXT, srcly, text); + + pcb_text_unreg(text); + pcb_text_reg(dstly, text); + + if (!dstly->text_tree) + dstly->text_tree = pcb_r_create_tree(); + pcb_r_insert_entry(dstly->text_tree, (pcb_box_t *) text); + pcb_poly_clear_from_poly(ctx->buffer.dst, PCB_OBJ_TEXT, dstly, text); + + return text; +} + +/* changes the scaling factor of a text object */ +void *pcb_textop_change_size(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_text_t *Text) +{ + int value = ctx->chgsize.is_absolute ? PCB_COORD_TO_MIL(ctx->chgsize.value) + : Text->Scale + PCB_COORD_TO_MIL(ctx->chgsize.value); + + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, Text)) + return NULL; + if (value <= PCB_MAX_TEXTSCALE && value >= PCB_MIN_TEXTSCALE && value != Text->Scale) { + pcb_undo_add_obj_to_size(PCB_OBJ_TEXT, Layer, Text, Text); + pcb_text_invalidate_erase(Layer, Text); + pcb_r_delete_entry(Layer->text_tree, (pcb_box_t *) Text); + pcb_poly_restore_to_poly(PCB->Data, PCB_OBJ_TEXT, Layer, Text); + Text->Scale = value; + pcb_text_bbox(pcb_font(PCB, Text->fid, 1), Text); + pcb_r_insert_entry(Layer->text_tree, (pcb_box_t *) Text); + pcb_poly_clear_from_poly(PCB->Data, PCB_OBJ_TEXT, Layer, Text); + pcb_text_invalidate_draw(Layer, Text); + return Text; + } + return NULL; +} + +/* changes the thickness of a text object */ +void *pcb_textop_change_2nd_size(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_text_t *Text) +{ + int value = ctx->chgsize.is_absolute ? ctx->chgsize.value : Text->thickness + ctx->chgsize.value; + + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, Text)) + return NULL; + if (value != Text->thickness) { + pcb_undo_add_obj_to_2nd_size(PCB_OBJ_TEXT, Layer, Text, Text); + pcb_text_invalidate_erase(Layer, Text); + pcb_r_delete_entry(Layer->text_tree, (pcb_box_t *) Text); + pcb_poly_restore_to_poly(PCB->Data, PCB_OBJ_TEXT, Layer, Text); + Text->thickness = value; + pcb_text_bbox(pcb_font(PCB, Text->fid, 1), Text); + pcb_r_insert_entry(Layer->text_tree, (pcb_box_t *) Text); + pcb_poly_clear_from_poly(PCB->Data, PCB_OBJ_TEXT, Layer, Text); + pcb_text_invalidate_draw(Layer, Text); + return Text; + } + return NULL; +} + +/* changes the rotation of a text object */ +void *pcb_textop_change_rot(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_text_t *Text) +{ + int value = ctx->chgsize.is_absolute ? ctx->chgsize.value : Text->rot + ctx->chgsize.value; + + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, Text)) + return NULL; + if (value != Text->rot) { + pcb_undo_add_obj_to_rot(PCB_OBJ_TEXT, Layer, Text, Text); + pcb_text_invalidate_erase(Layer, Text); + pcb_r_delete_entry(Layer->text_tree, (pcb_box_t *) Text); + pcb_poly_restore_to_poly(PCB->Data, PCB_OBJ_TEXT, Layer, Text); + Text->rot = value; + pcb_text_bbox(pcb_font(PCB, Text->fid, 1), Text); + pcb_r_insert_entry(Layer->text_tree, (pcb_box_t *) Text); + pcb_poly_clear_from_poly(PCB->Data, PCB_OBJ_TEXT, Layer, Text); + pcb_text_invalidate_draw(Layer, Text); + return Text; + } + return NULL; +} + +/* sets data of a text object and calculates bounding box; memory must have + already been allocated the one for the new string is allocated */ +void *pcb_textop_change_name(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_text_t *Text) +{ + char *old = Text->TextString; + + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, Text)) + return NULL; + pcb_text_invalidate_erase(Layer, Text); + pcb_r_delete_entry(Layer->text_tree, (pcb_box_t *)Text); + pcb_poly_restore_to_poly(PCB->Data, PCB_OBJ_TEXT, Layer, Text); + Text->TextString = ctx->chgname.new_name; + + /* calculate size of the bounding box */ + pcb_text_bbox(pcb_font(PCB, Text->fid, 1), Text); + pcb_r_insert_entry(Layer->text_tree, (pcb_box_t *) Text); + pcb_poly_clear_from_poly(PCB->Data, PCB_OBJ_TEXT, Layer, Text); + pcb_text_invalidate_draw(Layer, Text); + return old; +} + +/* changes the clearance flag of a text */ +void *pcb_textop_change_join(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_text_t *Text) +{ + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, Text)) + return NULL; + pcb_text_invalidate_erase(Layer, Text); + if (PCB_FLAG_TEST(PCB_FLAG_CLEARLINE, Text)) { + pcb_undo_add_obj_to_clear_poly(PCB_OBJ_TEXT, Layer, Text, Text, pcb_false); + pcb_poly_restore_to_poly(PCB->Data, PCB_OBJ_TEXT, Layer, Text); + } + pcb_undo_add_obj_to_flag(Text); + PCB_FLAG_TOGGLE(PCB_FLAG_CLEARLINE, Text); + if (PCB_FLAG_TEST(PCB_FLAG_CLEARLINE, Text)) { + pcb_undo_add_obj_to_clear_poly(PCB_OBJ_TEXT, Layer, Text, Text, pcb_true); + pcb_poly_clear_from_poly(PCB->Data, PCB_OBJ_TEXT, Layer, Text); + } + pcb_text_invalidate_draw(Layer, Text); + return Text; +} + +/* sets the clearance flag of a text */ +void *pcb_textop_set_join(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_text_t *Text) +{ + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, Text) || PCB_FLAG_TEST(PCB_FLAG_CLEARLINE, Text)) + return NULL; + return pcb_textop_change_join(ctx, Layer, Text); +} + +/* clears the clearance flag of a text */ +void *pcb_textop_clear_join(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_text_t *Text) +{ + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, Text) || !PCB_FLAG_TEST(PCB_FLAG_CLEARLINE, Text)) + return NULL; + return pcb_textop_change_join(ctx, Layer, Text); +} + +/* copies a text */ +void *pcb_textop_copy(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_text_t *Text) +{ + pcb_text_t *text; + + text = pcb_text_new(Layer, pcb_font(PCB, Text->fid, 1), Text->X + ctx->copy.DeltaX, + Text->Y + ctx->copy.DeltaY, Text->rot, Text->Scale, Text->thickness, Text->TextString, pcb_flag_mask(Text->Flags, PCB_FLAG_FOUND)); + pcb_text_copy_meta(text, Text); + pcb_text_invalidate_draw(Layer, text); + pcb_undo_add_obj_to_create(PCB_OBJ_TEXT, Layer, text, text); + return text; +} + +/* moves a text object */ +void *pcb_textop_move_noclip(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_text_t *Text) +{ + if (Layer->meta.real.vis) { + pcb_text_invalidate_erase(Layer, Text); + pcb_text_move(Text, ctx->move.dx, ctx->move.dy); + pcb_text_invalidate_draw(Layer, Text); + } + else + pcb_text_move(Text, ctx->move.dx, ctx->move.dy); + return Text; +} + +void *pcb_textop_move(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_text_t *Text) +{ + pcb_r_delete_entry(Layer->text_tree, (pcb_box_t *) Text); + pcb_poly_restore_to_poly(PCB->Data, PCB_OBJ_TEXT, Layer, Text); + pcb_textop_move_noclip(ctx, Layer, Text); + pcb_r_insert_entry(Layer->text_tree, (pcb_box_t *) Text); + pcb_poly_clear_from_poly(PCB->Data, PCB_OBJ_TEXT, Layer, Text); + return Text; +} + +void *pcb_textop_clip(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_text_t *Text) +{ + if (ctx->clip.restore) { + pcb_r_delete_entry(Layer->text_tree, (pcb_box_t *) Text); + pcb_poly_restore_to_poly(PCB->Data, PCB_OBJ_TEXT, Layer, Text); + } + if (ctx->clip.clear) { + pcb_r_insert_entry(Layer->text_tree, (pcb_box_t *) Text); + pcb_poly_clear_from_poly(PCB->Data, PCB_OBJ_TEXT, Layer, Text); + } + return Text; +} + + +/* moves a text object between layers; lowlevel routines */ +void *pcb_textop_move_to_layer_low(pcb_opctx_t *ctx, pcb_layer_t * Source, pcb_text_t * text, pcb_layer_t * Destination) +{ + pcb_poly_restore_to_poly(PCB->Data, PCB_OBJ_TEXT, Source, text); + pcb_r_delete_entry(Source->text_tree, (pcb_box_t *) text); + + pcb_text_unreg(text); + pcb_text_reg(Destination, text); + + if (pcb_layer_flags_(Destination) & PCB_LYT_BOTTOM) + PCB_FLAG_SET(PCB_FLAG_ONSOLDER, text); /* get the text mirrored on display */ + else + PCB_FLAG_CLEAR(PCB_FLAG_ONSOLDER, text); + + /* re-calculate the bounding box (it could be mirrored now) */ + pcb_text_bbox(pcb_font(PCB, text->fid, 1), text); + if (!Destination->text_tree) + Destination->text_tree = pcb_r_create_tree(); + pcb_r_insert_entry(Destination->text_tree, (pcb_box_t *) text); + pcb_poly_clear_from_poly(PCB->Data, PCB_OBJ_TEXT, Destination, text); + + return text; +} + +/* moves a text object between layers */ +void *pcb_textop_move_to_layer(pcb_opctx_t *ctx, pcb_layer_t * layer, pcb_text_t * text) +{ + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, text)) { + pcb_message(PCB_MSG_WARNING, "Sorry, text object is locked\n"); + return NULL; + } + if (ctx->move.dst_layer != layer) { + pcb_undo_add_obj_to_move_to_layer(PCB_OBJ_TEXT, layer, text, text); + if (layer->meta.real.vis) + pcb_text_invalidate_erase(layer, text); + text = pcb_textop_move_to_layer_low(ctx, layer, text, ctx->move.dst_layer); + if (ctx->move.dst_layer->meta.real.vis) + pcb_text_invalidate_draw(ctx->move.dst_layer, text); + } + return text; +} + +/* destroys a text from a layer */ +void *pcb_textop_destroy(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_text_t *Text) +{ + free(Text->TextString); + pcb_r_delete_entry(Layer->text_tree, (pcb_box_t *) Text); + + pcb_text_free(Text); + + return NULL; +} + +/* removes a text from a layer */ +void *pcb_textop_remove(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_text_t *Text) +{ + /* erase from screen */ + if (Layer->meta.real.vis) { + pcb_text_invalidate_erase(Layer, Text); + pcb_r_delete_entry(Layer->text_tree, (pcb_box_t *)Text); + } + pcb_undo_move_obj_to_remove(PCB_OBJ_TEXT, Layer, Text, Text); + return NULL; +} + +void *pcb_text_destroy(pcb_layer_t *Layer, pcb_text_t *Text) +{ + void *res; + pcb_opctx_t ctx; + + ctx.remove.pcb = PCB; + ctx.remove.destroy_target = NULL; + + res = pcb_textop_remove(&ctx, Layer, Text); + pcb_draw(); + return res; +} + +/* rotates a text in 90 degree steps; only the bounding box is rotated, + text rotation itself is done by the drawing routines */ +void pcb_text_rotate90(pcb_text_t *Text, pcb_coord_t X, pcb_coord_t Y, unsigned Number) +{ + int number = PCB_FLAG_TEST(PCB_FLAG_ONSOLDER, Text) ? (4 - Number) & 3 : Number; + PCB_COORD_ROTATE90(Text->X, Text->Y, X, Y, Number); + + Text->rot += number*90.0; + if (Text->rot > 360.0) + Text->rot -= 360.0; + else if (Text->rot < 0.0) + Text->rot += 360.0; + + /* can't optimize with box rotation because of closed boxes */ + pcb_text_bbox(pcb_font(PCB, Text->fid, 1), Text); +} + +/* rotates a text; only the bounding box is rotated, + text rotation itself is done by the drawing routines */ +void pcb_text_rotate(pcb_text_t *Text, pcb_coord_t X, pcb_coord_t Y, double cosa, double sina, double rotdeg) +{ + pcb_rotate(&Text->X, &Text->Y, X, Y, cosa, sina); + Text->rot += rotdeg; + if (Text->rot > 360.0) + Text->rot -= 360.0; + else if (Text->rot < 0.0) + Text->rot += 360.0; + + /* can't optimize with box rotation because of closed boxes */ + pcb_text_bbox(pcb_font(PCB, Text->fid, 1), Text); +} + +/* rotates a text object and redraws it */ +void *pcb_textop_rotate90(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_text_t *Text) +{ + pcb_text_invalidate_erase(Layer, Text); + pcb_poly_restore_to_poly(PCB->Data, PCB_OBJ_TEXT, Layer, Text); + if (Layer->text_tree != NULL) + pcb_r_delete_entry(Layer->text_tree, (pcb_box_t *) Text); + pcb_text_rotate90(Text, ctx->rotate.center_x, ctx->rotate.center_y, ctx->rotate.number); + if (Layer->text_tree != NULL) + pcb_r_insert_entry(Layer->text_tree, (pcb_box_t *) Text); + pcb_poly_clear_from_poly(PCB->Data, PCB_OBJ_TEXT, Layer, Text); + pcb_text_invalidate_draw(Layer, Text); + return Text; +} + +void *pcb_textop_rotate(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_text_t *Text) +{ + pcb_text_invalidate_erase(Layer, Text); + pcb_poly_restore_to_poly(PCB->Data, PCB_OBJ_TEXT, Layer, Text); + if (Layer->text_tree != NULL) + pcb_r_delete_entry(Layer->text_tree, (pcb_box_t *) Text); + + if (Text->rot < 0.0) + Text->rot += 360.0; + + pcb_rotate(&Text->X, &Text->Y, ctx->rotate.center_x, ctx->rotate.center_y, ctx->rotate.cosa, ctx->rotate.sina); + if (PCB_FLAG_TEST(PCB_FLAG_ONSOLDER, Text)) + Text->rot -= ctx->rotate.angle; + else + Text->rot += ctx->rotate.angle; + pcb_text_bbox(NULL, Text); + + if (Layer->text_tree != NULL) + pcb_r_insert_entry(Layer->text_tree, (pcb_box_t *) Text); + pcb_poly_clear_from_poly(PCB->Data, PCB_OBJ_TEXT, Layer, Text); + pcb_text_invalidate_draw(Layer, Text); + return Text; +} + +void pcb_text_flip_side(pcb_layer_t *layer, pcb_text_t *text, pcb_coord_t y_offs) +{ + if (layer->text_tree != NULL) + pcb_r_delete_entry(layer->text_tree, (pcb_box_t *) text); + text->X = PCB_SWAP_X(text->X); + text->Y = PCB_SWAP_Y(text->Y) + y_offs; + PCB_FLAG_TOGGLE(PCB_FLAG_ONSOLDER, text); + pcb_text_bbox(pcb_font(PCB, text->fid, 1), text); + if (layer->text_tree != NULL) + pcb_r_insert_entry(layer->text_tree, (pcb_box_t *) text); +} + +void pcb_text_mirror_coords(pcb_layer_t *layer, pcb_text_t *text, pcb_coord_t y_offs) +{ + if (layer->text_tree != NULL) + pcb_r_delete_entry(layer->text_tree, (pcb_box_t *) text); + text->X = PCB_SWAP_X(text->X); + text->Y = PCB_SWAP_Y(text->Y) + y_offs; + pcb_text_bbox(pcb_font(PCB, text->fid, 1), text); + if (layer->text_tree != NULL) + pcb_r_insert_entry(layer->text_tree, (pcb_box_t *) text); +} + +void pcb_text_scale(pcb_text_t *text, double sx, double sy, double sth) +{ + int onbrd = (text->parent.layer != NULL) && (!text->parent.layer->is_bound); + + if (onbrd) + pcb_text_pre(text); + + if (sx != 1.0) + text->X = pcb_round((double)text->X * sx); + + if (sy != 1.0) + text->Y = pcb_round((double)text->Y * sy); + + if ((sx != 1.0) || (sy != 1.0)) + text->Scale = pcb_round((double)text->Scale * (sy+sx)/2.0); + + if ((sth != 1.0) && (text->thickness > 0.0)) + text->thickness = pcb_round((double)text->thickness * sth); + + pcb_text_bbox(pcb_font(PCB, text->fid, 1), text); + if (onbrd) + pcb_text_post(text); +} + + +void pcb_text_set_font(pcb_text_t *text, pcb_font_id_t fid) +{ + pcb_layer_t *layer = text->parent.layer; + + assert(text->parent_type = PCB_PARENT_LAYER); + + pcb_poly_restore_to_poly(PCB->Data, PCB_OBJ_TEXT, layer, text); + pcb_r_delete_entry(layer->text_tree, (pcb_box_t *) text); + text->fid = fid; + pcb_text_bbox(pcb_font(PCB, text->fid, 1), text); + pcb_r_insert_entry(layer->text_tree, (pcb_box_t *) text); + pcb_poly_clear_from_poly(PCB->Data, PCB_OBJ_TEXT, layer, text); +} + +void pcb_text_pre(pcb_text_t *text) +{ + pcb_layer_t *ly = pcb_layer_get_real(text->parent.layer); + if (ly == NULL) + return; + if (ly->text_tree != NULL) + pcb_r_delete_entry(ly->text_tree, (pcb_box_t *)text); + pcb_poly_restore_to_poly(ly->parent.data, PCB_OBJ_TEXT, ly, text); +} + +void pcb_text_post(pcb_text_t *text) +{ + pcb_layer_t *ly = pcb_layer_get_real(text->parent.layer); + if (ly == NULL) + return; + if (ly->text_tree != NULL) + pcb_r_insert_entry(ly->text_tree, (pcb_box_t *)text); + pcb_poly_clear_from_poly(ly->parent.data, PCB_OBJ_TEXT, ly, text); +} + + +void pcb_text_update(pcb_layer_t *layer, pcb_text_t *text) +{ + pcb_data_t *data = layer->parent.data; + pcb_board_t *pcb = pcb_data_get_top(data); + + if (pcb == NULL) + return; + + pcb_poly_restore_to_poly(data, PCB_OBJ_TEXT, layer, text); + pcb_r_delete_entry(layer->text_tree, (pcb_box_t *) text); + pcb_text_bbox(pcb_font(pcb, text->fid, 1), text); + pcb_r_insert_entry(layer->text_tree, (pcb_box_t *) text); + pcb_poly_clear_from_poly(data, PCB_OBJ_TEXT, layer, text); +} + +void pcb_text_flagchg_pre(pcb_text_t *Text, unsigned long flagbits, void **save) +{ + pcb_data_t *data = Text->parent.layer->parent.data; + + *save = NULL; + if ((flagbits & PCB_FLAG_CLEARLINE) || (flagbits & PCB_FLAG_ONSOLDER)) + pcb_poly_restore_to_poly(data, PCB_OBJ_TEXT, Text->parent.layer, Text); + if (flagbits & PCB_FLAG_ONSOLDER) { /* bbox will also change, need to do rtree administration */ + *save = Text->parent.layer; + pcb_r_delete_entry(Text->parent.layer->text_tree, (pcb_box_t *)Text); + } +} + +void pcb_text_flagchg_post(pcb_text_t *Text, unsigned long oldflagbits, void **save) +{ + pcb_data_t *data = Text->parent.layer->parent.data; + pcb_layer_t *orig_layer = *save; + unsigned long newflagbits = Text->Flags.f; + + if ((oldflagbits & PCB_FLAG_DYNTEXT) || (newflagbits & PCB_FLAG_DYNTEXT) || (orig_layer != NULL)) + pcb_text_bbox(pcb_font(PCB, Text->fid, 1), Text); + + if (orig_layer != NULL) + pcb_r_insert_entry(orig_layer->text_tree, (pcb_box_t *)Text); + + if ((newflagbits & PCB_FLAG_CLEARLINE) || (orig_layer != NULL)) + pcb_poly_clear_from_poly(data, PCB_OBJ_TEXT, Text->parent.layer, Text); + + *save = NULL; +} + +void *pcb_textop_change_flag(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_text_t *Text) +{ + void *save; + static pcb_flag_values_t pcb_text_flags = 0; + unsigned long oldflg = Text->Flags.f; + + if (pcb_text_flags == 0) + pcb_text_flags = pcb_obj_valid_flags(PCB_OBJ_TEXT); + + if ((ctx->chgflag.flag & pcb_text_flags) != ctx->chgflag.flag) + return NULL; + if ((ctx->chgflag.flag & PCB_FLAG_TERMNAME) && (Text->term == NULL)) + return NULL; + pcb_undo_add_obj_to_flag(Text); + + pcb_text_flagchg_pre(/*ctx->chgflag.pcb->Data, */Text, ctx->chgflag.flag, &save); + PCB_FLAG_CHANGE(ctx->chgflag.how, ctx->chgflag.flag, Text); + pcb_text_flagchg_post(Text, oldflg, &save); + + return Text; +} + +void *pcb_textop_invalidate_label(pcb_opctx_t *ctx, pcb_layer_t *layer, pcb_text_t *text) +{ + pcb_text_name_invalidate_draw(text); + return text; +} + +void pcb_text_dyn_bbox_update(pcb_data_t *data) +{ + PCB_TEXT_ALL_LOOP(data); { + if (PCB_FLAG_TEST(PCB_FLAG_DYNTEXT, text)) + pcb_text_update(layer, text); + } PCB_ENDALL_LOOP; +} + +/*** draw ***/ + +#define MAX_SIMPLE_POLY_POINTS 256 +static void draw_text_poly(pcb_draw_info_t *info, pcb_poly_t *poly, pcb_xform_mx_t mx, pcb_coord_t xo, int xordraw, int thindraw, pcb_coord_t xordx, pcb_coord_t xordy) +{ + pcb_coord_t x[MAX_SIMPLE_POLY_POINTS], y[MAX_SIMPLE_POLY_POINTS]; + int max, n; + pcb_point_t *p; + + max = poly->PointN; + if (max > MAX_SIMPLE_POLY_POINTS) { + max = MAX_SIMPLE_POLY_POINTS; + } + + /* transform each coordinate */ + for(n = 0, p = poly->Points; n < max; n++,p++) { + x[n] = pcb_round(pcb_xform_x(mx, p->X + xo, p->Y)); + y[n] = pcb_round(pcb_xform_y(mx, p->X + xo, p->Y)); + } + + if ((info != NULL) && (info->xform != NULL) && (info->xform->bloat != 0)) { + pcb_polo_t *p, pp[MAX_SIMPLE_POLY_POINTS]; + double a2, dv; + for(n = 0, p = pp; n < max; n++,p++) { + p->x = x[n]; + p->y = y[n]; + } + pcb_polo_norms(pp, max); + a2 = pcb_polo_2area(pp, max); + if (a2 < 0) + dv = -0.5; + else + dv = 0.5; + pcb_polo_offs(info->xform->bloat*dv, pp, max); + for(n = 0, p = pp; n < max; n++,p++) { + x[n] = pcb_round(p->x); + y[n] = pcb_round(p->y); + } + } + + if (xordraw || thindraw) { + pcb_hid_gc_t gc = xordraw ? pcb_crosshair.GC : pcb_draw_out.fgGC; + for(n = 1, p = poly->Points+1; n < max; n++,p++) + pcb_gui->draw_line(gc, xordx + x[n-1], xordy + y[n-1], xordx + x[n], xordy + y[n]); + pcb_gui->draw_line(gc, xordx + x[0], xordy + y[0], xordx + x[max-1], xordy + y[max-1]); + } + else + pcb_gui->fill_polygon(pcb_draw_out.fgGC, poly->PointN, x, y); +} + +/* Very rough estimation on the full width of the text */ +pcb_coord_t pcb_text_width(pcb_font_t *font, int scale, const unsigned char *string) +{ + pcb_coord_t w = 0; + const pcb_box_t *defaultsymbol; + if (string == NULL) + return 0; + defaultsymbol = &font->DefaultSymbol; + while(*string) { + /* draw lines if symbol is valid and data is present */ + if (*string <= PCB_MAX_FONTPOSITION && font->Symbol[*string].Valid) + w += (font->Symbol[*string].Width + font->Symbol[*string].Delta); + else + w += (defaultsymbol->X2 - defaultsymbol->X1) * 6 / 5; + string++; + } + return PCB_SCALE_TEXT(w, scale); +} + +pcb_coord_t pcb_text_height(pcb_font_t *font, int scale, const unsigned char *string) +{ + pcb_coord_t h; + if (string == NULL) + return 0; + h = font->MaxHeight; + while(*string != '\0') { + if (*string == '\n') + h += font->MaxHeight; + string++; + } + return PCB_SCALE_TEXT(h, scale); +} + + +PCB_INLINE void cheap_text_line(pcb_hid_gc_t gc, pcb_xform_mx_t mx, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2, pcb_coord_t xordx, pcb_coord_t xordy) +{ + pcb_coord_t tx1, ty1, tx2, ty2; + + tx1 = pcb_round(pcb_xform_x(mx, x1, y1)); + ty1 = pcb_round(pcb_xform_y(mx, x1, y1)); + tx2 = pcb_round(pcb_xform_x(mx, x2, y2)); + ty2 = pcb_round(pcb_xform_y(mx, x2, y2)); + + tx1 += xordx; + ty1 += xordy; + tx2 += xordx; + ty2 += xordy; + + pcb_gui->draw_line(gc, tx1, ty1, tx2, ty2); +} + + +/* Decreased level-of-detail: draw only a few lines for the whole text */ +PCB_INLINE int draw_text_cheap(pcb_font_t *font, pcb_xform_mx_t mx, const unsigned char *string, int scale, int xordraw, pcb_coord_t xordx, pcb_coord_t xordy, pcb_text_tiny_t tiny) +{ + pcb_coord_t w, h = PCB_SCALE_TEXT(font->MaxHeight, scale); + if (tiny == PCB_TXT_TINY_HIDE) { + if (h <= pcb_gui->coord_per_pix*6) /* <= 6 pixel high: unreadable */ + return 1; + } + else if (tiny == PCB_TXT_TINY_CHEAP) { + if (h <= pcb_gui->coord_per_pix*2) { /* <= 1 pixel high: draw a single line in the middle */ + w = pcb_text_width(font, scale, string); + if (xordraw) { + cheap_text_line(pcb_crosshair.GC, mx, 0, h/2, w, h/2, xordx, xordy); + } + else { + pcb_hid_set_line_width(pcb_draw_out.fgGC, -1); + pcb_hid_set_line_cap(pcb_draw_out.fgGC, pcb_cap_square); + cheap_text_line(pcb_draw_out.fgGC, mx, 0, h/2, w, h/2, 0, 0); + } + return 1; + } + else if (h <= pcb_gui->coord_per_pix*4) { /* <= 4 pixel high: draw a mirrored Z-shape */ + w = pcb_text_width(font, scale, string); + if (xordraw) { + h /= 4; + cheap_text_line(pcb_crosshair.GC, mx, 0, h, w, h, xordx, xordy); + cheap_text_line(pcb_crosshair.GC, mx, 0, h, w, h*3, xordx, xordy); + cheap_text_line(pcb_crosshair.GC, mx, 0, h*3, w, h*3, xordx, xordy); + } + else { + h /= 4; + pcb_hid_set_line_width(pcb_draw_out.fgGC, -1); + pcb_hid_set_line_cap(pcb_draw_out.fgGC, pcb_cap_square); + cheap_text_line(pcb_draw_out.fgGC, mx, 0, h, w, h, 0, 0); + cheap_text_line(pcb_draw_out.fgGC, mx, 0, h, w, h*3, 0, 0); + cheap_text_line(pcb_draw_out.fgGC, mx, 0, h*3, w, h*3, 0, 0); + } + return 1; + } + } + return 0; +} + +static void pcb_text_draw_string_(pcb_draw_info_t *info, pcb_font_t *font, const unsigned char *string, pcb_coord_t x0, pcb_coord_t y0, int scale, double rotdeg, int mirror, pcb_coord_t thickness, pcb_coord_t min_line_width, int xordraw, pcb_coord_t xordx, pcb_coord_t xordy, pcb_text_tiny_t tiny) +{ + pcb_coord_t x = 0; + pcb_cardinal_t n; + pcb_xform_mx_t mx = PCB_XFORM_MX_IDENT; + double sc = (double)scale / 100.0; + + pcb_xform_mx_translate(mx, x0, y0); + pcb_xform_mx_scale(mx, sc, sc); + if (mirror) + pcb_xform_mx_scale(mx, 1, -1); + pcb_xform_mx_rotate(mx, rotdeg); + + /* Text too small at this zoom level: cheap draw */ + if (tiny != PCB_TXT_TINY_ACCURATE) { + if (draw_text_cheap(font, mx, string, scale, xordraw, xordx, xordy, tiny)) + return; + } + + /* normal draw */ + while (string && *string) { + /* draw lines if symbol is valid and data is present */ + if (*string <= PCB_MAX_FONTPOSITION && font->Symbol[*string].Valid) { + pcb_line_t *line = font->Symbol[*string].Line; + pcb_line_t newline; + pcb_poly_t *p; + pcb_arc_t *a, newarc; + int poly_thin; + + for (n = font->Symbol[*string].LineN; n; n--, line++) { + /* create one line, scale, move, rotate and swap it */ + newline = *line; + newline.Point1.X = pcb_round(pcb_xform_x(mx, line->Point1.X+x, line->Point1.Y)); + newline.Point1.Y = pcb_round(pcb_xform_y(mx, line->Point1.X+x, line->Point1.Y)); + newline.Point2.X = pcb_round(pcb_xform_x(mx, line->Point2.X+x, line->Point2.Y)); + newline.Point2.Y = pcb_round(pcb_xform_y(mx, line->Point2.X+x, line->Point2.Y)); + newline.Thickness = PCB_SCALE_TEXT(newline.Thickness, scale / 2); + + if (newline.Thickness < min_line_width) + newline.Thickness = min_line_width; + if (thickness > 0) + newline.Thickness = thickness; + if (xordraw) + pcb_gui->draw_line(pcb_crosshair.GC, xordx + newline.Point1.X, xordy + newline.Point1.Y, xordx + newline.Point2.X, xordy + newline.Point2.Y); + else + pcb_line_draw_(info, &newline, 0); + } + + /* draw the arcs */ + for(a = arclist_first(&font->Symbol[*string].arcs); a != NULL; a = arclist_next(a)) { + newarc = *a; + + newarc.X = pcb_round(pcb_xform_x(mx, a->X + x, a->Y)); + newarc.Y = pcb_round(pcb_xform_y(mx, a->X + x, a->Y)); + newarc.Height = newarc.Width = PCB_SCALE_TEXT(newarc.Height, scale); + newarc.Thickness = PCB_SCALE_TEXT(newarc.Thickness, scale / 2); + newarc.StartAngle += rotdeg; + if (mirror) { + newarc.StartAngle = PCB_SWAP_ANGLE(newarc.StartAngle); + newarc.Delta = PCB_SWAP_DELTA(newarc.Delta); + } + if (newarc.Thickness < min_line_width) + newarc.Thickness = min_line_width; + if (thickness > 0) + newarc.Thickness = thickness; + if (xordraw) + pcb_gui->draw_arc(pcb_crosshair.GC, xordx + newarc.X, xordy + newarc.Y, newarc.Width, newarc.Height, newarc.StartAngle, newarc.Delta); + else + pcb_arc_draw_(info, &newarc, 0); + } + + /* draw the polygons */ + poly_thin = conf_core.editor.thin_draw || conf_core.editor.wireframe_draw; + for(p = polylist_first(&font->Symbol[*string].polys); p != NULL; p = polylist_next(p)) + draw_text_poly(info, p, mx, x, xordraw, poly_thin, xordx, xordy); + + /* move on to next cursor position */ + x += (font->Symbol[*string].Width + font->Symbol[*string].Delta); + } + else { + /* the default symbol is a filled box */ + pcb_coord_t size = (font->DefaultSymbol.X2 - font->DefaultSymbol.X1) * 6 / 5; + pcb_coord_t px[4], py[4]; + + px[0] = pcb_round(pcb_xform_x(mx, font->DefaultSymbol.X1 + x, font->DefaultSymbol.Y1)); + py[0] = pcb_round(pcb_xform_y(mx, font->DefaultSymbol.X1 + x, font->DefaultSymbol.Y1)); + px[1] = pcb_round(pcb_xform_x(mx, font->DefaultSymbol.X2 + x, font->DefaultSymbol.Y1)); + py[1] = pcb_round(pcb_xform_y(mx, font->DefaultSymbol.X2 + x, font->DefaultSymbol.Y1)); + px[2] = pcb_round(pcb_xform_x(mx, font->DefaultSymbol.X2 + x, font->DefaultSymbol.Y2)); + py[2] = pcb_round(pcb_xform_y(mx, font->DefaultSymbol.X2 + x, font->DefaultSymbol.Y2)); + px[3] = pcb_round(pcb_xform_x(mx, font->DefaultSymbol.X1 + x, font->DefaultSymbol.Y2)); + py[3] = pcb_round(pcb_xform_y(mx, font->DefaultSymbol.X1 + x, font->DefaultSymbol.Y2)); + + /* draw move on to next cursor position */ + if (xordraw || (conf_core.editor.thin_draw || conf_core.editor.wireframe_draw)) { + if (xordraw) { + pcb_gui->draw_line(pcb_crosshair.GC, px[0] + xordx, py[0] + xordy, px[1] + xordx, py[1] + xordy); + pcb_gui->draw_line(pcb_crosshair.GC, px[1] + xordx, py[1] + xordy, px[2] + xordx, py[2] + xordy); + pcb_gui->draw_line(pcb_crosshair.GC, px[2] + xordx, py[2] + xordy, px[3] + xordx, py[3] + xordy); + pcb_gui->draw_line(pcb_crosshair.GC, px[3] + xordx, py[3] + xordy, px[0] + xordx, py[0] + xordy); + } + else { + pcb_gui->draw_line(pcb_draw_out.fgGC, px[0], py[0], px[1], py[1]); + pcb_gui->draw_line(pcb_draw_out.fgGC, px[1], py[1], px[2], py[2]); + pcb_gui->draw_line(pcb_draw_out.fgGC, px[2], py[2], px[3], py[3]); + pcb_gui->draw_line(pcb_draw_out.fgGC, px[3], py[3], px[0], py[0]); + } + } + else { + pcb_gui->fill_polygon(pcb_draw_out.fgGC, 4, px, py); + } + x += size; + } + string++; + } +} + +void pcb_text_draw_string(pcb_draw_info_t *info, pcb_font_t *font, const unsigned char *string, pcb_coord_t x0, pcb_coord_t y0, int scale, double rotdeg, int mirror, pcb_coord_t thickness, pcb_coord_t min_line_width, int xordraw, pcb_coord_t xordx, pcb_coord_t xordy, pcb_text_tiny_t tiny) +{ + pcb_text_draw_string_(info, font, string, x0, y0, scale, rotdeg, mirror, thickness, min_line_width, xordraw, xordx, xordy, tiny); +} + +void pcb_text_draw_string_simple(pcb_font_t *font, const char *string, pcb_coord_t x0, pcb_coord_t y0, int scale, double rotdeg, int mirror, pcb_coord_t thickness, int xordraw, pcb_coord_t xordx, pcb_coord_t xordy) +{ + if (font == NULL) + font = pcb_font(PCB, 0, 0); + + pcb_text_draw_string_(NULL, font, (const unsigned char *)string, x0, y0, scale, rotdeg, mirror, thickness, 0, xordraw, xordx, xordy, PCB_TXT_TINY_CHEAP); +} + + +/* lowlevel drawing routine for text objects */ +static void DrawTextLowLevel_(pcb_draw_info_t *info, pcb_text_t *Text, pcb_coord_t min_line_width, int xordraw, pcb_coord_t xordx, pcb_coord_t xordy, pcb_text_tiny_t tiny) +{ + unsigned char *rendered = pcb_text_render_str(Text); + pcb_text_draw_string_(info, pcb_font(PCB, Text->fid, 1), rendered, Text->X, Text->Y, Text->Scale, Text->rot, PCB_FLAG_TEST(PCB_FLAG_ONSOLDER, Text), Text->thickness, min_line_width, xordraw, xordx, xordy, tiny); + pcb_text_free_str(Text, rendered); +} + +static pcb_bool is_text_term_vert(const pcb_text_t *text) +{ + pcb_coord_t dx, dy; + + dx = text->BoundingBox.X2 - text->BoundingBox.X1; + if (dx < 0) + dx = -dx; + + dy = text->BoundingBox.Y2 - text->BoundingBox.Y1; + if (dy < 0) + dy = -dy; + + return dx < dy; +} + + +void pcb_text_name_invalidate_draw(pcb_text_t *text) +{ + if (text->term != NULL) + pcb_term_label_invalidate((text->BoundingBox.X1 + text->BoundingBox.X2)/2, (text->BoundingBox.Y1 + text->BoundingBox.Y2)/2, + 100.0, is_text_term_vert(text), pcb_true, (pcb_any_obj_t *)text); +} + +void pcb_text_draw_label(pcb_draw_info_t *info, pcb_text_t *text) +{ + if (text->term != NULL) + pcb_term_label_draw(info, (text->BoundingBox.X1 + text->BoundingBox.X2)/2, (text->BoundingBox.Y1 + text->BoundingBox.Y2)/2, + conf_core.appearance.term_label_size, is_text_term_vert(text), pcb_true, (pcb_any_obj_t *)text); +} + + +void pcb_text_draw_(pcb_draw_info_t *info, pcb_text_t *text, pcb_coord_t min_line_width, int allow_term_gfx, pcb_text_tiny_t tiny) +{ + if (delayed_terms_enabled && (text->term != NULL)) { + pcb_draw_delay_obj_add((pcb_any_obj_t *)text); + return; + } + + DrawTextLowLevel_(info, text, min_line_width, 0, 0, 0, tiny); + + if (text->term != NULL) { + if ((allow_term_gfx) && ((pcb_draw_force_termlab) || PCB_FLAG_TEST(PCB_FLAG_TERMNAME, text))) + pcb_draw_delay_label_add((pcb_any_obj_t *)text); + } +} + +static void pcb_text_draw(pcb_draw_info_t *info, pcb_text_t *text, int allow_term_gfx) +{ + int min_silk_line; + unsigned int flg = 0; + const pcb_layer_t *layer = info->layer != NULL ? info->layer : pcb_layer_get_real(text->parent.layer); + + if (layer == NULL) /* if the layer is inbound, e.g. in preview, fall back using the layer recipe */ + layer = text->parent.layer; + + if (PCB_FLAG_TEST(PCB_FLAG_SELECTED, text)) { + if (layer->is_bound) { + const pcb_color_t *color; + PCB_OBJ_COLOR_ON_BOUND_LAYER(color, layer, 1); + pcb_gui->set_color(pcb_draw_out.fgGC, color); + } + else + pcb_gui->set_color(pcb_draw_out.fgGC, &conf_core.appearance.color.selected); + } + else if (PCB_HAS_COLOROVERRIDE(text)) { + pcb_gui->set_color(pcb_draw_out.fgGC, text->override_color); + } + else if (layer->is_bound) { + const pcb_color_t *color; + PCB_OBJ_COLOR_ON_BOUND_LAYER(color, layer, 0); + pcb_gui->set_color(pcb_draw_out.fgGC, color); + } + else + pcb_gui->set_color(pcb_draw_out.fgGC, &layer->meta.real.color); + + if ((!layer->is_bound) && (layer->meta.real.grp >= 0)) + flg = pcb_layergrp_flags(PCB, layer->meta.real.grp); + + if (flg & PCB_LYT_SILK) + min_silk_line = conf_core.design.min_slk; + else + min_silk_line = conf_core.design.min_wid; + + pcb_text_draw_(info, text, min_silk_line, allow_term_gfx, PCB_TXT_TINY_CHEAP); +} + +pcb_r_dir_t pcb_text_draw_callback(const pcb_box_t * b, void *cl) +{ + pcb_text_t *text = (pcb_text_t *) b; + pcb_draw_info_t *info = cl; + + if (pcb_hidden_floater((pcb_any_obj_t*)b)) + return PCB_R_DIR_FOUND_CONTINUE; + + if (!PCB->SubcPartsOn && pcb_lobj_parent_subc(text->parent_type, &text->parent)) + return PCB_R_DIR_FOUND_CONTINUE; + + pcb_text_draw(info, text, 0); + return PCB_R_DIR_FOUND_CONTINUE; +} + +pcb_r_dir_t pcb_text_draw_term_callback(const pcb_box_t * b, void *cl) +{ + pcb_text_t *text = (pcb_text_t *) b; + pcb_draw_info_t *info = cl; + + if (pcb_hidden_floater((pcb_any_obj_t*)b)) + return PCB_R_DIR_FOUND_CONTINUE; + + if (!PCB->SubcPartsOn && pcb_lobj_parent_subc(text->parent_type, &text->parent)) + return PCB_R_DIR_FOUND_CONTINUE; + + pcb_text_draw(info, text, 1); + return PCB_R_DIR_FOUND_CONTINUE; +} + +/* erases a text on a layer */ +void pcb_text_invalidate_erase(pcb_layer_t *Layer, pcb_text_t *Text) +{ + pcb_draw_invalidate(Text); +} + +void pcb_text_invalidate_draw(pcb_layer_t *Layer, pcb_text_t *Text) +{ + pcb_draw_invalidate(Text); +} + +void pcb_text_draw_xor(pcb_text_t *text, pcb_coord_t x, pcb_coord_t y) +{ + DrawTextLowLevel_(NULL, text, 0, 1, x, y, PCB_TXT_TINY_CHEAP); + if ((conf_core.appearance.text_host_bbox) && (text->BoundingBox.X1 != text->BoundingBox.X2)) { + pcb_gui->draw_line(pcb_crosshair.GC, x + text->BoundingBox.X1, y + text->BoundingBox.Y1, x + text->BoundingBox.X1, y + text->BoundingBox.Y2); + pcb_gui->draw_line(pcb_crosshair.GC, x + text->BoundingBox.X1, y + text->BoundingBox.Y1, x + text->BoundingBox.X2, y + text->BoundingBox.Y1); + pcb_gui->draw_line(pcb_crosshair.GC, x + text->BoundingBox.X2, y + text->BoundingBox.Y2, x + text->BoundingBox.X1, y + text->BoundingBox.Y2); + pcb_gui->draw_line(pcb_crosshair.GC, x + text->BoundingBox.X2, y + text->BoundingBox.Y2, x + text->BoundingBox.X2, y + text->BoundingBox.Y1); + } +} + +/*** init ***/ +static const char *text_cookie = "obj_text"; + +/* Recursively update the text objects of data and subcircuits; returns non-zero + if a redraw is needed */ +static int pcb_text_font_chg_data(pcb_data_t *data, pcb_font_id_t fid) +{ + int need_redraw = 0; + + LAYER_LOOP(data, data->LayerN); { + PCB_TEXT_LOOP(layer); { + if (text->fid == fid) { + pcb_text_update(layer, text); + need_redraw = 1; + } + } PCB_END_LOOP; + } PCB_END_LOOP; + + PCB_SUBC_LOOP(data); { + int chg = pcb_text_font_chg_data(subc->data, fid); + if (chg) { + need_redraw = 1; + pcb_r_delete_entry(data->subc_tree, (pcb_box_t *)subc); + pcb_subc_bbox(subc); + pcb_r_insert_entry(data->subc_tree, (pcb_box_t *)subc); + } + } PCB_END_LOOP; + + return need_redraw; +} + +static void pcb_text_font_chg(void *user_data, int argc, pcb_event_arg_t argv[]) +{ + + if ((argc < 2) || (argv[1].type != PCB_EVARG_INT)) + return; + + if (pcb_text_font_chg_data(PCB->Data, argv[1].d.i)) + pcb_gui->invalidate_all(); /* can't just redraw the text, as the old text may have been bigger, before the change! */ + + pcb_trace("font change %d\n", argv[1].d.i); +} + +pcb_bool pcb_text_old_direction(int *dir_out, double rot) +{ + double r; + + r = fmod(rot, 90.0); + + if (dir_out != NULL) { + int d = pcb_round(rot / 90); + if (d < 0) + d += 4; + *dir_out = d; + } + + return (r <= 0.5); +} + +void pcb_text_init(void) +{ + pcb_event_bind(PCB_EVENT_FONT_CHANGED, pcb_text_font_chg, NULL, text_cookie); +} + +void pcb_text_uninit(void) +{ + pcb_event_unbind_allcookie(text_cookie); +} Index: tags/2.1.2/src/obj_text.h =================================================================== --- tags/2.1.2/src/obj_text.h (nonexistent) +++ tags/2.1.2/src/obj_text.h (revision 24813) @@ -0,0 +1,157 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +/* Drawing primitive: text */ + +#ifndef PCB_OBJ_TEXT_H +#define PCB_OBJ_TEXT_H + +#include "obj_common.h" +#include "font.h" +#include + +struct pcb_text_s { + PCB_ANY_PRIMITIVE_FIELDS; + int Scale; /* text scaling in percent */ + pcb_coord_t X, Y; /* origin */ + pcb_font_id_t fid; + char *TextString; /* string */ + pcb_coord_t thickness; /* if non-zero, thickness of line/arc within the font */ + double rot; /* used when Direction is PCB_TEXT_FREEROT */ + gdl_elem_t link; /* a text is in a list of a layer */ +}; + +/* These need to be carefully written to avoid overflows, and return + a Coord type. */ +#define PCB_SCALE_TEXT(COORD,TEXTSCALE) ((pcb_coord_t)pcb_round((COORD) * ((double)(TEXTSCALE) / 100.0))) +#define PCB_UNPCB_SCALE_TEXT(COORD,TEXTSCALE) ((pcb_coord_t)pcb_round((COORD) * (100.0 / (double)(TEXTSCALE)))) + +pcb_text_t *pcb_text_alloc(pcb_layer_t * layer); +pcb_text_t *pcb_text_alloc_id(pcb_layer_t *layer, long int id); +void pcb_text_free(pcb_text_t * data); +pcb_text_t *pcb_text_new(pcb_layer_t *Layer, pcb_font_t *PCBFont, pcb_coord_t X, pcb_coord_t Y, double rot, int Scale, pcb_coord_t thickness, const char *TextString, pcb_flag_t Flags); +pcb_text_t *pcb_text_dup(pcb_layer_t *dst, pcb_text_t *src); +pcb_text_t *pcb_text_dup_at(pcb_layer_t *dst, pcb_text_t *src, pcb_coord_t dx, pcb_coord_t dy); +void *pcb_text_destroy(pcb_layer_t *Layer, pcb_text_t *Text); + + +/* Add objects without creating them or making any "sanity modifications" to them */ +void pcb_add_text_on_layer(pcb_layer_t *Layer, pcb_text_t *text, pcb_font_t *PCBFont); + +void pcb_text_bbox(pcb_font_t *FontPtr, pcb_text_t *Text); +void pcb_text_rotate90(pcb_text_t *Text, pcb_coord_t X, pcb_coord_t Y, unsigned Number); +void pcb_text_rotate(pcb_text_t *Text, pcb_coord_t X, pcb_coord_t Y, double cosa, double sina, double rotdeg); +void pcb_text_scale(pcb_text_t *text, double sx, double sy, double sth); +void pcb_text_flip_side(pcb_layer_t *layer, pcb_text_t *text, pcb_coord_t y_offs); +void pcb_text_mirror_coords(pcb_layer_t *layer, pcb_text_t *text, pcb_coord_t y_offs); /* mirror the coords but do not mirror the text itself (no on-solder) */ +void pcb_text_set_font(pcb_text_t *text, pcb_font_id_t fid); +void pcb_text_update(pcb_layer_t *layer, pcb_text_t *text); + +void pcb_text_reg(pcb_layer_t *layer, pcb_text_t *text); +void pcb_text_unreg(pcb_text_t *text); + +void pcb_text_pre(pcb_text_t *text); +void pcb_text_post(pcb_text_t *text); + +/* Before and after a flag change on text, call these; flagbits should + be the new bits we are changing to; save should be the + address of a local (void *) cache. The calls make sure bbox and rtree + administration are done properly */ +void pcb_text_flagchg_pre(pcb_text_t *Text, unsigned long flagbits, void **save); +void pcb_text_flagchg_post(pcb_text_t *Text, unsigned long oldflagbits, void **save); + +/* Low level draw call for direct rendering on preview */ +void pcb_text_draw_string_simple(pcb_font_t *font, const char *string, pcb_coord_t x0, pcb_coord_t y0, int scale, double rotdeg, int mirror, pcb_coord_t thickness, int xordraw, pcb_coord_t xordx, pcb_coord_t xordy); + +/* Recalculate the bounding box of all dynamic text objects that are + directly under data - useful e.g. on parent attr change */ +void pcb_text_dyn_bbox_update(pcb_data_t *data); + +/* Return the old direction value (n*90 deg rotation) for text rotation value. + Returns false if has a rounding error greater than 0.5 deg */ +pcb_bool pcb_text_old_direction(int *dir_out, double rot); + +/* hash and eq */ +int pcb_text_eq(const pcb_host_trans_t *tr1, const pcb_text_t *t1, const pcb_host_trans_t *tr2, const pcb_text_t *t2); +unsigned int pcb_text_hash(const pcb_host_trans_t *tr, const pcb_text_t *t); + +/* Append dyntext fmt rendered from the perspective of obj */ +int pcb_append_dyntext(gds_t *dst, const pcb_any_obj_t *obj, const char *fmt); + +void pcb_text_init(void); +void pcb_text_uninit(void); + +#define pcb_text_move(t,dx,dy) \ + do { \ + pcb_coord_t __dx__ = (dx), __dy__ = (dy); \ + pcb_text_t *__t__ = (t); \ + PCB_BOX_MOVE_LOWLEVEL(&((__t__)->BoundingBox), __dx__, __dy__); \ + PCB_BOX_MOVE_LOWLEVEL(&((__t__)->bbox_naked), __dx__, __dy__); \ + PCB_MOVE_POINT((__t__)->X, (__t__)->Y, __dx__, __dy__); \ + } while(0) + +/* Determines if text is actually visible */ +#define pcb_text_is_visible(b, l, t) ((l)->meta.real.vis) + +#define PCB_TEXT_LOOP(layer) do { \ + pcb_text_t *text; \ + gdl_iterator_t __it__; \ + textlist_foreach(&(layer)->Text, &__it__, text) { + +#define PCB_TEXT_ALL_LOOP(top) do { \ + pcb_cardinal_t l; \ + pcb_layer_t *layer = (top)->Layer; \ + for (l = 0; l < ((top)->LayerN > 0 ? (top)->LayerN : PCB->Data->LayerN); l++, layer++) \ + { \ + PCB_TEXT_LOOP(layer) + +#define PCB_TEXT_COPPER_LOOP(top) do { \ + pcb_cardinal_t l; \ + pcb_layer_t *layer = (top)->Layer; \ + for (l = 0; l < ((top)->LayerN > 0 ? (top)->LayerN : PCB->Data->LayerN); l++, layer++) \ + { \ + if (!(pcb_layer_flags(PCB, l) & PCB_LYT_COPPER)) continue; \ + PCB_TEXT_LOOP(layer) + +#define PCB_SILK_COPPER_LOOP(top) do { \ + pcb_cardinal_t l; \ + pcb_layer_t *layer = (top)->Layer; \ + for (l = 0; l < ((top)->LayerN > 0 ? (top)->LayerN : PCB->Data->LayerN); l++, layer++) \ + { \ + if (!(pcb_layer_flags(PCB, l) & PCB_LYT_SILK)) continue; \ + PCB_TEXT_LOOP(layer) + +#define PCB_TEXT_VISIBLE_LOOP(board) do { \ + pcb_cardinal_t l; \ + pcb_layer_t *layer = (board)->Data->Layer; \ + for (l = 0; l < ((board)->Data->LayerN > 0 ? (board)->Data->LayerN : PCB->Data->LayerN); l++, layer++) \ + { \ + PCB_TEXT_LOOP(layer); \ + if (pcb_text_is_visible((board), layer, text)) + +#endif Index: tags/2.1.2/src/obj_text_draw.h =================================================================== --- tags/2.1.2/src/obj_text_draw.h (nonexistent) +++ tags/2.1.2/src/obj_text_draw.h (revision 24813) @@ -0,0 +1,58 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +/*** Standard draw of text ***/ + +#include "draw.h" + +/* Include rtree.h for these */ +#ifdef PCB_RTREE_H +pcb_r_dir_t pcb_text_draw_callback(const pcb_box_t * b, void *cl); +pcb_r_dir_t pcb_text_draw_term_callback(const pcb_box_t * b, void *cl); +#endif + +typedef enum pcb_text_tiny_e { /* How to draw text that is too tiny to be readable */ + PCB_TXT_TINY_HIDE, /* do not draw it at all */ + PCB_TXT_TINY_CHEAP, /* draw a cheaper, simplified approximation that shows there's something there */ + PCB_TXT_TINY_ACCURATE /* always draw text accurately, even if it will end up unreadable */ +} pcb_text_tiny_t; + +void pcb_text_draw_(pcb_draw_info_t *info, pcb_text_t *Text, pcb_coord_t min_line_width, int allow_term_gfx, pcb_text_tiny_t tiny); +void pcb_text_invalidate_erase(pcb_layer_t *Layer, pcb_text_t *Text); +void pcb_text_invalidate_draw(pcb_layer_t *Layer, pcb_text_t *Text); +void pcb_text_draw_xor(pcb_text_t *text, pcb_coord_t x, pcb_coord_t y); +void pcb_text_name_invalidate_draw(pcb_text_t *txt); +void pcb_text_draw_label(pcb_draw_info_t *info, pcb_text_t *text); + +/* lowlevel drawing routine for text strings */ +void pcb_text_draw_string(pcb_draw_info_t *info, pcb_font_t *font, const unsigned char *string, pcb_coord_t x0, pcb_coord_t y0, int scale, double rotdeg, int mirror, pcb_coord_t thickness, pcb_coord_t min_line_width, int xordraw, pcb_coord_t xordx, pcb_coord_t xordy, pcb_text_tiny_t tiny); + +/* lowlevel text bounding box calculation */ +pcb_coord_t pcb_text_width(pcb_font_t *font, int scale, const unsigned char *string); +pcb_coord_t pcb_text_height(pcb_font_t *font, int scale, const unsigned char *string); + Index: tags/2.1.2/src/obj_text_list.c =================================================================== --- tags/2.1.2/src/obj_text_list.c (nonexistent) +++ tags/2.1.2/src/obj_text_list.c (revision 24813) @@ -0,0 +1,34 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 2016 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +/* Include these before TDL_DONT_UNDEF to avoid TDL redefs */ +#include "obj_poly_list.h" +#include "obj_arc_list.h" + +#define TDL_DONT_UNDEF +#include "obj_text_list.h" +#include Index: tags/2.1.2/src/obj_text_list.h =================================================================== --- tags/2.1.2/src/obj_text_list.h (nonexistent) +++ tags/2.1.2/src/obj_text_list.h (revision 24813) @@ -0,0 +1,47 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2016 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#ifndef PCB_OBJ_TEXT_LIST_H +#define PCB_OBJ_TEXT_LIST_H + +#include "obj_text.h" + +/* List of Text */ +#define TDL(x) textlist_ ## x +#define TDL_LIST_T textlist_t +#define TDL_ITEM_T pcb_text_t +#define TDL_FIELD link +#define TDL_SIZE_T size_t +#define TDL_FUNC + +#define textlist_foreach(list, iterator, loop_elem) \ + gdl_foreach_((&((list)->lst)), (iterator), (loop_elem)) + + +#include +#include + +#endif Index: tags/2.1.2/src/obj_text_op.h =================================================================== --- tags/2.1.2/src/obj_text_op.h (nonexistent) +++ tags/2.1.2/src/obj_text_op.h (revision 24813) @@ -0,0 +1,54 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +/*** Standard operations on text ***/ + +#include "operation.h" + +void *pcb_textop_add_to_buffer(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_text_t *Text); +void *pcb_textop_move_buffer(pcb_opctx_t *ctx, pcb_layer_t * layer, pcb_text_t * text); +void *pcb_textop_change_size(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_text_t *Text); +void *pcb_textop_change_2nd_size(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_text_t *Text); +void *pcb_textop_change_rot(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_text_t *Text); +void *pcb_textop_change_name(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_text_t *Text); +void *pcb_textop_change_join(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_text_t *Text); +void *pcb_textop_set_join(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_text_t *Text); +void *pcb_textop_clear_join(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_text_t *Text); +void *pcb_textop_copy(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_text_t *Text); +void *pcb_textop_move(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_text_t *Text); +void *pcb_textop_move_noclip(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_text_t *Text); +void *pcb_textop_clip(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_text_t *Text); +void *pcb_textop_move_to_layer_low(pcb_opctx_t *ctx, pcb_layer_t * Source, pcb_text_t * text, pcb_layer_t * Destination); +void *pcb_textop_move_to_layer(pcb_opctx_t *ctx, pcb_layer_t * layer, pcb_text_t * text); +void *pcb_textop_destroy(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_text_t *Text); +void *pcb_textop_remove(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_text_t *Text); +void *pcb_textop_rotate90(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_text_t *Text); +void *pcb_textop_rotate(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_text_t *Text); +void *pcb_textop_change_flag(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_text_t *Text); +void *pcb_textop_invalidate_label(pcb_opctx_t *ctx, pcb_layer_t *layer, pcb_text_t *text); + Index: tags/2.1.2/src/object_act.c =================================================================== --- tags/2.1.2/src/object_act.c (nonexistent) +++ tags/2.1.2/src/object_act.c (revision 24813) @@ -0,0 +1,1053 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * Copyright (C) 1997, 1998, 1999, 2000, 2001 Harry Eaton + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + * + * Old contact info: + * Harry Eaton, 6697 Buttonhole Ct, Columbia, MD 21044, USA + * haceaton@aplcomm.jhuapl.edu + * + */ +#include "config.h" +#include "conf_core.h" + +#include "data.h" +#include "board.h" +#include "tool.h" +#include "change.h" +#include "error.h" +#include "undo.h" +#include "event.h" +#include "funchash_core.h" + +#include "search.h" +#include "draw.h" +#include "move.h" +#include "remove.h" +#include "compat_misc.h" +#include "layer_vis.h" +#include "operation.h" +#include "obj_pstk.h" +#include "macro.h" +#include "rotate.h" +#include "actions.h" + +static const char pcb_acts_Attributes[] = "Attributes(Layout|Layer|Element|Subc)\n" "Attributes(Layer,layername)"; +static const char pcb_acth_Attributes[] = + "Let the user edit the attributes of the layout, current or given\n" + "layer, or selected subcircuit."; +/* DOC: attributes.html */ +static fgw_error_t pcb_act_Attributes(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + int id; + const char *layername; + char *buf; + + PCB_ACT_CONVARG(1, FGW_KEYWORD, Attributes, id = fgw_keyword(&argv[1])); + PCB_ACT_MAY_CONVARG(1, FGW_STR, Attributes, layername = argv[1].val.str); + PCB_ACT_IRES(0); + + if (!pcb_gui->edit_attributes) { + pcb_message(PCB_MSG_ERROR, "This GUI doesn't support Attribute Editing\n"); + return FGW_ERR_UNKNOWN; + } + + switch(id) { + case F_Layout: + { + pcb_gui->edit_attributes("Layout Attributes", &(PCB->Attributes)); + return 0; + } + + case F_Layer: + { + pcb_layer_t *layer = CURRENT; + if (layername) { + int i; + layer = NULL; + for (i = 0; i < pcb_max_layer; i++) + if (strcmp(PCB->Data->Layer[i].name, layername) == 0) { + layer = &(PCB->Data->Layer[i]); + break; + } + if (layer == NULL) { + pcb_message(PCB_MSG_ERROR, "No layer named %s\n", layername); + return 1; + } + } + pcb_layer_edit_attrib(layer); + return 0; + } + + case F_Element: + case F_Subc: + { + int n_found = 0; + pcb_subc_t *s = NULL; + PCB_SUBC_LOOP(PCB->Data); + { + if (PCB_FLAG_TEST(PCB_FLAG_SELECTED, subc)) { + s = subc; + n_found++; + } + } + PCB_END_LOOP; + if (n_found > 1) { + pcb_message(PCB_MSG_ERROR, "Too many subcircuits selected\n"); + return 1; + } + if (n_found == 0) { + pcb_coord_t x, y; + void *ptrtmp; + pcb_hid_get_coords("Click on a subcircuit", &x, &y, 0); + if ((pcb_search_screen(x, y, PCB_OBJ_SUBC, &ptrtmp, &ptrtmp, &ptrtmp)) != PCB_OBJ_VOID) + s = (pcb_subc_t *)ptrtmp; + else { + pcb_message(PCB_MSG_ERROR, "No subcircuit found there\n"); + PCB_ACT_IRES(-1); + return 0; + } + } + + if (s->refdes != NULL) + buf = pcb_strdup_printf("Subcircuit %s Attributes", s->refdes); + else + buf = pcb_strdup("Unnamed Subcircuit's Attributes"); + + pcb_gui->edit_attributes(buf, &(s->Attributes)); + free(buf); + break; + } + + default: + PCB_ACT_FAIL(Attributes); + } + + return 0; +} + +static const char pcb_acts_DisperseElements[] = "DisperseElements(All|Selected)"; +static const char pcb_acth_DisperseElements[] = "Disperses subcircuits."; + +#define GAP PCB_MIL_TO_COORD(100) + +/* DOC: disperseelements.html */ + +static void disperse_obj(pcb_board_t *pcb, pcb_any_obj_t *obj, pcb_coord_t ox, pcb_coord_t oy, pcb_coord_t *dx, pcb_coord_t *dy, pcb_coord_t *minx, pcb_coord_t *miny, pcb_coord_t *maxy) +{ + pcb_coord_t newx2, newy2; + + /* If we want to disperse selected objects, maybe we need smarter + code here to avoid putting components on top of others which + are not selected. For now, I'm assuming that this is typically + going to be used either with a brand new design or a scratch + design holding some new components */ + + /* figure out how much to move the object */ + *dx = *minx - obj->BoundingBox.X1; + + /* snap to the grid */ + *dx -= (ox + *dx) % pcb->Grid; + + /* and add one grid size so we make sure we always space by GAP or more */ + *dx += pcb->Grid; + + /* Figure out if this row has room. If not, start a new row */ + if (GAP + obj->BoundingBox.X2 + *dx > pcb->MaxWidth) { + *miny = *maxy + GAP; + *minx = GAP; + } + + /* figure out how much to move the object */ + *dx = *minx - obj->BoundingBox.X1; + *dy = *miny - obj->BoundingBox.Y1; + + /* snap to the grid */ + *dx -= (ox + *dx) % pcb->Grid; + *dx += pcb->Grid; + *dy -= (oy + *dy) % pcb->Grid; + *dy += pcb->Grid; + + /* new X2 and Y2 coords with snapping considered */ + newx2 = obj->BoundingBox.X2 + *dx; + newy2 = obj->BoundingBox.Y2 + *dy; + + /* keep track of how tall this row is */ + *minx = newx2 + GAP; + if (*maxy < newy2) { + *maxy = newy2; + if (*maxy > PCB->MaxHeight - GAP) { + *maxy = GAP; + pcb_message(PCB_MSG_WARNING, "The board is too small for hosting all subcircuits,\ndiesperse restarted from the top.\nExpect overlapping subcircuits\n"); + } + } +} + +static fgw_error_t pcb_act_DisperseElements(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + pcb_coord_t minx = GAP, miny = GAP, maxy = GAP, dx, dy; + int all = 0, id; + + PCB_ACT_CONVARG(1, FGW_KEYWORD, DisperseElements, id = fgw_keyword(&argv[1])); + PCB_ACT_IRES(0); + + switch(id) { + case F_All: all = 1; break; + case F_Selected: all = 0; break; + default: PCB_ACT_FAIL(DisperseElements); + } + + pcb_draw_inhibit_inc(); + PCB_SUBC_LOOP(PCB->Data); + { + if (!PCB_FLAG_TEST(PCB_FLAG_LOCK, subc) && (all || PCB_FLAG_TEST(PCB_FLAG_SELECTED, subc))) { + pcb_coord_t ox, oy; + if (pcb_subc_get_origin(subc, &ox, &oy) != 0) { + ox = (subc->BoundingBox.X1 + subc->BoundingBox.X2)/2; + oy = (subc->BoundingBox.Y1 + subc->BoundingBox.Y2)/2; + } + disperse_obj(PCB, (pcb_any_obj_t *)subc, ox, oy, &dx, &dy, &minx, &miny, &maxy); + pcb_move_obj(PCB_OBJ_SUBC, subc, subc, subc, dx, dy); + } + } + PCB_END_LOOP; + pcb_draw_inhibit_dec(); + + /* done with our action so increment the undo # */ + pcb_undo_inc_serial(); + + pcb_redraw(); + pcb_board_set_changed_flag(pcb_true); + + return 0; +} + +#undef GAP + +static const char pcb_acts_Flip[] = "Flip(Object|Selected)"; +static const char pcb_acth_Flip[] = "Flip a subcircuit to the opposite side of the board."; +/* DOC: flip.html */ +static fgw_error_t pcb_act_Flip(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + pcb_coord_t x, y; + int id; + void *ptrtmp; + + PCB_ACT_CONVARG(1, FGW_KEYWORD, Flip, id = fgw_keyword(&argv[1])); + PCB_ACT_IRES(0); + + pcb_hid_get_coords("Click on Object or Flip Point", &x, &y, 0); + + switch(id) { + case F_Object: + if ((pcb_search_screen(pcb_crosshair.X, pcb_crosshair.Y, PCB_OBJ_SUBC, &ptrtmp, &ptrtmp, &ptrtmp)) != PCB_OBJ_VOID) { + pcb_subc_t *subc = (pcb_subc_t *)ptrtmp; + pcb_undo_freeze_serial(); + pcb_subc_change_side(subc, 2 * pcb_crosshair.Y - PCB->MaxHeight); + pcb_undo_unfreeze_serial(); + pcb_undo_inc_serial(); + pcb_draw(); + } + break; + case F_Selected: + case F_SelectedElements: + pcb_undo_freeze_serial(); + pcb_selected_subc_change_side(); + pcb_undo_unfreeze_serial(); + pcb_undo_inc_serial(); + pcb_draw(); + break; + default: + PCB_ACT_FAIL(Flip); + } + return 0; +} + +static const char pcb_acts_MoveObject[] = "pcb_move_obj(X,Y,[units])"; +static const char pcb_acth_MoveObject[] = "Moves the object under the crosshair."; +/* DOC: moveobject.html */ +static fgw_error_t pcb_act_MoveObject(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + char *units = NULL, *saved; + fgw_coords_t *nx, *ny; + pcb_coord_t x, y; + void *ptr1, *ptr2, *ptr3; + int type; + + PCB_ACT_MAY_CONVARG(3, FGW_STR, MoveObject, units = argv[3].val.str); + fgw_str2coord_unit_set(saved, units); + PCB_ACT_CONVARG(1, FGW_COORDS, MoveObject, nx = fgw_coords(&argv[1])); + PCB_ACT_CONVARG(2, FGW_COORDS, MoveObject, ny = fgw_coords(&argv[2])); + fgw_str2coord_unit_restore(saved); + + + pcb_hid_get_coords("Select an Object", &x, &y, 0); + + type = pcb_search_screen(pcb_crosshair.X, pcb_crosshair.Y, PCB_MOVE_TYPES, &ptr1, &ptr2, &ptr3); + if (type == PCB_OBJ_VOID) { + pcb_message(PCB_MSG_ERROR, "Nothing found under crosshair\n"); + return 1; + } + + if (nx->absolute[0]) + nx->c[0] -= pcb_crosshair.X; + if (ny->absolute[0]) + ny->c[0] -= pcb_crosshair.Y; + + pcb_event(PCB_EVENT_RUBBER_RESET, NULL); + if (conf_core.editor.rubber_band_mode) + pcb_event(PCB_EVENT_RUBBER_LOOKUP_LINES, "ippp", type, ptr1, ptr2, ptr3); + if (type == PCB_OBJ_SUBC) + pcb_event(PCB_EVENT_RUBBER_LOOKUP_RATS, "ippp", type, ptr1, ptr2, ptr3); + pcb_move_obj_and_rubberband(type, ptr1, ptr2, ptr3, nx->c[0], ny->c[0]); + pcb_board_set_changed_flag(pcb_true); + + PCB_ACT_IRES(0); + return 0; +} + +static const char pcb_acts_MoveToCurrentLayer[] = "MoveToCurrentLayer(Object|SelectedObjects)"; +static const char pcb_acth_MoveToCurrentLayer[] = "Moves objects to the current layer."; +/* DOC: movetocurrentlayer.html */ +static fgw_error_t pcb_act_MoveToCurrentLayer(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + int id; + + PCB_ACT_CONVARG(1, FGW_KEYWORD, MoveToCurrentLayer, id = fgw_keyword(&argv[1])); + PCB_ACT_IRES(0); + + switch(id) { + case F_Object: + { + pcb_coord_t x, y; + int type; + void *ptr1, *ptr2, *ptr3; + + pcb_hid_get_coords("Select an Object", &x, &y, 0); + if ((type = pcb_search_screen(x, y, PCB_MOVETOLAYER_TYPES | PCB_LOOSE_SUBC, &ptr1, &ptr2, &ptr3)) != PCB_OBJ_VOID) { + pcb_layer_t *target = CURRENT; + pcb_any_obj_t *o = ptr2; + + /* if object is part of a subc (must be a floater!), target layer + shall be within the subc too else we would move out the object from + under the subc to under the board as an unwanted side effect */ + if ((o->parent_type == PCB_PARENT_LAYER) && (o->parent.layer->parent.data->parent_type == PCB_PARENT_SUBC)) { + pcb_subc_t *subc= o->parent.layer->parent.data->parent.subc; + pcb_layer_type_t lyt = pcb_layer_flags_(CURRENT); + int old_len = subc->data->LayerN; + target = pcb_subc_get_layer(subc, lyt, CURRENT->comb, 1, CURRENT->name, 0); + if (target == NULL) { + pcb_message(PCB_MSG_ERROR, "Failed to find or allocate the matching subc layer\n"); + break; + } + if (old_len != subc->data->LayerN) + pcb_subc_rebind(PCB, subc); /* had to alloc a new layer */ + } + if (pcb_move_obj_to_layer(type, ptr1, ptr2, ptr3, target, pcb_false)) + pcb_board_set_changed_flag(pcb_true); + } + break; + } + + case F_SelectedObjects: + case F_Selected: + if (pcb_move_selected_objs_to_layer(CURRENT)) + pcb_board_set_changed_flag(pcb_true); + break; + } + return 0; +} + +static const char pcb_acts_ElementList[] = "ElementList(Start|Done|Need,,,)"; +static const char pcb_acth_ElementList[] = "Adds the given element if it doesn't already exist."; +/* DOC: elementlist.html */ +static int number_of_footprints_not_found; + +static int parse_layout_attribute_units(const char *name, int def) +{ + const char *as = pcb_attrib_get(PCB, name); + if (!as) + return def; + return pcb_get_value(as, NULL, NULL, NULL); +} + +static int subc_differs(pcb_subc_t *sc, const char *expect_name) +{ + const char *got_name = pcb_attribute_get(&sc->Attributes, "footprint"); + if ((expect_name != NULL) && (*expect_name == '\0')) + expect_name = NULL; + if ((got_name != NULL) && (*got_name == '\0')) + got_name = NULL; + if ((got_name == NULL) && (expect_name == NULL)) + return 0; + if ((got_name == NULL) || (expect_name == NULL)) + return 1; + return strcmp(got_name, expect_name); +} + +static fgw_error_t pcb_act_ElementList(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + int op; + pcb_subc_t *sc; + const char *refdes, *value, *footprint; + fgw_arg_t rs, args[4]; + int fx, fy, fs; + + PCB_ACT_CONVARG(1, FGW_KEYWORD, ElementList, op = fgw_keyword(&argv[1])); + +#ifdef DEBUG + printf("Entered pcb_act_ElementList, executing function %s\n", function); +#endif + + if (op == F_Start) { + PCB_SUBC_LOOP(PCB->Data); + { + PCB_FLAG_CLEAR(PCB_FLAG_FOUND, subc); + } + PCB_END_LOOP; + number_of_footprints_not_found = 0; + return 0; + } + + if (op == F_Done) { + PCB_SUBC_LOOP(PCB->Data); + { + if (PCB_FLAG_TEST(PCB_FLAG_FOUND, subc)) { + PCB_FLAG_CLEAR(PCB_FLAG_FOUND, subc); + } + else if (!PCB_EMPTY_STRING_P(subc->refdes)) { + /* Unnamed elements should remain untouched */ + PCB_FLAG_SET(PCB_FLAG_SELECTED, subc); + } + } + PCB_END_LOOP; + if ((number_of_footprints_not_found > 0) && (!conf_core.rc.quiet)) + pcb_message(PCB_MSG_ERROR, "Footprint import: not all requested footprints were found.\nSee the message log above for details\n"); + return 0; + } + + if (op != F_Need) + PCB_ACT_FAIL(ElementList); + + PCB_ACT_CONVARG(2, FGW_STR, ElementList, refdes = argv[2].val.str); + PCB_ACT_CONVARG(3, FGW_STR, ElementList, footprint = argv[3].val.str); + PCB_ACT_CONVARG(4, FGW_STR, ElementList, value = argv[4].val.str); + + args[0].type = FGW_FUNC; + args[0].val.func = NULL; + args[1] = argv[3]; + args[2] = argv[2]; + args[3] = argv[4]; + argc = 4; + + /* turn of flip to avoid mirror/rotat confusion */ + fx = conf_core.editor.view.flip_x; + fy = conf_core.editor.view.flip_y; + fs = conf_core.editor.show_solder_side; + conf_force_set_bool(conf_core.editor.view.flip_x, 0); + conf_force_set_bool(conf_core.editor.view.flip_y, 0); + conf_force_set_bool(conf_core.editor.show_solder_side, 0); + +#ifdef DEBUG + printf(" ... footprint = %s\n", footprint); + printf(" ... refdes = %s\n", refdes); + printf(" ... value = %s\n", value); +#endif + + sc = pcb_subc_by_refdes(PCB->Data, refdes); + + if (sc == NULL) { + pcb_coord_t nx, ny, d; + +#ifdef DEBUG + printf(" ... Footprint not on board, need to add it.\n"); +#endif + /* Not on board, need to add it. */ + if (PCB_ACT_CALL_C(pcb_act_LoadFootprint, &rs, argc, args) != 0) { + number_of_footprints_not_found++; + PCB_ACT_IRES(1); + return 0; + } + + nx = PCB->MaxWidth / 2; + ny = PCB->MaxHeight / 2; + d = MIN(PCB->MaxWidth, PCB->MaxHeight) / 10; + + nx = parse_layout_attribute_units("import::newX", nx); + ny = parse_layout_attribute_units("import::newY", ny); + d = parse_layout_attribute_units("import::disperse", d); + + if (d > 0) { + nx += pcb_rand() % (d * 2) - d; + ny += pcb_rand() % (d * 2) - d; + } + + if (nx < 0) + nx = 0; + if (nx >= PCB->MaxWidth) + nx = PCB->MaxWidth - 1; + if (ny < 0) + ny = 0; + if (ny >= PCB->MaxHeight) + ny = PCB->MaxHeight - 1; + + /* Place components onto center of board. */ + pcb_crosshair.Y = ny; /* flipping side depends on the crosshair unfortunately */ + if (pcb_buffer_copy_to_layout(PCB, nx, ny)) + pcb_board_set_changed_flag(pcb_true); + } + else if (sc && subc_differs(sc, footprint)) { +#ifdef DEBUG + printf(" ... Footprint on board, but different from footprint loaded.\n"); +#endif + int orig_on_top, paste_ok = 0; + pcb_coord_t orig_cx, orig_cy; + double orig_rot; + + /* Different footprint, we need to swap them out. */ + if (PCB_ACT_CALL_C(pcb_act_LoadFootprint, &rs, argc, args) != 0) { + number_of_footprints_not_found++; + PCB_ACT_IRES(1); + return 0; + } + + { + orig_rot = 0.0; + orig_cx = 0; + orig_cy = 0; + orig_on_top = 0; + pcb_subc_get_rotation(sc, &orig_rot); + pcb_subc_get_origin(sc, &orig_cx, &orig_cy); + pcb_subc_get_side(sc, &orig_on_top); + orig_on_top = !orig_on_top; + } + + { + /* replace with subc */ + pcb_subc_t *psc; + psc = pcb_subclist_first(&(PCB_PASTEBUFFER->Data->subc)); + if (psc != NULL) { + pcb_coord_t pcx = 0, pcy = 0; + pcb_subc_get_origin(psc, &pcx, &pcy); + if (!orig_on_top) + pcb_subc_change_side(psc, pcy * 2 - PCB->MaxHeight); + if (orig_rot != 0) { + double cosa, sina; + cosa = cos(orig_rot / PCB_RAD_TO_DEG); + sina = sin(orig_rot / PCB_RAD_TO_DEG); + pcb_subc_rotate(psc, pcx, pcy, cosa, sina, orig_rot); + } + +/* Not needed anymore: pcb_buffer_copy_to_layout solves this + pcb_opctx_t op; + op.move.pcb = PCB; + op.move.dx = orig_cx; + op.move.dy = orig_cy; + op.move.dst_layer = NULL; + op.move.more_to_come = pcb_true; + pcb_subcop_move(&op, psc); +*/ + paste_ok = 1; + } + } + + if (paste_ok) { + if (sc != NULL) + pcb_subc_remove(sc); + if (pcb_buffer_copy_to_layout(PCB, orig_cx, orig_cy)) + pcb_board_set_changed_flag(pcb_true); + } + } + + /* Now reload footprint */ + sc = pcb_subc_by_refdes(PCB->Data, refdes); + if (sc != NULL) { +/* pcb_attribute_put(&sc->Attributes, "refdes", refdes);*/ + pcb_attribute_put(&sc->Attributes, "value", value); + PCB_FLAG_SET(PCB_FLAG_FOUND, sc); + } + +#ifdef DEBUG + printf(" ... Leaving pcb_act_ElementList.\n"); +#endif + + conf_force_set_bool(conf_core.editor.view.flip_x, fx); + conf_force_set_bool(conf_core.editor.view.flip_y, fy); + conf_force_set_bool(conf_core.editor.show_solder_side, fs); + + PCB_ACT_IRES(0); + return 0; +} + +static const char pcb_acts_ElementSetAttr[] = "ElementSetAttr(refdes,name[,value])"; +static const char pcb_acth_ElementSetAttr[] = "Sets or clears an element-specific attribute."; +/* DOC: elementsetattr */ +static fgw_error_t pcb_act_ElementSetAttr(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + pcb_subc_t *sc; + const char *refdes, *name, *value; + + PCB_ACT_CONVARG(1, FGW_STR, ElementList, refdes = argv[1].val.str); + PCB_ACT_CONVARG(2, FGW_STR, ElementList, name = argv[2].val.str); + PCB_ACT_MAY_CONVARG(3, FGW_STR, ElementList, value = argv[3].val.str); + + sc = pcb_subc_by_refdes(PCB->Data, refdes); + if (sc == NULL) { + pcb_message(PCB_MSG_ERROR, "Can't find subcircuit with refdes '%s'\n", refdes); + PCB_ACT_IRES(1); + return 0; + } + + if (value != NULL) + pcb_attribute_put(&sc->Attributes, name, value); + else + pcb_attribute_remove(&sc->Attributes, name); + + PCB_ACT_IRES(0); + return 0; +} + +static const char pcb_acts_RipUp[] = "RipUp(All|Selected|Element)"; +static const char pcb_acth_RipUp[] = "Ripup auto-routed tracks"; +/* DOC: ripup.html */ +static fgw_error_t pcb_act_RipUp(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + int op; + pcb_bool changed = pcb_false; + + PCB_ACT_CONVARG(1, FGW_KEYWORD, RipUp, op = fgw_keyword(&argv[1])); + + switch(op) { + case F_All: + PCB_LINE_ALL_LOOP(PCB->Data); + { + if (PCB_FLAG_TEST(PCB_FLAG_AUTO, line) && !PCB_FLAG_TEST(PCB_FLAG_LOCK, line)) { + pcb_remove_object(PCB_OBJ_LINE, layer, line, line); + changed = pcb_true; + } + } + PCB_ENDALL_LOOP; + PCB_ARC_ALL_LOOP(PCB->Data); + { + if (PCB_FLAG_TEST(PCB_FLAG_AUTO, arc) && !PCB_FLAG_TEST(PCB_FLAG_LOCK, arc)) { + pcb_remove_object(PCB_OBJ_ARC, layer, arc, arc); + changed = pcb_true; + } + } + PCB_ENDALL_LOOP; + + PCB_PADSTACK_LOOP(PCB->Data); + { + if (PCB_FLAG_TEST(PCB_FLAG_AUTO, padstack) && !PCB_FLAG_TEST(PCB_FLAG_LOCK, padstack)) { + pcb_remove_object(PCB_OBJ_PSTK, padstack, padstack, padstack); + changed = pcb_true; + } + } + PCB_END_LOOP; + + if (changed) { + pcb_undo_inc_serial(); + pcb_board_set_changed_flag(pcb_true); + } + break; + case F_Selected: + PCB_LINE_VISIBLE_LOOP(PCB->Data); + { + if (PCB_FLAGS_TEST(PCB_FLAG_AUTO | PCB_FLAG_SELECTED, line) + && !PCB_FLAG_TEST(PCB_FLAG_LOCK, line)) { + pcb_remove_object(PCB_OBJ_LINE, layer, line, line); + changed = pcb_true; + } + } + PCB_ENDALL_LOOP; + if (PCB->pstk_on) + PCB_PADSTACK_LOOP(PCB->Data); + { + if (PCB_FLAGS_TEST(PCB_FLAG_AUTO | PCB_FLAG_SELECTED, padstack) + && !PCB_FLAG_TEST(PCB_FLAG_LOCK, padstack)) { + pcb_remove_object(PCB_OBJ_PSTK, padstack, padstack, padstack); + changed = pcb_true; + } + } + PCB_END_LOOP; + if (changed) { + pcb_undo_inc_serial(); + pcb_board_set_changed_flag(pcb_true); + } + break; + } + PCB_ACT_IRES(0); + return 0; +} + +static const char pcb_acts_MinClearGap[] = "MinClearGap(delta)\n" "MinClearGap(Selected, delta)"; +static const char pcb_acth_MinClearGap[] = "Ensures that polygons are a minimum distance from objects."; +/* DOC: mincleargap.html */ +static void minclr(pcb_data_t *data, pcb_coord_t value, int flags) +{ + PCB_SUBC_LOOP(data); + { + if (!PCB_FLAGS_TEST(flags, subc)) + continue; + minclr(subc->data, value, 0); + } + PCB_END_LOOP; + + PCB_PADSTACK_LOOP(data); + { + if (!PCB_FLAGS_TEST(flags, padstack)) + continue; + if (padstack->Clearance < value) { + pcb_chg_obj_clear_size(PCB_OBJ_PSTK, padstack, 0, 0, value, 1); + pcb_undo_restore_serial(); + } + } + PCB_END_LOOP; + + PCB_LINE_ALL_LOOP(data); + { + if (!PCB_FLAGS_TEST(flags, line)) + continue; + if ((line->Clearance != 0) && (line->Clearance < value)) { + pcb_chg_obj_clear_size(PCB_OBJ_LINE, layer, line, 0, value, 1); + pcb_undo_restore_serial(); + } + } + PCB_ENDALL_LOOP; + PCB_ARC_ALL_LOOP(data); + { + if (!PCB_FLAGS_TEST(flags, arc)) + continue; + if ((arc->Clearance != 0) && (arc->Clearance < value)) { + pcb_chg_obj_clear_size(PCB_OBJ_ARC, layer, arc, 0, value, 1); + pcb_undo_restore_serial(); + } + } + PCB_ENDALL_LOOP; + PCB_POLY_ALL_LOOP(data); + { + if (!PCB_FLAGS_TEST(flags, polygon)) + continue; + if ((polygon->Clearance != 0) && (polygon->Clearance < value)) { + pcb_chg_obj_clear_size(PCB_OBJ_POLY, layer, polygon, 0, value, 1); + pcb_undo_restore_serial(); + } + } + PCB_ENDALL_LOOP; +} + +static fgw_error_t pcb_act_MinClearGap(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + const char *function; + const char *delta = NULL; + const char *units = NULL; + pcb_bool absolute; + pcb_coord_t value; + int flags; + + PCB_ACT_CONVARG(1, FGW_STR, MinClearGap, function = argv[1].val.str); + PCB_ACT_MAY_CONVARG(2, FGW_STR, MinClearGap, delta = argv[2].val.str); + PCB_ACT_MAY_CONVARG(3, FGW_STR, MinClearGap, delta = argv[3].val.str); + + if (pcb_strcasecmp(function, "Selected") == 0) + flags = PCB_FLAG_SELECTED; + else { + units = delta; + delta = function; + flags = 0; + } + value = 2 * pcb_get_value(delta, units, &absolute, NULL); + + pcb_undo_save_serial(); + minclr(PCB->Data, value, flags); + pcb_undo_restore_serial(); + pcb_undo_inc_serial(); + PCB_ACT_IRES(0); + return 0; +} + +static const char pcb_acts_MoveLayer[] = "MoveLayer(old,new)\nMoveLayer(lid,group,gid)"; +static const char pcb_acth_MoveLayer[] = "Moves/Creates/Deletes Layers."; +/* DOC: movelayer.html */ +extern pcb_layergrp_id_t pcb_actd_EditGroup_gid; +fgw_error_t pcb_act_MoveLayer(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + const char *a0, *a1; + int old_index, new_index; + + PCB_ACT_CONVARG(1, FGW_STR, MoveLayer, a0 = argv[1].val.str); + PCB_ACT_CONVARG(2, FGW_STR, MoveLayer, a1 = argv[2].val.str); + + if (strcmp(a0, "c") == 0) + old_index = INDEXOFCURRENT; + else + old_index = atoi(a0); + + if (strcmp(a1, "c") == 0) { + new_index = INDEXOFCURRENT; + if (new_index < 0) + new_index = 0; + } + else if (strcmp(a1, "gi") == 0) { + PCB_ACT_IRES(pcb_layer_move(PCB, -1, 0, pcb_actd_EditGroup_gid)); + return 0; + } + else if (strcmp(a1, "ga") == 0) { + PCB_ACT_IRES(pcb_layer_move(PCB, -1, 1, pcb_actd_EditGroup_gid)); + return 0; + } + else if (strcmp(a1, "group") == 0) { + long gid; + PCB_ACT_CONVARG(3, FGW_LONG, MoveLayer, gid = argv[3].val.nat_long); + pcb_layer_move_to_group(PCB, old_index, gid); + PCB_ACT_IRES(0); + return 0; + } + else if (strcmp(a1, "up") == 0) { + new_index = INDEXOFCURRENT - 1; + if (new_index < 0) { + PCB_ACT_IRES(1); + return 0; + } + } + else if (strcmp(a1, "down") == 0) { + new_index = INDEXOFCURRENT + 1; + if (new_index >= pcb_max_layer) { + PCB_ACT_IRES(1); + return 0; + } + } + else if (strncmp(a1, "step", 4) == 0) { + pcb_layer_t *l = CURRENT; + pcb_layergrp_t *g = pcb_get_layergrp(PCB, l->meta.real.grp); + if (g == NULL) { + pcb_message(PCB_MSG_ERROR, "Invalid layer group\n"); + return 1; + } + switch(a1[4]) { + case '+': return pcb_layergrp_step_layer(PCB, g, pcb_layer_id(PCB->Data, l), +1); break; + case '-': return pcb_layergrp_step_layer(PCB, g, pcb_layer_id(PCB->Data, l), -1); break; + } + pcb_message(PCB_MSG_ERROR, "Invalid step direction\n"); + PCB_ACT_IRES(1); + return 0; + } + + else + new_index = atoi(a1); + + if (new_index < 0) { + if (pcb_layer_flags(PCB, old_index) & PCB_LYT_SILK) { + pcb_layer_t *l = pcb_get_layer(PCB->Data, old_index); + pcb_layergrp_t *g = pcb_get_layergrp(PCB, l->meta.real.grp); + if (g->len == 1) { + pcb_message(PCB_MSG_ERROR, "Removing this layer would result in an empty top or bottom silk group, which is not possible at the moment.\n"); + PCB_ACT_IRES(1); + return 0; + } + } + } + + PCB_ACT_IRES(pcb_layer_move(PCB, old_index, new_index, -1)); + return 0; +} + +static const char pcb_acts_CreateText[] = "CreateText(layer, fontID, X, Y, direction, scale, text)\n"; +static const char pcb_acth_CreateText[] = "Create a new text object"; +static fgw_error_t pcb_act_CreateText(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + const char *txt; + pcb_coord_t x, y; + pcb_layer_t *ly; + int fid, dir, scale; + pcb_text_t *t; + + PCB_ACT_CONVARG(1, FGW_LAYER, CreateText, ly = fgw_layer(&argv[1])); + PCB_ACT_CONVARG(2, FGW_INT, CreateText, fid = argv[2].val.nat_int); + PCB_ACT_CONVARG(3, FGW_COORD, CreateText, x = fgw_coord(&argv[3])); + PCB_ACT_CONVARG(4, FGW_COORD, CreateText, y = fgw_coord(&argv[4])); + PCB_ACT_CONVARG(5, FGW_INT, CreateText, dir = argv[5].val.nat_int); + PCB_ACT_CONVARG(6, FGW_INT, CreateText, scale = argv[6].val.nat_int); + PCB_ACT_CONVARG(7, FGW_STR, CreateText, txt = argv[7].val.str); + + if (scale < 1) { + pcb_message(PCB_MSG_ERROR, "Invalid scale (must be larger than zero)\n"); + return 1; + } + + if ((dir < 0) || (dir > 3)) { + pcb_message(PCB_MSG_ERROR, "Invalid direction (must be 0, 1, 2 or 3)\n"); + return 1; + } + + t = pcb_text_new(ly, pcb_font(PCB, fid, 1), x, y, dir, scale, 0, txt, pcb_no_flags()); + res->type = FGW_LONG; + res->val.nat_long = (t == NULL ? -1 : t->ID); + return 0; +} + +static const char pcb_acts_subc[] = + "subc(hash, [board|selected])\n" + "subc(loose, on|off|toggle|check)\n" + ; +static const char pcb_acth_subc[] = "Various operations on subc"; +static fgw_error_t pcb_act_subc(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + int op1, op2 = -2; + + PCB_ACT_CONVARG(1, FGW_KEYWORD, subc, op1 = fgw_keyword(&argv[1])); + PCB_ACT_MAY_CONVARG(2, FGW_KEYWORD, subc, op2 = fgw_keyword(&argv[2])); + PCB_ACT_IRES(0); + + switch(op1) { + case F_Loose: + switch(op2) { + case -2: + case F_Toggle: PCB->loose_subc = !PCB->loose_subc; break; + case F_On: PCB->loose_subc = 1; break; + case F_Off: PCB->loose_subc = 0; break; + case F_Check: PCB_ACT_IRES(PCB->loose_subc); return 0; + default: PCB_ACT_FAIL(subc); return 1; + } + /* have to manually trigger the update as it is not a conf item */ + if ((pcb_gui != NULL) && (pcb_gui->update_menu_checkbox != NULL)) + pcb_gui->update_menu_checkbox(NULL); + return 0; + case F_Hash: + { + int selected_only = 0; + gdl_iterator_t it; + pcb_subc_t *sc; + + switch(op2) { + case -2: break; + case F_Selected: selected_only = 1; break; + default: PCB_ACT_FAIL(subc); return 1; + } + + polylist_foreach(&PCB->Data->subc, &it, sc) { + if (selected_only && !PCB_FLAG_TEST(PCB_FLAG_SELECTED, sc)) + continue; + pcb_message(PCB_MSG_INFO, "subc #%ld (%s): %u\n", sc->ID, (sc->refdes == NULL ? "" : sc->refdes), pcb_subc_hash(sc)); + } + } + break; + case F_Eq: + { + int selected_only = 0; + gdl_iterator_t it; + pcb_subc_t *sc; + vtp0_t *vt; + htip_t hash2scs; /* hash to subcircuit vector */ + htip_entry_t *e; + gds_t str; + + gds_init(&str); + htip_init(&hash2scs, longhash, longkeyeq); + switch(op2) { + case -2: break; + case F_Selected: selected_only = 1; break; + default: PCB_ACT_FAIL(subc); return 1; + } + polylist_foreach(&PCB->Data->subc, &it, sc) { + unsigned int hash; + if (selected_only && !PCB_FLAG_TEST(PCB_FLAG_SELECTED, sc)) + continue; + hash = pcb_subc_hash(sc); + vt = htip_get(&hash2scs, hash); + if (vt == 0) { + vt = calloc(sizeof(vtp0_t), 1); + htip_set(&hash2scs, hash, vt); + } + vtp0_append(vt, sc); + } + + /* print the result */ + for (e = htip_first(&hash2scs); e; e = htip_next(&hash2scs, e)) { + int n; + + vt = e->value; + str.used = 0; + pcb_append_printf(&str, "subc eq %u:", e->key); + for(n = 0; n < vt->used; n++) { + sc = (pcb_subc_t *)vt->array[n]; + pcb_append_printf(&str, " #%ld(%s):%d", sc->ID, (sc->refdes == NULL ? "" : sc->refdes), pcb_subc_eq(sc, (pcb_subc_t*)vt->array[0])); + } + pcb_message(PCB_MSG_INFO, "%s\n", str.array); + vtp0_uninit(vt); + free(vt); + } + gds_uninit(&str); + htip_uninit(&hash2scs); + } + break; + } + + return 0; +} + +static const char pcb_acts_Rotate90[] = "pcb_move_obj(steps)"; +static const char pcb_acth_Rotate90[] = "Rotates the object under the crosshair by 90 degree steps."; +/* DOC: rotate90.html */ +static fgw_error_t pcb_act_Rotate90(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + int steps; + pcb_coord_t x, y; + + PCB_ACT_CONVARG(1, FGW_INT, Rotate90, steps = argv[1].val.nat_int); + PCB_ACT_IRES(0); + + pcb_hid_get_coords("Select an Object", &x, &y, 0); + + if (conf_core.editor.show_solder_side) + steps = -steps; + + steps = steps % 4; + if (steps < 0) + steps = 4+steps; + + pcb_screen_obj_rotate90(x, y, steps); + + return 0; +} + +pcb_action_t object_action_list[] = { + {"Attributes", pcb_act_Attributes, pcb_acth_Attributes, pcb_acts_Attributes}, + {"DisperseElements", pcb_act_DisperseElements, pcb_acth_DisperseElements, pcb_acts_DisperseElements}, + {"Flip", pcb_act_Flip, pcb_acth_Flip, pcb_acts_Flip}, + {"MoveObject", pcb_act_MoveObject, pcb_acth_MoveObject, pcb_acts_MoveObject}, + {"MoveToCurrentLayer", pcb_act_MoveToCurrentLayer, pcb_acth_MoveToCurrentLayer, pcb_acts_MoveToCurrentLayer}, + {"ElementList", pcb_act_ElementList, pcb_acth_ElementList, pcb_acts_ElementList}, + {"ElementSetAttr", pcb_act_ElementSetAttr, pcb_acth_ElementSetAttr, pcb_acts_ElementSetAttr}, + {"RipUp", pcb_act_RipUp, pcb_acth_RipUp, pcb_acts_RipUp}, + {"MinClearGap", pcb_act_MinClearGap, pcb_acth_MinClearGap, pcb_acts_MinClearGap}, + {"MoveLayer", pcb_act_MoveLayer, pcb_acth_MoveLayer, pcb_acts_MoveLayer}, + {"subc", pcb_act_subc, pcb_acth_subc, pcb_acts_subc}, + {"CreateText", pcb_act_CreateText, pcb_acth_CreateText, pcb_acts_CreateText}, + {"Rotate90", pcb_act_Rotate90, pcb_acth_Rotate90, pcb_acts_Rotate90} +}; + +PCB_REGISTER_ACTIONS(object_action_list, NULL) Index: tags/2.1.2/src/operation.c =================================================================== --- tags/2.1.2/src/operation.c (nonexistent) +++ tags/2.1.2/src/operation.c (revision 24813) @@ -0,0 +1,246 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +#include "config.h" + +#include "operation.h" +#include "board.h" +#include "data.h" +#include "conf_core.h" +#include "undo.h" +#include "brave.h" + +/* ---------------------------------------------------------------------- + * performs several operations on the passed object + */ +void *pcb_object_operation(pcb_opfunc_t *F, pcb_opctx_t *ctx, int Type, void *Ptr1, void *Ptr2, void *Ptr3) +{ + switch (Type) { + case PCB_OBJ_LINE: + if (F->Line) + return (F->Line(ctx, (pcb_layer_t *) Ptr1, (pcb_line_t *) Ptr2)); + break; + + case PCB_OBJ_ARC: + if (F->Arc) + return (F->Arc(ctx, (pcb_layer_t *) Ptr1, (pcb_arc_t *) Ptr2)); + break; + + case PCB_OBJ_LINE_POINT: + if (F->LinePoint) + return (F->LinePoint(ctx, (pcb_layer_t *) Ptr1, (pcb_line_t *) Ptr2, (pcb_point_t *) Ptr3)); + break; + + case PCB_OBJ_ARC_POINT: + if (F->ArcPoint) + return (F->ArcPoint(ctx, (pcb_layer_t *) Ptr1, (pcb_arc_t *) Ptr2, (int *) Ptr3)); + break; + + case PCB_OBJ_TEXT: + if (F->Text) + return (F->Text(ctx, (pcb_layer_t *) Ptr1, (pcb_text_t *) Ptr2)); + break; + + case PCB_OBJ_POLY: + if (F->Polygon) + return (F->Polygon(ctx, (pcb_layer_t *) Ptr1, (pcb_poly_t *) Ptr2)); + break; + + case PCB_OBJ_POLY_POINT: + if (F->Point) + return (F->Point(ctx, (pcb_layer_t *) Ptr1, (pcb_poly_t *) Ptr2, (pcb_point_t *) Ptr3)); + break; + + case PCB_OBJ_SUBC: + if (F->subc) + return (F->subc(ctx, (pcb_subc_t *) Ptr2)); + break; + + case PCB_OBJ_PSTK: + if (F->padstack) + return (F->padstack(ctx, (pcb_pstk_t *)Ptr2)); + break; + + case PCB_OBJ_RAT: + if (F->Rat) + return (F->Rat(ctx, (pcb_rat_t *) Ptr2)); + break; + } + return NULL; +} + +/* ---------------------------------------------------------------------- + * performs several operations on selected objects which are also visible + * The lowlevel procedures are passed together with additional information + * resets the selected flag if requested + * returns pcb_true if anything has changed + */ +pcb_bool pcb_selected_operation(pcb_board_t *pcb, pcb_data_t *data, pcb_opfunc_t *F, pcb_opctx_t *ctx, pcb_bool Reset, int type, pcb_bool on_locked_too) +{ + pcb_bool changed = pcb_false; + + if ((pcb_brave & PCB_BRAVE_CLIPBATCH) && (data != NULL)) + pcb_data_clip_inhibit_inc(data); + + /* check lines */ + if (type & PCB_OBJ_LINE && F->Line) { + PCB_LINE_VISIBLE_LOOP(data); + { + if (!PCB_FLAG_TEST(PCB_FLAG_SELECTED, line)) + continue; + if (!on_locked_too && PCB_FLAG_TEST(PCB_FLAG_LOCK, line)) + continue; + if (Reset) { + pcb_undo_add_obj_to_flag(line); + PCB_FLAG_CLEAR(PCB_FLAG_SELECTED, line); + } + F->Line(ctx, layer, line); + changed = pcb_true; + } + PCB_ENDALL_LOOP; + } + + /* check arcs */ + if (type & PCB_OBJ_ARC && F->Arc) { + PCB_ARC_VISIBLE_LOOP(data); + { + if (!PCB_FLAG_TEST(PCB_FLAG_SELECTED, arc)) + continue; + if (!on_locked_too && PCB_FLAG_TEST(PCB_FLAG_LOCK, arc)) + continue; + if (Reset) { + pcb_undo_add_obj_to_flag(arc); + PCB_FLAG_CLEAR(PCB_FLAG_SELECTED, arc); + } + F->Arc(ctx, layer, arc); + changed = pcb_true; + } + PCB_ENDALL_LOOP; + } + + /* check text */ + if (type & PCB_OBJ_TEXT && F->Text) { + PCB_TEXT_ALL_LOOP(data); + { + if (!PCB_FLAG_TEST(PCB_FLAG_SELECTED, text) || !pcb_text_is_visible(PCB, layer, text)) + continue; + if (!on_locked_too && PCB_FLAG_TEST(PCB_FLAG_LOCK, text)) + continue; + if (Reset) { + pcb_undo_add_obj_to_flag(text); + PCB_FLAG_CLEAR(PCB_FLAG_SELECTED, text); + } + F->Text(ctx, layer, text); + changed = pcb_true; + } + PCB_ENDALL_LOOP; + } + + /* check polygons */ + if (type & PCB_OBJ_POLY && F->Polygon) { + PCB_POLY_VISIBLE_LOOP(data); + { + if (!PCB_FLAG_TEST(PCB_FLAG_SELECTED, polygon)) + continue; + if (!on_locked_too && PCB_FLAG_TEST(PCB_FLAG_LOCK, polygon)) + continue; + if (Reset) { + pcb_undo_add_obj_to_flag(polygon); + PCB_FLAG_CLEAR(PCB_FLAG_SELECTED, polygon); + } + F->Polygon(ctx, layer, polygon); + changed = pcb_true; + } + PCB_ENDALL_LOOP; + } + + if ((type & (PCB_OBJ_SUBC | PCB_OBJ_SUBC_PART)) && F->subc) { + PCB_SUBC_LOOP(data); + { + if (!on_locked_too && PCB_FLAG_TEST(PCB_FLAG_LOCK, subc)) + continue; + if (PCB_FLAG_TEST(PCB_FLAG_SELECTED, subc)) { + if (Reset) { + pcb_undo_add_obj_to_flag(subc); + PCB_FLAG_CLEAR(PCB_FLAG_SELECTED, subc); + } + F->subc(ctx, subc); + changed = pcb_true; + } + else if ((pcb->loose_subc) || (type & PCB_OBJ_SUBC_PART)) { + if (pcb_selected_operation(pcb, subc->data, F, ctx, Reset, type, on_locked_too)) + changed = pcb_true; + } + } + PCB_END_LOOP; + } + + /* process padstacks */ + if (type & PCB_OBJ_PSTK && pcb->pstk_on && F->padstack) { + PCB_PADSTACK_LOOP(data); + { + if (!PCB_FLAG_TEST(PCB_FLAG_SELECTED, padstack)) + continue; + if (!on_locked_too && PCB_FLAG_TEST(PCB_FLAG_LOCK, padstack)) + continue; + if (Reset) { + pcb_undo_add_obj_to_flag(padstack); + PCB_FLAG_CLEAR(PCB_FLAG_SELECTED, padstack); + } + F->padstack(ctx, padstack); + changed = pcb_true; + } + PCB_END_LOOP; + } + + /* and rat-lines */ + if (type & PCB_OBJ_RAT && pcb->RatOn && F->Rat) { + PCB_RAT_LOOP(data); + { + if (!PCB_FLAG_TEST(PCB_FLAG_SELECTED, line)) + continue; + if (!on_locked_too && PCB_FLAG_TEST(PCB_FLAG_LOCK, line)) + continue; + if (Reset) { + pcb_undo_add_obj_to_flag(line); + PCB_FLAG_CLEAR(PCB_FLAG_SELECTED, line); + } + F->Rat(ctx, line); + changed = pcb_true; + } + PCB_END_LOOP; + } + + if (Reset && changed) + pcb_undo_inc_serial(); + + if ((pcb_brave & PCB_BRAVE_CLIPBATCH) && (data != NULL)) + pcb_data_clip_inhibit_dec(data, 0); + + return changed; +} Index: tags/2.1.2/src/operation.h =================================================================== --- tags/2.1.2/src/operation.h (nonexistent) +++ tags/2.1.2/src/operation.h (revision 24813) @@ -0,0 +1,153 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996, 2004 Thomas Nau + * 15 Oct 2008 Ineiev: add different crosshair shapes + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +#ifndef PCB_OPERATION_H +#define PCB_OPERATION_H + +#include "global_typedefs.h" + +/* Each object operation gets an operation-context with some operation-specific + configuration, and the board to operate on. Optionally this is the place to + hold temporary states of a multi-call operation too. */ + +typedef struct { + pcb_board_t *pcb; + int extraflg; + pcb_data_t *dst, *src; +} pcb_opctx_buffer_t; + +typedef struct { + pcb_board_t *pcb; + int is_primary; /* whether the primary parameter should be changed */ + pcb_bool is_absolute; + pcb_coord_t value; /* delta or absolute (depending on is_absoulute) */ +} pcb_opctx_chgsize_t; + +typedef struct { + pcb_board_t *pcb; + int is_primary; /* whether the primary parameter should be changed */ + pcb_bool is_absolute; + pcb_angle_t value; /* same as above, but for angles */ +} pcb_opctx_chgangle_t; + +typedef struct { + pcb_board_t *pcb; + char *new_name; +} pcb_opctx_chgname_t; + +typedef struct { + pcb_board_t *pcb; + int style; /* the new bits */ + unsigned long lid; /* the layer to operate on */ +} pcb_opctx_chgtherm_t; + +typedef struct { + pcb_board_t *pcb; + pcb_coord_t DeltaX, DeltaY; /* movement vector */ + int from_outside; +} pcb_opctx_copy_t; + +typedef struct { + pcb_board_t *pcb; + pcb_coord_t x, y; + pcb_cardinal_t idx; /* poly point idx */ + pcb_bool last; + pcb_bool forcible; +} pcb_opctx_insert_t; + +typedef struct { + pcb_board_t *pcb; + pcb_coord_t dx, dy; /* used by local routines as offset */ + pcb_layer_t *dst_layer; + pcb_bool more_to_come; +} pcb_opctx_move_t; + +typedef struct { + pcb_board_t *pcb; + pcb_data_t *destroy_target; +} pcb_opctx_remove_t; + +typedef struct { + pcb_board_t *pcb; + pcb_coord_t center_x, center_y; /* center of rotation */ + unsigned number; /* number of rotations, for 90 deg rotation */ + double cosa, sina, angle; /* for arbitrary angle rotation */ +} pcb_opctx_rotate_t; + +typedef struct { + pcb_board_t *pcb; + unsigned long how; /* pcb_change_flag_t */ + unsigned long flag; /* pcb_flag_values_t */ +} pcb_opctx_chgflag_t; + +typedef struct { + pcb_board_t *pcb; +} pcb_opctx_noarg_t; + +typedef struct { + pcb_board_t *pcb; + int restore; + int clear; +} pcb_opctx_clip_t; + +typedef union { + pcb_opctx_buffer_t buffer; + pcb_opctx_chgname_t chgname; + pcb_opctx_chgsize_t chgsize; + pcb_opctx_chgangle_t chgangle; + pcb_opctx_chgtherm_t chgtherm; + pcb_opctx_copy_t copy; + pcb_opctx_insert_t insert; + pcb_opctx_move_t move; + pcb_opctx_remove_t remove; + pcb_opctx_rotate_t rotate; + pcb_opctx_chgflag_t chgflag; + pcb_opctx_noarg_t noarg; + pcb_opctx_clip_t clip; +} pcb_opctx_t; + +/* pointer to low-level operation (copy, move and rotate) functions */ +typedef struct { + void *(*Line)(pcb_opctx_t *ctx, pcb_layer_t *, pcb_line_t *); + void *(*Text)(pcb_opctx_t *ctx, pcb_layer_t *, pcb_text_t *); + void *(*Polygon)(pcb_opctx_t *ctx, pcb_layer_t *, pcb_poly_t *); +/*5*/ + void *(*LinePoint)(pcb_opctx_t *ctx, pcb_layer_t *, pcb_line_t *, pcb_point_t *); + void *(*Point)(pcb_opctx_t *ctx, pcb_layer_t *, pcb_poly_t *, pcb_point_t *); + void *(*Arc)(pcb_opctx_t *ctx, pcb_layer_t *, pcb_arc_t *); + void *(*Rat)(pcb_opctx_t *ctx, pcb_rat_t *); + void *(*ArcPoint)(pcb_opctx_t *ctx, pcb_layer_t *, pcb_arc_t *, int *end_id); + void *(*subc)(pcb_opctx_t *ctx, pcb_subc_t *); + void *(*padstack)(pcb_opctx_t *ctx, pcb_pstk_t *); +} pcb_opfunc_t; + +void *pcb_object_operation(pcb_opfunc_t *F, pcb_opctx_t *ctx, int Type, void *Ptr1, void *Ptr2, void *Ptr3); +pcb_bool pcb_selected_operation(pcb_board_t *pcb, pcb_data_t *data, pcb_opfunc_t *F, pcb_opctx_t *ctx, pcb_bool Reset, int type, pcb_bool on_locked_too); + +#endif Index: tags/2.1.2/src/paths.c =================================================================== --- tags/2.1.2/src/paths.c (nonexistent) +++ tags/2.1.2/src/paths.c (revision 24813) @@ -0,0 +1,303 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2016 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +/* Resolve paths, build paths using template */ +#include +#include +#include +#include "config.h" +#include "paths.h" +#include "error.h" +#include "conf_core.h" + +/* don't include board.h or compat_misc.h because of gsch2pcb-rnd */ +const char *pcb_board_get_filename(void); +const char *pcb_board_get_name(void); +int pcb_getpid(void); + + +int pcb_build_fn_cb(void *ctx, gds_t *s, const char **input) +{ + char buff[20]; + const char *name; + + switch(**input) { + case 'P': + sprintf(buff, "%.8i", pcb_getpid()); + gds_append_str(s, buff); + (*input)++; + return 0; + case 'F': + name = pcb_board_get_filename(); + gds_append_str(s, (name != NULL) ? name : "PCB-anon"); + (*input)++; + return 0; + case 'B': + name = pcb_board_get_filename(); + if (name != NULL) { + const char *bn = strrchr(name, '/'); + if (bn != NULL) + bn++; + else + bn = name; + gds_append_str(s, bn); + } + else + gds_append_str(s, "no_file_name"); + (*input)++; + return 0; + case 'D': + name = pcb_board_get_filename(); + if (name != NULL) { + char *bn = strrchr(name, '/'); + if (bn != NULL) + gds_append_len(s, name, bn-name+1); + else + gds_append_str(s, "./"); + } + else + gds_append_str(s, "./"); + (*input)++; + return 0; + case 'N': + name = pcb_board_get_name(); + gds_append_str(s, (name != NULL) ? name : "no_name"); + (*input)++; + return 0; + case 'T': + sprintf(buff, "%lu", (unsigned long int)time(NULL)); + gds_append_str(s, buff); + (*input)++; + return 0; + } + return -1; +} + +int pcb_build_argfn_cb(void *ctx_, gds_t *s, const char **input) +{ + if ((**input >= 'a') && (**input <= 'z')) { + int idx = **input - 'a'; + pcb_build_argfn_t *ctx = ctx_; + if (ctx->params[idx] == NULL) + return -1; + gds_append_str(s, ctx->params[idx]); + (*input)++; + return 0; + } + return pcb_build_fn_cb(NULL, s, input); +} + +char *pcb_build_fn(const char *template) +{ + return pcb_strdup_subst(template, pcb_build_fn_cb, NULL, PCB_SUBST_ALL); +} + +char *pcb_build_argfn(const char *template, pcb_build_argfn_t *arg) +{ + return pcb_strdup_subst(template, pcb_build_argfn_cb, arg, PCB_SUBST_ALL); +} + +int pcb_subst_append(gds_t *s, const char *template, int (*cb)(void *ctx, gds_t *s, const char **input), void *ctx, pcb_strdup_subst_t flags, size_t extra_room) +{ + const char *curr, *next; + + if (template == NULL) + return -1; + + gds_init(s); + + if (*template == '?') + template++; + + if ((*template == '~') && (flags & PCB_SUBST_HOME)) { + if (conf_core.rc.path.home == NULL) { + pcb_message(PCB_MSG_ERROR, "pcb_strdup_subst(): can't resolve home dir required for path %s\n", template); + goto error; + } + gds_append_str(s, conf_core.rc.path.home); + template++; + } + + for(curr = template;;) { + next = strpbrk(curr, "%$\\"); + if (next == NULL) { + gds_append_str(s, curr); + gds_enlarge(s, gds_len(s) + extra_room); + return 0; + } + if (next > curr) + gds_append_len(s, curr, next-curr); + + switch(*next) { + case '\\': + if (flags & PCB_SUBST_BACKSLASH) { + char c; + next++; + switch(*next) { + case 'n': c = '\n'; break; + case 'r': c = '\r'; break; + case 't': c = '\t'; break; + case '\\': c = '\\'; break; + default: c = *next; + } + gds_append(s, c); + curr = next; + } + else { + gds_append(s, *next); + curr = next+1; + } + break; + case '%': + if (flags & PCB_SUBST_PERCENT) { + next++; + switch(*next) { + case '%': + gds_append(s, '%'); + curr = next+1; + break; + default: + if (cb(ctx, s, &next) != 0) { + /* keep the directive intact */ + gds_append(s, '%'); + } + curr = next; + } + } + else { + gds_append(s, '%'); + curr = next+1; + } + break; + case '$': + if (flags & PCB_SUBST_CONF) { + const char *start, *end; + next++; + switch(*next) { + case '(': + next++; + start = next; + end = strchr(next, ')'); + if (end != NULL) { + conf_native_t *cn; + char path[256], *q; + size_t len = end - start; + if (len > sizeof(path) - 1) { + if (!(flags & PCB_SUBST_QUIET)) + pcb_message(PCB_MSG_ERROR, "pcb_strdup_subst(): can't resolve $() conf var, name too long: %s\n", start); + goto error; + } + memcpy(path, start, len); + path[len] = '\0'; + for(q = path; *q != '\0'; q++) + if (*q == '.') + *q = '/'; + cn = conf_get_field(path); + if (cn == NULL) { + if (!(flags & PCB_SUBST_QUIET)) + pcb_message(PCB_MSG_ERROR, "pcb_strdup_subst(): can't resolve $(%s) conf var: not found in the conf tree\n", path); + goto error; + } + if (cn->type != CFN_STRING) { + if (!(flags & PCB_SUBST_QUIET)) + pcb_message(PCB_MSG_ERROR, "pcb_strdup_subst(): can't resolve $(%s) conf var: value type is not string\n", path); + goto error; + } + if (cn->val.string[0] != NULL) + gds_append_str(s, cn->val.string[0]); + curr = end+1; + } + else { + if (!(flags & PCB_SUBST_QUIET)) + pcb_message(PCB_MSG_ERROR, "pcb_strdup_subst(): unterminated $(%s)\n", start); + goto error; + } + break; + case '$': + gds_append(s, '$'); + curr = next+1; + break; + default: + gds_append(s, '$'); + curr = next; + break; + } + } + else { + gds_append(s, '$'); + curr = next+1; + } + break; + } + } + abort(); /* can't get here */ + + error:; + return -1; +} + +static char *pcb_strdup_subst_(const char *template, int (*cb)(void *ctx, gds_t *s, const char **input), void *ctx, pcb_strdup_subst_t flags, size_t extra_room) +{ + gds_t s; + + if (template == NULL) + return NULL; + + memset(&s, 0, sizeof(s)); /* shouldn't do gds_init() here, pcb_subst_append() will do that */ + + if (pcb_subst_append(&s, template, cb, ctx, flags, extra_room) == 0) + return s.array; + + gds_uninit(&s); + return NULL; +} + +char *pcb_strdup_subst(const char *template, int (*cb)(void *ctx, gds_t *s, const char **input), void *ctx, pcb_strdup_subst_t flags) +{ + return pcb_strdup_subst_(template, cb, ctx, flags, 0); +} + +void pcb_paths_resolve(const char **in, char **out, int numpaths, unsigned int extra_room, int quiet) +{ + pcb_strdup_subst_t flags = PCB_SUBST_ALL; + if (quiet) + flags |= PCB_SUBST_QUIET; + for (; numpaths > 0; numpaths--, in++, out++) + *out = pcb_strdup_subst_(*in, pcb_build_fn_cb, NULL, flags, extra_room); +} + +void pcb_path_resolve(const char *in, char **out, unsigned int extra_room, int quiet) +{ + pcb_paths_resolve(&in, out, 1, extra_room, quiet); +} + +char *pcb_path_resolve_inplace(char *in, unsigned int extra_room, int quiet) +{ + char *out; + pcb_path_resolve(in, &out, extra_room, quiet); + free(in); + return out; +} Index: tags/2.1.2/src/paths.h =================================================================== --- tags/2.1.2/src/paths.h (nonexistent) +++ tags/2.1.2/src/paths.h (revision 24813) @@ -0,0 +1,78 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2016, 2017 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +/* Resolve paths, build paths using template */ + +#include "genvector/gds_char.h" + +/* Allocate *out and copy the path from in to out, replacing ~ with conf_core.rc.path.home + If extra_room is non-zero, allocate this many bytes extra for each slot; + this leaves some room to append a file name. If quiet is non-zero, suppress + error messages. */ +void pcb_path_resolve(const char *in, char **out, unsigned int extra_room, int quiet); + +/* Same as resolve_path, but it returns the pointer to the new path and calls + free() on in */ +char *pcb_path_resolve_inplace(char *in, unsigned int extra_room, int quiet); + + +/* Resolve all paths from a in[] into out[](should be large enough) */ +void pcb_paths_resolve(const char **in, char **out, int numpaths, unsigned int extra_room, int quiet); + +/* Resolve all paths from a char *in[] into a freshly allocated char **out */ +#define pcb_paths_resolve_all(in, out, extra_room, quiet) \ +do { \ + int __numpath__ = sizeof(in) / sizeof(char *); \ + if (__numpath__ > 0) { \ + out = malloc(sizeof(char *) * __numpath__); \ + pcb_paths_resolve(in, out, __numpath__, extra_room, quiet); \ + } \ +} while(0) + + +/* generic file name template substitution callbacks for pcb_strdup_subst: + %P pid + %F load-time file name of the current pcb + %B basename (load-time file name of the current pcb without path) + %D dirname (load-time file path of the current pcb, without file name, with trailing slash, might be ./) + %N name of the current pcb + %T wall time (Epoch) +*/ +int pcb_build_fn_cb(void *ctx, gds_t *s, const char **input); + +char *pcb_build_fn(const char *template); + + +/* Same as above, but also replaces lower case formatting to the members of + the array if they are not NULL; use with pcb_build_argfn() */ +typedef struct { + const char *params['z' - 'a' + 1]; /* [0] for 'a' */ +} pcb_build_argfn_t; + +char *pcb_build_argfn(const char *template, pcb_build_argfn_t *arg); + +int pcb_build_argfn_cb(void *ctx, gds_t *s, const char **input); + Index: tags/2.1.2/src/pcb-conf.lht =================================================================== --- tags/2.1.2/src/pcb-conf.lht (nonexistent) +++ tags/2.1.2/src/pcb-conf.lht (revision 24813) @@ -0,0 +1,276 @@ +li:pcb-rnd-conf-v1 { + ha:overwrite { + ha:editor { + grid_unit = mil + grid = 25 mil + li:grids = { + {0.1 mil}; {1 mil}; {5 mil}; {10 mil}; {25 mil}; {50 mil}; {100 mil}; + {0.01 mm}; {0.05 mm}; {0.1 mm}; {0.25 mm}; {0.5 mm}; {1 mm}; + } + grids_idx = 4 + zoom = 1 + mode = 1 + buffer_number = 0 + clear_line = 1 + clear_polypoly = 0 + full_poly = 0 + unique_names = 0 + marker_snaps = 1 + snap_pin = 1 + snap_offgrid_line = 1 + highlight_on_point = 0 + show_solder_side = 0 + save_last_command = 0 + save_in_tmp = 0 + draw_grid = 1 + all_direction_lines = 0 + line_refraction = 1 + rubber_band_mode = 0 + rubber_band_keep_midlinedir = 0 + swap_start_direction = 0 + show_drc = 0 + auto_drc = 0 + conn_find_rat = 1 + show_number = 0 + orthogonal_moves = 0 + reset_after_element = 1 + auto_place = 0 + lock_names = 0 + only_names = 0 + thin_draw = 0 + thin_draw_poly = 0 + as_drawn_poly = 0 + wireframe_draw = 0 + local_ref = 0 + check_planes = 0 + hide_names = 0 + description = 0 + name_on_pcb = 1 + enable_stroke = 1 + live_routing = 0 + beep_when_finished = 0 + click_time = 200 + auto_via = 1 + io_incomp_popup = 1 + io_incomp_style = list + ha:view { + flip_x = 0 + flip_y = 0 + } + ha:selection { + disable_negative = 0 + symmetric_negative = 0 + } + undo_warning_size = 1024 + fullscreen = 0 + move_linepoint_uses_route = 1 + subc_conv_refdes = U0 + } # editor + + ha:rc { + verbose = 0 + quiet = 0 + backup_interval = 60 + hid_fallback = 1 + brave = {} + menu_file = {default} +# font_command = {} +# file_command = {} +# file_path = {} + library_shell = {} + export_basename = 0 + + emergency_name = {PCB.%ld.save} + emergency_format = {lihata} + backup_name = {%F.%P.backup} + backup_format = {lihata} + + li:library_search_paths = { + ?../pcblib + ?~/pcblib/ + $(rc.path.share)/pcblib + } + + keep_save_backups = false + save_command = {} + + li:default_font_file = { + {./default_font} + {$(rc.path.share)/default_font} + } + li:default_pcb_file = { + {./default4.lht} + {$(rc.path.share)/default4.lht} + } + +# script_filename = {} +# action_string = {} +# rat_path = {} +# rat_command = {} + li:preferred_gui = { gtk2_gl; gtk2_gdk; lesstif; batch } + save_final_fallback_fmt = lihata + save_fp_fmt = lihata + } # rc + + ha:design { +# old DRC (design rule checked) section + bloat = 12.00 mil + shrink = 9.00 mil + min_drill = 15.00 mil + min_ring = 10.00 mil + min_slk = 7.00 mil + min_wid = 10.00 mil + line_thickness = 10.00 mil + clearance = 20.00 mil + poly_isle_area = 200000000.2 + + via_thickness = 2000.00 um + via_drilling_hole = 31.50 mil + + text_scale = 100 + text_thickness = 0 + text_font_id = 0 +# poly_isle_area = 0 +# background_image = {} +# fab_author = {} + paste_adjust = 0 + } # design + + ha:appearance { + compact = 1 + rat_thickness = 0.25 mm + mark_size = 50 mil + layer_alpha = 0.7 + drill_alpha = 0.85 + text_host_bbox = true + term_label_size = 50 + subc_layer_per_side = 1 + invis_other_groups = 0 + black_current_group = 0 + + ha:loglevels { + debug_tag = {} + debug_popup = false + info_tag = {} + info_popup = false + warning_tag = {} + warning_popup = true + error_tag = {} + error_popup = true + } + ha:color { + background = {#e5e5e5} + crosshair = {#ff0000} + cross = {#cdcd00} + selected = {#00ffff} + via = {#7f7f7f} + via_far = {#aaaaaa} + pin = {#4d4d4d} + pin_far = {#999999} + pin_name = {#ff0000} + element = {#000000} + subc = {#CC0000} + subc_nonetlist = {#CC9900} + padstackmark = {#CC0000} + rat = {#b8860b} + invisible_objects = {#cccccc} + connected = {#00ff00} + off_limit = {#aaaaaa} + grid = {#ff0000} + li:layer = { + {#8b2323}; {#3a5fcd}; {#104e8b}; {#cd3700}; {#548b54}; + {#8b7355}; {#00868b}; {#228b22}; {#8b2323}; {#3a5fcd}; + {#104e8b}; {#cd3700}; {#548b54}; {#8b7355}; {#00868b}; + {#228b22}; + {#8b2323}; {#3a5fcd}; {#104e8b}; {#cd3700}; {#548b54}; + {#8b7355}; {#00868b}; {#228b22}; {#8b2323}; {#3a5fcd}; + {#104e8b}; {#cd3700}; {#548b54}; {#8b7355}; {#00868b}; + {#228b22}; + {#8b2323}; {#3a5fcd}; {#104e8b}; {#cd3700}; {#548b54}; + {#8b7355}; + } + warn = {#ff8000} + mask = {#ff0000} + paste = {#cd00cd} + } + ha:padstack { + cross_thick = 1 + cross_size = 0.1 mm + } + ha:subc { + dash_freq = 5 + } + ha:messages { +# char_per_line = 0 + } +# ha:misc { +# volume = 0 +# } misc; + } # appearance; + + ha:plugins { + ha:lib_hid_common { + ha:cli_history { + file = {$(rc.path.home)/.pcb-rnd/cli_history} + slots = 64 + } + } + ha:io_lihata { + aux_pcb_pattern = {%D.%B.lht.pcb} + } + ha:mincut { + enable = 1 + } + ha:djopt { + auto_only = 1 + } + ha:vendor { + enable = 0 + } + ha:diag { + auto_integrity = 0 + } + ha:import_sch { + gnetlist_program = gnetlist + make_program = make + verbose = false + } + ha:import_mentor_sch { + li:map_search_paths = { + {./mentor_parts.map} + {$(rc.path.share)/mentor_parts.map} + } + } + ha:hid_gtk { + ha:local_grid { + enable = 0 + radius = 16 + } + ha:global_grid { + sparse = 0 + min_dist_px = 4 + } + } + ha:report { + columns = 8 + } + ha:fp_wget { + auto_update_gedasymbols = 0 + auto_update_edakrill = 0 + } + ha:export_gerber { + plated_g85_slot = 0 + unplated_g85_slot = 0 + } + } # plugins + + ha:utils { + ha:gsch2pcb-rnd { + remove_unfound_elements = 1 + quiet_mode = 0 + verbose = 0 + } + } # utils + } # main +} # root + Index: tags/2.1.2/src/pcb-menu-default.lht =================================================================== --- tags/2.1.2/src/pcb-menu-default.lht (nonexistent) +++ tags/2.1.2/src/pcb-menu-default.lht (revision 24813) @@ -0,0 +1,768 @@ +ha:{ + li:mouse { + li:left { + li:press = { Mode(Notify) } + li:press-shift = { Mode(Notify) } + li:press-ctrl = { Mode(Save); Mode(None); Mode(Restore); Mode(Notify) } + li:release = { Mode(Release) } + li:release-shift = { Mode(Release) } + li:release-ctrl = { Mode(Release) } + } + li:middle { + li:press = { Pan(1) } + li:release = { Pan(0) } + } + li:right { + li:press = { Mode(Stroke) } + li:release = { Mode(Release); Popup(popup-obj, obj-type) } + li:shift-release = { Popup(popup-obj-misc) } + li:press-ctrl = { Display(CycleCrosshair) } + } + li:scroll-up { + li:press = { Zoom(0.8) } + li:press-shift = { Scroll(up) } + li:press-ctrl = { Scroll(left) } + } + li:scroll-down { + li:press = { Zoom(1.25) } + li:press-shift = { Scroll(down) } + li:press-ctrl = { Scroll(right) } + } + } + + li:main_menu { + ### File Menu + ha:File { + li:submenu { + ha:Start New Layout = { li:a={{f;n}; {Ctrln};}; action=New() } + ha:Revert = { a={f;r}; action=Load(Revert,none); tip=Revert to the layout stored on disk } + - + ha:Load layout... = { li:a={{f;o};{f;l};} action=Load(Layout); tip=Load a layout from a file } + - + ha:Save Layout = { li:a={{f;s}; {Ctrls};}; action=Save(Layout); tip=Saves current layout } + ha:Save Layout As... = { li:a={{f;a}; {Shift Ctrls};}; action=Save(LayoutAs); tip=Saves current layout into a new file } + - + ha:Import { + li:submenu { + ha:Import gschem schematics = { action=Import() } + ha:Import tEDAx schematics = { action=LoadTedaxFrom(netlist) } + ha:Import KiCad/eeschema schematics = { action=LoadEeschemaFrom() } + ha:Import mentor graphics schematics = { action=LoadMentorFrom() } + ha:Load subcircuit data to paste-buffer = { li:action={PasteBuffer(Clear); Load(ElementTobuffer)} } + ha:Load layout data to paste-buffer = { li:action={PasteBuffer(Clear); Load(LayoutTobuffer)} } + ha:Load netlist file = { action=Load(Netlist) } + ha:Load IPC-D-356 netlist = { action=LoadIpc356From() } + ha:Load vendor resource file = { action=LoadVendorFrom() } + ha:Load routed dsn or ses file = { action=LoadDsnFrom() } + ha:Load MUCS pl file = { action=LoadMucsFrom() } + ha:Load TinyCAD .net file = { action=LoadTinyCADFrom() } + ha:Load Calay .net+.cmp files = { action=LoadCalayFrom() } + ha:Load LTSpice .net and .asc files = { action=LoadLTSpiceFrom() } + ha:Load HP-GL plot to paste-buffer = { action=LoadHPGLFrom() } + ha:Load Hyperlynx .hyp file = { action=LoadHypFrom() } + ha:Load FreePCB netlist (EasyEDA) = { action=LoadFpcbnlFrom() } + } + } + - + ha:Save connection data of { + li:submenu { + ha:a single element = { li:action={ Save(ElementConnections) } } + ha:all elements = { action=Save(AllConnections) } + ha:unused pins = { action=Save(AllUnusedPins) } + ha:netlist patch for back annotation = {li:a={{f;x;p}; {a;b;x};}; action=SavePatch() } + } + } + ha:Print layout... = { a={f;p}; action=Print()} + ha:Export layout... = { a={f;e}; action=ExportGUI()} + ha:Export with CAM job...={ a={f;c}; action=cam()} + ha:Reports { + li:submenu { + ha:Generate object report = { a={i;r}; action=ReportObject() } + ha:Generate drill summary = { a={i;d}; action=Report(DrillReport) } + ha:Report found padstacks = { a={i;f}; action=Report(FoundPins) } + } + } + - + ha:Preferences... = { a={i;c;p}; action=preferences} + ha:Maintenance { + li:submenu { + ha:Calibrate Printer... = { a={i;c;c}; action=PrintCalibrate() } + ha:Re-scan the footprint library = { a={i;c;r}; action=fp_rehash() } + ha:Data integrity check = { a={i;c;i}; action=Integrity() } + - + ha:Edit current font = { action=FontEdit() } + ha:Edit on-disk font = { action={ LoadFontFrom("", 126); conf(set, design/text_font_id, 126, design); FontEdit() } } + ha:Save font from font editor = { action=FontSave() } + - + ha:Undo dialog (for debugging) = { a={u;d;}; action=UndoDialog() } + } + } + - + ha:Quit Program = { li:a={{f;q}; {Ctrlq};}; action=Quit() } + } + } # File + + ha:Edit { + li:submenu { + ha:Undo last operation = { li:a={{u; u}; {Ctrlz};}; action=Undo() } + ha:Redo last undone operation = { li:a={{u; r}; {Ctrly};}; action=Redo() } + ha:Clear undo-buffer = { a={u; c}; action=Undo(ClearList) } + - + ha:Cut selection to buffer = { li:a={{e; x}; a=Ctrlx;}; li:action={ GetXY(Click to set the snap point for this buffer); PasteBuffer(Clear); PasteBuffer(AddSelected); RemoveSelected(); Unselect(All); Mode(PasteBuffer) } } + ha:Copy selection to buffer = { li:a={{e; c}; {Ctrlc;};}; li:action={ GetXY(Click to set the snap point for this buffer); PasteBuffer(Clear); PasteBuffer(AddSelected); Unselect(All); Mode(PasteBuffer) } } + ha:Paste buffer to layout = { li:a={{e; v}; a=Ctrlv;}; action=Mode(PasteBuffer) } + - + ha:Remove object = { li:a={{e;d};{Delete};}; li:action={Mode(Save); Mode(Remove); Mode(Notify); Mode(Restore)} } + ha:Change object { + li:submenu { + ha:Set Same Style = { a={e; s; s}; action=SetSame() } + ha:Flip Object = { a={e; i}; action=Flip(Object) } + ha:Move to current layer = { a={e; l}; action=MoveToCurrentLayer(Object) } + ha:ChangeJoin Object = { a={e; j}; action=ChangeJoin(Object) } + + ha:Geometry { + li:submenu { + ha:Clearance +2 mil = { a={e; g; c}; action=ChangeClearSize(Object,+2,mil) } + ha:Clearance -2 mil = { a={e; g; Shiftc}; action=ChangeClearSize(Object,-2,mil) } + ha:ChangeSizes to Route style = { a={e; g; y}; action=ChangeSizes(Object,style,mil) } + ha:ChangeSize +5 mil = { a={e; g; s}; action=ChangeSize(Object,+5,mil) } + ha:ChangeSize -5 mil = { a={e; g; Shifts}; action=ChangeSize(Object,-5,mil) } + ha:ChangeDrill +5 mil = { a={e; g; d}; action=ChangeDrillSize(Object,+5,mil) } + ha:ChangeDrill -5 mil = { a={e; g; Shiftd}; action=ChangeDrillSize(Object,-5,mil) } + } + } + } + } # Change object + ha:Add/place object { + li:submenu { + ha:Place mark = { li:a={{a;m}; {a;w}; }; action=MarkCrosshair() } + ha:Place via = { a={a;v}; li:action={Mode(Save); Mode(Via); Mode(Notify); Mode(Restore);} } + ha:Start routing a line = { a={a;l}; li:action={Mode(Save); Mode(Line); Mode(Notify); } } + ha:Start routing an arc = { a={a;a}; li:action={Mode(Save); Mode(Arc); Mode(Notify); } } + } + } + - + ha:Edit properties of { + li:submenu { + ha:Layout = { action=Propedit(board) } + ha:Current Layer = { action={Propedit(layer)} } + ha:Current Layer Group = { action={Propedit(layergrp)} } + } + } + ha:Route Styles { + li:submenu { + @routestyles + - + ha:Edit... = { action=AdjustStyle(0) } + } + } + ha:Board padstack prototypes... = { action=pstklib() } + - + ha:Subcircuit { + li:submenu { + ha:Layer bindings... = { a={e; s; b}; action=LayerBinding() } + ha:External editor... = { a={e; s; e}; li:action={ GetXY(Click on the subcircuit to edit); extedit(object) } } + ha:Refdes = { a={e; s; r}; action=ChangeName(Subc) } + } + } + ha:Object flags... = { a={e; f}; action=FlagEdit() } + ha:Object Properties... = { a={e; p}; action=PropEdit(selection) } + } + } # Edit + + ha:View { + li:submenu { + ha:Grid { + li:submenu { + ha:Enable visible grid = { a={g; v}; checked=editor/draw_grid; action=conf(toggle, editor/draw_grid, design) } + ha:Enable local grid = { a={g; l}; checked=plugins/hid_gtk/local_grid/enable; action=conf(toggle, plugins/hid_gtk/local_grid/enable, design) } + ha:Grid units { + li:submenu { + ha:mil = { a={g; i}; checked=ChkGridUnits(mil); action=SetUnits(mil); update_on={editor/grid_unit} } + ha:mm = { a={g; m}; checked=ChkGridUnits(mm); action=SetUnits(mm); update_on={editor/grid_unit} } + } + } + ha:Grid size = { + li:submenu { + ha:No Grid = { checked=ChkGridSize(none); action=SetValue(Grid,1); update_on={editor/grid} } + - + @grid + - + ha:Previous grid = { li:a={{g; b};{[};}; action=Grid(down) } + ha:Next grid = { li:a={{g; f};{]};}; action=Grid(up) } + - + ha:Grid *2 = { a={g; d}; action=SetValue(Grid,*2) } + ha:Grid /2 = { a={g; h}; action=SetValue(Grid,/2) } + ha:Grid -5mil = { action=SetValue(Grid,-5,mil) } + ha:Grid +5mil = { action=SetValue(Grid,+5,mil) } + ha:Grid -0.05mm = { action=SetValue(Grid,-0.05,mm) } + ha:Grid +0.05mm = { action=SetValue(Grid,+0.05,mm) } + } + } + ha:Grid properties = { + li:submenu { + ha:Enable local grid = { checked=plugins/hid_gtk/local_grid/enable; action=conf(toggle, plugins/hid_gtk/local_grid/enable, design) } + - + ha:local grid radius 4 = { checked={conf(iseq, plugins/hid_gtk/local_grid/radius, 4)}; li:action={conf(set, plugins/hid_gtk/local_grid/radius, 4, design); conf(set, plugins/hid_gtk/local_grid/enable, 1, design) } update_on={} } + ha:local grid radius 8 = { checked={conf(iseq, plugins/hid_gtk/local_grid/radius, 8)}; li:action={conf(set, plugins/hid_gtk/local_grid/radius, 8, design); conf(set, plugins/hid_gtk/local_grid/enable, 1, design) } update_on={} } + ha:local grid radius 16 = { checked={conf(iseq, plugins/hid_gtk/local_grid/radius, 16)}; li:action={conf(set, plugins/hid_gtk/local_grid/radius, 16, design); conf(set, plugins/hid_gtk/local_grid/enable, 1, design) } update_on={} } + ha:local grid radius 32 = { checked={conf(iseq, plugins/hid_gtk/local_grid/radius, 32)}; li:action={conf(set, plugins/hid_gtk/local_grid/radius, 32, design); conf(set, plugins/hid_gtk/local_grid/enable, 1, design) } update_on={} } + - + ha:sparse global grid = { checked=plugins/hid_gtk/global_grid/sparse; action=conf(toggle, plugins/hid_gtk/global_grid/sparse, design) } + ha:global grid density 4 = { checked={conf(iseq, plugins/hid_gtk/global_grid/min_dist_px, 4)}; li:action={conf(set, plugins/hid_gtk/global_grid/min_dist_px, 4, design); conf(set, plugins/hid_gtk/local_grid/enable, 0, design) } update_on={} } + ha:global grid density 8 = { checked={conf(iseq, plugins/hid_gtk/global_grid/min_dist_px, 8)}; li:action={conf(set, plugins/hid_gtk/global_grid/min_dist_px, 8, design); conf(set, plugins/hid_gtk/local_grid/enable, 0, design) } update_on={} } + ha:global grid density 16 = { checked={conf(iseq, plugins/hid_gtk/global_grid/min_dist_px, 16)}; li:action={conf(set, plugins/hid_gtk/global_grid/min_dist_px, 16, design); conf(set, plugins/hid_gtk/local_grid/enable, 0, design) } update_on={} } + } + } + ha:Realign grid = { a={g; r}; action={ GetXY(Click to set the grid origin); Display(ToggleGrid) } } + } + } + - + ha:Displayed subcircuit ID { + li:submenu { + ha:refdes = { a={v; s; r}; checked=ChkSubcID(%a.refdes%); action=Display(SubcID, "%a.refdes%"); update_on={editor/subc_id} } + ha:footprint = { a={v; s; f}; checked=ChkSubcID(%a.footprint%); action=Display(SubcID,"%a.footprint%"); update_on={editor/subc_id} } + ha:value = { a={v; s; v}; checked=ChkSubcID(%a.value%); action=Display(SubcID,"%a.value%"); update_on={editor/subc_id} } + ha:refdes+value = { a={v; s; s}; checked=ChkSubcID(%a.refdes%\\n%a.value%); action=Display(SubcID,"%a.refdes%\\\\n%a.value%"); update_on={editor/subc_id} } + ha:user configured = { a={v; s; c}; action=Display(SubcID); } + } + } + ha:Displayed terminal ID { + li:submenu { + ha:term = { a={v; t; t}; checked=ChkTermID(%a.term%); action=Display(TermID, "%a.term%"); update_on={editor/term_id} } + ha:name = { a={v; t; n}; checked=ChkTermID(%a.name%); action=Display(TermID, "%a.name%"); update_on={editor/term_id} } + ha:term+name = { a={v; t; s}; checked=ChkTermID("%a.term%,%a.name%"); action=Display(TermID, "%a.term%,%a.name%"); update_on={editor/term_id} } + ha:user configured = { a={v; t; c}; action=Display(TermID); } + } + } + ha:Zoom and side { + li:submenu { + ha:Zoom In 20% = { li:a={{z;z;}; {+};} action=Zoom(-1.2) } + ha:Zoom Out 20% = { li:a={{z;x;}; {-};} action=Zoom(+1.2) } + ha:Zoom In 2X = { action=Zoom(-2) } + ha:Zoom Out 2X = { action=Zoom(+2) } + ha:Zoom to 0.1mil/px = { action={Zoom(=0.1mil)} } + ha:Zoom to 0.01mm/px = { action={Zoom(=0.01mm)} } + ha:Zoom to 1mil/px = { action={Zoom(=1mil)} } + ha:Zoom to 0.05mm/px = { action={Zoom(=0.05mm)} } + ha:Zoom to 2.5mil/px = { action={Zoom(=2.5mil)} } + ha:Zoom to 0.1mm/px = { action={Zoom(=0.1mm)} } + ha:Zoom to 10mil/px = { action={Zoom(=10mil)} } + ha:Zoom In 20% and center = { li:action={Zoom(-1.2); Center()} } + ha:Zoom Out 20% and center= { li:action={Zoom(+1.2); Center()} } + - + ha:Zoom Extents = { li:a={{z;e;}; {v;f};}; action=Zoom() } + ha:Zoom to selection = { a={z;s;}; action=ZoomTo(selected) } + ha:Zoom to found = { a={z;f;}; action=ZoomTo(found) } + - + ha:Flip up/down = { checked=editor/view/flip_y; a=Tab; action=SwapSides(V) } + ha:Flip left/right = { checked=editor/view/flip_x; a=ShiftTab; action=SwapSides(H) } + ha:Spin 180 degrees = { a=CtrlTab; action=SwapSides(R) } + ha:Swap Sides = { a=Ctrl ShiftTab; action=SwapSides() } + - + ha:Center cursor = { a={v; c} action=Center() } + } + } + ha:Layers { + li:submenu { + ha:Shown Layers { + li:submenu { + @layerview + - + ha:Edit Layer Groups = { action=Preferences("layers") } + } + } + ha:Current Layer { + li:submenu { + anon2=@layerpick + - + ha:Delete current layer = { action=MoveLayer(c,-1) } + ha:Add new layer = { action=MoveLayer(-1,c) } + ha:Move current layer up = { action=MoveLayer(c,step-) } + ha:Move current layer down= { action=MoveLayer(c,step+) } + } + } + } + } + ha:Show padstack numbers in a subc = { a={v; n} action=Display(PinOrPadName) } + ha:Full screen = { checked=editor/fullscreen; a=\\; action=fullscreen(toggle) } + } + } # View + + ha:Mode = { + li:submenu { + ha:Routing { + li:submenu { + ha:'All-direction' lines = { li:a={{m; l; a}; {.};}; checked=editor/all_direction_lines; action=conf(toggle, editor/all_direction_lines, design); update_on={editor/all_direction_lines} } + ha:Cycle line clip/refraction = { li:a={{m; l; f}; {/};}; action=Display(CycleClip) } + ha:Auto swap line start angle = { checked=editor/swap_start_direction; action=conf(toggle, editor/swap_start_direction, design) } + ha:Auto enforce DRC clearance = { a={m; l; d}; checked=editor/auto_drc; action=conf(toggle, editor/auto_drc, design) } + - + ha:Rubber band mode = { a={m; r; r}; checked=editor/rubber_band_mode; action=conf(toggle, editor/rubber_band_mode, design) } + ha:Rubber band keeps middle line dir= { a={m; r; m}; checked=editor/rubber_band_keep_midlinedir; action=conf(toggle, editor/rubber_band_keep_midlinedir, design) } + - + ha:Route radius +0.5 = { li:a={{r; r; +}; {r; r; p};}; action=conf(delta, editor/route_radius, +0.5, design); } + ha:Route radius -0.5 = { li:a={{r; r; -}; {r; r; m};}; action=conf(delta, editor/route_radius, -0.5, design); } + - + ha:New lines, arcs clear polygons = { a={m; l; c}; checked=editor/clear_line; action=conf(toggle, editor/clear_line, design) } + ha:New polygons are full ones = { a={m; p; f}; checked=editor/full_poly; action=conf(toggle, editor/full_poly, design) } + ha:New polygons clear polygons = { a={m; p; c}; checked=editor/clear_polypoly; action=conf(toggle, editor/clear_polypoly, design) } + ha:Polygon clip inhibit (toggle) = { a={m; p; i}; checked=ClipInhibit(check); action=ClipInhibit(toggle); update_on={temp/clip_inhibit_chg} } + } + } + ha:Cursor/snap { + li:submenu { + ha:Orthogonal moves = { a={m; c; o}; checked=editor/orthogonal_moves; action=conf(toggle, editor/orthogonal_moves, design) } + ha:Crosshair snaps to padstacks = { a={m; c; p}; checked=editor/snap_pin; action=conf(toggle, editor/snap_pin, design) } + ha:Crosshair snaps to off-grid points on lines = { a={m; c; s};checked=editor/snap_offgrid_line; action=conf(toggle, editor/snap_offgrid_line, design) } + ha:Crosshair shows DRC clearance = { a={m; c; c}; checked=editor/show_drc; action=conf(toggle, editor/show_drc, design) } + } + } + ha:Drawing { + li:submenu { + ha:Show autorouter trials = { a={m; d; a}; checked=editor/live_routing; action=conf(toggle, editor/live_routing, design) } + ha:Highlighting on line, arc points = { a={m; d; h}; checked=editor/highlight_on_point; action=conf(toggle, editor/highlight_on_point, design) } + ha:Wireframe draw = { li:a={{m; d; w}; {|};}; checked=editor/wireframe_draw; action=conf(toggle, editor/wireframe_draw, design) } + ha:Thin draw = { a={m; d; t}; checked=editor/thin_draw; action=conf(toggle, editor/thin_draw, design) } + ha:Thin draw poly = { a={m; d; p}; checked=editor/thin_draw_poly; action=conf(toggle, editor/thin_draw_poly, design); update_on={editor/thin_draw_poly} } + ha:poly as-drawn frame annotation = { a={m; d; d}; checked=editor/as_drawn_poly; action=conf(toggle, editor/as_drawn_poly, design); update_on={editor/as_drawn_poly} } + ha:Check polygons = { a={m; d; c}; checked=editor/check_planes; action=conf(toggle, editor/check_planes, design) } + - + ha:Lock floaters = { a={m; f; l}; checked=editor/lock_names; action=conf(toggle, editor/lock_names, design) } + ha:Only floaters = { a={m; f; o}; checked=editor/only_names; action=conf(toggle, editor/only_names, design) } + ha:Hide floaters = { a={m; f; h}; checked=editor/hide_names; action=conf(toggle, editor/hide_names, design) } + - + ha:Line Tool size +5 mil = { a={m; l; +}; action=SetValue(LineSize,+5,mil) } + ha:Line Tool size -5 mil = { a={m; l; -}; action=SetValue(LineSize,-5,mil) } + ha:Text Tool scale +10 mil = { a={m; t; +}; action=SetValue(TextScale,+10,mil) } + ha:Text Tool scale -10 mil = { a={m; t; -}; action=SetValue(TextScale,-10,mil) } + - + ha:Render color override { + li:submenu { + ha:Invisible-color on other groups = { a={m; o; i}; checked=appearance/invis_other_groups; action=conf(toggle, appearance/invis_other_groups, design) } + ha:black current group = { a={m; o; b}; checked=appearance/black_current_group; action=conf(toggle, appearance/black_current_group, design) } + } + } + } + } + ha:Mincut on shorts = { checked=plugins/mincut/enable; action=conf(toggle, plugins/mincut/enable, design) } + ha:Auto-zero delta measurements = { checked=editor/local_ref; action=conf(toggle, editor/local_ref, design) } + ha:Brave mode = { action=brave() } + ha:Vendor drill mapping = { checked=plugins/vendor/enable; action=conf(toggle, plugins/vendor/enable, design) } + ha:Loose subcircuits (no subc lock) = { a={m; k; s}; checked=subc(loose, check); action=subc(loose, toggle); update_on={} } + ha:Tool { + li:submenu { + ha:Via = { checked=ChkMode(via); li:a={{t;v};{F1};}; action=Mode(Via); update_on={editor/mode} } + ha:Line = { checked=ChkMode(line); li:a={{t;l};{F2};}; action=Mode(Line); update_on={editor/mode} } + ha:Arc = { checked=ChkMode(arc); li:a={{t;a};{F3};}; action=Mode(Arc); update_on={editor/mode} } + ha:Text = { checked=ChkMode(text); li:a={{t;t};{F4};}; action=Mode(Text); update_on={editor/mode} } + ha:Rectangle = { checked=ChkMode(rectangle); li:a={{t;r};{F5};}; action=Mode(Rectangle); update_on={editor/mode} } + ha:Polygon = { checked=ChkMode(poly); li:a={{t;p};{F6};}; action=Mode(Polygon); update_on={editor/mode} } + ha:Polygon Hole = { checked=ChkMode(polyhole); a={t;h}; action=Mode(PolygonHole); update_on={editor/mode} } + ha:Buffer = { checked=ChkMode(buffer); li:a={{t;b};{F7};}; action=Mode(PasteBuffer); update_on={editor/mode} } + ha:Del/Remove = { checked=ChkMode(remove); li:a={{t;d};{F8};}; action=Mode(Remove); update_on={editor/mode} } + ha:Rotate = { checked=ChkMode(rotate); li:a={{t;o};{F9};}; action=Mode(Rotate); update_on={editor/mode} } + ha:Thermal = { checked=ChkMode(thermal); li:a={{t;e};{F10};}; action=Mode(Thermal); update_on={editor/mode} } + ha:Arrow = { checked=ChkMode(arrow); li:a={{t;n};{F11};{space};}; action=Mode(Arrow); update_on={editor/mode} } + ha:Insert Point = { checked=ChkMode(insert); li:a={{t;i};{Insert};}; action=Mode(InsertPoint); update_on={editor/mode} } + ha:Move = { checked=ChkMode(move); a={t;m}; action=Mode(Move); update_on={editor/mode} } + ha:Copy = { checked=ChkMode(copy); a={t;c}; action=Mode(Copy); update_on={editor/mode} } + ha:Lock = { checked=ChkMode(lock); li:a={{t;k};{F12};}; action=Mode(Lock); update_on={editor/mode} } + ha:Cancel = { a={Escape}; action=Mode(Escape) } + } + } # Tool + } + } #Mode + + ha:Select { + li:submenu { + ha:Select all visible objects = { a={s; a; a;}; action=Select(All) } + ha:Select all connected objects = { a={s; a; c;}; action=Select(Connection) } + ha:Unselect all objects = { a={s; u; a;}; action=Unselect(All) } + ha:unselect all connected objects = { a={s; u; c;}; action=Unselect(Connection) } + ha:Invert selection = { a={s; i; }; action=Select(Invert) } + - +#TODO: this is gtk-specific + ha:Advanced search and select = { a={s; s;} action=DoWindows(search) } + - + ha:Move selected subcircuits to other side= { a={s; f;} action=Flip(SelectedElements) } + ha:Move selected objects to current layer = { a={s; l;} action=MoveToCurrentLayer(Selected) } + ha:Remove selected objects = { a={s; r;} action=RemoveSelected() } + ha:Convert selection to subcircuit = { a={s; c; s;} action=Select(ConvertSubc) } + ha:Convert selection to padstack = { a={s; c; p;} li:action={PadstackConvert(selected); Mode(PasteBuffer);} } + ha:Break selection subcircuits to pieces = { a={s; b; s}; li:action={PasteBuffer(Push); PasteBuffer(5); PasteBuffer(Clear); PasteBuffer(AddSelected); RemoveSelected(); PasteBuffer(Restore); PasteBuffer(ToLayout, crosshair); PasteBuffer(Clear); PasteBuffer(Pop);} } + ha:Break selection padstack to pieces = { a={s; b; p}; action=PadstackBreakup(selected) } + ha:Change selected objects { + li:submenu { + ha:Lines -10 mil = { li:action={ChangeSize(SelectedLines,-10,mil); ChangeSize(SelectedArcs,-10,mil)} } + ha:Lines +10 mil = { li:action={ChangeSize(SelectedLines,+10,mil); ChangeSize(SelectedArcs,+10,mil)} } + ha:Texts -10 mil = { action=ChangeSize(SelectedTexts,-10,mil) } + ha:Texts +10 mil = { action=ChangeSize(SelectedTexts,+10,mil) } + - + ha:Clearance +2 mil = { action=ChangeClearSize(SelectedObjects,+2,mil) } + ha:Clearance -2 mil = { action=ChangeClearSize(SelectedObjects,-2,mil) } + - + ha:Hole -10 mil = { action=ChangeDrillSize(SelectedPadstacks,-10,mil) } + ha:Hole +10 mil = { action=ChangeDrillSize(SelectedPadstacks,+10,mil) } + - + ha:Toggle join = { action=ChangeJoin(SelectedObjects) } + } + } + } + } # Select + + ha:Buffer { + li:submenu { + ha:Rotate buffer 90 deg CCW (left) = { li:a={{b;r;l}; {ShiftF7};}; li:action={Mode(PasteBuffer); PasteBuffer(Rotate,1)} } + ha:Rotate buffer 90 deg CW (right) = { a={b;r;r}; li:action={Mode(PasteBuffer); PasteBuffer(Rotate,3)} } + ha:Arbitrarily Rotate Buffer = { a={b;r;a}; li:action={Mode(PasteBuffer); FreeRotateBuffer()} } + ha:Mirror buffer (up/down) = { a={b;m;u}; li:action={Mode(PasteBuffer); PasteBuffer(Mirror)} } + ha:Mirror buffer (left/right) = { a={b;m;l}; li:action={Mode(PasteBuffer); PasteBuffer(Rotate,1); PasteBuffer(Mirror); PasteBuffer(Rotate,3)} } + ha:Scale = { action=ScaleBuffer(); } + ha:Normalize = { a={b;n}; li:action={Mode(PasteBuffer); PasteBuffer(Rotate,1); PasteBuffer(Normalize);} } + - + ha:Clear buffer = { a={b;c;c;}; action=PasteBuffer(Clear) } + ha:Convert buffer to subcircuit = { a={b;c;s}; action=PasteBuffer(ConvertSubc) } + ha:Convert buffer to padstack = { a={b;c;p}; li:action={PadstackConvert(buffer); Mode(PasteBuffer);} } + ha:Break buffer subcircuits to pieces = { a={b;s;b}; action=PasteBuffer(Restore) } + ha:Break buffer padstacks to pieces = { a={b;s;p}; action=PadstackBreakup(buffer) } + ha:Save buffer subcircuits to file = { a={b;s;s}; action=Save(PasteBuffer) } + ha:Layer bindings... = { a={b;b;}; action=LayerBinding(buffer) } + + ha:Buffer selection { + li:submenu { + ha:Select Buffer \#1 = { checked=ChkBuffer(1); a={b;1;} action=PasteBuffer(1); update_on={editor/buffer_number} } + ha:Select Buffer \#2 = { checked=ChkBuffer(2); a={b;2;} action=PasteBuffer(2); update_on={editor/buffer_number} } + ha:Select Buffer \#3 = { checked=ChkBuffer(3); a={b;3;} action=PasteBuffer(3); update_on={editor/buffer_number} } + ha:Select Buffer \#4 = { checked=ChkBuffer(4); a={b;4;} action=PasteBuffer(4); update_on={editor/buffer_number} } + ha:Select scratchpad = { checked=ChkBuffer(5); a={b;5;} action=PasteBuffer(5); update_on={editor/buffer_number} } + } + } + } + } # Buffer + + ha:Connects = { + li:submenu { + ha:Rats nest { + li:submenu { + ha:Optimize rats nest = { a={c;r;}; li:action={Atomic(Save); DeleteRats(AllRats); Atomic(Restore); AddRats(AllRats); Atomic(Block)} } + ha:Erase rats nest = { a={c;e;}; action=DeleteRats(AllRats) } + - + ha:Select shortest rat = { a={c;s;}; action=AddRats(Close) } + ha:AddRats to selected pins = { li:action={Atomic(Save); DeleteRats(AllRats); Atomic(Restore); AddRats(SelectedRats); Atomic(Block)} } + ha:AddRats Selected = { action=AddRats(SelectedRats) } + ha:Add All Rats = { action=AddRats(AllRats) } + } + } + - + ha:Find Connections = { a={c;f;}; li:action={Connection(Reset); Connection(Find)} } + ha:Clear/reset lookup = { a={c;c;}; li:action={Connection(Reset); Display(Redraw)} } + - + ha:Del/Remove Connected = { a={c;d;}; li:action={Atomic(Save); Connection(Reset); Atomic(Restore); Unselect(All); Atomic(Restore); Connection(Find); Atomic(Restore); Select(Connection); Atomic(Restore); RemoveSelected(); Atomic(Restore); Connection(Reset); Atomic(Restore); Unselect(All); Atomic(Block)} } + - + ha:Subcircuit Placement { + li:submenu { + ha:Auto-place selected subcircuits = { a={a;p;s;}; action=AutoPlaceSelected() } + ha:Disperse all subcircuits = { a={a;d;a;}; action=DisperseElements(All) } + ha:Disperse selected subcircuits = { a={a;d;s;}; action=DisperseElements(Selected) } + } + } + ha:Automatic Routing { + li:submenu { + ha:Auto-route selected rats = { a={a;r;s;}; action=AutoRoute(SelectedRats) } + ha:Auto-route all rats = { a={a;r;a;}; action=AutoRoute(AllRats) } + ha:Rip up selected auto-routed tracks = { a={a;r;t;}; action=RipUp(Selected) } + ha:Rip up all auto-routed tracks = { a={a;r;r;}; action=RipUp(All) } + } + } + ha:Optimize routed tracks { + li:submenu { + ha:Auto-Optimize = { a={a;o;a;}; action=djopt(auto) } + ha:Debumpify = { a={a;o;d;}; action=djopt(debumpify) } + ha:Unjaggy = { a={a;o;u;}; action=djopt(unjaggy) } + ha:Vianudge = { a={a;o;n;}; action=djopt(vianudge) } + ha:Viatrim = { a={a;o;t;}; action=djopt(viatrim) } + ha:Ortho pull = { a={a;o;o;}; action=djopt(orthopull) } + ha:Simple optimization = { a={a;o;s;}; action=djopt(simple) } + ha:Miter = { a={a;o;m;}; action=djopt(miter) } + ha:Puller = { a={a;o;p;}; action=Puller() } + ha:Global Puller { + li:submenu { + ha:Selected = { action=GlobalPuller(selected) } + ha:Found = { action=GlobalPuller(found) } + ha:All = { action=GlobalPuller() } + } + } + - + ha:Only autorouted nets = { checked=plugins/djopt/auto_only; action=conf(toggle, plugins/djopt/auto_only, design) } + } + } + - + ha:Design Rule Checker = { a={a;x;}; action=DRC() } + - + ha:Apply vendor drill mapping = { action=ApplyVendor() } + - + ha:Design changes (back annotation) { + li:submenu { + ha:Swap nets on two selected pins = { a={a;b;s;}; action=net(swap) } + ha:Replace footprint = { a={a;b;f;}; action=ReplaceFootprint() } + - + ha:claim net by object = { a={n;c;o;}; action=ClaimNet(object) } + ha:claim net on found = { a={n;c;f;}; action=ClaimNet(found) } + ha:claim net on selected = { a={n;c;s;}; action=ClaimNet(selected) } + } + } + } + } # Connects + + ha:Plugins { + li:submenu { + ha:script = { + # submenu dedicated for user scripts to register their menu items + li:submenu { + @scripts + } + } + ha:Manage plugins... = { a={p;m;p;}; action=ManagePlugins() } + ha:Manage scripts... = { a={p;m;s;}; action=BrowseScripts() } + } + } # Plugins + + ha:Window { + li:submenu { + ha:Library = { a={w;l}; action=DoWindows(Library) } + ha:Message Log = { a={w;m}; action=LogDialog() } + ha:DRC Check = { a={w;d}; action=DRC() } + ha:Netlist = { a={w;n}; action=DoWindows(Netlist) } + ha:Command Entry = { li:a={a={w;c}; {:};} action=Command() } + ha:Pinout = { a={w;p}; action=Display(Pinout) } + ha:Font selector = { a={w;f}; action=FontSel() } + - + ha:Key Bindings { + li:submenu { + ha:Cycle object being dragged = { li:a={{,};{e;y;};}; action=CycleDrag() } + + + ha:Step Cursor { + li:submenu { + ha:Step Up = { a=Up; action=Cursor(Warp,0,1,grid) } + ha:Step Down = { a=Down; action=Cursor(Warp,0,-1,grid) } + ha:Step Left = { a=Left; action=Cursor(Warp,-1,0,grid) } + ha:Step Right = { a=Right; action=Cursor(Warp,1,0,grid) } + ha:Step +Up = { a=ShiftUp; action=Cursor(Pan,0,50,view) } + ha:Step +Down = { a=ShiftDown; action=Cursor(Pan,0,-50,view) } + ha:Step +Left = { a=ShiftLeft; action=Cursor(Pan,-50,0,view) } + ha:Step +Right = { a=ShiftRight; action=Cursor(Pan,50,0,view) } + ha:Click = { a=Enter; li:action={Mode(Notify); Mode(Release)} } + } + } + ha:layer keys { + li:submenu { + ha:Select Layer 1 = { a=1; action=SelectLayer(1) } + ha:Select Layer 2 = { a=2; action=SelectLayer(2) } + ha:Select Layer 3 = { a=3; action=SelectLayer(3) } + ha:Select Layer 4 = { a=4; action=SelectLayer(4) } + ha:Select Layer 5 = { a=5; action=SelectLayer(5) } + ha:Select Layer 6 = { a=6; action=SelectLayer(6) } + ha:Select Layer 7 = { a=7; action=SelectLayer(7) } + ha:Select Layer 8 = { a=8; action=SelectLayer(8) } + ha:Select Layer 9 = { a=9; action=SelectLayer(9) } + ha:Select Layer 10 = { a=0; action=SelectLayer(10) } + ha:Select Layer 11 = { a=Alt1; action=SelectLayer(11) } + ha:Select Layer 12 = { a=Alt2; action=SelectLayer(12) } + ha:Select Layer 13 = { a=Alt3; action=SelectLayer(13) } + ha:Select Layer 14 = { a=Alt4; action=SelectLayer(14) } + ha:Select Layer 15 = { a=Alt5; action=SelectLayer(15) } + ha:Select Layer 16 = { a=Alt6; action=SelectLayer(16) } + ha:Select Layer 17 = { a=Alt7; action=SelectLayer(17) } + ha:Select Layer 18 = { a=Alt8; action=SelectLayer(18) } + ha:Select Layer 19 = { a=Alt9; action=SelectLayer(19) } + ha:Select Layer 20 = { a=Alt0; action=SelectLayer(20) } + - + ha:Toggle Layer 1 = { a=Ctrl1; action=ToggleView(1) } + ha:Toggle Layer 2 = { a=Ctrl2; action=ToggleView(2) } + ha:Toggle Layer 3 = { a=Ctrl3; action=ToggleView(3) } + ha:Toggle Layer 4 = { a=Ctrl4; action=ToggleView(4) } + ha:Toggle Layer 5 = { a=Ctrl5; action=ToggleView(5) } + ha:Toggle Layer 6 = { a=Ctrl6; action=ToggleView(6) } + ha:Toggle Layer 7 = { a=Ctrl7; action=ToggleView(7) } + ha:Toggle Layer 8 = { a=Ctrl8; action=ToggleView(8) } + ha:Toggle Layer 9 = { a=Ctrl9; action=ToggleView(9) } + ha:Toggle Layer 10 = { a=Ctrl0; action=ToggleView(10) } + ha:Toggle Layer 11 = { a=Ctrl-Alt1; action=ToggleView(11) } + ha:Toggle Layer 12 = { a=Ctrl-Alt2; action=ToggleView(12) } + ha:Toggle Layer 13 = { a=Ctrl-Alt3; action=ToggleView(13) } + ha:Toggle Layer 14 = { a=Ctrl-Alt4; action=ToggleView(14) } + ha:Toggle Layer 15 = { a=Ctrl-Alt5; action=ToggleView(15) } + ha:Toggle Layer 16 = { a=Ctrl-Alt6; action=ToggleView(16) } + ha:Toggle Layer 17 = { a=Ctrl-Alt7; action=ToggleView(17) } + ha:Toggle Layer 18 = { a=Ctrl-Alt8; action=ToggleView(18) } + ha:Toggle Layer 19 = { a=Ctrl-Alt9; action=ToggleView(19) } + ha:Toggle Layer 20 = { a=Ctrl-Alt0; action=ToggleView(20) } + } + } # layer keys + } + } + ha:About... = { li:a={{w;a}; {i;a};}; action=About() } + } + } # Window + } # main menu + + li:popups { +# context sensitive right click: popup per object type under the cursor + + ha:popup-obj-line { + li:submenu { + ha:Edit properties { action=propedit(object) } + ha:Edit flags... { action=FlagEdit() } + ha:Set Same Style { action=SetSame() } + - + ha:Remove line { li:action={Mode(Save); Mode(Remove); Mode(Notify); Mode(Restore)} } + ha:Copy to buffer { li:action={Unselect(All); Select(object); PasteBuffer(Clear); PasteBuffer(AddSelected); Unselect(All); Mode(PasteBuffer) } } + ha:Move to current layer { action=MoveToCurrentLayer(object) } + } + } + + ha:popup-obj-arc { + li:submenu { + ha:Edit properties { action=propedit(object) } + ha:Edit flags... { action=FlagEdit() } + ha:Set Same Style { action=SetSame() } + - + ha:Remove arc { li:action={Mode(Save); Mode(Remove); Mode(Notify); Mode(Restore)} } + ha:Copy to buffer { li:action={Unselect(All); Select(object); PasteBuffer(Clear); PasteBuffer(AddSelected); Unselect(All); Mode(PasteBuffer) } } + ha:Move to current layer { action=MoveToCurrentLayer(object) } + } + } + + ha:popup-obj-polygon { + li:submenu { + ha:Edit properties { action=propedit(object) } + ha:Edit flags... { action=FlagEdit() } + - + ha:Remove polygon { li:action={Mode(Save); Mode(Remove); Mode(Notify); Mode(Restore)} } + ha:Copy to buffer { li:action={Unselect(All); Select(object); PasteBuffer(Clear); PasteBuffer(AddSelected); Unselect(All); Mode(PasteBuffer) } } + ha:Move to current layer { action=MoveToCurrentLayer(object) } + } + } + + ha:popup-obj-text { + li:submenu { + ha:Edit properties { action=propedit(object) } + ha:Edit flags... { action=FlagEdit() } + ha:Edit text... { li:a={{e;t};}; action=ChangeName(Object) } + ha:Set Same Style { action=SetSame() } + ha:Change font... { li:a={{e;o};} action=FontSel(Object) } + - + ha:Remove text { li:action={Mode(Save); Mode(Remove); Mode(Notify); Mode(Restore)} } + ha:Copy to buffer { li:action={Unselect(All); Select(object); PasteBuffer(Clear); PasteBuffer(AddSelected); Unselect(All); Mode(PasteBuffer) } } + ha:Move to current layer { action=MoveToCurrentLayer(object) } + } + } + + ha:popup-obj-padstack { + li:submenu { + ha:Edit properties { action=propedit(object) } + ha:Edit geometry/prototype {action=padstackedit } + ha:Edit flags... { action=FlagEdit() } + ha:Set Same Style { action=SetSame() } + - + ha:Remove padstack { li:action={Mode(Save); Mode(Remove); Mode(Notify); Mode(Restore)} } + ha:Break up padstack { action=PadstackBreakup(object) } + ha:Copy to buffer { li:action={Unselect(All); Select(object); PasteBuffer(Clear); PasteBuffer(AddSelected); Unselect(All); Mode(PasteBuffer) } } + } + } + + ha:popup-obj-subcircuit { + li:submenu { + ha:Edit properties { action=propedit(object) } + ha:External editor... { action=extedit(object) } + ha:Edit flags... { action=FlagEdit() } + ha:Edit layer bindings... { action=LayerBinding() } + ha:Change refdes { li:a={{e;r};}; action=ChangeName(Refdes) } + ha:Edit padstack prototypes... = { action=pstklib(object) } + +#TODO: replace from lib + - + ha:Remove subcircuit { li:action={Mode(Save); Mode(Remove); Mode(Notify); Mode(Restore)} } + ha:Copy to buffer { li:action={Unselect(All); Select(object); PasteBuffer(Clear); PasteBuffer(AddSelected); Unselect(All); Mode(PasteBuffer) } } + ha:Move to other side { action=Flip(object) } + } + } + + ha:popup-obj-misc { + li:submenu { + ha:Operations on selections { + li:submenu { + ha:Unselect all objects = { action=Unselect(All) } + ha:Remove selected objects = { action=RemoveSelected() } + ha:Copy selection to buffer = { li:action={GetXY(Click to set the snap point for this buffer); PasteBuffer(Clear); PasteBuffer(AddSelected); Mode(PasteBuffer)} } + ha:Cut selection to buffer = { li:action={GetXY(Click to set the snap point for this buffer); PasteBuffer(Clear); PasteBuffer(AddSelected); RemoveSelected(); Mode(PasteBuffer)} } + ha:Convert selection to subcircuit = { action=Select(ConvertSubc) } + ha:Auto place selected subcircuits = { action=AutoPlaceSelected() } + ha:Autoroute selected subcircuits = { action=AutoRoute(SelectedRats) } + ha:Rip up selected auto-routed tracks = { action=RipUp(Selected) } + ha:Rotate selected = { action={GetXY(Click to set the snap point for this buffer); PasteBuffer(Clear); PasteBuffer(AddSelected); RemoveSelected(); Mode(PasteBuffer) FreeRotateBuffer(); Mode(PasteBuffer); PasteBuffer(Tolayout, crosshair); } } + } + } + ha:Operations on this location { + li:submenu { + ha:Generate object report = { li:action={GetXY(Click on the object); Report(Object)} } + } + } + - + ha:Undo last operation = { action=Undo() } + ha:Redo last undone operation = { action=Redo() } + } + } # popup-obj-misc + + ha:layer { + li:submenu { + ha:Layer comb. flags... = { action=EditLayer() } + ha:Layer properties... = { action=Propedit(layer) } + ha:Grouping... (layer preferences) = { action=Preferences("layers") } + - + ha:Move up (within group) = { action=MoveLayer(c, step-) } + ha:Move down (within group) = { action=MoveLayer(c, step+) } + - + ha:Remove layer = { action=MoveLayer(c, -1) } + ha:Insert new, before this layer = { action={ MoveLayer(-1, c); EditLayer() } } + ha:Insert new, after this layer = { action={ MoveLayer(-1, c); MoveLayer(c, step+); EditLayer() } } + - + ha:all layers on = { action=ToggleView(all, vis, set) } + ha:all layers off = { action=ToggleView(all, vis, clear) } + } + } # layer + + ha:group { + li:submenu { + ha:Group name & type... = { action=EditGroup(@) } + ha:Group properties... = { action=Propedit(layergrp) } + ha:Grouping... (layer preferences) = { action=Preferences("layers") } + - + ha:Duplicate group = { action={ DupGroup(@) } } + ha:Create new group { + li:submenu { + ha:Boundary, unplated, routed = { action={ NewGroup(boundary, global, uroute) } } + ha:Boundary, plated, routed = { action={ NewGroup(boundary, global, proute) } } + ha:Mech, unplated, routed = { action={ NewGroup(mech, global, uroute, auto) } } + ha:Mech, plated, routed = { action={ NewGroup(mech, global, proute, auto) } } + ha:Doc, top side = { action={ NewGroup(doc, top) } } + ha:Doc, bottom side = { action={ NewGroup(doc, bottom) } } + ha:Doc, global = { action={ NewGroup(doc, global) } } + } + } + ha:Remove group = { action={ DelGroup(@) } } + - + ha:Insert new layer = { action={ MoveLayer(-1, gi); EditLayer() } } + ha:Append new layer = { action={ MoveLayer(-1, ga); EditLayer() } } + - + ha:expand groups = { action=ToggleView(all, open, set) } + ha:collapse groups = { action=ToggleView(all, open, clear) } + ha:all layers on = { action=ToggleView(all, vis, set) } + ha:all layers off = { action=ToggleView(all, vis, clear) } + } + } # group + + } # popups +} # root Index: tags/2.1.2/src/pcb-menu-gtk.lht =================================================================== --- tags/2.1.2/src/pcb-menu-gtk.lht (nonexistent) +++ tags/2.1.2/src/pcb-menu-gtk.lht (revision 24813) @@ -0,0 +1,636 @@ +# Old, OBSOLETE, somewhat unmaintained menu file for users who got used +# to the old gtk menus and have not yet switched to the new, unified default +# menu file, pcb-menu-default.lht +ha:{ + li:mouse { + li:left { + li:press = { Mode(Notify) } + li:press-shift = { Mode(Notify) } + li:press-ctrl = { Mode(Save); Mode(None); Mode(Restore); Mode(Notify) } + li:press-shift-ctrl = { Mode(Save); Mode(Remove); Mode(Notify); Mode(Restore) } + li:release = { Mode(Release) } + li:release-shift = { Mode(Release) } + li:release-ctrl = { Mode(Release) } + li:release-shift-ctrl = { Mode(Release) } + } + li:right { + li:press = { Pan(1) } + li:release = { Pan(0) } + li:press-shift = { Popup(popup1) } + li:press-ctrl = { Display(CycleCrosshair) } + } + li:middle { + li:press = { Mode(Stroke) } + li:release = { Mode(Release) } + li:press-ctrl = { Mode(Save); Mode(Copy); Mode(Notify) } + li:release-ctrl = { Mode(Notify); Mode(Restore); } + li:press-shift-ctrl = { conf(toggle, editor/rubber_band_mode, design); Mode(Save); Mode(Move); Mode(Notify) } + li:release-shift-ctrl = { Mode(Notify); Mode(Restore); conf(toggle, editor/rubber_band_mode, design) } + } + li:scroll-up { + li:press = { Zoom(0.8) } + li:press-shift = { Scroll(up) } + li:press-ctrl = { Scroll(left) } + } + li:scroll-down { + li:press = { Zoom(1.25) } + li:press-shift = { Scroll(down) } + li:press-ctrl = { Scroll(right) } + } +# If you want zoom to center, do this instead. + #ha:scroll-up = { li:{} = {Zoom(0.8); Center()} } + #ha:scroll-down = { li:{} = {Zoom(1.25); Center()} } + } + + li:main_menu { + ### File Menu + ha:File { + li:submenu { + ha:Start New Layout = { a=Ctrln; action=New() } + ha:Revert = { action=Load(Revert,none); tip=Revert to the layout stored on disk } + - + ha:Load layout = { action=Load(Layout); tip=Load a layout from a file } + - + ha:Save Layout = { a={Ctrls}; action=Save(Layout); tip=Saves current layout } + ha:Save Layout As... = { a={Shift Ctrls}; action=Save(LayoutAs); tip=Saves current layout into a new file } + - + ha:Import { + li:submenu { + ha:Import gschem schematics = { action=Import() } + ha:Import tEDAx schematics = { action=LoadTedaxFrom(netlist) } + ha:Import KiCad/eeschema schematics = { action=LoadEeschemaFrom() } + ha:Import mentor graphics schematics = { action=LoadMentorFrom() } + ha:Load subcircuit data to paste-buffer = { li:action={PasteBuffer(Clear); Load(ElementTobuffer)} } + ha:Load layout data to paste-buffer = { li:action={PasteBuffer(Clear); Load(LayoutTobuffer)} } + ha:Load netlist file = { action=Load(Netlist) } + ha:Load vendor resource file = { action=LoadVendorFrom() } + ha:Load routed dsn or ses file = { action=LoadDsnFrom() } + ha:Load MUCS pl file = { action=LoadMucsFrom() } + ha:Load TinyCAD .net file = { action=LoadTinyCADFrom() } + ha:Load LTSpice .net and .asc files = { action=LoadLTSpiceFrom() } + ha:Load HP-GL plot to paste-buffer = { action=LoadHPGLFrom() } + ha:Load Hyperlynx .hyp file = { action=LoadHypFrom() } + } + } + - + ha:Save connection data of { + li:submenu { + ha:a single element = { action=Save(ElementConnections)} + ha:all elements = { action=Save(AllConnections) } + ha:unused pins = { action=Save(AllUnusedPins) } + ha:netlist patch for back annotation = {a=Alt Ctrlb; action=SavePatch() } + } + } + ha:Print layout... = { action=Print()} + ha:Export layout... = { action=ExportGUI()} + - + ha:Preferences... = { action=DoWindows(Preferences)} + ha:Maintenance { + li:submenu { + ha:Calibrate Printer... = { action=PrintCalibrate() } + ha:Re-scan the footprint library = { action=fp_rehash() } + - + ha:Edit current font = { action=FontEdit() } + ha:Edit on-disk font = { action={ LoadFontFrom("", 126); conf(set, design/text_font_id, 126, design); FontEdit() } } + ha:Save font from font editor = { action=FontSave() } + } + } + - + ha:Quit Program = { a=Ctrlq; action=Quit() } + } + } + + ha:Edit { + li:submenu { + ha:Undo last operation = { a=u; action=Undo() } + ha:Redo last undone operation = { a=Shiftr; action=Redo() } + ha:Clear undo-buffer = { a=Shift Ctrlu; action=Undo(ClearList) } + - + ha:Cut selection to buffer = { a=Ctrlx; li:action={ GetXY(Click to set the snap point for this buffer); PasteBuffer(Clear); PasteBuffer(AddSelected); RemoveSelected(); Mode(PasteBuffer) } } + ha:Copy selection to buffer = { a=Ctrlc; li:action={ GetXY(Click to set the snap point for this buffer); PasteBuffer(Clear); PasteBuffer(AddSelected); Unselect(All); Mode(PasteBuffer) } } + ha:Paste buffer to layout = { a=Ctrlv; action=Mode(PasteBuffer) } + - + ha:Unselect all = { a=Shift Alta; action=Unselect(All) } + ha:Select all visible = { a=Alta; action=Select(All) } + - + ha:Change font on layout = { a=Alt Ctrlf; action=FontSel(Object) } + ha:Edit name of { + li:submenu { + ha:text on layout = { a=n; action=ChangeName(Object) } + ha:pin on layout = { a=Shift Ctrln; action=ChangeName(Object, Number) } + ha:layout = { action=ChangeName(Layout) } + ha:active layer = { action=ChangeName(Layer) } + } + } + ha:Edit attributes of { + li:submenu { + ha:Layout = { action=Attributes(Layout) } + ha:CurrentLayer = { action=Attributes(Layer) } + ha:Subcircuit = { action=Attributes(Subc) } + } + } + ha:Route Styles { + li:submenu { + @routestyles + - + ha:Edit... = { action=AdjustStyle(0) } + } + } + ha:Subcircuit { + li:submenu { + ha:Layer bindings... = { action=LayerBinding() } + ha:External editor... = { li:action={ GetXY(Click on the subcircuit to edit); extedit(object) } } + } + } + ha:Object flags... = { action=FlagEdit() } + } + } # Edit + + ha:View { + li:submenu { + ha:Enable visible grid = { checked=editor/draw_grid; action=conf(toggle, editor/draw_grid, design) } + ha:Enable local grid = { checked=plugins/hid_gtk/local_grid/enable; action=conf(toggle, plugins/hid_gtk/local_grid/enable, design) } + ha:Grid units { + li:submenu { + ha:mil = { checked=ChkGridUnits(mil); action=SetUnits(mil); update_on={editor/grid_unit} } + ha:mm = { checked=ChkGridUnits(mm); action=SetUnits(mm); update_on={editor/grid_unit} } + } + } + ha:Grid size = { + li:submenu { + ha:No Grid = { checked=ChkGridSize(none); action=SetValue(Grid,1); update_on={editor/grid} } + - + ha:0.1 mil = { checked=ChkGridSize(0.1mil); li:action={SetUnits(mil); SetValue(Grid,0.1mil)}; update_on={editor/grid}} + ha:1 mil = { checked=ChkGridSize(1mil); li:action={SetUnits(mil); SetValue(Grid,1mil)}; update_on={editor/grid} } + ha:5 mil = { checked=ChkGridSize(5mil); li:action={SetUnits(mil); SetValue(Grid,5mil)}; update_on={editor/grid} } + ha:10 mil = { checked=ChkGridSize(10mil); li:action={SetUnits(mil); SetValue(Grid,10mil)}; update_on={editor/grid} } + ha:25 mil = { checked=ChkGridSize(25mil); li:action={SetUnits(mil); SetValue(Grid,25mil)}; update_on={editor/grid} } + ha:50 mil = { checked=ChkGridSize(50mil); li:action={SetUnits(mil); SetValue(Grid,50mil)}; update_on={editor/grid} } + ha:100 mil = { checked=ChkGridSize(100mil); li:action={SetUnits(mil); SetValue(Grid,100mil)}; update_on={editor/grid} } + - + ha:0.01 mm = { checked=ChkGridSize(0.01mm); li:action={SetUnits(mm); SetValue(Grid,0.01mm)}; update_on={editor/grid} } + ha:0.05 mm = { checked=ChkGridSize(0.05mm); li:action={SetUnits(mm); SetValue(Grid,0.05mm)}; update_on={editor/grid} } + ha:0.1 mm = { checked=ChkGridSize(0.10mm); li:action={SetUnits(mm); SetValue(Grid,0.1mm)}; update_on={editor/grid} } + ha:0.25 mm = { checked=ChkGridSize(0.25mm); li:action={SetUnits(mm); SetValue(Grid,0.25mm)}; update_on={editor/grid} } + ha:0.5 mm = { checked=ChkGridSize(0.50mm); li:action={SetUnits(mm); SetValue(Grid,0.5mm)}; update_on={editor/grid} } + ha:1 mm = { checked=ChkGridSize(1mm); li:action={SetUnits(mm); SetValue(Grid,1mm)}; update_on={editor/grid} } + - + ha:Grid -5mil = { a=Shiftg; action=SetValue(Grid,-5,mil) } + ha:Grid +5mil = { a=g; action=SetValue(Grid,+5,mil) } + ha:Grid -0.05mm = { a=Shift Ctrlg; action=SetValue(Grid,-0.05,mm) } + ha:Grid +0.05mm = { a=Ctrlg; action=SetValue(Grid,+0.05,mm) } + } + } + ha:Grid properties = { + li:submenu { + ha:Enable local grid = { checked=plugins/hid_gtk/local_grid/enable; action=conf(toggle, plugins/hid_gtk/local_grid/enable, design) } + - + ha:local grid radius 4 = { checked={conf(iseq, plugins/hid_gtk/local_grid/radius, 4)}; li:action={conf(set, plugins/hid_gtk/local_grid/radius, 4, design); conf(set, plugins/hid_gtk/local_grid/enable, 1, design) }; update_on={} } + ha:local grid radius 8 = { checked={conf(iseq, plugins/hid_gtk/local_grid/radius, 8)}; li:action={conf(set, plugins/hid_gtk/local_grid/radius, 8, design); conf(set, plugins/hid_gtk/local_grid/enable, 1, design) }; update_on={} } + ha:local grid radius 16 = { checked={conf(iseq, plugins/hid_gtk/local_grid/radius, 16)}; li:action={conf(set, plugins/hid_gtk/local_grid/radius, 16, design); conf(set, plugins/hid_gtk/local_grid/enable, 1, design) }; update_on={} } + ha:local grid radius 32 = { checked={conf(iseq, plugins/hid_gtk/local_grid/radius, 32)}; li:action={conf(set, plugins/hid_gtk/local_grid/radius, 32, design); conf(set, plugins/hid_gtk/local_grid/enable, 1, design) }; update_on={} } + - + ha:sparse global grid = { checked=plugins/hid_gtk/global_grid/sparse; action=conf(toggle, plugins/hid_gtk/global_grid/sparse, design); update_on={} } + ha:global grid density 4 = { checked={conf(iseq, plugins/hid_gtk/global_grid/min_dist_px, 4)}; li:action={conf(set, plugins/hid_gtk/global_grid/min_dist_px, 4, design); conf(set, plugins/hid_gtk/local_grid/enable, 0, design) }; update_on={} } + ha:global grid density 8 = { checked={conf(iseq, plugins/hid_gtk/global_grid/min_dist_px, 8)}; li:action={conf(set, plugins/hid_gtk/global_grid/min_dist_px, 8, design); conf(set, plugins/hid_gtk/local_grid/enable, 0, design) }; update_on={} } + ha:global grid density 16 = { checked={conf(iseq, plugins/hid_gtk/global_grid/min_dist_px, 16)}; li:action={conf(set, plugins/hid_gtk/global_grid/min_dist_px, 16, design); conf(set, plugins/hid_gtk/local_grid/enable, 0, design) }; update_on={} } + } + } + ha:Realign grid = { action={ GetXY(Click to set the grid origin); Display(ToggleGrid) } } + - + ha:Displayed subcircuit ID { + li:submenu { + ha:refdes = { checked=ChkSubcID(); action=Display(SubcID); update_on={editor/name_on_pcb} } + ha:footprint = { checked=ChkSubcID(%a.footprint%); action=Display(SubcID,"%a.footprint%"); update_on={editor/subc_id} } + ha:value = { checked=ChkSubcID(%a.value%); action=Display(SubcID,"%a.value%"); update_on={editor/subc_id} } + ha:refdes+value = { checked=ChkSubcID(%a.refdes%\\n%a.value%); action=Display(SubcID,"%a.refdes%\\\\n%a.value%"); update_on={editor/subc_id} } + } + } + ha:Pins/Via show Name/Number = { a=d; action=Display(PinOrPadName) } + ha:Zoom In 20% = { a=z; action=Zoom(-1.2) } + ha:Zoom Out 20% = { a=Shiftz; action=Zoom(+1.2) } + ha:More zooms and view changes { + li:submenu { + ha:Zoom Max = { a=v; action=Zoom() } + ha:Zoom In 2X = { action=Zoom(-2) } + ha:Zoom Out 2X = { action=Zoom(+2) } + ha:Zoom to 0.1mil/px = { action={Zoom(=0.1mil)} } + ha:Zoom to 0.01mm/px = { action={Zoom(=0.01mm)} } + ha:Zoom to 1mil/px = { action={Zoom(=1mil)} } + ha:Zoom to 0.05mm/px = { action={Zoom(=0.05mm)} } + ha:Zoom to 2.5mil/px = { action={Zoom(=2.5mil)} } + ha:Zoom to 0.1mm/px = { action={Zoom(=0.1mm)} } + ha:Zoom to 10mil/px = { action={Zoom(=10mil)} } + ha:Zoom In 20% and center = { li:action={Zoom(-1.2); Center()} } + ha:Zoom Out 20% and center= { li:action={Zoom(+1.2); Center()} } + ha:Flip up/down = { checked=editor/view/flip_y; a=Tab; action=SwapSides(V) } + ha:Flip left/right = { checked=editor/view/flip_x; a=ShiftTab; action=SwapSides(H) } + ha:Spin 180 degrees = { a=CtrlTab; action=SwapSides(R) } + ha:Swap Sides = { a=Ctrl ShiftTab; action=SwapSides() } + ha:Center cursor = { a=c; action=Center() } + } + } + - + ha:Shown Layers { + li:submenu { + @layerview + - + ha:Edit Layer Groups = { action=DoWindows(Preferences, 1, "User PoV/Layers") } + } + } + ha:Current Layer { + li:submenu { + anon2=@layerpick + - + ha:Delete current layer = { action=MoveLayer(c,-1) } + ha:Add new layer = { action=MoveLayer(-1,c) } + ha:Move current layer up = { action=MoveLayer(c,step-) } + ha:Move current layer down= { action=MoveLayer(c,step+) } + } + } + ha:Full screen = { checked=editor/fullscreen; a=\\; action=fullscreen(toggle) } + } + } # View + + ha:Settings = { + li:submenu { + ha:'All-direction' lines = { checked=editor/all_direction_lines; a=.; action=conf(toggle, editor/all_direction_lines, design) } + ha:Auto swap line start angle = { checked=editor/swap_start_direction; action=conf(toggle, editor/swap_start_direction, design) } + ha:Orthogonal moves = { checked=editor/orthogonal_moves; action=conf(toggle, editor/orthogonal_moves, design) } + ha:Crosshair snaps to pins and pads = { checked=editor/snap_pin; action=conf(toggle, editor/snap_pin, design) } + ha:Crosshair snaps to off-grid points on lines = { checked=editor/snap_offgrid_line; action=conf(toggle, editor/snap_offgrid_line, design) } + ha:Crosshair shows DRC clearance = { checked=editor/show_drc; action=conf(toggle, editor/show_drc, design) } + ha:Auto enforce DRC clearance = { checked=editor/auto_drc; action=conf(toggle, editor/auto_drc, design) } + ha:Lock floaters = { checked=editor/lock_names; action=conf(toggle, editor/lock_names, design) } + ha:Only floaters = { checked=editor/only_names; action=conf(toggle, editor/only_names, design) } + ha:Hide floaters = { checked=editor/hide_names; action=conf(toggle, editor/hide_names, design) } + ha:Mincut on shorts = { checked=plugins/mincut/enable; action=conf(toggle, plugins/mincut/enable, design) } + ha:Libstroke gestures on middle button = { checked=editor/enable_stroke; action=conf(toggle, editor/enable_stroke, design) } + - + ha:Rubber band mode = { checked=editor/rubber_band_mode; action=conf(toggle, editor/rubber_band_mode, design) } + ha:Rubber band keeps middle line dir= { checked=editor/rubber_band_keep_midlinedir; action=conf(toggle, editor/rubber_band_keep_midlinedir, design) } + ha:Auto-zero delta measurements = { checked=editor/local_ref; action=conf(toggle, editor/local_ref, design) } + ha:New lines, arcs clear polygons = { checked=editor/clear_line; action=conf(toggle, editor/clear_line, design) } + ha:New polygons clear polygons = { checked=editor/clear_polypoly; action=conf(toggle, editor/clear_polypoly, design) } + ha:New polygons are full ones = { checked=editor/full_poly; action=conf(toggle, editor/full_poly, design) } + ha:Show autorouter trials = { checked=editor/live_routing; action=conf(toggle, editor/live_routing, design) } + ha:Highlighting on line, arc points = { checked=editor/highlight_on_point; action=conf(toggle, editor/highlight_on_point, design) } + ha:Wireframe draw = { checked=editor/wireframe_draw; a=Ctrlw; action=conf(toggle, editor/wireframe_draw, design) } + ha:Thin draw = { checked=editor/thin_draw; a=|; action=conf(toggle, editor/thin_draw, design) } + ha:Thin draw poly = { checked=editor/thin_draw_poly; a=Ctrl Shiftp; action=conf(toggle, editor/thin_draw_poly, design) } + ha:Check polygons = { checked=editor/check_planes; action=conf(toggle, editor/check_planes, design) } + ha:Brave mode = { action=brave() } + - + ha:Vendor drill mapping = { checked=plugins/vendor/enable; action=conf(toggle, plugins/vendor/enable, design) } + ha:Import New Elements at = { + li:submenu { + ha:Center = { action=Import(setnewpoint,center) } + ha:Mark = { action=Import(setnewpoint,mark) } + ha:Crosshair = { action=Import(setnewpoint) } + - + ha:Set Dispersion = { action=Import(setdisperse) } + } + } + } + } #Settings + + ha:Select { + li:submenu { + ha:Select all visible objects = { action=Select(All) } + ha:Select all connected objects = { action=Select(Connection) } + - + ha:Unselect all objects = { action=Unselect(All) } + ha:unselect all connected objects = { action=Unselect(Connection) } + - +#TODO: this is gtk-specific + ha:Advanced search and select= { action=DoWindows(search) } + - + ha:Auto-place selected subcircuits = { a=Ctrlp; action=AutoPlaceSelected() } + ha:Disperse all subcircuits = { action=DisperseElements(All) } + ha:Disperse selected subcircuits = { action=DisperseElements(Selected) } + - + ha:Move selected subcircuits to other side= { a=Shiftb; action=Flip(SelectedElements) } + ha:Move selected to current layer = { a=Shiftm; action=MoveToCurrentLayer(Selected) } + ha:Remove selected objects = { a=ShiftDelete; action=RemoveSelected() } + ha:Convert selection to subcircuit = { action=Select(ConvertSubc) } + ha:Convert selection to padstack = { li:action={PadstackConvert(selected); Mode(PasteBuffer);} } + - + ha:Optimize selected rats = { li:action={DeleteRats(SelectedRats); AddRats(SelectedRats) } } + ha:Auto-route selected rats = { a=Altr; action=AutoRoute(SelectedRats) } + ha:Rip up selected auto-routed tracks = { action=RipUp(Selected) } + - + ha:Edit properties of selected... = { a=Ctrle; action=PropEdit(Selected) } + ha:Change size of selected objects { + li:submenu { + ha:Lines -10 mil = { li:action={ChangeSize(SelectedLines,-10,mil); ChangeSize(SelectedArcs,-10,mil)} } + ha:Lines +10 mil = { li:action={ChangeSize(SelectedLines,+10,mil); ChangeSize(SelectedArcs,+10,mil)} } + ha:Pads -10 mil = { action=ChangeSize(SelectedPads,-10,mil) } + ha:Pads +10 mil = { action=ChangeSize(SelectedPads,+10,mil) } + ha:Pins -10 mil = { action=ChangeSize(SelectedPins,-10,mil) } + ha:Pins +10 mil = { action=ChangeSize(SelectedPins,+10,mil) } + ha:Texts -10 mil = { action=ChangeSize(SelectedTexts,-10,mil) } + ha:Texts +10 mil = { action=ChangeSize(SelectedTexts,+10,mil) } + ha:Vias -10 mil = { action=ChangeSize(SelectedVias,-10,mil) } + ha:Vias +10 mil = { action=ChangeSize(SelectedVias,+10,mil) } + } + } + - + ha:Change drilling hole of selected padstacks { + li:submenu { + ha:Vias -10 mil = { action=ChangeDrillSize(SelectedPadstacks,-10,mil) } + ha:Vias +10 mil = { action=ChangeDrillSize(SelectedPadstacks,+10,mil) } + } + } + - + ha:Cycle object being dragged = { a=x; action=CycleDrag() } + } + } # Select + + ha:Buffer { + li:submenu { + ha:Cut selection to buffer = { li:action={GetXY(Click to set the snap point for this buffer); PasteBuffer(Clear); PasteBuffer(AddSelected); RemoveSelected(); Mode(PasteBuffer)} } + ha:Paste buffer to layout = { action=Mode(PasteBuffer) } + - + ha:Rotate buffer 90 deg CCW = { a=ShiftF7; li:action={Mode(PasteBuffer); PasteBuffer(Rotate,1)} } + ha:Rotate buffer 90 deg CW = { li:action={Mode(PasteBuffer); PasteBuffer(Rotate,3)} } + ha:Arbitrarily Rotate Buffer = { li:action={Mode(PasteBuffer); FreeRotateBuffer()} } + ha:Mirror buffer (up/down) = { li:action={Mode(PasteBuffer); PasteBuffer(Mirror)} } + ha:Mirror buffer (left/right) = { li:action={Mode(PasteBuffer); PasteBuffer(Rotate,1); PasteBuffer(Mirror); PasteBuffer(Rotate,3)} } + - + ha:Clear buffer = { action=PasteBuffer(Clear) } + ha:Convert buffer to subcircuit = { action=PasteBuffer(ConvertSubc) } + ha:Convert buffer to padstack = { li:action={PadstackConvert(buffer); Mode(PasteBuffer);} } + ha:Break buffer subcircuits to pieces = { action=PasteBuffer(Restore) } + ha:Save buffer subcircuits to file = { action=Save(PasteBuffer) } + ha:Layer bindings... = { action=LayerBinding(buffer) } + - + ha:Select Buffer \#1 = { checked=ChkBuffer(1); a=Shift1; action=PasteBuffer(1); update_on={editor/buffer_number} } + ha:Select Buffer \#2 = { checked=ChkBuffer(2); a=Shift2; action=PasteBuffer(2); update_on={editor/buffer_number} } + ha:Select Buffer \#3 = { checked=ChkBuffer(3); a=Shift3; action=PasteBuffer(3); update_on={editor/buffer_number} } + ha:Select Buffer \#4 = { checked=ChkBuffer(4); a=Shift4; action=PasteBuffer(4); update_on={editor/buffer_number} } + ha:Select Buffer \#5 = { checked=ChkBuffer(5); a=Shift5; action=PasteBuffer(5); update_on={editor/buffer_number} } + } + } # Buffer + + ha:Connects = { + li:submenu { + ha:Lookup connection to object = { a=Ctrlf; li:action={GetXY(Click on the object); Connection(Find)} } + ha:Reset scanned pads/pins/vias = { li:action={Connection(ResetPinsViasAndPads); Display(Redraw)} } + ha:Reset scanned lines/polygons = { li:action={Connection(ResetLinesAndPolygons); Display(Redraw)} } + ha:Reset all connections = { a=Shiftf; li:action={Connection(Reset); Display(Redraw)} } + - + ha:Optimize rats nest = { a=o; li:action={Atomic(Save); DeleteRats(AllRats); Atomic(Restore); AddRats(AllRats); Atomic(Block)} } + ha:Erase rats nest = { a=e; action=DeleteRats(AllRats) } + ha:Erase selected rats = { a=Shifte; action=DeleteRats(SelectedRats) } + - + ha:Auto-route selected rats = { action=AutoRoute(Selected) } + ha:Auto-route all rats = { action=AutoRoute(AllRats) } + ha:Rip up all auto-routed tracks = { action=RipUp(All) } + - + ha:Optimize routed tracks { + li:submenu { + ha:Auto-Optimize = { a={Ctrl=}; action=djopt(auto) } + ha:Debumpify = { action=djopt(debumpify) } + ha:Unjaggy = { action=djopt(unjaggy) } + ha:Vianudge = { action=djopt(vianudge) } + ha:Viatrim = { action=djopt(viatrim) } + ha:Ortho pull = { action=djopt(orthopull) } + ha:Simple optimization = { a={=}; action=djopt(simple) } + ha:Miter = { action=djopt(miter) } + ha:Puller = { a=y; action=Puller() } + ha:Global Puller { + li:submenu { + ha:Selected = { action=GlobalPuller(selected) } + ha:Found = { action=GlobalPuller(found) } + ha:All = { action=GlobalPuller() } + } + } + - + ha:Only autorouted nets = { checked=plugins/djopt/auto_only; action=conf(toggle, plugins/djopt/auto_only, design) } + } + } + - + ha:Design Rule Checker = { action=DRC() } + - + ha:Apply vendor drill mapping = { action=ApplyVendor() } + - + ha:Design changes (back annotation) { + li:submenu { + ha:Swap nets on two selected pins = { a=Shiftx; action=net(swap) } + ha:Replace footprint = { a=Alt Shiftf; action=ReplaceFootprint() } + } + } + } + } # Connects + + ha:Plugins { + li:submenu { + ha:Manage plugins... = { a=Altp; action=ManagePlugins() } + } + } # Plugins + + ha:Info = { + li:submenu { + ha:Generate object report = { a=Ctrlr; action=ReportObject() } + ha:Generate drill summary = { action=Report(DrillReport) } + ha:Report found pins\/pads = { action=Report(FoundPins) } + ha:Key Bindings { + li:submenu { + ha:Remove = { a=Delete; li:action={Mode(Save); Mode(Remove); Mode(Notify); Mode(Restore)} } + ha:Remove Selected = { a=BackSpace; action=RemoveSelected() } + ha:Remove Connected = { a=ShiftBackSpace; li:action={Atomic(Save); Connection(Reset); Atomic(Restore); Unselect(All); Atomic(Restore); Connection(Find); Atomic(Restore); Select(Connection); Atomic(Restore); RemoveSelected(); Atomic(Restore); Connection(Reset); Atomic(Restore); Unselect(All); Atomic(Block)} } + ha:Remove Connected = { li:action={Atomic(Save); Connection(Reset); Atomic(Restore); Unselect(All); Atomic(Restore); Connection(Find); Atomic(Restore); Select(Connection); Atomic(Restore); RemoveSelected(); Atomic(Restore); Connection(Reset); Atomic(Restore); Unselect(All); Atomic(Block)} } + ha:Set Same = { a=a; action=SetSame() } + ha:Flip Object = { a=b; action=Flip(Object) } + ha:Find Connections = { a=f; li:action={Connection(Reset); Connection(Find)} } + ha:ChangeJoin Object = { a=j; action=ChangeJoin(Object) } + ha:ChangeJoin SelectedObject = { a=Shiftj; action=ChangeJoin(SelectedObjects) } + ha:Clear Object +2 mil = { a=k; action=ChangeClearSize(Object,+2,mil) } + ha:Clear Object -2 mil = { a=Shiftk; action=ChangeClearSize(Object,-2,mil) } + ha:Clear Selected +2 mil = { a=Ctrlk; action=ChangeClearSize(SelectedObjects,+2,mil) } + ha:Clear Selected -2 mil = { a=Shift Ctrlk; action=ChangeClearSize(SelectedObjects,-2,mil) } + ha:Line Tool size +5 mil = { a=l; action=SetValue(LineSize,+5,mil) } + ha:Line Tool size -5 mil = { a=Shiftl; action=SetValue(LineSize,-5,mil) } + ha:Move Object to current layer = { a=m; action=MoveToCurrentLayer(Object) } + ha:MarkCrosshair = { a=Ctrlm; action=MarkCrosshair() } + ha:Select shortest rat = { a=Shiftn; action=AddRats(Close) } + ha:AddRats to selected pins = { a=Shifto; li:action={Atomic(Save); DeleteRats(AllRats); Atomic(Restore); AddRats(SelectedRats); Atomic(Block)} } + ha:Polygon PreviousPoint = { a=p; action=Polygon(PreviousPoint) } + ha:Polygon Close = { a=Shiftp; action=Polygon(Close) } + ha:ChangeSizes to Route style = { a=Shifty; action=ChangeSizes(Object,style,mil) } + ha:ChangeSize +5 mil = { a=s; action=ChangeSize(Object,+5,mil) } + ha:ChangeSize -5 mil = { a=Shifts; action=ChangeSize(Object,-5,mil) } + ha:ChangeDrill +5 mil = { a=Alts; action=ChangeDrillSize(Object,+5,mil) } + ha:ChangeDrill -5 mil = { a=Alt Shifts; action=ChangeDrillSize(Object,-5,mil) } + ha:Text Tool scale +10 mil = { a=t; action=SetValue(TextScale,+10,mil) } + ha:Text Tool scale -10 mil = { a=Shiftt; action=SetValue(TextScale,-10,mil) } + ha:Route radius +0.5 = { a=Altc; action=conf(delta, editor/route_radius, +0.5, design); } + ha:Route radius -0.5 = { a=Alt Shiftc; action=conf(delta, editor/route_radius, -0.5, design); } + ha:AddRats Selected = { a=Shiftw; action=AddRats(SelectedRats) } + ha:Add All Rats = { a=w; action=AddRats(AllRats) } + ha:Cycle Clip = { a=/; action=Display(CycleClip) } + ha:Arrow Mode = { a=space; checked=ChkMode(arrow); action=Mode(Arrow); update_on={editor/mode} } + ha:Temp Arrow ON = { a=[; li:action={Mode(Save); Mode(Arrow); Mode(Notify)} } + ha:Temp Arrow OFF = { a=]; li:action={Mode(Release); Mode(Restore)} } + - + ha:Step Up = { a=Up; action=Cursor(Warp,0,1,grid) } + ha:Step Down = { a=Down; action=Cursor(Warp,0,-1,grid) } + ha:Step Left = { a=Left; action=Cursor(Warp,-1,0,grid) } + ha:Step Right = { a=Right; action=Cursor(Warp,1,0,grid) } + ha:Step +Up = { a=ShiftUp; action=Cursor(Pan,0,50,view) } + ha:Step +Down = { a=ShiftDown; action=Cursor(Pan,0,-50,view) } + ha:Step +Left = { a=ShiftLeft; action=Cursor(Pan,-50,0,view) } + ha:Step +Right = { a=ShiftRight; action=Cursor(Pan,50,0,view) } + ha:Click = { a=Enter; li:action={Mode(Notify); Mode(Release)} } + - + ha:layer keys { + li:submenu { + ha:Select Layer 1 = { a=1; action=SelectLayer(1) } + ha:Select Layer 2 = { a=2; action=SelectLayer(2) } + ha:Select Layer 3 = { a=3; action=SelectLayer(3) } + ha:Select Layer 4 = { a=4; action=SelectLayer(4) } + ha:Select Layer 5 = { a=5; action=SelectLayer(5) } + ha:Select Layer 6 = { a=6; action=SelectLayer(6) } + ha:Select Layer 7 = { a=7; action=SelectLayer(7) } + ha:Select Layer 8 = { a=8; action=SelectLayer(8) } + ha:Select Layer 9 = { a=9; action=SelectLayer(9) } + ha:Select Layer 10 = { a=0; action=SelectLayer(10) } + ha:Select Layer 11 = { a=Alt1; action=SelectLayer(11) } + ha:Select Layer 12 = { a=Alt2; action=SelectLayer(12) } + ha:Select Layer 13 = { a=Alt3; action=SelectLayer(13) } + ha:Select Layer 14 = { a=Alt4; action=SelectLayer(14) } + ha:Select Layer 15 = { a=Alt5; action=SelectLayer(15) } + ha:Select Layer 16 = { a=Alt6; action=SelectLayer(16) } + ha:Select Layer 17 = { a=Alt7; action=SelectLayer(17) } + ha:Select Layer 18 = { a=Alt8; action=SelectLayer(18) } + ha:Select Layer 19 = { a=Alt9; action=SelectLayer(19) } + ha:Select Layer 20 = { a=Alt0; action=SelectLayer(20) } + - + ha:Toggle Layer 1 = { a=Ctrl1; action=ToggleView(1) } + ha:Toggle Layer 2 = { a=Ctrl2; action=ToggleView(2) } + ha:Toggle Layer 3 = { a=Ctrl3; action=ToggleView(3) } + ha:Toggle Layer 4 = { a=Ctrl4; action=ToggleView(4) } + ha:Toggle Layer 5 = { a=Ctrl5; action=ToggleView(5) } + ha:Toggle Layer 6 = { a=Ctrl6; action=ToggleView(6) } + ha:Toggle Layer 7 = { a=Ctrl7; action=ToggleView(7) } + ha:Toggle Layer 8 = { a=Ctrl8; action=ToggleView(8) } + ha:Toggle Layer 9 = { a=Ctrl9; action=ToggleView(9) } + ha:Toggle Layer 10 = { a=Ctrl0; action=ToggleView(10) } + ha:Toggle Layer 11 = { a=Ctrl-Alt1; action=ToggleView(11) } + ha:Toggle Layer 12 = { a=Ctrl-Alt2; action=ToggleView(12) } + ha:Toggle Layer 13 = { a=Ctrl-Alt3; action=ToggleView(13) } + ha:Toggle Layer 14 = { a=Ctrl-Alt4; action=ToggleView(14) } + ha:Toggle Layer 15 = { a=Ctrl-Alt5; action=ToggleView(15) } + ha:Toggle Layer 16 = { a=Ctrl-Alt6; action=ToggleView(16) } + ha:Toggle Layer 17 = { a=Ctrl-Alt7; action=ToggleView(17) } + ha:Toggle Layer 18 = { a=Ctrl-Alt8; action=ToggleView(18) } + ha:Toggle Layer 19 = { a=Ctrl-Alt9; action=ToggleView(19) } + ha:Toggle Layer 20 = { a=Ctrl-Alt0; action=ToggleView(20) } + } + } # layer keys + } + } + } + } # Info + + ha:Window { + li:submenu { + ha:Library = { a=i; action=DoWindows(Library) } + ha:Message Log = { action=DoWindows(Log) } + ha:DRC Check = { action=DoWindows(DRC) } + ha:Netlist = { action=DoWindows(Netlist) } + ha:Command Entry = { a={:}; action=Command() } + ha:Pinout = { a=Shiftd; action=Display(Pinout) } + ha:Font selector = { a=Ctrl Shiftf; action=FontSel() } + - + ha:About... = { action=About() } + } + } # Window + } # main menu + + li:popups { + + ha:popup1 { + li:submenu { + ha:Operations on selections { + li:submenu { + ha:Unselect all objects = { action=Unselect(All) } + ha:Remove selected objects = { action=RemoveSelected() } + ha:Copy selection to buffer = { li:action={GetXY(Click to set the snap point for this buffer); PasteBuffer(Clear); PasteBuffer(AddSelected); Mode(PasteBuffer)} } + ha:Cut selection to buffer = { li:action={GetXY(Click to set the snap point for this buffer); PasteBuffer(Clear); PasteBuffer(AddSelected); RemoveSelected(); Mode(PasteBuffer)} } + ha:Convert selection to subcircuit = { action=Select(ConvertSubc) } + ha:Auto place selected subcircuits = { action=AutoPlaceSelected() } + ha:Autoroute selected subcircuits = { action=AutoRoute(SelectedRats) } + ha:Rip up selected auto-routed tracks = { action=RipUp(Selected) } + ha:Rotate selected = { action={GetXY(Click to set the snap point for this buffer); PasteBuffer(Clear); PasteBuffer(AddSelected); RemoveSelected(); Mode(PasteBuffer) FreeRotateBuffer(); Mode(PasteBuffer); PasteBuffer(Tolayout, crosshair); } } + } + } + ha:Operations on this location { + li:submenu { + ha:Generate object report = { li:action={GetXY(Click on the object); Report(Object)} } + } + } + - + ha:Undo last operation = { action=Undo() } + ha:Redo last undone operation = { action=Redo() } + - + ha:Tools { + li:submenu { + ha:None = { checked=ChkMode(none); action=Mode(None); update_on={editor/mode} } + ha:Via = { checked=ChkMode(via); a=F1; action=Mode(Via); update_on={editor/mode} } + ha:Line = { checked=ChkMode(line); a=F2; action=Mode(Line); update_on={editor/mode} } + ha:Arc = { checked=ChkMode(arc); a=F3; action=Mode(Arc); update_on={editor/mode} } + ha:Text = { checked=ChkMode(text); a=F4; action=Mode(Text); update_on={editor/mode} } + ha:Rectangle = { checked=ChkMode(rectangle); a=F5; action=Mode(Rectangle); update_on={editor/mode} } + ha:Polygon = { checked=ChkMode(polygon); a=F6; action=Mode(Polygon); update_on={editor/mode} } + ha:Polygon Hole = { checked=ChkMode(polygonhole); action=Mode(PolygonHole); update_on={editor/mode} } + ha:Buffer = { checked=ChkMode(pastebuffer); a=F7; action=Mode(PasteBuffer); update_on={editor/mode} } + ha:Remove = { checked=ChkMode(remove); a=F8; action=Mode(Remove); update_on={editor/mode} } + ha:Rotate = { checked=ChkMode(rotate); a=F9; action=Mode(Rotate); update_on={editor/mode} } + ha:Thermal = { checked=ChkMode(thermal); a=F10; action=Mode(Thermal); update_on={editor/mode} } + ha:Arrow = { checked=ChkMode(arrow); a=F11; action=Mode(Arrow); update_on={editor/mode} } + ha:Insert Point = { checked=ChkMode(insertpoint); a=Insert; action=Mode(InsertPoint); update_on={editor/mode} } + ha:Move = { checked=ChkMode(move); action=Mode(Move); update_on={editor/mode} } + ha:Copy = { checked=ChkMode(copy); action=Mode(Copy); update_on={editor/mode} } + ha:Lock = { checked=ChkMode(lock); a=F12; action=Mode(Lock); update_on={editor/mode} } + ha:Cancel = { a=Escape; action=Mode(Escape) } + } + } + } + } # popup1 + + ha:layer { + li:submenu { + ha:Layer properties... = { action=EditLayer() } + ha:Layer attributes... = { action=Attributes(Layer) } + ha:Grouping... (layer preferences) = { action=DoWindows(Preferences, 1, "User PoV/Layers") } + - + ha:Move up (within group) = { action=MoveLayer(c, step-) } + ha:Move down (within group) = { action=MoveLayer(c, step+) } + - + ha:Remove = { action=MoveLayer(c, -1) } + ha:Insert new, before this layer = { action={ MoveLayer(-1, c); EditLayer() } } + ha:Insert new, after this layer = { action={ MoveLayer(-1, c); MoveLayer(c, step+); EditLayer() } } + - + ha:all layers on = { action=ToggleView(all, vis, set) } + ha:all layers off = { action=ToggleView(all, vis, clear) } + } + } # layer + + ha:group { + li:submenu { + ha:Group properties... = { action=EditGroup(@) } + ha:Grouping... (layer preferences) = { action=DoWindows(Preferences, 1, "User PoV/Layers") } + - + ha:Insert new layer = { action={ MoveLayer(-1, gi); EditLayer() } } + ha:Append new layer = { action={ MoveLayer(-1, ga); EditLayer() } } + - + ha:expand groups = { action=ToggleView(all, open, set) } + ha:collapse groups = { action=ToggleView(all, open, clear) } + ha:all layers on = { action=ToggleView(all, vis, set) } + ha:all layers off = { action=ToggleView(all, vis, clear) } + } + } # group + + } # popups +} # root Index: tags/2.1.2/src/pcb-menu-lesstif.lht =================================================================== --- tags/2.1.2/src/pcb-menu-lesstif.lht (nonexistent) +++ tags/2.1.2/src/pcb-menu-lesstif.lht (revision 24813) @@ -0,0 +1,517 @@ +# Old, OBSOLETE, somewhat unmaintained menu file for users who got used +# to the old lesstif menus and have not yet switched to the new, unified default +# menu file, pcb-menu-default.lht + +ha:{ + li:mouse { + li:left { + li:press = { Mode(Notify) } + li:press-shift = { Mode(Notify) } + li:release = { Mode(Release) } + li:release-shift = { Mode(Release) } + } + li:right { + li:press = { Mode(Save); Mode(Rotate); Mode(Notify); Mode(Release); Mode(Restore); } + li:press-ctrl = { Display(CycleCrosshair) } + } + li:middle { + li:press = { Pan(1) } + li:release = { Pan(0) } + li:press-ctrl = { Pan(thumb,1) } + li:release-ctrl = { Pan(thumb,0) } + } + li:scroll-up { + li:press = { Zoom(0.8) } + } + li:scroll-down { + li:press = { Zoom(1.25) } + } + #If you want zoom to center, do this instead. + #in scroll-up: + #li:press = {Zoom(0.8); Center()} + #in scroll-down: + #li:perss = {Zoom(1.25); Center()} + } + + li:main_menu { + ha:File = { + li:submenu { + ha:About... = { action=About() } + ha:Save layout = { a=Ctrls; action=Save(Layout) } + ha:Save layout as... = { a=Shift Ctrls; action=Save(LayoutAs) } + ha:Revert = { action=Load(Revert,none) } + ha:Load layout = { action=Load(Layout) } + ha:Import = { + li:submenu { + ha:Import gschem schematics = { action=Import() } + ha:Import tEDAx schematics = { action=LoadTedaxFrom(netlist) } + ha:Import KiCad/eeschema schematics = { action=LoadEeschemaFrom() } + ha:Import mentor graphics schematics = { action=LoadMentorFrom() } + ha:Load subcircuit data to paste-buffer = { li:action={PasteBuffer(Clear); Load(ElementTobuffer)} } + ha:Load layout data to paste-buffer = { li:action={PasteBuffer(Clear); Load(LayoutTobuffer)} } + ha:Load netlist file = { action=Load(Netlist) } + ha:Load vendor resource file = { action=LoadVendor() } + ha:Load routed dsn or ses file = { action=LoadDsnFrom() } + ha:Load MUCS pl file = { action=LoadMucsFrom() } + ha:Load TinyCAD .net file = { action=LoadTinyCADFrom() } + ha:Load LTSpice .net and .asc files = { action=LoadLTSpiceFrom() } + ha:Load HP-GL plot to paste-buffer = { action=LoadHPGLFrom() } + ha:Load Hyperlynx .hyp file = { action=LoadHypFrom() } + } + } + ha:Print layout... = { action=Print() } + ha:Export layout... = { action=ExportGUI() } + ha:Maintenance { + li:submenu { + ha:Calibrate Printer... = { action=PrintCalibrate() } + ha:Re-scan the footprint library = { action=fp_rehash() } + - + ha:Edit current font = { action=FontEdit() } + ha:Edit on-disk font = { action={ LoadFontFrom("", 126); conf(set, design/text_font_id, 126, design); FontEdit() } } + ha:Save font from font editor = { action=FontSave() } + } + } + - + ha:Save connection data of... = { foreground=grey50; sensitive=false } + ha: a single element = { action=Save(ElementConnections) } + ha: all elements = { action=Save(AllConnections) } + ha: unused pins = { action=Save(AllUnusedPins) } + - + ha:Start new layout = { a=Ctrln; action=New() } + - + ha:Quit Program = { a=Ctrlq; action=Quit() } + } + } # File + + ha:View { + li:submenu { + ha:Flip up/down = { checked=editor/view/flip_y; a=Tab; action=SwapSides(V) } + ha:Flip left/right = { checked=editor/view/flip_x; a=ShiftTab; action=SwapSides(H) } + ha:Spin 180° = { a=CtrlTab; action=SwapSides(R) } + ha:Swap Sides = { a=Ctrl ShiftTab; action=SwapSides() } + ha:Center cursor = { a=c; action=Center() } + ha:Show soldermask = { checked=editor/show_mask; action=Display(ToggleMask) } + - + ha:Displayed subcircuit ID... = { foreground=grey50; sensitive=false } + ha:refdes = { checked=ChkSubcID(); action=Display(SubcID) } + ha:footprint = { checked=ChkSubcID(%a.footprint%); action=Display(SubcID,"%a.footprint%") } + ha:value = { checked=ChkSubcID(%a.value%); action=Display(SubcID,"%a.value%") } + ha:refdes+value = { checked=ChkSubcID(%a.refdes%\\n%a.value%); action=Display(SubcID,"%a.refdes%\\\\n%a.value%") } + ha:Lock floaters = { checked=editor/lock_names; action=conf(toggle, editor/lock_names, design) } + ha:Only floaters = { checked=editor/only_names; action=conf(toggle, editor/only_names, design) } + ha:Hide floaters = { checked=editor/hide_names; action=conf(toggle, editor/hide_names, design) } + ha:Mincut on shorts = { checked=plugins/mincut/enable; action=conf(toggle, plugins/mincut/enable, design) } + - + ha:Open pinout menu = { action=Display(Pinout) } + ha:Zoom { + li:submenu { + ha:Zoom In 2X = { action=Zoom(-2) } + ha:Zoom In 20% = { a=z; action=Zoom(-1.2) } + ha:Zoom Out 20% = { a=Shiftz; action=Zoom(+1.2); } + ha:Zoom Out 2X = { action=Zoom(+2) } + ha:Zoom Max = { a=v; action=Zoom() } + ha:Zoom Toggle = { a=`; action=Zoom(Toggle) } + - + ha:Zoom to 0.1mil\/px = { action={Zoom(=0.1mil)} } + ha:Zoom to 0.01mm\/px = { action={Zoom(=0.01mil)} } + ha:Zoom to 1mil\/px = { action={Zoom(=1mil)} } + ha:Zoom to 0.05mm\/px = { action={Zoom(=0.05mm)} } + ha:Zoom to 2.5mil\/px = { action={Zoom(=2.5mil)} } + ha:Zoom to 0.1mm\/px = { action={Zoom(=0.1mm)} } + ha:Zoom to 10mil\/px = { action={Zoom(=10mil)} } + } + } + ha:Grid { + li:submenu { + ha:mil = { checked=ChkGridUnits(mil); action=SetUnits(mil) } + ha:mm = { checked=ChkGridUnits(mm); action=SetUnits(mm) } + ha:Display grid = { checked=editor/draw_grid; action=conf(toggle, editor/draw_grid, design) } + ha:Realign grid = { action={ GetXY(Click to set the grid origin); Display(ToggleGrid) } } + ha:No Grid = { checked=ChkGridSize(none); action=SetValue(Grid,1) } + - + ha:0.1 mil = { checked=ChkGridSize(0.1mil); li:action={SetUnits(mil); SetValue(Grid,0.1mil)} } + ha:1 mil = { checked=ChkGridSize(1mil); li:action={SetUnits(mil); SetValue(Grid,1mil)} } + ha:5 mil = { checked=ChkGridSize(5mil); li:action={SetUnits(mil); SetValue(Grid,5mil)} } + ha:10 mil = { checked=ChkGridSize(10mil); li:action={SetUnits(mil); SetValue(Grid,10mil)} } + ha:25 mil = { checked=ChkGridSize(25mil); li:action={SetUnits(mil); SetValue(Grid,25mil)} } + ha:50 mil = { checked=ChkGridSize(50mil); li:action={SetUnits(mil); SetValue(Grid,50mil)} } + ha:100 mil = { checked=ChkGridSize(100mil); li:action={SetUnits(mil); SetValue(Grid,100mil)} } + - + ha:0.01 mm = { checked=ChkGridSize(0.01mm); li:action={SetUnits(mm); SetValue(Grid,0.01mm)} } + ha:0.05 mm = { checked=ChkGridSize(0.05mm); li:action={SetUnits(mm); SetValue(Grid,0.05mm)} } + ha:0.1 mm = { checked=ChkGridSize(0.10mm); li:action={SetUnits(mm); SetValue(Grid,0.1mm)} } + ha:0.25 mm = { checked=ChkGridSize(0.25mm); li:action={SetUnits(mm); SetValue(Grid,0.25mm)} } + ha:0.5 mm = { checked=ChkGridSize(0.50mm); li:action={SetUnits(mm); SetValue(Grid,0.5mm)} } + ha:1 mm = { checked=ChkGridSize(1mm); li:action={SetUnits(mm); SetValue(Grid,1mm)} } + - + ha:Grid -5mil = { a=Shiftg; action=SetValue(Grid,-5,mil) } + ha:Grid +5mil = { a=g; action=SetValue(Grid,+5,mil) } + ha:Grid -0.05mm = { a=Shift Ctrlg; action=SetValue(Grid,-0.05,mm) } + ha:Grid +0.05mm = { a=Ctrlg; action=SetValue(Grid,+0.05,mm) } + } + } + - + ha:Shown Layers { + li:submenu { + @layerview + - + ha:Edit Layer Groups = { action=EditLayerGroups() } + } + } + ha:Current Layer { + li:submenu { + @layerpick + - + ha:Delete current layer = { action=MoveLayer(c,-1) } + ha:Add new layer = { action=MoveLayer(-1,c) } + ha:Move current layer up = { action=MoveLayer(c,step-) } + ha:Move current layer down = { action=MoveLayer(c,step+) } + } + } + } + } # View + + ha:Edit { + li:submenu { + ha:Undo last operation = { a=u; action=Undo() } + ha:Redo last undone operation = { a=Shiftr; action=Redo() } + ha:Clear undo-buffer = { a=Shift Ctrlu; action=Undo(ClearList); } + - + ha:Cut selection to buffer = { a=Ctrlx; li:action={ GetXY(Click to set the snap point for this buffer); PasteBuffer(Clear); PasteBuffer(AddSelected); RemoveSelected(); Mode(PasteBuffer) }} + ha:Copy selection to buffer = { a=Ctrlc; li:action={GetXY(Click to set the snap point for this buffer); PasteBuffer(Clear); PasteBuffer(AddSelected); Mode(PasteBuffer)} } + ha:Paste buffer to layout = { a=Ctrlv; action=Mode(PasteBuffer) } + - + ha:Unselect all = { a=Shift Alta; action=Unselect(All) } + ha:Select all visible = { a=Alta; action=Select(All) } + - + ha:Edit Names... = { foreground=grey50; sensitive=false } + ha: Change text on layout = { a=n; action=ChangeName(Object) } + ha: Change number on layout = { a=Shift Ctrln; action=ChangeName(Object, Number) } + ha: Edit name of layout = { action=ChangeName(Layout) } + ha: Edit name of active layer = { action=ChangeName(Layer) } + ha: Change font on layout = { a=Alt Ctrlf; action=FontSel(Object) } + ha:Edit Attributes... = { foreground=grey50; sensitive=false } + ha: Layout = { action=Attributes(Layout) } + ha: CurrentLayer = { action=Attributes(Layer) } + ha: Element = { action=Attributes(Element) } + ha: Subcircuit = { action=Attributes(Subc) } + - + ha:Board Sizes = { action=AdjustSizes() } + ha:Route Styles { + li:submenu { + @routestyles + - + ha:Edit... = { action=AdjustStyle(0) } + } + } + ha:Subcircuit { + li:submenu { + ha:Layer bindings... = { action=LayerBinding() } + ha:External editor... = { li:action={ GetXY(Click on the subcircuit to edit); extedit(object) } } + } + } + ha:Object flags... = { action=FlagEdit() } + } + } # Edit + + ha:Tools { + li:submenu { + ha:None = { checked=ChkMode(none); action=Mode(None) } + ha:Via = { checked=ChkMode(via); a=F1; action=Mode(Via) } + ha:Line = { checked=ChkMode(line); a=F2; action=Mode(Line) } + ha:Arc = { checked=ChkMode(arc); a=F3; action=Mode(Arc) } + ha:Text = { checked=ChkMode(text); a=F4; action=Mode(Text) } + ha:Rectangle = { checked=ChkMode(rectangle); a=F5; action=Mode(Rectangle) } + ha:Polygon = { checked=ChkMode(polygon); a=F6; action=Mode(Polygon) } + ha:Polygon Hole = { checked=ChkMode(polygonhole); action=Mode(PolygonHole); } + ha:Buffer = { checked=ChkMode(pastebuffer); a=F7; action=Mode(PasteBuffer) } + ha:Remove = { checked=ChkMode(remove); a=F8; action=Mode(Remove) } + ha:Rotate = { checked=ChkMode(rotate); a=F9; action=Mode(Rotate) } + ha:Thermal = { checked=ChkMode(thermal); a=F10; action=Mode(Thermal) } + ha:Arrow = { checked=ChkMode(arrow); a=F11; action=Mode(Arrow) } + ha:Insert Point = { checked=ChkMode(insertpoint); a=Insert; action=Mode(InsertPoint) } + ha:Move = { checked=ChkMode(move); action=Mode(Move) } + ha:Copy = { checked=ChkMode(copy); action=Mode(Copy) } + ha:Lock = { checked=ChkMode(lock); a=F12; action=Mode(Lock) } + ha:Cancel = { a=Escape; action=Mode(Cancel) } + - + ha:Command = { a={:}; action=Command() } + } + } # Tools + + ha:Settings { + li:submenu { + ha:Layer groups = { foreground=grey50; sensitive=false } + ha:Edit layer groupings = { action=EditLayerGroups() } + - + ha:'All-direction' lines = { checked=editor/all_direction_lines; a=.; action=conf(toggle, editor/all_direction_lines, design) } + ha:Auto swap line start angle = { checked=editor/swap_start_direction; action=conf(toggle, editor/swap_start_direction, design) } + ha:Orthogonal moves = { checked=editor/orthogonal_moves; action=conf(toggle, editor/orthogonal_moves, design) } + ha:Crosshair snaps to pins and pads = { checked=editor/snap_pin; action=conf(toggle, editor/snap_pin, design) } + ha:Crosshair snaps to off-grid points on lines = { checked=editor/snap_offgrid_line; action=conf(toggle, editor/snap_offgrid_line, design) } + ha:Crosshair shows DRC clearance = { checked=editor/show_drc; action=conf(toggle, editor/show_drc, design) } + ha:Auto enforce DRC clearance = { checked=editor/auto_drc; action=conf(toggle, editor/auto_drc, design) } + - + ha:Rubber band mode = { checked=editor/rubber_band_mode; action=conf(toggle, editor/rubber_band_mode, design) } + ha:Rubber band keeps middle line dir= { checked=editor/rubber_band_keep_midlinedir; action=conf(toggle, editor/rubber_band_keep_midlinedir, design) } + ha:Auto-zero delta measurements = { checked=editor/local_ref; action=conf(toggle, editor/local_ref, design) } + ha:New lines, arcs clear polygons = { checked=editor/clear_line; action=conf(toggle, editor/clear_line, design) } + ha:New polygons are full ones = { checked=editor/full_poly; action=conf(toggle, editor/full_poly, design) } + ha:Show autorouter trials = { checked=editor/live_routing; action=conf(toggle, editor/live_routing, design) } + ha:Highlighting on line, arc points = { checked=editor/highlight_on_point; action=conf(toggle, editor/highlight_on_point, design) } + ha:Wireframe draw = { checked=editor/wireframe_draw; a=Ctrlw; action=conf(toggle, editor/wireframe_draw, design) } + ha:Thin draw = { checked=editor/thin_draw; a=|; action=conf(toggle, editor/thin_draw, design) } + ha:Thin draw poly = { checked=editor/thin_drawpoly; a=Ctrl Shiftp; action=conf(toggle, editor/thin_draw_poly, design) } + ha:Check polygons = { checked=editor/check_planes; action=conf(toggle, editor/check_planes, design) } + ha:Brave mode = { action=brave() } + - + ha:Pinout shows number = { checked=editor/show_number; action=conf(toggle, editor/show_number, design) } + ha:Pins/Via show Name/Number = { a=d; action=Display(PinOrPadName) } + ha:Enable vendor drill mapping = { checked=plugins/vendor/enable; action=conf(toggle, plugins/vendor/enable, design) } + ha:Import Settings { + li:submenu { + ha:New subcircuits added at... = { foreground=grey50; sensitive=false } + ha: Center = { action=Import(setnewpoint,center) } + ha: Mark = { action=Import(setnewpoint,mark) } + ha: Crosshair = { action=Import(setnewpoint) } + - + ha:Set Dispersion = { action=Import(setdisperse) } + } + } + } + } # Settings + + ha:Select { + li:submenu { + ha:Select all visible objects = { action=Select(All) } + ha:Select all connected objects = { action=Select(Connection) } + - + ha:Unselect all objects = { action=Unselect(All) } + ha:unselect all connected objects = { action=Unselect(Connection) } + - + ha:Auto-place selected subcircuits = { a=Ctrlp; action=AutoPlaceSelected() } + ha:Disperse all subcircuits = { action=DisperseElements(All) } + ha:Move selected subcircuits to other side = { a=Shiftb; action=Flip(SelectedElements) } + ha:Move selected to current layer = { a=Shiftm; action=MoveToCurrentLayer(Selected) } + ha:Delete selected objects = { a=Delete; action=Delete(Selected) } + ha:Convert selection to subcircuit = { action=Select(ConvertSubc) } + ha:Convert selection to padstack = { li:action={PadstackConvert(selected); Mode(PasteBuffer);} } + - + ha:Optimize selected rats = { li:action={DeleteRats(SelectedRats); AddRats(SelectedRats)} } + ha:Auto-route selected rats = { a=Altr; action=AutoRoute(SelectedRats) } + ha:Rip up selected auto-routed tracks = { action=RipUp(Selected) } + - + ha:Change size of selected objects = { foreground=grey50; sensitive=false } + ha:ChangeSizes to Route style = { a=Shifty; action=ChangeSizes(Object,style,mil); } + ha:Lines -10 mil = { li:action={ChangeSize(SelectedLines,-10,mil); ChangeSize(SelectedArcs,-10,mil)} } + ha:Lines +10 mil = { li:action={ChangeSize(SelectedLines,+10,mil); ChangeSize(SelectedArcs,+10,mil)} } + ha:Pads -10 mil = { action=ChangeSize(SelectedPads,-10,mil) } + ha:Pads +10 mil = { action=ChangeSize(SelectedPads,+10,mil) } + ha:Pins -10 mil = { action=ChangeSize(SelectedPins,-10,mil) } + ha:Pins +10 mil = { action=ChangeSize(SelectedPins,+10,mil) } + ha:Texts -10 mil = { action=ChangeSize(SelectedTexts,-10,mil) } + ha:Texts +10 mil = { action=ChangeSize(SelectedTexts,+10,mil) } + ha:Vias -10 mil = { action=ChangeSize(SelectedVias,-10,mil) } + ha:Vias +10 mil = { action=ChangeSize(SelectedVias,+10,mil) } + - + ha:Change drilling hole of selected padstacks = { foreground=grey50; sensitive=false } + ha:Vias -10 mil = { action=ChangeDrillSize(SelectedPadstacks,-10,mil) } + ha:Vias +10 mil = { action=ChangeDrillSize(SelectedPadstacks,+10,mil) } + ha:Pins -10 mil = { action=ChangeDrillSize(SelectedPins,-10,mil) } + ha:Pins +10 mil = { action=ChangeDrillSize(SelectedPins,+10,mil) } + - + ha:Route radius +0.5 = { a=Altc; action=conf(delta, editor/route_radius, +0.5, design); } + ha:Route radius -0.5 = { a=Alt Shiftc; action=conf(delta, editor/route_radius, -0.5, design); } + } + } # Select + + + ha:Buffer { + li:submenu { + ha:Copy selection to buffer = { li:action={GetXY(Click to set the snap point for this buffer); PasteBuffer(Clear); PasteBuffer(AddSelected); Mode(PasteBuffer)} } + ha:Cut selection to buffer = { li:action={GetXY(Click to set the snap point for this buffer); PasteBuffer(Clear); PasteBuffer(AddSelected); RemoveSelected(); Mode(PasteBuffer)} } + ha:Paste buffer to layout = { action=Mode(PasteBuffer) } + - + ha:Rotate buffer 90 deg CCW = { a=ShiftF7; li:action={Mode(PasteBuffer); PasteBuffer(Rotate,1)} } + ha:Rotate buffer 90 deg CW = { li:action={Mode(PasteBuffer); PasteBuffer(Rotate,3)} } + ha:Arbitrarily Rotate Buffer = { li:action={Mode(PasteBuffer); FreeRotateBuffer()} } + ha:Mirror buffer (up/down) = { li:action={Mode(PasteBuffer); PasteBuffer(Mirror)} } + ha:Mirror buffer (left/right) = { li:action={Mode(PasteBuffer); PasteBuffer(Rotate,1); PasteBuffer(Mirror); PasteBuffer(Rotate,3)} } + - + ha:Clear buffer = { action=PasteBuffer(Clear) } + ha:Convert buffer to subcircuit = { action=PasteBuffer(ConvertSubc) } + ha:Convert buffer to padstack = { li:action={PadstackConvert(buffer); Mode(PasteBuffer);} } + ha:Break buffer subcircuits to pieces = { action=PasteBuffer(Restore) } + ha:Save buffer subcircuits to file = { action=Save(PasteBuffer) } + ha:Layer bindings... = { action=LayerBinding(buffer) } + - + ha:Select current buffer = { foreground=grey50; sensitive=false } + ha:\#1 = { checked=ChkBuffer(1); a=Shift1; action=PasteBuffer(1) } + ha:\#2 = { checked=ChkBuffer(2); a=Shift2; action=PasteBuffer(2) } + ha:\#3 = { checked=ChkBuffer(3); a=Shift3; action=PasteBuffer(3) } + ha:\#4 = { checked=ChkBuffer(4); a=Shift4; action=PasteBuffer(4) } + ha:\#5 = { checked=ChkBuffer(5); a=Shift5; action=PasteBuffer(5) } + } + } # Buffer + + + ha:Connects { + li:submenu { + ha:Lookup connection to object = { a=Ctrlf; li:action={GetXY(Click on the object); Connection(Find)} } + ha:Reset scanned pads/pins/vias = { li:action={Connection(ResetPinsViasAndPads); Display(Redraw)} } + ha:Reset scanned lines/polygons = { li:action={Connection(ResetLinesAndPolygons); Display(Redraw)} } + ha:Reset all connections = { a=Shiftf; li:action={Connection(Reset); Display(Redraw)} } + - + ha:Optimize rats-nest = { a=o; li:action={Atomic(Save); DeleteRats(AllRats); Atomic(Restore); AddRats(AllRats); Atomic(Block)} } + ha:Erase rats-nest = { a=e; action=DeleteRats(AllRats) } + ha:Erase selected rats = { a=Shifte; action=DeleteRats(SelectedRats) } + - + ha:Auto-route selected rats = { action=AutoRoute(Selected) } + ha:Auto-route all rats = { action=AutoRoute(AllRats) } + ha:Rip up all auto-routed tracks = { action=RipUp(All) } + - + ha:Auto-Optimize = { a={Ctrl=}; action=djopt(auto) } + ha:Debumpify = { action=djopt(debumpify) } + ha:Unjaggy = { action=djopt(unjaggy) } + ha:Vianudge = { action=djopt(vianudge) } + ha:Viatrim = { action=djopt(viatrim) } + ha:Orthopull = { action=djopt(orthopull) } + ha:SimpleOpts = { a={=}; action=djopt(simple) } + ha:Miter = { action=djopt(miter) } + ha:Puller = { a=y; action=Puller() } + ha:Global Puller = { + li:submenu { + ha:Selected = { action=GlobalPuller(selected) } + ha:Found = { action=GlobalPuller(found) } + ha:All = { action=GlobalPuller() } + } + } + ha:Only autorouted nets = { checked=plugins/djopt/auto_only; action=conf(toggle, plugins/djopt/auto_only, design) } + - + ha:Design Rule Checker = { action=DRC() } + - + ha:Apply vendor drill mapping = { action=ApplyVendor() } + } + } # Connects + + ha:Plugins = { + li:submenu { + ha:Manage plugins... = { a=Altp; action=ManagePlugins() } + } + } # Plugins + + + ha:Info { + li:submenu { + ha:Generate object report = { a=Ctrlr; action=ReportObject() } + ha:Generate drill summary = { action=Report(DrillReport) } + ha:Report found pins/pads = { action=Report(FoundPins) } + ha:Report net length = { a=r; action=Report(NetLength) } + ha:Key Bindings { + li:submenu { + ha:Remove = { a=BackSpace; action=Delete(Selected) } + ha:Remove Connected = { a=ShiftBackSpace; li:action={Atomic(Save); Connection(Reset); Atomic(Restore); Unselect(All); Atomic(Restore); Connection(Find); Atomic(Restore); Select(Connection); Atomic(Restore); RemoveSelected(); Atomic(Restore); Connection(Reset); Atomic(Restore); Unselect(All); Atomic(Block)} } + ha:Remove Connected = { a=ShiftDelete; li:action={Atomic(Save); Connection(Reset); Atomic(Restore); Unselect(All); Atomic(Restore); Connection(Find); Atomic(Restore); Select(Connection); Atomic(Restore); RemoveSelected(); Atomic(Restore); Connection(Reset); Atomic(Restore); Unselect(All); Atomic(Block)} } + ha:Set Same = { a=a; action=SetSame() } + ha:Flip Object = { a=b; action=Flip(Object) } + ha:Find Connections = { a=f; li:action={Connection(Reset); Connection(Find)} } + ha:ChangeJoin Object = { a=j; action=ChangeJoin(Object) } + ha:ChangeJoin SelectedObject = { a=Shiftj; action=ChangeJoin(SelectedObjects) } + ha:Clear Object +2 mil = { a=k; action=ChangeClearSize(Object,+2,mil) } + ha:Clear Object -2 mil = { a=Shiftk; action=ChangeClearSize(Object,-2,mil) } + ha:Clear Selected +2 mil = { a=Ctrlk; action=ChangeClearSize(SelectedObjects,+2,mil) } + ha:Clear Selected -2 mil = { a=Shift Ctrlk; action=ChangeClearSize(SelectedObjects,-2,mil) } + ha:Line Tool size +5 mil = { a=l; action=SetValue(LineSize,+5,mil) } + ha:Line Tool size -5 mil = { a=Shiftl; action=SetValue(LineSize,-5,mil) } + ha:Move Object to current layer = { a=m; action=MoveToCurrentLayer(Object) } + ha:MarkCrosshair = { a=Ctrlm; action=MarkCrosshair() } + ha:Select shortest rat = { a=Shiftn; action=AddRats(Close) } + ha:AddRats to selected pins = { a=Shifto; li:action={Atomic(Save); DeleteRats(AllRats); Atomic(Restore); AddRats(SelectedRats); Atomic(Block)} } + ha:Polygon PreviousPoint = { a=p; action=Polygon(PreviousPoint) } + ha:Polygon Close = { a=Shiftp; action=Polygon(Close) } + ha:ChangeSize +5 mil = { a=s; action=ChangeSize(Object,+5,mil) } + ha:ChangeSize -5 mil = { a=Shifts; action=ChangeSize(Object,-5,mil) } + ha:ChangeDrill +5 mil = { a=Alts; action=ChangeDrillSize(Object,+5,mil) } + ha:ChangeDrill -5 mil = { a=Alt Shifts; action=ChangeDrillSize(Object,-5,mil) } + ha:Text Tool scale +10 mil = { a=t; action=SetValue(TextScale,+10,mil) } + ha:Text Tool scale -10 mil = { a=Shiftt; action=SetValue(TextScale,-10,mil) } + ha:AddRats Selected = { a=Shiftw; action=AddRats(SelectedRats) } + ha:Add All Rats = { a=w; action=AddRats(AllRats) } + ha:Undo = { a=Altz; action=Undo() } + ha:Cycle Clip = { a=/; action=Display(CycleClip) } + ha:Arrow = { a=space; checked=ChkMode(arrow); action=Mode(Arrow) } + ha:Temp Arrow ON = { a=[; li:action={Mode(Save); Mode(Arrow); Mode(Notify)} } + ha:Temp Arrow OFF = { a=]; li:action={Mode(Release); Mode(Restore)} } + ha:Step Up = { a=Up; action=Cursor(Warp,0,1,grid) } + ha:Step Down = { a=Down; action=Cursor(Warp,0,-1,grid) } + ha:Step Left = { a=Left; action=Cursor(Warp,-1,0,grid) } + ha:Step Right = { a=Right; action=Cursor(Warp,1,0,grid) } + ha:Step +Up = { a=ShiftUp; action=Cursor(Pan,0,50,view) } + ha:Step +Down = { a=ShiftDown; action=Cursor(Pan,0,-50,view) } + ha:Step +Left = { a=ShiftLeft; action=Cursor(Pan,-50,0,view) } + ha:Step +Right = { a=ShiftRight; action=Cursor(Pan,50,0,view) } + ha:"Click" = { a=Enter; li:action={Mode(Notify); Mode(Release)} } + - + ha:layer keys { + li:submenu { + ha:Select Layer 1 = { a=1; action=SelectLayer(1) } + ha:Select Layer 2 = { a=2; action=SelectLayer(2) } + ha:Select Layer 3 = { a=3; action=SelectLayer(3) } + ha:Select Layer 4 = { a=4; action=SelectLayer(4) } + ha:Select Layer 5 = { a=5; action=SelectLayer(5) } + ha:Select Layer 6 = { a=6; action=SelectLayer(6) } + ha:Select Layer 7 = { a=7; action=SelectLayer(7) } + ha:Select Layer 8 = { a=8; action=SelectLayer(8) } + ha:Select Layer 9 = { a=9; action=SelectLayer(9) } + ha:Select Layer 10 = { a=0; action=SelectLayer(10) } + ha:Select Layer 11 = { a=Alt1; action=SelectLayer(11) } + ha:Select Layer 12 = { a=Alt2; action=SelectLayer(12) } + ha:Select Layer 13 = { a=Alt3; action=SelectLayer(13) } + ha:Select Layer 14 = { a=Alt4; action=SelectLayer(14) } + ha:Select Layer 15 = { a=Alt5; action=SelectLayer(15) } + ha:Select Layer 16 = { a=Alt6; action=SelectLayer(16) } + ha:Select Layer 17 = { a=Alt7; action=SelectLayer(17) } + ha:Select Layer 18 = { a=Alt8; action=SelectLayer(18) } + ha:Select Layer 19 = { a=Alt9; action=SelectLayer(19) } + ha:Select Layer 20 = { a=Alt0; action=SelectLayer(20) } + - + ha:Toggle Layer 1 = { a=Ctrl1; action=ToggleView(1) } + ha:Toggle Layer 2 = { a=Ctrl2; action=ToggleView(2) } + ha:Toggle Layer 3 = { a=Ctrl3; action=ToggleView(3) } + ha:Toggle Layer 4 = { a=Ctrl4; action=ToggleView(4) } + ha:Toggle Layer 5 = { a=Ctrl5; action=ToggleView(5) } + ha:Toggle Layer 6 = { a=Ctrl6; action=ToggleView(6) } + ha:Toggle Layer 7 = { a=Ctrl7; action=ToggleView(7) } + ha:Toggle Layer 8 = { a=Ctrl8; action=ToggleView(8) } + ha:Toggle Layer 9 = { a=Ctrl9; action=ToggleView(9) } + ha:Toggle Layer 10 = { a=Ctrl0; action=ToggleView(10) } + ha:Toggle Layer 11 = { a=Ctrl-Alt1; action=ToggleView(11) } + ha:Toggle Layer 12 = { a=Ctrl-Alt2; action=ToggleView(12) } + ha:Toggle Layer 13 = { a=Ctrl-Alt3; action=ToggleView(13) } + ha:Toggle Layer 14 = { a=Ctrl-Alt4; action=ToggleView(14) } + ha:Toggle Layer 15 = { a=Ctrl-Alt5; action=ToggleView(15) } + ha:Toggle Layer 16 = { a=Ctrl-Alt6; action=ToggleView(16) } + ha:Toggle Layer 17 = { a=Ctrl-Alt7; action=ToggleView(17) } + ha:Toggle Layer 18 = { a=Ctrl-Alt8; action=ToggleView(18) } + ha:Toggle Layer 19 = { a=Ctrl-Alt9; action=ToggleView(19) } + ha:Toggle Layer 20 = { a=Ctrl-Alt0; action=ToggleView(20) } + } + } # layer keys + } + } # Key Bindings + } + } # Info + + ha:Window { + li:submenu { + ha:Board Layout = { action=DoWindows(Layout) } + ha:Library = { action=DoWindows(Library) } + ha:Message Log = { action=DoWindows(Log) } + ha:Netlist = { action=DoWindows(Netlist) } + ha:Pinout = { a=Shiftd; action=Display(Pinout) } + ha:Font selector = { a=Ctrl Shiftf; action=FontSel() } + } + } # Window + + } # main_menu +} #root Index: tags/2.1.2/src/pcb-printf.c =================================================================== --- tags/2.1.2/src/pcb-printf.c (nonexistent) +++ tags/2.1.2/src/pcb-printf.c (revision 24813) @@ -0,0 +1,855 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 2011 Andrew Poelstra + * Copyright (C) 2016 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + * + * Old contact info: + * Andrew Poelstra, 16966 60A Ave, V3S 8X5 Surrey, BC, Canada + * asp11@sfu.ca + * + */ + +/* Implementation of printf wrapper to output pcb coords and angles + * For details of all supported specifiers, see the comment at the + * top of pcb-printf.h */ + +#include +#include +#include +#include "config.h" +#include "pcb-printf.h" + +const char *pcb_printf_slot[PCB_PRINTF_SLOT_max] = +{ + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 8 user formats */ + "%mr", /* original unitless cmil file format coord */ + "%.07$$mS" /* safe file format coord */ +}; + +static int min_sig_figs(double d) +{ + char buf[50]; + int rv; + + if (d == 0) + return 0; + + /* Normalize to x.xxxx... form */ + if (d < 0) + d *= -1; + while (d >= 10) + d /= 10; + while (d < 1) + d *= 10; + + rv = sprintf(buf, "%g", d); + return rv; +} + +/* Truncate trailing 0's from str */ +static int do_trunc0(char *str) +{ + char *end = str + strlen(str) - 1; + while((end > str) && (*end == '0') && (end[-1] != '.')) { + *end = '\0'; + end--; + } + return end-str+1; +} + + +/* Create sprintf specifier, using default_prec no precision is given */ +static inline void make_printf_spec(char *printf_spec_new, const char *printf_spec, int precision, int *trunc0) +{ + int i = 0; + + while (printf_spec[i] == '%' || isdigit(printf_spec[i]) || + printf_spec[i] == '-' || printf_spec[i] == '+' || printf_spec[i] == '#' || printf_spec[i] == '0') + ++i; + + if (printf_spec[i] == '.') { + if ((printf_spec[i+1] == '0') && (isdigit(printf_spec[i+2]))) + *trunc0 = 1; + sprintf(printf_spec_new, ", %sf", printf_spec); + } + else + sprintf(printf_spec_new, ", %s.%df", printf_spec, precision); +} + +/* sprintf a value (used to change locale on is_file_mode) */ +#define sprintf_lc_safe(is_file_mode, out, fmt, val) \ +do { \ + sprintf(out, fmt, val); \ + if (trunc0) \ + do_trunc0(filemode_buff); \ +} while(0) + +/* append a suffix, with or without space */ +static int inline append_suffix(gds_t *dest, enum pcb_suffix_e suffix_type, const char *suffix) +{ + switch (suffix_type) { + case PCB_UNIT_NO_SUFFIX: + break; + case PCB_UNIT_SUFFIX: + if (gds_append(dest, ' ') != 0) return -1; + /* deliberate fall-thru */ + case PCB_UNIT_FILE_MODE: + if (gds_append_str(dest, suffix) != 0) return -1; + break; + } + return 0; +} + + +/* Internal coord-to-string converter for pcb-printf + * Converts a (group of) measurement(s) to a comma-delimited + * string, with appropriate units. If more than one coord is + * given, the list is enclosed in parens to make the scope of + * the unit suffix clear. + * + * dest Append the output to this dynamic string + * coord Array of coords to convert + * n_coords Number of coords in array + * printf_spec printf sub-specifier to use with %f + * e_allow Bitmap of units the function may use + * suffix_type Whether to add a suffix + * + * return 0 on success, -1 on error + */ +static int CoordsToString(gds_t *dest, pcb_coord_t coord[], int n_coords, const gds_t *printf_spec_, enum pcb_allow_e allow, + enum pcb_suffix_e suffix_type) +{ + char filemode_buff[128]; /* G_ASCII_DTOSTR_BUF_SIZE */ + char printf_spec_new_local[256]; + double *value, value_local[32]; + enum pcb_family_e family; + const char *suffix; + int i, n, retval = -1, trunc0 = 0; + const char *printf_spec = printf_spec_->array; + char *printf_spec_new; + + if (n_coords > (sizeof(value_local) / sizeof(value_local[0]))) { + value = malloc(n_coords * sizeof *value); + if (value == NULL) + return -1; + } + else + value = value_local; + + if (allow == 0) + allow = PCB_UNIT_ALLOW_ALL_SANE; + + i = printf_spec_->used + 64; + if (i > sizeof(printf_spec_new_local)) + printf_spec_new = malloc(i); + else + printf_spec_new = printf_spec_new_local; + + /* Check our freedom in choosing units */ + if ((allow & PCB_UNIT_ALLOW_IMPERIAL) == 0) + family = PCB_UNIT_METRIC; + else if ((allow & PCB_UNIT_ALLOW_METRIC) == 0) + family = PCB_UNIT_IMPERIAL; + else { + int met_votes = 0, imp_votes = 0; + + for (i = 0; i < n_coords; ++i) + if (min_sig_figs(PCB_COORD_TO_MIL(coord[i])) < min_sig_figs(PCB_COORD_TO_MM(coord[i]))) + ++imp_votes; + else + ++met_votes; + + if (imp_votes > met_votes) + family = PCB_UNIT_IMPERIAL; + else + family = PCB_UNIT_METRIC; + } + + /* Set base unit */ + for (i = 0; i < n_coords; ++i) { + switch (family) { + case PCB_UNIT_METRIC: + value[i] = PCB_COORD_TO_MM(coord[i]); + break; + case PCB_UNIT_IMPERIAL: + value[i] = PCB_COORD_TO_MIL(coord[i]); + break; + } + } + + /* Determine scale factor -- find smallest unit that brings + * the whole group above unity */ + for (n = 0; n < pcb_get_n_units(); ++n) { + if ((pcb_units[n].allow & allow) != 0 && (pcb_units[n].family == family)) { + int n_above_one = 0; + + for (i = 0; i < n_coords; ++i) + if (abs(value[i] * pcb_units[n].scale_factor) > 1) + ++n_above_one; + if (n_above_one == n_coords) + break; + } + } + /* If nothing worked, wind back to the smallest allowable unit */ + if (n == pcb_get_n_units()) { + do { + --n; + } while ((pcb_units[n].allow & allow) == 0 || pcb_units[n].family != family); + } + + /* Apply scale factor */ + suffix = pcb_units[n].suffix; + for (i = 0; i < n_coords; ++i) + value[i] = value[i] * pcb_units[n].scale_factor; + + make_printf_spec(printf_spec_new, printf_spec, pcb_units[n].default_prec, &trunc0); + + /* Actually sprintf the values in place + * (+ 2 skips the ", " for first value) */ + if (n_coords > 1) + if (gds_append(dest, '(') != 0) + goto err; + + sprintf_lc_safe((suffix_type == PCB_UNIT_FILE_MODE), filemode_buff, printf_spec_new + 2, value[0]); + if (gds_append_str(dest, filemode_buff) != 0) + goto err; + + for (i = 1; i < n_coords; ++i) { + sprintf_lc_safe((suffix_type == PCB_UNIT_FILE_MODE), filemode_buff, printf_spec_new, value[i]); + if (gds_append_str(dest, filemode_buff) != 0) + goto err; + } + if (n_coords > 1) + if (gds_append(dest, ')') != 0) goto err; + + + /* Append suffix */ + if (value[0] != 0 || n_coords > 1) + if (append_suffix(dest, suffix_type, suffix) != 0) + goto err; + + retval = 0; +err:; + if (printf_spec_new != printf_spec_new_local) + free(printf_spec_new); + + if (value != value_local) + free(value); + return retval; +} + +typedef struct { + int score_factor; + + enum pcb_allow_e base; + double down_limit; + enum pcb_allow_e down; + double up_limit; + enum pcb_allow_e up; + + /* persistent, calculated once */ + const pcb_unit_t *base_unit, *down_unit, *up_unit; +} human_coord_t; + +/* Conversion preference table */ +static human_coord_t human_coord[] = { + {2, PCB_UNIT_ALLOW_MM, 0.001, PCB_UNIT_ALLOW_UM, 1000.0, PCB_UNIT_ALLOW_M ,NULL,NULL,NULL}, + {1, PCB_UNIT_ALLOW_MIL, 0, 0, 1000.0, PCB_UNIT_ALLOW_IN ,NULL,NULL,NULL} +}; +#define NUM_HUMAN_COORD (sizeof(human_coord) / sizeof(human_coord[0])) + +static inline int try_human_coord(pcb_coord_t coord, const pcb_unit_t *unit, double down_limit, double up_limit, int score_factor, double *value, unsigned int *best, const char **suffix) +{ + double v, frac, save; + long int digs, zeros; + unsigned int score; + + /* convert the value to the proposed unit */ + if (unit->family == PCB_UNIT_METRIC) + v = PCB_COORD_TO_MM(coord); + else + v = PCB_COORD_TO_MIL(coord); + save = v = v * unit->scale_factor; + if (v < 0) v = -v; + + /* Check if neighbour units are better */ + if ((down_limit > 0) && (v < down_limit)) + return -1; + if ((up_limit > 0) && (v > up_limit)) + return +1; + + /* count trailing zeros after the decimal point up to 8 digits */ + frac = v - floor(v); + digs = frac * 100000000.0; + if (digs != 0) + for(zeros = 0; (digs % 10) == 0; zeros++, digs /= 10); + else + zeros = 8; + + /* score is higher for more zeroes */ + score = score_factor + 8 * zeros; + +/* printf("try: %s '%.8f' -> %.8f %d score=%d\n", unit->suffix, v, frac, zeros, score);*/ + + /* update the best score */ + if (score > *best) { + *value = save; + *best = score; + *suffix = unit->suffix; + } + + return 0; +} + +/* Same as CoordsToString but take only one coord and print it in human readable format */ +static int CoordsToHumanString(gds_t *dest, pcb_coord_t coord, const gds_t *printf_spec_, enum pcb_suffix_e suffix_type) +{ + char filemode_buff[128]; /* G_ASCII_DTOSTR_BUF_SIZE */ + char printf_spec_new_local[256]; + char *printf_spec_new; + int i, retval = -1, trunc0; + const char *printf_spec = printf_spec_->array; + const char *suffix; + double value; + unsigned int best_score = 0; + + i = printf_spec_->used + 64; + if (i > sizeof(printf_spec_new_local)) + printf_spec_new = malloc(i); + else + printf_spec_new = printf_spec_new_local; + + /* cache unit lookup */ + if (human_coord[0].base_unit == NULL) { + for(i = 0; i < NUM_HUMAN_COORD; i++) { + human_coord[i].base_unit = get_unit_struct_by_allow(human_coord[i].base); + human_coord[i].down_unit = get_unit_struct_by_allow(human_coord[i].down); + human_coord[i].up_unit = get_unit_struct_by_allow(human_coord[i].up); + } + } + + for(i = 0; i < NUM_HUMAN_COORD; i++) { + int res; + /* try the base units first */ + res = try_human_coord(coord, human_coord[i].base_unit, human_coord[i].down_limit, human_coord[i].up_limit, human_coord[i].score_factor,&value, &best_score, &suffix); + if (res < 0) + try_human_coord(coord, human_coord[i].down_unit, 0, 0, human_coord[i].score_factor, &value, &best_score, &suffix); + else if (res > 0) + try_human_coord(coord, human_coord[i].up_unit, 0, 0, human_coord[i].score_factor,&value, &best_score, &suffix); + } + + make_printf_spec(printf_spec_new, printf_spec, 8, &trunc0); + sprintf_lc_safe((suffix_type == PCB_UNIT_FILE_MODE), filemode_buff, printf_spec_new + 2, value); + if (gds_append_str(dest, filemode_buff) != 0) + goto err; + + if (value != 0) { + if (suffix_type == PCB_UNIT_NO_SUFFIX) + suffix_type = PCB_UNIT_SUFFIX; + if (append_suffix(dest, suffix_type, suffix) != 0) + goto err; + } + + err:; + if (printf_spec_new != printf_spec_new_local) + free(printf_spec_new); + return retval; +} + +int QstringToString(gds_t *dest, const char *qstr, char q, char esc, const char *needq) +{ + const char *s; + + if ((qstr == NULL) || (*qstr == '\0')) { + gds_append(dest, q); + gds_append(dest, q); + return 0; + } + + /* check if quoting is needed */ + if (strpbrk(qstr, needq) == NULL) { + gds_append_str(dest, qstr); + return 0; + } + + /* wrap in quotes and protect escape and quote chars */ + gds_append(dest, q); + for(s = qstr; *s != '\0'; s++) { + if ((*s == esc) || (*s == q)) + gds_append(dest, esc); + gds_append(dest, *s); + } + gds_append(dest, q); + return 0; +} + +/* Main low level pcb-printf function + * This is a printf wrapper that accepts new format specifiers to + * output pcb coords as various units. See the comment at the top + * of pcb-printf.h for full details. + * + * [in] string Append anything new at the end of this dynamic string (must be initialized before the call) + * [in] fmt Format specifier + * [in] args Arguments to specifier + * + * return 0 on success */ +int pcb_append_vprintf(gds_t *string, const char *fmt, va_list args) +{ + gds_t spec; + const char *qstr, *needsq; + char tmp[128]; /* large enough for rendering a long long int */ + int tmplen, retval = -1, slot_recursion = 0, mq_has_spec; + char *dot, *free_fmt = NULL; + enum pcb_allow_e mask = PCB_UNIT_ALLOW_ALL_SANE; + + gds_init(&spec); + + new_fmt:; + while (*fmt) { + enum pcb_suffix_e suffix = PCB_UNIT_NO_SUFFIX; + + if (*fmt == '%') { + const char *ext_unit = ""; + pcb_coord_t value[10]; + int count, i; + + gds_truncate(&spec, 0); + mq_has_spec = 0; + + /* Get printf sub-specifiers */ + if (gds_append(&spec, *fmt++) != 0) goto err; + while (isdigit(*fmt) || *fmt == '.' || *fmt == ' ' || *fmt == '*' + || *fmt == '#' || *fmt == 'l' || *fmt == 'L' || *fmt == 'h' + || *fmt == '+' || *fmt == '-' || *fmt == '[' || *fmt == '{') { + if (*fmt == '*') { + char itmp[32]; + int ilen; + ilen = sprintf(itmp, "%d", va_arg(args, int)); + if (gds_append_len(&spec, itmp, ilen) != 0) goto err; + fmt++; + } + else + if (gds_append(&spec, *fmt++) != 0) goto err; + } + + /* check if specifier is %[] */ + if ((gds_len(&spec) > 2) && (spec.array[1] == '[')) { + int slot = atoi(spec.array+2); + gds_t new_spec; + if ((slot < 0) || (slot > PCB_PRINTF_SLOT_max)) { + fprintf(stderr, "Internal error: invalid printf slot addressed: '%s'\n", spec.array); + abort(); + } + slot_recursion++; + if (slot_recursion > 16) { + fprintf(stderr, "Internal error: printf slot recursion too deep on addressed: '%s'\n", spec.array); + abort(); + } + if (pcb_printf_slot[slot] == NULL) { + fprintf(stderr, "Internal error: printf empty slot reference: '%s'\n", spec.array); + abort(); + } + gds_init(&new_spec); + gds_append_str(&new_spec, pcb_printf_slot[slot]); + if (*fmt == ']') + fmt++; + gds_append_str(&new_spec, fmt); + if (free_fmt != NULL) + free(free_fmt); + fmt = free_fmt = new_spec.array; + memset(&new_spec, 0, sizeof(new_spec)); + gds_truncate(&spec, 0); + goto new_fmt; + } + if ((spec.array[0] == '%') && (spec.array[1] == '{')) { + /* {} specifier for %mq */ + const char *end; + gds_truncate(&spec, 0); + for(end = fmt; *end != '\0'; end++) { + if ((end[0] != '\\') && (end[1] == '}')) { + end++; + break; + } + } + if (*end == '\0') + goto err; + gds_append_len(&spec, fmt, end-fmt); + fmt = end+1; + mq_has_spec = 1; + } + else + slot_recursion = 0; + + /* Get our sub-specifiers */ + if (*fmt == '#') { + mask = PCB_UNIT_ALLOW_CMIL; /* This must be pcb's base unit */ + fmt++; + } + if (*fmt == '$') { + suffix = PCB_UNIT_SUFFIX; + fmt++; + if (*fmt == '$') { + fmt++; + suffix = PCB_UNIT_FILE_MODE; + } + } + /* Tack full specifier onto specifier */ + if (*fmt != 'm') + if (gds_append(&spec, *fmt) != 0) goto err; + switch (*fmt) { + /* Printf specs */ + case 'o': + case 'i': + case 'd': + case 'u': + case 'x': + case 'X': + if (spec.array[1] == 'l') + tmplen = sprintf(tmp, spec.array, va_arg(args, long)); + else + tmplen = sprintf(tmp, spec.array, va_arg(args, int)); + if (gds_append_len(string, tmp, tmplen) != 0) goto err; + break; + case 'e': + case 'E': + case 'f': + case 'g': + case 'G': + if (strchr(spec.array, '*')) { + int prec = va_arg(args, int); + tmplen = sprintf(tmp, spec.array, va_arg(args, double), prec); + } + else + tmplen = sprintf(tmp, spec.array, va_arg(args, double)); + if (gds_append_len(string, tmp, tmplen) != 0) goto err; + break; + case 'c': + if (spec.array[1] == 'l' && sizeof(int) <= sizeof(wchar_t)) + tmplen = sprintf(tmp, spec.array, va_arg(args, wchar_t)); + else + tmplen = sprintf(tmp, spec.array, va_arg(args, int)); + if (gds_append_len(string, tmp, tmplen) != 0) goto err; + break; + case 's': + if (spec.array[0] == 'l') { + /* TODO: convert wchar to char and append it */ + fprintf(stderr, "Internal error: appending %%ls is not supported\n"); + abort(); + } + else { + const char *s = va_arg(args, const char *); + if (s == NULL) s = "(null)"; + if (gds_append_str(string, s) != 0) goto err; + } + break; + case 'n': + /* Depending on gcc settings, this will probably break with + * some silly "can't put %n in writable data space" message */ + tmplen = sprintf(tmp, spec.array, va_arg(args, int *)); + if (gds_append_len(string, tmp, tmplen) != 0) goto err; + break; + case 'p': + tmplen = sprintf(tmp, spec.array, va_arg(args, void *)); + if (gds_append_len(string, tmp, tmplen) != 0) goto err; + break; + case '%': + if (gds_append(string, '%') != 0) goto err; + break; + /* Our specs */ + case 'm': + ++fmt; + if (*fmt == '*') + ext_unit = va_arg(args, const char *); + if (*fmt != '+' && *fmt != 'a' && *fmt != 'A' && *fmt != 'f' && *fmt != 'q') + value[0] = va_arg(args, pcb_coord_t); + count = 1; + switch (*fmt) { + case 'q': + qstr = va_arg(args, const char *); + if (mq_has_spec) + needsq = spec.array; + else + needsq = " \"\\"; + if (QstringToString(string, qstr, '"', '\\', needsq) != 0) goto err; + break; + case 'I': + if (CoordsToString(string, value, 1, &spec, PCB_UNIT_ALLOW_NM, PCB_UNIT_NO_SUFFIX) != 0) goto err; + break; + case 's': + if (CoordsToString(string, value, 1, &spec, PCB_UNIT_ALLOW_MM | PCB_UNIT_ALLOW_MIL, suffix) != 0) goto err; + break; + case 'S': + if (CoordsToString(string, value, 1, &spec, mask & PCB_UNIT_ALLOW_NATURAL, suffix) != 0) goto err; + break; + case 'N': + if (CoordsToString(string, value, 1, &spec, mask, suffix) != 0) goto err; + break; + case 'H': + if (CoordsToHumanString(string, value[0], &spec, suffix) != 0) goto err; + break; + case 'M': + if (CoordsToString(string, value, 1, &spec, mask & PCB_UNIT_ALLOW_METRIC, suffix) != 0) goto err; + break; + case 'L': + if (CoordsToString(string, value, 1, &spec, mask & PCB_UNIT_ALLOW_IMPERIAL, suffix) != 0) goto err; + break; + case 'k': + if (CoordsToString(string, value, 1, &spec, PCB_UNIT_ALLOW_DMIL, suffix) != 0) goto err; + break; + case 'r': + if (CoordsToString(string, value, 1, &spec, PCB_UNIT_ALLOW_READABLE, PCB_UNIT_NO_SUFFIX) != 0) goto err; + break; + /* All these fallthroughs are deliberate */ + case '9': + value[count++] = va_arg(args, pcb_coord_t); + case '8': + value[count++] = va_arg(args, pcb_coord_t); + case '7': + value[count++] = va_arg(args, pcb_coord_t); + case '6': + value[count++] = va_arg(args, pcb_coord_t); + case '5': + value[count++] = va_arg(args, pcb_coord_t); + case '4': + value[count++] = va_arg(args, pcb_coord_t); + case '3': + value[count++] = va_arg(args, pcb_coord_t); + case '2': + case 'D': + value[count++] = va_arg(args, pcb_coord_t); + if (CoordsToString(string, value, count, &spec, mask & PCB_UNIT_ALLOW_ALL_SANE, suffix) != 0) goto err; + break; + case 'd': + value[1] = va_arg(args, pcb_coord_t); + if (CoordsToString(string, value, 2, &spec, PCB_UNIT_ALLOW_MM | PCB_UNIT_ALLOW_MIL, suffix) != 0) goto err; + break; + case '*': + { + int found = 0; + for (i = 0; i < pcb_get_n_units(); ++i) { + if (strcmp(ext_unit, pcb_units[i].suffix) == 0) { + if (CoordsToString(string, value, 1, &spec, pcb_units[i].allow, suffix) != 0) goto err; + found = 1; + break; + } + } + if (!found) + if (CoordsToString(string, value, 1, &spec, mask & PCB_UNIT_ALLOW_ALL_SANE, suffix) != 0) goto err; + } + break; + case 'a': + if (gds_append_len(&spec, ".0f", 3) != 0) goto err; + if (suffix == PCB_UNIT_SUFFIX) + if (gds_append_len(&spec, " deg", 4) != 0) goto err; + tmplen = sprintf(tmp, spec.array, (double) va_arg(args, pcb_angle_t)); + if (gds_append_len(string, tmp, tmplen) != 0) goto err; + break; + case 'A': + if (gds_append_len(&spec, ".0f", 3) != 0) goto err; + /* if (suffix == PCB_UNIT_SUFFIX) + if (gds_append_len(&spec, " deg", 4) != 0) goto err;*/ + tmplen = sprintf(tmp, spec.array, 10*((double) va_arg(args, pcb_angle_t))); /* kicad legacy needs decidegrees */ + if (gds_append_len(string, tmp, tmplen) != 0) goto err; + break; + case 'f': + gds_append_len(&spec, "f", 1); + tmplen = sprintf(tmp, spec.array, va_arg(args, double)); + dot = strchr(spec.array, '.'); + if ((dot != NULL) && (dot[1] == '0')) + tmplen = do_trunc0(tmp); + if (gds_append_len(string, tmp, tmplen) != 0) goto err; + break; + case '+': + mask = va_arg(args, enum pcb_allow_e); + break; + default: + { + int found = 0; + for (i = 0; i < pcb_get_n_units(); ++i) { + if (*fmt == pcb_units[i].printf_code) { + if (CoordsToString(string, value, 1, &spec, pcb_units[i].allow, suffix) != 0) goto err; + found = 1; + break; + } + } + if (!found) + if (CoordsToString(string, value, 1, &spec, PCB_UNIT_ALLOW_ALL_SANE, suffix) != 0) goto err; + } + break; + } + break; + } + } + else + if (gds_append(string, *fmt) != 0) goto err; + ++fmt; + } + + retval = 0; +err:; + gds_uninit(&spec); + if (free_fmt != NULL) + free(free_fmt); + + return retval; +} + +int pcb_sprintf(char *string, const char *fmt, ...) +{ + gds_t str; + va_list args; + + memset(&str, 0, sizeof(str)); /* can't use gds_init, it'd allocate str.array */ + va_start(args, fmt); + + /* pretend the string is already allocated to something huge; this doesn't + make the code less safe but saves a copy */ + str.array = string; + str.alloced = 1<<31; + str.no_realloc = 1; + + pcb_append_vprintf(&str, fmt, args); + + va_end(args); + return str.used; +} + +int pcb_snprintf(char *string, size_t len, const char *fmt, ...) +{ + gds_t str; + va_list args; + + memset(&str, 0, sizeof(str)); /* can't use gds_init, it'd allocate str.array */ + va_start(args, fmt); + + str.array = string; + str.alloced = len; + str.no_realloc = 1; + + pcb_append_vprintf(&str, fmt, args); + + va_end(args); + return str.used; +} + +int pcb_vsnprintf(char *string, size_t len, const char *fmt, va_list args) +{ + gds_t str; + + memset(&str, 0, sizeof(str)); /* can't use gds_init, it'd allocate str.array */ + + str.array = string; + str.alloced = len; + str.no_realloc = 1; + + pcb_append_vprintf(&str, fmt, args); + + return str.used; +} + +int pcb_fprintf(FILE * fh, const char *fmt, ...) +{ + int rv; + va_list args; + + va_start(args, fmt); + rv = pcb_vfprintf(fh, fmt, args); + va_end(args); + + return rv; +} + +int pcb_vfprintf(FILE * fh, const char *fmt, va_list args) +{ + int rv; + gds_t str; + gds_init(&str); + + if (fh == NULL) + rv = -1; + else { + pcb_append_vprintf(&str, fmt, args); + rv = fprintf(fh, "%s", str.array); + } + + gds_uninit(&str); + return rv; +} + +int pcb_printf(const char *fmt, ...) +{ + int rv; + gds_t str; + va_list args; + + gds_init(&str); + va_start(args, fmt); + + pcb_append_vprintf(&str, fmt, args); + rv = printf("%s", str.array); + + va_end(args); + gds_uninit(&str); + return rv; +} + +char *pcb_strdup_printf(const char *fmt, ...) +{ + gds_t str; + va_list args; + + gds_init(&str); + + va_start(args, fmt); + pcb_append_vprintf(&str, fmt, args); + va_end(args); + + return str.array; /* no other allocation has been made */ +} + +char *pcb_strdup_vprintf(const char *fmt, va_list args) +{ + gds_t str; + gds_init(&str); + + pcb_append_vprintf(&str, fmt, args); + + return str.array; /* no other allocation has been made */ +} + + +/* Wrapper for pcb_append_vprintf that appends to a string using vararg API */ +int pcb_append_printf(gds_t *str, const char *fmt, ...) +{ + int retval; + + va_list args; + va_start(args, fmt); + retval = pcb_append_vprintf(str, fmt, args); + va_end(args); + + return retval; +} Index: tags/2.1.2/src/pcb-printf.h =================================================================== --- tags/2.1.2/src/pcb-printf.h (nonexistent) +++ tags/2.1.2/src/pcb-printf.h (revision 24813) @@ -0,0 +1,168 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 2011 Andrew Poelstra + * Copyright (C) 2016 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + * + * Old contact info: + * Andrew Poelstra, 16966 60A Ave, V3S 8X5 Surrey, BC, Canada + * asp11@sfu.ca + * + */ + +/* This file defines a wrapper around sprintf, that + * defines new specifiers that take pcb_coord_t objects + * as input. + * + * There is a fair bit of nasty (repetitious) code in + * here, but I feel the gain in clarity for output + * code elsewhere in the project will make it worth + * it. + * + * The new coord/angle specifiers are: + * %mI output a raw internal coordinate without any suffix + * %mm output a measure in mm + * %mu output a measure in um + * %mM output a measure in scaled (mm/um) metric + * %ml output a measure in mil + * %mk output a measure in decimil (kicad legacy format) + * %mL output a measure in scaled (mil/in) imperial + * %ms output a measure in most natural mm/mil units + * %mS output a measure in most natural scaled units + * %mN output a measure in requested natural units (enforces the choice of %m+ without further modifications) + * %mH output a measure in most human readable scaled units + * %md output a pair of measures in most natural mm/mil units + * %mD output a pair of measures in most natural scaled units + * %m3 output 3 measures in most natural scaled units + * ... + * %m9 output 9 measures in most natural scaled units + * %m* output a measure with unit given as an additional + * const char* parameter + * %m+ accepts an e_allow parameter that masks all subsequent + * "natural" (N/S/D/3/.../9) specifiers to only use certain + * units + * %mr output a measure in a unit readable by parse_l.l + * (outputs in centimil without units - compatibility with mainline) + * %ma output an angle in degrees (expects degrees) + * %mA output an angle in decidegrees (degrees x 10) for kicad legacy + * %mf output an a double (same as %f, expect it understands the .0n modifier) + * + * These accept the usual printf modifiers for %f, as well as + * $ output a unit suffix after the measure (with space between measure and unit) + * $$ output a unit suffix after the measure (without space) + * .n number of digits after the decimal point (the usual %f modifier) + * .0n where n is a digit; same as %.n, but truncates trailing zeros + * [n] use stored format n + * # prevents all scaling for %mS/D/1/.../9 (this should + * ONLY be used for debug code since its output exposes + * pcb's base units). + * + * The usual printf(3) precision and length modifiers should work with + * any format specifier that outputs coords, e.g. %.3mm will output in + * mm up to 3 decimal digits after the decimal point. + * + * The new string specifiers are: + * %mq output a quoted string (""); quote if contains quote. Use + * backslash to protect quotes within the quoted string. Modifiers: + * {chars} start quoting if any of these appear; "\}" in {chars} is a plain '}' + * + * + * KNOWN ISSUES: + * No support for %zu size_t printf spec + */ + +#ifndef PCB_PCB_PRINTF_H +#define PCB_PCB_PRINTF_H + +#include +#include +#include +#include "unit.h" + +int pcb_fprintf(FILE * f, const char *fmt, ...); +int pcb_vfprintf(FILE * f, const char *fmt, va_list args); +int pcb_sprintf(char *string, const char *fmt, ...); +int pcb_snprintf(char *string, size_t len, const char *fmt, ...); +int pcb_vsnprintf(char *string, size_t len, const char *fmt, va_list args); +int pcb_printf(const char *fmt, ...); +char *pcb_strdup_printf(const char *fmt, ...); +char *pcb_strdup_vprintf(const char *fmt, va_list args); + +int pcb_append_printf(gds_t *str, const char *fmt, ...); +int pcb_append_vprintf(gds_t *string, const char *fmt, va_list args); + +/* Predefined slots (macros): %[n] will use the nth string from this list. + The first 8 are user-definable. */ +typedef enum { + PCB_PRINTF_SLOT_USER0, + PCB_PRINTF_SLOT_USER1, + PCB_PRINTF_SLOT_USER2, + PCB_PRINTF_SLOT_USER3, + PCB_PRINTF_SLOT_USER4, + PCB_PRINTF_SLOT_USER5, + PCB_PRINTF_SLOT_USER6, + PCB_PRINTF_SLOT_USER7, + PCB_PRINTF_SLOT_FF_ORIG_COORD, /* %[8] original .pcb file format coord prints */ + PCB_PRINTF_SLOT_FF_SAFE_COORD, /* %[9] safe .pcb file format coord print that doesn't lose precision */ + PCB_PRINTF_SLOT_max +} pcb_printf_slot_idx_t; +extern const char *pcb_printf_slot[PCB_PRINTF_SLOT_max]; + +/* strdup and return a string built from a template, controlled by flags: + + PCB_SUBST_HOME: replace leading ~ with the user's home directory + + PCB_SUBST_PERCENT: attempt to replace printf-like formatting + directives (e.g. %P) using an user provided callback function. The callback + function needs to recognize the directive at **input (pointing to the byte + after the %) and append the substitution to s and increase *input to point + beyond the format directive. The callback returns 0 on success or -1 + on unknown directive (which will be copied verbatim). %% will always + be translated into a single %, without calling cb. + + PCB_SUBST_CONF: replace $(conf) automatically (no callback) + + Implemented in paths.c because it depends on conf_core.h and error.h . +*/ +typedef enum { + PCB_SUBST_HOME = 1, + PCB_SUBST_PERCENT = 2, + PCB_SUBST_CONF = 4, + PCB_SUBST_BACKSLASH = 8, /* substitute \ sequences as printf(3) does */ + + PCB_SUBST_ALL = 0x7f, /* substitute all, but do not enable quiet */ + + PCB_SUBST_QUIET = 0x80 +} pcb_strdup_subst_t; + +/* Substitute template using cb, leaving extra room at the end and append the + result to s. Returns 0 on success. */ +int pcb_subst_append(gds_t *s, const char *template, int (*cb)(void *ctx, gds_t *s, const char **input), void *ctx, pcb_strdup_subst_t flags, size_t extra_room); + +/* Same as pcb_subst_append(), but returns a dynamic allocated string + (the caller needs to free() after use) or NULL on error. */ +char *pcb_strdup_subst(const char *template, int (*cb)(void *ctx, gds_t *s, const char **input), void *ctx, pcb_strdup_subst_t flags); + +#endif Index: tags/2.1.2/src/pcb_bool.c =================================================================== --- tags/2.1.2/src/pcb_bool.c (nonexistent) +++ tags/2.1.2/src/pcb_bool.c (revision 24813) @@ -0,0 +1,38 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2017 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "config.h" +#include "pcb_bool.h" +#include "compat_misc.h" + +pcb_bool_op_t pcb_str2boolop(const char *s) +{ + if (pcb_strcasecmp(s, "set") == 0) return PCB_BOOL_SET; + if (pcb_strcasecmp(s, "clear") == 0) return PCB_BOOL_CLEAR; + if (pcb_strcasecmp(s, "toggle") == 0) return PCB_BOOL_TOGGLE; + if (pcb_strcasecmp(s, "preserve") == 0) return PCB_BOOL_PRESERVE; + return PCB_BOOL_INVALID; +} Index: tags/2.1.2/src/pcb_bool.h =================================================================== --- tags/2.1.2/src/pcb_bool.h (nonexistent) +++ tags/2.1.2/src/pcb_bool.h (revision 24813) @@ -0,0 +1,61 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2016, 2017 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#ifndef PCB_BOOL_H +#define PCB_BOOL_H +/* Because stdbool is not c89 */ +typedef int pcb_bool; +typedef enum pcb_bool_e { + pcb_false = 0, + pcb_true = 1 +} pcb_bool_t; + + + /* for arguments optionally changing the value of a bool */ +typedef enum pcb_bool_op_e { + PCB_BOOL_CLEAR = 0, + PCB_BOOL_SET = 1, + PCB_BOOL_TOGGLE = -1, + PCB_BOOL_PRESERVE = -2, + PCB_BOOL_INVALID = -8 +} pcb_bool_op_t; + +/* changes the value of pcb_bool dst as requested by pcb_bool_op_t op + WARNING: evaluates dst multiple times */ +#define pcb_bool_op(dst, op) \ +do { \ + switch(op) { \ + case PCB_BOOL_CLEAR: (dst) = 0; break; \ + case PCB_BOOL_SET: (dst) = 1; break; \ + case PCB_BOOL_TOGGLE: (dst) = !(dst); break; \ + case PCB_BOOL_INVALID: \ + case PCB_BOOL_PRESERVE: break; \ + } \ +} while(0) + +pcb_bool_op_t pcb_str2boolop(const char *s); + +#endif Index: tags/2.1.2/src/pcb_minuid.c =================================================================== --- tags/2.1.2/src/pcb_minuid.c (nonexistent) +++ tags/2.1.2/src/pcb_minuid.c (revision 24813) @@ -0,0 +1,14 @@ +#include +#include "compat_misc.h" +#include "pcb_minuid.h" + +minuid_session_t pcb_minuid; + + +void pcb_minuid_init(void) +{ + int pid = pcb_getpid(); + minuid_init(&pcb_minuid); + minuid_salt(&pcb_minuid, &pid, sizeof(pid)); +} + Index: tags/2.1.2/src/pcb_minuid.h =================================================================== --- tags/2.1.2/src/pcb_minuid.h (nonexistent) +++ tags/2.1.2/src/pcb_minuid.h (revision 24813) @@ -0,0 +1,4 @@ +#include +extern minuid_session_t pcb_minuid; + +void pcb_minuid_init(void); Index: tags/2.1.2/src/plug_footprint.c =================================================================== --- tags/2.1.2/src/plug_footprint.c (nonexistent) +++ tags/2.1.2/src/plug_footprint.c (revision 24813) @@ -0,0 +1,479 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +#include "config.h" + +#include "plug_footprint.h" +#include "plugins.h" + +#include +#include +#include "conf_core.h" +#include "error.h" +#include "compat_misc.h" +#include "event.h" + +FILE PCB_FP_FOPEN_IN_DST_, *PCB_FP_FOPEN_IN_DST = &PCB_FP_FOPEN_IN_DST_; + + +pcb_plug_fp_t *pcb_plug_fp_chain = NULL; +pcb_fplibrary_t pcb_library; + +int pcb_fp_dupname(const char *name, char **basename, char **params) +{ + char *newname, *s; + + *basename = newname = pcb_strdup(name); + s = strchr(newname, '('); + if (s == NULL) { + *params = NULL; + return 0; + } + + /* split at '(' */ + *s = '\0'; + *params = s + 1; + s = *params + strlen(*params) - 1; + + /* strip ')' */ + if (*s == ')') + *s = '\0'; + + return 1; +} + +static htsp_t *fp_tags = NULL; + +const void *pcb_fp_tag(const char *tag, int alloc) +{ + htsp_entry_t *e; + static char *counter = NULL; + + if (fp_tags == NULL) + fp_tags = htsp_alloc(strhash, strkeyeq); + e = htsp_getentry(fp_tags, tag); + if ((e == NULL) && alloc) { + htsp_set(fp_tags, pcb_strdup(tag), (void *) counter); + counter++; + e = htsp_getentry(fp_tags, tag); + } + return e == NULL ? NULL : e->key; +} + +void pcb_fp_init() +{ + pcb_library.type = LIB_DIR; + pcb_library.name = pcb_strdup("/"); /* All names are eventually free()'d */ +} + +void pcb_fp_uninit() +{ + htsp_entry_t *e; + + if (pcb_plug_fp_chain != NULL) + pcb_message(PCB_MSG_ERROR, "pcb_plug_fp_chain is not empty; a plugin did not remove itself from the chain. Fix your plugins!\n"); + + pcb_fp_free_children(&pcb_library); + if (fp_tags != NULL) { + for (e = htsp_first(fp_tags); e; e = htsp_next(fp_tags, e)) + free(e->key); + htsp_free(fp_tags); + fp_tags = NULL; + } + free(pcb_library.name); + pcb_library.name = NULL; +} + +const char *pcb_fp_tagname(const void *tagid) +{ + return (char *) tagid; +} + +FILE *pcb_fp_fopen(const char *path, const char *name, pcb_fp_fopen_ctx_t *fctx, pcb_data_t *dst) +{ + FILE *res = NULL; + if (strchr(path, ':') != NULL) { + char *tmp, *next, *curr; + + curr = tmp = pcb_strdup(path); + while((res == NULL) && (curr != NULL)) { + next = strchr(curr, ':'); + if (next != NULL) { + *next= '\0'; + next++; + } + + PCB_HOOK_CALL(pcb_plug_fp_t, pcb_plug_fp_chain, fp_fopen, res, != NULL, (self, curr, name, fctx, dst)); + curr = next; + } + free(tmp); + } + else + PCB_HOOK_CALL(pcb_plug_fp_t, pcb_plug_fp_chain, fp_fopen, res, != NULL, (self, path, name, fctx, dst)); + return res; +} + +void pcb_fp_fclose(FILE * f, pcb_fp_fopen_ctx_t *fctx) +{ + if ((fctx->backend != NULL) && (fctx->backend->fp_fclose != NULL)) + fctx->backend->fp_fclose(fctx->backend, f, fctx); +} + +pcb_fplibrary_t *pcb_fp_append_entry(pcb_fplibrary_t *parent, const char *name, pcb_fptype_t type, void *tags[]) +{ + pcb_fplibrary_t *entry; /* Pointer to individual menu entry */ + + assert(parent->type == LIB_DIR); + entry = pcb_get_library_memory(parent); + if (entry == NULL) + return NULL; + + if (type == PCB_FP_PARAMETRIC) { + /* concat name and () */ + /* do not use pcb_strdup_printf or Concat here, do not increase gsch2pcb-rnd deps */ + int nl = strlen(name); + entry->name = malloc(nl+3); + memcpy(entry->name, name, nl); + strcpy(entry->name+nl, "()"); + } + else + entry->name = pcb_strdup(name); + + entry->type = LIB_FOOTPRINT; + entry->data.fp.type = type; + entry->data.fp.tags = tags; + entry->data.fp.loc_info = NULL; + entry->data.fp.backend_data = NULL; + return entry; +} + +pcb_fplibrary_t *fp_lib_search_len(pcb_fplibrary_t *dir, const char *name, int name_len) +{ + pcb_fplibrary_t *l; + int n; + + if (dir->type != LIB_DIR) + return NULL; + + for(n = 0, l = dir->data.dir.children.array; n < dir->data.dir.children.used; n++, l++) + if (strncmp(l->name, name, name_len) == 0) + return l; + + return NULL; +} + +pcb_fplibrary_t *pcb_fp_lib_search(pcb_fplibrary_t *dir, const char *name) +{ + pcb_fplibrary_t *l; + int n; + + if (dir->type != LIB_DIR) + return NULL; + + for(n = 0, l = dir->data.dir.children.array; n < dir->data.dir.children.used; n++, l++) + if (strcmp(l->name, name) == 0) + return l; + + return NULL; +} + + +pcb_fplibrary_t *pcb_fp_mkdir_len(pcb_fplibrary_t *parent, const char *name, int name_len) +{ + pcb_fplibrary_t *l = pcb_get_library_memory(parent); + + if (name_len > 0) + l->name = pcb_strndup(name, name_len); + else + l->name = pcb_strdup(name); + l->parent = parent; + l->type = LIB_DIR; + l->data.dir.backend = NULL; + vtlib_init(&l->data.dir.children); + return l; +} + +pcb_fplibrary_t *pcb_fp_mkdir_p(const char *path) +{ + pcb_fplibrary_t *l, *parent = NULL; + const char *next; + + /* search for the last existing dir in the path */ + + while(*path == '/') path++; + for(parent = l = &pcb_library; l != NULL; parent = l,path = next) { + next = strchr(path, '/'); + if (next == NULL) + l = pcb_fp_lib_search(l, path); + else + l = fp_lib_search_len(l, path, next-path); + + /* skip path sep */ + if (next != NULL) { + while(*next == '/') next++; + if (*next == '\0') + next = NULL; + } + + /* last elem of the path */ + if (next == NULL) { + if (l != NULL) + return l; + break; /* found a non-existing node */ + } + + if (l == NULL) + break; + } + + /* by now path points to the first non-existing dir, under parent */ + for(;path != NULL; path = next) { + next = strchr(path, '/'); + parent = pcb_fp_mkdir_len(parent, path, next-path); + if (next != NULL) { + while(*next == '/') next++; + if (*next == '\0') + next = NULL; + } + } + + return parent; +} + +static int fp_sort_cb(const void *a, const void *b) +{ + const pcb_fplibrary_t *fa = a, *fb = b; + int res = strcmp(fa->name, fb->name); + return res == 0 ? 1 : res; +} + +void pcb_fp_sort_children(pcb_fplibrary_t *parent) +{ + vtlib_t *v; + int n; + + if (parent->type != LIB_DIR) + return; + + v = &parent->data.dir.children; + qsort(v->array, vtlib_len(v), sizeof(pcb_fplibrary_t), fp_sort_cb); + + for (n = 0; n < vtlib_len(v); n++) + pcb_fp_sort_children(&v->array[n]); +} + +void fp_free_entry(pcb_fplibrary_t *l) +{ + switch(l->type) { + case LIB_DIR: + pcb_fp_free_children(l); + vtlib_uninit(&(l->data.dir.children)); + break; + case LIB_FOOTPRINT: + if (l->data.fp.loc_info != NULL) + free(l->data.fp.loc_info); + if (l->data.fp.tags != NULL) + free(l->data.fp.tags); + break; + case LIB_INVALID: break; /* suppress compiler warning */ + } + if (l->name != NULL) { + free(l->name); + l->name = NULL; + } + l->type = LIB_INVALID; +} + +void pcb_fp_free_children(pcb_fplibrary_t *parent) +{ + int n; + pcb_fplibrary_t *l; + + assert(parent->type == LIB_DIR); + + for(n = 0, l = parent->data.dir.children.array; n < parent->data.dir.children.used; n++, l++) + fp_free_entry(l); + + vtlib_truncate(&(parent->data.dir.children), 0); +} + + +void pcb_fp_rmdir(pcb_fplibrary_t *dir) +{ + pcb_fplibrary_t *l, *parent = dir->parent; + int n; + fp_free_entry(dir); + if (parent != NULL) { + for(n = 0, l = parent->data.dir.children.array; n < parent->data.dir.children.used; n++,l++) { + if (l == dir) { + vtlib_remove(&(parent->data.dir.children), n, 1); + break; + } + } + } +} + +/* Debug functions */ +void fp_dump_dir(pcb_fplibrary_t *dir, int level) +{ + pcb_fplibrary_t *l; + int n, p; + + for(n = 0, l = dir->data.dir.children.array; n < dir->data.dir.children.used; n++, l++) { + for(p = 0; p < level; p++) + putchar(' '); + if (l->type == LIB_DIR) { + printf("%s/\n", l->name); + fp_dump_dir(l, level+1); + } + else if (l->type == LIB_FOOTPRINT) + printf("%s\n", l->name); + else + printf("*INVALID*\n"); + } +} + +void fp_dump() +{ + fp_dump_dir(&pcb_library, 0); +} + +/* This function loads the newlib footprints into the Library. + * It examines all directories pointed to by the search paths + * (normally Settings.LibraryTree). + * In each directory specified there, it looks both in that directory, + * as well as *one* level down. It calls the subfunction + * fp_fs_load_dir to put the footprints into PCB's internal + * datastructures. + */ +static int fp_read_lib_all_(const char *searchpath) +{ + char *toppath, toppath_[PCB_PATH_MAX + 1]; /* String holding abs path to top level library dir */ + char *libpaths; /* String holding list of library paths to search */ + char *p; /* Helper string used in iteration */ + int n_footprints = 0; /* Running count of footprints found */ + int res; + + /* Additional loop to allow for multiple 'newlib' style library directories + * called out in Settings.LibraryTree + */ + libpaths = pcb_strdup(searchpath); + for (p = strtok(libpaths, PCB_PATH_DELIMETER); p && *p; p = strtok(NULL, PCB_PATH_DELIMETER)) { + int silent_fail = 0; + + /* remove trailing path delimiter */ + strncpy(toppath_, p, sizeof(toppath_) - 1); + toppath_[sizeof(toppath_) - 1] = '\0'; + + /* make paths starting with '?' optional (silently fail) */ + toppath = toppath_; + if (toppath[0] == '?') { + toppath++; + silent_fail = 1; + } + +#ifdef DEBUG + printf("In ParseLibraryTree, looking for newlib footprints inside top level directory %s ... \n", toppath); +#endif + + /* Next read in any footprints in the top level dir */ + res = -1; + PCB_HOOK_CALL(pcb_plug_fp_t, pcb_plug_fp_chain, load_dir, res, >= 0, (self, toppath, 0)); + if (res >= 0) + n_footprints += res; + else if (!silent_fail) + pcb_message(PCB_MSG_WARNING, "Warning: footprint library list error on %s\n", toppath); + } + +#ifdef DEBUG + printf("Leaving ParseLibraryTree, found %d footprints.\n", n_footprints); +#endif + + free(libpaths); + return n_footprints; +} + +static gds_t fpds_paths; +static int fpds_inited = 0; + +const char *pcb_fp_default_search_path(void) +{ + return conf_concat_strlist(&conf_core.rc.library_search_paths, &fpds_paths, &fpds_inited, ':'); +} + +int pcb_fp_host_uninit(void) +{ + if (fpds_inited) + gds_uninit(&fpds_paths); + return 0; +} + +int pcb_fp_read_lib_all(void) +{ + FILE *resultFP = NULL; + + /* List all footprint libraries. Then sort the whole + * library. + */ + if (fp_read_lib_all_(pcb_fp_default_search_path()) > 0 || resultFP != NULL) { + pcb_fp_sort_children(&pcb_library); + return 0; + } + + return 1; +} + +int pcb_fp_rehash(pcb_fplibrary_t *l) +{ + pcb_plug_fp_t *be; + char *path; + int res; + + if (l == NULL) { + pcb_fp_free_children(&pcb_library); + return pcb_fp_read_lib_all(); + } + if (l->type != LIB_DIR) + return -1; + + be = l->data.dir.backend; + if ((be == NULL) || (be->load_dir == NULL)) + return -1; + + path = pcb_strdup(l->name); + pcb_fp_rmdir(l); + res = be->load_dir(be, path, 1); + pcb_fp_sort_children(&pcb_library); + free(path); + + if (res >= 0) { + pcb_event(PCB_EVENT_LIBRARY_CHANGED, NULL); + return 0; + } + return -1; +} Index: tags/2.1.2/src/plug_footprint.h =================================================================== --- tags/2.1.2/src/plug_footprint.h (nonexistent) +++ tags/2.1.2/src/plug_footprint.h (revision 24813) @@ -0,0 +1,96 @@ +#ifndef PCB_PLUG_FOOTPRINT_H +#define PCB_PLUG_FOOTPRINT_H + +#include +#include "vtlibrary.h" +#include "data.h" + +typedef struct pcb_plug_fp_s pcb_plug_fp_t; + +typedef struct { + pcb_plug_fp_t *backend; + union { + int i; + void *p; + } field[4]; +} pcb_fp_fopen_ctx_t; + +/* hook bindings, see below */ +FILE *pcb_fp_fopen(const char *path, const char *name, pcb_fp_fopen_ctx_t *fctx, pcb_data_t *dst); +void pcb_fp_fclose(FILE * f, pcb_fp_fopen_ctx_t *fctx); + +/* duplicates the name and splits it into a basename and params; + params is NULL if the name is not parametric (and "" if parameter list is empty) + returns 1 if name is parametric footprint, 0 if static file footprint. + The caller shall free only *basename at the end. + */ +int pcb_fp_dupname(const char *name, char **basename, char **params); + +/**** tag management ****/ +/* Resolve a tag name to an unique void * ID; create unknown tag if alloc != 0 */ +const void *pcb_fp_tag(const char *tag, int alloc); + +/* Resolve a tag ID to a tag name */ +const char *pcb_fp_tagname(const void *tagid); + +/* init/uninit the footprint lib, free tag key memory */ +void pcb_fp_init(); +void pcb_fp_uninit(); + +/**************************** API definition *********************************/ +extern FILE *PCB_FP_FOPEN_IN_DST; + +struct pcb_plug_fp_s { + pcb_plug_fp_t *next; + void *plugin_data; + + /* returns the number of footprints loaded into the library or -1 on + error; next in chain is run only on error. If force is 1, force doing the + expensive part of the load (e.g. wget) */ + int (*load_dir)(pcb_plug_fp_t *ctx, const char *path, int force); + +/* Open a footprint for reading; if the footprint is parametric, it's run + prefixed with libshell (or executed directly, if libshell is NULL). + If name is not an absolute path, search_path is searched for the first match. + The user has to supply a state integer that will be used by pcb_pcb_fp_fclose(). + Must fill in fctx->backend, may use any other field of fctx as well. + If dst is non-NULL, some backends (e.g. fp_board) may decide to place the + loaded footprint in dst and return PCB_FP_FOPEN_IN_DST. + */ + FILE *(*fp_fopen)(pcb_plug_fp_t *ctx, const char *path, const char *name, pcb_fp_fopen_ctx_t *fctx, pcb_data_t *dst); + +/* Close the footprint file opened by pcb_pcb_fp_fopen(). */ + void (*fp_fclose)(pcb_plug_fp_t *ctx, FILE * f, pcb_fp_fopen_ctx_t *fctx); +}; + +extern pcb_plug_fp_t *pcb_plug_fp_chain; + + +/* Optional pcb-rnd-side glue for some implementations */ + +extern pcb_fplibrary_t pcb_library; /* the footprint library */ + +#define pcb_get_library_memory(parent) vtlib_alloc_append(((parent) == NULL ? &pcb_library.data.dir.children : &(parent)->data.dir.children), 1); + +void pcb_fp_free_children(pcb_fplibrary_t *parent); +void pcb_fp_sort_children(pcb_fplibrary_t *parent); +void pcb_fp_rmdir(pcb_fplibrary_t *dir); +pcb_fplibrary_t *pcb_fp_mkdir_p(const char *path); +pcb_fplibrary_t *pcb_fp_mkdir_len(pcb_fplibrary_t *parent, const char *name, int name_len); +pcb_fplibrary_t *pcb_fp_lib_search(pcb_fplibrary_t *dir, const char *name); + +/* Append a menu entry in the tree */ +pcb_fplibrary_t *pcb_fp_append_entry(pcb_fplibrary_t *parent, const char *name, pcb_fptype_t type, void *tags[]); + +/* walk through all lib paths and build the library menu */ +int pcb_fp_read_lib_all(void); + + +const char *pcb_fp_default_search_path(void); + +int pcb_fp_host_uninit(void); + +/* rescan/reload all footprints in the library cache */ +int pcb_fp_rehash(pcb_fplibrary_t *l); + +#endif Index: tags/2.1.2/src/plug_footprint_act.c =================================================================== --- tags/2.1.2/src/plug_footprint_act.c (nonexistent) +++ tags/2.1.2/src/plug_footprint_act.c (revision 24813) @@ -0,0 +1,82 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2016 Tibor 'Igor2' Palinkas + * + * This module was written and is Copyright (C) 2016 by Tibor Palinkas + * this module is also subject to the GNU GPL as described below + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "config.h" +#include "actions.h" +#include "plug_footprint.h" + +static const char pcb_acts_fp_rehash[] = "fp_rehash()" ; +static const char pcb_acth_fp_rehash[] = "Flush the library index; rescan all library search paths and rebuild the library index. Useful if there are changes in the library during a pcb-rnd session."; +static fgw_error_t pcb_act_fp_rehash(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + const char *name = NULL; + pcb_fplibrary_t *l; + + PCB_ACT_MAY_CONVARG(1, FGW_STR, fp_rehash, name = argv[1].val.str); + PCB_ACT_IRES(0); + + if (name == NULL) { + pcb_fp_rehash(NULL); + return 0; + } + + l = pcb_fp_lib_search(&pcb_library, name); + if (l == NULL) { + pcb_message(PCB_MSG_ERROR, "Can't find library path %s\n", name); + PCB_ACT_IRES(1); + return 0; + } + + if (l->type != LIB_DIR) { + pcb_message(PCB_MSG_ERROR, "Library path %s is not a directory\n", name); + PCB_ACT_IRES(1); + return 0; + } + + if (l->data.dir.backend == NULL) { + pcb_message(PCB_MSG_ERROR, "Library path %s is not a top level directory of a fp_ plugin\n", name); + PCB_ACT_IRES(1); + return 0; + } + + if (pcb_fp_rehash(l) != 0) { + pcb_message(PCB_MSG_ERROR, "Failed to rehash %s\n", name); + PCB_ACT_IRES(1); + return 0; + } + + return 0; +} + + +pcb_action_t conf_plug_footprint_list[] = { + {"fp_rehash", pcb_act_fp_rehash, pcb_acth_fp_rehash, pcb_acts_fp_rehash} +}; + +PCB_REGISTER_ACTIONS(conf_plug_footprint_list, NULL) Index: tags/2.1.2/src/plug_import.c =================================================================== --- tags/2.1.2/src/plug_import.c (nonexistent) +++ tags/2.1.2/src/plug_import.c (revision 24813) @@ -0,0 +1,129 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996,1997,1998,2005,2006 Thomas Nau + * Copyright (C) 2015,2016 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +/* This used to be file.c; it's a hook based plugin API now */ + +#include "config.h" +#include "conf_core.h" + +#include +#include +#include +#include +#include + +#include "plugins.h" +#include "plug_import.h" +#include "error.h" +#include "safe_fs.h" + + +pcb_plug_import_t *pcb_plug_import_chain = NULL; + +typedef struct { + pcb_plug_import_t *plug; + int prio; +} find_t; + +/* Find the plugin that offers the highest write prio for the format */ +static pcb_plug_import_t *find_importer(unsigned int aspects, FILE *f, const char *filename) +{ + find_t available[32]; /* wish we had more than 32 import plugins... */ + int n, len = 0, best = 0, bestidx = -1; + +#define cb_append(pl, pr) \ + do { \ + rewind(f); \ + if (pr > 0) { \ + assert(len < sizeof(available)/sizeof(available[0])); \ + available[len].plug = pl; \ + available[len++].prio = pr; \ + } \ + } while(0) + + if (f == NULL) + return NULL; + + PCB_HOOK_CALL_ALL(pcb_plug_import_t, pcb_plug_import_chain, fmt_support_prio, cb_append, (self, aspects, f, filename)); + if (len == 0) + return NULL; + + for(n = 0; n < len; n++) { + if (available[n].prio > best) { + bestidx = n; + best = available[n].prio; + } + } + + if (best == 0) + return NULL; + + return available[bestidx].plug; +#undef cb_append +} + + +int pcb_import(char *filename, unsigned int aspect) +{ + pcb_plug_import_t *plug; + FILE *fp; + + if (!filename) { + pcb_message(PCB_MSG_ERROR, "Error: need a file name for pcb_import_netlist()\n"); + return 1; /* nothing to do */ + } + fp = pcb_fopen(filename, "r"); + + plug = find_importer(aspect, fp, filename); + if (plug == NULL) { + if (fp != NULL) { + pcb_message(PCB_MSG_ERROR, "Error: can't find a suitable netlist parser for %s\n", filename); + fclose(fp); + } + else + pcb_message(PCB_MSG_ERROR, "Error: can't find a suitable netlist parser for %s - might be related: can't open %s for reading\n", filename, filename); + return 1; + } + + if (fp != NULL) + fclose(fp); + + return plug->import(plug, aspect, filename); +} + +int pcb_import_netlist(char *filename) +{ + return pcb_import(filename, IMPORT_ASPECT_NETLIST); +} + +void pcb_import_uninit(void) +{ + if (pcb_plug_import_chain != NULL) + pcb_message(PCB_MSG_ERROR, "pcb_plug_import_chain is not empty; a plugin did not remove itself from the chain. Fix your plugins!\n"); +} Index: tags/2.1.2/src/plug_import.h =================================================================== --- tags/2.1.2/src/plug_import.h (nonexistent) +++ tags/2.1.2/src/plug_import.h (revision 24813) @@ -0,0 +1,66 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996,1997,1998,2005,2006 Thomas Nau + * Copyright (C) 2016 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +#ifndef PCB_PLUG_IMPORT_H +#define PCB_PLUG_IMPORT_H + +#include "config.h" +#include "conf.h" + +/**************************** API definition *********************************/ + +typedef enum pcb_plug_import_aspect_e { /* bitfield of aspects that can be imported */ + IMPORT_ASPECT_NETLIST = 1 +} pcb_plug_import_aspect_t; + +typedef struct pcb_plug_import_s pcb_plug_import_t; +struct pcb_plug_import_s { + pcb_plug_import_t *next; + void *plugin_data; + + /* Check if the plugin supports format fmt. Return 0 if not supported or + an integer priority if supported. The higher the prio is the more likely + the plugin gets the next operation on the file. Base prio should be 100 + for native formats. Return non-0 only if all aspects are supported. */ + int (*fmt_support_prio)(pcb_plug_import_t *ctx, unsigned int aspects, FILE *f, const char *filename); + + /* Perform the import; return 0 on success */ + int (*import)(pcb_plug_import_t *ctx, unsigned int aspects, const char *fn); +}; + +extern pcb_plug_import_t *pcb_plug_import_chain; + +void pcb_import_uninit(void); + +/********** hook wrappers **********/ +int pcb_import(char *filename, unsigned int aspect); +int pcb_import_netlist(char *); + + +#endif Index: tags/2.1.2/src/plug_io.c =================================================================== --- tags/2.1.2/src/plug_io.c (nonexistent) +++ tags/2.1.2/src/plug_io.c (revision 24813) @@ -0,0 +1,939 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996,1997,1998,2005,2006 Thomas Nau + * Copyright (C) 2015,2016 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + + +/* This used to be file.c; some of the code landed in the io_pcb plugin, + the format-independent parts ended up here. */ + +/* file save, load, merge ... routines */ + +/* If emergency format is not configured but emergency file name is, default + to saving in the native format */ +#define DEFAULT_EMERGENCY_FMT "lihata" + +#include "config.h" +#include "conf_core.h" + +#include +#include +#include +#include +#include +#include + +#include "change.h" +#include "conf.h" +#include "data.h" +#include "error.h" +#include "plug_io.h" +#include "remove.h" +#include "paths.h" +#include "rats_patch.h" +#include "actions.h" +#include "pcb-printf.h" +#include "plugins.h" +#include "event.h" +#include "compat_misc.h" +#include "route_style.h" +#include "compat_fs.h" +#include "compat_lrealpath.h" +#include "layer_vis.h" +#include "safe_fs.h" +#include "plug_footprint.h" +#include "file_loaded.h" +#include "macro.h" +#include "view.h" + +/* for opendir */ +#include "compat_inc.h" + +pcb_plug_io_t *pcb_plug_io_chain = NULL; +int pcb_io_err_inhibit = 0; +pcb_view_list_t pcb_io_incompat_lst; +static pcb_bool pcb_io_incompat_lst_enable = pcb_false; + +static void plug_io_err(int res, const char *what, const char *filename) +{ + if (pcb_io_err_inhibit) + return; + if (res != 0) { + const char *reason = "", *comment = ""; + if (pcb_plug_io_chain != NULL) { + if (filename == NULL) { + reason = "none of io plugins could successfully write the file"; + filename = ""; + } + else { + FILE *f; + reason = "none of io plugins could successfully read file"; + f = pcb_fopen(filename, "r"); + if (f != NULL) { + fclose(f); + comment = "(unknown/invalid file format?)"; + } + else + comment = "(can not open the file for reading)"; + } + } + else { + reason = "no io plugin loaded, I don't know any file format"; + if (filename == NULL) + filename = ""; + } + pcb_message(PCB_MSG_ERROR, "IO error during %s: %s %s %s\n", what, reason, filename, comment); + } +} + +static char *last_design_dir = NULL; +void pcb_set_design_dir(const char *fn) +{ + char *end; + + free(last_design_dir); + last_design_dir = NULL; + + if (fn != NULL) + last_design_dir = pcb_lrealpath(fn); + + if (last_design_dir == NULL) { + last_design_dir = pcb_strdup(""); + conf_force_set_str(conf_core.rc.path.design, last_design_dir); + pcb_conf_ro("rc/path/design"); + return; + } + + end = strrchr(last_design_dir, PCB_DIR_SEPARATOR_C); + if (end != NULL) + *end = '\0'; + + conf_force_set_str(conf_core.rc.path.design, last_design_dir); + pcb_conf_ro("rc/path/design"); +} + +static int pcb_test_parse_all(FILE *ft, const char *Filename, const char *fmt, pcb_plug_iot_t type, pcb_find_io_t *available, int *accepts, int *accept_total, int maxav, int ignore_missing, int gen_event) +{ + int len, n; + + if (ft == NULL) { + if (!ignore_missing) + pcb_message(PCB_MSG_ERROR, "Error: can't open %s for reading (format is %s)\n", Filename, fmt); + return -1; + } + + if (gen_event) + pcb_event(PCB_EVENT_LOAD_PRE, "s", Filename); + + len = pcb_find_io(available, maxav, type, 0, fmt); + if (fmt != NULL) { + /* explicit format */ + for(n = 0; n < len; n++) { + void (*f)(); + switch(type) { + case PCB_IOT_PCB: f = (void (*)())available[n].plug->parse_pcb; break; + default: assert(!"internal error: pcb_test_parse_all: wrong type"); f = NULL; + } + if (f != NULL) { + accepts[n] = 1; /* force-accept - if it can handle the format, and the user explicitly wanted this format, let's try it */ + (*accept_total)++; + } + } + + if (*accept_total <= 0) { + pcb_message(PCB_MSG_ERROR, "can't find a IO_ plugin to load a PCB using format %s\n", fmt); + return -1; + } + + if (*accept_total > 1) { + pcb_message(PCB_MSG_INFO, "multiple IO_ plugins can handle format %s - I'm going to try them all, but you may want to be more specific next time; formats found:\n", fmt); + for(n = 0; n < len; n++) + pcb_message(PCB_MSG_INFO, " %s\n", available[n].plug->description); + } + } + else { + /* test-parse with all plugins to see who can handle the syntax */ + if((fgetc(ft) != EOF)) { + rewind(ft); + for(n = 0; n < len; n++) { + if ((available[n].plug->test_parse == NULL) || (available[n].plug->test_parse(available[n].plug, type, Filename, ft))) { + accepts[n] = 1; + (*accept_total)++; + } + else + accepts[n] = 0; + rewind(ft); + } + } + } + + if (*accept_total == 0) { + pcb_message(PCB_MSG_ERROR, "none of the IO_ plugin recognized the file format of %s - it's either not a valid board file or does not match the format specified\n", Filename); + return -1; + } + return len; +} + +int pcb_parse_pcb(pcb_board_t *Ptr, const char *Filename, const char *fmt, int load_settings, int ignore_missing) +{ + int res = -1, len, n; + pcb_find_io_t available[PCB_IO_MAX_FORMATS]; + int accepts[PCB_IO_MAX_FORMATS]; /* test-parse output */ + int accept_total = 0; + FILE *ft; + + ft = pcb_fopen(Filename, "r"); + len = pcb_test_parse_all(ft, Filename, fmt, PCB_IOT_PCB, available, accepts, &accept_total, sizeof(available)/sizeof(available[0]), ignore_missing, load_settings); + if (ft != NULL) + fclose(ft); + if (len < 0) + return -1; + + Ptr->Data->loader = NULL; + + /* try all plugins that said it could handle the file */ + for(n = 0; n < len; n++) { + if ((available[n].plug->parse_pcb == NULL) || (!accepts[n])) /* can't parse or doesn't want to parse this file */ + continue; + res = available[n].plug->parse_pcb(available[n].plug, Ptr, Filename, load_settings); + if (res == 0) { + if (Ptr->Data->loader == NULL) /* if the loader didn't set this (to some more fine grained, e.g. depending on file format version) */ + Ptr->Data->loader = available[n].plug; + break; + } + } + + if ((res == 0) && (load_settings)) + conf_load_project(NULL, Filename); + + if (res == 0) + pcb_set_design_dir(Filename); + + if (load_settings) + pcb_event(PCB_EVENT_LOAD_POST, "si", Filename, res); + pcb_event(PCB_EVENT_ROUTE_STYLES_CHANGED, NULL); + conf_set(CFR_DESIGN, "design/text_font_id", 0, "0", POL_OVERWRITE); /* we have only one font now, make sure it is selected */ + + plug_io_err(res, "load pcb", Filename); + return res; +} + +int pcb_parse_footprint(pcb_data_t *Ptr, const char *Filename, const char *fmt) +{ + int res = -1, len, n; + pcb_find_io_t available[PCB_IO_MAX_FORMATS]; + int accepts[PCB_IO_MAX_FORMATS]; /* test-parse output */ + int accept_total = 0; + FILE *f; + pcb_fp_fopen_ctx_t fctx; + + f = pcb_fp_fopen(pcb_fp_default_search_path(), Filename, &fctx, Ptr); + if (f == PCB_FP_FOPEN_IN_DST) + return 0; + len = pcb_test_parse_all(f, Filename, fmt, PCB_IOT_FOOTPRINT, available, accepts, &accept_total, sizeof(available)/sizeof(available[0]), 0, 0); + if (f != NULL) + pcb_fp_fclose(f, &fctx); + if (len < 0) + return -1; + + Ptr->loader = NULL; + + /* try all plugins that said it could handle the file */ + for(n = 0; n < len; n++) { + if ((available[n].plug->parse_footprint == NULL) || (!accepts[n])) /* can't parse or doesn't want to parse this file */ + continue; + res = available[n].plug->parse_footprint(available[n].plug, Ptr, Filename); + if (res == 0) { + if (Ptr->loader == NULL) /* if the loader didn't set this (to some more fine grained, e.g. depending on file format version) */ + Ptr->loader = available[n].plug; + break; + } + } + + /* remove selected/found flag when loading reusable footprints */ + if (res == 0) + pcb_data_flag_change(Ptr, PCB_OBJ_CLASS_REAL, PCB_CHGFLG_CLEAR, PCB_FLAG_FOUND | PCB_FLAG_SELECTED); + + plug_io_err(res, "load footprint", Filename); + return res; +} + +int pcb_parse_font(pcb_font_t *Ptr, const char *Filename) +{ + int res = -1; + PCB_HOOK_CALL(pcb_plug_io_t, pcb_plug_io_chain, parse_font, res, == 0, (self, Ptr, Filename)); + + plug_io_err(res, "load font", Filename); + return res; +} + +static int find_prio_cmp(const void *p1, const void *p2) +{ + const pcb_find_io_t *f1 = p1, *f2 = p2; + if (f1->prio < f2->prio) + return 1; + return -1; +} + +int pcb_find_io(pcb_find_io_t *available, int avail_len, pcb_plug_iot_t typ, int is_wr, const char *fmt) +{ + int len = 0; + +#define cb_append(pl, pr) \ + do { \ + if (pr > 0) { \ + assert(len < avail_len ); \ + available[len].plug = pl; \ + if (fmt == NULL) \ + available[len].prio = pl->save_preference_prio; \ + else \ + available[len].prio = pr; \ + len++; \ + } \ + } while(0) + + PCB_HOOK_CALL_ALL(pcb_plug_io_t, pcb_plug_io_chain, fmt_support_prio, cb_append, (self, typ, is_wr, (fmt == NULL ? self->default_fmt : fmt))); + + if (len > 0) + qsort(available, len, sizeof(available[0]), find_prio_cmp); +#undef cb_append + + return len; +} + +/* Find the plugin that offers the highest write prio for the format */ +static pcb_plug_io_t *find_writer(pcb_plug_iot_t typ, const char *fmt) +{ + pcb_find_io_t available[PCB_IO_MAX_FORMATS]; + int len; + + if (fmt == NULL) { + if (PCB->Filename != NULL) { /* have a file name, guess from extension */ + int fn_len = strlen(PCB->Filename); + const char *end = PCB->Filename + fn_len; + pcb_plug_io_t *n, *best = NULL; + int best_score = 0; + + /* the the plugin that has a matching extension and has the highest save_preference_prio value */ + for(n = pcb_plug_io_chain; n != NULL; n = n->next) { + if (n->default_extension != NULL) { + int elen = strlen(n->default_extension); + if ((elen < fn_len) && (strcmp(end-elen, n->default_extension) == 0)) { + if (n->save_preference_prio > best_score) { + best_score = n->save_preference_prio; + best = n; + } + } + } + } + if (best != NULL) + return best; + } + + /* no file name or format hint, or file name not recognized: choose the ultimate default */ + fmt = conf_core.rc.save_final_fallback_fmt; + if (fmt == NULL) { + pcb_message(PCB_MSG_WARNING, "Saving a file with unknown format: failed to guess format from file name, no value configured in rc/save_final_fallback_fmt - CAN NOT SAVE FILE, try save as.\n"); + return NULL; + } + else { + if (PCB->Filename != NULL) + pcb_message(PCB_MSG_WARNING, "Saving a file with unknown format: failed to guess format from file name, falling back to %s as configured in rc/save_final_fallback_fmt\n", fmt); + } + } + + len = pcb_find_io(available, sizeof(available)/sizeof(available[0]), typ, 1, fmt); + + if (len == 0) + return NULL; + + return available[0].plug; +} + + +int pcb_write_buffer(FILE *f, pcb_buffer_t *buff, const char *fmt, pcb_bool elem_only) +{ + int res/*, newfmt = 0*/; + pcb_plug_io_t *p = find_writer(PCB_IOT_BUFFER, fmt); + + if (p != NULL) { + res = p->write_buffer(p, f, buff, elem_only); + /*newfmt = 1;*/ + } + +/* if ((res == 0) && (newfmt)) + PCB->Data->loader = p;*/ + + plug_io_err(res, "write buffer", NULL); + return res; +} + +int pcb_write_footprint_data(FILE *f, pcb_data_t *e, const char *fmt) +{ + int res, newfmt = 0; + pcb_plug_io_t *p = e->loader; + + if ((p == NULL) || ((fmt != NULL) && (*fmt != '\0'))) { + p = find_writer(PCB_IOT_FOOTPRINT, fmt); + newfmt = 1; + } + + if ((p != NULL) && (p->write_footprint != NULL)) + res = p->write_footprint(p, f, e); + + if ((res == 0) && (newfmt)) + e->loader = p; + + plug_io_err(res, "write element", NULL); + return res; +} + +int pcb_write_font(pcb_font_t *Ptr, const char *Filename, const char *fmt) +{ + int res/*, newfmt = 0*/; + pcb_plug_io_t *p = find_writer(PCB_IOT_FONT, fmt); + + if (p != NULL) { + res = p->write_font(p, Ptr, Filename); + /*newfmt = 1;*/ + } + else + res = -1; + +/* if ((res == 0) && (newfmt)) + PCB->Data->loader = p;*/ + + plug_io_err(res, "write font", NULL); + return res; +} + + +static int pcb_write_pcb(FILE *f, const char *old_filename, const char *new_filename, const char *fmt, pcb_bool emergency) +{ + int res, newfmt = 0; + pcb_plug_io_t *p = PCB->Data->loader; + + if ((p == NULL) || ((fmt != NULL) && (*fmt != '\0'))) { + p = find_writer(PCB_IOT_PCB, fmt); + newfmt = 1; + } + + if (p != NULL) { + if (p->write_pcb != NULL) { + pcb_event(PCB_EVENT_SAVE_PRE, "s", fmt); + res = p->write_pcb(p, f, old_filename, new_filename, emergency); + pcb_event(PCB_EVENT_SAVE_POST, "si", fmt, res); + } + else { + pcb_message(PCB_MSG_ERROR, "Can't write PCB: internal error: io plugin %s doesn't implement write_pcb()\n", p->description); + res = -1; + } + } + + if ((res == 0) && (newfmt)) + PCB->Data->loader = p; + + if (res == 0) + pcb_set_design_dir(new_filename); + + plug_io_err(res, "write pcb", NULL); + return res; +} + +/* load PCB: parse the file with enabled 'PCB mode' (see parser); if + successful, update some other stuff. If revert is pcb_true, we pass + "revert" as a parameter to the pcb changed event. */ +static int real_load_pcb(const char *Filename, const char *fmt, pcb_bool revert, pcb_bool require_font, int how) +{ + const char *unit_suffix; + char *new_filename; + pcb_board_t *newPCB = pcb_board_new_(pcb_false); + pcb_board_t *oldPCB; + conf_role_t settings_dest; +#ifdef DEBUG + double elapsed; + clock_t start, end; + + start = clock(); +#endif + + pcb_path_resolve(Filename, &new_filename, 0, pcb_false); + + oldPCB = PCB; + PCB = newPCB; + + /* mark the default font invalid to know if the file has one */ + newPCB->fontkit.valid = pcb_false; + + switch(how & 0x0F) { + case 0: settings_dest = CFR_DESIGN; break; + case 1: settings_dest = CFR_DEFAULTPCB; break; + case 2: settings_dest = CFR_invalid; break; + default: abort(); + } + + /* new data isn't added to the undo list */ + if (!pcb_parse_pcb(PCB, new_filename, fmt, settings_dest, how & 0x10)) { + pcb_board_remove(oldPCB); + + pcb_board_new_postproc(PCB, 0); + if (how == 0) { + /* update cursor location */ + pcb_crosshair.X = PCB->MaxWidth/2; + pcb_crosshair.Y = PCB->MaxHeight/2; + + /* update cursor confinement and output area (scrollbars) */ + pcb_board_resize(PCB->MaxWidth, PCB->MaxHeight); + } + + /* have to be called after pcb_board_resize() so vis update is after a board changed update */ + pcb_event(PCB_EVENT_LAYERS_CHANGED, NULL); + pcb_layervis_reset_stack(); + + /* enable default font if necessary */ + if (!PCB->fontkit.valid) { + if ((require_font) && (!PCB->is_footprint)) + pcb_message(PCB_MSG_WARNING, "File '%s' has no font information, using default font\n", new_filename); + PCB->fontkit.valid = pcb_true; + } + + /* footprint edition: let the user directly manipulate subc parts */ + PCB->loose_subc = PCB->is_footprint; + + /* clear 'changed flag' */ + pcb_board_set_changed_flag(pcb_false); + PCB->Filename = new_filename; + /* just in case a bad file saved file is loaded */ + + /* Use attribute PCB::grid::unit as unit, if we can */ + unit_suffix = pcb_attrib_get(PCB, "PCB::grid::unit"); + if (unit_suffix && *unit_suffix) { + const pcb_unit_t *new_unit = get_unit_struct(unit_suffix); + if (new_unit) + conf_set(settings_dest, "editor/grid_unit", -1, unit_suffix, POL_OVERWRITE); + } + pcb_attrib_put(PCB, "PCB::grid::unit", conf_core.editor.grid_unit->suffix); + + pcb_ratspatch_make_edited(PCB); + +/* set route style to the first one, if the current one doesn't + happen to match any. This way, "revert" won't change the route style. */ + { + extern fgw_error_t pcb_act_GetStyle(fgw_arg_t *res, int argc, fgw_arg_t *argv); + fgw_arg_t res, argv; + if (PCB_ACT_CALL_C(pcb_act_GetStyle, &res, 1, &argv) < 0) + pcb_use_route_style_idx(&PCB->RouteStyle, 0); + } + + if ((how == 0) || (revert)) + pcb_board_changed(revert); + +#ifdef DEBUG + end = clock(); + elapsed = ((double) (end - start)) / CLOCKS_PER_SEC; + pcb_message(PCB_MSG_INFO, "Loading file %s took %f seconds of CPU time\n", new_filename, elapsed); +#endif + + conf_core.temp.rat_warn = pcb_true; /* make sure the first click can remove warnings */ + + return 0; + } + + free(new_filename); + PCB = oldPCB; + if (PCB == NULL) { + /* bozo: we are trying to revert back to a non-existing pcb... create one to avoid a segfault */ + PCB = pcb_board_new_(pcb_false); + if (PCB == NULL) { + pcb_message(PCB_MSG_ERROR, "FATAL: can't create a new empty pcb!"); + exit(1); + } + } + + if (!(how & PCB_INHIBIT_BOARD_CHANGED)) + pcb_board_changed(0); + + /* release unused memory */ + pcb_board_remove(newPCB); + + return 1; +} + + +#if !defined(HAS_ATEXIT) +static char *TMPFilename = NULL; +#endif + +#define F2S(OBJ, TYPE) pcb_strflg_f2s((OBJ)->Flags, TYPE) + +int pcb_save_buffer_elements(const char *Filename, const char *fmt) +{ + int result; + + if (conf_core.editor.show_solder_side) + pcb_buffers_flip_side(PCB); + result = pcb_write_pipe(Filename, pcb_false, fmt, pcb_true); + if (conf_core.editor.show_solder_side) + pcb_buffers_flip_side(PCB); + return result; +} + +int pcb_save_pcb(const char *file, const char *fmt) +{ + int retcode; + + pcb_io_incompat_lst_enable = pcb_true; + if (conf_core.editor.io_incomp_popup) + pcb_view_list_free_fields(&pcb_io_incompat_lst); + + if (pcb_gui->notify_save_pcb != NULL) { + pcb_gui->notify_save_pcb(file, pcb_false); + retcode = pcb_write_pipe(file, pcb_true, fmt, pcb_false); + pcb_gui->notify_save_pcb(file, pcb_true); + } + else + retcode = pcb_write_pipe(file, pcb_true, fmt, pcb_false); + + pcb_io_incompat_lst_enable = pcb_false; + if (conf_core.editor.io_incomp_popup) { + long int len = pcb_view_list_length(&pcb_io_incompat_lst); + if (len > 0) { + pcb_message(PCB_MSG_ERROR, "There were %ld save incompatibility errors.\nData in memory is not affected, but the file created may be slightly broken.\nSee the popup view listing for detauls.\n", len); + pcb_actionl("IOincompatList", conf_core.editor.io_incomp_style, "auto", NULL); + } + } + + return retcode; +} + +int pcb_load_pcb(const char *file, const char *fmt, pcb_bool require_font, int how) +{ + int res = real_load_pcb(file, fmt, pcb_false, require_font, how); + if (res == 0) { + pcb_file_loaded_set_at("design", "main", file, PCB->is_footprint ? "footprint" : "board"); + if (PCB->is_footprint) { + pcb_box_t b; + /* a footprint has no board size set, need to invent one */ + pcb_data_bbox(&b, PCB->Data, 0); + if ((b.X2 < b.X1) || (b.Y2 < b.Y1)) { + pcb_message(PCB_MSG_ERROR, "Invalid footprint file: can not determine bounding box\n"); + res = -1; + } + else + pcb_board_resize(b.X2*1.5, b.Y2*1.5); + } + } + return res; +} + +int pcb_revert_pcb(void) +{ + return real_load_pcb(PCB->Filename, NULL, pcb_true, pcb_true, 1); +} + +void pcb_print_quoted_string_(FILE * FP, const char *S) +{ + const char *start; + + for(start = S; *S != '\0'; S++) { + if (*S == '"' || *S == '\\') { + if (start != S) + fwrite(start, S-start, 1, FP); + fputc('\\', FP); + fputc(*S, FP); + start = S+1; + } + } + + if (start != S) + fwrite(start, S-start, 1, FP); +} + +void pcb_print_quoted_string(FILE *FP, const char *S) +{ + fputc('"', FP); + pcb_print_quoted_string_(FP, S); + fputc('"', FP); +} + +/* this is used for fatal errors and does not call the program specified in + 'saveCommand' for safety reasons */ +void pcb_save_in_tmp(void) +{ + char filename[256]; + + /* memory might have been released before this function is called */ + if (PCB && PCB->Changed && (conf_core.rc.emergency_name != NULL) && (*conf_core.rc.emergency_name != '\0')) { + const char *fmt = conf_core.rc.emergency_format == NULL ? DEFAULT_EMERGENCY_FMT : conf_core.rc.emergency_format; + sprintf(filename, conf_core.rc.emergency_name, (long int)pcb_getpid()); + pcb_message(PCB_MSG_INFO, "Trying to save your layout in '%s'\n", filename); + pcb_write_pcb_file(filename, pcb_true, fmt, pcb_true, pcb_false); + } +} + +/* front-end for pcb_save_in_tmp() to makes sure it is only called once */ +static pcb_bool dont_save_any_more = pcb_false; +void pcb_emergency_save(void) +{ + + if (!dont_save_any_more) { + dont_save_any_more = pcb_true; + pcb_save_in_tmp(); + } +} + +void pcb_disable_emergency_save(void) +{ + dont_save_any_more = pcb_true; +} + +/*** Autosave ***/ + +static pcb_hidval_t backup_timer; + +/* + * If the backup interval is > 0 then set another timer. Otherwise + * we do nothing and it is up to the GUI to call pcb_enable_autosave() + * after setting conf_core.rc.backup_interval > 0 again. + */ +static void backup_cb(pcb_hidval_t data) +{ + backup_timer.ptr = NULL; + pcb_backup(); + if (conf_core.rc.backup_interval > 0 && pcb_gui->add_timer) + backup_timer = pcb_gui->add_timer(backup_cb, 1000 * conf_core.rc.backup_interval, data); +} + +void pcb_enable_autosave(void) +{ + pcb_hidval_t x; + + x.ptr = NULL; + + /* If we already have a timer going, then cancel it out */ + if (backup_timer.ptr != NULL && pcb_gui->stop_timer) + pcb_gui->stop_timer(backup_timer); + + backup_timer.ptr = NULL; + /* Start up a new timer */ + if (conf_core.rc.backup_interval > 0 && pcb_gui->add_timer) + backup_timer = pcb_gui->add_timer(backup_cb, 1000 * conf_core.rc.backup_interval, x); +} + +/* Saves the board in a backup file using the name configured in + conf_core.rc.backup_name */ +void pcb_backup(void) +{ + char *filename = NULL; + const char *fmt = NULL; + pcb_plug_io_t *orig; + + filename = pcb_build_fn(conf_core.rc.backup_name); + if (filename == NULL) { + fprintf(stderr, "pcb_backup(): can't build file name for a backup\n"); + exit(1); + } + + if ((conf_core.rc.backup_format != NULL) && (strcmp(conf_core.rc.backup_format, "original") != 0)) + fmt = conf_core.rc.backup_format; + + orig = PCB->Data->loader; + pcb_write_pcb_file(filename, pcb_true, fmt, pcb_true, pcb_false); + PCB->Data->loader = orig; + + free(filename); +} + +/* Write the pcb file, a footprint or a buffer */ +static int pcb_write_file(FILE *fp, pcb_bool thePcb, const char *old_path, const char *new_path, const char *fmt, pcb_bool emergency, pcb_bool elem_only) +{ + if (thePcb) { + if (PCB->is_footprint) + return pcb_write_footprint_data(fp, PCB->Data, fmt); + return pcb_write_pcb(fp, old_path, new_path, fmt, emergency); + } + return pcb_write_buffer(fp, PCB_PASTEBUFFER, fmt, elem_only); +} + +int pcb_write_pcb_file(const char *Filename, pcb_bool thePcb, const char *fmt, pcb_bool emergency, pcb_bool elem_only) +{ + FILE *fp; + int result, overwrite; + char *fn_tmp = NULL; + + overwrite = pcb_file_readable(Filename); + if (overwrite) { + int len = strlen(Filename); + fn_tmp = malloc(len+8); + memcpy(fn_tmp, Filename, len); + strcpy(fn_tmp+len, ".old"); + if (pcb_rename(Filename, fn_tmp) != 0) { + if (emergency) { + /* Try an alternative emergency file */ + strcpy(fn_tmp+len, ".emr"); + Filename = fn_tmp; + } + else { + pcb_message(PCB_MSG_ERROR, "Can't rename %s to %s before save\n", Filename, fn_tmp); + return -1; + } + } + } + + if ((fp = pcb_fopen(Filename, "w")) == NULL) { + pcb_open_error_message(Filename); + return (-1); + } + + result = pcb_write_file(fp, thePcb, fn_tmp, Filename, fmt, emergency, elem_only); + + fclose(fp); + if (fn_tmp != NULL) { + if ((result == 0) && (!conf_core.rc.keep_save_backups)) + unlink(fn_tmp); + free(fn_tmp); + } + return result; +} + + +/* writes to pipe using the command defined by conf_core.rc.save_command + * %f are replaced by the passed filename */ +int pcb_write_pipe(const char *Filename, pcb_bool thePcb, const char *fmt, pcb_bool elem_only) +{ + FILE *fp; + int result; + const char *p; + static gds_t command; + const char *save_cmd; + + if (PCB_EMPTY_STRING_P(conf_core.rc.save_command)) + return pcb_write_pcb_file(Filename, thePcb, fmt, pcb_false, elem_only); + + save_cmd = conf_core.rc.save_command; + /* setup commandline */ + gds_truncate(&command,0); + for (p = save_cmd; *p; p++) { + /* copy character if not special or add string to command */ + if (!(p[0] == '%' && p[1] == 'f')) + gds_append(&command, *p); + else { + gds_append_str(&command, Filename); + + /* skip the character */ + p++; + } + } + printf("write to pipe \"%s\"\n", command.array); + if ((fp = pcb_popen(command.array, "w")) == NULL) { + pcb_popen_error_message(command.array); + return (-1); + } + + result = pcb_write_file(fp, thePcb, NULL, NULL, fmt, pcb_false, elem_only); + + return (pcb_pclose(fp) ? (-1) : result); +} + + +int pcb_io_list(pcb_io_formats_t *out, pcb_plug_iot_t typ, int wr, int do_digest, pcb_io_list_ext_t ext) +{ + pcb_find_io_t available[PCB_IO_MAX_FORMATS]; + int n; + + memset(out, 0, sizeof(pcb_io_formats_t)); + out->len = pcb_find_io(available, sizeof(available)/sizeof(available[0]), typ, 1, NULL); + + if (out->len == 0) + return 0; + + for(n = 0; n < out->len; n++) { + out->plug[n] = available[n].plug; + switch(ext) { + case PCB_IOL_EXT_NONE: out->extension[n] = NULL; break; + case PCB_IOL_EXT_BOARD: out->extension[n] = out->plug[n]->default_extension; break; + case PCB_IOL_EXT_FP: out->extension[n] = out->plug[n]->fp_extension; break; + } + } + + if (do_digest) { + for(n = 0; n < out->len; n++) + out->digest[n] = pcb_strdup_printf("%s (%s)", out->plug[n]->default_fmt, out->plug[n]->description); + out->digest[n] = NULL; + } + + return out->len; +} + +void pcb_io_list_free(pcb_io_formats_t *out) +{ + int n; + + for(n = 0; n < out->len; n++) { + if (out->digest[n] != NULL) { + free(out->digest[n]); + out->digest[n] = NULL; + } + } +} + + +pcb_cardinal_t pcb_io_incompat_save(pcb_data_t *data, pcb_any_obj_t *obj, const char *type, const char *title, const char *description) +{ + + if ((pcb_io_incompat_lst_enable) && (conf_core.editor.io_incomp_popup)) { + pcb_view_t *violation = pcb_view_new(type, title, description); + if ((obj != NULL) && (obj->type & PCB_OBJ_CLASS_REAL)) { + pcb_view_append_obj(violation, 0, obj); + pcb_view_set_bbox_by_objs(PCB->Data, violation); + } + pcb_view_list_append(&pcb_io_incompat_lst, violation); + } + else { + pcb_message(PCB_MSG_ERROR, "save error: %s\n", title); + if (obj != NULL) { + pcb_coord_t x = (obj->BoundingBox.X1 + obj->BoundingBox.X2)/2; + pcb_coord_t y = (obj->BoundingBox.Y1 + obj->BoundingBox.Y2)/2; + pcb_message(PCB_MSG_ERROR, " near %$mm %$mm\n", x, y); + } + if (description != NULL) + pcb_message(PCB_MSG_ERROR, " (%s)\n", description); + } + return 0; +} + + +void pcb_io_uninit(void) +{ + pcb_view_list_free_fields(&pcb_io_incompat_lst); + if (pcb_plug_io_chain != NULL) { + pcb_message(PCB_MSG_ERROR, "pcb_plug_io_chain is not empty; a plugin did not remove itself from the chain. Fix your plugins!\n"); + pcb_message(PCB_MSG_ERROR, "head: desc='%s'\n", pcb_plug_io_chain->description); + } + free(last_design_dir); + last_design_dir = NULL; +} Index: tags/2.1.2/src/plug_io.h =================================================================== --- tags/2.1.2/src/plug_io.h (nonexistent) +++ tags/2.1.2/src/plug_io.h (revision 24813) @@ -0,0 +1,184 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996,1997,1998,2005,2006 Thomas Nau + * Copyright (C) 2016 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +#ifndef PCB_PLUG_IO_H +#define PCB_PLUG_IO_H + +#include "global_typedefs.h" +#include "conf.h" + +typedef enum { /* I/O type bitmask; each bit is one thing to save or load, not all formats support all things */ + PCB_IOT_PCB = 1, + PCB_IOT_FOOTPRINT = 2, + PCB_IOT_FONT = 4, + PCB_IOT_BUFFER = 8 +} pcb_plug_iot_t; + +/**************************** API definition *********************************/ +struct pcb_plug_io_s { + pcb_plug_io_t *next; + void *plugin_data; + + /* Check if the plugin supports format fmt, for writing (if wr != 0) or for + reading (if wr == 0) for I/O type typ. Return 0 if not supported or an + integer priority if supported. The higher the prio is the more likely + the plugin gets the next operation on the file. Base prio should be + 100 for native formats. + NOTE: if any format can be chosen for output, the user will have to pick + one; for ordering plugins in that case, the format-neutral + save_preference_prio field is used. + */ + int (*fmt_support_prio)(pcb_plug_io_t *ctx, pcb_plug_iot_t typ, int wr, const char *fmt); + + /* Test if the given file is readable by the plugin. The plugin should return + 1 if it can handle the file or 0 if it can not. This check is not a deep + syntax analysis; the plugin should read barely enough headers to decide if + the file contains a the format it expect, then return error from parse_pcb + if there are syntax errors later. The file is open for read and positioned + to file begin in f */ + int (*test_parse)(pcb_plug_io_t *ctx, pcb_plug_iot_t typ, const char *Filename, FILE *f); + + /* Attempt to load a pcb design from Filename to Ptr. + Conf subtree at settings_dest is replaced by settings loaded from the + file unless it's CFR_invalid. + Return 0 on success. */ + int (*parse_pcb)(pcb_plug_io_t *ctx, pcb_board_t *Ptr, const char *Filename, conf_role_t settings_dest); + + /* Attempt to load an element from Filename to Ptr. Return 0 on success. */ + int (*parse_footprint)(pcb_plug_io_t *ctx, pcb_data_t *Ptr, const char *name); + + /* Attempt to load fonts from a file. Return 0 on success. */ + int (*parse_font)(pcb_plug_io_t *ctx, pcb_font_t *Ptr, const char *Filename); + + + /* Write the buffer to a file. Return 0 on success. */ + int (*write_buffer)(pcb_plug_io_t *ctx, FILE *f, pcb_buffer_t *buff, pcb_bool elem_only); + + /* Write element data to a file. Return 0 on success. */ + int (*write_footprint)(pcb_plug_io_t *ctx, FILE *f, pcb_data_t *e); + + /* Write PCB to f; there's a copy of the file we are going to + "overwrite", named in old_filename and the new file name we are + using is new_filename. The file names are NULL if we are saving + into a pipe. If emergency is true, do the safest save possible, + don't mind formatting and extras. + Return 0 on success. */ + int (*write_pcb)(pcb_plug_io_t *ctx, FILE *f, const char *old_filename, const char *new_filename, pcb_bool emergency); + + /* Attempt to write the font to file. Return 0 on success. */ + int (*write_font)(pcb_plug_io_t *ctx, pcb_font_t *font, const char *Filename); + + const char *default_fmt; + const char *description; + const char *default_extension; /* used to generate save-as filename */ + const char *fp_extension; /* used to generate save-as filename for footprints */ + const char *mime_type; + + int save_preference_prio; /* all available save plugins are sorted by this before presenting them to the user to choose one */ +}; +extern pcb_plug_io_t *pcb_plug_io_chain; + + +/********** hook wrappers **********/ +int pcb_parse_pcb(pcb_board_t *Ptr, const char *Filename, const char *fmt, int load_settings, int ignore_missing); +int pcb_parse_footprint(pcb_data_t *Ptr, const char *name, const char *fmt); +int pcb_parse_font(pcb_font_t *Ptr, const char *Filename); +int pcb_write_buffer(FILE *f, pcb_buffer_t *buff, const char *fmt, pcb_bool elem_only); +int pcb_write_footprint_data(FILE *f, pcb_data_t *e, const char *fmt); +int pcb_write_font(pcb_font_t *Ptr, const char *Filename, const char *fmt); + +/********** common function used to be part of file.[ch] and friends **********/ +int pcb_save_pcb(const char *, const char *fmt); +#define PCB_INHIBIT_BOARD_CHANGED 0x20 +int pcb_load_pcb(const char *name, const char *fmt, pcb_bool, int how); /* how: 0=normal pcb; 1=default.pcb, 2=misc (do not load settings) | 0x10: ignore missing file, | PCB_INHIBIT_BOARD_CHANGED: do not send a board changed event */ +void pcb_enable_autosave(void); +void pcb_backup(void); +void pcb_save_in_tmp(void); +void pcb_emergency_save(void); +void pcb_disable_emergency_save(void); +int pcb_revert_pcb(void); +int pcb_save_buffer_elements(const char *, const char *fmt); +void pcb_print_quoted_string_(FILE *, const char *); /* without wrapping in "" */ +void pcb_print_quoted_string(FILE *, const char *); /* with wrapping in "" */ +int pcb_write_pcb_file(const char *Filename, pcb_bool thePcb, const char *fmt, pcb_bool emergency, pcb_bool elem_only); +int pcb_write_pipe(const char *, pcb_bool, const char *fmt, pcb_bool elem_only); +void pcb_set_design_dir(const char *fn); + +/********** helpers **********/ + +/* wish we had more than 32 IO plugins... */ +#define PCB_IO_MAX_FORMATS 32 + +/* A list of format plugins available for a given purpose */ +typedef struct { + int len; + const pcb_plug_io_t *plug[PCB_IO_MAX_FORMATS+1]; + char *digest[PCB_IO_MAX_FORMATS+1]; /* string that contains the format identifier and the description (strdup'd) */ + const char *extension[PCB_IO_MAX_FORMATS+1]; /* default file extension, with the leading . (not strdup'd) */ +} pcb_io_formats_t; + +typedef enum { + PCB_IOL_EXT_NONE, + PCB_IOL_EXT_BOARD, + PCB_IOL_EXT_FP +} pcb_io_list_ext_t; + +/* Search all io plugins to see if typ/wr is supported. Return an ordered + list in out. If do_digest is non-zero, fill in the digest field. Returns + number of suitable io plugins. Call pcb_io_list_free() on out when it is not + needed anymore. */ +int pcb_io_list(pcb_io_formats_t *out, pcb_plug_iot_t typ, int wr, int do_digest, pcb_io_list_ext_t ext); +void pcb_io_list_free(pcb_io_formats_t *out); + +extern int pcb_io_err_inhibit; +#define pcb_io_err_inhibit_inc() pcb_io_err_inhibit++ +#define pcb_io_err_inhibit_dec() \ +do { \ + if (pcb_io_err_inhibit > 0) \ + pcb_io_err_inhibit--; \ +} while(0) + +/* Find all plugins that can handle typ/is_wr and build an ordered list in available[], + highest prio first. If fmt is NULL, use the default fmt for each plugin. + Return the length of the array. */ +typedef struct { + pcb_plug_io_t *plug; + int prio; +} pcb_find_io_t; +int pcb_find_io(pcb_find_io_t *available, int avail_len, pcb_plug_iot_t typ, int is_wr, const char *fmt); + +/* Indicate an incompatibility on save; data and obj may be NULL (they are + used for navigating the user to the problem). Desc should be a short + description (must not be NULL), details should go in hint (can be NULL). + Returns a report ID. */ +pcb_cardinal_t pcb_io_incompat_save(pcb_data_t *data, pcb_any_obj_t *obj, const char *type, const char *title, const char *description); + +void pcb_io_uninit(void); + +#endif Index: tags/2.1.2/src/plugins.c =================================================================== --- tags/2.1.2/src/plugins.c (nonexistent) +++ tags/2.1.2/src/plugins.c (revision 24813) @@ -0,0 +1,62 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2015 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include +#include +#include "plugins.h" + +/* for the action */ +#include "config.h" +#include "genvector/gds_char.h" +#include "compat_misc.h" +#include "actions.h" + +unsigned long pcb_api_ver = PCB_API_VER; + +pup_context_t pcb_pup; +char **pcb_pup_paths = NULL; +static int paths_used = 0, paths_alloced = 0; + +void pcb_plugin_add_dir(const char *dir) +{ + if (paths_used+1 >= paths_alloced) { + paths_alloced += 16; + pcb_pup_paths = realloc(pcb_pup_paths, sizeof(char *) * paths_alloced); + } + pcb_pup_paths[paths_used] = pcb_strdup(dir); + paths_used++; + pcb_pup_paths[paths_used] = NULL; +} + +void pcb_plugin_uninit(void) +{ + int n; + for(n = 0; n < paths_used; n++) + free(pcb_pup_paths[n]); + free(pcb_pup_paths); + pcb_pup_paths = NULL; +} + Index: tags/2.1.2/src/plugins.h =================================================================== --- tags/2.1.2/src/plugins.h (nonexistent) +++ tags/2.1.2/src/plugins.h (revision 24813) @@ -0,0 +1,103 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2015 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#ifndef PCB_RND_PLUGINS_H +#define PCB_RND_PLUGINS_H + +#include +#include + +/* core's version stored in plugins.o */ +extern unsigned long pcb_api_ver; + +#define PCB_API_VER_MATCH (PCB_API_VER == pcb_api_ver) +#define PCB_API_CHK_VER \ +do { \ + if (!PCB_API_VER_MATCH) {\ + fprintf(stderr, "pcb-rnd API version incompatibility: " __FILE__ "=%lu core=%lu\n(not loading this plugin)\n", (unsigned long)PCB_API_VER, pcb_api_ver); \ + return 1; \ + } \ +} while(0) + +extern pup_context_t pcb_pup; +extern char **pcb_pup_paths; + +void pcb_plugin_add_dir(const char *dir); +void pcb_plugin_uninit(void); + +/* Hook based plugin generics; plugins that implement a common API should use + HOOK_REGISTER with an api struct. The core should run the plugins using + HOOK_CALL */ + +#define PCB_HOOK_CALL_DO(chain_type, chain, func, res, accept, funcargs, do_on_success) \ +do { \ + chain_type *self; \ + for(self = (chain); self != NULL; self = self->next) { \ + if (self->func == NULL) \ + continue; \ + res = self->func funcargs; \ + if (res accept) {\ + do_on_success; \ + break; \ + } \ + } \ +} while(0) + +#define PCB_HOOK_CALL(chain_type, chain, func, res, accept, funcargs) \ + PCB_HOOK_CALL_DO(chain_type, chain, func, res, accept, funcargs, (void)0) + +#define PCB_HOOK_CALL_ALL(chain_type, chain, func, cb, funcargs) \ +do { \ + chain_type *self; \ + for(self = (chain); self != NULL; self = self->next) { \ + int res; \ + if (self->func == NULL) \ + continue; \ + res = self->func funcargs; \ + cb(self, res); \ + } \ +} while(0) + +#define PCB_HOOK_REGISTER(chain_type, chain, hstruct) \ +do { \ + (hstruct)->next = chain; \ + chain = (hstruct); \ +} while(0) + + +#define PCB_HOOK_UNREGISTER(chain_type, chain, hstruct) \ +do { \ + chain_type *__n__, *__prev__ = NULL, *__h__ = (hstruct); \ + while (chain == __h__) \ + chain = chain->next; \ + for(__n__ = chain; __n__ != NULL; __n__ = __n__->next) { \ + if ((__n__ == __h__) && (__prev__ != NULL)) \ + __prev__->next = __n__->next; \ + __prev__ = __n__; \ + } \ +} while(0) + +#endif Index: tags/2.1.2/src/polyarea.h =================================================================== --- tags/2.1.2/src/polyarea.h (nonexistent) +++ tags/2.1.2/src/polyarea.h (revision 24813) @@ -0,0 +1,165 @@ +/* + poly_Boolean: a polygon clip library + Copyright (C) 1997 Alexey Nikitin, Michael Leonov + leonov@propro.iis.nsk.su + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + polyarea.h + (C) 1997 Alexey Nikitin, Michael Leonov + (C) 1997 Klamer Schutte (minor patches) +*/ + +#ifndef PCB_POLYAREA_H +#define PCB_POLYAREA_H + +#define PCB_PLF_DIR 1 +#define PCB_PLF_INV 0 +#define PCB_PLF_MARK 1 + +typedef pcb_coord_t pcb_vertex_t[2]; /* longing point representation of + coordinates */ +typedef pcb_vertex_t pcb_vector_t; + +#define pcb_vertex_equ(a,b) (memcmp((a),(b),sizeof(pcb_vector_t))==0) +#define pcb_vertex_cpy(a,b) memcpy((a),(b),sizeof(pcb_vector_t)) + + +extern pcb_vector_t vect_zero; + +enum { + pcb_err_no_memory = 2, + pcb_err_bad_parm = 3, + pcb_err_ok = 0 +}; + + +typedef struct pcb_cvc_list_s pcb_cvc_list_t; +typedef struct pcb_vnode_s pcb_vnode_t; +struct pcb_cvc_list_s { + double angle; + pcb_vnode_t *parent; + pcb_cvc_list_t *prev, *next, *head; + char poly, side; +}; +struct pcb_vnode_s { + pcb_vnode_t *next, *prev, *shared; + struct { + unsigned int status:3; + unsigned int mark:1; + unsigned int in_hub:1; + } Flags; + pcb_cvc_list_t *cvc_prev; + pcb_cvc_list_t *cvc_next; + pcb_vector_t point; +}; + +typedef struct pcb_pline_s pcb_pline_t; +struct pcb_pline_s { + pcb_coord_t xmin, ymin, xmax, ymax; + pcb_pline_t *next; + pcb_vnode_t head; + unsigned int Count; + double area; + pcb_rtree_t *tree; + pcb_bool is_round; + pcb_coord_t cx, cy; + pcb_coord_t radius; + struct { + unsigned int status:3; + unsigned int orient:1; + } Flags; +}; + +pcb_pline_t *pcb_poly_contour_new(pcb_vector_t v); + +void pcb_poly_contour_init(pcb_pline_t * c); +void pcb_poly_contour_clear(pcb_pline_t * c); /* clears list of vertices */ +void pcb_poly_contour_del(pcb_pline_t ** c); + +pcb_bool pcb_poly_contour_copy(pcb_pline_t ** dst, pcb_pline_t * src); + +void pcb_poly_contour_pre(pcb_pline_t * c, pcb_bool optimize); /* prepare contour */ +void pcb_poly_contour_inv(pcb_pline_t * c); /* invert contour */ + +pcb_vnode_t *pcb_poly_node_create(pcb_vector_t v); + +void pcb_poly_vertex_include(pcb_vnode_t * after, pcb_vnode_t * node); +void pcb_poly_vertex_exclude(pcb_vnode_t * node); + +/**********************************************************************/ + +struct pcb_polyarea_s { + pcb_polyarea_t *f, *b; + pcb_pline_t *contours; + pcb_rtree_t *contour_tree; +}; + +pcb_bool pcb_polyarea_m_copy0(pcb_polyarea_t ** dst, const pcb_polyarea_t * srcfst); +void pcb_polyarea_m_include(pcb_polyarea_t ** list, pcb_polyarea_t * a); + +pcb_bool pcb_polyarea_copy0(pcb_polyarea_t ** dst, const pcb_polyarea_t * src); +pcb_bool pcb_polyarea_copy1(pcb_polyarea_t * dst, const pcb_polyarea_t * src); + +pcb_bool pcb_polyarea_contour_include(pcb_polyarea_t * p, pcb_pline_t * c); +pcb_bool pcb_polyarea_contour_exclude(pcb_polyarea_t * p, pcb_pline_t * c); + + +pcb_bool pcb_polyarea_contour_check(pcb_pline_t * a); + +pcb_bool pcb_polyarea_contour_inside(pcb_polyarea_t * c, pcb_vector_t v0); +pcb_bool pcb_polyarea_touching(pcb_polyarea_t * p1, pcb_polyarea_t * p2); + +/**********************************************************************/ + +/* tools for clipping */ + +/* checks whether point lies within contour +independently of its orientation */ + +int pcb_poly_contour_inside(pcb_pline_t * c, pcb_vector_t v); +int pcb_poly_contour_in_contour(pcb_pline_t * poly, pcb_pline_t * inner); +pcb_polyarea_t *pcb_polyarea_create(void); + +void pcb_polyarea_free(pcb_polyarea_t ** p); +void pcb_polyarea_init(pcb_polyarea_t * p); +void pcb_poly_contours_free(pcb_pline_t ** pl); +pcb_bool pcb_poly_valid(pcb_polyarea_t * p); + +enum pcb_poly_bool_op_e { + PCB_PBO_UNITE, + PCB_PBO_ISECT, + PCB_PBO_SUB, + PCB_PBO_XOR +}; + +double pcb_vect_dist2(pcb_vector_t v1, pcb_vector_t v2); +double pcb_vect_det2(pcb_vector_t v1, pcb_vector_t v2); +double pcb_vect_len2(pcb_vector_t v1); + +int pcb_vect_inters2(pcb_vector_t A, pcb_vector_t B, pcb_vector_t C, pcb_vector_t D, pcb_vector_t S1, pcb_vector_t S2); + +int pcb_polyarea_boolean(const pcb_polyarea_t * a, const pcb_polyarea_t * b, pcb_polyarea_t ** res, int action); +int pcb_polyarea_boolean_free(pcb_polyarea_t * a, pcb_polyarea_t * b, pcb_polyarea_t ** res, int action); +int pcb_polyarea_and_subtract_free(pcb_polyarea_t * a, pcb_polyarea_t * b, pcb_polyarea_t ** aandb, pcb_polyarea_t ** aminusb); +int pcb_polyarea_save(pcb_polyarea_t * PA, char *fname); + +/* calculate the bounding box of a pcb_polyarea_t and save result in b */ +void pcb_polyarea_bbox(pcb_polyarea_t * p, pcb_box_t * b); + +/* Move each point of pa1 by dx and dy */ +void pcb_polyarea_move(pcb_polyarea_t *pa1, pcb_coord_t dx, pcb_coord_t dy); + +#endif /* PCB_POLYAREA_H */ Index: tags/2.1.2/src/polygon.c =================================================================== --- tags/2.1.2/src/polygon.c (nonexistent) +++ tags/2.1.2/src/polygon.c (revision 24813) @@ -0,0 +1,2146 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996,2010 Thomas Nau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +/* pcb-rnd specific polygon editing routines + see doc/developer/polygon.html for more info */ + +#include "config.h" +#include "conf_core.h" + +#include +#include +#include +#include + +#include "board.h" +#include "box.h" +#include "data.h" +#include "draw.h" +#include "error.h" +#include "polygon.h" +#include "remove.h" +#include "search.h" +#include "thermal.h" +#include "undo.h" +#include "layer.h" +#include "obj_poly_draw.h" +#include "polygon_selfi.h" +#include "event.h" + +#define ROUND(x) ((long)(((x) >= 0 ? (x) + 0.5 : (x) - 0.5))) + +#define UNSUBTRACT_BLOAT 10 +#define SUBTRACT_PIN_VIA_BATCH_SIZE 100 +#define SUBTRACT_PADSTACK_BATCH_SIZE 50 +#define SUBTRACT_LINE_BATCH_SIZE 20 + +#define sqr(x) ((x)*(x)) + +#undef min +#undef max +#define min(x, y) ((x) < (y) ? (x) : (y)) +#define max(x, y) ((x) > (y) ? (x) : (y)) + +static double rotate_circle_seg[4]; + +static int Unsubtract(pcb_polyarea_t * np1, pcb_poly_t * p); + +static const char *polygon_cookie = "core polygon"; + + +void pcb_poly_layers_chg(void *user_data, int argc, pcb_event_arg_t argv[]) +{ + pcb_layer_t *ly; + pcb_data_t *data; + + if ((argc < 2) || (argv[1].type != PCB_EVARG_PTR)) + return; + ly = argv[1].d.p; + if ((ly->is_bound) || (ly->parent_type != PCB_PARENT_DATA)) + return; + + data = ly->parent.data; + pcb_data_clip_inhibit_inc(data); + PCB_POLY_LOOP(ly); { + polygon->clip_dirty = 1; + } + PCB_END_LOOP; + pcb_data_clip_inhibit_dec(data, 1); +} + +void pcb_polygon_init(void) +{ + double cos_ang = cos(2.0 * M_PI / PCB_POLY_CIRC_SEGS_F); + double sin_ang = sin(2.0 * M_PI / PCB_POLY_CIRC_SEGS_F); + + rotate_circle_seg[0] = cos_ang; + rotate_circle_seg[1] = -sin_ang; + rotate_circle_seg[2] = sin_ang; + rotate_circle_seg[3] = cos_ang; + + pcb_event_bind(PCB_EVENT_LAYER_CHANGED_GRP, pcb_poly_layers_chg, NULL, polygon_cookie); +} + +void pcb_polygon_uninit(void) +{ + pcb_event_unbind_allcookie(polygon_cookie); +} + +pcb_cardinal_t pcb_poly_point_idx(pcb_poly_t *polygon, pcb_point_t *point) +{ + assert(point >= polygon->Points); + assert(point <= polygon->Points + polygon->PointN); + return ((char *) point - (char *) polygon->Points) / sizeof(pcb_point_t); +} + +/* Find contour number: 0 for outer, 1 for first hole etc.. */ +pcb_cardinal_t pcb_poly_contour_point(pcb_poly_t *polygon, pcb_cardinal_t point) +{ + pcb_cardinal_t i; + pcb_cardinal_t contour = 0; + + for (i = 0; i < polygon->HoleIndexN; i++) + if (point >= polygon->HoleIndex[i]) + contour = i + 1; + return contour; +} + +pcb_cardinal_t pcb_poly_contour_next_point(pcb_poly_t *polygon, pcb_cardinal_t point) +{ + pcb_cardinal_t contour; + pcb_cardinal_t this_contour_start; + pcb_cardinal_t next_contour_start; + + contour = pcb_poly_contour_point(polygon, point); + + this_contour_start = (contour == 0) ? 0 : polygon->HoleIndex[contour - 1]; + next_contour_start = (contour == polygon->HoleIndexN) ? polygon->PointN : polygon->HoleIndex[contour]; + + /* Wrap back to the start of the contour we're in if we pass the end */ + if (++point == next_contour_start) + point = this_contour_start; + + return point; +} + +pcb_cardinal_t pcb_poly_contour_prev_point(pcb_poly_t *polygon, pcb_cardinal_t point) +{ + pcb_cardinal_t contour; + pcb_cardinal_t prev_contour_end; + pcb_cardinal_t this_contour_end; + + contour = pcb_poly_contour_point(polygon, point); + + prev_contour_end = (contour == 0) ? 0 : polygon->HoleIndex[contour - 1]; + this_contour_end = (contour == polygon->HoleIndexN) ? polygon->PointN - 1 : polygon->HoleIndex[contour] - 1; + + /* Wrap back to the start of the contour we're in if we pass the end */ + if (point == prev_contour_end) + point = this_contour_end; + else + point--; + + return point; +} + +static void add_noholes_polyarea(pcb_pline_t * pline, void *user_data) +{ + pcb_poly_t *poly = (pcb_poly_t *) user_data; + + /* Prepend the pline into the NoHoles linked list */ + pline->next = poly->NoHoles; + poly->NoHoles = pline; +} + +void pcb_poly_compute_no_holes(pcb_poly_t * poly) +{ + pcb_poly_contours_free(&poly->NoHoles); + if (poly->Clipped) + pcb_poly_no_holes_dicer(poly, NULL, add_noholes_polyarea, poly); + else + printf("Compute_noholes caught poly->Clipped = NULL\n"); + poly->NoHolesValid = 1; +} + +static pcb_polyarea_t *biggest(pcb_polyarea_t * p) +{ + pcb_polyarea_t *n, *top = NULL; + pcb_pline_t *pl; + pcb_rtree_t *tree; + double big = -1; + if (!p) + return NULL; + n = p; + do { +#if 0 + if (n->contours->area < conf_core.design.poly_isle_area) { + n->b->f = n->f; + n->f->b = n->b; + pcb_poly_contour_del(&n->contours); + if (n == p) + p = n->f; + n = n->f; + if (!n->contours) { + free(n); + return NULL; + } + } +#endif + if (n->contours->area > big) { + top = n; + big = n->contours->area; + } + } + while ((n = n->f) != p); + assert(top); + if (top == p) + return p; + pl = top->contours; + tree = top->contour_tree; + top->contours = p->contours; + top->contour_tree = p->contour_tree; + p->contours = pl; + p->contour_tree = tree; + assert(pl); + assert(p->f); + assert(p->b); + return p; +} + +pcb_polyarea_t *pcb_poly_from_contour(pcb_pline_t * contour) +{ + pcb_polyarea_t *p; + pcb_poly_contour_pre(contour, pcb_true); + assert(contour->Flags.orient == PCB_PLF_DIR); + if (!(p = pcb_polyarea_create())) + return NULL; + pcb_polyarea_contour_include(p, contour); + assert(pcb_poly_valid(p)); + return p; +} + +/* Convert a polygon to an unclipped polyarea */ +static pcb_polyarea_t *original_poly(pcb_poly_t *p, pcb_bool *need_full) +{ + pcb_pline_t *contour = NULL; + pcb_polyarea_t *np1 = NULL, *np = NULL; + pcb_cardinal_t n; + pcb_vector_t v; + int hole = 0; + + *need_full = pcb_false; + + np1 = np = pcb_polyarea_create(); + if (np == NULL) + return NULL; + + /* first make initial polygon contour */ + for (n = 0; n < p->PointN; n++) { + /* No current contour? Make a new one starting at point */ + /* (or) Add point to existing contour */ + + v[0] = p->Points[n].X; + v[1] = p->Points[n].Y; + if (contour == NULL) { + if ((contour = pcb_poly_contour_new(v)) == NULL) + return NULL; + } + else { + pcb_poly_vertex_include(contour->head.prev, pcb_poly_node_create(v)); + } + + /* Is current point last in contour? If so process it. */ + if (n == p->PointN - 1 || (hole < p->HoleIndexN && n == p->HoleIndex[hole] - 1)) { + pcb_poly_contour_pre(contour, pcb_true); + + /* make sure it is a positive contour (outer) or negative (hole) */ + if (contour->Flags.orient != (hole ? PCB_PLF_INV : PCB_PLF_DIR)) + pcb_poly_contour_inv(contour); + assert(contour->Flags.orient == (hole ? PCB_PLF_INV : PCB_PLF_DIR)); + + /* attempt to auto-correct simple self intersecting cases */ + if (0 && pcb_pline_is_selfint(contour)) { + vtp0_t islands; + int n; + + /* self intersecting polygon - attempt to fix it by splitting up into multiple polyareas */ + vtp0_init(&islands); + pcb_pline_split_selfint(contour, &islands); + for(n = 0; n < vtp0_len(&islands); n++) { + pcb_pline_t *pl = *vtp0_get(&islands, n, 0); + if (n > 0) { + pcb_polyarea_t *newpa = pcb_polyarea_create(); + newpa->b = np; + newpa->f = np->f; + np->f->b = newpa; + np->f = newpa; + np = newpa; + *need_full = pcb_true; + } + pcb_poly_contour_pre(pl, pcb_true); + if (pl->Flags.orient != (hole ? PCB_PLF_INV : PCB_PLF_DIR)) + pcb_poly_contour_inv(pl); + assert(pl->Flags.orient == (hole ? PCB_PLF_INV : PCB_PLF_DIR)); + pcb_polyarea_contour_include(np, pl); + } + vtp0_uninit(&islands); + free(contour); + } + else + pcb_polyarea_contour_include(np, contour); + contour = NULL; + assert(pcb_poly_valid(np)); + + hole++; + } + } + return biggest(np1); +} + +pcb_polyarea_t *pcb_poly_from_poly(pcb_poly_t * p) +{ + pcb_bool tmp; + return original_poly(p, &tmp); +} + +pcb_polyarea_t *pcb_poly_from_rect(pcb_coord_t x1, pcb_coord_t x2, pcb_coord_t y1, pcb_coord_t y2) +{ + pcb_pline_t *contour = NULL; + pcb_vector_t v; + + /* Return NULL for zero or negatively sized rectangles */ + if (x2 <= x1 || y2 <= y1) + return NULL; + + v[0] = x1; + v[1] = y1; + if ((contour = pcb_poly_contour_new(v)) == NULL) + return NULL; + v[0] = x2; + v[1] = y1; + pcb_poly_vertex_include(contour->head.prev, pcb_poly_node_create(v)); + v[0] = x2; + v[1] = y2; + pcb_poly_vertex_include(contour->head.prev, pcb_poly_node_create(v)); + v[0] = x1; + v[1] = y2; + pcb_poly_vertex_include(contour->head.prev, pcb_poly_node_create(v)); + return pcb_poly_from_contour(contour); +} + +pcb_polyarea_t *pcb_poly_from_octagon(pcb_coord_t x, pcb_coord_t y, pcb_coord_t radius, int style) +{ + pcb_pline_t *contour = NULL; + pcb_vector_t v; + double xm[8], ym[8]; + + pcb_poly_square_pin_factors(style, xm, ym); + +TODO(": rewrite this to use the same table as the square/oct pin draw function") + /* point 7 */ + v[0] = x + ROUND(radius * 0.5) * xm[7]; + v[1] = y + ROUND(radius * PCB_TAN_22_5_DEGREE_2) * ym[7]; + if ((contour = pcb_poly_contour_new(v)) == NULL) + return NULL; + /* point 6 */ + v[0] = x + ROUND(radius * PCB_TAN_22_5_DEGREE_2) * xm[6]; + v[1] = y + ROUND(radius * 0.5) * ym[6]; + pcb_poly_vertex_include(contour->head.prev, pcb_poly_node_create(v)); + /* point 5 */ + v[0] = x - ROUND(radius * PCB_TAN_22_5_DEGREE_2) * xm[5]; + v[1] = y + ROUND(radius * 0.5) * ym[5]; + pcb_poly_vertex_include(contour->head.prev, pcb_poly_node_create(v)); + /* point 4 */ + v[0] = x - ROUND(radius * 0.5) * xm[4]; + v[1] = y + ROUND(radius * PCB_TAN_22_5_DEGREE_2) * ym[4]; + pcb_poly_vertex_include(contour->head.prev, pcb_poly_node_create(v)); + /* point 3 */ + v[0] = x - ROUND(radius * 0.5) * xm[3]; + v[1] = y - ROUND(radius * PCB_TAN_22_5_DEGREE_2) * ym[3]; + pcb_poly_vertex_include(contour->head.prev, pcb_poly_node_create(v)); + /* point 2 */ + v[0] = x - ROUND(radius * PCB_TAN_22_5_DEGREE_2) * xm[2]; + v[1] = y - ROUND(radius * 0.5) * ym[2]; + pcb_poly_vertex_include(contour->head.prev, pcb_poly_node_create(v)); + /* point 1 */ + v[0] = x + ROUND(radius * PCB_TAN_22_5_DEGREE_2) * xm[1]; + v[1] = y - ROUND(radius * 0.5) * ym[1]; + pcb_poly_vertex_include(contour->head.prev, pcb_poly_node_create(v)); + /* point 0 */ + v[0] = x + ROUND(radius * 0.5) * xm[0]; + v[1] = y - ROUND(radius * PCB_TAN_22_5_DEGREE_2) * ym[0]; + pcb_poly_vertex_include(contour->head.prev, pcb_poly_node_create(v)); + return pcb_poly_from_contour(contour); +} + +static void pcb_poly_frac_circle_(pcb_pline_t * c, pcb_coord_t X, pcb_coord_t Y, pcb_vector_t v, int range, int add_last) +{ + double oe1, oe2, e1, e2, t1; + int i, orange = range; + + oe1 = (v[0] - X); + oe2 = (v[1] - Y); + + pcb_poly_vertex_include(c->head.prev, pcb_poly_node_create(v)); + + /* move vector to origin */ + e1 = (v[0] - X) * PCB_POLY_CIRC_RADIUS_ADJ; + e2 = (v[1] - Y) * PCB_POLY_CIRC_RADIUS_ADJ; + + /* NB: the caller adds the last vertex, hence the -1 */ + range = PCB_POLY_CIRC_SEGS / range - 1; + for (i = 0; i < range; i++) { + /* rotate the vector */ + t1 = rotate_circle_seg[0] * e1 + rotate_circle_seg[1] * e2; + e2 = rotate_circle_seg[2] * e1 + rotate_circle_seg[3] * e2; + e1 = t1; + v[0] = X + ROUND(e1); + v[1] = Y + ROUND(e2); + pcb_poly_vertex_include(c->head.prev, pcb_poly_node_create(v)); + } + + if ((add_last) && (orange == 4)) { + v[0] = X - ROUND(oe2); + v[1] = Y + ROUND(oe1); + pcb_poly_vertex_include(c->head.prev, pcb_poly_node_create(v)); + } +} + + +/* add vertices in a fractional-circle starting from v + * centered at X, Y and going counter-clockwise + * does not include the first point + * last argument is 1 for a full circle + * 2 for a half circle + * or 4 for a quarter circle + */ +void pcb_poly_frac_circle(pcb_pline_t * c, pcb_coord_t X, pcb_coord_t Y, pcb_vector_t v, int range) +{ + pcb_poly_frac_circle_(c, X, Y, v, range, 0); +} + +/* same but adds the last vertex */ +void pcb_poly_frac_circle_end(pcb_pline_t * c, pcb_coord_t X, pcb_coord_t Y, pcb_vector_t v, int range) +{ + pcb_poly_frac_circle_(c, X, Y, v, range, 1); +} + + +/* create a circle approximation from lines */ +pcb_polyarea_t *pcb_poly_from_circle(pcb_coord_t x, pcb_coord_t y, pcb_coord_t radius) +{ + pcb_pline_t *contour; + pcb_vector_t v; + + if (radius <= 0) + return NULL; + v[0] = x + radius; + v[1] = y; + if ((contour = pcb_poly_contour_new(v)) == NULL) + return NULL; + pcb_poly_frac_circle(contour, x, y, v, 1); + contour->is_round = pcb_true; + contour->cx = x; + contour->cy = y; + contour->radius = radius; + return pcb_poly_from_contour(contour); +} + +/* make a rounded-corner rectangle with radius t beyond x1,x2,y1,y2 rectangle */ +pcb_polyarea_t *RoundRect(pcb_coord_t x1, pcb_coord_t x2, pcb_coord_t y1, pcb_coord_t y2, pcb_coord_t t) +{ + pcb_pline_t *contour = NULL; + pcb_vector_t v; + + assert(x2 > x1); + assert(y2 > y1); + v[0] = x1 - t; + v[1] = y1; + if ((contour = pcb_poly_contour_new(v)) == NULL) + return NULL; + pcb_poly_frac_circle_end(contour, x1, y1, v, 4); + v[0] = x2; + v[1] = y1 - t; + pcb_poly_vertex_include(contour->head.prev, pcb_poly_node_create(v)); + pcb_poly_frac_circle_end(contour, x2, y1, v, 4); + v[0] = x2 + t; + v[1] = y2; + pcb_poly_vertex_include(contour->head.prev, pcb_poly_node_create(v)); + pcb_poly_frac_circle_end(contour, x2, y2, v, 4); + v[0] = x1; + v[1] = y2 + t; + pcb_poly_vertex_include(contour->head.prev, pcb_poly_node_create(v)); + pcb_poly_frac_circle_end(contour, x1, y2, v, 4); + return pcb_poly_from_contour(contour); +} + +#define ARC_ANGLE 5 +static pcb_polyarea_t *ArcPolyNoIntersect(pcb_arc_t * a, pcb_coord_t thick, int end_caps) +{ + pcb_pline_t *contour = NULL; + pcb_polyarea_t *np = NULL; + pcb_vector_t v, v2; + pcb_box_t ends; + int i, segs; + double ang, da, rx, ry; + long half; + double radius_adj; + pcb_coord_t edx, edy; + + if (thick <= 0) + return NULL; + if (a->Delta < 0) { + a->StartAngle += a->Delta; + a->Delta = -a->Delta; + } + half = (thick + 1) / 2; + + pcb_arc_get_end(a, 0, &ends.X1, &ends.Y1); + pcb_arc_get_end(a, 1, &ends.X2, &ends.Y2); + + /* start with inner radius */ + rx = MAX(a->Width - half, 0); + ry = MAX(a->Height - half, 0); + segs = 1; + if (thick > 0) + segs = MAX(segs, a->Delta * M_PI / 360 * + sqrt(sqrt((double) rx * rx + (double) ry * ry) / PCB_POLY_ARC_MAX_DEVIATION / 2 / thick)); + segs = MAX(segs, a->Delta / ARC_ANGLE); + + ang = a->StartAngle; + da = (1.0 * a->Delta) / segs; + radius_adj = (M_PI * da / 360) * (M_PI * da / 360) / 2; + v[0] = a->X - rx * cos(ang * PCB_M180); + v[1] = a->Y + ry * sin(ang * PCB_M180); + if ((contour = pcb_poly_contour_new(v)) == NULL) + return 0; + for (i = 0; i < segs - 1; i++) { + ang += da; + v[0] = a->X - rx * cos(ang * PCB_M180); + v[1] = a->Y + ry * sin(ang * PCB_M180); + pcb_poly_vertex_include(contour->head.prev, pcb_poly_node_create(v)); + } + /* find last point */ + ang = a->StartAngle + a->Delta; + v[0] = a->X - rx * cos(ang * PCB_M180) * (1 - radius_adj); + v[1] = a->Y + ry * sin(ang * PCB_M180) * (1 - radius_adj); + + /* add the round cap at the end */ + if (end_caps) + pcb_poly_frac_circle(contour, ends.X2, ends.Y2, v, 2); + + /* and now do the outer arc (going backwards) */ + rx = (a->Width + half) * (1 + radius_adj); + ry = (a->Width + half) * (1 + radius_adj); + da = -da; + for (i = 0; i < segs; i++) { + v[0] = a->X - rx * cos(ang * PCB_M180); + v[1] = a->Y + ry * sin(ang * PCB_M180); + pcb_poly_vertex_include(contour->head.prev, pcb_poly_node_create(v)); + ang += da; + } + + /* explicitly draw the last point if the manhattan-distance is large enough */ + ang = a->StartAngle; + v2[0] = a->X - rx * cos(ang * PCB_M180) * (1 - radius_adj); + v2[1] = a->Y + ry * sin(ang * PCB_M180) * (1 - radius_adj); + edx = (v[0] - v2[0]); + edy = (v[1] - v2[1]); + if (edx < 0) edx = -edx; + if (edy < 0) edy = -edy; + if (edx+edy > PCB_MM_TO_COORD(0.001)) + pcb_poly_vertex_include(contour->head.prev, pcb_poly_node_create(v2)); + + + /* now add other round cap */ + if (end_caps) + pcb_poly_frac_circle(contour, ends.X1, ends.Y1, v2, 2); + + /* now we have the whole contour */ + if (!(np = pcb_poly_from_contour(contour))) + return NULL; + return np; +} + +#define MIN_CLEARANCE_BEFORE_BISECT 10. +pcb_polyarea_t *pcb_poly_from_arc(pcb_arc_t * a, pcb_coord_t thick) +{ + double delta; + pcb_arc_t seg1, seg2; + pcb_coord_t half; + + delta = (a->Delta < 0) ? -a->Delta : a->Delta; + + half = (thick + 1) / 2; + + /* corner case: can't even calculate the end cap properly because radius + is so small that there's no inner arc of the clearance */ + if ((a->Width - half <= 0) || (a->Height - half <= 0)) { + pcb_line_t lin = {0}; + pcb_polyarea_t *tmp_arc, *tmp1, *tmp2, *res, *ends; + + tmp_arc = ArcPolyNoIntersect(a, thick, 0); + + pcb_arc_get_end(a, 0, &lin.Point1.X, &lin.Point1.Y); + lin.Point2.X = lin.Point1.X; + lin.Point2.Y = lin.Point1.Y; + tmp1 = pcb_poly_from_line(&lin, thick); + + pcb_arc_get_end(a, 1, &lin.Point1.X, &lin.Point1.Y); + lin.Point2.X = lin.Point1.X; + lin.Point2.Y = lin.Point1.Y; + tmp2 = pcb_poly_from_line(&lin, thick); + + pcb_polyarea_boolean_free(tmp1, tmp2, &ends, PCB_PBO_UNITE); + pcb_polyarea_boolean_free(ends, tmp_arc, &res, PCB_PBO_UNITE); + return res; + } + + /* If the arc segment would self-intersect, we need to construct it as the union of + two non-intersecting segments */ + if (2 * M_PI * a->Width * (1. - (double) delta / 360.) - thick < MIN_CLEARANCE_BEFORE_BISECT) { + pcb_polyarea_t *tmp1, *tmp2, *res; + int half_delta = a->Delta / 2; + + seg1 = seg2 = *a; + seg1.Delta = half_delta; + seg2.Delta -= half_delta; + seg2.StartAngle += half_delta; + + tmp1 = ArcPolyNoIntersect(&seg1, thick, 1); + tmp2 = ArcPolyNoIntersect(&seg2, thick, 1); + pcb_polyarea_boolean_free(tmp1, tmp2, &res, PCB_PBO_UNITE); + return res; + } + + return ArcPolyNoIntersect(a, thick, 1); +} + +pcb_polyarea_t *pcb_poly_from_line(pcb_line_t * L, pcb_coord_t thick) +{ + pcb_pline_t *contour = NULL; + pcb_polyarea_t *np = NULL; + pcb_vector_t v; + double d, dx, dy; + long half; + pcb_line_t _l = *L, *l = &_l; + + if (thick <= 0) + return NULL; + half = (thick + 1) / 2; + d = sqrt(PCB_SQUARE(l->Point1.X - l->Point2.X) + PCB_SQUARE(l->Point1.Y - l->Point2.Y)); + if (!PCB_FLAG_TEST(PCB_FLAG_SQUARE, l)) + if (d == 0) /* line is a point */ + return pcb_poly_from_circle(l->Point1.X, l->Point1.Y, half); + if (d != 0) { + d = half / d; + dx = (l->Point1.Y - l->Point2.Y) * d; + dy = (l->Point2.X - l->Point1.X) * d; + } + else { + dx = half; + dy = 0; + } + if (PCB_FLAG_TEST(PCB_FLAG_SQUARE, l)) { /* take into account the ends */ + l->Point1.X -= dy; + l->Point1.Y += dx; + l->Point2.X += dy; + l->Point2.Y -= dx; + } + v[0] = l->Point1.X - dx; + v[1] = l->Point1.Y - dy; + if ((contour = pcb_poly_contour_new(v)) == NULL) + return 0; + v[0] = l->Point2.X - dx; + v[1] = l->Point2.Y - dy; + if (PCB_FLAG_TEST(PCB_FLAG_SQUARE, l)) + pcb_poly_vertex_include(contour->head.prev, pcb_poly_node_create(v)); + else + pcb_poly_frac_circle(contour, l->Point2.X, l->Point2.Y, v, 2); + v[0] = l->Point2.X + dx; + v[1] = l->Point2.Y + dy; + pcb_poly_vertex_include(contour->head.prev, pcb_poly_node_create(v)); + v[0] = l->Point1.X + dx; + v[1] = l->Point1.Y + dy; + if (PCB_FLAG_TEST(PCB_FLAG_SQUARE, l)) + pcb_poly_vertex_include(contour->head.prev, pcb_poly_node_create(v)); + else + pcb_poly_frac_circle(contour, l->Point1.X, l->Point1.Y, v, 2); + /* now we have the line contour */ + if (!(np = pcb_poly_from_contour(contour))) + return NULL; + return np; +} + +/* clear np1 from the polygon - should be inline with -O3 */ +static int Subtract(pcb_polyarea_t * np1, pcb_poly_t * p, pcb_bool fnp) +{ + pcb_polyarea_t *merged = NULL, *np = np1; + int x; + assert(np); + assert(p); + if (!p->Clipped) { + if (fnp) + pcb_polyarea_free(&np); + return 1; + } + assert(pcb_poly_valid(p->Clipped)); + assert(pcb_poly_valid(np)); + if (fnp) + x = pcb_polyarea_boolean_free(p->Clipped, np, &merged, PCB_PBO_SUB); + else { + x = pcb_polyarea_boolean(p->Clipped, np, &merged, PCB_PBO_SUB); + pcb_polyarea_free(&p->Clipped); + } + assert(!merged || pcb_poly_valid(merged)); + if (x != pcb_err_ok) { + fprintf(stderr, "Error while clipping PCB_PBO_SUB: %d\n", x); + pcb_polyarea_free(&merged); + p->Clipped = NULL; + if (p->NoHoles) + printf("Just leaked in Subtract\n"); + p->NoHoles = NULL; + return -1; + } + p->Clipped = biggest(merged); + assert(!p->Clipped || pcb_poly_valid(p->Clipped)); + if (!p->Clipped) + pcb_message(PCB_MSG_WARNING, "Polygon cleared out of existence near (%$mm, %$mm)\n", + (p->BoundingBox.X1 + p->BoundingBox.X2) / 2, (p->BoundingBox.Y1 + p->BoundingBox.Y2) / 2); + return 1; +} + +int pcb_poly_subtract(pcb_polyarea_t *np1, pcb_poly_t *p, pcb_bool fnp) +{ + return Subtract(np1, p, fnp); +} + +pcb_polyarea_t *pcb_poly_from_box_bloated(pcb_box_t * box, pcb_coord_t bloat) +{ + return pcb_poly_from_rect(box->X1 - bloat, box->X2 + bloat, box->Y1 - bloat, box->Y2 + bloat); +} + +/* remove the padstack clearance from the polygon */ +static int SubtractPadstack(pcb_data_t *d, pcb_pstk_t *ps, pcb_layer_t *l, pcb_poly_t *p) +{ + pcb_polyarea_t *np; + pcb_layer_id_t i; + + /* ps->Clearance == 0 doesn't mean no clearance because of the per shape clearances */ + if (!PCB_FLAG_TEST(PCB_FLAG_CLEARLINE, ps)) + return 0; + i = pcb_layer_id(d, l); + np = pcb_thermal_area_pstk(pcb_data_get_top(d), ps, i); + if (np == 0) + return 0; + + return Subtract(np, p, pcb_true); +} + +/* return the clearance polygon for a line */ +static pcb_polyarea_t *line_clearance_poly(pcb_cardinal_t layernum, pcb_board_t *pcb, pcb_line_t *line) +{ + if (line->thermal & PCB_THERMAL_ON) + return pcb_thermal_area_line(pcb, line, layernum); + return pcb_poly_from_line(line, line->Thickness + line->Clearance); +} + +static int SubtractLine(pcb_line_t * line, pcb_poly_t * p) +{ + pcb_polyarea_t *np; + + if (!PCB_NONPOLY_HAS_CLEARANCE(line)) + return 0; + if (!(np = line_clearance_poly(-1, NULL, line))) + return -1; + return Subtract(np, p, pcb_true); +} + +static int SubtractArc(pcb_arc_t * arc, pcb_poly_t * p) +{ + pcb_polyarea_t *np; + + if (!PCB_NONPOLY_HAS_CLEARANCE(arc)) + return 0; + if (!(np = pcb_poly_from_arc(arc, arc->Thickness + arc->Clearance))) + return -1; + return Subtract(np, p, pcb_true); +} + +static int SubtractText(pcb_text_t * text, pcb_poly_t * p) +{ + pcb_polyarea_t *np; + const pcb_box_t *b = &text->BoundingBox; + + if (!PCB_FLAG_TEST(PCB_FLAG_CLEARLINE, text)) + return 0; + if (!(np = RoundRect(b->X1 + conf_core.design.bloat, b->X2 - conf_core.design.bloat, b->Y1 + conf_core.design.bloat, b->Y2 - conf_core.design.bloat, conf_core.design.bloat))) + return -1; + return Subtract(np, p, pcb_true); +} + +struct cpInfo { + const pcb_box_t *other; + pcb_data_t *data; + pcb_layer_t *layer; + pcb_poly_t *polygon; + pcb_bool solder; + pcb_polyarea_t *accumulate; + int batch_size; + jmp_buf env; +}; + +static void subtract_accumulated(struct cpInfo *info, pcb_poly_t *polygon) +{ + if (info->accumulate == NULL) + return; + Subtract(info->accumulate, polygon, pcb_true); + info->accumulate = NULL; + info->batch_size = 0; +} + +static int pcb_poly_clip_noop = 0; +static void *pcb_poly_clip_prog_ctx; +static void (*pcb_poly_clip_prog)(void *ctx) = NULL; + +/* call the progress report callback and return if no-op is set */ +#define POLY_CLIP_PROG() \ +do { \ + if (pcb_poly_clip_prog != NULL) \ + pcb_poly_clip_prog(pcb_poly_clip_prog_ctx); \ + if (pcb_poly_clip_noop) \ + return PCB_R_DIR_FOUND_CONTINUE; \ +} while(0) + +static pcb_r_dir_t padstack_sub_callback(const pcb_box_t *b, void *cl) +{ + pcb_pstk_t *ps = (pcb_pstk_t *)b; + struct cpInfo *info = (struct cpInfo *)cl; + pcb_poly_t *polygon; + pcb_polyarea_t *np; + pcb_polyarea_t *merged; + pcb_layer_id_t i; + + /* don't subtract the object that was put back! */ + if (b == info->other) + return PCB_R_DIR_NOT_FOUND; + polygon = info->polygon; + + /* ps->Clearance == 0 doesn't mean no clearance because of the per shape clearances */ + if (!PCB_FLAG_TEST(PCB_FLAG_CLEARLINE, ps)) + return PCB_R_DIR_NOT_FOUND; + + i = pcb_layer_id(info->data, info->layer); + + np = pcb_thermal_area_pstk(pcb_data_get_top(info->data), ps, i); + if (np == 0) + return PCB_R_DIR_FOUND_CONTINUE; + + info->batch_size++; + POLY_CLIP_PROG(); + + pcb_polyarea_boolean_free(info->accumulate, np, &merged, PCB_PBO_UNITE); + info->accumulate = merged; + + if (info->batch_size == SUBTRACT_PADSTACK_BATCH_SIZE) + subtract_accumulated(info, polygon); + + return PCB_R_DIR_FOUND_CONTINUE; +} + +static pcb_r_dir_t arc_sub_callback(const pcb_box_t * b, void *cl) +{ + pcb_arc_t *arc = (pcb_arc_t *) b; + struct cpInfo *info = (struct cpInfo *) cl; + pcb_poly_t *polygon; + + /* don't subtract the object that was put back! */ + if (b == info->other) + return PCB_R_DIR_NOT_FOUND; + if (!PCB_NONPOLY_HAS_CLEARANCE(arc)) + return PCB_R_DIR_NOT_FOUND; + + POLY_CLIP_PROG(); + + polygon = info->polygon; + + if (SubtractArc(arc, polygon) < 0) + longjmp(info->env, 1); + return PCB_R_DIR_FOUND_CONTINUE; +} + +/* quick create a polygon area from a line, knowing the coords and width */ +static pcb_polyarea_t *poly_sub_callback_line(pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2, pcb_coord_t width) +{ + static pcb_line_t lin; + static int inited = 0; + + if (!inited) { + lin.type = PCB_OBJ_LINE; + lin.Flags = pcb_no_flags(); + PCB_FLAG_SET(PCB_FLAG_CLEARLINE, &lin); + lin.Thickness = 0; + inited = 1; + } + + lin.Point1.X = x1; + lin.Point1.Y = y1; + lin.Point2.X = x2; + lin.Point2.Y = y2; + lin.Clearance = width; + + return pcb_poly_from_line(&lin, width); +} + +#define pa_append(src) \ + do { \ + pcb_polyarea_boolean(*dst, src, &tmp, PCB_PBO_UNITE); \ + pcb_polyarea_free(dst); \ + *dst = tmp; \ + } while(0) + +void pcb_poly_pa_clearance_construct(pcb_polyarea_t **dst, pcb_poly_it_t *it, pcb_coord_t clearance) +{ + pcb_polyarea_t *tmp, *lin; + pcb_coord_t x, y, px, py, x0, y0; + pcb_pline_t *pl; + int go; + pcb_cardinal_t cnt; + + if (*dst != NULL) + pa_append(it->pa); + else + pcb_polyarea_copy0(dst, it->pa); + + clearance *= 2; + + /* care about the outer contours only */ + pl = pcb_poly_contour(it); + if (pl != NULL) { + /* iterate over the vectors of the contour */ + for(go = pcb_poly_vect_first(it, &x, &y), cnt = 0; go; go = pcb_poly_vect_next(it, &x, &y), cnt++) { + if (cnt > 0) { + lin = poly_sub_callback_line(px, py, x, y, clearance); + pa_append(lin); + pcb_polyarea_free(&lin); + } + else { + x0 = x; + y0 = y; + } + px = x; + py = y; + } + if (cnt > 0) { + lin = poly_sub_callback_line(px, py, x0, y0, clearance); + pa_append(lin); + pcb_polyarea_free(&lin); + } + } +} +#undef pa_append + +/* Construct a poly area that represents the enlarged subpoly - so it can be + subtracted from the parent poly to form the clearance for subpoly */ +pcb_polyarea_t *pcb_poly_clearance_construct(pcb_poly_t *subpoly) +{ + pcb_polyarea_t *ret = NULL, *pa; + pcb_poly_it_t it; + + /* iterate over all islands of a polygon */ + for(pa = pcb_poly_island_first(subpoly, &it); pa != NULL; pa = pcb_poly_island_next(&it)) + pcb_poly_pa_clearance_construct(&ret, &it, subpoly->Clearance/2); + + return ret; +} + +/* return the clearance polygon for a line */ +static pcb_polyarea_t *poly_clearance_poly(pcb_cardinal_t layernum, pcb_board_t *pcb, pcb_poly_t *subpoly) +{ + if (subpoly->thermal & PCB_THERMAL_ON) + return pcb_thermal_area_poly(pcb, subpoly, layernum); + return pcb_poly_clearance_construct(subpoly); +} + + +static int SubtractPolyPoly(pcb_poly_t *subpoly, pcb_poly_t *frompoly) +{ + pcb_polyarea_t *pa; + + if (PCB_FLAG_TEST(PCB_FLAG_CLEARPOLYPOLY, frompoly)) /* two clearing polys won't interact */ + return 0; /* but it's not an error, that'd kill other clearances in the same poly */ + + pa = poly_clearance_poly(-1, NULL, subpoly); + if (pa == NULL) + return -1; + + Subtract(pa, frompoly, pcb_true); + frompoly->NoHolesValid = 0; + return 0; +} + + +static int UnsubtractPolyPoly(pcb_poly_t *subpoly, pcb_poly_t *frompoly) +{ + pcb_polyarea_t *pa; + + if (PCB_FLAG_TEST(PCB_FLAG_CLEARPOLYPOLY, frompoly)) /* two clearing polys won't interact */ + return 0; /* but it's not an error, that'd kill other clearances in the same poly */ + + pa = poly_clearance_poly(-1, NULL, subpoly); + if (pa == NULL) + return -1; + + if (!Unsubtract(pa, frompoly)) + return -1; + frompoly->NoHolesValid = 0; + return 0; +} + +static pcb_r_dir_t poly_sub_callback(const pcb_box_t *b, void *cl) +{ + pcb_poly_t *subpoly = (pcb_poly_t *)b; + struct cpInfo *info = (struct cpInfo *) cl; + pcb_poly_t *polygon; + + polygon = info->polygon; + + /* don't do clearance in itself */ + if (subpoly == polygon) + return PCB_R_DIR_NOT_FOUND; + + /* don't subtract the object that was put back! */ + if (b == info->other) + return PCB_R_DIR_NOT_FOUND; + if (!PCB_POLY_HAS_CLEARANCE(subpoly)) + return PCB_R_DIR_NOT_FOUND; + + POLY_CLIP_PROG(); + + if (SubtractPolyPoly(subpoly, polygon) < 0) + longjmp(info->env, 1); + + return PCB_R_DIR_FOUND_CONTINUE; +} + +static pcb_r_dir_t line_sub_callback(const pcb_box_t * b, void *cl) +{ + pcb_line_t *line = (pcb_line_t *) b; + struct cpInfo *info = (struct cpInfo *) cl; + pcb_poly_t *polygon; + pcb_polyarea_t *np; + pcb_polyarea_t *merged; + + /* don't subtract the object that was put back! */ + if (b == info->other) + return PCB_R_DIR_NOT_FOUND; + if (!PCB_NONPOLY_HAS_CLEARANCE(line)) + return PCB_R_DIR_NOT_FOUND; + polygon = info->polygon; + + POLY_CLIP_PROG(); + + np = line_clearance_poly(-1, NULL, line); + if (!np) + longjmp(info->env, 1); + + pcb_polyarea_boolean_free(info->accumulate, np, &merged, PCB_PBO_UNITE); + info->accumulate = merged; + info->batch_size++; + + if (info->batch_size == SUBTRACT_LINE_BATCH_SIZE) + subtract_accumulated(info, polygon); + + return PCB_R_DIR_FOUND_CONTINUE; +} + +static pcb_r_dir_t text_sub_callback(const pcb_box_t * b, void *cl) +{ + pcb_text_t *text = (pcb_text_t *) b; + struct cpInfo *info = (struct cpInfo *) cl; + pcb_poly_t *polygon; + + /* don't subtract the object that was put back! */ + if (b == info->other) + return PCB_R_DIR_NOT_FOUND; + if (!PCB_FLAG_TEST(PCB_FLAG_CLEARLINE, text)) + return PCB_R_DIR_NOT_FOUND; + + POLY_CLIP_PROG(); + + polygon = info->polygon; + if (SubtractText(text, polygon) < 0) + longjmp(info->env, 1); + return PCB_R_DIR_FOUND_CONTINUE; +} + +static pcb_cardinal_t clearPoly(pcb_data_t *Data, pcb_layer_t *Layer, pcb_poly_t *polygon, const pcb_box_t *here, pcb_coord_t expand, int noop) +{ + pcb_cardinal_t r = 0; + int seen; + pcb_box_t region; + struct cpInfo info; + pcb_layergrp_id_t group; + unsigned int gflg; + pcb_layer_type_t lf; + int old_noop; + + lf = pcb_layer_flags_(Layer); + if (!(lf & PCB_LYT_COPPER)) { /* also handles lf == 0 */ + polygon->NoHolesValid = 0; + return 0; + } + + if (!PCB_FLAG_TEST(PCB_FLAG_CLEARPOLY, polygon)) + return 0; + + old_noop = pcb_poly_clip_noop; + pcb_poly_clip_noop = noop; + + group = pcb_layer_get_group_(Layer); + gflg = pcb_layergrp_flags(PCB, group); + info.solder = (gflg & PCB_LYT_BOTTOM); + info.data = Data; + info.other = here; + info.layer = Layer; + info.polygon = polygon; + if (here) + region = pcb_clip_box(here, &polygon->BoundingBox); + else + region = polygon->BoundingBox; + region = pcb_bloat_box(®ion, expand); + + if (setjmp(info.env) == 0) { + + r = 0; + info.accumulate = NULL; + info.batch_size = 0; + PCB_COPPER_GROUP_LOOP(Data, group); + { + pcb_r_search(layer->line_tree, ®ion, NULL, line_sub_callback, &info, &seen); + r += seen; + subtract_accumulated(&info, polygon); + pcb_r_search(layer->arc_tree, ®ion, NULL, arc_sub_callback, &info, &seen); + r += seen; + pcb_r_search(layer->text_tree, ®ion, NULL, text_sub_callback, &info, &seen); + r += seen; + pcb_r_search(layer->polygon_tree, ®ion, NULL, poly_sub_callback, &info, &seen); + r += seen; + } + PCB_END_LOOP; + pcb_r_search(Data->padstack_tree, ®ion, NULL, padstack_sub_callback, &info, &seen); + r += seen; + subtract_accumulated(&info, polygon); + } + if (!noop) + polygon->NoHolesValid = 0; + pcb_poly_clip_noop = old_noop; + return r; +} + +static int Unsubtract(pcb_polyarea_t * np1, pcb_poly_t * p) +{ + pcb_polyarea_t *merged = NULL, *np = np1; + pcb_polyarea_t *orig_poly, *clipped_np; + int x; + pcb_bool need_full; + assert(np); + assert(p); /* NOTE: p->clipped might be NULL if a poly is "cleared out of existence" and is now coming back */ + + orig_poly = original_poly(p, &need_full); + + x = pcb_polyarea_boolean_free(np, orig_poly, &clipped_np, PCB_PBO_ISECT); + if (x != pcb_err_ok) { + fprintf(stderr, "Error while clipping PCB_PBO_ISECT: %d\n", x); + pcb_polyarea_free(&clipped_np); + goto fail; + } + + x = pcb_polyarea_boolean_free(p->Clipped, clipped_np, &merged, PCB_PBO_UNITE); + if (x != pcb_err_ok) { + fprintf(stderr, "Error while clipping PCB_PBO_UNITE: %d\n", x); + pcb_polyarea_free(&merged); + goto fail; + } + p->Clipped = biggest(merged); + assert(!p->Clipped || pcb_poly_valid(p->Clipped)); + return 1; + +fail: + p->Clipped = NULL; + if (p->NoHoles) + printf("Just leaked in Unsubtract\n"); + p->NoHoles = NULL; + return 0; +} + +static int UnsubtractPadstack(pcb_data_t *data, pcb_pstk_t *ps, pcb_layer_t *l, pcb_poly_t *p) +{ + pcb_polyarea_t *np; + + /* overlap a bit to prevent gaps from rounding errors */ + np = pcb_poly_from_box_bloated(&ps->BoundingBox, UNSUBTRACT_BLOAT * 400000); + + if (!np) + return 0; + if (!Unsubtract(np, p)) + return 0; + + clearPoly(PCB->Data, l, p, (const pcb_box_t *)ps, 2 * UNSUBTRACT_BLOAT * 400000, 0); + return 1; +} + + + +static int UnsubtractArc(pcb_arc_t * arc, pcb_layer_t * l, pcb_poly_t * p) +{ + pcb_polyarea_t *np; + + if (!PCB_NONPOLY_HAS_CLEARANCE(arc)) + return 0; + + /* overlap a bit to prevent gaps from rounding errors */ + np = pcb_poly_from_box_bloated(&arc->BoundingBox, UNSUBTRACT_BLOAT); + + if (!np) + return 0; + if (!Unsubtract(np, p)) + return 0; + clearPoly(PCB->Data, l, p, (const pcb_box_t *) arc, 2 * UNSUBTRACT_BLOAT, 0); + return 1; +} + +static int UnsubtractLine(pcb_line_t * line, pcb_layer_t * l, pcb_poly_t * p) +{ + pcb_polyarea_t *np; + + if (!PCB_NONPOLY_HAS_CLEARANCE(line)) + return 0; + + /* overlap a bit to prevent notches from rounding errors */ + np = pcb_poly_from_box_bloated(&line->BoundingBox, UNSUBTRACT_BLOAT); + + if (!np) + return 0; + if (!Unsubtract(np, p)) + return 0; + clearPoly(PCB->Data, l, p, (const pcb_box_t *) line, 2 * UNSUBTRACT_BLOAT, 0); + return 1; +} + +static int UnsubtractText(pcb_text_t * text, pcb_layer_t * l, pcb_poly_t * p) +{ + pcb_polyarea_t *np; + + if (!PCB_FLAG_TEST(PCB_FLAG_CLEARLINE, text)) + return 0; + + /* overlap a bit to prevent notches from rounding errors */ + np = pcb_poly_from_box_bloated(&text->BoundingBox, UNSUBTRACT_BLOAT); + + if (!np) + return -1; + if (!Unsubtract(np, p)) + return 0; + clearPoly(PCB->Data, l, p, (const pcb_box_t *) text, 2 * UNSUBTRACT_BLOAT, 0); + return 1; +} + +static pcb_bool inhibit = pcb_false; + +int pcb_poly_init_clip_prog(pcb_data_t *Data, pcb_layer_t *layer, pcb_poly_t *p, void (*cb)(void *ctx), void *ctx) +{ + pcb_board_t *pcb; + pcb_bool need_full; + void (*old_cb)(void *ctx); + void *old_ctx; + + if (inhibit) + return 0; + + if (Data->clip_inhibit > 0) { + p->clip_dirty = 1; + return 0; + } + + if (layer->is_bound) + layer = layer->meta.bound.real; + + if (p->Clipped) + pcb_polyarea_free(&p->Clipped); + p->Clipped = original_poly(p, &need_full); + if (need_full && !PCB_FLAG_TEST(PCB_FLAG_FULLPOLY, p)) { + pcb_message(PCB_MSG_WARNING, "Polygon #%ld was self intersecting; it had to be split up and\nthe full poly flag set.\n", (long)p->ID); + PCB_FLAG_SET(PCB_FLAG_FULLPOLY, p); + } + pcb_poly_contours_free(&p->NoHoles); + + if (layer == NULL) + return 0; + + if (!p->Clipped) + return 0; + assert(pcb_poly_valid(p->Clipped)); + + /* calculate clipping for the real data (in case of subcircuits) */ + pcb = pcb_data_get_top(Data); + if (pcb != NULL) + Data = pcb->Data; + + old_cb = pcb_poly_clip_prog; + old_ctx = pcb_poly_clip_prog_ctx; + pcb_poly_clip_prog = cb; + pcb_poly_clip_prog_ctx = ctx; + + if (PCB_FLAG_TEST(PCB_FLAG_CLEARPOLY, p)) + clearPoly(Data, layer, p, NULL, 0, 0); + else + p->NoHolesValid = 0; + + pcb_poly_clip_prog = old_cb; + pcb_poly_clip_prog_ctx = old_ctx; + return 1; +} + +int pcb_poly_init_clip(pcb_data_t *Data, pcb_layer_t *layer, pcb_poly_t *p) +{ + return pcb_poly_init_clip_prog(Data, layer, p, NULL, NULL); +} + +pcb_cardinal_t pcb_poly_num_clears(pcb_data_t *data, pcb_layer_t *layer, pcb_poly_t *polygon) +{ + pcb_cardinal_t res; + void (*old_cb)(void *ctx); + + if (layer->is_bound) + layer = layer->meta.bound.real; + + old_cb = pcb_poly_clip_prog; + pcb_poly_clip_prog = NULL; + + res = clearPoly(data, layer, polygon, NULL, 0, 1); + + pcb_poly_clip_prog = old_cb; + return res; +} + +/* -------------------------------------------------------------------------- + * remove redundant polygon points. Any point that lies on the straight + * line between the points on either side of it is redundant. + * returns pcb_true if any points are removed + */ +pcb_bool pcb_poly_remove_excess_points(pcb_layer_t *Layer, pcb_poly_t *Polygon) +{ + pcb_point_t *p; + pcb_cardinal_t n, prev, next; + pcb_line_t line; + pcb_bool changed = pcb_false; + + if (pcb_undoing()) + return pcb_false; + + for (n = 0; n < Polygon->PointN; n++) { + prev = pcb_poly_contour_prev_point(Polygon, n); + next = pcb_poly_contour_next_point(Polygon, n); + p = &Polygon->Points[n]; + + line.Point1 = Polygon->Points[prev]; + line.Point2 = Polygon->Points[next]; + line.Thickness = 0; + if (pcb_is_point_on_line(p->X, p->Y, 0.0, &line)) { + pcb_remove_object(PCB_OBJ_POLY_POINT, Layer, Polygon, p); + changed = pcb_true; + } + } + return changed; +} + +/* --------------------------------------------------------------------------- + * returns the index of the polygon point which is the end + * point of the segment with the lowest distance to the passed + * coordinates + */ +pcb_cardinal_t pcb_poly_get_lowest_distance_point(pcb_poly_t *Polygon, pcb_coord_t X, pcb_coord_t Y) +{ + double mindistance = (double) PCB_MAX_COORD * PCB_MAX_COORD; + pcb_point_t *ptr1, *ptr2; + pcb_cardinal_t n, result = 0; + + /* we calculate the distance to each segment and choose the + * shortest distance. If the closest approach between the + * given point and the projected line (i.e. the segment extended) + * is not on the segment, then the distance is the distance + * to the segment end point. + */ + + for (n = 0; n < Polygon->PointN; n++) { + double u, dx, dy; + ptr1 = &Polygon->Points[pcb_poly_contour_prev_point(Polygon, n)]; + ptr2 = &Polygon->Points[n]; + + dx = ptr2->X - ptr1->X; + dy = ptr2->Y - ptr1->Y; + if (dx != 0.0 || dy != 0.0) { + /* projected intersection is at P1 + u(P2 - P1) */ + u = ((X - ptr1->X) * dx + (Y - ptr1->Y) * dy) / (dx * dx + dy * dy); + + if (u < 0.0) { /* ptr1 is closest point */ + u = PCB_SQUARE(X - ptr1->X) + PCB_SQUARE(Y - ptr1->Y); + } + else if (u > 1.0) { /* ptr2 is closest point */ + u = PCB_SQUARE(X - ptr2->X) + PCB_SQUARE(Y - ptr2->Y); + } + else { /* projected intersection is closest point */ + u = PCB_SQUARE(X - ptr1->X * (1.0 - u) - u * ptr2->X) + PCB_SQUARE(Y - ptr1->Y * (1.0 - u) - u * ptr2->Y); + } + if (u < mindistance) { + mindistance = u; + result = n; + } + } + } + return result; +} + +/* --------------------------------------------------------------------------- + * go back to the previous point of the polygon (undo) + */ +void pcb_polygon_go_to_prev_point(void) +{ + switch (pcb_crosshair.AttachedPolygon.PointN) { + /* do nothing if mode has just been entered */ + case 0: + break; + + /* reset number of points and 'PCB_MODE_LINE' state */ + case 1: + pcb_crosshair.AttachedPolygon.PointN = 0; + pcb_crosshair.AttachedLine.State = PCB_CH_STATE_FIRST; + break; + + /* back-up one point */ + default: + { + pcb_point_t *points = pcb_crosshair.AttachedPolygon.Points; + pcb_cardinal_t n = pcb_crosshair.AttachedPolygon.PointN - 2; + + pcb_crosshair.AttachedPolygon.PointN--; + pcb_crosshair.AttachedLine.Point1.X = points[n].X; + pcb_crosshair.AttachedLine.Point1.Y = points[n].Y; + break; + } + } +} + +/* --------------------------------------------------------------------------- + * go forward to the next point of the polygon (redo) + */ +void pcb_polygon_go_to_next_point(void) +{ + if ((pcb_crosshair.AttachedPolygon.PointN > 0) && (pcb_crosshair.AttachedPolygon.PointN < pcb_crosshair.AttachedPolygon_pts)) { + pcb_point_t *points = pcb_crosshair.AttachedPolygon.Points; + pcb_cardinal_t n = pcb_crosshair.AttachedPolygon.PointN; + + pcb_crosshair.AttachedPolygon.PointN++; + pcb_crosshair.AttachedLine.Point1.X = points[n].X; + pcb_crosshair.AttachedLine.Point1.Y = points[n].Y; + } +} + +/* --------------------------------------------------------------------------- + * close polygon if possible + */ +void pcb_polygon_close_poly(void) +{ + pcb_cardinal_t n = pcb_crosshair.AttachedPolygon.PointN; + + /* check number of points */ + if (n >= 3) { + /* if 45 degree lines are what we want do a quick check + * if closing the polygon makes sense + */ + if (!conf_core.editor.all_direction_lines) { + pcb_coord_t dx, dy; + + dx = coord_abs(pcb_crosshair.AttachedPolygon.Points[n - 1].X - pcb_crosshair.AttachedPolygon.Points[0].X); + dy = coord_abs(pcb_crosshair.AttachedPolygon.Points[n - 1].Y - pcb_crosshair.AttachedPolygon.Points[0].Y); + if (!(dx == 0 || dy == 0 || dx == dy)) { + pcb_message(PCB_MSG_ERROR, "Cannot close polygon because 45 degree lines are requested.\n"); + return; + } + } + pcb_polygon_copy_attached_to_layer(); + pcb_draw(); + } + else + pcb_message(PCB_MSG_ERROR, "A polygon has to have at least 3 points\n"); +} + +static void poly_copy_data(pcb_poly_t *dst, pcb_poly_t *src) +{ + pcb_poly_t p; + void *old_parent = dst->parent.any; + pcb_parenttype_t old_pt = dst->parent_type; + + memcpy(dst, src, ((char *)&p.link - (char *)&p)); + dst->type = PCB_OBJ_POLY; + dst->parent.any = old_parent; + dst->parent_type = old_pt; +} + +/* --------------------------------------------------------------------------- + * moves the data of the attached (new) polygon to the current layer + */ +void pcb_polygon_copy_attached_to_layer(void) +{ + pcb_layer_t *layer = pcb_loose_subc_layer(PCB, CURRENT, pcb_true); + pcb_poly_t *polygon; + int saveID; + + /* move data to layer and clear attached struct */ + polygon = pcb_poly_new(layer, 0, pcb_no_flags()); + saveID = polygon->ID; + poly_copy_data(polygon, &pcb_crosshair.AttachedPolygon); + polygon->Clearance = 2 * conf_core.design.clearance; + polygon->ID = saveID; + PCB_FLAG_SET(PCB_FLAG_CLEARPOLY, polygon); + if (conf_core.editor.full_poly) + PCB_FLAG_SET(PCB_FLAG_FULLPOLY, polygon); + if (conf_core.editor.clear_polypoly) + PCB_FLAG_SET(PCB_FLAG_CLEARPOLYPOLY, polygon); + + memset(&pcb_crosshair.AttachedPolygon, 0, sizeof(pcb_poly_t)); + + pcb_add_poly_on_layer(layer, polygon); + + pcb_poly_init_clip(PCB->Data, layer, polygon); + pcb_poly_invalidate_draw(layer, polygon); + pcb_board_set_changed_flag(pcb_true); + + /* reset state of attached line */ + pcb_crosshair.AttachedLine.State = PCB_CH_STATE_FIRST; + + /* add to undo list */ + pcb_undo_add_obj_to_create(PCB_OBJ_POLY, layer, polygon, polygon); + pcb_undo_inc_serial(); +} + +/* --------------------------------------------------------------------------- + * close polygon hole if possible + */ +void pcb_polygon_close_hole(void) +{ + pcb_cardinal_t n = pcb_crosshair.AttachedPolygon.PointN; + + /* check number of points */ + if (n >= 3) { + /* if 45 degree lines are what we want do a quick check + * if closing the polygon makes sense + */ + if (!conf_core.editor.all_direction_lines) { + pcb_coord_t dx, dy; + + dx = coord_abs(pcb_crosshair.AttachedPolygon.Points[n - 1].X - pcb_crosshair.AttachedPolygon.Points[0].X); + dy = coord_abs(pcb_crosshair.AttachedPolygon.Points[n - 1].Y - pcb_crosshair.AttachedPolygon.Points[0].Y); + if (!(dx == 0 || dy == 0 || dx == dy)) { + pcb_message(PCB_MSG_ERROR, "Cannot close polygon hole because 45 degree lines are requested.\n"); + return; + } + } + pcb_polygon_hole_create_from_attached(); + pcb_draw(); + } + else + pcb_message(PCB_MSG_ERROR, "A polygon hole has to have at least 3 points\n"); +} + +/* --------------------------------------------------------------------------- + * creates a hole of attached polygon shape in the underneath polygon + */ +void pcb_polygon_hole_create_from_attached(void) +{ + pcb_polyarea_t *original, *new_hole, *result; + pcb_flag_t Flags; + + /* Create pcb_polyarea_ts from the original polygon + * and the new hole polygon */ + original = pcb_poly_from_poly((pcb_poly_t *) pcb_crosshair.AttachedObject.Ptr2); + new_hole = pcb_poly_from_poly(&pcb_crosshair.AttachedPolygon); + + /* Subtract the hole from the original polygon shape */ + pcb_polyarea_boolean_free(original, new_hole, &result, PCB_PBO_SUB); + + /* Convert the resulting polygon(s) into a new set of nodes + * and place them on the page. Delete the original polygon. + */ + pcb_undo_save_serial(); + Flags = ((pcb_poly_t *) pcb_crosshair.AttachedObject.Ptr2)->Flags; + pcb_poly_to_polygons_on_layer(PCB->Data, (pcb_layer_t *) pcb_crosshair.AttachedObject.Ptr1, result, Flags); + pcb_remove_object(PCB_OBJ_POLY, + pcb_crosshair.AttachedObject.Ptr1, pcb_crosshair.AttachedObject.Ptr2, pcb_crosshair.AttachedObject.Ptr3); + pcb_undo_restore_serial(); + pcb_undo_inc_serial(); + + /* reset state of attached line */ + memset(&pcb_crosshair.AttachedPolygon, 0, sizeof(pcb_poly_t)); + pcb_crosshair.AttachedLine.State = PCB_CH_STATE_FIRST; + pcb_crosshair.AttachedObject.State = PCB_CH_STATE_FIRST; +} + +/* find polygon holes in range, then call the callback function for + * each hole. If the callback returns non-zero, stop + * the search. + */ +int +pcb_poly_holes(pcb_poly_t * polygon, const pcb_box_t * range, int (*callback) (pcb_pline_t * contour, void *user_data), void *user_data) +{ + pcb_polyarea_t *pa = polygon->Clipped; + pcb_pline_t *pl; + /* If this hole is so big the polygon doesn't exist, then it's not + * really a hole. + */ + if (!pa) + return 0; + for (pl = pa->contours->next; pl; pl = pl->next) { + if (range != NULL && (pl->xmin > range->X2 || pl->xmax < range->X1 || pl->ymin > range->Y2 || pl->ymax < range->Y1)) + continue; + if (callback(pl, user_data)) { + return 1; + } + } + return 0; +} + +struct plow_info { + int type; + void *ptr1, *ptr2; + pcb_layer_t *layer; + pcb_data_t *data; + void *user_data; + pcb_r_dir_t (*callback)(pcb_data_t *, pcb_layer_t *, pcb_poly_t *, int, void *, void *, void *user_data); +}; + +static pcb_r_dir_t subtract_plow(pcb_data_t *Data, pcb_layer_t *Layer, pcb_poly_t *Polygon, int type, void *ptr1, void *ptr2, void *user_data) +{ + if (!Polygon->Clipped) + return 0; + switch (type) { + case PCB_OBJ_PSTK: + SubtractPadstack(Data, (pcb_pstk_t *) ptr2, Layer, Polygon); + Polygon->NoHolesValid = 0; + return PCB_R_DIR_FOUND_CONTINUE; + case PCB_OBJ_LINE: + SubtractLine((pcb_line_t *) ptr2, Polygon); + Polygon->NoHolesValid = 0; + return PCB_R_DIR_FOUND_CONTINUE; + case PCB_OBJ_ARC: + SubtractArc((pcb_arc_t *) ptr2, Polygon); + Polygon->NoHolesValid = 0; + return PCB_R_DIR_FOUND_CONTINUE; + case PCB_OBJ_POLY: + if (ptr2 != Polygon) { + SubtractPolyPoly((pcb_poly_t *) ptr2, Polygon); + Polygon->NoHolesValid = 0; + return PCB_R_DIR_FOUND_CONTINUE; + } + break; + case PCB_OBJ_TEXT: + SubtractText((pcb_text_t *) ptr2, Polygon); + Polygon->NoHolesValid = 0; + return PCB_R_DIR_FOUND_CONTINUE; + } + return PCB_R_DIR_NOT_FOUND; +} + +static pcb_r_dir_t add_plow(pcb_data_t *Data, pcb_layer_t *Layer, pcb_poly_t *Polygon, int type, void *ptr1, void *ptr2, void *user_data) +{ + switch (type) { + case PCB_OBJ_PSTK: + UnsubtractPadstack(Data, (pcb_pstk_t *) ptr2, Layer, Polygon); + return PCB_R_DIR_FOUND_CONTINUE; + case PCB_OBJ_LINE: + UnsubtractLine((pcb_line_t *) ptr2, Layer, Polygon); + return PCB_R_DIR_FOUND_CONTINUE; + case PCB_OBJ_ARC: + UnsubtractArc((pcb_arc_t *) ptr2, Layer, Polygon); + return PCB_R_DIR_FOUND_CONTINUE; + case PCB_OBJ_POLY: + if (ptr2 != Polygon) { + UnsubtractPolyPoly((pcb_poly_t *) ptr2, Polygon); + return PCB_R_DIR_FOUND_CONTINUE; + } + break; + case PCB_OBJ_TEXT: + UnsubtractText((pcb_text_t *) ptr2, Layer, Polygon); + return PCB_R_DIR_FOUND_CONTINUE; + } + return PCB_R_DIR_NOT_FOUND; +} + +int pcb_poly_sub_obj(pcb_data_t *Data, pcb_layer_t *Layer, pcb_poly_t *Polygon, int type, void *obj) +{ + if (subtract_plow(Data, Layer, Polygon, type, NULL, obj, NULL) == PCB_R_DIR_FOUND_CONTINUE) + return 0; + return -1; +} + +int pcb_poly_unsub_obj(pcb_data_t *Data, pcb_layer_t *Layer, pcb_poly_t *Polygon, int type, void *obj) +{ + if (add_plow(Data, Layer, Polygon, type, NULL, obj, NULL) == PCB_R_DIR_FOUND_CONTINUE) + return 0; + return -1; +} + + +static pcb_r_dir_t plow_callback(const pcb_box_t * b, void *cl) +{ + struct plow_info *plow = (struct plow_info *) cl; + pcb_poly_t *polygon = (pcb_poly_t *) b; + + if (PCB_FLAG_TEST(PCB_FLAG_CLEARPOLY, polygon)) + return plow->callback(plow->data, plow->layer, polygon, plow->type, plow->ptr1, plow->ptr2, plow->user_data); + return PCB_R_DIR_NOT_FOUND; +} + +/* poly plows while clipping inhibit is on: mark any potentail polygon dirty */ +static pcb_r_dir_t poly_plows_inhibited_cb(pcb_data_t *data, pcb_layer_t *lay, pcb_poly_t *poly, int type, void *ptr1, void *ptr2, void *user_data) +{ + poly->clip_dirty = 1; + return PCB_R_DIR_FOUND_CONTINUE; +} + + +int pcb_poly_plows(pcb_data_t *Data, int type, void *ptr1, void *ptr2, + pcb_r_dir_t (*call_back) (pcb_data_t *data, pcb_layer_t *lay, pcb_poly_t *poly, int type, void *ptr1, void *ptr2, void *user_data), + void *user_data) +{ + pcb_box_t sb = ((pcb_any_obj_t *) ptr2)->BoundingBox; + int r = 0, seen; + struct plow_info info; + + if (Data->clip_inhibit > 0) + call_back = poly_plows_inhibited_cb; + + info.type = type; + info.ptr1 = ptr1; + info.ptr2 = ptr2; + info.data = Data; + info.user_data = user_data; + info.callback = call_back; + switch (type) { + case PCB_OBJ_PSTK: + if (Data->parent_type != PCB_PARENT_BOARD) + return 0; + if (ptr1 == NULL) { /* no layer specified: run on all layers */ + LAYER_LOOP(Data, pcb_max_layer); + { + if (!(pcb_layer_flags_(layer) & PCB_LYT_COPPER)) + continue; + r += pcb_poly_plows(Data, type, layer, ptr2, call_back, NULL); + } + PCB_END_LOOP; + return r; + } + + /* run on the specified layer (ptr1), if there's any need for clearing */ + /* ps->Clearance == 0 doesn't mean no clearance because of the per shape clearances */ + if (!PCB_FLAG_TEST(PCB_FLAG_CLEARLINE, (pcb_pstk_t *)ptr2)) + return 0; + goto doit; + case PCB_OBJ_POLY: + if (!PCB_POLY_HAS_CLEARANCE((pcb_poly_t *) ptr2)) + return 0; + goto doit; + + case PCB_OBJ_LINE: + case PCB_OBJ_ARC: + /* the cast works equally well for lines and arcs */ + if (!PCB_NONPOLY_HAS_CLEARANCE((pcb_line_t *) ptr2)) + return 0; + goto doit; + + case PCB_OBJ_TEXT: + /* text has no clearance property */ + if (!PCB_FLAG_TEST(PCB_FLAG_CLEARLINE, (pcb_line_t *) ptr2)) + return 0; + /* non-copper (e.g. silk, outline) doesn't plow */ +TODO(": use pcb_layer_flags_ here - but what PCB?") + if (!(pcb_layer_flags(PCB, pcb_layer_id(Data, (pcb_layer_t *) ptr1) & PCB_LYT_COPPER))) + return 0; + doit:; + PCB_COPPER_GROUP_LOOP(Data, pcb_layer_get_group(PCB, pcb_layer_id(Data, ((pcb_layer_t *) ptr1)))); + { + info.layer = layer; + pcb_r_search(layer->polygon_tree, &sb, NULL, plow_callback, &info, &seen); + r += seen; + } + PCB_END_LOOP; + break; + } + return r; +} + +void pcb_poly_restore_to_poly(pcb_data_t * Data, int type, void *ptr1, void *ptr2) +{ + pcb_data_t *dt = Data; + while((dt != NULL) && (dt->parent_type == PCB_PARENT_SUBC)) + dt = dt->parent.subc->parent.data; + if ((dt == NULL) || (dt->parent_type != PCB_PARENT_BOARD)) /* clear/restore only on boards */ + return; + if (type == PCB_OBJ_POLY) + pcb_poly_init_clip(dt, (pcb_layer_t *) ptr1, (pcb_poly_t *) ptr2); + pcb_poly_plows(dt, type, ptr1, ptr2, add_plow, NULL); +} + +void pcb_poly_clear_from_poly(pcb_data_t * Data, int type, void *ptr1, void *ptr2) +{ + pcb_data_t *dt = Data; + while((dt != NULL) && (dt->parent_type == PCB_PARENT_SUBC)) + dt = dt->parent.subc->parent.data; + if ((dt == NULL) || (dt->parent_type != PCB_PARENT_BOARD)) /* clear/restore only on boards */ + return; + if (type == PCB_OBJ_POLY) + pcb_poly_init_clip(dt, (pcb_layer_t *) ptr1, (pcb_poly_t *) ptr2); + pcb_poly_plows(dt, type, ptr1, ptr2, subtract_plow, NULL); +} + +pcb_bool pcb_poly_isects_poly(pcb_polyarea_t * a, pcb_poly_t *p, pcb_bool fr) +{ + pcb_polyarea_t *x; + pcb_bool ans; + ans = pcb_polyarea_touching(a, p->Clipped); + /* argument may be register, so we must copy it */ + x = a; + if (fr) + pcb_polyarea_free(&x); + return ans; +} + + +pcb_bool pcb_poly_is_point_in_p(pcb_coord_t X, pcb_coord_t Y, pcb_coord_t r, pcb_poly_t *p) +{ + pcb_polyarea_t *c; + pcb_vector_t v; + v[0] = X; + v[1] = Y; + if (pcb_polyarea_contour_inside(p->Clipped, v)) + return pcb_true; + + if (PCB_FLAG_TEST(PCB_FLAG_FULLPOLY, p)) { + pcb_poly_t tmp = *p; + + /* Check all clipped-away regions that are now drawn because of full-poly */ + for (tmp.Clipped = p->Clipped->f; tmp.Clipped != p->Clipped; tmp.Clipped = tmp.Clipped->f) + if (pcb_polyarea_contour_inside(tmp.Clipped, v)) + return pcb_true; + } + + if (r < 1) + return pcb_false; + if (!(c = pcb_poly_from_circle(X, Y, r))) + return pcb_false; + return pcb_poly_isects_poly(c, p, pcb_true); +} + + +pcb_bool pcb_poly_is_point_in_p_ignore_holes(pcb_coord_t X, pcb_coord_t Y, pcb_poly_t *p) +{ + pcb_vector_t v; + v[0] = X; + v[1] = Y; + return pcb_poly_contour_inside(p->Clipped->contours, v); +} + +pcb_bool pcb_poly_is_rect_in_p(pcb_coord_t X1, pcb_coord_t Y1, pcb_coord_t X2, pcb_coord_t Y2, pcb_poly_t *p) +{ + pcb_polyarea_t *s; + if (!(s = pcb_poly_from_rect(min(X1, X2), max(X1, X2), min(Y1, Y2), max(Y1, Y2)))) + return pcb_false; + return pcb_poly_isects_poly(s, p, pcb_true); +} + +TODO(": this should be in polygon1.c") +/* NB: This function will free the passed pcb_polyarea_t. + * It must only be passed a single pcb_polyarea_t (pa->f == pa->b == pa) + */ +static void r_NoHolesPolygonDicer(pcb_polyarea_t * pa, void (*emit) (pcb_pline_t *, void *), void *user_data) +{ + pcb_pline_t *p = pa->contours; + + if (!pa->contours->next) { /* no holes */ + pa->contours = NULL; /* The callback now owns the contour */ + /* Don't bother removing it from the pcb_polyarea_t's rtree + since we're going to free the pcb_polyarea_t below anyway */ + emit(p, user_data); + pcb_polyarea_free(&pa); + return; + } + else { + pcb_polyarea_t *poly2, *left, *right; + + /* make a rectangle of the left region slicing through the middle of the first hole */ + poly2 = pcb_poly_from_rect(p->xmin, (p->next->xmin + p->next->xmax) / 2, p->ymin, p->ymax); + pcb_polyarea_and_subtract_free(pa, poly2, &left, &right); + if (left) { + pcb_polyarea_t *cur, *next; + cur = left; + do { + next = cur->f; + cur->f = cur->b = cur; /* Detach this polygon piece */ + r_NoHolesPolygonDicer(cur, emit, user_data); + /* NB: The pcb_polyarea_t was freed by its use in the recursive dicer */ + } + while ((cur = next) != left); + } + if (right) { + pcb_polyarea_t *cur, *next; + cur = right; + do { + next = cur->f; + cur->f = cur->b = cur; /* Detach this polygon piece */ + r_NoHolesPolygonDicer(cur, emit, user_data); + /* NB: The pcb_polyarea_t was freed by its use in the recursive dicer */ + } + while ((cur = next) != right); + } + } +} + +void pcb_poly_no_holes_dicer(pcb_poly_t *p, const pcb_box_t * clip, void (*emit) (pcb_pline_t *, void *), void *user_data) +{ + pcb_polyarea_t *main_contour, *cur, *next; + + main_contour = pcb_polyarea_create(); + /* copy the main poly only */ + pcb_polyarea_copy1(main_contour, p->Clipped); + /* clip to the bounding box */ + if (clip) { + pcb_polyarea_t *cbox = pcb_poly_from_rect(clip->X1, clip->X2, clip->Y1, clip->Y2); + pcb_polyarea_boolean_free(main_contour, cbox, &main_contour, PCB_PBO_ISECT); + } + if (main_contour == NULL) + return; + /* Now dice it up. + * NB: Could be more than one piece (because of the clip above) + */ + cur = main_contour; + do { + next = cur->f; + cur->f = cur->b = cur; /* Detach this polygon piece */ + r_NoHolesPolygonDicer(cur, emit, user_data); + /* NB: The pcb_polyarea_t was freed by its use in the recursive dicer */ + } + while ((cur = next) != main_contour); +} + +/* make a polygon split into multiple parts into multiple polygons */ +pcb_bool pcb_poly_morph(pcb_layer_t *layer, pcb_poly_t *poly) +{ + pcb_polyarea_t *p, *start; + pcb_bool many = pcb_false; + pcb_flag_t flags; + + if (!poly->Clipped || PCB_FLAG_TEST(PCB_FLAG_LOCK, poly)) + return pcb_false; + if (poly->Clipped->f == poly->Clipped) + return pcb_false; + pcb_poly_invalidate_erase(poly); + start = p = poly->Clipped; + /* This is ugly. The creation of the new polygons can cause + * all of the polygon pointers (including the one we're called + * with to change if there is a realloc in pcb_poly_alloc(). + * That will invalidate our original "poly" argument, potentially + * inside the loop. We need to steal the Clipped pointer and + * hide it from the Remove call so that it still exists while + * we do this dirty work. + */ + poly->Clipped = NULL; + if (poly->NoHoles) + printf("Just leaked in MorpyPolygon\n"); + poly->NoHoles = NULL; + flags = poly->Flags; + pcb_poly_remove(layer, poly); + inhibit = pcb_true; + do { + pcb_vnode_t *v; + pcb_poly_t *newone; + + if (p->contours->area > conf_core.design.poly_isle_area) { + newone = pcb_poly_new(layer, poly->Clearance, flags); + if (!newone) + return pcb_false; + many = pcb_true; + v = &p->contours->head; + pcb_poly_point_new(newone, v->point[0], v->point[1]); + for (v = v->next; v != &p->contours->head; v = v->next) + pcb_poly_point_new(newone, v->point[0], v->point[1]); + newone->BoundingBox.X1 = p->contours->xmin; + newone->BoundingBox.X2 = p->contours->xmax + 1; + newone->BoundingBox.Y1 = p->contours->ymin; + newone->BoundingBox.Y2 = p->contours->ymax + 1; + pcb_undo_add_obj_to_create(PCB_OBJ_POLY, layer, newone, newone); + newone->Clipped = p; + p = p->f; /* go to next pline */ + newone->Clipped->b = newone->Clipped->f = newone->Clipped; /* unlink from others */ + pcb_r_insert_entry(layer->polygon_tree, (pcb_box_t *) newone); + pcb_poly_invalidate_draw(layer, newone); + } + else { + pcb_polyarea_t *t = p; + + p = p->f; + pcb_poly_contour_del(&t->contours); + free(t); + } + } + while (p != start); + inhibit = pcb_false; + pcb_undo_inc_serial(); + return many; +} + +void debug_pline(pcb_pline_t * pl) +{ + pcb_vnode_t *v; + pcb_fprintf(stderr, "\txmin %#mS xmax %#mS ymin %#mS ymax %#mS\n", pl->xmin, pl->xmax, pl->ymin, pl->ymax); + v = &pl->head; + while (v) { + pcb_fprintf(stderr, "\t\tvnode: %#mD\n", v->point[0], v->point[1]); + v = v->next; + if (v == &pl->head) + break; + } +} + +void debug_polyarea(pcb_polyarea_t * p) +{ + pcb_pline_t *pl; + + fprintf(stderr, "pcb_polyarea_t %p\n", (void *)p); + for (pl = p->contours; pl; pl = pl->next) + debug_pline(pl); +} + +void debug_polygon(pcb_poly_t * p) +{ + pcb_cardinal_t i; + pcb_polyarea_t *pa; + fprintf(stderr, "POLYGON %p %d pts\n", (void *)p, p->PointN); + for (i = 0; i < p->PointN; i++) + pcb_fprintf(stderr, "\t%d: %#mD\n", i, p->Points[i].X, p->Points[i].Y); + if (p->HoleIndexN) { + fprintf(stderr, "%d holes, starting at indices\n", p->HoleIndexN); + for (i = 0; i < p->HoleIndexN; i++) + fprintf(stderr, "\t%d: %d\n", i, p->HoleIndex[i]); + } + else + fprintf(stderr, "it has no holes\n"); + pa = p->Clipped; + while (pa) { + debug_polyarea(pa); + pa = pa->f; + if (pa == p->Clipped) + break; + } +} + +/* Convert a pcb_polyarea_t (and all linked pcb_polyarea_t) to + * raw PCB polygons on the given layer. + */ +void pcb_poly_to_polygons_on_layer(pcb_data_t * Destination, pcb_layer_t * Layer, pcb_polyarea_t * Input, pcb_flag_t Flags) +{ + pcb_poly_t *Polygon; + pcb_polyarea_t *pa; + pcb_pline_t *pline; + pcb_vnode_t *node; + pcb_bool outer; + + if (Input == NULL) + return; + + pa = Input; + do { + Polygon = pcb_poly_new(Layer, 2 * conf_core.design.clearance, Flags); + + pline = pa->contours; + outer = pcb_true; + + do { + if (!outer) + pcb_poly_hole_new(Polygon); + outer = pcb_false; + + node = &pline->head; + do { + pcb_poly_point_new(Polygon, node->point[0], node->point[1]); + } + while ((node = node->next) != &pline->head); + + } + while ((pline = pline->next) != NULL); + + pcb_poly_init_clip(Destination, Layer, Polygon); + pcb_poly_bbox(Polygon); + if (!Layer->polygon_tree) + Layer->polygon_tree = pcb_r_create_tree(); + pcb_r_insert_entry(Layer->polygon_tree, (pcb_box_t *) Polygon); + + pcb_poly_invalidate_draw(Layer, Polygon); + /* add to undo list */ + pcb_undo_add_obj_to_create(PCB_OBJ_POLY, Layer, Polygon, Polygon); + } + while ((pa = pa->f) != Input); + + pcb_board_set_changed_flag(pcb_true); +} + +pcb_bool pcb_pline_is_rectangle(pcb_pline_t *pl) +{ + int n; + pcb_coord_t x[4], y[4]; + pcb_vnode_t *v; + + v = pl->head.next; + n = 0; + do { + x[n] = v->point[0]; + y[n] = v->point[1]; + n++; + v = v->next; + } while((n < 4) && (v != pl->head.next)); + + if (n != 4) + return pcb_false; + + if (sqr(x[0] - x[2]) + sqr(y[0] - y[2]) == sqr(x[1] - x[3]) + sqr(y[1] - y[3])) + return pcb_true; + + return pcb_false; +} + +#include "polygon_offs.c" Index: tags/2.1.2/src/polygon.h =================================================================== --- tags/2.1.2/src/polygon.h (nonexistent) +++ tags/2.1.2/src/polygon.h (revision 24813) @@ -0,0 +1,129 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +/* High level polygon support: pcb-specific polygon operations on complex + polygon objects with islands and holes */ + +#ifndef PCB_POLYGON_H +#define PCB_POLYGON_H + +#include "config.h" +#include "flag.h" +#include "rtree.h" +#include "math_helper.h" +#include "polyarea.h" + +/* Implementation constants */ + +#define PCB_POLY_CIRC_SEGS 40 +#define PCB_POLY_CIRC_SEGS_F ((float)PCB_POLY_CIRC_SEGS) + +/* adjustment to make the segments outline the circle rather than connect + * points on the circle: 1 - cos (\alpha / 2) < (\alpha / 2) ^ 2 / 2 + */ +#define PCB_POLY_CIRC_RADIUS_ADJ (1.0 + M_PI / PCB_POLY_CIRC_SEGS_F * \ + M_PI / PCB_POLY_CIRC_SEGS_F / 2.0) + +/* polygon diverges from modelled arc no more than MAX_ARC_DEVIATION * thick */ +#define PCB_POLY_ARC_MAX_DEVIATION 0.02 + +/* Prototypes */ + +void pcb_polygon_init(void); +void pcb_polygon_uninit(void); +pcb_cardinal_t pcb_poly_point_idx(pcb_poly_t *polygon, pcb_point_t *point); +pcb_cardinal_t pcb_poly_contour_point(pcb_poly_t *polygon, pcb_cardinal_t point); +pcb_cardinal_t pcb_poly_contour_prev_point(pcb_poly_t *polygon, pcb_cardinal_t point); +pcb_cardinal_t pcb_poly_contour_next_point(pcb_poly_t *polygon, pcb_cardinal_t point); +pcb_cardinal_t pcb_poly_get_lowest_distance_point(pcb_poly_t *, pcb_coord_t, pcb_coord_t); +pcb_bool pcb_poly_remove_excess_points(pcb_layer_t *, pcb_poly_t *); +void pcb_polygon_go_to_prev_point(void); /* undo */ +void pcb_polygon_go_to_next_point(void); /* redo */ +void pcb_polygon_close_poly(void); +void pcb_polygon_copy_attached_to_layer(void); +void pcb_polygon_close_hole(void); +void pcb_polygon_hole_create_from_attached(void); +int pcb_poly_holes(pcb_poly_t * ptr, const pcb_box_t * range, int (*callback) (pcb_pline_t *, void *user_data), void *user_data); +int pcb_poly_plows(pcb_data_t *Data, int type, void *ptr1, void *ptr2, + pcb_r_dir_t (*cb)(pcb_data_t *data, pcb_layer_t *lay, pcb_poly_t *poly, int type, void *ptr1, void *ptr2, void *user_data), + void *user_data); +void pcb_poly_compute_no_holes(pcb_poly_t * poly); + +/* helpers: create complex shaped polygons */ +pcb_polyarea_t *pcb_poly_from_contour(pcb_pline_t *); +pcb_polyarea_t *pcb_poly_from_poly(pcb_poly_t *); +pcb_polyarea_t *pcb_poly_from_rect(pcb_coord_t x1, pcb_coord_t x2, pcb_coord_t y1, pcb_coord_t y2); +pcb_polyarea_t *pcb_poly_from_circle(pcb_coord_t x, pcb_coord_t y, pcb_coord_t radius); +pcb_polyarea_t *pcb_poly_from_octagon(pcb_coord_t x, pcb_coord_t y, pcb_coord_t radius, int style); +pcb_polyarea_t *pcb_poly_from_line(pcb_line_t * l, pcb_coord_t thick); +pcb_polyarea_t *pcb_poly_from_arc(pcb_arc_t * l, pcb_coord_t thick); +pcb_polyarea_t *pcb_poly_from_box_bloated(pcb_box_t * box, pcb_coord_t radius); +pcb_polyarea_t *pcb_poly_clearance_construct(pcb_poly_t *subpoly); /* clearance shape for when clearpolypoly is set */ + + +void pcb_poly_frac_circle(pcb_pline_t *, pcb_coord_t, pcb_coord_t, pcb_vector_t, int); +int pcb_poly_init_clip(pcb_data_t * d, pcb_layer_t * l, pcb_poly_t * p); +void pcb_poly_restore_to_poly(pcb_data_t *, int, void *, void *); +void pcb_poly_clear_from_poly(pcb_data_t *, int, void *, void *); + +/* Same as pcb_poly_init_clip() but also call cb before each operation, + giving the caller a chance to draw a progress bar */ +int pcb_poly_init_clip_prog(pcb_data_t *Data, pcb_layer_t *layer, pcb_poly_t *p, void (*cb)(void *ctx), void *ctx); + +/* Return the number of subtractions that have to be executed by a + pcb_poly_init_clip() on the given polygon */ +pcb_cardinal_t pcb_poly_num_clears(pcb_data_t *data, pcb_layer_t *layer, pcb_poly_t *polygon); + + +pcb_bool pcb_poly_is_point_in_p(pcb_coord_t, pcb_coord_t, pcb_coord_t, pcb_poly_t *); +pcb_bool pcb_poly_is_point_in_p_ignore_holes(pcb_coord_t, pcb_coord_t, pcb_poly_t *); +pcb_bool_t pcb_is_point_in_convex_quad(pcb_vector_t p, pcb_vector_t *q); +pcb_bool pcb_poly_is_rect_in_p(pcb_coord_t, pcb_coord_t, pcb_coord_t, pcb_coord_t, pcb_poly_t *); +pcb_bool pcb_poly_isects_poly(pcb_polyarea_t *, pcb_poly_t *, pcb_bool); +pcb_bool pcb_pline_isect_line(pcb_pline_t *pl, pcb_coord_t lx1, pcb_coord_t ly1, pcb_coord_t lx2, pcb_coord_t ly2, pcb_coord_t *cx, pcb_coord_t *cy); +pcb_bool pcb_pline_isect_circ(pcb_pline_t *pl, pcb_coord_t cx, pcb_coord_t cy, pcb_coord_t r); /* cirlce contour crosses polyline contour */ +pcb_bool pcb_pline_embraces_circ(pcb_pline_t *pl, pcb_coord_t cx, pcb_coord_t cy, pcb_coord_t r); /* circle is within the polyline; caller must make sure they do not cross! */ +pcb_bool pcb_pline_overlaps_circ(pcb_pline_t *pl, pcb_coord_t cx, pcb_coord_t cy, pcb_coord_t r); /* circle is within or is crossing the polyline */ +pcb_bool pcb_poly_morph(pcb_layer_t *, pcb_poly_t *); +void pcb_poly_no_holes_dicer(pcb_poly_t * p, const pcb_box_t * clip, void (*emit) (pcb_pline_t *, void *), void *user_data); +void pcb_poly_to_polygons_on_layer(pcb_data_t *, pcb_layer_t *, pcb_polyarea_t *, pcb_flag_t); + +void pcb_poly_square_pin_factors(int style, double *xm, double *ym); + +pcb_bool pcb_pline_is_rectangle(pcb_pline_t *pl); + +/* clear np1 from the polygon; also free np1 if fnp is true. Returns 1 on + success. */ +int pcb_poly_subtract(pcb_polyarea_t *np1, pcb_poly_t *p, pcb_bool fnp); + +/* Subtract or unsubtract obj from poly; Layer is used for looking up thermals */ +int pcb_poly_sub_obj(pcb_data_t *Data, pcb_layer_t *Layer, pcb_poly_t *Polygon, int type, void *obj); +int pcb_poly_unsub_obj(pcb_data_t *Data, pcb_layer_t *Layer, pcb_poly_t *Polygon, int type, void *obj); + + +#endif Index: tags/2.1.2/src/polygon1.c =================================================================== --- tags/2.1.2/src/polygon1.c (nonexistent) +++ tags/2.1.2/src/polygon1.c (revision 24813) @@ -0,0 +1,3568 @@ +/* + polygon clipping functions. harry eaton implemented the algorithm + described in "A Closed Set of Algorithms for Performing Set + Operations on Polygonal Regions in the Plane" which the original + code did not do. I also modified it for integer coordinates + and faster computation. The license for this modified copy was + switched to the GPL per term (3) of the original LGPL license. + Copyright (C) 2006 harry eaton + + based on: + poly_Boolean: a polygon clip library + Copyright (C) 1997 Alexey Nikitin, Michael Leonov + (also the authors of the paper describing the actual algorithm) + leonov@propro.iis.nsk.su + + in turn based on: + nclip: a polygon clip library + Copyright (C) 1993 Klamer Schutte + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public + License along with this program; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + polygon1.c + (C) 1997 Alexey Nikitin, Michael Leonov + (C) 1993 Klamer Schutte + + all cases where original (Klamer Schutte) code is present + are marked +*/ + +#include +#include +#include +#include +#include + +#include "config.h" +#include "rtree.h" +#include "math_helper.h" +#include "heap.h" +#include "compat_cc.h" +#include "pcb-printf.h" +#include "polyarea.h" +#include "obj_common.h" +#include "macro.h" +#include "box.h" + + +#define ROUND(a) (long)((a) > 0 ? ((a) + 0.5) : ((a) - 0.5)) + +#define EPSILON (1E-8) +#define IsZero(a, b) (fabs((a) - (b)) < EPSILON) + +#undef min +#undef max +#define min(x, y) ((x) < (y) ? (x) : (y)) +#define max(x, y) ((x) > (y) ? (x) : (y)) + +/*********************************************************************/ +/* L o n g V e c t o r S t u f f */ +/*********************************************************************/ + +#define Vcopy(a,b) {(a)[0]=(b)[0];(a)[1]=(b)[1];} +int vect_equal(pcb_vector_t v1, pcb_vector_t v2); +void vect_init(pcb_vector_t v, double x, double y); +void vect_sub(pcb_vector_t res, pcb_vector_t v2, pcb_vector_t v3); + +void vect_min(pcb_vector_t res, pcb_vector_t v2, pcb_vector_t v3); +void vect_max(pcb_vector_t res, pcb_vector_t v2, pcb_vector_t v3); + +double pcb_vect_dist2(pcb_vector_t v1, pcb_vector_t v2); +double pcb_vect_det2(pcb_vector_t v1, pcb_vector_t v2); +double pcb_vect_len2(pcb_vector_t v1); + +int pcb_vect_inters2(pcb_vector_t A, pcb_vector_t B, pcb_vector_t C, pcb_vector_t D, pcb_vector_t S1, pcb_vector_t S2); + +/* note that a vertex v's Flags.status represents the edge defined by + * v to v->next (i.e. the edge is forward of v) + */ +#define ISECTED 3 +#define UNKNWN 0 +#define INSIDE 1 +#define OUTSIDE 2 +#define SHARED 3 +#define SHARED2 4 + +#define TOUCHES 99 + +#define NODE_LABEL(n) ((n)->Flags.status) +#define LABEL_NODE(n,l) ((n)->Flags.status = (l)) + +#define error(code) longjmp(*(e), code) + +#define MemGet(ptr, type) \ + if (PCB_UNLIKELY(((ptr) = (type *)malloc(sizeof(type))) == NULL)) \ + error(pcb_err_no_memory); + +#undef DEBUG_LABEL +#undef DEBUG_ALL_LABELS +#undef DEBUG_JUMP +#undef DEBUG_GATHER +#undef DEBUG_ANGLE +#undef DEBUG + +#ifndef NDEBUG +#include +PCB_INLINE void DEBUGP(const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + pcb_vfprintf(stderr, fmt, ap); + va_end(ap); +} +#else +PCB_INLINE void DEBUGP(const char *fmt, ...) { } +#endif + +/* ///////////////////////////////////////////////////////////////////////////// * / +/ * 2-Dimensional stuff +/ * ///////////////////////////////////////////////////////////////////////////// */ + +#define Vsub2(r,a,b) {(r)[0] = (a)[0] - (b)[0]; (r)[1] = (a)[1] - (b)[1];} +#define Vadd2(r,a,b) {(r)[0] = (a)[0] + (b)[0]; (r)[1] = (a)[1] + (b)[1];} +#define Vsca2(r,a,s) {(r)[0] = (a)[0] * (s); (r)[1] = (a)[1] * (s);} +#define Vcpy2(r,a) {(r)[0] = (a)[0]; (r)[1] = (a)[1];} +#define Vequ2(a,b) ((a)[0] == (b)[0] && (a)[1] == (b)[1]) +#define Vadds(r,a,b,s) {(r)[0] = ((a)[0] + (b)[0]) * (s); (r)[1] = ((a)[1] + (b)[1]) * (s);} +#define Vswp2(a,b) { long t; \ + t = (a)[0], (a)[0] = (b)[0], (b)[0] = t; \ + t = (a)[1], (a)[1] = (b)[1], (b)[1] = t; \ +} + +#ifdef DEBUG +static char *theState(pcb_vnode_t * v); + +static void pline_dump(pcb_vnode_t * v) +{ + pcb_vnode_t *s, *n; + + s = v; + do { + n = v->next; + pcb_fprintf(stderr, "Line [%#mS %#mS %#mS %#mS 10 10 \"%s\"]\n", + v->point[0], v->point[1], n->point[0], n->point[1], theState(v)); + } + while ((v = v->next) != s); +} + +static void poly_dump(pcb_polyarea_t * p) +{ + pcb_polyarea_t *f = p; + pcb_pline_t *pl; + + do { + pl = p->contours; + do { + pline_dump(&pl->head); + fprintf(stderr, "NEXT pcb_pline_t\n"); + } + while ((pl = pl->next) != NULL); + fprintf(stderr, "NEXT POLY\n"); + } + while ((p = p->f) != f); +} +#endif + +/***************************************************************/ +/* routines for processing intersections */ + +/* +node_add + (C) 1993 Klamer Schutte + (C) 1997 Alexey Nikitin, Michael Leonov + (C) 2006 harry eaton + + returns a bit field in new_point that indicates where the + point was. + 1 means a new node was created and inserted + 4 means the intersection was not on the dest point +*/ +static pcb_vnode_t *node_add_single(pcb_vnode_t * dest, pcb_vector_t po) +{ + pcb_vnode_t *p; + + if (vect_equal(po, dest->point)) + return dest; + if (vect_equal(po, dest->next->point)) + return dest->next; + p = pcb_poly_node_create(po); + if (p == NULL) + return NULL; + p->cvc_prev = p->cvc_next = NULL; + p->Flags.status = UNKNWN; + return p; +} /* node_add */ + +#define ISECT_BAD_PARAM (-1) +#define ISECT_NO_MEMORY (-2) + + +/* +new_descriptor + (C) 2006 harry eaton +*/ +static pcb_cvc_list_t *new_descriptor(pcb_vnode_t * a, char poly, char side) +{ + pcb_cvc_list_t *l = (pcb_cvc_list_t *) malloc(sizeof(pcb_cvc_list_t)); + pcb_vector_t v; + register double ang, dx, dy; + + if (!l) + return NULL; + l->head = NULL; + l->parent = a; + l->poly = poly; + l->side = side; + l->next = l->prev = l; + if (side == 'P') /* previous */ + vect_sub(v, a->prev->point, a->point); + else /* next */ + vect_sub(v, a->next->point, a->point); + /* Uses slope/(slope+1) in quadrant 1 as a proxy for the angle. + * It still has the same monotonic sort result + * and is far less expensive to compute than the real angle. + */ + if (vect_equal(v, vect_zero)) { + if (side == 'P') { + if (a->prev->cvc_prev == (pcb_cvc_list_t *) - 1) + a->prev->cvc_prev = a->prev->cvc_next = NULL; + pcb_poly_vertex_exclude(a->prev); + vect_sub(v, a->prev->point, a->point); + } + else { + if (a->next->cvc_prev == (pcb_cvc_list_t *) - 1) + a->next->cvc_prev = a->next->cvc_next = NULL; + pcb_poly_vertex_exclude(a->next); + vect_sub(v, a->next->point, a->point); + } + } + assert(!vect_equal(v, vect_zero)); + dx = fabs((double) v[0]); + dy = fabs((double) v[1]); + ang = dy / (dy + dx); + /* now move to the actual quadrant */ + if (v[0] < 0 && v[1] >= 0) + ang = 2.0 - ang; /* 2nd quadrant */ + else if (v[0] < 0 && v[1] < 0) + ang += 2.0; /* 3rd quadrant */ + else if (v[0] >= 0 && v[1] < 0) + ang = 4.0 - ang; /* 4th quadrant */ + l->angle = ang; + assert(ang >= 0.0 && ang <= 4.0); +#ifdef DEBUG_ANGLE + DEBUGP("node on %c at %#mD assigned angle %g on side %c\n", poly, a->point[0], a->point[1], ang, side); +#endif + return l; +} + +/* +insert_descriptor + (C) 2006 harry eaton + + argument a is a cross-vertex node. + argument poly is the polygon it comes from ('A' or 'B') + argument side is the side this descriptor goes on ('P' for previous + 'N' for next. + argument start is the head of the list of cvclists +*/ +static pcb_cvc_list_t *insert_descriptor(pcb_vnode_t * a, char poly, char side, pcb_cvc_list_t * start) +{ + pcb_cvc_list_t *l, *newone, *big, *small; + + if (!(newone = new_descriptor(a, poly, side))) + return NULL; + /* search for the pcb_cvc_list_t for this point */ + if (!start) { + start = newone; /* return is also new, so we know where start is */ + start->head = newone; /* circular list */ + return newone; + } + else { + l = start; + do { + assert(l->head); + if (l->parent->point[0] == a->point[0] + && l->parent->point[1] == a->point[1]) { /* this pcb_cvc_list_t is at our point */ + start = l; + newone->head = l->head; + break; + } + if (l->head->parent->point[0] == start->parent->point[0] + && l->head->parent->point[1] == start->parent->point[1]) { + /* this seems to be a new point */ + /* link this cvclist to the list of all cvclists */ + for (; l->head != newone; l = l->next) + l->head = newone; + newone->head = start; + return newone; + } + l = l->head; + } + while (1); + } + assert(start); + l = big = small = start; + do { + if (l->next->angle < l->angle) { /* find start/end of list */ + small = l->next; + big = l; + } + else if (newone->angle >= l->angle && newone->angle <= l->next->angle) { + /* insert new cvc if it lies between existing points */ + newone->prev = l; + newone->next = l->next; + l->next = l->next->prev = newone; + return newone; + } + } + while ((l = l->next) != start); + /* didn't find it between points, it must go on an end */ + if (big->angle <= newone->angle) { + newone->prev = big; + newone->next = big->next; + big->next = big->next->prev = newone; + return newone; + } + assert(small->angle >= newone->angle); + newone->next = small; + newone->prev = small->prev; + small->prev = small->prev->next = newone; + return newone; +} + +/* +node_add_point + (C) 1993 Klamer Schutte + (C) 1997 Alexey Nikitin, Michael Leonov + + return 1 if new node in b, 2 if new node in a and 3 if new node in both +*/ + +static pcb_vnode_t *node_add_single_point(pcb_vnode_t * a, pcb_vector_t p) +{ + pcb_vnode_t *next_a, *new_node; + + next_a = a->next; + + new_node = node_add_single(a, p); + assert(new_node != NULL); + + new_node->cvc_prev = new_node->cvc_next = (pcb_cvc_list_t *) - 1; + + if (new_node == a || new_node == next_a) + return NULL; + + return new_node; +} /* node_add_point */ + +/* +node_label + (C) 2006 harry eaton +*/ +static unsigned int node_label(pcb_vnode_t * pn) +{ + pcb_cvc_list_t *first_l, *l; + char this_poly; + int region = UNKNWN; + + assert(pn); + assert(pn->cvc_next); + this_poly = pn->cvc_next->poly; + /* search counter-clockwise in the cross vertex connectivity (CVC) list + * + * check for shared edges (that could be prev or next in the list since the angles are equal) + * and check if this edge (pn -> pn->next) is found between the other poly's entry and exit + */ + if (pn->cvc_next->angle == pn->cvc_next->prev->angle) + l = pn->cvc_next->prev; + else + l = pn->cvc_next->next; + + first_l = l; + while ((l->poly == this_poly) && (l != first_l->prev)) + l = l->next; + assert(l->poly != this_poly); + + assert(l && l->angle >= 0 && l->angle <= 4.0); + if (l->poly != this_poly) { + if (l->side == 'P') { + if (l->parent->prev->point[0] == pn->next->point[0] && l->parent->prev->point[1] == pn->next->point[1]) { + region = SHARED2; + pn->shared = l->parent->prev; + } + else + region = INSIDE; + } + else { + if (l->angle == pn->cvc_next->angle) { + assert(l->parent->next->point[0] == pn->next->point[0] && l->parent->next->point[1] == pn->next->point[1]); + region = SHARED; + pn->shared = l->parent; + } + else + region = OUTSIDE; + } + } + if (region == UNKNWN) { + for (l = l->next; l != pn->cvc_next; l = l->next) { + if (l->poly != this_poly) { + if (l->side == 'P') + region = INSIDE; + else + region = OUTSIDE; + break; + } + } + } + assert(region != UNKNWN); + assert(NODE_LABEL(pn) == UNKNWN || NODE_LABEL(pn) == region); + LABEL_NODE(pn, region); + if (region == SHARED || region == SHARED2) + return UNKNWN; + return region; +} /* node_label */ + +/* + add_descriptors + (C) 2006 harry eaton +*/ +static pcb_cvc_list_t *add_descriptors(pcb_pline_t * pl, char poly, pcb_cvc_list_t * list) +{ + pcb_vnode_t *node = &pl->head; + + do { + if (node->cvc_prev) { + assert(node->cvc_prev == (pcb_cvc_list_t *) - 1 && node->cvc_next == (pcb_cvc_list_t *) - 1); + list = node->cvc_prev = insert_descriptor(node, poly, 'P', list); + if (!node->cvc_prev) + return NULL; + list = node->cvc_next = insert_descriptor(node, poly, 'N', list); + if (!node->cvc_next) + return NULL; + } + } + while ((node = node->next) != &pl->head); + return list; +} + +static inline void cntrbox_adjust(pcb_pline_t * c, pcb_vector_t p) +{ + c->xmin = min(c->xmin, p[0]); + c->xmax = max(c->xmax, p[0] + 1); + c->ymin = min(c->ymin, p[1]); + c->ymax = max(c->ymax, p[1] + 1); +} + +/* some structures for handling segment intersections using the rtrees */ + +typedef struct seg { + pcb_box_t box; + pcb_vnode_t *v; + pcb_pline_t *p; + int intersected; +} seg; + +typedef struct _insert_node_task insert_node_task; + +struct _insert_node_task { + insert_node_task *next; + seg *node_seg; + pcb_vnode_t *new_node; +}; + +typedef struct info { + double m, b; + pcb_rtree_t *tree; + pcb_vnode_t *v; + struct seg *s; + jmp_buf *env, sego, *touch; + int need_restart; + insert_node_task *node_insert_list; +} info; + +typedef struct contour_info { + pcb_pline_t *pa; + jmp_buf restart; + jmp_buf *getout; + int need_restart; + insert_node_task *node_insert_list; +} contour_info; + + +/* + * adjust_tree() + * (C) 2006 harry eaton + * This replaces the segment in the tree with the two new segments after + * a vertex has been added + */ +static int adjust_tree(pcb_rtree_t * tree, struct seg *s) +{ + struct seg *q; + + q = (seg *) malloc(sizeof(struct seg)); + if (!q) + return 1; + q->intersected = 0; + q->v = s->v; + q->p = s->p; + q->box.X1 = min(q->v->point[0], q->v->next->point[0]); + q->box.X2 = max(q->v->point[0], q->v->next->point[0]) + 1; + q->box.Y1 = min(q->v->point[1], q->v->next->point[1]); + q->box.Y2 = max(q->v->point[1], q->v->next->point[1]) + 1; + pcb_r_insert_entry(tree, (const pcb_box_t *) q); + q = (seg *) malloc(sizeof(struct seg)); + if (!q) + return 1; + q->intersected = 0; + q->v = s->v->next; + q->p = s->p; + q->box.X1 = min(q->v->point[0], q->v->next->point[0]); + q->box.X2 = max(q->v->point[0], q->v->next->point[0]) + 1; + q->box.Y1 = min(q->v->point[1], q->v->next->point[1]); + q->box.Y2 = max(q->v->point[1], q->v->next->point[1]) + 1; + pcb_r_insert_entry(tree, (const pcb_box_t *) q); + pcb_r_delete_entry(tree, (const pcb_box_t *) s); + free(s); + return 0; +} + +/* + * seg_in_region() + * (C) 2006, harry eaton + * This prunes the search for boxes that don't intersect the segment. + */ +static pcb_r_dir_t seg_in_region(const pcb_box_t * b, void *cl) +{ + struct info *i = (struct info *) cl; + double y1, y2; + /* for zero slope the search is aligned on the axis so it is already pruned */ + if (i->m == 0.) + return PCB_R_DIR_FOUND_CONTINUE; + y1 = i->m * b->X1 + i->b; + y2 = i->m * b->X2 + i->b; + if (min(y1, y2) >= b->Y2) + return PCB_R_DIR_NOT_FOUND; + if (max(y1, y2) < b->Y1) + return PCB_R_DIR_NOT_FOUND; + return PCB_R_DIR_FOUND_CONTINUE; /* might intersect */ +} + +/* Prepend a deferred node-insertion task to a list */ +static insert_node_task *prepend_insert_node_task(insert_node_task * list, seg * seg, pcb_vnode_t * new_node) +{ + insert_node_task *task = (insert_node_task *) malloc(sizeof(*task)); + task->node_seg = seg; + task->new_node = new_node; + task->next = list; + return task; +} + +/* + * seg_in_seg() + * (C) 2006 harry eaton + * This routine checks if the segment in the tree intersect the search segment. + * If it does, the plines are marked as intersected and the point is marked for + * the cvclist. If the point is not already a vertex, a new vertex is inserted + * and the search for intersections starts over at the beginning. + * That is potentially a significant time penalty, but it does solve the snap rounding + * problem. There are efficient algorithms for finding intersections with snap + * rounding, but I don't have time to implement them right now. + */ +static pcb_r_dir_t seg_in_seg(const pcb_box_t * b, void *cl) +{ + struct info *i = (struct info *) cl; + struct seg *s = (struct seg *) b; + pcb_vector_t s1, s2; + int cnt; + pcb_vnode_t *new_node; + + /* When new nodes are added at the end of a pass due to an intersection + * the segments may be altered. If either segment we're looking at has + * already been intersected this pass, skip it until the next pass. + */ + if (s->intersected || i->s->intersected) + return PCB_R_DIR_NOT_FOUND; + + cnt = pcb_vect_inters2(s->v->point, s->v->next->point, i->v->point, i->v->next->point, s1, s2); + if (!cnt) + return PCB_R_DIR_NOT_FOUND; + if (i->touch) /* if checking touches one find and we're done */ + longjmp(*i->touch, TOUCHES); + i->s->p->Flags.status = ISECTED; + s->p->Flags.status = ISECTED; + for (; cnt; cnt--) { + pcb_bool done_insert_on_i = pcb_false; + new_node = node_add_single_point(i->v, cnt > 1 ? s2 : s1); + if (new_node != NULL) { +#ifdef DEBUG_INTERSECT + DEBUGP("new intersection on segment \"i\" at %#mD\n", cnt > 1 ? s2[0] : s1[0], cnt > 1 ? s2[1] : s1[1]); +#endif + i->node_insert_list = prepend_insert_node_task(i->node_insert_list, i->s, new_node); + i->s->intersected = 1; + done_insert_on_i = pcb_true; + } + new_node = node_add_single_point(s->v, cnt > 1 ? s2 : s1); + if (new_node != NULL) { +#ifdef DEBUG_INTERSECT + DEBUGP("new intersection on segment \"s\" at %#mD\n", cnt > 1 ? s2[0] : s1[0], cnt > 1 ? s2[1] : s1[1]); +#endif + i->node_insert_list = prepend_insert_node_task(i->node_insert_list, s, new_node); + s->intersected = 1; + return PCB_R_DIR_NOT_FOUND; /* Keep looking for intersections with segment "i" */ + } + /* Skip any remaining r_search hits against segment i, as any further + * intersections will be rejected until the next pass anyway. + */ + if (done_insert_on_i) + longjmp(*i->env, 1); + } + return PCB_R_DIR_NOT_FOUND; +} + +static void *make_edge_tree(pcb_pline_t * pb) +{ + struct seg *s; + pcb_vnode_t *bv; + pcb_rtree_t *ans = pcb_r_create_tree(); + bv = &pb->head; + do { + s = (seg *) malloc(sizeof(struct seg)); + s->intersected = 0; + if (bv->point[0] < bv->next->point[0]) { + s->box.X1 = bv->point[0]; + s->box.X2 = bv->next->point[0] + 1; + } + else { + s->box.X2 = bv->point[0] + 1; + s->box.X1 = bv->next->point[0]; + } + if (bv->point[1] < bv->next->point[1]) { + s->box.Y1 = bv->point[1]; + s->box.Y2 = bv->next->point[1] + 1; + } + else { + s->box.Y2 = bv->point[1] + 1; + s->box.Y1 = bv->next->point[1]; + } + s->v = bv; + s->p = pb; + pcb_r_insert_entry(ans, (const pcb_box_t *) s); + } + while ((bv = bv->next) != &pb->head); + return (void *) ans; +} + +static pcb_r_dir_t get_seg(const pcb_box_t * b, void *cl) +{ + struct info *i = (struct info *) cl; + struct seg *s = (struct seg *) b; + if (i->v == s->v) { + i->s = s; + return PCB_R_DIR_CANCEL; /* found */ + } + return PCB_R_DIR_NOT_FOUND; +} + +/* + * intersect() (and helpers) + * (C) 2006, harry eaton + * This uses an rtree to find A-B intersections. Whenever a new vertex is + * added, the search for intersections is re-started because the rounding + * could alter the topology otherwise. + * This should use a faster algorithm for snap rounding intersection finding. + * The best algorithm is probably found in: + * + * "Improved output-sensitive snap rounding," John Hershberger, Proceedings + * of the 22nd annual symposium on Computational geometry, 2006, pp 357-366. + * http://doi.acm.org/10.1145/1137856.1137909 + * + * Algorithms described by de Berg, or Goodrich or Halperin, or Hobby would + * probably work as well. + * + */ + +static pcb_r_dir_t contour_bounds_touch(const pcb_box_t * b, void *cl) +{ + contour_info *c_info = (contour_info *) cl; + pcb_pline_t *pa = c_info->pa; + pcb_pline_t *pb = (pcb_pline_t *) b; + pcb_pline_t *rtree_over; + pcb_pline_t *looping_over; + pcb_vnode_t *av; /* node iterators */ + struct info info; + pcb_box_t box; + jmp_buf restart; + + /* Have seg_in_seg return to our desired location if it touches */ + info.env = &restart; + info.touch = c_info->getout; + info.need_restart = 0; + info.node_insert_list = c_info->node_insert_list; + + /* Pick which contour has the fewer points, and do the loop + * over that. The r_tree makes hit-testing against a contour + * faster, so we want to do that on the bigger contour. + */ + if (pa->Count < pb->Count) { + rtree_over = pb; + looping_over = pa; + } + else { + rtree_over = pa; + looping_over = pb; + } + + av = &looping_over->head; + do { /* Loop over the nodes in the smaller contour */ + pcb_r_dir_t rres; + /* check this edge for any insertions */ + double dx; + info.v = av; + /* compute the slant for region trimming */ + dx = av->next->point[0] - av->point[0]; + if (dx == 0) + info.m = 0; + else { + info.m = (av->next->point[1] - av->point[1]) / dx; + info.b = av->point[1] - info.m * av->point[0]; + } + box.X2 = (box.X1 = av->point[0]) + 1; + box.Y2 = (box.Y1 = av->point[1]) + 1; + + /* fill in the segment in info corresponding to this node */ + rres = pcb_r_search(looping_over->tree, &box, NULL, get_seg, &info, NULL); + assert(rres == PCB_R_DIR_CANCEL); + + /* If we're going to have another pass anyway, skip this */ + if (info.s->intersected && info.node_insert_list != NULL) + continue; + + if (setjmp(restart)) + continue; + + /* NB: If this actually hits anything, we are teleported back to the beginning */ + info.tree = rtree_over->tree; + if (info.tree) { + int seen; + pcb_r_search(info.tree, &info.s->box, seg_in_region, seg_in_seg, &info, &seen); + if (PCB_UNLIKELY(seen)) + assert(0); /* XXX: Memory allocation failure */ + } + } + while ((av = av->next) != &looping_over->head); + + c_info->node_insert_list = info.node_insert_list; + if (info.need_restart) + c_info->need_restart = 1; + return PCB_R_DIR_NOT_FOUND; +} + +static int intersect_impl(jmp_buf * jb, pcb_polyarea_t * b, pcb_polyarea_t * a, int add) +{ + pcb_polyarea_t *t; + pcb_pline_t *pa; + contour_info c_info; + int need_restart = 0; + insert_node_task *task; + c_info.need_restart = 0; + c_info.node_insert_list = NULL; + + /* Search the r-tree of the object with most contours + * We loop over the contours of "a". Swap if necessary. + */ + if (a->contour_tree->size > b->contour_tree->size) { + t = b; + b = a; + a = t; + } + + for (pa = a->contours; pa; pa = pa->next) { /* Loop over the contours of pcb_polyarea_t "a" */ + pcb_box_t sb; + jmp_buf out; + int retval; + + c_info.getout = NULL; + c_info.pa = pa; + + if (!add) { + retval = setjmp(out); + if (retval) { + /* The intersection test short-circuited back here, + * we need to clean up, then longjmp to jb */ + longjmp(*jb, retval); + } + c_info.getout = &out; + } + + sb.X1 = pa->xmin; + sb.Y1 = pa->ymin; + sb.X2 = pa->xmax + 1; + sb.Y2 = pa->ymax + 1; + + pcb_r_search(b->contour_tree, &sb, NULL, contour_bounds_touch, &c_info, NULL); + if (c_info.need_restart) + need_restart = 1; + } + + /* Process any deferred node insertions */ + task = c_info.node_insert_list; + while (task != NULL) { + insert_node_task *next = task->next; + + /* Do insertion */ + task->new_node->prev = task->node_seg->v; + task->new_node->next = task->node_seg->v->next; + task->node_seg->v->next->prev = task->new_node; + task->node_seg->v->next = task->new_node; + task->node_seg->p->Count++; + + cntrbox_adjust(task->node_seg->p, task->new_node->point); + if (adjust_tree(task->node_seg->p->tree, task->node_seg)) + assert(0); /* XXX: Memory allocation failure */ + + need_restart = 1; /* Any new nodes could intersect */ + + free(task); + task = next; + } + + return need_restart; +} + +static int intersect(jmp_buf * jb, pcb_polyarea_t * b, pcb_polyarea_t * a, int add) +{ + int call_count = 1; + while (intersect_impl(jb, b, a, add)) + call_count++; + return 0; +} + +static void M_pcb_polyarea_t_intersect(jmp_buf * e, pcb_polyarea_t * afst, pcb_polyarea_t * bfst, int add) +{ + pcb_polyarea_t *a = afst, *b = bfst; + pcb_pline_t *curcA, *curcB; + pcb_cvc_list_t *the_list = NULL; + + if (a == NULL || b == NULL) + error(pcb_err_bad_parm); + do { + do { + if (a->contours->xmax >= b->contours->xmin && + a->contours->ymax >= b->contours->ymin && + a->contours->xmin <= b->contours->xmax && a->contours->ymin <= b->contours->ymax) { + if (PCB_UNLIKELY(intersect(e, a, b, add))) + error(pcb_err_no_memory); + } + } + while (add && (a = a->f) != afst); + for (curcB = b->contours; curcB != NULL; curcB = curcB->next) + if (curcB->Flags.status == ISECTED) { + the_list = add_descriptors(curcB, 'B', the_list); + if (PCB_UNLIKELY(the_list == NULL)) + error(pcb_err_no_memory); + } + } + while (add && (b = b->f) != bfst); + do { + for (curcA = a->contours; curcA != NULL; curcA = curcA->next) + if (curcA->Flags.status == ISECTED) { + the_list = add_descriptors(curcA, 'A', the_list); + if (PCB_UNLIKELY(the_list == NULL)) + error(pcb_err_no_memory); + } + } + while (add && (a = a->f) != afst); +} /* M_pcb_polyarea_t_intersect */ + +static inline int cntrbox_inside(pcb_pline_t * c1, pcb_pline_t * c2) +{ + assert(c1 != NULL && c2 != NULL); + return ((c1->xmin >= c2->xmin) && (c1->ymin >= c2->ymin) && (c1->xmax <= c2->xmax) && (c1->ymax <= c2->ymax)); +} + +/*****************************************************************/ +/* Routines for making labels */ + +static pcb_r_dir_t count_contours_i_am_inside(const pcb_box_t * b, void *cl) +{ + pcb_pline_t *me = (pcb_pline_t *) cl; + pcb_pline_t *check = (pcb_pline_t *) b; + + if (pcb_poly_contour_in_contour(check, me)) + return PCB_R_DIR_FOUND_CONTINUE; + return PCB_R_DIR_NOT_FOUND; +} + +/* cntr_in_M_pcb_polyarea_t +returns poly is inside outfst ? pcb_true : pcb_false */ +static int cntr_in_M_pcb_polyarea_t(pcb_pline_t * poly, pcb_polyarea_t * outfst, pcb_bool test) +{ + pcb_polyarea_t *outer = outfst; + pcb_heap_t *heap; + + assert(poly != NULL); + assert(outer != NULL); + + heap = pcb_heap_create(); + do { + if (cntrbox_inside(poly, outer->contours)) + pcb_heap_insert(heap, outer->contours->area, (void *) outer); + } + /* if checking touching, use only the first polygon */ + while (!test && (outer = outer->f) != outfst); + /* we need only check the smallest poly container + * but we must loop in case the box container is not + * the poly container */ + do { + int cnt; + + if (pcb_heap_is_empty(heap)) + break; + outer = (pcb_polyarea_t *) pcb_heap_remove_smallest(heap); + + pcb_r_search(outer->contour_tree, (pcb_box_t *) poly, NULL, count_contours_i_am_inside, poly, &cnt); + switch (cnt) { + case 0: /* Didn't find anything in this piece, Keep looking */ + break; + case 1: /* Found we are inside this piece, and not any of its holes */ + pcb_heap_destroy(&heap); + return pcb_true; + case 2: /* Found inside a hole in the smallest polygon so far. No need to check the other polygons */ + pcb_heap_destroy(&heap); + return pcb_false; + default: + printf("Something strange here\n"); + break; + } + } + while (1); + pcb_heap_destroy(&heap); + return pcb_false; +} /* cntr_in_M_pcb_polyarea_t */ + +#ifdef DEBUG + +static char *theState(pcb_vnode_t * v) +{ + static char u[] = "UNKNOWN"; + static char i[] = "INSIDE"; + static char o[] = "OUTSIDE"; + static char s[] = "SHARED"; + static char s2[] = "SHARED2"; + + switch (NODE_LABEL(v)) { + case INSIDE: + return i; + case OUTSIDE: + return o; + case SHARED: + return s; + case SHARED2: + return s2; + default: + return u; + } +} + +#ifdef DEBUG_ALL_LABELS +static void print_labels(pcb_pline_t * a) +{ + pcb_vnode_t *c = &a->head; + + do { + DEBUGP("%#mD->%#mD labeled %s\n", c->point[0], c->point[1], c->next->point[0], c->next->point[1], theState(c)); + } + while ((c = c->next) != &a->head); +} +#endif +#endif + +/* +label_contour + (C) 2006 harry eaton + (C) 1993 Klamer Schutte + (C) 1997 Alexey Nikitin, Michael Leonov +*/ + +static pcb_bool label_contour(pcb_pline_t * a) +{ + pcb_vnode_t *cur = &a->head; + pcb_vnode_t *first_labelled = NULL; + int label = UNKNWN; + + do { + if (cur->cvc_next) { /* examine cross vertex */ + label = node_label(cur); + if (first_labelled == NULL) + first_labelled = cur; + continue; + } + + if (first_labelled == NULL) + continue; + + /* This labels nodes which aren't cross-connected */ + assert(label == INSIDE || label == OUTSIDE); + LABEL_NODE(cur, label); + } + while ((cur = cur->next) != first_labelled); +#ifdef DEBUG_ALL_LABELS + print_labels(a); + DEBUGP("\n\n"); +#endif + return pcb_false; +} /* label_contour */ + +static pcb_bool cntr_label_pcb_polyarea_t(pcb_pline_t * poly, pcb_polyarea_t * ppl, pcb_bool test) +{ + assert(ppl != NULL && ppl->contours != NULL); + if (poly->Flags.status == ISECTED) { + label_contour(poly); /* should never get here when pcb_bool is pcb_true */ + } + else if (cntr_in_M_pcb_polyarea_t(poly, ppl, test)) { + if (test) + return pcb_true; + poly->Flags.status = INSIDE; + } + else { + if (test) + return pcb_false; + poly->Flags.status = OUTSIDE; + } + return pcb_false; +} /* cntr_label_pcb_polyarea_t */ + +static pcb_bool M_pcb_polyarea_t_label_separated(pcb_pline_t * afst, pcb_polyarea_t * b, pcb_bool touch) +{ + pcb_pline_t *curc = afst; + + for (curc = afst; curc != NULL; curc = curc->next) { + if (cntr_label_pcb_polyarea_t(curc, b, touch) && touch) + return pcb_true; + } + return pcb_false; +} + +static pcb_bool M_pcb_polyarea_t_label(pcb_polyarea_t * afst, pcb_polyarea_t * b, pcb_bool touch) +{ + pcb_polyarea_t *a = afst; + pcb_pline_t *curc; + + assert(a != NULL); + do { + for (curc = a->contours; curc != NULL; curc = curc->next) + if (cntr_label_pcb_polyarea_t(curc, b, touch)) { + if (touch) + return pcb_true; + } + } + while (!touch && (a = a->f) != afst); + return pcb_false; +} + +/****************************************************************/ + +/* routines for temporary storing resulting contours */ +static void InsCntr(jmp_buf * e, pcb_pline_t * c, pcb_polyarea_t ** dst) +{ + pcb_polyarea_t *newp; + + if (*dst == NULL) { + MemGet(*dst, pcb_polyarea_t); + (*dst)->f = (*dst)->b = *dst; + newp = *dst; + } + else { + MemGet(newp, pcb_polyarea_t); + newp->f = *dst; + newp->b = (*dst)->b; + newp->f->b = newp->b->f = newp; + } + newp->contours = c; + newp->contour_tree = pcb_r_create_tree(); + pcb_r_insert_entry(newp->contour_tree, (pcb_box_t *) c); + c->next = NULL; +} /* InsCntr */ + +static void +PutContour(jmp_buf * e, pcb_pline_t * cntr, pcb_polyarea_t ** contours, pcb_pline_t ** holes, + pcb_polyarea_t * owner, pcb_polyarea_t * parent, pcb_pline_t * parent_contour) +{ + assert(cntr != NULL); + assert(cntr->Count > 2); + cntr->next = NULL; + + if (cntr->Flags.orient == PCB_PLF_DIR) { + if (owner != NULL) + pcb_r_delete_entry(owner->contour_tree, (pcb_box_t *) cntr); + InsCntr(e, cntr, contours); + } + /* put hole into temporary list */ + else { + /* if we know this belongs inside the parent, put it there now */ + if (parent_contour) { + cntr->next = parent_contour->next; + parent_contour->next = cntr; + if (owner != parent) { + if (owner != NULL) + pcb_r_delete_entry(owner->contour_tree, (pcb_box_t *) cntr); + pcb_r_insert_entry(parent->contour_tree, (pcb_box_t *) cntr); + } + } + else { + cntr->next = *holes; + *holes = cntr; /* let cntr be 1st hole in list */ + /* We don't insert the holes into an r-tree, + * they just form a linked list */ + if (owner != NULL) + pcb_r_delete_entry(owner->contour_tree, (pcb_box_t *) cntr); + } + } +} /* PutContour */ + +static inline void remove_contour(pcb_polyarea_t * piece, pcb_pline_t * prev_contour, pcb_pline_t * contour, int remove_rtree_entry) +{ + if (piece->contours == contour) + piece->contours = contour->next; + else if (prev_contour != NULL) { + assert(prev_contour->next == contour); + prev_contour->next = contour->next; + } + + contour->next = NULL; + + if (remove_rtree_entry) + pcb_r_delete_entry(piece->contour_tree, (pcb_box_t *) contour); +} + +struct polyarea_info { + pcb_box_t BoundingBox; + pcb_polyarea_t *pa; +}; + +static pcb_r_dir_t heap_it(const pcb_box_t * b, void *cl) +{ + pcb_heap_t *heap = (pcb_heap_t *) cl; + struct polyarea_info *pa_info = (struct polyarea_info *) b; + pcb_pline_t *p = pa_info->pa->contours; + if (p->Count == 0) + return PCB_R_DIR_NOT_FOUND; /* how did this happen? */ + pcb_heap_insert(heap, p->area, pa_info); + return PCB_R_DIR_FOUND_CONTINUE; +} + +struct find_inside_info { + jmp_buf jb; + pcb_pline_t *want_inside; + pcb_pline_t *result; +}; + +static pcb_r_dir_t find_inside(const pcb_box_t * b, void *cl) +{ + struct find_inside_info *info = (struct find_inside_info *) cl; + pcb_pline_t *check = (pcb_pline_t *) b; + /* Do test on check to see if it inside info->want_inside */ + /* If it is: */ + if (check->Flags.orient == PCB_PLF_DIR) { + return PCB_R_DIR_NOT_FOUND; + } + if (pcb_poly_contour_in_contour(info->want_inside, check)) { + info->result = check; + longjmp(info->jb, 1); + } + return PCB_R_DIR_NOT_FOUND; +} + +void pcb_poly_insert_holes(jmp_buf * e, pcb_polyarea_t * dest, pcb_pline_t ** src) +{ + pcb_polyarea_t *curc; + pcb_pline_t *curh, *container; + pcb_heap_t *heap; + pcb_rtree_t *tree; + int i; + int num_polyareas = 0; + struct polyarea_info *all_pa_info, *pa_info; + + if (*src == NULL) + return; /* empty hole list */ + if (dest == NULL) + error(pcb_err_bad_parm); /* empty contour list */ + + /* Count dest polyareas */ + curc = dest; + do { + num_polyareas++; + } + while ((curc = curc->f) != dest); + + /* make a polyarea info table */ + /* make an rtree of polyarea info table */ + all_pa_info = (struct polyarea_info *) malloc(sizeof(struct polyarea_info) * num_polyareas); + tree = pcb_r_create_tree(); + i = 0; + curc = dest; + do { + all_pa_info[i].BoundingBox.X1 = curc->contours->xmin; + all_pa_info[i].BoundingBox.Y1 = curc->contours->ymin; + all_pa_info[i].BoundingBox.X2 = curc->contours->xmax; + all_pa_info[i].BoundingBox.Y2 = curc->contours->ymax; + all_pa_info[i].pa = curc; + pcb_r_insert_entry(tree, (const pcb_box_t *) &all_pa_info[i]); + i++; + } + while ((curc = curc->f) != dest); + + /* loop through the holes and put them where they belong */ + while ((curh = *src) != NULL) { + *src = curh->next; + + container = NULL; + /* build a heap of all of the polys that the hole is inside its bounding box */ + heap = pcb_heap_create(); + pcb_r_search(tree, (pcb_box_t *) curh, NULL, heap_it, heap, NULL); + if (pcb_heap_is_empty(heap)) { +#ifndef NDEBUG +#ifdef DEBUG + poly_dump(dest); +#endif +#endif + pcb_poly_contour_del(&curh); + error(pcb_err_bad_parm); + } + /* Now search the heap for the container. If there was only one item + * in the heap, assume it is the container without the expense of + * proving it. + */ + pa_info = (struct polyarea_info *) pcb_heap_remove_smallest(heap); + if (pcb_heap_is_empty(heap)) { /* only one possibility it must be the right one */ + assert(pcb_poly_contour_in_contour(pa_info->pa->contours, curh)); + container = pa_info->pa->contours; + } + else { + do { + if (pcb_poly_contour_in_contour(pa_info->pa->contours, curh)) { + container = pa_info->pa->contours; + break; + } + if (pcb_heap_is_empty(heap)) + break; + pa_info = (struct polyarea_info *) pcb_heap_remove_smallest(heap); + } + while (1); + } + pcb_heap_destroy(&heap); + if (container == NULL) { + /* bad input polygons were given */ +#ifndef NDEBUG +#ifdef DEBUG + poly_dump(dest); +#endif +#endif + curh->next = NULL; + pcb_poly_contour_del(&curh); + error(pcb_err_bad_parm); + } + else { + /* Need to check if this new hole means we need to kick out any old ones for reprocessing */ + while (1) { + struct find_inside_info info; + pcb_pline_t *prev; + + info.want_inside = curh; + + /* Set jump return */ + if (setjmp(info.jb)) { + /* Returned here! */ + } + else { + info.result = NULL; + /* Rtree search, calling back a routine to longjmp back with data about any hole inside the added one */ + /* Be sure not to bother jumping back to report the main contour! */ + pcb_r_search(pa_info->pa->contour_tree, (pcb_box_t *) curh, NULL, find_inside, &info, NULL); + + /* Nothing found? */ + break; + } + + /* We need to find the contour before it, so we can update its next pointer */ + prev = container; + while (prev->next != info.result) { + prev = prev->next; + } + + /* Remove hole from the contour */ + remove_contour(pa_info->pa, prev, info.result, pcb_true); + + /* Add hole as the next on the list to be processed in this very function */ + info.result->next = *src; + *src = info.result; + } + /* End check for kicked out holes */ + + /* link at front of hole list */ + curh->next = container->next; + container->next = curh; + pcb_r_insert_entry(pa_info->pa->contour_tree, (pcb_box_t *) curh); + + } + } + pcb_r_destroy_tree(&tree); + free(all_pa_info); +} /* pcb_poly_insert_holes */ + + +/****************************************************************/ +/* routines for collecting result */ + +typedef enum { + FORW, BACKW +} DIRECTION; + +/* Start Rule */ +typedef int (*S_Rule) (pcb_vnode_t *, DIRECTION *); + +/* Jump Rule */ +typedef int (*J_Rule) (char, pcb_vnode_t *, DIRECTION *); + +static int UniteS_Rule(pcb_vnode_t * cur, DIRECTION * initdir) +{ + *initdir = FORW; + return (NODE_LABEL(cur) == OUTSIDE) || (NODE_LABEL(cur) == SHARED); +} + +static int IsectS_Rule(pcb_vnode_t * cur, DIRECTION * initdir) +{ + *initdir = FORW; + return (NODE_LABEL(cur) == INSIDE) || (NODE_LABEL(cur) == SHARED); +} + +static int SubS_Rule(pcb_vnode_t * cur, DIRECTION * initdir) +{ + *initdir = FORW; + return (NODE_LABEL(cur) == OUTSIDE) || (NODE_LABEL(cur) == SHARED2); +} + +static int XorS_Rule(pcb_vnode_t * cur, DIRECTION * initdir) +{ + if (cur->Flags.status == INSIDE) { + *initdir = BACKW; + return pcb_true; + } + if (cur->Flags.status == OUTSIDE) { + *initdir = FORW; + return pcb_true; + } + return pcb_false; +} + +static int IsectJ_Rule(char p, pcb_vnode_t * v, DIRECTION * cdir) +{ + assert(*cdir == FORW); + return (v->Flags.status == INSIDE || v->Flags.status == SHARED); +} + +static int UniteJ_Rule(char p, pcb_vnode_t * v, DIRECTION * cdir) +{ + assert(*cdir == FORW); + return (v->Flags.status == OUTSIDE || v->Flags.status == SHARED); +} + +static int XorJ_Rule(char p, pcb_vnode_t * v, DIRECTION * cdir) +{ + if (v->Flags.status == INSIDE) { + *cdir = BACKW; + return pcb_true; + } + if (v->Flags.status == OUTSIDE) { + *cdir = FORW; + return pcb_true; + } + return pcb_false; +} + +static int SubJ_Rule(char p, pcb_vnode_t * v, DIRECTION * cdir) +{ + if (p == 'B' && v->Flags.status == INSIDE) { + *cdir = BACKW; + return pcb_true; + } + if (p == 'A' && v->Flags.status == OUTSIDE) { + *cdir = FORW; + return pcb_true; + } + if (v->Flags.status == SHARED2) { + if (p == 'A') + *cdir = FORW; + else + *cdir = BACKW; + return pcb_true; + } + return pcb_false; +} + +/* return the edge that comes next. + * if the direction is BACKW, then we return the next vertex + * so that prev vertex has the flags for the edge + * + * returns pcb_true if an edge is found, pcb_false otherwise + */ +static int jump(pcb_vnode_t ** cur, DIRECTION * cdir, J_Rule rule) +{ + pcb_cvc_list_t *d, *start; + pcb_vnode_t *e; + DIRECTION newone; + + if (!(*cur)->cvc_prev) { /* not a cross-vertex */ + if (*cdir == FORW ? (*cur)->Flags.mark : (*cur)->prev->Flags.mark) + return pcb_false; + return pcb_true; + } +#ifdef DEBUG_JUMP + DEBUGP("jump entering node at %$mD\n", (*cur)->point[0], (*cur)->point[1]); +#endif + if (*cdir == FORW) + d = (*cur)->cvc_prev->prev; + else + d = (*cur)->cvc_next->prev; + start = d; + do { + e = d->parent; + if (d->side == 'P') + e = e->prev; + newone = *cdir; + if (!e->Flags.mark && rule(d->poly, e, &newone)) { + if ((d->side == 'N' && newone == FORW) || (d->side == 'P' && newone == BACKW)) { +#ifdef DEBUG_JUMP + if (newone == FORW) + DEBUGP("jump leaving node at %#mD\n", e->next->point[0], e->next->point[1]); + else + DEBUGP("jump leaving node at %#mD\n", e->point[0], e->point[1]); +#endif + *cur = d->parent; + *cdir = newone; + return pcb_true; + } + } + } + while ((d = d->prev) != start); + return pcb_false; +} + +static int Gather(pcb_vnode_t * start, pcb_pline_t ** result, J_Rule v_rule, DIRECTION initdir) +{ + pcb_vnode_t *cur = start, *newn; + DIRECTION dir = initdir; +#ifdef DEBUG_GATHER + DEBUGP("gather direction = %d\n", dir); +#endif + assert(*result == NULL); + do { + /* see where to go next */ + if (!jump(&cur, &dir, v_rule)) + break; + /* add edge to polygon */ + if (!*result) { + *result = pcb_poly_contour_new(cur->point); + if (*result == NULL) + return pcb_err_no_memory; + } + else { + if ((newn = pcb_poly_node_create(cur->point)) == NULL) + return pcb_err_no_memory; + pcb_poly_vertex_include((*result)->head.prev, newn); + } +#ifdef DEBUG_GATHER + DEBUGP("gather vertex at %#mD\n", cur->point[0], cur->point[1]); +#endif + /* Now mark the edge as included. */ + newn = (dir == FORW ? cur : cur->prev); + newn->Flags.mark = 1; + /* for SHARED edge mark both */ + if (newn->shared) + newn->shared->Flags.mark = 1; + + /* Advance to the next edge. */ + cur = (dir == FORW ? cur->next : cur->prev); + } + while (1); + return pcb_err_ok; +} /* Gather */ + +static void Collect1(jmp_buf * e, pcb_vnode_t * cur, DIRECTION dir, pcb_polyarea_t ** contours, pcb_pline_t ** holes, J_Rule j_rule) +{ + pcb_pline_t *p = NULL; /* start making contour */ + int errc = pcb_err_ok; + if ((errc = Gather(dir == FORW ? cur : cur->next, &p, j_rule, dir)) != pcb_err_ok) { + if (p != NULL) + pcb_poly_contour_del(&p); + error(errc); + } + if (!p) + return; + pcb_poly_contour_pre(p, pcb_true); + if (p->Count > 2) { +#ifdef DEBUG_GATHER + DEBUGP("adding contour with %d vertices and direction %c\n", p->Count, p->Flags.orient ? 'F' : 'B'); +#endif + PutContour(e, p, contours, holes, NULL, NULL, NULL); + } + else { + /* some sort of computation error ? */ +#ifdef DEBUG_GATHER + DEBUGP("Bad contour! Not enough points!!\n"); +#endif + pcb_poly_contour_del(&p); + } +} + +static void Collect(jmp_buf * e, pcb_pline_t * a, pcb_polyarea_t ** contours, pcb_pline_t ** holes, S_Rule s_rule, J_Rule j_rule) +{ + pcb_vnode_t *cur, *other; + DIRECTION dir; + + cur = &a->head; + do { + if (s_rule(cur, &dir) && cur->Flags.mark == 0) + Collect1(e, cur, dir, contours, holes, j_rule); + other = cur; + if ((other->cvc_prev && jump(&other, &dir, j_rule))) + Collect1(e, other, dir, contours, holes, j_rule); + } + while ((cur = cur->next) != &a->head); +} /* Collect */ + + +static int +cntr_Collect(jmp_buf * e, pcb_pline_t ** A, pcb_polyarea_t ** contours, pcb_pline_t ** holes, + int action, pcb_polyarea_t * owner, pcb_polyarea_t * parent, pcb_pline_t * parent_contour) +{ + pcb_pline_t *tmprev; + + if ((*A)->Flags.status == ISECTED) { + switch (action) { + case PCB_PBO_UNITE: + Collect(e, *A, contours, holes, UniteS_Rule, UniteJ_Rule); + break; + case PCB_PBO_ISECT: + Collect(e, *A, contours, holes, IsectS_Rule, IsectJ_Rule); + break; + case PCB_PBO_XOR: + Collect(e, *A, contours, holes, XorS_Rule, XorJ_Rule); + break; + case PCB_PBO_SUB: + Collect(e, *A, contours, holes, SubS_Rule, SubJ_Rule); + break; + }; + } + else { + switch (action) { + case PCB_PBO_ISECT: + if ((*A)->Flags.status == INSIDE) { + tmprev = *A; + /* disappear this contour (rtree entry removed in PutContour) */ + *A = tmprev->next; + tmprev->next = NULL; + PutContour(e, tmprev, contours, holes, owner, NULL, NULL); + return pcb_true; + } + break; + case PCB_PBO_XOR: + if ((*A)->Flags.status == INSIDE) { + tmprev = *A; + /* disappear this contour (rtree entry removed in PutContour) */ + *A = tmprev->next; + tmprev->next = NULL; + pcb_poly_contour_inv(tmprev); + PutContour(e, tmprev, contours, holes, owner, NULL, NULL); + return pcb_true; + } + /* break; *//* Fall through (I think this is correct! pcjc2) */ + case PCB_PBO_UNITE: + case PCB_PBO_SUB: + if ((*A)->Flags.status == OUTSIDE) { + tmprev = *A; + /* disappear this contour (rtree entry removed in PutContour) */ + *A = tmprev->next; + tmprev->next = NULL; + PutContour(e, tmprev, contours, holes, owner, parent, parent_contour); + return pcb_true; + } + break; + } + } + return pcb_false; +} /* cntr_Collect */ + +static void M_B_AREA_Collect(jmp_buf * e, pcb_polyarea_t * bfst, pcb_polyarea_t ** contours, pcb_pline_t ** holes, int action) +{ + pcb_polyarea_t *b = bfst; + pcb_pline_t **cur, **next, *tmp; + + assert(b != NULL); + do { + for (cur = &b->contours; *cur != NULL; cur = next) { + next = &((*cur)->next); + if ((*cur)->Flags.status == ISECTED) + continue; + + if ((*cur)->Flags.status == INSIDE) + switch (action) { + case PCB_PBO_XOR: + case PCB_PBO_SUB: + pcb_poly_contour_inv(*cur); + case PCB_PBO_ISECT: + tmp = *cur; + *cur = tmp->next; + next = cur; + tmp->next = NULL; + tmp->Flags.status = UNKNWN; + PutContour(e, tmp, contours, holes, b, NULL, NULL); + break; + case PCB_PBO_UNITE: + break; /* nothing to do - already included */ + } + else if ((*cur)->Flags.status == OUTSIDE) + switch (action) { + case PCB_PBO_XOR: + case PCB_PBO_UNITE: + /* include */ + tmp = *cur; + *cur = tmp->next; + next = cur; + tmp->next = NULL; + tmp->Flags.status = UNKNWN; + PutContour(e, tmp, contours, holes, b, NULL, NULL); + break; + case PCB_PBO_ISECT: + case PCB_PBO_SUB: + break; /* do nothing, not included */ + } + } + } + while ((b = b->f) != bfst); +} + + +static inline int contour_is_first(pcb_polyarea_t * a, pcb_pline_t * cur) +{ + return (a->contours == cur); +} + + +static inline int contour_is_last(pcb_pline_t * cur) +{ + return (cur->next == NULL); +} + + +static inline void remove_polyarea(pcb_polyarea_t ** list, pcb_polyarea_t * piece) +{ + /* If this item was the start of the list, advance that pointer */ + if (*list == piece) + *list = (*list)->f; + + /* But reset it to NULL if it wraps around and hits us again */ + if (*list == piece) + *list = NULL; + + piece->b->f = piece->f; + piece->f->b = piece->b; + piece->f = piece->b = piece; +} + +static void M_pcb_polyarea_separate_isected(jmp_buf * e, pcb_polyarea_t ** pieces, pcb_pline_t ** holes, pcb_pline_t ** isected) +{ + pcb_polyarea_t *a = *pieces; + pcb_polyarea_t *anext; + pcb_pline_t *curc, *next, *prev; + int finished; + + if (a == NULL) + return; + + /* TODO: STASH ENOUGH INFORMATION EARLIER ON, SO WE CAN REMOVE THE INTERSECTED + CONTOURS WITHOUT HAVING TO WALK THE FULL DATA-STRUCTURE LOOKING FOR THEM. */ + + do { + int hole_contour = 0; + int is_outline = 1; + + anext = a->f; + finished = (anext == *pieces); + + prev = NULL; + for (curc = a->contours; curc != NULL; curc = next, is_outline = 0) { + int is_first = contour_is_first(a, curc); + int is_last = contour_is_last(curc); + int isect_contour = (curc->Flags.status == ISECTED); + + next = curc->next; + + if (isect_contour || hole_contour) { + + /* Reset the intersection flags, since we keep these pieces */ + if (curc->Flags.status != ISECTED) + curc->Flags.status = UNKNWN; + + remove_contour(a, prev, curc, !(is_first && is_last)); + + if (isect_contour) { + /* Link into the list of intersected contours */ + curc->next = *isected; + *isected = curc; + } + else if (hole_contour) { + /* Link into the list of holes */ + curc->next = *holes; + *holes = curc; + } + else { + assert(0); + } + + if (is_first && is_last) { + remove_polyarea(pieces, a); + pcb_polyarea_free(&a); /* NB: Sets a to NULL */ + } + + } + else { + /* Note the item we just didn't delete as the next + candidate for having its "next" pointer adjusted. + Saves walking the contour list when we delete one. */ + prev = curc; + } + + /* If we move or delete an outer contour, we need to move any holes + we wish to keep within that contour to the holes list. */ + if (is_outline && isect_contour) + hole_contour = 1; + + } + + /* If we deleted all the pieces of the polyarea, *pieces is NULL */ + } + while ((a = anext), *pieces != NULL && !finished); +} + + +struct find_inside_m_pa_info { + jmp_buf jb; + pcb_polyarea_t *want_inside; + pcb_pline_t *result; +}; + +static pcb_r_dir_t find_inside_m_pa(const pcb_box_t * b, void *cl) +{ + struct find_inside_m_pa_info *info = (struct find_inside_m_pa_info *) cl; + pcb_pline_t *check = (pcb_pline_t *) b; + /* Don't report for the main contour */ + if (check->Flags.orient == PCB_PLF_DIR) + return PCB_R_DIR_NOT_FOUND; + /* Don't look at contours marked as being intersected */ + if (check->Flags.status == ISECTED) + return PCB_R_DIR_NOT_FOUND; + if (cntr_in_M_pcb_polyarea_t(check, info->want_inside, pcb_false)) { + info->result = check; + longjmp(info->jb, 1); + } + return PCB_R_DIR_NOT_FOUND; +} + + +static void M_pcb_polyarea_t_update_primary(jmp_buf * e, pcb_polyarea_t ** pieces, pcb_pline_t ** holes, int action, pcb_polyarea_t * bpa) +{ + pcb_polyarea_t *a = *pieces; + pcb_polyarea_t *b; + pcb_polyarea_t *anext; + pcb_pline_t *curc, *next, *prev; + pcb_box_t box; + /* int inv_inside = 0; */ + int del_inside = 0; + int del_outside = 0; + int finished; + + if (a == NULL) + return; + + switch (action) { + case PCB_PBO_ISECT: + del_outside = 1; + break; + case PCB_PBO_UNITE: + case PCB_PBO_SUB: + del_inside = 1; + break; + case PCB_PBO_XOR: /* NOT IMPLEMENTED OR USED */ + /* inv_inside = 1; */ + assert(0); + break; + } + + box = *((pcb_box_t *) bpa->contours); + b = bpa; + while ((b = b->f) != bpa) { + pcb_box_t *b_box = (pcb_box_t *) b->contours; + PCB_MAKE_MIN(box.X1, b_box->X1); + PCB_MAKE_MIN(box.Y1, b_box->Y1); + PCB_MAKE_MAX(box.X2, b_box->X2); + PCB_MAKE_MAX(box.Y2, b_box->Y2); + } + + if (del_inside) { + + do { + anext = a->f; + finished = (anext == *pieces); + + /* Test the outer contour first, as we may need to remove all children */ + + /* We've not yet split intersected contours out, just ignore them */ + if (a->contours->Flags.status != ISECTED && + /* Pre-filter on bounding box */ + ((a->contours->xmin >= box.X1) && (a->contours->ymin >= box.Y1) + && (a->contours->xmax <= box.X2) + && (a->contours->ymax <= box.Y2)) && + /* Then test properly */ + cntr_in_M_pcb_polyarea_t(a->contours, bpa, pcb_false)) { + + /* Delete this contour, all children -> holes queue */ + + /* Delete the outer contour */ + curc = a->contours; + remove_contour(a, NULL, curc, pcb_false); /* Rtree deleted in poly_Free below */ + /* a->contours now points to the remaining holes */ + pcb_poly_contour_del(&curc); + + if (a->contours != NULL) { + /* Find the end of the list of holes */ + curc = a->contours; + while (curc->next != NULL) + curc = curc->next; + + /* Take the holes and prepend to the holes queue */ + curc->next = *holes; + *holes = a->contours; + a->contours = NULL; + } + + remove_polyarea(pieces, a); + pcb_polyarea_free(&a); /* NB: Sets a to NULL */ + + continue; + } + + /* Loop whilst we find INSIDE contours to delete */ + while (1) { + struct find_inside_m_pa_info info; + pcb_pline_t *prev; + + info.want_inside = bpa; + + /* Set jump return */ + if (setjmp(info.jb)) { + /* Returned here! */ + } + else { + info.result = NULL; + /* r-tree search, calling back a routine to longjmp back with + * data about any hole inside the B polygon. + * NB: Does not jump back to report the main contour! + */ + pcb_r_search(a->contour_tree, &box, NULL, find_inside_m_pa, &info, NULL); + + /* Nothing found? */ + break; + } + + /* We need to find the contour before it, so we can update its next pointer */ + prev = a->contours; + while (prev->next != info.result) { + prev = prev->next; + } + + /* Remove hole from the contour */ + remove_contour(a, prev, info.result, pcb_true); + pcb_poly_contour_del(&info.result); + } + /* End check for deleted holes */ + + /* If we deleted all the pieces of the polyarea, *pieces is NULL */ + } + while ((a = anext), *pieces != NULL && !finished); + + return; + } + else { + /* This path isn't optimised for speed */ + } + + do { + int hole_contour = 0; + int is_outline = 1; + + anext = a->f; + finished = (anext == *pieces); + + prev = NULL; + for (curc = a->contours; curc != NULL; curc = next, is_outline = 0) { + int is_first = contour_is_first(a, curc); + int is_last = contour_is_last(curc); + int del_contour = 0; + + next = curc->next; + + if (del_outside) + del_contour = curc->Flags.status != ISECTED && !cntr_in_M_pcb_polyarea_t(curc, bpa, pcb_false); + + /* Skip intersected contours */ + if (curc->Flags.status == ISECTED) { + prev = curc; + continue; + } + + /* Reset the intersection flags, since we keep these pieces */ + curc->Flags.status = UNKNWN; + + if (del_contour || hole_contour) { + + remove_contour(a, prev, curc, !(is_first && is_last)); + + if (del_contour) { + /* Delete the contour */ + pcb_poly_contour_del(&curc); /* NB: Sets curc to NULL */ + } + else if (hole_contour) { + /* Link into the list of holes */ + curc->next = *holes; + *holes = curc; + } + else { + assert(0); + } + + if (is_first && is_last) { + remove_polyarea(pieces, a); + pcb_polyarea_free(&a); /* NB: Sets a to NULL */ + } + + } + else { + /* Note the item we just didn't delete as the next + candidate for having its "next" pointer adjusted. + Saves walking the contour list when we delete one. */ + prev = curc; + } + + /* If we move or delete an outer contour, we need to move any holes + we wish to keep within that contour to the holes list. */ + if (is_outline && del_contour) + hole_contour = 1; + + } + + /* If we deleted all the pieces of the polyarea, *pieces is NULL */ + } + while ((a = anext), *pieces != NULL && !finished); +} + +static void +M_pcb_polyarea_t_Collect_separated(jmp_buf * e, pcb_pline_t * afst, pcb_polyarea_t ** contours, pcb_pline_t ** holes, int action, pcb_bool maybe) +{ + pcb_pline_t **cur, **next; + + for (cur = &afst; *cur != NULL; cur = next) { + next = &((*cur)->next); + /* if we disappear a contour, don't advance twice */ + if (cntr_Collect(e, cur, contours, holes, action, NULL, NULL, NULL)) + next = cur; + } +} + +static void M_pcb_polyarea_t_Collect(jmp_buf * e, pcb_polyarea_t * afst, pcb_polyarea_t ** contours, pcb_pline_t ** holes, int action, pcb_bool maybe) +{ + pcb_polyarea_t *a = afst; + pcb_polyarea_t *parent = NULL; /* Quiet compiler warning */ + pcb_pline_t **cur, **next, *parent_contour; + + assert(a != NULL); + while ((a = a->f) != afst); + /* now the non-intersect parts are collected in temp/holes */ + do { + if (maybe && a->contours->Flags.status != ISECTED) + parent_contour = a->contours; + else + parent_contour = NULL; + + /* Take care of the first contour - so we know if we + * can shortcut reparenting some of its children + */ + cur = &a->contours; + if (*cur != NULL) { + next = &((*cur)->next); + /* if we disappear a contour, don't advance twice */ + if (cntr_Collect(e, cur, contours, holes, action, a, NULL, NULL)) { + parent = (*contours)->b; /* InsCntr inserts behind the head */ + next = cur; + } + else + parent = a; + cur = next; + } + for (; *cur != NULL; cur = next) { + next = &((*cur)->next); + /* if we disappear a contour, don't advance twice */ + if (cntr_Collect(e, cur, contours, holes, action, a, parent, parent_contour)) + next = cur; + } + } + while ((a = a->f) != afst); +} + +/* determine if two polygons touch or overlap */ +pcb_bool pcb_polyarea_touching(pcb_polyarea_t * a, pcb_polyarea_t * b) +{ + jmp_buf e; + int code; + + if ((code = setjmp(e)) == 0) { +#ifdef DEBUG + if (!pcb_poly_valid(a)) + return -1; + if (!pcb_poly_valid(b)) + return -1; +#endif + M_pcb_polyarea_t_intersect(&e, a, b, pcb_false); + + if (M_pcb_polyarea_t_label(a, b, pcb_true)) + return pcb_true; + if (M_pcb_polyarea_t_label(b, a, pcb_true)) + return pcb_true; + } + else if (code == TOUCHES) + return pcb_true; + return pcb_false; +} + +/* the main clipping routines */ +int pcb_polyarea_boolean(const pcb_polyarea_t * a_org, const pcb_polyarea_t * b_org, pcb_polyarea_t ** res, int action) +{ + pcb_polyarea_t *a = NULL, *b = NULL; + + if (!pcb_polyarea_m_copy0(&a, a_org) || !pcb_polyarea_m_copy0(&b, b_org)) + return pcb_err_no_memory; + + return pcb_polyarea_boolean_free(a, b, res, action); +} /* poly_Boolean */ + +/* just like poly_Boolean but frees the input polys */ +int pcb_polyarea_boolean_free(pcb_polyarea_t * ai, pcb_polyarea_t * bi, pcb_polyarea_t ** res, int action) +{ + pcb_polyarea_t *a = ai, *b = bi; + pcb_pline_t *a_isected = NULL; + pcb_pline_t *p, *holes = NULL; + jmp_buf e; + int code; + + *res = NULL; + + if (!a) { + switch (action) { + case PCB_PBO_XOR: + case PCB_PBO_UNITE: + *res = bi; + return pcb_err_ok; + case PCB_PBO_SUB: + case PCB_PBO_ISECT: + if (b != NULL) + pcb_polyarea_free(&b); + return pcb_err_ok; + } + } + if (!b) { + switch (action) { + case PCB_PBO_SUB: + case PCB_PBO_XOR: + case PCB_PBO_UNITE: + *res = ai; + return pcb_err_ok; + case PCB_PBO_ISECT: + if (a != NULL) + pcb_polyarea_free(&a); + return pcb_err_ok; + } + } + + if ((code = setjmp(e)) == 0) { +#ifdef DEBUG + assert(pcb_poly_valid(a)); + assert(pcb_poly_valid(b)); +#endif + + /* intersect needs to make a list of the contours in a and b which are intersected */ + M_pcb_polyarea_t_intersect(&e, a, b, pcb_true); + + /* We could speed things up a lot here if we only processed the relevant contours */ + /* NB: Relevant parts of a are labeled below */ + M_pcb_polyarea_t_label(b, a, pcb_false); + + *res = a; + M_pcb_polyarea_t_update_primary(&e, res, &holes, action, b); + M_pcb_polyarea_separate_isected(&e, res, &holes, &a_isected); + M_pcb_polyarea_t_label_separated(a_isected, b, pcb_false); + M_pcb_polyarea_t_Collect_separated(&e, a_isected, res, &holes, action, pcb_false); + M_B_AREA_Collect(&e, b, res, &holes, action); + pcb_polyarea_free(&b); + + /* free a_isected */ + while ((p = a_isected) != NULL) { + a_isected = p->next; + pcb_poly_contour_del(&p); + } + + pcb_poly_insert_holes(&e, *res, &holes); + } + /* delete holes if any left */ + while ((p = holes) != NULL) { + holes = p->next; + pcb_poly_contour_del(&p); + } + + if (code) { + pcb_polyarea_free(res); + return code; + } + assert(!*res || pcb_poly_valid(*res)); + return code; +} /* poly_Boolean_free */ + +static void clear_marks(pcb_polyarea_t * p) +{ + pcb_polyarea_t *n = p; + pcb_pline_t *c; + pcb_vnode_t *v; + + do { + for (c = n->contours; c; c = c->next) { + v = &c->head; + do { + v->Flags.mark = 0; + } + while ((v = v->next) != &c->head); + } + } + while ((n = n->f) != p); +} + +/* compute the intersection and subtraction (divides "a" into two pieces) + * and frees the input polys. This assumes that bi is a single simple polygon. + */ +int pcb_polyarea_and_subtract_free(pcb_polyarea_t * ai, pcb_polyarea_t * bi, pcb_polyarea_t ** aandb, pcb_polyarea_t ** aminusb) +{ + pcb_polyarea_t *a = ai, *b = bi; + pcb_pline_t *p, *holes = NULL; + jmp_buf e; + int code; + + *aandb = NULL; + *aminusb = NULL; + + if ((code = setjmp(e)) == 0) { + +#ifdef DEBUG + if (!pcb_poly_valid(a)) + return -1; + if (!pcb_poly_valid(b)) + return -1; +#endif + M_pcb_polyarea_t_intersect(&e, a, b, pcb_true); + + M_pcb_polyarea_t_label(a, b, pcb_false); + M_pcb_polyarea_t_label(b, a, pcb_false); + + M_pcb_polyarea_t_Collect(&e, a, aandb, &holes, PCB_PBO_ISECT, pcb_false); + pcb_poly_insert_holes(&e, *aandb, &holes); + assert(pcb_poly_valid(*aandb)); + /* delete holes if any left */ + while ((p = holes) != NULL) { + holes = p->next; + pcb_poly_contour_del(&p); + } + holes = NULL; + clear_marks(a); + clear_marks(b); + M_pcb_polyarea_t_Collect(&e, a, aminusb, &holes, PCB_PBO_SUB, pcb_false); + pcb_poly_insert_holes(&e, *aminusb, &holes); + pcb_polyarea_free(&a); + pcb_polyarea_free(&b); + assert(pcb_poly_valid(*aminusb)); + } + /* delete holes if any left */ + while ((p = holes) != NULL) { + holes = p->next; + pcb_poly_contour_del(&p); + } + + + if (code) { + pcb_polyarea_free(aandb); + pcb_polyarea_free(aminusb); + return code; + } + assert(!*aandb || pcb_poly_valid(*aandb)); + assert(!*aminusb || pcb_poly_valid(*aminusb)); + return code; +} /* poly_AndSubtract_free */ + +static inline int cntrbox_pointin(pcb_pline_t * c, pcb_vector_t p) +{ + return (p[0] >= c->xmin && p[1] >= c->ymin && p[0] <= c->xmax && p[1] <= c->ymax); + +} + +static inline int node_neighbours(pcb_vnode_t * a, pcb_vnode_t * b) +{ + return (a == b) || (a->next == b) || (b->next == a) || (a->next == b->next); +} + +pcb_vnode_t *pcb_poly_node_create(pcb_vector_t v) +{ + pcb_vnode_t *res; + pcb_coord_t *c; + + assert(v); + res = (pcb_vnode_t *) calloc(1, sizeof(pcb_vnode_t)); + if (res == NULL) + return NULL; + /* bzero (res, sizeof (pcb_vnode_t) - sizeof(pcb_vector_t)); */ + c = res->point; + *c++ = *v++; + *c = *v; + return res; +} + +void pcb_poly_contour_init(pcb_pline_t * c) +{ + if (c == NULL) + return; + /* bzero (c, sizeof(pcb_pline_t)); */ + c->head.next = c->head.prev = &c->head; + c->xmin = c->ymin = COORD_MAX; + c->xmax = c->ymax = -COORD_MAX-1; + c->is_round = pcb_false; + c->cx = 0; + c->cy = 0; + c->radius = 0; +} + +pcb_pline_t *pcb_poly_contour_new(pcb_vector_t v) +{ + pcb_pline_t *res; + + res = (pcb_pline_t *) calloc(1, sizeof(pcb_pline_t)); + if (res == NULL) + return NULL; + + pcb_poly_contour_init(res); + + if (v != NULL) { + Vcopy(res->head.point, v); + cntrbox_adjust(res, v); + } + + return res; +} + +void pcb_poly_contour_clear(pcb_pline_t * c) +{ + pcb_vnode_t *cur; + + assert(c != NULL); + while ((cur = c->head.next) != &c->head) { + pcb_poly_vertex_exclude(cur); + free(cur); + } + pcb_poly_contour_init(c); +} + +void pcb_poly_contour_del(pcb_pline_t ** c) +{ + pcb_vnode_t *cur, *prev; + + if (*c == NULL) + return; + for (cur = (*c)->head.prev; cur != &(*c)->head; cur = prev) { + prev = cur->prev; + if (cur->cvc_next != NULL) { + free(cur->cvc_next); + free(cur->cvc_prev); + } + free(cur); + } + if ((*c)->head.cvc_next != NULL) { + free((*c)->head.cvc_next); + free((*c)->head.cvc_prev); + } + /* FIXME -- strict aliasing violation. */ + if ((*c)->tree) { + pcb_rtree_t *r = (*c)->tree; + pcb_r_free_tree_data(r, free); + pcb_r_destroy_tree(&r); + } + free(*c), *c = NULL; +} + +void pcb_poly_contour_pre(pcb_pline_t * C, pcb_bool optimize) +{ + double area = 0; + pcb_vnode_t *p, *c; + pcb_vector_t p1, p2; + + assert(C != NULL); + + if (optimize) { + for (c = (p = &C->head)->next; c != &C->head; c = (p = c)->next) { + /* if the previous node is on the same line with this one, we should remove it */ + Vsub2(p1, c->point, p->point); + Vsub2(p2, c->next->point, c->point); + /* If the product below is zero then + * the points on either side of c + * are on the same line! + * So, remove the point c + */ + + if (pcb_vect_det2(p1, p2) == 0) { + pcb_poly_vertex_exclude(c); + free(c); + c = p; + } + } + } + C->Count = 0; + C->xmin = C->xmax = C->head.point[0]; + C->ymin = C->ymax = C->head.point[1]; + + p = (c = &C->head)->prev; + if (c != p) { + do { + /* calculate area for orientation */ + area += (double) (p->point[0] - c->point[0]) * (p->point[1] + c->point[1]); + cntrbox_adjust(C, c->point); + C->Count++; + } + while ((c = (p = c)->next) != &C->head); + } + C->area = PCB_ABS(area); + if (C->Count > 2) + C->Flags.orient = ((area < 0) ? PCB_PLF_INV : PCB_PLF_DIR); + C->tree = (pcb_rtree_t *) make_edge_tree(C); +} /* poly_PreContour */ + +static pcb_r_dir_t flip_cb(const pcb_box_t * b, void *cl) +{ + struct seg *s = (struct seg *) b; + s->v = s->v->prev; + return PCB_R_DIR_FOUND_CONTINUE; +} + +void pcb_poly_contour_inv(pcb_pline_t * c) +{ + pcb_vnode_t *cur, *next; + int r; + + assert(c != NULL); + cur = &c->head; + do { + next = cur->next; + cur->next = cur->prev; + cur->prev = next; + /* fix the segment tree */ + } + while ((cur = next) != &c->head); + c->Flags.orient ^= 1; + if (c->tree) { + pcb_r_search(c->tree, NULL, NULL, flip_cb, NULL, &r); + assert(r == c->Count); + } +} + +void pcb_poly_vertex_exclude(pcb_vnode_t * node) +{ + assert(node != NULL); + if (node->cvc_next) { + free(node->cvc_next); + free(node->cvc_prev); + } + node->prev->next = node->next; + node->next->prev = node->prev; +} + +void pcb_poly_vertex_include(pcb_vnode_t * after, pcb_vnode_t * node) +{ + double a, b; + assert(after != NULL); + assert(node != NULL); + + node->prev = after; + node->next = after->next; + after->next = after->next->prev = node; + /* remove points on same line */ + if (node->prev->prev == node) + return; /* we don't have 3 points in the poly yet */ + a = (node->point[1] - node->prev->prev->point[1]); + a *= (node->prev->point[0] - node->prev->prev->point[0]); + b = (node->point[0] - node->prev->prev->point[0]); + b *= (node->prev->point[1] - node->prev->prev->point[1]); + if (fabs(a - b) < EPSILON) { + pcb_vnode_t *t = node->prev; + t->prev->next = node; + node->prev = t->prev; + free(t); + } +} + +pcb_bool pcb_poly_contour_copy(pcb_pline_t ** dst, pcb_pline_t * src) +{ + pcb_vnode_t *cur, *newnode; + + assert(src != NULL); + *dst = NULL; + *dst = pcb_poly_contour_new(src->head.point); + if (*dst == NULL) + return pcb_false; + + (*dst)->Count = src->Count; + (*dst)->Flags.orient = src->Flags.orient; + (*dst)->xmin = src->xmin, (*dst)->xmax = src->xmax; + (*dst)->ymin = src->ymin, (*dst)->ymax = src->ymax; + (*dst)->area = src->area; + + for (cur = src->head.next; cur != &src->head; cur = cur->next) { + if ((newnode = pcb_poly_node_create(cur->point)) == NULL) + return pcb_false; + /* newnode->Flags = cur->Flags; */ + pcb_poly_vertex_include((*dst)->head.prev, newnode); + } + (*dst)->tree = (pcb_rtree_t *) make_edge_tree(*dst); + return pcb_true; +} + +/**********************************************************************/ +/* polygon routines */ + +pcb_bool pcb_polyarea_copy0(pcb_polyarea_t ** dst, const pcb_polyarea_t * src) +{ + *dst = NULL; + if (src != NULL) + *dst = (pcb_polyarea_t *) calloc(1, sizeof(pcb_polyarea_t)); + if (*dst == NULL) + return pcb_false; + (*dst)->contour_tree = pcb_r_create_tree(); + + return pcb_polyarea_copy1(*dst, src); +} + +pcb_bool pcb_polyarea_copy1(pcb_polyarea_t * dst, const pcb_polyarea_t * src) +{ + pcb_pline_t *cur, **last = &dst->contours; + + *last = NULL; + dst->f = dst->b = dst; + + for (cur = src->contours; cur != NULL; cur = cur->next) { + if (!pcb_poly_contour_copy(last, cur)) + return pcb_false; + pcb_r_insert_entry(dst->contour_tree, (pcb_box_t *) * last); + last = &(*last)->next; + } + return pcb_true; +} + +void pcb_polyarea_m_include(pcb_polyarea_t ** list, pcb_polyarea_t * a) +{ + if (*list == NULL) + a->f = a->b = a, *list = a; + else { + a->f = *list; + a->b = (*list)->b; + (*list)->b = (*list)->b->f = a; + } +} + +pcb_bool pcb_polyarea_m_copy0(pcb_polyarea_t ** dst, const pcb_polyarea_t * srcfst) +{ + const pcb_polyarea_t *src = srcfst; + pcb_polyarea_t *di; + + *dst = NULL; + if (src == NULL) + return pcb_false; + do { + if ((di = pcb_polyarea_create()) == NULL || !pcb_polyarea_copy1(di, src)) + return pcb_false; + pcb_polyarea_m_include(dst, di); + } + while ((src = src->f) != srcfst); + return pcb_true; +} + +pcb_bool pcb_polyarea_contour_include(pcb_polyarea_t * p, pcb_pline_t * c) +{ + pcb_pline_t *tmp; + + if ((c == NULL) || (p == NULL)) + return pcb_false; + if (c->Flags.orient == PCB_PLF_DIR) { + if (p->contours != NULL) + return pcb_false; + p->contours = c; + } + else { + if (p->contours == NULL) + return pcb_false; + /* link at front of hole list */ + tmp = p->contours->next; + p->contours->next = c; + c->next = tmp; + } + pcb_r_insert_entry(p->contour_tree, (pcb_box_t *) c); + return pcb_true; +} + +typedef struct pip { + int f; + pcb_vector_t p; + jmp_buf env; +} pip; + + +static pcb_r_dir_t crossing(const pcb_box_t * b, void *cl) +{ + struct seg *s = (struct seg *) b; + struct pip *p = (struct pip *) cl; + + if (s->v->point[1] <= p->p[1]) { + if (s->v->next->point[1] > p->p[1]) { + pcb_vector_t v1, v2; + pcb_long64_t cross; + Vsub2(v1, s->v->next->point, s->v->point); + Vsub2(v2, p->p, s->v->point); + cross = (pcb_long64_t) v1[0] * v2[1] - (pcb_long64_t) v2[0] * v1[1]; + if (cross == 0) { + p->f = 1; + longjmp(p->env, 1); + } + if (cross > 0) + p->f += 1; + } + } + else { + if (s->v->next->point[1] <= p->p[1]) { + pcb_vector_t v1, v2; + pcb_long64_t cross; + Vsub2(v1, s->v->next->point, s->v->point); + Vsub2(v2, p->p, s->v->point); + cross = (pcb_long64_t) v1[0] * v2[1] - (pcb_long64_t) v2[0] * v1[1]; + if (cross == 0) { + p->f = 1; + longjmp(p->env, 1); + } + if (cross < 0) + p->f -= 1; + } + } + return PCB_R_DIR_FOUND_CONTINUE; +} + +int pcb_poly_contour_inside(pcb_pline_t * c, pcb_vector_t p) +{ + struct pip info; + pcb_box_t ray; + + if (!cntrbox_pointin(c, p)) + return pcb_false; + info.f = 0; + info.p[0] = ray.X1 = p[0]; + info.p[1] = ray.Y1 = p[1]; + ray.X2 = COORD_MAX; + ray.Y2 = p[1] + 1; + if (setjmp(info.env) == 0) + pcb_r_search(c->tree, &ray, NULL, crossing, &info, NULL); + return info.f; +} + +pcb_bool pcb_polyarea_contour_inside(pcb_polyarea_t * p, pcb_vector_t v0) +{ + pcb_pline_t *cur; + + if ((p == NULL) || (v0 == NULL) || (p->contours == NULL)) + return pcb_false; + cur = p->contours; + if (pcb_poly_contour_inside(cur, v0)) { + for (cur = cur->next; cur != NULL; cur = cur->next) + if (pcb_poly_contour_inside(cur, v0)) + return pcb_false; + return pcb_true; + } + return pcb_false; +} + +pcb_bool poly_M_CheckInside(pcb_polyarea_t * p, pcb_vector_t v0) +{ + pcb_polyarea_t *cur; + + if ((p == NULL) || (v0 == NULL)) + return pcb_false; + cur = p; + do { + if (pcb_polyarea_contour_inside(cur, v0)) + return pcb_true; + } + while ((cur = cur->f) != p); + return pcb_false; +} + +static double dot(pcb_vector_t A, pcb_vector_t B) +{ + return (double) A[0] * (double) B[0] + (double) A[1] * (double) B[1]; +} + +/* Compute whether point is inside a triangle formed by 3 other points */ +/* Algorithm from http://www.blackpawn.com/texts/pointinpoly/default.html */ +static int point_in_triangle(pcb_vector_t A, pcb_vector_t B, pcb_vector_t C, pcb_vector_t P) +{ + pcb_vector_t v0, v1, v2; + double dot00, dot01, dot02, dot11, dot12; + double invDenom; + double u, v; + + /* Compute vectors */ + v0[0] = C[0] - A[0]; + v0[1] = C[1] - A[1]; + v1[0] = B[0] - A[0]; + v1[1] = B[1] - A[1]; + v2[0] = P[0] - A[0]; + v2[1] = P[1] - A[1]; + + /* Compute dot products */ + dot00 = dot(v0, v0); + dot01 = dot(v0, v1); + dot02 = dot(v0, v2); + dot11 = dot(v1, v1); + dot12 = dot(v1, v2); + + /* Compute barycentric coordinates */ + invDenom = 1. / (dot00 * dot11 - dot01 * dot01); + u = (dot11 * dot02 - dot01 * dot12) * invDenom; + v = (dot00 * dot12 - dot01 * dot02) * invDenom; + + /* Check if point is in triangle */ + return (u > 0.0) && (v > 0.0) && (u + v < 1.0); +} + + +/* Returns the dot product of pcb_vector_t A->B, and a vector + * orthogonal to pcb_vector_t C->D. The result is not normalised, so will be + * weighted by the magnitude of the C->D vector. + */ +static double dot_orthogonal_to_direction(pcb_vector_t A, pcb_vector_t B, pcb_vector_t C, pcb_vector_t D) +{ + pcb_vector_t l1, l2, l3; + l1[0] = B[0] - A[0]; + l1[1] = B[1] - A[1]; + l2[0] = D[0] - C[0]; + l2[1] = D[1] - C[1]; + + l3[0] = -l2[1]; + l3[1] = l2[0]; + + return dot(l1, l3); +} + +/* Algorithm from http://www.exaflop.org/docs/cgafaq/cga2.html + * + * "Given a simple polygon, find some point inside it. Here is a method based + * on the proof that there exists an internal diagonal, in [O'Rourke, 13-14]. + * The idea is that the midpoint of a diagonal is interior to the polygon. + * + * 1. Identify a convex vertex v; let its adjacent vertices be a and b. + * 2. For each other vertex q do: + * 2a. If q is inside avb, compute distance to v (orthogonal to ab). + * 2b. Save point q if distance is a new min. + * 3. If no point is inside, return midpoint of ab, or centroid of avb. + * 4. Else if some point inside, qv is internal: return its midpoint." + * + * [O'Rourke]: Computational Geometry in C (2nd Ed.) + * Joseph O'Rourke, Cambridge University Press 1998, + * ISBN 0-521-64010-5 Pbk, ISBN 0-521-64976-5 Hbk + */ +static void poly_ComputeInteriorPoint(pcb_pline_t * poly, pcb_vector_t v) +{ + pcb_vnode_t *pt1, *pt2, *pt3, *q; + pcb_vnode_t *min_q = NULL; + double dist; + double min_dist = 0.0; + double dir = (poly->Flags.orient == PCB_PLF_DIR) ? 1. : -1; + + /* Find a convex node on the polygon */ + pt1 = &poly->head; + do { + double dot_product; + + pt2 = pt1->next; + pt3 = pt2->next; + + dot_product = dot_orthogonal_to_direction(pt1->point, pt2->point, pt3->point, pt2->point); + + if (dot_product * dir > 0.) + break; + } + while ((pt1 = pt1->next) != &poly->head); + + /* Loop over remaining vertices */ + q = pt3; + do { + /* Is current vertex "q" outside pt1 pt2 pt3 triangle? */ + if (!point_in_triangle(pt1->point, pt2->point, pt3->point, q->point)) + continue; + + /* NO: compute distance to pt2 (v) orthogonal to pt1 - pt3) */ + /* Record minimum */ + dist = dot_orthogonal_to_direction(q->point, pt2->point, pt1->point, pt3->point); + if (min_q == NULL || dist < min_dist) { + min_dist = dist; + min_q = q; + } + } + while ((q = q->next) != pt2); + + /* Were any "q" found inside pt1 pt2 pt3? */ + if (min_q == NULL) { + /* NOT FOUND: Return midpoint of pt1 pt3 */ + v[0] = (pt1->point[0] + pt3->point[0]) / 2; + v[1] = (pt1->point[1] + pt3->point[1]) / 2; + } + else { + /* FOUND: Return mid point of min_q, pt2 */ + v[0] = (pt2->point[0] + min_q->point[0]) / 2; + v[1] = (pt2->point[1] + min_q->point[1]) / 2; + } +} + + +/* NB: This function assumes the caller _knows_ the contours do not + * intersect. If the contours intersect, the result is undefined. + * It will return the correct result if the two contours share + * common points between their contours. (Identical contours + * are treated as being inside each other). + */ +int pcb_poly_contour_in_contour(pcb_pline_t * poly, pcb_pline_t * inner) +{ + pcb_vector_t point; + assert(poly != NULL); + assert(inner != NULL); + if (cntrbox_inside(inner, poly)) { + /* We need to prove the "inner" contour is not outside + * "poly" contour. If it is outside, we can return. + */ + if (!pcb_poly_contour_inside(poly, inner->head.point)) + return 0; + + poly_ComputeInteriorPoint(inner, point); + return pcb_poly_contour_inside(poly, point); + } + return 0; +} + +void pcb_polyarea_init(pcb_polyarea_t * p) +{ + p->f = p->b = p; + p->contours = NULL; + p->contour_tree = pcb_r_create_tree(); +} + +pcb_polyarea_t *pcb_polyarea_create(void) +{ + pcb_polyarea_t *res; + + if ((res = (pcb_polyarea_t *) malloc(sizeof(pcb_polyarea_t))) != NULL) + pcb_polyarea_init(res); + return res; +} + +void pcb_poly_contours_free(pcb_pline_t ** pline) +{ + pcb_pline_t *pl; + + while ((pl = *pline) != NULL) { + *pline = pl->next; + pcb_poly_contour_del(&pl); + } +} + +void pcb_polyarea_free(pcb_polyarea_t ** p) +{ + pcb_polyarea_t *cur; + + if (*p == NULL) + return; + for (cur = (*p)->f; cur != *p; cur = (*p)->f) { + pcb_poly_contours_free(&cur->contours); + pcb_r_destroy_tree(&cur->contour_tree); + cur->f->b = cur->b; + cur->b->f = cur->f; + free(cur); + } + pcb_poly_contours_free(&cur->contours); + pcb_r_destroy_tree(&cur->contour_tree); + free(*p), *p = NULL; +} + +static pcb_bool inside_sector(pcb_vnode_t * pn, pcb_vector_t p2) +{ + pcb_vector_t cdir, ndir, pdir; + int p_c, n_c, p_n; + + assert(pn != NULL); + vect_sub(cdir, p2, pn->point); + vect_sub(pdir, pn->point, pn->prev->point); + vect_sub(ndir, pn->next->point, pn->point); + + p_c = pcb_vect_det2(pdir, cdir) >= 0; + n_c = pcb_vect_det2(ndir, cdir) >= 0; + p_n = pcb_vect_det2(pdir, ndir) >= 0; + + if ((p_n && p_c && n_c) || ((!p_n) && (p_c || n_c))) + return pcb_true; + else + return pcb_false; +} /* inside_sector */ + +/* returns pcb_true if bad contour */ +typedef struct { + int marks, lines; +#ifndef NDEBUG + pcb_coord_t x[8], y[8]; + pcb_coord_t x1[8], y1[8], x2[8], y2[8]; + char msg[256]; +#endif +} pa_chk_res_t; + + +#ifndef NDEBUG +#define PA_CHK_MARK(x_, y_) \ +do { \ + if (res->marks < sizeof(res->x) / sizeof(res->x[0])) { \ + res->x[res->marks] = x_; \ + res->y[res->marks] = y_; \ + res->marks++; \ + } \ +} while(0) +#define PA_CHK_LINE(x1_, y1_, x2_, y2_) \ +do { \ + if (res->lines < sizeof(res->x1) / sizeof(res->x1[0])) { \ + res->x1[res->lines] = x1_; \ + res->y1[res->lines] = y1_; \ + res->x2[res->lines] = x2_; \ + res->y2[res->lines] = y2_; \ + res->lines++; \ + } \ +} while(0) +#else +#define PA_CHK_MARK(x, y) +#define PA_CHK_LINE(x1, y1, x2, y2) +#endif + + +PCB_INLINE pcb_bool PA_CHK_ERROR(pa_chk_res_t *res, const char *fmt, ...) +{ +#ifndef NDEBUG + va_list ap; + va_start(ap, fmt); + pcb_vsnprintf(res->msg, sizeof(res->msg), fmt, ap); + va_end(ap); +#endif + return pcb_true; +} + +pcb_bool pcb_polyarea_contour_check_(pcb_pline_t *a, pa_chk_res_t *res) +{ + pcb_vnode_t *a1, *a2, *hit1, *hit2; + pcb_vector_t i1, i2; + int icnt; + +#ifndef NDEBUG + *res->msg = '\0'; +#endif + res->marks = res->lines = 0; + + assert(a != NULL); + a1 = &a->head; + do { + a2 = a1; + do { + if (!node_neighbours(a1, a2) && (icnt = pcb_vect_inters2(a1->point, a1->next->point, a2->point, a2->next->point, i1, i2)) > 0) { + if (icnt > 1) { + PA_CHK_MARK(a1->point[0], a1->point[1]); + PA_CHK_MARK(a2->point[0], a2->point[1]); + return PA_CHK_ERROR(res, "icnt > 1 (%d) at %mm;%mm or %mm;%mm", icnt, a1->point[0], a1->point[1], a2->point[0], a2->point[1]); + } + +TODO(": ugly workaround: test where exactly the intersection happens and tune the endpoint of the line") + /* EPSILON^2 for endpoint matching; the bool algebra code is not + perfect and causes tiny self intersections at the end of sharp + spikes. Accept at most 10 nanometer of such intersection */ +# define ENDP_EPSILON 100 + + if (pcb_vect_dist2(i1, a1->point) < ENDP_EPSILON) + hit1 = a1; + else if (pcb_vect_dist2(i1, a1->next->point) < ENDP_EPSILON) + hit1 = a1->next; + else + hit1 = NULL; + + if (pcb_vect_dist2(i1, a2->point) < ENDP_EPSILON) + hit2 = a2; + else if (pcb_vect_dist2(i1, a2->next->point) < ENDP_EPSILON) + hit2 = a2->next; + else + hit2 = NULL; + + if ((hit1 == NULL) && (hit2 == NULL)) { + /* If the intersection didn't land on an end-point of either + * line, we know the lines cross and we return pcb_true. + */ + PA_CHK_LINE(a1->point[0], a1->point[1], a1->next->point[0], a1->next->point[1]); + PA_CHK_LINE(a2->point[0], a2->point[1], a2->next->point[0], a2->next->point[1]); + return PA_CHK_ERROR(res, "lines cross between %mm;%mm and %mm;%mm", a1->point[0], a1->point[1], a2->point[0], a2->point[1]); + } + else if (hit1 == NULL) { + /* An end-point of the second line touched somewhere along the + length of the first line. Check where the second line leads. */ + if (inside_sector(hit2, a1->point) != inside_sector(hit2, a1->next->point)) { + PA_CHK_MARK(a1->point[0], a1->point[1]); + PA_CHK_MARK(hit2->point[0], hit2->point[1]); + return PA_CHK_ERROR(res, "lines is inside sector (1) at %mm;%mm", a1->point[0], a1->point[1]); + } + } + else if (hit2 == NULL) { + /* An end-point of the first line touched somewhere along the + length of the second line. Check where the first line leads. */ + if (inside_sector(hit1, a2->point) != inside_sector(hit1, a2->next->point)) { + PA_CHK_MARK(a2->point[0], a2->point[1]); + PA_CHK_MARK(hit1->point[0], hit1->point[1]); + return PA_CHK_ERROR(res, "lines is inside sector (2) at %mm;%mm", a2->point[0], a2->point[1]); + } + } + else { + /* Both lines intersect at an end-point. Check where they lead. */ + if (inside_sector(hit1, hit2->prev->point) != inside_sector(hit1, hit2->next->point)) { + PA_CHK_MARK(hit1->point[0], hit2->point[1]); + PA_CHK_MARK(hit2->point[0], hit2->point[1]); + return PA_CHK_ERROR(res, "lines is inside sector (3) at %mm;%mm or %mm;%mm", hit1->point[0], hit1->point[1], hit2->point[0], hit2->point[1]); + } + } + } + } + while ((a2 = a2->next) != &a->head); + } + while ((a1 = a1->next) != &a->head); + return pcb_false; +} + +pcb_bool pcb_polyarea_contour_check(pcb_pline_t *a) +{ + pa_chk_res_t res; + return pcb_polyarea_contour_check_(a, &res); +} + +void pcb_polyarea_bbox(pcb_polyarea_t * p, pcb_box_t * b) +{ + pcb_pline_t *n; + /*int cnt;*/ + + n = p->contours; + b->X1 = b->X2 = n->xmin; + b->Y1 = b->Y2 = n->ymin; + + for (/*cnt = 0*/; /*cnt < 2 */ n != NULL; n = n->next) { + if (n->xmin < b->X1) + b->X1 = n->xmin; + if (n->ymin < b->Y1) + b->Y1 = n->ymin; + if (n->xmax > b->X2) + b->X2 = n->xmax; + if (n->ymax > b->Y2) + b->Y2 = n->ymax; +/* if (n == p->contours) + cnt++;*/ + } +} + +#ifndef NDEBUG +static void pcb_poly_valid_report(pcb_pline_t *c, pcb_vnode_t *pl, pa_chk_res_t *chk) +{ + pcb_vnode_t *v, *n; + pcb_coord_t minx = COORD_MAX, miny = COORD_MAX, maxx = -COORD_MAX, maxy = -COORD_MAX; + +#define update_minmax(min, max, val) \ + if (val < min) min = val; \ + if (val > max) max = val; + if (chk != NULL) + pcb_fprintf(stderr, "Details: %s\n", chk->msg); + pcb_fprintf(stderr, "!!!animator start\n"); + v = pl; + do { + n = v->next; + update_minmax(minx, maxx, v->point[0]); + update_minmax(miny, maxy, v->point[1]); + update_minmax(minx, maxx, n->point[0]); + update_minmax(miny, maxy, n->point[1]); + } + while ((v = v->next) != pl); + pcb_fprintf(stderr, "scale 1 -1\n"); + pcb_fprintf(stderr, "viewport %mm %mm - %mm %mm\n", minx, miny, maxx, maxy); + pcb_fprintf(stderr, "frame\n"); + v = pl; + do { + n = v->next; + pcb_fprintf(stderr, "line %#mm %#mm %#mm %#mm\n", v->point[0], v->point[1], n->point[0], n->point[1]); + } + while ((v = v->next) != pl); + + if ((chk != NULL) && (chk->marks > 0)) { + int n, MR=PCB_MM_TO_COORD(0.05); + fprintf(stderr, "color #770000\n"); + for(n = 0; n < chk->marks; n++) { + pcb_fprintf(stderr, "line %#mm %#mm %#mm %#mm\n", chk->x[n]-MR, chk->y[n]-MR, chk->x[n]+MR, chk->y[n]+MR); + pcb_fprintf(stderr, "line %#mm %#mm %#mm %#mm\n", chk->x[n]-MR, chk->y[n]+MR, chk->x[n]+MR, chk->y[n]-MR); + } + } + + if ((chk != NULL) && (chk->lines > 0)) { + int n; + fprintf(stderr, "color #990000\n"); + for(n = 0; n < chk->lines; n++) + pcb_fprintf(stderr, "line %#mm %#mm %#mm %#mm\n", chk->x1[n], chk->y1[n], chk->x2[n], chk->y2[n]); + } + + fprintf(stderr, "flush\n"); + fprintf(stderr, "!!!animator end\n"); + +#undef update_minmax +} +#endif + + +pcb_bool pcb_poly_valid(pcb_polyarea_t * p) +{ + pcb_pline_t *c; + pa_chk_res_t chk; + + if ((p == NULL) || (p->contours == NULL)) + return pcb_false; + + if (p->contours->Flags.orient == PCB_PLF_INV) { +#ifndef NDEBUG + pcb_fprintf(stderr, "Invalid Outer pcb_pline_t: failed orient\n"); + pcb_poly_valid_report(p->contours, &p->contours->head, NULL); +#endif + return pcb_false; + } + + if (pcb_polyarea_contour_check_(p->contours, &chk)) { +#ifndef NDEBUG + pcb_fprintf(stderr, "Invalid Outer pcb_pline_t: failed contour check\n"); + pcb_poly_valid_report(p->contours, &p->contours->head, &chk); +#endif + return pcb_false; + } + + for (c = p->contours->next; c != NULL; c = c->next) { + if (c->Flags.orient == PCB_PLF_DIR) { +#ifndef NDEBUG + pcb_fprintf(stderr, "Invalid Inner: pcb_pline_t orient = %d\n", c->Flags.orient); + pcb_poly_valid_report(c, &c->head, NULL); +#endif + return pcb_false; + } + if (pcb_polyarea_contour_check_(c, &chk)) { +#ifndef NDEBUG + pcb_fprintf(stderr, "Invalid Inner: failed contour check\n"); + pcb_poly_valid_report(c, &c->head, &chk); +#endif + return pcb_false; + } + if (!pcb_poly_contour_in_contour(p->contours, c)) { +#ifndef NDEBUG + pcb_fprintf(stderr, "Invalid Inner: overlap with outer\n"); + pcb_poly_valid_report(c, &c->head, NULL); +#endif + return pcb_false; + } + } + return pcb_true; +} + + +pcb_vector_t vect_zero = { (long) 0, (long) 0 }; + +/*********************************************************************/ +/* L o n g V e c t o r S t u f f */ +/*********************************************************************/ + +void vect_init(pcb_vector_t v, double x, double y) +{ + v[0] = (long) x; + v[1] = (long) y; +} /* vect_init */ + +#define Vzero(a) ((a)[0] == 0. && (a)[1] == 0.) + +#define Vsub(a,b,c) {(a)[0]=(b)[0]-(c)[0];(a)[1]=(b)[1]-(c)[1];} + +int vect_equal(pcb_vector_t v1, pcb_vector_t v2) +{ + return (v1[0] == v2[0] && v1[1] == v2[1]); +} /* vect_equal */ + + +void vect_sub(pcb_vector_t res, pcb_vector_t v1, pcb_vector_t v2) +{ +Vsub(res, v1, v2)} /* vect_sub */ + +void vect_min(pcb_vector_t v1, pcb_vector_t v2, pcb_vector_t v3) +{ + v1[0] = (v2[0] < v3[0]) ? v2[0] : v3[0]; + v1[1] = (v2[1] < v3[1]) ? v2[1] : v3[1]; +} /* vect_min */ + +void vect_max(pcb_vector_t v1, pcb_vector_t v2, pcb_vector_t v3) +{ + v1[0] = (v2[0] > v3[0]) ? v2[0] : v3[0]; + v1[1] = (v2[1] > v3[1]) ? v2[1] : v3[1]; +} /* vect_max */ + +double pcb_vect_len2(pcb_vector_t v) +{ + return ((double) v[0] * v[0] + (double) v[1] * v[1]); /* why sqrt? only used for compares */ +} + +double pcb_vect_dist2(pcb_vector_t v1, pcb_vector_t v2) +{ + double dx = v1[0] - v2[0]; + double dy = v1[1] - v2[1]; + + return (dx * dx + dy * dy); /* why sqrt */ +} + +/* value has sign of angle between vectors */ +double pcb_vect_det2(pcb_vector_t v1, pcb_vector_t v2) +{ + return (((double) v1[0] * v2[1]) - ((double) v2[0] * v1[1])); +} + +static double vect_m_dist(pcb_vector_t v1, pcb_vector_t v2) +{ + double dx = v1[0] - v2[0]; + double dy = v1[1] - v2[1]; + double dd = (dx * dx + dy * dy); /* sqrt */ + + if (dx > 0) + return +dd; + if (dx < 0) + return -dd; + if (dy > 0) + return +dd; + return -dd; +} /* vect_m_dist */ + +/* +vect_inters2 + (C) 1993 Klamer Schutte + (C) 1997 Michael Leonov, Alexey Nikitin +*/ + +int pcb_vect_inters2(pcb_vector_t p1, pcb_vector_t p2, pcb_vector_t q1, pcb_vector_t q2, pcb_vector_t S1, pcb_vector_t S2) +{ + double s, t, deel; + double rpx, rpy, rqx, rqy; + + if (max(p1[0], p2[0]) < min(q1[0], q2[0]) || + max(q1[0], q2[0]) < min(p1[0], p2[0]) || max(p1[1], p2[1]) < min(q1[1], q2[1]) || max(q1[1], q2[1]) < min(p1[1], p2[1])) + return 0; + + rpx = p2[0] - p1[0]; + rpy = p2[1] - p1[1]; + rqx = q2[0] - q1[0]; + rqy = q2[1] - q1[1]; + + deel = rpy * rqx - rpx * rqy; /* -vect_det(rp,rq); */ + + /* coordinates are 30-bit integers so deel will be exactly zero + * if the lines are parallel + */ + + if (deel == 0) { /* parallel */ + double dc1, dc2, d1, d2, h; /* Check to see whether p1-p2 and q1-q2 are on the same line */ + pcb_vector_t hp1, hq1, hp2, hq2, q1p1, q1q2; + + Vsub2(q1p1, q1, p1); + Vsub2(q1q2, q1, q2); + + + /* If this product is not zero then p1-p2 and q1-q2 are not on same line! */ + if (pcb_vect_det2(q1p1, q1q2) != 0) + return 0; + dc1 = 0; /* m_len(p1 - p1) */ + + dc2 = vect_m_dist(p1, p2); + d1 = vect_m_dist(p1, q1); + d2 = vect_m_dist(p1, q2); + +/* Sorting the independent points from small to large */ + Vcpy2(hp1, p1); + Vcpy2(hp2, p2); + Vcpy2(hq1, q1); + Vcpy2(hq2, q2); + if (dc1 > dc2) { /* hv and h are used as help-variable. */ + Vswp2(hp1, hp2); + h = dc1, dc1 = dc2, dc2 = h; + } + if (d1 > d2) { + Vswp2(hq1, hq2); + h = d1, d1 = d2, d2 = h; + } + +/* Now the line-pieces are compared */ + + if (dc1 < d1) { + if (dc2 < d1) + return 0; + if (dc2 < d2) { + Vcpy2(S1, hp2); + Vcpy2(S2, hq1); + } + else { + Vcpy2(S1, hq1); + Vcpy2(S2, hq2); + }; + } + else { + if (dc1 > d2) + return 0; + if (dc2 < d2) { + Vcpy2(S1, hp1); + Vcpy2(S2, hp2); + } + else { + Vcpy2(S1, hp1); + Vcpy2(S2, hq2); + }; + } + return (Vequ2(S1, S2) ? 1 : 2); + } + else { /* not parallel */ + /* + * We have the lines: + * l1: p1 + s(p2 - p1) + * l2: q1 + t(q2 - q1) + * And we want to know the intersection point. + * Calculate t: + * p1 + s(p2-p1) = q1 + t(q2-q1) + * which is similar to the two equations: + * p1x + s * rpx = q1x + t * rqx + * p1y + s * rpy = q1y + t * rqy + * Multiplying these by rpy resp. rpx gives: + * rpy * p1x + s * rpx * rpy = rpy * q1x + t * rpy * rqx + * rpx * p1y + s * rpx * rpy = rpx * q1y + t * rpx * rqy + * Subtracting these gives: + * rpy * p1x - rpx * p1y = rpy * q1x - rpx * q1y + t * ( rpy * rqx - rpx * rqy ) + * So t can be isolated: + * t = (rpy * ( p1x - q1x ) + rpx * ( - p1y + q1y )) / ( rpy * rqx - rpx * rqy ) + * and s can be found similarly + * s = (rqy * (q1x - p1x) + rqx * (p1y - q1y))/( rqy * rpx - rqx * rpy) + */ + + if (Vequ2(q1, p1) || Vequ2(q1, p2)) { + S1[0] = q1[0]; + S1[1] = q1[1]; + } + else if (Vequ2(q2, p1) || Vequ2(q2, p2)) { + S1[0] = q2[0]; + S1[1] = q2[1]; + } + else { + s = (rqy * (p1[0] - q1[0]) + rqx * (q1[1] - p1[1])) / deel; + if (s < 0 || s > 1.) + return 0; + t = (rpy * (p1[0] - q1[0]) + rpx * (q1[1] - p1[1])) / deel; + if (t < 0 || t > 1.) + return 0; + + S1[0] = q1[0] + ROUND(t * rqx); + S1[1] = q1[1] + ROUND(t * rqy); + } + return 1; + } +} /* vect_inters2 */ + +/* + * pcb_pline_isect_line() + * (C) 2017, 2018 Tibor 'Igor2' Palinkas +*/ + +typedef struct { + pcb_vector_t l1, l2; + pcb_coord_t cx, cy; +} pline_isect_line_t; + +static pcb_r_dir_t pline_isect_line_cb(const pcb_box_t * b, void *cl) +{ + pline_isect_line_t *ctx = (pline_isect_line_t *)cl; + struct seg *s = (struct seg *)b; + pcb_vector_t S1, S2; + + if (pcb_vect_inters2(s->v->point, s->v->next->point, ctx->l1, ctx->l2, S1, S2)) { + ctx->cx = S1[0]; + ctx->cy = S1[1]; + return PCB_R_DIR_CANCEL; /* found */ + } + + return PCB_R_DIR_NOT_FOUND; +} + +pcb_bool pcb_pline_isect_line(pcb_pline_t *pl, pcb_coord_t lx1, pcb_coord_t ly1, pcb_coord_t lx2, pcb_coord_t ly2, pcb_coord_t *cx, pcb_coord_t *cy) +{ + pline_isect_line_t ctx; + pcb_box_t lbx; + ctx.l1[0] = lx1; ctx.l1[1] = ly1; + ctx.l2[0] = lx2; ctx.l2[1] = ly2; + lbx.X1 = MIN(lx1, lx2); + lbx.Y1 = MIN(ly1, ly2); + lbx.X2 = MAX(lx1, lx2); + lbx.Y2 = MAX(ly1, ly2); + + if (pl->tree == NULL) + pl->tree = (pcb_rtree_t *) make_edge_tree(pl); + + if (pcb_r_search(pl->tree, &lbx, NULL, pline_isect_line_cb, &ctx, NULL) == PCB_R_DIR_CANCEL) { + if (cx != NULL) *cx = ctx.cx; + if (cy != NULL) *cy = ctx.cy; + return pcb_true; + } + return pcb_false; +} + +/* + * pcb_pline_isect_circle() + * (C) 2017 Tibor 'Igor2' Palinkas +*/ + +typedef struct { + pcb_coord_t cx, cy, r; + double r2; +} pline_isect_circ_t; + +static pcb_r_dir_t pline_isect_circ_cb(const pcb_box_t * b, void *cl) +{ + pline_isect_circ_t *ctx = (pline_isect_circ_t *)cl; + struct seg *s = (struct seg *)b; + pcb_vector_t S1, S2; + pcb_vector_t ray1, ray2; + double ox, oy, dx, dy, l; + + /* Cheap: if either line endpoint is within the circle, we sure have an intersection */ + if ((PCB_SQUARE(s->v->point[0] - ctx->cx) + PCB_SQUARE(s->v->point[1] - ctx->cy)) <= ctx->r2) + return PCB_R_DIR_CANCEL; /* found */ + if ((PCB_SQUARE(s->v->next->point[0] - ctx->cx) + PCB_SQUARE(s->v->next->point[1] - ctx->cy)) <= ctx->r2) + return PCB_R_DIR_CANCEL; /* found */ + + dx = s->v->point[0] - s->v->next->point[0]; + dy = s->v->point[1] - s->v->next->point[1]; + l = sqrt(PCB_SQUARE(dx) + PCB_SQUARE(dy)); + ox = -dy / l * (double)ctx->r; + oy = dx / l * (double)ctx->r; + + ray1[0] = ctx->cx - ox; ray1[1] = ctx->cy - oy; + ray2[0] = ctx->cx + ox; ray2[1] = ctx->cy + oy; + + if (pcb_vect_inters2(s->v->point, s->v->next->point, ray1, ray2, S1, S2)) + return PCB_R_DIR_CANCEL; /* found */ + + return PCB_R_DIR_NOT_FOUND; +} + +pcb_bool pcb_pline_isect_circ(pcb_pline_t *pl, pcb_coord_t cx, pcb_coord_t cy, pcb_coord_t r) +{ + pline_isect_circ_t ctx; + pcb_box_t cbx; + ctx.cx = cx; ctx.cy = cy; + ctx.r = r; ctx.r2 = (double)r * (double)r; + cbx.X1 = cx - r; cbx.Y1 = cy - r; + cbx.X2 = cx + r; cbx.Y2 = cy + r; + + if (pl->tree == NULL) + pl->tree = (pcb_rtree_t *) make_edge_tree(pl); + + return pcb_r_search(pl->tree, &cbx, NULL, pline_isect_circ_cb, &ctx, NULL) == PCB_R_DIR_CANCEL; +} + + +/* + * pcb_pline_embraces_circle() + * If the circle does not intersect the polygon (the caller needs to check this) + * return whether the circle is fully within the polygon or not. + * Shoots a ray to the right from center+radius, then one to the left from + * center-radius; if both ray cross odd number of pline segments, we are in + * (or intersecting). + * (C) 2017 Tibor 'Igor2' Palinkas +*/ +static pcb_r_dir_t pline_embraces_circ_cb(const pcb_box_t * b, void *cl) +{ + int *cnt = (int *)cl; + (*cnt)++; + return PCB_R_DIR_NOT_FOUND; +} + +pcb_bool pcb_pline_embraces_circ(pcb_pline_t *pl, pcb_coord_t cx, pcb_coord_t cy, pcb_coord_t r) +{ + pcb_box_t bx; + int cnt; + + bx.Y1 = cy; bx.Y2 = cy+1; + if (pl->tree == NULL) + pl->tree = (pcb_rtree_t *) make_edge_tree(pl); + + /* ray to the right */ + bx.X1 = cx + r; + bx.X2 = COORD_MAX; + cnt = 0; + pcb_r_search(pl->tree, &bx, NULL, pline_embraces_circ_cb, &cnt, NULL); + if ((cnt % 2) == 0) + return pcb_false; + + /* ray to the right */ + bx.X1 = -COORD_MAX; + bx.X2 = cx - r; + cnt = 0; + pcb_r_search(pl->tree, &bx, NULL, pline_embraces_circ_cb, &cnt, NULL); + if ((cnt % 2) == 0) + return pcb_false; + + return pcb_true; +} + +/* + * pcb_pline_isect_circle() + * (C) 2017 Tibor 'Igor2' Palinkas +*/ +pcb_bool pcb_pline_overlaps_circ(pcb_pline_t *pl, pcb_coord_t cx, pcb_coord_t cy, pcb_coord_t r) +{ + pcb_box_t cbx, pbx; + cbx.X1 = cx - r; cbx.Y1 = cy - r; + cbx.X2 = cx + r; cbx.Y2 = cy + r; + pbx.X1 = pl->xmin; pbx.Y1 = pl->ymin; + pbx.X2 = pl->xmax; pbx.Y2 = pl->ymax; + + /* if there's no overlap in bounding boxes, don't do any expensive calc */ + if (!(pcb_box_intersect(&cbx, &pbx))) + return pcb_false; + + if (pl->tree == NULL) + pl->tree = (pcb_rtree_t *) make_edge_tree(pl); + + if (pcb_pline_isect_circ(pl, cx, cy, r)) + return pcb_true; + + return pcb_pline_embraces_circ(pl, cx, cy, r); +} + + +/* + * pcb_is_point_in_convex_quad() + * (C) 2017 Tibor 'Igor2' Palinkas +*/ +pcb_bool_t pcb_is_point_in_convex_quad(pcb_vector_t p, pcb_vector_t *q) +{ + return point_in_triangle(q[0], q[1], q[2], p) || point_in_triangle(q[0], q[3], q[2], p); +} + + +/* + * pcb_polyarea_move() + * (C) 2017 Tibor 'Igor2' Palinkas +*/ +void pcb_polyarea_move(pcb_polyarea_t *pa1, pcb_coord_t dx, pcb_coord_t dy) +{ + int cnt; + pcb_polyarea_t *pa; + + for (pa = pa1, cnt = 0; pa != NULL; pa = pa->f) { + pcb_pline_t *pl; + if (pa == pa1) { + cnt++; + if (cnt > 1) + break; + } + if (pa->contour_tree != NULL) + pcb_r_destroy_tree(&pa->contour_tree); + pa->contour_tree = pcb_r_create_tree(); + for(pl = pa->contours; pl != NULL; pl = pl->next) { + pcb_vnode_t *v; + int cnt2 = 0; + for(v = &pl->head; v != NULL; v = v->next) { + if (v == &pl->head) { + cnt2++; + if (cnt2 > 1) + break; + } + v->point[0] += dx; + v->point[1] += dy; + } + pl->xmin += dx; + pl->ymin += dy; + pl->xmax += dx; + pl->ymax += dy; + if (pl->tree != NULL) { + pcb_r_free_tree_data(pl->tree, free); + pcb_r_destroy_tree(&pl->tree); + } + pl->tree = (pcb_rtree_t *)make_edge_tree(pl); + + pcb_r_insert_entry(pa->contour_tree, (pcb_box_t *)pl); + } + } +} + +#include "polygon_selfi.c" + +/* how about expanding polygons so that edges can be arcs rather than + * lines. Consider using the third coordinate to store the radius of the + * arc. The arc would pass through the vertex points. Positive radius + * would indicate the arc bows left (center on right of P1-P2 path) + * negative radius would put the center on the other side. 0 radius + * would mean the edge is a line instead of arc + * The intersections of the two circles centered at the vertex points + * would determine the two possible arc centers. If P2.x > P1.x then + * the center with smaller Y is selected for positive r. If P2.y > P1.y + * then the center with greater X is selected for positive r. + * + * the vec_inters2() routine would then need to handle line-line + * line-arc and arc-arc intersections. + * + * perhaps reverse tracing the arc would require look-ahead to check + * for arcs + */ Index: tags/2.1.2/src/polygon_act.c =================================================================== --- tags/2.1.2/src/polygon_act.c (nonexistent) +++ tags/2.1.2/src/polygon_act.c (revision 24813) @@ -0,0 +1,130 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * Copyright (C) 1997, 1998, 1999, 2000, 2001 Harry Eaton + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + * + * Old contact info: + * Harry Eaton, 6697 Buttonhole Ct, Columbia, MD 21044, USA + * haceaton@aplcomm.jhuapl.edu + * + */ +#include "config.h" +#include "conf_core.h" + +#include "board.h" +#include "data.h" +#include "undo.h" +#include "funchash_core.h" + +#include "polygon.h" +#include "draw.h" +#include "search.h" +#include "crosshair.h" +#include "tool.h" +#include "actions.h" + +#include "obj_poly.h" + +static const char pcb_acts_MorphPolygon[] = "pcb_poly_morph(Object|Selected)"; +static const char pcb_acth_MorphPolygon[] = "Converts dead polygon islands into separate polygons."; +/* DOC: morphpolygon.html */ +static fgw_error_t pcb_act_MorphPolygon(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + int op; + + PCB_ACT_CONVARG(1, FGW_KEYWORD, MorphPolygon, op = fgw_keyword(&argv[1])); + + switch(op) { + case F_Object: + { + pcb_coord_t x, y; + int type; + void *ptr1, *ptr2, *ptr3; + + pcb_hid_get_coords("Select an Object", &x, &y, 0); + if ((type = pcb_search_screen(x, y, PCB_OBJ_POLY, &ptr1, &ptr2, &ptr3)) != PCB_OBJ_VOID) { + pcb_poly_morph((pcb_layer_t *) ptr1, (pcb_poly_t *) ptr3); + pcb_draw(); + pcb_undo_inc_serial(); + } + break; + } + case F_Selected: + case F_SelectedObjects: + PCB_POLY_ALL_LOOP(PCB->Data); + { + if (PCB_FLAG_TEST(PCB_FLAG_SELECTED, polygon)) + pcb_poly_morph(layer, polygon); + } + PCB_ENDALL_LOOP; + pcb_draw(); + pcb_undo_inc_serial(); + break; + } + PCB_ACT_IRES(0); + return 0; +} + +static const char pcb_acts_Polygon[] = "Polygon(Close|CloseHole|PreviousPoint)"; +static const char pcb_acth_Polygon[] = "Some polygon related stuff."; +/* DOC: polygon.html */ +static fgw_error_t pcb_act_Polygon(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + int op; + + PCB_ACT_CONVARG(1, FGW_KEYWORD, Polygon, op = fgw_keyword(&argv[1])); + + if ((argc > 1) && ((conf_core.editor.mode == PCB_MODE_POLYGON) || (conf_core.editor.mode == PCB_MODE_POLYGON_HOLE))) { + pcb_notify_crosshair_change(pcb_false); + switch(op) { + /* close open polygon if possible */ + case F_Close: + pcb_polygon_close_poly(); + break; + + /* close open polygon hole if possible */ + case F_CloseHole: + pcb_polygon_close_hole(); + break; + + /* go back to the previous point */ + case F_PreviousPoint: + pcb_polygon_go_to_prev_point(); + break; + } + pcb_notify_crosshair_change(pcb_true); + } + PCB_ACT_IRES(0); + return 0; +} + + +pcb_action_t polygon_action_list[] = { + {"MorphPolygon", pcb_act_MorphPolygon, pcb_acth_MorphPolygon, pcb_acts_MorphPolygon}, + {"Polygon", pcb_act_Polygon, pcb_acth_Polygon, pcb_acts_Polygon} +}; + +PCB_REGISTER_ACTIONS(polygon_action_list, NULL) Index: tags/2.1.2/src/polygon_offs.c =================================================================== --- tags/2.1.2/src/polygon_offs.c (nonexistent) +++ tags/2.1.2/src/polygon_offs.c (revision 24813) @@ -0,0 +1,169 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2017 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +/* Polygon contour offset calculation */ + +#include "compat_misc.h" +#include "polygon_offs.h" + +void pcb_polo_norm(double *nx, double *ny, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2) +{ + double dx = x2 - x1, dy = y2 - y1, len = sqrt(dx*dx + dy*dy); + *nx = -dy / len; + *ny = dx / len; +} + +void pcb_polo_normd(double *nx, double *ny, double x1, double y1, double x2, double y2) +{ + double dx = x2 - x1, dy = y2 - y1, len = sqrt(dx*dx + dy*dy); + *nx = -dy / len; + *ny = dx / len; +} + +static long warp(long n, long len) +{ + if (n < 0) n += len; + else if (n >= len) n -= len; + return n; +} + +void pcb_polo_edge_shift(double offs, + double *x0, double *y0, double nx, double ny, + double *x1, double *y1, + double prev_x, double prev_y, double prev_nx, double prev_ny, + double next_x, double next_y, double next_nx, double next_ny) +{ + double ax, ay, al, a1l, a1x, a1y; + + offs = -offs; + + /* previous edge's endpoint offset */ + ax = (*x0) - prev_x; + ay = (*y0) - prev_y; + al = sqrt(ax*ax + ay*ay); + ax /= al; + ay /= al; + a1l = ax*nx + ay*ny; + a1x = offs / a1l * ax; + a1y = offs / a1l * ay; + + (*x0) += a1x; + (*y0) += a1y; + + /* next edge's endpoint offset */ + ax = next_x - (*x1); + ay = next_y - (*y1); + al = sqrt(ax*ax + ay*ay); + ax /= al; + ay /= al; + + a1l = ax*nx + ay*ny; + a1x = offs / a1l * ax; + a1y = offs / a1l * ay; + + (*x1) += a1x; + (*y1) += a1y; +} + +void pcb_polo_offs(double offs, pcb_polo_t *pcsh, long num_pts) +{ + long n; + + for(n = 0; n < num_pts; n++) { + long np = warp(n-1, num_pts), nn1 = warp(n+1, num_pts), nn2 = warp(n+2, num_pts); + pcb_polo_edge_shift(offs, + &pcsh[n].x, &pcsh[n].y, pcsh[n].nx, pcsh[n].ny, + &pcsh[nn1].x, &pcsh[nn1].y, + pcsh[np].x, pcsh[np].y, pcsh[np].nx, pcsh[np].ny, + pcsh[nn2].x, pcsh[nn2].y, pcsh[nn2].nx, pcsh[nn2].ny + ); + } +} + + +void pcb_polo_norms(pcb_polo_t *pcsh, long num_pts) +{ + long n; + + for(n = 0; n < num_pts; n++) { + long nn = warp(n+1, num_pts); + pcb_polo_normd(&pcsh[n].nx, &pcsh[n].ny, pcsh[n].x, pcsh[n].y, pcsh[nn].x, pcsh[nn].y); + } +} + +double pcb_polo_2area(pcb_polo_t *pcsh, long num_pts) +{ + double a = 0; + long n; + + for(n = 0; n < num_pts-1; n++) { + long nn = warp(n+1, num_pts); + a += pcsh[n].x * pcsh[nn].y; + a -= pcsh[n].y * pcsh[nn].x; + } + return a; +} + +pcb_pline_t *pcb_pline_dup_offset(const pcb_pline_t *src, pcb_coord_t offs) +{ + const pcb_vnode_t *v; + pcb_vector_t tmp; + pcb_pline_t *res = NULL; + long num_pts, n; + pcb_polo_t *pcsh; + + /* count corners */ + v = &src->head; + num_pts = 0; + do { + num_pts++; + } while((v = v->next) != &src->head); + + /* allocate the cache and copy all data */ + pcsh = malloc(sizeof(pcb_polo_t) * num_pts); + for(n = 0, v = &src->head; n < num_pts; n++, v = v->next) { + pcsh[n].x = v->point[0]; + pcsh[n].y = v->point[1]; + pcb_polo_norm(&pcsh[n].nx, &pcsh[n].ny, v->point[0], v->point[1], v->next->point[0], v->next->point[1]); + } + + /* offset the cache */ + pcb_polo_offs(offs, pcsh, num_pts); + + + /* create a new pline by copying the cache */ + tmp[0] = pcb_round(pcsh[0].x); + tmp[1] = pcb_round(pcsh[0].y); + res = pcb_poly_contour_new(tmp); + for(n = 1; n < num_pts; n++) { + tmp[0] = pcb_round(pcsh[n].x); + tmp[1] = pcb_round(pcsh[n].y); + pcb_poly_vertex_include(res->head.prev, pcb_poly_node_create(tmp)); + } + + free(pcsh); + return res; +} Index: tags/2.1.2/src/polygon_offs.h =================================================================== --- tags/2.1.2/src/polygon_offs.h (nonexistent) +++ tags/2.1.2/src/polygon_offs.h (revision 24813) @@ -0,0 +1,57 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2017 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +/* Polygon contour offset calculation */ + + +pcb_pline_t *pcb_pline_dup_offset(const pcb_pline_t *src, pcb_coord_t offs); + + +/* low level */ + +typedef struct { + double x, y, nx, ny; +} pcb_polo_t; + +/* Calculate the normal vectors of a cache */ +void pcb_polo_norms(pcb_polo_t *pcsh, long num_pts); + +/* Calculate and return the double of the area of a cached polygon */ +double pcb_polo_2area(pcb_polo_t *pcsh, long num_pts); + +/* Ortho-shift all edges of a polygon. Positive offset means grow. */ +void pcb_polo_offs(double offs, pcb_polo_t *pcsh, long num_pts); + +/* Orhto-shift an edge specified by x0;y0 and x1;y1. Calculate the new + edge points by extending/shrinking the previous and next line segment. + Modifies the target edge's start and end coords. Requires cached normals + Positive offset means grow. */ +void pcb_polo_edge_shift(double offs, + double *x0, double *y0, double nx, double ny, + double *x1, double *y1, + double prev_x, double prev_y, double prev_nx, double prev_ny, + double next_x, double next_y, double next_nx, double next_ny); + Index: tags/2.1.2/src/polygon_selfi.c =================================================================== --- tags/2.1.2/src/polygon_selfi.c (nonexistent) +++ tags/2.1.2/src/polygon_selfi.c (revision 24813) @@ -0,0 +1,243 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2018 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "config.h" +#include "polygon_selfi.h" + +/* expect no more than this number of hubs in a complex polygon */ +#define MAX_HUB_TRIES 1024 + +#if 0 +# define TRACE pcb_trace +#else + void TRACE(const char *fmt, ...) {} +#endif + +typedef struct { + vtp0_t node; +} vhub_t; + +static pcb_vnode_t *pcb_pline_split(pcb_vnode_t *v, pcb_vector_t at) +{ + pcb_vnode_t *v2 = node_add_single(v, at); + + v2 = pcb_poly_node_create(at); + assert(v2 != NULL); + v2->cvc_prev = v2->cvc_next = NULL; + v2->Flags.status = UNKNWN; + + /* link in */ + v->next->prev = v2; + v2->next = v->next; + v2->prev = v; + v->next = v2; + + return v2; +} + +static pcb_vnode_t *pcb_pline_end_at(pcb_vnode_t *v, pcb_vector_t at) +{ + if (pcb_vect_dist2(at, v->point) < ENDP_EPSILON) + return v; + if (pcb_vect_dist2(at, v->next->point) < ENDP_EPSILON) + return v->next; + return NULL; +} + +static vhub_t *hub_find(vtp0_t *hubs, pcb_vnode_t *v, pcb_bool insert) +{ + int n, m; + vhub_t *h; + + for(n = 0, h = hubs->array[0]; n < vtp0_len(hubs); n++,h++) { + pcb_vnode_t *stored = *vtp0_get(&h->node, 0, 0); + /* found the hub at the specific location */ + if (pcb_vect_dist2(stored->point, v->point) < ENDP_EPSILON) { + for(m = 0; m < vtp0_len(&h->node); m++) { + stored = *vtp0_get(&h->node, m, 0); + if (stored == v) /* already on the list */ + return h; + } + /* not found on the hub's list, maybe insert */ + if (insert) { + vtp0_append(&h->node, v); + return h; + } + return NULL; /* there is only one hub per point - if the coord matched and the node is not on, it's not going to be on any other hub's list */ + } + } + return NULL; +} + +/* returns 1 if a new intersection is mapped */ +static int pcb_pline_add_isectp(vtp0_t *hubs, pcb_vnode_t *v) +{ + vhub_t *h; + + assert(v != NULL); + + v->Flags.in_hub = 1; + if (hubs->array != NULL) { + if (hub_find(hubs, v, pcb_true) != NULL) /* already on the list (... by now) */ + return 0; + } + + h = malloc(sizeof(vhub_t)); + vtp0_append(hubs, h); + vtp0_init(&h->node); + vtp0_append(&h->node, v); + return 1; +} + +static int pline_split_off_loop(vtp0_t *hubs, vtp0_t *out, vhub_t *h, pcb_vnode_t *start) +{ + pcb_vnode_t *v, *next, *tmp; + pcb_pline_t *newpl = NULL; + pcb_cardinal_t cnt; + vhub_t *endh; + + for(v = start->next, cnt = 0; v->Flags.in_hub == 0; v = v->next) cnt++; + endh = hub_find(hubs, v, pcb_false); + if (h == endh) { /* forward loop */ + TRACE(" Fwd %ld!\n", (long)cnt); + newpl = pcb_poly_contour_new(start->point); + next = start->next; + pcb_poly_vertex_exclude(start); + for(v = next; cnt > 0; v = next, cnt--) { + TRACE(" Append %mm %mm!\n", v->point[0], v->point[1]); + next = v->next; + pcb_poly_vertex_exclude(v); + tmp = pcb_poly_node_create(v->point); + pcb_poly_vertex_include(newpl->head.prev, tmp); + } + goto new_pl; + } + + for(v = start->prev, cnt = 0; v->Flags.in_hub == 0; v = v->prev) cnt++; + if (h == endh) { /* backward loop */ + TRACE(" Bwd %ld!\n", (long)cnt); + newpl = pcb_poly_contour_new(start->point); + next = start->prev; + newpl->head = *start; + pcb_poly_vertex_exclude(start); + for(v = next; cnt > 0; v = next, cnt--) { + TRACE(" Append!\n"); + next = v->prev; + pcb_poly_vertex_exclude(v); + tmp = pcb_poly_node_create(v->point); + pcb_poly_vertex_include(start, tmp); + } + goto new_pl; + } + return 0; + + new_pl:; +TRACE("APPEND: %p %p\n", newpl, newpl->head.next); + vtp0_append(out, newpl); + return 1; +} + +pcb_bool pcb_pline_is_selfint(pcb_pline_t *pl) +{ + pcb_vnode_t *va, *vb; + + va = (pcb_vnode_t *)&pl->head; + do { + for(vb = va->next->next; vb->next != va; vb = vb->next) { + pcb_vector_t i, tmp; + if (pcb_vect_inters2(va->point, va->next->point, vb->point, vb->next->point, i, tmp) > 0) + return pcb_true; + } + va = va->next; + } while (va != &pl->head); + return pcb_false; +} + + +void pcb_pline_split_selfint(pcb_pline_t *pl, vtp0_t *out) +{ + int n; + vtp0_t hubs; + pcb_vnode_t *va, *vb, *iva, *ivb; + + vtp0_init(&hubs); + + /* reset the in_hub flag */ + va = (pcb_vnode_t *)&pl->head; + do { + va->Flags.in_hub = 0; + va = va->next; + } while (va != &pl->head); + + /* insert corners at intersections, collect a list of intersection hubs */ + va = (pcb_vnode_t *)&pl->head; + do { + for(vb = va->next->next; vb->next != va; vb = vb->next) { + pcb_vector_t i, tmp; + if (pcb_vect_inters2(va->point, va->next->point, vb->point, vb->next->point, i, tmp) > 0) { + iva = pcb_pline_end_at(va, i); + if (iva == NULL) + iva = pcb_pline_split(va, i); + ivb = pcb_pline_end_at(vb, i); + if (ivb == NULL) + ivb = pcb_pline_split(vb, i); + if (pcb_pline_add_isectp(&hubs, iva) || pcb_pline_add_isectp(&hubs, ivb)) + TRACE("Intersect at %mm;%mm\n", i[0], i[1]); + } + } + va = va->next; + } while (va != &pl->head); + +/* for(t = MAX_HUB_TRIES; t > 0; t--)*/ { + + for(n = 0; n < vtp0_len(&hubs); n++) { + int m; + vhub_t *h = *vtp0_get(&hubs, n, 0); + pcb_vnode_t *v = *vtp0_get(&h->node, 0, 0); + TRACE("hub %p at %mm;%mm:\n", h, v->point[0], v->point[1]); + for(m = 0; m < vtp0_len(&h->node); m++) { + v = *vtp0_get(&h->node, m, 0); + TRACE(" %d=%p\n", m, v); + /* try to split off a leaf loop from the hub */ + + if (pline_split_off_loop(&hubs, out, h, v)) { + vtp0_remove(&h->node, m, 1); + m--; + if (vtp0_len(&h->node) == 0) { + vtp0_uninit(&h->node); + free(h); + vtp0_remove(&hubs, n, 1); + n--; + break; + } + } + } + TRACE("\n"); + } + } + + vtp0_uninit(&hubs); +} Index: tags/2.1.2/src/polygon_selfi.h =================================================================== --- tags/2.1.2/src/polygon_selfi.h (nonexistent) +++ tags/2.1.2/src/polygon_selfi.h (revision 24813) @@ -0,0 +1,41 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2018 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +/* Resolve polygon self intersections */ + +#include +#include "polyarea.h" + +/* Returns whether a polyline is self-intersecting. O(n^2) */ +pcb_bool pcb_pline_is_selfint(pcb_pline_t *pl); + + +/* Assume pl is self-intersecting split it up into a list of freshly allocated + plines in out. Converts the original pline into a version that has a point + on each intersection; O(n^2) */ +void pcb_pline_split_selfint(pcb_pline_t *pl, vtp0_t *out); + + Index: tags/2.1.2/src/rats_act.c =================================================================== --- tags/2.1.2/src/rats_act.c (nonexistent) +++ tags/2.1.2/src/rats_act.c (revision 24813) @@ -0,0 +1,204 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * Copyright (C) 1997, 1998, 1999, 2000, 2001 Harry Eaton + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + * + * Old contact info: + * Harry Eaton, 6697 Buttonhole Ct, Columbia, MD 21044, USA + * haceaton@aplcomm.jhuapl.edu + * + */ +#include "config.h" +#include "conf_core.h" + +#include "board.h" +#include "data.h" +#include "error.h" +#include "undo.h" +#include "find.h" +#include "remove.h" +#include "funchash_core.h" +#include "obj_rat.h" +#include "actions.h" +#include "netlist2.h" +#include "draw.h" + +#include "obj_rat_draw.h" + + +static const char pcb_acts_AddRats[] = "AddRats(AllRats|SelectedRats|Close)"; +static const char pcb_acth_AddRats[] = "Add one or more rat lines to the board."; +/* DOC: addrats.html */ +static fgw_error_t pcb_act_AddRats(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + int op; + pcb_rat_t *shorty; + float len, small; + + PCB_ACT_CONVARG(1, FGW_KEYWORD, AddRats, op = fgw_keyword(&argv[1])); + + if (conf_core.temp.rat_warn) { + pcb_data_clear_flag(PCB->Data, PCB_FLAG_WARN, 1, 0); + pcb_draw(); + } + switch (op) { + case F_AllRats: + if (pcb_net_add_all_rats(PCB, PCB_RATACC_PRECISE | PCB_RATACC_INFO) > 0) + pcb_board_set_changed_flag(pcb_true); + break; + case F_SelectedRats: + case F_Selected: + if (pcb_net_add_all_rats(PCB, PCB_RATACC_PRECISE | PCB_RATACC_INFO | PCB_RATACC_ONLY_SELECTED) > 0) + pcb_board_set_changed_flag(pcb_true); + break; + case F_Close: + small = PCB_SQUARE(PCB_MAX_COORD); + shorty = NULL; + PCB_RAT_LOOP(PCB->Data); + { + if (PCB_FLAG_TEST(PCB_FLAG_SELECTED, line)) + continue; + len = PCB_SQUARE(line->Point1.X - line->Point2.X) + PCB_SQUARE(line->Point1.Y - line->Point2.Y); + if (len < small) { + small = len; + shorty = line; + } + } + PCB_END_LOOP; + if (shorty) { + pcb_undo_add_obj_to_flag(shorty); + PCB_FLAG_SET(PCB_FLAG_SELECTED, shorty); + pcb_rat_invalidate_draw(shorty); + pcb_draw(); + pcb_center_display((shorty->Point2.X + shorty->Point1.X) / 2, (shorty->Point2.Y + shorty->Point1.Y) / 2); + } + break; + + default: + PCB_ACT_FAIL(AddRats); + } + PCB_ACT_IRES(0); + return 0; +} + +static const char pcb_acts_Connection[] = "Connection(Find|ResetLinesAndPolygons|ResetPinsAndVias|Reset)"; +static const char pcb_acth_Connection[] = "Searches connections of the object at the cursor position."; +/* DOC: connection.html */ +static fgw_error_t pcb_act_Connection(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + int op; + + PCB_ACT_CONVARG(1, FGW_KEYWORD, Connection, op = fgw_keyword(&argv[1])); + + switch(op) { + case F_Find: + { + pcb_coord_t x, y; + unsigned long res; + pcb_find_t fctx; + pcb_hid_get_coords("Click on a connection", &x, &y, 0); + memset(&fctx, 0, sizeof(fctx)); + fctx.flag_set = PCB_FLAG_FOUND; + fctx.flag_chg_undoable = 1; + fctx.consider_rats = !!conf_core.editor.conn_find_rat; + res = pcb_find_from_xy(&fctx, PCB->Data, x, y); + pcb_message(PCB_MSG_INFO, "found %ld objects\n", res); + pcb_find_free(&fctx); + break; + } + + case F_ResetLinesAndPolygons: + case F_ResetLayerObjects: + if (pcb_data_clear_obj_flag(PCB->Data, PCB_OBJ_LINE | PCB_OBJ_ARC | PCB_OBJ_POLY | PCB_OBJ_TEXT, PCB_FLAG_FOUND, 1, 1) > 0) { + pcb_undo_inc_serial(); + pcb_draw(); + } + break; + + case F_ResetPinsViasAndPads: + case F_ResetPadstacks: + if (pcb_data_clear_obj_flag(PCB->Data, PCB_OBJ_PSTK, PCB_FLAG_FOUND, 1, 1) > 0) { + pcb_undo_inc_serial(); + pcb_draw(); + } + break; + + case F_Reset: + if (pcb_data_clear_flag(PCB->Data, PCB_FLAG_FOUND, 1, 1) > 0) { + pcb_undo_inc_serial(); + pcb_draw(); + } + break; + + default: + PCB_ACT_FAIL(Connection); + } + + PCB_ACT_IRES(0); + return 0; +} + +/* --------------------------------------------------------------------------- */ + +static const char pcb_acts_DeleteRats[] = "DeleteRats(AllRats|Selected|SelectedRats)"; +static const char pcb_acth_DeleteRats[] = "Delete rat lines."; +static fgw_error_t pcb_act_DeleteRats(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + int op; + + PCB_ACT_CONVARG(1, FGW_KEYWORD, DeleteRats, op = fgw_keyword(&argv[1])); + + if (conf_core.temp.rat_warn) { + pcb_data_clear_flag(PCB->Data, PCB_FLAG_WARN, 1, 0); + pcb_draw(); + } + switch(op) { + case F_AllRats: + if (pcb_rats_destroy(pcb_false)) + pcb_board_set_changed_flag(pcb_true); + break; + case F_SelectedRats: + case F_Selected: + if (pcb_rats_destroy(pcb_true)) + pcb_board_set_changed_flag(pcb_true); + break; + + default: + PCB_ACT_FAIL(DeleteRats); + } + + PCB_ACT_IRES(0); + return 0; +} + + +pcb_action_t rats_action_list[] = { + {"AddRats", pcb_act_AddRats, pcb_acth_AddRats, pcb_acts_AddRats}, + {"Connection", pcb_act_Connection, pcb_acth_Connection, pcb_acts_Connection}, + {"DeleteRats", pcb_act_DeleteRats, pcb_acth_DeleteRats, pcb_acts_DeleteRats} +}; + +PCB_REGISTER_ACTIONS(rats_action_list, NULL) Index: tags/2.1.2/src/rats_patch.c =================================================================== --- tags/2.1.2/src/rats_patch.c (nonexistent) +++ tags/2.1.2/src/rats_patch.c (revision 24813) @@ -0,0 +1,534 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2015..2019 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "rats_patch.h" +#include "genht/htsp.h" +#include "genht/hash.h" + +#include "config.h" +#include "actions.h" +#include "data.h" +#include "error.h" +#include "move.h" +#include "compat_misc.h" +#include "safe_fs.h" +#include "funchash_core.h" +#include "search.h" +#include "undo.h" +#include "conf_core.h" +#include "netlist2.h" + +static void rats_patch_remove(pcb_board_t *pcb, pcb_ratspatch_line_t * n, int do_free); + +const char *pcb_netlist_names[PCB_NUM_NETLISTS] = { + "input", + "edited" +}; + +void pcb_ratspatch_append(pcb_board_t *pcb, pcb_rats_patch_op_t op, const char *id, const char *a1, const char *a2) +{ + pcb_ratspatch_line_t *n; + + n = malloc(sizeof(pcb_ratspatch_line_t)); + + n->op = op; + n->id = pcb_strdup(id); + n->arg1.net_name = pcb_strdup(a1); + if (a2 != NULL) + n->arg2.attrib_val = pcb_strdup(a2); + else + n->arg2.attrib_val = NULL; + + /* link in */ + n->prev = pcb->NetlistPatchLast; + if (pcb->NetlistPatches != NULL) { + pcb->NetlistPatchLast->next = n; + pcb->NetlistPatchLast = n; + } + else + pcb->NetlistPatchLast = pcb->NetlistPatches = n; + n->next = NULL; +} + +static void rats_patch_free_fields(pcb_ratspatch_line_t *n) +{ + if (n->id != NULL) + free(n->id); + if (n->arg1.net_name != NULL) + free(n->arg1.net_name); + if (n->arg2.attrib_val != NULL) + free(n->arg2.attrib_val); +} + +void pcb_ratspatch_destroy(pcb_board_t *pcb) +{ + pcb_ratspatch_line_t *n, *next; + + for(n = pcb->NetlistPatches; n != NULL; n = next) { + next = n->next; + rats_patch_free_fields(n); + free(n); + } +} + +void pcb_ratspatch_append_optimize(pcb_board_t *pcb, pcb_rats_patch_op_t op, const char *id, const char *a1, const char *a2) +{ + pcb_rats_patch_op_t seek_op; + pcb_ratspatch_line_t *n; + + switch (op) { + case RATP_ADD_CONN: + seek_op = RATP_DEL_CONN; + break; + case RATP_DEL_CONN: + seek_op = RATP_ADD_CONN; + break; + case RATP_CHANGE_ATTRIB: + seek_op = RATP_CHANGE_ATTRIB; + break; + } + + /* keep the list clean: remove the last operation that becomes obsolete by the new one */ + for (n = pcb->NetlistPatchLast; n != NULL; n = n->prev) { + if ((n->op == seek_op) && (strcmp(n->id, id) == 0)) { + switch (op) { + case RATP_CHANGE_ATTRIB: + if (strcmp(n->arg1.attrib_name, a1) != 0) + break; + rats_patch_remove(pcb, n, 1); + goto quit; + case RATP_ADD_CONN: + case RATP_DEL_CONN: + if (strcmp(n->arg1.net_name, a1) != 0) + break; + rats_patch_remove(pcb, n, 1); + goto quit; + } + } + } + +quit:; + pcb_ratspatch_append(pcb, op, id, a1, a2); +} + +/* Unlink n from the list; if do_free is non-zero, also free fields and n */ +static void rats_patch_remove(pcb_board_t *pcb, pcb_ratspatch_line_t * n, int do_free) +{ + /* if we are the first or last... */ + if (n == pcb->NetlistPatches) + pcb->NetlistPatches = n->next; + if (n == pcb->NetlistPatchLast) + pcb->NetlistPatchLast = n->prev; + + /* extra ifs, just in case n is already unlinked */ + if (n->prev != NULL) + n->prev->next = n->next; + if (n->next != NULL) + n->next->prev = n->prev; + + if (do_free) { + rats_patch_free_fields(n); + free(n); + } +} + +static int rats_patch_apply_conn(pcb_board_t *pcb, pcb_ratspatch_line_t *patch, int del) +{ + pcb_net_t *net; + pcb_net_term_t *term; + char *sep, *termid; + int refdeslen; + + + sep = strchr(patch->id, '-'); + if (sep == NULL) + return 1; /* invalid id */ + termid = sep+1; + refdeslen = sep - patch->id; + if (refdeslen < 1) + return 1; /* invalid id */ + + net = pcb_net_get(pcb, &pcb->netlist[PCB_NETLIST_EDITED], patch->arg1.net_name, 1); + for(term = pcb_termlist_first(&net->conns); term != NULL; term = pcb_termlist_next(term)) { + if ((strncmp(patch->id, term->refdes, refdeslen) == 0) && (strcmp(termid, term->term) == 0)) { + if (del) { + /* want to delete and it's on the list */ + pcb_net_term_del(net, term); + return 0; + } + /* want to add, and pin is on the list -> already added */ + return 1; + } + } + + /* If we got here, pin is not on the list */ + if (del) + return 1; + + /* Wanted to add, let's add it */ + *sep = '\0'; + term = pcb_net_term_get(net, patch->id, termid, 1); + *sep = '-'; + if (term != NULL) + return 0; + return 1; +} + +int pcb_ratspatch_apply(pcb_board_t *pcb, pcb_ratspatch_line_t * patch) +{ + switch (patch->op) { + case RATP_ADD_CONN: + return rats_patch_apply_conn(pcb, patch, 0); + case RATP_DEL_CONN: + return rats_patch_apply_conn(pcb, patch, 1); + case RATP_CHANGE_ATTRIB: +TODO("just check wheter it is still valid") + break; + } + return 0; +} + +void pcb_ratspatch_make_edited(pcb_board_t *pcb) +{ + pcb_ratspatch_line_t *n; + + pcb_netlist_uninit(&(pcb->netlist[PCB_NETLIST_EDITED])); + pcb_netlist_init(&(pcb->netlist[PCB_NETLIST_EDITED])); + pcb_netlist_copy(pcb, &(pcb->netlist[PCB_NETLIST_EDITED]), &(pcb->netlist[PCB_NETLIST_INPUT])); + + for (n = pcb->NetlistPatches; n != NULL; n = n->next) + pcb_ratspatch_apply(pcb, n); +} + +int pcb_rats_patch_export(pcb_board_t *pcb, pcb_ratspatch_line_t *pat, pcb_bool need_info_lines, void (*cb)(void *ctx, pcb_rats_patch_export_ev_t ev, const char *netn, const char *key, const char *val), void *ctx) +{ + pcb_ratspatch_line_t *n; + + if (need_info_lines) { + htsp_t *seen; + seen = htsp_alloc(strhash, strkeyeq); + + /* have to print net_info lines */ + for (n = pat; n != NULL; n = n->next) { + switch (n->op) { + case RATP_ADD_CONN: + case RATP_DEL_CONN: + if (htsp_get(seen, n->arg1.net_name) == NULL) { + { + /* document the original (input) state */ + pcb_net_t *net = pcb_net_get(pcb, &pcb->netlist[PCB_NETLIST_INPUT], n->arg1.net_name, 0); + if (net != NULL) { + pcb_net_term_t *term; + htsp_set(seen, n->arg1.net_name, net); + cb(ctx, PCB_RPE_INFO_BEGIN, n->arg1.net_name, NULL, NULL); + for(term = pcb_termlist_first(&net->conns); term != NULL; term = pcb_termlist_next(term)) { + char *tmp = pcb_concat(term->refdes, "-", term->term, NULL); + cb(ctx, PCB_RPE_INFO_TERMINAL, n->arg1.net_name, NULL, tmp); + free(tmp); + } + cb(ctx, PCB_RPE_INFO_END, n->arg1.net_name, NULL, NULL); + } + } + } + case RATP_CHANGE_ATTRIB: + break; + } + } + htsp_free(seen); + } + + /* action lines */ + for (n = pat; n != NULL; n = n->next) { + switch (n->op) { + case RATP_ADD_CONN: + cb(ctx, PCB_RPE_CONN_ADD, n->arg1.net_name, NULL, n->id); + break; + case RATP_DEL_CONN: + cb(ctx, PCB_RPE_CONN_DEL, n->arg1.net_name, NULL, n->id); + break; + case RATP_CHANGE_ATTRIB: + cb(ctx, PCB_RPE_ATTR_CHG, n->id, n->arg1.attrib_name, n->arg2.attrib_val); + break; + } + } + return 0; +} + +typedef struct { + FILE *f; + const char *q, *po, *pc, *line_prefix; +} fexport_t; + +static void fexport_cb(void *ctx_, pcb_rats_patch_export_ev_t ev, const char *netn, const char *key, const char *val) +{ + fexport_t *ctx = ctx_; + switch(ev) { + case PCB_RPE_INFO_BEGIN: fprintf(ctx->f, "%snet_info%s%s%s%s", ctx->line_prefix, ctx->po, ctx->q, netn, ctx->q); break; + case PCB_RPE_INFO_TERMINAL: fprintf(ctx->f, " %s%s%s", ctx->q, val, ctx->q); break; + case PCB_RPE_INFO_END: fprintf(ctx->f, "%s\n", ctx->pc); break; + case PCB_RPE_CONN_ADD: fprintf(ctx->f, "%sadd_conn%s%s%s%s %s%s%s%s\n", ctx->line_prefix, ctx->po, ctx->q, val, ctx->q, ctx->q, netn, ctx->q, ctx->pc); break; + case PCB_RPE_CONN_DEL: fprintf(ctx->f, "%sdel_conn%s%s%s%s %s%s%s%s\n", ctx->line_prefix, ctx->po, ctx->q, val, ctx->q, ctx->q, netn, ctx->q, ctx->pc); break; + case PCB_RPE_ATTR_CHG: + fprintf(ctx->f, "%schange_attrib%s%s%s%s %s%s%s %s%s%s%s\n", + ctx->line_prefix, ctx->po, + ctx->q, netn, ctx->q, + ctx->q, key, ctx->q, + ctx->q, val, ctx->q, + ctx->pc); + } +} + +int pcb_ratspatch_fexport(pcb_board_t *pcb, FILE *f, int fmt_pcb) +{ + fexport_t ctx; + if (fmt_pcb) { + ctx.q = "\""; + ctx.po = "("; + ctx.pc = ")"; + ctx.line_prefix = "\t"; + } + else { + ctx.q = ""; + ctx.po = " "; + ctx.pc = ""; + ctx.line_prefix = ""; + } + ctx.f = f; + return pcb_rats_patch_export(pcb, pcb->NetlistPatches, !fmt_pcb, fexport_cb, &ctx); +} + +static const char pcb_acts_ReplaceFootprint[] = "ReplaceFootprint([Selected|Object], [footprint], [dumb])\n"; +static const char pcb_acth_ReplaceFootprint[] = "Replace the footprint of the selected components with the footprint specified."; +/* DOC: replacefootprint.html */ + +static int act_replace_footprint_dst(int op, pcb_subc_t **olds) +{ + int found = 0; + + switch(op) { + case F_Selected: + /* check if we have elements selected and quit if not */ + PCB_SUBC_LOOP(PCB->Data); + { + if (PCB_FLAG_TEST(PCB_FLAG_SELECTED, subc) && (subc->refdes != NULL)) { + found = 1; + break; + } + } + PCB_END_LOOP; + + if (!(found)) { + pcb_message(PCB_MSG_ERROR, "ReplaceFootprint(Selected) called with no selection\n"); + return 1; + } + break; + case F_Object: + { + void *ptr1, *ptr2, *ptr3; + pcb_objtype_t type = pcb_search_screen(pcb_crosshair.X, pcb_crosshair.Y, PCB_OBJ_SUBC, &ptr1, &ptr2, &ptr3); + if ((type != PCB_OBJ_SUBC) || (ptr1 == NULL)) { + pcb_message(PCB_MSG_ERROR, "ReplaceFootprint(Object): no subc under cursor\n"); + return 1; + } + *olds = ptr1; + } + break; + + default: + pcb_message(PCB_MSG_ERROR, "ReplaceFootprint(): invalid first argument\n"); + return 1; + } + return 0; +} + +static int act_replace_footprint_src(char *fpname, pcb_subc_t **news) +{ + int len, bidx; + const char *what, *what2; + + if (fpname == NULL) { + fpname = pcb_hid_prompt_for("Footprint name to use for replacement:", "", "Footprint"); + if (fpname == NULL) { + pcb_message(PCB_MSG_ERROR, "No footprint name supplied\n"); + return 1; + } + } + else + fpname = pcb_strdup(fpname); + + if (strcmp(fpname, "@buffer") != 0) { + /* check if the footprint is available */ + bidx = PCB_MAX_BUFFER-1; + pcb_buffer_load_footprint(&pcb_buffers[bidx], fpname, NULL); + what = "Footprint file "; + what2 = fpname; + } + else { + what = "Buffer"; + what2 = ""; + bidx = conf_core.editor.buffer_number; + } + + len = pcb_subclist_length(&pcb_buffers[bidx].Data->subc); + if (len == 0) { + pcb_message(PCB_MSG_ERROR, "%s%s contains no subcircuits\n", what, what2); + return 1; + } + + if (len > 1) { + pcb_message(PCB_MSG_ERROR, "%s%s contains multiple subcircuits\n", what, what2); + return 1; + } + *news = pcb_subclist_first(&pcb_buffers[bidx].Data->subc); + return 0; +} + + +static int act_replace_footprint(int op, pcb_subc_t *olds, pcb_subc_t *news, char *fpname, int dumb) +{ + int changed = 0; + pcb_subc_t *placed; + + pcb_undo_save_serial(); + switch(op) { + case F_Selected: + PCB_SUBC_LOOP(PCB->Data); + { + + if (!PCB_FLAG_TEST(PCB_FLAG_SELECTED, subc) || (subc->refdes == NULL)) + continue; + placed = pcb_subc_replace(PCB, subc, news, pcb_true, dumb); + if (placed != NULL) { + if (!dumb) + pcb_ratspatch_append_optimize(PCB, RATP_CHANGE_ATTRIB, placed->refdes, "footprint", fpname); + changed = 1; + } + } + PCB_END_LOOP; + break; + case F_Object: + placed = pcb_subc_replace(PCB, olds, news, pcb_true, dumb); + if (placed != NULL) { + if (!dumb) + pcb_ratspatch_append_optimize(PCB, RATP_CHANGE_ATTRIB, placed->refdes, "footprint", fpname); + changed = 1; + } + break; + } + + + pcb_undo_restore_serial(); + if (changed) { + pcb_undo_inc_serial(); + pcb_gui->invalidate_all(); + } + return 0; +} + + + +static fgw_error_t pcb_act_ReplaceFootprint(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + char *fpname = NULL, *dumbs = NULL; + pcb_subc_t *olds = NULL, *news; + int dumb = 0, op = F_Selected; + + PCB_ACT_MAY_CONVARG(1, FGW_KEYWORD, ReplaceFootprint, op = fgw_keyword(&argv[1])); + + if (act_replace_footprint_dst(op, &olds) != 0) { + PCB_ACT_IRES(1); + return 0; + } + + /* fetch the name of the new footprint */ + PCB_ACT_MAY_CONVARG(2, FGW_STR, ReplaceFootprint, fpname = pcb_strdup(argv[2].val.str)); + if (act_replace_footprint_src(fpname, &news) != 0) { + PCB_ACT_IRES(1); + return 0; + } + + PCB_ACT_MAY_CONVARG(3, FGW_STR, ReplaceFootprint, dumbs = argv[3].val.str); + if ((dumbs != NULL) && (strcmp(dumbs, "dumb") == 0)) + dumb = 1; + + + PCB_ACT_IRES(act_replace_footprint(op, olds, news, fpname, dumb)); + free(fpname); + return 0; +} + +static const char pcb_acts_SavePatch[] = "SavePatch(filename)"; +static const char pcb_acth_SavePatch[] = "Save netlist patch for back annotation."; +static fgw_error_t pcb_act_SavePatch(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + const char *fn = NULL; + FILE *f; + + PCB_ACT_MAY_CONVARG(1, FGW_STR, SavePatch, fn = argv[1].val.str); + + if (fn == NULL) { + char *default_file; + + if (PCB->Filename != NULL) { + char *end; + int len; + len = strlen(PCB->Filename); + default_file = malloc(len + 8); + memcpy(default_file, PCB->Filename, len + 1); + end = strrchr(default_file, '.'); + if ((end == NULL) || (pcb_strcasecmp(end, ".pcb") != 0)) + end = default_file + len; + strcpy(end, ".bap"); + } + else + default_file = pcb_strdup("unnamed.bap"); + + fn = pcb_gui->fileselect("Save netlist patch as ...", + "Choose a file to save netlist patch to\n" + "for back annotation\n", default_file, ".bap", NULL, "patch", 0, NULL); + + free(default_file); + } + + f = pcb_fopen(fn, "w"); + if (f == NULL) { + pcb_message(PCB_MSG_ERROR, "Can't open netlist patch file %s for writing\n", fn); + PCB_ACT_IRES(-1); + return 0; + } + pcb_ratspatch_fexport(PCB, f, 0); + fclose(f); + + PCB_ACT_IRES(0); + return 0; +} + +pcb_action_t rats_patch_action_list[] = { + {"ReplaceFootprint", pcb_act_ReplaceFootprint, pcb_acth_ReplaceFootprint, pcb_acts_ReplaceFootprint}, + {"SavePatch", pcb_act_SavePatch, pcb_acth_SavePatch, pcb_acts_SavePatch} +}; + +PCB_REGISTER_ACTIONS(rats_patch_action_list, NULL) Index: tags/2.1.2/src/rats_patch.h =================================================================== --- tags/2.1.2/src/rats_patch.h (nonexistent) +++ tags/2.1.2/src/rats_patch.h (revision 24813) @@ -0,0 +1,98 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2013..2015 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#ifndef PCB_RATS_PATCH_H +#define PCB_RATS_PATCH_H + +#include +#include "board.h" + +typedef enum { + RATP_ADD_CONN, + RATP_DEL_CONN, + RATP_CHANGE_ATTRIB +} pcb_rats_patch_op_t; + +struct pcb_ratspatch_line_s { + pcb_rats_patch_op_t op; + char *id; + union { + char *net_name; + char *attrib_name; + } arg1; + union { + char *attrib_val; + } arg2; + + pcb_ratspatch_line_t *prev, *next; +}; + + + +/* Single-word netlist class names */ +const char *pcb_netlist_names[PCB_NUM_NETLISTS]; + +/* Allocate and append a patch line to the patch list */ +void pcb_ratspatch_append(pcb_board_t *pcb, pcb_rats_patch_op_t op, const char *id, const char *a1, const char *a2); + +/* Free the patch list and all memory claimed by patch list items */ +void pcb_ratspatch_destroy(pcb_board_t *pcb); + +/* Same as pcb_ratspatch_append() but also optimize previous entries so that + redundant entries are removed */ +void pcb_ratspatch_append_optimize(pcb_board_t *pcb, pcb_rats_patch_op_t op, const char *id, const char *a1, const char *a2); + +/* Create [PCB_NETLIST_EDITED] from [PCB_NETLIST_INPUT] applying the patch */ +void pcb_ratspatch_make_edited(pcb_board_t *pcb); + +/* apply a single patch record on [PCB_NETLIST_EDITED]; returns non-zero on failure */ +int pcb_ratspatch_apply(pcb_board_t *pcb, pcb_ratspatch_line_t * patch); + +/**** exporter ****/ + +/* Special text exporter: + save all patch lines as an ordered list of text lines + if fmt is non-zero, generate pcb savefile compatible lines, else generate a back annotation patch */ +int pcb_ratspatch_fexport(pcb_board_t *pcb, FILE * f, int fmt_pcb); + +/* Generic, callback based exporter: */ + + /* EVENT ARGUMENTS */ +typedef enum { /* netn is always the net name, unless specified otherwise */ + PCB_RPE_INFO_BEGIN, /* netn */ + PCB_RPE_INFO_TERMINAL, /* netn; val is the terminal pin/pad name */ + PCB_RPE_INFO_END, /* netn */ + + PCB_RPE_CONN_ADD, /* netn; val is the terminal pin/pad name */ + PCB_RPE_CONN_DEL, /* netn; val is the terminal pin/pad name */ + PCB_RPE_ATTR_CHG /* netn; key is the attribute name, val is the new attribute value */ +} pcb_rats_patch_export_ev_t; + +/* Call cb() for each item to output; PCB_PTRE_INFO* is calculated/called only + if need_info_lines is true; the pcb pointer is used for looking up connections */ +int pcb_rats_patch_export(pcb_board_t *pcb, pcb_ratspatch_line_t *pat, pcb_bool need_info_lines, void (*cb)(void *ctx, pcb_rats_patch_export_ev_t ev, const char *netn, const char *key, const char *val), void *ctx); + +#endif Index: tags/2.1.2/src/remove.c =================================================================== --- tags/2.1.2/src/remove.c (nonexistent) +++ tags/2.1.2/src/remove.c (revision 24813) @@ -0,0 +1,117 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ +#include "config.h" +#include "conf_core.h" + +#include "board.h" +#include "draw.h" +#include "remove.h" +#include "select.h" +#include "undo.h" +#include "obj_arc_op.h" +#include "obj_line_op.h" +#include "obj_poly_op.h" +#include "obj_text_op.h" +#include "obj_rat_op.h" +#include "obj_subc_op.h" +#include "obj_pstk_op.h" + +static pcb_opfunc_t RemoveFunctions = { + pcb_lineop_remove, + pcb_textop_remove, + pcb_polyop_remove, + pcb_lineop_remove_point, + pcb_polyop_remove_point, + pcb_arcop_remove, + pcb_ratop_remove, + pcb_arcop_remove_point, + pcb_subcop_remove, + pcb_pstkop_remove +}; + +static pcb_opfunc_t DestroyFunctions = { + pcb_lineop_destroy, + pcb_textop_destroy, + pcb_polyop_destroy, + NULL, + pcb_polyop_destroy_point, + pcb_arcop_destroy, + pcb_ratop_destroy, + NULL, + pcb_subcop_destroy, + pcb_pstkop_destroy, +}; + +/* ---------------------------------------------------------------------- + * removes all selected and visible objects + * returns pcb_true if any objects have been removed + */ +pcb_bool pcb_remove_selected(pcb_bool locked_too) +{ + pcb_opctx_t ctx; + + ctx.remove.pcb = PCB; + ctx.remove.destroy_target = NULL; + + if (pcb_selected_operation(PCB, PCB->Data, &RemoveFunctions, &ctx, pcb_false, PCB_OBJ_ANY & (~PCB_OBJ_SUBC_PART), locked_too)) { + pcb_undo_inc_serial(); + pcb_draw(); + return pcb_true; + } + return pcb_false; +} + +/* --------------------------------------------------------------------------- + * remove object as referred by pointers and type, + * allocated memory is passed to the 'remove undo' list + */ +void *pcb_remove_object(int Type, void *Ptr1, void *Ptr2, void *Ptr3) +{ + pcb_opctx_t ctx; + void *ptr; + + ctx.remove.pcb = PCB; + ctx.remove.destroy_target = NULL; + + ptr = pcb_object_operation(&RemoveFunctions, &ctx, Type, Ptr1, Ptr2, Ptr3); + pcb_draw(); + return ptr; +} + +void *pcb_destroy_object(pcb_data_t *Target, pcb_objtype_t Type, void *Ptr1, void *Ptr2, void *Ptr3) +{ + void *res; + pcb_opctx_t ctx; + + ctx.remove.pcb = PCB; + ctx.remove.destroy_target = Target; + + res = pcb_object_operation(&DestroyFunctions, &ctx, Type, Ptr1, Ptr2, Ptr3); + pcb_draw(); + return res; +} Index: tags/2.1.2/src/remove.h =================================================================== --- tags/2.1.2/src/remove.h (nonexistent) +++ tags/2.1.2/src/remove.h (revision 24813) @@ -0,0 +1,48 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +/* Remove objects from the board */ + +#ifndef PCB_REMOVE_H +#define PCB_REMOVE_H + +#include "config.h" + +#define PCB_REMOVE_TYPES \ + (PCB_OBJ_PSTK | PCB_OBJ_LINE_POINT | PCB_OBJ_LINE | PCB_OBJ_TEXT | PCB_OBJ_SUBC | \ + PCB_OBJ_POLY_POINT | PCB_OBJ_POLY | PCB_OBJ_RAT | PCB_OBJ_ARC | PCB_OBJ_ARC_POINT) + +pcb_bool pcb_remove_selected(pcb_bool locked_too); + +/* Undoable delete (operation wrapper) */ +void *pcb_remove_object(int Type, void *Ptr1, void *Ptr2, void *Ptr3); + +/* Non-undoable delete (operation wrapper) */ +void *pcb_destroy_object(pcb_data_t *Target, pcb_objtype_t Type, void *Ptr1, void *Ptr2, void *Ptr3); + +#endif Index: tags/2.1.2/src/remove_act.c =================================================================== --- tags/2.1.2/src/remove_act.c (nonexistent) +++ tags/2.1.2/src/remove_act.c (revision 24813) @@ -0,0 +1,96 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * Copyright (C) 1997, 1998, 1999, 2000, 2001 Harry Eaton + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + * + * Old contact info: + * Harry Eaton, 6697 Buttonhole Ct, Columbia, MD 21044, USA + * haceaton@aplcomm.jhuapl.edu + * + */ +#include "config.h" +#include "data.h" +#include "actions.h" +#include "tool.h" +#include "remove.h" +#include "board.h" +#include "funchash_core.h" + +static const char pcb_acts_Delete[] = "Delete(Object|Selected)\n" "Delete(AllRats|SelectedRats)"; +static const char pcb_acth_Delete[] = "Delete stuff."; +static fgw_error_t pcb_act_Delete(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + int id; + + PCB_ACT_CONVARG(1, FGW_KEYWORD, Delete, id = fgw_keyword(&argv[1])); + + if (id == -1) { /* no arg */ + if (pcb_remove_selected(pcb_false) == pcb_false) + id = F_Object; + } + + switch(id) { + case F_Object: + pcb_hid_get_coords("Click on object to delete", &pcb_tool_note.X, &pcb_tool_note.Y, 0); + pcb_tool_save(); + pcb_tool_select_by_id(PCB_MODE_REMOVE); + pcb_notify_mode(); + pcb_tool_restore(); + break; + case F_Selected: + pcb_remove_selected(pcb_false); + break; + case F_AllRats: + if (pcb_rats_destroy(pcb_false)) + pcb_board_set_changed_flag(pcb_true); + break; + case F_SelectedRats: + if (pcb_rats_destroy(pcb_true)) + pcb_board_set_changed_flag(pcb_true); + break; + } + + PCB_ACT_IRES(0); + return 0; +} + +static const char pcb_acts_RemoveSelected[] = "pcb_remove_selected()"; +static const char pcb_acth_RemoveSelected[] = "Removes any selected objects."; +static fgw_error_t pcb_act_RemoveSelected(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + if (pcb_remove_selected(pcb_false)) + pcb_board_set_changed_flag(pcb_true); + PCB_ACT_IRES(0); + return 0; +} + + +pcb_action_t remove_action_list[] = { + {"Delete", pcb_act_Delete, pcb_acth_Delete, pcb_acts_Delete}, + {"RemoveSelected", pcb_act_RemoveSelected, pcb_acth_RemoveSelected, pcb_acts_RemoveSelected} +}; + +PCB_REGISTER_ACTIONS(remove_action_list, NULL) Index: tags/2.1.2/src/rotate.c =================================================================== --- tags/2.1.2/src/rotate.c (nonexistent) +++ tags/2.1.2/src/rotate.c (revision 24813) @@ -0,0 +1,175 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ +#include "config.h" + +#include + +#include "board.h" +#include "data.h" +#include "draw.h" +#include "error.h" +#include "polygon.h" +#include "rotate.h" +#include "search.h" +#include "select.h" +#include "undo.h" +#include "event.h" +#include "conf_core.h" +#include "obj_arc_op.h" +#include "obj_line_op.h" +#include "obj_poly_op.h" +#include "obj_text_op.h" +#include "obj_subc_op.h" +#include "obj_pstk_op.h" + +#include "obj_line_draw.h" +#include "obj_rat_draw.h" + +pcb_opfunc_t Rotate90Functions = { + pcb_lineop_rotate90, + pcb_textop_rotate90, + pcb_polyop_rotate90, + pcb_lineop_rotate90_point, + NULL, + pcb_arcop_rotate90, + NULL, + NULL, + pcb_subcop_rotate90, + pcb_pstkop_rotate90 +}; + +pcb_opfunc_t RotateFunctions = { + pcb_lineop_rotate, + pcb_textop_rotate, + pcb_polyop_rotate, + NULL, + NULL, + pcb_arcop_rotate, + NULL, + NULL, + pcb_subcop_rotate, + pcb_pstkop_rotate +}; + +/* --------------------------------------------------------------------------- + * rotates a point in 90 degree steps + */ +void pcb_point_rotate90(pcb_point_t *Point, pcb_coord_t X, pcb_coord_t Y, unsigned Number) +{ + PCB_COORD_ROTATE90(Point->X, Point->Y, X, Y, Number); +} + +void *pcb_obj_rotate90(int Type, void *Ptr1, void *Ptr2, void *Ptr3, pcb_coord_t X, pcb_coord_t Y, unsigned Steps) +{ + void *ptr2; + int changed = 0; + pcb_opctx_t ctx; + + /* setup default global identifiers */ + ctx.rotate.pcb = PCB; + ctx.rotate.number = Steps; + ctx.rotate.center_x = X; + ctx.rotate.center_y = Y; + + pcb_event(PCB_EVENT_RUBBER_ROTATE90, "ipppccip", Type, Ptr1, Ptr2, Ptr2, ctx.rotate.center_x, ctx.rotate.center_y, ctx.rotate.number, &changed); + + if (Type != PCB_OBJ_PSTK) /* padstack has its own way doing the rotation-undo */ + pcb_undo_add_obj_to_rotate90(Type, Ptr1, Ptr2, Ptr3, ctx.rotate.center_x, ctx.rotate.center_y, ctx.rotate.number); + ptr2 = pcb_object_operation(&Rotate90Functions, &ctx, Type, Ptr1, Ptr2, Ptr3); + changed |= (ptr2 != NULL); + if (changed) { + pcb_draw(); + pcb_undo_inc_serial(); + } + return ptr2; +} + +void *pcb_obj_rotate(int Type, void *Ptr1, void *Ptr2, void *Ptr3, pcb_coord_t X, pcb_coord_t Y, pcb_angle_t angle) +{ + void *ptr2; + int changed = 0; + pcb_opctx_t ctx; + + /* setup default global identifiers */ + ctx.rotate.pcb = PCB; + ctx.rotate.angle = angle; + ctx.rotate.center_x = X; + ctx.rotate.center_y = Y; + + pcb_event(PCB_EVENT_RUBBER_ROTATE, "ipppccip", Type, Ptr1, Ptr2, Ptr2, ctx.rotate.center_x, ctx.rotate.center_y, ctx.rotate.angle, &changed); + + if (Type != PCB_OBJ_PSTK) /* padstack has its own way doing the rotation-undo */ + pcb_undo_add_obj_to_rotate(Type, Ptr1, Ptr2, Ptr3, ctx.rotate.center_x, ctx.rotate.center_y, ctx.rotate.angle); + ptr2 = pcb_object_operation(&RotateFunctions, &ctx, Type, Ptr1, Ptr2, Ptr3); + changed |= (ptr2 != NULL); + if (changed) { + pcb_draw(); + pcb_undo_inc_serial(); + } + return ptr2; +} + +void pcb_screen_obj_rotate90(pcb_coord_t X, pcb_coord_t Y, unsigned Steps) +{ + int type; + void *ptr1, *ptr2, *ptr3; + if ((type = pcb_search_screen(X, Y, PCB_ROTATE_TYPES | PCB_LOOSE_SUBC, &ptr1, &ptr2, &ptr3)) != PCB_OBJ_VOID) { + pcb_any_obj_t *obj = (pcb_any_obj_t *)ptr2; + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, obj)) { + pcb_message(PCB_MSG_WARNING, "Sorry, %s object is locked\n", pcb_obj_type_name(obj->type)); + return; + } + pcb_event(PCB_EVENT_RUBBER_RESET, NULL); + if (conf_core.editor.rubber_band_mode) + pcb_event(PCB_EVENT_RUBBER_LOOKUP_LINES, "ippp", type, ptr1, ptr2, ptr3); + if (type == PCB_OBJ_SUBC) + pcb_event(PCB_EVENT_RUBBER_LOOKUP_RATS, "ippp", type, ptr1, ptr2, ptr3); + pcb_obj_rotate90(type, ptr1, ptr2, ptr3, X, Y, Steps); + pcb_board_set_changed_flag(pcb_true); + } +} + +void pcb_screen_obj_rotate(pcb_coord_t X, pcb_coord_t Y, pcb_angle_t angle) +{ + int type; + void *ptr1, *ptr2, *ptr3; + if ((type = pcb_search_screen(X, Y, PCB_ROTATE_TYPES | PCB_LOOSE_SUBC, &ptr1, &ptr2, &ptr3)) != PCB_OBJ_VOID) { + pcb_any_obj_t *obj = (pcb_any_obj_t *)ptr2; + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, obj)) { + pcb_message(PCB_MSG_WARNING, "Sorry, %s object is locked\n", pcb_obj_type_name(obj->type)); + return; + } + pcb_event(PCB_EVENT_RUBBER_RESET, NULL); + if (conf_core.editor.rubber_band_mode) + pcb_event(PCB_EVENT_RUBBER_LOOKUP_LINES, "ippp", type, ptr1, ptr2, ptr3); + if (type == PCB_OBJ_SUBC) + pcb_event(PCB_EVENT_RUBBER_LOOKUP_RATS, "ippp", type, ptr1, ptr2, ptr3); + pcb_obj_rotate(type, ptr1, ptr2, ptr3, X, Y, angle); + pcb_board_set_changed_flag(pcb_true); + } +} Index: tags/2.1.2/src/rotate.h =================================================================== --- tags/2.1.2/src/rotate.h (nonexistent) +++ tags/2.1.2/src/rotate.h (revision 24813) @@ -0,0 +1,82 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +#ifndef PCB_ROTATE_H +#define PCB_ROTATE_H + +#include "config.h" +#include "global_typedefs.h" +#include "compat_misc.h" + +/*** Transformation macros ***/ +#define PCB_COORD_ROTATE90(x,y,x0,y0,n) \ + do { \ + pcb_coord_t dx = (x)-(x0), \ + dy = (y)-(y0); \ + \ + switch(n & 0x03) \ + { \ + case 1: (x)=(x0)+dy; (y)=(y0)-dx; \ + break; \ + case 2: (x)=(x0)-dx; (y)=(y0)-dy; \ + break; \ + case 3: (x)=(x0)-dy; (y)=(y0)+dx; \ + break; \ + default: break; \ + } \ + } while(0) + +#define PCB_ROTATE_TYPES (PCB_OBJ_PSTK | PCB_OBJ_SUBC | PCB_OBJ_TEXT | PCB_OBJ_ARC | PCB_OBJ_LINE_POINT | PCB_OBJ_LINE | PCB_OBJ_POLY | PCB_OBJ_FLOATER) + +/* rotates an object passed; + * the center of rotation is determined by the current cursor location + */ +void *pcb_obj_rotate90(int, void *, void *, void *, pcb_coord_t, pcb_coord_t, unsigned); + +/* rotates an objects passed; + * the center of rotation is determined by the current cursor location */ +void *pcb_obj_rotate(int Type, void *Ptr1, void *Ptr2, void *Ptr3, pcb_coord_t X, pcb_coord_t Y, pcb_angle_t angle); + +void pcb_screen_obj_rotate90(pcb_coord_t, pcb_coord_t, unsigned); +void pcb_screen_obj_rotate(pcb_coord_t X, pcb_coord_t Y, pcb_angle_t angle); +void pcb_point_rotate90(pcb_point_t *Point, pcb_coord_t X, pcb_coord_t Y, unsigned Number); + +PCB_INLINE void pcb_rotate(pcb_coord_t * x, pcb_coord_t * y, pcb_coord_t cx, pcb_coord_t cy, double cosa, double sina) +{ + double nx, ny; + pcb_coord_t px = *x - cx; + pcb_coord_t py = *y - cy; + + nx = pcb_round(px * cosa + py * sina + cx); + ny = pcb_round(py * cosa - px * sina + cy); + + *x = nx; + *y = ny; +} + +#endif Index: tags/2.1.2/src/route.c =================================================================== --- tags/2.1.2/src/route.c (nonexistent) +++ tags/2.1.2/src/route.c (revision 24813) @@ -0,0 +1,729 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996, 2004 Thomas Nau + * Copyright (C) 2017 Adrian Purser + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ +#include "config.h" + +#include "compat_misc.h" +#include "conf_core.h" +#include "math_helper.h" +#include "board.h" +#include "data.h" +#include "find.h" +#include "polygon.h" +#include "rtree.h" +#include "route.h" +#include "undo.h" +#include "obj_line_draw.h" +#include "obj_arc_draw.h" +#include "route_draw.h" +#include "obj_line.h" +#include "obj_line_op.h" +#include "draw_wireframe.h" + +void pcb_route_init(pcb_route_t *p_route) +{ + p_route->size = 0; + p_route->capacity = ROUTE_SMALL_DATA_SIZE; + p_route->objects = &p_route->small_data[0]; +} + +void pcb_route_destroy(pcb_route_t *p_route) +{ + if (p_route->capacity > ROUTE_SMALL_DATA_SIZE) + free(p_route->objects); + p_route->size = 0; + p_route->capacity = ROUTE_SMALL_DATA_SIZE; + p_route->objects = &p_route->small_data[0]; +} + +void pcb_route_reset(pcb_route_t *p_route) +{ + /* NOTE: Currently this function just sets the size back to zero. It does not + free any memory used so the capacity will stay the same. + */ + + p_route->size = 0; +} + +void pcb_route_reserve(pcb_route_t *p_route, int size) +{ + int grow; + + if (size <= p_route->capacity) + return; + + grow = size - p_route->capacity; + if (grow < 8) + grow = 8; + + if (p_route->capacity == ROUTE_SMALL_DATA_SIZE) { + p_route->capacity += grow; + p_route->objects = (pcb_route_object_t *) malloc(p_route->capacity * sizeof(pcb_route_object_t)); + memcpy(p_route->objects, &p_route->small_data[0], p_route->size * sizeof(pcb_route_object_t)); + } + else { + p_route->capacity += grow; + p_route->objects = (pcb_route_object_t *) realloc(p_route->objects, p_route->capacity * sizeof(pcb_route_object_t)); + } +} + +void pcb_route_resize(pcb_route_t *p_route, int size) +{ + pcb_route_reserve(p_route, size); + p_route->size = size; +} + +pcb_route_object_t *pcb_route_alloc_object(pcb_route_t *p_route) +{ + pcb_route_resize(p_route, p_route->size + 1); + return &p_route->objects[p_route->size - 1]; +} + +void pcb_route_add_line(pcb_route_t *p_route, pcb_point_t *point1, pcb_point_t *point2, pcb_layer_id_t layer) +{ + pcb_route_object_t *p_object = pcb_route_alloc_object(p_route); + if (p_object == NULL) + return; + + p_object->point1 = *point1; + p_object->point2 = *point2; + p_object->layer = layer; + p_object->type = PCB_OBJ_LINE; + p_route->end_point = *point2; +} + +void pcb_route_add_arc(pcb_route_t *p_route, pcb_point_t *center, pcb_angle_t start_angle, pcb_angle_t delta, pcb_coord_t radius, pcb_layer_id_t layer) +{ + pcb_route_object_t *p_object = pcb_route_alloc_object(p_route); + if (p_object == NULL) + return; + + p_object->point1 = *center; + p_object->start_angle = start_angle; + p_object->delta_angle = delta; + p_object->radius = radius; + p_object->layer = layer; + p_object->type = PCB_OBJ_ARC; + + p_route->end_point.X = pcb_round((double)center->X - ((double)radius * cos((start_angle + delta) * PCB_M180))); + p_route->end_point.Y = pcb_round((double)center->Y + ((double)radius * sin((start_angle + delta) * PCB_M180))); +} + + +void pcb_route_direct(pcb_board_t *PCB, pcb_route_t *route, pcb_point_t *point1, pcb_point_t *point2, pcb_layer_id_t layer, pcb_coord_t thickness, pcb_coord_t clearance, pcb_flag_t flags) +{ + pcb_route_reset(route); + route->start_point = *point1; + route->end_point = *point2; + route->start_layer = layer; + route->end_layer = layer; + route->thickness = thickness; + route->clearance = clearance; + route->PCB = PCB; + route->flags = flags; + pcb_route_add_line(route, point1, point2, layer); +} + +/*----------------------------------------------------------- + * Calculate an arc fitted to a corner. + *---------------------------------------------------------*/ + +void pcb_route_calculate_corner_arc(const pcb_point_t *point1, const pcb_point_t *point2, const pcb_point_t *point3, double radius, pcb_route_object_t *p_out_obj, pcb_point_t *p_endpoint1, pcb_point_t *p_endpoint2) +{ + const double r_min = 10.0; + + const pcb_coord_t dx1 = point1->X - point2->X; + const pcb_coord_t dy1 = point1->Y - point2->Y; + const pcb_coord_t dx2 = point3->X - point2->X; + const pcb_coord_t dy2 = point3->Y - point2->Y; + + const double angle1 = atan2(dy1, dx1); + const double angle2 = atan2(dy2, dx2); + + const double ad = angle2 - angle1; + const double d = ad > M_PI ? ad - (M_PI * 2.0) : (ad < -M_PI ? ad + (M_PI * 2.0) : ad); + + const double hangle = fabs(d * 0.5); + const double angle3 = angle1 + (d * 0.5); + + /* Vector from point2 to the other points */ + const double vx1 = cos(angle1); + const double vy1 = sin(angle1); + const double vx2 = cos(angle2); + const double vy2 = sin(angle2); + + /* Distance from point2 to the other points */ + const double l1 = fabs(abs(vx1) > fabs(vy1) ? dx1 / vx1 : dy1 / vy1); + const double l2 = fabs(abs(vx2) > fabs(vy2) ? dx2 / vx2 : dy2 / vy2); + + /* Calculate maximum possible radius */ + const double rmax = (l1 < l2 ? l1 : l2) * tan(hangle); + const double r = rmax < radius ? rmax : radius; + + if (r >= r_min) { + /* Calculate arc center coordinates. */ + const double sh = sin(hangle); + const pcb_coord_t xc = point2->X + (pcb_coord_t) ((cos(angle3) * r) / sh); + const pcb_coord_t yc = point2->Y + (pcb_coord_t) ((sin(angle3) * r) / sh); + + /* Calculate arc start and delta angles. */ + const double delta = d < 0 ? -(M_PI + d) : M_PI - d; + const double start = (d < 0.0 ? (M_PI * 0.5) - angle1 : ((M_PI * 0.5) - angle2) - delta); + + p_out_obj->point1.X = xc; + p_out_obj->point1.Y = yc; + p_out_obj->start_angle = start * PCB_RAD_TO_DEG; /* Start Angle */ + p_out_obj->delta_angle = delta * PCB_RAD_TO_DEG; /* Delta Angle */ + p_out_obj->radius = r; + + if (p_endpoint1) { + p_endpoint1->X = xc - (pcb_coord_t) (r * cos(start)); + p_endpoint1->Y = yc + (pcb_coord_t) (r * sin(start)); + } + + if (p_endpoint1) { + p_endpoint2->X = xc - (pcb_coord_t) (r * cos(start + delta)); + p_endpoint2->Y = yc + (pcb_coord_t) (r * sin(start + delta)); + } + } + else { + if (p_endpoint1) + *p_endpoint1 = *point2; + + if (p_endpoint2) + *p_endpoint2 = *point2; + } +} + +void pcb_route_calculate_45(pcb_point_t *start_point, pcb_point_t *target_point) +{ + + pcb_coord_t dx, dy, min; + unsigned direction = 0; + double m; + + /* first calculate direction of line */ + dx = target_point->X - start_point->X; + dy = target_point->Y - start_point->Y; + + if (!dx) { + if (!dy) + /* zero length line, don't draw anything */ + return; + else + direction = dy > 0 ? 0 : 4; + } + else { + m = (double)dy / dx; + direction = 2; + if (m > PCB_TAN_30_DEGREE) + direction = m > PCB_TAN_60_DEGREE ? 0 : 1; + else if (m < -PCB_TAN_30_DEGREE) + direction = m < -PCB_TAN_60_DEGREE ? 0 : 3; + } + + if (dx < 0) + direction += 4; + + dx = coord_abs(dx); + dy = coord_abs(dy); + min = MIN(dx, dy); + + /* now set up the second pair of coordinates */ + switch (direction) { + case 0: + case 4: + target_point->X = start_point->X; + break; + + case 2: + case 6: + target_point->Y = start_point->Y; + break; + + case 1: + target_point->X = start_point->X + min; + target_point->Y = start_point->Y + min; + break; + + case 3: + target_point->X = start_point->X + min; + target_point->Y = start_point->Y - min; + break; + + case 5: + target_point->X = start_point->X - min; + target_point->Y = start_point->Y - min; + break; + + case 7: + target_point->X = start_point->X - min; + target_point->Y = start_point->Y + min; + break; + } +} + +void pcb_route_start(pcb_board_t *PCB, pcb_route_t *route, pcb_point_t *point, pcb_layer_id_t layer_id, pcb_coord_t thickness, pcb_coord_t clearance, pcb_flag_t flags) +{ + /* Restart the route */ + pcb_route_reset(route); + route->start_point = *point; + route->end_point = *point; + route->thickness = thickness; + route->clearance = clearance; + route->start_layer = layer_id; + route->end_layer = layer_id; + route->PCB = PCB; + route->flags = flags; +} + +void pcb_route_calculate_to(pcb_route_t *route, pcb_point_t *point, int mod1, int mod2) +{ + TODO("If an external route calculator has been selected then use it instead of this default one.") + TODO("Add DRC Checking") + + pcb_point_t *point1 = &route->end_point; + pcb_point_t *point2 = point; + pcb_layer_id_t layer_id = route->end_layer; + + /* Set radius to 0 for standard 45/90 operation */ + const pcb_coord_t radius = route->thickness * conf_core.editor.route_radius; + + /* If the start point is the same as the end point then add a single 0-length line. + * If a 0-length line is not added then some operations such as moving a line point + * could cause the line to disappear. + */ + if ((point1->X == point2->X) && (point1->Y == point2->Y)) { + route->end_point = *point2; + pcb_route_add_line(route, point1, point2, layer_id); + } + /* If Refraction is 0 then add a single line segment that is horizontal, vertical or 45 degrees. + * This line segment might not end under the crosshair. + */ + else if (conf_core.editor.line_refraction == 0) { + pcb_point_t target = *point2; + pcb_route_calculate_45(point1, &target); + pcb_route_add_line(route, point1, &target, layer_id); + route->end_point = target; + } + else { + /* Refraction is non-zero so add multiple lines (horizontal, vertical and/or 45 degrees). */ + pcb_coord_t dx, dy; + pcb_point_t target; + pcb_bool way = (conf_core.editor.line_refraction == 1 ? pcb_false : pcb_true); + + /* swap the 'way' if mod1 is set (typically the shift key) */ + if (mod1) + way = !way; + + dx = point2->X - point1->X; + dy = point2->Y - point1->Y; + + if (!way) { + if (coord_abs(dx) > coord_abs(dy)) { + target.X = point2->X - SGN(dx) * coord_abs(dy); + target.Y = point1->Y; + } + else { + target.X = point1->X; + target.Y = point2->Y - SGN(dy) * coord_abs(dx); + } + } + else { + if (coord_abs(dx) > coord_abs(dy)) { + target.X = point1->X + SGN(dx) * coord_abs(dy); + target.Y = point2->Y; + } + else { + target.X = point2->X; + target.Y = point1->Y + SGN(dy) * coord_abs(dx);; + } + } + + if (radius > 0.0) { + pcb_route_object_t arc; + pcb_point_t target1; + pcb_point_t target2; + + pcb_route_calculate_corner_arc(point1, &target, point2, radius, &arc, &target1, &target2); + + if ((point1->X != target1.X) || (point1->Y != target1.Y)) + pcb_route_add_line(route, point1, &target1, layer_id); + + if ((target1.X != target2.X) || (target1.Y != target2.Y)) + pcb_route_add_arc(route, &arc.point1, arc.start_angle, arc.delta_angle, arc.radius, layer_id); + + if ((point2->X != target2.X) || (point2->Y != target2.Y)) + pcb_route_add_line(route, &target2, point2, layer_id); + + route->end_point = *point2; + } + else { + if ((point1->X != target.X) || (point1->Y != target.Y)) + pcb_route_add_line(route, point1, &target, layer_id); + if ((point2->X != target.X) || (point2->Y != target.Y)) + pcb_route_add_line(route, &target, point2, layer_id); + route->end_point = *point2; + } + } + +} + +TODO("Pass in other required information such as object flags") +void pcb_route_calculate(pcb_board_t *PCB, pcb_route_t *route, pcb_point_t *point1, pcb_point_t *point2, pcb_layer_id_t layer_id, pcb_coord_t thickness, pcb_coord_t clearance, pcb_flag_t flags, int mod1, int mod2) +{ + /* Set radius to 0 for standard 45/90 operation */ +/* const pcb_coord_t radius = thickness * conf_core.editor.route_radius; - TODO: remove this if not needed */ + + pcb_route_start(PCB, route, point1, layer_id, thickness, clearance, flags); + + /* If the line can be drawn directly to the target then add a single line segment. */ + if (conf_core.editor.all_direction_lines) { + pcb_route_add_line(route, point1, point2, layer_id); + return; + } + + pcb_route_calculate_to(route, point2, mod1, mod2); +} + +int pcb_route_apply(const pcb_route_t *p_route) +{ + return pcb_route_apply_to_line(p_route, NULL, NULL); +} + +int pcb_route_apply_to_line(const pcb_route_t *p_route, pcb_layer_t *apply_to_line_layer, pcb_line_t *apply_to_line) +{ + int i; + int applied = 0; + + for(i = 0; i < p_route->size; i++) { + pcb_route_object_t const *p_obj = &p_route->objects[i]; + pcb_layer_t *layer = pcb_loose_subc_layer(PCB, pcb_get_layer(PCB->Data, p_obj->layer), pcb_true); + + switch (p_obj->type) { + case PCB_OBJ_LINE: + /* If the route is being applied to an existing line then the existing + line will be used as the first line in the route. This maintains the + ID of the line and line points. This is especially useful if the + route contains a single line. + */ + if (apply_to_line) { + /* Move the existing line points to the position of the route line. */ + if ((p_obj->point1.X != apply_to_line->Point1.X) || (p_obj->point1.Y != apply_to_line->Point1.Y)) + pcb_undo_add_obj_to_move(PCB_OBJ_LINE_POINT, apply_to_line_layer, apply_to_line, &apply_to_line->Point1, p_obj->point1.X - apply_to_line->Point1.X, p_obj->point1.Y - apply_to_line->Point1.Y); + + if ((p_obj->point2.X != apply_to_line->Point2.X) || (p_obj->point2.Y != apply_to_line->Point2.Y)) + pcb_undo_add_obj_to_move(PCB_OBJ_LINE_POINT, apply_to_line_layer, apply_to_line, &apply_to_line->Point2, p_obj->point2.X - apply_to_line->Point2.X, p_obj->point2.Y - apply_to_line->Point2.Y); + + /* Move the existing line point/s */ + pcb_line_invalidate_erase(apply_to_line); + pcb_r_delete_entry(apply_to_line_layer->line_tree, (pcb_box_t *) apply_to_line); + pcb_poly_restore_to_poly(PCB->Data, PCB_OBJ_LINE, apply_to_line_layer, apply_to_line); + apply_to_line->Point1.X = p_obj->point1.X; + apply_to_line->Point1.Y = p_obj->point1.Y; + apply_to_line->Point2.X = p_obj->point2.X; + apply_to_line->Point2.Y = p_obj->point2.Y; + pcb_line_bbox(apply_to_line); + pcb_r_insert_entry(layer->line_tree, (pcb_box_t *) apply_to_line); + pcb_poly_clear_from_poly(PCB->Data, PCB_OBJ_LINE, layer, apply_to_line); + pcb_line_invalidate_draw(layer, apply_to_line); + apply_to_line_layer = layer; + + /* The existing line has been used so forget about it. */ + apply_to_line = NULL; + applied = 1; + } + else { + /* Create a new line */ + pcb_line_t *line = pcb_line_new_merge(layer, + p_obj->point1.X, + p_obj->point1.Y, + p_obj->point2.X, + p_obj->point2.Y, + p_route->thickness, + p_route->clearance, + p_route->flags); + if (line) { + pcb_added_lines++; + pcb_obj_add_attribs(line, PCB->pen_attr); + pcb_line_invalidate_draw(layer, line); + pcb_undo_add_obj_to_create(PCB_OBJ_LINE, layer, line, line); + applied = 1; + } + } + break; + + case PCB_OBJ_ARC: + { + /* Create a new arc */ + pcb_arc_t *arc = pcb_arc_new(layer, + p_obj->point1.X, + p_obj->point1.Y, + p_obj->radius, + p_obj->radius, + p_obj->start_angle, + p_obj->delta_angle, + p_route->thickness, + p_route->clearance, + p_route->flags, pcb_true); + if (arc) { + pcb_added_lines++; + pcb_obj_add_attribs(arc, PCB->pen_attr); + pcb_undo_add_obj_to_create(PCB_OBJ_ARC, layer, arc, arc); + pcb_arc_invalidate_draw(layer, arc); + applied = 1; + } + } + break; + + default: + break; + } + } + + /* If the existing apply-to-line wasn't updated then it should be deleted */ + /* (This can happen if the route does not contain any lines.) */ + if (apply_to_line != NULL) + pcb_line_destroy(apply_to_line_layer, apply_to_line); + + if (applied) + pcb_subc_as_board_update(PCB); + + return applied; +} + +int pcb_route_apply_to_arc(const pcb_route_t *p_route, pcb_layer_t *apply_to_arc_layer, pcb_arc_t *apply_to_arc) +{ + int i; + int applied = 0; + + for(i = 0; i < p_route->size; i++) { + pcb_route_object_t const *p_obj = &p_route->objects[i]; + pcb_layer_t *layer = pcb_loose_subc_layer(PCB, pcb_get_layer(PCB->Data, p_obj->layer), pcb_true); + + switch (p_obj->type) { + case PCB_OBJ_ARC: + /* If the route is being applied to an existing arc then the existing + arc will be used as the first arc in the route. This maintains the + ID of the arc. + */ + if (apply_to_arc) { + int changes = 0; + + /* Move the existing line points to the position of the route line. */ + if ((p_obj->radius != apply_to_arc->Width) || (p_obj->radius != apply_to_arc->Height)) { + pcb_undo_add_obj_to_change_radii(PCB_OBJ_ARC, apply_to_arc, apply_to_arc, apply_to_arc); + ++changes; + } + + if ((p_obj->start_angle != apply_to_arc->StartAngle) || (p_obj->delta_angle != apply_to_arc->Delta)) { + pcb_undo_add_obj_to_change_angles(PCB_OBJ_ARC, apply_to_arc, apply_to_arc, apply_to_arc); + ++changes; + } + + if (p_route->thickness != apply_to_arc->Thickness) { + pcb_undo_add_obj_to_size(PCB_OBJ_ARC, apply_to_arc_layer, apply_to_arc, apply_to_arc); + ++changes; + } + + if ((p_obj->point1.X != apply_to_arc->X) || (p_obj->point1.Y != apply_to_arc->Y)) { + pcb_undo_add_obj_to_move(PCB_OBJ_ARC, apply_to_arc_layer, apply_to_arc, NULL, p_obj->point1.X - apply_to_arc->X, p_obj->point1.Y - apply_to_arc->Y); + ++changes; + } + + if (changes > 0) { + /* Modify the existing arc */ + pcb_arc_invalidate_erase(apply_to_arc); + + pcb_r_delete_entry(apply_to_arc_layer->arc_tree, (pcb_box_t *) apply_to_arc); + pcb_poly_restore_to_poly(PCB->Data, PCB_OBJ_ARC, apply_to_arc_layer, apply_to_arc); + + apply_to_arc->X = p_obj->point1.X; + apply_to_arc->Y = p_obj->point1.Y; + apply_to_arc->Width = p_obj->radius; + apply_to_arc->Height = p_obj->radius; + apply_to_arc->StartAngle = p_obj->start_angle; + apply_to_arc->Delta = p_obj->delta_angle; + apply_to_arc->Thickness = p_route->thickness; + pcb_arc_bbox(apply_to_arc); + pcb_r_insert_entry(apply_to_arc_layer->arc_tree, (pcb_box_t *) apply_to_arc); + pcb_poly_clear_from_poly(PCB->Data, PCB_OBJ_ARC, apply_to_arc_layer, apply_to_arc); + pcb_arc_invalidate_draw(layer, apply_to_arc); + apply_to_arc_layer = layer; + } + + /* The existing arc has been used so forget about it. */ + apply_to_arc = NULL; + applied = 1; + } + else { + /* Create a new arc */ + pcb_arc_t *arc = pcb_arc_new(layer, + p_obj->point1.X, + p_obj->point1.Y, + p_obj->radius, + p_obj->radius, + p_obj->start_angle, + p_obj->delta_angle, + p_route->thickness, + p_route->clearance, + p_route->flags, pcb_true); + if (arc) { + pcb_added_lines++; + pcb_obj_add_attribs(arc, PCB->pen_attr); + pcb_undo_add_obj_to_create(PCB_OBJ_ARC, layer, arc, arc); + pcb_arc_invalidate_draw(layer, arc); + applied = 1; + } + } + break; + + case PCB_OBJ_LINE: + { + /* Create a new line */ + pcb_line_t *line = pcb_line_new_merge(layer, + p_obj->point1.X, + p_obj->point1.Y, + p_obj->point2.X, + p_obj->point2.Y, + p_route->thickness, + p_route->clearance, + p_route->flags); + if (line) { + pcb_added_lines++; + pcb_obj_add_attribs(line, PCB->pen_attr); + pcb_line_invalidate_draw(layer, line); + pcb_undo_add_obj_to_create(PCB_OBJ_LINE, layer, line, line); + applied = 1; + } + } + break; + + default: + break; + } + } + + /* If the existing apply-to-arc wasn't updated then it should be deleted */ + /* (This can happen if the route does not contain any arcs.) */ + if (apply_to_arc != NULL) + pcb_arc_destroy(apply_to_arc_layer, apply_to_arc); + + if (applied) + pcb_subc_as_board_update(PCB); + + return applied; +} + +/*============================================================================= + * + * Route Drawing + * + *===========================================================================*/ + +/*----------------------------------------------------------- + * Draws the outline of an arc + *---------------------------------------------------------*/ +void pcb_route_draw_arc(pcb_hid_gc_t GC, pcb_coord_t x, pcb_coord_t y, pcb_angle_t start_angle, pcb_angle_t delta, pcb_coord_t radius, pcb_coord_t thickness) +{ + double x1, y1, x2, y2, wid = thickness / 2; + + if (delta < 0) { + start_angle += delta; + delta = -delta; + } + + x1 = x - (cos(PCB_M180 * start_angle) * radius); + y1 = y + (sin(PCB_M180 * start_angle) * radius); + x2 = x - (cos(PCB_M180 * (start_angle + delta)) * radius); + y2 = y + (sin(PCB_M180 * (start_angle + delta)) * radius); + + pcb_gui->draw_arc(GC, x, y, radius + wid, radius + wid, start_angle, delta); + if (wid > pcb_pixel_slop) { + pcb_gui->draw_arc(GC, x, y, radius - wid, radius - wid, start_angle, delta); + pcb_gui->draw_arc(GC, x1, y1, wid, wid, start_angle, -180 * SGN(delta)); + pcb_gui->draw_arc(GC, x2, y2, wid, wid, start_angle + delta, 180 * SGN(delta)); + } + +} + +/*----------------------------------------------------------- + * Draws the route as outlines + *---------------------------------------------------------*/ +void pcb_route_draw(pcb_route_t *p_route, pcb_hid_gc_t GC) +{ + int i = 0; + for(i = 0; i < p_route->size; ++i) { + const pcb_route_object_t *p_obj = &p_route->objects[i]; + + pcb_layer_t *layer = pcb_get_layer(PCB->Data, p_obj->layer); + if (layer) + pcb_gui->set_color(GC, &layer->meta.real.color); + + switch (p_obj->type) { + case PCB_OBJ_LINE: + pcb_draw_wireframe_line(GC, p_obj->point1.X, p_obj->point1.Y, p_obj->point2.X, p_obj->point2.Y, p_route->thickness, 0); + break; + + case PCB_OBJ_ARC: + pcb_route_draw_arc(GC, p_obj->point1.X, p_obj->point1.Y, p_obj->start_angle, p_obj->delta_angle, p_obj->radius, p_route->thickness); + break; + + default: + break; + } + } +} + +/*----------------------------------------------------------- + * Draws a drc outline around the route + *---------------------------------------------------------*/ +void pcb_route_draw_drc(pcb_route_t *p_route, pcb_hid_gc_t GC) +{ + pcb_coord_t thickness = p_route->thickness + 2 * conf_core.design.bloat; + int i; + + pcb_gui->set_color(GC, &conf_core.appearance.color.cross); + + for(i = 0; i < p_route->size; ++i) { + const pcb_route_object_t *p_obj = &p_route->objects[i]; + + switch (p_obj->type) { + case PCB_OBJ_LINE: + pcb_draw_wireframe_line(GC, p_obj->point1.X, p_obj->point1.Y, p_obj->point2.X, p_obj->point2.Y, thickness, 0); + break; + + case PCB_OBJ_ARC: + pcb_route_draw_arc(GC, p_obj->point1.X, p_obj->point1.Y, p_obj->start_angle, p_obj->delta_angle, p_obj->radius, thickness); + break; + + default: + break; + } + } +} Index: tags/2.1.2/src/route.h =================================================================== --- tags/2.1.2/src/route.h (nonexistent) +++ tags/2.1.2/src/route.h (revision 24813) @@ -0,0 +1,82 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996, 2004 Thomas Nau + * Copyright (C) 2017 Adrian Purser + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +#ifndef PCB_ROUTE_H +#define PCB_ROUTE_H + +#define ROUTE_SMALL_DATA_SIZE 4 + +#include "obj_common.h" +#include "global_typedefs.h" + +typedef struct { + pcb_objtype_t type; + pcb_point_t point1; /* Line: Start Point, Arc: Center Point */ + pcb_point_t point2; /* Line: End Point */ + pcb_coord_t radius; /* Arc */ + pcb_angle_t start_angle; /* Arc */ + pcb_angle_t delta_angle; /* Arc */ + pcb_layer_id_t layer; +} pcb_route_object_t; + +typedef struct { + pcb_point_t start_point; + pcb_point_t end_point; + pcb_coord_t thickness; + pcb_coord_t clearance; + pcb_layer_id_t start_layer; /* The ID of the layer that the route started on */ + pcb_layer_id_t end_layer; /* The ID of the layer that the route ended on, usually the same as the start for simple routes */ + pcb_board_t *PCB; + pcb_flag_t flags; + int size; /* The number of active objects in the array */ + int capacity; /* The size of the object array */ + pcb_route_object_t *objects; /* Pointer to the object array data */ + pcb_route_object_t small_data[ROUTE_SMALL_DATA_SIZE]; /* Small object array used to avoid allocating memory for small routes */ +} pcb_route_t; + + +void pcb_route_init(pcb_route_t *p_route); +void pcb_route_destroy(pcb_route_t *p_route); +void pcb_route_reset(pcb_route_t *p_route); +void pcb_route_reserve(pcb_route_t *p_route, int size); +void pcb_route_resize(pcb_route_t *p_route, int size); +void pcb_route_start(pcb_board_t *PCB, pcb_route_t *route, pcb_point_t *point, pcb_layer_id_t layer_id, pcb_coord_t thickness, pcb_coord_t clearance, pcb_flag_t flags); + +void pcb_route_add_line(pcb_route_t *p_route, pcb_point_t *point1, pcb_point_t *point2, pcb_layer_id_t layer); +void pcb_route_add_arc(pcb_route_t *p_route, pcb_point_t *center, pcb_angle_t start_angle, pcb_angle_t delta, pcb_coord_t radius, pcb_layer_id_t layer); + +void pcb_route_calculate(pcb_board_t *PCB, pcb_route_t *route, pcb_point_t *point1, pcb_point_t *point2, pcb_layer_id_t layer_id, pcb_coord_t thickness, pcb_coord_t clearance, pcb_flag_t flags, int mod1, int mod2); +void pcb_route_calculate_to(pcb_route_t *route, pcb_point_t *point, int mod1, int mod2); +void pcb_route_direct(pcb_board_t *PCB, pcb_route_t *p_route, pcb_point_t *point1, pcb_point_t *point2, pcb_layer_id_t layer, pcb_coord_t thickness, pcb_coord_t clearance, pcb_flag_t flags); + +int pcb_route_apply(const pcb_route_t *p_route); +int pcb_route_apply_to_line(const pcb_route_t *p_route, pcb_layer_t *Layer, pcb_line_t *apply_to_line); +int pcb_route_apply_to_arc(const pcb_route_t *p_route, pcb_layer_t *apply_to_arc_layer, pcb_arc_t *apply_to_arc); + +#endif Index: tags/2.1.2/src/route_draw.h =================================================================== --- tags/2.1.2/src/route_draw.h (nonexistent) +++ tags/2.1.2/src/route_draw.h (revision 24813) @@ -0,0 +1,10 @@ +#ifndef PCB_ROUTE_DRAW_H +#define PCB_ROUTE_DRAW_H + +#include "global_typedefs.h" +#include "hid.h" + +void pcb_route_draw(pcb_route_t *p_route, pcb_hid_gc_t GC); +void pcb_route_draw_drc(pcb_route_t *p_route, pcb_hid_gc_t GC); + +#endif Index: tags/2.1.2/src/route_style.c =================================================================== --- tags/2.1.2/src/route_style.c (nonexistent) +++ tags/2.1.2/src/route_style.c (revision 24813) @@ -0,0 +1,246 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996,2004,2006 Thomas Nau + * Copyright (C) 2016 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ +#include +#include "config.h" +#include "pcb-printf.h" +#include "genvector/gds_char.h" +#include "route_style.h" +#include "error.h" +#include "conf.h" +#include "misc_util.h" +#include "board.h" +#include "funchash_core.h" +#include "conf_core.h" + +pcb_route_style_t pcb_custom_route_style; + + +static pcb_coord_t pcb_get_num(char **s, const char *default_unit) +{ + /* Read value */ + pcb_coord_t ret_val = pcb_get_value_ex(*s, NULL, NULL, NULL, default_unit, NULL); + /* Advance pointer */ + while (isalnum(**s) || **s == '.') + (*s)++; + return ret_val; +} + + +/* Serializes the route style list */ +char *pcb_route_string_make(vtroutestyle_t *styles) +{ + gds_t str; + int i; + + gds_init(&str); + for (i = 0; i < vtroutestyle_len(styles); ++i) { + pcb_append_printf(&str, "%s,%mc,%mc,%mc,%mc", styles->array[i].name, + styles->array[i].Thick, styles->array[i].Diameter, + styles->array[i].Hole, styles->array[i].Clearance); + if (i > 0) + gds_append(&str, ':'); + } + return str.array; /* this is the only allocation made, return this and don't uninit */ +} + +/* ---------------------------------------------------------------------- + * parses the routes definition string which is a colon separated list of + * comma separated Name, Dimension, Dimension, Dimension, Dimension + * e.g. Signal,20,40,20,10:Power,40,60,28,10:... + */ +int pcb_route_string_parse1(char **str, pcb_route_style_t *routeStyle, const char *default_unit) +{ + char *s = *str; + char Name[256]; + int i, len; + + while (*s && isspace((int) *s)) + s++; + for (i = 0; *s && *s != ','; i++) + Name[i] = *s++; + Name[i] = '\0'; + len = strlen(Name); + if (len > sizeof(routeStyle->name)-1) { + memcpy(routeStyle->name, Name, sizeof(routeStyle->name)-1); + routeStyle->name[sizeof(routeStyle->name)-1] = '\0'; + pcb_message(PCB_MSG_WARNING, "Route style name '%s' too long, truncated to '%s'\n", Name, routeStyle->name); + } + else + strcpy(routeStyle->name, Name); + if (!isdigit((int) *++s)) + goto error; + routeStyle->Thick = pcb_get_num(&s, default_unit); + while (*s && isspace((int) *s)) + s++; + if (*s++ != ',') + goto error; + while (*s && isspace((int) *s)) + s++; + if (!isdigit((int) *s)) + goto error; + routeStyle->Diameter = pcb_get_num(&s, default_unit); + while (*s && isspace((int) *s)) + s++; + if (*s++ != ',') + goto error; + while (*s && isspace((int) *s)) + s++; + if (!isdigit((int) *s)) + goto error; + routeStyle->Hole = pcb_get_num(&s, default_unit); + /* for backwards-compatibility, we use a 10-mil default + * for styles which omit the clearance specification. */ + if (*s != ',') + routeStyle->Clearance = PCB_MIL_TO_COORD(10); + else { + s++; + while (*s && isspace((int) *s)) + s++; + if (!isdigit((int) *s)) + goto error; + routeStyle->Clearance = pcb_get_num(&s, default_unit); + while (*s && isspace((int) *s)) + s++; + } + + *str = s; + return 0; + error:; + *str = s; + return -1; +} + +int pcb_route_string_parse(char *s, vtroutestyle_t *styles, const char *default_unit) +{ + int n; + + vtroutestyle_truncate(styles, 0); + for(n = 0;;n++) { + vtroutestyle_enlarge(styles, n+1); + if (pcb_route_string_parse1(&s, &styles->array[n], default_unit) != 0) { + n--; + break; + } + while (*s && isspace((int) *s)) + s++; + if (*s == '\0') + break; + if (*s++ != ':') { + vtroutestyle_truncate(styles, 0); + return -1; + } + } + vtroutestyle_truncate(styles, n+1); + return 0; +} + +void pcb_use_route_style(pcb_route_style_t * rst) +{ + conf_set_design("design/line_thickness", "%$mS", rst->Thick); + conf_set_design("design/text_scale", "%d", rst->texts <= 0 ? 100 : rst->texts); + conf_set_design("design/text_thickness", "%$mS", rst->textt); + conf_set_design("design/via_thickness", "%$mS", rst->Diameter); + conf_set_design("design/via_drilling_hole", "%$mS", rst->Hole); + conf_set_design("design/clearance", "%$mS", rst->Clearance); + PCB->pen_attr = &rst->attr; +} + +int pcb_use_route_style_idx(vtroutestyle_t *styles, int idx) +{ + if ((idx < 0) || (idx >= vtroutestyle_len(styles))) + return -1; + pcb_use_route_style(styles->array+idx); + return 0; +} + +#define cmp(a,b) (((a) != -1) && (coord_abs((a)-(b)) > 32)) +#define cmps(a,b) (((a) != NULL) && (strcmp((a), (b)) != 0)) +int pcb_route_style_match(pcb_route_style_t *rst, pcb_coord_t Thick, pcb_coord_t Diameter, pcb_coord_t Hole, pcb_coord_t Clearance, char *Name) +{ + if (cmp(Thick, rst->Thick)) return 0; + if (cmp(Diameter, rst->Diameter)) return 0; + if (cmp(Hole, rst->Hole)) return 0; + if (cmp(Clearance, rst->Clearance)) return 0; + if (cmps(Name, rst->name)) return 0; + return 1; +} +#undef cmp +#undef cmps + +int pcb_route_style_lookup(vtroutestyle_t *styles, pcb_coord_t Thick, pcb_coord_t Diameter, pcb_coord_t Hole, pcb_coord_t Clearance, char *Name) +{ + int n; + for (n = 0; n < vtroutestyle_len(styles); n++) + if (pcb_route_style_match(&styles->array[n], Thick, Diameter, Hole, Clearance, Name)) + return n; + return -1; +} + + +int pcb_get_style_size(int funcid, pcb_coord_t * out, int type, int size_id) +{ + switch (funcid) { + case F_Object: + switch (type) { + case PCB_OBJ_LINE: + return pcb_get_style_size(F_SelectedLines, out, 0, size_id); + case PCB_OBJ_ARC: + return pcb_get_style_size(F_SelectedArcs, out, 0, size_id); + } + pcb_message(PCB_MSG_ERROR, "Sorry, can't fetch the style of that object type (%x)\n", type); + return -1; + case F_SelectedPads: + if (size_id != 2) /* don't mess with pad size */ + return -1; + case F_SelectedVias: + case F_SelectedPins: + case F_SelectedObjects: + case F_Selected: + case F_SelectedElements: + if (size_id == 0) + *out = conf_core.design.via_thickness; + else if (size_id == 1) + *out = conf_core.design.via_drilling_hole; + else + *out = conf_core.design.clearance; + break; + case F_SelectedArcs: + case F_SelectedLines: + if (size_id == 2) + *out = conf_core.design.clearance; + else + *out = conf_core.design.line_thickness; + return 0; + case F_SelectedTexts: + case F_SelectedNames: + pcb_message(PCB_MSG_ERROR, "Sorry, can't change style of every selected object\n"); + return -1; + } + return 0; +} Index: tags/2.1.2/src/route_style.h =================================================================== --- tags/2.1.2/src/route_style.h (nonexistent) +++ tags/2.1.2/src/route_style.h (revision 24813) @@ -0,0 +1,62 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996, 2004 Thomas Nau + * Copyright (C) 2016 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +#include "vtroutestyle.h" + +/* Parse a single route string into one pcb_route_style_t *slot. Returns 0 on success. */ +int pcb_route_string_parse1(char **str, pcb_route_style_t *routeStyle, const char *default_unit); + +/* Parse a ':' separated list of route strings into a styles vector + The vector is initialized before the call. On error the vector is left empty + (but still initialized). Returns 0 on success. */ +int pcb_route_string_parse(char *s, vtroutestyle_t *styles, const char *default_unit); + +char *pcb_route_string_make(vtroutestyle_t *styles); + +/* Set design configuration (the pen we draw with) to a given route style */ +void pcb_use_route_style(pcb_route_style_t *rst); + +/* Same as pcb_use_route_style() but uses one of the styles in a vector; + returns -1 if idx is out of bounds, 0 on success. */ +int pcb_use_route_style_idx(vtroutestyle_t *styles, int idx); + +/* Compare supplied parameters to each style in the vector and return the index + of the first matching style. All non-(-1) parameters need to match to accept + a style. Return -1 on no match. */ +int pcb_route_style_lookup(vtroutestyle_t *styles, pcb_coord_t Thick, pcb_coord_t Diameter, pcb_coord_t Hole, pcb_coord_t Clearance, char *Name); + +/* Return 1 if rst matches the style in supplied args. Same matching rules as + in pcb_route_style_lookup(). */ +int pcb_route_style_match(pcb_route_style_t *rst, pcb_coord_t Thick, pcb_coord_t Diameter, pcb_coord_t Hole, pcb_coord_t Clearance, char *Name); + +extern pcb_route_style_t pcb_custom_route_style; + +/* helper: get route style size for a function and selected object type. + size_id: 0=main size; 1=2nd size (drill); 2=clearance */ +int pcb_get_style_size(int funcid, pcb_coord_t * out, int type, int size_id); Index: tags/2.1.2/src/rtree.c =================================================================== --- tags/2.1.2/src/rtree.c (nonexistent) +++ tags/2.1.2/src/rtree.c (revision 24813) @@ -0,0 +1,173 @@ + /* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2017 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "config.h" + +#include +#include +#include + +#include "unit.h" +#include "rtree.h" + +#include +#include +#include +#include + +/* Temporary compatibility layer for the transition */ +pcb_rtree_t *pcb_r_create_tree(void) +{ + pcb_rtree_t *root = malloc(sizeof(pcb_rtree_t)); + pcb_rtree_init(root); + return root; +} + +void pcb_r_destroy_tree(pcb_rtree_t **tree) +{ + pcb_rtree_uninit(*tree); + free(*tree); + *tree = NULL; +} + +void pcb_r_insert_entry(pcb_rtree_t *rtree, const pcb_box_t *which) +{ + pcb_any_obj_t *obj = (pcb_any_obj_t *)which; /* assumes first field is the bounding box */ + assert(obj != NULL); + pcb_rtree_insert(rtree, obj, (pcb_rtree_box_t *)which); +} + +void pcb_r_insert_array(pcb_rtree_t *rtree, const pcb_box_t *boxlist[], pcb_cardinal_t len) +{ + pcb_cardinal_t n; + + if (len == 0) + return; + + assert(boxlist != 0); + + for(n = 0; n < len; n++) + pcb_r_insert_entry(rtree, boxlist[n]); +} + +pcb_bool pcb_r_delete_entry(pcb_rtree_t *rtree, const pcb_box_t *which) +{ + pcb_any_obj_t *obj = (pcb_any_obj_t *)which; /* assumes first field is the bounding box */ + assert(obj != NULL); + return pcb_rtree_delete(rtree, obj, (pcb_rtree_box_t *)which) == 0; +} + +pcb_bool pcb_r_delete_entry_free_data(pcb_rtree_t *rtree, const pcb_box_t *box, void (*free_data)(void *d)) +{ + pcb_any_obj_t *obj = (pcb_any_obj_t *)box; /* assumes first field is the bounding box */ + assert(obj != NULL); + if (pcb_rtree_delete(rtree, obj, (pcb_rtree_box_t *)box) != 0) + return pcb_false; + free_data(obj); + return pcb_true; +} + +typedef struct { + pcb_r_dir_t (*region_in_search)(const pcb_box_t *region, void *closure); + pcb_r_dir_t (*rectangle_in_region)(const pcb_box_t *box, void *closure); + void *clo; +} r_cb_t; + +static pcb_rtree_dir_t r_cb_node(void *ctx_, void *obj, const pcb_rtree_box_t *box) +{ + r_cb_t *ctx = (r_cb_t *)ctx_; + return ctx->region_in_search((const pcb_box_t *)box, ctx->clo); +} + +static pcb_rtree_dir_t r_cb_obj(void *ctx_, void *obj, const pcb_rtree_box_t *box) +{ + r_cb_t *ctx = (r_cb_t *)ctx_; + return ctx->rectangle_in_region((const pcb_box_t *)obj, ctx->clo); +} + + +pcb_r_dir_t pcb_r_search(pcb_rtree_t *rtree, const pcb_box_t *query, + pcb_r_dir_t (*region_in_search)(const pcb_box_t *region, void *closure), + pcb_r_dir_t (*rectangle_in_region)(const pcb_box_t *box, void *closure), + void *closure, int *num_found) +{ + pcb_r_dir_t res; + pcb_rtree_cardinal_t out_cnt; + r_cb_t ctx; + ctx.region_in_search = region_in_search; + ctx.rectangle_in_region = rectangle_in_region; + ctx.clo = closure; + + res = pcb_rtree_search_any(rtree, (const pcb_rtree_box_t *)query, + (ctx.region_in_search != NULL) ? r_cb_node : NULL, + (ctx.rectangle_in_region != NULL) ? r_cb_obj : NULL, + &ctx, &out_cnt); + + if (num_found != NULL) + *num_found = out_cnt; + + return res; +} + +int pcb_r_region_is_empty(pcb_rtree_t *rtree, const pcb_box_t *region) +{ + return pcb_rtree_is_box_empty(rtree, (const pcb_rtree_box_t *)region); +} + +static void r_print_obj(FILE *f, void *obj) +{ + fprintf(f, "\n", obj); +} + +void pcb_r_dump_tree(pcb_rtree_t *root, int unused) +{ + pcb_rtree_dump_text(stdout, root, r_print_obj); +} + +void pcb_r_free_tree_data(pcb_rtree_t *rtree, void (*free)(void *ptr)) +{ + pcb_rtree_it_t it; + void *o; + + for(o = pcb_rtree_all_first(&it, rtree); o != NULL; o = pcb_rtree_all_next(&it)) + free(o); +} + +pcb_box_t *pcb_r_first(pcb_rtree_t *tree, pcb_rtree_it_t *it) +{ + if (tree == NULL) + return NULL; + return (pcb_box_t *)pcb_rtree_all_first(it, tree); +} + +pcb_box_t *pcb_r_next(pcb_rtree_it_t *it) +{ + return (pcb_box_t *)pcb_rtree_all_next(it); +} + +void pcb_r_end(pcb_rtree_it_t *it) +{ +} Index: tags/2.1.2/src/rtree.h =================================================================== --- tags/2.1.2/src/rtree.h (nonexistent) +++ tags/2.1.2/src/rtree.h (revision 24813) @@ -0,0 +1,48 @@ + /* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2017 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#ifndef PCB_RTREE_H +#define PCB_RTREE_H + +#include "global_typedefs.h" + +typedef long int pcb_rtree_cardinal_t; +typedef pcb_coord_t pcb_rtree_coord_t; + +/* Instantiate an rtree */ +#define RTR(n) pcb_rtree_ ## n +#define RTRU(n) pcb_RTREE_ ## n +#define pcb_rtree_privfunc static +#define pcb_rtree_size 6 +#define pcb_rtree_stack_max 1024 + +#define RTREE_NO_TREE_TYPEDEFS + +#include + +#include "rtree2_compat.h" + +#endif /* PCB_RTREE_H */ Index: tags/2.1.2/src/rtree2_compat.h =================================================================== --- tags/2.1.2/src/rtree2_compat.h (nonexistent) +++ tags/2.1.2/src/rtree2_compat.h (revision 24813) @@ -0,0 +1,91 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * Copyright (C) 1998,1999,2000,2001 harry eaton + * + * this file, rtree.h, was written and is + * Copyright (c) 2004 harry eaton, it's based on C. Scott's kdtree.h template + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + * + * Old contact info: + * harry eaton, 6697 Buttonhole Ct, Columbia, MD 21044 USA + * haceaton@aplcomm.jhuapl.edu + * + */ + +/* Compatibility layer between the new rtree and the old rtree for the + period of transition */ + +/* callback direction to the search engine */ +typedef enum pcb_r_dir_e { + PCB_R_DIR_NOT_FOUND = 0, /* object not found or not accepted */ + PCB_R_DIR_FOUND_CONTINUE = 1, /* object found or accepted, go on searching */ + PCB_R_DIR_CANCEL = 2 /* cancel the search and return immediately */ +} pcb_r_dir_t; + +pcb_rtree_t *pcb_r_create_tree(void); +void pcb_r_destroy_tree(pcb_rtree_t **tree); +void pcb_r_free_tree_data(pcb_rtree_t *rtree, void (*free)(void *ptr)); + +void pcb_r_insert_entry(pcb_rtree_t *rtree, const pcb_box_t *which); +void pcb_r_insert_array(pcb_rtree_t *rtree, const pcb_box_t *boxlist[], pcb_cardinal_t len); + +pcb_bool pcb_r_delete_entry(pcb_rtree_t *rtree, const pcb_box_t *which); +pcb_bool pcb_r_delete_entry_free_data(pcb_rtree_t *rtree, const pcb_box_t *box, void (*free_data)(void *d)); + +/* generic search routine */ +/* region_in_search should return pcb_true if "what you're looking for" is + * within the specified region; + * rectangle_in_region should return pcb_true if the given rectangle is + * "what you're looking for". + * The search will find all rectangles matching the criteria given + * by region_in_search and rectangle_in_region and return a count of + * how many things rectangle_in_region returned pcb_true for. closure is + * used to abort the search if desired from within rectangle_in_region + * Look at the implementation of r_region_is_empty for how to + * abort the search if that is the desired behavior. + */ +pcb_r_dir_t pcb_r_search(pcb_rtree_t *rtree, const pcb_box_t *query, + pcb_r_dir_t (*region_in_search)(const pcb_box_t *region, void *closure), + pcb_r_dir_t (*rectangle_in_region)(const pcb_box_t *box, void *closure), + void *closure, int *num_found); + +/* return 0 if there are any rectangles in the given region. */ +int pcb_r_region_is_empty(pcb_rtree_t *rtree, const pcb_box_t *region); + +void pcb_r_dump_tree(pcb_rtree_t *root, int unused); + +#define PCB_RTREE_EMPTY(rt) (((rt) == NULL) || ((rt)->size == 0)) + +/* -- Iterate through an rtree; DO NOT modify the tree while iterating -- */ + +/* Get the first item, get fields of iterator set up; return can be casted to an object; returns NULL if rtree is empty */ +pcb_box_t *pcb_r_first(pcb_rtree_t *tree, pcb_rtree_it_t *it); + +/* Get the next item, return can be casted to an object; returns NULL if no more items */ +pcb_box_t *pcb_r_next(pcb_rtree_it_t *it); + +/* Free fields of the iterator - not needed anymore, will be removed */ +void pcb_r_end(pcb_rtree_it_t *it); Index: tags/2.1.2/src/safe_fs.c =================================================================== --- tags/2.1.2/src/safe_fs.c (nonexistent) +++ tags/2.1.2/src/safe_fs.c (revision 24813) @@ -0,0 +1,317 @@ + /* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2017 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +/* permit direct access to the libc calls (turn off config.h masking) */ +#define PCB_SAFE_FS + +/* opendir, readdir */ +#include "compat_inc.h" + +#include "config.h" + + +#include +#include + +#include "safe_fs.h" + +#include "compat_fs.h" +#include "compat_misc.h" +#include "error.h" +#include "globalconst.h" +#include "paths.h" + + +/* Evaluates op(arg1,arg2); returns 0 if the operation is permitted */ +static int pcb_safe_fs_check(const char *op, const char *arg1, const char *arg2) +{ + return 0; +} + +/* Evaluate op(arg1,arg2) and print error and return err_ret if not permitted */ +#define CHECK(func, op, arg1, arg2, err_inst) \ +do { \ + if (pcb_safe_fs_check(op, arg1, arg2) != 0) { \ + pcb_message(PCB_MSG_ERROR, "File system operation %s(): access denied on %s(%s,%s)\n", func, op, arg1, arg2); \ + err_inst; \ + } \ +} while(0) + +FILE *pcb_fopen_fn(const char *path, const char *mode, char **fn_out) +{ + FILE *f; + char *path_exp; + + /* skip expensive path building for empty paths that are going to fail anyway */ + if ((path == NULL) || (*path == '\0')) { + if (fn_out != NULL) + *fn_out = NULL; + return NULL; + } + + path_exp = pcb_build_fn(path); + + CHECK("fopen", "access", path_exp, mode, goto err); + CHECK("fopen", "fopen", path_exp, mode, goto err); + + f = fopen(path_exp, mode); + if (f == NULL) + goto err; + + if (fn_out != NULL) + *fn_out = path_exp; + else + free(path_exp); + + return f; + + err:; + free(path_exp); + if (fn_out != NULL) + *fn_out = NULL; + return NULL; +} + +FILE *pcb_fopen(const char *path, const char *mode) +{ + return pcb_fopen_fn(path, mode, NULL); +} + +char *pcb_fopen_check(const char *path, const char *mode) +{ + char *path_exp = pcb_build_fn(path); + + CHECK("fopen", "access", path_exp, mode, goto err); + CHECK("fopen", "fopen", path_exp, mode, goto err); + return path_exp; + + err:; + free(path_exp); + return NULL; +} + +FILE *pcb_popen(const char *cmd, const char *mode) +{ + FILE *f = NULL; + char *cmd_exp = pcb_build_fn(cmd); + + CHECK("popen", "access", cmd_exp, mode, goto err); + CHECK("popen", "exec", cmd_exp, NULL, goto err); + CHECK("popen", "popen", cmd_exp, mode, goto err); + + f = popen(cmd_exp, mode); + + err:; + free(cmd_exp); + return f; +} + +int pcb_pclose(FILE *f) +{ + return pclose(f); +} + + +int pcb_system(const char *cmd) +{ + int res = -1; + char *cmd_exp = pcb_build_fn(cmd); + + CHECK("access", "access", cmd_exp, "r", goto err); + CHECK("access", "exec", cmd_exp, NULL, goto err); + CHECK("access", "system", cmd_exp, NULL, goto err); + + res = system(cmd_exp); + + err:; + free(cmd_exp); + return res; +} + +int pcb_remove(const char *path) +{ + int res = -1; + char *path_exp = pcb_build_fn(path); + + CHECK("remove", "access", path_exp, "w", goto err); + CHECK("remove", "remove", path_exp, NULL, goto err); + + res = remove(path); + + err:; + free(path_exp); + return res; +} + +int pcb_rename(const char *old_path, const char *new_path) +{ + int res = -1; + char *old_path_exp = pcb_build_fn(old_path); + char *new_path_exp = pcb_build_fn(new_path); + + CHECK("rename", "access", old_path_exp, "w", goto err); + CHECK("rename", "access", new_path_exp, "w", goto err); + CHECK("rename", "rename", old_path_exp, new_path_exp, goto err); + + res = rename(old_path_exp, new_path_exp); + + err:; + free(old_path_exp); + free(new_path_exp); + return res; +} + +static FILE *pcb_fopen_at_(const char *from, const char *fn, const char *mode, char **full_path, int recursive) +{ + char tmp[PCB_PATH_MAX]; + DIR *d; + struct dirent *de; + FILE *res; + + /* try the trivial: directly under this dir */ + pcb_snprintf(tmp, sizeof(tmp), "%s%c%s", from, PCB_DIR_SEPARATOR_C, fn); + res = pcb_fopen(tmp, mode); + + if (res != NULL) { + if (full_path != NULL) + *full_path = pcb_strdup(tmp); + return res; + } + + /* no luck, recurse into each subdir */ + if (!recursive) + return NULL; + + d = opendir(from); + if (d == NULL) + return NULL; + + while((de = readdir(d)) != NULL) { + struct stat st; + if (de->d_name[0] == '.') + continue; + pcb_snprintf(tmp, sizeof(tmp), "%s%c%s", from, PCB_DIR_SEPARATOR_C, de->d_name); + if (stat(tmp, &st) != 0) + continue; + if (!S_ISDIR(st.st_mode)) + continue; + + /* dir: recurse */ + res = pcb_fopen_at_(tmp, fn, mode, full_path, recursive); + if (res != NULL) { + closedir(d); + return res; + } + } + closedir(d); + return NULL; +} + +FILE *pcb_fopen_at(const char *dir, const char *fn, const char *mode, char **full_path, int recursive) +{ + if (full_path != NULL) + *full_path = NULL; + + return pcb_fopen_at_(dir, fn, mode, full_path, recursive); +} + +FILE *pcb_fopen_first(const conflist_t *paths, const char *fn, const char *mode, char **full_path, int recursive) +{ + FILE *res; + char *real_fn = pcb_build_fn(fn); + conf_listitem_t *ci; + + if (full_path != NULL) + *full_path = NULL; + + if (real_fn == NULL) + return NULL; + + if (pcb_is_path_abs(fn)) { + res = pcb_fopen(real_fn, mode); + if ((res != NULL) && (full_path != NULL)) + *full_path = real_fn; + else + free(real_fn); + return res; + } + + /* have to search paths */ + { + for (ci = conflist_first((conflist_t *)paths); ci != NULL; ci = conflist_next(ci)) { + const char *p = ci->val.string[0]; + char *real_p; + size_t pl; + + if (ci->type != CFN_STRING) + continue; + if (*p == '?') + p++; + + /* resolve the path from the list, truncate trailing '/' */ + real_p = pcb_build_fn(p); + pl = strlen(real_p); + if ((pl > 0) && (real_p[pl-1] == '/')) + real_p[pl-1] = '\0'; + + res = pcb_fopen_at(real_p, real_fn, mode, full_path, recursive); + free(real_p); + + if (res != NULL) { + free(real_fn); + return res; + } + } + } + + return NULL; +} + +extern int pcb_mkdir_(const char *path, int mode); +int pcb_mkdir(const char *path, int mode) +{ + CHECK("mkdir", "access", path, NULL, return -1); + CHECK("mkdir", "mkdir", path, NULL, return -1); + + return pcb_mkdir_(path, mode); +} + + +extern long pcb_file_size_(const char *path); +long pcb_file_size(const char *path) +{ + CHECK("file_size", "access", path, NULL, return -1); + CHECK("file_size", "stat", path, NULL, return -1); + return pcb_file_size_(path); +} + +extern int pcb_is_dir_(const char *path); +int pcb_is_dir(const char *path) +{ + CHECK("is_dir", "access", path, NULL, return -1); + CHECK("is_dir", "stat", path, NULL, return -1); + return pcb_is_dir_(path); +} Index: tags/2.1.2/src/safe_fs.h =================================================================== --- tags/2.1.2/src/safe_fs.h (nonexistent) +++ tags/2.1.2/src/safe_fs.h (revision 24813) @@ -0,0 +1,76 @@ + /* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2017 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +/* Wrap standard file system calls, giving the user a chance to control + where pcb-rnd may go on the file system */ + +#ifndef PCB_SAFE_FS_H +#define PCB_SAFE_FS_H + +#include + + +FILE *pcb_fopen(const char *path, const char *mode); +FILE *pcb_popen(const char *cmd, const char *mode); +int pcb_pclose(FILE *f); +int pcb_system(const char *cmd); +int pcb_remove(const char *path); +int pcb_rename(const char *old_path, const char *new_path); +int pcb_mkdir(const char *path, int mode); + +/* Return the size of non-large files; on error or for large files + (size larger than the value long can hold) return -1 */ +long pcb_file_size(const char *path); + +/* Return non-zero if path is a directory */ +int pcb_is_dir(const char *path); + +/* Check if path could be open with mode; if yes, return the substituted/expanded + file name, if no, return NULL */ +char *pcb_fopen_check(const char *path, const char *mode); + +/* Same as pcb_fopen(), but on success load fn_out() with the malloc()'d + file name as it looked after the substitution */ +FILE *pcb_fopen_fn(const char *path, const char *mode, char **fn_out); + +/* Open a file given as a basename fn, under the directory dir, optionally + doing a recusrive search in the directory tree. If full_path is not NULL, + and the call succeeds, load it with the full path of the file opened. */ +FILE *pcb_fopen_at(const char *dir, const char *fn, const char *mode, char **full_path, int recursive); + + +#include "conf.h" + +/* Open a file with standard path search and substitutions performed on + the file name. If fn is not an absolute path, search paths for the + first directory from which fn is accessible. If the call doesn't fail + and full_path is not NULL, it is set to point to the final full path + (or NULL on failure); the caller needs to call free() on it. + If recursive is set, all subcirectories under each path is also searched for the file. + */ +FILE *pcb_fopen_first(const conflist_t *paths, const char *fn, const char *mode, char **full_path, int recursive); + +#endif Index: tags/2.1.2/src/search.c =================================================================== --- tags/2.1.2/src/search.c (nonexistent) +++ tags/2.1.2/src/search.c (revision 24813) @@ -0,0 +1,1617 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + + +/* search routines + * some of the functions use dummy parameters + */ + +#include "config.h" +#include "conf_core.h" + +#include + +#include "board.h" +#include "data.h" +#include "error.h" +#include "find.h" +#include "polygon.h" +#include "search.h" +#include "obj_subc_parent.h" +#include "obj_pstk_inlines.h" + +static double PosX, PosY; /* search position for subroutines */ +static pcb_coord_t SearchRadius; +static pcb_box_t SearchBox; +static pcb_layer_t *SearchLayer; + +/* --------------------------------------------------------------------------- + * The first parameter includes PCB_OBJ_LOCKED if we + * want to include locked object in the search and PCB_OBJ_SUBC_PART if + * objects that are part of a subcircuit should be found. + */ +static pcb_bool SearchLineByLocation(unsigned long, unsigned long, pcb_layer_t **, pcb_line_t **, pcb_line_t **); +static pcb_bool SearchArcByLocation(unsigned long, unsigned long, pcb_layer_t **, pcb_arc_t **, pcb_arc_t **); +static pcb_bool SearchRatLineByLocation(unsigned long, unsigned long, pcb_rat_t **, pcb_rat_t **, pcb_rat_t **); +static pcb_bool SearchTextByLocation(unsigned long, unsigned long, pcb_layer_t **, pcb_text_t **, pcb_text_t **); +static pcb_bool SearchPolygonByLocation(unsigned long, unsigned long, pcb_layer_t **, pcb_poly_t **, pcb_poly_t **); +static pcb_bool SearchLinePointByLocation(unsigned long, unsigned long, pcb_layer_t **, pcb_line_t **, pcb_point_t **); +static pcb_bool SearchArcPointByLocation(unsigned long, unsigned long, pcb_layer_t **, pcb_arc_t **, int **); +static pcb_bool SearchPointByLocation(unsigned long, unsigned long, unsigned long, pcb_layer_t **, pcb_poly_t **, pcb_point_t **); +static pcb_bool SearchSubcByLocation(unsigned long, unsigned long, pcb_subc_t **, pcb_subc_t **, pcb_subc_t **, pcb_bool); + +/* Return not-found for subc parts and locked items unless objst says otherwise + obj is the object to be checked if part of subc; check lock on locked_obj + Also return not-found if flags are required but the object doesn't have them */ +#define TEST_OBJST_(objst, req_flag, locality, obj, locked_obj, reject) \ +do { \ + if ((req_flag != 0) && (!PCB_FLAG_TEST(req_flag, obj))) \ + reject; \ + if (!(objst & PCB_OBJ_SUBC_PART) && (pcb_ ## locality ## obj_parent_subc(obj->parent_type, &obj->parent))) \ + reject; \ + if (!(objst & PCB_OBJ_LOCKED) && (PCB_FLAG_TEST(objst & PCB_FLAG_LOCK, locked_obj))) \ + reject; \ +} while(0) + +#define TEST_OBJST(objst, req_flag, locality, obj, locked_obj) \ + TEST_OBJST_(objst, req_flag, locality, obj, locked_obj, return PCB_R_DIR_NOT_FOUND) + +struct ans_info { + void **ptr1, **ptr2, **ptr3; + pcb_bool BackToo; + double area; + unsigned long objst, req_flag; + int on_current; + pcb_layer_type_t on_lyt; +}; + +/* --------------------------------------------------------------------------- + * searches a padstack + */ +static pcb_r_dir_t padstack_callback(const pcb_box_t *box, void *cl) +{ + struct ans_info *i = (struct ans_info *) cl; + pcb_pstk_t *ps = (pcb_pstk_t *) box; + pcb_data_t *pdata; + + TEST_OBJST(i->objst, i->req_flag, g, ps, ps); + + if (!pcb_is_point_in_pstk(PosX, PosY, SearchRadius, ps, NULL)) + return PCB_R_DIR_NOT_FOUND; + if ((i->on_current) && (pcb_pstk_shape_at(PCB, ps, CURRENT) == NULL) && (!pcb_pstk_bb_drills(PCB, ps, CURRENT->meta.real.grp, NULL))) + return PCB_R_DIR_NOT_FOUND; + if ((i->on_lyt != 0) && (pcb_pstk_shape(ps, i->on_lyt, 0) == NULL)) + return PCB_R_DIR_NOT_FOUND; + *i->ptr2 = *i->ptr3 = ps; + assert(ps->parent_type == PCB_PARENT_DATA); + pdata = ps->parent.data; + if (pdata->parent_type == PCB_PARENT_SUBC) + *i->ptr1 = pdata->parent.subc; /* padstack of a subcircuit */ + else + *i->ptr1 = ps; /* padstack on a board (e.g. via) */ + return PCB_R_DIR_CANCEL; /* found, stop searching */ +} + +static pcb_bool SearchPadstackByLocation(unsigned long objst, unsigned long req_flag, pcb_pstk_t **ps, pcb_pstk_t **Dummy1, pcb_pstk_t **Dummy2, int on_current, pcb_layer_type_t on_lyt) +{ + struct ans_info info; + + /* search only if via-layer is visible */ + if (!PCB->pstk_on) + return pcb_false; + + info.ptr1 = (void **)ps; + info.ptr2 = (void **)Dummy1; + info.ptr3 = (void **)Dummy2; + info.objst = objst; + info.req_flag = req_flag; + info.on_current = on_current; + info.on_lyt = on_lyt; + + if (pcb_r_search(PCB->Data->padstack_tree, &SearchBox, NULL, padstack_callback, &info, NULL) != PCB_R_DIR_NOT_FOUND) + return pcb_true; + return pcb_false; +} + +/* --------------------------------------------------------------------------- + * searches ordinary line on the SearchLayer + */ + +struct line_info { + pcb_line_t **Line; + pcb_point_t **Point; + double least; + unsigned long objst, req_flag; +}; + + +static pcb_r_dir_t line_callback(const pcb_box_t * box, void *cl) +{ + struct line_info *i = (struct line_info *) cl; + pcb_line_t *l = (pcb_line_t *) box; + + TEST_OBJST(i->objst, i->req_flag, l, l, l); + + if (!pcb_is_point_in_line(PosX, PosY, SearchRadius, (pcb_any_line_t *)l)) + return PCB_R_DIR_NOT_FOUND; + *i->Line = l; + *i->Point = (pcb_point_t *) l; + + return PCB_R_DIR_CANCEL; /* found what we were looking for */ +} + + +static pcb_bool SearchLineByLocation(unsigned long objst, unsigned long req_flag, pcb_layer_t ** Layer, pcb_line_t ** Line, pcb_line_t ** Dummy) +{ + struct line_info info; + + info.Line = Line; + info.Point = (pcb_point_t **) Dummy; + info.objst = objst; + info.req_flag = req_flag; + + *Layer = SearchLayer; + if (pcb_r_search(SearchLayer->line_tree, &SearchBox, NULL, line_callback, &info, NULL) != PCB_R_DIR_NOT_FOUND) + return pcb_true; + + return pcb_false; +} + +static pcb_r_dir_t rat_callback(const pcb_box_t * box, void *cl) +{ + pcb_line_t *line = (pcb_line_t *) box; + struct ans_info *i = (struct ans_info *) cl; + + TEST_OBJST(i->objst, i->req_flag, l, line, line); + + if (PCB_FLAG_TEST(PCB_FLAG_VIA, line) ? + (pcb_distance(line->Point1.X, line->Point1.Y, PosX, PosY) <= + line->Thickness * 2 + SearchRadius) : pcb_is_point_on_line(PosX, PosY, SearchRadius, line)) { + *i->ptr1 = *i->ptr2 = *i->ptr3 = line; + return PCB_R_DIR_CANCEL; + } + return PCB_R_DIR_NOT_FOUND; +} + +/* --------------------------------------------------------------------------- + * searches rat lines if they are visible + */ +static pcb_bool SearchRatLineByLocation(unsigned long objst, unsigned long req_flag, pcb_rat_t ** Line, pcb_rat_t ** Dummy1, pcb_rat_t ** Dummy2) +{ + struct ans_info info; + + info.ptr1 = (void **) Line; + info.ptr2 = (void **) Dummy1; + info.ptr3 = (void **) Dummy2; + info.objst = objst; + info.req_flag = req_flag; + + if (pcb_r_search(PCB->Data->rat_tree, &SearchBox, NULL, rat_callback, &info, NULL) != PCB_R_DIR_NOT_FOUND) + return pcb_true; + return pcb_false; +} + +/* --------------------------------------------------------------------------- + * searches arc on the SearchLayer + */ +struct arc_info { + pcb_arc_t **Arc, **Dummy; + unsigned long objst, req_flag; + int **arc_pt; /* 0=start, 1=end (start+delta) */ + double least; +}; + +static pcb_r_dir_t arc_callback(const pcb_box_t * box, void *cl) +{ + struct arc_info *i = (struct arc_info *) cl; + pcb_arc_t *a = (pcb_arc_t *) box; + + TEST_OBJST(i->objst, i->req_flag, l, a, a); + + if (!pcb_is_point_on_arc(PosX, PosY, SearchRadius, a)) + return 0; + *i->Arc = a; + *i->Dummy = a; + return PCB_R_DIR_CANCEL; /* found */ +} + + +static pcb_bool SearchArcByLocation(unsigned long objst, unsigned long req_flag, pcb_layer_t ** Layer, pcb_arc_t ** Arc, pcb_arc_t ** Dummy) +{ + struct arc_info info; + + info.Arc = Arc; + info.Dummy = Dummy; + info.objst = objst; + info.req_flag = req_flag; + + *Layer = SearchLayer; + if (pcb_r_search(SearchLayer->arc_tree, &SearchBox, NULL, arc_callback, &info, NULL) != PCB_R_DIR_NOT_FOUND) + return pcb_true; + return pcb_false; +} + +static pcb_r_dir_t text_callback(const pcb_box_t * box, void *cl) +{ + pcb_text_t *text = (pcb_text_t *) box; + struct ans_info *i = (struct ans_info *) cl; + + TEST_OBJST(i->objst, i->req_flag, l, text, text); + + if (PCB_POINT_IN_BOX(PosX, PosY, &text->BoundingBox)) { + *i->ptr2 = *i->ptr3 = text; + return PCB_R_DIR_CANCEL; /* found */ + } + return PCB_R_DIR_NOT_FOUND; +} + +/* --------------------------------------------------------------------------- + * searches text on the SearchLayer + */ +static pcb_bool SearchTextByLocation(unsigned long objst, unsigned long req_flag, pcb_layer_t ** Layer, pcb_text_t ** Text, pcb_text_t ** Dummy) +{ + struct ans_info info; + + *Layer = SearchLayer; + info.ptr2 = (void **) Text; + info.ptr3 = (void **) Dummy; + info.objst = objst; + info.req_flag = req_flag; + + if (pcb_r_search(SearchLayer->text_tree, &SearchBox, NULL, text_callback, &info, NULL) != PCB_R_DIR_NOT_FOUND) + return pcb_true; + return pcb_false; +} + +static pcb_r_dir_t polygon_callback(const pcb_box_t * box, void *cl) +{ + pcb_poly_t *polygon = (pcb_poly_t *) box; + struct ans_info *i = (struct ans_info *) cl; + + TEST_OBJST(i->objst, i->req_flag, l, polygon, polygon); + + if (pcb_poly_is_point_in_p(PosX, PosY, SearchRadius, polygon)) { + *i->ptr2 = *i->ptr3 = polygon; + return PCB_R_DIR_CANCEL; /* found */ + } + return PCB_R_DIR_NOT_FOUND; +} + + +/* --------------------------------------------------------------------------- + * searches a polygon on the SearchLayer + */ +static pcb_bool SearchPolygonByLocation(unsigned long objst, unsigned long req_flag, pcb_layer_t ** Layer, pcb_poly_t ** Polygon, pcb_poly_t ** Dummy) +{ + struct ans_info info; + + *Layer = SearchLayer; + info.ptr2 = (void **) Polygon; + info.ptr3 = (void **) Dummy; + info.objst = objst; + info.req_flag = req_flag; + + if (pcb_r_search(SearchLayer->polygon_tree, &SearchBox, NULL, polygon_callback, &info, NULL) != PCB_R_DIR_NOT_FOUND) + return pcb_true; + return pcb_false; +} + +static pcb_r_dir_t linepoint_callback(const pcb_box_t * b, void *cl) +{ + pcb_line_t *line = (pcb_line_t *) b; + struct line_info *i = (struct line_info *) cl; + pcb_r_dir_t ret_val = PCB_R_DIR_NOT_FOUND; + double d; + + TEST_OBJST(i->objst, i->req_flag, l, line, line); + + /* some stupid code to check both points */ + d = pcb_distance(PosX, PosY, line->Point1.X, line->Point1.Y); + if (d < i->least) { + i->least = d; + *i->Line = line; + *i->Point = &line->Point1; + ret_val = PCB_R_DIR_FOUND_CONTINUE; + } + + d = pcb_distance(PosX, PosY, line->Point2.X, line->Point2.Y); + if (d < i->least) { + i->least = d; + *i->Line = line; + *i->Point = &line->Point2; + ret_val = PCB_R_DIR_FOUND_CONTINUE; + } + return ret_val; +} + +static pcb_r_dir_t arcpoint_callback(const pcb_box_t * b, void *cl) +{ + pcb_box_t ab; + pcb_arc_t *arc = (pcb_arc_t *) b; + struct arc_info *i = (struct arc_info *) cl; + pcb_r_dir_t ret_val = PCB_R_DIR_NOT_FOUND; + double d; + + TEST_OBJST(i->objst, i->req_flag, l, arc, arc); + + /* some stupid code to check both points */ + pcb_arc_get_end(arc, 0, &ab.X1, &ab.Y1); + pcb_arc_get_end(arc, 1, &ab.X2, &ab.Y2); + + d = pcb_distance(PosX, PosY, ab.X1, ab.Y1); + if (d < i->least) { + i->least = d; + *i->Arc = arc; + *i->arc_pt = pcb_arc_start_ptr; + ret_val = PCB_R_DIR_FOUND_CONTINUE; + } + + d = pcb_distance(PosX, PosY, ab.X2, ab.Y2); + if (d < i->least) { + i->least = d; + *i->Arc = arc; + *i->arc_pt = pcb_arc_end_ptr; + ret_val = PCB_R_DIR_FOUND_CONTINUE; + } + return ret_val; +} + +/* --------------------------------------------------------------------------- + * searches a line-point on all the search layer + */ +static pcb_bool SearchLinePointByLocation(unsigned long objst, unsigned long req_flag, pcb_layer_t ** Layer, pcb_line_t ** Line, pcb_point_t ** Point) +{ + struct line_info info; + *Layer = SearchLayer; + info.Line = Line; + info.Point = Point; + *Point = NULL; + info.least = PCB_MAX_LINE_POINT_DISTANCE + SearchRadius; + info.objst = objst; + info.req_flag = req_flag; + + if (pcb_r_search(SearchLayer->line_tree, &SearchBox, NULL, linepoint_callback, &info, NULL)) + return pcb_true; + return pcb_false; +} + +/* --------------------------------------------------------------------------- + * searches a line-point on all the search layer + */ +static pcb_bool SearchArcPointByLocation(unsigned long objst, unsigned long req_flag, pcb_layer_t ** Layer, pcb_arc_t ** Arc, int **Point) +{ + struct arc_info info; + *Layer = SearchLayer; + info.Arc = Arc; + info.arc_pt = Point; + *Point = NULL; + info.least = PCB_MAX_LINE_POINT_DISTANCE + SearchRadius; + info.objst = objst; + info.req_flag = req_flag; + + if (pcb_r_search(SearchLayer->arc_tree, &SearchBox, NULL, arcpoint_callback, &info, NULL)) + return pcb_true; + return pcb_false; +} + +/* --------------------------------------------------------------------------- + * searches a polygon-point on all layers that are switched on + * in layerstack order + */ +typedef struct { + double least; + pcb_bool found; + unsigned long Type; + + /* result */ + pcb_poly_t **Polygon; + pcb_point_t **Point; +} ptcb_t; + +static pcb_r_dir_t polypoint_callback(const pcb_box_t *box, void *cl) +{ + pcb_poly_t *polygon = (pcb_poly_t *)box; + ptcb_t *ctx = (ptcb_t *)cl; + double d; + pcb_data_t *dt; + + dt = polygon->parent.layer->parent.data; /* polygon -> layer -> data */ + if ((dt != NULL) && (dt->parent_type == PCB_PARENT_SUBC)) { + /* do not find subc part poly points if not explicitly requested */ + if (!(ctx->Type & PCB_OBJ_SUBC_PART)) + return PCB_R_DIR_NOT_FOUND; + + /* don't find subc poly points even as subc part unless we are editing a subc */ + if (!PCB->loose_subc) + return PCB_R_DIR_NOT_FOUND; + } + + PCB_POLY_POINT_LOOP(polygon); + { + d = pcb_distance2(point->X, point->Y, PosX, PosY); + if (d < ctx->least) { + ctx->least = d; + *ctx->Polygon = polygon; + *ctx->Point = point; + ctx->found = pcb_true; + } + } + PCB_END_LOOP; + + return PCB_R_DIR_NOT_FOUND; +} + +static pcb_bool SearchPointByLocation(unsigned long Type, unsigned long objst, unsigned long req_flag, pcb_layer_t ** Layer, pcb_poly_t ** Polygon, pcb_point_t ** Point) +{ + ptcb_t ctx; + + *Layer = SearchLayer; + ctx.Type = Type; + ctx.Polygon = Polygon; + ctx.Point = Point; + ctx.found = pcb_false;; + ctx.least = SearchRadius + PCB_MAX_POLYGON_POINT_DISTANCE; + ctx.least = ctx.least * ctx.least; + pcb_r_search(SearchLayer->polygon_tree, &SearchBox, NULL, polypoint_callback, &ctx, NULL); + + if (ctx.found) + return pcb_true; + return pcb_false; +} + + +static pcb_r_dir_t subc_callback(const pcb_box_t *box, void *cl) +{ + pcb_subc_t *subc = (pcb_subc_t *) box; + struct ans_info *i = (struct ans_info *) cl; + double newarea; + int subc_on_bottom = 0, front; + + pcb_subc_get_side(subc, &subc_on_bottom); + front = subc_on_bottom == conf_core.editor.show_solder_side; + + TEST_OBJST(i->objst, i->req_flag, g, subc, subc); + + if ((front || i->BackToo) && PCB_POINT_IN_BOX(PosX, PosY, &subc->BoundingBox)) { + /* use the subcircuit with the smallest bounding box */ + newarea = (subc->BoundingBox.X2 - subc->BoundingBox.X1) * (double) (subc->BoundingBox.Y2 - subc->BoundingBox.Y1); + if (newarea < i->area) { + i->area = newarea; + *i->ptr1 = *i->ptr2 = *i->ptr3 = subc; + return PCB_R_DIR_FOUND_CONTINUE; + } + } + return PCB_R_DIR_NOT_FOUND; +} + + +/* --------------------------------------------------------------------------- + * searches a subcircuit + * if more than one subc matches, the smallest one is taken + */ +static pcb_bool +SearchSubcByLocation(unsigned long objst, unsigned long req_flag, pcb_subc_t **subc, pcb_subc_t ** Dummy1, pcb_subc_t ** Dummy2, pcb_bool BackToo) +{ + struct ans_info info; + + /* Both package layers have to be switched on */ + info.ptr1 = (void **) subc; + info.ptr2 = (void **) Dummy1; + info.ptr3 = (void **) Dummy2; + info.area = PCB_SQUARE(PCB_MAX_COORD); + info.BackToo = (BackToo && PCB->InvisibleObjectsOn); + info.objst = objst; + info.req_flag = req_flag; + + if (pcb_r_search(PCB->Data->subc_tree, &SearchBox, NULL, subc_callback, &info, NULL)) + return pcb_true; + return pcb_false; +} + +/* find the first floater on any layer */ +static pcb_bool SearchSubcFloaterByLocation(unsigned long objst, unsigned long req_flag, pcb_subc_t **out_subc, pcb_text_t **out_txt, void **dummy, pcb_bool other_side) +{ + pcb_rtree_it_t it; + void *obj; + int n; + pcb_layer_type_t my_side_lyt; + + if (other_side) + my_side_lyt = conf_core.editor.show_solder_side ? PCB_LYT_TOP : PCB_LYT_BOTTOM; + else + my_side_lyt = conf_core.editor.show_solder_side ? PCB_LYT_BOTTOM : PCB_LYT_TOP; + + for(n = 0; n < PCB->Data->LayerN; n++) { + pcb_layer_t *ly = &PCB->Data->Layer[n]; + pcb_layer_type_t lyt; + + if ((ly->text_tree == NULL) || (!ly->meta.real.vis)) + continue; + + lyt = pcb_layer_flags_(ly); + if (!(lyt & my_side_lyt)) + continue; + + for(obj = pcb_rtree_first(&it, ly->text_tree, (pcb_rtree_box_t *)&SearchBox); obj != NULL; obj = pcb_rtree_next(&it)) { + pcb_text_t *txt = (pcb_text_t *)obj; + pcb_subc_t *subc; + + if (PCB_FLAG_TEST(PCB_FLAG_FLOATER, txt) == 0) + continue; + + subc = pcb_lobj_parent_subc(txt->parent_type, &txt->parent); + if (subc == NULL) + continue; + + TEST_OBJST_(objst, req_flag, l, txt, subc, continue); + + *out_subc = subc; + *out_txt = txt; + *dummy = txt; + return pcb_true; + } + } + + return pcb_false; +} + +/* for checking if a rat-line end is on a PV */ +pcb_bool pcb_is_point_on_line_end(pcb_coord_t X, pcb_coord_t Y, pcb_rat_t *Line) +{ + if (((X == Line->Point1.X) && (Y == Line->Point1.Y)) || ((X == Line->Point2.X) && (Y == Line->Point2.Y))) + return pcb_true; + return pcb_false; +} + +/* --------------------------------------------------------------------------- + * Calculate the distance (squared) from a point to a line. + * + * let the point be (X,Y) and the line (X1,Y1)(X2,Y2) + * + * Calculate the position along the line that is closest to X,Y. The value + * ranges from 0 to 1 when the point is within the line boundaries with a + * value of 0 being at point X1,Y1 and a value of 1.0 being at point X2,Y2. + * + * t = ((X-X1)*(X2-X1)) + ((Y-Y1)*(Y2-Y1)) + * ----------------------------------- + * (X2-X1)^2 + (Y2-Y1)^2 + * + * let Q be the point of perpendicular projection of (X,Y) onto the line + * + * QX = X1 + t * (X2-X1) + * QY = Y1 + t * (Y2-Y1) + * + * Calculate the distace (squared) using Pythagorean theorem. + * + * distance^2 = (X-QX)^2 + (Y-QY)^2 + */ + +double pcb_point_line_dist2(pcb_coord_t X, pcb_coord_t Y, pcb_line_t *Line) +{ + const double abx = Line->Point2.X - Line->Point1.X; + const double aby = Line->Point2.Y - Line->Point1.Y; + const double apx = X - Line->Point1.X; + const double apy = Y - Line->Point1.Y; + double qx,qy,dx,dy; + + /* Calculate t, the normalised position along the line of the closest point + * to (X,Y). A value between 0 and 1 indicates that the closest point on the + * line is within the bounds of the end points. + */ + double t = ( (apx * abx) + (apy * aby) ) / ( (abx * abx) + (aby * aby) ); + + /* Clamp 't' to the line bounds */ + if(t < 0.0) t = 0.0; + if(t > 1.0) t = 1.0; + + /* Calculate the point Q on the line that is closest to (X,Y) */ + qx = Line->Point1.X + (t * abx); + qy = Line->Point1.Y + (t * aby); + + /* Return the distance from Q to (X,Y), squared */ + dx = X - qx; + dy = Y - qy; + + return (dx * dx) + (dy * dy); +} + +pcb_bool pcb_is_point_on_line(pcb_coord_t X, pcb_coord_t Y, pcb_coord_t Radius, pcb_line_t *Line) +{ + double max = Radius + Line->Thickness / 2; + + return pcb_point_line_dist2(X, Y, Line) < (max * max); +} + +static int is_point_on_line(pcb_coord_t px, pcb_coord_t py, pcb_coord_t lx1, pcb_coord_t ly1, pcb_coord_t lx2, pcb_coord_t ly2) +{ + /* ohh well... let's hope the optimizer does something clever with inlining... */ + pcb_line_t l; + l.Point1.X = lx1; + l.Point1.Y = ly1; + l.Point2.X = lx2; + l.Point2.Y = ly2; + l.Thickness = 1; + return pcb_is_point_on_line(px, py, 1, &l); +} + +pcb_bool pcb_is_point_on_thinline( pcb_coord_t X, pcb_coord_t Y, pcb_coord_t X1, pcb_coord_t Y1, pcb_coord_t X2,pcb_coord_t Y2 ) +{ + /* Calculate the cross product of the vector from the first line point to the test point + * and the vector from the first line point to the second line point. If the result is + * not 0 then the point does not lie on the line. + */ + const pcb_coord_t lx = X2 - X1; + const pcb_coord_t ly = Y2 - Y1; + const pcb_coord_t cross = ((X-X1) * ly) - ((Y-Y1) * lx); + + if(cross != 0) + return pcb_false; + + /* If the point does lie on the line then we do a simple check to see if the point is + * between the end points. Use the longest side of the line to perform the check. + */ + if(abs(lx) > abs(ly)) + return (X >= MIN(X1,X2)) && (X <= MAX(X1,X2)) ? pcb_true : pcb_false; + + return (Y >= MIN(Y1,Y2)) && (Y <= MAX(Y1,Y2)) ? pcb_true : pcb_false; +} + +/* checks if a line crosses a rectangle or is within the rectangle */ +pcb_bool pcb_is_line_in_rectangle(pcb_coord_t X1, pcb_coord_t Y1, pcb_coord_t X2, pcb_coord_t Y2, pcb_line_t *Line) +{ + pcb_line_t line; + + /* first, see if point 1 is inside the rectangle */ + /* in case the whole line is inside the rectangle */ + if (X1 < Line->Point1.X && X2 > Line->Point1.X && Y1 < Line->Point1.Y && Y2 > Line->Point1.Y) + return pcb_true; + /* construct a set of dummy lines and check each of them */ + line.Thickness = 0; + line.Flags = pcb_no_flags(); + + /* upper-left to upper-right corner */ + line.Point1.Y = line.Point2.Y = Y1; + line.Point1.X = X1; + line.Point2.X = X2; + if (pcb_isc_line_line(&line, Line)) + return pcb_true; + + /* upper-right to lower-right corner */ + line.Point1.X = X2; + line.Point1.Y = Y1; + line.Point2.Y = Y2; + if (pcb_isc_line_line(&line, Line)) + return pcb_true; + + /* lower-right to lower-left corner */ + line.Point1.Y = Y2; + line.Point1.X = X1; + line.Point2.X = X2; + if (pcb_isc_line_line(&line, Line)) + return pcb_true; + + /* lower-left to upper-left corner */ + line.Point2.X = X1; + line.Point1.Y = Y1; + line.Point2.Y = Y2; + if (pcb_isc_line_line(&line, Line)) + return pcb_true; + + return pcb_false; +} + +/*checks if a point (of null radius) is in a slanted rectangle */ +static int IsPointInQuadrangle(pcb_point_t p[4], pcb_point_t *l) +{ + pcb_coord_t dx, dy, x, y; + double prod0, prod1; + + dx = p[1].X - p[0].X; + dy = p[1].Y - p[0].Y; + x = l->X - p[0].X; + y = l->Y - p[0].Y; + prod0 = (double) x *dx + (double) y *dy; + x = l->X - p[1].X; + y = l->Y - p[1].Y; + prod1 = (double) x *dx + (double) y *dy; + if (prod0 * prod1 <= 0) { + dx = p[1].X - p[2].X; + dy = p[1].Y - p[2].Y; + prod0 = (double) x *dx + (double) y *dy; + x = l->X - p[2].X; + y = l->Y - p[2].Y; + prod1 = (double) x *dx + (double) y *dy; + if (prod0 * prod1 <= 0) + return pcb_true; + } + return pcb_false; +} + +/* --------------------------------------------------------------------------- + * checks if a line crosses a quadrangle or is within the quadrangle: almost + * copied from pcb_is_line_in_rectangle() + * Note: actually this quadrangle is a slanted rectangle + */ +pcb_bool pcb_is_line_in_quadrangle(pcb_point_t p[4], pcb_line_t *Line) +{ + pcb_line_t line; + + /* first, see if point 1 is inside the rectangle */ + /* in case the whole line is inside the rectangle */ + if (IsPointInQuadrangle(p, &(Line->Point1))) + return pcb_true; + if (IsPointInQuadrangle(p, &(Line->Point2))) + return pcb_true; + /* construct a set of dummy lines and check each of them */ + line.Thickness = 0; + line.Flags = pcb_no_flags(); + + /* upper-left to upper-right corner */ + line.Point1.X = p[0].X; + line.Point1.Y = p[0].Y; + line.Point2.X = p[1].X; + line.Point2.Y = p[1].Y; + if (pcb_isc_line_line(&line, Line)) + return pcb_true; + + /* upper-right to lower-right corner */ + line.Point1.X = p[2].X; + line.Point1.Y = p[2].Y; + if (pcb_isc_line_line(&line, Line)) + return pcb_true; + + /* lower-right to lower-left corner */ + line.Point2.X = p[3].X; + line.Point2.Y = p[3].Y; + if (pcb_isc_line_line(&line, Line)) + return pcb_true; + + /* lower-left to upper-left corner */ + line.Point1.X = p[0].X; + line.Point1.Y = p[0].Y; + if (pcb_isc_line_line(&line, Line)) + return pcb_true; + + return pcb_false; +} + +/* --------------------------------------------------------------------------- + * checks if an arc crosses a rectangle (or arc is within the rectangle) + */ +pcb_bool pcb_is_arc_in_rectangle(pcb_coord_t X1, pcb_coord_t Y1, pcb_coord_t X2, pcb_coord_t Y2, pcb_arc_t *Arc) +{ + pcb_line_t line; + pcb_coord_t x, y; + pcb_box_t box; + + /* check if any of arc endpoints is inside the rectangle */ + box.X1 = X1; box.Y1 = Y1; + box.X2 = X2; box.Y2 = Y2; + pcb_arc_get_end (Arc, 0, &x, &y); + if (PCB_POINT_IN_BOX(x, y, &box)) + return pcb_true; + pcb_arc_get_end (Arc, 1, &x, &y); + if (PCB_POINT_IN_BOX(x, y, &box)) + return pcb_true; + + /* construct a set of dummy lines and check each of them */ + line.Thickness = 0; + line.Flags = pcb_no_flags(); + + /* upper-left to upper-right corner */ + line.Point1.Y = line.Point2.Y = Y1; + line.Point1.X = X1; + line.Point2.X = X2; + if (pcb_isc_line_arc(&line, Arc)) + return pcb_true; + + /* upper-right to lower-right corner */ + line.Point1.X = line.Point2.X = X2; + line.Point1.Y = Y1; + line.Point2.Y = Y2; + if (pcb_isc_line_arc(&line, Arc)) + return pcb_true; + + /* lower-right to lower-left corner */ + line.Point1.Y = line.Point2.Y = Y2; + line.Point1.X = X1; + line.Point2.X = X2; + if (pcb_isc_line_arc(&line, Arc)) + return pcb_true; + + /* lower-left to upper-left corner */ + line.Point1.X = line.Point2.X = X1; + line.Point1.Y = Y1; + line.Point2.Y = Y2; + if (pcb_isc_line_arc(&line, Arc)) + return pcb_true; + + return pcb_false; +} + +/* --------------------------------------------------------------------------- + * Check if a circle of Radius with center at (X, Y) intersects a line. + * Written to enable arbitrary line directions; for rounded/square lines, too. + */ +pcb_bool pcb_is_point_in_line(pcb_coord_t X, pcb_coord_t Y, pcb_coord_t Radius, pcb_any_line_t *Pad) +{ + double r, Sin, Cos; + pcb_coord_t x; + + /* Also used from line_callback with line type smaller than pad type; + use the smallest common subset; ->Thickness is still ok. */ + pcb_coord_t t2 = (Pad->Thickness + 1) / 2, range; + pcb_any_line_t pad = *Pad; + + + /* series of transforms saving range */ + /* move Point1 to the origin */ + X -= pad.Point1.X; + Y -= pad.Point1.Y; + + pad.Point2.X -= pad.Point1.X; + pad.Point2.Y -= pad.Point1.Y; + /* so, pad.Point1.X = pad.Point1.Y = 0; */ + + /* rotate round (0, 0) so that Point2 coordinates be (r, 0) */ + r = pcb_distance(0, 0, pad.Point2.X, pad.Point2.Y); + if (r < .1) { + Cos = 1; + Sin = 0; + } + else { + Sin = pad.Point2.Y / r; + Cos = pad.Point2.X / r; + } + x = X; + X = X * Cos + Y * Sin; + Y = Y * Cos - x * Sin; + /* now pad.Point2.X = r; pad.Point2.Y = 0; */ + + /* take into account the ends */ + if (PCB_FLAG_TEST(PCB_FLAG_SQUARE, Pad)) { + r += Pad->Thickness; + X += t2; + } + if (Y < 0) + Y = -Y; /* range value is evident now */ + + if (PCB_FLAG_TEST(PCB_FLAG_SQUARE, Pad)) { + if (X <= 0) { + if (Y <= t2) + range = -X; + else + return Radius > pcb_distance(0, t2, X, Y); + } + else if (X >= r) { + if (Y <= t2) + range = X - r; + else + return Radius > pcb_distance(r, t2, X, Y); + } + else + range = Y - t2; + } + else { /*Rounded pad: even more simple */ + + if (X <= 0) + return (Radius + t2) > pcb_distance(0, 0, X, Y); + else if (X >= r) + return (Radius + t2) > pcb_distance(r, 0, X, Y); + else + range = Y - t2; + } + return range < Radius; +} + +pcb_bool pcb_is_point_in_box(pcb_coord_t X, pcb_coord_t Y, pcb_box_t *box, pcb_coord_t Radius) +{ + pcb_coord_t width, height, range; + + /* NB: Assumes box has point1 with numerically lower X and Y coordinates */ + + /* Compute coordinates relative to Point1 */ + X -= box->X1; + Y -= box->Y1; + + width = box->X2 - box->X1; + height = box->Y2 - box->Y1; + + if (X <= 0) { + if (Y < 0) + return Radius > pcb_distance(0, 0, X, Y); + else if (Y > height) + return Radius > pcb_distance(0, height, X, Y); + else + range = -X; + } + else if (X >= width) { + if (Y < 0) + return Radius > pcb_distance(width, 0, X, Y); + else if (Y > height) + return Radius > pcb_distance(width, height, X, Y); + else + range = X - width; + } + else { + if (Y < 0) + range = -Y; + else if (Y > height) + range = Y - height; + else + return pcb_true; + } + + return range < Radius; +} + +pcb_bool pcb_arc_in_box(pcb_arc_t *arc, pcb_box_t *b) +{ + pcb_box_t ab = pcb_arc_mini_bbox(arc); + return PCB_BOX_IN_BOX(&ab, b); +} + +/* TODO: this code is BROKEN in the case of non-circular arcs, + * and in the case that the arc thickness is greater than + * the radius. + */ +pcb_bool pcb_is_point_on_arc(pcb_coord_t X, pcb_coord_t Y, pcb_coord_t Radius, pcb_arc_t *Arc) +{ + /* Calculate angle of point from arc center */ + double p_dist = pcb_distance(X, Y, Arc->X, Arc->Y); + double p_cos = (X - Arc->X) / p_dist; + pcb_angle_t p_ang = acos(p_cos) * PCB_RAD_TO_DEG; + pcb_angle_t ang1, ang2; +#define angle_in_range(r1, r2, ang) (((ang) >= (r1)) && ((ang) <= (r2))) + + + /* Convert StartAngle, Delta into bounding angles in [0, 720) */ + if (Arc->Delta > 0) { + ang1 = pcb_normalize_angle(Arc->StartAngle); + ang2 = pcb_normalize_angle(Arc->StartAngle + Arc->Delta); + } + else { + ang1 = pcb_normalize_angle(Arc->StartAngle + Arc->Delta); + ang2 = pcb_normalize_angle(Arc->StartAngle); + } + if (ang1 > ang2) + ang2 += 360; + /* Make sure full circles aren't treated as zero-length arcs */ + if (Arc->Delta == 360 || Arc->Delta == -360) + ang2 = ang1 + 360; + + if (Y > Arc->Y) + p_ang = -p_ang; + p_ang += 180; + + + /* Check point is outside arc range, check distance from endpoints + Need to check p_ang+360 too, because after the angle swaps above ang2 + might be larger than 360 and that section of the arc shouldn't be missed + either. */ + if (!angle_in_range(ang1, ang2, p_ang) && !angle_in_range(ang1, ang2, p_ang+360)) { + pcb_coord_t ArcX, ArcY; + ArcX = Arc->X + Arc->Width * cos((Arc->StartAngle + 180) / PCB_RAD_TO_DEG); + ArcY = Arc->Y - Arc->Height * sin((Arc->StartAngle + 180) / PCB_RAD_TO_DEG); + if (pcb_distance(X, Y, ArcX, ArcY) < Radius + Arc->Thickness / 2) + return pcb_true; + + ArcX = Arc->X + Arc->Width * cos((Arc->StartAngle + Arc->Delta + 180) / PCB_RAD_TO_DEG); + ArcY = Arc->Y - Arc->Height * sin((Arc->StartAngle + Arc->Delta + 180) / PCB_RAD_TO_DEG); + if (pcb_distance(X, Y, ArcX, ArcY) < Radius + Arc->Thickness / 2) + return pcb_true; + return pcb_false; + } + + if ((Arc->Width == Arc->Height) || (fabs(Arc->Width - Arc->Height) < PCB_MM_TO_COORD(0.1))) { + /* Simple circular case: if point is inside the arc range, just compare it to the arc */ + return fabs(pcb_distance(X, Y, Arc->X, Arc->Y) - Arc->Width) < Radius + Arc->Thickness / 2; + } + else { + /* elliptical case: guess where the arc would be in that point, by angle */ + double ang, dx, dy; + pcb_coord_t ax, ay, d; + +TODO(": elliptical arc: rewrite this, as it does not work properly on extreme cases") + dy = (double)(Y - Arc->Y) / (double)Arc->Height; + dx = (double)(X - Arc->X) / (double)Arc->Width; + ang = -atan2(dy, dx); + + ax = Arc->X + cos(ang) * Arc->Width; + ay = Arc->Y - sin(ang) * Arc->Height; + + d = fabs(pcb_distance(X, Y, ax, ay)); + + return d < Arc->Thickness / 2; + } +#undef angle_in_range +} + +pcb_line_t *pcb_line_center_cross_point(pcb_layer_t *layer, pcb_coord_t x, pcb_coord_t y, pcb_angle_t *ang, pcb_bool no_subc_part, pcb_bool no_term) +{ + pcb_rtree_it_t it; + pcb_rtree_box_t pt; + pcb_line_t *l; + +/* TODO: set pt coords to x and y */ + + for(l = pcb_rtree_first(&it, layer->line_tree, &pt); l != NULL; l = pcb_rtree_next(&it)) { + /* check if line needs to be ignored and "continue;" if so: + l->term is non-NULL if it's a terminal, + pcb_lobj_parent_subc(pcb_parenttype_t pt, pcb_parent_t *p) returns non-NULL if it's in a subc + */ + /* if the line shouldn't be ignored, check if x;y is on the centerline and + "continue;" if bad */ + /* check if angle is required and is correct; "continue;" on mismatch */ + return l; + } + return NULL; /* found nothing */ +} + +pcb_layer_type_t pstk_vis_layers(pcb_board_t *pcb, pcb_layer_type_t material) +{ + pcb_layer_type_t res = 0, lyt; + pcb_layer_id_t lid; + for(lid = 0; lid < pcb->Data->LayerN; lid++) { + pcb_layer_t *ly = &pcb->Data->Layer[lid]; + lyt = pcb_layer_flags_(ly); + if ((ly->meta.real.vis) && (lyt & material)) + res |= (lyt & PCB_LYT_ANYWHERE); + } + return res | material; +} + +static int pcb_search_obj_by_loc_layer(unsigned long Type, void **Result1, void **Result2, void **Result3, unsigned long req_flag, pcb_layer_t *SearchLayer, int HigherAvail, double HigherBound, int objst) +{ + if (SearchLayer->meta.real.vis) { + if ((HigherAvail & (PCB_OBJ_PSTK)) == 0 && + Type & PCB_OBJ_POLY_POINT && + SearchPointByLocation(Type, objst, req_flag, (pcb_layer_t **) Result1, (pcb_poly_t **) Result2, (pcb_point_t **) Result3)) + return PCB_OBJ_POLY_POINT; + + if ((HigherAvail & (PCB_OBJ_PSTK)) == 0 && + Type & PCB_OBJ_LINE_POINT && + SearchLinePointByLocation(objst, req_flag, (pcb_layer_t **) Result1, (pcb_line_t **) Result2, (pcb_point_t **) Result3)) + return PCB_OBJ_LINE_POINT; + + if ((HigherAvail & (PCB_OBJ_PSTK)) == 0 && + Type & PCB_OBJ_ARC_POINT && + SearchArcPointByLocation(objst, req_flag, (pcb_layer_t **) Result1, (pcb_arc_t **) Result2, (int **) Result3)) + return PCB_OBJ_ARC_POINT; + + if ((HigherAvail & (PCB_OBJ_PSTK)) == 0 && Type & PCB_OBJ_LINE + && SearchLineByLocation(objst, req_flag, (pcb_layer_t **) Result1, (pcb_line_t **) Result2, (pcb_line_t **) Result3)) + return PCB_OBJ_LINE; + + if ((HigherAvail & (PCB_OBJ_PSTK)) == 0 && Type & PCB_OBJ_ARC && + SearchArcByLocation(objst, req_flag, (pcb_layer_t **) Result1, (pcb_arc_t **) Result2, (pcb_arc_t **) Result3)) + return PCB_OBJ_ARC; + + if ((HigherAvail & (PCB_OBJ_PSTK)) == 0 && Type & PCB_OBJ_TEXT + && SearchTextByLocation(objst, req_flag, (pcb_layer_t **) Result1, (pcb_text_t **) Result2, (pcb_text_t **) Result3)) + return PCB_OBJ_TEXT; + + if (Type & PCB_OBJ_POLY && + SearchPolygonByLocation(objst, req_flag, (pcb_layer_t **) Result1, (pcb_poly_t **) Result2, (pcb_poly_t **) Result3)) { + if (HigherAvail) { + pcb_box_t *box = &(*(pcb_poly_t **) Result2)->BoundingBox; + double area = (double) (box->X2 - box->X1) * (double) (box->X2 - box->X1); + if (HigherBound < area) + return -1; + else + return PCB_OBJ_POLY; + } + else + return PCB_OBJ_POLY; + } + } + return 0; +} + +/* --------------------------------------------------------------------------- + * searches for any kind of object or for a set of object types + * the calling routine passes two pointers to allocated memory for storing + * the results. + * A type value is returned too which is PCB_OBJ_VOID if no objects has been found. + * A set of object types is passed in. + * The object is located by it's position. + * + * The layout is checked in the following order: + * polygon-point, padstack, line, text, polygon, subcircuit + * + * Note that if Type includes PCB_OBJ_LOCKED, then the search includes + * locked items. Otherwise, locked items are ignored. + + * Note that if Type includes PCB_OBJ_SUBC_PART, then the search includes + * objects that are part of subcircuits, else they are ignored. + */ +static int pcb_search_obj_by_location_(unsigned long Type, void **Result1, void **Result2, void **Result3, pcb_coord_t X, pcb_coord_t Y, pcb_coord_t Radius, unsigned long req_flag) +{ + void *r1, *r2, *r3; + void **pr1 = &r1, **pr2 = &r2, **pr3 = &r3; + int i; + double HigherBound = 0; + int HigherAvail = PCB_OBJ_VOID; + int objst = Type & (PCB_OBJ_LOCKED | PCB_OBJ_SUBC_PART); + pcb_layer_id_t front_silk_id, back_silk_id; + + /* setup variables used by local functions */ + PosX = X; + PosY = Y; + SearchRadius = Radius; + if (Radius) { + SearchBox.X1 = X - Radius; + SearchBox.Y1 = Y - Radius; + SearchBox.X2 = X + Radius; + SearchBox.Y2 = Y + Radius; + } + else { + SearchBox = pcb_point_box(X, Y); + } + + if (conf_core.editor.only_names) { + Type &= PCB_OBJ_TEXT; + } + + if (conf_core.editor.thin_draw || conf_core.editor.thin_draw_poly) { + Type &= ~PCB_OBJ_POLY; + } + + if (Type & PCB_OBJ_RAT && PCB->RatOn && + SearchRatLineByLocation(objst, req_flag, (pcb_rat_t **) Result1, (pcb_rat_t **) Result2, (pcb_rat_t **) Result3)) + return PCB_OBJ_RAT; + + if (Type & PCB_OBJ_PSTK && SearchPadstackByLocation(objst, req_flag, (pcb_pstk_t **) Result1, (pcb_pstk_t **) Result2, (pcb_pstk_t **) Result3, 1, 0)) + return PCB_OBJ_PSTK; + + if (Type & PCB_OBJ_PSTK && SearchPadstackByLocation(objst, req_flag, (pcb_pstk_t **) Result1, (pcb_pstk_t **) Result2, (pcb_pstk_t **) Result3, 0, PCB_LYT_VISIBLE_SIDE() | PCB_LYT_COPPER)) + return PCB_OBJ_PSTK; + + if (Type & PCB_OBJ_PSTK && SearchPadstackByLocation(objst, req_flag, (pcb_pstk_t **) Result1, (pcb_pstk_t **) Result2, (pcb_pstk_t **) Result3, 0, (PCB_LYT_VISIBLE_SIDE() | PCB_LYT_ANYTHING) & pstk_vis_layers(PCB, PCB_LYT_ANYTHING))) + return PCB_OBJ_PSTK; + + if (Type & PCB_OBJ_PSTK && SearchPadstackByLocation(objst, req_flag, (pcb_pstk_t **) Result1, (pcb_pstk_t **) Result2, (pcb_pstk_t **) Result3, 0, pstk_vis_layers(PCB, PCB_LYT_MASK))) + return PCB_OBJ_PSTK; + + if (Type & PCB_OBJ_PSTK && SearchPadstackByLocation(objst, req_flag, (pcb_pstk_t **) Result1, (pcb_pstk_t **) Result2, (pcb_pstk_t **) Result3, 0, pstk_vis_layers(PCB, PCB_LYT_COPPER))) + return PCB_OBJ_PSTK; + + if (Type & PCB_OBJ_PSTK && SearchPadstackByLocation(objst, req_flag, (pcb_pstk_t **) Result1, (pcb_pstk_t **) Result2, (pcb_pstk_t **) Result3, 0, pstk_vis_layers(PCB, PCB_LYT_PASTE))) + return PCB_OBJ_PSTK; + + if (!HigherAvail && (Type & PCB_OBJ_FLOATER) && (Type & PCB_OBJ_TEXT) && + SearchSubcFloaterByLocation(objst, req_flag, (pcb_subc_t **)pr1, (pcb_text_t **) pr2, pr3, pcb_false)) { + *Result1 = ((pcb_text_t *)r2)->parent.layer; + *Result2 = r2; + *Result3 = r3; + return PCB_OBJ_TEXT; + } + + if (!HigherAvail && Type & PCB_OBJ_SUBC && PCB->SubcOn && + SearchSubcByLocation(objst, req_flag, (pcb_subc_t **) pr1, (pcb_subc_t **) pr2, (pcb_subc_t **) pr3, pcb_false)) { + pcb_box_t *box = &((pcb_subc_t *) r1)->BoundingBox; + HigherBound = (double) (box->X2 - box->X1) * (double) (box->Y2 - box->Y1); + HigherAvail = PCB_OBJ_SUBC; + } + + front_silk_id = conf_core.editor.show_solder_side ? pcb_layer_get_bottom_silk() : pcb_layer_get_top_silk(); + back_silk_id = conf_core.editor.show_solder_side ? pcb_layer_get_top_silk() : pcb_layer_get_bottom_silk(); + + for (i = -1; i < pcb_max_layer + 1; i++) { + int found; + if (pcb_layer_flags(PCB, i) & PCB_LYT_SILK) /* special order: silks are i=-1 and i=max+1, if we meet them elsewhere, skip */ + continue; + + if (i < 0) { + if (front_silk_id < 0) + continue; + SearchLayer = &PCB->Data->Layer[front_silk_id]; + } + else if (i < pcb_max_layer) { + SearchLayer = LAYER_ON_STACK(i); + } + else { + if (back_silk_id < 0) + continue; + SearchLayer = &PCB->Data->Layer[back_silk_id]; + if (!PCB->InvisibleObjectsOn) + continue; + } + found = pcb_search_obj_by_loc_layer(Type, Result1, Result2, Result3, req_flag, SearchLayer, HigherAvail, HigherBound, objst); + if (found < 0) + break; + if (found != 0) + return found; + } + /* return any previously found objects */ + if (HigherAvail & PCB_OBJ_PSTK) { + *Result1 = r1; + *Result2 = r2; + *Result3 = r3; + return PCB_OBJ_PSTK; + } + + if (HigherAvail & PCB_OBJ_SUBC) { + *Result1 = r1; + *Result2 = r2; + *Result3 = r3; + return PCB_OBJ_SUBC; + } + + /* search the 'invisible objects' last */ + if (!PCB->InvisibleObjectsOn) + return PCB_OBJ_VOID; + + if ((Type & PCB_OBJ_FLOATER) && (Type & PCB_OBJ_TEXT) && + SearchSubcFloaterByLocation(objst, req_flag, (pcb_subc_t **)pr1, (pcb_text_t **) pr2, pr3, pcb_true)) { + *Result1 = ((pcb_text_t *)r2)->parent.layer; + *Result2 = r2; + *Result3 = r3; + return PCB_OBJ_TEXT; + } + + if (Type & PCB_OBJ_SUBC && PCB->SubcOn && + SearchSubcByLocation(objst, req_flag, (pcb_subc_t **) Result1, (pcb_subc_t **) Result2, (pcb_subc_t **) Result3, pcb_true)) + return PCB_OBJ_SUBC; + + return PCB_OBJ_VOID; +} + +int pcb_search_obj_by_location(unsigned long Type, void **Result1, void **Result2, void **Result3, pcb_coord_t X, pcb_coord_t Y, pcb_coord_t Radius) +{ + int res; + + if ((conf_core.editor.lock_names) || (conf_core.editor.hide_names)) + Type &= ~ PCB_OBJ_FLOATER; + + res = pcb_search_obj_by_location_(Type, Result1, Result2, Result3, X, Y, Radius, 0); + if ((res != PCB_OBJ_VOID) && (res != PCB_OBJ_SUBC)) + return res; + + /* found a subc because it was still the best option over all the plain + objects; if floaters can be found, repeat the search on them, they + have higher prio than subc, but lower prio than plain objects */ + if ((!conf_core.editor.lock_names) && (!conf_core.editor.hide_names)) { + int fres; + void *fr1, *fr2, *fr3; + Type &= ~PCB_OBJ_SUBC; + Type |= PCB_OBJ_SUBC_PART; + fres = pcb_search_obj_by_location_(Type, &fr1, &fr2, &fr3, X, Y, Radius, PCB_FLAG_FLOATER); + if (fres != PCB_OBJ_VOID) { + *Result1 = fr1; + *Result2 = fr2; + *Result3 = fr3; + return fres; + } + } + + return res; +} + + +/* --------------------------------------------------------------------------- + * searches for a object by it's unique ID. It doesn't matter if + * the object is visible or not. The search is performed on a PCB, a + * buffer or on the remove list. + * The calling routine passes two pointers to allocated memory for storing + * the results. + * A type value is returned too which is PCB_OBJ_VOID if no objects has been found. + */ +int pcb_search_obj_by_id_(pcb_data_t *Base, void **Result1, void **Result2, void **Result3, int ID, int type) +{ + if (type == PCB_OBJ_LINE || type == PCB_OBJ_LINE_POINT) { + PCB_LINE_ALL_LOOP(Base); + { + if (line->ID == ID) { + *Result1 = (void *) layer; + *Result2 = *Result3 = (void *) line; + return PCB_OBJ_LINE; + } + if (line->Point1.ID == ID) { + *Result1 = (void *) layer; + *Result2 = (void *) line; + *Result3 = (void *) &line->Point1; + return PCB_OBJ_LINE_POINT; + } + if (line->Point2.ID == ID) { + *Result1 = (void *) layer; + *Result2 = (void *) line; + *Result3 = (void *) &line->Point2; + return PCB_OBJ_LINE_POINT; + } + } + PCB_ENDALL_LOOP; + } + if (type == PCB_OBJ_ARC || type == PCB_OBJ_ARC_POINT) { + PCB_ARC_ALL_LOOP(Base); + { + if (arc->ID == ID) { + *Result1 = (void *) layer; + *Result2 = *Result3 = (void *) arc; + return PCB_OBJ_ARC; + } + } + PCB_ENDALL_LOOP; + } + + if (type == PCB_OBJ_TEXT) { + PCB_TEXT_ALL_LOOP(Base); + { + if (text->ID == ID) { + *Result1 = (void *) layer; + *Result2 = *Result3 = (void *) text; + return PCB_OBJ_TEXT; + } + } + PCB_ENDALL_LOOP; + } + + if (type == PCB_OBJ_POLY || type == PCB_OBJ_POLY_POINT) { + PCB_POLY_ALL_LOOP(Base); + { + if (polygon->ID == ID) { + *Result1 = (void *) layer; + *Result2 = *Result3 = (void *) polygon; + return PCB_OBJ_POLY; + } + if (type == PCB_OBJ_POLY_POINT) + PCB_POLY_POINT_LOOP(polygon); + { + if (point->ID == ID) { + *Result1 = (void *) layer; + *Result2 = (void *) polygon; + *Result3 = (void *) point; + return PCB_OBJ_POLY_POINT; + } + } + PCB_END_LOOP; + } + PCB_ENDALL_LOOP; + } + + if (type == PCB_OBJ_PSTK) { + PCB_PADSTACK_LOOP(Base); + { + if (padstack->ID == ID) { + *Result1 = *Result2 = *Result3 = (void *)padstack; + return PCB_OBJ_PSTK; + } + } + PCB_END_LOOP; + } + + if (type == PCB_OBJ_RAT || type == PCB_OBJ_LINE_POINT) { + PCB_RAT_LOOP(Base); + { + if (line->ID == ID) { + *Result1 = *Result2 = *Result3 = (void *) line; + return PCB_OBJ_RAT; + } + if (line->Point1.ID == ID) { + *Result1 = (void *) NULL; + *Result2 = (void *) line; + *Result3 = (void *) &line->Point1; + return PCB_OBJ_LINE_POINT; + } + if (line->Point2.ID == ID) { + *Result1 = (void *) NULL; + *Result2 = (void *) line; + *Result3 = (void *) &line->Point2; + return PCB_OBJ_LINE_POINT; + } + } + PCB_END_LOOP; + } + +TODO("subc: once elements are gone, rewrite these to search the rtree instead of recursion") + PCB_SUBC_LOOP(Base); + { + int res; + if (type == PCB_OBJ_SUBC) { + if (subc->ID == ID) { + *Result1 = *Result2 = *Result3 = (void *)subc; + return PCB_OBJ_SUBC; + } + } + + res = pcb_search_obj_by_id_(subc->data, Result1, Result2, Result3, ID, type); + if (res != PCB_OBJ_VOID) + return res; + } + PCB_END_LOOP; + + return PCB_OBJ_VOID; +} + +int pcb_search_obj_by_id(pcb_data_t *Base, void **Result1, void **Result2, void **Result3, int ID, int type) +{ + int res = pcb_search_obj_by_id_(Base, Result1, Result2, Result3, ID, type); + if (res == PCB_OBJ_VOID) + pcb_message(PCB_MSG_ERROR, "hace: Internal error, search for ID %d failed\n", ID); + return res; +} + +int pcb_search_obj_by_id_buf2(pcb_data_t *Base, void **Result1, void **Result2, void **Result3, int ID, int type) +{ + int bid = 0; + long res; + + res = pcb_search_obj_by_id_(Base, Result1, Result2, Result3, ID, type); + if (res != PCB_OBJ_VOID) + return res; + + while(res == PCB_OBJ_VOID) { + res = pcb_search_obj_by_id_(pcb_buffers[bid].Data, Result1, Result2, Result3, ID, type); + if (res != PCB_OBJ_VOID) + return res; + bid++; + if (bid >= PCB_MAX_BUFFER) + break; + } + + pcb_message(PCB_MSG_ERROR, "hace: Internal error, search for ID %d failed\n", ID); + return PCB_OBJ_VOID; +} + +/* --------------------------------------------------------------------------- + * searches the cursor position for the type + */ +int pcb_search_screen(pcb_coord_t X, pcb_coord_t Y, int Type, void **Result1, void **Result2, void **Result3) +{ + return pcb_search_obj_by_location(Type, Result1, Result2, Result3, X, Y, PCB_SLOP * pcb_pixel_slop); +} + +/* --------------------------------------------------------------------------- + * searches the cursor position for the type + */ +int pcb_search_grid_slop(pcb_coord_t X, pcb_coord_t Y, int Type, void **Result1, void **Result2, void **Result3) +{ + int ans; + + ans = pcb_search_obj_by_location(Type, Result1, Result2, Result3, X, Y, PCB->Grid / 2); + return ans; +} + +int pcb_lines_intersect(pcb_coord_t ax1, pcb_coord_t ay1, pcb_coord_t ax2, pcb_coord_t ay2, pcb_coord_t bx1, pcb_coord_t by1, pcb_coord_t bx2, pcb_coord_t by2) +{ +/* TODO: this should be long double if pcb_coord_t is 64 bits */ + double ua, xi, yi, X1, Y1, X2, Y2, X3, Y3, X4, Y4, tmp; + int is_a_pt, is_b_pt; + + /* degenerate cases: a line is actually a point */ + is_a_pt = (ax1 == ax2) && (ay1 == ay2); + is_b_pt = (bx1 == bx2) && (by1 == by2); + + if (is_a_pt && is_b_pt) + return (ax1 == bx1) && (ay1 == by1); + + if (is_a_pt) + return is_point_on_line(ax1, ay1, bx1, by1, bx2, by2); + if (is_b_pt) + return is_point_on_line(bx1, by1, ax1, ay1, ax2, ay2); + + /* maths from http://local.wasp.uwa.edu.au/~pbourke/geometry/lineline2d/ */ + + X1 = ax1; + X2 = ax2; + X3 = bx1; + X4 = bx2; + Y1 = ay1; + Y2 = ay2; + Y3 = by1; + Y4 = by2; + + tmp = ((Y4 - Y3) * (X2 - X1) - (X4 - X3) * (Y2 - Y1)); + + if (tmp == 0) { + /* Corner case: parallel lines; intersect only if the endpoint of either line + is on the other line */ + return + is_point_on_line(ax1, ay1, bx1, by1, bx2, by2) || + is_point_on_line(ax2, ay2, bx1, by1, bx2, by2) || + is_point_on_line(bx1, by1, ax1, ay1, ax2, ay2) || + is_point_on_line(bx2, by2, ax1, ay1, ax2, ay2); + } + + + ua = ((X4 - X3) * (Y1 - Y3) - (Y4 - Y3) * (X1 - X3)) / tmp; +/* ub = ((X2 - X1) * (Y1 - Y3) - (Y2 - Y1) * (X1 - X3)) / tmp;*/ + xi = X1 + ua * (X2 - X1); + yi = Y1 + ua * (Y2 - Y1); + +#define check(e1, e2, i) \ + if (e1 < e2) { \ + if ((i < e1) || (i > e2)) \ + return 0; \ + } \ + else { \ + if ((i > e1) || (i < e2)) \ + return 0; \ + } + + check(ax1, ax2, xi); + check(bx1, bx2, xi); + check(ay1, ay2, yi); + check(by1, by2, yi); + return 1; +} + + +pcb_r_dir_t pcb_search_data_by_loc(pcb_data_t *data, pcb_objtype_t type, const pcb_box_t *query_box, pcb_r_dir_t (*cb_)(void *closure, pcb_any_obj_t *obj, void *box), void *closure) +{ + pcb_layer_t *ly; + pcb_layer_id_t lid; + pcb_r_dir_t res; + const pcb_rtree_box_t *query = (const pcb_rtree_box_t *)query_box; + pcb_rtree_dir_t (*cb)(void *, void *, const pcb_rtree_box_t *) = (pcb_rtree_dir_t(*)(void *, void *, const pcb_rtree_box_t *))cb_; + + if ((type & PCB_OBJ_PSTK) && (data->padstack_tree != NULL)) { + res = pcb_rtree_search_any(data->padstack_tree, query, NULL, cb, closure, NULL); + if (res & pcb_RTREE_DIR_STOP) + return res; + } + + if ((type & PCB_OBJ_SUBC) && (data->subc_tree != NULL)) { + res = pcb_rtree_search_any(data->subc_tree, query, NULL, cb, closure, NULL); + if (res & pcb_RTREE_DIR_STOP) + return res; + } + + if ((type & PCB_OBJ_RAT) && (data->rat_tree != NULL)) { + res = pcb_rtree_search_any(data->rat_tree, query, NULL, cb, closure, NULL); + if (res & pcb_RTREE_DIR_STOP) + return res; + } + + for(lid = 0, ly = data->Layer; lid < data->LayerN; lid++,ly++) { + + if ((type & PCB_OBJ_ARC) && (ly->arc_tree != NULL)) { + res = pcb_rtree_search_any(ly->arc_tree, query, NULL, cb, closure, NULL); + if (res & pcb_RTREE_DIR_STOP) + return res; + } + if ((type & PCB_OBJ_LINE) && (ly->line_tree != NULL)) { + res = pcb_rtree_search_any(ly->line_tree, query, NULL, cb, closure, NULL); + if (res & pcb_RTREE_DIR_STOP) + return res; + } + if ((type & PCB_OBJ_POLY) && (ly->polygon_tree != NULL)) { + res = pcb_rtree_search_any(ly->polygon_tree, query, NULL, cb, closure, NULL); + if (res & pcb_RTREE_DIR_STOP) + return res; + } + if ((type & PCB_OBJ_TEXT) && (ly->text_tree != NULL)) { + res = pcb_rtree_search_any(ly->text_tree, query, NULL, cb, closure, NULL); + if (res & pcb_RTREE_DIR_STOP) + return res; + } + + } + return 0; +} + Index: tags/2.1.2/src/search.h =================================================================== --- tags/2.1.2/src/search.h (nonexistent) +++ tags/2.1.2/src/search.h (revision 24813) @@ -0,0 +1,194 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +/* Search object by location routines */ + +#ifndef PCB_SEARCH_H +#define PCB_SEARCH_H + +#include "global_typedefs.h" +#include "layer.h" + +int pcb_lines_intersect(pcb_coord_t ax1, pcb_coord_t ay1, pcb_coord_t ax2, pcb_coord_t ay2, pcb_coord_t bx1, pcb_coord_t by1, pcb_coord_t bx2, pcb_coord_t by2); +pcb_bool pcb_arc_in_box(pcb_arc_t *arc, pcb_box_t *b); + +#define PCB_SLOP 5 + +/* --------------------------------------------------------------------------- + * some define to check for 'type' in box + */ +#define PCB_POINT_IN_BOX(x,y,b) \ + (PCB_IS_BOX_NEGATIVE(b) ? \ + ((x) >= (b)->X2 && (x) <= (b)->X1 && (y) >= (b)->Y2 && (y) <= (b)->Y1) \ + : \ + ((x) >= (b)->X1 && (x) <= (b)->X2 && (y) >= (b)->Y1 && (y) <= (b)->Y2)) + +#define PCB_VIA_OR_PIN_IN_BOX(v,b) \ + ( \ + PCB_POINT_IN_BOX((v)->X-(v)->Thickness/2,(v)->Y-(v)->Thickness/2,(b)) && \ + PCB_POINT_IN_BOX((v)->X+(v)->Thickness/2,(v)->Y+(v)->Thickness/2,(b)) \ + ) + +#define PCB_LINE_IN_BOX(l,b) \ + (PCB_POINT_IN_BOX((l)->Point1.X,(l)->Point1.Y,(b)) && \ + PCB_POINT_IN_BOX((l)->Point2.X,(l)->Point2.Y,(b))) + +#define PCB_PAD_IN_BOX(p,b) PCB_LINE_IN_BOX((pcb_line_t *)(p),(b)) + +#define PCB_BOX_IN_BOX(b1,b) \ + ((b1)->X1 >= (b)->X1 && (b1)->X2 <= (b)->X2 && \ + ((b1)->Y1 >= (b)->Y1 && (b1)->Y2 <= (b)->Y2)) + +#define PCB_TEXT_IN_BOX(t,b) \ + (PCB_BOX_IN_BOX(&((t)->BoundingBox), (b))) + +#define PCB_POLYGON_IN_BOX(p,b) \ + (PCB_BOX_IN_BOX(&((p)->BoundingBox), (b))) + +#define PCB_SUBC_IN_BOX(s,b) \ + (PCB_BOX_IN_BOX(&((s)->BoundingBox), (b))) + +#define PCB_ELEMENT_IN_BOX(e,b) \ + (PCB_BOX_IN_BOX(&((e)->BoundingBox), (b))) + +/* the bounding box is much larger than the minimum, use it to decide it + it is worth doing the expensive precise calculations */ +#define PCB_ARC_IN_BOX(a,b) \ + ((PCB_BOX_TOUCHES_BOX(&((a)->BoundingBox), (b))) && (pcb_arc_in_box(a,b))) + +/* == the same but accept if any part of the object touches the box == */ +#define PCB_POINT_IN_CIRCLE(x, y, cx, cy, r) \ + (pcb_distance2(x, y, cx, cy) <= (double)(r) * (double)(r)) + +#define PCB_CIRCLE_TOUCHES_BOX(cx, cy, r, b) \ + ( PCB_POINT_IN_BOX((cx)-(r),(cy),(b)) || PCB_POINT_IN_BOX((cx)+(r),(cy),(b)) || PCB_POINT_IN_BOX((cx),(cy)-(r),(b)) || PCB_POINT_IN_BOX((cx),(cy)+(r),(b)) \ + || PCB_POINT_IN_CIRCLE((b)->X1, (b)->Y1, (cx), (cy), (r)) || PCB_POINT_IN_CIRCLE((b)->X2, (b)->Y1, (cx), (cy), (r)) || PCB_POINT_IN_CIRCLE((b)->X1, (b)->Y2, (cx), (cy), (r)) || PCB_POINT_IN_CIRCLE((b)->X2, (b)->Y2, (cx), (cy), (r))) + +#define PCB_VIA_OR_PIN_TOUCHES_BOX(v,b) \ + PCB_CIRCLE_TOUCHES_BOX((v)->X,(v)->Y,((v)->Thickness + (v)->DrillingHole/2),(b)) + +#define PCB_LINE_TOUCHES_BOX(l,b) \ + ( pcb_lines_intersect((l)->Point1.X,(l)->Point1.Y,(l)->Point2.X,(l)->Point2.Y, (b)->X1, (b)->Y1, (b)->X2, (b)->Y1) \ + || pcb_lines_intersect((l)->Point1.X,(l)->Point1.Y,(l)->Point2.X,(l)->Point2.Y, (b)->X1, (b)->Y1, (b)->X1, (b)->Y2) \ + || pcb_lines_intersect((l)->Point1.X,(l)->Point1.Y,(l)->Point2.X,(l)->Point2.Y, (b)->X2, (b)->Y2, (b)->X1, (b)->Y2) \ + || pcb_lines_intersect((l)->Point1.X,(l)->Point1.Y,(l)->Point2.X,(l)->Point2.Y, (b)->X2, (b)->Y2, (b)->X2, (b)->Y1) \ + || PCB_LINE_IN_BOX((l), (b))) + +#define PCB_XYLINE_ISECTS_BOX(x1,y1,x2,y2,b) \ + ( pcb_lines_intersect(x1,y1,x2,y2, (b)->X1, (b)->Y1, (b)->X2, (b)->Y1) \ + || pcb_lines_intersect(x1,y1,x2,y2, (b)->X1, (b)->Y1, (b)->X1, (b)->Y2) \ + || pcb_lines_intersect(x1,y1,x2,y2, (b)->X2, (b)->Y2, (b)->X1, (b)->Y2) \ + || pcb_lines_intersect(x1,y1,x2,y2, (b)->X2, (b)->Y2, (b)->X2, (b)->Y1) \ + ) + +#define PCB_PAD_TOUCHES_BOX(p,b) PCB_LINE_TOUCHES_BOX((pcb_line_t *)(p),(b)) + +/* a corner of either box is within the other, or edges cross */ +#define PCB_BOX_TOUCHES_BOX(b1,b2) \ + ( PCB_POINT_IN_BOX((b1)->X1,(b1)->Y1,b2) || PCB_POINT_IN_BOX((b1)->X1,(b1)->Y2,b2) || PCB_POINT_IN_BOX((b1)->X2,(b1)->Y1,b2) || PCB_POINT_IN_BOX((b1)->X2,(b1)->Y2,b2) \ + || PCB_POINT_IN_BOX((b2)->X1,(b2)->Y1,b1) || PCB_POINT_IN_BOX((b2)->X1,(b2)->Y2,b1) || PCB_POINT_IN_BOX((b2)->X2,(b2)->Y1,b1) || PCB_POINT_IN_BOX((b2)->X2,(b2)->Y2,b1) \ + || pcb_lines_intersect((b1)->X1,(b1)->Y1, (b1)->X2,(b1)->Y1, (b2)->X1,(b2)->Y1, (b2)->X1,(b2)->Y2) \ + || pcb_lines_intersect((b2)->X1,(b2)->Y1, (b2)->X2,(b2)->Y1, (b1)->X1,(b1)->Y1, (b1)->X1,(b1)->Y2)) + +#define PCB_TEXT_TOUCHES_BOX(t,b) \ + (PCB_BOX_TOUCHES_BOX(&((t)->BoundingBox), (b))) + +#define PCB_POLYGON_TOUCHES_BOX(p,b) \ + (pcb_poly_is_rect_in_p((b)->X2, (b)->Y2, (b)->X1, (b)->Y1, (p))) + +#define PCB_SUBC_TOUCHES_BOX(s,b) \ + (PCB_BOX_TOUCHES_BOX(&((s)->BoundingBox), (b))) + +#define PCB_ELEMENT_TOUCHES_BOX(e,b) \ + (PCB_BOX_TOUCHES_BOX(&((e)->BoundingBox), (b))) + +#define PCB_ARC_TOUCHES_BOX(a,b) \ + (pcb_is_arc_in_rectangle((b)->X2, (b)->Y2, (b)->X1, (b)->Y1, (a))) + + +/* == the combination of *_IN_* and *_TOUCHES_*: use IN for positive boxes == */ +#define PCB_IS_BOX_NEGATIVE(b) (((b)->X2 < (b)->X1) || ((b)->Y2 < (b)->Y1)) + +#define PCB_BOX_NEAR_BOX(b1,b) \ + (PCB_IS_BOX_NEGATIVE(b) ? PCB_BOX_TOUCHES_BOX(b1,b) : PCB_BOX_IN_BOX(b1,b)) + +#define PCB_VIA_OR_PIN_NEAR_BOX(v,b) \ + (PCB_IS_BOX_NEGATIVE(b) ? PCB_VIA_OR_PIN_TOUCHES_BOX(v,b) : PCB_VIA_OR_PIN_IN_BOX(v,b)) + +#define PCB_LINE_NEAR_BOX(l,b) \ + (PCB_IS_BOX_NEGATIVE(b) ? PCB_LINE_TOUCHES_BOX(l,b) : PCB_LINE_IN_BOX(l,b)) + +#define PCB_PAD_NEAR_BOX(p,b) \ + (PCB_IS_BOX_NEGATIVE(b) ? PCB_PAD_TOUCHES_BOX(p,b) : PCB_PAD_IN_BOX(p,b)) + +#define PCB_TEXT_NEAR_BOX(t,b) \ + (PCB_IS_BOX_NEGATIVE(b) ? PCB_TEXT_TOUCHES_BOX(t,b) : PCB_TEXT_IN_BOX(t,b)) + +#define PCB_POLYGON_NEAR_BOX(p,b) \ + (PCB_IS_BOX_NEGATIVE(b) ? PCB_POLYGON_TOUCHES_BOX(p,b) : PCB_POLYGON_IN_BOX(p,b)) + +#define PCB_SUBC_NEAR_BOX(s,b) \ + (PCB_IS_BOX_NEGATIVE(b) ? PCB_SUBC_TOUCHES_BOX(s,b) : PCB_SUBC_IN_BOX(s,b)) + +#define PCB_ELEMENT_NEAR_BOX(e,b) \ + (PCB_IS_BOX_NEGATIVE(b) ? PCB_ELEMENT_TOUCHES_BOX(e,b) : PCB_ELEMENT_IN_BOX(e,b)) + +#define PCB_ARC_NEAR_BOX(a,b) \ + (PCB_IS_BOX_NEGATIVE(b) ? PCB_ARC_TOUCHES_BOX(a,b) : PCB_ARC_IN_BOX(a,b)) + +pcb_bool pcb_is_point_on_line(pcb_coord_t X, pcb_coord_t Y, pcb_coord_t Radius, pcb_line_t *Line); +pcb_bool pcb_is_point_on_thinline( pcb_coord_t X, pcb_coord_t Y, pcb_coord_t X1, pcb_coord_t Y1, pcb_coord_t X2,pcb_coord_t Y2 ); +pcb_bool pcb_is_point_on_line_end(pcb_coord_t X, pcb_coord_t Y, pcb_rat_t *Line); +pcb_bool pcb_is_point_on_arc(pcb_coord_t X, pcb_coord_t Y, pcb_coord_t Radius, pcb_arc_t *Arc); +pcb_bool pcb_is_line_in_rectangle(pcb_coord_t X1, pcb_coord_t Y1, pcb_coord_t X2, pcb_coord_t Y2, pcb_line_t *Line); +pcb_bool pcb_is_line_in_quadrangle(pcb_point_t p[4], pcb_line_t *Line); +pcb_bool pcb_is_arc_in_rectangle(pcb_coord_t X1, pcb_coord_t Y1, pcb_coord_t X2, pcb_coord_t Y2, pcb_arc_t *Arc); +pcb_bool pcb_is_point_in_line(pcb_coord_t X, pcb_coord_t Y, pcb_coord_t Radius, pcb_any_line_t *Pad); +pcb_bool pcb_is_point_in_box(pcb_coord_t X, pcb_coord_t Y, pcb_box_t *box, pcb_coord_t Radius); + +/* Return the distance^2 between a line-center and a point */ +double pcb_point_line_dist2(pcb_coord_t X, pcb_coord_t Y, pcb_line_t *Line); + +/* Return the first line object that has its centerline crossing the point; + if ang is not NULL, only return lines that are pointing in the right + angle (also accept 180 degree rotation) + if no_subc_part is true, ignore lines that are part of subcircuits; + if no_term is true, ignore lines that are terminals */ +pcb_line_t *pcb_line_center_cross_point(pcb_layer_t *layer, pcb_coord_t x, pcb_coord_t y, pcb_angle_t *ang, pcb_bool no_subc_part, pcb_bool no_term); + +int pcb_search_screen(pcb_coord_t X, pcb_coord_t Y, int Type, void **Result1, void **Result2, void **Result3); +int pcb_search_grid_slop(pcb_coord_t X, pcb_coord_t Y, int Type, void **Result1, void **Result2, void **Result3); +int pcb_search_obj_by_location(unsigned long Type, void **Result1, void **Result2, void **Result3, pcb_coord_t X, pcb_coord_t Y, pcb_coord_t Radius); +int pcb_search_obj_by_id(pcb_data_t *Base, void **Result1, void **Result2, void **Result3, int ID, int type); +int pcb_search_obj_by_id_(pcb_data_t *Base, void **Result1, void **Result2, void **Result3, int ID, int type); /* no-hace version */ + +/* Same as pcb_search_obj_by_id, but search in buffers too */ +int pcb_search_obj_by_id_buf2(pcb_data_t *Base, void **Result1, void **Result2, void **Result3, int ID, int type); + +#endif + Index: tags/2.1.2/src/search_r.h =================================================================== --- tags/2.1.2/src/search_r.h (nonexistent) +++ tags/2.1.2/src/search_r.h (revision 24813) @@ -0,0 +1,37 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2018 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +/* Search functions with rtree callbacks; implementation: in search.c */ + +#ifndef PCB_SEARCH_R_H +#define PCB_SEARCH_R_H + +#include "rtree.h" + +/* Search data for given object types within a box using the usual rtree conventions for the callback */ +pcb_r_dir_t pcb_search_data_by_loc(pcb_data_t *data, pcb_objtype_t type, const pcb_box_t *query_box, pcb_r_dir_t (*cb_)(void *closure, pcb_any_obj_t *obj, void *box), void *closure); + +#endif Index: tags/2.1.2/src/select.c =================================================================== --- tags/2.1.2/src/select.c (nonexistent) +++ tags/2.1.2/src/select.c (revision 24813) @@ -0,0 +1,487 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + + +/* select routines + */ + +#include "config.h" +#include "conf_core.h" + +#include "board.h" +#include "data.h" +#include "data_it.h" +#include "draw.h" +#include "error.h" +#include "polygon.h" +#include "search.h" +#include "select.h" +#include "undo.h" +#include "find.h" +#include "compat_misc.h" + +#include "obj_arc_draw.h" +#include "obj_line_draw.h" +#include "obj_poly_draw.h" +#include "obj_text_draw.h" +#include "obj_rat_draw.h" +#include "obj_pstk_draw.h" + +#include + +/* --------------------------------------------------------------------------- + * toggles the selection of any kind of object + * the different types are defined by search.h + */ +pcb_bool pcb_select_object(pcb_board_t *pcb) +{ + void *ptr1, *ptr2, *ptr3; + pcb_layer_t *layer; + int type; + + pcb_bool changed = pcb_true; + + type = pcb_search_screen(pcb_crosshair.X, pcb_crosshair.Y, PCB_SELECT_TYPES | PCB_LOOSE_SUBC | PCB_OBJ_FLOATER, &ptr1, &ptr2, &ptr3); + if (type == PCB_OBJ_VOID || PCB_FLAG_TEST(PCB_FLAG_LOCK, (pcb_any_obj_t *) ptr2)) + return pcb_false; + switch (type) { + + case PCB_OBJ_PSTK: + pcb_undo_add_obj_to_flag(ptr1); + PCB_FLAG_TOGGLE(PCB_FLAG_SELECTED, (pcb_pstk_t *) ptr1); + pcb_pstk_invalidate_draw((pcb_pstk_t *) ptr1); + break; + + case PCB_OBJ_LINE: + { + pcb_line_t *line = (pcb_line_t *) ptr2; + + layer = (pcb_layer_t *) ptr1; + pcb_undo_add_obj_to_flag(ptr2); + PCB_FLAG_TOGGLE(PCB_FLAG_SELECTED, line); + pcb_line_invalidate_draw(layer, line); + break; + } + + case PCB_OBJ_RAT: + { + pcb_rat_t *rat = (pcb_rat_t *) ptr2; + + pcb_undo_add_obj_to_flag(ptr1); + PCB_FLAG_TOGGLE(PCB_FLAG_SELECTED, rat); + pcb_rat_invalidate_draw(rat); + break; + } + + case PCB_OBJ_ARC: + { + pcb_arc_t *arc = (pcb_arc_t *) ptr2; + + layer = (pcb_layer_t *) ptr1; + pcb_undo_add_obj_to_flag(ptr2); + PCB_FLAG_TOGGLE(PCB_FLAG_SELECTED, arc); + pcb_arc_invalidate_draw(layer, arc); + break; + } + + case PCB_OBJ_TEXT: + { + pcb_text_t *text = (pcb_text_t *) ptr2; + + layer = (pcb_layer_t *) ptr1; + pcb_undo_add_obj_to_flag(ptr2); + PCB_FLAG_TOGGLE(PCB_FLAG_SELECTED, text); + pcb_text_invalidate_draw(layer, text); + break; + } + + case PCB_OBJ_POLY: + { + pcb_poly_t *poly = (pcb_poly_t *) ptr2; + + layer = (pcb_layer_t *) ptr1; + pcb_undo_add_obj_to_flag(ptr2); + PCB_FLAG_TOGGLE(PCB_FLAG_SELECTED, poly); + pcb_poly_invalidate_draw(layer, poly); + /* changing memory order no longer effects draw order */ + break; + } + + case PCB_OBJ_SUBC: + pcb_subc_select(pcb, (pcb_subc_t *) ptr1, PCB_CHGFLG_TOGGLE, 1); + break; + } + pcb_draw(); + pcb_undo_inc_serial(); + return changed; +} + +static void fix_box_dir(pcb_box_t *Box, int force_pos) +{ +#define swap(a,b) \ +do { \ + pcb_coord_t tmp; \ + tmp = a; \ + a = b; \ + b = tmp; \ +} while(0) + + /* If board view is flipped, box coords need to be flipped too to reflect + the on-screen direction of draw */ + if (conf_core.editor.view.flip_x) + swap(Box->X1, Box->X2); + if (conf_core.editor.view.flip_y) + swap(Box->Y1, Box->Y2); + + if ((force_pos) || (conf_core.editor.selection.disable_negative)) { + if (Box->X1 > Box->X2) + swap(Box->X1, Box->X2); + if (Box->Y1 > Box->Y2) + swap(Box->Y1, Box->Y2); + } + else { + if (conf_core.editor.selection.symmetric_negative) { + if (Box->Y1 > Box->Y2) + swap(Box->Y1, Box->Y2); + } + /* Make sure our negative box is canonical: always from bottom-right to top-left + This limits all possible box coordinate orders to two, one for positive and + one for negative. */ + if (PCB_IS_BOX_NEGATIVE(Box)) { + if (Box->X1 < Box->X2) + swap(Box->X1, Box->X2); + if (Box->Y1 < Box->Y2) + swap(Box->Y1, Box->Y2); + } + } +#undef swap + +} + +/* ---------------------------------------------------------------------- + * selects/unselects or lists visible objects within the passed box + * If len is NULL: + * Flag determines if the block is to be selected or unselected + * returns non-NULL if the state of any object has changed + * if len is non-NULL: + * returns a list of object IDs matched the search and loads len with the + * length of the list. Returns NULL on no match. + */ +TODO("cleanup: should be rewritten with generic ops and rtree") +static long int *ListBlock_(pcb_board_t *pcb, pcb_box_t *Box, pcb_bool Flag, int *len) +{ + int changed = 0; + int used = 0, alloced = 0; + long int *list = NULL; + + fix_box_dir(Box, 0); +/*pcb_printf("box: %mm %mm - %mm %mm [ %d ] %d %d\n", Box->X1, Box->Y1, Box->X2, Box->Y2, PCB_IS_BOX_NEGATIVE(Box), conf_core.editor.view.flip_x, conf_core.editor.view.flip_y);*/ + +/* append an object to the return list OR set the flag if there's no list */ +#define append(undo_type, p1, obj) \ +do { \ + if (len == NULL) { \ + pcb_undo_add_obj_to_flag(obj); \ + PCB_FLAG_ASSIGN(PCB_FLAG_SELECTED, Flag, obj); \ + } \ + else { \ + if (used >= alloced) { \ + alloced += 64; \ + list = realloc(list, sizeof(*list) * alloced); \ + } \ + list[used] = obj->ID; \ + used++; \ + } \ + changed = 1; \ +} while(0) + + if (PCB_IS_BOX_NEGATIVE(Box) && ((Box->X1 == Box->X2) || (Box->Y2 == Box->Y1))) { + if (len != NULL) + *len = 0; + return NULL; + } + + if (pcb->RatOn || !Flag) + PCB_RAT_LOOP(pcb->Data); + { + if (PCB_LINE_NEAR_BOX((pcb_line_t *) line, Box) && !PCB_FLAG_TEST(PCB_FLAG_LOCK, line) && PCB_FLAG_TEST(PCB_FLAG_SELECTED, line) != Flag) { + append(PCB_OBJ_RAT, line, line); + if (pcb->RatOn) + pcb_rat_invalidate_draw(line); + } + } + PCB_END_LOOP; + + /* check layers */ + LAYER_LOOP(pcb->Data, pcb_max_layer); + { + unsigned int lflg = pcb_layer_flags(pcb, n); + + if ((lflg & PCB_LYT_SILK) && (PCB_LAYERFLG_ON_VISIBLE_SIDE(lflg))) { + if (!(pcb_silk_on(pcb) || !Flag)) + continue; + } + else if ((lflg & PCB_LYT_SILK) && !(PCB_LAYERFLG_ON_VISIBLE_SIDE(lflg))) { + if (!(pcb->InvisibleObjectsOn || !Flag)) + continue; + } + else if (!(layer->meta.real.vis || !Flag)) + continue; + + PCB_LINE_LOOP(layer); + { + if (PCB_LINE_NEAR_BOX(line, Box) + && !PCB_FLAG_TEST(PCB_FLAG_LOCK, line) + && PCB_FLAG_TEST(PCB_FLAG_SELECTED, line) != Flag) { + append(PCB_OBJ_LINE, layer, line); + if (layer->meta.real.vis) + pcb_line_invalidate_draw(layer, line); + } + } + PCB_END_LOOP; + PCB_ARC_LOOP(layer); + { + if (PCB_ARC_NEAR_BOX(arc, Box) + && !PCB_FLAG_TEST(PCB_FLAG_LOCK, arc) + && PCB_FLAG_TEST(PCB_FLAG_SELECTED, arc) != Flag) { + append(PCB_OBJ_ARC, layer, arc); + if (layer->meta.real.vis) + pcb_arc_invalidate_draw(layer, arc); + } + } + PCB_END_LOOP; + PCB_TEXT_LOOP(layer); + { + if (!Flag || pcb_text_is_visible(PCB, layer, text)) { + if (PCB_TEXT_NEAR_BOX(text, Box) + && !PCB_FLAG_TEST(PCB_FLAG_LOCK, text) + && PCB_FLAG_TEST(PCB_FLAG_SELECTED, text) != Flag) { + append(PCB_OBJ_TEXT, layer, text); + if (pcb_text_is_visible(PCB, layer, text)) + pcb_text_invalidate_draw(layer, text); + } + } + } + PCB_END_LOOP; + PCB_POLY_LOOP(layer); + { + if (PCB_POLYGON_NEAR_BOX(polygon, Box) + && !PCB_FLAG_TEST(PCB_FLAG_LOCK, polygon) + && PCB_FLAG_TEST(PCB_FLAG_SELECTED, polygon) != Flag) { + append(PCB_OBJ_POLY, layer, polygon); + if (layer->meta.real.vis) + pcb_poly_invalidate_draw(layer, polygon); + } + } + PCB_END_LOOP; + } + PCB_END_LOOP; + + if (PCB->SubcOn) { + PCB_SUBC_LOOP(pcb->Data); + { + if (PCB_SUBC_NEAR_BOX(subc, Box) + && !PCB_FLAG_TEST(PCB_FLAG_LOCK, subc) + && PCB_FLAG_TEST(PCB_FLAG_SELECTED, subc) != Flag) { + + if (len == NULL) { + pcb_subc_select(PCB, subc, Flag, 1); + } + else { + if (used >= alloced) { + alloced += 64; + list = realloc(list, sizeof(*list) * alloced); + } + list[used] = subc->ID; + used++; + } + changed = 1; + DrawSubc(subc); + } + } + PCB_END_LOOP; + } + + /* end with vias */ + if (pcb->pstk_on || !Flag) { + PCB_PADSTACK_LOOP(pcb->Data); + { + if (pcb_pstk_near_box(padstack, Box, NULL) + && !PCB_FLAG_TEST(PCB_FLAG_LOCK, padstack) + && PCB_FLAG_TEST(PCB_FLAG_SELECTED, padstack) != Flag) { + append(PCB_OBJ_PSTK, padstack, padstack); + if (pcb->pstk_on) + pcb_pstk_invalidate_draw(padstack); + } + } + PCB_END_LOOP; + } + + if (changed) { + pcb_draw(); + pcb_undo_inc_serial(); + } + + if (len == NULL) { + static long int non_zero; + return (changed ? &non_zero : NULL); + } + else { + *len = used; + return list; + } +} + +#undef append + +static int pcb_obj_near_box(pcb_any_obj_t *obj, pcb_box_t *box) +{ + switch(obj->type) { + case PCB_OBJ_RAT: + case PCB_OBJ_LINE: return PCB_LINE_NEAR_BOX((pcb_line_t *)obj, box); + case PCB_OBJ_TEXT: return PCB_TEXT_NEAR_BOX((pcb_text_t *)obj, box); + case PCB_OBJ_POLY: return PCB_POLYGON_NEAR_BOX((pcb_poly_t *)obj, box); + case PCB_OBJ_ARC: return PCB_ARC_NEAR_BOX((pcb_arc_t *)obj, box); + case PCB_OBJ_PSTK: return pcb_pstk_near_box((pcb_pstk_t *)obj, box, NULL); + case PCB_OBJ_SUBC: return PCB_SUBC_NEAR_BOX((pcb_subc_t *)obj, box); + default: return 0; + } +} + +typedef struct { + pcb_box_t box; + pcb_bool flag; + pcb_bool invert; +} select_ctx_t; + +static pcb_r_dir_t pcb_select_block_cb(const pcb_box_t *box, void *cl) +{ + select_ctx_t *ctx = cl; + pcb_any_obj_t *obj = (pcb_any_obj_t *)box; + + if (!ctx->invert && (PCB_FLAG_TEST(PCB_FLAG_SELECTED, obj) == ctx->flag)) /* cheap check on the flag: don't do anything if the flag is already right */ + return PCB_R_DIR_NOT_FOUND; + + /* do not let locked object selected, but allow deselection */ + if ((PCB_FLAG_TEST(PCB_FLAG_LOCK, obj) == pcb_true) && (ctx->flag)) + return PCB_R_DIR_NOT_FOUND; + + if (!pcb_obj_near_box(obj, &ctx->box)) /* detailed box matching */ + return PCB_R_DIR_NOT_FOUND; + + pcb_undo_add_obj_to_flag((void *)obj); + pcb_draw_obj(obj); + if (ctx->invert) + PCB_FLAG_TOGGLE(PCB_FLAG_SELECTED, obj); + else + PCB_FLAG_ASSIGN(PCB_FLAG_SELECTED, ctx->flag, obj); + return PCB_R_DIR_FOUND_CONTINUE; +} + +/* ---------------------------------------------------------------------- + * selects/unselects all visible objects within the passed box + * Flag determines if the block is to be selected or unselected + * returns pcb_true if the state of any object has changed + */ +pcb_bool pcb_select_block(pcb_board_t *pcb, pcb_box_t *Box, pcb_bool flag, pcb_bool vis_only, pcb_bool invert) +{ + select_ctx_t ctx; + + fix_box_dir(Box, 0); + + ctx.box = *Box; + ctx.flag = flag; + ctx.invert = invert; + + fix_box_dir(Box, 1); + + return pcb_data_r_search(pcb->Data, PCB_OBJ_ANY, Box, NULL, pcb_select_block_cb, &ctx, NULL, vis_only) == PCB_R_DIR_FOUND_CONTINUE; +} + +/* ---------------------------------------------------------------------- + * List all visible objects within the passed box + */ +long int *pcb_list_block(pcb_board_t *pcb, pcb_box_t *Box, int *len) +{ + return ListBlock_(pcb, Box, 1, len); +} + +/* ---------------------------------------------------------------------- + * selects/unselects all objects which were found during a connection scan + * Flag determines if they are to be selected or unselected + * returns pcb_true if the state of any object has changed + * + * text objects and subcircuits cannot be selected by this routine + */ +static pcb_bool pcb_select_connection_(pcb_data_t *data, pcb_bool Flag) +{ + pcb_bool changed = pcb_false; + pcb_any_obj_t *o; + pcb_data_it_t it; + + for(o = pcb_data_first(&it, data, PCB_OBJ_CLASS_REAL); o != NULL; o = pcb_data_next(&it)) { + if (PCB_FLAG_TEST(PCB_FLAG_FOUND, o)) { + pcb_undo_add_obj_to_flag(o); + PCB_FLAG_ASSIGN(PCB_FLAG_SELECTED, Flag, o); + pcb_draw_obj(o); + changed = pcb_true; + } + if ((o->type == PCB_OBJ_SUBC) && (pcb_select_connection_(((pcb_subc_t *)o)->data, Flag))) + changed = pcb_true; + } + + return changed; +} + +pcb_bool pcb_select_connection(pcb_board_t *pcb, pcb_bool Flag) +{ + return pcb_select_connection_(pcb->Data, Flag); +} + +/* --------------------------------------------------------------------------- + * selects objects as defined by Type by name; + * it's a case insensitive match + * returns pcb_true if any object has been selected + */ +#define REGEXEC(arg) \ + (method == PCB_SM_REGEX ? regexec_match_all(regex, (arg)) : strlst_match(pat, (arg))) + +static int regexec_match_all(re_sei_t *preg, const char *string) +{ + return !!re_sei_exec(preg, string); +} + +/* case insensitive match of each item in the array pat against name + returns 1 if any of them matched */ +static int strlst_match(const char **pat, const char *name) +{ + for (; *pat != NULL; pat++) + if (pcb_strcasecmp(*pat, name) == 0) + return 1; + return 0; +} Index: tags/2.1.2/src/select.h =================================================================== --- tags/2.1.2/src/select.h (nonexistent) +++ tags/2.1.2/src/select.h (revision 24813) @@ -0,0 +1,45 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +#ifndef PCB_SELECT_H +#define PCB_SELECT_H + +#include "config.h" +#include "operation.h" + +#define PCB_SELECT_TYPES \ + (PCB_OBJ_LINE | PCB_OBJ_TEXT | PCB_OBJ_POLY | PCB_OBJ_SUBC | \ + PCB_OBJ_PSTK | PCB_OBJ_RAT | PCB_OBJ_ARC) + +pcb_bool pcb_select_object(pcb_board_t *pcb); +pcb_bool pcb_select_block(pcb_board_t *pcb, pcb_box_t *Box, pcb_bool flag, pcb_bool vis_only, pcb_bool invert); +long int *pcb_list_block(pcb_board_t *pcb, pcb_box_t *Box, int *len); + +pcb_bool pcb_select_connection(pcb_board_t *pcb, pcb_bool); + +#endif Index: tags/2.1.2/src/select_act.c =================================================================== --- tags/2.1.2/src/select_act.c (nonexistent) +++ tags/2.1.2/src/select_act.c (revision 24813) @@ -0,0 +1,226 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * Copyright (C) 1997, 1998, 1999, 2000, 2001 Harry Eaton + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + * + * Old contact info: + * Harry Eaton, 6697 Buttonhole Ct, Columbia, MD 21044, USA + * haceaton@aplcomm.jhuapl.edu + * + */ +#include "config.h" +#include "conf_core.h" + +#include "board.h" +#include "data.h" +#include "error.h" +#include "undo.h" +#include "funchash_core.h" + +#include "tool.h" +#include "select.h" +#include "draw.h" +#include "remove.h" +#include "move.h" +#include "grid.h" +#include "hid_attrib.h" +#include "compat_misc.h" +#include "actions.h" + + +static const char pcb_acts_Select[] = + "Select(Object|ToggleObject)\n" + "Select(All|Block|Connection|Invert)\n" + "Select(Convert)"; +static const char pcb_acth_Select[] = "Toggles or sets the selection."; +/* DOC: select.html */ +static fgw_error_t pcb_act_Select(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + int op; + PCB_ACT_CONVARG(1, FGW_KEYWORD, Select, op = fgw_keyword(&argv[1])); + + switch(op) { + + /* select a single object */ + case F_ToggleObject: + case F_Object: + if (pcb_select_object(PCB)) + pcb_board_set_changed_flag(pcb_true); + break; + + /* all objects in block */ + case F_Block: + { + pcb_box_t box; + + box.X1 = MIN(pcb_crosshair.AttachedBox.Point1.X, pcb_crosshair.AttachedBox.Point2.X); + box.Y1 = MIN(pcb_crosshair.AttachedBox.Point1.Y, pcb_crosshair.AttachedBox.Point2.Y); + box.X2 = MAX(pcb_crosshair.AttachedBox.Point1.X, pcb_crosshair.AttachedBox.Point2.X); + box.Y2 = MAX(pcb_crosshair.AttachedBox.Point1.Y, pcb_crosshair.AttachedBox.Point2.Y); + pcb_notify_crosshair_change(pcb_false); + pcb_tool_notify_block(); + if (pcb_crosshair.AttachedBox.State == PCB_CH_STATE_THIRD && pcb_select_block(PCB, &box, pcb_true, pcb_true, pcb_false)) { + pcb_board_set_changed_flag(pcb_true); + pcb_crosshair.AttachedBox.State = PCB_CH_STATE_FIRST; + } + pcb_notify_crosshair_change(pcb_true); + break; + } + + /* select all visible(?) objects */ + case F_All: + { + pcb_box_t box; + + box.X1 = -PCB_MAX_COORD; + box.Y1 = -PCB_MAX_COORD; + box.X2 = PCB_MAX_COORD; + box.Y2 = PCB_MAX_COORD; + if (pcb_select_block(PCB, &box, pcb_true, pcb_true, pcb_false)) + pcb_board_set_changed_flag(pcb_true); + break; + } + + case F_Invert: + { + pcb_box_t box; + + box.X1 = -PCB_MAX_COORD; + box.Y1 = -PCB_MAX_COORD; + box.X2 = PCB_MAX_COORD; + box.Y2 = PCB_MAX_COORD; + if (pcb_select_block(PCB, &box, pcb_true, pcb_true, pcb_true)) + pcb_board_set_changed_flag(pcb_true); + break; + } + + /* all found connections */ + case F_Connection: + if (pcb_select_connection(PCB, pcb_true)) { + pcb_draw(); + pcb_undo_inc_serial(); + pcb_board_set_changed_flag(pcb_true); + } + break; + + case F_Convert: + case F_ConvertSubc: + { + pcb_coord_t x, y; + pcb_tool_note.Buffer = conf_core.editor.buffer_number; + pcb_buffer_set_number(PCB_MAX_BUFFER - 1); + pcb_buffer_clear(PCB, PCB_PASTEBUFFER); + pcb_hid_get_coords("Select the Subcircuit's Origin (mark) Location", &x, &y, 0); + x = pcb_grid_fit(x, PCB->Grid, PCB->GridOffsetX); + y = pcb_grid_fit(y, PCB->Grid, PCB->GridOffsetY); + pcb_buffer_add_selected(PCB, PCB_PASTEBUFFER, x, y, pcb_true); + pcb_undo_save_serial(); + pcb_remove_selected(pcb_false); + pcb_subc_convert_from_buffer(PCB_PASTEBUFFER); + pcb_undo_restore_serial(); + pcb_buffer_copy_to_layout(PCB, x, y); + pcb_buffer_set_number(pcb_tool_note.Buffer); + } + break; + + default: + PCB_ACT_FAIL(Select); + break; + } + + PCB_ACT_IRES(0); + return 0; +} + +/* --------------------------------------------------------------------------- */ + +static const char pcb_acts_Unselect[] = "Unselect(All|Block|Connection)\n"; +static const char pcb_acth_Unselect[] = "Unselects the object at the pointer location or the specified objects."; +/* DOC: unselect.html */ +static fgw_error_t pcb_act_Unselect(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + int op; + PCB_ACT_CONVARG(1, FGW_KEYWORD, Unselect, op = fgw_keyword(&argv[1])); + + switch(op) { + + /* all objects in block */ + case F_Block: + { + pcb_box_t box; + + box.X1 = MIN(pcb_crosshair.AttachedBox.Point1.X, pcb_crosshair.AttachedBox.Point2.X); + box.Y1 = MIN(pcb_crosshair.AttachedBox.Point1.Y, pcb_crosshair.AttachedBox.Point2.Y); + box.X2 = MAX(pcb_crosshair.AttachedBox.Point1.X, pcb_crosshair.AttachedBox.Point2.X); + box.Y2 = MAX(pcb_crosshair.AttachedBox.Point1.Y, pcb_crosshair.AttachedBox.Point2.Y); + pcb_notify_crosshair_change(pcb_false); + pcb_tool_notify_block(); + if (pcb_crosshair.AttachedBox.State == PCB_CH_STATE_THIRD && pcb_select_block(PCB, &box, pcb_false, pcb_true, pcb_false)) { + pcb_board_set_changed_flag(pcb_true); + pcb_crosshair.AttachedBox.State = PCB_CH_STATE_FIRST; + } + pcb_notify_crosshair_change(pcb_true); + break; + } + + /* unselect all visible objects */ + case F_All: + { + pcb_box_t box; + + box.X1 = -PCB_MAX_COORD; + box.Y1 = -PCB_MAX_COORD; + box.X2 = PCB_MAX_COORD; + box.Y2 = PCB_MAX_COORD; + if (pcb_select_block(PCB, &box, pcb_false, pcb_false, pcb_false)) + pcb_board_set_changed_flag(pcb_true); + break; + } + + /* all found connections */ + case F_Connection: + if (pcb_select_connection(PCB, pcb_false)) { + pcb_draw(); + pcb_undo_inc_serial(); + pcb_board_set_changed_flag(pcb_true); + } + break; + + default: + PCB_ACT_FAIL(Unselect); + break; + + } + PCB_ACT_IRES(0); + return 0; +} + +pcb_action_t select_action_list[] = { + {"Select", pcb_act_Select, pcb_acth_Select, pcb_acts_Select}, + {"Unselect", pcb_act_Unselect, pcb_acth_Unselect, pcb_acts_Unselect} +}; + +PCB_REGISTER_ACTIONS(select_action_list, NULL) Index: tags/2.1.2/src/stub_draw.c =================================================================== --- tags/2.1.2/src/stub_draw.c (nonexistent) +++ tags/2.1.2/src/stub_draw.c (revision 24813) @@ -0,0 +1,96 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ +#include "config.h" +#include "stub_draw.h" +#include "obj_text.h" +#include "obj_text_draw.h" + +/****** common code ******/ +void dummy_draw_text(pcb_draw_info_t *info, pcb_hid_gc_t gc, const char *str) +{ + pcb_text_t t; + + pcb_gui->set_color(gc, pcb_color_red); + + memset(&t, 0, sizeof(t)); + t.TextString = (char *)str; + t.fid = 0; /* use the default font */ + t.Scale = 150; + t.Flags = pcb_no_flags(); + pcb_text_draw_(info, &t, 0, 0, PCB_TXT_TINY_ACCURATE); +} + +static pcb_bool dummy_mouse(pcb_hid_mouse_ev_t kind, pcb_coord_t x, pcb_coord_t y) +{ + return 0; +} + + +/****** fab ******/ + +int dummy_DrawFab_overhang(void) +{ + return 0; +} + +void dummy_DrawFab(pcb_draw_info_t *info, pcb_hid_gc_t gc, const pcb_hid_expose_ctx_t *e) +{ + dummy_draw_text(info, gc, "Can't render the fab layer: the draw_fab plugin is not compiled and/or not loaded"); +} + +int (*pcb_stub_draw_fab_overhang)(void) = dummy_DrawFab_overhang; +void (*pcb_stub_draw_fab)(pcb_draw_info_t *info, pcb_hid_gc_t gc, const pcb_hid_expose_ctx_t *e) = dummy_DrawFab; + + +/****** csect - cross section of the board ******/ + + +static void dummy_draw_csect(pcb_hid_gc_t gc, const pcb_hid_expose_ctx_t *e) +{ + dummy_draw_text(NULL, gc, "Can't render the fab layer: the draw_csect plugin is not compiled and/or not loaded"); +} + + +void (*pcb_stub_draw_csect)(pcb_hid_gc_t gc, const pcb_hid_expose_ctx_t *e) = dummy_draw_csect; +pcb_bool (*pcb_stub_draw_csect_mouse_ev)(pcb_hid_mouse_ev_t kind, pcb_coord_t x, pcb_coord_t y) = dummy_mouse; + + +/****** font selector GUI ******/ +static void dummy_draw_fontsel(pcb_hid_gc_t gc, const pcb_hid_expose_ctx_t *e, pcb_text_t *txt) +{ + dummy_draw_text(NULL, gc, "Can't render the font selector: the draw_fontsel plugin is not compiled and/or not loaded"); +} + +static pcb_bool dummy_mouse_fontsel(pcb_hid_mouse_ev_t kind, pcb_coord_t x, pcb_coord_t y, pcb_text_t *txt) +{ + return 0; +} + +void (*pcb_stub_draw_fontsel)(pcb_hid_gc_t gc, const pcb_hid_expose_ctx_t *e, pcb_text_t *txt) = dummy_draw_fontsel; +pcb_bool (*pcb_stub_draw_fontsel_mouse_ev)(pcb_hid_mouse_ev_t kind, pcb_coord_t x, pcb_coord_t y, pcb_text_t *txt) = dummy_mouse_fontsel; + Index: tags/2.1.2/src/stub_draw.h =================================================================== --- tags/2.1.2/src/stub_draw.h (nonexistent) +++ tags/2.1.2/src/stub_draw.h (revision 24813) @@ -0,0 +1,51 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +/* drawing the fab layer is a plugin now */ + +#ifndef PCB_STUB_DRAW_FAB_H +#define PCB_STUB_DRAW_FAB_H + +#include "hid.h" +#include "pcb_bool.h" +#include "global_typedefs.h" +#include "draw.h" + +/* fab */ +extern int (*pcb_stub_draw_fab_overhang)(void); +extern void (*pcb_stub_draw_fab)(pcb_draw_info_t *info, pcb_hid_gc_t gc, const pcb_hid_expose_ctx_t *e); + +/* csect */ +extern void (*pcb_stub_draw_csect)(pcb_hid_gc_t gc, const pcb_hid_expose_ctx_t *e); +extern pcb_bool (*pcb_stub_draw_csect_mouse_ev)(pcb_hid_mouse_ev_t kind, pcb_coord_t x, pcb_coord_t y); + +/* fontsel */ +extern void (*pcb_stub_draw_fontsel)(pcb_hid_gc_t gc, const pcb_hid_expose_ctx_t *e, pcb_text_t *txt); +extern pcb_bool (*pcb_stub_draw_fontsel_mouse_ev)(pcb_hid_mouse_ev_t kind, pcb_coord_t x, pcb_coord_t y, pcb_text_t *txt); + +#endif Index: tags/2.1.2/src/stub_stroke.c =================================================================== --- tags/2.1.2/src/stub_stroke.c (nonexistent) +++ tags/2.1.2/src/stub_stroke.c (revision 24813) @@ -0,0 +1,81 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2016 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ +#include "error.h" +#include "config.h" +#include "pcb_bool.h" + +pcb_bool pcb_mid_stroke = pcb_false; + +/* Warn if gesture is wider or higher than this amount of coords (2mm) */ +#define MIN_CDIFF 2*1000000 + +/* Warn only once, for large gestures */ +static pcb_bool far = pcb_false, warned = pcb_false; +static pcb_coord_t x1 = -1, y1; + +static void stub_stroke_record_dummy(pcb_coord_t ev_x, pcb_coord_t ev_y) +{ + if (x1 < 0) { + x1 = ev_x; + y1 = ev_y; + } + else { + pcb_coord_t d; + + d = x1 - ev_x; + if (d < 0) d = -d; + if (d > MIN_CDIFF) far = pcb_true; + + d = y1 - ev_y; + if (d < 0) d = -d; + if (d > MIN_CDIFF) far = pcb_true; + } +} + +static void stub_stroke_start_dummy(void) +{ + pcb_mid_stroke = pcb_true; +} + +static int stub_stroke_finish_dummy(void) +{ + if (far) { + if (!warned) { + pcb_message(PCB_MSG_WARNING, "No gesture recognition, can not use libstroke: not compiled as a buildin and not loaded as a plugin\n"); + warned = pcb_true; + } + } + pcb_mid_stroke = pcb_false; + x1 = -1; + + return -1; +} + +void (*pcb_stub_stroke_record)(pcb_coord_t ev_x, pcb_coord_t ev_y) = stub_stroke_record_dummy; +void (*pcb_stub_stroke_start)(void) = stub_stroke_start_dummy; + +/* Returns 0 on success (gesture recognized) */ +int (*pcb_stub_stroke_finish)(void) = stub_stroke_finish_dummy; Index: tags/2.1.2/src/stub_stroke.h =================================================================== --- tags/2.1.2/src/stub_stroke.h (nonexistent) +++ tags/2.1.2/src/stub_stroke.h (revision 24813) @@ -0,0 +1,30 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2016 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +extern pcb_bool pcb_mid_stroke; +extern void (*pcb_stub_stroke_record)(pcb_coord_t ev_x, pcb_coord_t ev_y); +extern void (*pcb_stub_stroke_start)(void); +extern int (*pcb_stub_stroke_finish)(void); Index: tags/2.1.2/src/thermal.c =================================================================== --- tags/2.1.2/src/thermal.c (nonexistent) +++ tags/2.1.2/src/thermal.c (revision 24813) @@ -0,0 +1,819 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2017 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "config.h" + +#include "thermal.h" + +#include "compat_misc.h" +#include "data.h" +#include "obj_pstk.h" +#include "obj_pstk_inlines.h" +#include "obj_pinvia_therm.h" +#include "polygon.h" + +pcb_cardinal_t pcb_themal_style_new2old(unsigned char t) +{ + switch(t) { + case 0: return 0; + case PCB_THERMAL_ON | PCB_THERMAL_SHARP | PCB_THERMAL_DIAGONAL: return 1; + case PCB_THERMAL_ON | PCB_THERMAL_SHARP: return 2; + case PCB_THERMAL_ON | PCB_THERMAL_SOLID: return 3; + case PCB_THERMAL_ON | PCB_THERMAL_ROUND | PCB_THERMAL_DIAGONAL: return 4; + case PCB_THERMAL_ON | PCB_THERMAL_ROUND: return 5; + } + return 0; +} + +unsigned char pcb_themal_style_old2new(pcb_cardinal_t t) +{ + switch(t) { + case 0: return 0; + case 1: return PCB_THERMAL_ON | PCB_THERMAL_SHARP | PCB_THERMAL_DIAGONAL; + case 2: return PCB_THERMAL_ON | PCB_THERMAL_SHARP; + case 3: return PCB_THERMAL_ON | PCB_THERMAL_SOLID; + case 4: return PCB_THERMAL_ON | PCB_THERMAL_ROUND | PCB_THERMAL_DIAGONAL; + case 5: return PCB_THERMAL_ON | PCB_THERMAL_ROUND; + } + return 0; +} + +pcb_thermal_t pcb_thermal_str2bits(const char *str) +{ + /* shape */ + if (strcmp(str, "noshape") == 0) return PCB_THERMAL_NOSHAPE; + if (strcmp(str, "round") == 0) return PCB_THERMAL_ROUND; + if (strcmp(str, "sharp") == 0) return PCB_THERMAL_SHARP; + if (strcmp(str, "solid") == 0) return PCB_THERMAL_SOLID; + + /* orientation */ + if (strcmp(str, "diag") == 0) return PCB_THERMAL_DIAGONAL; + + if (strcmp(str, "on") == 0) return PCB_THERMAL_ON; + + return 0; +} + +const char *pcb_thermal_bits2str(pcb_thermal_t *bit) +{ + if ((*bit) & PCB_THERMAL_ON) { + *bit &= ~PCB_THERMAL_ON; + return "on"; + } + if ((*bit) & PCB_THERMAL_DIAGONAL) { + *bit &= ~PCB_THERMAL_DIAGONAL; + return "diag"; + } + if ((*bit) & 3) { + int shape = (*bit) & 3; + *bit &= ~3; + switch(shape) { + case PCB_THERMAL_NOSHAPE: return "noshape"; + case PCB_THERMAL_ROUND: return "round"; + case PCB_THERMAL_SHARP: return "sharp"; + case PCB_THERMAL_SOLID: return "solid"; + default: return NULL; + } + } + return NULL; +} + + +/* generate a round-cap line polygon */ +static pcb_polyarea_t *pa_line_at(double x1, double y1, double x2, double y2, pcb_coord_t clr, pcb_bool square) +{ + pcb_line_t ltmp; + + if (square) + ltmp.Flags = pcb_flag_make(PCB_FLAG_SQUARE); + else + ltmp.Flags = pcb_no_flags(); + ltmp.Point1.X = pcb_round(x1); ltmp.Point1.Y = pcb_round(y1); + ltmp.Point2.X = pcb_round(x2); ltmp.Point2.Y = pcb_round(y2); + return pcb_poly_from_line(<mp, clr); +} + +/* generate a round-cap arc polygon knowing the center and endpoints */ +static pcb_polyarea_t *pa_arc_at(double cx, double cy, double r, double e1x, double e1y, double e2x, double e2y, pcb_coord_t clr, double max_span_angle) +{ + double sa, ea, da; + pcb_arc_t atmp; + + sa = atan2(-(e1y - cy), e1x - cx) * PCB_RAD_TO_DEG + 180.0; + ea = atan2(-(e2y - cy), e2x - cx) * PCB_RAD_TO_DEG + 180.0; + +/* pcb_trace("sa=%f ea=%f diff=%f\n", sa, ea, ea-sa);*/ + + atmp.Flags = pcb_no_flags(); + atmp.X = pcb_round(cx); + atmp.Y = pcb_round(cy); + + da = ea-sa; + if ((da < max_span_angle) && (da > -max_span_angle)) { + atmp.StartAngle = sa; + atmp.Delta = ea-sa; + } + else { + if (ea < sa) { + double tmp = ea; + ea = sa; + sa = tmp; + } + atmp.StartAngle = ea; + atmp.Delta = 360-ea+sa; + } + atmp.Width = atmp.Height = r; + return pcb_poly_from_arc(&atmp, clr); +} + +pcb_polyarea_t *pcb_thermal_area_line(pcb_board_t *pcb, pcb_line_t *line, pcb_layer_id_t lid) +{ + pcb_polyarea_t *pa, *pb, *pc; + double dx, dy, len, vx, vy, nx, ny, clr, clrth, x1, y1, x2, y2, mx, my; + pcb_coord_t th; + + if ((line->Point1.X == line->Point2.X) && (line->Point1.Y == line->Point2.Y)) { + /* conrer case zero-long line is a circle: do the same as for vias */ +TODO("thermal TODO") + abort(); + } + + x1 = line->Point1.X; + y1 = line->Point1.Y; + x2 = line->Point2.X; + y2 = line->Point2.Y; + mx = (x1+x2)/2.0; + my = (y1+y2)/2.0; + dx = x1 - x2; + dy = y1 - y2; + + len = sqrt(dx*dx + dy*dy); + vx = dx / len; + vy = dy / len; + nx = -vy; + ny = vx; + + clr = line->Clearance/2; + clrth = (line->Clearance/2 + line->Thickness) / 2; + + assert(line->thermal & PCB_THERMAL_ON); /* caller should have checked this */ + switch(line->thermal & 3) { + case PCB_THERMAL_NOSHAPE: + case PCB_THERMAL_SOLID: return 0; + + case PCB_THERMAL_ROUND: + if (PCB_FLAG_TEST(PCB_FLAG_SQUARE, line)) { + + if (line->thermal & PCB_THERMAL_DIAGONAL) { + /* side clear lines */ + pa = pa_line_at( + x1 - clrth * nx + clrth * vx - clr*vx, y1 - clrth * ny + clrth * vy - clr*vy, + x2 - clrth * nx - clrth * vx + clr*vx, y2 - clrth * ny - clrth * vy + clr*vy, + clr, pcb_false); + pb = pa_line_at( + x1 + clrth * nx + clrth * vx - clr*vx, y1 + clrth * ny + clrth * vy - clr*vy, + x2 + clrth * nx - clrth * vx + clr*vx, y2 + clrth * ny - clrth * vy + clr*vy, + clr, pcb_false); + pcb_polyarea_boolean_free(pa, pb, &pc, PCB_PBO_UNITE); + + /* cross clear lines */ + pa = pc; pc = NULL; + pb = pa_line_at( + x1 - clrth * nx + clrth * vx + clr*nx, y1 - clrth * ny + clrth * vy + clr*ny, + x1 + clrth * nx + clrth * vx - clr*nx, y1 + clrth * ny + clrth * vy - clr*ny, + clr, pcb_false); + pcb_polyarea_boolean_free(pa, pb, &pc, PCB_PBO_UNITE); + + pa = pc; pc = NULL; + pb = pa_line_at( + x2 - clrth * nx - clrth * vx + clr*nx, y2 - clrth * ny - clrth * vy + clr*ny, + x2 + clrth * nx - clrth * vx - clr*nx, y2 + clrth * ny - clrth * vy - clr*ny, + clr, pcb_false); + pcb_polyarea_boolean_free(pa, pb, &pc, PCB_PBO_UNITE); + } + else { + /* side clear lines */ + pa = pa_line_at( + x1 - clrth * nx + clrth * vx, y1 - clrth * ny + clrth * vy, + mx - clrth * nx + clr * vx, my - clrth * ny + clr * vy, + clr, pcb_false); + pb = pa_line_at( + x1 + clrth * nx + clrth * vx, y1 + clrth * ny + clrth * vy, + mx + clrth * nx + clr * vx, my + clrth * ny + clr * vy, + clr, pcb_false); + pcb_polyarea_boolean_free(pa, pb, &pc, PCB_PBO_UNITE); + + pa = pc; pc = NULL; + pb = pa_line_at( + x2 - clrth * nx - clrth * vx, y2 - clrth * ny - clrth * vy, + mx - clrth * nx - clr * vx, my - clrth * ny - clr * vy, + clr, pcb_false); + pcb_polyarea_boolean_free(pa, pb, &pc, PCB_PBO_UNITE); + + pa = pc; pc = NULL; + pb = pa_line_at( + x2 + clrth * nx - clrth * vx, y2 + clrth * ny - clrth * vy, + mx + clrth * nx - clr * vx, my + clrth * ny - clr * vy, + clr, pcb_false); + pcb_polyarea_boolean_free(pa, pb, &pc, PCB_PBO_UNITE); + + /* cross clear lines */ + pa = pc; pc = NULL; + pb = pa_line_at( + x1 - clrth * nx + clrth * vx, y1 - clrth * ny + clrth * vy, + x1 - clr * nx + clrth * vx, y1 - clr * ny + clrth * vy, + clr, pcb_false); + pcb_polyarea_boolean_free(pa, pb, &pc, PCB_PBO_UNITE); + + pa = pc; pc = NULL; + pb = pa_line_at( + x1 + clrth * nx + clrth * vx, y1 + clrth * ny + clrth * vy, + x1 + clr * nx + clrth * vx, y1 + clr * ny + clrth * vy, + clr, pcb_false); + pcb_polyarea_boolean_free(pa, pb, &pc, PCB_PBO_UNITE); + + pa = pc; pc = NULL; + pb = pa_line_at( + x2 - clrth * nx - clrth * vx, y2 - clrth * ny - clrth * vy, + x2 - clr * nx - clrth * vx, y2 - clr * ny - clrth * vy, + clr, pcb_false); + pcb_polyarea_boolean_free(pa, pb, &pc, PCB_PBO_UNITE); + + pa = pc; pc = NULL; + pb = pa_line_at( + x2 + clrth * nx - clrth * vx, y2 + clrth * ny - clrth * vy, + x2 + clr * nx - clrth * vx, y2 + clr * ny - clrth * vy, + clr, pcb_false); + pcb_polyarea_boolean_free(pa, pb, &pc, PCB_PBO_UNITE); + } + } + else { + /* round cap line: arcs! */ + if (line->thermal & PCB_THERMAL_DIAGONAL) { + /* side clear lines */ + pa = pa_line_at( + x1 - clrth * nx - clr * vx * 0.75, y1 - clrth * ny - clr * vy * 0.75, + x2 - clrth * nx + clr * vx * 0.75, y2 - clrth * ny + clr * vy * 0.75, + clr, pcb_false); + pb = pa_line_at( + x1 + clrth * nx - clr * vx * 0.75, y1 + clrth * ny - clr * vy * 0.75, + x2 + clrth * nx + clr * vx * 0.75, y2 + clrth * ny + clr * vy * 0.75, + clr, pcb_false); + pcb_polyarea_boolean_free(pa, pb, &pc, PCB_PBO_UNITE); + + /* x1;y1 cap arc */ + pa = pc; pc = NULL; + pb = pa_arc_at(x1, y1, clrth, + x1 - clrth * nx + clr * vx * 2.0, y1 - clrth * ny + clr * vy * 2.0, + x1 + clrth * nx + clr * vx * 2.0, y1 + clrth * ny + clr * vy * 2.0, + clr, 180.0); + pcb_polyarea_boolean_free(pa, pb, &pc, PCB_PBO_UNITE); + + /* x2;y2 cap arc */ + pa = pc; pc = NULL; + pb = pa_arc_at(x2, y2, clrth, + x2 - clrth * nx - clr * vx * 2.0, y2 - clrth * ny - clr * vy * 2.0, + x2 + clrth * nx - clr * vx * 2.0, y2 + clrth * ny - clr * vy * 2.0, + clr, 180.0); + pcb_polyarea_boolean_free(pa, pb, &pc, PCB_PBO_UNITE); + } + else { /* non-diagonal */ + /* split side lines */ + pa = pa_line_at( + x1 - clrth * nx - clr * vx * 0.00, y1 - clrth * ny - clr * vy * 0.00, + mx - clrth * nx + clr * vx * 1.00, my - clrth * ny + clr * vy * 1.00, + clr, pcb_false); + pb = pa_line_at( + x1 + clrth * nx - clr * vx * 0.00, y1 + clrth * ny - clr * vy * 0.00, + mx + clrth * nx + clr * vx * 1.00, my + clrth * ny + clr * vy * 1.00, + clr, pcb_false); + pcb_polyarea_boolean_free(pa, pb, &pc, PCB_PBO_UNITE); + + pa = pc; pc = NULL; + pb = pa_line_at( + mx - clrth * nx - clr * vx * 1.00, my - clrth * ny - clr * vy * 1.00, + x2 - clrth * nx + clr * vx * 0.00, y2 - clrth * ny + clr * vy * 0.00, + clr, pcb_false); + pcb_polyarea_boolean_free(pa, pb, &pc, PCB_PBO_UNITE); + + pa = pc; pc = NULL; + pb = pa_line_at( + mx + clrth * nx - clr * vx * 1.00, my + clrth * ny - clr * vy * 1.00, + x2 + clrth * nx + clr * vx * 0.00, y2 + clrth * ny + clr * vy * 0.00, + clr, pcb_false); + pcb_polyarea_boolean_free(pa, pb, &pc, PCB_PBO_UNITE); + + /* split round cap, x1;y1 */ + pa = pc; pc = NULL; + pb = pa_arc_at(x1, y1, clrth, + x1 - clrth * nx, y1 - clrth * ny, + x1 + clrth * vx - clr * nx, y1 + clrth * vy - clr * ny, + clr, 180.0); + pcb_polyarea_boolean_free(pa, pb, &pc, PCB_PBO_UNITE); + + pa = pc; pc = NULL; + pb = pa_arc_at(x1, y1, clrth, + x1 + clrth * nx, y1 + clrth * ny, + x1 + clrth * vx + clr * nx, y1 + clrth * vy + clr * ny, + clr, 180.0); + pcb_polyarea_boolean_free(pa, pb, &pc, PCB_PBO_UNITE); + + /* split round cap, x2;y2 */ + pa = pc; pc = NULL; + pb = pa_arc_at(x2, y2, clrth, + x2 - clrth * nx, y2 - clrth * ny, + x2 - clrth * vx - clr * nx, y2 - clrth * vy - clr * ny, + clr, 180.0); + pcb_polyarea_boolean_free(pa, pb, &pc, PCB_PBO_UNITE); + + pa = pc; pc = NULL; + pb = pa_arc_at(x2, y2, clrth, + x2 + clrth * nx, y2 + clrth * ny, + x2 - clrth * vx + clr * nx, y2 - clrth * vy + clr * ny, + clr, 180.0); + pcb_polyarea_boolean_free(pa, pb, &pc, PCB_PBO_UNITE); + } + } + return pc; + case PCB_THERMAL_SHARP: + pa = pcb_poly_from_line(line, line->Thickness + line->Clearance); + th = line->Thickness/2 < clr ? line->Thickness/2 : clr; + clrth *= 2; + if (line->thermal & PCB_THERMAL_DIAGONAL) { + /* x1;y1 V-shape */ + pb = pa_line_at(x1, y1, x1-nx*clrth+vx*clrth, y1-ny*clrth+vy*clrth, th, pcb_false); + pcb_polyarea_boolean_free(pa, pb, &pc, PCB_PBO_SUB); + + pa = pc; pc = NULL; + pb = pa_line_at(x1, y1, x1+nx*clrth+vx*clrth, y1+ny*clrth+vy*clrth, th, pcb_false); + pcb_polyarea_boolean_free(pa, pb, &pc, PCB_PBO_SUB); + + /* x2;y2 V-shape */ + pa = pc; pc = NULL; + pb = pa_line_at(x2, y2, x2-nx*clrth-vx*clrth, y2-ny*clrth-vy*clrth, th, pcb_false); + pcb_polyarea_boolean_free(pa, pb, &pc, PCB_PBO_SUB); + + pa = pc; pc = NULL; + pb = pa_line_at(x2, y2, x2+nx*clrth-vx*clrth, y2+ny*clrth-vy*clrth, th, pcb_false); + pcb_polyarea_boolean_free(pa, pb, &pc, PCB_PBO_SUB); + } + else { + /* perpendicular */ + pb = pa_line_at(mx-nx*clrth, my-ny*clrth, mx+nx*clrth, my+ny*clrth, th, pcb_true); + pcb_polyarea_boolean_free(pa, pb, &pc, PCB_PBO_SUB); + + /* straight */ + pa = pc; pc = NULL; + pb = pa_line_at(x1+vx*clrth, y1+vy*clrth, x2-vx*clrth, y2-vy*clrth, th, pcb_true); + pcb_polyarea_boolean_free(pa, pb, &pc, PCB_PBO_SUB); + } + return pc; + } + return NULL; +} + +/* combine a base poly-area into the result area (pres) */ +static void polytherm_base(pcb_polyarea_t **pres, const pcb_polyarea_t *src) +{ + pcb_polyarea_t *p; + + if (*pres != NULL) { + pcb_polyarea_boolean(src, *pres, &p, PCB_PBO_UNITE); + pcb_polyarea_free(pres); + *pres = p; + } + else + pcb_polyarea_copy0(pres, src); +} + +#define CONG_MAX 256 + +static int cong_map(char *cong, pcb_poly_it_t *it, pcb_coord_t clr) +{ + int n, go, first = 1; + pcb_coord_t cx, cy; + double cl2 = (double)clr * (double)clr * 1.5; + double px, py, x, y; + + for(n = 0, go = pcb_poly_vect_first(it, &cx, &cy); go; go = pcb_poly_vect_next(it, &cx, &cy), n++) { + x = cx; y = cy; + if (first) { +/*pcb_trace("prev %mm;%mm\n", cx, cy);*/ + pcb_poly_vect_peek_prev(it, &cx, &cy); +/*pcb_trace(" %mm;%mm\n", cx, cy);*/ + px = cx; py = cy; + first = 0; + } + if (n >= CONG_MAX-1) { + n++; + break; + } + cong[n] = (pcb_distance2(x, y, px, py) < cl2); + px = x; py = y; + } + return n; +} + +/* combine a round clearance line set into pres; "it" is an iterator + already initialized to a polyarea contour */ +static void polytherm_round(pcb_polyarea_t **pres, pcb_poly_it_t *it, pcb_coord_t clr, pcb_bool is_diag) +{ + pcb_polyarea_t *ptmp, *p; + double fact = 0.5, fact_ortho=0.75; + pcb_coord_t cx, cy; + double px, py, x, y, dx, dy, vx, vy, nx, ny, mx, my, len; + int n, go, first = 1; + char cong[CONG_MAX]; + + clr -= 2; + + cong_map(cong, it, clr); + + /* iterate over the vectors of the contour */ + for(n = 0, go = pcb_poly_vect_first(it, &cx, &cy); go; go = pcb_poly_vect_next(it, &cx, &cy), n++) { + x = cx; y = cy; + if (first) { + pcb_poly_vect_peek_prev(it, &cx, &cy); + px = cx; py = cy; + + first = 0; + } + +/*pcb_trace("[%d] %d %mm;%mm\n", n, cong[n], (pcb_coord_t)x, (pcb_coord_t)y);*/ + + + dx = x - px; + dy = y - py; + mx = (x+px)/2.0; + my = (y+py)/2.0; + + len = sqrt(dx*dx + dy*dy); + vx = dx / len; + vy = dy / len; + + nx = -vy; + ny = vx; + + /* skip points too dense */ + if ((n >= CONG_MAX) || (cong[n])) { + if (!is_diag) { + /* have to draw a short clearance for the small segments */ + ptmp = pa_line_at(x - nx * clr/2, y - ny * clr/2, px - nx * clr/2, py - ny * clr/2, clr+4, pcb_false); + + pcb_polyarea_boolean(ptmp, *pres, &p, PCB_PBO_UNITE); + pcb_polyarea_free(pres); + pcb_polyarea_free(&ptmp); + *pres = p; + } + px = x; py = y; + continue; + } + + /* cheat: clr-2+4 to guarantee some overlap with the poly cutout */ + if (is_diag) { + /* one line per edge, slightly shorter than the edge */ + ptmp = pa_line_at(x - vx * clr * fact - nx * clr/2, y - vy * clr * fact - ny * clr/2, px + vx * clr *fact - nx * clr/2, py + vy * clr * fact - ny * clr/2, clr+4, pcb_false); + + pcb_polyarea_boolean(ptmp, *pres, &p, PCB_PBO_UNITE); + pcb_polyarea_free(pres); + pcb_polyarea_free(&ptmp); + *pres = p; + } + else { + /* two half lines per edge */ + ptmp = pa_line_at(x - nx * clr/2 , y - ny * clr/2, mx + vx * clr * fact_ortho - nx * clr/2, my + vy * clr * fact_ortho - ny * clr/2, clr+4, pcb_false); + pcb_polyarea_boolean(ptmp, *pres, &p, PCB_PBO_UNITE); + pcb_polyarea_free(pres); + pcb_polyarea_free(&ptmp); + *pres = p; + + ptmp = pa_line_at(px - nx * clr/2, py - ny * clr/2, mx - vx * clr * fact_ortho - nx * clr/2, my - vy * clr * fact_ortho - ny * clr/2, clr+4, pcb_false); + pcb_polyarea_boolean(ptmp, *pres, &p, PCB_PBO_UNITE); + pcb_polyarea_free(pres); + pcb_polyarea_free(&ptmp); + *pres = p; + + /* optical tuning: make sure the clearance is large enough around corners + even if lines didn't meet - just throw in a big circle */ + ptmp = pcb_poly_from_circle(x, y, clr); + pcb_polyarea_boolean(ptmp, *pres, &p, PCB_PBO_UNITE); + pcb_polyarea_free(pres); + pcb_polyarea_free(&ptmp); + *pres = p; + } + px = x; + py = y; + } +} + +static void polytherm_sharp(pcb_polyarea_t **pres, pcb_poly_it_t *it, pcb_coord_t clr, pcb_bool is_diag) +{ + pcb_polyarea_t *ptmp, *p; + pcb_coord_t cx, cy, x2c, y2c; + double px, py, x, y, dx, dy, vx, vy, nx, ny, mx, my, len, x2, y2, vx2, vy2, len2, dx2, dy2; + int n, go, first = 1; + char cong[CONG_MAX], cong2[CONG_MAX]; + + if (is_diag) { + int start = -1, v = cong_map(cong2, it, clr); + memset(cong, 1, sizeof(cong)); + + /* in case of sharp-diag, draw the bridge in the middle of each congestion; + run *2 and do module v so congestions spanning over the end are no special */ + for(n = 0; n < v*2; n++) { + if (cong2[n % v] == 0) { + if (start >= 0) + cong[((start+n)/2) % v] = 0; + start = n; + } + } + } + else { + /* normal congestion logic: use long edges only */ + cong_map(cong, it, clr); + } + + /* iterate over the vectors of the contour */ + for(n = 0, go = pcb_poly_vect_first(it, &cx, &cy); go; go = pcb_poly_vect_next(it, &cx, &cy), n++) { + x = cx; y = cy; + if (first) { + pcb_poly_vect_peek_prev(it, &cx, &cy); + px = cx; py = cy; + first = 0; + } + +/*pcb_trace("[%d] %d %mm;%mm\n", n, cong[n], (pcb_coord_t)x, (pcb_coord_t)y);*/ + + /* skip points too dense */ + if ((n >= CONG_MAX) || (cong[n])) { + px = x; py = y; + continue; + } + + + dx = x - px; + dy = y - py; + + len = sqrt(dx*dx + dy*dy); + vx = dx / len; + vy = dy / len; + + if (is_diag) { + pcb_poly_vect_peek_next(it, &x2c, &y2c); + x2 = x2c; y2 = y2c; + dx2 = x - x2; + dy2 = y - y2; + len2 = sqrt(dx2*dx2 + dy2*dy2); + vx2 = dx2 / len2; + vy2 = dy2 / len2; + + nx = -(vy2 - vy); + ny = vx2 - vx; + + /* line from each corner at the average angle of the two edges from the corner */ + ptmp = pa_line_at(x-nx*clr*0.2, y-ny*clr*0.2, x + nx*clr*4, y + ny*clr*4, clr/2, pcb_false); + pcb_polyarea_boolean(*pres, ptmp, &p, PCB_PBO_SUB); + pcb_polyarea_free(pres); + pcb_polyarea_free(&ptmp); + *pres = p; + } + else { + nx = -vy; + ny = vx; + mx = (x+px)/2.0; + my = (y+py)/2.0; + + /* perpendicular line from the middle of each edge */ + ptmp = pa_line_at(mx, my, mx - nx*clr, my - ny*clr, clr/2, pcb_true); + pcb_polyarea_boolean(*pres, ptmp, &p, PCB_PBO_SUB); + pcb_polyarea_free(pres); + pcb_polyarea_free(&ptmp); + *pres = p; + } + px = x; + py = y; + } +} + +/* generate round thermal around a polyarea specified by the iterator */ +static void pcb_thermal_area_pa_round(pcb_polyarea_t **pres, pcb_poly_it_t *it, pcb_coord_t clr, pcb_bool_t is_diag) +{ + pcb_pline_t *pl; + +/* cut out the poly so terminals will be displayed proerply */ + polytherm_base(pres, it->pa); + + /* generate the clear-lines */ + pl = pcb_poly_contour(it); + if (pl != NULL) + polytherm_round(pres, it, clr, is_diag); +} + +/* generate sharp thermal around a polyarea specified by the iterator */ +static void pcb_thermal_area_pa_sharp(pcb_polyarea_t **pres, pcb_poly_it_t *it, pcb_coord_t clr, pcb_bool_t is_diag) +{ + pcb_pline_t *pl; + + /* add the usual clearance glory around the polygon */ + pcb_poly_pa_clearance_construct(pres, it, clr); + + pl = pcb_poly_contour(it); + if (pl != NULL) + polytherm_sharp(pres, it, clr, is_diag); + + /* trim internal stubs */ + polytherm_base(pres, it->pa); +} + +pcb_polyarea_t *pcb_thermal_area_poly(pcb_board_t *pcb, pcb_poly_t *poly, pcb_layer_id_t lid) +{ + pcb_polyarea_t *pa, *pres = NULL; + pcb_coord_t clr = poly->Clearance/2; + pcb_poly_it_t it; + + assert(poly->thermal & PCB_THERMAL_ON); /* caller should have checked this */ + switch(poly->thermal & 3) { + case PCB_THERMAL_NOSHAPE: + case PCB_THERMAL_SOLID: return NULL; + + case PCB_THERMAL_ROUND: + for(pa = pcb_poly_island_first(poly, &it); pa != NULL; pa = pcb_poly_island_next(&it)) + pcb_thermal_area_pa_round(&pres, &it, clr, (poly->thermal & PCB_THERMAL_DIAGONAL)); + return pres; + + case PCB_THERMAL_SHARP: + for(pa = pcb_poly_island_first(poly, &it); pa != NULL; pa = pcb_poly_island_next(&it)) + pcb_thermal_area_pa_sharp(&pres, &it, clr, (poly->thermal & PCB_THERMAL_DIAGONAL)); + return pres; + } + + return NULL; +} + +/* Generate a clearance around a padstack shape, with no thermal */ +static pcb_polyarea_t *pcb_thermal_area_pstk_nothermal(pcb_board_t *pcb, pcb_pstk_t *ps, pcb_layer_id_t lid, pcb_pstk_shape_t *shp, pcb_coord_t clearance) +{ + pcb_poly_it_t it; + pcb_polyarea_t *pres = NULL; + pcb_pstk_shape_t tmpshp; + + retry:; + switch(shp->shape) { + case PCB_PSSH_HSHADOW: + shp = pcb_pstk_hshadow_shape(ps, shp, &tmpshp); + if (shp == NULL) + return NULL; + goto retry; + case PCB_PSSH_CIRC: + return pcb_poly_from_circle(ps->x + shp->data.circ.x, ps->y + shp->data.circ.y, shp->data.circ.dia/2 + clearance); + case PCB_PSSH_LINE: + return pa_line_at(ps->x + shp->data.line.x1, ps->y + shp->data.line.y1, ps->x + shp->data.line.x2, ps->y + shp->data.line.y2, shp->data.line.thickness + clearance*2, shp->data.line.square); + case PCB_PSSH_POLY: + if (shp->data.poly.pa == NULL) + pcb_pstk_shape_update_pa(&shp->data.poly); + if (shp->data.poly.pa == NULL) + return NULL; + pcb_poly_iterate_polyarea(shp->data.poly.pa, &it); + pcb_poly_pa_clearance_construct(&pres, &it, clearance); + pcb_polyarea_move(pres, ps->x, ps->y); + return pres; + } + return NULL; +} + +pcb_polyarea_t *pcb_thermal_area_pstk(pcb_board_t *pcb, pcb_pstk_t *ps, pcb_layer_id_t lid) +{ + unsigned char thr; + pcb_pstk_shape_t *shp, tmpshp; + pcb_polyarea_t *pres = NULL; + pcb_layer_t *layer = pcb_get_layer(pcb->Data, lid); + pcb_coord_t clearance = ps->Clearance; + + /* if we have no clearance, there's no reason to do anything; + ps->Clearance == 0 doesn't mean no clearance because of the per shape clearances */ + if (!PCB_FLAG_TEST(PCB_FLAG_CLEARLINE, ps)) + return NULL; + + /* retrieve shape; assume 0 (no shape) for layers not named */ + if (lid < ps->thermals.used) + thr = ps->thermals.shape[lid]; + else + thr = 0; + + shp = pcb_pstk_shape_at_(pcb, ps, layer, 1); + if (shp == NULL) + return NULL; + + if (clearance <= 0) + clearance = shp->clearance/2; + + if (clearance <= 0) + return NULL; + + if (!(thr & PCB_THERMAL_ON)) + return pcb_thermal_area_pstk_nothermal(pcb, ps, lid, shp, clearance); + + switch(thr & 3) { + case PCB_THERMAL_NOSHAPE: + tmpshp.shape = PCB_PSSH_HSHADOW; + tmpshp.clearance = shp->clearance; + return pcb_thermal_area_pstk_nothermal(pcb, ps, lid, &tmpshp, clearance); + case PCB_THERMAL_SOLID: return NULL; + case PCB_THERMAL_ROUND: + case PCB_THERMAL_SHARP: + retry:; + switch(shp->shape) { + case PCB_PSSH_HSHADOW: + shp = pcb_pstk_hshadow_shape(ps, shp, &tmpshp); + if (shp == NULL) + return NULL; + goto retry; + case PCB_PSSH_CIRC: + return ThermPoly_(pcb, ps->x + shp->data.circ.x, ps->y + shp->data.circ.y, shp->data.circ.dia, clearance*2, pcb_themal_style_new2old(thr)); + case PCB_PSSH_LINE: + { + pcb_line_t ltmp; + if (shp->data.line.square) + ltmp.Flags = pcb_flag_make(PCB_FLAG_SQUARE); + else + ltmp.Flags = pcb_no_flags(); + ltmp.Point1.X = ps->x + shp->data.line.x1; + ltmp.Point1.Y = ps->y + shp->data.line.y1; + ltmp.Point2.X = ps->x + shp->data.line.x2; + ltmp.Point2.Y = ps->y + shp->data.line.y2; + ltmp.Thickness = shp->data.line.thickness; + ltmp.Clearance = clearance*2; + ltmp.thermal = thr; + pres = pcb_thermal_area_line(pcb, <mp, lid); + } + return pres; + + case PCB_PSSH_POLY: + { + pcb_poly_it_t it; + if (shp->data.poly.pa == NULL) + pcb_pstk_shape_update_pa(&shp->data.poly); + if (shp->data.poly.pa == NULL) + return NULL; + pcb_poly_iterate_polyarea(shp->data.poly.pa, &it); + if (thr & PCB_THERMAL_ROUND) + pcb_thermal_area_pa_round(&pres, &it, clearance, (thr & PCB_THERMAL_DIAGONAL)); + else + pcb_thermal_area_pa_sharp(&pres, &it, clearance, (thr & PCB_THERMAL_DIAGONAL)); + + if (pres != NULL) + pcb_polyarea_move(pres, ps->x, ps->y); + } + return pres; + } + + } + + return NULL; +} + +pcb_polyarea_t *pcb_thermal_area(pcb_board_t *pcb, pcb_any_obj_t *obj, pcb_layer_id_t lid) +{ + switch(obj->type) { + + case PCB_OBJ_LINE: + return pcb_thermal_area_line(pcb, (pcb_line_t *)obj, lid); + + case PCB_OBJ_POLY: + return pcb_thermal_area_poly(pcb, (pcb_poly_t *)obj, lid); + + case PCB_OBJ_PSTK: + return pcb_thermal_area_pstk(pcb, (pcb_pstk_t *)obj, lid); + + case PCB_OBJ_ARC: + break; + + default: break; + } + + return NULL; +} + Index: tags/2.1.2/src/thermal.h =================================================================== --- tags/2.1.2/src/thermal.h (nonexistent) +++ tags/2.1.2/src/thermal.h (revision 24813) @@ -0,0 +1,65 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2017 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#ifndef PCB_THERMAL_H +#define PCB_THERMAL_H + +#include "obj_common.h" +#include "layer.h" + +typedef enum pcb_thermal_e { + /* bit 0 and 1: shape */ + PCB_THERMAL_NOSHAPE = 0, /* padstack: no shape shall be drawn, omit copper, no connection */ + PCB_THERMAL_ROUND = 1, + PCB_THERMAL_SHARP = 2, + PCB_THERMAL_SOLID = 3, + + /* bit 2: orientation */ + PCB_THERMAL_DIAGONAL = 4, + + /* bit 3: do we have a thermal at all? */ + PCB_THERMAL_ON = 8 +} pcb_thermal_t; + +/* convert the textual version of thermal to a bitmask */ +pcb_thermal_t pcb_thermal_str2bits(const char *str); + +/* convert a bitmask to a single word of thermal description and remove the + affected bits from bits. Call this repeatedly until bits == 0 to get + all words. */ +const char *pcb_thermal_bits2str(pcb_thermal_t *bits); + + +pcb_polyarea_t *pcb_thermal_area(pcb_board_t *p, pcb_any_obj_t *obj, pcb_layer_id_t lid); +pcb_polyarea_t *pcb_thermal_area_line(pcb_board_t *pcb, pcb_line_t *line, pcb_layer_id_t lid); +pcb_polyarea_t *pcb_thermal_area_poly(pcb_board_t *pcb, pcb_poly_t *poly, pcb_layer_id_t lid); +pcb_polyarea_t *pcb_thermal_area_pstk(pcb_board_t *pcb, pcb_pstk_t *ps, pcb_layer_id_t lid); + +unsigned char pcb_themal_style_old2new(pcb_cardinal_t t); +pcb_cardinal_t pcb_themal_style_new2old(unsigned char t); + + +#endif Index: tags/2.1.2/src/tool.c =================================================================== --- tags/2.1.2/src/tool.c (nonexistent) +++ tags/2.1.2/src/tool.c (revision 24813) @@ -0,0 +1,419 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2017 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "config.h" + +#include "tool.h" + +#include "board.h" +#include "conf_core.h" +#include "crosshair.h" +#include "data.h" +#include "draw.h" +#include "error.h" +#include "event.h" +#include "find.h" +#include "grid.h" +#include "undo.h" +#include "actions.h" + + +pcb_toolid_t pcb_tool_prev_id; +pcb_toolid_t pcb_tool_next_id; +static int save_position = 0; +static int save_stack[PCB_MAX_MODESTACK_DEPTH]; + +static void default_tool_reg(void); +static void default_tool_unreg(void); +static void init_current_tool(void); +static void uninit_current_tool(void); + +void pcb_tool_init(void) +{ + vtp0_init(&pcb_tools); + default_tool_reg(); /* temporary */ +} + +void pcb_tool_uninit(void) +{ + default_tool_unreg(); /* temporary */ + while(vtp0_len(&pcb_tools) != 0) { + const pcb_tool_t *tool = pcb_tool_get(0); + pcb_message(PCB_MSG_WARNING, "Unregistered tool: %s of %s; check your plugins, fix them to unregister their tools!\n", tool->name, tool->cookie); + pcb_tool_unreg_by_cookie(tool->cookie); + } + vtp0_uninit(&pcb_tools); +} + +int pcb_tool_reg(pcb_tool_t *tool, const char *cookie) +{ + if (pcb_tool_lookup(tool->name) != PCB_TOOLID_INVALID) /* don't register two tools with the same name */ + return -1; + tool->cookie = cookie; + vtp0_append(&pcb_tools, (void *)tool); + return 0; +} + +void pcb_tool_unreg_by_cookie(const char *cookie) +{ + pcb_toolid_t n; + for(n = 0; n < vtp0_len(&pcb_tools); n++) { + const pcb_tool_t *tool = (const pcb_tool_t *)pcb_tools.array[n]; + if (tool->cookie == cookie) { + vtp0_remove(&pcb_tools, n, 1); + n--; + } + } +} + +pcb_toolid_t pcb_tool_lookup(const char *name) +{ + pcb_toolid_t n; + for(n = 0; n < vtp0_len(&pcb_tools); n++) { + const pcb_tool_t *tool = (const pcb_tool_t *)pcb_tools.array[n]; + if (strcmp(tool->name, name) == 0) + return n; + } + return PCB_TOOLID_INVALID; +} + +int pcb_tool_select_by_name(const char *name) +{ + pcb_toolid_t id = pcb_tool_lookup(name); + if (id == PCB_TOOLID_INVALID) + return -1; + return pcb_tool_select_by_id(id); +} + +int pcb_tool_select_by_id(pcb_toolid_t id) +{ + char id_s[32]; + static pcb_bool recursing = pcb_false; + + if ((id < 0) || (id > vtp0_len(&pcb_tools))) + return -1; + + /* protect the cursor while changing the mode + * perform some additional stuff depending on the new mode + * reset 'state' of attached objects + */ + if (recursing) + return -1; + recursing = pcb_true; + + if (PCB->RatDraw && !pcb_tool_get(id)->allow_when_drawing_ratlines) { + pcb_message(PCB_MSG_WARNING, "That mode is NOT allowed when drawing ratlines!\n"); + id = PCB_MODE_NO; + } + + pcb_tool_prev_id = conf_core.editor.mode; + pcb_tool_next_id = id; + uninit_current_tool(); + sprintf(id_s, "%d", id); + conf_set(CFR_DESIGN, "editor/mode", -1, id_s, POL_OVERWRITE); + init_current_tool(); + + recursing = pcb_false; + + /* force a crosshair grid update because the valid range + * may have changed + */ + pcb_notify_crosshair_change(pcb_false); + pcb_crosshair_move_relative(0, 0); + pcb_notify_crosshair_change(pcb_true); + return 0; +} + +int pcb_tool_select_highest(void) +{ + pcb_toolid_t n, bestn = PCB_TOOLID_INVALID; + unsigned int bestp = -1; + for(n = 0; n < vtp0_len(&pcb_tools) && (bestp > 0); n++) { + const pcb_tool_t *tool = (const pcb_tool_t *)pcb_tools.array[n]; + if (tool->priority < bestp) { + bestp = tool->priority; + bestn = n; + } + } + if (bestn == PCB_TOOLID_INVALID) + return -1; + return pcb_tool_select_by_id(bestn); +} + +int pcb_tool_save(void) +{ + save_stack[save_position] = conf_core.editor.mode; + if (save_position < PCB_MAX_MODESTACK_DEPTH - 1) + save_position++; + else + return -1; + return 0; +} + +int pcb_tool_restore(void) +{ + if (save_position == 0) { + pcb_message(PCB_MSG_ERROR, "hace: underflow of restore mode\n"); + return -1; + } + return pcb_tool_select_by_id(save_stack[--save_position]); +} + +/**** current tool function wrappers ****/ +#define wrap(func, err_ret, prefix, args) \ + do { \ + const pcb_tool_t *tool; \ + if ((conf_core.editor.mode < 0) || (conf_core.editor.mode >= vtp0_len(&pcb_tools))) \ + { err_ret; } \ + tool = (const pcb_tool_t *)pcb_tools.array[conf_core.editor.mode]; \ + if (tool->func == NULL) \ + { err_ret; } \ + prefix tool->func args; \ + } while(0) + +#define wrap_void(func, args) wrap(func, return, ;, args) +#define wrap_retv(func, err_ret, args) wrap(func, err_ret, return, args) + +static void init_current_tool(void) +{ + wrap_void(init, ()); +} + +static void uninit_current_tool(void) +{ + wrap_void(uninit, ()); +} + +void pcb_tool_notify_mode(void) +{ + wrap_void(notify_mode, ()); +} + +void pcb_tool_release_mode(void) +{ + wrap_void(release_mode, ()); +} + +void pcb_tool_adjust_attached_objects(void) +{ + wrap_void(adjust_attached_objects, ()); +} + +void pcb_tool_draw_attached(void) +{ + wrap_void(draw_attached, ()); +} + +pcb_bool pcb_tool_undo_act(void) +{ + wrap_retv(undo_act, return pcb_true, ()); +} + +pcb_bool pcb_tool_redo_act(void) +{ + wrap_retv(redo_act, return pcb_true, ()); +} + + +/**** tool helper functions ****/ + +pcb_tool_note_t pcb_tool_note; +pcb_bool pcb_tool_is_saved = pcb_false; + +static void get_grid_lock_coordinates(int type, void *ptr1, void *ptr2, void *ptr3, pcb_coord_t * x, pcb_coord_t * y) +{ + switch (type) { + case PCB_OBJ_LINE: + *x = ((pcb_line_t *) ptr2)->Point1.X; + *y = ((pcb_line_t *) ptr2)->Point1.Y; + break; + case PCB_OBJ_TEXT: + *x = ((pcb_text_t *) ptr2)->X; + *y = ((pcb_text_t *) ptr2)->Y; + break; + case PCB_OBJ_POLY: + *x = ((pcb_poly_t *) ptr2)->Points[0].X; + *y = ((pcb_poly_t *) ptr2)->Points[0].Y; + break; + + case PCB_OBJ_LINE_POINT: + case PCB_OBJ_POLY_POINT: + *x = ((pcb_point_t *) ptr3)->X; + *y = ((pcb_point_t *) ptr3)->Y; + break; + case PCB_OBJ_ARC: + pcb_arc_get_end((pcb_arc_t *) ptr2, 0, x, y); + break; + case PCB_OBJ_ARC_POINT: + if (ptr3 != NULL) /* need to check because: if snap off, there's no known endpoint (leave x;y as is, then) */ + pcb_arc_get_end((pcb_arc_t *) ptr2, ((*(int **)ptr3) != pcb_arc_start_ptr), x, y); + break; + } +} + +void pcb_tool_attach_for_copy(pcb_coord_t PlaceX, pcb_coord_t PlaceY, pcb_bool do_rubberband) +{ + pcb_box_t box; + pcb_coord_t mx = 0, my = 0; + + pcb_event(PCB_EVENT_RUBBER_RESET, NULL); + if (!conf_core.editor.snap_pin) { + /* dither the grab point so that the mark, center, etc + * will end up on a grid coordinate + */ + get_grid_lock_coordinates(pcb_crosshair.AttachedObject.Type, + pcb_crosshair.AttachedObject.Ptr1, + pcb_crosshair.AttachedObject.Ptr2, pcb_crosshair.AttachedObject.Ptr3, &mx, &my); + mx = pcb_grid_fit(mx, PCB->Grid, PCB->GridOffsetX) - mx; + my = pcb_grid_fit(my, PCB->Grid, PCB->GridOffsetY) - my; + } + pcb_crosshair.AttachedObject.X = PlaceX - mx; + pcb_crosshair.AttachedObject.Y = PlaceY - my; + if (!pcb_marked.status || conf_core.editor.local_ref) + pcb_crosshair_set_local_ref(PlaceX - mx, PlaceY - my, pcb_true); + pcb_crosshair.AttachedObject.State = PCB_CH_STATE_SECOND; + + /* get boundingbox of object and set cursor range */ + pcb_obj_get_bbox_naked(pcb_crosshair.AttachedObject.Type, pcb_crosshair.AttachedObject.Ptr1, pcb_crosshair.AttachedObject.Ptr2, pcb_crosshair.AttachedObject.Ptr3, &box); + pcb_crosshair_set_range(pcb_crosshair.AttachedObject.X - box.X1, + pcb_crosshair.AttachedObject.Y - box.Y1, + PCB->MaxWidth - (box.X2 - pcb_crosshair.AttachedObject.X), + PCB->MaxHeight - (box.Y2 - pcb_crosshair.AttachedObject.Y)); + + /* get all attached objects if necessary */ + if (do_rubberband && conf_core.editor.rubber_band_mode) + pcb_event(PCB_EVENT_RUBBER_LOOKUP_LINES, "ippp", pcb_crosshair.AttachedObject.Type, pcb_crosshair.AttachedObject.Ptr1, pcb_crosshair.AttachedObject.Ptr2, pcb_crosshair.AttachedObject.Ptr3); + if (do_rubberband && + (pcb_crosshair.AttachedObject.Type == PCB_OBJ_SUBC || + pcb_crosshair.AttachedObject.Type == PCB_OBJ_PSTK || + pcb_crosshair.AttachedObject.Type == PCB_OBJ_LINE || pcb_crosshair.AttachedObject.Type == PCB_OBJ_LINE_POINT)) + pcb_event(PCB_EVENT_RUBBER_LOOKUP_RATS, "ippp", pcb_crosshair.AttachedObject.Type, pcb_crosshair.AttachedObject.Ptr1, pcb_crosshair.AttachedObject.Ptr2, pcb_crosshair.AttachedObject.Ptr3); +} + +void pcb_tool_notify_block(void) +{ + pcb_notify_crosshair_change(pcb_false); + switch (pcb_crosshair.AttachedBox.State) { + case PCB_CH_STATE_FIRST: /* setup first point */ + pcb_crosshair.AttachedBox.Point1.X = pcb_crosshair.AttachedBox.Point2.X = pcb_crosshair.X; + pcb_crosshair.AttachedBox.Point1.Y = pcb_crosshair.AttachedBox.Point2.Y = pcb_crosshair.Y; + pcb_crosshair.AttachedBox.State = PCB_CH_STATE_SECOND; + break; + + case PCB_CH_STATE_SECOND: /* setup second point */ + pcb_crosshair.AttachedBox.State = PCB_CH_STATE_THIRD; + break; + } + pcb_notify_crosshair_change(pcb_true); +} + +pcb_bool pcb_tool_should_snap_offgrid_line(pcb_layer_t *layer, pcb_line_t *line) +{ + /* Allow snapping to off-grid lines when drawing new lines (on + * the same layer), and when moving a line end-point + * (but don't snap to the same line) + */ + if ((conf_core.editor.mode == PCB_MODE_LINE && CURRENT == layer) || + (conf_core.editor.mode == PCB_MODE_MOVE + && pcb_crosshair.AttachedObject.Type == PCB_OBJ_LINE_POINT + && pcb_crosshair.AttachedObject.Ptr1 == layer + && pcb_crosshair.AttachedObject.Ptr2 != line)) + return pcb_true; + else + return pcb_false; +} + +TODO("tool: move this out to a tool plugin") + +#include "tool_arc.h" +#include "tool_arrow.h" +#include "tool_buffer.h" +#include "tool_copy.h" +#include "tool_insert.h" +#include "tool_line.h" +#include "tool_lock.h" +#include "tool_move.h" +#include "tool_poly.h" +#include "tool_polyhole.h" +#include "tool_rectangle.h" +#include "tool_remove.h" +#include "tool_rotate.h" +#include "tool_text.h" +#include "tool_thermal.h" +#include "tool_via.h" + +static const char *pcb_tool_cookie = "default tools"; + +static void default_tool_reg(void) +{ + pcb_tool_reg(&pcb_tool_arc, pcb_tool_cookie); + pcb_tool_reg(&pcb_tool_arrow, pcb_tool_cookie); + pcb_tool_reg(&pcb_tool_buffer, pcb_tool_cookie); + pcb_tool_reg(&pcb_tool_copy, pcb_tool_cookie); + pcb_tool_reg(&pcb_tool_insert, pcb_tool_cookie); + pcb_tool_reg(&pcb_tool_line, pcb_tool_cookie); + pcb_tool_reg(&pcb_tool_lock, pcb_tool_cookie); + pcb_tool_reg(&pcb_tool_move, pcb_tool_cookie); + pcb_tool_reg(&pcb_tool_poly, pcb_tool_cookie); + pcb_tool_reg(&pcb_tool_polyhole, pcb_tool_cookie); + pcb_tool_reg(&pcb_tool_rectangle, pcb_tool_cookie); + pcb_tool_reg(&pcb_tool_remove, pcb_tool_cookie); + pcb_tool_reg(&pcb_tool_rotate, pcb_tool_cookie); + pcb_tool_reg(&pcb_tool_text, pcb_tool_cookie); + pcb_tool_reg(&pcb_tool_thermal, pcb_tool_cookie); + pcb_tool_reg(&pcb_tool_via, pcb_tool_cookie); +} + +static void default_tool_unreg(void) +{ + pcb_tool_unreg_by_cookie(pcb_tool_cookie); +} + + +/*** old helpers ***/ +void pcb_release_mode(void) +{ + if (pcb_crosshair.click_cmd_entry_active && (pcb_cli_mouse(0) == 0)) + return; + + pcb_tool_release_mode(); + + if (pcb_tool_is_saved) + pcb_tool_restore(); + pcb_tool_is_saved = pcb_false; + pcb_draw(); +} + +void pcb_notify_mode(void) +{ + if (pcb_crosshair.click_cmd_entry_active && (pcb_cli_mouse(1) == 0)) + return; + + if (conf_core.temp.rat_warn) + pcb_data_clear_flag(PCB->Data, PCB_FLAG_WARN, 1, 0); + pcb_tool_notify_mode(); + pcb_draw(); +} Index: tags/2.1.2/src/tool.h =================================================================== --- tags/2.1.2/src/tool.h (nonexistent) +++ tags/2.1.2/src/tool.h (revision 24813) @@ -0,0 +1,150 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2017 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#ifndef PCB_TOOL_H +#define PCB_TOOL_H + +#include + +#include "global_typedefs.h" +#include "pcb_bool.h" + +typedef enum { + PCB_MODE_NO = -1, /* no mode selected - panning - TODO: remove this in favor of the default mode (it's the same as the arrow mode) */ + PCB_MODE_VIA = 15, /* draw vias */ + PCB_MODE_LINE = 5, /* draw lines */ + PCB_MODE_RECTANGLE = 10, /* create rectangles */ + PCB_MODE_POLYGON = 8, /* draw filled polygons */ + PCB_MODE_PASTE_BUFFER = 2, /* paste objects from buffer */ + PCB_MODE_TEXT = 13, /* create text objects */ + PCB_MODE_ROTATE = 12, /* rotate objects */ + PCB_MODE_REMOVE = 11, /* remove objects */ + PCB_MODE_MOVE = 7, /* move objects */ + PCB_MODE_COPY = 3, /* copy objects */ + PCB_MODE_INSERT_POINT = 4, /* insert point into line/polygon */ + PCB_MODE_RUBBERBAND_MOVE = 16, /* move objects and attached lines */ + PCB_MODE_THERMAL = 14, /* toggle thermal layer flag */ + PCB_MODE_ARC = 0, /* draw arcs */ + PCB_MODE_ARROW = 1, /* selection with arrow mode */ + PCB_MODE_LOCK = 6, /* lock/unlock objects */ + PCB_MODE_POLYGON_HOLE = 9 /* cut holes in filled polygons */ +} pcb_mode_t; + +typedef int pcb_toolid_t; +#define PCB_TOOLID_INVALID (-1) + +typedef struct pcb_tool_s { + const char *name; /* textual name of the tool */ + const char *cookie; /* plugin cookie _pointer_ of the registrar (comparision is pointer based, not strcmp) */ + unsigned int priority; /* lower values are higher priorities; escaping mode will try to select the highest prio tool */ + + /* tool implementation */ + void (*init)(void); + void (*uninit)(void); + void (*notify_mode)(void); + void (*release_mode)(void); + void (*adjust_attached_objects)(void); + void (*draw_attached)(void); + pcb_bool (*undo_act)(void); + pcb_bool (*redo_act)(void); + + pcb_bool allow_when_drawing_ratlines; +} pcb_tool_t; + +vtp0_t pcb_tools; + +/* (un)initialize the tool subsystem */ +void pcb_tool_init(void); +void pcb_tool_uninit(void); + +/* Insert a new tool in pcb_tools; returns 0 on success */ +int pcb_tool_reg(pcb_tool_t *tool, const char *cookie); + +/* Unregister all tools that has matching cookie */ +void pcb_tool_unreg_by_cookie(const char *cookie); + +/* Return the ID of a tool by name; returns -1 on error */ +pcb_toolid_t pcb_tool_lookup(const char *name); + + +/* Select a tool by name, id or pick the highest prio tool; return 0 on success */ +int pcb_tool_select_by_name(const char *name); +int pcb_tool_select_by_id(pcb_toolid_t id); +int pcb_tool_select_highest(void); + +int pcb_tool_save(void); +int pcb_tool_restore(void); + +/**** Tool function wrappers; calling these will operate on the current tool + as defined in conf_core.editor.mode ****/ + +void pcb_tool_notify_mode(void); +void pcb_tool_release_mode(void); +void pcb_tool_adjust_attached_objects(void); +void pcb_tool_draw_attached(void); +pcb_bool pcb_tool_undo_act(void); +pcb_bool pcb_tool_redo_act(void); + + +/**** tool helper functions ****/ + +typedef struct { + pcb_coord_t X, Y; + pcb_cardinal_t Buffer; /* buffer number */ + pcb_bool Click; /* true if clicked somewhere with the arrow tool */ + pcb_bool Moving; /* true if clicked on an object of PCB_SELECT_TYPES */ + int Hit; /* type of a hit object of PCB_MOVE_TYPES; 0 if there was no PCB_MOVE_TYPES object under the crosshair */ + void *ptr1; + void *ptr2; + void *ptr3; +} pcb_tool_note_t; + +extern pcb_tool_note_t pcb_tool_note; +extern pcb_bool pcb_tool_is_saved; +extern pcb_toolid_t pcb_tool_prev_id; +extern pcb_toolid_t pcb_tool_next_id; + +void pcb_tool_attach_for_copy(pcb_coord_t PlaceX, pcb_coord_t PlaceY, pcb_bool do_rubberband); +void pcb_tool_notify_block(void); /* create first or second corner of a marked block (when clicked) */ +pcb_bool pcb_tool_should_snap_offgrid_line(pcb_layer_t *layer, pcb_line_t *line); + + +/**** old heleprs ****/ + +/* does what's appropriate for the current mode setting (when clicked). This + normally means creation of an object at the current crosshair location. + new created objects are added to the create undo list of course */ +void pcb_notify_mode(void); + +void pcb_release_mode(void); + + +/**** Low level, for internal use ****/ + +/* Get the tool pointer of a tool by id */ +#define pcb_tool_get(id) ((const pcb_tool_t *)*vtp0_get(&pcb_tools, id, 0)) + +#endif Index: tags/2.1.2/src/tool_arc.c =================================================================== --- tags/2.1.2/src/tool_arc.c (nonexistent) +++ tags/2.1.2/src/tool_arc.c (revision 24813) @@ -0,0 +1,202 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 1994,1995,1996 Thomas Nau + * Copyright (C) 1997, 1998, 1999, 2000, 2001 Harry Eaton + * Copyright (C) 2017 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + * + * Old contact info: + * Harry Eaton, 6697 Buttonhole Ct, Columbia, MD 21044, USA + * haceaton@aplcomm.jhuapl.edu + * + */ + +#include "config.h" +#include "conf_core.h" + +#include "board.h" +#include "crosshair.h" +#include "data.h" +#include "draw.h" +#include "draw_wireframe.h" +#include "search.h" +#include "tool.h" +#include "undo.h" +#include "macro.h" + +#include "obj_arc_draw.h" + + +void pcb_tool_arc_init(void) +{ + pcb_notify_crosshair_change(pcb_false); + if (pcb_tool_prev_id == PCB_MODE_LINE && pcb_crosshair.AttachedLine.State != PCB_CH_STATE_FIRST) { + pcb_crosshair.AttachedLine.State = PCB_CH_STATE_FIRST; + pcb_crosshair.AttachedBox.State = PCB_CH_STATE_SECOND; + pcb_crosshair.AttachedBox.Point1.X = pcb_crosshair.AttachedBox.Point2.X = pcb_crosshair.AttachedLine.Point1.X; + pcb_crosshair.AttachedBox.Point1.Y = pcb_crosshair.AttachedBox.Point2.Y = pcb_crosshair.AttachedLine.Point1.Y; + pcb_tool_adjust_attached_objects(); + } + pcb_notify_crosshair_change(pcb_true); +} + +void pcb_tool_arc_uninit(void) +{ + pcb_notify_crosshair_change(pcb_false); + pcb_added_lines = 0; + if (pcb_tool_next_id != PCB_MODE_LINE) { + pcb_crosshair.AttachedBox.State = PCB_CH_STATE_FIRST; + pcb_crosshair_set_local_ref(0, 0, pcb_false); + } + pcb_notify_crosshair_change(pcb_true); +} + +void pcb_tool_arc_notify_mode(void) +{ + switch (pcb_crosshair.AttachedBox.State) { + case PCB_CH_STATE_FIRST: + pcb_crosshair.AttachedBox.Point1.X = pcb_crosshair.AttachedBox.Point2.X = pcb_tool_note.X; + pcb_crosshair.AttachedBox.Point1.Y = pcb_crosshair.AttachedBox.Point2.Y = pcb_tool_note.Y; + pcb_crosshair.AttachedBox.State = PCB_CH_STATE_SECOND; + break; + + case PCB_CH_STATE_SECOND: + case PCB_CH_STATE_THIRD: + { + pcb_arc_t *arc; + pcb_coord_t wx, wy; + pcb_angle_t sa, dir; + + wx = pcb_tool_note.X - pcb_crosshair.AttachedBox.Point1.X; + wy = pcb_tool_note.Y - pcb_crosshair.AttachedBox.Point1.Y; + if (PCB_XOR(pcb_crosshair.AttachedBox.otherway, coord_abs(wy) > coord_abs(wx))) { + pcb_crosshair.AttachedBox.Point2.X = pcb_crosshair.AttachedBox.Point1.X + coord_abs(wy) * PCB_SGNZ(wx); + sa = (wx >= 0) ? 0 : 180; + dir = (PCB_SGNZ(wx) == PCB_SGNZ(wy)) ? 90 : -90; + } + else { + pcb_crosshair.AttachedBox.Point2.Y = pcb_crosshair.AttachedBox.Point1.Y + coord_abs(wx) * PCB_SGNZ(wy); + sa = (wy >= 0) ? -90 : 90; + dir = (PCB_SGNZ(wx) == PCB_SGNZ(wy)) ? -90 : 90; + wy = wx; + } + if (coord_abs(wy) > 0 && (arc = pcb_arc_new(pcb_loose_subc_layer(PCB, CURRENT, pcb_true), + pcb_crosshair.AttachedBox.Point2.X, + pcb_crosshair.AttachedBox.Point2.Y, + coord_abs(wy), + coord_abs(wy), + sa, + dir, + conf_core.design.line_thickness, + 2 * conf_core.design.clearance, + pcb_flag_make(conf_core.editor.clear_line ? PCB_FLAG_CLEARLINE : 0), pcb_true))) { + pcb_obj_add_attribs(arc, PCB->pen_attr); + pcb_arc_get_end(arc, 1, &pcb_crosshair.AttachedBox.Point2.X, &pcb_crosshair.AttachedBox.Point2.Y); + pcb_crosshair.AttachedBox.Point1.X = pcb_crosshair.AttachedBox.Point2.X; + pcb_crosshair.AttachedBox.Point1.Y = pcb_crosshair.AttachedBox.Point2.Y; + pcb_undo_add_obj_to_create(PCB_OBJ_ARC, CURRENT, arc, arc); + pcb_undo_inc_serial(); + pcb_added_lines++; + pcb_arc_invalidate_draw(CURRENT, arc); + pcb_subc_as_board_update(PCB); + pcb_draw(); + pcb_crosshair.AttachedBox.State = PCB_CH_STATE_THIRD; + } + break; + } + } +} + +void pcb_tool_arc_adjust_attached_objects(void) +{ + pcb_crosshair.AttachedBox.otherway = pcb_gui->shift_is_pressed(); +} + +void pcb_tool_arc_draw_attached(void) +{ + if (pcb_crosshair.AttachedBox.State != PCB_CH_STATE_FIRST) { + pcb_xordraw_attached_arc(conf_core.design.line_thickness); + if (conf_core.editor.show_drc) { + pcb_gui->set_color(pcb_crosshair.GC, &conf_core.appearance.color.cross); + pcb_xordraw_attached_arc(conf_core.design.line_thickness + 2 * (conf_core.design.bloat + 1)); + pcb_gui->set_color(pcb_crosshair.GC, &conf_core.appearance.color.crosshair); + } + } + else { + /* Draw a circle (0 length line) to show where the arc will start when placed */ + if(CURRENT) + pcb_gui->set_color(pcb_crosshair.GC, &CURRENT->meta.real.color); + + pcb_draw_wireframe_line(pcb_crosshair.GC, + pcb_crosshair.X, pcb_crosshair.Y, + pcb_crosshair.X, pcb_crosshair.Y, + conf_core.design.line_thickness, 0); + + if(conf_core.editor.show_drc) { + pcb_gui->set_color(pcb_crosshair.GC, &conf_core.appearance.color.cross); + pcb_draw_wireframe_line(pcb_crosshair.GC, + pcb_crosshair.X, pcb_crosshair.Y, + pcb_crosshair.X, pcb_crosshair.Y, + conf_core.design.line_thickness + (2 * conf_core.design.bloat), 0); + pcb_gui->set_color(pcb_crosshair.GC, &conf_core.appearance.color.crosshair); + } + } + +} + +pcb_bool pcb_tool_arc_undo_act(void) +{ + if (pcb_crosshair.AttachedBox.State == PCB_CH_STATE_SECOND) { + pcb_crosshair.AttachedBox.State = PCB_CH_STATE_FIRST; + pcb_notify_crosshair_change(pcb_true); + return pcb_false; + } + if (pcb_crosshair.AttachedBox.State == PCB_CH_STATE_THIRD) { + void *ptr1, *ptr2, *ptr3; + /* guaranteed to succeed */ + pcb_search_obj_by_location(PCB_OBJ_ARC, &ptr1, &ptr2, &ptr3, + pcb_crosshair.AttachedBox.Point1.X, pcb_crosshair.AttachedBox.Point1.Y, 0); + pcb_arc_get_end((pcb_arc_t *) ptr2, 0, &pcb_crosshair.AttachedBox.Point2.X, &pcb_crosshair.AttachedBox.Point2.Y); + pcb_crosshair.AttachedBox.Point1.X = pcb_crosshair.AttachedBox.Point2.X; + pcb_crosshair.AttachedBox.Point1.Y = pcb_crosshair.AttachedBox.Point2.Y; + pcb_tool_adjust_attached_objects(); + if (--pcb_added_lines == 0) + pcb_crosshair.AttachedBox.State = PCB_CH_STATE_SECOND; + } + return pcb_true; +} + +pcb_tool_t pcb_tool_arc = { + "arc", NULL, 100, + pcb_tool_arc_init, + pcb_tool_arc_uninit, + pcb_tool_arc_notify_mode, + NULL, + pcb_tool_arc_adjust_attached_objects, + pcb_tool_arc_draw_attached, + pcb_tool_arc_undo_act, + NULL, + + pcb_false +}; Index: tags/2.1.2/src/tool_arc.h =================================================================== --- tags/2.1.2/src/tool_arc.h (nonexistent) +++ tags/2.1.2/src/tool_arc.h (revision 24813) @@ -0,0 +1,8 @@ +extern pcb_tool_t pcb_tool_arc; + +void pcb_tool_arc_init(void); +void pcb_tool_arc_uninit(void); +void pcb_tool_arc_notify_mode(void); +void pcb_tool_arc_adjust_attached_objects(void); +void pcb_tool_arc_draw_attached(void); +pcb_bool pcb_tool_arc_undo_act(void); Index: tags/2.1.2/src/tool_arrow.c =================================================================== --- tags/2.1.2/src/tool_arrow.c (nonexistent) +++ tags/2.1.2/src/tool_arrow.c (revision 24813) @@ -0,0 +1,230 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 1994,1995,1996 Thomas Nau + * Copyright (C) 1997, 1998, 1999, 2000, 2001 Harry Eaton + * Copyright (C) 2017 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + * + * Old contact info: + * Harry Eaton, 6697 Buttonhole Ct, Columbia, MD 21044, USA + * haceaton@aplcomm.jhuapl.edu + * + */ + +#include "config.h" +#include "conf_core.h" + +#include "board.h" +#include "buffer.h" +#include "crosshair.h" +#include "data.h" +#include "actions.h" +#include "remove.h" +#include "move.h" +#include "search.h" +#include "select.h" +#include "tool.h" +#include "undo.h" + + +void pcb_tool_arrow_uninit(void) +{ + pcb_notify_crosshair_change(pcb_false); + pcb_crosshair.AttachedObject.Type = PCB_OBJ_VOID; + pcb_crosshair.AttachedObject.State = PCB_CH_STATE_FIRST; + pcb_crosshair.AttachedBox.State = PCB_CH_STATE_FIRST; + pcb_notify_crosshair_change(pcb_true); +} + +/* Called some time after the click if there was a release but no second click + a.k.a. finalize single click (some things are already done in pcb_notify_mode + at the initial click event) */ +static void click_timer_cb(pcb_hidval_t hv) +{ + if (pcb_tool_note.Click) { + pcb_notify_crosshair_change(pcb_false); + pcb_tool_note.Click = pcb_false; + if (pcb_tool_note.Moving && !pcb_gui->shift_is_pressed()) { + pcb_tool_note.Buffer = conf_core.editor.buffer_number; + pcb_buffer_set_number(PCB_MAX_BUFFER - 1); + pcb_buffer_clear(PCB, PCB_PASTEBUFFER); + pcb_buffer_add_selected(PCB, PCB_PASTEBUFFER, pcb_tool_note.X, pcb_tool_note.Y, pcb_true); + pcb_undo_save_serial(); + pcb_remove_selected(pcb_false); + pcb_tool_save(); + pcb_tool_is_saved = pcb_true; + pcb_tool_select_by_id(PCB_MODE_PASTE_BUFFER); + } + else if (pcb_tool_note.Hit && !pcb_gui->shift_is_pressed()) { + pcb_box_t box; + + pcb_tool_save(); + pcb_tool_is_saved = pcb_true; + pcb_tool_select_by_id(pcb_gui->control_is_pressed()? PCB_MODE_COPY : PCB_MODE_MOVE); + pcb_crosshair.AttachedObject.Ptr1 = pcb_tool_note.ptr1; + pcb_crosshair.AttachedObject.Ptr2 = pcb_tool_note.ptr2; + pcb_crosshair.AttachedObject.Ptr3 = pcb_tool_note.ptr3; + pcb_crosshair.AttachedObject.Type = pcb_tool_note.Hit; + + if (pcb_crosshair.drags != NULL) { + free(pcb_crosshair.drags); + pcb_crosshair.drags = NULL; + } + pcb_crosshair.dragx = pcb_tool_note.X; + pcb_crosshair.dragy = pcb_tool_note.Y; + box.X1 = pcb_tool_note.X + PCB_SLOP * pcb_pixel_slop; + box.X2 = pcb_tool_note.X - PCB_SLOP * pcb_pixel_slop; + box.Y1 = pcb_tool_note.Y + PCB_SLOP * pcb_pixel_slop; + box.Y2 = pcb_tool_note.Y - PCB_SLOP * pcb_pixel_slop; + pcb_crosshair.drags = pcb_list_block(PCB, &box, &pcb_crosshair.drags_len); + pcb_crosshair.drags_current = 0; + pcb_tool_attach_for_copy(pcb_tool_note.X, pcb_tool_note.Y, pcb_true); + } + else { + pcb_box_t box; + + pcb_tool_note.Hit = 0; + pcb_tool_note.Moving = pcb_false; + pcb_undo_save_serial(); + box.X1 = -PCB_MAX_COORD; + box.Y1 = -PCB_MAX_COORD; + box.X2 = PCB_MAX_COORD; + box.Y2 = PCB_MAX_COORD; + /* unselect first if shift key not down */ + if (!pcb_gui->shift_is_pressed() && pcb_select_block(PCB, &box, pcb_false, pcb_false, pcb_false)) + pcb_board_set_changed_flag(pcb_true); + pcb_tool_notify_block(); + pcb_crosshair.AttachedBox.Point1.X = pcb_tool_note.X; + pcb_crosshair.AttachedBox.Point1.Y = pcb_tool_note.Y; + } + pcb_notify_crosshair_change(pcb_true); + } +} + +void pcb_tool_arrow_notify_mode(void) +{ + void *ptr1, *ptr2, *ptr3; + int type; + int test; + pcb_hidval_t hv; + + pcb_tool_note.Click = pcb_true; + /* do something after click time */ + pcb_gui->add_timer(click_timer_cb, conf_core.editor.click_time, hv); + + /* see if we clicked on something already selected + * (pcb_tool_note.Moving) or clicked on a MOVE_TYPE + * (pcb_tool_note.Hit) + */ + for (test = (PCB_SELECT_TYPES | PCB_MOVE_TYPES | PCB_OBJ_FLOATER | PCB_LOOSE_SUBC) & ~PCB_OBJ_RAT; test; test &= ~type) { + type = pcb_search_screen(pcb_tool_note.X, pcb_tool_note.Y, test, &ptr1, &ptr2, &ptr3); + if (!pcb_tool_note.Hit && (type & PCB_MOVE_TYPES) && !PCB_FLAG_TEST(PCB_FLAG_LOCK, (pcb_any_obj_t *) ptr2)) { + pcb_tool_note.Hit = type; + pcb_tool_note.ptr1 = ptr1; + pcb_tool_note.ptr2 = ptr2; + pcb_tool_note.ptr3 = ptr3; + pcb_crosshair.AttachedObject.tx = pcb_tool_note.X; + pcb_crosshair.AttachedObject.ty = pcb_tool_note.Y; + } + if (!pcb_tool_note.Moving && (type & (PCB_SELECT_TYPES | PCB_LOOSE_SUBC)) && PCB_FLAG_TEST(PCB_FLAG_SELECTED, (pcb_any_obj_t *) ptr2)) { + pcb_tool_note.Moving = pcb_true; + /* remember where the user clicked to start this op */ + pcb_crosshair.AttachedObject.tx = pcb_crosshair.AttachedObject.X = pcb_tool_note.X; + pcb_crosshair.AttachedObject.ty = pcb_crosshair.AttachedObject.Y = pcb_tool_note.Y; + } + if ((pcb_tool_note.Hit && pcb_tool_note.Moving) || type == PCB_OBJ_VOID) + return; + } +} + +void pcb_tool_arrow_release_mode(void) +{ + pcb_box_t box; + + if (pcb_tool_note.Click) { + pcb_box_t box; + + box.X1 = -PCB_MAX_COORD; + box.Y1 = -PCB_MAX_COORD; + box.X2 = PCB_MAX_COORD; + box.Y2 = PCB_MAX_COORD; + + pcb_tool_note.Click = pcb_false; /* inhibit timer action */ + pcb_undo_save_serial(); + /* unselect first if shift key not down */ + if (!pcb_gui->shift_is_pressed()) { + if (pcb_select_block(PCB, &box, pcb_false, pcb_false, pcb_false)) + pcb_board_set_changed_flag(pcb_true); + if (pcb_tool_note.Moving) { + pcb_tool_note.Moving = 0; + pcb_tool_note.Hit = 0; + return; + } + } + /* Restore the SN so that if we select something the deselect/select combo + gets the same SN. */ + pcb_undo_restore_serial(); + if (pcb_select_object(PCB)) + pcb_board_set_changed_flag(pcb_true); + else + pcb_undo_inc_serial(); /* We didn't select anything new, so, the deselection should get its own SN. */ + pcb_tool_note.Hit = 0; + pcb_tool_note.Moving = 0; + } + else if (pcb_crosshair.AttachedBox.State == PCB_CH_STATE_SECOND) { + box.X1 = pcb_crosshair.AttachedBox.Point1.X; + box.Y1 = pcb_crosshair.AttachedBox.Point1.Y; + box.X2 = pcb_crosshair.AttachedBox.Point2.X; + box.Y2 = pcb_crosshair.AttachedBox.Point2.Y; + + pcb_undo_restore_serial(); + if (pcb_select_block(PCB, &box, pcb_true, pcb_true, pcb_false)) + pcb_board_set_changed_flag(pcb_true); + else if (pcb_bumped) + pcb_undo_inc_serial(); + pcb_crosshair.AttachedBox.State = PCB_CH_STATE_FIRST; + } +} + +void pcb_tool_arrow_adjust_attached_objects(void) +{ + if (pcb_crosshair.AttachedBox.State) { + pcb_crosshair.AttachedBox.Point2.X = pcb_crosshair.X; + pcb_crosshair.AttachedBox.Point2.Y = pcb_crosshair.Y; + } +} + +pcb_tool_t pcb_tool_arrow = { + "arrow", NULL, 10, + NULL, + pcb_tool_arrow_uninit, + pcb_tool_arrow_notify_mode, + pcb_tool_arrow_release_mode, + pcb_tool_arrow_adjust_attached_objects, + NULL, + NULL, + NULL, + + pcb_true +}; Index: tags/2.1.2/src/tool_arrow.h =================================================================== --- tags/2.1.2/src/tool_arrow.h (nonexistent) +++ tags/2.1.2/src/tool_arrow.h (revision 24813) @@ -0,0 +1,6 @@ +extern pcb_tool_t pcb_tool_arrow; + +void pcb_tool_arrow_uninit(void); +void pcb_tool_arrow_notify_mode(void); +void pcb_tool_arrow_release_mode(void); +void pcb_tool_arrow_adjust_attached_objects(void); Index: tags/2.1.2/src/tool_buffer.c =================================================================== --- tags/2.1.2/src/tool_buffer.c (nonexistent) +++ tags/2.1.2/src/tool_buffer.c (revision 24813) @@ -0,0 +1,106 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 1994,1995,1996 Thomas Nau + * Copyright (C) 1997, 1998, 1999, 2000, 2001 Harry Eaton + * Copyright (C) 2017 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + * + * Old contact info: + * Harry Eaton, 6697 Buttonhole Ct, Columbia, MD 21044, USA + * haceaton@aplcomm.jhuapl.edu + * + */ + +#include "config.h" +#include "conf_core.h" + +#include "board.h" +#include "buffer.h" +#include "compat_misc.h" +#include "data.h" +#include "actions.h" +#include "rtree.h" +#include "search.h" +#include "tool.h" +#include "undo.h" + +void pcb_tool_buffer_init(void) +{ + pcb_crosshair_range_to_buffer(); +} + +void pcb_tool_buffer_uninit(void) +{ + pcb_crosshair_set_range(0, 0, PCB->MaxWidth, PCB->MaxHeight); +} + +void pcb_tool_buffer_notify_mode(void) +{ + if (pcb_gui->shift_is_pressed()) { + pcb_actionl("ReplaceFootprint", "object", "@buffer", "dumb", NULL); + return; + } + + if (pcb_buffer_copy_to_layout(PCB, pcb_crosshair.AttachedObject.tx, pcb_crosshair.AttachedObject.ty)) { + pcb_board_set_changed_flag(pcb_true); + pcb_gui->invalidate_all(); + } +} + +void pcb_tool_buffer_release_mode(void) +{ + if (pcb_tool_note.Moving) { + pcb_undo_restore_serial(); + pcb_tool_buffer_notify_mode(); + pcb_buffer_clear(PCB, PCB_PASTEBUFFER); + pcb_buffer_set_number(pcb_tool_note.Buffer); + pcb_tool_note.Moving = pcb_false; + pcb_tool_note.Hit = 0; + } +} + +void pcb_tool_buffer_adjust_attached_objects(void) +{ + pcb_crosshair.AttachedObject.tx = pcb_crosshair.X; + pcb_crosshair.AttachedObject.ty = pcb_crosshair.Y; +} + +void pcb_tool_buffer_draw_attached(void) +{ + pcb_xordraw_buffer(PCB_PASTEBUFFER); +} + +pcb_tool_t pcb_tool_buffer = { + "buffer", NULL, 100, + pcb_tool_buffer_init, + pcb_tool_buffer_uninit, + pcb_tool_buffer_notify_mode, + pcb_tool_buffer_release_mode, + pcb_tool_buffer_adjust_attached_objects, + pcb_tool_buffer_draw_attached, + NULL, + NULL, + + pcb_true +}; Index: tags/2.1.2/src/tool_buffer.h =================================================================== --- tags/2.1.2/src/tool_buffer.h (nonexistent) +++ tags/2.1.2/src/tool_buffer.h (revision 24813) @@ -0,0 +1,7 @@ +extern pcb_tool_t pcb_tool_buffer; + +void pcb_tool_buffer_init(void); +void pcb_tool_buffer_uninit(void); +void pcb_tool_buffer_notify_mode(void); +void pcb_tool_buffer_release_mode(void); +void pcb_tool_buffer_draw_attached(void); Index: tags/2.1.2/src/tool_copy.c =================================================================== --- tags/2.1.2/src/tool_copy.c (nonexistent) +++ tags/2.1.2/src/tool_copy.c (revision 24813) @@ -0,0 +1,129 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 1994,1995,1996 Thomas Nau + * Copyright (C) 1997, 1998, 1999, 2000, 2001 Harry Eaton + * Copyright (C) 2017 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + * + * Old contact info: + * Harry Eaton, 6697 Buttonhole Ct, Columbia, MD 21044, USA + * haceaton@aplcomm.jhuapl.edu + * + */ + +#include "config.h" + +#include "board.h" +#include "move.h" +#include "crosshair.h" +#include "search.h" +#include "tool.h" + +void pcb_tool_copy_uninit(void) +{ + pcb_notify_crosshair_change(pcb_false); + pcb_crosshair.AttachedObject.Type = PCB_OBJ_VOID; + pcb_crosshair.AttachedObject.State = PCB_CH_STATE_FIRST; + pcb_notify_crosshair_change(pcb_true); +} + +void pcb_tool_copy_notify_mode(void) +{ + switch (pcb_crosshair.AttachedObject.State) { + /* first notify, lookup object */ + case PCB_CH_STATE_FIRST: + { + int types = PCB_COPY_TYPES; + + pcb_crosshair.AttachedObject.Type = + pcb_search_screen(pcb_tool_note.X, pcb_tool_note.Y, types, + &pcb_crosshair.AttachedObject.Ptr1, &pcb_crosshair.AttachedObject.Ptr2, &pcb_crosshair.AttachedObject.Ptr3); + if (pcb_crosshair.AttachedObject.Type != PCB_OBJ_VOID) { + pcb_tool_attach_for_copy(pcb_tool_note.X, pcb_tool_note.Y, pcb_false); + } + break; + } + + /* second notify, move or copy object */ + case PCB_CH_STATE_SECOND: + + if ((PCB->is_footprint) && (pcb_crosshair.AttachedObject.Type == PCB_OBJ_SUBC)) { + pcb_message(PCB_MSG_WARNING, "Can not copy subcircuit in the footprint edit mode\n"); + } + else { + pcb_copy_obj(pcb_crosshair.AttachedObject.Type, + pcb_crosshair.AttachedObject.Ptr1, + pcb_crosshair.AttachedObject.Ptr2, + pcb_crosshair.AttachedObject.Ptr3, pcb_crosshair.AttachedObject.tx - pcb_crosshair.AttachedObject.X, pcb_crosshair.AttachedObject.ty - pcb_crosshair.AttachedObject.Y); + pcb_subc_as_board_update(PCB); + pcb_board_set_changed_flag(pcb_true); + } + + /* reset identifiers */ + pcb_crosshair.AttachedObject.Type = PCB_OBJ_VOID; + pcb_crosshair.AttachedObject.State = PCB_CH_STATE_FIRST; + break; + } +} + +void pcb_tool_copy_release_mode (void) +{ + if (pcb_tool_note.Hit) { + pcb_tool_copy_notify_mode(); + pcb_tool_note.Hit = 0; + } +} + +void pcb_tool_copy_adjust_attached_objects(void) +{ + pcb_crosshair.AttachedObject.tx = pcb_crosshair.X; + pcb_crosshair.AttachedObject.ty = pcb_crosshair.Y; +} + +void pcb_tool_copy_draw_attached(void) +{ + pcb_xordraw_movecopy(); +} + +pcb_bool pcb_tool_copy_undo_act(void) +{ + /* don't allow undo in the middle of an operation */ + if (pcb_crosshair.AttachedObject.State != PCB_CH_STATE_FIRST) + return pcb_false; + return pcb_true; +} + +pcb_tool_t pcb_tool_copy = { + "copy", NULL, 100, + NULL, + pcb_tool_copy_uninit, + pcb_tool_copy_notify_mode, + pcb_tool_copy_release_mode, + pcb_tool_copy_adjust_attached_objects, + pcb_tool_copy_draw_attached, + pcb_tool_copy_undo_act, + NULL, + + pcb_true +}; Index: tags/2.1.2/src/tool_copy.h =================================================================== --- tags/2.1.2/src/tool_copy.h (nonexistent) +++ tags/2.1.2/src/tool_copy.h (revision 24813) @@ -0,0 +1,7 @@ +extern pcb_tool_t pcb_tool_copy; + +void pcb_tool_copy_uninit(void); +void pcb_tool_copy_notify_mode(void); +void pcb_tool_copy_release_mode (void); +void pcb_tool_copy_draw_attached(void); +pcb_bool pcb_tool_copy_undo_act(void); Index: tags/2.1.2/src/tool_insert.c =================================================================== --- tags/2.1.2/src/tool_insert.c (nonexistent) +++ tags/2.1.2/src/tool_insert.c (revision 24813) @@ -0,0 +1,146 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 1994,1995,1996 Thomas Nau + * Copyright (C) 1997, 1998, 1999, 2000, 2001 Harry Eaton + * Copyright (C) 2017 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + * + * Old contact info: + * Harry Eaton, 6697 Buttonhole Ct, Columbia, MD 21044, USA + * haceaton@aplcomm.jhuapl.edu + * + */ + +#include "config.h" + +#include "board.h" +#include "crosshair.h" +#include "insert.h" +#include "polygon.h" +#include "search.h" +#include "tool.h" + + +static struct { + pcb_poly_t *poly; + pcb_line_t line; +} fake; + +static pcb_point_t InsertedPoint; +static pcb_cardinal_t polyIndex = 0; + + +void pcb_tool_insert_uninit(void) +{ + pcb_notify_crosshair_change(pcb_false); + pcb_crosshair.AttachedObject.Type = PCB_OBJ_VOID; + pcb_crosshair.AttachedObject.State = PCB_CH_STATE_FIRST; + pcb_notify_crosshair_change(pcb_true); +} + +void pcb_tool_insert_notify_mode(void) +{ + switch (pcb_crosshair.AttachedObject.State) { + /* first notify, lookup object */ + case PCB_CH_STATE_FIRST: + pcb_crosshair.AttachedObject.Type = + pcb_search_screen(pcb_tool_note.X, pcb_tool_note.Y, PCB_INSERT_TYPES, + &pcb_crosshair.AttachedObject.Ptr1, &pcb_crosshair.AttachedObject.Ptr2, &pcb_crosshair.AttachedObject.Ptr3); + + if (pcb_crosshair.AttachedObject.Type != PCB_OBJ_VOID) { + pcb_any_obj_t *obj = (pcb_any_obj_t *)pcb_crosshair.AttachedObject.Ptr2; + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, obj)) { + pcb_message(PCB_MSG_WARNING, "Sorry, %s object is locked\n", pcb_obj_type_name(obj->type)); + pcb_crosshair.AttachedObject.Type = PCB_OBJ_VOID; + break; + } + else { + /* get starting point of nearest segment */ + if (pcb_crosshair.AttachedObject.Type == PCB_OBJ_POLY) { + fake.poly = (pcb_poly_t *) pcb_crosshair.AttachedObject.Ptr2; + polyIndex = pcb_poly_get_lowest_distance_point(fake.poly, pcb_tool_note.X, pcb_tool_note.Y); + fake.line.Point1 = fake.poly->Points[polyIndex]; + fake.line.Point2 = fake.poly->Points[pcb_poly_contour_prev_point(fake.poly, polyIndex)]; + pcb_crosshair.AttachedObject.Ptr2 = &fake.line; + + } + pcb_crosshair.AttachedObject.State = PCB_CH_STATE_SECOND; + InsertedPoint = *pcb_adjust_insert_point(); + } + } + break; + + /* second notify, insert new point into object */ + case PCB_CH_STATE_SECOND: + if (pcb_crosshair.AttachedObject.Type == PCB_OBJ_POLY) + pcb_insert_point_in_object(PCB_OBJ_POLY, + pcb_crosshair.AttachedObject.Ptr1, fake.poly, + &polyIndex, InsertedPoint.X, InsertedPoint.Y, pcb_false, pcb_false); + else + pcb_insert_point_in_object(pcb_crosshair.AttachedObject.Type, + pcb_crosshair.AttachedObject.Ptr1, + pcb_crosshair.AttachedObject.Ptr2, &polyIndex, InsertedPoint.X, InsertedPoint.Y, pcb_false, pcb_false); + pcb_board_set_changed_flag(pcb_true); + + /* reset identifiers */ + pcb_crosshair.AttachedObject.Type = PCB_OBJ_VOID; + pcb_crosshair.AttachedObject.State = PCB_CH_STATE_FIRST; + break; + } +} + +void pcb_tool_insert_adjust_attached_objects(void) +{ + pcb_point_t *pnt; + pnt = pcb_adjust_insert_point(); + if (pnt) + InsertedPoint = *pnt; +} + +void pcb_tool_insert_draw_attached(void) +{ + pcb_xordraw_insert_pt_obj(); +} + +pcb_bool pcb_tool_insert_undo_act(void) +{ + /* don't allow undo in the middle of an operation */ + if (pcb_crosshair.AttachedObject.State != PCB_CH_STATE_FIRST) + return pcb_false; + return pcb_true; +} + +pcb_tool_t pcb_tool_insert = { + "insert", NULL, 100, + NULL, + pcb_tool_insert_uninit, + pcb_tool_insert_notify_mode, + NULL, + pcb_tool_insert_adjust_attached_objects, + pcb_tool_insert_draw_attached, + pcb_tool_insert_undo_act, + NULL, + + pcb_true +}; Index: tags/2.1.2/src/tool_insert.h =================================================================== --- tags/2.1.2/src/tool_insert.h (nonexistent) +++ tags/2.1.2/src/tool_insert.h (revision 24813) @@ -0,0 +1,7 @@ +extern pcb_tool_t pcb_tool_insert; + +void pcb_tool_insert_uninit(void); +void pcb_tool_insert_notify_mode(void); +void pcb_tool_insert_adjust_attached_objects(void); +void pcb_tool_insert_draw_attached(void); +pcb_bool pcb_tool_insert_undo_act(void); Index: tags/2.1.2/src/tool_line.c =================================================================== --- tags/2.1.2/src/tool_line.c (nonexistent) +++ tags/2.1.2/src/tool_line.c (revision 24813) @@ -0,0 +1,475 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 1994,1995,1996 Thomas Nau + * Copyright (C) 1997, 1998, 1999, 2000, 2001 Harry Eaton + * Copyright (C) 2017,2019 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + * + * Old contact info: + * Harry Eaton, 6697 Buttonhole Ct, Columbia, MD 21044, USA + * haceaton@aplcomm.jhuapl.edu + * + */ + +#include "config.h" +#include "conf_core.h" + +#include "board.h" +#include "crosshair.h" +#include "data.h" +#include "draw.h" +#include "draw_wireframe.h" +#include "find.h" +#include "obj_line.h" +#include "obj_subc.h" +#include "search.h" +#include "tool.h" +#include "undo.h" +#include "netlist2.h" + +#include "obj_line_draw.h" +#include "obj_pstk_draw.h" +#include "obj_rat_draw.h" +#include "route_draw.h" + +TODO("pstk: remove this when via is removed and the padstack is created from style directly") +#include "src_plugins/lib_compat_help/pstk_compat.h" + +static pcb_layer_t *last_layer; + + +void pcb_tool_line_init(void) +{ + pcb_notify_crosshair_change(pcb_false); + if (pcb_tool_prev_id == PCB_MODE_ARC && pcb_crosshair.AttachedBox.State != PCB_CH_STATE_FIRST) { + pcb_crosshair.AttachedBox.State = PCB_CH_STATE_FIRST; + pcb_crosshair.AttachedLine.State = PCB_CH_STATE_SECOND; + pcb_crosshair.AttachedLine.Point1.X = pcb_crosshair.AttachedLine.Point2.X = pcb_crosshair.AttachedBox.Point1.X; + pcb_crosshair.AttachedLine.Point1.Y = pcb_crosshair.AttachedLine.Point2.Y = pcb_crosshair.AttachedBox.Point1.Y; + pcb_tool_adjust_attached_objects(); + } + else { + if (conf_core.editor.auto_drc) { + if (pcb_data_clear_flag(PCB->Data, PCB_FLAG_FOUND, 1, 1) > 0) { + pcb_undo_inc_serial(); + pcb_draw(); + } + } + } + pcb_notify_crosshair_change(pcb_true); +} + +void pcb_tool_line_uninit(void) +{ + pcb_notify_crosshair_change(pcb_false); + pcb_added_lines = 0; + pcb_route_reset(&pcb_crosshair.Route); + if (pcb_tool_next_id != PCB_MODE_ARC) { + pcb_crosshair.AttachedLine.State = PCB_CH_STATE_FIRST; + pcb_crosshair_set_local_ref(0, 0, pcb_false); + } + pcb_notify_crosshair_change(pcb_true); +} + +/* creates points of a line (when clicked) */ +static void notify_line(void) +{ + int type = PCB_OBJ_VOID; + void *ptr1, *ptr2, *ptr3; + + if (!pcb_marked.status || conf_core.editor.local_ref) + pcb_crosshair_set_local_ref(pcb_crosshair.X, pcb_crosshair.Y, pcb_true); + switch (pcb_crosshair.AttachedLine.State) { + case PCB_CH_STATE_FIRST: /* first point */ +TODO("subc: this should work on heavy terminals too!") + if (PCB->RatDraw && pcb_search_screen(pcb_crosshair.X, pcb_crosshair.Y, PCB_OBJ_PSTK | PCB_OBJ_SUBC_PART, &ptr1, &ptr1, &ptr1) == PCB_OBJ_VOID) { + pcb_gui->beep(); + break; + } + if (conf_core.editor.auto_drc) { + pcb_find_t fctx; + type = pcb_search_screen(pcb_crosshair.X, pcb_crosshair.Y, PCB_OBJ_PSTK | PCB_OBJ_SUBC_PART, &ptr1, &ptr2, &ptr3); + memset(&fctx, 0, sizeof(fctx)); + fctx.flag_set = PCB_FLAG_FOUND; + fctx.flag_chg_undoable = 1; + pcb_find_from_xy(&fctx, PCB->Data, pcb_crosshair.X, pcb_crosshair.Y); + pcb_find_free(&fctx); + } + if (type == PCB_OBJ_PSTK) { + pcb_pstk_t *pstk = (pcb_pstk_t *)ptr2; + pcb_crosshair.AttachedLine.Point1.X = pstk->x; + pcb_crosshair.AttachedLine.Point1.Y = pstk->y; + } + else { + pcb_crosshair.AttachedLine.Point1.X = pcb_crosshair.AttachedLine.Point2.X = pcb_crosshair.X; + pcb_crosshair.AttachedLine.Point1.Y = pcb_crosshair.AttachedLine.Point2.Y = pcb_crosshair.Y; + } + pcb_crosshair.AttachedLine.State = PCB_CH_STATE_SECOND; + break; + + case PCB_CH_STATE_SECOND: + /* fall through to third state too */ + last_layer = CURRENT; + default: /* all following points */ + pcb_crosshair.AttachedLine.State = PCB_CH_STATE_THIRD; + break; + } +} + +void pcb_tool_line_notify_mode(void) +{ + void *ptr1, *ptr2, *ptr3; + + /* do update of position */ + notify_line(); + if (pcb_crosshair.AttachedLine.State != PCB_CH_STATE_THIRD) + return; + /* Remove anchor if clicking on start point; + * this means we can't paint 0 length lines + * which could be used for square SMD pads. + * Instead use a very small delta, or change + * the file after saving. + */ + if (pcb_crosshair.X == pcb_crosshair.AttachedLine.Point1.X && pcb_crosshair.Y == pcb_crosshair.AttachedLine.Point1.Y) { + pcb_tool_select_by_id(PCB_MODE_LINE); + return; + } + + if (PCB->RatDraw) { + pcb_rat_t *line = pcb_net_create_by_rat_coords(PCB, pcb_crosshair.AttachedLine.Point1.X, pcb_crosshair.AttachedLine.Point1.Y, pcb_crosshair.AttachedLine.Point2.X, pcb_crosshair.AttachedLine.Point2.Y, 1); + + if (line != NULL) { + pcb_added_lines++; + pcb_undo_add_obj_to_create(PCB_OBJ_RAT, line, line, line); + pcb_undo_inc_serial(); + pcb_rat_invalidate_draw(line); + pcb_crosshair.AttachedLine.Point1.X = pcb_crosshair.AttachedLine.Point2.X; + pcb_crosshair.AttachedLine.Point1.Y = pcb_crosshair.AttachedLine.Point2.Y; + pcb_draw(); + } + return; + } + else if(pcb_crosshair.Route.size > 0) + { + pcb_pstk_t *ps = NULL; + + /* place a via if vias are visible, the layer is + in a new group since the last line and there + isn't a pin already here */ +TODO("pstk #21: do not work in comp mode, use a pstk proto - scconfig also has TODO #21, fix it there too") + if (conf_core.editor.auto_via && PCB->pstk_on + && pcb_layer_get_group_(CURRENT) != pcb_layer_get_group_(last_layer) + && pcb_search_obj_by_location(PCB_OBJ_CLASS_PIN, &ptr1, &ptr2, &ptr3, + pcb_crosshair.AttachedLine.Point1.X, + pcb_crosshair.AttachedLine.Point1.Y, + conf_core.design.via_thickness / 2) == + PCB_OBJ_VOID + && (pcb_layer_flags_(CURRENT) & PCB_LYT_COPPER) + && (pcb_layer_flags_(last_layer) & PCB_LYT_COPPER) + && (!PCB->is_footprint) + && ((ps = pcb_pstk_new_compat_via(PCB->Data, -1, + pcb_crosshair.AttachedLine.Point1.X, + pcb_crosshair.AttachedLine.Point1.Y, + conf_core.design.via_drilling_hole, conf_core.design.via_thickness, conf_core.design.clearance, + 0, PCB_PSTK_COMPAT_ROUND, pcb_true)) != NULL)) { + pcb_obj_add_attribs(ps, PCB->pen_attr); + pcb_undo_add_obj_to_create(PCB_OBJ_PSTK, ps, ps, ps); + } + + /* Add the route to the design */ + pcb_route_apply(&pcb_crosshair.Route); + + /* move to new start point */ + pcb_crosshair.AttachedLine.Point1.X = pcb_crosshair.Route.end_point.X; + pcb_crosshair.AttachedLine.Point1.Y = pcb_crosshair.Route.end_point.Y; + pcb_crosshair.AttachedLine.Point2.X = pcb_crosshair.Route.end_point.X; + pcb_crosshair.AttachedLine.Point2.Y = pcb_crosshair.Route.end_point.Y; + + if (conf_core.editor.swap_start_direction) + conf_setf(CFR_DESIGN,"editor/line_refraction", -1, "%d",conf_core.editor.line_refraction ^ 3); + + if (conf_core.editor.orthogonal_moves) { + /* set the mark to the new starting point so ortho works as expected and we can draw a perpendicular line from here */ + pcb_marked.X = pcb_crosshair.Route.end_point.X; + pcb_marked.Y = pcb_crosshair.Route.end_point.Y; + } + + if (ps) + pcb_pstk_invalidate_draw(ps); + + pcb_draw(); + pcb_undo_inc_serial(); + last_layer = CURRENT; + } + else + /* create line if both ends are determined && length != 0 */ + { + pcb_line_t *line; + int maybe_found_flag; + + if (conf_core.editor.line_refraction + && pcb_crosshair.AttachedLine.Point1.X == + pcb_crosshair.AttachedLine.Point2.X + && pcb_crosshair.AttachedLine.Point1.Y == + pcb_crosshair.AttachedLine.Point2.Y + && (pcb_crosshair.AttachedLine.Point2.X != pcb_tool_note.X || pcb_crosshair.AttachedLine.Point2.Y != pcb_tool_note.Y)) { + /* We will only need to paint the second line segment. + Since we only check for vias on the first segment, + swap them so the non-empty segment is the first segment. */ + pcb_crosshair.AttachedLine.Point2.X = pcb_tool_note.X; + pcb_crosshair.AttachedLine.Point2.Y = pcb_tool_note.Y; + } + + if (conf_core.editor.auto_drc + && (pcb_layer_flags_(CURRENT) & PCB_LYT_COPPER)) + maybe_found_flag = PCB_FLAG_FOUND; + else + maybe_found_flag = 0; + + if ((pcb_crosshair.AttachedLine.Point1.X != + pcb_crosshair.AttachedLine.Point2.X || pcb_crosshair.AttachedLine.Point1.Y != pcb_crosshair.AttachedLine.Point2.Y) + && (line = + pcb_line_new_merge(pcb_loose_subc_layer(PCB, CURRENT, pcb_true), + pcb_crosshair.AttachedLine.Point1.X, + pcb_crosshair.AttachedLine.Point1.Y, + pcb_crosshair.AttachedLine.Point2.X, + pcb_crosshair.AttachedLine.Point2.Y, + conf_core.design.line_thickness, + 2 * conf_core.design.clearance, + pcb_flag_make(maybe_found_flag | + (conf_core.editor.clear_line ? PCB_FLAG_CLEARLINE : 0)))) != NULL) { + pcb_pstk_t *ps = NULL; + + pcb_added_lines++; + pcb_obj_add_attribs(line, PCB->pen_attr); + pcb_undo_add_obj_to_create(PCB_OBJ_LINE, CURRENT, line, line); + pcb_line_invalidate_draw(CURRENT, line); + /* place a via if vias are visible, the layer is + in a new group since the last line and there + isn't a pin already here */ +TODO("pstk #21: do not work in comp mode, use a pstk proto - scconfig also has TODO #21, fix it there too") + if (PCB->pstk_on + && pcb_layer_get_group_(CURRENT) != pcb_layer_get_group_(last_layer) + && (pcb_layer_flags_(CURRENT) & PCB_LYT_COPPER) + && (pcb_layer_flags_(last_layer) & PCB_LYT_COPPER) + && (!PCB->is_footprint) + && pcb_search_obj_by_location(PCB_OBJ_CLASS_PIN, &ptr1, &ptr2, &ptr3, + pcb_crosshair.AttachedLine.Point1.X, + pcb_crosshair.AttachedLine.Point1.Y, + conf_core.design.via_thickness / 2) == PCB_OBJ_VOID + && ((ps = pcb_pstk_new_compat_via(PCB->Data, -1, + pcb_crosshair.AttachedLine.Point1.X, + pcb_crosshair.AttachedLine.Point1.Y, + conf_core.design.via_drilling_hole, conf_core.design.via_thickness, conf_core.design.clearance, + 0, PCB_PSTK_COMPAT_ROUND, pcb_true)) != NULL)) { + pcb_obj_add_attribs(ps, PCB->pen_attr); + pcb_undo_add_obj_to_create(PCB_OBJ_PSTK, ps, ps, ps); + pcb_pstk_invalidate_draw(ps); + } + /* copy the coordinates */ + pcb_crosshair.AttachedLine.Point1.X = pcb_crosshair.AttachedLine.Point2.X; + pcb_crosshair.AttachedLine.Point1.Y = pcb_crosshair.AttachedLine.Point2.Y; + pcb_undo_inc_serial(); + last_layer = CURRENT; + pcb_subc_as_board_update(PCB); + } + if (conf_core.editor.line_refraction && (pcb_tool_note.X != pcb_crosshair.AttachedLine.Point2.X || pcb_tool_note.Y != pcb_crosshair.AttachedLine.Point2.Y) + && (line = + pcb_line_new_merge(pcb_loose_subc_layer(PCB, CURRENT, pcb_true), + pcb_crosshair.AttachedLine.Point2.X, + pcb_crosshair.AttachedLine.Point2.Y, + pcb_tool_note.X, pcb_tool_note.Y, + conf_core.design.line_thickness, + 2 * conf_core.design.clearance, + pcb_flag_make((conf_core.editor.auto_drc ? PCB_FLAG_FOUND : 0) | + (conf_core.editor.clear_line ? PCB_FLAG_CLEARLINE : 0)))) != NULL) { + pcb_added_lines++; + pcb_obj_add_attribs(line, PCB->pen_attr); + pcb_undo_add_obj_to_create(PCB_OBJ_LINE, CURRENT, line, line); + pcb_undo_inc_serial(); + pcb_line_invalidate_draw(CURRENT, line); + /* move to new start point */ + pcb_crosshair.AttachedLine.Point1.X = pcb_tool_note.X; + pcb_crosshair.AttachedLine.Point1.Y = pcb_tool_note.Y; + pcb_crosshair.AttachedLine.Point2.X = pcb_tool_note.X; + pcb_crosshair.AttachedLine.Point2.Y = pcb_tool_note.Y; + + + if (conf_core.editor.swap_start_direction) { + conf_setf(CFR_DESIGN,"editor/line_refraction", -1, "%d",conf_core.editor.line_refraction ^ 3); + } + pcb_subc_as_board_update(PCB); + } + if (conf_core.editor.orthogonal_moves) { + /* set the mark to the new starting point so ortho works as expected and we can draw a perpendicular line from here */ + pcb_marked.X = pcb_tool_note.X; + pcb_marked.Y = pcb_tool_note.Y; + } + pcb_draw(); + } +} + +void pcb_tool_line_adjust_attached_objects(void) +{ + /* don't draw outline when ctrl key is pressed */ + if (pcb_gui->control_is_pressed()) { + pcb_crosshair.AttachedLine.draw = pcb_false; + } + else { + pcb_crosshair.AttachedLine.draw = pcb_true; + pcb_line_adjust_attached(); + } +} + +void pcb_tool_line_draw_attached(void) +{ + if (PCB->RatDraw) { + /* draw only if starting point exists and the line has length */ + if (pcb_crosshair.AttachedLine.State != PCB_CH_STATE_FIRST && pcb_crosshair.AttachedLine.draw) + pcb_draw_wireframe_line(pcb_crosshair.GC, + pcb_crosshair.AttachedLine.Point1.X, pcb_crosshair.AttachedLine.Point1.Y, + pcb_crosshair.AttachedLine.Point2.X, pcb_crosshair.AttachedLine.Point2.Y, + 10, 0); + } + else if (pcb_crosshair.Route.size > 0) { + pcb_route_draw(&pcb_crosshair.Route,pcb_crosshair.GC); + if (conf_core.editor.show_drc) + pcb_route_draw_drc(&pcb_crosshair.Route,pcb_crosshair.GC); + pcb_gui->set_color(pcb_crosshair.GC, &conf_core.appearance.color.crosshair); + } + else { + /* Draw a circle (0 length line) to show where the line will be placed */ + if (CURRENT) + pcb_gui->set_color(pcb_crosshair.GC, &CURRENT->meta.real.color); + + pcb_draw_wireframe_line(pcb_crosshair.GC, + pcb_crosshair.X, pcb_crosshair.Y, + pcb_crosshair.X, pcb_crosshair.Y, + conf_core.design.line_thickness,0 ); + + if (conf_core.editor.show_drc) { + pcb_gui->set_color(pcb_crosshair.GC, &conf_core.appearance.color.cross); + pcb_draw_wireframe_line(pcb_crosshair.GC, + pcb_crosshair.X, pcb_crosshair.Y, + pcb_crosshair.X, pcb_crosshair.Y, + conf_core.design.line_thickness + (2 * conf_core.design.bloat), 0); + pcb_gui->set_color(pcb_crosshair.GC, &conf_core.appearance.color.crosshair); + } + } +} + +pcb_bool pcb_tool_line_undo_act(void) +{ + if (pcb_crosshair.AttachedLine.State == PCB_CH_STATE_SECOND) { + if (conf_core.editor.auto_drc) + pcb_undo(pcb_true); /* undo the connection find */ + pcb_crosshair.AttachedLine.State = PCB_CH_STATE_FIRST; + pcb_route_reset(&pcb_crosshair.Route); + pcb_crosshair_set_local_ref(0, 0, pcb_false); + return pcb_false; + } + if (pcb_crosshair.AttachedLine.State == PCB_CH_STATE_THIRD) { + int type; + void *ptr1, *ptr3, *ptrtmp; + pcb_line_t *ptr2; + ptrtmp = &pcb_crosshair.AttachedLine; /* a workaround for the line undo bug */ + /* this search is guaranteed to succeed */ + pcb_search_obj_by_location(PCB_OBJ_LINE | PCB_OBJ_RAT, &ptr1, + &ptrtmp, &ptr3, pcb_crosshair.AttachedLine.Point1.X, pcb_crosshair.AttachedLine.Point1.Y, 0); + ptr2 = (pcb_line_t *) ptrtmp; + + /* save both ends of line */ + pcb_crosshair.AttachedLine.Point2.X = ptr2->Point1.X; + pcb_crosshair.AttachedLine.Point2.Y = ptr2->Point1.Y; + if ((type = pcb_undo(pcb_true)) == 0) + pcb_board_set_changed_flag(pcb_true); + /* check that the undo was of the right type */ + if ((type & PCB_UNDO_CREATE) == 0) { + /* wrong undo type, restore anchor points */ + pcb_crosshair.AttachedLine.Point2.X = pcb_crosshair.AttachedLine.Point1.X; + pcb_crosshair.AttachedLine.Point2.Y = pcb_crosshair.AttachedLine.Point1.Y; + return pcb_false; + } + /* move to new anchor */ + pcb_crosshair.AttachedLine.Point1.X = pcb_crosshair.AttachedLine.Point2.X; + pcb_crosshair.AttachedLine.Point1.Y = pcb_crosshair.AttachedLine.Point2.Y; + /* check if an intermediate point was removed */ + if (type & PCB_UNDO_REMOVE) { + /* this search should find the restored line */ + pcb_search_obj_by_location(PCB_OBJ_LINE | PCB_OBJ_RAT, &ptr1, &ptrtmp, &ptr3, pcb_crosshair.AttachedLine.Point2.X, pcb_crosshair.AttachedLine.Point2.Y, 0); + ptr2 = (pcb_line_t *) ptrtmp; + if (conf_core.editor.auto_drc) { + /* undo loses PCB_FLAG_FOUND */ + PCB_FLAG_SET(PCB_FLAG_FOUND, ptr2); + pcb_line_invalidate_draw(CURRENT, ptr2); + } + pcb_crosshair.AttachedLine.Point1.X = pcb_crosshair.AttachedLine.Point2.X = ptr2->Point2.X; + pcb_crosshair.AttachedLine.Point1.Y = pcb_crosshair.AttachedLine.Point2.Y = ptr2->Point2.Y; + } + pcb_crosshair_grid_fit(pcb_crosshair.X, pcb_crosshair.Y); + pcb_tool_adjust_attached_objects(); + if (--pcb_added_lines == 0) { + pcb_crosshair.AttachedLine.State = PCB_CH_STATE_SECOND; + last_layer = CURRENT; + } + else { + /* this search is guaranteed to succeed too */ + pcb_search_obj_by_location(PCB_OBJ_LINE | PCB_OBJ_RAT, &ptr1, &ptrtmp, &ptr3, pcb_crosshair.AttachedLine.Point1.X, pcb_crosshair.AttachedLine.Point1.Y, 0); + ptr2 = (pcb_line_t *) ptrtmp; + last_layer = (pcb_layer_t *) ptr1; + } + return pcb_false; + } + return pcb_true; +} + +pcb_bool pcb_tool_line_redo_act(void) +{ + if (pcb_crosshair.AttachedLine.State == PCB_CH_STATE_SECOND) + return pcb_false; + if (pcb_redo(pcb_true)) { + pcb_board_set_changed_flag(pcb_true); + if (pcb_crosshair.AttachedLine.State != PCB_CH_STATE_FIRST) { + pcb_line_t *line = linelist_last(&CURRENT->Line); + pcb_crosshair.AttachedLine.Point1.X = pcb_crosshair.AttachedLine.Point2.X = line->Point2.X; + pcb_crosshair.AttachedLine.Point1.Y = pcb_crosshair.AttachedLine.Point2.Y = line->Point2.Y; + pcb_added_lines++; + } + } + return pcb_false; +} + +pcb_tool_t pcb_tool_line = { + "line", NULL, 100, + pcb_tool_line_init, + pcb_tool_line_uninit, + pcb_tool_line_notify_mode, + NULL, + pcb_tool_line_adjust_attached_objects, + pcb_tool_line_draw_attached, + pcb_tool_line_undo_act, + pcb_tool_line_redo_act, + + pcb_true +}; Index: tags/2.1.2/src/tool_line.h =================================================================== --- tags/2.1.2/src/tool_line.h (nonexistent) +++ tags/2.1.2/src/tool_line.h (revision 24813) @@ -0,0 +1,9 @@ +extern pcb_tool_t pcb_tool_line; + +void pcb_tool_line_init(void); +void pcb_tool_line_uninit(void); +void pcb_tool_line_notify_mode(void); +void pcb_tool_line_adjust_attached_objects(void); +void pcb_tool_line_draw_attached(void); +pcb_bool pcb_tool_line_undo_act(void); +pcb_bool pcb_tool_line_redo_act(void); Index: tags/2.1.2/src/tool_lock.c =================================================================== --- tags/2.1.2/src/tool_lock.c (nonexistent) +++ tags/2.1.2/src/tool_lock.c (revision 24813) @@ -0,0 +1,89 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 1994,1995,1996 Thomas Nau + * Copyright (C) 1997, 1998, 1999, 2000, 2001 Harry Eaton + * Copyright (C) 2017 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + * + * Old contact info: + * Harry Eaton, 6697 Buttonhole Ct, Columbia, MD 21044, USA + * haceaton@aplcomm.jhuapl.edu + * + */ + +#include "config.h" + +#include "board.h" +#include "change.h" +#include "data.h" +#include "draw.h" +#include "actions.h" +#include "search.h" +#include "tool.h" +#include "tool_lock.h" + +#define PCB_OBJ_CLASS_LOCK (PCB_OBJ_PSTK | PCB_OBJ_LINE | PCB_OBJ_ARC | PCB_OBJ_POLY | PCB_OBJ_SUBC | PCB_OBJ_TEXT | PCB_OBJ_LOCKED) + +void pcb_tool_lock_notify_mode(void) +{ + void *ptr1, *ptr2, *ptr3; + int type; + + type = pcb_search_screen(pcb_tool_note.X, pcb_tool_note.Y, PCB_OBJ_CLASS_LOCK, &ptr1, &ptr2, &ptr3); + + if (type == PCB_OBJ_SUBC) { + pcb_subc_t *subc = (pcb_subc_t *)ptr2; + pcb_flag_change(PCB, PCB_CHGFLG_TOGGLE, PCB_FLAG_LOCK, PCB_OBJ_SUBC, ptr1, ptr2, ptr3); + + DrawSubc(subc); + pcb_draw(); + pcb_actionl("Report", "Subc", "log", NULL); + } + else if (type != PCB_OBJ_VOID) { + pcb_text_t *thing = (pcb_text_t *) ptr3; + PCB_FLAG_TOGGLE(PCB_FLAG_LOCK, thing); + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, thing) + && PCB_FLAG_TEST(PCB_FLAG_SELECTED, thing)) { + /* this is not un-doable since LOCK isn't */ + PCB_FLAG_CLEAR(PCB_FLAG_SELECTED, thing); + pcb_draw_obj((pcb_any_obj_t *)ptr2); + pcb_draw(); + } + pcb_actionl("Report", "Object", "log", NULL); + } +} + +pcb_tool_t pcb_tool_lock = { + "lock", NULL, 100, + NULL, + NULL, + pcb_tool_lock_notify_mode, + NULL, + NULL, + NULL, + NULL, + NULL, + + pcb_true +}; Index: tags/2.1.2/src/tool_lock.h =================================================================== --- tags/2.1.2/src/tool_lock.h (nonexistent) +++ tags/2.1.2/src/tool_lock.h (revision 24813) @@ -0,0 +1,3 @@ +extern pcb_tool_t pcb_tool_lock; + +void pcb_tool_lock_notify_mode(void); Index: tags/2.1.2/src/tool_move.c =================================================================== --- tags/2.1.2/src/tool_move.c (nonexistent) +++ tags/2.1.2/src/tool_move.c (revision 24813) @@ -0,0 +1,135 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 1994,1995,1996 Thomas Nau + * Copyright (C) 1997, 1998, 1999, 2000, 2001 Harry Eaton + * Copyright (C) 2017 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + * + * Old contact info: + * Harry Eaton, 6697 Buttonhole Ct, Columbia, MD 21044, USA + * haceaton@aplcomm.jhuapl.edu + * + */ + +#include "config.h" + +#include "board.h" +#include "move.h" +#include "crosshair.h" +#include "search.h" +#include "tool.h" + + +void pcb_tool_move_uninit(void) +{ + pcb_notify_crosshair_change(pcb_false); + pcb_crosshair.AttachedObject.Type = PCB_OBJ_VOID; + pcb_crosshair.AttachedObject.State = PCB_CH_STATE_FIRST; + pcb_notify_crosshair_change(pcb_true); +} + +void pcb_tool_move_notify_mode(void) +{ + pcb_coord_t dx, dy; + + switch (pcb_crosshair.AttachedObject.State) { + /* first notify, lookup object */ + case PCB_CH_STATE_FIRST: + { + int types = PCB_MOVE_TYPES; + + pcb_crosshair.AttachedObject.Type = + pcb_search_screen(pcb_tool_note.X, pcb_tool_note.Y, types, + &pcb_crosshair.AttachedObject.Ptr1, &pcb_crosshair.AttachedObject.Ptr2, &pcb_crosshair.AttachedObject.Ptr3); + if (pcb_crosshair.AttachedObject.Type != PCB_OBJ_VOID) { + pcb_any_obj_t *obj = (pcb_any_obj_t *)pcb_crosshair.AttachedObject.Ptr2; + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, obj)) { + pcb_message(PCB_MSG_WARNING, "Sorry, %s object is locked\n", pcb_obj_type_name(obj->type)); + pcb_crosshair.AttachedObject.Type = PCB_OBJ_VOID; + } + else + pcb_tool_attach_for_copy(pcb_tool_note.X, pcb_tool_note.Y, pcb_true); + } + break; + } + + /* second notify, move object */ + case PCB_CH_STATE_SECOND: + dx = pcb_crosshair.AttachedObject.tx - pcb_crosshair.AttachedObject.X; + dy = pcb_crosshair.AttachedObject.ty - pcb_crosshair.AttachedObject.Y; + if ((dx != 0) || (dy != 0)) { + pcb_move_obj_and_rubberband(pcb_crosshair.AttachedObject.Type, pcb_crosshair.AttachedObject.Ptr1, pcb_crosshair.AttachedObject.Ptr2, pcb_crosshair.AttachedObject.Ptr3, dx, dy); + pcb_crosshair_set_local_ref(0, 0, pcb_false); + pcb_subc_as_board_update(PCB); + pcb_board_set_changed_flag(pcb_true); + } + + /* reset identifiers */ + pcb_crosshair.AttachedObject.Type = PCB_OBJ_VOID; + pcb_crosshair.AttachedObject.State = PCB_CH_STATE_FIRST; + pcb_crosshair_set_range(0, 0, PCB->MaxWidth, PCB->MaxHeight); + break; + } +} + +void pcb_tool_move_release_mode (void) +{ + if (pcb_tool_note.Hit) { + pcb_tool_move_notify_mode(); + pcb_tool_note.Hit = 0; + } +} + +void pcb_tool_move_adjust_attached_objects(void) +{ + pcb_crosshair.AttachedObject.tx = pcb_crosshair.X; + pcb_crosshair.AttachedObject.ty = pcb_crosshair.Y; +} + +void pcb_tool_move_draw_attached(void) +{ + pcb_xordraw_movecopy(); +} + +pcb_bool pcb_tool_move_undo_act(void) +{ + /* don't allow undo in the middle of an operation */ + if (pcb_crosshair.AttachedObject.State != PCB_CH_STATE_FIRST) + return pcb_false; + return pcb_true; +} + +pcb_tool_t pcb_tool_move = { + "move", NULL, 100, + NULL, + pcb_tool_move_uninit, + pcb_tool_move_notify_mode, + pcb_tool_move_release_mode, + pcb_tool_move_adjust_attached_objects, + pcb_tool_move_draw_attached, + pcb_tool_move_undo_act, + NULL, + + pcb_true +}; Index: tags/2.1.2/src/tool_move.h =================================================================== --- tags/2.1.2/src/tool_move.h (nonexistent) +++ tags/2.1.2/src/tool_move.h (revision 24813) @@ -0,0 +1,7 @@ +extern pcb_tool_t pcb_tool_move; + +void pcb_tool_move_uninit(void); +void pcb_tool_move_notify_mode(void); +void pcb_tool_move_release_mode (void); +void pcb_tool_move_draw_attached(void); +pcb_bool pcb_tool_move_undo_act(void); Index: tags/2.1.2/src/tool_poly.c =================================================================== --- tags/2.1.2/src/tool_poly.c (nonexistent) +++ tags/2.1.2/src/tool_poly.c (revision 24813) @@ -0,0 +1,160 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 1994,1995,1996 Thomas Nau + * Copyright (C) 1997, 1998, 1999, 2000, 2001 Harry Eaton + * Copyright (C) 2017 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + * + * Old contact info: + * Harry Eaton, 6697 Buttonhole Ct, Columbia, MD 21044, USA + * haceaton@aplcomm.jhuapl.edu + * + */ + +#include "config.h" +#include "conf_core.h" + +#include "crosshair.h" +#include "actions.h" +#include "polygon.h" +#include "tool.h" + + +void pcb_tool_poly_uninit(void) +{ + pcb_notify_crosshair_change(pcb_false); + pcb_crosshair.AttachedPolygon.PointN = 0; + pcb_crosshair.AttachedLine.State = PCB_CH_STATE_FIRST; + pcb_notify_crosshair_change(pcb_true); +} + +void pcb_tool_poly_notify_mode(void) +{ + pcb_point_t *points = pcb_crosshair.AttachedPolygon.Points; + pcb_cardinal_t n = pcb_crosshair.AttachedPolygon.PointN; + + /* do update of position */ + if (pcb_crosshair.AttachedLine.State == PCB_CH_STATE_FIRST) { + pcb_crosshair.AttachedLine.Point1.X = pcb_crosshair.AttachedLine.Point2.X = pcb_crosshair.X; + pcb_crosshair.AttachedLine.Point1.Y = pcb_crosshair.AttachedLine.Point2.Y = pcb_crosshair.Y; + pcb_crosshair.AttachedLine.State = PCB_CH_STATE_THIRD; + pcb_crosshair.AttachedPolygon_pts = 0; + } + + /* check if this is the last point of a polygon */ + if (n >= 3 && points[0].X == pcb_crosshair.AttachedLine.Point2.X && points[0].Y == pcb_crosshair.AttachedLine.Point2.Y) { + pcb_actionl("Polygon", "Close", NULL); + return; + } + + /* Someone clicking twice on the same point ('doubleclick'): close polygon */ + if (n >= 3 && points[n - 1].X == pcb_crosshair.AttachedLine.Point2.X && points[n - 1].Y == pcb_crosshair.AttachedLine.Point2.Y) { + pcb_actionl("Polygon", "Close", NULL); + return; + } + + /* create new point if it's the first one or if it's + * different to the last one + */ + if (!n || points[n - 1].X != pcb_crosshair.AttachedLine.Point2.X || points[n - 1].Y != pcb_crosshair.AttachedLine.Point2.Y) { + pcb_poly_point_new(&pcb_crosshair.AttachedPolygon, pcb_crosshair.AttachedLine.Point2.X, pcb_crosshair.AttachedLine.Point2.Y); + pcb_crosshair.AttachedPolygon_pts = pcb_crosshair.AttachedPolygon.PointN; + + /* copy the coordinates */ + pcb_crosshair.AttachedLine.Point1.X = pcb_crosshair.AttachedLine.Point2.X; + pcb_crosshair.AttachedLine.Point1.Y = pcb_crosshair.AttachedLine.Point2.Y; + } + + if (conf_core.editor.orthogonal_moves) { + /* set the mark to the new starting point so ortho works */ + pcb_marked.X = pcb_tool_note.X; + pcb_marked.Y = pcb_tool_note.Y; + } +} + +void pcb_tool_poly_adjust_attached_objects(void) +{ + pcb_attached_line_t *line = &pcb_crosshair.AttachedLine; + + if (pcb_gui->control_is_pressed()) { + line->draw = pcb_false; + return; + } + else + line->draw = pcb_true; + if (conf_core.editor.all_direction_lines) { + line->Point2.X = pcb_crosshair.X; + line->Point2.Y = pcb_crosshair.Y; + return; + } + + pcb_line_45(line); +} + +void pcb_tool_poly_draw_attached(void) +{ + /* draw only if starting point is set */ + if (pcb_crosshair.AttachedLine.State != PCB_CH_STATE_FIRST) + pcb_gui->draw_line(pcb_crosshair.GC, + pcb_crosshair.AttachedLine.Point1.X, + pcb_crosshair.AttachedLine.Point1.Y, pcb_crosshair.AttachedLine.Point2.X, pcb_crosshair.AttachedLine.Point2.Y); + + /* draw attached polygon only if in PCB_MODE_POLYGON or PCB_MODE_POLYGON_HOLE */ + if (pcb_crosshair.AttachedPolygon.PointN > 1) { + pcb_xordraw_poly(&pcb_crosshair.AttachedPolygon, 0, 0, 1); + } +} + +pcb_bool pcb_tool_poly_undo_act(void) +{ + if (pcb_crosshair.AttachedPolygon.PointN) { + pcb_polygon_go_to_prev_point(); + return pcb_false; + } + return pcb_true; +} + +pcb_bool pcb_tool_poly_redo_act(void) +{ + if (pcb_crosshair.AttachedPolygon.PointN) { + pcb_polygon_go_to_next_point(); + return pcb_false; + } + else + return pcb_true; +} + +pcb_tool_t pcb_tool_poly = { + "poly", NULL, 100, + NULL, + pcb_tool_poly_uninit, + pcb_tool_poly_notify_mode, + NULL, + pcb_tool_poly_adjust_attached_objects, + pcb_tool_poly_draw_attached, + pcb_tool_poly_undo_act, + pcb_tool_poly_redo_act, + + pcb_false +}; Index: tags/2.1.2/src/tool_poly.h =================================================================== --- tags/2.1.2/src/tool_poly.h (nonexistent) +++ tags/2.1.2/src/tool_poly.h (revision 24813) @@ -0,0 +1,8 @@ +extern pcb_tool_t pcb_tool_poly; + +void pcb_tool_poly_uninit(void); +void pcb_tool_poly_notify_mode(void); +void pcb_tool_poly_adjust_attached_objects(void); +void pcb_tool_poly_draw_attached(void); +pcb_bool pcb_tool_poly_undo_act(void); +pcb_bool pcb_tool_poly_redo_act(void); Index: tags/2.1.2/src/tool_polyhole.c =================================================================== --- tags/2.1.2/src/tool_polyhole.c (nonexistent) +++ tags/2.1.2/src/tool_polyhole.c (revision 24813) @@ -0,0 +1,189 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 1994,1995,1996 Thomas Nau + * Copyright (C) 1997, 1998, 1999, 2000, 2001 Harry Eaton + * Copyright (C) 2017 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + * + * Old contact info: + * Harry Eaton, 6697 Buttonhole Ct, Columbia, MD 21044, USA + * haceaton@aplcomm.jhuapl.edu + * + */ + +#include "config.h" +#include "conf_core.h" + +#include "crosshair.h" +#include "actions.h" +#include "polygon.h" +#include "search.h" +#include "tool.h" + + +void pcb_tool_polyhole_uninit(void) +{ + pcb_notify_crosshair_change(pcb_false); + pcb_crosshair.AttachedPolygon.PointN = 0; + pcb_crosshair.AttachedLine.State = PCB_CH_STATE_FIRST; + pcb_notify_crosshair_change(pcb_true); +} + +void pcb_tool_polyhole_notify_mode(void) +{ + switch (pcb_crosshair.AttachedObject.State) { + /* first notify, lookup object */ + case PCB_CH_STATE_FIRST: + pcb_crosshair.AttachedPolygon_pts = 0; + pcb_crosshair.AttachedObject.Type = + pcb_search_screen(pcb_tool_note.X, pcb_tool_note.Y, PCB_OBJ_POLY, + &pcb_crosshair.AttachedObject.Ptr1, &pcb_crosshair.AttachedObject.Ptr2, &pcb_crosshair.AttachedObject.Ptr3); + + if (pcb_crosshair.AttachedObject.Type == PCB_OBJ_VOID) { + pcb_message(PCB_MSG_WARNING, "The first point of a polygon hole must be on a polygon.\n"); + break; /* don't start doing anything if clicket out of polys */ + } + + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, (pcb_poly_t *)pcb_crosshair.AttachedObject.Ptr2)) { + pcb_message(PCB_MSG_WARNING, "Sorry, poly object is locked\n"); + pcb_crosshair.AttachedObject.Type = PCB_OBJ_VOID; + break; + } + else + pcb_crosshair.AttachedObject.State = PCB_CH_STATE_SECOND; + /* fall thru: first click is also the first point of the poly hole */ + + /* second notify, insert new point into object */ + case PCB_CH_STATE_SECOND: + { + pcb_point_t *points = pcb_crosshair.AttachedPolygon.Points; + pcb_cardinal_t n = pcb_crosshair.AttachedPolygon.PointN; + + /* do update of position */ + if (pcb_crosshair.AttachedLine.State == PCB_CH_STATE_FIRST) { + pcb_crosshair.AttachedLine.Point1.X = pcb_crosshair.AttachedLine.Point2.X = pcb_crosshair.X; + pcb_crosshair.AttachedLine.Point1.Y = pcb_crosshair.AttachedLine.Point2.Y = pcb_crosshair.Y; + pcb_crosshair.AttachedLine.State = PCB_CH_STATE_THIRD; + } + + if (conf_core.editor.orthogonal_moves) { + /* set the mark to the new starting point so ortho works */ + pcb_marked.X = pcb_tool_note.X; + pcb_marked.Y = pcb_tool_note.Y; + } + + /* check if this is the last point of a polygon */ + if (n >= 3 && points[0].X == pcb_crosshair.AttachedLine.Point2.X && points[0].Y == pcb_crosshair.AttachedLine.Point2.Y) { + pcb_actionl("Polygon", "CloseHole", NULL); + break; + } + + /* Someone clicking twice on the same point ('doubleclick'): close polygon hole */ + if (n >= 3 && points[n - 1].X == pcb_crosshair.AttachedLine.Point2.X && points[n - 1].Y == pcb_crosshair.AttachedLine.Point2.Y) { + pcb_actionl("Polygon", "CloseHole", NULL); + break; + } + + /* create new point if it's the first one or if it's + * different to the last one + */ + if (!n || points[n - 1].X != pcb_crosshair.AttachedLine.Point2.X || points[n - 1].Y != pcb_crosshair.AttachedLine.Point2.Y) { + pcb_poly_point_new(&pcb_crosshair.AttachedPolygon, + pcb_crosshair.AttachedLine.Point2.X, pcb_crosshair.AttachedLine.Point2.Y); + pcb_crosshair.AttachedPolygon_pts = pcb_crosshair.AttachedPolygon.PointN; + + /* copy the coordinates */ + pcb_crosshair.AttachedLine.Point1.X = pcb_crosshair.AttachedLine.Point2.X; + pcb_crosshair.AttachedLine.Point1.Y = pcb_crosshair.AttachedLine.Point2.Y; + } + break; + } + } +} + +void pcb_tool_polyhole_adjust_attached_objects(void) +{ + pcb_attached_line_t *line = &pcb_crosshair.AttachedLine; + + if (pcb_gui->control_is_pressed()) { + line->draw = pcb_false; + return; + } + else + line->draw = pcb_true; + if (conf_core.editor.all_direction_lines) { + line->Point2.X = pcb_crosshair.X; + line->Point2.Y = pcb_crosshair.Y; + return; + } + + pcb_line_45(line); +} + +void pcb_tool_polyhole_draw_attached(void) +{ + /* draw only if starting point is set */ + if (pcb_crosshair.AttachedLine.State != PCB_CH_STATE_FIRST) + pcb_gui->draw_line(pcb_crosshair.GC, + pcb_crosshair.AttachedLine.Point1.X, + pcb_crosshair.AttachedLine.Point1.Y, pcb_crosshair.AttachedLine.Point2.X, pcb_crosshair.AttachedLine.Point2.Y); + + /* draw attached polygon only if in PCB_MODE_POLYGON or PCB_MODE_POLYGON_HOLE */ + if (pcb_crosshair.AttachedPolygon.PointN > 1) { + pcb_xordraw_poly(&pcb_crosshair.AttachedPolygon, 0, 0, 1); + } +} + +pcb_bool pcb_tool_polyhole_undo_act(void) +{ + if (pcb_crosshair.AttachedPolygon.PointN) { + pcb_polygon_go_to_prev_point(); + return pcb_false; + } + return pcb_true; +} + +pcb_bool pcb_tool_polyhole_redo_act(void) +{ + if (pcb_crosshair.AttachedPolygon.PointN) { + pcb_polygon_go_to_next_point(); + return pcb_false; + } + else + return pcb_true; +} + +pcb_tool_t pcb_tool_polyhole = { + "polyhole", NULL, 100, + NULL, + pcb_tool_polyhole_uninit, + pcb_tool_polyhole_notify_mode, + NULL, + pcb_tool_polyhole_adjust_attached_objects, + pcb_tool_polyhole_draw_attached, + pcb_tool_polyhole_undo_act, + pcb_tool_polyhole_redo_act, + + pcb_false +}; Index: tags/2.1.2/src/tool_polyhole.h =================================================================== --- tags/2.1.2/src/tool_polyhole.h (nonexistent) +++ tags/2.1.2/src/tool_polyhole.h (revision 24813) @@ -0,0 +1,8 @@ +extern pcb_tool_t pcb_tool_polyhole; + +void pcb_tool_polyhole_uninit(void); +void pcb_tool_polyhole_notify_mode(void); +void pcb_tool_polyhole_adjust_attached_objects(void); +void pcb_tool_polyhole_draw_attached(void); +pcb_bool pcb_tool_polyhole_undo_act(void); +pcb_bool pcb_tool_polyhole_redo_act(void); Index: tags/2.1.2/src/tool_rectangle.c =================================================================== --- tags/2.1.2/src/tool_rectangle.c (nonexistent) +++ tags/2.1.2/src/tool_rectangle.c (revision 24813) @@ -0,0 +1,127 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 1994,1995,1996 Thomas Nau + * Copyright (C) 1997, 1998, 1999, 2000, 2001 Harry Eaton + * Copyright (C) 2017 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + * + * Old contact info: + * Harry Eaton, 6697 Buttonhole Ct, Columbia, MD 21044, USA + * haceaton@aplcomm.jhuapl.edu + * + */ + +#include "config.h" +#include "conf_core.h" + +#include "board.h" +#include "crosshair.h" +#include "data.h" +#include "draw.h" +#include "tool.h" +#include "undo.h" + +#include "obj_poly_draw.h" + + +void pcb_tool_rectangle_uninit(void) +{ + pcb_notify_crosshair_change(pcb_false); + pcb_crosshair.AttachedBox.State = PCB_CH_STATE_FIRST; + pcb_notify_crosshair_change(pcb_true); +} + +void pcb_tool_rectangle_notify_mode(void) +{ + /* do update of position */ + pcb_tool_notify_block(); + + /* create rectangle if both corners are determined + * and width, height are != 0 + */ + if (pcb_crosshair.AttachedBox.State == PCB_CH_STATE_THIRD && + pcb_crosshair.AttachedBox.Point1.X != pcb_crosshair.AttachedBox.Point2.X && + pcb_crosshair.AttachedBox.Point1.Y != pcb_crosshair.AttachedBox.Point2.Y) { + pcb_poly_t *polygon; + pcb_layer_t *layer = pcb_loose_subc_layer(PCB, CURRENT, pcb_true); + + int flags = PCB_FLAG_CLEARPOLY; + if (conf_core.editor.full_poly) + flags |= PCB_FLAG_FULLPOLY; + if (conf_core.editor.clear_polypoly) + flags |= PCB_FLAG_CLEARPOLYPOLY; + if ((polygon = pcb_poly_new_from_rectangle(layer, + pcb_crosshair.AttachedBox.Point1.X, + pcb_crosshair.AttachedBox.Point1.Y, + pcb_crosshair.AttachedBox.Point2.X, + pcb_crosshair.AttachedBox.Point2.Y, + 2 * conf_core.design.clearance, + pcb_flag_make(flags))) != NULL) { + pcb_obj_add_attribs(polygon, PCB->pen_attr); + pcb_undo_add_obj_to_create(PCB_OBJ_POLY, layer, polygon, polygon); + pcb_undo_inc_serial(); + pcb_poly_invalidate_draw(layer, polygon); + pcb_draw(); + } + + /* reset state to 'first corner' */ + pcb_crosshair.AttachedBox.State = PCB_CH_STATE_FIRST; + pcb_subc_as_board_update(PCB); + } +} + +void pcb_tool_rectangle_adjust_attached_objects(void) +{ + switch (pcb_crosshair.AttachedBox.State) { + case PCB_CH_STATE_SECOND: /* one corner is selected */ + { + /* update coordinates */ + pcb_crosshair.AttachedBox.Point2.X = pcb_crosshair.X; + pcb_crosshair.AttachedBox.Point2.Y = pcb_crosshair.Y; + break; + } + } +} + +pcb_bool pcb_tool_rectangle_anydo_act(void) +{ + /* don't allow undo in the middle of an operation */ + if (pcb_crosshair.AttachedBox.State != PCB_CH_STATE_FIRST) + return pcb_false; + return pcb_true; +} + +pcb_tool_t pcb_tool_rectangle = { + "rectangle", NULL, 100, + NULL, + pcb_tool_rectangle_uninit, + pcb_tool_rectangle_notify_mode, + NULL, + pcb_tool_rectangle_adjust_attached_objects, + NULL, + pcb_tool_rectangle_anydo_act, + pcb_tool_rectangle_anydo_act, + + pcb_false +}; Index: tags/2.1.2/src/tool_rectangle.h =================================================================== --- tags/2.1.2/src/tool_rectangle.h (nonexistent) +++ tags/2.1.2/src/tool_rectangle.h (revision 24813) @@ -0,0 +1,6 @@ +extern pcb_tool_t pcb_tool_rectangle; + +void pcb_tool_rectangle_uninit(void); +void pcb_tool_rectangle_notify_mode(void); +void pcb_tool_rectangle_adjust_attached_objects(void); +pcb_bool pcb_tool_rectangle_undo_act(void); Index: tags/2.1.2/src/tool_remove.c =================================================================== --- tags/2.1.2/src/tool_remove.c (nonexistent) +++ tags/2.1.2/src/tool_remove.c (revision 24813) @@ -0,0 +1,96 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 1994,1995,1996 Thomas Nau + * Copyright (C) 1997, 1998, 1999, 2000, 2001 Harry Eaton + * Copyright (C) 2017 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + * + * Old contact info: + * Harry Eaton, 6697 Buttonhole Ct, Columbia, MD 21044, USA + * haceaton@aplcomm.jhuapl.edu + * + */ + +#include "config.h" + +#include "board.h" +#include "event.h" +#include "actions.h" +#include "undo.h" +#include "remove.h" +#include "search.h" +#include "tool.h" + + +void pcb_tool_remove_notify_mode(void) +{ + void *ptr1, *ptr2, *ptr3; + pcb_any_obj_t *obj; + int type; + + if ((type = pcb_search_screen(pcb_tool_note.X, pcb_tool_note.Y, PCB_REMOVE_TYPES | PCB_LOOSE_SUBC | PCB_OBJ_FLOATER, &ptr1, &ptr2, &ptr3)) != PCB_OBJ_VOID) { + obj = (pcb_any_obj_t *)ptr2; + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, obj)) { + pcb_message(PCB_MSG_WARNING, "Sorry, %s object is locked\n", pcb_obj_type_name(obj->type)); + return; + } + + if (type == PCB_OBJ_SUBC) { + if(PCB->is_footprint) { + pcb_message(PCB_MSG_WARNING, "Can not remove the subcircuit being edited in the footprint edit mode\n"); + return; + } + } + + obj = ptr2; + pcb_rat_update_obj_removed(PCB, obj); + + /* preserve original parent over the board layer pcb_search_screen operated on - + this is essential for undo: it needs to put back the object to the original + layer (e.g. inside a subc) instead of on the board layer */ + if (obj->parent_type == PCB_PARENT_LAYER) + ptr1 = obj->parent.layer; + else if (obj->parent_type == PCB_PARENT_DATA) + ptr1 = obj->parent.data; + + pcb_remove_object(type, ptr1, ptr2, ptr3); + pcb_undo_inc_serial(); + pcb_subc_as_board_update(PCB); + pcb_board_set_changed_flag(pcb_true); + } +} + +pcb_tool_t pcb_tool_remove = { + "remove", NULL, 100, + NULL, + NULL, + pcb_tool_remove_notify_mode, + NULL, + NULL, + NULL, + NULL, + NULL, + + pcb_true +}; Index: tags/2.1.2/src/tool_remove.h =================================================================== --- tags/2.1.2/src/tool_remove.h (nonexistent) +++ tags/2.1.2/src/tool_remove.h (revision 24813) @@ -0,0 +1,3 @@ +extern pcb_tool_t pcb_tool_remove; + +void pcb_tool_remove_notify_mode(void); Index: tags/2.1.2/src/tool_rotate.c =================================================================== --- tags/2.1.2/src/tool_rotate.c (nonexistent) +++ tags/2.1.2/src/tool_rotate.c (revision 24813) @@ -0,0 +1,63 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 1994,1995,1996 Thomas Nau + * Copyright (C) 1997, 1998, 1999, 2000, 2001 Harry Eaton + * Copyright (C) 2017 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + * + * Old contact info: + * Harry Eaton, 6697 Buttonhole Ct, Columbia, MD 21044, USA + * haceaton@aplcomm.jhuapl.edu + * + */ + +#include "config.h" +#include "conf_core.h" + +#include "actions.h" +#include "board.h" +#include "rotate.h" +#include "tool.h" + + +void pcb_tool_rotate_notify_mode(void) +{ + pcb_screen_obj_rotate90(pcb_tool_note.X, pcb_tool_note.Y, pcb_gui->shift_is_pressed()? (conf_core.editor.show_solder_side ? 1 : 3) + : (conf_core.editor.show_solder_side ? 3 : 1)); + pcb_subc_as_board_update(PCB); +} + +pcb_tool_t pcb_tool_rotate = { + "rotate", NULL, 100, + NULL, + NULL, + pcb_tool_rotate_notify_mode, + NULL, + NULL, + NULL, + NULL, + NULL, + + pcb_true +}; Index: tags/2.1.2/src/tool_rotate.h =================================================================== --- tags/2.1.2/src/tool_rotate.h (nonexistent) +++ tags/2.1.2/src/tool_rotate.h (revision 24813) @@ -0,0 +1,3 @@ +extern pcb_tool_t pcb_tool_rotate; + +void pcb_tool_rotate_notify_mode(void); Index: tags/2.1.2/src/tool_text.c =================================================================== --- tags/2.1.2/src/tool_text.c (nonexistent) +++ tags/2.1.2/src/tool_text.c (revision 24813) @@ -0,0 +1,107 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 1994,1995,1996 Thomas Nau + * Copyright (C) 1997, 1998, 1999, 2000, 2001 Harry Eaton + * Copyright (C) 2017 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + * + * Old contact info: + * Harry Eaton, 6697 Buttonhole Ct, Columbia, MD 21044, USA + * haceaton@aplcomm.jhuapl.edu + * + */ + +#include "config.h" +#include "conf_core.h" + +#include "board.h" +#include "data.h" +#include "draw.h" +#include "actions.h" +#include "tool.h" +#include "undo.h" + +#include "obj_text_draw.h" + + +void pcb_tool_text_notify_mode(void) +{ + char *string; + + if ((string = pcb_hid_prompt_for("Enter text:", "", "text")) != NULL) { + if (strlen(string) > 0) { + pcb_text_t *text; + int flag = PCB_FLAG_CLEARLINE; + + if (pcb_layer_flags(PCB, INDEXOFCURRENT) & PCB_LYT_BOTTOM) + flag |= PCB_FLAG_ONSOLDER; + if ((text = pcb_text_new(pcb_loose_subc_layer(PCB, CURRENT, pcb_true), pcb_font(PCB, conf_core.design.text_font_id, 1), pcb_tool_note.X, + pcb_tool_note.Y, 0, conf_core.design.text_scale, conf_core.design.text_thickness, string, pcb_flag_make(flag))) != NULL) { + pcb_undo_add_obj_to_create(PCB_OBJ_TEXT, CURRENT, text, text); + pcb_undo_inc_serial(); + pcb_text_invalidate_draw(CURRENT, text); + pcb_subc_as_board_update(PCB); + pcb_draw(); + } + } + free(string); + } +} + +void pcb_tool_text_draw_attached(void) +{ + pcb_text_t text; + int flag = PCB_FLAG_CLEARLINE; + + if (pcb_layer_flags(PCB, INDEXOFCURRENT) & PCB_LYT_BOTTOM) + flag |= PCB_FLAG_ONSOLDER; + + text.X = pcb_crosshair.X; + text.Y = pcb_crosshair.Y; + text.rot = 0; + text.Flags = pcb_flag_make(flag); + text.Scale = conf_core.design.text_scale; + text.thickness = conf_core.design.text_thickness; + text.TextString = "A"; + text.fid = conf_core.design.text_font_id; + text.ID = 0; + text.BoundingBox.X1 = text.BoundingBox.Y1 = text.BoundingBox.X2 = text.BoundingBox.Y2 = 0; + pcb_text_draw_xor(&text,0,0); + +} + +pcb_tool_t pcb_tool_text = { + "text", NULL, 100, + NULL, + NULL, + pcb_tool_text_notify_mode, + NULL, + NULL, + pcb_tool_text_draw_attached, + NULL, + NULL, + + pcb_false +}; + Index: tags/2.1.2/src/tool_text.h =================================================================== --- tags/2.1.2/src/tool_text.h (nonexistent) +++ tags/2.1.2/src/tool_text.h (revision 24813) @@ -0,0 +1,3 @@ +extern pcb_tool_t pcb_tool_text; + +void pcb_tool_text_notify_mode(void); Index: tags/2.1.2/src/tool_thermal.c =================================================================== --- tags/2.1.2/src/tool_thermal.c (nonexistent) +++ tags/2.1.2/src/tool_thermal.c (revision 24813) @@ -0,0 +1,116 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 1994,1995,1996 Thomas Nau + * Copyright (C) 1997, 1998, 1999, 2000, 2001 Harry Eaton + * Copyright (C) 2017 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + * + * Old contact info: + * Harry Eaton, 6697 Buttonhole Ct, Columbia, MD 21044, USA + * haceaton@aplcomm.jhuapl.edu + * + */ + +#include "config.h" + +#include "board.h" +#include "change.h" +#include "data.h" +#include "actions.h" +#include "obj_pstk.h" +#include "search.h" +#include "thermal.h" +#include "tool.h" + +void pcb_tool_thermal_on_pstk(pcb_pstk_t *ps, unsigned long lid) +{ + unsigned char *th, newth = 0; + unsigned char cycle[] = { + PCB_THERMAL_ON | PCB_THERMAL_ROUND | PCB_THERMAL_DIAGONAL, /* default start shape */ + PCB_THERMAL_ON | PCB_THERMAL_ROUND, + PCB_THERMAL_ON | PCB_THERMAL_SHARP | PCB_THERMAL_DIAGONAL, + PCB_THERMAL_ON | PCB_THERMAL_SHARP, + PCB_THERMAL_ON | PCB_THERMAL_SOLID, + PCB_THERMAL_ON | PCB_THERMAL_NOSHAPE + }; + int cycles = sizeof(cycle) / sizeof(cycle[0]); + + th = pcb_pstk_get_thermal(ps, lid, 1); + if (pcb_gui->shift_is_pressed()) { + int n, curr = -1; + /* cycle through the variants to find the current one */ + for(n = 0; n < cycles; n++) { + if (*th == cycle[n]) { + curr = n; + break; + } + } + + /* bump current pattern to the next or set it up */ + if (curr >= 0) { + curr++; + if (curr >= cycles) + curr = 0; + } + else + curr = 0; + + newth = cycle[curr]; + } + else { + if ((th != NULL) && (*th != 0)) + newth = *th ^ PCB_THERMAL_ON; /* existing thermal, toggle */ + else + newth = cycle[0]; /* new thermal, use default */ + } + + pcb_chg_obj_thermal(PCB_OBJ_PSTK, ps, ps, ps, newth, lid); +} + + +void pcb_tool_thermal_notify_mode(void) +{ + void *ptr1, *ptr2, *ptr3; + int type; + + if (((type = pcb_search_screen(pcb_tool_note.X, pcb_tool_note.Y, PCB_OBJ_CLASS_PIN, &ptr1, &ptr2, &ptr3)) != PCB_OBJ_VOID) + && !PCB_FLAG_TEST(PCB_FLAG_HOLE, (pcb_any_obj_t *) ptr3)) { + if (type == PCB_OBJ_PSTK) + pcb_tool_thermal_on_pstk((pcb_pstk_t *)ptr2, INDEXOFCURRENT); + } +} + +pcb_tool_t pcb_tool_thermal = { + "thermal", NULL, 100, + NULL, + NULL, + pcb_tool_thermal_notify_mode, + NULL, + NULL, + NULL, + NULL, + NULL, + + pcb_false +}; Index: tags/2.1.2/src/tool_thermal.h =================================================================== --- tags/2.1.2/src/tool_thermal.h (nonexistent) +++ tags/2.1.2/src/tool_thermal.h (revision 24813) @@ -0,0 +1,6 @@ +extern pcb_tool_t pcb_tool_thermal; + +void pcb_tool_thermal_notify_mode(void); + +/* direct call: cycle through thermal modes on a padstack - provided for tool_via.h */ +void pcb_tool_thermal_on_pstk(pcb_pstk_t *ps, unsigned long lid); Index: tags/2.1.2/src/tool_via.c =================================================================== --- tags/2.1.2/src/tool_via.c (nonexistent) +++ tags/2.1.2/src/tool_via.c (revision 24813) @@ -0,0 +1,116 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 1994,1995,1996 Thomas Nau + * Copyright (C) 1997, 1998, 1999, 2000, 2001 Harry Eaton + * Copyright (C) 2017 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + * + * Old contact info: + * Harry Eaton, 6697 Buttonhole Ct, Columbia, MD 21044, USA + * haceaton@aplcomm.jhuapl.edu + * + */ + +#include "config.h" +#include "conf_core.h" + +#include "board.h" +#include "change.h" +#include "hid_inlines.h" +#include "data.h" +#include "draw.h" +#include "tool.h" +#include "tool_thermal.h" +#include "undo.h" + +#include "obj_pstk_draw.h" + +TODO("padstack: remove this when via is removed and the padstack is created from style directly") +#include "src_plugins/lib_compat_help/pstk_compat.h" + +void pcb_tool_via_notify_mode(void) +{ + + if (!PCB->pstk_on) { + pcb_message(PCB_MSG_WARNING, "You must turn via visibility on before\nyou can place vias\n"); + return; + } + + if (conf_core.design.via_drilling_hole >= conf_core.design.via_thickness) { + pcb_message(PCB_MSG_ERROR, "Can't place via: invalid via geometry (hole too large for via size)\n"); + return; + } + +TODO("pstk #21: do not work in comp mode, use a pstk proto - scconfig also has TODO #21, fix it there too") + { + pcb_pstk_t *ps = pcb_pstk_new_compat_via(PCB->Data, -1, pcb_tool_note.X, pcb_tool_note.Y, + conf_core.design.via_drilling_hole, conf_core.design.via_thickness, conf_core.design.clearance, + 0, PCB_PSTK_COMPAT_ROUND, pcb_true); + if (ps == NULL) + return; + + pcb_obj_add_attribs(ps, PCB->pen_attr); + pcb_undo_add_obj_to_create(PCB_OBJ_PSTK, ps, ps, ps); + + if (pcb_gui->shift_is_pressed()) + pcb_tool_thermal_on_pstk(ps, INDEXOFCURRENT); + + pcb_undo_inc_serial(); + pcb_pstk_invalidate_draw(ps); + pcb_draw(); + } +} + +static void xor_draw_fake_via(pcb_coord_t x, pcb_coord_t y, pcb_coord_t dia, pcb_coord_t clearance) +{ + pcb_coord_t r = (dia/2)+clearance; + pcb_gui->draw_arc(pcb_crosshair.GC, x, y, r, r, 0, 360); +} + + +void pcb_tool_via_draw_attached(void) +{ +TODO("pstk: replace this when route style has a prototype") + xor_draw_fake_via(pcb_crosshair.X, pcb_crosshair.Y, conf_core.design.via_thickness, 0); + if (conf_core.editor.show_drc) { + /* XXX: Naughty cheat - use the mask to draw DRC clearance! */ + pcb_gui->set_color(pcb_crosshair.GC, &conf_core.appearance.color.cross); + xor_draw_fake_via(pcb_crosshair.X, pcb_crosshair.Y, conf_core.design.via_thickness, conf_core.design.clearance); + pcb_gui->set_color(pcb_crosshair.GC, &conf_core.appearance.color.crosshair); + } +} + +pcb_tool_t pcb_tool_via = { + "via", NULL, 100, + NULL, + NULL, + pcb_tool_via_notify_mode, + NULL, + NULL, + pcb_tool_via_draw_attached, + NULL, + NULL, + + pcb_false +}; Index: tags/2.1.2/src/tool_via.h =================================================================== --- tags/2.1.2/src/tool_via.h (nonexistent) +++ tags/2.1.2/src/tool_via.h (revision 24813) @@ -0,0 +1,4 @@ +extern pcb_tool_t pcb_tool_via; + +void pcb_tool_via_notify_mode(void); +void pcb_tool_via_draw_attached(void); Index: tags/2.1.2/src/undo.c =================================================================== --- tags/2.1.2/src/undo.c (nonexistent) +++ tags/2.1.2/src/undo.c (revision 24813) @@ -0,0 +1,310 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +/* functions used to undo operations + * + * Description: + * There are two lists which hold + * - the uundo list (information about a command) + * - data of removed objects + * Both lists are organized as first-in-last-out which means that the undo + * list can always use the last entry of the remove list. + * A serial number is incremented whenever an operation is completed. + * An operation itself may consist of several basic instructions. + * E.g.: removing all selected objects is one operation with exactly one + * serial number even if the remove function is called several times. + * + * a lock flag ensures that no infinite loops occur + */ + +#include "config.h" + +#include +#include + +#include "board.h" +#include "change.h" +#include "data.h" +#include "draw.h" +#include "error.h" +#include "event.h" +#include "insert.h" +#include "polygon.h" +#include "remove.h" +#include "rotate.h" +#include "search.h" +#include "undo.h" +#include "undo_old.h" +#include "flag_str.h" +#include "conf_core.h" +#include "compat_misc.h" + +#include "obj_poly_draw.h" + +static pcb_bool between_increment_and_restore = pcb_false; +static pcb_bool added_undo_between_increment_and_restore = pcb_false; + +pcb_data_t *pcb_removelist = NULL; /* lists of removed objects */ +static pcb_bool Locked = pcb_false; /* do not add entries if */ +pcb_bool pcb_undo_and_draw = pcb_true; /* flag is set; prevents from infinite loops */ +uundo_list_t pcb_uundo; /* only the undo dialog box should have access to it */ + +void *pcb_undo_alloc(pcb_board_t *pcb, const uundo_oper_t *oper, size_t data_len) +{ + return uundo_append(&pcb_uundo, oper, data_len); +} + +int pcb_undo(pcb_bool draw) +{ + int res; + + pcb_undo_and_draw = draw; + + if (pcb_uundo.num_undo == 0) { + pcb_message(PCB_MSG_INFO, "Nothing to undo - buffer is empty\n"); + return -1; + } + + if (pcb_uundo.serial == 0) { + pcb_message(PCB_MSG_ERROR, "ERROR: Attempt to pcb_undo() with Serial == 0\n Please save your work and report this bug.\n"); + return -1; + } + + if ((pcb_uundo.tail != NULL) && (pcb_uundo.tail->serial > pcb_uundo.serial)) { + pcb_message(PCB_MSG_ERROR, "ERROR: Bad undo serial number %d in undo stack - expecting %d or lower\n" + " Please save your work and report this bug.\n", pcb_uundo.tail->serial, pcb_uundo.serial); + + /* It is likely that the serial number got corrupted through some bad + * use of the pcb_undo_save_serial() / pcb_undo_restore_serial() APIs. + * + * Reset the serial number to be consistent with that of the last + * operation on the undo stack in the hope that this might clear + * the problem and allow the user to hit Undo again. + */ + pcb_uundo.serial = pcb_uundo.tail->serial + 1; + return -1; + } + + pcb_undo_lock(); /* lock undo module to prevent from loops */ + res = uundo_undo(&pcb_uundo); + pcb_undo_unlock(); + + if (res != 0) + pcb_message(PCB_MSG_ERROR, "ERROR: Failed to undo some operations\n"); + else if (pcb_undo_and_draw) + pcb_draw(); + + pcb_event(PCB_EVENT_UNDO_POST, "i", PCB_UNDO_EV_UNDO); + + return res; +} + +int pcb_undo_above(uundo_serial_t s_min) +{ + return uundo_undo_above(&pcb_uundo, s_min); +} + +int pcb_redo(pcb_bool draw) +{ + int res; + + pcb_undo_and_draw = draw; + + if (pcb_uundo.num_redo == 0) { + pcb_message(PCB_MSG_INFO, "Nothing to redo. Perhaps changes have been made since last undo\n"); + return 0; + } + + if ((pcb_uundo.tail != NULL) && (pcb_uundo.tail->next != NULL) && (pcb_uundo.tail->next->serial > pcb_uundo.serial)) { + + pcb_message(PCB_MSG_ERROR, "ERROR: Bad undo serial number %d in redo stack - expecting %d or higher\n" + " Please save your work and report this bug.\n", pcb_uundo.tail->next->serial, pcb_uundo.serial); + + /* It is likely that the serial number got corrupted through some bad + * use of the pcb_undo_save_serial() / pcb_undo_restore_serial() APIs. + * + * Reset the serial number to be consistent with that of the first + * operation on the redo stack in the hope that this might clear + * the problem and allow the user to hit Redo again. + */ + + pcb_uundo.serial = pcb_uundo.tail->next->serial; + return 0; + } + + pcb_undo_lock(); /* lock undo module to prevent from loops */ + uundo_freeze_add(&pcb_uundo); + res = uundo_redo(&pcb_uundo); + uundo_unfreeze_add(&pcb_uundo); + pcb_undo_unlock(); + + if (res != 0) + pcb_message(PCB_MSG_ERROR, "ERROR: Failed to redo some operations\n"); + else if (pcb_undo_and_draw) + pcb_draw(); + + pcb_event(PCB_EVENT_UNDO_POST, "i", PCB_UNDO_EV_REDO); + + return res; +} + +/* --------------------------------------------------------------------------- + * restores the serial number of the undo list + */ +void pcb_undo_restore_serial(void) +{ + if (added_undo_between_increment_and_restore) + pcb_message(PCB_MSG_ERROR, "ERROR: Operations were added to the Undo stack with an incorrect serial number\n"); + between_increment_and_restore = pcb_false; + added_undo_between_increment_and_restore = pcb_false; + uundo_restore_serial(&pcb_uundo); +} + +/* --------------------------------------------------------------------------- + * saves the serial number of the undo list + */ +void pcb_undo_save_serial(void) +{ + pcb_bumped = pcb_false; + between_increment_and_restore = pcb_false; + added_undo_between_increment_and_restore = pcb_false; + uundo_save_serial(&pcb_uundo); +} + +/* --------------------------------------------------------------------------- + * increments the serial number of the undo list + * it's not done automatically because some operations perform more + * than one request with the same serial # + */ +void pcb_undo_inc_serial(void) +{ + if (!Locked) { + /* Set the changed flag if anything was added prior to this bump */ + if ((pcb_uundo.tail != NULL) && (pcb_uundo.tail->serial == pcb_uundo.serial)) + pcb_board_set_changed_flag(pcb_true); + + uundo_inc_serial(&pcb_uundo); + pcb_bumped = pcb_true; + between_increment_and_restore = pcb_true; + } +} + +/* --------------------------------------------------------------------------- + * releases memory of the undo- and remove list + */ +void pcb_undo_clear_list(pcb_bool Force) +{ + if (pcb_uundo.num_undo && (Force || pcb_hid_message_box("warning", "clear undo buffer", "Do you reall want to clear 'undo' buffer?", "yes", 1, "no", 0, NULL) == 1)) { + uundo_list_clear(&pcb_uundo); + pcb_event(PCB_EVENT_UNDO_POST, "i", PCB_UNDO_EV_CLEAR_LIST); + } +} + +/* --------------------------------------------------------------------------- + * set lock flag + */ +void pcb_undo_lock(void) +{ + Locked = pcb_true; +} + +/* --------------------------------------------------------------------------- + * reset lock flag + */ +void pcb_undo_unlock(void) +{ + Locked = pcb_false; +} + +/* --------------------------------------------------------------------------- + * return undo lock state + */ +pcb_bool pcb_undoing(void) +{ + return Locked; +} + +uundo_serial_t pcb_undo_serial(void) +{ + return pcb_uundo.serial; +} + + +void pcb_undo_truncate_from(uundo_serial_t sfirst) +{ + uundo_list_truncate_from(&pcb_uundo, sfirst); + pcb_event(PCB_EVENT_UNDO_POST, "i", PCB_UNDO_EV_TRUNCATE); +} + +int undo_check(void) +{ + const char *res = uundo_check(&pcb_uundo, NULL); + +#ifndef NDEBUG + if (res != NULL) { + printf("Undo broken: %s\n", res); + uundo_dump(&pcb_uundo, NULL, NULL); + } +#endif + + return (res != NULL); +} + +#ifndef NDEBUG +void undo_dump(void) +{ + uundo_dump(&pcb_uundo, NULL, NULL); +} +#endif + +size_t pcb_num_undo(void) +{ + return pcb_uundo.num_undo; +} + +void pcb_undo_freeze_serial(void) +{ + uundo_freeze_serial(&pcb_uundo); +} + +void pcb_undo_unfreeze_serial(void) +{ + uundo_unfreeze_serial(&pcb_uundo); +} + + +void pcb_undo_freeze_add(void) +{ + uundo_freeze_add(&pcb_uundo); +} + +void pcb_undo_unfreeze_add(void) +{ + uundo_unfreeze_add(&pcb_uundo); +} + Index: tags/2.1.2/src/undo.h =================================================================== --- tags/2.1.2/src/undo.h (nonexistent) +++ tags/2.1.2/src/undo.h (revision 24813) @@ -0,0 +1,80 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +#ifndef PCB_UNDO_H +#define PCB_UNDO_H + +#include +#include + +/* Temporary for compatibility */ +#include "undo_old.h" + +typedef enum pcb_undo_ev_e { + PCB_UNDO_EV_UNDO, + PCB_UNDO_EV_REDO, + PCB_UNDO_EV_CLEAR_LIST, + PCB_UNDO_EV_TRUNCATE +} pcb_undo_ev_t; + +void *pcb_undo_alloc(pcb_board_t *pcb, const uundo_oper_t *oper, size_t data_len); +int pcb_undo(pcb_bool); +int pcb_redo(pcb_bool); +int pcb_undo_above(uundo_serial_t s_min); + +void pcb_undo_inc_serial(void); +void pcb_undo_save_serial(void); +void pcb_undo_restore_serial(void); +void pcb_undo_clear_list(pcb_bool); + +void pcb_undo_lock(void); +void pcb_undo_unlock(void); +pcb_bool pcb_undoing(void); + +uundo_serial_t pcb_undo_serial(void); +void pcb_undo_truncate_from(uundo_serial_t sfirst); + +void pcb_undo_freeze_serial(void); +void pcb_undo_unfreeze_serial(void); +void pcb_undo_freeze_add(void); +void pcb_undo_unfreeze_add(void); + +/* Return the number of undo slots in use */ +size_t pcb_num_undo(void); + +/* Returns 0 if undo integrity is not broken */ +int undo_check(void); + +void undo_dump(void); + +/* temporary */ +#include "pcb_bool.h" +extern pcb_data_t *pcb_removelist; +extern pcb_bool pcb_undo_and_draw; + +#endif Index: tags/2.1.2/src/undo_act.c =================================================================== --- tags/2.1.2/src/undo_act.c (nonexistent) +++ tags/2.1.2/src/undo_act.c (revision 24813) @@ -0,0 +1,140 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * Copyright (C) 1997, 1998, 1999, 2000, 2001 Harry Eaton + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + * + * Old contact info: + * Harry Eaton, 6697 Buttonhole Ct, Columbia, MD 21044, USA + * haceaton@aplcomm.jhuapl.edu + * + */ +#include "config.h" +#include "conf_core.h" + +#include "board.h" +#include "actions.h" +#include "data.h" +#include "compat_misc.h" +#include "error.h" +#include "funchash_core.h" + +#include "undo.h" +#include "undo_act.h" +#include "polygon.h" +#include "search.h" + +#include "obj_line_draw.h" + +#include "tool.h" + +static const char pcb_acts_Atomic[] = "Atomic(Save|Restore|Close|Block)"; +static const char pcb_acth_Atomic[] = "Save or restore the undo serial number."; +/* DOC: atomic.html */ +fgw_error_t pcb_act_Atomic(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + int op; + PCB_ACT_CONVARG(1, FGW_KEYWORD, Atomic, op = fgw_keyword(&argv[1])); + + switch (op) { + case F_Save: + pcb_undo_save_serial(); + break; + case F_Restore: + pcb_undo_restore_serial(); + break; + case F_Close: + pcb_undo_restore_serial(); + pcb_undo_inc_serial(); + break; + case F_Block: + pcb_undo_restore_serial(); + if (pcb_bumped) + pcb_undo_inc_serial(); + break; + default: + pcb_message(PCB_MSG_ERROR, "Invalid argument for Atomic()\n"); + PCB_ACT_IRES(-1); + return 0; + } + PCB_ACT_IRES(0); + return 0; +} + +/* --------------------------------------------------------------------------- */ + +static const char pcb_acts_Undo[] = "undo()\n" "undo(ClearList)"; + +static const char pcb_acth_Undo[] = "Undo recent changes."; + +/* DOC: undo.html */ + +fgw_error_t pcb_act_Undo(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + const char *function = NULL; + PCB_ACT_MAY_CONVARG(1, FGW_STR, Undo, function = argv[1].val.str); + if (!function || !*function) { + pcb_notify_crosshair_change(pcb_false); + if (pcb_tool_undo_act()) + if (pcb_undo(pcb_true) == 0) + pcb_board_set_changed_flag(pcb_true); + } + else if (function) { + pcb_notify_crosshair_change(pcb_false); + if (pcb_strcasecmp(function, "ClearList") == 0) + pcb_undo_clear_list(pcb_false); + } + pcb_notify_crosshair_change(pcb_true); + PCB_ACT_IRES(0); + return 0; +} + +/* --------------------------------------------------------------------------- */ + +static const char pcb_acts_Redo[] = "redo()"; + +static const char pcb_acth_Redo[] = "Redo recent \"undo\" operations."; + +/* DOC: redo.html */ + +fgw_error_t pcb_act_Redo(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + pcb_notify_crosshair_change(pcb_false); + if (pcb_tool_redo_act()) + if (pcb_redo(pcb_true)) + pcb_board_set_changed_flag(pcb_true); + pcb_notify_crosshair_change(pcb_true); + PCB_ACT_IRES(0); + return 0; +} + + +pcb_action_t undo_action_list[] = { + {"Atomic", pcb_act_Atomic, pcb_acth_Atomic, pcb_acts_Atomic}, + {"Undo", pcb_act_Undo, pcb_acth_Undo, pcb_acts_Undo}, + {"Redo", pcb_act_Redo, pcb_acth_Redo, pcb_acts_Redo} +}; + +PCB_REGISTER_ACTIONS(undo_action_list, NULL) Index: tags/2.1.2/src/undo_act.h =================================================================== --- tags/2.1.2/src/undo_act.h (nonexistent) +++ tags/2.1.2/src/undo_act.h (revision 24813) @@ -0,0 +1,4 @@ +/* Publish actions - these may be useful for other actions */ +fgw_error_t pcb_act_Undo(fgw_arg_t *res, int oargc, fgw_arg_t *oargv); +fgw_error_t pcb_act_Redo(fgw_arg_t *res, int oargc, fgw_arg_t *oargv); +fgw_error_t pcb_act_Atomic(fgw_arg_t *res, int oargc, fgw_arg_t *oargv); Index: tags/2.1.2/src/undo_old.c =================================================================== --- tags/2.1.2/src/undo_old.c (nonexistent) +++ tags/2.1.2/src/undo_old.c (revision 24813) @@ -0,0 +1,1308 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +/* functions used to undo operations + * + * Description: + * There are two lists which hold + * - information about a command + * - data of removed objects + * Both lists are organized as first-in-last-out which means that the undo + * list can always use the last entry of the remove list. + * A serial number is incremented whenever an operation is completed. + * An operation itself may consist of several basic instructions. + * E.g.: removing all selected objects is one operation with exactly one + * serial number even if the remove function is called several times. + * + * a lock flag ensures that no infinite loops occur + */ + +#include "config.h" + +#include +#include + +#include "board.h" +#include "change.h" +#include "data.h" +#include "draw.h" +#include "move.h" +#include "error.h" +#include "insert.h" +#include "polygon.h" +#include "remove.h" +#include "rotate.h" +#include "search.h" +#include "undo.h" +#include "undo_old.h" +#include "flag_str.h" +#include "conf_core.h" +#include "compat_misc.h" +#include "netlist2.h" + +#include "obj_poly_draw.h" +#include "obj_subc_parent.h" + +#include "brave.h" + +#define STEP_REMOVELIST 500 +#define STEP_UNDOLIST 500 + +#define Locked pcb_undoing() + +#include "undo_old_str.h" + +static pcb_bool UndoRotate90(UndoListTypePtr); +static pcb_bool UndoRotate(UndoListTypePtr); +static pcb_bool UndoChangeName(UndoListTypePtr); +static pcb_bool UndoCopyOrCreate(UndoListTypePtr); +static pcb_bool UndoMove(UndoListTypePtr); +static pcb_bool UndoRemove(UndoListTypePtr); +static pcb_bool UndoRemovePoint(UndoListTypePtr); +static pcb_bool UndoInsertPoint(UndoListTypePtr); +static pcb_bool UndoRemoveContour(UndoListTypePtr); +static pcb_bool UndoInsertContour(UndoListTypePtr); +static pcb_bool UndoMoveToLayer(UndoListTypePtr); +static pcb_bool UndoFlag(UndoListTypePtr); +static pcb_bool UndoOtherSide(UndoListTypePtr); +static pcb_bool UndoChangeSize(UndoListTypePtr); +static pcb_bool UndoChange2ndSize(UndoListTypePtr); +static pcb_bool UndoChangeAngles(UndoListTypePtr); +static pcb_bool UndoChangeRadii(UndoListTypePtr); +static pcb_bool UndoChangeClearSize(UndoListTypePtr); +static pcb_bool UndoClearPoly(UndoListTypePtr); + +#define PCB_OBJECT_ID(p) (((pcb_any_obj_t *) p)->ID) + +static void pcb_undo_old_free(void *udata); +static int pcb_undo_old_undo(void *udata); + +void pcb_undo_old_print(void *udata, char *dst, size_t dst_len) +{ + UndoListType *slot = udata; +#ifndef NDEBUG + const char *res = undo_type2str(slot->Type); + pcb_snprintf(dst, dst_len, "%s ser=%d id=%d", res, slot->Serial, slot->ID); +#else + sprintf(dst, "%d", slot->Type); +#endif + +} + +static const uundo_oper_t pcb_undo_old_oper = { + "core-old", + pcb_undo_old_free, + pcb_undo_old_undo, + pcb_undo_old_undo, /* redo is the same as undo */ + pcb_undo_old_print +}; + +static UndoListType *GetUndoSlot(int CommandType, long int ID, pcb_objtype_t Kind) +{ + UndoListType *slot = pcb_undo_alloc(PCB, &pcb_undo_old_oper, sizeof(UndoListType)); + + slot->Type = CommandType; + slot->ID = ID; + slot->Kind = Kind; + + return slot; +} + + +/* --------------------------------------------------------------------------- + * redraws the recovered object + */ +static void DrawRecoveredObject(pcb_any_obj_t *obj) +{ + pcb_draw_obj(obj); +} + +/* --------------------------------------------------------------------------- + * recovers an object from a 90 deg 'rotate' operation + * returns pcb_true if anything has been recovered + */ +static pcb_bool UndoRotate90(UndoListTypePtr Entry) +{ + void *ptr1, *ptr2, *ptr3; + int type; + + /* lookup entry by it's ID */ + type = pcb_search_obj_by_id(PCB->Data, &ptr1, &ptr2, &ptr3, Entry->ID, Entry->Kind); + if (type != PCB_OBJ_VOID) { + pcb_obj_rotate90(type, ptr1, ptr2, ptr3, + Entry->Data.Rotate.CenterX, Entry->Data.Rotate.CenterY, (4 - Entry->Data.Rotate.Steps) & 0x03); + Entry->Data.Rotate.Steps = (4 - Entry->Data.Rotate.Steps) & 0x03; + return pcb_true; + } + return pcb_false; +} + +/* --------------------------------------------------------------------------- + * recovers an object from an arbitrary angle 'rotate' operation + * returns pcb_true if anything has been recovered + */ +static pcb_bool UndoRotate(UndoListTypePtr Entry) +{ + void *ptr1, *ptr2, *ptr3; + int type; + + /* lookup entry by it's ID */ + type = pcb_search_obj_by_id(PCB->Data, &ptr1, &ptr2, &ptr3, Entry->ID, Entry->Kind); + if (type != PCB_OBJ_VOID) { + pcb_obj_rotate(type, ptr1, ptr2, ptr3, Entry->Data.Rotate.CenterX, Entry->Data.Rotate.CenterY, -(Entry->Data.Angle)); + Entry->Data.Angle = -(Entry->Data.Angle); + return pcb_true; + } + return pcb_false; +} + +/* --------------------------------------------------------------------------- + * recovers an object from a clear/restore poly operation + * returns pcb_true if anything has been recovered + */ +static pcb_bool UndoClearPoly(UndoListTypePtr Entry) +{ + void *ptr1, *ptr2, *ptr3; + int type; + + type = pcb_search_obj_by_id(PCB->Data, &ptr1, &ptr2, &ptr3, Entry->ID, Entry->Kind); + if (type != PCB_OBJ_VOID) { + if (Entry->Data.ClearPoly.Clear) + pcb_poly_restore_to_poly(PCB->Data, type, Entry->Data.ClearPoly.Layer, ptr3); + else + pcb_poly_clear_from_poly(PCB->Data, type, Entry->Data.ClearPoly.Layer, ptr3); + Entry->Data.ClearPoly.Clear = !Entry->Data.ClearPoly.Clear; + return pcb_true; + } + return pcb_false; +} + +/* --------------------------------------------------------------------------- + * recovers an object from a 'change name' operation + * returns pcb_true if anything has been recovered + */ +static pcb_bool UndoChangeName(UndoListTypePtr Entry) +{ + void *ptr1, *ptr2, *ptr3; + int type; + + /* lookup entry by it's ID */ + type = pcb_search_obj_by_id(PCB->Data, &ptr1, &ptr2, &ptr3, Entry->ID, Entry->Kind); + if (type != PCB_OBJ_VOID) { + Entry->Data.ChangeName.Name = (char *) (pcb_chg_obj_name(type, ptr1, ptr2, ptr3, Entry->Data.ChangeName.Name)); + return pcb_true; + } + return pcb_false; +} + +/* --------------------------------------------------------------------------- + * recovers an object from a ChangeAngles change operation + */ +static pcb_bool UndoChangeAngles(UndoListTypePtr Entry) +{ + void *ptr1, *ptr2, *ptr3; + int type; + double old_sa, old_da; + + /* lookup entry by ID */ + type = pcb_search_obj_by_id(PCB->Data, &ptr1, &ptr2, &ptr3, Entry->ID, Entry->Kind); + if (type == PCB_OBJ_ARC) { + pcb_layer_t *Layer = (pcb_layer_t *) ptr1; + pcb_arc_t *a = (pcb_arc_t *) ptr2; + pcb_r_delete_entry(Layer->arc_tree, (pcb_box_t *) a); + old_sa = a->StartAngle; + old_da = a->Delta; + if (pcb_undo_and_draw) + pcb_erase_obj(type, Layer, a); + a->StartAngle = Entry->Data.AngleChange.angle[0]; + a->Delta = Entry->Data.AngleChange.angle[1]; + pcb_arc_bbox(a); + pcb_r_insert_entry(Layer->arc_tree, (pcb_box_t *) a); + Entry->Data.AngleChange.angle[0] = old_sa; + Entry->Data.AngleChange.angle[1] = old_da; + pcb_draw_obj((pcb_any_obj_t *)a); + return pcb_true; + } + return pcb_false; +} + +/* --------------------------------------------------------------------------- + * recovers an object from a ChangeRadii change operation + */ +static pcb_bool UndoChangeRadii(UndoListTypePtr Entry) +{ + void *ptr1, *ptr2, *ptr3; + int type; + pcb_coord_t old_w, old_h; + + /* lookup entry by ID */ + type = pcb_search_obj_by_id(PCB->Data, &ptr1, &ptr2, &ptr3, Entry->ID, Entry->Kind); + if (type == PCB_OBJ_ARC) { + pcb_layer_t *Layer = (pcb_layer_t *) ptr1; + pcb_arc_t *a = (pcb_arc_t *) ptr2; + pcb_r_delete_entry(Layer->arc_tree, (pcb_box_t *) a); + old_w = a->Width; + old_h = a->Height; + if (pcb_undo_and_draw) + pcb_erase_obj(type, Layer, a); + a->Width = Entry->Data.Move.DX; + a->Height = Entry->Data.Move.DY; + pcb_arc_bbox(a); + pcb_r_insert_entry(Layer->arc_tree, (pcb_box_t *) a); + Entry->Data.Move.DX = old_w; + Entry->Data.Move.DY = old_h; + pcb_draw_obj((pcb_any_obj_t *)a); + return pcb_true; + } + return pcb_false; +} + +/* --------------------------------------------------------------------------- + * recovers an object from a clearance size change operation + */ +static pcb_bool UndoChangeClearSize(UndoListTypePtr Entry) +{ + void *ptr1, *ptr2, *ptr3; + int type; + pcb_coord_t swap; + + /* lookup entry by ID */ + type = pcb_search_obj_by_id(PCB->Data, &ptr1, &ptr2, &ptr3, Entry->ID, Entry->Kind); + if (type != PCB_OBJ_VOID) { + swap = ((pcb_line_t *) ptr2)->Clearance; + pcb_poly_restore_to_poly(PCB->Data, type, ptr1, ptr2); + if (pcb_undo_and_draw) + pcb_erase_obj(type, ptr1, ptr2); + ((pcb_line_t *) ptr2)->Clearance = Entry->Data.Size; + pcb_poly_clear_from_poly(PCB->Data, type, ptr1, ptr2); + Entry->Data.Size = swap; + if (pcb_undo_and_draw) + pcb_draw_obj((pcb_any_obj_t *)ptr2); + return pcb_true; + } + return pcb_false; +} + +/* --------------------------------------------------------------------------- + * recovers an object from a Size change operation + */ +static pcb_bool UndoChangeSize(UndoListTypePtr Entry) +{ + void *ptr1, *ptr2, *ptr3, *ptr1e; + int type; + pcb_coord_t swap; + + /* lookup entry by ID */ + type = pcb_search_obj_by_id(PCB->Data, &ptr1, &ptr2, &ptr3, Entry->ID, Entry->Kind); + ptr1e = ptr1; + + if (type != PCB_OBJ_VOID) { + /* Size change for lines and arcs can. Text has it's own mechanism */ + swap = ((pcb_line_t *) ptr2)->Thickness; + pcb_poly_restore_to_poly(PCB->Data, type, ptr1, ptr2); + if ((pcb_undo_and_draw) && (ptr1e != NULL)) + pcb_erase_obj(type, ptr1e, ptr2); + ((pcb_line_t *) ptr2)->Thickness = Entry->Data.Size; + Entry->Data.Size = swap; + pcb_poly_clear_from_poly(PCB->Data, type, ptr1, ptr2); + if (pcb_undo_and_draw) + pcb_draw_obj((pcb_any_obj_t *)ptr2); + return pcb_true; + } + return pcb_false; +} + +/* --------------------------------------------------------------------------- + * recovers an object from a 2nd Size change operation + */ +static pcb_bool UndoChange2ndSize(UndoListTypePtr Entry) +{ + void *ptr1, *ptr2, *ptr3; + int type; + pcb_coord_t swap; + + /* lookup entry by ID */ + type = pcb_search_obj_by_id(PCB->Data, &ptr1, &ptr2, &ptr3, Entry->ID, Entry->Kind); + + if (type == PCB_OBJ_TEXT) { /* thickness */ + swap = ((pcb_text_t *)ptr2)->thickness; + pcb_text_pre((pcb_text_t *)ptr2); + ((pcb_text_t *)ptr2)->thickness = Entry->Data.Size; + Entry->Data.Size = swap; + pcb_text_post((pcb_text_t *)ptr2); + return pcb_true; + } + return pcb_false; +} + +/* --------------------------------------------------------------------------- + * recovers an object from a Size change operation + */ +static pcb_bool UndoChangeRot(UndoListTypePtr Entry) +{ + void *ptr1, *ptr2, *ptr3, *ptr1e; + int type; + double swap; + pcb_bool ret = pcb_false; + + /* lookup entry by ID */ + type = pcb_search_obj_by_id(PCB->Data, &ptr1, &ptr2, &ptr3, Entry->ID, Entry->Kind); + ptr1e = ptr1; + + + if (pcb_undo_and_draw) + pcb_draw_obj((pcb_any_obj_t *)ptr2); + + switch(type) { + case PCB_OBJ_PSTK: + swap = ((pcb_pstk_t *)ptr2)->rot; + pcb_pstk_pre(((pcb_pstk_t *)ptr2)); + ((pcb_pstk_t *)ptr2)->rot = Entry->Data.Size; + Entry->Data.Size = swap; + pcb_pstk_post(((pcb_pstk_t *)ptr2)); + ret = pcb_true; + break; + + case PCB_OBJ_TEXT: + swap = ((pcb_text_t *)ptr2)->rot; + pcb_text_pre(((pcb_text_t *)ptr2)); + ((pcb_text_t *)ptr2)->rot = Entry->Data.Size; + Entry->Data.Size = swap; + pcb_text_post(((pcb_text_t *)ptr2)); + ret = pcb_true; + break; + } + + if (pcb_undo_and_draw) + pcb_draw_obj((pcb_any_obj_t *)ptr2); + return ret; +} + +/* --------------------------------------------------------------------------- + * recovers an object from a FLAG change operation + */ +static pcb_bool UndoFlag(UndoListTypePtr Entry) +{ + void *ptr1, *ptr1e, *ptr2, *ptr3, *txt_save; + int type; + pcb_flag_t swap; + int must_redraw; + unsigned long oldflg; + + /* lookup entry by ID */ + type = pcb_search_obj_by_id(PCB->Data, &ptr1, &ptr2, &ptr3, Entry->ID, Entry->Kind); + if (type != PCB_OBJ_VOID) { + pcb_flag_t f1, f2; + pcb_any_obj_t *obj = (pcb_any_obj_t *)ptr2; + + ptr1e = ptr1; + swap = obj->Flags; + + must_redraw = 0; + f1 = pcb_flag_mask(obj->Flags, ~DRAW_FLAGS); + f2 = pcb_flag_mask(Entry->Data.Flags, ~DRAW_FLAGS); + + if (!PCB_FLAG_EQ(f1, f2)) + must_redraw = 1; + + if (pcb_undo_and_draw && must_redraw && (ptr1e != NULL)) + pcb_erase_obj(type, ptr1e, ptr2); + + if (obj->type == PCB_OBJ_TEXT) { + oldflg = obj->Flags.f; + pcb_text_flagchg_pre((pcb_text_t *)obj, Entry->Data.Flags.f, &txt_save); + } + + obj->Flags = Entry->Data.Flags; + Entry->Data.Flags = swap; + + if (obj->type == PCB_OBJ_TEXT) + pcb_text_flagchg_post((pcb_text_t *)obj, oldflg, &txt_save); + + if (pcb_undo_and_draw && must_redraw) + pcb_draw_obj((pcb_any_obj_t *)ptr2); + return pcb_true; + } + pcb_message(PCB_MSG_ERROR, "hace Internal error: Can't find ID %d type %08x\n", Entry->ID, Entry->Kind); + pcb_message(PCB_MSG_ERROR, "for UndoFlag Operation. Previous flags: %s\n", pcb_strflg_f2s(Entry->Data.Flags, 0, NULL, 0)); + return pcb_false; +} + +/* --------------------------------------------------------------------------- + * recovers a subc from an other-side operation + * returns pcb_true if anything has been recovered + */ +static pcb_bool UndoOtherSide(UndoListTypePtr Entry) +{ + void *ptr1, *ptr2, *ptr3; + int type; + + /* lookup entry by ID */ + type = pcb_search_obj_by_id(PCB->Data, &ptr1, &ptr2, &ptr3, Entry->ID, Entry->Kind); + if (type == PCB_OBJ_SUBC) { + pcb_subc_t *subc = (pcb_subc_t *)ptr3; + if (pcb_undo_and_draw) + EraseSubc(subc); + pcb_subc_change_side(subc, Entry->Data.Move.DY); + if (pcb_undo_and_draw) + DrawSubc(subc); + return pcb_true; + } + pcb_message(PCB_MSG_ERROR, "hace Internal error: UndoOtherside on object type %x\n", type); + return pcb_false; +} + +/* --------------------------------------------------------------------------- + * recovers an object from a 'copy' or 'create' operation + * returns pcb_true if anything has been recovered + */ +static pcb_bool UndoCopyOrCreate(UndoListTypePtr Entry) +{ + void *ptr1, *ptr2, *ptr3; + int type; + + /* lookup entry by it's ID */ + type = pcb_search_obj_by_id(PCB->Data, &ptr1, &ptr2, &ptr3, Entry->ID, Entry->Kind); + if (type != PCB_OBJ_VOID) { + Removed *r = &Entry->Data.Removed; + if (!pcb_removelist) + pcb_removelist = pcb_buffer_new(NULL); + if (pcb_undo_and_draw) + pcb_erase_obj(type, ptr1, ptr2); + /* in order to make this re-doable we move it to the pcb_removelist */ + pcb_move_obj_to_buffer(PCB, pcb_removelist, PCB->Data, type, ptr1, ptr2, ptr3); + Entry->Type = PCB_UNDO_REMOVE; + r->p_subc_id = 0; + return pcb_true; + } + return pcb_false; +} + +/* --------------------------------------------------------------------------- + * recovers an object from a 'move' operation + * returns pcb_true if anything has been recovered + */ +static pcb_bool UndoMove(UndoListTypePtr Entry) +{ + void *ptr1, *ptr2, *ptr3; + int type; + + /* lookup entry by it's ID */ + type = pcb_search_obj_by_id(PCB->Data, &ptr1, &ptr2, &ptr3, Entry->ID, Entry->Kind); + if (type != PCB_OBJ_VOID) { + pcb_move_obj(type, ptr1, ptr2, ptr3, -Entry->Data.Move.DX, -Entry->Data.Move.DY); + Entry->Data.Move.DX *= -1; + Entry->Data.Move.DY *= -1; + return pcb_true; + } + return pcb_false; +} + +/* ---------------------------------------------------------------------- + * recovers an object from a 'remove' operation + * returns pcb_true if anything has been recovered + */ +static pcb_bool UndoRemove(UndoListTypePtr Entry) +{ + void *ptr1, *ptr2, *ptr3; + int type; + Removed *r = &Entry->Data.Removed; + pcb_data_t *data = PCB->Data; + + if (pcb_brave & PCB_BRAVE_CLIPBATCH) + pcb_data_clip_inhibit_inc(PCB->Data); + + /* lookup entry by it's ID */ + type = pcb_search_obj_by_id(pcb_removelist, &ptr1, &ptr2, &ptr3, Entry->ID, Entry->Kind); + if (type != PCB_OBJ_VOID) { + if (r->p_subc_id > 0) { /* need to use a subc layer - putting back a floater */ + void *p1, *p2, *p3; + if (pcb_search_obj_by_id(PCB->Data, &p1, &p2, &p3, r->p_subc_id, PCB_OBJ_SUBC) != 0) { + pcb_subc_t *subc = p2; + if (r->p_subc_layer < subc->data->LayerN) { + data = subc->data; + ptr1 = &data->Layer[r->p_subc_layer]; + } + } + } + pcb_move_obj_to_buffer(PCB, data, pcb_removelist, type, ptr1, ptr2, ptr3); + if (pcb_undo_and_draw) + DrawRecoveredObject((pcb_any_obj_t *)ptr2); + Entry->Type = PCB_UNDO_CREATE; + + if (pcb_brave & PCB_BRAVE_CLIPBATCH) + pcb_data_clip_inhibit_dec(PCB->Data, 1); + + return pcb_true; + } + + if (pcb_brave & PCB_BRAVE_CLIPBATCH) + pcb_data_clip_inhibit_dec(PCB->Data, 1); + + return pcb_false; +} + +/* ---------------------------------------------------------------------- + * recovers an object from a 'move to another layer' operation + * returns pcb_true if anything has been recovered + */ +static pcb_bool UndoMoveToLayer(UndoListTypePtr Entry) +{ + void *ptr1, *ptr2, *ptr3; + int type; + pcb_layer_id_t swap; + + /* lookup entry by it's ID */ + type = pcb_search_obj_by_id(PCB->Data, &ptr1, &ptr2, &ptr3, Entry->ID, Entry->Kind); + if (type != PCB_OBJ_VOID) { + swap = pcb_layer_id(PCB->Data, (pcb_layer_t *) ptr1); + pcb_move_obj_to_layer(type, ptr1, ptr2, ptr3, LAYER_PTR(Entry->Data.MoveToLayer.OriginalLayer), pcb_true); + Entry->Data.MoveToLayer.OriginalLayer = swap; + return pcb_true; + } + return pcb_false; +} + +/* --------------------------------------------------------------------------- + * recovers a removed polygon point + * returns pcb_true on success + */ +static pcb_bool UndoRemovePoint(UndoListTypePtr Entry) +{ + pcb_layer_t *layer; + pcb_poly_t *polygon; + void *ptr3; + int type; + + /* lookup entry (polygon not point was saved) by it's ID */ + assert(Entry->Kind == PCB_OBJ_POLY); + type = pcb_search_obj_by_id(PCB->Data, (void **) &layer, (void **) &polygon, &ptr3, Entry->ID, Entry->Kind); + switch (type) { + case PCB_OBJ_POLY: /* restore the removed point */ + { + /* recover the point */ + if (pcb_undo_and_draw && layer->meta.real.vis) + pcb_poly_invalidate_erase(polygon); + pcb_insert_point_in_object(PCB_OBJ_POLY, layer, polygon, + &Entry->Data.RemovedPoint.Index, + Entry->Data.RemovedPoint.X, + Entry->Data.RemovedPoint.Y, pcb_true, Entry->Data.RemovedPoint.last_in_contour); + + polygon->Points[Entry->Data.RemovedPoint.Index].ID = Entry->Data.RemovedPoint.ID; + if (pcb_undo_and_draw && layer->meta.real.vis) + pcb_poly_invalidate_draw(layer, polygon); + Entry->Type = PCB_UNDO_INSERT_POINT; + Entry->ID = Entry->Data.RemovedPoint.ID; + Entry->Kind = PCB_OBJ_POLY_POINT; + return pcb_true; + } + + default: + return pcb_false; + } +} + +/* --------------------------------------------------------------------------- + * recovers an inserted polygon point + * returns pcb_true on success + */ +static pcb_bool UndoInsertPoint(UndoListTypePtr Entry) +{ + pcb_layer_t *layer; + pcb_poly_t *polygon; + pcb_point_t *pnt; + int type; + pcb_cardinal_t point_idx; + pcb_cardinal_t hole; + pcb_bool last_in_contour = pcb_false; + + assert((long int)Entry->Kind == PCB_OBJ_POLY_POINT); + /* lookup entry by it's ID */ + type = pcb_search_obj_by_id(PCB->Data, (void **) &layer, (void **) &polygon, (void **) &pnt, Entry->ID, Entry->Kind); + switch (type) { + case PCB_OBJ_POLY_POINT: /* removes an inserted polygon point */ + { + if (pcb_undo_and_draw && layer->meta.real.vis) + pcb_poly_invalidate_erase(polygon); + + /* Check whether this point was at the end of its contour. + * If so, we need to flag as such when re-adding the point + * so it goes back in the correct place + */ + point_idx = pcb_poly_point_idx(polygon, pnt); + for (hole = 0; hole < polygon->HoleIndexN; hole++) + if (point_idx == polygon->HoleIndex[hole] - 1) + last_in_contour = pcb_true; + if (point_idx == polygon->PointN - 1) + last_in_contour = pcb_true; + Entry->Data.RemovedPoint.last_in_contour = last_in_contour; + + Entry->Data.RemovedPoint.X = pnt->X; + Entry->Data.RemovedPoint.Y = pnt->Y; + Entry->Data.RemovedPoint.ID = pnt->ID; + Entry->ID = polygon->ID; + Entry->Kind = PCB_OBJ_POLY; + Entry->Type = PCB_UNDO_REMOVE_POINT; + Entry->Data.RemovedPoint.Index = point_idx; + pcb_destroy_object(PCB->Data, PCB_OBJ_POLY_POINT, layer, polygon, pnt); + if (pcb_undo_and_draw && layer->meta.real.vis) + pcb_poly_invalidate_draw(layer, polygon); + return pcb_true; + } + + default: + return pcb_false; + } +} + +static pcb_bool UndoSwapCopiedObject(UndoListTypePtr Entry) +{ + void *ptr1, *ptr2, *ptr3; + void *ptr1b, *ptr2b, *ptr3b; + pcb_any_obj_t *obj, *obj2; + int type; + long int swap_id; + + /* lookup entry by it's ID */ + type = pcb_search_obj_by_id(pcb_removelist, &ptr1, &ptr2, &ptr3, Entry->Data.CopyID, Entry->Kind); + if (type == PCB_OBJ_VOID) + return pcb_false; + + type = pcb_search_obj_by_id(PCB->Data, &ptr1b, &ptr2b, &ptr3b, Entry->ID, Entry->Kind); + if (type == PCB_OBJ_VOID) + return pcb_false; + + obj = (pcb_any_obj_t *) ptr2; + obj2 = (pcb_any_obj_t *) ptr2b; + + swap_id = obj->ID; + obj->ID = obj2->ID; + obj2->ID = swap_id; + + pcb_move_obj_to_buffer(PCB, pcb_removelist, PCB->Data, type, ptr1b, ptr2b, ptr3b); + + if (pcb_undo_and_draw) + DrawRecoveredObject((pcb_any_obj_t *)ptr2); + + obj = (pcb_any_obj_t *) pcb_move_obj_to_buffer(PCB, PCB->Data, pcb_removelist, type, ptr1, ptr2, ptr3); + if (Entry->Kind == PCB_OBJ_POLY) + pcb_poly_init_clip(PCB->Data, (pcb_layer_t *) ptr1b, (pcb_poly_t *) obj); + return pcb_true; +} + +/* --------------------------------------------------------------------------- + * recovers an removed polygon point + * returns pcb_true on success + */ +static pcb_bool UndoRemoveContour(UndoListTypePtr Entry) +{ + assert(Entry->Kind == PCB_OBJ_POLY); + return UndoSwapCopiedObject(Entry); +} + +/* --------------------------------------------------------------------------- + * recovers an inserted polygon point + * returns pcb_true on success + */ +static pcb_bool UndoInsertContour(UndoListTypePtr Entry) +{ + assert(Entry->Kind == PCB_OBJ_POLY); + return UndoSwapCopiedObject(Entry); +} + +/* --------------------------------------------------------------------------- + * undo a layer change + * returns pcb_true on success + */ +static pcb_bool UndoLayerMove(UndoListTypePtr Entry) +{ + LayerChangeTypePtr l = &Entry->Data.LayerChange; + int tmp; + + if (l->old_index == -1) { /* was creating new */ + l->old_index = l->at; + l->at = l->new_index; + l->new_index = -1; + } + else if (l->new_index == -1) { /* was deleting existing */ + l->new_index = l->at; + l->at = l->old_index; + l->old_index = -1; + } + else { + tmp = l->new_index; + l->new_index = l->old_index; + l->old_index = tmp; + } + + if (pcb_layer_move(PCB, l->old_index, l->new_index, -1)) + return pcb_false; + else + return pcb_true; +} + +static int pcb_undo_old_undo(void *ptr_) +{ + UndoListTypePtr ptr = ptr_; + switch (ptr->Type) { + case PCB_UNDO_CHANGENAME: + if (UndoChangeName(ptr)) + return 0; + break; + + case PCB_UNDO_CREATE: + if (UndoCopyOrCreate(ptr)) + return 0; + break; + + case PCB_UNDO_MOVE: + if (UndoMove(ptr)) + return 0; + break; + + case PCB_UNDO_REMOVE: + if (UndoRemove(ptr)) + return 0; + break; + + case PCB_UNDO_REMOVE_POINT: + if (UndoRemovePoint(ptr)) + return 0; + break; + + case PCB_UNDO_INSERT_POINT: + if (UndoInsertPoint(ptr)) + return 0; + break; + + case PCB_UNDO_REMOVE_CONTOUR: + if (UndoRemoveContour(ptr)) + return 0; + break; + + case PCB_UNDO_INSERT_CONTOUR: + if (UndoInsertContour(ptr)) + return 0; + break; + + case PCB_UNDO_ROTATE: + if (UndoRotate(ptr)) + return 0; + break; + + case PCB_UNDO_ROTATE90: + if (UndoRotate90(ptr)) + return 0; + break; + + case PCB_UNDO_CLEAR: + if (UndoClearPoly(ptr)) + return 0; + break; + + case PCB_UNDO_MOVETOLAYER: + if (UndoMoveToLayer(ptr)) + return 0; + break; + + case PCB_UNDO_FLAG: + if (UndoFlag(ptr)) + return 0; + break; + + case PCB_UNDO_CHANGESIZE: + if (UndoChangeSize(ptr)) + return 0; + break; + + case PCB_UNDO_CHANGE2SIZE: + if (UndoChange2ndSize(ptr)) + return 0; + break; + + case PCB_UNDO_CHANGEROT: + if (UndoChangeRot(ptr)) + return 0; + break; + + case PCB_UNDO_CHANGECLEARSIZE: + if (UndoChangeClearSize(ptr)) + return 0; + break; + + case PCB_UNDO_CHANGEANGLES: + if (UndoChangeAngles(ptr)) + return 0; + break; + + case PCB_UNDO_CHANGERADII: + if (UndoChangeRadii(ptr)) + return 0; + break; + + case PCB_UNDO_LAYERMOVE: + if (UndoLayerMove(ptr)) + return 0; + break; + + case PCB_UNDO_OTHERSIDE: + if (UndoOtherSide(ptr)) + return 0; + break; + } + return -1; +} + +/* --------------------------------------------------------------------------- + * adds an object to the list of clearpoly objects + */ +void pcb_undo_add_obj_to_clear_poly(int Type, void *Ptr1, void *Ptr2, void *Ptr3, pcb_bool clear) +{ + UndoListTypePtr undo; + + if (!Locked) { + undo = GetUndoSlot(PCB_UNDO_CLEAR, PCB_OBJECT_ID(Ptr3), Type); + undo->Data.ClearPoly.Clear = clear; + undo->Data.ClearPoly.Layer = (pcb_layer_t *) Ptr1; + } +} + +/* --------------------------------------------------------------------------- + * adds an subc to the list of objects tossed to the other side + */ +void pcb_undo_add_subc_to_otherside(int Type, void *Ptr1, void *Ptr2, void *Ptr3, pcb_coord_t yoff) +{ + UndoListTypePtr undo; + + if (!Locked) { + undo = GetUndoSlot(PCB_UNDO_OTHERSIDE, PCB_OBJECT_ID(Ptr3), Type); + undo->Data.Move.DY = yoff; + } +} + +/* --------------------------------------------------------------------------- + * adds an object to the list of 90-deg rotated objects + */ +void pcb_undo_add_obj_to_rotate90(int Type, void *Ptr1, void *Ptr2, void *Ptr3, pcb_coord_t CenterX, pcb_coord_t CenterY, unsigned int Steps) +{ + UndoListTypePtr undo; + + if (!Locked) { + undo = GetUndoSlot(PCB_UNDO_ROTATE90, PCB_OBJECT_ID(Ptr3), Type); + undo->Data.Rotate.CenterX = CenterX; + undo->Data.Rotate.CenterY = CenterY; + undo->Data.Rotate.Steps = Steps; + } +} + +/* --------------------------------------------------------------------------- + * adds an object to the list of rotated objects + */ +void pcb_undo_add_obj_to_rotate(int Type, void *Ptr1, void *Ptr2, void *Ptr3, pcb_coord_t CenterX, pcb_coord_t CenterY, pcb_angle_t angle) +{ + UndoListTypePtr undo; + + if (!Locked) { + undo = GetUndoSlot(PCB_UNDO_ROTATE, PCB_OBJECT_ID(Ptr3), Type); + undo->Data.Rotate.CenterX = CenterX; + undo->Data.Rotate.CenterY = CenterY; + undo->Data.Angle = angle; + } +} + +/* --------------------------------------------------------------------------- + * adds an object to the list of removed objects and removes it from + * the current PCB + */ +void pcb_undo_move_obj_to_remove(int Type, void *Ptr1, void *Ptr2, void *Ptr3) +{ + UndoListTypePtr Entry; + Removed *r; + pcb_any_obj_t *o = Ptr3; + pcb_subc_t *subc; + + if (Locked) + return; + + if (!pcb_removelist) + pcb_removelist = pcb_buffer_new(NULL); + + Entry = GetUndoSlot(PCB_UNDO_REMOVE, PCB_OBJECT_ID(Ptr3), Type); + r = &Entry->Data.Removed; + r->p_subc_id = 0; + + switch(o->type) { + case PCB_OBJ_LINE: + case PCB_OBJ_ARC: + case PCB_OBJ_TEXT: + case PCB_OBJ_POLY: + subc = pcb_obj_parent_subc(Ptr3); + if (subc != NULL) { + r->p_subc_id = subc->ID; + r->p_subc_layer = o->parent.layer - subc->data->Layer; + } + break; + case PCB_OBJ_PSTK: + subc = pcb_obj_parent_subc(Ptr3); + if (subc != NULL) + r->p_subc_id = subc->ID; + break; +TODO("subc: floater subc in subc should remember its subc parent too") + default: + break; + } + + + pcb_move_obj_to_buffer(PCB, pcb_removelist, PCB->Data, Type, Ptr1, Ptr2, Ptr3); +} + +/* --------------------------------------------------------------------------- + * adds an object to the list of removed polygon/... points + */ +void pcb_undo_add_obj_to_remove_point(int Type, void *Ptr1, void *Ptr2, pcb_cardinal_t index) +{ + UndoListTypePtr undo; + pcb_poly_t *polygon = (pcb_poly_t *) Ptr2; + pcb_cardinal_t hole; + pcb_bool last_in_contour = pcb_false; + + if (!Locked) { + switch (Type) { + case PCB_OBJ_POLY_POINT: + { + /* save the ID of the parent object; else it will be + * impossible to recover the point + */ + undo = GetUndoSlot(PCB_UNDO_REMOVE_POINT, PCB_OBJECT_ID(polygon), PCB_OBJ_POLY); + undo->Data.RemovedPoint.X = polygon->Points[index].X; + undo->Data.RemovedPoint.Y = polygon->Points[index].Y; + undo->Data.RemovedPoint.ID = polygon->Points[index].ID; + undo->Data.RemovedPoint.Index = index; + + /* Check whether this point was at the end of its contour. + * If so, we need to flag as such when re-adding the point + * so it goes back in the correct place + */ + for (hole = 0; hole < polygon->HoleIndexN; hole++) + if (index == polygon->HoleIndex[hole] - 1) + last_in_contour = pcb_true; + if (index == polygon->PointN - 1) + last_in_contour = pcb_true; + undo->Data.RemovedPoint.last_in_contour = last_in_contour; + } + break; + } + } +} + +/* --------------------------------------------------------------------------- + * adds an object to the list of inserted polygon/... points + */ +void pcb_undo_add_obj_to_insert_point(int Type, void *Ptr1, void *Ptr2, void *Ptr3) +{ + if (!Locked) + GetUndoSlot(PCB_UNDO_INSERT_POINT, PCB_OBJECT_ID(Ptr3), Type); +} + +static void CopyObjectToUndoList(int undo_type, int Type, void *Ptr1, void *Ptr2, void *Ptr3) +{ + UndoListTypePtr undo; + pcb_any_obj_t *copy; + + if (Locked) + return; + + if (!pcb_removelist) + pcb_removelist = pcb_buffer_new(NULL); + + undo = GetUndoSlot(undo_type, PCB_OBJECT_ID(Ptr2), Type); + copy = (pcb_any_obj_t *) pcb_copy_obj_to_buffer(PCB, pcb_removelist, PCB->Data, Type, Ptr1, Ptr2, Ptr3); + undo->Data.CopyID = copy->ID; +} + +/* --------------------------------------------------------------------------- + * adds an object to the list of removed contours + * (Actually just takes a copy of the whole polygon to restore) + */ +void pcb_undo_add_obj_to_remove_contour(int Type, pcb_layer_t * Layer, pcb_poly_t * Polygon) +{ + CopyObjectToUndoList(PCB_UNDO_REMOVE_CONTOUR, Type, Layer, Polygon, NULL); +} + +/* --------------------------------------------------------------------------- + * adds an object to the list of insert contours + * (Actually just takes a copy of the whole polygon to restore) + */ +void pcb_undo_add_obj_to_insert_contour(int Type, pcb_layer_t * Layer, pcb_poly_t * Polygon) +{ + CopyObjectToUndoList(PCB_UNDO_INSERT_CONTOUR, Type, Layer, Polygon, NULL); +} + +/* --------------------------------------------------------------------------- + * adds an object to the list of moved objects + */ +void pcb_undo_add_obj_to_move(int Type, void *Ptr1, void *Ptr2, void *Ptr3, pcb_coord_t DX, pcb_coord_t DY) +{ + UndoListTypePtr undo; + + if (!Locked) { + undo = GetUndoSlot(PCB_UNDO_MOVE, PCB_OBJECT_ID(Ptr3), Type); + undo->Data.Move.DX = DX; + undo->Data.Move.DY = DY; + } +} + +/* --------------------------------------------------------------------------- + * adds an object to the list of objects with changed names + */ +void pcb_undo_add_obj_to_change_name(int Type, void *Ptr1, void *Ptr2, void *Ptr3, char *OldName) +{ + UndoListTypePtr undo; + + if (!Locked) { + undo = GetUndoSlot(PCB_UNDO_CHANGENAME, PCB_OBJECT_ID(Ptr3), Type); + undo->Data.ChangeName.Name = OldName; + } +} + +/* --------------------------------------------------------------------------- + * adds an object to the list of objects moved to another layer + */ +void pcb_undo_add_obj_to_move_to_layer(int Type, void *Ptr1, void *Ptr2, void *Ptr3) +{ + UndoListTypePtr undo; + + if (!Locked) { + undo = GetUndoSlot(PCB_UNDO_MOVETOLAYER, PCB_OBJECT_ID(Ptr3), Type); + undo->Data.MoveToLayer.OriginalLayer = pcb_layer_id(PCB->Data, (pcb_layer_t *) Ptr1); + } +} + +/* --------------------------------------------------------------------------- + * adds an object to the list of created objects + */ +void pcb_undo_add_obj_to_create(int Type, void *Ptr1, void *Ptr2, void *Ptr3) +{ + if (!Locked) + GetUndoSlot(PCB_UNDO_CREATE, PCB_OBJECT_ID(Ptr3), Type); + pcb_poly_clear_from_poly(PCB->Data, Type, Ptr1, Ptr2); +} + +/* --------------------------------------------------------------------------- + * adds an object to the list of objects with flags changed + */ +void pcb_undo_add_obj_to_flag(void *obj_) +{ + UndoListTypePtr undo; + pcb_any_obj_t *obj = obj_; + + if (!Locked) { + undo = GetUndoSlot(PCB_UNDO_FLAG, PCB_OBJECT_ID(obj), obj->type); + undo->Data.Flags = obj->Flags; + } +} + +/* --------------------------------------------------------------------------- + * adds an object to the list of objects with Size changes + */ +void pcb_undo_add_obj_to_size(int Type, void *ptr1, void *ptr2, void *ptr3) +{ + UndoListTypePtr undo; + + if (!Locked) { + undo = GetUndoSlot(PCB_UNDO_CHANGESIZE, PCB_OBJECT_ID(ptr2), Type); + switch (Type) { + case PCB_OBJ_LINE: + undo->Data.Size = ((pcb_line_t *) ptr2)->Thickness; + break; + case PCB_OBJ_TEXT: + undo->Data.Size = ((pcb_text_t *) ptr2)->Scale; + break; + case PCB_OBJ_ARC: + undo->Data.Size = ((pcb_arc_t *) ptr2)->Thickness; + break; + } + } +} + + +/* --------------------------------------------------------------------------- + * adds an object to the list of objects with Size changes + */ +void pcb_undo_add_obj_to_2nd_size(int Type, void *ptr1, void *ptr2, void *ptr3) +{ + UndoListTypePtr undo; + + if (!Locked) { + undo = GetUndoSlot(PCB_UNDO_CHANGE2SIZE, PCB_OBJECT_ID(ptr2), Type); + switch (Type) { + case PCB_OBJ_TEXT: + undo->Data.Size = ((pcb_text_t *) ptr2)->thickness; + break; + } + } +} + +/* --------------------------------------------------------------------------- + * adds an object to the list of objects with rot changes + */ +void pcb_undo_add_obj_to_rot(int Type, void *ptr1, void *ptr2, void *ptr3) +{ + UndoListTypePtr undo; + + if (!Locked) { + undo = GetUndoSlot(PCB_UNDO_CHANGEROT, PCB_OBJECT_ID(ptr2), Type); + switch (Type) { + case PCB_OBJ_PSTK: + undo->Data.Size = ((pcb_pstk_t *) ptr2)->rot; + break; + case PCB_OBJ_TEXT: + undo->Data.Size = ((pcb_text_t *) ptr2)->rot; + break; + } + } +} + +/* --------------------------------------------------------------------------- + * adds an object to the list of objects with Size changes + */ +void pcb_undo_add_obj_to_clear_size(int Type, void *ptr1, void *ptr2, void *ptr3) +{ + UndoListTypePtr undo; + + if (!Locked) { + undo = GetUndoSlot(PCB_UNDO_CHANGECLEARSIZE, PCB_OBJECT_ID(ptr2), Type); + switch (Type) { + case PCB_OBJ_LINE: + undo->Data.Size = ((pcb_line_t *) ptr2)->Clearance; + break; + case PCB_OBJ_ARC: + undo->Data.Size = ((pcb_arc_t *) ptr2)->Clearance; + break; + } + } +} + +/* --------------------------------------------------------------------------- + * adds an object to the list of changed angles. Note that you must + * call this before changing the angles, passing the new start/delta. + */ +void pcb_undo_add_obj_to_change_angles(int Type, void *Ptr1, void *Ptr2, void *Ptr3) +{ + UndoListTypePtr undo; + pcb_arc_t *a = (pcb_arc_t *) Ptr3; + + if (!Locked) { + undo = GetUndoSlot(PCB_UNDO_CHANGEANGLES, PCB_OBJECT_ID(Ptr3), Type); + undo->Data.AngleChange.angle[0] = a->StartAngle; + undo->Data.AngleChange.angle[1] = a->Delta; + } +} + +/* --------------------------------------------------------------------------- + * adds an object to the list of changed radii. Note that you must + * call this before changing the radii, passing the new width/height. + */ +void pcb_undo_add_obj_to_change_radii(int Type, void *Ptr1, void *Ptr2, void *Ptr3) +{ + UndoListTypePtr undo; + pcb_arc_t *a = (pcb_arc_t *) Ptr3; + + if (!Locked) { + undo = GetUndoSlot(PCB_UNDO_CHANGERADII, PCB_OBJECT_ID(Ptr3), Type); + undo->Data.Move.DX = a->Width; + undo->Data.Move.DY = a->Height; + } +} + +/* --------------------------------------------------------------------------- + * adds a layer change (new, delete, move) to the undo list. + */ +void pcb_undo_add_layer_move(int old_index, int new_index, int at) +{ + UndoListTypePtr undo; + + if (!Locked) { + undo = GetUndoSlot(PCB_UNDO_LAYERMOVE, 0, 0); + undo->Data.LayerChange.old_index = old_index; + undo->Data.LayerChange.new_index = new_index; + undo->Data.LayerChange.at = at; + } +} + +#ifndef NDEBUG +const char *undo_type2str(int type) +{ + static char buff[32]; + switch(type) { + case PCB_UNDO_CHANGENAME: return "changename"; + case PCB_UNDO_MOVE: return "move"; + case PCB_UNDO_REMOVE: return "remove"; + case PCB_UNDO_REMOVE_POINT: return "remove_point"; + case PCB_UNDO_INSERT_POINT: return "insert_point"; + case PCB_UNDO_REMOVE_CONTOUR: return "remove_contour"; + case PCB_UNDO_INSERT_CONTOUR: return "insert_contour"; + case PCB_UNDO_ROTATE90: return "rotate90"; + case PCB_UNDO_ROTATE: return "rotate"; + case PCB_UNDO_CREATE: return "create"; + case PCB_UNDO_MOVETOLAYER: return "movetolayer"; + case PCB_UNDO_FLAG: return "flag"; + case PCB_UNDO_CHANGESIZE: return "changesize"; + case PCB_UNDO_CHANGEROT: return "changerot"; + case PCB_UNDO_OTHERSIDE: return "otherside"; + case PCB_UNDO_CHANGECLEARSIZE: return "chngeclearsize"; + case PCB_UNDO_CHANGEANGLES: return "changeangles"; + case PCB_UNDO_CHANGERADII: return "changeradii"; + case PCB_UNDO_LAYERMOVE: return "layermove"; + case PCB_UNDO_CLEAR: return "clear"; + } + sprintf(buff, "Unknown %d", type); + return buff; +} + +#endif + +static void pcb_undo_old_free(void *ptr_) +{ + UndoListTypePtr ptr = ptr_; + void *ptr1, *ptr2, *ptr3; + int type; + + switch (ptr->Type) { + case PCB_UNDO_CHANGENAME: + free(ptr->Data.ChangeName.Name); + break; + case PCB_UNDO_REMOVE: + type = pcb_search_obj_by_id(pcb_removelist, &ptr1, &ptr2, &ptr3, ptr->ID, ptr->Kind); + if (type != PCB_OBJ_VOID) + pcb_destroy_object(pcb_removelist, type, ptr1, ptr2, ptr3); + break; + default: + break; + } +} Index: tags/2.1.2/src/undo_old.h =================================================================== --- tags/2.1.2/src/undo_old.h (nonexistent) +++ tags/2.1.2/src/undo_old.h (revision 24813) @@ -0,0 +1,94 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +/* old undo infra: should be replaced by per operation local undo */ + +#ifndef PCB_UNDO_OLD_H +#define PCB_UNDO_OLD_H + +#include "global_typedefs.h" + +#define DRAW_FLAGS (PCB_FLAG_RAT | PCB_FLAG_SELECTED \ + | PCB_FLAG_HIDENAME | PCB_FLAG_HOLE | PCB_FLAG_OCTAGON | PCB_FLAG_FOUND | PCB_FLAG_CLEARLINE) + +/* different layers */ + +void pcb_undo_move_obj_to_remove(int, void *, void *, void *); +void pcb_undo_add_obj_to_remove_point(int, void *, void *, pcb_cardinal_t); +void pcb_undo_add_obj_to_insert_point(int, void *, void *, void *); +void pcb_undo_add_obj_to_remove_contour(int, pcb_layer_t *, pcb_poly_t *); +void pcb_undo_add_obj_to_insert_contour(int, pcb_layer_t *, pcb_poly_t *); +void pcb_undo_add_obj_to_move(int, void *, void *, void *, pcb_coord_t, pcb_coord_t); +void pcb_undo_add_obj_to_change_name(int, void *, void *, void *, char *); +void pcb_undo_add_obj_to_change_pinnum(int, void *, void *, void *, char *); +void pcb_undo_add_obj_to_rotate90(int, void *, void *, void *, pcb_coord_t, pcb_coord_t, unsigned int); +void pcb_undo_add_obj_to_rotate(int Type, void *Ptr1, void *Ptr2, void *Ptr3, pcb_coord_t CenterX, pcb_coord_t CenterY, pcb_angle_t angle); +void pcb_undo_add_obj_to_create(int, void *, void *, void *); +void pcb_undo_add_subc_to_otherside(int Type, void *Ptr1, void *Ptr2, void *Ptr3, pcb_coord_t yoff); +void pcb_undo_add_obj_to_move_to_layer(int, void *, void *, void *); +void pcb_undo_add_obj_to_flag(void *obj); +void pcb_undo_add_obj_to_size(int, void *, void *, void *); +void pcb_undo_add_obj_to_2nd_size(int Type, void *ptr1, void *ptr2, void *ptr3); +void pcb_undo_add_obj_to_rot(int Type, void *ptr1, void *ptr2, void *ptr3); +void pcb_undo_add_obj_to_clear_size(int, void *, void *, void *); +void pcb_undo_add_obj_to_change_angles(int, void *, void *, void *); +void pcb_undo_add_obj_to_change_radii(int, void *, void *, void *); +void pcb_undo_add_obj_to_clear_poly(int, void *, void *, void *, pcb_bool); +void pcb_undo_add_layer_move(int, int, int); + +/* --------------------------------------------------------------------------- + * define supported types of undo operations + * note these must be separate bits now + */ +typedef enum { + PCB_UNDO_CHANGENAME = 0x000001, /* change of names */ + PCB_UNDO_MOVE = 0x000002, /* moving objects */ + PCB_UNDO_REMOVE = 0x000004, /* removing objects */ + PCB_UNDO_REMOVE_POINT = 0x000008, /* removing polygon/... points */ + PCB_UNDO_INSERT_POINT = 0x000010, /* inserting polygon/... points */ + PCB_UNDO_REMOVE_CONTOUR = 0x000020, /* removing a contour from a polygon */ + PCB_UNDO_INSERT_CONTOUR = 0x000040, /* inserting a contour from a polygon */ + PCB_UNDO_ROTATE90 = 0x000080, /* rotations by 90 deg steps */ + PCB_UNDO_CREATE = 0x000100, /* creation of objects */ + PCB_UNDO_MOVETOLAYER = 0x000200, /* moving objects to */ + PCB_UNDO_FLAG = 0x000400, /* toggling SELECTED flag */ + PCB_UNDO_CHANGESIZE = 0x000800, /* change size of object */ + PCB_UNDO_CHANGECLEARSIZE = 0x004000, /* change clearance size */ + PCB_UNDO_CHANGEANGLES = 0x010000, /* change arc angles */ + PCB_UNDO_LAYERMOVE = 0x020000, /* layer new/delete/move */ + PCB_UNDO_CLEAR = 0x040000, /* clear/restore to polygons */ + PCB_UNDO_CHANGERADII = 0x200000, /* change arc radii */ + PCB_UNDO_OTHERSIDE = 0x400000, /* change side of board (subcircuit) */ + PCB_UNDO_ROTATE = 0x800000, /* rotations at arbitrary angle */ + PCB_UNDO_CHANGEROT = 0x1000000, /* change internal/self rotation of an object */ + PCB_UNDO_CHANGE2SIZE = 0x2000000 /* change 2nd size of object */ +} pcb_undo_op_t; + +const char *undo_type2str(int type); + +#endif Index: tags/2.1.2/src/undo_old_str.h =================================================================== --- tags/2.1.2/src/undo_old_str.h (nonexistent) +++ tags/2.1.2/src/undo_old_str.h (revision 24813) @@ -0,0 +1,73 @@ +TODO("cleanup: move this back to undo_old.c") + +typedef struct { /* information about a change command */ + char *Name; +} ChangeNameType, *ChangeNameTypePtr; + +typedef struct { /* information about a move command */ + pcb_coord_t DX, DY; /* movement vector */ +} MoveType, *MoveTypePtr; + +typedef struct { + long p_subc_id; /* parent subc ID (0 if parent is not a subc) */ + int p_subc_layer; /* parent subc layer index, for layer objects */ +} Removed; + +typedef struct { /* information about removed polygon points */ + pcb_coord_t X, Y; /* data */ + int ID; + pcb_cardinal_t Index; /* index in a polygons array of points */ + pcb_bool last_in_contour; /* Whether the point was the last in its contour */ +} RemovedPointType, *RemovedPointTypePtr; + +typedef struct { /* information about rotation */ + pcb_coord_t CenterX, CenterY; /* center of rotation */ + pcb_cardinal_t Steps; /* number of steps */ +} RotateType, *RotateTypePtr; + +typedef struct { /* information about moves between layers */ + pcb_cardinal_t OriginalLayer; /* the index of the original layer */ +} MoveToLayer; + +typedef struct { /* information about layer changes */ + int old_index; + int new_index; + int at; +} LayerChangeType, *LayerChangeTypePtr; + +typedef struct { /* information about poly clear/restore */ + pcb_bool Clear; /* pcb_true was clear, pcb_false was restore */ + pcb_layer_t *Layer; +} ClearPolyType, *ClearPolyTypePtr; + +typedef struct { + pcb_angle_t angle[2]; +} AngleChangeType; + +typedef struct { /* information about netlist lib changes */ + pcb_net_t *old; + pcb_net_t *lib; +} NetlistChangeType, *NetlistChangeTypePtr; + +typedef struct { /* holds information about an operation */ + int Serial; /* serial number of operation */ + int Type; /* type of operation */ + pcb_objtype_t Kind; /* type of object with given ID */ + long int ID; /* object ID */ + union { /* some additional information */ + ChangeNameType ChangeName; + MoveType Move; + Removed Removed; + RemovedPointType RemovedPoint; + RotateType Rotate; + MoveToLayer MoveToLayer; + pcb_flag_t Flags; + pcb_coord_t Size; + LayerChangeType LayerChange; + ClearPolyType ClearPoly; + NetlistChangeType NetlistChange; + long int CopyID; + AngleChangeType AngleChange; + pcb_angle_t Angle; + } Data; +} UndoListType, *UndoListTypePtr; Index: tags/2.1.2/src/unit.c =================================================================== --- tags/2.1.2/src/unit.c (nonexistent) +++ tags/2.1.2/src/unit.c (revision 24813) @@ -0,0 +1,206 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 2011 Andrew Poelstra + * Copyright (C) 2016,2017 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + * + * Old contact info: + * Andrew Poelstra, 16966 60A Ave, V3S 8X5 Surrey, BC, Canada + * asp11@sfu.ca + * + */ +#include "config.h" +#include +#include +#include +#include "compat_misc.h" +#include "unit.h" + +/* Helper macros for tables */ +#define PCB_MM_TO_COORD3(a,b,c) PCB_MM_TO_COORD (a), PCB_MM_TO_COORD (b), PCB_MM_TO_COORD (c) +#define PCB_MIL_TO_COORD3(a,b,c) PCB_MIL_TO_COORD (a), PCB_MIL_TO_COORD (b), PCB_MIL_TO_COORD (c) +#define PCB_MM_TO_COORD5(a,b,c,d,e) PCB_MM_TO_COORD (a), PCB_MM_TO_COORD (b), PCB_MM_TO_COORD (c), \ + PCB_MM_TO_COORD (d), PCB_MM_TO_COORD (e) +#define PCB_MIL_TO_COORD5(a,b,c,d,e) PCB_MIL_TO_COORD (a), PCB_MIL_TO_COORD (b), PCB_MIL_TO_COORD (c), \ + PCB_MIL_TO_COORD (d), PCB_MIL_TO_COORD (e) + +/* These should be kept in order of smallest scale_factor + * to largest -- the code uses this ordering when finding + * the best scale to use for a group of measures */ +pcb_unit_t pcb_units[] = { + {0, "km", NULL, 'k', 0.000001, PCB_UNIT_METRIC, PCB_UNIT_ALLOW_KM, 5, + 0.00005, 0.0005, 0.0025, 0.05, 0.25, + {""}}, + {0, "m", NULL, 'f', 0.001, PCB_UNIT_METRIC, PCB_UNIT_ALLOW_M, 5, + 0.0005, 0.005, 0.025, 0.5, 2.5, + {""}}, + {0, "cm", NULL, 'e', 0.1, PCB_UNIT_METRIC, PCB_UNIT_ALLOW_CM, 5, + 0.005, 0.05, 0.25, 5, 25, + {""}}, + {0, "mm", NULL, 'm', 1, PCB_UNIT_METRIC, PCB_UNIT_ALLOW_MM, 4, + 0.005, 0.05, 0.25, 5, 25, + {""}}, + {0, "um", NULL, 'u', 1000, PCB_UNIT_METRIC, PCB_UNIT_ALLOW_UM, 2, + 0.005, 0.05, 0.25, 5, 25, + {""}}, + {0, "du", NULL, 'd', 10000, PCB_UNIT_METRIC, PCB_UNIT_ALLOW_DU, 2, /* eagle bin decimicron */ + 0.005, 0.05, 0.25, 5, 25, + {""}}, + {0, "nm", NULL, 'n', 1000000, PCB_UNIT_METRIC, PCB_UNIT_ALLOW_NM, 0, + 5, 50, 2500, 5000, 25000, + {""}}, + + {0, "in", NULL, 'i', 0.001, PCB_UNIT_IMPERIAL, PCB_UNIT_ALLOW_IN, 5, + 0.1, 1.0, 5.0, 25, 100, + {"inch"}}, + {0, "mil", NULL, 'l', 1, PCB_UNIT_IMPERIAL, PCB_UNIT_ALLOW_MIL, 2, + 0.1, 1.0, 10, 100, 1000, + {""}}, + {0, "dmil", NULL, 'k', 10, PCB_UNIT_IMPERIAL, PCB_UNIT_ALLOW_DMIL, 1, /* kicad legacy decimil unit */ + 0.1, 1.0, 10, 100, 1000, /* wild guess at factors */ + {""}}, + {0, "cmil", NULL, 'c', 100, PCB_UNIT_IMPERIAL, PCB_UNIT_ALLOW_CMIL, 0, + 1, 10, 100, 1000, 10000, + {"pcb"}} +}; + +#define N_UNITS ((int) (sizeof pcb_units / sizeof pcb_units[0])) + +void pcb_units_init(void) +{ + int i; + for (i = 0; i < N_UNITS; ++i) { + pcb_units[i].index = i; + pcb_units[i].in_suffix = pcb_units[i].suffix; + } +} + +const pcb_unit_t *get_unit_struct_(const char *suffix, int strict) +{ + int i; + int s_len = 0; + + /* Determine bounds */ + while (isspace(*suffix)) + suffix++; + while (isalnum(suffix[s_len])) + s_len++; + + /* Also understand plural suffixes: "inches", "mils" */ + if (s_len > 2) { + if (suffix[s_len - 2] == 'e' && suffix[s_len - 1] == 's') + s_len -= 2; + else if (suffix[s_len - 1] == 's') + s_len -= 1; + } + + /* Do lookup */ + if (s_len <= 0) + return NULL; + + if (strict) { + for (i = 0; i < N_UNITS; ++i) + if (strcmp(suffix, pcb_units[i].suffix) == 0) + return &pcb_units[i]; + } + else { + for (i = 0; i < N_UNITS; ++i) + if (strncmp(suffix, pcb_units[i].suffix, s_len) == 0 || strncmp(suffix, pcb_units[i].alias[0], s_len) == 0) + return &pcb_units[i]; + } + + return NULL; +} + +const pcb_unit_t *get_unit_struct(const char *suffix) +{ + return get_unit_struct_(suffix, 0); +} + + +const pcb_unit_t *get_unit_struct_by_allow(enum pcb_allow_e allow) +{ + int i; + for (i = 0; i < N_UNITS; ++i) + if (pcb_units[i].allow == allow) + return &pcb_units[i]; + + return NULL; +} + +const pcb_unit_t *get_unit_by_idx(int idx) +{ + if ((idx < 0) || (idx >= N_UNITS)) + return NULL; + return pcb_units + idx; +} + +int pcb_get_n_units(void) +{ + return N_UNITS; +} + +double pcb_coord_to_unit(const pcb_unit_t * unit, pcb_coord_t x) +{ + double base; + if (unit == NULL) + return -1; + base = unit->family == PCB_UNIT_METRIC ? PCB_COORD_TO_MM(1) + : PCB_COORD_TO_MIL(1); + return x * unit->scale_factor * base; +} + +pcb_coord_t pcb_unit_to_coord(const pcb_unit_t * unit, double x) +{ + double base, res; + + if (unit == NULL) + return -1; + + base = unit->family == PCB_UNIT_METRIC ? PCB_MM_TO_COORD(x) : PCB_MIL_TO_COORD(x); + res = pcb_round(base/unit->scale_factor); + + /* clamp */ + if (res >= (double)COORD_MAX) + return COORD_MAX; + if (res <= -1.0 * (double)COORD_MAX) + return -COORD_MAX; + + return res; +} + +double pcb_unit_to_factor(const pcb_unit_t * unit) +{ + return 1.0 / pcb_coord_to_unit(unit, 1); +} + +pcb_angle_t pcb_normalize_angle(pcb_angle_t a) +{ + while (a < 0) + a += 360.0; + while (a >= 360.0) + a -= 360.0; + return a; +} Index: tags/2.1.2/src/unit.h =================================================================== --- tags/2.1.2/src/unit.h (nonexistent) +++ tags/2.1.2/src/unit.h (revision 24813) @@ -0,0 +1,153 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 2011 Andrew Poelstra + * Copyright (C) 2016 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + * + * Old contact info: + * Andrew Poelstra, 16966 60A Ave, V3S 8X5 Surrey, BC, Canada + * asp11@sfu.ca + * + */ + +#ifndef PCB_UNIT_H +#define PCB_UNIT_H + +#include "config.h" + +/* typedef ... pcb_coord_t; pcb base unit, typedef'd in config.h */ +typedef double pcb_angle_t; /* degrees */ + +enum pcb_allow_e { + PCB_UNIT_NO_PRINT = 0, /* suffixes we can read but not print (i.e., "inch") */ + PCB_UNIT_ALLOW_NM = 1, + PCB_UNIT_ALLOW_UM = 2, + PCB_UNIT_ALLOW_MM = 4, + PCB_UNIT_ALLOW_CM = 8, + PCB_UNIT_ALLOW_M = 16, + PCB_UNIT_ALLOW_KM = 32, + PCB_UNIT_ALLOW_DU = 64, /* "du" = 0.1 micron "decimicron" units, for eagle bin */ + + PCB_UNIT_ALLOW_CMIL = 1024, + PCB_UNIT_ALLOW_MIL = 2048, + PCB_UNIT_ALLOW_IN = 4096, + + PCB_UNIT_ALLOW_DMIL = 8192, /* for kicad legacy decimil units */ + + PCB_UNIT_ALLOW_METRIC = PCB_UNIT_ALLOW_NM | PCB_UNIT_ALLOW_UM | PCB_UNIT_ALLOW_MM | PCB_UNIT_ALLOW_CM | PCB_UNIT_ALLOW_M | PCB_UNIT_ALLOW_KM, + PCB_UNIT_ALLOW_IMPERIAL = PCB_UNIT_ALLOW_DMIL | PCB_UNIT_ALLOW_CMIL | PCB_UNIT_ALLOW_MIL | PCB_UNIT_ALLOW_IN, + /* This is all units allowed in parse_l.l */ +#if 0 + PCB_UNIT_ALLOW_READABLE = PCB_UNIT_ALLOW_NM | PCB_UNIT_ALLOW_UM | PCB_UNIT_ALLOW_MM | PCB_UNIT_ALLOW_M | PCB_UNIT_ALLOW_KM | PCB_UNIT_ALLOW_CMIL | PCB_UNIT_ALLOW_MIL | PCB_UNIT_ALLOW_IN, +#else + PCB_UNIT_ALLOW_READABLE = PCB_UNIT_ALLOW_CMIL, +#endif + + /* Used for pcb-printf %mS - should not include unusual units like km, cmil and dmil */ + PCB_UNIT_ALLOW_NATURAL = PCB_UNIT_ALLOW_NM | PCB_UNIT_ALLOW_UM | PCB_UNIT_ALLOW_MM | PCB_UNIT_ALLOW_M | PCB_UNIT_ALLOW_MIL | PCB_UNIT_ALLOW_IN, + + /* Allow all but the most exotic */ + PCB_UNIT_ALLOW_ALL_SANE = ~(PCB_UNIT_ALLOW_DU | PCB_UNIT_ALLOW_DMIL), + + PCB_UNIT_ALLOW_ALL = ~0 +}; + +enum pcb_family_e { PCB_UNIT_METRIC, PCB_UNIT_IMPERIAL }; +enum pcb_suffix_e { PCB_UNIT_NO_SUFFIX, PCB_UNIT_SUFFIX, PCB_UNIT_FILE_MODE }; + +struct pcb_unit_s { + int index; /* Index into Unit[] list */ + const char *suffix; + const char *in_suffix; /* internationalized suffix */ + char printf_code; + double scale_factor; + enum pcb_family_e family; + enum pcb_allow_e allow; + int default_prec; + /* used for gui spinboxes */ + double step_tiny; + double step_small; + double step_medium; + double step_large; + double step_huge; + /* aliases -- right now we only need 1 ("inch"->"in"), add as needed */ + const char *alias[1]; +}; + +typedef struct pcb_unit_s pcb_unit_t; +extern pcb_unit_t pcb_units[]; + +/* Look up a given suffix in the units array. Pluralized units are supported. + The _ version allows strict (full name match) lookup if strict iz non-zero. */ +const pcb_unit_t *get_unit_struct(const char *suffix); +const pcb_unit_t *get_unit_struct_(const char *suffix, int strict); + +/* Return the furst unit that matches allow */ +const pcb_unit_t *get_unit_struct_by_allow(enum pcb_allow_e allow); + +/* Return the list of units and number of units (obsolete, do not use) */ +int pcb_get_n_units(void); + +/* Return the idxth unit or NULL (bounds check) */ +const pcb_unit_t *get_unit_by_idx(int idx); + +/* Convert x to the given unit */ +double pcb_coord_to_unit(const pcb_unit_t *unit, pcb_coord_t x); + +/* Return how many PCB-internal-Coord-unit a unit translates to */ +double pcb_unit_to_factor(const pcb_unit_t * unit); + +/* Convert a given unit to pcb coords; clamp at the end of the ranges */ +pcb_coord_t pcb_unit_to_coord(const pcb_unit_t * unit, double x); + +/* Bring an angle into [0, 360) range */ +pcb_angle_t pcb_normalize_angle(pcb_angle_t a); + + +/* Initialize non-static unit data: assigns each unit its index for + quick access through the main units array, and internationalize + the units for GUI display. */ +void pcb_units_init(void); + +/* PCB/physical unit conversions */ +#define PCB_COORD_TO_MIL(n) ((n) / 25400.0) +#define PCB_MIL_TO_COORD(n) ((n) * 25400.0) +#define PCB_COORD_TO_MM(n) ((n) / 1000000.0) +#define PCB_MM_TO_COORD(n) ((n) * 1000000.0) +#define PCB_COORD_TO_INCH(n) (PCB_COORD_TO_MIL(n) / 1000.0) +#define PCB_INCH_TO_COORD(n) (PCB_MIL_TO_COORD(n) * 1000.0) +#define PCB_COORD_TO_DECIMIL(n) (PCB_COORD_TO_MIL(n) * 10.0) +#define PCB_DECIMIL_TO_COORD(n) (PCB_MIL_TO_COORD(n) / 10.0) + +#define PCB_SWAP_ANGLE(a) (-(a)) +#define PCB_SWAP_DELTA(d) (-(d)) + +PCB_INLINE pcb_coord_t pcb_coord_abs(pcb_coord_t c) +{ + if (c < 0) return -c; + return c; +} + +#endif Index: tags/2.1.2/src/view.c =================================================================== --- tags/2.1.2/src/view.c (nonexistent) +++ tags/2.1.2/src/view.c (revision 24813) @@ -0,0 +1,522 @@ +/* + * + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2018 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ +#include "config.h" + +#include "idpath.h" +#include + +#define TDL_DONT_UNDEF +#include "view.h" +#include +#undef TDL_DONT_UNDEF +#include + +#include + +#include + +#include "actions.h" +#include "compat_misc.h" +#include "error.h" +#include "pcb-printf.h" + +static unsigned long int pcb_view_next_uid = 0; + +void pcb_view_free(pcb_view_t *item) +{ + pcb_view_list_remove(item); + pcb_idpath_list_clear(&item->objs[0]); + pcb_idpath_list_clear(&item->objs[1]); + free(item->title); + free(item->description); + free(item); +} + +void pcb_view_list_free_fields(pcb_view_list_t *lst) +{ + for(;;) { + pcb_view_t *item = pcb_view_list_first(lst); + if (item == NULL) + break; + pcb_view_free(item); + } +} + +void pcb_view_list_free(pcb_view_list_t *lst) +{ + pcb_view_list_free_fields(lst); + free(lst); +} + +pcb_view_t *pcb_view_by_uid(const pcb_view_list_t *lst, unsigned long int uid) +{ + pcb_view_t *v; + + for(v = pcb_view_list_first((pcb_view_list_t *)lst); v != NULL; v = pcb_view_list_next(v)) + if (v->uid == uid) + return v; + + return NULL; +} + +pcb_view_t *pcb_view_by_uid_cnt(const pcb_view_list_t *lst, unsigned long int uid, long *cnt) +{ + pcb_view_t *v; + long c = 0; + + for(v = pcb_view_list_first((pcb_view_list_t *)lst); v != NULL; v = pcb_view_list_next(v), c++) { + if (v->uid == uid) { + *cnt = c; + return v; + } + } + + *cnt = -1; + return NULL; +} + + +void pcb_view_goto(pcb_view_t *item) +{ + if (item->have_bbox) { + fgw_arg_t res, argv[5]; + + argv[1].type = FGW_COORD; fgw_coord(&argv[1]) = item->bbox.X1; + argv[2].type = FGW_COORD; fgw_coord(&argv[2]) = item->bbox.Y1; + argv[3].type = FGW_COORD; fgw_coord(&argv[3]) = item->bbox.X2; + argv[4].type = FGW_COORD; fgw_coord(&argv[4]) = item->bbox.Y2; + pcb_actionv_bin("zoom", &res, 5, argv); + } +} + +pcb_view_t *pcb_view_new(const char *type, const char *title, const char *description) +{ + pcb_view_t *v = calloc(sizeof(pcb_view_t), 1); + + pcb_view_next_uid++; + v->uid = pcb_view_next_uid; + + if (type == NULL) type = ""; + if (title == NULL) title = ""; + if (description == NULL) description = ""; + + v->type = pcb_strdup(type); + v->title = pcb_strdup(title); + v->description = pcb_strdup(description); + + return v; +} + +void pcb_view_append_obj(pcb_view_t *view, int grp, pcb_any_obj_t *obj) +{ + pcb_idpath_t *idp; + + assert((grp == 0) || (grp == 1)); + + switch(obj->type) { + case PCB_OBJ_TEXT: + case PCB_OBJ_SUBC: + case PCB_OBJ_LINE: + case PCB_OBJ_ARC: + case PCB_OBJ_POLY: + case PCB_OBJ_PSTK: + case PCB_OBJ_RAT: + idp = pcb_obj2idpath(obj); + if (idp == NULL) + pcb_message(PCB_MSG_ERROR, "Internal error in pcb_drc_append_obj: can not resolve object id path\n"); + else + pcb_idpath_list_append(&view->objs[grp], idp); + break; + default: + pcb_message(PCB_MSG_ERROR, "Internal error in pcb_drc_append_obj: unknown object type %i\n", obj->type); + } +} + +void pcb_view_set_bbox_by_objs(pcb_data_t *data, pcb_view_t *v) +{ + int g; + pcb_box_t b; + pcb_any_obj_t *obj; + pcb_idpath_t *idp; + + /* special case: no object - leave coords unloaded/invalid */ + if ((pcb_idpath_list_length(&v->objs[0]) < 1) && (pcb_idpath_list_length(&v->objs[1]) < 1)) + return; + + /* special case: single objet in group A, use the center */ + if (pcb_idpath_list_length(&v->objs[0]) == 1) { + idp = pcb_idpath_list_first(&v->objs[0]); + obj = pcb_idpath2obj(data, idp); + if (obj != NULL) { + v->have_bbox = 1; + pcb_obj_center(obj, &v->x, &v->y); + memcpy(&v->bbox, &obj->BoundingBox, sizeof(obj->BoundingBox)); + pcb_box_enlarge(&v->bbox, 0.25, 0.25); + return; + } + } + + b.X1 = b.Y1 = PCB_MAX_COORD; + b.X2 = b.Y2 = -PCB_MAX_COORD; + for(g = 0; g < 2; g++) { + for(idp = pcb_idpath_list_first(&v->objs[g]); idp != NULL; idp = pcb_idpath_list_next(idp)) { + obj = pcb_idpath2obj(data, idp); + if (obj != NULL) { + v->have_bbox = 1; + pcb_box_bump_box(&b, &obj->BoundingBox); + } + } + } + + if (v->have_bbox) { + v->x = (b.X1 + b.X2)/2; + v->y = (b.Y1 + b.Y2)/2; + memcpy(&v->bbox, &b, sizeof(b)); + pcb_box_enlarge(&v->bbox, 0.25, 0.25); + } +} + +static void view_append_str(gds_t *dst, const char *prefix, const char *key, const char *value) +{ + const char *s; + pcb_append_printf(dst, "%s %s = {", prefix, key); + for(s = value; *s != '\0'; s++) { + switch(*s) { + case '\\': + case '}': + gds_append(dst, '\\'); + break; + } + gds_append(dst, *s); + } + gds_append_str(dst, "}\n"); +} + +void pcb_view_save_list_begin(gds_t *dst, const char *prefix) +{ + if (prefix != NULL) + gds_append_str(dst, prefix); + gds_append_str(dst, "li:view-list-v1 {\n"); +} + +void pcb_view_save_list_end(gds_t *dst, const char *prefix) +{ + if (prefix != NULL) + gds_append_str(dst, prefix); + gds_append_str(dst, "}\n"); +} + +void pcb_view_save(pcb_view_t *v, gds_t *dst, const char *prefix) +{ + int g, n; + + if (prefix == NULL) + prefix = ""; + + pcb_append_printf(dst, "%sha:view.%lu {\n", prefix, v->uid); + view_append_str(dst, prefix, "type", v->type); + view_append_str(dst, prefix, "title", v->title); + view_append_str(dst, prefix, "description", v->description); + if (v->have_bbox) + pcb_append_printf(dst, "%s li:bbox = {%.08$$mm; %.08$$mm; %.08$$mm; %.08$$mm;}\n", prefix, v->bbox.X1, v->bbox.Y1, v->bbox.X2, v->bbox.Y2); + if (v->have_xy) + pcb_append_printf(dst, "%s li:xy = {%.08$$mm; %.08$$mm;}\n", prefix, v->x, v->y); + + for(g = 0; g < 2; g++) { + if (pcb_idpath_list_length(&v->objs[g]) > 0) { + pcb_idpath_t *i; + pcb_append_printf(dst, "%s li:objs.%d {\n", prefix, g); + for(i = pcb_idpath_list_first(&v->objs[g]); i != NULL; i = pcb_idpath_list_next(i)) { + pcb_append_printf(dst, "%s li:id {", prefix); + for(n = 0; n < i->len; n++) + pcb_append_printf(dst, "%ld;", i->id[n]); + pcb_append_printf(dst, "}\n", prefix); + } + pcb_append_printf(dst, "%s }\n", prefix); + } + } + + switch(v->data_type) { + case PCB_VIEW_PLAIN: + pcb_append_printf(dst, "%s data_type = plain\n", prefix); + break; + case PCB_VIEW_DRC: + pcb_append_printf(dst, "%s data_type = drc\n", prefix); + pcb_append_printf(dst, "%s ha:data {\n", prefix); + pcb_append_printf(dst, "%s required_value = %.08$$mm\n", prefix, v->data.drc.required_value); + if (v->data.drc.have_measured) + pcb_append_printf(dst, "%s measured_value = %.08$$mm\n", prefix, v->data.drc.measured_value); + pcb_append_printf(dst, "%s }\n", prefix); + break; + } + + pcb_append_printf(dst, "%s}\n", prefix); +} + +typedef struct { + lht_doc_t *doc; + lht_node_t *next; +} load_ctx_t; + +void pcb_view_load_end(void *load_ctx) +{ + load_ctx_t *ctx = load_ctx; + lht_dom_uninit(ctx->doc); + free(ctx); +} + +static void *view_load_post(load_ctx_t *ctx) +{ + if (ctx->doc->root == NULL) + goto error; + + if (ctx->doc->root->type == LHT_LIST) { + if (strcmp(ctx->doc->root->name, "view-list-v1") != 0) + goto error; + ctx->next = ctx->doc->root->data.list.first; + return ctx; + } + + if (ctx->doc->root->type == LHT_HASH) { + if (strncmp(ctx->doc->root->name, "view.", 5) != 0) + goto error; + ctx->next = ctx->doc->root; + return ctx; + } + + error:; + pcb_view_load_end(ctx); + return NULL; +} + +void *pcb_view_load_start_str(const char *src) +{ + load_ctx_t *ctx = malloc(sizeof(load_ctx_t)); + + ctx->doc = lht_dom_init(); + + for(; *src != '\0'; src++) { + lht_err_t err = lht_dom_parser_char(ctx->doc, *src); + if ((err != LHTE_SUCCESS) && (err != LHTE_STOP)) { + pcb_view_load_end(ctx); + return NULL; + } + } + return view_load_post(ctx); +} + +void *pcb_view_load_start_file(FILE *f) +{ + int c; + load_ctx_t *ctx = malloc(sizeof(load_ctx_t)); + + ctx->doc = lht_dom_init(); + + while((c = fgetc(f)) != EOF) { + lht_err_t err = lht_dom_parser_char(ctx->doc, c); + if ((err != LHTE_SUCCESS) && (err != LHTE_STOP)) { + pcb_view_load_end(ctx); + return NULL; + } + } + return view_load_post(ctx); +} + +#define LOADERR "Error loading view: " + +static void pcb_view_load_objs(pcb_view_t *dst, int grp, lht_node_t *olist) +{ + lht_node_t *n, *m; + for(n = olist->data.list.first; n != NULL; n = n->next) { + if ((n->type == LHT_LIST) && (strcmp(n->name, "id") == 0)) { + pcb_idpath_t *i; + int len, cnt; + + for(m = n->data.list.first, len = 0; m != NULL; m = m->next) { + if (m->type != LHT_TEXT) { + pcb_message(PCB_MSG_ERROR, LOADERR "Invalid object id (non-text)\n"); + goto nope; + } + len++; + } + + i = pcb_idpath_alloc(len); + for(m = n->data.list.first, cnt = 0; m != NULL; m = m->next, cnt++) + i->id[cnt] = strtol(m->data.text.value, NULL, 10); + + pcb_idpath_list_append(&dst->objs[grp], i); + } + else + pcb_message(PCB_MSG_ERROR, LOADERR "Invalid object id-path\n"); + nope:; + } +} + +pcb_view_t *pcb_view_load_next(void *load_ctx, pcb_view_t *dst) +{ + load_ctx_t *ctx = load_ctx; + lht_node_t *n, *c; + unsigned long int uid; + char *end; + pcb_view_type_t data_type; + pcb_bool succ; + + if (ctx->next == NULL) + return NULL; + + if ((ctx->next->type != LHT_HASH) || (strncmp(ctx->next->name, "view.", 5) != 0)) + return NULL; + + uid = strtoul(ctx->next->name + 5, &end, 10); + if (*end != '\0') + return NULL; + + data_type = PCB_VIEW_PLAIN; + n = lht_dom_hash_get(ctx->next, "data_type"); + if ((n != NULL) && (n->type == LHT_TEXT)) { + if (strcmp(n->data.text.value, "drc") == 0) + data_type = PCB_VIEW_DRC; + else if (strcmp(n->data.text.value, "plain") == 0) + data_type = PCB_VIEW_PLAIN; + else { + pcb_message(PCB_MSG_ERROR, LOADERR "Invalid data type: '%s'\n", n->data.text.value); + return NULL; + } + } + + if (dst == NULL) + dst = calloc(sizeof(pcb_view_t), 1); + + dst->uid = uid; + dst->data_type= data_type; + + n = lht_dom_hash_get(ctx->next, "type"); + if ((n != NULL) && (n->type == LHT_TEXT)) { + dst->type = n->data.text.value; + n->data.text.value = NULL; + } + + n = lht_dom_hash_get(ctx->next, "title"); + if ((n != NULL) && (n->type == LHT_TEXT)) { + dst->title = n->data.text.value; + n->data.text.value = NULL; + } + + n = lht_dom_hash_get(ctx->next, "description"); + if ((n != NULL) && (n->type == LHT_TEXT)) { + dst->description = n->data.text.value; + n->data.text.value = NULL; + } + + n = lht_dom_hash_get(ctx->next, "bbox"); + if ((n != NULL) && (n->type == LHT_LIST)) { + int ok = 0; + + c = n->data.list.first; + if ((c != NULL) && (c->type == LHT_TEXT)) { + dst->bbox.X1 = pcb_get_value(c->data.text.value, NULL, NULL, &succ); + if (succ) ok++; + c = c->next; + } + if ((c != NULL) && (c->type == LHT_TEXT)) { + dst->bbox.Y1 = pcb_get_value(c->data.text.value, NULL, NULL, &succ); + if (succ) ok++; + c = c->next; + } + if ((c != NULL) && (c->type == LHT_TEXT)) { + dst->bbox.X2 = pcb_get_value(c->data.text.value, NULL, NULL, &succ); + if (succ) ok++; + c = c->next; + } + if ((c != NULL) && (c->type == LHT_TEXT)) { + dst->bbox.Y2 = pcb_get_value(c->data.text.value, NULL, NULL, &succ); + if (succ) ok++; + c = c->next; + } + if ((c == NULL) && (ok == 4)) + dst->have_bbox = 1; + else + pcb_message(PCB_MSG_ERROR, LOADERR "Invalid bbox values\n"); + } + + n = lht_dom_hash_get(ctx->next, "xy"); + if ((n != NULL) && (n->type == LHT_LIST)) { + int ok = 0; + + c = n->data.list.first; + if ((c != NULL) && (c->type == LHT_TEXT)) { + dst->x = pcb_get_value(c->data.text.value, NULL, NULL, &succ); + if (succ) ok++; + c = c->next; + } + if ((c != NULL) && (c->type == LHT_TEXT)) { + dst->y = pcb_get_value(c->data.text.value, NULL, NULL, &succ); + if (succ) ok++; + c = c->next; + } + if ((c == NULL) && (ok == 2)) + dst->have_bbox = 1; + else + pcb_message(PCB_MSG_ERROR, LOADERR "Invalid xy values\n"); + } + + n = lht_dom_hash_get(ctx->next, "objs.0"); + if ((n != NULL) && (n->type == LHT_LIST)) + pcb_view_load_objs(dst, 0, n); + + n = lht_dom_hash_get(ctx->next, "objs.1"); + if ((n != NULL) && (n->type == LHT_LIST)) + pcb_view_load_objs(dst, 1, n); + + switch(dst->data_type) { + case PCB_VIEW_PLAIN: break; + case PCB_VIEW_DRC: + n = lht_dom_hash_get(ctx->next, "data"); + if ((n != NULL) && (n->type == LHT_HASH)) { + c = lht_dom_hash_get(n, "required_value"); + if ((c != NULL) && (c->type == LHT_TEXT)) { + dst->data.drc.required_value = pcb_get_value(c->data.text.value, NULL, NULL, &succ); + if (!succ) + pcb_message(PCB_MSG_ERROR, LOADERR "invalid drc required value: '%s'\n", c->data.text.value); + } + c = lht_dom_hash_get(n, "measured_value"); + if ((c != NULL) && (c->type == LHT_TEXT)) { + dst->data.drc.measured_value = pcb_get_value(c->data.text.value, NULL, NULL, &succ); + if (succ) + dst->data.drc.have_measured = 1; + else + pcb_message(PCB_MSG_ERROR, LOADERR "invalid drc measured value: '%s'\n", c->data.text.value); + } + } + break; + } + + ctx->next = ctx->next->next; + return dst; +} + Index: tags/2.1.2/src/view.h =================================================================== --- tags/2.1.2/src/view.h (nonexistent) +++ tags/2.1.2/src/view.h (revision 24813) @@ -0,0 +1,143 @@ +/* + * + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2018 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ +#ifndef PCB_VIEW_H +#define PCB_VIEW_H + +#include +#include +#include +#include "unit.h" +#include "idpath.h" +#include "box.h" + +/* A saved view on the board (e.g. a drc violation); metadata includes two lists + of objects to highlight on preview and some optional, application-specific + data (e.g. drc size values) */ + +typedef enum pcb_view_type_e { + PCB_VIEW_PLAIN, /* has no data */ + PCB_VIEW_DRC +} pcb_view_type_t; + +struct pcb_view_s { + unsigned long int uid; /* ID unique for each view (for GUI identification) - 0 means invalid */ + + char *type; + char *title; + char *description; + + /* these indicate whether some of the following fields are valid */ + unsigned have_bbox:1; + unsigned have_xy:1; + + pcb_box_t bbox; /* bounding box of all error objects (in both groups) */ + + pcb_coord_t x, y; /* optional: a coord to mark on the preview */ + pcb_idpath_list_t objs[2]; /* optional: two groups of objects to highlight on preview */ + + pcb_view_type_t data_type; + union { + struct { + unsigned have_measured:1; + pcb_coord_t measured_value; + pcb_coord_t required_value; + } drc; + } data; + + gdl_elem_t link; /* always part of a list */ +}; + +/* List of drc violations */ +#define TDL(x) pcb_view_list_ ## x +#define TDL_LIST_T pcb_view_list_t +#define TDL_ITEM_T pcb_view_t +#define TDL_FIELD link +#define TDL_SIZE_T size_t +#define TDL_FUNC + +#define pcb_view_list_foreach(list, iterator, loop_elem) \ + gdl_foreach_((&((list)->lst)), (iterator), (loop_elem)) + +#include +#include + +/* Free all fields and the view pointer too */ +void pcb_view_free(pcb_view_t *item); + +/* Free all items and empty the list but do not free the list pointer */ +void pcb_view_list_free_fields(pcb_view_list_t *lst); + +void pcb_view_list_free(pcb_view_list_t *lst); + + +/* Slow, linear search for an UID in a list; returns NULL if not found; + optionally count the number of preceeding items and sotre it in cnt. */ +pcb_view_t *pcb_view_by_uid(const pcb_view_list_t *lst, unsigned long int uid); +pcb_view_t *pcb_view_by_uid_cnt(const pcb_view_list_t *lst, unsigned long int uid, long *cnt); + +/* Zoom the drawing area to the drc error */ +void pcb_view_goto(pcb_view_t *item); + +/* Allocate a new, floating (unlinked) view with no data or bbox */ +pcb_view_t *pcb_view_new(const char *type, const char *title, const char *description); + +/* Append obj to one of the object groups in view (resolving to idpath) */ +void pcb_view_append_obj(pcb_view_t *view, int grp, pcb_any_obj_t *obj); + +/* Calculate and set v->bbox from v->objs[] bboxes */ +void pcb_view_set_bbox_by_objs(pcb_data_t *data, pcb_view_t *v); + + +/*** Save a serialized view (or list of views) ***/ + +/* In case of saving a list or saving into a file, call begin/end before/after + saving the view item */ +void pcb_view_save_list_begin(gds_t *dst, const char *prefix); +void pcb_view_save_list_end(gds_t *dst, const char *prefix); + +/* Serialize/save a view into dst as a lihata string, each line optionally + prefixed (prefix can be NULL) */ +void pcb_view_save(pcb_view_t *v, gds_t *dst, const char *prefix); + + +/*** Load a serialized view (or list of views) ***/ + +/* Parse a serialized string/file into memory; returns a load_ctx or NULL on + error. Does not close the file. */ +void *pcb_view_load_start_str(const char *src); +void *pcb_view_load_start_file(FILE *f); + +/* Load the next item from load_ctx; returns NULL on error if there are no + more items. If dst is not NULL, it's returned on success; else a newly + allocated pcb_view_t is returned on success. */ +pcb_view_t *pcb_view_load_next(void *load_ctx, pcb_view_t *dst); + +/* call after the last item or to cancel the load */ +void pcb_view_load_end(void *load_ctx); + +#endif Index: tags/2.1.2/src/vtc0.c =================================================================== --- tags/2.1.2/src/vtc0.c (nonexistent) +++ tags/2.1.2/src/vtc0.c (revision 24813) @@ -0,0 +1,3 @@ +#define GVT_DONT_UNDEF +#include "vtc0.h" +#include Index: tags/2.1.2/src/vtc0.h =================================================================== --- tags/2.1.2/src/vtc0.h (nonexistent) +++ tags/2.1.2/src/vtc0.h (revision 24813) @@ -0,0 +1,21 @@ +#ifndef VTC0_H +#define VTC0_H + +#include "config.h" +#include +#include + +#define GVT(x) vtc0_ ## x +#define GVT_ELEM_TYPE pcb_coord_t +#define GVT_SIZE_TYPE size_t +#define GVT_DOUBLING_THRS 4096 +#define GVT_START_SIZE 32 +#define GVT_FUNC +#define GVT_SET_NEW_BYTES_TO 0 + +#include +#define GVT_REALLOC(vect, ptr, size) realloc(ptr, size) +#define GVT_FREE(vect, ptr) free(ptr) +#include + +#endif Index: tags/2.1.2/src/vtlibrary.c =================================================================== --- tags/2.1.2/src/vtlibrary.c (nonexistent) +++ tags/2.1.2/src/vtlibrary.c (revision 24813) @@ -0,0 +1,3 @@ +#define GVT_DONT_UNDEF +#include "vtlibrary.h" +#include Index: tags/2.1.2/src/vtlibrary.h =================================================================== --- tags/2.1.2/src/vtlibrary.h (nonexistent) +++ tags/2.1.2/src/vtlibrary.h (revision 24813) @@ -0,0 +1,74 @@ +#include +#include + +typedef enum { + LIB_INVALID, + LIB_DIR, + LIB_FOOTPRINT +} pcb_fplibrary_type_t; + +typedef enum { + PCB_FP_INVALID, + PCB_FP_DIR, /* used temporarily during the mapping - a finalized tree wouldn't have this */ + PCB_FP_FILE, + PCB_FP_PARAMETRIC +} pcb_fptype_t; + + +typedef struct pcb_fplibrary_s pcb_fplibrary_t; + +/* Elem=library_t; init=none */ + +/* all public symbols are wrapped in GVT() - see vt_t(7) */ +#define GVT(x) vtlib_ ## x + +/* Array elem type - see vt_t(7) */ +#define GVT_ELEM_TYPE pcb_fplibrary_t + +/* Type that represents array lengths - see vt_t(7) */ +#define GVT_SIZE_TYPE size_t + +/* Below this length, always double allocation size when the array grows */ +#define GVT_DOUBLING_THRS 64 + +/* Initial array size when the first element is written */ +#define GVT_START_SIZE 8 + +/* Optional prefix for function definitions (e.g. static inline) */ +#define GVT_FUNC + +/* Enable this to set all new bytes ever allocated to this value - see + vt_set_new_bytes_to(7) */ +#define GVT_SET_NEW_BYTES_TO 0 + + +/* Include the actual header implementation */ +#include + +/* Memory allocator - see vt_allocation(7) */ +#define GVT_REALLOC(vect, ptr, size) realloc(ptr, size) +#define GVT_FREE(vect, ptr) free(ptr) + +/* clean up #defines */ +#include + +/* An element of a library: either a directory or a footprint */ +struct pcb_fplibrary_s { + char *name; /* visible name */ + pcb_fplibrary_type_t type; + pcb_fplibrary_t *parent; + + union { + struct { /* type == LIB_DIR */ + vtlib_t children; + void *backend; /* pcb_plug_fp_t* */ + } dir; + struct { /* type == LIB_FOOTPRINT */ + char *loc_info; + void *backend_data; + pcb_fptype_t type; + void **tags; /* an array of void * tag IDs; last tag ID is NULL */ + } fp; + } data; +} ; + Index: tags/2.1.2/src/vtonpoint.c =================================================================== --- tags/2.1.2/src/vtonpoint.c (nonexistent) +++ tags/2.1.2/src/vtonpoint.c (revision 24813) @@ -0,0 +1,8 @@ +#define GVT_DONT_UNDEF + +#include "config.h" + +TODO("cleanup: this should be replaced with pcb_obj_t") + +#include "vtonpoint.h" +#include Index: tags/2.1.2/src/vtonpoint.h =================================================================== --- tags/2.1.2/src/vtonpoint.h (nonexistent) +++ tags/2.1.2/src/vtonpoint.h (revision 24813) @@ -0,0 +1,78 @@ +#ifndef PCB_VTOP_H +#define PCB_VTOP_H + +#include +#include +#include "global_typedefs.h" + +typedef struct pcb_onpoint_st { + int type; + union { + void *any; + pcb_line_t *line; + pcb_arc_t *arc; + } obj; +} pcb_onpoint_t; + +/* Elem=pcb_onpoint_t; init=none */ + +/* all public symbols are wrapped in GVT() - see vt_t(7) */ +#define GVT(x) vtop_ ## x + +/* Array elem type - see vt_t(7) */ +#define GVT_ELEM_TYPE pcb_onpoint_t + +/* Type that represents array lengths - see vt_t(7) */ +#define GVT_SIZE_TYPE size_t + +/* Below this length, always double allocation size when the array grows */ +#define GVT_DOUBLING_THRS 64 + +/* Initial array size when the first element is written */ +#define GVT_START_SIZE 8 + +/* Optional terminator; when present, it is always appended at the end - see + vt_term(7)*/ +/* #define GVT_TERM '\0' */ + +/* Optional prefix for function definitions (e.g. static inline) */ +#define GVT_FUNC + +/* Enable this to set all new bytes ever allocated to this value - see + vt_set_new_bytes_to(7) */ +/* #define GVT_SET_NEW_BYTES_TO 0 */ + +/* Enable GVT_INIT_ELEM_FUNC and an user configured function is called + for each new element allocated (even between used and alloced). + See vt_init_elem(7) */ +/*#define GVT_INIT_ELEM_FUNC*/ + +/* Enable GVT_ELEM_CONSTRUCTOR and an user configured function is called + for each element that is getting within the range of ->used. + See vt_construction(7) */ +/*#define GVT_ELEM_CONSTRUCTOR */ + +/* Enable GVT_ELEM_DESTRUCTOR and an user configured function is called + for each element that was once constructed and now getting beyond ->used. + See vt_construction(7) */ +/*#define GVT_ELEM_DESTRUCTOR */ + +/* Enable GVT_ELEM_COPY and an user configured function is called + for copying elements into the array. + See vt_construction(7) */ +/*#define GVT_ELEM_COPY */ + +/* Optional extra fields in the vector struct - see vt_user_fields(7) */ +/* #define GVT_USER_FIELDS int foo; char bar[12]; */ + +/* Include the actual header implementation */ +#include + +/* Memory allocator - see vt_allocation(7) */ +#define GVT_REALLOC(vect, ptr, size) realloc(ptr, size) +#define GVT_FREE(vect, ptr) free(ptr) + +/* clean up #defines */ +#include + +#endif Index: tags/2.1.2/src/vtpadstack.c =================================================================== --- tags/2.1.2/src/vtpadstack.c (nonexistent) +++ tags/2.1.2/src/vtpadstack.c (revision 24813) @@ -0,0 +1,6 @@ +#include "obj_pstk.h" + +#define GVT_DONT_UNDEF +#include "vtpadstack.h" +#include + Index: tags/2.1.2/src/vtpadstack.h =================================================================== --- tags/2.1.2/src/vtpadstack.h (nonexistent) +++ tags/2.1.2/src/vtpadstack.h (revision 24813) @@ -0,0 +1,41 @@ +#ifndef PCB_VTPADSTACK_H +#define PCB_VTPADSTACK_H + +/* Elem=pcb_pstk_proto_t; init=none */ + +#include "obj_pstk.h" + +/* all public symbols are wrapped in GVT() - see vt_t(7) */ +#define GVT(x) pcb_vtpadstack_proto_ ## x + +/* Array elem type - see vt_t(7) */ +#define GVT_ELEM_TYPE pcb_pstk_proto_t + +/* Type that represents array lengths - see vt_t(7) */ +#define GVT_SIZE_TYPE size_t + +/* Below this length, always double allocation size when the array grows */ +#define GVT_DOUBLING_THRS 64 + +/* Initial array size when the first element is written */ +#define GVT_START_SIZE 8 + +/* Optional prefix for function definitions (e.g. static inline) */ +#define GVT_FUNC + +/* Enable this to set all new bytes ever allocated to this value - see + vt_set_new_bytes_to(7) */ +#define GVT_SET_NEW_BYTES_TO 0 + + +/* Include the actual header implementation */ +#include + +/* Memory allocator - see vt_allocation(7) */ +#define GVT_REALLOC(vect, ptr, size) realloc(ptr, size) +#define GVT_FREE(vect, ptr) free(ptr) + +/* clean up #defines */ +#include + +#endif Index: tags/2.1.2/src/vtpadstack_t.c =================================================================== --- tags/2.1.2/src/vtpadstack_t.c (nonexistent) +++ tags/2.1.2/src/vtpadstack_t.c (revision 24813) @@ -0,0 +1,6 @@ +#include +#include +#include "color.h" +#define GVT_DONT_UNDEF +#include "vtpadstack_t.h" +#include Index: tags/2.1.2/src/vtpadstack_t.h =================================================================== --- tags/2.1.2/src/vtpadstack_t.h (nonexistent) +++ tags/2.1.2/src/vtpadstack_t.h (revision 24813) @@ -0,0 +1,41 @@ +#ifndef PCB_VTPADSTACK_T_H +#define PCB_VTPADSTACK_T_H + +/* Elem=pcb_pstk_proto_t; init=none */ + +#include "obj_pstk_shape.h" + +/* all public symbols are wrapped in GVT() - see vt_t(7) */ +#define GVT(x) pcb_vtpadstack_tshape_ ## x + +/* Array elem type - see vt_t(7) */ +#define GVT_ELEM_TYPE pcb_pstk_tshape_t + +/* Type that represents array lengths - see vt_t(7) */ +#define GVT_SIZE_TYPE size_t + +/* Below this length, always double allocation size when the array grows */ +#define GVT_DOUBLING_THRS 32 + +/* Initial array size when the first element is written */ +#define GVT_START_SIZE 6 + +/* Optional prefix for function definitions (e.g. static inline) */ +#define GVT_FUNC + +/* Enable this to set all new bytes ever allocated to this value - see + vt_set_new_bytes_to(7) */ +#define GVT_SET_NEW_BYTES_TO 0 + + +/* Include the actual header implementation */ +#include + +/* Memory allocator - see vt_allocation(7) */ +#define GVT_REALLOC(vect, ptr, size) realloc(ptr, size) +#define GVT_FREE(vect, ptr) free(ptr) + +/* clean up #defines */ +#include + +#endif Index: tags/2.1.2/src/vtr0.c =================================================================== --- tags/2.1.2/src/vtr0.c (nonexistent) +++ tags/2.1.2/src/vtr0.c (revision 24813) @@ -0,0 +1,3 @@ +#define GVT_DONT_UNDEF +#include "vtr0.h" +#include Index: tags/2.1.2/src/vtr0.h =================================================================== --- tags/2.1.2/src/vtr0.h (nonexistent) +++ tags/2.1.2/src/vtr0.h (revision 24813) @@ -0,0 +1,31 @@ +#ifndef VTR0_H +#define VTR0_H + +#include "config.h" +#include +#include + +typedef struct pcb_range_s { + pcb_coord_t begin, end; + union { + long l; + pcb_coord_t c; + double d; + void *ptr; + } data[4]; +} pcb_range_t; + +#define GVT(x) vtr0_ ## x +#define GVT_ELEM_TYPE pcb_range_t +#define GVT_SIZE_TYPE size_t +#define GVT_DOUBLING_THRS 4096 +#define GVT_START_SIZE 32 +#define GVT_FUNC +#define GVT_SET_NEW_BYTES_TO 0 + +#include +#define GVT_REALLOC(vect, ptr, size) realloc(ptr, size) +#define GVT_FREE(vect, ptr) free(ptr) +#include + +#endif Index: tags/2.1.2/src/vtroutestyle.c =================================================================== --- tags/2.1.2/src/vtroutestyle.c (nonexistent) +++ tags/2.1.2/src/vtroutestyle.c (revision 24813) @@ -0,0 +1,3 @@ +#define GVT_DONT_UNDEF +#include "vtroutestyle.h" +#include Index: tags/2.1.2/src/vtroutestyle.h =================================================================== --- tags/2.1.2/src/vtroutestyle.h (nonexistent) +++ tags/2.1.2/src/vtroutestyle.h (revision 24813) @@ -0,0 +1,83 @@ +#ifndef PCB_VTROUTESTYLE_H +#define PCB_VTROUTESTYLE_H +#include +#include +#include "unit.h" +#include "attrib.h" +#include "global_typedefs.h" + +/* Elem=RouteStyle; init=0 */ + +typedef struct { + pcb_coord_t Thick; /* line thickness */ + pcb_coord_t textt; /* text thickness */ + pcb_coord_t texts; /* text scale */ + pcb_coord_t Clearance; /* min. separation from other nets */ + pcb_cardinal_t via_proto; /* via padstack prototype ID */ + int via_proto_set; /* 1 if via_proto is set/valid, 0 for old file formats */ + pcb_coord_t Diameter, Hole; /* OBSOLETE: via diameter and drill hole; kept for compatibility with old file formats (lihata board v1..v4) */ + char name[32]; /* fixed length name to save malloc/free */ + pcb_attribute_list_t attr; +} pcb_route_style_t; + +/* all public symbols are wrapped in GVT() - see vt_t(7) */ +#define GVT(x) vtroutestyle_ ## x +#define HAVE_VTROUTESTYLE_T + +/* Array elem type - see vt_t(7) */ +#define GVT_ELEM_TYPE pcb_route_style_t + +/* Type that represents array lengths - see vt_t(7) */ +#define GVT_SIZE_TYPE size_t + +/* Below this length, always double allocation size when the array grows */ +#define GVT_DOUBLING_THRS 16 + +/* Initial array size when the first element is written */ +#define GVT_START_SIZE 4 + +/* Optional terminator; when present, it is always appended at the end - see + vt_term(7)*/ +/* #define GVT_TERM '\0' */ + +/* Optional prefix for function definitions (e.g. static inline) */ +#define GVT_FUNC + +/* Enable this to set all new bytes ever allocated to this value - see + vt_set_new_bytes_to(7) */ +#define GVT_SET_NEW_BYTES_TO 0 + +/* Enable GVT_INIT_ELEM_FUNC and an user configured function is called + for each new element allocated (even between used and alloced). + See vt_init_elem(7) */ +/*#define GVT_INIT_ELEM_FUNC*/ + +/* Enable GVT_ELEM_CONSTRUCTOR and an user configured function is called + for each element that is getting within the range of ->used. + See vt_construction(7) */ +/*#define GVT_ELEM_CONSTRUCTOR */ + +/* Enable GVT_ELEM_DESTRUCTOR and an user configured function is called + for each element that was once constructed and now getting beyond ->used. + See vt_construction(7) */ +/*#define GVT_ELEM_DESTRUCTOR */ + +/* Enable GVT_ELEM_COPY and an user configured function is called + for copying elements into the array. + See vt_construction(7) */ +/*#define GVT_ELEM_COPY */ + +/* Optional extra fields in the vector struct - see vt_user_fields(7) */ +/* #define GVT_USER_FIELDS int foo; char bar[12]; */ + +/* Include the actual header implementation */ +#include + +/* Memory allocator - see vt_allocation(7) */ +#define GVT_REALLOC(vect, ptr, size) realloc(ptr, size) +#define GVT_FREE(vect, ptr) free(ptr) + +/* clean up #defines */ +#include + +#endif Index: tags/2.1.2/src =================================================================== --- tags/2.1.2/src (nonexistent) +++ tags/2.1.2/src (revision 24813) Property changes on: tags/2.1.2/src ___________________________________________________________________ Added: svn:externals ## -0,0 +1 ## + Index: tags/2.1.2/src_3rd/Makefile.conf =================================================================== --- tags/2.1.2/src_3rd/Makefile.conf (nonexistent) +++ tags/2.1.2/src_3rd/Makefile.conf (revision 24813) @@ -0,0 +1 @@ +# placeholder for genvector Index: tags/2.1.2/src_3rd/README =================================================================== --- tags/2.1.2/src_3rd/README (nonexistent) +++ tags/2.1.2/src_3rd/README (revision 24813) @@ -0,0 +1 @@ +3rd party software libs Index: tags/2.1.2/src_3rd/libuhpgl/Makefile =================================================================== --- tags/2.1.2/src_3rd/libuhpgl/Makefile (nonexistent) +++ tags/2.1.2/src_3rd/libuhpgl/Makefile (revision 24813) @@ -0,0 +1,4 @@ +CFLAGS = -Wall -g -ansi -pedantic + +parse.o: parse.c uhpgl_math.h libuhpgl.h arc_iterate.h + Index: tags/2.1.2/src_3rd/libuhpgl/README =================================================================== --- tags/2.1.2/src_3rd/libuhpgl/README (nonexistent) +++ tags/2.1.2/src_3rd/libuhpgl/README (revision 24813) @@ -0,0 +1,15 @@ +The micro HP-GL library +~~~~~~~~~~~~~~~~~~~~~~~ + +Libuhpgl is a small, portable (C89) library for parsing and generating +HP-GL data. It is designed for use as a converter in an application that +has its own 2d object model. + +To accomodate to the object model of the application, the lib offers different +options for the drawing primitives, e.g. the application may chose whether to +support filled polygons or vurves (arcs, circles). The lib loads a sequence +of HP-GL instructions, builds a complex object (such as a polygon) in memory +and passes it to the application when all details of the object is already +known. + + Index: tags/2.1.2/src_3rd/libuhpgl/arc_iterate.h =================================================================== --- tags/2.1.2/src_3rd/libuhpgl/arc_iterate.h (nonexistent) +++ tags/2.1.2/src_3rd/libuhpgl/arc_iterate.h (revision 24813) @@ -0,0 +1,125 @@ +/* + libuhpgl - the micro HP-GL library + Copyright (C) 2017 Tibor 'Igor2' Palinkas + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + + This library is part of pcb-rnd: http://repo.hu/projects/pcb-rnd +*/ + +/* Arc approximation loops for internal use - not intended to be + included by the library user */ + +#ifndef LIBUHPGL_ARC_ITERATE_H +#define LIBUHPGL_ARC_ITERATE_H + +/* Arc approximation loops */ + +typedef struct uhpgl_arc_it_s { + const uhpgl_arc_t *arc; + double step; /* stepping angle */ + double ang; + uhpgl_point_t pt; + int remain; +} uhpgl_arc_it_t; + +/* Do not call directly. Set up iterator for angle based steps. */ +static uhpgl_point_t *uhpgl_arc_it_first_ang(uhpgl_arc_it_t *it, const uhpgl_arc_t *arc, double step) +{ + double minstep = 360.0 / (arc->r*CONST_PI*2.0); + + if (step < 0) + step = -step; + else if (step == 0) + step = 5; + + if (step < minstep) + step = minstep; + + if (arc->deltaa < 0) + step = -step; + + it->arc = arc; + it->step = step; + it->remain = floor(arc->deltaa / step)+2; + + it->pt = arc->startp; + it->ang = arc->starta; + return &it->pt; +} + +/* Do not call directly. Set up iterator for radius error based steps. */ +static uhpgl_point_t *uhpgl_arc_it_first_err(uhpgl_arc_it_t *it, const uhpgl_arc_t *arc, double err) +{ + double step; + + if (err > arc->r / 4) + return uhpgl_arc_it_first_ang(it, arc, 0); + + step = RAD2DEG(acos((arc->r - err) / arc->r) * 2); + if (step < 0) + step = -step; + + if (step < 0.1) + step = 0.1; + else if (step > 15) + step = 15; + + return uhpgl_arc_it_first_ang(it, arc, step); +} + +/* Start an iteration, return the first point */ +static uhpgl_point_t *uhpgl_arc_it_first(uhpgl_ctx_t *ctx, uhpgl_arc_it_t *it, const uhpgl_arc_t *arc, double resolution) +{ + if (ctx->state.ct == 0) + return uhpgl_arc_it_first_ang(it, arc, resolution); + return uhpgl_arc_it_first_err(it, arc, resolution); +} + +/* Return the next point or NULL if there are no more points */ +static uhpgl_point_t *uhpgl_arc_it_next(uhpgl_arc_it_t *it) +{ + uhpgl_coord_t x, y; + it->remain--; + switch(it->remain) { + case 0: /* beyond the endpoint */ + return NULL; + case 1: /* at the endpoint */ + last_pt:; + /* special case: endpoint reached in the previous iterationm remaining correction path is 0 long */ + if ((it->pt.x == it->arc->endp.x) && (it->pt.y == it->arc->endp.y)) + return NULL; + it->pt = it->arc->endp; + return &it->pt; + default: + for(;;) { + it->ang += it->step; + x = ROUND((double)it->arc->center.x + it->arc->r * cos(DEG2RAD(it->ang))); + y = ROUND((double)it->arc->center.y + it->arc->r * sin(DEG2RAD(it->ang))); + if ((it->pt.x != x) || (it->pt.y != y)) { + it->pt.x = x; + it->pt.y = y; + return &it->pt; + } + it->remain--; + if (it->remain == 1) + goto last_pt; + } + } + return NULL; +} + +#endif Index: tags/2.1.2/src_3rd/libuhpgl/examples/Makefile =================================================================== --- tags/2.1.2/src_3rd/libuhpgl/examples/Makefile (nonexistent) +++ tags/2.1.2/src_3rd/libuhpgl/examples/Makefile (revision 24813) @@ -0,0 +1,7 @@ +CFLAGS = -I../.. +CFLAGS += -Wall -g -ansi -pedantic +LDFLAGS = -lm + +dump_hpgl: dump_hpgl.o ../parse.o + +dump_hpgl.o: dump_hpgl.c Index: tags/2.1.2/src_3rd/libuhpgl/examples/aa.hpgl =================================================================== --- tags/2.1.2/src_3rd/libuhpgl/examples/aa.hpgl (nonexistent) +++ tags/2.1.2/src_3rd/libuhpgl/examples/aa.hpgl (revision 24813) @@ -0,0 +1,10 @@ +IN; +SP1; +CT1; +PU; +PA5,0; +PD; +AA5,5,-180,0.1; +PA15,10; +AA15,5,-180,0.4; +PA5,0; Index: tags/2.1.2/src_3rd/libuhpgl/examples/circ.hpgl =================================================================== --- tags/2.1.2/src_3rd/libuhpgl/examples/circ.hpgl (nonexistent) +++ tags/2.1.2/src_3rd/libuhpgl/examples/circ.hpgl (revision 24813) @@ -0,0 +1,7 @@ +IN; + +SP1; + +PA50,50; +CI20,10; + Index: tags/2.1.2/src_3rd/libuhpgl/examples/dump_hpgl.c =================================================================== --- tags/2.1.2/src_3rd/libuhpgl/examples/dump_hpgl.c (nonexistent) +++ tags/2.1.2/src_3rd/libuhpgl/examples/dump_hpgl.c (revision 24813) @@ -0,0 +1,102 @@ +/* + libuhpgl - the micro HP-GL library + Copyright (C) 2017 Tibor 'Igor2' Palinkas + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + + This library is part of pcb-rnd: http://repo.hu/projects/pcb-rnd +*/ + +#include +#include +#include +#include + + +static int dump_line(uhpgl_ctx_t *ctx, uhpgl_line_t *line) +{ + printf("line {%d}: %ld;%ld %ld;%ld\n", line->pen, line->p1.x, line->p1.y, line->p2.x, line->p2.y); + return 0; +} + +static void dump_arc_(uhpgl_ctx_t *ctx, uhpgl_arc_t *arc, const char *type) +{ + printf("%s {%d}: %ld;%ld;%ld %f->%f (%f) (%ld;%ld->%ld;%ld)\n", type, arc->pen, + arc->center.x, arc->center.y, arc->r, + arc->starta, arc->enda, arc->deltaa, + arc->startp.x, arc->startp.y, arc->endp.x, arc->endp.y); +} + +static int dump_arc(uhpgl_ctx_t *ctx, uhpgl_arc_t *arc) +{ + dump_arc_(ctx, arc, "arc"); + return 0; +} + + +static int dump_circ(uhpgl_ctx_t *ctx, uhpgl_arc_t *circ) +{ + printf("circ {%d}: %ld;%ld;%ld\n", circ->pen, + circ->center.x, circ->center.y, circ->r); + return 0; +} + +static int dump_poly(uhpgl_ctx_t *ctx, uhpgl_poly_t *poly) +{ +/*#warning TODO*/ + return 0; +} + +static int dump_wedge(uhpgl_ctx_t *ctx, uhpgl_wedge_t *wedge) +{ + dump_arc_(ctx, &wedge->arc, "wedge"); + return 0; +} + +static int dump_rect(uhpgl_ctx_t *ctx, uhpgl_rect_t *rect) +{ + printf("rect {%d}: %ld;%ld %ld;%ld\n", rect->pen, rect->p1.x, rect->p1.y, rect->p2.x, rect->p2.y); + return 0; +} + +static int print_error(uhpgl_ctx_t *ctx) +{ + fprintf(stderr, "Error on stdin:%d.%d: %s\n", ctx->error.line, ctx->error.col, ctx->error.msg); + return -1; +} + +int main() +{ + uhpgl_ctx_t ctx; + + memset(&ctx, 0, sizeof(ctx)); + + ctx.conf.line = dump_line; + ctx.conf.arc = dump_arc; + ctx.conf.circ = dump_circ; + ctx.conf.poly = dump_poly; + ctx.conf.wedge = dump_wedge; + ctx.conf.rect = dump_rect; + + if (uhpgl_parse_open(&ctx) != 0) + return print_error(&ctx); + if (uhpgl_parse_file(&ctx, stdin) != 0) + return print_error(&ctx); + if (uhpgl_parse_close(&ctx) != 0) + return print_error(&ctx); + return 0; +} + Index: tags/2.1.2/src_3rd/libuhpgl/examples/rect.hpgl =================================================================== --- tags/2.1.2/src_3rd/libuhpgl/examples/rect.hpgl (nonexistent) +++ tags/2.1.2/src_3rd/libuhpgl/examples/rect.hpgl (revision 24813) @@ -0,0 +1,13 @@ +IN; + +SP1; + +PA0,0; + +PD; +PA200,0; +PA200,200; +PA0,200; +PR0,-200; +PU; + Index: tags/2.1.2/src_3rd/libuhpgl/examples/rect_bound.hpgl =================================================================== --- tags/2.1.2/src_3rd/libuhpgl/examples/rect_bound.hpgl (nonexistent) +++ tags/2.1.2/src_3rd/libuhpgl/examples/rect_bound.hpgl (revision 24813) @@ -0,0 +1,13 @@ +IN; +IP0,0,4000,4000; +SC0,200,0,200; +SP1; +PA0,0; + +PD; +PA200,0; +PA200,200; +PA0,200; +PA0,0; +PU; + Index: tags/2.1.2/src_3rd/libuhpgl/examples/vararg.hpgl =================================================================== --- tags/2.1.2/src_3rd/libuhpgl/examples/vararg.hpgl (nonexistent) +++ tags/2.1.2/src_3rd/libuhpgl/examples/vararg.hpgl (revision 24813) @@ -0,0 +1,9 @@ +IN; +SP1; +PU; +PA10,10; +PD; +PD20,10,20,20,10,20,10,10; +PR2,2,-3,3; +PA5,5,3,7; +PU; Index: tags/2.1.2/src_3rd/libuhpgl/libuhpgl.h =================================================================== --- tags/2.1.2/src_3rd/libuhpgl/libuhpgl.h (nonexistent) +++ tags/2.1.2/src_3rd/libuhpgl/libuhpgl.h (revision 24813) @@ -0,0 +1,151 @@ +/* + libuhpgl - the micro HP-GL library + Copyright (C) 2017 Tibor 'Igor2' Palinkas + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + + This library is part of pcb-rnd: http://repo.hu/projects/pcb-rnd +*/ + +#ifndef LIBUHPGL_H +#define LIBUHPGL_H + +#include + +/*** low level types ***/ +typedef long int uhpgl_coord_t; /* 1 unit is 0.025 mm */ +typedef double uhpgl_angle_t; /* in degrees; absolute angles are [0..360], relative angles are [-360..+360] */ + +typedef enum uhpgl_obj_type_s { + UHPGL_OBJ_INVALID, + UHPGL_OBJ_LINE, + UHPGL_OBJ_ARC, + UHPGL_OBJ_WEDGE, + UHPGL_OBJ_RECT, + UHPGL_OBJ_POLY +} uhpgl_obj_type_t; + +typedef enum uhpgl_fill_type_s { + UHPGL_FILL_NONE, + UHPGL_FILL_PAINT1, + UHPGL_FILL_PAINT2, + UHPGL_FILL_SINGLE, + UHPGL_FILL_CROSS +} uhpgl_fill_type_t; + +typedef struct uhpgl_fill_stroke_s { + uhpgl_fill_type_t type; /* UHPGL_FILL_NONE if no fill */ + uhpgl_coord_t spacing; + uhpgl_angle_t angle; + double pen_thick; + unsigned stroke:1; /* 1 if stroked */ +} uhpgl_fill_stroke_t; + +typedef struct uhpgl_point_s { + uhpgl_coord_t x, y; +} uhpgl_point_t; + +typedef struct uhpgl_obj_s uhpgl_obj_t; + +/*** drawing objects ***/ +typedef struct uhpgl_line_s { + int pen; + uhpgl_point_t p1, p2; +} uhpgl_line_t; + +typedef struct uhpgl_arc_s { + int pen; + uhpgl_point_t center; + uhpgl_coord_t r; + uhpgl_point_t startp, endp; + uhpgl_angle_t starta, enda, deltaa; +} uhpgl_arc_t; + +typedef struct uhpgl_wedge_s { + int pen; + uhpgl_arc_t arc; + uhpgl_fill_stroke_t fill_stroke; +} uhpgl_wedge_t; + +typedef struct uhpgl_rect_s { + int pen; + uhpgl_point_t p1, p2; /* p1 is the minimal x;y and p2 is the maximal x;y */ + uhpgl_fill_stroke_t fill_stroke; +} uhpgl_rect_t; + +typedef struct uhpgl_poly_s { + int pen; + uhpgl_point_t bb1, bb2; /* bounding box; bb1 is the minimal x;y and bb2 is the maximal x;y */ + uhpgl_obj_t *outline; /* outer contour (linked list of non-poly objects) */ + int num_holes; + uhpgl_obj_t **holes; /* inner/hole contours (each is a linked list of non-poly objects) */ + uhpgl_fill_stroke_t fill_stroke; +} uhpgl_poly_t; + +/*** common object and context ***/ +struct uhpgl_obj_s { + uhpgl_obj_type_t type; + union { + uhpgl_line_t line; + uhpgl_arc_t arc; + uhpgl_wedge_t wedge; + uhpgl_rect_t rect; + uhpgl_poly_t poly; + } obj; + uhpgl_obj_t *next; /* singly linked list of objects, NULL terminates the list */ +}; + +typedef struct uhpgl_ctx_s uhpgl_ctx_t; +struct uhpgl_ctx_s { + /* configuration: read-only for the lib, written by the caller */ + struct { + unsigned approx_curve_in_poly:1; /* if 1, use line approx in polygons even if arc() is non-NULL */ + + /* callbacks for objects found; if returns non-zero, parsing is abandoned */ + int (*line)(uhpgl_ctx_t *ctx, uhpgl_line_t *line); /* must NOT be NULL */ + int (*arc)(uhpgl_ctx_t *ctx, uhpgl_arc_t *arc); /* if NULL, use line() approx */ + int (*circ)(uhpgl_ctx_t *ctx, uhpgl_arc_t *circ); /* if NULL, use arc() */ + int (*poly)(uhpgl_ctx_t *ctx, uhpgl_poly_t *poly); /* if NULL, use draw the outline only (even for filled polygons) */ + int (*wedge)(uhpgl_ctx_t *ctx, uhpgl_wedge_t *wedge); /* if NULL, use polygon() */ + int (*rect)(uhpgl_ctx_t *ctx, uhpgl_rect_t *rect); /* if NULL, use polygon() */ + } conf; + + /* current state: read-only for the caller, written by the lib */ + struct { + int pen; /* selected pen [0..255] */ + int pen_speed; + unsigned pen_down:1; /* whether pen is down (drawing) */ + uhpgl_point_t at; /* last known coordinate of the pen */ + int ct; /* Chord Tolerance */ + uhpgl_fill_stroke_t fill; + + /* last char parsed */ + size_t offs; + size_t line, col; + } state; + + /* parser error report: written by the lib, read-only for the caller */ + struct { + size_t offs; + size_t line, col; + const char *msg; + } error; + + void *parser; /* opaque parser data */ + void *user_data; /* only used by the caller */ +}; + +#endif Index: tags/2.1.2/src_3rd/libuhpgl/parse.c =================================================================== --- tags/2.1.2/src_3rd/libuhpgl/parse.c (nonexistent) +++ tags/2.1.2/src_3rd/libuhpgl/parse.c (revision 24813) @@ -0,0 +1,503 @@ +/* + libuhpgl - the micro HP-GL library + Copyright (C) 2017 Tibor 'Igor2' Palinkas + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + + This library is part of pcb-rnd: http://repo.hu/projects/pcb-rnd +*/ + +#include +#include +#include "uhpgl_math.h" +#include "libuhpgl.h" +#include "parse.h" +#include "arc_iterate.h" + +#define inst2num(s1, s2) ((((int)s1) << 8) | (int)s2) + +typedef enum state_e { + ST_IDLE, + ST_INST, + ST_INST_END, + ST_NUMBERS_OR_END, + ST_SPC_NUMBERS_OR_END, + ST_NUMBERS, + ST_ESCAPED +} state_t; + +typedef struct { + size_t token_offs; + size_t token_line, token_col; + char inst[2]; + char token[32]; + int len; /* token length */ + + double argv[32]; + int argc; + + state_t state; + unsigned error:1; + unsigned eof:1; +} parse_t; + +static int error(uhpgl_ctx_t *ctx, const char *msg) +{ + parse_t *p = ctx->parser; + + ctx->error.offs = p->token_offs; + ctx->error.line = p->token_line; + ctx->error.col = p->token_col; + ctx->error.msg = msg; + + p->error = 1; + return -1; +} + +static const char *err_beyond_end = "Character after EOF"; +static const char *err_not_open = "Parser is not open"; + +#define decl_parser_ctx \ + parse_t *p = ctx->parser; \ + if (p == NULL) {\ + ctx->error.msg = err_not_open; \ + return -1; \ + } \ + if (p->error) \ + return -1; \ + if (p->eof) \ + return error(ctx, err_beyond_end); + +int uhpgl_parse_str(uhpgl_ctx_t *ctx, const char *str) +{ + int ret; + decl_parser_ctx; + + for(;*str != '\0'; str++) { + ret = uhpgl_parse_char(ctx, *str); + if (ret != 0) + return ret; + } + return 0; +} + +int uhpgl_parse_file(uhpgl_ctx_t *ctx, FILE *f) +{ + int ret, c; + decl_parser_ctx; + + while((c = fgetc(f)) != EOF) { + ret = uhpgl_parse_char(ctx, c); + if (ret != 0) + return ret; + } + return 0; +} + +int uhpgl_parse_open(uhpgl_ctx_t *ctx) +{ + if (ctx->parser != NULL) { + ctx->error.msg = "Parser already open"; + return -1; + } + ctx->parser = calloc(sizeof(parse_t), 1); + ctx->state.offs = 0; + ctx->state.line = 1; + ctx->state.col = 1; + return 0; +} + +int uhpgl_parse_close(uhpgl_ctx_t *ctx) +{ + decl_parser_ctx; + if (p->state != ST_IDLE) { + error(ctx, "premature end of stream"); + free(p); + ctx->parser = NULL; + return -1; + } + + free(p); + ctx->parser = NULL; + return 0; +} + +/*** execute ***/ +static void move_to(uhpgl_ctx_t *ctx, uhpgl_coord_t x, uhpgl_coord_t y) +{ + ctx->state.at.x = x; + ctx->state.at.y = y; +} + +static int draw_line(uhpgl_ctx_t *ctx, uhpgl_coord_t x1, uhpgl_coord_t y1, uhpgl_coord_t x2, uhpgl_coord_t y2) +{ + uhpgl_line_t line; + line.pen = ctx->state.pen; + line.p1.x = x1; + line.p1.y = y1; + line.p2.x = x2; + line.p2.y = y2; + move_to(ctx, x2, y2); + return ctx->conf.line(ctx, &line); +} + +static int draw_arc_(uhpgl_ctx_t *ctx, uhpgl_arc_t *arc, double resolution) +{ + uhpgl_arc_it_t it; + int cnt; + uhpgl_point_t *p, prev; + + move_to(ctx, arc->endp.x, arc->endp.y); + if (ctx->conf.arc != NULL) + return ctx->conf.arc(ctx, arc); + + for(cnt = 0, p = uhpgl_arc_it_first(ctx, &it, arc, resolution); p != NULL; cnt++, p = uhpgl_arc_it_next(&it)) { + if (cnt > 0) { + if (draw_line(ctx, prev.x, prev.y, p->x, p->y) != 0) + return -1; + } + prev = *p; + } + + return 0; +} + +static int draw_arc(uhpgl_ctx_t *ctx, uhpgl_coord_t cx, uhpgl_coord_t cy, double da, double res) +{ + uhpgl_arc_t arc; + arc.pen = ctx->state.pen; + arc.center.x = cx; + arc.center.y = cy; + arc.startp.x = ctx->state.at.x; + arc.startp.y = ctx->state.at.y; + arc.r = ROUND(DDIST(arc.startp.y - arc.center.y, arc.startp.x - arc.center.x)); + arc.deltaa = da; + + arc.starta = RAD2DEG(atan2(arc.startp.y - arc.center.y, arc.startp.x - arc.center.x)); + arc.enda = arc.starta + da; + + arc.endp.x = ROUND((double)cx + arc.r * cos(DEG2RAD(arc.enda))); + arc.endp.y = ROUND((double)cy + arc.r * sin(DEG2RAD(arc.enda))); + + return draw_arc_(ctx, &arc, res); +} + + +static int draw_circ(uhpgl_ctx_t *ctx, uhpgl_coord_t cx, uhpgl_coord_t cy, uhpgl_coord_t r, uhpgl_coord_t res) +{ + uhpgl_arc_t arc; + arc.pen = ctx->state.pen; + arc.center.x = cx; + arc.center.y = cy; + arc.r = r; + arc.startp.x = cx + r; + arc.startp.y = cy; + arc.endp.x = cx + r; + arc.endp.y = cy; + arc.starta = 0; + arc.enda = 360; + arc.deltaa = 360; + if (ctx->conf.circ != NULL) { + move_to(ctx, arc.endp.x, arc.endp.y); + return ctx->conf.circ(ctx, &arc); + } + return draw_arc_(ctx, &arc, res); +} + + +/*** the actual parser: high level (grammar) ***/ +static int parse_inst(uhpgl_ctx_t *ctx) +{ + parse_t *p = ctx->parser; + p->inst[0] = p->token[0]; + p->inst[1] = p->token[1]; + switch(inst2num(p->inst[0], p->inst[1])) { + case inst2num('I','N'): + /* ignore */ + p->state = ST_INST_END; + return 0; + case inst2num('P','U'): + ctx->state.pen_down = 0; + p->state = ST_NUMBERS_OR_END; + return 0; + case inst2num('P','D'): + ctx->state.pen_down = 1; + p->state = ST_NUMBERS_OR_END; + return 0; + case inst2num('W','U'): + case inst2num('P','W'): + case inst2num('L','T'): + p->state = ST_NUMBERS_OR_END; + return 0; + + case inst2num('P','A'): + case inst2num('P','R'): + case inst2num('S','P'): + case inst2num('C','T'): + case inst2num('C','I'): + case inst2num('A','A'): + case inst2num('A','R'): + case inst2num('F','T'): + case inst2num('P','T'): +/* + case inst2num('L','T'): + case inst2num('W','G'): + case inst2num('E','W'): + case inst2num('R','A'): + case inst2num('E','A'): + case inst2num('R','R'): + case inst2num('E','R'): + case inst2num('P','M'): + case inst2num('E','P'): + case inst2num('F','P'): +*/ + /* prepare to read coords */ + p->state = ST_NUMBERS; + return 0; + case inst2num('V','S'): + p->state = ST_SPC_NUMBERS_OR_END; + return 0; + } + return error(ctx, "unimplemented instruction"); +} + +/* Consume all current arguments and report end or go on for the next set + of arguments; useful for vararg instructions like PA */ +#define shift_all() \ +do { \ + if (!is_last) {\ + p->argc = 0; \ + p->state = ST_NUMBERS; \ + } \ + else \ + p->state = ST_INST_END; \ +} while(0) + +static int parse_coord(uhpgl_ctx_t *ctx, double coord, int is_last) +{ + parse_t *p = ctx->parser; + p->argv[p->argc] = coord; + p->argc++; + switch(inst2num(p->inst[0], p->inst[1])) { + case inst2num('S','P'): + if ((coord < 0) || (coord > 255)) + return error(ctx, "invalid pen index"); + ctx->state.pen = coord; + p->state = ST_INST_END; + return 0; + case inst2num('C','T'): + ctx->state.ct = coord; + p->state = ST_INST_END; + return 0; + case inst2num('P','U'): + case inst2num('P','A'): + case inst2num('P','D'): + p->state = ST_NUMBERS; /* make sure to load even a single pair */ + if (p->argc == 2) { + if (ctx->state.pen_down) { + if (draw_line(ctx, ctx->state.at.x, ctx->state.at.y, p->argv[0], p->argv[1]) < 0) + return -1; + } + else + move_to(ctx, p->argv[0], p->argv[1]); + shift_all(); + } + return 0; + case inst2num('P','R'): + if (p->argc == 2) { + if (ctx->state.pen_down) { + if (draw_line(ctx, ctx->state.at.x, ctx->state.at.y, ctx->state.at.x + p->argv[0], ctx->state.at.y + p->argv[1]) < 0) + return -1; + } + else + move_to(ctx, ctx->state.at.x + p->argv[0], ctx->state.at.y + p->argv[1]); + shift_all(); + } + return 0; + case inst2num('C','I'): + if ((p->argc == 2) || (is_last)) { + p->state = ST_INST_END; + if (draw_circ(ctx, ctx->state.at.x, ctx->state.at.y, p->argv[0], (p->argc == 2 ? p->argv[1] : -1)) < 0) + return -1; + } + return 0; + case inst2num('A','A'): + if ((p->argc == 4) || (is_last)) { + p->state = ST_INST_END; + if (draw_arc(ctx, p->argv[0], p->argv[1], p->argv[2], (p->argc == 4 ? p->argv[3] : 0)) < 0) + return -1; + } + return 0; + case inst2num('A','R'): + if ((p->argc == 4) || (is_last)) { + p->state = ST_INST_END; + if (draw_arc(ctx, ctx->state.at.x + p->argv[0], ctx->state.at.y + p->argv[1], p->argv[2], (p->argc == 4 ? p->argv[3] : 0)) < 0) + return -1; + } + return 0; + case inst2num('F','T'): + if (is_last) { + switch(p->argc) { + case 3: ctx->state.fill.angle = p->argv[2]; + case 2: ctx->state.fill.spacing = p->argv[1]; + case 1: ctx->state.fill.type = p->argv[0]; break; + case 0: ctx->state.fill.type = 1; break; + default: + return error(ctx, "Wrong number of arguments (expected 0, 1, 2 or 3)"); + } + } + return 0; + case inst2num('P','T'): + if ((p->argc == 1) && (is_last)) { + ctx->state.fill.pen_thick = p->argv[0]; + return 0; + } + return error(ctx, "PT needs 1 argument"); + case inst2num('L','T'): + if (is_last) { + if ((p->argc <= 3) && (is_last)) + return 0; + return error(ctx, "LT needs at most 3 argument"); + } + return 0; + case inst2num('V','S'): + if (is_last) { + if ((p->argc == 1) || (p->argc == 2)) { + ctx->state.pen_speed = p->argv[0]; + p->state = ST_INST_END; + return 0; + } + printf("argc=%d\n", p->argc); + return error(ctx, "VS needs 1 or 2 arguments"); + } + return 0; + case inst2num('W','U'): /* unknown */ + if (is_last) { + if (p->argc == 1) + return 0; + return error(ctx, "WU needs 1 argument"); + } + return 0; + case inst2num('P','W'): /* unknown; maybe pen width? */ + if (is_last) { + if (p->argc == 2) + return 0; + return error(ctx, "PW needs 2 arguments"); + } + return 0; + } + return error(ctx, "unimplemented coord instruction"); +} + +/*** the actual parser: low level (tokens) ***/ +#define token_start() \ +do { \ + p->len = 0; \ + p->token_offs = ctx->state.offs; \ + p->token_line = ctx->state.line; \ + p->token_col = ctx->state.col-1; \ +} while(0) + +int uhpgl_parse_char(uhpgl_ctx_t *ctx, int c) +{ + int res; + decl_parser_ctx; + + ctx->state.col++; + switch(c) { + case EOF: + p->eof = 1; + return 0; + case '\n': + ctx->state.line++; + ctx->state.col = 1; + return 0; + case '\r': + case '\t': + return 0; + case ' ': + if ((p->state == ST_NUMBERS) || (p->state == ST_NUMBERS_OR_END)) + break; + return 0; + } + + switch(p->state) { + case ST_IDLE: + if (c == 0x1B) { /* starting at ESC, spans till the first ':' - ignore it */ + p->state = ST_ESCAPED; + return 0; + } + if (c == ';') /* be liberal: accept multiple terminators or empty instructions */ + return 0; + p->state = ST_INST; + p->argc = 0; + token_start(); + /* fall through to read the first char */ + case ST_INST: + if (!isalpha(c)) + return error(ctx, "Invalid character in instruction (must be alpha)"); + p->token[p->len] = toupper(c); + p->len++; + if (p->len == 2) { + p->len = 0; + return parse_inst(ctx); + } + return 0; + case ST_INST_END: + got_end:; + if (c != ';') + return error(ctx, "Expected semicolon to terminate instruction"); + p->state = ST_IDLE; + return 0; + case ST_SPC_NUMBERS_OR_END: + if (c == ' ') + return 0; + p->state = ST_NUMBERS; + /* fall thru: number */ + case ST_NUMBERS_OR_END: + if (c == ';') + goto got_end; + /* fall thru: number */ + case ST_NUMBERS: + if ((c == ',') || (c == ' ') || (c == ';')) { + char *end; + int last = (c == ';'); + p->token[p->len] = '\0'; + res = parse_coord(ctx, strtod(p->token, &end), last); + if (*end != '\0') + return error(ctx, "Invalid numeric format"); + token_start(); + if ((p->state == ST_INST_END) && (!last)) + return error(ctx, "Expected semicolon"); + else if ((p->state != ST_INST_END) && (last)) + return error(ctx, "Premature semicolon"); + else if ((p->state == ST_INST_END) && (last)) + p->state = ST_IDLE; /* wanted to finish and finished */ + return res; + } + if (isdigit(c) || (c == '.') || ((c == '-') && (p->len == 0))) { + p->token[p->len] = c; + p->len++; + return 0; + } + return error(ctx, "Expected digit or separator in number"); + case ST_ESCAPED: + if (c == ':') + p->state = ST_IDLE; + return 0; + } + return error(ctx, "Internal error: broken state machine"); +} Index: tags/2.1.2/src_3rd/libuhpgl/parse.h =================================================================== --- tags/2.1.2/src_3rd/libuhpgl/parse.h (nonexistent) +++ tags/2.1.2/src_3rd/libuhpgl/parse.h (revision 24813) @@ -0,0 +1,45 @@ +/* + libuhpgl - the micro HP-GL library + Copyright (C) 2017 Tibor 'Igor2' Palinkas + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + + This library is part of pcb-rnd: http://repo.hu/projects/pcb-rnd +*/ + + +#ifndef LIBUHPGL_PRASE_H +#define LIBUHPGL_PRASE_H + +#include +#include "libuhpgl.h" + +/* Shall be called before parsing starts (call uhpgl_parse_open() at the end) */ +int uhpgl_parse_open(uhpgl_ctx_t *ctx); + +/* Parse next character of a stream; c may be EOF; returns 0 on success */ +int uhpgl_parse_char(uhpgl_ctx_t *ctx, int c); + +/* Parse next portion of a stream from a string; returns 0 on success */ +int uhpgl_parse_str(uhpgl_ctx_t *ctx, const char *str); + +/* Parse next portion of a stream from a file; returns 0 on success */ +int uhpgl_parse_file(uhpgl_ctx_t *ctx, FILE *f); + +/* Shall be called after the last portion parsed; returns 0 on success */ +int uhpgl_parse_close(uhpgl_ctx_t *ctx); + +#endif Index: tags/2.1.2/src_3rd/libuhpgl/uhpgl_math.h =================================================================== --- tags/2.1.2/src_3rd/libuhpgl/uhpgl_math.h (nonexistent) +++ tags/2.1.2/src_3rd/libuhpgl/uhpgl_math.h (revision 24813) @@ -0,0 +1,54 @@ +/* + libuhpgl - the micro HP-GL library + Copyright (C) 2017 Tibor 'Igor2' Palinkas + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + + This library is part of pcb-rnd: http://repo.hu/projects/pcb-rnd +*/ + +/* Math helper for internal use - not intended to be included by the + library user */ + +#ifndef LIBUHPGL_MATH_H +#define LIBUHPGL_MATH_H + +#include + +#define CONST_PI 3.14159265358979323846 +#define RAD2DEG(r) ((r) * 180.0 / CONST_PI) +#define DEG2RAD(d) ((d) * CONST_PI / 180.0) +#define DDIST(dx, dy) sqrt((double)(dx)*(double)(dx) + (double)(dy)*(double)(dy)) + +/* Implementation idea borrowed from an old gcc */ +static double ROUND(double x) +{ + double t; + + if (x >= 0.0) { + t = ceil(x); + if (t - x > 0.5) + t -= 1.0; + return t; + } + + t = ceil(-x); + if ((t + x) > 0.5) + t -= 1.0; + return -t; +} + +#endif Index: tags/2.1.2/src_3rd/qparse/Makefile =================================================================== --- tags/2.1.2/src_3rd/qparse/Makefile (nonexistent) +++ tags/2.1.2/src_3rd/qparse/Makefile (revision 24813) @@ -0,0 +1,10 @@ +#CFLAGS = -Wall -Wextra -g +CFLAGS = -g + +example: example.o qparse.o + +qparse.o: qparse.c qparse.h + $(CC) -c qparse.c -o qparse.o + +clean: + rm qparse.o example example.o ; true Index: tags/2.1.2/src_3rd/qparse/example.c =================================================================== --- tags/2.1.2/src_3rd/qparse/example.c (nonexistent) +++ tags/2.1.2/src_3rd/qparse/example.c (revision 24813) @@ -0,0 +1,26 @@ +#include +#include +#include "qparse.h" + +/* Read lines of text from stdin and split them in fields using qparse. */ + +int main() +{ + char s[1024]; + while(fgets(s, sizeof(s), stdin) != NULL) { + int n, argc; + char *end, **argv; + + /* remove trailing newline (if we don't we just get an extra empty field at the end) */ + for(end = s + strlen(s) - 1; (end >= s) && ((*end == '\r') || (*end == '\n')); end--) + *end = '\0'; + + /* split and print fields */ + printf("Splitting '%s':\n", s); + argc = qparse2(s, &argv, QPARSE_DOUBLE_QUOTE | QPARSE_SINGLE_QUOTE); + for(n = 0; n < argc; n++) + printf(" [%d] '%s'\n", n, argv[n]); + qparse_free(argc, &argv); + } + return 0; +} Index: tags/2.1.2/src_3rd/qparse/qparse.c =================================================================== --- tags/2.1.2/src_3rd/qparse/qparse.c (nonexistent) +++ tags/2.1.2/src_3rd/qparse/qparse.c (revision 24813) @@ -0,0 +1,209 @@ +/* + libgpmi - General Package/Module Interface - qparse package + Copyright (C) 2006-2007, 2017 Tibor 'Igor2' Palinkas + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include +#include +#include "qparse.h" + +typedef enum qp_state_e { + qp_normal, + qp_dquote, + qp_squote, + qp_paren +} qp_state_t; + +#define qpush(chr) \ + { \ + if (buff_used >= buff_len) { \ + buff_len += 128; \ + buff = realloc(buff, buff_len); \ + } \ + buff[buff_used] = chr; \ + buff_used++; \ + } + +#define qbackslash(chr) \ + switch(chr) { \ + case 'n': qpush('\n'); break; \ + case 'r': qpush('\r'); break; \ + case 't': qpush('\t'); break; \ + case 'b': qpush('\b'); break; \ + case '"': qpush('"'); break; \ + case '\'': qpush('\''); break; \ + case ' ': qpush(' '); break; \ + case '\0': break; \ + default: \ + qpush('\\'); \ + qpush(chr); \ + } + +#define qnext() \ + { \ + if (argc >= allocated) { \ + allocated += 8; \ + argv = realloc(argv, sizeof(char *) * allocated); \ + } \ + buff[buff_used] = '\0'; \ + argv[argc] = qparse_strdup(buff); \ + argc++; \ + *buff = '\0'; \ + buff_used = 0; \ + } + +int qparse2(const char *input, char **argv_ret[], flags_t flg) +{ + int argc; + int allocated; + qp_state_t state; + const char *s; + char *buff; + int buff_len, buff_used; + char **argv; + + argc = 0; + allocated = 0; + argv = NULL; + state = qp_normal; + + buff_len = 128; + buff_used = 0; + buff = malloc(buff_len); + + for(s = input; *s != '\0'; s++) { + switch (state) { + case qp_normal: + switch (*s) { + case '\\': + s++; + qbackslash(*s); + break; + case '"': + if (flg & QPARSE_DOUBLE_QUOTE) + state = qp_dquote; + else + qpush(*s); + break; + case '\'': + if (flg & QPARSE_SINGLE_QUOTE) + state = qp_squote; + else + qpush(*s); + break; + case '(': + if (flg & QPARSE_PAREN) + state = qp_paren; + else + qpush(*s); + break; + case ' ': + case '\t': + case '\n': + case '\r': + if (flg & QPARSE_MULTISEP) + while(isspace(s[1])) s++; + qnext(); + break; + default: + qpush(*s); + } + /* End of qp_normal */ + break; + + case qp_dquote: + switch (*s) { + case '\\': + s++; + qbackslash(*s); + break; + case '"': + state = qp_normal; + break; + default: + qpush(*s); + } + /* End of qp_dquote */ + break; + + case qp_squote: + switch (*s) { + case '\\': + s++; + qbackslash(*s); + break; + case '\'': + state = qp_normal; + break; + default: + qpush(*s); + } + /* End of qp_dquote */ + break; + + case qp_paren: + switch (*s) { + case '\\': + s++; + qbackslash(*s); + break; + case ')': + state = qp_normal; + break; + default: + qpush(*s); + } + /* End of qp_paren */ + break; + } + } + + qnext(); + + if (buff != NULL) + free(buff); + + *argv_ret = argv; + return argc; +} + +int qparse(const char *input, char **argv_ret[]) +{ + return qparse2(input, argv_ret, QPARSE_DOUBLE_QUOTE); +} + + +void qparse_free(int argc, char **argv_ret[]) +{ + int n; + + for (n = 0; n < argc; n++) + free((*argv_ret)[n]); + + free(*argv_ret); + *argv_ret = NULL; +} + +char *qparse_strdup(const char *s) +{ + int l = strlen(s); + char *o; + o = malloc(l+1); + memcpy(o, s, l+1); + return o; +} Index: tags/2.1.2/src_3rd/qparse/qparse.h =================================================================== --- tags/2.1.2/src_3rd/qparse/qparse.h (nonexistent) +++ tags/2.1.2/src_3rd/qparse/qparse.h (revision 24813) @@ -0,0 +1,22 @@ +/* Split input into a list of strings in argv_ret[] using whitepsace as field + separator. It supports double quoted fields and backslash as escape character. + Returns the number of arguments. argv_ret should be free'd using + qparse_free(). */ +int qparse(const char *input, char **argv_ret[]); + +/* Free an argv_ret array allocated by qparse. */ +void qparse_free(int argc, char **argv_ret[]); + +/* for C89 - that doesn't have strdup()*/ +char *qparse_strdup(const char *s); + +/* More advanced API with more control over the format */ +typedef enum { + QPARSE_DOUBLE_QUOTE = 1, + QPARSE_SINGLE_QUOTE = 2, + QPARSE_PAREN = 4, + QPARSE_MULTISEP = 8 /* multiple separators are taken as a single separator */ +} flags_t; + +int qparse2(const char *input, char **argv_ret[], flags_t flg); + Index: tags/2.1.2/src_3rd =================================================================== --- tags/2.1.2/src_3rd (nonexistent) +++ tags/2.1.2/src_3rd (revision 24813) Property changes on: tags/2.1.2/src_3rd ___________________________________________________________________ Added: svn:externals ## -0,0 +1,13 ## +genht svn://repo.hu/genht/trunk/src +genlist svn://repo.hu/genlist/trunk/genlist +genvector svn://repo.hu/genvector/trunk/genvector +liblihata svn://repo.hu/lihata/trunk/src/liblihata +liblhtpers svn://repo.hu/lihata/trunk/src/liblhtpers +genregex svn://repo.hu/genregex/trunk/src +sphash svn://repo.hu/sphash/trunk +gensexpr svn://repo.hu/gensexpr/trunk/gensexpr +puplug svn://repo.hu/puplug/trunk/puplug +libminuid svn://repo.hu/libminuid/trunk/libminuid +libuundo svn://repo.hu/libuundo/trunk/libuundo +genrtree svn://repo.hu/genrtree/trunk/genrtree +libfungw svn://repo.hu/fungw/trunk/libfungw Index: tags/2.1.2/src_plugins/Buildin.tmpasm =================================================================== --- tags/2.1.2/src_plugins/Buildin.tmpasm (nonexistent) +++ tags/2.1.2/src_plugins/Buildin.tmpasm (revision 24813) @@ -0,0 +1,38 @@ +# tmpasm script for compiling a plugin_src/ module as a buildin +# Requires variables before the include: +# /local/pcb/mod basename of the module (e.g. autoplace) +# /local/pcb/mod/OBJS full path of all object files +# /local/pcb/mod/OBJS_C99 full path of all object files for non-c89 +# /local/pcb/mod/CONF config file name + +append /local/pcb/buildin_init_extern [@extern pcb_uninit_t hid_@/local/pcb/mod@_init();@] {\n} + +append /local/pcb/buildin_pups [@@/local/pcb/mod@=@/local/pcb/mod@/@/local/pcb/mod@.pup@] {\n} + +append /local/pcb/buildin_init_code [@ + uninit_func = hid_@/local/pcb/mod@_init(); + pcb_plugin_register("@/local/pcb/mod@", "<@/local/pcb/mod@>", NULL, 0, uninit_func); +@] {\n} + +append /local/pcb/OBJS ?/local/pcb/mod/OBJS +append /local/pcb/OBJS_C99 ?/local/pcb/mod/OBJS_C99 +append /local/pcb/LDFLAGS /local/pcb/mod/LDFLAGS +append /local/pcb/CFLAGS /local/pcb/mod/CFLAGS +append /local/pcb/RULES [@ + +mod_@/local/pcb/mod@: all + +@] + +# if plugin is part of the hidlib system, also append the objects +# to the hidlib object lists +put /local/pcb/mod/is_hidlib [@/local/pcb/@/local/pcb/mod@/hidlib@] +resolve /local/pcb/mod/is_hidlib ?/local/pcb/mod/is_hidlib +if ?/local/pcb/mod/is_hidlib +then + append /local/pcb/HIDLIB_PLG /local/pcb/mod + append /local/pcb/OBJS_HIDLIB_PLG ?/local/pcb/mod/OBJS + append /local/pcb/OBJS_C99_HIDLIB_PLG ?/local/pcb/mod/OBJS_C99 +end + +include /local/pcb/tmpasm/common_enabled Index: tags/2.1.2/src_plugins/Common_enabled.tmpasm =================================================================== --- tags/2.1.2/src_plugins/Common_enabled.tmpasm (nonexistent) +++ tags/2.1.2/src_plugins/Common_enabled.tmpasm (revision 24813) @@ -0,0 +1,82 @@ +# explicit rules: .y -> .c +# do not assume old yacc to work to different file names, do the generation +# in a separate directory to allow parallel compilation with -j +switch /local/pcb/mod/YACC + case {^$} end + default + foreach /local/n in /local/pcb/mod/YACC + put /local/bn /local/n + sub {/local/bn} {^.*/} {} + put /local/dn /local/n + sub {/local/dn} {/[^/]*$} {} + + if /local/pcb/want_parsgen + then + append /local/pcb/RULES [@ +# yacc for @/local/pcb/mod@ +@/local/n@.c @/local/n@.h: @/local/n@.y + cd @/local/dn@ && bison --defines=@/local/bn@.h --output=@/local/bn@.c --report-file=@/local/bn@.output -d @/local/bn@.y +@] + else + append /local/pcb/RULES [@ +# dummy yacc for @/local/pcb/mod@ +@/local/n@.c @/local/n@.h: + echo "skipping yacc..." +@] + end + end + end +end + +# explicit rules: .l -> .c +# do not assume old lex to work to different file names, do the generation +# in a separate directory to allow parallel compilation with -j +switch /local/pcb/mod/LEX + case {^$} end + default + foreach /local/n in /local/pcb/mod/LEX + if /local/pcb/want_parsgen + then + put /local/bn /local/n + sub {/local/bn} {^.*/} {} + put /local/dn /local/n + sub {/local/dn} {/[^/]*$} {} + + append /local/pcb/RULES [@ +# lex for @/local/pcb/mod@ +@/local/n@.c @/local/n@.h: @/local/n@.l + cd @/local/dn@ && flex --outfile=@/local/bn@.c --header-file=@/local/bn@.h @/local/bn@.l +@] + else + append /local/pcb/RULES [@ +# dummy lex for @/local/pcb/mod@ +@/local/n@.c: + echo "skipping flex..." +@] + end + end + end +end + +put /local/pcb/mod/enabled {1} + +include /local/pcb/tmpasm/plugin_conf +include /local/pcb/tmpasm/plugin_sphash +include /local/pcb/tmpasm/plugin_intconf + +append /local/pcb/CLEANFILES ?/local/pcb/mod/CLEANFILES +append /local/pcb/DISTCLEANFILES ?/local/pcb/mod/DISTCLEANFILES + +put /local/pcb/mod/enabled {} +put /local/pcb/mod/OBJS {} +put /local/pcb/mod/OBJS_C99 {} +put /local/pcb/mod/LDFLAGS {} +put /local/pcb/mod/CFLAGS {} +put /local/pcb/mod/YACC {} +put /local/pcb/mod/LEX {} +put /local/pcb/mod/SPHASH {} +put /local/pcb/mod/CLEANFILES {} +put /local/pcb/mod/DISTCLEANFILES {} +put /local/pcb/mod {} +put /local/pcb/mod/CONFFILE {} +put /local/pcb/mod/CONFVAR {} Index: tags/2.1.2/src_plugins/Disable.tmpasm =================================================================== --- tags/2.1.2/src_plugins/Disable.tmpasm (nonexistent) +++ tags/2.1.2/src_plugins/Disable.tmpasm (revision 24813) @@ -0,0 +1,24 @@ +# tmpasm script for disable a plugin_src/ module +# Requires variables before the include: +# /local/pcb/mod/OBJS full path of all object files + +# append all objects to the source list used only for dependencies +# NOTE: .o suffixes will be replaced with .c before generating the dep +append /local/pcb/DEPSRCS ?/local/pcb/mod/OBJS +append /local/pcb/DEPSRCS ?/local/pcb/mod/OBJS_C99 + +put /local/pcb/mod/enabled {0} + +include /local/pcb/tmpasm/plugin_conf +include /local/pcb/tmpasm/plugin_sphash +include /local/pcb/tmpasm/plugin_intconf + +put /local/pcb/mod/enabled {} +put /local/pcb/mod/OBJS {} +put /local/pcb/mod/OBJS_C99 {} +put /local/pcb/mod/CONF {} +put /local/pcb/mod/LDFLAGS {} +put /local/pcb/mod/CFLAGS {} +put /local/pcb/mod {} +put /local/pcb/mod/CONFFILE {} +put /local/pcb/mod/CONFVAR {} Index: tags/2.1.2/src_plugins/Plugin.tmpasm =================================================================== --- tags/2.1.2/src_plugins/Plugin.tmpasm (nonexistent) +++ tags/2.1.2/src_plugins/Plugin.tmpasm (revision 24813) @@ -0,0 +1,48 @@ +# tmpasm script for compiling a plugin_src/ module as a plugin +# Requires variables before the include: +# /local/pcb/mod basename of the module (e.g. autoplace) +# /local/pcb/mod/OBJS full path of all object files +# /local/pcb/mod/OBJS_C99 full path of all object files for non-c89 + +# clean up input vars +uniq /local/pcb/mod/OBJS +uniq /local/pcb/mod/OBJS_C99 +uniq /local/pcb/mod/CFLAGS +uniq /local/pcb/mod/LDFLAGS +uniq /local/pcb/mod/LIBS + +# generate .c -> .o rules in /local/comp/output +put /local/comp/OBJS ?/local/pcb/mod/OBJS +put /local/comp/OBJS_C99 ?/local/pcb/mod/OBJS_C99 +put /local/comp/CFLAGS /local/pcb/mod/CFLAGS +include {../scconfig/template/comp_var.tmpasm} + +append /local/pcb/all [@ $(PLUGIDIR)/@/local/pcb/mod@.so @] + +append /local/pcb/rules/install_ [@ + $(SCCBOX) $(HOW) "$(PLUGDIR)/@/local/pcb/mod@/@/local/pcb/mod@.so" "$(LIBDIR)/plugins/@/local/pcb/mod@.so" + $(SCCBOX) $(HOW) "$(PLUGDIR)/@/local/pcb/mod@/@/local/pcb/mod@.pup" "$(LIBDIR)/plugins/@/local/pcb/mod@.pup"@] + +append /local/pcb/CLEANFILES [@ $(PLUGDIR)/@/local/pcb/mod@/@/local/pcb/mod@.so $(PLUGIDIR)/@/local/pcb/mod@.so @/local/pcb/mod/OBJS@ @/local/pcb/mod/OBJS_C99@ @] + +append /local/pcb/RULES [@ + +### Module @/local/pcb/mod@: plugin ### + +$(PLUGDIR)/@/local/pcb/mod@/@/local/pcb/mod@.so: @/local/pcb/mod/OBJS@ @/local/pcb/mod/OBJS_C99@ + $(CC) $(LDFLAGS) @/local/pcb/mod/LDFLAGS@ -shared @cc/rdynamic@ -o $(PLUGDIR)/@/local/pcb/mod@/@/local/pcb/mod@.so @/local/pcb/mod/OBJS@ @/local/pcb/mod/OBJS_C99@ + +mod_@/local/pcb/mod@: $(PLUGIDIR)/@/local/pcb/mod@.so + +$(PLUGIDIR)/@/local/pcb/mod@.so: $(PLUGDIR)/@/local/pcb/mod@/@/local/pcb/mod@.so + $(MKDIR) $(PLUGIDIR) + $(CP) $(PLUGDIR)/@/local/pcb/mod@/@/local/pcb/mod@.so $(PLUGIDIR)/@/local/pcb/mod@.so + $(CP) $(PLUGDIR)/@/local/pcb/mod@/@/local/pcb/mod@.pup $(PLUGIDIR)/@/local/pcb/mod@.pup + +# module .c -> .o rules +@/local/comp/output@ + +### Module @/local/pcb/mod@ end ### +@] + +include /local/pcb/tmpasm/common_enabled Index: tags/2.1.2/src_plugins/README =================================================================== --- tags/2.1.2/src_plugins/README (nonexistent) +++ tags/2.1.2/src_plugins/README (revision 24813) @@ -0,0 +1,13 @@ +This directory hosts core plugins. They are feature, IO, lib and hid plugins. + +Each subdirectory is a standalone plugin that can be selected to be a +(static linked) buildin, a (dynamic linked) plugin or disabled +(not compiled at all). The selection is made in ./configure. + +HID plugins are user interfaces; IO plugins convert the current design to +an alien format or imports from those formats; feature plugins create +actions or otherwise add functionality to the system independent of which +HID is running. Lib plugins provide common code for other plugins to use. + +Some of the plugins depend on ../src_3rd and all of them depend on +core (../src). There are also internal plugin-plugin dependencies. Index: tags/2.1.2/src_plugins/acompnet/Makefile =================================================================== --- tags/2.1.2/src_plugins/acompnet/Makefile (nonexistent) +++ tags/2.1.2/src_plugins/acompnet/Makefile (revision 24813) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_acompnet + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/2.1.2/src_plugins/acompnet/Plug.tmpasm =================================================================== --- tags/2.1.2/src_plugins/acompnet/Plug.tmpasm (nonexistent) +++ tags/2.1.2/src_plugins/acompnet/Plug.tmpasm (revision 24813) @@ -0,0 +1,11 @@ +put /local/pcb/mod {acompnet} +put /local/pcb/mod/OBJS [@ + $(PLUGDIR)/acompnet/acompnet.o + $(PLUGDIR)/acompnet/meshgraph.o +@] + +switch /local/pcb/acompnet/controls + case {buildin} include /local/pcb/tmpasm/buildin; end; + case {plugin} include /local/pcb/tmpasm/plugin; end; + case {disable} include /local/pcb/tmpasm/disable; end; +end Index: tags/2.1.2/src_plugins/acompnet/acompnet.c =================================================================== --- tags/2.1.2/src_plugins/acompnet/acompnet.c (nonexistent) +++ tags/2.1.2/src_plugins/acompnet/acompnet.c (revision 24813) @@ -0,0 +1,242 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2016,2019 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "config.h" +#include "board.h" +#include "data.h" +#include "layer.h" +#include "layer_ui.h" +/*#include "acompnet_conf.h"*/ +#include "actions.h" +#include "plugins.h" +#include "search.h" +#include "polygon.h" +#include "conf.h" +#include "conf_core.h" +#include "compat_misc.h" +#include "error.h" +#include "meshgraph.h" + +static pcb_layer_t *ly; + +typedef struct { + pcb_coord_t x, y; + pcb_coord_t r; +} overlap_t; + +static pcb_r_dir_t overlap(const pcb_box_t *box, void *closure) +{ + pcb_any_obj_t *obj = (pcb_any_obj_t *)box; + overlap_t *ovl = (overlap_t *)closure; + switch(obj->type) { + case PCB_OBJ_LINE: + if (pcb_is_point_in_line(ovl->x, ovl->y, ovl->r, (pcb_any_line_t *)obj)) + return PCB_R_DIR_CANCEL; + break; + case PCB_OBJ_ARC: + if (pcb_is_point_on_arc(ovl->x, ovl->y, ovl->r, (pcb_arc_t *)obj)) + return PCB_R_DIR_CANCEL; + break; + case PCB_OBJ_TEXT: + if (pcb_is_point_in_box(ovl->x, ovl->y, &obj->bbox_naked, ovl->r)) + return PCB_R_DIR_CANCEL; + break; + case PCB_OBJ_POLY: + if (pcb_poly_is_point_in_p(ovl->x, ovl->y, ovl->r, (pcb_poly_t *)obj)) + return PCB_R_DIR_CANCEL; + break; + default: break; + } + return PCB_R_DIR_NOT_FOUND; +} + +TODO("move this to search.[ch]") +/* Search for object(s) on a specific layer */ +static pcb_r_dir_t pcb_search_on_layer(pcb_layer_t *layer, const pcb_box_t *bbox, pcb_r_dir_t (*cb)(const pcb_box_t *box, void *closure), void *closure) +{ + pcb_r_dir_t res, fin = 0; + + if ((res = pcb_r_search(layer->line_tree, bbox, NULL, cb, closure, NULL)) == PCB_R_DIR_CANCEL) + return res; + fin |= res; + + if ((res = pcb_r_search(layer->arc_tree, bbox, NULL, cb, closure, NULL)) == PCB_R_DIR_CANCEL) + return res; + fin |= res; + + if ((res = pcb_r_search(layer->polygon_tree, bbox, NULL, cb, closure, NULL)) == PCB_R_DIR_CANCEL) + return res; + fin |= res; + + if ((res = pcb_r_search(layer->text_tree, bbox, NULL, cb, closure, NULL)) == PCB_R_DIR_CANCEL) + return res; + fin |= res; + +TODO("padstack too"); + + return res; +} + + +pcb_flag_t flg_mesh_pt; +static void acompnet_mesh_addpt(pcb_meshgraph_t *gr, pcb_layer_t *layer, double x, double y, int score, double sep) +{ + overlap_t ovl; + pcb_box_t bbox; + + x = pcb_round(x); + y = pcb_round(y); + + ovl.x = x; + ovl.y = y; + ovl.r = pcb_round(sep/2-1); + bbox.X1 = x - ovl.r; + bbox.X2 = x + ovl.r; + bbox.Y1 = y - ovl.r; + bbox.Y2 = y + ovl.r; + + if (pcb_search_on_layer(layer, &bbox, overlap, &ovl) == PCB_R_DIR_NOT_FOUND) { + bbox.X1 = x; + bbox.X2 = x+1; + bbox.Y1 = y; + bbox.Y2 = y+1; + pcb_msgr_add_node(gr, &bbox, score); + pcb_line_new(ly, x, y, x, y, conf_core.design.line_thickness, conf_core.design.bloat, flg_mesh_pt); + } +} + +static void acompnet_mesh(pcb_meshgraph_t *gr, pcb_layer_t *layer) +{ + double sep = conf_core.design.line_thickness + conf_core.design.bloat; + int n; + + PCB_LINE_LOOP(CURRENT) { + double i, len, vx, vy, x1, y1, x2, y2, nx, ny; + x1 = line->Point1.X; + x2 = line->Point2.X; + y1 = line->Point1.Y; + y2 = line->Point2.Y; + vx = x2 - x1; + vy = y2 - y1; + len = sqrt(vx*vx + vy*vy); + vx = vx/len; + vy = vy/len; + nx = vy; + ny = -vx; + + /* straight line extension points */ + acompnet_mesh_addpt(gr, layer, x1 - vx*sep, y1 - vy*sep, 0, sep); + acompnet_mesh_addpt(gr, layer, x2 + vx*sep, y2 + vy*sep, 0, sep); + + /* side and extended points; n is in-line offset from endpoint */ + for(n = 0; n <= 1; n++) { + acompnet_mesh_addpt(gr, layer, x1 - n*vx*sep + nx*sep, y1 - n*vy*sep + ny*sep, 1, sep); + acompnet_mesh_addpt(gr, layer, x1 - n*vx*sep - nx*sep, y1 - n*vy*sep - ny*sep, 1, sep); + + acompnet_mesh_addpt(gr, layer, x2 + n*vx*sep + nx*sep, y2 + n*vy*sep + ny*sep, 1, sep); + acompnet_mesh_addpt(gr, layer, x2 + n*vx*sep - nx*sep, y2 + n*vy*sep - ny*sep, 1, sep); + } + + for(i = 2*sep; i <= len - 2*sep; i += sep*3) { + acompnet_mesh_addpt(gr, layer, x1 + i*vx + nx*sep, y1 + i*vy + ny*sep, 2, sep); + acompnet_mesh_addpt(gr, layer, x1 + i*vx - nx*sep, y1 + i*vy - ny*sep, 2, sep); + } + } + PCB_END_LOOP; +} + + +static const char pcb_acts_acompnet[] = "acompnet()\n" ; +static const char pcb_acth_acompnet[] = "Attempt to auto-complete the current network"; + +static fgw_error_t pcb_act_acompnet(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + pcb_meshgraph_t gr; + long int is, ie; + + pcb_msgr_init(&gr); + acompnet_mesh(&gr, CURRENT); + + { /* temporary hack for testing: fixed, off-mesh start/end */ + pcb_box_t bbox; + bbox.X1 = PCB_MM_TO_COORD(6.35); bbox.X2 = bbox.X1+1; + bbox.Y1 = PCB_MM_TO_COORD(21.5); bbox.Y2 = bbox.Y1+1; + is = pcb_msgr_add_node(&gr, &bbox, 0); + bbox.X1 = PCB_MM_TO_COORD(12); bbox.X2 = bbox.X1+1; + bbox.Y1 = PCB_MM_TO_COORD(3.8); bbox.Y2 = bbox.Y1+1; + ie = pcb_msgr_add_node(&gr, &bbox, 0); + } + + pcb_msgr_astar(&gr, is, ie); + + { /* temporary visualisation code */ + long int id = ie; + for(;;) { + pcb_meshnode_t *curr, *prev; + curr = htip_get(&gr.id2node, id); + id = curr->came_from; + if (id == 0) + break; + prev = htip_get(&gr.id2node, id); + pcb_line_new(ly, curr->bbox.X1, curr->bbox.Y1, prev->bbox.X1, prev->bbox.Y1, conf_core.design.line_thickness/2, conf_core.design.bloat/2, flg_mesh_pt); +TODO("use pcb_drc_lines(), probably during A*, saving mid-point, and draw pairs of lines here"); + } + } + PCB_ACT_IRES(0); + return 0; +} + +pcb_action_t acompnet_action_list[] = { + {"acompnet", pcb_act_acompnet, pcb_acth_acompnet, pcb_acts_acompnet}, +}; + +static const char *acompnet_cookie = "acompnet plugin"; + +PCB_REGISTER_ACTIONS(acompnet_action_list, acompnet_cookie) + +int pplg_check_ver_acompnet(int ver_needed) { return 0; } + +void pplg_uninit_acompnet(void) +{ + pcb_remove_actions_by_cookie(acompnet_cookie); + pcb_uilayer_free_all_cookie(acompnet_cookie); +} + +#include "dolists.h" +int pplg_init_acompnet(void) +{ + static pcb_color_t clr; + + PCB_API_CHK_VER; + + if (clr.str[0] != '#') + pcb_color_load_str(&clr, "#c09920"); + + PCB_REGISTER_ACTIONS(acompnet_action_list, acompnet_cookie) + ly = pcb_uilayer_alloc(acompnet_cookie, "autocomp-net", &clr); + + return 0; +} Index: tags/2.1.2/src_plugins/acompnet/acompnet.pup =================================================================== --- tags/2.1.2/src_plugins/acompnet/acompnet.pup (nonexistent) +++ tags/2.1.2/src_plugins/acompnet/acompnet.pup (revision 24813) @@ -0,0 +1,6 @@ +$class feature +$short net auto-completion +$long Auto-complete the current network. A very limited autorouter/assistant. +$state WIP +default disable +autoload 1 Index: tags/2.1.2/src_plugins/acompnet/meshgraph.c =================================================================== --- tags/2.1.2/src_plugins/acompnet/meshgraph.c (nonexistent) +++ tags/2.1.2/src_plugins/acompnet/meshgraph.c (revision 24813) @@ -0,0 +1,161 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2019 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "config.h" +#include +#include +#include "board.h" +#include "conf_core.h" +#include "data.h" +#include "meshgraph.h" +#include "error.h" +#include "layer.h" +#include "route.h" + +#define INF_SCORE 9000000000.0 +#define SEARCHR PCB_MM_TO_COORD(5) + +void pcb_msgr_init(pcb_meshgraph_t *gr) +{ + pcb_rtree_init(&gr->ntree); + htip_init(&gr->id2node, longhash, longkeyeq); + gr->next_id = 1; +} + +long int pcb_msgr_add_node(pcb_meshgraph_t *gr, pcb_box_t *bbox, int score) +{ + pcb_meshnode_t *nd = malloc(sizeof(pcb_meshnode_t)); + nd->bbox = *bbox; + nd->id = gr->next_id; + nd->came_from = 0; + nd->gscore = INF_SCORE; + nd->fscore = INF_SCORE; + nd->iscore = score; + + pcb_rtree_insert(&gr->ntree, nd, (pcb_rtree_box_t *)nd); + htip_set(&gr->id2node, nd->id, nd); + gr->next_id++; + return nd->id; +} + +static double msgr_connect(pcb_meshnode_t *curr, pcb_meshnode_t *next) +{ + pcb_point_t np, cp; + pcb_route_t route; + pcb_route_init(&route); + + np.X = next->bbox.X1; + np.Y = next->bbox.Y1; + cp.X = curr->bbox.X1; + cp.Y = curr->bbox.Y1; + pcb_route_calculate(PCB, &route, &np, &cp, INDEXOFCURRENT, conf_core.design.line_thickness, conf_core.design.bloat, pcb_flag_make(PCB_FLAG_CLEARLINE), 0, 0); + + pcb_trace("size=%d\n", route.size); + + return curr->gscore + pcb_distance(curr->bbox.X1, curr->bbox.Y1, next->bbox.X1, next->bbox.Y1) * (next->iscore + 1.0); +} + +static double msgr_heurist(pcb_meshnode_t *curr, pcb_meshnode_t *end) +{ + return pcb_distance(curr->bbox.X1, curr->bbox.Y1, end->bbox.X1, end->bbox.Y1); +} + +int pcb_msgr_astar(pcb_meshgraph_t *gr, long int startid, long int endid) +{ + htip_t closed, open; + htip_entry_t *e; + pcb_meshnode_t *curr, *next, *end; + + curr = htip_get(&gr->id2node, startid); + if (curr == NULL) + return -1; + + end = htip_get(&gr->id2node, endid); + if (end == NULL) + return -1; + + htip_init(&closed, longhash, longkeyeq); + htip_init(&open, longhash, longkeyeq); + + htip_set(&open, startid, curr); + for(;;) { + pcb_rtree_box_t sb; + pcb_box_t *b; + pcb_rtree_it_t it; + double tentative_g, best; + +TODO("should use a faster way for picking lowest fscore") + /* get the best looking item from the open list */ + curr = NULL; + best = INF_SCORE; + for(e = htip_first(&open); e != NULL; e = htip_next(&open, e)) { + next = e->value; + if (next->fscore <= best) { + best = next->fscore; + curr = next; + } + } + + if (curr == NULL) { +pcb_trace("NO PATH\n"); + return 0; + } + htip_pop(&open, curr->id); + if (curr->id == endid) { +pcb_trace("found path\n"); + return 1; + } + htip_set(&closed, curr->id, curr); +pcb_trace("first: %ld\n", curr->id); + + /* search potential neighbors */ + sb.x1 = curr->bbox.X1 - SEARCHR; + sb.x2 = curr->bbox.X2 + SEARCHR; + sb.y1 = curr->bbox.Y1 - SEARCHR; + sb.y2 = curr->bbox.Y2 + SEARCHR; + for(b = pcb_rtree_first(&it, &gr->ntree, &sb); b != NULL; b = pcb_rtree_next(&it)) { + next = (pcb_meshnode_t *)b; + if (htip_get(&closed, next->id) != NULL) + continue; + + tentative_g = msgr_connect(curr, next); + if (tentative_g < 0) + continue; + + if (htip_get(&open, next->id) == NULL) /* not in open */ + htip_set(&open, next->id, next); + else if (tentative_g > next->gscore) + continue; + +pcb_trace("add: %ld\n", next->id); + next->came_from = curr->id; + next->gscore = tentative_g; + next->fscore = msgr_heurist(curr, end); + } + } +} + + Index: tags/2.1.2/src_plugins/acompnet/meshgraph.h =================================================================== --- tags/2.1.2/src_plugins/acompnet/meshgraph.h (nonexistent) +++ tags/2.1.2/src_plugins/acompnet/meshgraph.h (revision 24813) @@ -0,0 +1,26 @@ +#ifndef PCB_ACOMPNET_MESHGRAPH_H +#define PCB_ACOMPNET_MESHGRAPH_H +#include "rtree.h" +#include "box.h" +#include + +typedef struct { + pcb_box_t bbox; + long int id; + long int came_from; + double gscore, fscore; + int iscore; /* input score: how much we prefer to use this node */ +} pcb_meshnode_t; + + +typedef struct { + pcb_rtree_t ntree; + htip_t id2node; + long int next_id; +} pcb_meshgraph_t; + +void pcb_msgr_init(pcb_meshgraph_t *gr); +long int pcb_msgr_add_node(pcb_meshgraph_t *gr, pcb_box_t *bbox, int score); +int pcb_msgr_astar(pcb_meshgraph_t *gr, long int startid, long int endid); + +#endif Index: tags/2.1.2/src_plugins/act_draw/Makefile =================================================================== --- tags/2.1.2/src_plugins/act_draw/Makefile (nonexistent) +++ tags/2.1.2/src_plugins/act_draw/Makefile (revision 24813) @@ -0,0 +1,6 @@ +all: + cd ../../src && $(MAKE) mod_act_draw + + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/2.1.2/src_plugins/act_draw/Plug.tmpasm =================================================================== --- tags/2.1.2/src_plugins/act_draw/Plug.tmpasm (nonexistent) +++ tags/2.1.2/src_plugins/act_draw/Plug.tmpasm (revision 24813) @@ -0,0 +1,10 @@ +put /local/pcb/mod {act_draw} +put /local/pcb/mod/OBJS [@ + $(PLUGDIR)/act_draw/act_draw.o +@] + +switch /local/pcb/act_draw/controls + case {buildin} include /local/pcb/tmpasm/buildin; end; + case {plugin} include /local/pcb/tmpasm/plugin; end; + case {disable} include /local/pcb/tmpasm/disable; end; +end Index: tags/2.1.2/src_plugins/act_draw/act_draw.c =================================================================== --- tags/2.1.2/src_plugins/act_draw/act_draw.c (nonexistent) +++ tags/2.1.2/src_plugins/act_draw/act_draw.c (revision 24813) @@ -0,0 +1,474 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2018 Tibor 'Igor2' Palinkas + * + * This module, dialogs, was written and is Copyright (C) 2017 by Tibor Palinkas + * this module is also subject to the GNU GPL as described below + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "config.h" +#include "conf_core.h" + +#include "actions.h" +#include "board.h" +#include "compat_misc.h" +#include "flag_str.h" +#include "obj_arc.h" +#include "obj_line.h" +#include "obj_pstk.h" +#include "obj_text.h" +#include "plugins.h" +#include "undo.h" + +static const char *PTR_DOMAIN_POLY = "fgw_ptr_domain_poly"; + +static const char pcb_acts_GetValue[] = "GetValue(input, units, relative, default_unit)"; +static const char pcb_acth_GetValue[] = "Convert a coordinate value. Returns an unitless double or FGW_ERR_ARG_CONV. The 3rd parameter controls whether to require relative coordinates (+- prefix). Wraps pcb_get_value_ex()."; +static fgw_error_t pcb_act_GetValue(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + const char *input, *units, *def_unit; + int relative, a; + double v; + pcb_bool success; + + PCB_ACT_CONVARG(1, FGW_STR, GetValue, input = argv[1].val.str); + PCB_ACT_CONVARG(2, FGW_STR, GetValue, units = argv[2].val.str); + PCB_ACT_CONVARG(3, FGW_INT, GetValue, relative = argv[3].val.nat_int); + PCB_ACT_CONVARG(4, FGW_STR, GetValue, def_unit = argv[1].val.str); + + if (*units == '\0') + units = NULL; + + v = pcb_get_value_ex(input, units, &a, NULL, def_unit, &success); + if (!success || (relative && a)) + return FGW_ERR_ARG_CONV; + + res->type = FGW_DOUBLE; + res->val.nat_double = v; + return 0; +} + +static int flg_error(const char *msg) +{ + pcb_message(PCB_MSG_ERROR, "act_draw flag conversion error: %s\n", msg); + return 0; +} + +#define DRAWOPTARG \ + int noundo = 0, ao = 0; \ + if ((argv[1].type == FGW_STR) && (strcmp(argv[1].val.str, "noundo") == 0)) { \ + noundo = 1; \ + ao++; \ + } + +static const char pcb_acts_LineNew[] = "LineNew([noundo,] data, layer, X1, Y1, X2, Y2, Thickness, Clearance, Flags)"; +static const char pcb_acth_LineNew[] = "Create a pcb line segment on a layer. For now data must be \"pcb\". Returns the ID of the new object or 0 on error."; +static fgw_error_t pcb_act_LineNew(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + const char *sflg; + pcb_line_t *line; + pcb_data_t *data; + pcb_layer_t *layer; + pcb_coord_t x1, y1, x2, y2, th, cl; + pcb_flag_t flags; + DRAWOPTARG; + + PCB_ACT_IRES(0); + PCB_ACT_CONVARG(1+ao, FGW_DATA, LineNew, data = fgw_data(&argv[1+ao])); + PCB_ACT_CONVARG(2+ao, FGW_LAYER, LineNew, layer = fgw_layer(&argv[2+ao])); + PCB_ACT_CONVARG(3+ao, FGW_COORD, LineNew, x1 = fgw_coord(&argv[3+ao])); + PCB_ACT_CONVARG(4+ao, FGW_COORD, LineNew, y1 = fgw_coord(&argv[4+ao])); + PCB_ACT_CONVARG(5+ao, FGW_COORD, LineNew, x2 = fgw_coord(&argv[5+ao])); + PCB_ACT_CONVARG(6+ao, FGW_COORD, LineNew, y2 = fgw_coord(&argv[6+ao])); + PCB_ACT_CONVARG(7+ao, FGW_COORD, LineNew, th = fgw_coord(&argv[7+ao])); + PCB_ACT_CONVARG(8+ao, FGW_COORD, LineNew, cl = fgw_coord(&argv[8+ao])); + PCB_ACT_CONVARG(9+ao, FGW_STR, LineNew, sflg = argv[9+ao].val.str); + + if ((data != PCB->Data) || (layer == NULL)) + return 0; + + flags = pcb_strflg_s2f(sflg, flg_error, NULL, 0); + line = pcb_line_new(layer, x1, y1, x2, y2, th, cl*2, flags); + + if (line != NULL) { + res->type = FGW_LONG; + res->val.nat_long = line->ID; + if (!noundo) + pcb_undo_add_obj_to_create(PCB_OBJ_LINE, layer, line, line); + } + return 0; +} + +static const char pcb_acts_ArcNew[] = "ArcNew([noundo,] data, layer, centx, centy, radiusx, radiusy, start_ang, delta_ang, thickness, clearance, flags)"; +static const char pcb_acth_ArcNew[] = "Create a pcb arc segment on a layer. For now data must be \"pcb\". Returns the ID of the new object or 0 on error."; +static fgw_error_t pcb_act_ArcNew(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + const char *sflg; + pcb_arc_t *arc; + pcb_data_t *data; + pcb_layer_t *layer; + pcb_coord_t cx, cy, hr, wr, th, cl; + double sa, da; + pcb_flag_t flags; + DRAWOPTARG; + + PCB_ACT_IRES(0); + PCB_ACT_CONVARG(1+ao, FGW_DATA, ArcNew, data = fgw_data(&argv[1+ao])); + PCB_ACT_CONVARG(2+ao, FGW_LAYER, ArcNew, layer = fgw_layer(&argv[2+ao])); + PCB_ACT_CONVARG(3+ao, FGW_COORD, ArcNew, cx = fgw_coord(&argv[3+ao])); + PCB_ACT_CONVARG(4+ao, FGW_COORD, ArcNew, cy = fgw_coord(&argv[4+ao])); + PCB_ACT_CONVARG(5+ao, FGW_COORD, ArcNew, wr = fgw_coord(&argv[5+ao])); + PCB_ACT_CONVARG(6+ao, FGW_COORD, ArcNew, hr = fgw_coord(&argv[6+ao])); + PCB_ACT_CONVARG(7+ao, FGW_DOUBLE, ArcNew, sa = argv[7+ao].val.nat_double); + PCB_ACT_CONVARG(8+ao, FGW_DOUBLE, ArcNew, da = argv[8+ao].val.nat_double); + PCB_ACT_CONVARG(9+ao, FGW_COORD, ArcNew, th = fgw_coord(&argv[9+ao])); + PCB_ACT_CONVARG(10+ao, FGW_COORD, ArcNew, cl = fgw_coord(&argv[10+ao])); + PCB_ACT_CONVARG(11+ao, FGW_STR, ArcNew, sflg = argv[11+ao].val.str); + + if ((data != PCB->Data) || (layer == NULL)) + return 0; + + flags = pcb_strflg_s2f(sflg, flg_error, NULL, 0); + arc = pcb_arc_new(layer, cx, cy, wr, hr, sa, da, th, cl*2, flags, 0); + + if (arc != NULL) { + res->type = FGW_LONG; + res->val.nat_long = arc->ID; + if (!noundo) + pcb_undo_add_obj_to_create(PCB_OBJ_ARC, layer, arc, arc); + } + return 0; +} + +static const char pcb_acts_TextNew[] = "TextNew([noundo,] data, layer, fontID, x, y, rot, scale, thickness, test_string, flags)"; +static const char pcb_acth_TextNew[] = "Create a pcb text on a layer. For now data must be \"pcb\". Font id 0 is the default font. Thickness 0 means default, calculated thickness. Scale=100 is the original font size. Returns the ID of the new object or 0 on error."; +static fgw_error_t pcb_act_TextNew(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + const char *sflg, *str; + pcb_text_t *text = NULL; + pcb_data_t *data; + pcb_layer_t *layer; + pcb_coord_t x, y, th; + int scale, fontid; + double rot; + pcb_flag_t flags; + pcb_font_t *font; + DRAWOPTARG; + + PCB_ACT_IRES(0); + PCB_ACT_CONVARG(1+ao, FGW_DATA, TextNew, data = fgw_data(&argv[1+ao])); + PCB_ACT_CONVARG(2+ao, FGW_LAYER, TextNew, layer = fgw_layer(&argv[2+ao])); + PCB_ACT_CONVARG(3+ao, FGW_INT, TextNew, fontid = argv[3+ao].val.nat_int); + PCB_ACT_CONVARG(4+ao, FGW_COORD, TextNew, x = fgw_coord(&argv[4+ao])); + PCB_ACT_CONVARG(5+ao, FGW_COORD, TextNew, y = fgw_coord(&argv[5+ao])); + PCB_ACT_CONVARG(6+ao, FGW_DOUBLE, TextNew, rot = argv[6+ao].val.nat_double); + PCB_ACT_CONVARG(7+ao, FGW_INT, TextNew, scale = argv[7+ao].val.nat_int); + PCB_ACT_CONVARG(8+ao, FGW_COORD, TextNew, th = fgw_coord(&argv[8+ao])); + PCB_ACT_CONVARG(9+ao, FGW_STR, TextNew, str = argv[9+ao].val.str); + PCB_ACT_CONVARG(10+ao, FGW_STR, TextNew, sflg = argv[10+ao].val.str); + + if ((data != PCB->Data) || (layer == NULL)) + return 0; + + font = pcb_font(PCB, fontid, 0); + if (font != NULL) { + flags = pcb_strflg_s2f(sflg, flg_error, NULL, 0); + text = pcb_text_new(layer, font, x, y, rot, scale, th, str, flags); + } + else + pcb_message(PCB_MSG_ERROR, "NewText: font %d not found\n", fontid); + + if (text != NULL) { + res->type = FGW_LONG; + res->val.nat_long = text->ID; + if (!noundo) + pcb_undo_add_obj_to_create(PCB_OBJ_TEXT, layer, text, text); + } + return 0; +} + +static const char pcb_acts_PstkNew[] = "PstkNew([noundo,] data, protoID, x, y, glob_clearance, flags)"; +static const char pcb_acth_PstkNew[] = "Create a padstack. For now data must be \"pcb\". glob_clearance=0 turns off global clearance. Returns the ID of the new object or 0 on error."; +static fgw_error_t pcb_act_PstkNew(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + const char *sflg; + pcb_pstk_t *pstk; + pcb_data_t *data; + long proto; + pcb_coord_t x, y, cl; + pcb_flag_t flags; + DRAWOPTARG; + + PCB_ACT_IRES(0); + PCB_ACT_CONVARG(1+ao, FGW_DATA, PstkNew, data = fgw_data(&argv[1+ao])); + PCB_ACT_CONVARG(2+ao, FGW_LONG, PstkNew, proto = argv[2+ao].val.nat_int); + PCB_ACT_CONVARG(3+ao, FGW_COORD, PstkNew, x = fgw_coord(&argv[3+ao])); + PCB_ACT_CONVARG(4+ao, FGW_COORD, PstkNew, y = fgw_coord(&argv[4+ao])); + PCB_ACT_CONVARG(5+ao, FGW_COORD, PstkNew, cl = fgw_coord(&argv[5+ao])); + PCB_ACT_CONVARG(6+ao, FGW_STR, PstkNew, sflg = argv[6+ao].val.str); + + if (data != PCB->Data) + return 0; + + flags = pcb_strflg_s2f(sflg, flg_error, NULL, 0); + pstk = pcb_pstk_new(data, -1, proto, x, y, cl, flags); + + if (pstk != NULL) { + res->type = FGW_LONG; + res->val.nat_long = pstk->ID; + if (!noundo) + pcb_undo_add_obj_to_create(PCB_OBJ_PSTK, data, pstk, pstk); + } + return 0; +} + +static const char pcb_acts_PolyNewFromRectangle[] = "PolyNewFromRectangle([noundo,] data, layer, x1, y1, x2, y2, clearance, flags)"; +static const char pcb_acth_PolyNewFromRectangle[] = "Create a rectangular polygon. For now data must be \"pcb\". Returns the ID of the new object or 0 on error."; +static fgw_error_t pcb_act_PolyNewFromRectangle(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + const char *sflg; + pcb_poly_t *poly; + pcb_data_t *data; + pcb_layer_t *layer; + pcb_coord_t x1, y1, x2, y2, cl; + pcb_flag_t flags; + DRAWOPTARG; + + PCB_ACT_IRES(0); + PCB_ACT_CONVARG(1+ao, FGW_DATA, PolyNewFromRectangle, data = fgw_data(&argv[1+ao])); + PCB_ACT_CONVARG(2+ao, FGW_LAYER, PolyNewFromRectangle, layer = fgw_layer(&argv[2+ao])); + PCB_ACT_CONVARG(3+ao, FGW_COORD, PolyNewFromRectangle, x1 = fgw_coord(&argv[3+ao])); + PCB_ACT_CONVARG(4+ao, FGW_COORD, PolyNewFromRectangle, y1 = fgw_coord(&argv[4+ao])); + PCB_ACT_CONVARG(5+ao, FGW_COORD, PolyNewFromRectangle, x2 = fgw_coord(&argv[5+ao])); + PCB_ACT_CONVARG(6+ao, FGW_COORD, PolyNewFromRectangle, y2 = fgw_coord(&argv[6+ao])); + PCB_ACT_CONVARG(7+ao, FGW_COORD, PolyNewFromRectangle, cl = fgw_coord(&argv[7+ao])); + PCB_ACT_CONVARG(8+ao, FGW_STR, PolyNewFromRectangle, sflg = argv[8+ao].val.str); + + if (data != PCB->Data) + return 0; + + flags = pcb_strflg_s2f(sflg, flg_error, NULL, 0); + poly = pcb_poly_new_from_rectangle(layer, x1, y1, x2, y2, cl*2, flags); + + if (poly != NULL) { + res->type = FGW_LONG; + res->val.nat_long = poly->ID; + if (!noundo) + pcb_undo_add_obj_to_create(PCB_OBJ_POLY, layer, poly, poly); + } + return 0; +} + +static long poly_append_ptlist(pcb_poly_t *poly, const char *ptlist) +{ + long len; + char *s, *next, *tmp = pcb_strdup(ptlist); + double c[2]; + pcb_bool success; + + s = tmp; + while (isspace(*s) || (*s == ',')) s++; + for(len = 0; s != NULL; s = next, len++) { + next = strchr(s, ','); + if (next != NULL) { + *next = '\0'; + next++; + while (isspace(*next) || (*next == ',')) next++; + if (*next == '\0') + next = NULL; + } + c[len % 2] = pcb_get_value_ex(s, NULL, NULL, NULL, "mm", &success); + if (!success) { + pcb_message(PCB_MSG_ERROR, "act_draw ptlist processing: '%s' is not a valid coordinate\n", s); + free(tmp); + return -1; + } + if ((len % 2) == 1) + pcb_poly_point_new(poly, c[0], c[1]); + } + free(tmp); + if ((len % 2) == 1) { + pcb_message(PCB_MSG_ERROR, "act_draw ptlist processing: odd number of points\n"); + return -1; + } + return len/2; +} + +static const char pcb_acts_PolyNewFromPoints[] = "PolyNewFromRectangle([noundo,] data, layer, ptlist, clearance, flags)"; +static const char pcb_acth_PolyNewFromPoints[] = "Create a polygon. For now data must be \"pcb\". ptlist is a comma separated list of coordinates (untiless coordinates are treated as mm). Returns the ID of the new object or 0 on error."; +static fgw_error_t pcb_act_PolyNewFromPoints(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + const char *sflg, *ptlist; + pcb_poly_t *poly; + pcb_data_t *data; + pcb_layer_t *layer; + pcb_coord_t cl; + pcb_flag_t flags; + DRAWOPTARG; + + PCB_ACT_IRES(0); + PCB_ACT_CONVARG(1+ao, FGW_DATA, PolyNewFromPoints, data = fgw_data(&argv[1+ao])); + PCB_ACT_CONVARG(2+ao, FGW_LAYER, PolyNewFromPoints, layer = fgw_layer(&argv[2+ao])); + PCB_ACT_CONVARG(3+ao, FGW_STR, PolyNewFromPoints, ptlist = argv[3+ao].val.str); + PCB_ACT_CONVARG(4+ao, FGW_COORD, PolyNewFromPoints, cl = fgw_coord(&argv[4+ao])); + PCB_ACT_CONVARG(5+ao, FGW_STR, PolyNewFromPoints, sflg = argv[5+ao].val.str); + + if (data != PCB->Data) + return 0; + + flags = pcb_strflg_s2f(sflg, flg_error, NULL, 0); + poly = pcb_poly_new(layer, cl*2, flags); + + if (poly != NULL) { + if (poly_append_ptlist(poly, ptlist) > 2) { + pcb_poly_init_clip(data, layer, poly); + pcb_add_poly_on_layer(layer, poly); + res->type = FGW_LONG; + res->val.nat_long = poly->ID; + if (!noundo) + pcb_undo_add_obj_to_create(PCB_OBJ_POLY, layer, poly, poly); + } + } + return 0; +} + +static const char pcb_acts_PolyNew[] = "PolyNew([noundo,] data, layer, ptlist, clearance, flags)"; +static const char pcb_acth_PolyNew[] = "Create an empty polygon. For now data must be \"pcb\". Use PolyNewPoint to add points. Returns a polygon pointer valid until PolyNewEnd() is called."; +static fgw_error_t pcb_act_PolyNew(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + const char *sflg; + pcb_poly_t *poly; + pcb_data_t *data; + pcb_layer_t *layer; + pcb_coord_t cl; + pcb_flag_t flags; + DRAWOPTARG; + (void)noundo; + + PCB_ACT_IRES(0); + PCB_ACT_CONVARG(1+ao, FGW_DATA, PolyNewFromPoints, data = fgw_data(&argv[1+ao])); + PCB_ACT_CONVARG(2+ao, FGW_LAYER, PolyNewFromPoints, layer = fgw_layer(&argv[2+ao])); + PCB_ACT_CONVARG(3+ao, FGW_COORD, PolyNewFromPoints, cl = fgw_coord(&argv[3+ao])); + PCB_ACT_CONVARG(4+ao, FGW_STR, PolyNewFromPoints, sflg = argv[4+ao].val.str); + + if (data != PCB->Data) + return 0; + + flags = pcb_strflg_s2f(sflg, flg_error, NULL, 0); + poly = pcb_poly_new(layer, cl*2, flags); + + if (poly != NULL) + fgw_ptr_reg(&pcb_fgw, res, PTR_DOMAIN_POLY, FGW_PTR, poly); + return 0; +} + +static const char pcb_acts_PolyNewPoints[] = "PolyNewPoints([noundo,] poly, ptlist)"; +static const char pcb_acth_PolyNewPoints[] = "Add a list of points to a polygon created by PolyNew. Returns 0 on success."; +static fgw_error_t pcb_act_PolyNewPoints(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + pcb_poly_t *poly; + const char *ptlist; + DRAWOPTARG; + (void)noundo; + + PCB_ACT_CONVARG(1+ao, FGW_PTR, PolyNewPoints, poly = argv[1+ao].val.ptr_void); + PCB_ACT_CONVARG(2+ao, FGW_STR, PolyNewPoints, ptlist = argv[2+ao].val.str); + if (!fgw_ptr_in_domain(&pcb_fgw, &argv[1], PTR_DOMAIN_POLY)) { + pcb_message(PCB_MSG_ERROR, "PolyNewPoints: invalid polygon pointer\n"); + PCB_ACT_IRES(-1); + return 0; + } + if (poly_append_ptlist(poly, ptlist) < 0) { + PCB_ACT_IRES(-1); + return 0; + } + + PCB_ACT_IRES(0); + return 0; +} + +static const char pcb_acts_PolyNewEnd[] = "PolyNewEnd([noundo,] data, layer, poly)"; +static const char pcb_acth_PolyNewEnd[] = "Close and place a polygon started by PolyNew. Returns the ID of the new object or 0 on error."; +static fgw_error_t pcb_act_PolyNewEnd(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + pcb_poly_t *poly; + pcb_data_t *data; + pcb_layer_t *layer; + DRAWOPTARG; + + PCB_ACT_CONVARG(1+ao, FGW_DATA, PolyNewFromPoints, data = fgw_data(&argv[1+ao])); + PCB_ACT_CONVARG(2+ao, FGW_LAYER, PolyNewFromPoints, layer = fgw_layer(&argv[2+ao])); + PCB_ACT_CONVARG(3+ao, FGW_PTR, PolyNewPoints, poly = argv[3+ao].val.ptr_void); + if (!fgw_ptr_in_domain(&pcb_fgw, &argv[1], PTR_DOMAIN_POLY)) { + pcb_message(PCB_MSG_ERROR, "PolyNewEnd: invalid polygon pointer\n"); + PCB_ACT_IRES(0); + return 0; + } + if (poly->PointN < 3) { + pcb_message(PCB_MSG_ERROR, "PolyNewEnd: can not finish polygon, need at least 3 points\n"); + PCB_ACT_IRES(0); + return 0; + } + + pcb_poly_init_clip(data, layer, poly); + pcb_add_poly_on_layer(layer, poly); + res->type = FGW_LONG; + res->val.nat_long = poly->ID; + if (!noundo) + pcb_undo_add_obj_to_create(PCB_OBJ_POLY, layer, poly, poly); + fgw_ptr_unreg(&pcb_fgw, &argv[1], PTR_DOMAIN_POLY); + return 0; +} + +pcb_action_t act_draw_action_list[] = { + {"GetValue", pcb_act_GetValue, pcb_acth_GetValue, pcb_acts_GetValue}, + {"LineNew", pcb_act_LineNew, pcb_acth_LineNew, pcb_acts_LineNew}, + {"ArcNew", pcb_act_ArcNew, pcb_acth_ArcNew, pcb_acts_ArcNew}, + {"TextNew", pcb_act_TextNew, pcb_acth_TextNew, pcb_acts_TextNew}, + {"PstkNew", pcb_act_PstkNew, pcb_acth_PstkNew, pcb_acts_PstkNew}, + {"PolyNewFromRectangle", pcb_act_PolyNewFromRectangle, pcb_acth_PolyNewFromRectangle, pcb_acts_PolyNewFromRectangle}, + {"PolyNewFromPoints", pcb_act_PolyNewFromPoints, pcb_acth_PolyNewFromPoints, pcb_acts_PolyNewFromPoints}, + {"PolyNew", pcb_act_PolyNew, pcb_acth_PolyNew, pcb_acts_PolyNew}, + {"PolyNewPoints", pcb_act_PolyNewPoints, pcb_acth_PolyNewPoints, pcb_acts_PolyNewPoints}, + {"PolyNewEnd", pcb_act_PolyNewEnd, pcb_acth_PolyNewEnd, pcb_acts_PolyNewEnd}, +}; + +static const char *act_draw_cookie = "act_draw"; + +PCB_REGISTER_ACTIONS(act_draw_action_list, act_draw_cookie) + +int pplg_check_ver_act_draw(int ver_needed) { return 0; } + +void pplg_uninit_act_draw(void) +{ + pcb_remove_actions_by_cookie(act_draw_cookie); +} + +#include "dolists.h" +int pplg_init_act_draw(void) +{ + PCB_API_CHK_VER; + PCB_REGISTER_ACTIONS(act_draw_action_list, act_draw_cookie) + return 0; +} Index: tags/2.1.2/src_plugins/act_draw/act_draw.pup =================================================================== --- tags/2.1.2/src_plugins/act_draw/act_draw.pup (nonexistent) +++ tags/2.1.2/src_plugins/act_draw/act_draw.pup (revision 24813) @@ -0,0 +1,7 @@ +$class feature +$short action wrappers for drawing +$long Expose drawing related API as actions +$state works +$package (core) +default buildin +autoload 1 Index: tags/2.1.2/src_plugins/ar_cpcb/Makefile =================================================================== --- tags/2.1.2/src_plugins/ar_cpcb/Makefile (nonexistent) +++ tags/2.1.2/src_plugins/ar_cpcb/Makefile (revision 24813) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_ar_cpcb + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/2.1.2/src_plugins/ar_cpcb/Plug.tmpasm =================================================================== --- tags/2.1.2/src_plugins/ar_cpcb/Plug.tmpasm (nonexistent) +++ tags/2.1.2/src_plugins/ar_cpcb/Plug.tmpasm (revision 24813) @@ -0,0 +1,10 @@ +put /local/pcb/mod {ar_cpcb} +put /local/pcb/mod/OBJS [@ + $(PLUGDIR)/ar_cpcb/ar_cpcb.o +@] + +switch /local/pcb/ar_cpcb/controls + case {buildin} include /local/pcb/tmpasm/buildin; end; + case {plugin} include /local/pcb/tmpasm/plugin; end; + case {disable} include /local/pcb/tmpasm/disable; end; +end Index: tags/2.1.2/src_plugins/ar_cpcb/ar_cpcb.c =================================================================== --- tags/2.1.2/src_plugins/ar_cpcb/ar_cpcb.c (nonexistent) +++ tags/2.1.2/src_plugins/ar_cpcb/ar_cpcb.c (revision 24813) @@ -0,0 +1,427 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * + * auto routing with c-pcb (selective import/export in c-pcb format) + * pcb-rnd Copyright (C) 2018 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "config.h" + +#include +#include +#include + +#include "board.h" +#include "data.h" +#include "plugins.h" +#include "actions.h" +#include "safe_fs.h" +#include "conf_core.h" +#include "obj_pstk_inlines.h" +#include "src_plugins/lib_compat_help/pstk_compat.h" +#include "src_plugins/lib_netmap/netmap.h" + +static const char *cpcb_cookie = "cpcb plugin"; + +typedef struct { + int maxlayer; + pcb_layer_t *copper[PCB_MAX_LAYERGRP]; +} cpcb_layers_t; + +typedef struct { + pcb_netmap_t netmap; + + /* int -> net conversion */ + pcb_net_t **i2n; + int maxnets; + + /* net->int conversion */ + htpi_t n2i; +} cpcb_netmap_t; + +static void cpcb_map_layers(pcb_board_t *pcb, cpcb_layers_t *dst) +{ + int gid; + pcb_layergrp_t *grp; + /* map copper layers from top to bottom */ + dst->maxlayer = 0; + for(gid = 0, grp = pcb->LayerGroups.grp; gid < pcb->LayerGroups.len; gid++,grp++) { + if ((grp->ltype & PCB_LYT_COPPER) && (grp->len > 0) && (grp->vis)) { + dst->copper[dst->maxlayer] = pcb_get_layer(pcb->Data, grp->lid[0]); + dst->maxlayer++; + } + } +} + +static int cpcb_map_nets(pcb_board_t *pcb, cpcb_netmap_t *dst) +{ + htpp_entry_t *e; + long id; + + if (pcb_netmap_init(&dst->netmap, pcb) != 0) + return -1; + + dst->maxnets = 0; + for(e = htpp_first(&dst->netmap.o2n); e != NULL; e = htpp_next(&dst->netmap.o2n, e)) + dst->maxnets++; + + if (dst->maxnets == 0) + return -1; + + dst->i2n = malloc(sizeof(pcb_net_t *) * dst->maxnets); + htpi_init(&dst->n2i, ptrhash, ptrkeyeq); + + id = 0; + for(e = htpp_first(&dst->netmap.n2o); e != NULL; e = htpp_next(&dst->netmap.n2o, e)) { + dst->i2n[id] = (pcb_net_t *)e->key; + htpi_set(&dst->n2i, e->key, id); + id++; + } + + return 0; +} + + +static void cpcb_free_nets(cpcb_netmap_t *dst) +{ + htpi_uninit(&dst->n2i); + free(dst->i2n); + pcb_netmap_uninit(&dst->netmap); +} + + +static int cpcb_load(pcb_board_t *pcb, FILE *f, cpcb_layers_t *stack, cpcb_netmap_t *nmap) +{ + gsx_parse_res_t res; + gsxl_dom_t dom; + gsxl_node_t *rn, *n; + int c; + + /* low level s-expression parse */ + gsxl_init(&dom, gsxl_node_t); + dom.parse.line_comment_char = '#'; + gsxl_parse_char(&dom, '('); /* have to fake the whole file is a single expression */ + do { + c = fgetc(f); + if (c == EOF) + gsxl_parse_char(&dom, ')'); /* have to fake the whole file is a single expression */ + } while((res = gsxl_parse_char(&dom, c)) == GSX_RES_NEXT); + if (res != GSX_RES_EOE) + return -1; + + for(rn = gsxl_children(dom.root); rn != NULL; rn = gsxl_next(rn)) { + int numch = 0; + gsxl_node_t *p, *nid, *ntr, *nvr, *ngap, *npads, *npaths, *nx, *ny, *nl; + pcb_coord_t thick, clear, via_dia; + char *end; + + for(n = gsxl_children(rn); n != NULL; n = gsxl_next(n)) numch++; + switch(numch) { + case 0: + printf("EOF\n"); + break; + case 3: + printf("dim: %s %s ly=%s\n", gsxl_nth(rn, 1)->str, gsxl_nth(rn, 2)->str, gsxl_nth(rn, 3)->str); + break; + case 6: /* tracks */ + nid = gsxl_nth(rn, 1); + ntr = gsxl_next(nid); thick = 2*PCB_MM_TO_COORD(strtod(ntr->str, NULL)); + nvr = gsxl_next(ntr); via_dia = 2*PCB_MM_TO_COORD(strtod(nvr->str, NULL)); + ngap = gsxl_next(nvr); clear = PCB_MM_TO_COORD(strtod(ngap->str, NULL)); + npads = gsxl_next(ngap); + npaths = gsxl_next(npads); + + for(n = gsxl_children(npaths); n != NULL; n = gsxl_next(n)) { /* iterate over all paths of the track */ + pcb_coord_t lx, ly, x, y; + int len = 0, lidx, llidx; + + for(p = gsxl_children(n); p != NULL; p = gsxl_next(p)) { /* iterate over all points of the path */ + pcb_line_t *line; + nx = gsxl_children(p); x = PCB_MM_TO_COORD(strtod(nx->str, NULL)); + ny = gsxl_next(nx); y = PCB_MM_TO_COORD(strtod(ny->str, NULL)); + nl = gsxl_next(ny); + + lidx = strtol(nl->str, &end, 10); + if (*end != '\0') { + pcb_message(PCB_MSG_ERROR, "Ignoring invalid layer index '%s' (not an integer) in line %ld\n", nl->str, (long)nl->line); + continue; + } + if ((lidx < 0) || (lidx >= stack->maxlayer)) { + pcb_message(PCB_MSG_ERROR, "Ignoring invalid layer index '%s' (out of range) in line %ld\n", nl->str, (long)nl->line); + continue; + } + + if (len > 0) { + if (llidx != lidx) { + if ((lx == x) && (ly == y)) { + pcb_pstk_t *ps = pcb_pstk_new_compat_via(pcb->Data, -1, x, y, + conf_core.design.via_drilling_hole, via_dia, conf_core.design.clearance, + 0, PCB_PSTK_COMPAT_ROUND, pcb_true); + } + else + pcb_message(PCB_MSG_ERROR, "Invalid via: not vertical, in line %ld:%ld\n", (long)nl->line, (long)nl->col); + } + else + line = pcb_line_new(stack->copper[lidx], lx, ly, x, y, thick, clear, pcb_flag_make(PCB_FLAG_CLEARLINE)); + } + lx = x; + ly = y; + llidx = lidx; + len++; + } + } + break; + } + } + + return 0; +} + +static void cpcb_print_pads(pcb_board_t *pcb, FILE *f, pcb_any_obj_t *o, cpcb_layers_t *stack) +{ + int lidx; + + switch(o->type) { + case PCB_OBJ_PSTK: + for(lidx = 0; lidx < stack->maxlayer; lidx++) { + int n; + pcb_pstk_t *ps = (pcb_pstk_t *)o; + pcb_pstk_shape_t *shp = pcb_pstk_shape_at(pcb, ps, stack->copper[lidx]); + if (shp == NULL) + continue; + switch(shp->shape) { + case PCB_PSSH_LINE: + case PCB_PSSH_HSHADOW: + TODO("generate a poly"); + break; + case PCB_PSSH_POLY: + pcb_fprintf(f, "(0 %mm (%mm %mm %d) (", conf_core.design.clearance, ps->x, ps->y, lidx); + for(n = 0; n < shp->data.poly.len; n++) + pcb_fprintf(f, "(%mm %mm)", shp->data.poly.x[n], shp->data.poly.y[n]); + fprintf(f, "))"); + break; + case PCB_PSSH_CIRC: + pcb_fprintf(f, "(%mm %mm (%mm %mm %d) ())", shp->data.circ.dia/2, conf_core.design.clearance, ps->x, ps->y, lidx); + break; + } + } + break; + case PCB_OBJ_LINE: + break; + case PCB_OBJ_POLY: + break; + case PCB_OBJ_TEXT: + case PCB_OBJ_ARC: + break; + +TODO("subc-in-subc: subc as terminal") + case PCB_OBJ_SUBC: + break; + + /* these can not ever be terminals */ + case PCB_OBJ_VOID: + case PCB_OBJ_RAT: + case PCB_OBJ_NET: + case PCB_OBJ_NET_TERM: + case PCB_OBJ_LAYER: + case PCB_OBJ_LAYERGRP: + break; + } +} + +static int cpcb_save(pcb_board_t *pcb, FILE *f, cpcb_layers_t *stack, cpcb_netmap_t *nmap) +{ + htpp_entry_t *e; + + /* print dims */ + pcb_fprintf(f, "(%d %d %d)\n", (int)(PCB_COORD_TO_MM(pcb->MaxWidth)+0.5), (int)(PCB_COORD_TO_MM(pcb->MaxHeight)+0.5), stack->maxlayer); + + /* print tracks */ + for(e = htpp_first(&nmap->netmap.n2o); e != NULL; e = htpp_next(&nmap->netmap.n2o, e)) { + pcb_net_t *net = e->key; + dyn_obj_t *o, *olist = e->value; + long id = htpi_get(&nmap->n2i, net); + +/* pcb_fprintf(f, "# %s: %ld\n", net->Name, id);*/ + pcb_fprintf(f, "(%ld %mm %mm %mm\n", id, conf_core.design.line_thickness/2, conf_core.design.via_thickness/2, conf_core.design.clearance); + + /* print pads (terminals) */ + pcb_fprintf(f, " ("); + for(o = olist; o != NULL; o = o->next) + if (o->obj->term != NULL) + cpcb_print_pads(pcb, f, o->obj, stack); + pcb_fprintf(f, ")\n"); + + fprintf(f, " ()\n"); + + fprintf(f, ")\n"); + } + + /* print eof marker */ + fprintf(f, "()\n"); + return 0; +} + +static const char pcb_acts_import_cpcb[] = "ImportcpcbFrom(filename)"; +static const char pcb_acth_import_cpcb[] = "Loads the auto-routed tracks from the specified c-pcb output."; +fgw_error_t pcb_act_import_cpcb(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + const char *fn; + FILE *f; + cpcb_layers_t stk; + + PCB_ACT_CONVARG(1, FGW_STR, import_cpcb, fn = argv[1].val.str); + + f = pcb_fopen(fn, "r"); + if (f == NULL) { + pcb_message(PCB_MSG_ERROR, "Can not open %s for read\n", fn); + PCB_ACT_IRES(-1); + return 0; + } + + cpcb_map_layers(PCB, &stk); + cpcb_load(PCB, f, &stk, NULL); + + fclose(f); + + PCB_ACT_IRES(0); + return 0; +} + +static const char pcb_acts_export_cpcb[] = "ExportcpcbTo(filename)"; +static const char pcb_acth_export_cpcb[] = "Dumps the current board in c-pcb format."; +fgw_error_t pcb_act_export_cpcb(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + const char *fn; + FILE *f; + cpcb_layers_t stk; + cpcb_netmap_t nmap; + + PCB_ACT_CONVARG(1, FGW_STR, export_cpcb, fn = argv[1].val.str); + + f = pcb_fopen(fn, "w"); + if (f == NULL) { + pcb_message(PCB_MSG_ERROR, "Can not open %s for write\n", fn); + PCB_ACT_IRES(-1); + return 0; + } + + if (cpcb_map_nets(PCB, &nmap) != 0) { + fclose(f); + pcb_message(PCB_MSG_ERROR, "Failed to map nets\n"); + PCB_ACT_IRES(-1); + return 0; + } + + cpcb_map_layers(PCB, &stk); + cpcb_save(PCB, f, &stk, &nmap); + cpcb_free_nets(&nmap); + + fclose(f); + + PCB_ACT_IRES(0); + return 0; +} + +static const char pcb_acts_cpcb[] = "cpcb(board|selected, [command])"; +static const char pcb_acth_cpcb[] = "Executed external autorouter cpcb to route the board or parts of the board"; +fgw_error_t pcb_act_cpcb(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + const char *scope, *cmd = "cpcb", *tmpfn = "cpcb.tmp"; + char *cmdline; + FILE *f; + cpcb_layers_t stk; + cpcb_netmap_t nmap; + + PCB_ACT_CONVARG(1, FGW_STR, cpcb, scope = argv[1].val.str); + PCB_ACT_MAY_CONVARG(2, FGW_STR, cpcb, cmd = argv[2].val.str); + + if (strcmp(scope, "board") != 0) { + pcb_message(PCB_MSG_ERROR, "Only board routing is supported at the moment\n"); + PCB_ACT_IRES(-1); + return 0; + } + + f = pcb_fopen(tmpfn, "w"); + if (f == NULL) { + pcb_message(PCB_MSG_ERROR, "Can not open temp file %s for write\n", tmpfn); + PCB_ACT_IRES(-1); + return 0; + } + + if (cpcb_map_nets(PCB, &nmap) != 0) { + fclose(f); + pcb_message(PCB_MSG_ERROR, "Failed to map nets\n"); + PCB_ACT_IRES(-1); + return 0; + } + + cpcb_map_layers(PCB, &stk); + cpcb_save(PCB, f, &stk, &nmap); + fclose(f); + + cmdline = pcb_strdup_printf("%s < %s", cmd, tmpfn); + f = pcb_popen(cmdline, "r"); + if (f != NULL) { + cpcb_load(PCB, f, &stk, NULL); + pclose(f); + PCB_ACT_IRES(0); + } + else { + pcb_message(PCB_MSG_ERROR, "Failed to execute c-pcb\n"); + PCB_ACT_IRES(-1); + return 0; + } + +/* pcb_remove(tmpfn);*/ + free(cmdline); + cpcb_free_nets(&nmap); + return 0; +} + +static pcb_action_t cpcb_action_list[] = { + {"ImportcpcbFrom", pcb_act_import_cpcb, pcb_acth_import_cpcb, pcb_acts_import_cpcb}, + {"ExportcpcbTo", pcb_act_export_cpcb, pcb_acth_export_cpcb, pcb_acts_export_cpcb}, + {"cpcb", pcb_act_cpcb, pcb_acth_cpcb, pcb_acts_cpcb} +}; + +PCB_REGISTER_ACTIONS(cpcb_action_list, cpcb_cookie) + +int pplg_check_ver_ar_cpcb(int ver_needed) { return 0; } + +void pplg_uninit_ar_cpcb(void) +{ + pcb_remove_actions_by_cookie(cpcb_cookie); +} + + +#include "dolists.h" +int pplg_init_ar_cpcb(void) +{ + PCB_API_CHK_VER; + + PCB_REGISTER_ACTIONS(cpcb_action_list, cpcb_cookie) + + return 0; +} Index: tags/2.1.2/src_plugins/ar_cpcb/ar_cpcb.pup =================================================================== --- tags/2.1.2/src_plugins/ar_cpcb/ar_cpcb.pup (nonexistent) +++ tags/2.1.2/src_plugins/ar_cpcb/ar_cpcb.pup (revision 24813) @@ -0,0 +1,11 @@ +$class feature +$short autoroute with c-pcb +$long Autoroute using external tool c-pcb +$state WIP +$package auto +default buildin +dep lib_gensexpr +dep lib_compat_help +dep lib_netmap +autoload 1 + Index: tags/2.1.2/src_plugins/asm/Makefile =================================================================== --- tags/2.1.2/src_plugins/asm/Makefile (nonexistent) +++ tags/2.1.2/src_plugins/asm/Makefile (revision 24813) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_asm + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/2.1.2/src_plugins/asm/Plug.tmpasm =================================================================== --- tags/2.1.2/src_plugins/asm/Plug.tmpasm (nonexistent) +++ tags/2.1.2/src_plugins/asm/Plug.tmpasm (revision 24813) @@ -0,0 +1,14 @@ +put /local/pcb/mod {asm} +put /local/pcb/mod/CONF {$(PLUGDIR)/asm/asm_conf.h} +put /local/pcb/mod/CONFFILE {asm.conf} +put /local/pcb/mod/CONFVAR {asm_conf_internal} +put /local/pcb/mod/OBJS [@ + $(PLUGDIR)/asm/asm.o +@] + + +switch /local/pcb/asm/controls + case {buildin} include /local/pcb/tmpasm/buildin; end; + case {plugin} include /local/pcb/tmpasm/plugin; end; + case {disable} include /local/pcb/tmpasm/disable; end; +end Index: tags/2.1.2/src_plugins/asm/asm.c =================================================================== --- tags/2.1.2/src_plugins/asm/asm.c (nonexistent) +++ tags/2.1.2/src_plugins/asm/asm.c (revision 24813) @@ -0,0 +1,601 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * + * hand assembly assistant GUI + * pcb-rnd Copyright (C) 2018 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "config.h" + +#include +#include +#include + +#include "board.h" +#include "data.h" +#include "plugins.h" +#include "actions.h" +#include "compat_misc.h" +#include "obj_subc.h" +#include "pcb-printf.h" +#include "hid_dad.h" +#include "hid_dad_tree.h" +#include "search.h" +#include "draw.h" +#include "select.h" +#include "asm_conf.h" +#include "../src_plugins/asm/conf_internal.c" + +conf_asm_t conf_asm; +#define ASM_CONF_FN "asm.conf" + + +static const char *asm_cookie = "asm plugin"; + +/*** internal list of all parts, grouped; have to be arrays for qsort(), so can't + avoid it and just use tree-table list based trees ***/ +typedef enum { + TT_ATTR, + TT_SIDE, + TT_X, + TT_Y +} ttype_t; + +typedef struct { + ttype_t type; + const char *key; + gdl_elem_t link; +} template_t; + +typedef struct { + int is_grp; + char *name; + pcb_hid_row_t *row; + vtp0_t parts; +} group_t; + +typedef struct { + int is_grp; + char *name; + long int id; + int done; + pcb_hid_row_t *row; + group_t *parent; +} part_t; + +/* dialog context */ +typedef struct{ + PCB_DAD_DECL_NOINIT(dlg) + vtp0_t grps; + vtclr_t layer_colors; /* saved before greying out */ + int wtbl, wskipg, wdoneg, wskipp, wdonep; + int active; /* already open - allow only one instance */ +} asm_ctx_t; + +asm_ctx_t asm_ctx; + +/*** template compiling ***/ +static void templ_append(gdl_list_t *dst, ttype_t type, const char *key) +{ + template_t *t = calloc(sizeof(template_t), 1); + t->type = type; + t->key = key; + gdl_append(dst, t, link); +} + +static char *templ_compile(gdl_list_t *dst, const char *src_) +{ + char *s, *next, *src = pcb_strdup(src_); + + for(s = src; (s != NULL) && (*s != '\0'); s = next) { + while(isspace(*s) || (*s == ',')) s++; + next = strpbrk(s, " \t\r\n,"); + if (next != NULL) { + *next = '\0'; + next++; + } + if ((s[0] == 'a') && (s[1] == '.')) { + s+=2; + templ_append(dst, TT_ATTR, s); + } + else if (strcmp(s, "side") == 0) + templ_append(dst, TT_SIDE, NULL); + else if (strcmp(s, "x") == 0) + templ_append(dst, TT_X, NULL); + else if (strcmp(s, "y") == 0) + templ_append(dst, TT_Y, NULL); + else + pcb_message(PCB_MSG_ERROR, "Ignoring unknown asm template entry: '%s'\n", s); + } + return src; +} + +/* allocate a string and build a sortable text summary of a subc using the template */ +static char *templ_exec(pcb_subc_t *subc, gdl_list_t *temp) +{ + gds_t s; + template_t *t; + int n, bot, have_coords = 0; + char *tmp, buf[64]; + pcb_coord_t x = 0, y = 0; + + gds_init(&s); + for(n = 0, t = gdl_first(temp); t != NULL; n++, t = gdl_next(temp, t)) { + if (n != 0) + gds_append(&s, ','); + switch(t->type) { + case TT_ATTR: + tmp = pcb_attribute_get(&subc->Attributes, t->key); + if (tmp != NULL) + gds_append_str(&s, tmp); + break; + case TT_SIDE: + bot = 0; + pcb_subc_get_side(subc, &bot); + gds_append_str(&s, (bot ? "1/bottom" : "0/top")); + break; + case TT_X: + if (!have_coords) { + pcb_subc_get_origin(subc, &x, &y); + have_coords = 1; + } + pcb_sprintf(buf, "%.08mm", x); + break; + case TT_Y: + if (!have_coords) { + pcb_subc_get_origin(subc, &x, &y); + have_coords = 1; + } + pcb_sprintf(buf, "%.08mm", y); + break; + } + } + return s.array; +} + +static void templ_free(char *tmp, gdl_list_t *dst) +{ + template_t *t; + + for(t = gdl_first(dst); t != NULL; t = gdl_first(dst)) { + gdl_remove(dst, t, link); + free(t); + } + + free(tmp); +} + +static group_t *group_lookup(vtp0_t *grps, htsp_t *gh, char *name, int alloc) +{ + group_t *g = htsp_get(gh, name); + if (g != NULL) { + free(name); + return g; + } + + g = calloc(sizeof(group_t), 1); + g->is_grp = 1; + g->name = name; + + vtp0_append(grps, g); + htsp_set(gh, name, g); + return g; +} + +static void part_append(group_t *g, char *sortstr, long int id) +{ + part_t *p = malloc(sizeof(part_t)); + p->is_grp = 0; + p->name = sortstr; + p->id = id; + p->done = 0; + p->parent = g; + vtp0_append(&g->parts, p); +} + +/* Extract the part list from data */ +static void asm_extract(vtp0_t *dst, pcb_data_t *data, const char *group_template, const char *sort_template) +{ + gdl_list_t cgroup, csort; + char *tmp_group, *tmp_sort; + htsp_t gh; + + memset(&cgroup, 0, sizeof(cgroup)); + memset(&csort, 0, sizeof(csort)); + tmp_group = templ_compile(&cgroup, group_template); + tmp_sort = templ_compile(&csort, sort_template); + + htsp_init(&gh, strhash, strkeyeq); + + PCB_SUBC_LOOP(data); + { + char *grp, *srt; + group_t *g; + + grp = templ_exec(subc, &cgroup); + srt = templ_exec(subc, &csort); + g = group_lookup(dst, &gh, grp, 1); + part_append(g, srt, subc->ID); + /* no need to free grp or srt, they are stored in the group and part structs */ + } + PCB_END_LOOP; + + htsp_uninit(&gh); + templ_free(tmp_group, &cgroup); + templ_free(tmp_sort, &csort); +} + +/*** Sort the part list ***/ +static int group_cmp(const void *ga_, const void *gb_) +{ + const group_t * const *ga = ga_; + const group_t * const *gb = gb_; + return strcmp((*ga)->name, (*gb)->name); +} + +static int part_cmp(const void *pa_, const void *pb_) +{ + const part_t * const *pa = pa_; + const part_t * const *pb = pb_; + return strcmp((*pa)->name, (*pb)->name); +} + +static void asm_sort(vtp0_t *gv) +{ + group_t **g; + long n; + + qsort(gv->array, gv->used, sizeof(void *), group_cmp); + for(g = (group_t **)gv->array, n = 0; n < gv->used; g++,n++) + qsort((*g)->parts.array, (*g)->parts.used, sizeof(void *), part_cmp); +} + +/*** Gray out all layers to make selection stick out more ***/ +static int fade(int c, int factor) +{ + if (c > 127) + return 127 + (c - 127) / factor; + return 127 - (127 - c) / factor; +} + +static void asm_greyout(int grey) +{ + int n; + pcb_data_t *data = PCB->Data; + pcb_layer_t *ly; + + if (grey) { + vtclr_init(&asm_ctx.layer_colors); + vtclr_enlarge(&asm_ctx.layer_colors, data->LayerN); + for(n = 0, ly = data->Layer; n < data->LayerN; n++,ly++) { + int r, g, b; + + vtclr_set(&asm_ctx.layer_colors, n, ly->meta.real.color); + r = ly->meta.real.color.r; + g = ly->meta.real.color.g; + b = ly->meta.real.color.b; + r = fade(r, 4); + g = fade(g, 4); + b = fade(b, 4); + pcb_color_load_int(&ly->meta.real.color, r, g, b, 255); + } + } + else { + for(n = 0, ly = data->Layer; n < data->LayerN; n++,ly++) + ly->meta.real.color = asm_ctx.layer_colors.array[n]; + vtclr_uninit(&asm_ctx.layer_colors); + } + pcb_redraw(); +} + +/*** UI callbacks ***/ +static void asm_close_cb(void *caller_data, pcb_hid_attr_ev_t ev) +{ + group_t **g; + part_t **p; + long i, n; + asm_ctx_t *ctx = caller_data; + asm_greyout(0); + + for(g = (group_t **)asm_ctx.grps.array, n = 0; n < asm_ctx.grps.used; g++,n++) { + for(p = (part_t **)(*g)->parts.array, i = 0; i < (*g)->parts.used; p++,i++) + free(*p); + vtp0_uninit(&(*g)->parts); + free(*g); + } + vtp0_uninit(&asm_ctx.grps); + + PCB_DAD_FREE(ctx->dlg); + memset(ctx, 0, sizeof(asm_ctx_t)); +} + +static void select_part(part_t *p) +{ + void *r1, *r2, *r3; + pcb_objtype_t type; + + type = pcb_search_obj_by_id_(PCB->Data, &r1, &r2, &r3, p->id, PCB_OBJ_SUBC); + if (type != PCB_OBJ_SUBC) + return; + + pcb_subc_select(PCB, (pcb_subc_t *)r2, PCB_CHGFLG_SET, 1); +} + +static void asm_row_selected(pcb_hid_attribute_t *attrib, void *hid_ctx, pcb_hid_row_t *row) +{ + long n; + int isgrp = 0, ispart = 0; + pcb_box_t box; + + /* unselect all */ + box.X1 = -PCB_MAX_COORD; + box.Y1 = -PCB_MAX_COORD; + box.X2 = PCB_MAX_COORD; + box.Y2 = PCB_MAX_COORD; + if (pcb_select_block(PCB, &box, pcb_false, pcb_false, pcb_false)) + pcb_board_set_changed_flag(pcb_true); + + if (row == NULL) { + goto skip; + } + if (*(int *)row->user_data) { + group_t *g = row->user_data; + part_t **p; + isgrp = 1; + for(n = 0, p = (part_t **)g->parts.array; n < g->parts.used; n++,p++) + select_part(*p); + } + else { + part_t *p = row->user_data; + ispart = 1; + select_part(p); + } + + skip:; + pcb_gui->attr_dlg_widget_state(hid_ctx, asm_ctx.wskipg, isgrp | ispart); + pcb_gui->attr_dlg_widget_state(hid_ctx, asm_ctx.wdoneg, isgrp | ispart); + pcb_gui->attr_dlg_widget_state(hid_ctx, asm_ctx.wskipp, ispart); + pcb_gui->attr_dlg_widget_state(hid_ctx, asm_ctx.wdonep, ispart); + pcb_redraw(); /* for displaying the new selection */ +} + +static void skip(void *hid_ctx, int pick_grp, pcb_hid_row_t *row) +{ + pcb_hid_row_t *nr = NULL; + int is_grp = *(int *)row->user_data; + + if (pick_grp && !is_grp) { + /* special case: next group from a part: skip the whole group */ + goto skip_parent; + } + else if (!pick_grp || is_grp) { + /* try to pick the next row first */ + nr = row->link.next; + } + + if (nr == NULL) { + part_t *p; + if (is_grp) + goto last; /* skipping from the last group -> unselect all */ + /* skipping from last part in a group -> jump to next group's first part */ + skip_parent:; + p = row->user_data; + nr = p->parent->row; + nr = nr->link.next; + if (nr == NULL) + goto last; /* skipping from the last part of the last group -> unselect all */ + nr = gdl_first(&nr->children); + } + pcb_dad_tree_jumpto(&asm_ctx.dlg[asm_ctx.wtbl], nr); + return; + + last:; + /* what happens after the last */ + pcb_dad_tree_jumpto(&asm_ctx.dlg[asm_ctx.wtbl], NULL); + return; +} + +static void done(void *hid_ctx, part_t *part, int done) +{ + part->done = 1; + pcb_dad_tree_modify_cell(&asm_ctx.dlg[asm_ctx.wtbl], part->row, 5, "yes"); +} + +static void asm_done_part(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + pcb_hid_row_t *row = pcb_dad_tree_get_selected(&asm_ctx.dlg[asm_ctx.wtbl]); + if (*(int *)row->user_data) + return; + done(hid_ctx, row->user_data, 1); + skip(hid_ctx, 0, row); +} + +static void asm_skip_part(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + pcb_hid_row_t *row = pcb_dad_tree_get_selected(&asm_ctx.dlg[asm_ctx.wtbl]); + if (*(int *)row->user_data) + return; + skip(hid_ctx, 0, row); +} + +static void asm_done_group(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + long n; + group_t *g; + pcb_hid_row_t *row = pcb_dad_tree_get_selected(&asm_ctx.dlg[asm_ctx.wtbl]); + + if (!*(int *)row->user_data) { + part_t *p = row->user_data; + g = p->parent; + } + else + g = row->user_data; + + for(n = 0; n < g->parts.used; n++) + done(hid_ctx, g->parts.array[n], 1); + skip(hid_ctx, 1, row); +} + +static void asm_skip_group(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + pcb_hid_row_t *row = pcb_dad_tree_get_selected(&asm_ctx.dlg[asm_ctx.wtbl]); + + skip(hid_ctx, 1, row); +} + + +static const char pcb_acts_asm[] = "asm()"; +static const char pcb_acth_asm[] = "Interactive assembly assistant"; +fgw_error_t pcb_act_asm(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + const char *hdr[] = { "name", "refdes", "footprint", "value", "comments", "done", NULL }; + char *row[7]; + group_t **g; + part_t **p; + long n, i; + pcb_hid_dad_buttons_t clbtn[] = {{"Close", 0}, {NULL, 0}}; + + if (asm_ctx.active) { + PCB_ACT_IRES(0); + return 0; + } + + vtp0_init(&asm_ctx.grps); + asm_extract(&asm_ctx.grps, PCB->Data, conf_asm.plugins.asm1.group_template, conf_asm.plugins.asm1.sort_template); + asm_sort(&asm_ctx.grps); + + asm_greyout(1); + + PCB_DAD_BEGIN_VBOX(asm_ctx.dlg); + PCB_DAD_COMPFLAG(asm_ctx.dlg, PCB_HATF_EXPFILL); + PCB_DAD_TREE(asm_ctx.dlg, 6, 1, hdr); + asm_ctx.wtbl = PCB_DAD_CURRENT(asm_ctx.dlg); + PCB_DAD_COMPFLAG(asm_ctx.dlg, PCB_HATF_SCROLL); + for(g = (group_t **)asm_ctx.grps.array, n = 0; n < asm_ctx.grps.used; g++,n++) { + pcb_hid_row_t *parent, *child; + row[0] = (*g)->name; + row[1] = ""; + row[2] = ""; + row[3] = ""; + row[4] = ""; + row[5] = ""; + row[6] = NULL; + parent = PCB_DAD_TREE_APPEND(asm_ctx.dlg, NULL, row); + parent->user_data = *g; + (*g)->row = parent; + for(p = (part_t **)(*g)->parts.array, i = 0; i < (*g)->parts.used; p++,i++) { + void *r1, *r2, *r3; + pcb_subc_t *sc; + pcb_objtype_t type; + + type = pcb_search_obj_by_id_(PCB->Data, &r1, &r2, &r3, (*p)->id, PCB_OBJ_SUBC); + sc = r2; + + row[0] = (*p)->name; + if (type == PCB_OBJ_SUBC) { + int m; + row[1] = (char *)sc->refdes; + row[2] = pcb_attribute_get(&sc->Attributes, "footprint"); + row[3] = pcb_attribute_get(&sc->Attributes, "value"); + row[4] = pcb_attribute_get(&sc->Attributes, "asm::comment"); + row[5] = ""; + for(m = 1; m < 6; m++) + if (row[m] == NULL) + row[m] = ""; + } + else { + row[1] = ""; + row[2] = ""; + row[3] = ""; + row[4] = ""; + row[5] = ""; + } + row[6] = NULL; + child = PCB_DAD_TREE_APPEND_UNDER(asm_ctx.dlg, parent, row); + child->user_data = *p; + (*p)->row = child; + } + } + PCB_DAD_TREE_SET_CB(asm_ctx.dlg, selected_cb, asm_row_selected); + PCB_DAD_BEGIN_HBOX(asm_ctx.dlg); + PCB_DAD_BUTTON(asm_ctx.dlg, "skip part"); + asm_ctx.wskipp = PCB_DAD_CURRENT(asm_ctx.dlg); + PCB_DAD_HELP(asm_ctx.dlg, "Do not populate this part,\ncontinue with the next part"); + PCB_DAD_CHANGE_CB(asm_ctx.dlg, asm_skip_part); + PCB_DAD_BUTTON(asm_ctx.dlg, "skip group"); + asm_ctx.wskipg = PCB_DAD_CURRENT(asm_ctx.dlg); + PCB_DAD_HELP(asm_ctx.dlg, "Stop populating this group,\ncontinue with the next group"); + PCB_DAD_CHANGE_CB(asm_ctx.dlg, asm_skip_group); + PCB_DAD_BUTTON(asm_ctx.dlg, "done part"); + asm_ctx.wdonep = PCB_DAD_CURRENT(asm_ctx.dlg); + PCB_DAD_HELP(asm_ctx.dlg, "Mark current part done,\ncontinue with the next part"); + PCB_DAD_CHANGE_CB(asm_ctx.dlg, asm_done_part); + PCB_DAD_BUTTON(asm_ctx.dlg, "done group"); + asm_ctx.wdoneg = PCB_DAD_CURRENT(asm_ctx.dlg); + PCB_DAD_HELP(asm_ctx.dlg, "Mark all parts in this group done,\ncontinue with the next group"); + PCB_DAD_CHANGE_CB(asm_ctx.dlg, asm_done_group); + PCB_DAD_END(asm_ctx.dlg); + PCB_DAD_BUTTON_CLOSES(asm_ctx.dlg, clbtn); + PCB_DAD_END(asm_ctx.dlg); + + asm_ctx.active = 1; + PCB_DAD_NEW("asm", asm_ctx.dlg, "Hand assembly with pcb-rnd", &asm_ctx, pcb_false, asm_close_cb); + + /* expand all groups by default */ + for(g = (group_t **)asm_ctx.grps.array, n = 0; n < asm_ctx.grps.used; g++,n++) + pcb_dad_tree_expcoll(&asm_ctx.dlg[asm_ctx.wtbl], (*g)->row, 1, 0); + + PCB_ACT_IRES(0); + return 0; +} + +static pcb_action_t asm_action_list[] = { + {"asm", pcb_act_asm, pcb_acth_asm, pcb_acts_asm} +}; + +PCB_REGISTER_ACTIONS(asm_action_list, asm_cookie) + +int pplg_check_ver_asm(int ver_needed) { return 0; } + +void pplg_uninit_asm(void) +{ + pcb_remove_actions_by_cookie(asm_cookie); + conf_unreg_file(ASM_CONF_FN, asm_conf_internal); + conf_unreg_fields("plugins/asm1/"); +} + + +#include "dolists.h" +int pplg_init_asm(void) +{ + PCB_API_CHK_VER; + conf_reg_file(ASM_CONF_FN, asm_conf_internal); +#define conf_reg(field,isarray,type_name,cpath,cname,desc,flags) \ + conf_reg_field(conf_asm, field,isarray,type_name,cpath,cname,desc,flags); +#include "asm_conf_fields.h" + + PCB_REGISTER_ACTIONS(asm_action_list, asm_cookie) + + return 0; +} Index: tags/2.1.2/src_plugins/asm/asm.conf =================================================================== --- tags/2.1.2/src_plugins/asm/asm.conf (nonexistent) +++ tags/2.1.2/src_plugins/asm/asm.conf (revision 24813) @@ -0,0 +1,10 @@ +li:pcb-rnd-conf-v1 { + ha:append { + ha:plugins { + ha:asm1 { + group_template = {side, a.footprint, a.value, a.asm::group} + sort_template = {a.footprint, a.value, a.asm::group, side, x, y} + } + } + } +} Index: tags/2.1.2/src_plugins/asm/asm.pup =================================================================== --- tags/2.1.2/src_plugins/asm/asm.pup (nonexistent) +++ tags/2.1.2/src_plugins/asm/asm.pup (revision 24813) @@ -0,0 +1,8 @@ +$class feature +$short assembly GUI +$long hand assembly assistant GUI +$state WIP +$package auto +default buildin +autoload 1 + Index: tags/2.1.2/src_plugins/asm/asm_conf.h =================================================================== --- tags/2.1.2/src_plugins/asm/asm_conf.h (nonexistent) +++ tags/2.1.2/src_plugins/asm/asm_conf.h (revision 24813) @@ -0,0 +1,15 @@ +#ifndef PCB_ASM_CONF_H +#define PCB_ASM_CONF_H + +#include "conf.h" + +typedef struct { + const struct plugins { + const struct asm1 { + CFT_STRING group_template; /* asm template that determines grouping (parts resulting in the same string will be puit in the same group) */ + CFT_STRING sort_template; /* asm template that determines order of groups and parts within groups */ + } asm1; + } plugins; +} conf_asm_t; + +#endif Index: tags/2.1.2/src_plugins/autocrop/Makefile =================================================================== --- tags/2.1.2/src_plugins/autocrop/Makefile (nonexistent) +++ tags/2.1.2/src_plugins/autocrop/Makefile (revision 24813) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_autocrop + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/2.1.2/src_plugins/autocrop/Plug.tmpasm =================================================================== --- tags/2.1.2/src_plugins/autocrop/Plug.tmpasm (nonexistent) +++ tags/2.1.2/src_plugins/autocrop/Plug.tmpasm (revision 24813) @@ -0,0 +1,8 @@ +put /local/pcb/mod {autocrop} +put /local/pcb/mod/OBJS [@ $(PLUGDIR)/autocrop/autocrop.o @] + +switch /local/pcb/autocrop/controls + case {buildin} include /local/pcb/tmpasm/buildin; end; + case {plugin} include /local/pcb/tmpasm/plugin; end; + case {disable} include /local/pcb/tmpasm/disable; end; +end Index: tags/2.1.2/src_plugins/autocrop/autocrop.c =================================================================== --- tags/2.1.2/src_plugins/autocrop/autocrop.c (nonexistent) +++ tags/2.1.2/src_plugins/autocrop/autocrop.c (revision 24813) @@ -0,0 +1,96 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2016 Tibor 'Igor2' Palinkas + * + * This module, debug, was written and is Copyright (C) 2016 by Tibor Palinkas + * this module is also subject to the GNU GPL as described below + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ +#include "config.h" + +#include +#include + +#include "board.h" +#include "data.h" +#include "draw.h" +#include "undo.h" +#include "actions.h" +#include "plugins.h" + +static const char pcb_acth_autocrop[] = "Autocrops the board dimensions to (extants + a margin of 1 grid), keeping the move and board size grid aligned"; +static const char pcb_acts_autocrop[] = "autocrop()"; +static fgw_error_t pcb_act_autocrop(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + pcb_box_t box; + pcb_coord_t dx, dy, w, h; + + if (pcb_data_is_empty(PCB->Data)) + return 0; + + pcb_data_bbox(&box, PCB->Data, 0); + dx = -((box.X1 / PCB->Grid - 1) * PCB->Grid); + dy = -((box.Y1 / PCB->Grid - 1) * PCB->Grid); + w = ((box.X2 + dx) / PCB->Grid + 2) * PCB->Grid; + h = ((box.Y2 + dy) / PCB->Grid + 2) * PCB->Grid; + + if ((dx == 0) && (dy == 0) && (w == PCB->MaxWidth) && (h == PCB->MaxHeight)) + return 0; + + pcb_draw_inhibit_inc(); + pcb_data_clip_inhibit_inc(PCB->Data); + pcb_data_move(PCB->Data, dx, dy); + pcb_board_resize(w, h); + pcb_data_clip_inhibit_dec(PCB->Data, 1); + pcb_draw_inhibit_dec(); + + pcb_undo_inc_serial(); + pcb_redraw(); + pcb_board_set_changed_flag(1); + + PCB_ACT_IRES(0); + return 0; +} + +static pcb_action_t autocrop_action_list[] = { + {"autocrop", pcb_act_autocrop, pcb_acth_autocrop, pcb_acts_autocrop} +}; + +char *autocrop_cookie = "autocrop plugin"; + +PCB_REGISTER_ACTIONS(autocrop_action_list, autocrop_cookie) + +int pplg_check_ver_autocrop(int ver_needed) { return 0; } + +void pplg_uninit_autocrop(void) +{ + pcb_remove_actions_by_cookie(autocrop_cookie); +} + +#include "dolists.h" +int pplg_init_autocrop(void) +{ + PCB_API_CHK_VER; + PCB_REGISTER_ACTIONS(autocrop_action_list, autocrop_cookie); + return 0; +} Index: tags/2.1.2/src_plugins/autocrop/autocrop.pup =================================================================== --- tags/2.1.2/src_plugins/autocrop/autocrop.pup (nonexistent) +++ tags/2.1.2/src_plugins/autocrop/autocrop.pup (revision 24813) @@ -0,0 +1,7 @@ +$class feature +$short crop board to fit objects +$long Reduce the board dimensions to just enclose the objects on the board. +$package (core) +$state works +default buildin +autoload 1 Index: tags/2.1.2/src_plugins/autoplace/Makefile =================================================================== --- tags/2.1.2/src_plugins/autoplace/Makefile (nonexistent) +++ tags/2.1.2/src_plugins/autoplace/Makefile (revision 24813) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_autoplace + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/2.1.2/src_plugins/autoplace/Plug.tmpasm =================================================================== --- tags/2.1.2/src_plugins/autoplace/Plug.tmpasm (nonexistent) +++ tags/2.1.2/src_plugins/autoplace/Plug.tmpasm (revision 24813) @@ -0,0 +1,8 @@ +put /local/pcb/mod {autoplace} +put /local/pcb/mod/OBJS [@ $(PLUGDIR)/autoplace/autoplace.o $(PLUGDIR)/autoplace/action.o @] + +switch /local/pcb/autoplace/controls + case {buildin} include /local/pcb/tmpasm/buildin; end; + case {plugin} include /local/pcb/tmpasm/plugin; end; + case {disable} include /local/pcb/tmpasm/disable; end; +end Index: tags/2.1.2/src_plugins/autoplace/action.c =================================================================== --- tags/2.1.2/src_plugins/autoplace/action.c (nonexistent) +++ tags/2.1.2/src_plugins/autoplace/action.c (revision 24813) @@ -0,0 +1,77 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * Copyright (C) 1997, 1998, 1999, 2000, 2001 Harry Eaton + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + * + * Old contact info: + * Harry Eaton, 6697 Buttonhole Ct, Columbia, MD 21044, USA + * haceaton@aplcomm.jhuapl.edu + * + */ + +#include "config.h" +#include "autoplace.h" +#include "plugins.h" +#include "actions.h" +#include "board.h" +#include "event.h" + +static const char autoplace_syntax[] = "AutoPlaceSelected()"; +static const char autoplace_help[] = "Auto-place selected components."; +/* DOC: autoplaceselected */ +static fgw_error_t pcb_act_AutoPlaceSelected(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + pcb_event(PCB_EVENT_BUSY, NULL); + if (pcb_hid_message_box("question", "Autoplace start", "Auto-placement can NOT be undone.\nDo you want to continue anyway?", "no", 0, "yes", 1, NULL) == 1) { + if (AutoPlaceSelected()) + pcb_board_set_changed_flag(pcb_true); + } + PCB_ACT_IRES(0); + return 0; +} + +static const char *autoplace_cookie = "autoplace plugin"; + +pcb_action_t autoplace_action_list[] = { + {"AutoPlaceSelected", pcb_act_AutoPlaceSelected, autoplace_help, autoplace_syntax} +}; + +PCB_REGISTER_ACTIONS(autoplace_action_list, autoplace_cookie) + +int pplg_check_ver_autoplace(int ver_needed) { return 0; } + +void pplg_uninit_autoplace(void) +{ + pcb_remove_actions_by_cookie(autoplace_cookie); +} + +#include "dolists.h" +int pplg_init_autoplace(void) +{ + PCB_API_CHK_VER; + PCB_REGISTER_ACTIONS(autoplace_action_list, autoplace_cookie) + return 0; +} Index: tags/2.1.2/src_plugins/autoplace/autoplace.c =================================================================== --- tags/2.1.2/src_plugins/autoplace/autoplace.c (nonexistent) +++ tags/2.1.2/src_plugins/autoplace/autoplace.c (revision 24813) @@ -0,0 +1,806 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * Copyright (C) 1998,1999,2000,2001 harry eaton + * Copyright (C) 2018 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + * + * Old contact info: + * harry eaton, 6697 Buttonhole Ct, Columbia, MD 21044 USA + * haceaton@aplcomm.jhuapl.edu + * + */ + +/* + * This moduel, autoplace.c, was written by and is + * Copyright (c) 2001 C. Scott Ananian + */ + +/* functions used to autoplace subcircuits. + */ + +#include "config.h" + +#include +#include +#include +#include + +#include "board.h" +#include "autoplace.h" +#include "box.h" +#include "compat_misc.h" +#include "data.h" +#include "draw.h" +#include "error.h" +#include "layer.h" +#include "intersect.h" +#include "rtree.h" +#include "macro.h" +#include "move.h" +#include "netlist2.h" +#include "remove.h" +#include "rotate.h" +#include "obj_rat.h" +#include "obj_term.h" +#include "obj_pstk_inlines.h" +#include "board.h" +#include "data_it.h" +#include + +#define EXPANDRECTXY(r1, x1, y1, x2, y2) { \ + r1->X1=MIN(r1->X1, x1); r1->Y1=MIN(r1->Y1, y1); \ + r1->X2=MAX(r1->X2, x2); r1->Y2=MAX(r1->Y2, y2); \ +} +#define EXPANDRECT(r1, r2) EXPANDRECTXY(r1, r2->X1, r2->Y1, r2->X2, r2->Y2) + +const struct { + double via_cost; + double congestion_penalty; /* penalty length / unit area */ + double overlap_penalty_min; /* penalty length / unit area at start */ + double overlap_penalty_max; /* penalty length / unit area at end */ + double out_of_bounds_penalty; /* assessed for each component oob */ + double overall_area_penalty; /* penalty length / unit area */ + double matching_neighbor_bonus; /* length bonus per same-type neigh. */ + double aligned_neighbor_bonus; /* length bonus per aligned neigh. */ + double oriented_neighbor_bonus; /* length bonus per same-rot neigh. */ +#if 0 + double pin_alignment_bonus; /* length bonus per exact alignment */ + double bound_alignment_bonus; /* length bonus per exact alignment */ +#endif + double m; /* annealing stage cutoff constant */ + double gamma; /* annealing schedule constant */ + int good_ratio; /* ratio of moves to good moves for halting */ + pcb_bool fast; /* ignore SMD/pin conflicts */ + pcb_coord_t large_grid_size; /* snap perturbations to this grid when T is high */ + pcb_coord_t small_grid_size; /* snap to this grid when T is small. */ +} +/* wire cost is manhattan distance (in mils), thus 1 inch = 1000 */ CostParameter = +{ + 3e3, /* via cost */ + 2e-2, /* congestion penalty */ + 1e-2, /* initial overlap penalty */ + 1e2, /* final overlap penalty */ + 1e3, /* out of bounds penalty */ + 1e0, /* penalty for total area used */ + 1e0, /* subtract 1000 from cost for every same-type neighbor */ + 1e0, /* subtract 1000 from cost for every aligned neighbor */ + 1e0, /* subtract 1000 from cost for every same-rotation neighbor */ + 20, /* move on when each module has been profitably moved 20 times */ + 0.75, /* annealing schedule constant: 0.85 */ + 40, /* halt when there are 60 times as many moves as good moves */ + pcb_false, /* don't ignore SMD/pin conflicts */ + PCB_MIL_TO_COORD(100), /* coarse grid is 100 mils */ + PCB_MIL_TO_COORD(10), /* fine grid is 10 mils */ +}; + +enum ewhich { SHIFT, ROTATE, EXCHANGE }; + +typedef struct { + pcb_any_obj_t *comp; + enum ewhich which; + pcb_coord_t DX, DY; /* for shift */ + unsigned rotate; /* for rotate/flip */ + pcb_any_obj_t *other; /* for exchange */ +} PerturbationType; + +TODO("cleanup: remove this and use genvect") +#define STEP_POINT 100 + +/* get next slot for a box, allocates memory if necessary */ +static pcb_box_t *pcb_box_new(pcb_box_list_t *Boxes) +{ + pcb_box_t *box = Boxes->Box; + + /* realloc new memory if necessary and clear it */ + if (Boxes->BoxN >= Boxes->BoxMax) { + Boxes->BoxMax = STEP_POINT + (2 * Boxes->BoxMax); + box = (pcb_box_t *) realloc(box, Boxes->BoxMax * sizeof(pcb_box_t)); + Boxes->Box = box; + memset(box + Boxes->BoxN, 0, (Boxes->BoxMax - Boxes->BoxN) * sizeof(pcb_box_t)); + } + return (box + Boxes->BoxN++); +} + +/* frees memory used by a box list */ +static void pcb_box_free(pcb_box_list_t *Boxlist) +{ + if (Boxlist) { + free(Boxlist->Box); + memset(Boxlist, 0, sizeof(pcb_box_list_t)); + } +} + +/* Return a terminal's preferred layer group ID or -1 on error */ +static pcb_layergrp_id_t obj_layergrp(const pcb_any_obj_t *obj) +{ + pcb_layergrp_id_t SLayer = -1; + pcb_layer_t *layer; + + switch (obj->type) { + case PCB_OBJ_PSTK: + pcb_layergrp_list(PCB, PCB_LYT_BOTTOM | PCB_LYT_COPPER, &SLayer, 1); + return SLayer; /* any layer will do */ + break; + + /* terminals on layer */ + case PCB_OBJ_LINE: + case PCB_OBJ_ARC: + case PCB_OBJ_TEXT: + case PCB_OBJ_POLY: + layer = pcb_layer_get_real(obj->parent.layer); + if (layer != NULL) + return layer->meta.real.grp; + return SLayer; /* any layer will do */ + default: + pcb_message(PCB_MSG_ERROR, "Odd terminal type encountered in obj_layergrp()\n"); + } + return -1; +} + +/* --------------------------------------------------------------------------- + * Create a list of selected subcircuits + */ +static vtp0_t collectSelectedSubcircuits() +{ + vtp0_t list; + + vtp0_init(&list); + PCB_SUBC_LOOP(PCB->Data); + { + if (PCB_FLAG_TEST(PCB_FLAG_SELECTED, subc)) { + pcb_subc_t **epp = (pcb_subc_t **)vtp0_alloc_append(&list, 1); + *epp = subc; + } + } + PCB_END_LOOP; + return list; +} + +#if 0 /* only for debugging box lists */ +/* makes a line on the solder layer surrounding all boxes in blist */ +static void showboxes(pcb_box_list_t *blist) +{ + pcb_cardinal_t i; + pcb_layer_t *SLayer = &(PCB->Data->Layer[pcb_solder_silk_layer]); + for (i = 0; i < blist->BoxN; i++) { + pcb_line_new(SLayer, blist->Box[i].X1, blist->Box[i].Y1, blist->Box[i].X2, blist->Box[i].Y1, 1, 1, 0); + pcb_line_new(SLayer, blist->Box[i].X1, blist->Box[i].Y2, blist->Box[i].X2, blist->Box[i].Y2, 1, 1, 0); + pcb_line_new(SLayer, blist->Box[i].X1, blist->Box[i].Y1, blist->Box[i].X1, blist->Box[i].Y2, 1, 1, 0); + pcb_line_new(SLayer, blist->Box[i].X2, blist->Box[i].Y1, blist->Box[i].X2, blist->Box[i].Y2, 1, 1, 0); + } +} +#endif + +/* --------------------------------------------------------------------------- + * Helper function to compute "closest neighbor" for a box in a rtree. + * The closest neighbor on a certain side is the closest one in a trapezoid + * emanating from that side. + */ +/*------ r_find_neighbor ------*/ +struct r_neighbor_info { + const pcb_box_t *neighbor; + pcb_box_t trap; + pcb_direction_t search_dir; +}; +#define ROTATEBOX(box) { pcb_coord_t t;\ + t = (box).X1; (box).X1 = - (box).Y1; (box).Y1 = t;\ + t = (box).X2; (box).X2 = - (box).Y2; (box).Y2 = t;\ + t = (box).X1; (box).X1 = (box).X2; (box).X2 = t;\ +} +/* helper methods for __r_find_neighbor */ +static pcb_r_dir_t __r_find_neighbor_reg_in_sea(const pcb_box_t * region, void *cl) +{ + struct r_neighbor_info *ni = (struct r_neighbor_info *) cl; + pcb_box_t query = *region; + PCB_BOX_ROTATE_TO_NORTH(query, ni->search_dir); + /* ______________ __ trap.y1 __ + * \ / |__| query rect. + * \__________/ __ trap.y2 + * | | + * trap.x1 trap.x2 sides at 45-degree angle + */ + if ((query.Y2 > ni->trap.Y1) && (query.Y1 < ni->trap.Y2) && (query.X2 + ni->trap.Y2 > ni->trap.X1 + query.Y1) && (query.X1 + query.Y1 < ni->trap.X2 + ni->trap.Y2)) + return PCB_R_DIR_FOUND_CONTINUE; + return PCB_R_DIR_NOT_FOUND; +} + +static pcb_r_dir_t __r_find_neighbor_rect_in_reg(const pcb_box_t * box, void *cl) +{ + struct r_neighbor_info *ni = (struct r_neighbor_info *) cl; + pcb_box_t query = *box; + int r; + PCB_BOX_ROTATE_TO_NORTH(query, ni->search_dir); + /* ______________ __ trap.y1 __ + * \ / |__| query rect. + * \__________/ __ trap.y2 + * | | + * trap.x1 trap.x2 sides at 45-degree angle + */ + r = (query.Y2 > ni->trap.Y1) && (query.Y1 < ni->trap.Y2) && + (query.X2 + ni->trap.Y2 > ni->trap.X1 + query.Y1) && (query.X1 + query.Y1 < ni->trap.X2 + ni->trap.Y2); + r = r && (query.Y2 <= ni->trap.Y2); + if (r) { + ni->trap.Y1 = query.Y2; + ni->neighbor = box; + } + return r ? PCB_R_DIR_FOUND_CONTINUE : PCB_R_DIR_NOT_FOUND; +} + +/* main r_find_neighbor routine. Returns NULL if no neighbor in the + * requested direction. */ +static const pcb_box_t *r_find_neighbor(pcb_rtree_t * rtree, const pcb_box_t * box, pcb_direction_t search_direction) +{ + struct r_neighbor_info ni; + pcb_box_t bbox; + + ni.neighbor = NULL; + ni.trap = *box; + ni.search_dir = search_direction; + + bbox.X1 = bbox.Y1 = 0; + bbox.X2 = PCB->MaxWidth; + bbox.Y2 = PCB->MaxHeight; + /* rotate so that we can use the 'north' case for everything */ + PCB_BOX_ROTATE_TO_NORTH(bbox, search_direction); + PCB_BOX_ROTATE_TO_NORTH(ni.trap, search_direction); + /* shift Y's such that trap contains full bounds of trapezoid */ + ni.trap.Y2 = ni.trap.Y1; + ni.trap.Y1 = bbox.Y1; + /* do the search! */ + pcb_r_search(rtree, NULL, __r_find_neighbor_reg_in_sea, __r_find_neighbor_rect_in_reg, &ni, NULL); + return ni.neighbor; +} + +static int pstk_ispad(pcb_pstk_t *ps) +{ + pcb_pstk_proto_t *proto = pcb_pstk_get_proto(ps); + return !PCB_PSTK_PROTO_CUTS(proto); +} + +/* --------------------------------------------------------------------------- + * Compute cost function. + * note that area overlap cost is correct for SMD devices: SMD devices on + * opposite sides of the board don't overlap. + * + * Algorithms follow those described in sections 4.1 of + * "Placement and Routing of Electronic Modules" edited by Michael Pecht + * Marcel Dekker, Inc. 1993. ISBN: 0-8247-8916-4 TK7868.P7.P57 1993 + */ +static double ComputeCost(double T0, double T) +{ + double W = 0; /* wire cost */ + double delta1 = 0; /* wire congestion penalty function */ + double delta2 = 0; /* module overlap penalty function */ + double delta3 = 0; /* out of bounds penalty */ + double delta4 = 0; /* alignment bonus */ + double delta5 = 0; /* total area penalty */ + pcb_cardinal_t i; + pcb_coord_t minx, maxx, miny, maxy; + pcb_bool allpads, allsameside; + pcb_cardinal_t thegroup; + pcb_box_list_t bounds = { 0, 0, NULL }; /* save bounding rectangles here */ + pcb_box_list_t solderside = { 0, 0, NULL }; /* solder side component bounds */ + pcb_box_list_t componentside = { 0, 0, NULL }; /* component side bounds */ + + + { + htsp_entry_t *e; + + /* wire length term. approximated by half-perimeter of minimum + * rectangle enclosing the net. Note that we penalize vias in + * all-SMD nets by making the rectangle a cube and weighting + * the "layer height" of the net. */ + + for(e = htsp_first(&PCB->netlist[PCB_NETLIST_EDITED]); e != NULL; e = htsp_next(&PCB->netlist[PCB_NETLIST_EDITED], e)) { + pcb_net_t *net = e->value; + pcb_net_term_t *t; + pcb_any_obj_t *obj; + if (pcb_termlist_length(&net->conns) < 2) + continue; /* no cost to go nowhere */ + + t = pcb_termlist_first(&net->conns); + obj = pcb_term_find_name(PCB, PCB->Data, PCB_LYT_COPPER, t->refdes, t->term, NULL, NULL); + pcb_obj_center(obj, &maxx, &maxy); + minx = maxx; + miny = maxy; + thegroup = obj_layergrp(obj); + allpads = pstk_ispad((pcb_pstk_t *)obj); + allsameside = pcb_true; + + for(t = pcb_termlist_next(t); t != NULL; t = pcb_termlist_next(t)) { + pcb_coord_t X, Y; + obj = pcb_term_find_name(PCB, PCB->Data, PCB_LYT_COPPER, t->refdes, t->term, NULL, NULL); + pcb_obj_center(obj, &X, &Y); + PCB_MAKE_MIN(minx, X); + PCB_MAKE_MAX(maxx, X); + PCB_MAKE_MIN(miny, Y); + PCB_MAKE_MAX(maxy, Y); + if (!pstk_ispad((pcb_pstk_t *)obj)) + allpads = pcb_false; + if (obj_layergrp(obj) != thegroup) + allsameside = pcb_false; + } + /* okay, add half-perimeter to cost! */ + W += PCB_COORD_TO_MIL(maxx - minx) + PCB_COORD_TO_MIL(maxy - miny) + ((allpads && !allsameside) ? CostParameter.via_cost : 0); + } + } + + /* now compute penalty function Wc which is proportional to + * amount of overlap and congestion. */ + /* delta1 is congestion penalty function */ + delta1 = CostParameter.congestion_penalty * sqrt(fabs(pcb_intersect_box_box(&bounds))); +#if 0 + printf("Wire Congestion Area: %f\n", pcb_intersect_box_box(&bounds)); +#endif + /* free bounding rectangles */ + pcb_box_free(&bounds); + /* now collect module areas (bounding rect of pins/pads) */ + /* two lists for solder side / component side. */ + PCB_SUBC_LOOP(PCB->Data); + { + pcb_box_list_t *thisside, *otherside; + pcb_box_t *box, *lastbox = NULL; + pcb_coord_t clearance; + pcb_any_obj_t *o; + pcb_data_it_t it; + int onbtm = 0; + + pcb_subc_get_side(subc, &onbtm); +TODO("subc: this ignores the possibility of other-side pads; need to do this on a per object basis") + if (onbtm) { + thisside = &solderside; + otherside = &componentside; + } + else { + thisside = &componentside; + otherside = &solderside; + } + box = pcb_box_new(thisside); + /* initialize box so that it will take the dimensions of the first pin/pad */ + box->X1 = box->Y1 = PCB_MAX_COORD; + box->X2 = box->Y2 = -PCB_MAX_COORD; + for(o = pcb_data_first(&it, subc->data, PCB_TERM_OBJ_TYPES); o != NULL; o = pcb_data_next(&it)) { + if (o->term == NULL) + continue; /* we are interested in terminals only */ + +TODO("subc: look up clearance") + clearance = 0; + EXPANDRECTXY(box, + o->BoundingBox.X1 - clearance, o->BoundingBox.Y1 - clearance, + o->BoundingBox.X2 + clearance, o->BoundingBox.Y2 + clearance); + + /* add a box for each thru-hole pin to the "opposite side": + * surface mount components can't sit on top of pins */ + if ((!CostParameter.fast) && (o->type == PCB_OBJ_PSTK)) { + pcb_box_t box2; + box2.X1 = o->BoundingBox.X1 - clearance; + box2.Y1 = o->BoundingBox.Y1 - clearance; + box2.X2 = o->BoundingBox.X2 + clearance; + box2.Y2 = o->BoundingBox.Y2 + clearance; + /* speed hack! coalesce with last box if we can */ + if (lastbox != NULL && + ((lastbox->X1 == box2.X1 && + lastbox->X2 == box2.X2 && + MIN(labs(lastbox->Y1 - box2.Y2), labs(box2.Y1 - lastbox->Y2)) < clearance) || + (lastbox->Y1 == box2.Y1 && lastbox->Y2 == box2.Y2 && MIN(labs(lastbox->X1 - box2.X2), labs(box2.X1 - lastbox->X2)) < clearance))) { + EXPANDRECT(lastbox, box); + otherside->BoxN--; + } + else + lastbox = box; + } + } + } + PCB_END_LOOP; + + /* compute intersection area of module areas box list */ + delta2 = sqrt(fabs(pcb_intersect_box_box(&solderside) + pcb_intersect_box_box(&componentside))) * (CostParameter.overlap_penalty_min + (1 - (T / T0)) * CostParameter.overlap_penalty_max); +#if 0 + printf("Module Overlap Area (solder): %f\n", pcb_intersect_box_box(&solderside)); + printf("Module Overlap Area (component): %f\n", pcb_intersect_box_box(&componentside)); +#endif + pcb_box_free(&solderside); + pcb_box_free(&componentside); + /* reward pin/pad x/y alignment */ + /* score higher if pins/pads belong to same *type* of component */ + /* XXX: subkey should be *distance* from thing aligned with, so that + * aligning to something far away isn't profitable */ + { + /* create r tree */ + vtp0_t seboxes, ceboxes; + struct ebox { + pcb_box_t box; +TODO("subc: when elements are removed, turn this into pcb_subc_t * and remove the fields below") + pcb_any_obj_t *comp; + const char *refdes; + int rot90; + pcb_box_t *vbox; + }; + pcb_direction_t dir[4] = { PCB_NORTH, PCB_EAST, PCB_SOUTH, PCB_WEST }; + struct ebox **boxpp, *boxp; + pcb_rtree_t *rt_s, *rt_c; + int factor; + + vtp0_init(&seboxes); + vtp0_init(&ceboxes); + + PCB_SUBC_LOOP(PCB->Data); + { + int onbtm = 0; + double rot = 0; + + pcb_subc_get_side(subc, &onbtm); + boxpp = (struct ebox **) vtp0_alloc_append(onbtm ? &seboxes : &ceboxes, 1); + *boxpp = (struct ebox *) malloc(sizeof(**boxpp)); + if (*boxpp == NULL) { + fprintf(stderr, "malloc() failed in ComputeCost\n"); + exit(1); + } + + pcb_subc_get_rotation(subc, &rot); + (*boxpp)->box = subc->BoundingBox; + (*boxpp)->comp = (pcb_any_obj_t *)subc; + (*boxpp)->refdes = subc->refdes; + (*boxpp)->rot90 = pcb_round(rot / 90.0); + (*boxpp)->vbox = &subc->BoundingBox; + } + PCB_END_LOOP; + + rt_s = pcb_r_create_tree(); + pcb_r_insert_array(rt_s, (const pcb_box_t **) seboxes.array, vtp0_len(&seboxes)); + rt_c = pcb_r_create_tree(); + pcb_r_insert_array(rt_c, (const pcb_box_t **) ceboxes.array, vtp0_len(&ceboxes)); + vtp0_uninit(&seboxes); + vtp0_uninit(&ceboxes); + /* now, for each subcircuit, find its neighbor on all four sides */ + delta4 = 0; + for (i = 0; i < 4; i++) { + PCB_SUBC_LOOP(PCB->Data); + { + int onbtm = 0, rot90; + double rot = 0; + + pcb_subc_get_side(subc, &onbtm); + pcb_subc_get_rotation(subc, &rot); + rot90 = pcb_round(rot / 90.0); + + boxp = (struct ebox *)r_find_neighbor(onbtm ? rt_s : rt_c, &subc->BoundingBox, dir[i]); + /* score bounding box alignments */ + if (!boxp) + continue; + factor = 1; + if (subc->refdes && boxp->refdes && 0 == PCB_NSTRCMP(subc->refdes, boxp->refdes)) { + delta4 += CostParameter.matching_neighbor_bonus; + factor++; + } + if (rot90 == boxp->rot90) + delta4 += factor * CostParameter.oriented_neighbor_bonus; + if (subc->BoundingBox.X1 == boxp->vbox->X1 || + subc->BoundingBox.X1 == boxp->vbox->X2 || + subc->BoundingBox.X2 == boxp->vbox->X1 || + subc->BoundingBox.X2 == boxp->vbox->X2 || + subc->BoundingBox.Y1 == boxp->vbox->Y1 || + subc->BoundingBox.Y1 == boxp->vbox->Y2 || + subc->BoundingBox.Y2 == boxp->vbox->Y1 || + subc->BoundingBox.Y2 == boxp->vbox->Y2) + delta4 += factor * CostParameter.aligned_neighbor_bonus; + } + PCB_END_LOOP; + } + /* free k-d tree memory */ + pcb_r_free_tree_data(rt_s, free); + pcb_r_free_tree_data(rt_c, free); + pcb_r_destroy_tree(&rt_s); + pcb_r_destroy_tree(&rt_c); + } + /* penalize total area used by this layout */ + { + pcb_coord_t minX = PCB_MAX_COORD, minY = PCB_MAX_COORD; + pcb_coord_t maxX = -PCB_MAX_COORD, maxY = -PCB_MAX_COORD; + PCB_SUBC_LOOP(PCB->Data); + { + PCB_MAKE_MIN(minX, subc->BoundingBox.X1); + PCB_MAKE_MIN(minY, subc->BoundingBox.Y1); + PCB_MAKE_MAX(maxX, subc->BoundingBox.X2); + PCB_MAKE_MAX(maxY, subc->BoundingBox.Y2); + } + PCB_END_LOOP; + if (minX < maxX && minY < maxY) + delta5 = CostParameter.overall_area_penalty * sqrt(PCB_COORD_TO_MIL(maxX - minX) * PCB_COORD_TO_MIL(maxY - minY)); + } + if (T == 5) { + T = W + delta1 + delta2 + delta3 - delta4 + delta5; + printf("cost components are %.3f %.3f %.3f %.3f %.3f %.3f\n", + W / T, delta1 / T, delta2 / T, delta3 / T, -delta4 / T, delta5 / T); + } + /* done! */ + return W + (delta1 + delta2 + delta3 - delta4 + delta5); +} + +static pcb_bool is_smd(const pcb_any_obj_t *obj) +{ + return padstacklist_length(&(((pcb_subc_t *)obj)->data->padstack)) != 0; +} + +static pcb_bool on_bottom(const pcb_any_obj_t *obj) +{ + int onbtm = 0; + pcb_subc_get_side((pcb_subc_t *)obj, &onbtm); + return onbtm; +} + +/* --------------------------------------------------------------------------- + * Perturb: + * 1) flip SMD from solder side to component side or vice-versa. + * 2) rotate component 90, 180, or 270 degrees. + * 3) shift component random + or - amount in random direction. + * (magnitude of shift decreases over time) + * -- Only perturb selected subcircuits (need count/list of selected?) -- + */ +PerturbationType createPerturbation(vtp0_t *selected, double T) +{ + PerturbationType pt = { 0 }; + /* pick subcircuit to perturb */ + pt.comp = (pcb_any_obj_t *) selected->array[pcb_rand() % vtp0_len(selected)]; + /* exchange, flip/rotate or shift? */ + switch (pcb_rand() % ((vtp0_len(selected) > 1) ? 3 : 2)) { + case 0: + { /* shift! */ + pcb_coord_t grid; + double scaleX = PCB_CLAMP(sqrt(T), PCB_MIL_TO_COORD(2.5), PCB->MaxWidth / 3); + double scaleY = PCB_CLAMP(sqrt(T), PCB_MIL_TO_COORD(2.5), PCB->MaxHeight / 3); + pt.which = SHIFT; + pt.DX = scaleX * 2 * ((((double) pcb_rand()) / RAND_MAX) - 0.5); + pt.DY = scaleY * 2 * ((((double) pcb_rand()) / RAND_MAX) - 0.5); + /* snap to grid. different grids for "high" and "low" T */ + grid = (T > PCB_MIL_TO_COORD(10)) ? CostParameter.large_grid_size : CostParameter.small_grid_size; + /* (round away from zero) */ + pt.DX = ((pt.DX / grid) + SGN(pt.DX)) * grid; + pt.DY = ((pt.DY / grid) + SGN(pt.DY)) * grid; + /* limit DX/DY so we don't fall off board */ + { + pcb_subc_t *s = (pcb_subc_t *)pt.comp; + pt.DX = MAX(pt.DX, -s->BoundingBox.X1); + pt.DX = MIN(pt.DX, PCB->MaxWidth - s->BoundingBox.X2); + pt.DY = MAX(pt.DY, -s->BoundingBox.Y1); + pt.DY = MIN(pt.DY, PCB->MaxHeight - s->BoundingBox.Y2); + } + /* all done but the movin' */ + break; + } + case 1: + { /* flip/rotate! */ + /* only flip if it's an SMD component */ + pcb_bool isSMD = is_smd(pt.comp); + + pt.which = ROTATE; + pt.rotate = isSMD ? (pcb_rand() & 3) : (1 + (pcb_rand() % 3)); + /* 0 - flip; 1-3, rotate. */ + break; + } + case 2: + { /* exchange! */ + pt.which = EXCHANGE; + pt.other = (pcb_any_obj_t *)selected->array[pcb_rand() % (vtp0_len(selected) - 1)]; + if (pt.other == pt.comp) + pt.other = (pcb_any_obj_t *)selected->array[vtp0_len(selected) - 1]; + /* don't allow exchanging a solderside-side SMD component + * with a non-SMD component. */ + if ((!is_smd(pt.comp) && on_bottom(pt.other)) || + (!is_smd(pt.other) && on_bottom(pt.comp))) + return createPerturbation(selected, T); + break; + } + default: + assert(0); + } + return pt; +} + +void doPerturb(vtp0_t *selected, PerturbationType *pt, pcb_bool undo) +{ + pcb_box_t *bb; + pcb_coord_t bbcx, bbcy; + pcb_subc_t *subc = (pcb_subc_t *)pt->comp; + /* compute center of element bounding box */ + + bb = &subc->BoundingBox; + bbcx = (bb->X1 + bb->X2) / 2; + bbcy = (bb->Y1 + bb->Y2) / 2; + /* do exchange, shift or flip/rotate */ + switch (pt->which) { + case SHIFT: + { + pcb_coord_t DX = pt->DX, DY = pt->DY; + if (undo) { + DX = -DX; + DY = -DY; + } + pcb_subc_move(subc, DX, DY, 1); + return; + } + case ROTATE: + { + unsigned b = pt->rotate; + if (undo) + b = (4 - b) & 3; + /* 0 - flip; 1-3, rotate. */ + if (b) { + pcb_subc_rotate90(subc, bbcx, bbcy, b); + } + else { + pcb_cardinal_t n; + pcb_coord_t y = bb->Y1; + pcb_subc_change_side(subc, (bb->Y1+bb->Y2)/2); + /* mirroring moves the subc. move it back. */ + pcb_subc_move(subc, 0, y - subc->BoundingBox.Y1, 1); + for(n = 0; n < vtp0_len(selected); n++) + if (selected->array[n] == pt->comp) + selected->array[n] = subc; + pt->comp = (pcb_any_obj_t *)subc; + } + return; + } + case EXCHANGE: + { + /* first exchange positions */ + pcb_coord_t x1 = bb->X1; + pcb_coord_t y1 = bb->Y1; + pcb_coord_t x2 = pt->other->BoundingBox.X1; + pcb_coord_t y2 = pt->other->BoundingBox.Y1; + + pcb_subc_move(subc, x2 - x1, y2 - y1, 1); + pcb_subc_move((pcb_subc_t *)pt->other, x1 - x2, y1 - y2, 1); + + /* then flip both subcircuits if they are on opposite sides */ + if (on_bottom(pt->comp) != on_bottom(pt->other)) { + PerturbationType mypt; + mypt.comp = pt->comp; + mypt.which = ROTATE; + mypt.rotate = 0; /* flip */ + doPerturb(selected, &mypt, undo); + pt->comp = mypt.comp; + mypt.comp = pt->other; + doPerturb(selected, &mypt, undo); + pt->other = mypt.comp; + } + /* done */ + return; + } + default: + assert(0); + } +} + +/* --------------------------------------------------------------------------- + * Auto-place selected components. + */ +pcb_bool AutoPlaceSelected(void) +{ + vtp0_t Selected; + PerturbationType pt; + double C00, C0, T0; + pcb_bool changed = pcb_false; + + vtp0_init(&Selected); + + Selected = collectSelectedSubcircuits(); + if (vtp0_len(&Selected) == 0) { + pcb_message(PCB_MSG_ERROR, "No subcircuits selected to autoplace.\n"); + goto done; + } + + /* simulated annealing */ + { /* compute T0 by doing a random series of moves. */ + const int TRIALS = 10; + const double Tx = PCB_MIL_TO_COORD(300), P = 0.95; + double Cs = 0.0; + int i; + C00 = C0 = ComputeCost(Tx, Tx); + for (i = 0; i < TRIALS; i++) { + pt = createPerturbation(&Selected, PCB_INCH_TO_COORD(1)); + doPerturb(&Selected, &pt, pcb_false); + Cs += fabs(ComputeCost(Tx, Tx) - C0); + doPerturb(&Selected, &pt, pcb_true); + } + T0 = -(Cs / TRIALS) / log(P); + printf("Initial T: %f\n", T0); + } + /* now anneal in earnest */ + { + double T = T0; + long steps = 0; + int good_moves = 0, moves = 0; + const int good_move_cutoff = CostParameter.m * vtp0_len(&Selected); + const int move_cutoff = 2 * good_move_cutoff; + printf("Starting cost is %.0f\n", ComputeCost(T0, 5)); + C0 = ComputeCost(T0, T); + while (1) { + double Cprime; + pt = createPerturbation(&Selected, T); + doPerturb(&Selected, &pt, pcb_false); + Cprime = ComputeCost(T0, T); + if (Cprime < C0) { /* good move! */ + C0 = Cprime; + good_moves++; + steps++; + } + else if ((pcb_rand() / (double) RAND_MAX) < exp(MIN(MAX(-20, (C0 - Cprime) / T), 20))) { + /* not good but keep it anyway */ + C0 = Cprime; + steps++; + } + else + doPerturb(&Selected, &pt, pcb_true); /* undo last change */ + moves++; + /* are we at the end of a stage? */ + if (good_moves >= good_move_cutoff || moves >= move_cutoff) { + printf("END OF STAGE: COST %.0f\t" "GOOD_MOVES %d\tMOVES %d\t" "T: %.1f\n", C0, good_moves, moves, T); + pcb_draw(); + if (pcb_hid_progress(C00-T, C00, "Optimizing the placement...")) + break; + /* is this the end? */ + if (T < 5 || good_moves < moves / CostParameter.good_ratio) + break; + /* nope, adjust T and continue */ + moves = good_moves = 0; + T *= CostParameter.gamma; + /* cost is T dependent, so recompute */ + C0 = ComputeCost(T0, T); + } + } + changed = (steps > 0); + } +done: + pcb_hid_progress(0, 0, NULL); + if (changed) { + pcb_rats_destroy(pcb_false); + pcb_net_add_all_rats(PCB, PCB_RATACC_PRECISE); + pcb_redraw(); + } + vtp0_uninit(&Selected); + return changed; +} Index: tags/2.1.2/src_plugins/autoplace/autoplace.h =================================================================== --- tags/2.1.2/src_plugins/autoplace/autoplace.h (nonexistent) +++ tags/2.1.2/src_plugins/autoplace/autoplace.h (revision 24813) @@ -0,0 +1,45 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * Copyright (C) 1998,1999,2000,2001 harry eaton + * + * this file, autoplace.h, was written and is + * Copyright (c) 2001 C. Scott Ananian. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + * + * Old contact info: + * harry eaton, 6697 Buttonhole Ct, Columbia, MD 21044 USA + * haceaton@aplcomm.jhuapl.edu + * + */ + +#ifndef PCB_AUTOPLACE_H +#define PCB_AUTOPLACE_H + +#include "global_typedefs.h" + +pcb_bool AutoPlaceSelected(void); + +#endif Index: tags/2.1.2/src_plugins/autoplace/autoplace.pup =================================================================== --- tags/2.1.2/src_plugins/autoplace/autoplace.pup (nonexistent) +++ tags/2.1.2/src_plugins/autoplace/autoplace.pup (revision 24813) @@ -0,0 +1,7 @@ +$class feature +$short auto place components +$long Automatically place subcircuits. +$package auto +$state works +default buildin +autoload 1 Index: tags/2.1.2/src_plugins/autoroute/Makefile =================================================================== --- tags/2.1.2/src_plugins/autoroute/Makefile (nonexistent) +++ tags/2.1.2/src_plugins/autoroute/Makefile (revision 24813) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_autoroute + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/2.1.2/src_plugins/autoroute/Plug.tmpasm =================================================================== --- tags/2.1.2/src_plugins/autoroute/Plug.tmpasm (nonexistent) +++ tags/2.1.2/src_plugins/autoroute/Plug.tmpasm (revision 24813) @@ -0,0 +1,8 @@ +put /local/pcb/mod {autoroute} +put /local/pcb/mod/OBJS [@ $(PLUGDIR)/autoroute/autoroute.o $(PLUGDIR)/autoroute/mtspace.o $(PLUGDIR)/autoroute/action.o $(PLUGDIR)/autoroute/vector.o @] + +switch /local/pcb/autoroute/controls + case {buildin} include /local/pcb/tmpasm/buildin; end; + case {plugin} include /local/pcb/tmpasm/plugin; end; + case {disable} include /local/pcb/tmpasm/disable; end; +end Index: tags/2.1.2/src_plugins/autoroute/action.c =================================================================== --- tags/2.1.2/src_plugins/autoroute/action.c (nonexistent) +++ tags/2.1.2/src_plugins/autoroute/action.c (revision 24813) @@ -0,0 +1,92 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * Copyright (C) 1997, 1998, 1999, 2000, 2001 Harry Eaton + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + * + * Old contact info: + * Harry Eaton, 6697 Buttonhole Ct, Columbia, MD 21044, USA + * haceaton@aplcomm.jhuapl.edu + * + */ + +#include "config.h" +#include "autoroute.h" +#include "plugins.h" +#include "actions.h" +#include "event.h" +#include "funchash_core.h" + +static const char pcb_acts_AutoRoute[] = "AutoRoute(AllRats|SelectedRats)"; +static const char pcb_acth_AutoRoute[] = "Auto-route some or all rat lines."; +/* DOC: autoroute.html */ +static fgw_error_t pcb_act_AutoRoute(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + int op; + + PCB_ACT_CONVARG(1, FGW_KEYWORD, AutoRoute, op = fgw_keyword(&argv[1])); + + pcb_event(PCB_EVENT_BUSY, NULL); + switch(op) { + case F_AllRats: + case F_All: + if (AutoRoute(pcb_false)) + pcb_board_set_changed_flag(pcb_true); + break; + case F_SelectedRats: + case F_Selected: + if (AutoRoute(pcb_true)) + pcb_board_set_changed_flag(pcb_true); + break; + default: + PCB_ACT_FAIL(AutoRoute); + return 1; + } + PCB_ACT_IRES(0); + return 0; +} + +static const char *autoroute_cookie = "autoroute plugin"; + +pcb_action_t autoroute_action_list[] = { + {"AutoRoute", pcb_act_AutoRoute, pcb_acth_AutoRoute, pcb_acts_AutoRoute}, +}; + +PCB_REGISTER_ACTIONS(autoroute_action_list, autoroute_cookie) + +int pplg_check_ver_autoroute(int ver_needed) { return 0; } + +void pplg_uninit_autoroute(void) +{ + pcb_remove_actions_by_cookie(autoroute_cookie); +} + +#include "dolists.h" +int pplg_init_autoroute(void) +{ + PCB_API_CHK_VER; + PCB_REGISTER_ACTIONS(autoroute_action_list, autoroute_cookie) + return 0; +} Index: tags/2.1.2/src_plugins/autoroute/autoroute.c =================================================================== --- tags/2.1.2/src_plugins/autoroute/autoroute.c (nonexistent) +++ tags/2.1.2/src_plugins/autoroute/autoroute.c (revision 24813) @@ -0,0 +1,4783 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * Copyright (C) 1998,1999,2000,2001 harry eaton + * + * this file, autoroute.c, was written and is + * Copyright (c) 2001 C. Scott Ananian + * Copyright (c) 2006 harry eaton + * Copyright (c) 2009 harry eaton + * + * Updated for pcb-rnd for subcircuits, padstacks and netlist + * Copyright (c) 2018,2019 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + * + * Old contact info: + * harry eaton, 6697 Buttonhole Ct, Columbia, MD 21044 USA + * haceaton@aplcomm.jhuapl.edu + * + */ + +/* + *------------------------------------------------------------------- + * This file implements a rectangle-expansion router, based on + * "A Method for Gridless Routing of Printed Circuit Boards" by + * A. C. Finch, K. J. Mackenzie, G. J. Balsdon, and G. Symonds in the + * 1985 Proceedings of the 22nd ACM/IEEE Design Automation Conference. + * This reference is available from the ACM Digital Library at + * http://www.acm.org/dl for those with institutional or personal + * access to it. It's also available from your local engineering + * library. + * + * The code is much closer to what is described in the paper now, + * in that expansion areas can grow from corners and in all directions + * at once. Previously, these were emulated with discrete boxes moving + * in the cardinal directions. With the new method, there are fewer but + * larger expansion boxes that one might do a better job of routing in. + *-------------------------------------------------------------------- + */ +#define NET_HEAP 1 +#include "config.h" +#include "conf_core.h" + +#include +#include + +#include "data.h" +#include "macro.h" +#include "autoroute.h" +#include "box.h" +#include "draw.h" +#include "error.h" +#include "find.h" +#include "heap.h" +#include "rtree.h" +#include "netlist2.h" +#include "mtspace.h" +#include "polygon.h" +#include "remove.h" +#include "obj_pinvia_therm.h" +#include "undo.h" +#include "vector.h" +#include "pcb-printf.h" +#include "layer.h" +#include +#include "layer.h" + +#include "obj_line_draw.h" +#include "obj_pstk_draw.h" +#include "obj_pstk_inlines.h" + +TODO("padstack: when style contains proto, remove this") +#include "src_plugins/lib_compat_help/pstk_compat.h" + +#define autoroute_therm_style 4 + +/* #defines to enable some debugging output */ +/* +#define ROUTE_VERBOSE +*/ + +/* +#define ROUTE_DEBUG +//#define DEBUG_SHOW_ROUTE_BOXES +#define DEBUG_SHOW_EXPANSION_BOXES +//#define DEBUG_SHOW_EDGES +//#define DEBUG_SHOW_VIA_BOXES +#define DEBUG_SHOW_TARGETS +#define DEBUG_SHOW_SOURCES +//#define DEBUG_SHOW_ZIGZAG +*/ + +static pcb_direction_t directionIncrement(pcb_direction_t dir) +{ + switch (dir) { + case PCB_NORTH: + dir = PCB_EAST; + break; + case PCB_EAST: + dir = PCB_SOUTH; + break; + case PCB_SOUTH: + dir = PCB_WEST; + break; + case PCB_WEST: + dir = PCB_NE; + break; + case PCB_NE: + dir = PCB_SE; + break; + case PCB_SE: + dir = PCB_SW; + break; + case PCB_SW: + dir = PCB_NW; + break; + case PCB_NW: + dir = PCB_ANY_DIR; + break; + case PCB_ANY_DIR: + dir = PCB_NORTH; + break; + } + return dir; +} + +#ifdef ROUTE_DEBUG +pcb_hid_t *ddraw = NULL; +static pcb_hid_gc_t ar_gc = 0; +#endif + +#define EXPENSIVE 3e28 +/* round up "half" thicknesses */ +#define HALF_THICK(x) (((x)+1)/2) +/* a styles maximum bloat is its clearance plus the larger of its via radius + * or line half-thickness. */ +#define BLOAT(style)\ + ((style)->Clearance + HALF_THICK((style)->Thick)) +/* conflict penalty is less for traces laid down during previous pass than + * it is for traces already laid down in this pass. */ +#define CONFLICT_LEVEL(rb)\ + (((rb)->flags.is_odd==AutoRouteParameters.is_odd) ?\ + HI_CONFLICT : LO_CONFLICT ) +#define CONFLICT_PENALTY(rb)\ + ((CONFLICT_LEVEL(rb)==HI_CONFLICT ? \ + AutoRouteParameters.ConflictPenalty : \ + CONFLICT_LEVEL(rb)==LO_CONFLICT ? \ + AutoRouteParameters.LastConflictPenalty : 1) * (rb)->pass) + +#define _NORTH 1 +#define _EAST 2 +#define _SOUTH 4 +#define _WEST 8 + +#define LIST_LOOP(init, which, x) do {\ + routebox_t *__next_one__ = (init);\ + x = NULL;\ + if (!__next_one__)\ + assert(__next_one__);\ + else\ + while (!x || __next_one__ != (init)) {\ + x = __next_one__;\ + /* save next one first in case the command modifies or frees it */\ + __next_one__ = x->which.next +#define FOREACH_SUBNET(net, p) do {\ + routebox_t *_pp_;\ + /* fail-fast: check subnet_processed flags */\ + LIST_LOOP(net, same_net, p); \ + assert(!p->flags.subnet_processed);\ + PCB_END_LOOP;\ + /* iterate through *distinct* subnets */\ + LIST_LOOP(net, same_net, p); \ + if (!p->flags.subnet_processed) {\ + LIST_LOOP(p, same_subnet, _pp_);\ + _pp_->flags.subnet_processed=1;\ + PCB_END_LOOP +#define END_FOREACH(net, p) \ + }; \ + PCB_END_LOOP;\ + /* reset subnet_processed flags */\ + LIST_LOOP(net, same_net, p); \ + p->flags.subnet_processed=0;\ + PCB_END_LOOP;\ +} while (0) +#define SWAP(t, f, s) do { t a=s; s=f; f=a; } while (0) +/* notes: + * all rectangles are assumed to be closed on the top and left and + * open on the bottom and right. That is, they include their top-left + * corner but don't include their bottom and right edges. + * + * expansion regions are always half-closed. This means that when + * tracing paths, you must steer clear of the bottom and right edges., + * because these are not actually in the allowed box. + * + * All routeboxes *except* EXPANSION_AREAS now have their "box" bloated by + * their particular required clearance. This simplifies the tree searching. + * the "sbox" contains the unbloated box. + */ + +/* enumerated type for conflict levels */ +typedef enum { NO_CONFLICT = 0, LO_CONFLICT = 1, HI_CONFLICT = 2 } conflict_t; + +typedef struct routebox_s routebox_t; + +typedef struct routebox_list_s { + routebox_t *next, *prev; +} routebox_list_t; + +typedef enum etype { TERM, VIA, VIA_SHADOW, LINE, OTHER, EXPANSION_AREA, PLANE, THERMAL } etype; + +struct routebox_s { + pcb_box_t box, sbox; + struct { + pcb_coord_t x1, y1, x2, y2; + } line; /* exact coords of the line we are going to draw if type is line; reverse engineering these from the bounding box using halfthick and other hacks lead to rounding errors, a few LSB flicker in coords, e.g. breaking rubber band */ + union { + pcb_pstk_t *via; + pcb_any_obj_t *term; + routebox_t *via_shadow; /* points to the via in r-tree which + * points to the pcb_pstk_t in the PCB. */ + pcb_line_t *line; + void *generic; /* 'other' is polygon, arc, text */ + routebox_t *expansion_area; /* previous expansion area in search */ + } parent; + unsigned short group; + unsigned short layer; + etype type; + struct { + unsigned nonstraight:1; + unsigned fixed:1; + /* for searches */ + unsigned source:1; + unsigned target:1; + /* rects on same net as source and target don't need clearance areas */ + unsigned nobloat:1; + /* mark circular pins, so that we be sure to connect them up properly */ + unsigned circular:1; + /* we sometimes create routeboxen that don't actually belong to a + * r-tree yet -- make sure refcount of homelesss is set properly */ + unsigned homeless:1; + /* was this nonfixed obstacle generated on an odd or even pass? */ + unsigned is_odd:1; + /* fixed route boxes that have already been "routed through" in this + * search have their "touched" flag set. */ + unsigned touched:1; + /* this is a status bit for iterating through *different* subnets */ + unsigned subnet_processed:1; + /* some expansion_areas represent via candidates */ + unsigned is_via:1; + /* mark non-straight lines which go from bottom-left to upper-right, + * instead of from upper-left to bottom-right. */ + unsigned bl_to_ur:1; + /* mark polygons which are "transparent" for via-placement; that is, + * vias through the polygon will automatically be given a clearance + * and will not electrically connect to the polygon. */ + unsigned clear_poly:1; + /* this marks "conflicting" routes that must be torn up to obtain + * a correct routing. This flag allows us to return a correct routing + * even if the user cancels auto-route after a non-final pass. */ + unsigned is_bad:1; + /* for assertion that 'box' is never changed after creation */ + unsigned inited:1; + /* indicate this expansion ares is a thermal between the pin and plane */ + unsigned is_thermal; + } flags; + /* indicate the direction an expansion box came from */ + pcb_cost_t cost; + pcb_cheap_point_t cost_point; + /* reference count for homeless routeboxes; free when refcount==0 */ + int refcount; + /* when routing with conflicts, we keep a record of what we're + * conflicting with. + */ + vector_t *conflicts_with; + /* route style of the net associated with this routebox */ + pcb_route_style_t *style; + /* congestion values for the edges of an expansion box */ + unsigned char n, e, s, w; + /* what pass this this track was laid down on */ + unsigned char pass; + /* the direction this came from, if any */ + pcb_direction_t came_from; + /* circular lists with connectivity information. */ + routebox_list_t same_net, same_subnet, original_subnet, different_net; + union { + pcb_pstk_t *via; + pcb_line_t *line; + } livedraw_obj; +}; + +typedef struct routedata_s { + int max_styles; + /* one rtree per layer *group */ + pcb_rtree_t *layergrouptree[PCB_MAX_LAYERGRP]; /* no silkscreen layers here =) */ + /* root pointer into connectivity information */ + routebox_t *first_net; + /* default routing style */ + pcb_route_style_t defaultstyle; + /* style structures */ + pcb_route_style_t **styles; /* [max_styles+1] */ + /* what is the maximum bloat (clearance+line half-width or + * clearance+via_radius) for any style we've seen? */ + pcb_coord_t max_bloat; + pcb_coord_t max_keep; + mtspace_t *mtspace; +} routedata_t; + +typedef struct edge_struct_s { + routebox_t *rb; /* path expansion edges are real routeboxen. */ + pcb_cheap_point_t cost_point; + pcb_cost_t pcb_cost_to_point; /* from source */ + pcb_cost_t cost; /* cached edge cost */ + routebox_t *minpcb_cost_target; /* minimum cost from cost_point to any target */ + vetting_t *work; /* for via search edges */ + pcb_direction_t expand_dir; + struct { + /* this indicates that this 'edge' is a via candidate. */ + unsigned is_via:1; + /* record "conflict level" of via candidates, in case we need to split + * them later. */ + unsigned via_conflict_level:2; /* conflict_t */ + /* when "routing with conflicts", sometimes edge is interior. */ + unsigned is_interior:1; + /* this is a fake edge used to defer searching for via spaces */ + unsigned via_search:1; + /* this is a via edge in a plane where the cost point moves for free */ + unsigned in_plane:1; + } flags; +} edge_t; + +static struct AutoRouteParameters_s { + /* net style parameters */ + pcb_route_style_t *style; + /* the present bloat */ + pcb_coord_t bloat; + /* cost parameters */ + pcb_cost_t ViaCost, /* additional "length" cost for using a via */ + LastConflictPenalty, /* length mult. for routing over last pass' trace */ + ConflictPenalty, /* length multiplier for routing over another trace */ + JogPenalty, /* additional "length" cost for changing direction */ + CongestionPenalty, /* (rational) length multiplier for routing in */ + NewLayerPenalty, /* penalty for routing on a previously unused layer */ + MinPenalty; /* smallest Direction Penalty */ + /* maximum conflict incidence before calling it "no path found" */ + int hi_conflict; + /* are vias allowed? */ + pcb_bool use_vias; + /* is this an odd or even pass? */ + pcb_bool is_odd; + /* permit conflicts? */ + pcb_bool with_conflicts; + /* is this a final "smoothing" pass? */ + pcb_bool is_smoothing; + /* rip up nets regardless of conflicts? */ + pcb_bool rip_always; + pcb_bool last_smooth; + unsigned char pass; +} AutoRouteParameters; + +typedef struct routeone_state_s { + /* heap of all candidate expansion edges */ + pcb_heap_t *workheap; + /* information about the best path found so far. */ + routebox_t *best_path, *best_target; + pcb_cost_t best_cost; +} routeone_state_t; + + +static routebox_t *CreateExpansionArea(const pcb_box_t * area, pcb_cardinal_t group, + routebox_t * parent, pcb_bool relax_edge_requirements, edge_t * edge); + +static pcb_cost_t edge_cost(const edge_t * e, const pcb_cost_t too_big); +static void best_path_candidate(routeone_state_t *s, edge_t * e, routebox_t * best_target); + +static pcb_box_t edge_to_box(const routebox_t * rb, pcb_direction_t expand_dir); + +static void add_or_destroy_edge(routeone_state_t *s, edge_t * e); + +static void +RD_DrawThermal(routedata_t * rd, pcb_coord_t X, pcb_coord_t Y, pcb_cardinal_t group, pcb_cardinal_t layer, routebox_t * subnet, pcb_bool is_bad); +static void ResetSubnet(routebox_t * net); +#ifdef ROUTE_DEBUG +static int showboxen = -2; +static int aabort = 0; +static void showroutebox(routebox_t * rb); +#endif + +/* group number of groups that hold surface mount pads */ +static pcb_layergrp_id_t front, back; +static pcb_bool usedGroup[PCB_MAX_LAYERGRP]; +static int x_cost[PCB_MAX_LAYERGRP], y_cost[PCB_MAX_LAYERGRP]; +static pcb_bool is_layer_group_active[PCB_MAX_LAYERGRP]; +static int ro = 0; +static int smoothes = 1; +static int passes = 12; +static int routing_layers = 0; +static float total_wire_length = 0; +static int total_via_count = 0; + +/* assertion helper for routeboxen */ +#ifndef NDEBUG +static int __routepcb_box_is_good(routebox_t * rb) +{ + assert(rb && (rb->group < pcb_max_group(PCB)) && + (rb->box.X1 <= rb->box.X2) && (rb->box.Y1 <= rb->box.Y2) && + (rb->flags.homeless ? + (rb->box.X1 != rb->box.X2) || (rb->box.Y1 != rb->box.Y2) : (rb->box.X1 != rb->box.X2) && (rb->box.Y1 != rb->box.Y2))); + assert((rb->flags.source ? rb->flags.nobloat : 1) && + (rb->flags.target ? rb->flags.nobloat : 1) && + (rb->flags.homeless ? !rb->flags.touched : rb->refcount == 0) && (rb->flags.touched ? rb->type != EXPANSION_AREA : 1)); + assert((rb->flags.is_odd ? (!rb->flags.fixed) && + (rb->type == VIA || rb->type == VIA_SHADOW || rb->type == LINE || rb->type == PLANE) : 1)); + assert(rb->flags.clear_poly ? ((rb->type == OTHER || rb->type == PLANE) && rb->flags.fixed && !rb->flags.homeless) : 1); + assert(rb->flags.inited); +/* run through conflict list showing none are homeless, targets or sources */ + if (rb->conflicts_with) { + int i; + for (i = 0; i < vector_size(rb->conflicts_with); i++) { + routebox_t *c = vector_element(rb->conflicts_with, i); + assert(!c->flags.homeless && !c->flags.source && !c->flags.target && !c->flags.fixed); + } + } + assert(rb->style != NULL && rb->style != NULL); + assert(rb->type == EXPANSION_AREA + || (rb->same_net.next && rb->same_net.prev && rb->same_subnet.next + && rb->same_subnet.prev && rb->original_subnet.next + && rb->original_subnet.prev && rb->different_net.next && rb->different_net.prev)); + return 1; +} + +static int __edge_is_good(edge_t * e) +{ + assert(e && e->rb && __routepcb_box_is_good(e->rb)); + assert((e->rb->flags.homeless ? e->rb->refcount > 0 : 1)); + assert((0 <= e->expand_dir) && (e->expand_dir < 9) + && (e->flags.is_interior ? (e->expand_dir == PCB_ANY_DIR && e->rb->conflicts_with) : 1)); + assert((e->flags.is_via ? e->rb->flags.is_via : 1) + && (e->flags.via_conflict_level >= 0 && e->flags.via_conflict_level <= 2) + && (e->flags.via_conflict_level != 0 ? e->flags.is_via : 1)); + assert((e->pcb_cost_to_point >= 0) && e->cost >= 0); + return 1; +} + +int no_planes(const pcb_box_t * b, void *cl) +{ + routebox_t *rb = (routebox_t *) b; + if (rb->type == PLANE) + return 0; + return 1; +} +#endif /* !NDEBUG */ + +/*--------------------------------------------------------------------- + * route utility functions. + */ + +enum boxlist { NET, SUBNET, ORIGINAL, DIFFERENT_NET }; +static routebox_list_t *__select_list(routebox_t * r, enum boxlist which) +{ + assert(r); + switch (which) { + default: + assert(0); + case NET: + return &(r->same_net); + case SUBNET: + return &(r->same_subnet); + case ORIGINAL: + return &(r->original_subnet); + case DIFFERENT_NET: + return &(r->different_net); + } +} + +static void InitLists(routebox_t * r) +{ + static enum boxlist all[] = { NET, SUBNET, ORIGINAL, DIFFERENT_NET } + , *p; + for (p = all; p < all + (sizeof(all) / sizeof(*p)); p++) { + routebox_list_t *rl = __select_list(r, *p); + rl->prev = rl->next = r; + } +} + +static void MergeNets(routebox_t * a, routebox_t * b, enum boxlist which) +{ + routebox_list_t *al, *bl, *anl, *bnl; + routebox_t *an, *bn; + assert(a && b); + assert(a != b); + assert(a->type != EXPANSION_AREA); + assert(b->type != EXPANSION_AREA); + al = __select_list(a, which); + bl = __select_list(b, which); + assert(al && bl); + an = al->next; + bn = bl->next; + assert(an && bn); + anl = __select_list(an, which); + bnl = __select_list(bn, which); + assert(anl && bnl); + bl->next = an; + anl->prev = b; + al->next = bn; + bnl->prev = a; +} + +static void RemoveFromNet(routebox_t * a, enum boxlist which) +{ + routebox_list_t *al, *anl, *apl; + routebox_t *an, *ap; + assert(a); + al = __select_list(a, which); + assert(al); + an = al->next; + ap = al->prev; + if (an == a || ap == a) + return; /* not on any list */ + assert(an && ap); + anl = __select_list(an, which); + apl = __select_list(ap, which); + assert(anl && apl); + anl->prev = ap; + apl->next = an; + al->next = al->prev = a; + return; +} + +static void init_const_box(routebox_t * rb, pcb_coord_t X1, pcb_coord_t Y1, pcb_coord_t X2, pcb_coord_t Y2, pcb_coord_t clearance) +{ + pcb_box_t *bp = (pcb_box_t *) & rb->box; /* note discarding const! */ + assert(!rb->flags.inited); + assert(X1 <= X2 && Y1 <= Y2); + bp->X1 = X1 - clearance; + bp->Y1 = Y1 - clearance; + bp->X2 = X2 + clearance; + bp->Y2 = Y2 + clearance; + bp = (pcb_box_t *) & rb->sbox; + bp->X1 = X1; + bp->Y1 = Y1; + bp->X2 = X2; + bp->Y2 = Y2; + rb->flags.inited = 1; +} + +static inline pcb_box_t shrink_routebox(const routebox_t * rb) +{ + return rb->sbox; +} + +static inline pcb_cost_t box_area(const pcb_box_t b) +{ + pcb_cost_t ans = b.X2 - b.X1; + return ans * (b.Y2 - b.Y1); +} + +static inline pcb_cheap_point_t closest_point_in_routebox(const pcb_cheap_point_t * from, const routebox_t * rb) +{ + return pcb_closest_pcb_point_in_box(from, &rb->sbox); +} + +static inline pcb_bool point_in_shrunk_box(const routebox_t * box, pcb_coord_t X, pcb_coord_t Y) +{ + pcb_box_t b = shrink_routebox(box); + return pcb_point_in_box(&b, X, Y); +} + +/*--------------------------------------------------------------------- + * routedata initialization functions. + */ +static routebox_t *AddTerm_(vtp0_t layergroupboxes[], pcb_any_obj_t *term, pcb_route_style_t *style, pcb_layer_t *layer) +{ + routebox_t **rbpp; + pcb_layer_type_t lyt; + int layergroup = -1; + pcb_coord_t clr; + + lyt = pcb_layer_flags_(layer); + if (!(lyt & PCB_LYT_COPPER)) + return NULL; + if (lyt & PCB_LYT_TOP) + layergroup = front; + else if (lyt & PCB_LYT_BOTTOM) + layergroup = back; + else { + if (term->type != PCB_OBJ_PSTK) + assert(!"won't route to pad on internal layer"); + layergroup = pcb_layer_get_group_(layer); + } + assert(0 <= layergroup && layergroup < pcb_max_group(PCB)); + + assert(PCB->LayerGroups.grp[layergroup].len > 0); + rbpp = (routebox_t **)vtp0_alloc_append(&layergroupboxes[layergroup], 1); + assert(rbpp); + *rbpp = (routebox_t *)calloc(sizeof(**rbpp), 1); + assert(*rbpp); + (*rbpp)->group = layergroup; + clr = pcb_obj_clearance_at(PCB, term, layer); +pcb_printf("***** CLR=%mm\n", clr); + init_const_box(*rbpp, + /*X1 */ term->BoundingBox.X1 + clr, + /*Y1 */ term->BoundingBox.Y1 + clr, + /*X2 */ term->BoundingBox.X2 - clr, + /*Y2 */ term->BoundingBox.Y2 - clr, + style->Clearance); + /* kludge for non-manhattan pads (which are not allowed at present) */ +TODO("term:") +/* + if (pad->Point1.X != pad->Point2.X && pad->Point1.Y != pad->Point2.Y) + (*rbpp)->flags.nonstraight = 1; +*/ + (*rbpp)->flags.nonstraight = 0; /* otherwise the autorouter just ignores it */ + /* set aux. properties */ + (*rbpp)->type = TERM; + (*rbpp)->parent.term = term; + (*rbpp)->flags.fixed = 1; + (*rbpp)->came_from = PCB_ANY_DIR; + (*rbpp)->style = style; + /* circular lists */ + InitLists(*rbpp); + return *rbpp; +} + +static routebox_t *AddTerm(vtp0_t layergroupboxes[], pcb_any_obj_t *term, pcb_route_style_t *style) +{ + assert(term->parent_type == PCB_PARENT_LAYER); + return AddTerm_(layergroupboxes, term, style, term->parent.layer); +} + +static routebox_t *AddPstk(vtp0_t layergroupboxes[], pcb_pstk_t *ps, pcb_route_style_t *style) +{ + int i; + routebox_t *r, *last = NULL; + + for (i = 0; i < pcb_max_group(PCB); i++) { + if (pcb_pstk_shape_at(PCB, ps, &PCB->Data->Layer[i]) != NULL) { + r = AddTerm_(layergroupboxes, (pcb_any_obj_t *)ps, style, &PCB->Data->Layer[i]); + if (r != NULL) { + if (last != NULL) { + MergeNets(r, last, NET); + MergeNets(r, last, SUBNET); + MergeNets(r, last, ORIGINAL); + } + last = r; + } + } + } + + return last; +} + + +static routebox_t *AddLine(vtp0_t layergroupboxes[], int layergroup, pcb_line_t *line, + pcb_line_t *ptr, pcb_route_style_t * style) +{ + routebox_t **rbpp; + assert(layergroupboxes && line); + assert(0 <= layergroup && layergroup < pcb_max_group(PCB)); + assert(PCB->LayerGroups.grp[layergroup].len > 0); + + rbpp = (routebox_t **) vtp0_alloc_append(&layergroupboxes[layergroup], 1); + *rbpp = (routebox_t *) malloc(sizeof(**rbpp)); + memset(*rbpp, 0, sizeof(**rbpp)); + (*rbpp)->group = layergroup; + init_const_box(*rbpp, + /*X1 */ MIN(line->Point1.X, + line->Point2.X) - HALF_THICK(line->Thickness), + /*Y1 */ MIN(line->Point1.Y, + line->Point2.Y) - HALF_THICK(line->Thickness), + /*X2 */ MAX(line->Point1.X, + line->Point2.X) + HALF_THICK(line->Thickness), + /*Y2 */ MAX(line->Point1.Y, + line->Point2.Y) + HALF_THICK(line->Thickness), style->Clearance); + /* kludge for non-manhattan lines */ + if (line->Point1.X != line->Point2.X && line->Point1.Y != line->Point2.Y) { + (*rbpp)->flags.nonstraight = 1; + (*rbpp)->flags.bl_to_ur = + (MIN(line->Point1.X, line->Point2.X) == line->Point1.X) != (MIN(line->Point1.Y, line->Point2.Y) == line->Point1.Y); +#if defined(ROUTE_DEBUG) && defined(DEBUG_SHOW_ZIGZAG) + showroutebox(*rbpp); +#endif + } + /* set aux. properties */ + (*rbpp)->type = LINE; + (*rbpp)->line.x1 = line->Point1.X; + (*rbpp)->line.y1 = line->Point1.Y; + (*rbpp)->line.x2 = line->Point2.X; + (*rbpp)->line.y2 = line->Point2.Y; + (*rbpp)->parent.line = ptr; + (*rbpp)->flags.fixed = 1; + (*rbpp)->came_from = PCB_ANY_DIR; + (*rbpp)->style = style; + /* circular lists */ + InitLists(*rbpp); + return *rbpp; +} + +static routebox_t *AddIrregularObstacle(vtp0_t layergroupboxes[], + pcb_coord_t X1, pcb_coord_t Y1, + pcb_coord_t X2, pcb_coord_t Y2, pcb_cardinal_t layergroup, void *parent, pcb_route_style_t * style) +{ + routebox_t **rbpp; + pcb_coord_t keep = style->Clearance; + assert(layergroupboxes && parent); + assert(X1 <= X2 && Y1 <= Y2); + assert(0 <= layergroup && layergroup < pcb_max_group(PCB)); + assert(PCB->LayerGroups.grp[layergroup].len > 0); + + rbpp = (routebox_t **) vtp0_alloc_append(&layergroupboxes[layergroup], 1); + *rbpp = (routebox_t *) malloc(sizeof(**rbpp)); + memset(*rbpp, 0, sizeof(**rbpp)); + (*rbpp)->group = layergroup; + init_const_box(*rbpp, X1, Y1, X2, Y2, keep); + (*rbpp)->flags.nonstraight = 1; + (*rbpp)->type = OTHER; + (*rbpp)->parent.generic = parent; + (*rbpp)->flags.fixed = 1; + (*rbpp)->style = style; + /* circular lists */ + InitLists(*rbpp); + return *rbpp; +} + +static routebox_t *AddPolygon(vtp0_t layergroupboxes[], pcb_cardinal_t layer, pcb_poly_t *polygon, pcb_route_style_t * style) +{ + int is_not_rectangle = 1; + pcb_layergrp_id_t layergroup = pcb_layer_get_group(PCB, layer); + routebox_t *rb; + assert(0 <= layergroup && layergroup < pcb_max_group(PCB)); + rb = AddIrregularObstacle(layergroupboxes, + polygon->BoundingBox.X1, + polygon->BoundingBox.Y1, + polygon->BoundingBox.X2, polygon->BoundingBox.Y2, layergroup, polygon, style); + if (polygon->PointN == 4 && + polygon->HoleIndexN == 0 && + (polygon->Points[0].X == polygon->Points[1].X || + polygon->Points[0].Y == polygon->Points[1].Y) && + (polygon->Points[1].X == polygon->Points[2].X || + polygon->Points[1].Y == polygon->Points[2].Y) && + (polygon->Points[2].X == polygon->Points[3].X || + polygon->Points[2].Y == polygon->Points[3].Y) && + (polygon->Points[3].X == polygon->Points[0].X || polygon->Points[3].Y == polygon->Points[0].Y)) + is_not_rectangle = 0; + rb->flags.nonstraight = is_not_rectangle; + rb->layer = layer; + rb->came_from = PCB_ANY_DIR; + if (PCB_FLAG_TEST(PCB_FLAG_CLEARPOLY, polygon)) { + rb->flags.clear_poly = 1; + if (!is_not_rectangle) + rb->type = PLANE; + } + return rb; +} + +static void AddText(vtp0_t layergroupboxes[], pcb_cardinal_t layergroup, pcb_text_t *text, pcb_route_style_t * style) +{ + AddIrregularObstacle(layergroupboxes, + text->BoundingBox.X1, text->BoundingBox.Y1, + text->BoundingBox.X2, text->BoundingBox.Y2, layergroup, text, style); +} + +static routebox_t *AddArc(vtp0_t layergroupboxes[], pcb_cardinal_t layergroup, pcb_arc_t *arc, pcb_route_style_t * style) +{ + return AddIrregularObstacle(layergroupboxes, + arc->BoundingBox.X1, arc->BoundingBox.Y1, + arc->BoundingBox.X2, arc->BoundingBox.Y2, layergroup, arc, style); +} + +struct rb_info { + pcb_box_t query; + routebox_t *winner; + jmp_buf env; +}; + +static pcb_r_dir_t __found_one_on_lg(const pcb_box_t * box, void *cl) +{ + struct rb_info *inf = (struct rb_info *) cl; + routebox_t *rb = (routebox_t *) box; + pcb_box_t sb; + + if (rb->flags.nonstraight) + return PCB_R_DIR_NOT_FOUND; + sb = pcb_shrink_box(&rb->box, rb->style->Clearance); + if (inf->query.X1 >= sb.X2 || inf->query.X2 <= sb.X1 || inf->query.Y1 >= sb.Y2 || inf->query.Y2 <= sb.Y1) + return PCB_R_DIR_NOT_FOUND; + inf->winner = rb; + if (rb->type == PLANE) + return PCB_R_DIR_FOUND_CONTINUE; /* keep looking for something smaller if a plane was found */ + longjmp(inf->env, 1); + return PCB_R_DIR_NOT_FOUND; +} + +static routebox_t *FindRouteBoxOnLayerGroup(routedata_t * rd, pcb_coord_t X, pcb_coord_t Y, pcb_cardinal_t layergroup) +{ + struct rb_info info; + info.winner = NULL; + info.query = pcb_point_box(X, Y); + if (setjmp(info.env) == 0) + pcb_r_search(rd->layergrouptree[layergroup], &info.query, NULL, __found_one_on_lg, &info, NULL); + return info.winner; +} + +#ifdef ROUTE_DEBUG_VERBOSE +static void DumpRouteBox(routebox_t * rb) +{ + pcb_printf("RB: %#mD-%#mD l%d; ", rb->box.X1, rb->box.Y1, rb->box.X2, rb->box.Y2, (int) rb->group); + switch (rb->type) { + case TERM: + printf("TERM[%s] ", rb->parent.term->term); + break; + case LINE: + printf("LINE "); + break; + case OTHER: + printf("OTHER "); + break; + case EXPANSION_AREA: + printf("EXPAREA "); + break; + default: + printf("UNKNOWN "); + break; + } + if (rb->flags.nonstraight) + printf("(nonstraight) "); + if (rb->flags.fixed) + printf("(fixed) "); + if (rb->flags.source) + printf("(source) "); + if (rb->flags.target) + printf("(target) "); + if (rb->flags.homeless) + printf("(homeless) "); + printf("\n"); +} +#endif + +/* Add obstacles extracting them from data (subc-recursive) */ +static void CreateRouteData_subc(routedata_t *rd, vtp0_t layergroupboxes[], pcb_data_t *data) +{ + int i; + + PCB_PADSTACK_LOOP(data); + { + if (PCB_FLAG_TEST(PCB_FLAG_DRC, padstack)) + PCB_FLAG_CLEAR(PCB_FLAG_DRC, padstack); + else + AddPstk(layergroupboxes, padstack, rd->styles[rd->max_styles]); + } + PCB_END_LOOP; + + for (i = 0; i < data->LayerN; i++) { + pcb_layergrp_id_t layergroup; + pcb_layer_t *ly = &data->Layer[i]; + + if (!(pcb_layer_flags_(ly) & PCB_LYT_COPPER)) + continue; + + layergroup = pcb_layer_get_group_(ly); + + /* add all (non-rat) lines */ + PCB_LINE_LOOP(ly); + { + if (PCB_FLAG_TEST(PCB_FLAG_DRC, line)) { + PCB_FLAG_CLEAR(PCB_FLAG_DRC, line); + continue; + } + /* dice up non-straight lines into many tiny obstacles */ + if (line->Point1.X != line->Point2.X && line->Point1.Y != line->Point2.Y) { + pcb_line_t fake_line = *line; + pcb_coord_t dx = (line->Point2.X - line->Point1.X); + pcb_coord_t dy = (line->Point2.Y - line->Point1.Y); + int segs = MAX(PCB_ABS(dx), PCB_ABS(dy)) / (4 * rd->max_bloat + 1); + int qq; + segs = PCB_CLAMP(segs, 1, 32); /* don't go too crazy */ + dx /= segs; + dy /= segs; + for (qq = 0; qq < segs - 1; qq++) { + fake_line.Point2.X = fake_line.Point1.X + dx; + fake_line.Point2.Y = fake_line.Point1.Y + dy; + if (fake_line.Point2.X == line->Point2.X && fake_line.Point2.Y == line->Point2.Y) + break; + AddLine(layergroupboxes, layergroup, &fake_line, line, rd->styles[rd->max_styles]); + fake_line.Point1 = fake_line.Point2; + } + fake_line.Point2 = line->Point2; + AddLine(layergroupboxes, layergroup, &fake_line, line, rd->styles[rd->max_styles]); + } + else { + AddLine(layergroupboxes, layergroup, line, line, rd->styles[rd->max_styles]); + } + } + PCB_END_LOOP; + /* add all polygons */ + PCB_POLY_LOOP(ly); + { + if (PCB_FLAG_TEST(PCB_FLAG_DRC, polygon)) + PCB_FLAG_CLEAR(PCB_FLAG_DRC, polygon); + else + AddPolygon(layergroupboxes, i, polygon, rd->styles[rd->max_styles]); + } + PCB_END_LOOP; + /* add all copper text */ + PCB_TEXT_LOOP(ly); + { + AddText(layergroupboxes, layergroup, text, rd->styles[rd->max_styles]); + } + PCB_END_LOOP; + /* add all arcs */ + PCB_ARC_LOOP(ly); + { + AddArc(layergroupboxes, layergroup, arc, rd->styles[rd->max_styles]); + } + PCB_END_LOOP; + } + + /* subc recursion - re-add terms */ + PCB_SUBC_LOOP(data); + { + CreateRouteData_subc(rd, layergroupboxes, subc->data); + } + PCB_END_LOOP; + +} + +static routebox_t *crd_add_line(routedata_t *rd, vtp0_t *layergroupboxes, pcb_layergrp_id_t group, pcb_any_obj_t *obj, int j, routebox_t **last_in_net, routebox_t **last_in_subnet) +{ + routebox_t *rb = NULL; + pcb_line_t *line = (pcb_line_t *) obj; + + /* dice up non-straight lines into many tiny obstacles */ + if (line->Point1.X != line->Point2.X && line->Point1.Y != line->Point2.Y) { + pcb_line_t fake_line = *line; + pcb_coord_t dx = (line->Point2.X - line->Point1.X); + pcb_coord_t dy = (line->Point2.Y - line->Point1.Y); + int segs = MAX(PCB_ABS(dx), PCB_ABS(dy)) / (4 * BLOAT(rd->styles[j]) + 1); + int qq; + segs = PCB_CLAMP(segs, 1, 32); /* don't go too crazy */ + dx /= segs; + dy /= segs; + for (qq = 0; qq < segs - 1; qq++) { + fake_line.Point2.X = fake_line.Point1.X + dx; + fake_line.Point2.Y = fake_line.Point1.Y + dy; + if (fake_line.Point2.X == line->Point2.X && fake_line.Point2.Y == line->Point2.Y) + break; + rb = AddLine(layergroupboxes, group, &fake_line, line, rd->styles[j]); + if (*last_in_subnet && rb != *last_in_subnet) + MergeNets(*last_in_subnet, rb, ORIGINAL); + if (*last_in_net && rb != *last_in_net) + MergeNets(*last_in_net, rb, NET); + *last_in_subnet = *last_in_net = rb; + fake_line.Point1 = fake_line.Point2; + } + fake_line.Point2 = line->Point2; + rb = AddLine(layergroupboxes, group, &fake_line, line, rd->styles[j]); + } + else + rb = AddLine(layergroupboxes, group, line, line, rd->styles[j]); + + return rb; +} + +static routebox_t *crd_add_misc(routedata_t *rd, vtp0_t *layergroupboxes, pcb_any_obj_t *obj, int j) +{ + routebox_t *rb = NULL; + + switch (obj->type) { + case PCB_OBJ_VOID: break; + case PCB_OBJ_PSTK: + rb = AddPstk(layergroupboxes, (pcb_pstk_t *)obj, rd->styles[j]); + break; + case PCB_OBJ_POLY: + { + pcb_poly_t *poly = (pcb_poly_t *)obj; + pcb_layer_t *layer = obj->parent.layer; + if (poly->term != NULL) + rb = AddTerm(layergroupboxes, obj, rd->styles[j]); + else + rb = AddPolygon(layergroupboxes, pcb_layer_id(PCB->Data, layer), poly, rd->styles[j]); + } + break; + case PCB_OBJ_LINE: + case PCB_OBJ_TEXT: + case PCB_OBJ_ARC: + if (obj->term != NULL) + rb = AddTerm(layergroupboxes, obj, rd->styles[j]); + break; + + case PCB_OBJ_RAT: + case PCB_OBJ_SUBC: + case PCB_OBJ_NET: + case PCB_OBJ_NET_TERM: + case PCB_OBJ_LAYER: + case PCB_OBJ_LAYERGRP: + break; /* don't care about these */ + } + return rb; +} + +static void CreateRouteData_subnet(routedata_t *rd, vtp0_t *layergroupboxes, vtp0_t *objs, routebox_t **last_in_net, int j) +{ + routebox_t *last_in_subnet = NULL; + size_t oi; + + for(oi = 0; oi < vtp0_len(objs); oi++) { + routebox_t *rb = NULL; + pcb_any_obj_t *obj = objs->array[oi]; + + if (obj->type == PCB_OBJ_RAT) + continue; + + if (obj->term != NULL) + last_in_subnet = NULL; + + PCB_FLAG_SET(PCB_FLAG_DRC, obj); + + if ((obj->type == PCB_OBJ_LINE) && (obj->term != NULL)) + rb = AddTerm(layergroupboxes, obj, rd->styles[j]); + else if (obj->type == PCB_OBJ_LINE) { + pcb_layer_t *layer = pcb_layer_get_real(obj->parent.layer); + pcb_layergrp_id_t group = layer->meta.real.grp; + rb = crd_add_line(rd, layergroupboxes, group, obj, j, last_in_net, &last_in_subnet); + } + else + rb = crd_add_misc(rd, layergroupboxes, obj, j); + + assert(rb); + + /* update circular connectivity lists */ + if (last_in_subnet && rb != last_in_subnet) + MergeNets(last_in_subnet, rb, ORIGINAL); + if (*last_in_net && rb != *last_in_net) + MergeNets(*last_in_net, rb, NET); + last_in_subnet = *last_in_net = rb; + rd->max_bloat = MAX(rd->max_bloat, BLOAT(rb->style)); + rd->max_keep = MAX(rd->max_keep, rb->style->Clearance); + } +} + +static void CreateRouteData_nets(routedata_t *rd, vtp0_t *layergroupboxes) +{ + htsp_entry_t *e; + pcb_short_ctx_t sctx; + vtp0_t subnets; + routebox_t *last_net = NULL; + + vtp0_init(&subnets); + pcb_net_short_ctx_init(&sctx, PCB, NULL); + + for(e = htsp_first(&PCB->netlist[PCB_NETLIST_EDITED]); e != NULL; e = htsp_next(&PCB->netlist[PCB_NETLIST_EDITED], e)) { + size_t sni; + routebox_t *last_in_net = NULL; + pcb_net_t *net = e->value; + const char *style = pcb_attribute_get(&net->Attributes, "style"); + int j; + + if (style == NULL) + style = ""; + + for (j = 0; j < rd->max_styles; j++) + if (strcmp(style, rd->styles[j]->name) == 0) + break; + + sctx.current_net = (pcb_net_t *)e->value; + pcb_net_map_subnets(&sctx, PCB_RATACC_ONLY_MANHATTAN, &subnets); + for(sni = 0; sni < vtp0_len(&subnets); sni++) + CreateRouteData_subnet(rd, layergroupboxes, subnets.array[sni], &last_in_net, j); + pcb_net_reset_subnets(&subnets); + + if (last_net && last_in_net) + MergeNets(last_net, last_in_net, DIFFERENT_NET); + last_net = last_in_net; + } + rd->first_net = last_net; + + vtp0_uninit(&subnets); + pcb_net_short_ctx_uninit(&sctx); + + /* reset all nets to "original" connectivity (which we just set) */ + { + routebox_t *net; + LIST_LOOP(rd->first_net, different_net, net); + ResetSubnet(net); + PCB_END_LOOP; + } +} + +static routedata_t *CreateRouteData() +{ + vtp0_t layergroupboxes[PCB_MAX_LAYERGRP]; + pcb_box_t bbox; + routedata_t *rd; + int group, i; + + /* check which layers are active first */ + routing_layers = 0; + for (group = 0; group < pcb_max_group(PCB); group++) { + for (i = 0; i < PCB->LayerGroups.grp[group].len; i++) { + pcb_layer_id_t lid = PCB->LayerGroups.grp[group].lid[i]; + /* layer must be 1) copper and 2) on */ + if ((pcb_layer_flags(PCB, lid) & PCB_LYT_COPPER) && PCB->Data->Layer[lid].meta.real.vis) { + routing_layers++; + is_layer_group_active[group] = pcb_true; + break; + } + else + is_layer_group_active[group] = pcb_false; + } + } + /* if via visibility is turned off, don't use them */ + AutoRouteParameters.use_vias = routing_layers > 1 && PCB->pstk_on; + + back = front = -1; + if (pcb_layergrp_list(PCB, PCB_LYT_BOTTOM | PCB_LYT_COPPER, &back, 1) <= 0) + return NULL; + if (pcb_layergrp_list(PCB, PCB_LYT_TOP | PCB_LYT_COPPER, &front, 1) <= 0) + return NULL; + + /* determine preferred routing direction on each group */ + for (i = 0; i < pcb_max_group(PCB); i++) { + if (i != back && i != front) { + x_cost[i] = (i & 1) ? 2 : 1; + y_cost[i] = (i & 1) ? 1 : 2; + } + else if (i == back) { + x_cost[i] = 4; + y_cost[i] = 2; + } + else { + x_cost[i] = 2; + y_cost[i] = 2; + } + } + /* create routedata */ + rd = (routedata_t *) malloc(sizeof(*rd)); + memset((void *) rd, 0, sizeof(*rd)); + + rd->max_styles = vtroutestyle_len(&PCB->RouteStyle); +/* rd->layergrouptree = calloc(sizeof(rd->layergrouptree[0]), rd->max_layers);*/ + rd->styles = calloc(sizeof(rd->styles[0]), rd->max_styles+1); + + /* create default style */ + rd->defaultstyle.Thick = conf_core.design.line_thickness; + rd->defaultstyle.Diameter = conf_core.design.via_thickness; + rd->defaultstyle.Hole = conf_core.design.via_drilling_hole; + rd->defaultstyle.Clearance = conf_core.design.clearance; + rd->max_bloat = BLOAT(&rd->defaultstyle); + rd->max_keep = conf_core.design.clearance; + /* create styles structures */ + bbox.X1 = bbox.Y1 = 0; + bbox.X2 = PCB->MaxWidth; + bbox.Y2 = PCB->MaxHeight; + for (i = 0; i < rd->max_styles + 1; i++) { + pcb_route_style_t *style = (i < rd->max_styles) ? &PCB->RouteStyle.array[i] : &rd->defaultstyle; + rd->styles[i] = style; + } + + /* initialize pointer vectors */ + for (i = 0; i < pcb_max_group(PCB); i++) { + vtp0_init(&layergroupboxes[i]); + PCB_COPPER_GROUP_LOOP(PCB->Data, i); + { + if (!PCB_RTREE_EMPTY(layer->line_tree) || !PCB_RTREE_EMPTY(layer->arc_tree)) + usedGroup[i] = pcb_true; + else + usedGroup[i] = pcb_false; + } + PCB_END_LOOP; + } + usedGroup[front] = pcb_true; + usedGroup[back] = pcb_true; + + CreateRouteData_nets(rd, layergroupboxes); + + /* subc-recursively add all obstacles */ + CreateRouteData_subc(rd, layergroupboxes, PCB->Data); + + /* create r-trees from pointer lists */ + for (i = 0; i < pcb_max_group(PCB); i++) { + /* create the r-tree */ + rd->layergrouptree[i] = pcb_r_create_tree(); + pcb_r_insert_array(rd->layergrouptree[i], (const pcb_box_t **) layergroupboxes[i].array, vtp0_len(&layergroupboxes[i])); + } + + if (AutoRouteParameters.use_vias) { + rd->mtspace = mtspace_create(); + + /* create "empty-space" structures for via placement (now that we know + * appropriate clearances for all the fixed elements) */ + for (i = 0; i < pcb_max_group(PCB); i++) { + int ip; + for(ip = 0; ip < vtp0_len(&layergroupboxes[i]); ip++) { + void **ptr = &layergroupboxes[i].array[ip]; + routebox_t *rb = (routebox_t *) * ptr; + if (!rb->flags.clear_poly) + mtspace_add(rd->mtspace, &rb->box, FIXED, rb->style->Clearance); + } + } + } + /* free pointer lists */ + for (i = 0; i < pcb_max_group(PCB); i++) + vtp0_uninit(&layergroupboxes[i]); + /* done! */ + return rd; +} + +void DestroyRouteData(routedata_t ** rd) +{ + int i; + for (i = 0; i < pcb_max_group(PCB); i++) { + pcb_r_free_tree_data((*rd)->layergrouptree[i], free); + pcb_r_destroy_tree(&(*rd)->layergrouptree[i]); + } + if (AutoRouteParameters.use_vias) + mtspace_destroy(&(*rd)->mtspace); +/* free((*rd)->layergrouptree);*/ + free((*rd)->styles); + free(*rd); + *rd = NULL; +} + +/*----------------------------------------------------------------- + * routebox reference counting. + */ + +/* increment the reference count on a routebox. */ +static void RB_up_count(routebox_t * rb) +{ + assert(rb->flags.homeless); + rb->refcount++; +} + +/* decrement the reference count on a routebox, freeing if this box becomes + * unused. */ +static void RB_down_count(routebox_t * rb) +{ + assert(rb->type == EXPANSION_AREA); + assert(rb->flags.homeless); + assert(rb->refcount > 0); + if (--rb->refcount == 0) { + if (rb->parent.expansion_area->flags.homeless) + RB_down_count(rb->parent.expansion_area); + free(rb); + } +} + +/*----------------------------------------------------------------- + * Rectangle-expansion routing code. + */ + +static void ResetSubnet(routebox_t * net) +{ + routebox_t *rb; + /* reset connectivity of everything on this net */ + LIST_LOOP(net, same_net, rb); + rb->same_subnet = rb->original_subnet; + PCB_END_LOOP; +} + +static inline pcb_cost_t pcb_cost_to_point_on_layer(const pcb_cheap_point_t * p1, const pcb_cheap_point_t * p2, pcb_cardinal_t point_layer) +{ + pcb_cost_t x_dist = p1->X - p2->X, y_dist = p1->Y - p2->Y, r; + x_dist *= x_cost[point_layer]; + y_dist *= y_cost[point_layer]; + /* cost is proportional to orthogonal distance. */ + r = PCB_ABS(x_dist) + PCB_ABS(y_dist); + if (p1->X != p2->X && p1->Y != p2->Y) + r += AutoRouteParameters.JogPenalty; + return r; +} + +static pcb_cost_t pcb_cost_to_point(const pcb_cheap_point_t * p1, pcb_cardinal_t point_layer1, const pcb_cheap_point_t * p2, pcb_cardinal_t point_layer2) +{ + pcb_cost_t r = pcb_cost_to_point_on_layer(p1, p2, point_layer1); + /* apply via cost penalty if layers differ */ + if (point_layer1 != point_layer2) + r += AutoRouteParameters.ViaCost; + return r; +} + +/* return the minimum *cost* from a point to a box on any layer. + * It's safe to return a smaller than minimum cost + */ +static pcb_cost_t pcb_cost_to_layerless_box(const pcb_cheap_point_t * p, pcb_cardinal_t point_layer, const pcb_box_t * b) +{ + pcb_cheap_point_t p2 = pcb_closest_pcb_point_in_box(p, b); + register pcb_cost_t c1, c2; + + c1 = p2.X - p->X; + c2 = p2.Y - p->Y; + + c1 = PCB_ABS(c1); + c2 = PCB_ABS(c2); + if (c1 < c2) + return c1 * AutoRouteParameters.MinPenalty + c2; + else + return c2 * AutoRouteParameters.MinPenalty + c1; +} + +/* get to actual pins/pad target coordinates */ +pcb_bool TargetPoint(pcb_cheap_point_t * nextpoint, const routebox_t * target) +{ +/* if (target->type == PIN) { + nextpoint->X = target->parent.pin->X; + nextpoint->Y = target->parent.pin->Y; + return pcb_true; + }*/ + nextpoint->X = PCB_BOX_CENTER_X(target->sbox); + nextpoint->Y = PCB_BOX_CENTER_Y(target->sbox); + return pcb_false; +} + +/* return the *minimum cost* from a point to a route box, including possible + * via costs if the route box is on a different layer. + * assume routbox is bloated unless it is an expansion area + */ +static pcb_cost_t pcb_cost_to_routebox(const pcb_cheap_point_t * p, pcb_cardinal_t point_layer, const routebox_t * rb) +{ + register pcb_cost_t trial = 0; + pcb_cheap_point_t p2 = closest_point_in_routebox(p, rb); + if (!usedGroup[point_layer] || !usedGroup[rb->group]) + trial = AutoRouteParameters.NewLayerPenalty; + if ((p2.X - p->X) * (p2.Y - p->Y) != 0) + trial += AutoRouteParameters.JogPenalty; + /* special case for defered via searching */ + if (point_layer > pcb_max_group(PCB) || point_layer == rb->group) + return trial + PCB_ABS(p2.X - p->X) + PCB_ABS(p2.Y - p->Y); + /* if this target is only a via away, then the via is cheaper than the congestion */ + if (p->X == p2.X && p->Y == p2.Y) + return trial + 1; + trial += AutoRouteParameters.ViaCost; + trial += PCB_ABS(p2.X - p->X) + PCB_ABS(p2.Y - p->Y); + return trial; +} + + +static pcb_box_t bloat_routebox(routebox_t * rb) +{ + pcb_box_t r; + pcb_coord_t clearance; + assert(__routepcb_box_is_good(rb)); + + if (rb->flags.nobloat) + return rb->sbox; + + /* Obstacle exclusion zones get bloated by the larger of + * the two required clearances plus half the track width. + */ + clearance = MAX(AutoRouteParameters.style->Clearance, rb->style->Clearance); + r = pcb_bloat_box(&rb->sbox, clearance + HALF_THICK(AutoRouteParameters.style->Thick)); + return r; +} + + +#ifdef ROUTE_DEBUG /* only for debugging expansion areas */ + +typedef short pcb_dimension_t; +/* makes a line on the solder layer silk surrounding the box */ +static void showbox(pcb_box_t b, pcb_dimension_t thickness, int group) +{ + pcb_line_t *line; + pcb_layer_t *csl, *SLayer = LAYER_PTR(group); + pcb_layer_id_t cs_id; + if (showboxen < -1) + return; + if (showboxen != -1 && showboxen != group) + return; + + if (ddraw != NULL) { + ddraw->set_line_width(ar_gc, thickness); + ddraw->set_line_cap(ar_gc, pcb_cap_round); + ddraw->set_color(ar_gc, SLayer->Color); + + ddraw->draw_line(ar_gc, b.X1, b.Y1, b.X2, b.Y1); + ddraw->draw_line(ar_gc, b.X1, b.Y2, b.X2, b.Y2); + ddraw->draw_line(ar_gc, b.X1, b.Y1, b.X1, b.Y2); + ddraw->draw_line(ar_gc, b.X2, b.Y1, b.X2, b.Y2); + } + +#if 1 + if (pcb_layer_find(PCB_LYT_TOP | PCB_LYT_SILK, &cs_id, 1) > 0) { + csl = LAYER_PTR(cs_id); + if (b.Y1 == b.Y2 || b.X1 == b.X2) + thickness = 5; + line = pcb_line_new(csl, b.X1, b.Y1, b.X2, b.Y1, thickness, 0, pcb_flag_make(0)); + pcb_undo_add_obj_to_create(csl, line, line); + if (b.Y1 != b.Y2) { + line = pcb_line_new(csl, b.X1, b.Y2, b.X2, b.Y2, thickness, 0, pcb_flag_make(0)); + pcb_undo_add_obj_to_create(PCB_OBJ_LINE, csl, line, line); + } + line = pcb_line_new(csl, b.X1, b.Y1, b.X1, b.Y2, thickness, 0, pcb_flag_make(0)); + pcb_undo_add_obj_to_create(PCB_OBJ_LINE, csl, line, line); + if (b.X1 != b.X2) { + line = pcb_line_new(csl, b.X2, b.Y1, b.X2, b.Y2, thickness, 0, pcb_flag_make(0)); + pcb_undo_add_obj_to_create(PCB_OBJ_LINE, csl, line, line); + } + } +#endif +} +#endif + +#if defined(ROUTE_DEBUG) +static void showedge(edge_t * e) +{ + pcb_box_t *b = (pcb_box_t *) e->rb; + + if (ddraw == NULL) + return; + + ddraw->set_line_cap(ar_gc, pcb_cap_round); + ddraw->set_line_width(ar_gc, 1); + ddraw->set_color(ar_gc, Settings.MaskColor); + + switch (e->expand_dir) { + case PCB_NORTH: + ddraw->draw_line(ar_gc, b->X1, b->Y1, b->X2, b->Y1); + break; + case PCB_SOUTH: + ddraw->draw_line(ar_gc, b->X1, b->Y2, b->X2, b->Y2); + break; + case PCB_WEST: + ddraw->draw_line(ar_gc, b->X1, b->Y1, b->X1, b->Y2); + break; + case PCB_EAST: + ddraw->draw_line(ar_gc, b->X2, b->Y1, b->X2, b->Y2); + break; + default: + break; + } +} +#endif + +#if defined(ROUTE_DEBUG) +static void showroutebox(routebox_t * rb) +{ + pcb_layerid_t cs_id; + if (pcb_layer_find(PCB_LYT_TOP | PCB_LYT_SILK, &cs_id, 1) > 0) + showbox(rb->sbox, rb->flags.source ? 20 : (rb->flags.target ? 10 : 1), rb->flags.is_via ? LAYER_PTR(cs_id) : rb->group); +} +#endif + +/* return a "parent" of this edge which immediately precedes it in the route.*/ +static routebox_t *route_parent(routebox_t * rb) +{ + while (rb->flags.homeless && !rb->flags.is_via && !rb->flags.is_thermal) { + assert(rb->type == EXPANSION_AREA); + rb = rb->parent.expansion_area; + assert(rb); + } + return rb; +} + +static vector_t *path_conflicts(routebox_t * rb, routebox_t * conflictor, pcb_bool branch) +{ + if (branch) + rb->conflicts_with = vector_duplicate(rb->conflicts_with); + else if (!rb->conflicts_with) + rb->conflicts_with = vector_create(); + vector_append(rb->conflicts_with, conflictor); + return rb->conflicts_with; +} + +/* Touch everything (except fixed) on each net found + * in the conflicts vector. If the vector is different + * from the last one touched, untouch the last batch + * and touch the new one. Always call with touch=1 + * (except for recursive call). Call with NULL, 1 to + * clear the last batch touched. + * + * touched items become invisible to current path + * so we don't encounter the same conflictor more + * than once + */ + +static void touch_conflicts(vector_t * conflicts, int touch) +{ + static vector_t *last = NULL; + static int last_size = 0; + int i, n; + i = 0; + if (touch) { + if (last && conflicts != last) + touch_conflicts(last, 0); + if (!conflicts) + return; + last = conflicts; + i = last_size; + } + n = vector_size(conflicts); + for (; i < n; i++) { + routebox_t *rb = (routebox_t *) vector_element(conflicts, i); + routebox_t *p; + LIST_LOOP(rb, same_net, p); + if (!p->flags.fixed) + p->flags.touched = touch; + PCB_END_LOOP; + } + if (!touch) { + last = NULL; + last_size = 0; + } + else + last_size = n; +} + +/* return a "parent" of this edge which resides in a r-tree somewhere */ +/* -- actually, this "parent" *may* be a via box, which doesn't live in + * a r-tree. -- */ +static routebox_t *nonhomeless_parent(routebox_t * rb) +{ + return route_parent(rb); +} + +/* some routines to find the minimum *cost* from a cost point to + * a target (any target) */ +struct minpcb_cost_target_closure { + const pcb_cheap_point_t *CostPoint; + pcb_cardinal_t CostPointLayer; + routebox_t *nearest; + pcb_cost_t nearest_cost; +}; +static pcb_r_dir_t __region_within_guess(const pcb_box_t * region, void *cl) +{ + struct minpcb_cost_target_closure *mtc = (struct minpcb_cost_target_closure *) cl; + pcb_cost_t pcb_cost_to_region; + if (mtc->nearest == NULL) + return PCB_R_DIR_FOUND_CONTINUE; + pcb_cost_to_region = pcb_cost_to_layerless_box(mtc->CostPoint, mtc->CostPointLayer, region); + assert(pcb_cost_to_region >= 0); + /* if no guess yet, all regions are "close enough" */ + /* note that cost is *strictly more* than minimum distance, so we'll + * always search a region large enough. */ + return (pcb_cost_to_region < mtc->nearest_cost) ? PCB_R_DIR_FOUND_CONTINUE : PCB_R_DIR_NOT_FOUND; +} + +static pcb_r_dir_t __found_new_guess(const pcb_box_t * box, void *cl) +{ + struct minpcb_cost_target_closure *mtc = (struct minpcb_cost_target_closure *) cl; + routebox_t *guess = (routebox_t *) box; + pcb_cost_t pcb_cost_to_guess = pcb_cost_to_routebox(mtc->CostPoint, mtc->CostPointLayer, guess); + assert(pcb_cost_to_guess >= 0); + /* if this is cheaper than previous guess... */ + if (pcb_cost_to_guess < mtc->nearest_cost) { + mtc->nearest = guess; + mtc->nearest_cost = pcb_cost_to_guess; /* this is our new guess! */ + return PCB_R_DIR_FOUND_CONTINUE; + } + else + return PCB_R_DIR_NOT_FOUND; /* not less expensive than our last guess */ +} + +/* target_guess is our guess at what the nearest target is, or NULL if we + * just plum don't have a clue. */ +static routebox_t *minpcb_cost_target_to_point(const pcb_cheap_point_t * CostPoint, + pcb_cardinal_t CostPointLayer, pcb_rtree_t * targets, routebox_t * target_guess) +{ + struct minpcb_cost_target_closure mtc; + assert(target_guess == NULL || target_guess->flags.target); /* this is a target, right? */ + mtc.CostPoint = CostPoint; + mtc.CostPointLayer = CostPointLayer; + mtc.nearest = target_guess; + if (mtc.nearest) + mtc.nearest_cost = pcb_cost_to_routebox(mtc.CostPoint, mtc.CostPointLayer, mtc.nearest); + else + mtc.nearest_cost = EXPENSIVE; + pcb_r_search(targets, NULL, __region_within_guess, __found_new_guess, &mtc, NULL); + assert(mtc.nearest != NULL && mtc.nearest_cost >= 0); + assert(mtc.nearest->flags.target); /* this is a target, right? */ + return mtc.nearest; +} + +/* create edge from field values */ +/* minpcb_cost_target_guess can be NULL */ +static edge_t *CreateEdge(routebox_t * rb, + pcb_coord_t CostPointX, pcb_coord_t CostPointY, + pcb_cost_t pcb_cost_to_point, routebox_t * minpcb_cost_target_guess, pcb_direction_t expand_dir, pcb_rtree_t * targets) +{ + edge_t *e; + assert(__routepcb_box_is_good(rb)); + e = (edge_t *) malloc(sizeof(*e)); + memset((void *) e, 0, sizeof(*e)); + assert(e); + e->rb = rb; + if (rb->flags.homeless) + RB_up_count(rb); + e->cost_point.X = CostPointX; + e->cost_point.Y = CostPointY; + e->pcb_cost_to_point = pcb_cost_to_point; + e->flags.via_search = 0; + /* if this edge is created in response to a target, use it */ + if (targets) + e->minpcb_cost_target = minpcb_cost_target_to_point(&e->cost_point, rb->group, targets, minpcb_cost_target_guess); + else + e->minpcb_cost_target = minpcb_cost_target_guess; + e->expand_dir = expand_dir; + assert(e->rb && e->minpcb_cost_target); /* valid edge? */ + assert(!e->flags.is_via || e->expand_dir == PCB_ANY_DIR); + /* cost point should be on edge (unless this is a plane/via/conflict edge) */ +#if 0 + assert(rb->type == PLANE || rb->conflicts_with != NULL || rb->flags.is_via + || rb->flags.is_thermal + || ((expand_dir == PCB_NORTH || expand_dir == PCB_SOUTH) ? rb->sbox.X1 <= + CostPointX && CostPointX < rb->sbox.X2 && CostPointY == (expand_dir == PCB_NORTH ? rb->sbox.Y1 : rb->sbox.Y2 - 1) : + /* expand_dir==EAST || expand_dir==WEST */ + rb->sbox.Y1 <= CostPointY && CostPointY < rb->sbox.Y2 && + CostPointX == (expand_dir == PCB_EAST ? rb->sbox.X2 - 1 : rb->sbox.X1))); +#endif + assert(__edge_is_good(e)); + /* done */ + return e; +} + +/* create edge, using previous edge to fill in defaults. */ +/* most of the work here is in determining a new cost point */ +static edge_t *CreateEdge2(routebox_t * rb, pcb_direction_t expand_dir, + edge_t * previous_edge, pcb_rtree_t * targets, routebox_t * guess) +{ + pcb_box_t thisbox; + pcb_cheap_point_t thiscost, prevcost; + pcb_cost_t d; + + assert(rb && previous_edge); + /* okay, find cheapest costpoint to costpoint of previous edge */ + thisbox = edge_to_box(rb, expand_dir); + prevcost = previous_edge->cost_point; + /* find point closest to target */ + thiscost = pcb_closest_pcb_point_in_box(&prevcost, &thisbox); + /* compute cost-to-point */ + d = pcb_cost_to_point_on_layer(&prevcost, &thiscost, rb->group); + /* add in jog penalty */ + if (previous_edge->expand_dir != expand_dir) + d += AutoRouteParameters.JogPenalty; + /* okay, new edge! */ + return CreateEdge(rb, thiscost.X, thiscost.Y, + previous_edge->pcb_cost_to_point + d, guess ? guess : previous_edge->minpcb_cost_target, expand_dir, targets); +} + +/* create via edge, using previous edge to fill in defaults. */ +static edge_t *CreateViaEdge(const pcb_box_t * area, pcb_cardinal_t group, + routebox_t * parent, edge_t * previous_edge, + conflict_t to_site_conflict, conflict_t through_site_conflict, pcb_rtree_t * targets) +{ + routebox_t *rb; + pcb_cheap_point_t costpoint; + pcb_cost_t d; + edge_t *ne; + pcb_cost_t scale[3]; + + scale[0] = 1; + scale[1] = AutoRouteParameters.LastConflictPenalty; + scale[2] = AutoRouteParameters.ConflictPenalty; + + assert(pcb_box_is_good(area)); + assert(AutoRouteParameters.with_conflicts || (to_site_conflict == NO_CONFLICT && through_site_conflict == NO_CONFLICT)); + rb = CreateExpansionArea(area, group, parent, pcb_true, previous_edge); + rb->flags.is_via = 1; + rb->came_from = PCB_ANY_DIR; +#if defined(ROUTE_DEBUG) && defined(DEBUG_SHOW_VIA_BOXES) + showroutebox(rb); +#endif /* ROUTE_DEBUG && DEBUG_SHOW_VIA_BOXES */ + /* for planes, choose a point near the target */ + if (previous_edge->flags.in_plane) { + routebox_t *target; + pcb_cheap_point_t pnt; + /* find a target near this via box */ + pnt.X = PCB_BOX_CENTER_X(*area); + pnt.Y = PCB_BOX_CENTER_Y(*area); + target = minpcb_cost_target_to_point(&pnt, rb->group, targets, previous_edge->minpcb_cost_target); + /* now find point near the target */ + pnt.X = PCB_BOX_CENTER_X(target->box); + pnt.Y = PCB_BOX_CENTER_Y(target->box); + costpoint = closest_point_in_routebox(&pnt, rb); + /* we moved from the previous cost point through the plane which is free travel */ + d = (scale[through_site_conflict] * pcb_cost_to_point(&costpoint, group, &costpoint, previous_edge->rb->group)); + ne = CreateEdge(rb, costpoint.X, costpoint.Y, previous_edge->pcb_cost_to_point + d, target, PCB_ANY_DIR, NULL); + ne->minpcb_cost_target = target; + } + else { + routebox_t *target; + target = previous_edge->minpcb_cost_target; + costpoint = closest_point_in_routebox(&previous_edge->cost_point, rb); + d = + (scale[to_site_conflict] * + pcb_cost_to_point_on_layer(&costpoint, &previous_edge->cost_point, + previous_edge->rb->group)) + + (scale[through_site_conflict] * pcb_cost_to_point(&costpoint, group, &costpoint, previous_edge->rb->group)); + /* if the target is just this via away, then this via is cheaper */ + if (target->group == group && point_in_shrunk_box(target, costpoint.X, costpoint.Y)) + d -= AutoRouteParameters.ViaCost / 2; + ne = + CreateEdge(rb, costpoint.X, costpoint.Y, previous_edge->pcb_cost_to_point + d, previous_edge->minpcb_cost_target, PCB_ANY_DIR, targets); + } + ne->flags.is_via = 1; + ne->flags.via_conflict_level = to_site_conflict; + assert(__edge_is_good(ne)); + return ne; +} + +/* create "interior" edge for routing with conflicts */ +/* Presently once we "jump inside" the conflicting object + * we consider it a routing highway to travel inside since + * it will become available if the conflict is elliminated. + * That is why we ignore the interior_edge argument. + */ +static edge_t *CreateEdgeWithConflicts(const pcb_box_t * interior_edge, + routebox_t * container, edge_t * previous_edge, + pcb_cost_t cost_penalty_to_box, pcb_rtree_t * targets) +{ + routebox_t *rb; + pcb_cheap_point_t costpoint; + pcb_cost_t d; + edge_t *ne; + assert(interior_edge && container && previous_edge && targets); + assert(!container->flags.homeless); + assert(AutoRouteParameters.with_conflicts); + assert(container->flags.touched == 0); + assert(previous_edge->rb->group == container->group); + /* use the caller's idea of what this box should be */ + rb = CreateExpansionArea(interior_edge, previous_edge->rb->group, previous_edge->rb, pcb_true, previous_edge); + path_conflicts(rb, container, pcb_true); /* crucial! */ + costpoint = pcb_closest_pcb_point_in_box(&previous_edge->cost_point, interior_edge); + d = pcb_cost_to_point_on_layer(&costpoint, &previous_edge->cost_point, previous_edge->rb->group); + d *= cost_penalty_to_box; + d += previous_edge->pcb_cost_to_point; + ne = CreateEdge(rb, costpoint.X, costpoint.Y, d, NULL, PCB_ANY_DIR, targets); + ne->flags.is_interior = 1; + assert(__edge_is_good(ne)); + return ne; +} + +static void KillEdge(void *edge) +{ + edge_t *e = (edge_t *) edge; + assert(e); + if (e->rb->flags.homeless) + RB_down_count(e->rb); + if (e->flags.via_search) + mtsFreeWork(&e->work); + free(e); +} + +static void DestroyEdge(edge_t ** e) +{ + assert(e && *e); + KillEdge(*e); + *e = NULL; +} + +/* cost function for an edge. */ +static pcb_cost_t edge_cost(const edge_t * e, const pcb_cost_t too_big) +{ + pcb_cost_t penalty = e->pcb_cost_to_point; + if (e->rb->flags.is_thermal || e->rb->type == PLANE) + return penalty; /* thermals are cheap */ + if (penalty > too_big) + return penalty; + + /* pcb_cost_to_routebox adds in our via correction, too. */ + return penalty + pcb_cost_to_routebox(&e->cost_point, e->rb->group, e->minpcb_cost_target); +} + +/* given an edge of a box, return a box containing exactly the points on that + * edge. Note that the return box is treated as closed; that is, the bottom and + * right "edges" consist of points (just barely) not in the (half-open) box. */ +static pcb_box_t edge_to_box(const routebox_t * rb, pcb_direction_t expand_dir) +{ + pcb_box_t b = shrink_routebox(rb); + /* narrow box down to just the appropriate edge */ + switch (expand_dir) { + case PCB_NORTH: + b.Y2 = b.Y1 + 1; + break; + case PCB_EAST: + b.X1 = b.X2 - 1; + break; + case PCB_SOUTH: + b.Y1 = b.Y2 - 1; + break; + case PCB_WEST: + b.X2 = b.X1 + 1; + break; + default: + assert(0); + } + /* done! */ + return b; +} + +struct broken_boxes { + pcb_box_t left, center, right; + pcb_bool is_valid_left, is_valid_center, is_valid_right; +}; + +static struct broken_boxes break_box_edge(const pcb_box_t * original, pcb_direction_t which_edge, routebox_t * breaker) +{ + pcb_box_t origbox, breakbox; + struct broken_boxes result; + + assert(original && breaker); + + origbox = *original; + breakbox = bloat_routebox(breaker); + PCB_BOX_ROTATE_TO_NORTH(origbox, which_edge); + PCB_BOX_ROTATE_TO_NORTH(breakbox, which_edge); + result.right.Y1 = result.center.Y1 = result.left.Y1 = origbox.Y1; + result.right.Y2 = result.center.Y2 = result.left.Y2 = origbox.Y1 + 1; + /* validity of breaker is not important because the boxes are marked invalid */ + /*assert (breakbox.X1 <= origbox.X2 && breakbox.X2 >= origbox.X1); */ + /* left edge piece */ + result.left.X1 = origbox.X1; + result.left.X2 = breakbox.X1; + /* center (ie blocked) edge piece */ + result.center.X1 = MAX(breakbox.X1, origbox.X1); + result.center.X2 = MIN(breakbox.X2, origbox.X2); + /* right edge piece */ + result.right.X1 = breakbox.X2; + result.right.X2 = origbox.X2; + /* validity: */ + result.is_valid_left = (result.left.X1 < result.left.X2); + result.is_valid_center = (result.center.X1 < result.center.X2); + result.is_valid_right = (result.right.X1 < result.right.X2); + /* rotate back */ + PCB_BOX_ROTATE_FROM_NORTH(result.left, which_edge); + PCB_BOX_ROTATE_FROM_NORTH(result.center, which_edge); + PCB_BOX_ROTATE_FROM_NORTH(result.right, which_edge); + /* done */ + return result; +} + +#ifndef NDEBUG +static int share_edge(const pcb_box_t * child, const pcb_box_t * parent) +{ + return + (child->X1 == parent->X2 || child->X2 == parent->X1 || + child->Y1 == parent->Y2 || child->Y2 == parent->Y1) && + ((parent->X1 <= child->X1 && child->X2 <= parent->X2) || (parent->Y1 <= child->Y1 && child->Y2 <= parent->Y2)); +} + +static int edge_intersect(const pcb_box_t * child, const pcb_box_t * parent) +{ + return (child->X1 <= parent->X2) && (child->X2 >= parent->X1) && (child->Y1 <= parent->Y2) && (child->Y2 >= parent->Y1); +} +#endif + +/* area is the expansion area, on layer group 'group'. 'parent' is the + * immediately preceding expansion area, for backtracing. 'lastarea' is + * the last expansion area created, we string these together in a loop + * so we can remove them all easily at the end. */ +static routebox_t *CreateExpansionArea(const pcb_box_t * area, pcb_cardinal_t group, + routebox_t * parent, pcb_bool relax_edge_requirements, edge_t * src_edge) +{ + routebox_t *rb = (routebox_t *) malloc(sizeof(*rb)); + memset((void *) rb, 0, sizeof(*rb)); + assert(area && parent); + init_const_box(rb, area->X1, area->Y1, area->X2, area->Y2, 0); + rb->group = group; + rb->type = EXPANSION_AREA; + /* should always share edge or overlap with parent */ +#ifndef NDEBUG + { + /* work around rounding errors: grow both boxes by 2 nm */ + pcb_box_t b1 = rb->sbox, b2 = parent->sbox; + b1.X1--;b1.Y1--;b1.X2++;b1.Y2++; + b2.X1--;b2.Y1--;b2.X2++;b2.Y2++; + assert(relax_edge_requirements ? pcb_box_intersect(&b1, &b2) + : share_edge(&rb->sbox, &parent->sbox)); + } +#endif + rb->parent.expansion_area = route_parent(parent); + rb->cost_point = pcb_closest_pcb_point_in_box(&rb->parent.expansion_area->cost_point, area); + rb->cost = + rb->parent.expansion_area->cost + + pcb_cost_to_point_on_layer(&rb->parent.expansion_area->cost_point, &rb->cost_point, rb->group); + assert(relax_edge_requirements ? edge_intersect(&rb->sbox, &parent->sbox) + : share_edge(&rb->sbox, &parent->sbox)); + if (rb->parent.expansion_area->flags.homeless) + RB_up_count(rb->parent.expansion_area); + rb->flags.homeless = 1; + rb->flags.nobloat = 1; + rb->style = AutoRouteParameters.style; + rb->conflicts_with = parent->conflicts_with; +/* we will never link an EXPANSION_AREA into the nets because they + * are *ONLY* used for path searching. No need to call InitLists () + */ + rb->came_from = src_edge->expand_dir; +#if defined(ROUTE_DEBUG) && defined(DEBUG_SHOW_EXPANSION_BOXES) + showroutebox(rb); +#endif /* ROUTE_DEBUG && DEBUG_SHOW_EXPANSION_BOXES */ + return rb; +} + +/*------ Expand ------*/ +struct E_result { + routebox_t *parent; + routebox_t *n, *e, *s, *w; + pcb_coord_t keep, bloat; + pcb_box_t inflated, orig; + int done; +}; + +/* test method for Expand() + * this routebox potentially is a blocker limiting expansion + * if this is so, we limit the inflate box so another exactly + * like it wouldn't be seen. We do this while keep the inflated + * box as large as possible. + */ +static pcb_r_dir_t __Expand_this_rect(const pcb_box_t * box, void *cl) +{ + struct E_result *res = (struct E_result *) cl; + routebox_t *rb = (routebox_t *) box; + pcb_box_t rbox; + pcb_coord_t dn, de, ds, dw, bloat; + + /* we don't see conflicts already encountered */ + if (rb->flags.touched) + return PCB_R_DIR_NOT_FOUND; + + /* The inflated box outer edges include its own + * track width plus its own clearance. + * + * To check for intersection, we need to expand + * anything with greater clearance by its excess + * clearance. + * + * If something has nobloat then we need to shrink + * the inflated box back and see if it still touches. + */ + + if (rb->flags.nobloat) { + rbox = rb->sbox; + bloat = res->bloat; + if (rbox.X2 <= res->inflated.X1 + bloat || + rbox.X1 >= res->inflated.X2 - bloat || rbox.Y1 >= res->inflated.Y2 - bloat || rbox.Y2 <= res->inflated.Y1 + bloat) + return PCB_R_DIR_NOT_FOUND; /* doesn't touch */ + } + else { + if (rb->style->Clearance > res->keep) + rbox = pcb_bloat_box(&rb->sbox, rb->style->Clearance - res->keep); + else + rbox = rb->sbox; + + if (rbox.X2 <= res->inflated.X1 || rbox.X1 >= res->inflated.X2 + || rbox.Y1 >= res->inflated.Y2 || rbox.Y2 <= res->inflated.Y1) + return PCB_R_DIR_NOT_FOUND; /* doesn't touch */ + bloat = 0; + } + + /* this is an intersecting box; it has to jump through a few more hoops */ + if (rb == res->parent || rb->parent.expansion_area == res->parent) + return PCB_R_DIR_NOT_FOUND; /* don't see what we came from */ + + /* if we are expanding a source edge, don't let other sources + * or their expansions stop us. + */ +#if 1 + if (res->parent->flags.source) + if (rb->flags.source || (rb->type == EXPANSION_AREA && rb->parent.expansion_area->flags.source)) + return PCB_R_DIR_NOT_FOUND; +#endif + + /* we ignore via expansion boxes because maybe its + * cheaper to get there without the via through + * the path we're exploring now. + */ + if (rb->flags.is_via && rb->type == EXPANSION_AREA) + return PCB_R_DIR_NOT_FOUND; + + if (rb->type == PLANE) { /* expanding inside a plane is not good */ + if (rbox.X1 < res->orig.X1 && rbox.X2 > res->orig.X2 && rbox.Y1 < res->orig.Y1 && rbox.Y2 > res->orig.Y2) { + res->inflated = pcb_bloat_box(&res->orig, res->bloat); + return PCB_R_DIR_FOUND_CONTINUE; + } + } + /* calculate the distances from original box to this blocker */ + dn = de = ds = dw = 0; + if (!(res->done & _NORTH) && rbox.Y1 <= res->orig.Y1 && rbox.Y2 > res->inflated.Y1) + dn = res->orig.Y1 - rbox.Y2; + if (!(res->done & _EAST) && rbox.X2 >= res->orig.X2 && rbox.X1 < res->inflated.X2) + de = rbox.X1 - res->orig.X2; + if (!(res->done & _SOUTH) && rbox.Y2 >= res->orig.Y2 && rbox.Y1 < res->inflated.Y2) + ds = rbox.Y1 - res->orig.Y2; + if (!(res->done & _WEST) && rbox.X1 <= res->orig.X1 && rbox.X2 > res->inflated.X1) + dw = res->orig.X1 - rbox.X2; + if (dn <= 0 && de <= 0 && ds <= 0 && dw <= 0) + return PCB_R_DIR_FOUND_CONTINUE; + /* now shrink the inflated box to the largest blocking direction */ + if (dn >= de && dn >= ds && dn >= dw) { + res->inflated.Y1 = rbox.Y2 - bloat; + res->n = rb; + } + else if (de >= ds && de >= dw) { + res->inflated.X2 = rbox.X1 + bloat; + res->e = rb; + } + else if (ds >= dw) { + res->inflated.Y2 = rbox.Y1 + bloat; + res->s = rb; + } + else { + res->inflated.X1 = rbox.X2 - bloat; + res->w = rb; + } + return PCB_R_DIR_FOUND_CONTINUE; +} + +static pcb_bool boink_box(routebox_t * rb, struct E_result *res, pcb_direction_t dir) +{ + pcb_coord_t bloat; + if (rb->style->Clearance > res->keep) + bloat = res->keep - rb->style->Clearance; + else + bloat = 0; + if (rb->flags.nobloat) + bloat = res->bloat; + switch (dir) { + case PCB_NORTH: + case PCB_SOUTH: + if (rb->sbox.X2 <= res->inflated.X1 + bloat || rb->sbox.X1 >= res->inflated.X2 - bloat) + return pcb_false; + return pcb_true; + case PCB_EAST: + case PCB_WEST: + if (rb->sbox.Y1 >= res->inflated.Y2 - bloat || rb->sbox.Y2 <= res->inflated.Y1 + bloat) + return pcb_false; + return pcb_true; + break; + default: + assert(0); + } + return pcb_false; +} + +/* main Expand routine. + * + * The expansion probe edge includes the clearance and half thickness + * as the search is performed in order to see everything relevant. + * The result is backed off by this amount before being returned. + * Targets (and other no-bloat routeboxes) go all the way to touching. + * This is accomplished by backing off the probe edge when checking + * for touch against such an object. Usually the expanding edge + * bumps into neighboring pins on the same device that require a + * clearance, preventing seeing a target immediately. Rather than await + * another expansion to actually touch the target, the edge breaker code + * looks past the clearance to see these targets even though they + * weren't actually touched in the expansion. + */ +struct E_result *Expand(pcb_rtree_t * rtree, edge_t * e, const pcb_box_t * box) +{ + static struct E_result ans; + int noshrink; /* bit field of which edges to not shrink */ + + ans.bloat = AutoRouteParameters.bloat; + ans.orig = *box; + ans.n = ans.e = ans.s = ans.w = NULL; + + /* the inflated box must be bloated in all directions that it might + * hit something in order to guarantee that we see object in the + * tree it might hit. The tree holds objects bloated by their own + * clearance so we are guaranteed to honor that. + */ + switch (e->expand_dir) { + case PCB_ANY_DIR: + ans.inflated.X1 = (e->rb->came_from == PCB_EAST ? ans.orig.X1 : 0); + ans.inflated.Y1 = (e->rb->came_from == PCB_SOUTH ? ans.orig.Y1 : 0); + ans.inflated.X2 = (e->rb->came_from == PCB_WEST ? ans.orig.X2 : PCB->MaxWidth); + ans.inflated.Y2 = (e->rb->came_from == PCB_NORTH ? ans.orig.Y2 : PCB->MaxHeight); + if (e->rb->came_from == PCB_NORTH) + ans.done = noshrink = _SOUTH; + else if (e->rb->came_from == PCB_EAST) + ans.done = noshrink = _WEST; + else if (e->rb->came_from == PCB_SOUTH) + ans.done = noshrink = _NORTH; + else if (e->rb->came_from == PCB_WEST) + ans.done = noshrink = _EAST; + else + ans.done = noshrink = 0; + break; + case PCB_NORTH: + ans.done = _SOUTH + _EAST + _WEST; + noshrink = _SOUTH; + ans.inflated.X1 = box->X1 - ans.bloat; + ans.inflated.X2 = box->X2 + ans.bloat; + ans.inflated.Y2 = box->Y2; + ans.inflated.Y1 = 0; /* far north */ + break; + case PCB_NE: + ans.done = _SOUTH + _WEST; + noshrink = 0; + ans.inflated.X1 = box->X1 - ans.bloat; + ans.inflated.X2 = PCB->MaxWidth; + ans.inflated.Y2 = box->Y2 + ans.bloat; + ans.inflated.Y1 = 0; + break; + case PCB_EAST: + ans.done = _NORTH + _SOUTH + _WEST; + noshrink = _WEST; + ans.inflated.Y1 = box->Y1 - ans.bloat; + ans.inflated.Y2 = box->Y2 + ans.bloat; + ans.inflated.X1 = box->X1; + ans.inflated.X2 = PCB->MaxWidth; + break; + case PCB_SE: + ans.done = _NORTH + _WEST; + noshrink = 0; + ans.inflated.X1 = box->X1 - ans.bloat; + ans.inflated.X2 = PCB->MaxWidth; + ans.inflated.Y2 = PCB->MaxHeight; + ans.inflated.Y1 = box->Y1 - ans.bloat; + break; + case PCB_SOUTH: + ans.done = _NORTH + _EAST + _WEST; + noshrink = _NORTH; + ans.inflated.X1 = box->X1 - ans.bloat; + ans.inflated.X2 = box->X2 + ans.bloat; + ans.inflated.Y1 = box->Y1; + ans.inflated.Y2 = PCB->MaxHeight; + break; + case PCB_SW: + ans.done = _NORTH + _EAST; + noshrink = 0; + ans.inflated.X1 = 0; + ans.inflated.X2 = box->X2 + ans.bloat; + ans.inflated.Y2 = PCB->MaxHeight; + ans.inflated.Y1 = box->Y1 - ans.bloat; + break; + case PCB_WEST: + ans.done = _NORTH + _SOUTH + _EAST; + noshrink = _EAST; + ans.inflated.Y1 = box->Y1 - ans.bloat; + ans.inflated.Y2 = box->Y2 + ans.bloat; + ans.inflated.X1 = 0; + ans.inflated.X2 = box->X2; + break; + case PCB_NW: + ans.done = _SOUTH + _EAST; + noshrink = 0; + ans.inflated.X1 = 0; + ans.inflated.X2 = box->X2 + ans.bloat; + ans.inflated.Y2 = box->Y2 + ans.bloat; + ans.inflated.Y1 = 0; + break; + default: + noshrink = ans.done = 0; + assert(0); + } + ans.keep = e->rb->style->Clearance; + ans.parent = nonhomeless_parent(e->rb); + pcb_r_search(rtree, &ans.inflated, NULL, __Expand_this_rect, &ans, NULL); +/* because the overlaping boxes are found in random order, some blockers + * may have limited edges prematurely, so we check if the blockers realy + * are blocking, and make another try if not + */ + if (ans.n && !boink_box(ans.n, &ans, PCB_NORTH)) + ans.inflated.Y1 = 0; + else + ans.done |= _NORTH; + if (ans.e && !boink_box(ans.e, &ans, PCB_EAST)) + ans.inflated.X2 = PCB->MaxWidth; + else + ans.done |= _EAST; + if (ans.s && !boink_box(ans.s, &ans, PCB_SOUTH)) + ans.inflated.Y2 = PCB->MaxHeight; + else + ans.done |= _SOUTH; + if (ans.w && !boink_box(ans.w, &ans, PCB_WEST)) + ans.inflated.X1 = 0; + else + ans.done |= _WEST; + if (ans.done != _NORTH + _EAST + _SOUTH + _WEST) { + pcb_r_search(rtree, &ans.inflated, NULL, __Expand_this_rect, &ans, NULL); + } + if ((noshrink & _NORTH) == 0) + ans.inflated.Y1 += ans.bloat; + if ((noshrink & _EAST) == 0) + ans.inflated.X2 -= ans.bloat; + if ((noshrink & _SOUTH) == 0) + ans.inflated.Y2 -= ans.bloat; + if ((noshrink & _WEST) == 0) + ans.inflated.X1 += ans.bloat; + return &ans; +} + +/* blocker_to_heap puts the blockers into a heap so they + * can be retrieved in clockwise order. If a blocker + * is also a target, it gets put into the vector too. + * It returns 1 for any fixed blocker that is not part + * of this net and zero otherwise. + */ +static int blocker_to_heap(pcb_heap_t * heap, routebox_t * rb, pcb_box_t * box, pcb_direction_t dir) +{ + pcb_box_t b = rb->sbox; + if (rb->style->Clearance > AutoRouteParameters.style->Clearance) + b = pcb_bloat_box(&b, rb->style->Clearance - AutoRouteParameters.style->Clearance); + b = pcb_clip_box(&b, box); + assert(pcb_box_is_good(&b)); + /* we want to look at the blockers clockwise around the box */ + switch (dir) { + /* we need to use the other coordinate fraction to resolve + * ties since we want the shorter of the furthest + * first. + */ + case PCB_NORTH: + pcb_heap_insert(heap, b.X1 - b.X1 / (b.X2 + 1.0), rb); + break; + case PCB_EAST: + pcb_heap_insert(heap, b.Y1 - b.Y1 / (b.Y2 + 1.0), rb); + break; + case PCB_SOUTH: + pcb_heap_insert(heap, -(b.X2 + b.X1 / (b.X2 + 1.0)), rb); + break; + case PCB_WEST: + pcb_heap_insert(heap, -(b.Y2 + b.Y1 / (b.Y2 + 1.0)), rb); + break; + default: + assert(0); + } + if (rb->flags.fixed && !rb->flags.target && !rb->flags.source) + return 1; + return 0; +} + +/* this creates an EXPANSION_AREA to bridge small gaps or, + * (more commonly) create a supper-thin box to provide a + * home for an expansion edge. + */ +static routebox_t *CreateBridge(const pcb_box_t * area, routebox_t * parent, pcb_direction_t dir) +{ + routebox_t *rb = (routebox_t *) malloc(sizeof(*rb)); + memset((void *) rb, 0, sizeof(*rb)); + assert(area && parent); + init_const_box(rb, area->X1, area->Y1, area->X2, area->Y2, 0); + rb->group = parent->group; + rb->type = EXPANSION_AREA; + rb->came_from = dir; + rb->cost_point = pcb_closest_pcb_point_in_box(&parent->cost_point, area); + rb->cost = parent->cost + pcb_cost_to_point_on_layer(&parent->cost_point, &rb->cost_point, rb->group); + rb->parent.expansion_area = route_parent(parent); + if (rb->parent.expansion_area->flags.homeless) + RB_up_count(rb->parent.expansion_area); + rb->flags.homeless = 1; + rb->flags.nobloat = 1; + rb->style = parent->style; + rb->conflicts_with = parent->conflicts_with; +#if defined(ROUTE_DEBUG) && defined(DEBUG_SHOW_EDGES) + showroutebox(rb); +#endif + return rb; +} + +/* moveable_edge prepares the new search edges based on the + * starting box, direction and blocker if any. + */ +void +moveable_edge(vector_t * result, const pcb_box_t * box, pcb_direction_t dir, + routebox_t * rb, + routebox_t * blocker, edge_t * e, pcb_rtree_t * targets, + routeone_state_t *s, pcb_rtree_t * tree, vector_t * area_vec) +{ + pcb_box_t b; + assert(pcb_box_is_good(box)); + b = *box; + /* for the cardinal directions, move the box to overlap the + * the parent by 1 unit. Corner expansions overlap more + * and their starting boxes are pre-prepared. + * Check if anything is headed off the board edges + */ + switch (dir) { + default: + break; + case PCB_NORTH: + b.Y2 = b.Y1; + b.Y1--; + if (b.Y1 <= AutoRouteParameters.bloat) + return; /* off board edge */ + break; + case PCB_EAST: + b.X1 = b.X2; + b.X2++; + if (b.X2 >= PCB->MaxWidth - AutoRouteParameters.bloat) + return; /* off board edge */ + break; + case PCB_SOUTH: + b.Y1 = b.Y2; + b.Y2++; + if (b.Y2 >= PCB->MaxHeight - AutoRouteParameters.bloat) + return; /* off board edge */ + break; + case PCB_WEST: + b.X2 = b.X1; + b.X1--; + if (b.X1 <= AutoRouteParameters.bloat) + return; /* off board edge */ + break; + case PCB_NE: + if (b.Y1 <= AutoRouteParameters.bloat + 1 && b.X2 >= PCB->MaxWidth - AutoRouteParameters.bloat - 1) + return; /* off board edge */ + if (b.Y1 <= AutoRouteParameters.bloat + 1) + dir = PCB_EAST; /* north off board edge */ + if (b.X2 >= PCB->MaxWidth - AutoRouteParameters.bloat - 1) + dir = PCB_NORTH; /* east off board edge */ + break; + case PCB_SE: + if (b.Y2 >= PCB->MaxHeight - AutoRouteParameters.bloat - 1 && b.X2 >= PCB->MaxWidth - AutoRouteParameters.bloat - 1) + return; /* off board edge */ + if (b.Y2 >= PCB->MaxHeight - AutoRouteParameters.bloat - 1) + dir = PCB_EAST; /* south off board edge */ + if (b.X2 >= PCB->MaxWidth - AutoRouteParameters.bloat - 1) + dir = PCB_SOUTH; /* east off board edge */ + break; + case PCB_SW: + if (b.Y2 >= PCB->MaxHeight - AutoRouteParameters.bloat - 1 && b.X1 <= AutoRouteParameters.bloat + 1) + return; /* off board edge */ + if (b.Y2 >= PCB->MaxHeight - AutoRouteParameters.bloat - 1) + dir = PCB_WEST; /* south off board edge */ + if (b.X1 <= AutoRouteParameters.bloat + 1) + dir = PCB_SOUTH; /* west off board edge */ + break; + case PCB_NW: + if (b.Y1 <= AutoRouteParameters.bloat + 1 && b.X1 <= AutoRouteParameters.bloat + 1) + return; /* off board edge */ + if (b.Y1 <= AutoRouteParameters.bloat + 1) + dir = PCB_WEST; /* north off board edge */ + if (b.X1 <= AutoRouteParameters.bloat + 1) + dir = PCB_NORTH; /* west off board edge */ + break; + } + + if (!blocker) { + edge_t *ne; + routebox_t *nrb = CreateBridge(&b, rb, dir); + /* move the cost point in corner expansions + * these boxes are bigger, so move close to the target + */ + if (dir == PCB_NE || dir == PCB_SE || dir == PCB_SW || dir == PCB_NW) { + pcb_cheap_point_t p; + p = pcb_closest_pcb_point_in_box(&nrb->cost_point, &e->minpcb_cost_target->sbox); + p = pcb_closest_pcb_point_in_box(&p, &b); + nrb->cost += pcb_cost_to_point_on_layer(&p, &nrb->cost_point, nrb->group); + nrb->cost_point = p; + } + ne = CreateEdge(nrb, nrb->cost_point.X, nrb->cost_point.Y, nrb->cost, NULL, dir, targets); + vector_append(result, ne); + } + else if (AutoRouteParameters.with_conflicts && !blocker->flags.target + && !blocker->flags.fixed && !blocker->flags.touched && !blocker->flags.source && blocker->type != EXPANSION_AREA) { + edge_t *ne; + routebox_t *nrb; + /* make a bridge to the edge of the blocker + * in all directions from there + */ + switch (dir) { + case PCB_NORTH: + b.Y1 = blocker->sbox.Y2 - 1; + break; + case PCB_EAST: + b.X2 = blocker->sbox.X1 + 1; + break; + case PCB_SOUTH: + b.Y2 = blocker->sbox.Y1 + 1; + break; + case PCB_WEST: + b.X1 = blocker->sbox.X2 - 1; + break; + default: + assert(0); + } + if (!pcb_box_is_good(&b)) + return; /* how did this happen ? */ + nrb = CreateBridge(&b, rb, dir); + pcb_r_insert_entry(tree, &nrb->box); + vector_append(area_vec, nrb); + nrb->flags.homeless = 0; /* not homeless any more */ + /* mark this one as conflicted */ + path_conflicts(nrb, blocker, pcb_true); + /* and make an expansion edge */ + nrb->cost_point = pcb_closest_pcb_point_in_box(&nrb->cost_point, &blocker->sbox); + nrb->cost += + pcb_cost_to_point_on_layer(&nrb->parent.expansion_area->cost_point, &nrb->cost_point, nrb->group) * CONFLICT_PENALTY(blocker); + + ne = CreateEdge(nrb, nrb->cost_point.X, nrb->cost_point.Y, nrb->cost, NULL, PCB_ANY_DIR, targets); + ne->flags.is_interior = 1; + vector_append(result, ne); + } +#if 1 + else if (blocker->type == EXPANSION_AREA) { + if (blocker->cost < rb->cost || blocker->cost <= rb->cost + + pcb_cost_to_point_on_layer(&blocker->cost_point, &rb->cost_point, rb->group)) + return; + if (blocker->conflicts_with || rb->conflicts_with) + return; + /* does the blocker overlap this routebox ?? */ + /* does this re-parenting operation leave a memory leak? */ + if (blocker->parent.expansion_area->flags.homeless) + RB_down_count(blocker->parent.expansion_area); + blocker->parent.expansion_area = rb; + return; + } +#endif + else if (blocker->flags.target) { + routebox_t *nrb; + edge_t *ne; + b = pcb_bloat_box(&b, 1); + if (!pcb_box_intersect(&b, &blocker->sbox)) { + /* if the expansion edge stopped before touching, expand the bridge */ + switch (dir) { + case PCB_NORTH: + b.Y1 -= AutoRouteParameters.bloat + 1; + break; + case PCB_EAST: + b.X2 += AutoRouteParameters.bloat + 1; + break; + case PCB_SOUTH: + b.Y2 += AutoRouteParameters.bloat + 1; + break; + case PCB_WEST: + b.X1 -= AutoRouteParameters.bloat + 1; + break; + default: + assert(0); + } + } + assert(pcb_box_intersect(&b, &blocker->sbox)); + b = pcb_shrink_box(&b, 1); + nrb = CreateBridge(&b, rb, dir); + pcb_r_insert_entry(tree, &nrb->box); + vector_append(area_vec, nrb); + nrb->flags.homeless = 0; /* not homeless any more */ + ne = CreateEdge(nrb, nrb->cost_point.X, nrb->cost_point.Y, nrb->cost, blocker, dir, NULL); + best_path_candidate(s, ne, blocker); + DestroyEdge(&ne); + } +} + +struct break_info { + pcb_heap_t *heap; + routebox_t *parent; + pcb_box_t box; + pcb_direction_t dir; + pcb_bool ignore_source; +}; + +static pcb_r_dir_t __GatherBlockers(const pcb_box_t * box, void *cl) +{ + routebox_t *rb = (routebox_t *) box; + struct break_info *bi = (struct break_info *) cl; + pcb_box_t b; + + if (bi->parent == rb || rb->flags.touched || bi->parent->parent.expansion_area == rb) + return PCB_R_DIR_NOT_FOUND; + if (rb->flags.source && bi->ignore_source) + return PCB_R_DIR_NOT_FOUND; + b = rb->sbox; + if (rb->style->Clearance > AutoRouteParameters.style->Clearance) + b = pcb_bloat_box(&b, rb->style->Clearance - AutoRouteParameters.style->Clearance); + if (b.X2 <= bi->box.X1 || b.X1 >= bi->box.X2 || b.Y1 >= bi->box.Y2 || b.Y2 <= bi->box.Y1) + return PCB_R_DIR_NOT_FOUND; + if (blocker_to_heap(bi->heap, rb, &bi->box, bi->dir)) + return PCB_R_DIR_FOUND_CONTINUE; + return PCB_R_DIR_NOT_FOUND; +} + +/* shrink the box to the last limit for the previous direction, + * i.e. if dir is SOUTH, then this means fixing up an EAST leftover + * edge, which would be the southern most edge for that example. + */ +static inline pcb_box_t previous_edge(pcb_coord_t last, pcb_direction_t i, const pcb_box_t * b) +{ + pcb_box_t db = *b; + switch (i) { + case PCB_EAST: + db.X1 = last; + break; + case PCB_SOUTH: + db.Y1 = last; + break; + case PCB_WEST: + db.X2 = last; + break; + default: + pcb_message(PCB_MSG_ERROR, "previous edge bogus direction!"); + assert(0); + } + return db; +} + +/* Break all the edges of the box that need breaking, handling + * targets as they are found, and putting any moveable edges + * in the return vector. + */ +vector_t *BreakManyEdges(routeone_state_t * s, pcb_rtree_t * targets, pcb_rtree_t * tree, + vector_t * area_vec, struct E_result * ans, routebox_t * rb, edge_t * e) +{ + struct break_info bi; + vector_t *edges; + pcb_heap_t *heap[4]; + pcb_coord_t first, last; + pcb_coord_t bloat; + pcb_direction_t dir; + routebox_t fake; + + edges = vector_create(); + bi.ignore_source = rb->parent.expansion_area->flags.source; + bi.parent = rb; + /* we add 2 to the bloat. + * 1 will get us to the actual blocker that Expand() hit + * but 1 more is needed because the new expansion edges + * move out by 1 so they don't overlap their parents + * this extra expansion could "trap" the edge if + * there is a blocker 2 units from the original rb, + * it is 1 unit from the new expansion edge which + * would prevent expansion. So we want to break the + * edge on it now to avoid the trap. + */ + + bloat = AutoRouteParameters.bloat + 2; + /* for corner expansion, we need to have a fake blocker + * to prevent expansion back where we came from since + * we still need to break portions of all 4 edges + */ + if (e->expand_dir == PCB_NE || e->expand_dir == PCB_SE || e->expand_dir == PCB_SW || e->expand_dir == PCB_NW) { + pcb_box_t *fb = (pcb_box_t *) & fake.sbox; + memset(&fake, 0, sizeof(fake)); + *fb = e->rb->sbox; + fake.flags.fixed = 1; /* this stops expansion there */ + fake.type = LINE; + fake.style = AutoRouteParameters.style; +#ifndef NDEBUG + /* the routbox_is_good checker wants a lot more! */ + fake.flags.inited = 1; + fb = (pcb_box_t *) & fake.box; + *fb = e->rb->sbox; + fake.same_net.next = fake.same_net.prev = &fake; + fake.same_subnet.next = fake.same_subnet.prev = &fake; + fake.original_subnet.next = fake.original_subnet.prev = &fake; + fake.different_net.next = fake.different_net.prev = &fake; +#endif + } + /* gather all of the blockers in heaps so they can be accessed + * in clockwise order, which allows finding corners that can + * be expanded. + */ + for (dir = PCB_NORTH; dir <= PCB_WEST; dir = directionIncrement(dir)) { + int tmp; + /* don't break the edge we came from */ + if (e->expand_dir != ((dir + 2) % 4)) { + heap[dir] = pcb_heap_create(); + bi.box = pcb_bloat_box(&rb->sbox, bloat); + bi.heap = heap[dir]; + bi.dir = dir; + /* convert to edge */ + switch (dir) { + case PCB_NORTH: + bi.box.Y2 = bi.box.Y1 + bloat + 1; + /* for corner expansion, block the start edges and + * limit the blocker search to only the new edge segment + */ + if (e->expand_dir == PCB_SE || e->expand_dir == PCB_SW) + blocker_to_heap(heap[dir], &fake, &bi.box, dir); + if (e->expand_dir == PCB_SE) + bi.box.X1 = e->rb->sbox.X2; + if (e->expand_dir == PCB_SW) + bi.box.X2 = e->rb->sbox.X1; + pcb_r_search(tree, &bi.box, NULL, __GatherBlockers, &bi, &tmp); + rb->n = tmp; + break; + case PCB_EAST: + bi.box.X1 = bi.box.X2 - bloat - 1; + /* corner, same as above */ + if (e->expand_dir == PCB_SW || e->expand_dir == PCB_NW) + blocker_to_heap(heap[dir], &fake, &bi.box, dir); + if (e->expand_dir == PCB_SW) + bi.box.Y1 = e->rb->sbox.Y2; + if (e->expand_dir == PCB_NW) + bi.box.Y2 = e->rb->sbox.Y1; + pcb_r_search(tree, &bi.box, NULL, __GatherBlockers, &bi, &tmp); + rb->e = tmp; + break; + case PCB_SOUTH: + bi.box.Y1 = bi.box.Y2 - bloat - 1; + /* corner, same as above */ + if (e->expand_dir == PCB_NE || e->expand_dir == PCB_NW) + blocker_to_heap(heap[dir], &fake, &bi.box, dir); + if (e->expand_dir == PCB_NE) + bi.box.X1 = e->rb->sbox.X2; + if (e->expand_dir == PCB_NW) + bi.box.X2 = e->rb->sbox.X1; + pcb_r_search(tree, &bi.box, NULL, __GatherBlockers, &bi, &tmp); + rb->s = tmp; + break; + case PCB_WEST: + bi.box.X2 = bi.box.X1 + bloat + 1; + /* corner, same as above */ + if (e->expand_dir == PCB_NE || e->expand_dir == PCB_SE) + blocker_to_heap(heap[dir], &fake, &bi.box, dir); + if (e->expand_dir == PCB_SE) + bi.box.Y1 = e->rb->sbox.Y2; + if (e->expand_dir == PCB_NE) + bi.box.Y2 = e->rb->sbox.Y1; + pcb_r_search(tree, &bi.box, NULL, __GatherBlockers, &bi, &tmp); + rb->w = tmp; + break; + default: + assert(0); + } + } + else + heap[dir] = NULL; + } +#if 1 + rb->cost += (rb->n + rb->e + rb->s + rb->w) * AutoRouteParameters.CongestionPenalty / box_area(rb->sbox); +#endif +/* now handle the blockers: + * Go around the expansion area clockwise (North->East->South->West) + * pulling blockers from the heap (which makes them come out in the right + * order). Break the edges on the blocker and make the segments and corners + * moveable as possible. + */ + first = last = -1; + for (dir = PCB_NORTH; dir <= PCB_WEST; dir = directionIncrement(dir)) { + if (heap[dir] && !pcb_heap_is_empty(heap[dir])) { + /* pull the very first one out of the heap outside of the + * heap loop because it is special; it can be part of a corner + */ + routebox_t *blk = (routebox_t *) pcb_heap_remove_smallest(heap[dir]); + pcb_box_t b = rb->sbox; + struct broken_boxes broke = break_box_edge(&b, dir, blk); + if (broke.is_valid_left) { + /* if last > 0, then the previous edge had a segment + * joining this one, so it forms a valid corner expansion + */ + if (last > 0) { + /* make a corner expansion */ + pcb_box_t db = b; + switch (dir) { + case PCB_EAST: + /* possible NE expansion */ + db.X1 = last; + db.Y2 = MIN(db.Y2, broke.left.Y2); + break; + case PCB_SOUTH: + /* possible SE expansion */ + db.Y1 = last; + db.X1 = MAX(db.X1, broke.left.X1); + break; + case PCB_WEST: + /* possible SW expansion */ + db.X2 = last; + db.Y1 = MAX(db.Y1, broke.left.Y1); + break; + default: + assert(0); + break; + } + moveable_edge(edges, &db, (pcb_direction_t) (dir + 3), rb, NULL, e, targets, s, NULL, NULL); + } + else if (dir == PCB_NORTH) { /* north is start, so nothing "before" it */ + /* save for a possible corner once we've + * finished circling the box + */ + first = MAX(b.X1, broke.left.X2); + } + else { + /* this is just a boring straight expansion + * since the orthogonal segment was blocked + */ + moveable_edge(edges, &broke.left, dir, rb, NULL, e, targets, s, NULL, NULL); + } + } /* broke.is_valid_left */ + else if (last > 0) { + /* if the last one didn't become a corner, + * we still want to expand it straight out + * in the direction of the previous edge, + * which it belongs to. + */ + pcb_box_t db = previous_edge(last, dir, &rb->sbox); + moveable_edge(edges, &db, (pcb_direction_t) (dir - 1), rb, NULL, e, targets, s, NULL, NULL); + } + if (broke.is_valid_center && !blk->flags.source) + moveable_edge(edges, &broke.center, dir, rb, blk, e, targets, s, tree, area_vec); + /* this is the heap extraction loop. We break out + * if there's nothing left in the heap, but if we * are blocked all the way to the far edge, we can + * just leave stuff in the heap when it is destroyed + */ + while (broke.is_valid_right) { + /* move the box edge to the next potential free point */ + switch (dir) { + case PCB_NORTH: + last = b.X1 = MAX(broke.right.X1, b.X1); + break; + case PCB_EAST: + last = b.Y1 = MAX(broke.right.Y1, b.Y1); + break; + case PCB_SOUTH: + last = b.X2 = MIN(broke.right.X2, b.X2); + break; + case PCB_WEST: + last = b.Y2 = MIN(broke.right.Y2, b.Y2); + break; + default: + assert(0); + } + if (pcb_heap_is_empty(heap[dir])) + break; + blk = (routebox_t *) pcb_heap_remove_smallest(heap[dir]); + broke = break_box_edge(&b, dir, blk); + if (broke.is_valid_left) + moveable_edge(edges, &broke.left, dir, rb, NULL, e, targets, s, NULL, NULL); + if (broke.is_valid_center && !blk->flags.source) + moveable_edge(edges, &broke.center, dir, rb, blk, e, targets, s, tree, area_vec); + } + if (!broke.is_valid_right) + last = -1; + } + else { /* if (heap[dir]) */ + + /* nothing touched this edge! Expand the whole edge unless + * (1) it hit the board edge or (2) was the source of our expansion + * + * for this case (of hitting nothing) we give up trying for corner + * expansions because it is likely that they're not possible anyway + */ + if ((e->expand_dir == PCB_ANY_DIR ? e->rb->came_from : e->expand_dir) != ((dir + 2) % 4)) { + /* ok, we are not going back on ourselves, and the whole edge seems free */ + moveable_edge(edges, &rb->sbox, dir, rb, NULL, e, targets, s, NULL, NULL); + } + + if (last > 0) { + /* expand the leftover from the prior direction */ + pcb_box_t db = previous_edge(last, dir, &rb->sbox); + moveable_edge(edges, &db, (pcb_direction_t) (dir - 1), rb, NULL, e, targets, s, NULL, NULL); + } + last = -1; + } + } /* for loop */ + /* finally, check for the NW corner now that we've come full circle */ + if (first > 0 && last > 0) { + pcb_box_t db = rb->sbox; + db.X2 = first; + db.Y2 = last; + moveable_edge(edges, &db, PCB_NW, rb, NULL, e, targets, s, NULL, NULL); + } + else { + if (first > 0) { + pcb_box_t db = rb->sbox; + db.X2 = first; + moveable_edge(edges, &db, PCB_NORTH, rb, NULL, e, targets, s, NULL, NULL); + } + else if (last > 0) { + pcb_box_t db = rb->sbox; + db.Y2 = last; + moveable_edge(edges, &db, PCB_WEST, rb, NULL, e, targets, s, NULL, NULL); + } + } + /* done with all expansion edges of this box */ + for (dir = PCB_NORTH; dir <= PCB_WEST; dir = directionIncrement(dir)) { + if (heap[dir]) + pcb_heap_destroy(&heap[dir]); + } + return edges; +} + +static routebox_t *rb_source(routebox_t * rb) +{ + while (rb && !rb->flags.source) { + assert(rb->type == EXPANSION_AREA); + rb = rb->parent.expansion_area; + } + assert(rb); + return rb; +} + +/* ------------ */ + +struct foib_info { + const pcb_box_t *box; + routebox_t *intersect; + jmp_buf env; +}; + +static pcb_r_dir_t foib_rect_in_reg(const pcb_box_t * box, void *cl) +{ + struct foib_info *foib = (struct foib_info *) cl; + pcb_box_t rbox; + routebox_t *rb = (routebox_t *) box; + if (rb->flags.touched) + return PCB_R_DIR_NOT_FOUND; +/* if (rb->type == EXPANSION_AREA && !rb->flags.is_via)*/ + /* return PCB_R_DIR_NOT_FOUND; */ + rbox = bloat_routebox(rb); + if (!pcb_box_intersect(&rbox, foib->box)) + return PCB_R_DIR_NOT_FOUND; + /* this is an intersector! */ + foib->intersect = (routebox_t *) box; + longjmp(foib->env, 1); /* skip to the end! */ + return PCB_R_DIR_FOUND_CONTINUE; +} + +static routebox_t *FindOneInBox(pcb_rtree_t * rtree, routebox_t * rb) +{ + struct foib_info foib; + pcb_box_t r; + + r = rb->sbox; + foib.box = &r; + foib.intersect = NULL; + + if (setjmp(foib.env) == 0) + pcb_r_search(rtree, &r, NULL, foib_rect_in_reg, &foib, NULL); + return foib.intersect; +} + +struct therm_info { + routebox_t *plane; + pcb_box_t query; + jmp_buf env; +}; +static pcb_r_dir_t ftherm_rect_in_reg(const pcb_box_t * box, void *cl) +{ + routebox_t *rbox = (routebox_t *) box; + struct therm_info *ti = (struct therm_info *) cl; + pcb_box_t sq, sb; + + if (rbox->type != TERM) + return PCB_R_DIR_NOT_FOUND; + if (rbox->group != ti->plane->group) + return PCB_R_DIR_NOT_FOUND; + + sb = shrink_routebox(rbox); + switch (rbox->type) { + case TERM: + case VIA_SHADOW: + sq = pcb_shrink_box(&ti->query, rbox->style->Diameter); + if (!pcb_box_intersect(&sb, &sq)) + return PCB_R_DIR_NOT_FOUND; + sb.X1 = PCB_BOX_CENTER_X(sb); + sb.Y1 = PCB_BOX_CENTER_Y(sb); + break; + default: + assert(0); + } + ti->plane = rbox; + longjmp(ti->env, 1); + return PCB_R_DIR_FOUND_CONTINUE; +} + +/* check for a pin or via target that a polygon can just use a thermal to connect to */ +routebox_t *FindThermable(pcb_rtree_t * rtree, routebox_t * rb) +{ + struct therm_info info; + + info.plane = rb; + info.query = shrink_routebox(rb); + + if (setjmp(info.env) == 0) { + pcb_r_search(rtree, &info.query, NULL, ftherm_rect_in_reg, &info, NULL); + return NULL; + } + return info.plane; +} + +/*-------------------------------------------------------------------- + * Route-tracing code: once we've got a path of expansion boxes, trace + * a line through them to actually create the connection. + */ +static void RD_DrawThermal(routedata_t * rd, pcb_coord_t X, pcb_coord_t Y, pcb_cardinal_t group, pcb_cardinal_t layer, routebox_t * subnet, pcb_bool is_bad) +{ + routebox_t *rb; + rb = (routebox_t *) malloc(sizeof(*rb)); + memset((void *) rb, 0, sizeof(*rb)); + init_const_box(rb, X, Y, X + 1, Y + 1, 0); + rb->group = group; + rb->layer = layer; + rb->flags.fixed = 0; + rb->flags.is_bad = is_bad; + rb->flags.is_odd = AutoRouteParameters.is_odd; + rb->flags.circular = 0; + rb->style = AutoRouteParameters.style; + rb->type = THERMAL; + InitLists(rb); + MergeNets(rb, subnet, NET); + MergeNets(rb, subnet, SUBNET); + /* add it to the r-tree, this may be the whole route! */ + pcb_r_insert_entry(rd->layergrouptree[rb->group], &rb->box); + rb->flags.homeless = 0; +} + +static void RD_DrawVia(routedata_t * rd, pcb_coord_t X, pcb_coord_t Y, pcb_coord_t radius, routebox_t * subnet, pcb_bool is_bad) +{ + routebox_t *rb, *first_via = NULL; + int i; + int ka = AutoRouteParameters.style->Clearance; + pcb_pstk_t *live_via = NULL; + + if (conf_core.editor.live_routing) { +TODO("padstack: when style contains proto, remove this") + live_via = pcb_pstk_new_compat_via(PCB->Data, -1, X, Y, AutoRouteParameters.style->Hole, radius * 2, 2 * AutoRouteParameters.style->Clearance, 0, PCB_PSTK_COMPAT_ROUND, 1); + if (live_via != NULL) + pcb_pstk_invalidate_draw(live_via); + } + + /* a via cuts through every layer group */ + for (i = 0; i < pcb_max_group(PCB); i++) { + if (!is_layer_group_active[i]) + continue; + rb = (routebox_t *) malloc(sizeof(*rb)); + memset((void *) rb, 0, sizeof(*rb)); + init_const_box(rb, + /*X1 */ X - radius, /*Y1 */ Y - radius, + /*X2 */ X + radius + 1, /*Y2 */ Y + radius + 1, ka); + rb->group = i; + rb->flags.fixed = 0; /* indicates that not on PCB yet */ + rb->flags.is_odd = AutoRouteParameters.is_odd; + rb->flags.is_bad = is_bad; + rb->came_from = PCB_ANY_DIR; + rb->flags.circular = pcb_true; + rb->style = AutoRouteParameters.style; + rb->pass = AutoRouteParameters.pass; + if (first_via == NULL) { + rb->type = VIA; + rb->parent.via = NULL; /* indicates that not on PCB yet */ + first_via = rb; + /* only add the first via to mtspace, not the shadows too */ + mtspace_add(rd->mtspace, &rb->box, rb->flags.is_odd ? ODD : EVEN, rb->style->Clearance); + } + else { + rb->type = VIA_SHADOW; + rb->parent.via_shadow = first_via; + } + InitLists(rb); + /* add these to proper subnet. */ + MergeNets(rb, subnet, NET); + MergeNets(rb, subnet, SUBNET); + assert(__routepcb_box_is_good(rb)); + /* and add it to the r-tree! */ + pcb_r_insert_entry(rd->layergrouptree[rb->group], &rb->box); + rb->flags.homeless = 0; /* not homeless anymore */ + rb->livedraw_obj.via = live_via; + } +} + +static void +RD_DrawLine(routedata_t * rd, + pcb_coord_t X1, pcb_coord_t Y1, pcb_coord_t X2, + pcb_coord_t Y2, pcb_coord_t halfthick, pcb_cardinal_t group, routebox_t * subnet, pcb_bool is_bad, pcb_bool is_45) +{ + /* we hold the line in a queue to concatenate segments that + * ajoin one another. That reduces the number of things in + * the trees and allows conflict boxes to be larger, both of + * which are really useful. + */ + static pcb_coord_t qX1 = -1, qY1, qX2, qY2; + static pcb_coord_t qhthick; + static pcb_cardinal_t qgroup; + static pcb_bool qis_45, qis_bad; + static routebox_t *qsn; + + routebox_t *rb; + pcb_coord_t ka = AutoRouteParameters.style->Clearance; + + /* don't draw zero-length segments. */ + if (X1 == X2 && Y1 == Y2) + return; + if (qX1 == -1) { /* first ever */ + qX1 = X1; + qY1 = Y1; + qX2 = X2; + qY2 = Y2; + qhthick = halfthick; + qgroup = group; + qis_45 = is_45; + qis_bad = is_bad; + qsn = subnet; + return; + } + /* Check if the lines concatenat. We only check the + * normal expected nextpoint=lastpoint condition + */ + if (X1 == qX2 && Y1 == qY2 && qhthick == halfthick && qgroup == group) { + if (qX1 == qX2 && X1 == X2) { /* everybody on the same X here */ + qY2 = Y2; + return; + } + if (qY1 == qY2 && Y1 == Y2) { /* same Y all around */ + qX2 = X2; + return; + } + } + /* dump the queue, no match here */ + if (qX1 == -1) + return; /* but not this! */ + rb = (routebox_t *) malloc(sizeof(*rb)); + memset((void *) rb, 0, sizeof(*rb)); + assert(is_45 ? (PCB_ABS(qX2 - qX1) == PCB_ABS(qY2 - qY1)) /* line must be 45-degrees */ + : (qX1 == qX2 || qY1 == qY2) /* line must be ortho */ ); + init_const_box(rb, + /*X1 */ MIN(qX1, qX2) - qhthick, + /*Y1 */ MIN(qY1, qY2) - qhthick, + /*X2 */ MAX(qX1, qX2) + qhthick + 1, + /*Y2 */ MAX(qY1, qY2) + qhthick + 1, ka); + rb->group = qgroup; + rb->type = LINE; + rb->line.x1 = qX1; + rb->line.x2 = qX2; + rb->line.y1 = qY1; + rb->line.y2 = qY2; + rb->parent.line = NULL; /* indicates that not on PCB yet */ + rb->flags.fixed = 0; /* indicates that not on PCB yet */ + rb->flags.is_odd = AutoRouteParameters.is_odd; + rb->flags.is_bad = qis_bad; + rb->came_from = PCB_ANY_DIR; + rb->flags.homeless = 0; /* we're putting this in the tree */ + rb->flags.nonstraight = qis_45; + rb->flags.bl_to_ur = ((qX2 >= qX1 && qY2 <= qY1) + || (qX2 <= qX1 && qY2 >= qY1)); + rb->style = AutoRouteParameters.style; + rb->pass = AutoRouteParameters.pass; + InitLists(rb); + /* add these to proper subnet. */ + MergeNets(rb, qsn, NET); + MergeNets(rb, qsn, SUBNET); + assert(__routepcb_box_is_good(rb)); + /* and add it to the r-tree! */ + pcb_r_insert_entry(rd->layergrouptree[rb->group], &rb->box); + + if (conf_core.editor.live_routing) { + pcb_layer_t *layer = LAYER_PTR(PCB->LayerGroups.grp[rb->group].lid[0]); + pcb_line_t *line = pcb_line_new(layer, qX1, qY1, qX2, qY2, + 2 * qhthick, 0, pcb_flag_make(0)); + rb->livedraw_obj.line = line; + if (line != NULL) + pcb_line_invalidate_draw(layer, line); + } + + /* and to the via space structures */ + if (AutoRouteParameters.use_vias) + mtspace_add(rd->mtspace, &rb->box, rb->flags.is_odd ? ODD : EVEN, rb->style->Clearance); + usedGroup[rb->group] = pcb_true; + /* and queue this one */ + qX1 = X1; + qY1 = Y1; + qX2 = X2; + qY2 = Y2; + qhthick = halfthick; + qgroup = group; + qis_45 = is_45; + qis_bad = is_bad; + qsn = subnet; +} + +static pcb_bool +RD_DrawManhattanLine(routedata_t * rd, + const pcb_box_t * box1, const pcb_box_t * box2, + pcb_cheap_point_t start, pcb_cheap_point_t end, + pcb_coord_t halfthick, pcb_cardinal_t group, routebox_t * subnet, pcb_bool is_bad, pcb_bool last_was_x) +{ + pcb_cheap_point_t knee = start; + if (end.X == start.X) { + RD_DrawLine(rd, start.X, start.Y, end.X, end.Y, halfthick, group, subnet, is_bad, pcb_false); + return pcb_false; + } + else if (end.Y == start.Y) { + RD_DrawLine(rd, start.X, start.Y, end.X, end.Y, halfthick, group, subnet, is_bad, pcb_false); + return pcb_true; + } + /* find where knee belongs */ + if (pcb_point_in_box(box1, end.X, start.Y) + || pcb_point_in_box(box2, end.X, start.Y)) { + knee.X = end.X; + knee.Y = start.Y; + } + else { + knee.X = start.X; + knee.Y = end.Y; + } + if ((knee.X == end.X && !last_was_x) && (pcb_point_in_box(box1, start.X, end.Y) + || pcb_point_in_box(box2, start.X, end.Y))) { + knee.X = start.X; + knee.Y = end.Y; + } + assert(AutoRouteParameters.is_smoothing || pcb_point_in_closed_box(box1, knee.X, knee.Y) + || pcb_point_in_closed_box(box2, knee.X, knee.Y)); + + if (1 || !AutoRouteParameters.is_smoothing) { + /* draw standard manhattan paths */ + RD_DrawLine(rd, start.X, start.Y, knee.X, knee.Y, halfthick, group, subnet, is_bad, pcb_false); + RD_DrawLine(rd, knee.X, knee.Y, end.X, end.Y, halfthick, group, subnet, is_bad, pcb_false); + } + else { + /* draw 45-degree path across knee */ + pcb_coord_t len45 = MIN(PCB_ABS(start.X - end.X), PCB_ABS(start.Y - end.Y)); + pcb_cheap_point_t kneestart = knee, kneeend = knee; + if (kneestart.X == start.X) + kneestart.Y += (kneestart.Y > start.Y) ? -len45 : len45; + else + kneestart.X += (kneestart.X > start.X) ? -len45 : len45; + if (kneeend.X == end.X) + kneeend.Y += (kneeend.Y > end.Y) ? -len45 : len45; + else + kneeend.X += (kneeend.X > end.X) ? -len45 : len45; + RD_DrawLine(rd, start.X, start.Y, kneestart.X, kneestart.Y, halfthick, group, subnet, is_bad, pcb_false); + RD_DrawLine(rd, kneestart.X, kneestart.Y, kneeend.X, kneeend.Y, halfthick, group, subnet, is_bad, pcb_true); + RD_DrawLine(rd, kneeend.X, kneeend.Y, end.X, end.Y, halfthick, group, subnet, is_bad, pcb_false); + } + return (knee.X != end.X); +} + +/* for smoothing, don't pack traces to min clearance gratuitously */ +#if 0 +static void add_clearance(pcb_cheap_point_t * nextpoint, const pcb_box_t * b) +{ + if (nextpoint->X == b->X1) { + if (nextpoint->X + AutoRouteParameters.style->Clearance < (b->X1 + b->X2) / 2) + nextpoint->X += AutoRouteParameters.style->Clearance; + else + nextpoint->X = (b->X1 + b->X2) / 2; + } + else if (nextpoint->X == b->X2) { + if (nextpoint->X - AutoRouteParameters.style->Clearance > (b->X1 + b->X2) / 2) + nextpoint->X -= AutoRouteParameters.style->Clearance; + else + nextpoint->X = (b->X1 + b->X2) / 2; + } + else if (nextpoint->Y == b->Y1) { + if (nextpoint->Y + AutoRouteParameters.style->Clearance < (b->Y1 + b->Y2) / 2) + nextpoint->Y += AutoRouteParameters.style->Clearance; + else + nextpoint->Y = (b->Y1 + b->Y2) / 2; + } + else if (nextpoint->Y == b->Y2) { + if (nextpoint->Y - AutoRouteParameters.style->Clearance > (b->Y1 + b->Y2) / 2) + nextpoint->Y -= AutoRouteParameters.style->Clearance; + else + nextpoint->Y = (b->Y1 + b->Y2) / 2; + } +} +#endif + +/* This back-traces the expansion boxes along the best path + * it draws the lines that will make the actual path. + * during refinement passes, it should try to maximize the area + * for other tracks so routing completion is easier. + * + * during smoothing passes, it should try to make a better path, + * possibly using diagonals, etc. The path boxes are larger on + * average now so there is more possiblity to decide on a nice + * path. Any combination of lines and arcs is possible, so long + * as they don't poke more than half thick outside the path box. + */ + +static void TracePath(routedata_t * rd, routebox_t * path, const routebox_t * target, routebox_t * subnet, pcb_bool is_bad) +{ + pcb_bool last_x = pcb_false; + pcb_coord_t halfwidth = HALF_THICK(AutoRouteParameters.style->Thick); + pcb_coord_t radius = HALF_THICK(AutoRouteParameters.style->Diameter); + pcb_cheap_point_t lastpoint, nextpoint; + routebox_t *lastpath; + pcb_box_t b; + + assert(subnet->style == AutoRouteParameters.style); + /*XXX: because we round up odd thicknesses, there's the possibility that + * a connecting line end-point might be 0.005 mil off the "real" edge. + * don't worry about this because line *thicknesses* are always >= 0.01 mil. */ + + /* if we start with a thermal the target was a plane + * or the target was a pin and the source a plane + * in which case this thermal is the whole path + */ + if (path->flags.is_thermal) { + /* the target was a plane, so we need to find a good spot for the via + * now. It's logical to place it close to the source box which + * is where we're utlimately headed on this path. However, it + * must reside in the plane as well as the via area too. + */ + nextpoint.X = PCB_BOX_CENTER_X(path->sbox); + nextpoint.Y = PCB_BOX_CENTER_Y(path->sbox); + if (path->parent.expansion_area->flags.is_via) { + TargetPoint(&nextpoint, rb_source(path)); + /* nextpoint is the middle of the source terminal now */ + b = pcb_clip_box(&path->sbox, &path->parent.expansion_area->sbox); + nextpoint = pcb_closest_pcb_point_in_box(&nextpoint, &b); + /* now it's in the via and plane near the source */ + } + else { /* no via coming, target must have been a pin */ + + assert(target->type == TERM); + TargetPoint(&nextpoint, target); + } + assert(pcb_point_in_box(&path->sbox, nextpoint.X, nextpoint.Y)); + RD_DrawThermal(rd, nextpoint.X, nextpoint.Y, path->group, path->layer, subnet, is_bad); + } + else { + /* start from best place of target box */ + lastpoint.X = PCB_BOX_CENTER_X(target->sbox); + lastpoint.Y = PCB_BOX_CENTER_Y(target->sbox); + TargetPoint(&lastpoint, target); + if (AutoRouteParameters.last_smooth && pcb_box_in_box(&path->sbox, &target->sbox)) + path = path->parent.expansion_area; + b = path->sbox; + if (path->flags.circular) + b = pcb_shrink_box(&b, MIN(b.X2 - b.X1, b.Y2 - b.Y1) / 5); + nextpoint = pcb_closest_pcb_point_in_box(&lastpoint, &b); + if (AutoRouteParameters.last_smooth) + RD_DrawLine(rd, lastpoint.X, lastpoint.Y, nextpoint.X, nextpoint.Y, halfwidth, path->group, subnet, is_bad, pcb_true); + else + last_x = RD_DrawManhattanLine(rd, &target->sbox, &path->sbox, + lastpoint, nextpoint, halfwidth, path->group, subnet, is_bad, last_x); + } +#if defined(ROUTE_DEBUG) && defined(DEBUG_SHOW_ROUTE_BOXES) + showroutebox(path); +#if defined(ROUTE_VERBOSE) + pcb_printf("TRACEPOINT start %#mD\n", nextpoint.X, nextpoint.Y); +#endif +#endif + + do { + lastpoint = nextpoint; + lastpath = path; + assert(path->type == EXPANSION_AREA); + path = path->parent.expansion_area; + b = path->sbox; + if (path->flags.circular) + b = pcb_shrink_box(&b, MIN(b.X2 - b.X1, b.Y2 - b.Y1) / 5); + assert(b.X1 != b.X2 && b.Y1 != b.Y2); /* need someplace to put line! */ + /* find point on path perimeter closest to last point */ + /* if source terminal, try to hit a good place */ + nextpoint = pcb_closest_pcb_point_in_box(&lastpoint, &b); +#if 0 + /* leave more clearance if this is a smoothing pass */ + if (AutoRouteParameters.is_smoothing && (nextpoint.X != lastpoint.X || nextpoint.Y != lastpoint.Y)) + add_clearance(&nextpoint, &b); +#endif + if (path->flags.source && path->type != PLANE) + TargetPoint(&nextpoint, path); + assert(pcb_point_in_box(&lastpath->box, lastpoint.X, lastpoint.Y)); + assert(pcb_point_in_box(&path->box, nextpoint.X, nextpoint.Y)); +#if defined(ROUTE_DEBUG_VERBOSE) + printf("TRACEPATH: "); + DumpRouteBox(path); + pcb_printf("TRACEPATH: point %#mD to point %#mD layer %d\n", + lastpoint.X, lastpoint.Y, nextpoint.X, nextpoint.Y, path->group); +#endif + + /* draw orthogonal lines from lastpoint to nextpoint */ + /* knee is placed in lastpath box */ + /* should never cause line to leave union of lastpath/path boxes */ + if (AutoRouteParameters.last_smooth) + RD_DrawLine(rd, lastpoint.X, lastpoint.Y, nextpoint.X, nextpoint.Y, halfwidth, path->group, subnet, is_bad, pcb_true); + else + last_x = RD_DrawManhattanLine(rd, &lastpath->sbox, &path->sbox, + lastpoint, nextpoint, halfwidth, path->group, subnet, is_bad, last_x); + if (path->flags.is_via) { /* if via, then add via */ +#ifdef ROUTE_VERBOSE + printf(" (vias)"); +#endif + assert(pcb_point_in_box(&path->box, nextpoint.X, nextpoint.Y)); + RD_DrawVia(rd, nextpoint.X, nextpoint.Y, radius, subnet, is_bad); + } + + assert(lastpath->flags.is_via || path->group == lastpath->group); + +#if defined(ROUTE_DEBUG) && defined(DEBUG_SHOW_ROUTE_BOXES) + showroutebox(path); +#endif /* ROUTE_DEBUG && DEBUG_SHOW_ROUTE_BOXES */ + /* if this is connected to a plane, draw the thermal */ + if (path->flags.is_thermal || path->type == PLANE) + RD_DrawThermal(rd, lastpoint.X, lastpoint.Y, path->group, path->layer, subnet, is_bad); + /* when one hop from the source, make an extra path in *this* box */ + if (path->type == EXPANSION_AREA && path->parent.expansion_area->flags.source && path->parent.expansion_area->type != PLANE) { + /* find special point on source (if it exists) */ + if (TargetPoint(&lastpoint, path->parent.expansion_area)) { + lastpoint = closest_point_in_routebox(&lastpoint, path); + b = shrink_routebox(path); +#if 0 + if (AutoRouteParameters.is_smoothing) + add_clearance(&lastpoint, &b); +#else + if (AutoRouteParameters.last_smooth) + RD_DrawLine(rd, lastpoint.X, lastpoint.Y, nextpoint.X, nextpoint.Y, halfwidth, path->group, subnet, is_bad, pcb_true); + else +#endif + last_x = RD_DrawManhattanLine(rd, &b, &b, nextpoint, lastpoint, halfwidth, path->group, subnet, is_bad, last_x); +#if defined(ROUTE_DEBUG_VERBOSE) + printf("TRACEPATH: "); + DumpRouteBox(path); + pcb_printf + ("TRACEPATH: (to source) point %#mD to point %#mD layer %d\n", + nextpoint.X, nextpoint.Y, lastpoint.X, lastpoint.Y, path->group); +#endif + + nextpoint = lastpoint; + } + } + } + while (!path->flags.source); + /* flush the line queue */ + RD_DrawLine(rd, -1, 0, 0, 0, 0, 0, NULL, pcb_false, pcb_false); + + if (conf_core.editor.live_routing) + pcb_draw(); + +#ifdef ROUTE_DEBUG + if (ddraw != NULL) + ddraw->flush_debug_draw(); +#endif +} + +/* create a fake "edge" used to defer via site searching. */ +static void +CreateSearchEdge(routeone_state_t *s, vetting_t * work, edge_t * parent, + routebox_t * rb, conflict_t conflict, pcb_rtree_t * targets, pcb_bool in_plane) +{ + routebox_t *target; + pcb_box_t b; + pcb_cost_t cost; + assert(__routepcb_box_is_good(rb)); + /* find the cheapest target */ +#if 0 + target = minpcb_cost_target_to_point(&parent->cost_point, pcb_max_group(PCB) + 1, targets, parent->minpcb_cost_target); +#else + target = parent->minpcb_cost_target; +#endif + b = shrink_routebox(target); + cost = parent->pcb_cost_to_point + AutoRouteParameters.ViaCost + pcb_cost_to_layerless_box(&rb->cost_point, 0, &b); + if (cost < s->best_cost) { + edge_t *ne; + ne = (edge_t *) malloc(sizeof(*ne)); + memset((void *) ne, 0, sizeof(*ne)); + assert(ne); + ne->flags.via_search = 1; + ne->flags.in_plane = in_plane; + ne->rb = rb; + if (rb->flags.homeless) + RB_up_count(rb); + ne->work = work; + ne->minpcb_cost_target = target; + ne->flags.via_conflict_level = conflict; + ne->pcb_cost_to_point = parent->pcb_cost_to_point; + ne->cost_point = parent->cost_point; + ne->cost = cost; + pcb_heap_insert(s->workheap, ne->cost, ne); + } + else { + mtsFreeWork(&work); + } +} + +static void add_or_destroy_edge(routeone_state_t *s, edge_t * e) +{ + e->cost = edge_cost(e, s->best_cost); + assert(__edge_is_good(e)); + assert(is_layer_group_active[e->rb->group]); + if (e->cost < s->best_cost) + pcb_heap_insert(s->workheap, e->cost, e); + else + DestroyEdge(&e); +} + +static void best_path_candidate(routeone_state_t *s, edge_t * e, routebox_t * best_target) +{ + e->cost = edge_cost(e, EXPENSIVE); + if (s->best_path == NULL || e->cost < s->best_cost) { +#if defined(ROUTE_DEBUG) && defined (ROUTE_VERBOSE) + printf("New best path seen! cost = %f\n", e->cost); +#endif + /* new best path! */ + if (s->best_path && s->best_path->flags.homeless) + RB_down_count(s->best_path); + s->best_path = e->rb; + s->best_target = best_target; + s->best_cost = e->cost; + assert(s->best_cost >= 0); + /* don't free this when we destroy edge! */ + if (s->best_path->flags.homeless) + RB_up_count(s->best_path); + } +} + + +/* vectors for via site candidates (see mtspace.h) */ +struct routeone_via_site_state { + vector_t *free_space_vec; + vector_t *lo_conflict_space_vec; + vector_t *hi_conflict_space_vec; +}; + +void +add_via_sites(routeone_state_t *s, + struct routeone_via_site_state *vss, + mtspace_t * mtspace, routebox_t * within, + conflict_t within_conflict_level, edge_t * parent_edge, pcb_rtree_t * targets, pcb_coord_t shrink, pcb_bool in_plane) +{ + pcb_coord_t radius, clearance; + vetting_t *work; + pcb_box_t region = shrink_routebox(within); + pcb_shrink_box(®ion, shrink); + + radius = HALF_THICK(AutoRouteParameters.style->Diameter); + clearance = AutoRouteParameters.style->Clearance; + assert(AutoRouteParameters.use_vias); + /* XXX: need to clip 'within' to shrunk_pcb_bounds, because when + XXX: routing with conflicts may poke over edge. */ + + /* ask for a via box near our cost_point first */ + work = mtspace_query_rect(mtspace, ®ion, radius, clearance, + NULL, vss->free_space_vec, + vss->lo_conflict_space_vec, + vss->hi_conflict_space_vec, + AutoRouteParameters.is_odd, AutoRouteParameters.with_conflicts, &parent_edge->cost_point); + if (!work) + return; + CreateSearchEdge(s, work, parent_edge, within, within_conflict_level, targets, in_plane); +} + +void +do_via_search(edge_t * search, routeone_state_t *s, + struct routeone_via_site_state *vss, mtspace_t * mtspace, pcb_rtree_t * targets) +{ + int i, j, count = 0; + pcb_coord_t radius, clearance; + vetting_t *work; + routebox_t *within; + conflict_t within_conflict_level; + + radius = HALF_THICK(AutoRouteParameters.style->Diameter); + clearance = AutoRouteParameters.style->Clearance; + work = mtspace_query_rect(mtspace, NULL, 0, 0, + search->work, vss->free_space_vec, + vss->lo_conflict_space_vec, + vss->hi_conflict_space_vec, AutoRouteParameters.is_odd, AutoRouteParameters.with_conflicts, NULL); + within = search->rb; + within_conflict_level = search->flags.via_conflict_level; + for (i = 0; i < 3; i++) { + vector_t *v = + (i == NO_CONFLICT ? vss->free_space_vec : + i == LO_CONFLICT ? vss->lo_conflict_space_vec : i == HI_CONFLICT ? vss->hi_conflict_space_vec : NULL); + assert(v); + while (!vector_is_empty(v)) { + pcb_box_t cliparea; + pcb_box_t *area = (pcb_box_t *) vector_remove_last(v); + if (!(i == NO_CONFLICT || AutoRouteParameters.with_conflicts)) { + free(area); + continue; + } + /* answers are bloated by radius + clearance */ + cliparea = pcb_shrink_box(area, radius + clearance); + pcb_close_box(&cliparea); + free(area); + assert(pcb_box_is_good(&cliparea)); + count++; + for (j = 0; j < pcb_max_group(PCB); j++) { + edge_t *ne; + if (j == within->group || !is_layer_group_active[j]) + continue; + ne = CreateViaEdge(&cliparea, j, within, search, within_conflict_level, (conflict_t) i, targets); + add_or_destroy_edge(s, ne); + } + } + } + /* prevent freeing of work when this edge is destroyed */ + search->flags.via_search = 0; + if (!work) + return; + CreateSearchEdge(s, work, search, within, within_conflict_level, targets, search->flags.in_plane); + assert(vector_is_empty(vss->free_space_vec)); + assert(vector_is_empty(vss->lo_conflict_space_vec)); + assert(vector_is_empty(vss->hi_conflict_space_vec)); +} + +/* vector of expansion areas to be eventually removed from r-tree + * this is a global for troubleshooting + */ +vector_t *area_vec; + +/* some routines for use in gdb while debugging */ +#if defined(ROUTE_DEBUG) +static void list_conflicts(routebox_t * rb) +{ + int i, n; + if (!rb->conflicts_with) + return; + n = vector_size(rb->conflicts_with); + for (i = 0; i < n; i++) + printf("%p, ", (void *)vector_element(rb->conflicts_with, i)); +} + +static void show_area_vec(int lay) +{ + int n, save; + + if (!area_vec) + return; + save = showboxen; + showboxen = lay; + for (n = 0; n < vector_size(area_vec); n++) { + routebox_t *rb = (routebox_t *) vector_element(area_vec, n); + showroutebox(rb); + } + showboxen = save; +} + +static pcb_bool net_id(routebox_t * rb, long int id) +{ + routebox_t *p; + LIST_LOOP(rb, same_net, p); + if (p->flags.source && p->parent.pad->ID == id) + return pcb_true; + PCB_END_LOOP; + return pcb_false; +} + +static void trace_parents(routebox_t * rb) +{ + while (rb && rb->type == EXPANSION_AREA) { + printf(" %p ->", (void *)rb); + rb = rb->parent.expansion_area; + } + if (rb) + printf(" %p is source\n", (void *)rb); + else + printf("NULL!\n"); +} + +static void show_one(routebox_t * rb) +{ + int save = showboxen; + showboxen = -1; + showroutebox(rb); + showboxen = save; +} + +static void show_path(routebox_t * rb) +{ + while (rb && rb->type == EXPANSION_AREA) { + show_one(rb); + rb = rb->parent.expansion_area; + } + show_one(rb); +} + +static void show_sources(routebox_t * rb) +{ + routebox_t *p; + if (!rb->flags.source && !rb->flags.target) { + printf("start with a source or target please\n"); + return; + } + LIST_LOOP(rb, same_net, p); + if (p->flags.source) + show_one(p); + PCB_END_LOOP; +} + +#endif + +static pcb_r_dir_t __conflict_source(const pcb_box_t * box, void *cl) +{ + routebox_t *rb = (routebox_t *) box; + if (rb->flags.touched || rb->flags.fixed) + return PCB_R_DIR_NOT_FOUND; + else { + routebox_t *dis = (routebox_t *) cl; + path_conflicts(dis, rb, pcb_false); + touch_conflicts(dis->conflicts_with, 1); + } + return PCB_R_DIR_FOUND_CONTINUE; +} + +static void source_conflicts(pcb_rtree_t * tree, routebox_t * rb) +{ + if (!AutoRouteParameters.with_conflicts) + return; + pcb_r_search(tree, &rb->sbox, NULL, __conflict_source, rb, NULL); + touch_conflicts(NULL, 1); +} + +typedef struct routeone_status_s { + pcb_bool found_route; + int route_had_conflicts; + pcb_cost_t best_route_cost; + pcb_bool net_completely_routed; +} routeone_status_t; + + +static routeone_status_t RouteOne(routedata_t * rd, routebox_t * from, routebox_t * to, int max_edges) +{ + routeone_status_t result; + routebox_t *p; + int seen, i; + const pcb_box_t **target_list; + int num_targets; + pcb_rtree_t *targets; + /* vector of source edges for filtering */ + vector_t *source_vec; + /* working vector */ + vector_t *edge_vec; + + routeone_state_t s; + struct routeone_via_site_state vss; + + assert(rd && from); + result.route_had_conflicts = 0; + /* no targets on to/from net need clearance areas */ + LIST_LOOP(from, same_net, p); + p->flags.nobloat = 1; + PCB_END_LOOP; + /* set 'source' flags */ + LIST_LOOP(from, same_subnet, p); + if (!p->flags.nonstraight) + p->flags.source = 1; + PCB_END_LOOP; + + /* count up the targets */ + num_targets = 0; + seen = 0; + /* remove source/target flags from non-straight obstacles, because they + * don't fill their bounding boxes and so connecting to them + * after we've routed is problematic. Better solution? */ + if (to) { /* if we're routing to a specific target */ + if (!to->flags.source) { /* not already connected */ + /* check that 'to' and 'from' are on the same net */ + seen = 0; +#ifndef NDEBUG + LIST_LOOP(from, same_net, p); + if (p == to) + seen = 1; + PCB_END_LOOP; +#endif + assert(seen); /* otherwise from and to are on different nets! */ + /* set target flags only on 'to's subnet */ + LIST_LOOP(to, same_subnet, p); + if (!p->flags.nonstraight && is_layer_group_active[p->group]) { + p->flags.target = 1; + num_targets++; + } + PCB_END_LOOP; + } + } + else { + /* all nodes on the net but not connected to from are targets */ + LIST_LOOP(from, same_net, p); + if (!p->flags.source && is_layer_group_active[p->group] + && !p->flags.nonstraight) { + p->flags.target = 1; + num_targets++; + } + PCB_END_LOOP; + } + + /* if no targets, then net is done! reset flags and return. */ + if (num_targets == 0) { + LIST_LOOP(from, same_net, p); + p->flags.source = p->flags.target = p->flags.nobloat = 0; + PCB_END_LOOP; + result.found_route = pcb_false; + result.net_completely_routed = pcb_true; + result.best_route_cost = 0; + result.route_had_conflicts = 0; + + return result; + } + result.net_completely_routed = pcb_false; + + /* okay, there's stuff to route */ + assert(!from->flags.target); + assert(num_targets > 0); + /* create list of target pointers and from that a r-tree of targets */ + target_list = (const pcb_box_t **) malloc(num_targets * sizeof(*target_list)); + i = 0; + LIST_LOOP(from, same_net, p); + if (p->flags.target) { + target_list[i++] = &p->box; +#if defined(ROUTE_DEBUG) && defined(DEBUG_SHOW_TARGETS) + showroutebox(p); +#endif + } + PCB_END_LOOP; + targets = pcb_r_create_tree(); + pcb_r_insert_array(targets, (const pcb_box_t **)target_list, i); + assert(i <= num_targets); + free(target_list); + + source_vec = vector_create(); + /* touch the source subnet to prepare check for conflictors */ + LIST_LOOP(from, same_subnet, p); + p->flags.touched = 1; + PCB_END_LOOP; + LIST_LOOP(from, same_subnet, p); + { + /* we need the test for 'source' because this box may be nonstraight */ + if (p->flags.source && is_layer_group_active[p->group]) { + pcb_cheap_point_t cp; + edge_t *e; + pcb_box_t b = shrink_routebox(p); + +#if defined(ROUTE_DEBUG) && defined(DEBUG_SHOW_SOURCES) + showroutebox(p); +#endif + /* may expand in all directions from source; center edge cost point. */ + /* note that planes shouldn't really expand, but we need an edge */ + + cp.X = PCB_BOX_CENTER_X(b); + cp.Y = PCB_BOX_CENTER_Y(b); + e = CreateEdge(p, cp.X, cp.Y, 0, NULL, PCB_ANY_DIR, targets); + cp = pcb_closest_pcb_point_in_box(&cp, &e->minpcb_cost_target->sbox); + cp = pcb_closest_pcb_point_in_box(&cp, &b); + e->cost_point = cp; + p->cost_point = cp; + source_conflicts(rd->layergrouptree[p->group], p); + vector_append(source_vec, e); + } + } + PCB_END_LOOP; + LIST_LOOP(from, same_subnet, p); + p->flags.touched = 0; + PCB_END_LOOP; + /* break source edges; some edges may be too near obstacles to be able + * to exit from. */ + + /* okay, main expansion-search routing loop. */ + /* set up the initial activity heap */ + s.workheap = pcb_heap_create(); + assert(s.workheap); + while (!vector_is_empty(source_vec)) { + edge_t *e = (edge_t *) vector_remove_last(source_vec); + assert(is_layer_group_active[e->rb->group]); + e->cost = edge_cost(e, EXPENSIVE); + pcb_heap_insert(s.workheap, e->cost, e); + } + vector_destroy(&source_vec); + /* okay, process items from heap until it is empty! */ + s.best_path = NULL; + s.best_cost = EXPENSIVE; + area_vec = vector_create(); + edge_vec = vector_create(); + vss.free_space_vec = vector_create(); + vss.lo_conflict_space_vec = vector_create(); + vss.hi_conflict_space_vec = vector_create(); + while (!pcb_heap_is_empty(s.workheap)) { + edge_t *e = (edge_t *) pcb_heap_remove_smallest(s.workheap); +#ifdef ROUTE_DEBUG + if (aabort) + goto dontexpand; +#endif + /* don't bother expanding this edge if the minimum possible edge cost + * is already larger than the best edge cost we've found. */ + if (s.best_path && e->cost >= s.best_cost) { + pcb_heap_free(s.workheap, KillEdge); + goto dontexpand; /* skip this edge */ + } + /* surprisingly it helps to give up and not try too hard to find + * a route! This is not only faster, but results in better routing. + * who would have guessed? + */ + if (seen++ > max_edges) + goto dontexpand; + assert(__edge_is_good(e)); + /* mark or unmark conflictors as needed */ + touch_conflicts(e->rb->conflicts_with, 1); + if (e->flags.via_search) { + do_via_search(e, &s, &vss, rd->mtspace, targets); + goto dontexpand; + } + /* we should never add edges on inactive layer groups to the heap. */ + assert(is_layer_group_active[e->rb->group]); +#if defined(ROUTE_DEBUG) && defined(DEBUG_SHOW_EXPANSION_BOXES) + /*showedge (e); */ +#endif + if (e->rb->flags.is_thermal) { + best_path_candidate(&s, e, e->minpcb_cost_target); + goto dontexpand; + } + /* for a plane, look for quick connections with thermals or vias */ + if (e->rb->type == PLANE) { + routebox_t *pin = FindThermable(targets, e->rb); + if (pin) { + pcb_box_t b = shrink_routebox(pin); + edge_t *ne; + routebox_t *nrb; + assert(pin->flags.target); + nrb = CreateExpansionArea(&b, e->rb->group, e->rb, pcb_true, e); + nrb->flags.is_thermal = 1; + /* moving through the plane is free */ + e->cost_point.X = b.X1; + e->cost_point.Y = b.Y1; + ne = CreateEdge2(nrb, e->expand_dir, e, NULL, pin); + best_path_candidate(&s, ne, pin); + DestroyEdge(&ne); + } + else { + /* add in possible via sites in plane */ + if (AutoRouteParameters.use_vias && e->cost + AutoRouteParameters.ViaCost < s.best_cost) { + /* we need a giant thermal */ + routebox_t *nrb = CreateExpansionArea(&e->rb->sbox, e->rb->group, e->rb, + pcb_true, e); + edge_t *ne = CreateEdge2(nrb, e->expand_dir, e, NULL, + e->minpcb_cost_target); + nrb->flags.is_thermal = 1; + add_via_sites(&s, &vss, rd->mtspace, nrb, NO_CONFLICT, ne, targets, e->rb->style->Diameter, pcb_true); + } + } + goto dontexpand; /* planes only connect via thermals */ + } + if (e->flags.is_via) { /* special case via */ + routebox_t *intersecting; + assert(AutoRouteParameters.use_vias); + assert(e->expand_dir == PCB_ANY_DIR); + assert(vector_is_empty(edge_vec)); + /* if there is already something here on this layer (like an + * EXPANSION_AREA), then we don't want to expand from here + * at least not inside the expansion area. A PLANE on the + * other hand may be a target, or not. + */ + intersecting = FindOneInBox(rd->layergrouptree[e->rb->group], e->rb); + + if (intersecting && intersecting->flags.target && intersecting->type == PLANE) { + /* we have hit a plane */ + edge_t *ne; + routebox_t *nrb; + pcb_box_t b = shrink_routebox(e->rb); + /* limit via region to that inside the plane */ + pcb_clip_box(&b, &intersecting->sbox); + nrb = CreateExpansionArea(&b, e->rb->group, e->rb, pcb_true, e); + nrb->flags.is_thermal = 1; + ne = CreateEdge2(nrb, e->expand_dir, e, NULL, intersecting); + best_path_candidate(&s, ne, intersecting); + DestroyEdge(&ne); + goto dontexpand; + } + else if (intersecting == NULL) { + /* this via candidate is in an open area; add it to r-tree as + * an expansion area */ + assert(e->rb->type == EXPANSION_AREA && e->rb->flags.is_via); + /*assert (!pcb_r_search(rd->layergrouptree[e->rb->group], + &e->rb->box, NULL, no_planes,0)); + */ + pcb_r_insert_entry(rd->layergrouptree[e->rb->group], &e->rb->box); + e->rb->flags.homeless = 0; /* not homeless any more */ + /* add to vector of all expansion areas in r-tree */ + vector_append(area_vec, e->rb); + /* mark reset refcount to 0, since this is not homeless any more. */ + e->rb->refcount = 0; + /* go ahead and expand this edge! */ + } + else if (1) + goto dontexpand; + else if (0) { /* XXX: disabling this causes no via + collisions. */ + pcb_box_t a = bloat_routebox(intersecting), b; + edge_t *ne; + int i, j; + /* something intersects this via candidate. split via candidate + * into pieces and add these pieces to the workheap. */ + for (i = 0; i < 3; i++) { + for (j = 0; j < 3; j++) { + b = shrink_routebox(e->rb); + switch (i) { + case 0: + b.X2 = MIN(b.X2, a.X1); + break; /* left */ + case 1: + b.X1 = MAX(b.X1, a.X1); + b.X2 = MIN(b.X2, a.X2); + break; /*c */ + case 2: + b.X1 = MAX(b.X1, a.X2); + break; /* right */ + default: + assert(0); + } + switch (j) { + case 0: + b.Y2 = MIN(b.Y2, a.Y1); + break; /* top */ + case 1: + b.Y1 = MAX(b.Y1, a.Y1); + b.Y2 = MIN(b.Y2, a.Y2); + break; /*c */ + case 2: + b.Y1 = MAX(b.Y1, a.Y2); + break; /* bottom */ + default: + assert(0); + } + /* skip if this box is not valid */ + if (!(b.X1 < b.X2 && b.Y1 < b.Y2)) + continue; + if (i == 1 && j == 1) { + /* this bit of the via space is obstructed. */ + if (intersecting->type == EXPANSION_AREA || intersecting->flags.fixed) + continue; /* skip this bit, it's already been done. */ + /* create an edge with conflicts, if enabled */ + if (!AutoRouteParameters.with_conflicts) + continue; + ne = CreateEdgeWithConflicts(&b, intersecting, e, 1 + /*cost penalty to box */ + , targets); + add_or_destroy_edge(&s, ne); + } + else { + /* if this is not the intersecting piece, create a new + * (hopefully unobstructed) via edge and add it back to the + * workheap. */ + ne = CreateViaEdge(&b, e->rb->group, e->rb->parent.expansion_area, e, e->flags.via_conflict_level, NO_CONFLICT + /* value here doesn't matter */ + , targets); + add_or_destroy_edge(&s, ne); + } + } + } + goto dontexpand; + } + /* between the time these edges are inserted and the + * time they are processed, new expansion boxes (which + * conflict with these edges) may be added to the graph! + * w.o vias this isn't a problem because the broken box + * is not homeless. */ + } + if (1) { + routebox_t *nrb; + struct E_result *ans; + pcb_box_t b; + vector_t *broken; + if (e->flags.is_interior) { + assert(AutoRouteParameters.with_conflicts); /* no interior edges unless + routing with conflicts! */ + assert(e->rb->conflicts_with); + b = e->rb->sbox; + switch (e->rb->came_from) { + case PCB_NORTH: + b.Y2 = b.Y1 + 1; + b.X1 = PCB_BOX_CENTER_X(b); + b.X2 = b.X1 + 1; + break; + case PCB_EAST: + b.X1 = b.X2 - 1; + b.Y1 = PCB_BOX_CENTER_Y(b); + b.Y2 = b.Y1 + 1; + break; + case PCB_SOUTH: + b.Y1 = b.Y2 - 1; + b.X1 = PCB_BOX_CENTER_X(b); + b.X2 = b.X1 + 1; + break; + case PCB_WEST: + b.X2 = b.X1 + 1; + b.Y1 = PCB_BOX_CENTER_Y(b); + b.Y2 = b.Y1 + 1; + break; + default: + assert(0); + } + } + /* sources may not expand to their own edges because of + * adjacent blockers. + */ + else if (e->rb->flags.source) + b = pcb_box_center(&e->rb->sbox); + else + b = e->rb->sbox; + ans = Expand(rd->layergrouptree[e->rb->group], e, &b); + if (!pcb_box_intersect(&ans->inflated, &ans->orig)) + goto dontexpand; +#if 0 + /* skip if it didn't actually expand */ + if (ans->inflated.X1 >= e->rb->sbox.X1 && + ans->inflated.X2 <= e->rb->sbox.X2 && ans->inflated.Y1 >= e->rb->sbox.Y1 && ans->inflated.Y2 <= e->rb->sbox.Y2) + goto dontexpand; +#endif + + if (!pcb_box_is_good(&ans->inflated)) + goto dontexpand; + nrb = CreateExpansionArea(&ans->inflated, e->rb->group, e->rb, pcb_true, e); + pcb_r_insert_entry(rd->layergrouptree[nrb->group], &nrb->box); + vector_append(area_vec, nrb); + nrb->flags.homeless = 0; /* not homeless any more */ + broken = BreakManyEdges(&s, targets, rd->layergrouptree[nrb->group], area_vec, ans, nrb, e); + while (!vector_is_empty(broken)) { + edge_t *ne = (edge_t *) vector_remove_last(broken); + add_or_destroy_edge(&s, ne); + } + vector_destroy(&broken); + + /* add in possible via sites in nrb */ + if (AutoRouteParameters.use_vias && !e->rb->flags.is_via && e->cost + AutoRouteParameters.ViaCost < s.best_cost) + add_via_sites(&s, &vss, rd->mtspace, nrb, NO_CONFLICT, e, targets, 0, pcb_false); + goto dontexpand; + } + dontexpand: + DestroyEdge(&e); + } + touch_conflicts(NULL, 1); + pcb_heap_destroy(&s.workheap); + pcb_r_destroy_tree(&targets); + assert(vector_is_empty(edge_vec)); + vector_destroy(&edge_vec); + + /* we should have a path in best_path now */ + if (s.best_path) { + routebox_t *rb; +#ifdef ROUTE_VERBOSE + printf("%d:%d RC %.0f", ro++, seen, s.best_cost); +#endif + result.found_route = pcb_true; + result.best_route_cost = s.best_cost; + /* determine if the best path had conflicts */ + result.route_had_conflicts = 0; + if (AutoRouteParameters.with_conflicts && s.best_path->conflicts_with) { + while (!vector_is_empty(s.best_path->conflicts_with)) { + rb = (routebox_t *) vector_remove_last(s.best_path->conflicts_with); + rb->flags.is_bad = 1; + result.route_had_conflicts++; + } + } +#ifdef ROUTE_VERBOSE + if (result.route_had_conflicts) + printf(" (%d conflicts)", result.route_had_conflicts); +#endif + if (result.route_had_conflicts < AutoRouteParameters.hi_conflict) { + /* back-trace the path and add lines/vias to r-tree */ + TracePath(rd, s.best_path, s.best_target, from, result.route_had_conflicts); + MergeNets(from, s.best_target, SUBNET); + } + else { +#ifdef ROUTE_VERBOSE + printf(" (too many in fact)"); +#endif + result.found_route = pcb_false; + } +#ifdef ROUTE_VERBOSE + printf("\n"); +#endif + } + else { +#ifdef ROUTE_VERBOSE + printf("%d:%d NO PATH FOUND.\n", ro++, seen); +#endif + result.best_route_cost = s.best_cost; + result.found_route = pcb_false; + } + /* now remove all expansion areas from the r-tree. */ + while (!vector_is_empty(area_vec)) { + routebox_t *rb = (routebox_t *) vector_remove_last(area_vec); + assert(!rb->flags.homeless); + if (rb->conflicts_with && rb->parent.expansion_area->conflicts_with != rb->conflicts_with) + vector_destroy(&rb->conflicts_with); + pcb_r_delete_entry_free_data(rd->layergrouptree[rb->group], &rb->box, free); + } + vector_destroy(&area_vec); + /* clean up; remove all 'source', 'target', and 'nobloat' flags */ + LIST_LOOP(from, same_net, p); + if (p->flags.source && p->conflicts_with) + vector_destroy(&p->conflicts_with); + p->flags.touched = p->flags.source = p->flags.target = p->flags.nobloat = 0; + PCB_END_LOOP; + + vector_destroy(&vss.free_space_vec); + vector_destroy(&vss.lo_conflict_space_vec); + vector_destroy(&vss.hi_conflict_space_vec); + + return result; +} + +static void InitAutoRouteParameters(int pass, pcb_route_style_t * style, pcb_bool with_conflicts, pcb_bool is_smoothing, pcb_bool lastpass) +{ + int i; + /* routing style */ + AutoRouteParameters.style = style; + AutoRouteParameters.bloat = style->Clearance + HALF_THICK(style->Thick); + /* costs */ + AutoRouteParameters.ViaCost = PCB_INCH_TO_COORD(3.5) + style->Diameter * (is_smoothing ? 80 : 30); + AutoRouteParameters.LastConflictPenalty = (400 * pass / passes + 2) / (pass + 1); + AutoRouteParameters.ConflictPenalty = 4 * AutoRouteParameters.LastConflictPenalty; + AutoRouteParameters.JogPenalty = 1000 * (is_smoothing ? 20 : 4); + AutoRouteParameters.CongestionPenalty = 1e6; + AutoRouteParameters.MinPenalty = EXPENSIVE; + for (i = 0; i < pcb_max_group(PCB); i++) { + if (is_layer_group_active[i]) { + AutoRouteParameters.MinPenalty = MIN(x_cost[i], AutoRouteParameters.MinPenalty); + AutoRouteParameters.MinPenalty = MIN(y_cost[i], AutoRouteParameters.MinPenalty); + } + } + AutoRouteParameters.NewLayerPenalty = is_smoothing ? 0.5 * EXPENSIVE : 10 * AutoRouteParameters.ViaCost; + /* other */ + AutoRouteParameters.hi_conflict = MAX(8 * (passes - pass + 1), 6); + AutoRouteParameters.is_odd = (pass & 1); + AutoRouteParameters.with_conflicts = with_conflicts; + AutoRouteParameters.is_smoothing = is_smoothing; + AutoRouteParameters.rip_always = is_smoothing; + AutoRouteParameters.last_smooth = 0; /*lastpass; */ + AutoRouteParameters.pass = pass + 1; +} + +#ifndef NDEBUG +pcb_r_dir_t bad_boy(const pcb_box_t * b, void *cl) +{ + routebox_t *box = (routebox_t *) b; + if (box->type == EXPANSION_AREA) + return PCB_R_DIR_FOUND_CONTINUE; + return PCB_R_DIR_NOT_FOUND; +} + +pcb_bool no_expansion_boxes(routedata_t * rd) +{ + int i; + pcb_box_t big; + big.X1 = 0; + big.X2 = PCB_MAX_COORD; + big.Y1 = 0; + big.Y2 = PCB_MAX_COORD; + for (i = 0; i < pcb_max_group(PCB); i++) { + if (pcb_r_search(rd->layergrouptree[i], &big, NULL, bad_boy, NULL, NULL)) + return pcb_false; + } + return pcb_true; +} +#endif + +static void ripout_livedraw_obj(routebox_t * rb) +{ + if (rb->type == LINE && rb->livedraw_obj.line) { + pcb_layer_t *layer = LAYER_PTR(PCB->LayerGroups.grp[rb->group].lid[0]); + pcb_line_invalidate_erase(rb->livedraw_obj.line); + pcb_destroy_object(PCB->Data, PCB_OBJ_LINE, layer, rb->livedraw_obj.line, NULL); + rb->livedraw_obj.line = NULL; + } + + if (rb->type == VIA && rb->livedraw_obj.via) { + pcb_pstk_invalidate_erase(rb->livedraw_obj.via); + pcb_destroy_object(PCB->Data, PCB_OBJ_PSTK, rb->livedraw_obj.via, NULL, NULL); + rb->livedraw_obj.via = NULL; + } +} + +static pcb_r_dir_t ripout_livedraw_obj_cb(const pcb_box_t * b, void *cl) +{ + routebox_t *box = (routebox_t *) b; + ripout_livedraw_obj(box); + return PCB_R_DIR_NOT_FOUND; +} + +struct routeall_status { + /* --- for completion rate statistics ---- */ + int total_subnets; + /* total subnets routed without conflicts */ + int routed_subnets; + /* total subnets routed with conflicts */ + int conflict_subnets; + /* net failted entirely */ + int failed; + /* net was ripped */ + int ripped; + int total_nets_routed; +}; + +static double calculate_progress(double this_heap_item, double this_heap_size, struct routeall_status *ras) +{ + double total_passes = passes + smoothes + 1; /* + 1 is the refinement pass */ + double this_pass = AutoRouteParameters.pass - 1; /* Number passes from zero */ + double heap_fraction = (double) (ras->routed_subnets + ras->conflict_subnets + ras->failed) / (double) ras->total_subnets; + double pass_fraction = (this_heap_item + heap_fraction) / this_heap_size; + double process_fraction = (this_pass + pass_fraction) / total_passes; + + return process_fraction; +} + +struct routeall_status RouteAll(routedata_t * rd) +{ + struct routeall_status ras; + routeone_status_t ros; + pcb_bool rip; + int request_cancel; +#ifdef NET_HEAP + pcb_heap_t *net_heap; +#endif + pcb_heap_t *this_pass, *next_pass, *tmp; + routebox_t *net, *p, *pp; + pcb_cost_t total_net_cost, last_cost = 0, this_cost = 0; + int i; + int this_heap_size; + int this_heap_item; + + /* initialize heap for first pass; + * do smallest area first; that makes + * the subsequent costs more representative */ + this_pass = pcb_heap_create(); + next_pass = pcb_heap_create(); +#ifdef NET_HEAP + net_heap = pcb_heap_create(); +#endif + LIST_LOOP(rd->first_net, different_net, net); + { + double area; + pcb_box_t bb = shrink_routebox(net); + LIST_LOOP(net, same_net, p); + { + PCB_MAKE_MIN(bb.X1, p->sbox.X1); + PCB_MAKE_MIN(bb.Y1, p->sbox.Y1); + PCB_MAKE_MAX(bb.X2, p->sbox.X2); + PCB_MAKE_MAX(bb.Y2, p->sbox.Y2); + } + PCB_END_LOOP; + area = (double) (bb.X2 - bb.X1) * (bb.Y2 - bb.Y1); + pcb_heap_insert(this_pass, area, net); + } + PCB_END_LOOP; + + ras.total_nets_routed = 0; + /* refinement/finishing passes */ + for (i = 0; i <= passes + smoothes; i++) { +#ifdef ROUTE_VERBOSE + if (i > 0 && i <= passes) + printf("--------- STARTING REFINEMENT PASS %d ------------\n", i); + else if (i > passes) + printf("--------- STARTING SMOOTHING PASS %d -------------\n", i - passes); +#endif + ras.total_subnets = ras.routed_subnets = ras.conflict_subnets = ras.failed = ras.ripped = 0; + assert(pcb_heap_is_empty(next_pass)); + + this_heap_size = pcb_heap_size(this_pass); + for (this_heap_item = 0; !pcb_heap_is_empty(this_pass); this_heap_item++) { +#ifdef ROUTE_DEBUG + if (aabort) + break; +#endif + net = (routebox_t *) pcb_heap_remove_smallest(this_pass); + InitAutoRouteParameters(i, net->style, i < passes, i > passes, i == passes + smoothes); + if (i > 0) { + /* rip up all unfixed traces in this net ? */ + if (AutoRouteParameters.rip_always) + rip = pcb_true; + else { + rip = pcb_false; + LIST_LOOP(net, same_net, p); + if (p->flags.is_bad) { + rip = pcb_true; + break; + } + PCB_END_LOOP; + } + + LIST_LOOP(net, same_net, p); + p->flags.is_bad = 0; + if (!p->flags.fixed) { +#ifndef NDEBUG + pcb_bool del; +#endif + assert(!p->flags.homeless); + if (rip) { + RemoveFromNet(p, NET); + RemoveFromNet(p, SUBNET); + } + if (AutoRouteParameters.use_vias && p->type != VIA_SHADOW && p->type != PLANE) { + mtspace_remove(rd->mtspace, &p->box, p->flags.is_odd ? ODD : EVEN, p->style->Clearance); + if (!rip) + mtspace_add(rd->mtspace, &p->box, p->flags.is_odd ? EVEN : ODD, p->style->Clearance); + } + if (rip) { + if (conf_core.editor.live_routing) + ripout_livedraw_obj(p); +#ifndef NDEBUG + del = +#endif + pcb_r_delete_entry_free_data(rd->layergrouptree[p->group], &p->box, free); +#ifndef NDEBUG + assert(del); +#endif + } + else { + p->flags.is_odd = AutoRouteParameters.is_odd; + } + } + PCB_END_LOOP; + if (conf_core.editor.live_routing) + pcb_draw(); + /* reset to original connectivity */ + if (rip) { + ras.ripped++; + ResetSubnet(net); + } + else { + pcb_heap_insert(next_pass, 0, net); + continue; + } + } + /* count number of subnets */ + FOREACH_SUBNET(net, p); + ras.total_subnets++; + END_FOREACH(net, p); + /* the first subnet doesn't require routing. */ + ras.total_subnets--; + /* and re-route! */ + total_net_cost = 0; + /* only route that which isn't fully routed */ +#ifdef ROUTE_DEBUG + if (ras.total_subnets == 0 || aabort) +#else + if (ras.total_subnets == 0) +#endif + { + pcb_heap_insert(next_pass, 0, net); + continue; + } + + /* the loop here ensures that we get to all subnets even if + * some of them are unreachable from the first subnet. */ + LIST_LOOP(net, same_net, p); + { +#ifdef NET_HEAP + pcb_box_t b = shrink_routebox(p); + /* using a heap allows us to start from smaller objects and + * end at bigger ones. also prefer to start at planes, then pads */ + pcb_heap_insert(net_heap, (float) (b.X2 - b.X1) * +#if defined(ROUTE_RANDOMIZED) + (0.3 + pcb_rand() / (RAND_MAX + 1.0)) * +#endif + (b.Y2 - b.Y1) * (p->type == PLANE ? -1 : ((p->type == TERM) ? 1 : 10)), p); + } + PCB_END_LOOP; + ros.net_completely_routed = 0; + while (!pcb_heap_is_empty(net_heap)) { + p = (routebox_t *) pcb_heap_remove_smallest(net_heap); +#endif + if (!p->flags.fixed || p->flags.subnet_processed || p->type == OTHER) + continue; + + while (!ros.net_completely_routed) { + double percent; + + assert(no_expansion_boxes(rd)); + /* FIX ME: the number of edges to examine should be in autoroute parameters + * i.e. the 2000 and 800 hard-coded below should be controllable by the user + */ + ros = RouteOne(rd, p, NULL, ((AutoRouteParameters.is_smoothing ? 2000 : 800) * (i + 1)) * routing_layers); + total_net_cost += ros.best_route_cost; + if (ros.found_route) { + if (ros.route_had_conflicts) + ras.conflict_subnets++; + else { + ras.routed_subnets++; + ras.total_nets_routed++; + } + } + else { + if (!ros.net_completely_routed) + ras.failed++; + /* don't bother trying any other source in this subnet */ + LIST_LOOP(p, same_subnet, pp); + pp->flags.subnet_processed = 1; + PCB_END_LOOP; + break; + } + /* note that we can infer nothing about ras.total_subnets based + * on the number of calls to RouteOne, because we may be unable + * to route a net from a particular starting point, but perfectly + * able to route it from some other. */ + percent = calculate_progress(this_heap_item, this_heap_size, &ras); + request_cancel = pcb_hid_progress(percent * 100., 100, "Autorouting tracks"); + if (request_cancel) { + ras.total_nets_routed = 0; + ras.conflict_subnets = 0; + pcb_message(PCB_MSG_INFO, "Autorouting cancelled\n"); + goto out; + } + } + } +#ifndef NET_HEAP + PCB_END_LOOP; +#endif + if (!ros.net_completely_routed) + net->flags.is_bad = 1; /* don't skip this the next round */ + + /* Route easiest nets from this pass first on next pass. + * This works best because it's likely that the hardest + * is the last one routed (since it has the most obstacles) + * but it will do no good to rip it up and try it again + * without first changing any of the other routes + */ + pcb_heap_insert(next_pass, total_net_cost, net); + if (total_net_cost < EXPENSIVE) + this_cost += total_net_cost; + /* reset subnet_processed flags */ + LIST_LOOP(net, same_net, p); + { + p->flags.subnet_processed = 0; + } + PCB_END_LOOP; + } + /* swap this_pass and next_pass and do it all over again! */ + ro = 0; + assert(pcb_heap_is_empty(this_pass)); + tmp = this_pass; + this_pass = next_pass; + next_pass = tmp; +#if defined(ROUTE_DEBUG) || defined (ROUTE_VERBOSE) + printf + ("END OF PASS %d: %d/%d subnets routed without conflicts at cost %.0f, %d conflicts, %d failed %d ripped\n", + i, ras.routed_subnets, ras.total_subnets, this_cost, ras.conflict_subnets, ras.failed, ras.ripped); +#endif +#ifdef ROUTE_DEBUG + if (aabort) + break; +#endif + /* if no conflicts found, skip directly to smoothing pass! */ + if (ras.conflict_subnets == 0 && ras.routed_subnets == ras.total_subnets && i <= passes) + i = passes - (smoothes ? 0 : 1); + /* if no changes in a smoothing round, then we're done */ + if (this_cost == last_cost && i > passes && i < passes + smoothes) + i = passes + smoothes - 1; + last_cost = this_cost; + this_cost = 0; + } + + pcb_message(PCB_MSG_INFO, "%d of %d nets successfully routed.\n", ras.routed_subnets, ras.total_subnets); + +out: + pcb_heap_destroy(&this_pass); + pcb_heap_destroy(&next_pass); +#ifdef NET_HEAP + pcb_heap_destroy(&net_heap); +#endif + + /* no conflicts should be left at the end of the process. */ + assert(ras.conflict_subnets == 0); + + return ras; +} + +struct fpin_info { + pcb_pstk_t *ps; + pcb_coord_t x, y; + jmp_buf env; +}; + +static pcb_r_dir_t fpstk_rect(const pcb_box_t * b, void *cl) +{ + pcb_pstk_t *ps = (pcb_pstk_t *)b; + struct fpin_info *info = (struct fpin_info *) cl; + if (ps->x == info->x && ps->y == info->y) { + info->ps = ps; + longjmp(info->env, 1); + } + return PCB_R_DIR_NOT_FOUND; +} + +static int FindPin(const pcb_box_t *box, pcb_pstk_t **ps_out) +{ + struct fpin_info info; + + info.ps = NULL; + info.x = box->X1; + info.y = box->Y1; + if (setjmp(info.env) == 0) { + pcb_r_search(PCB->Data->padstack_tree, box, NULL, fpstk_rect, &info, NULL); + } + else { + *ps_out = info.ps; + return PCB_OBJ_PSTK; + } + + *ps_out = NULL; + return PCB_OBJ_VOID; +} + + +/* paths go on first 'on' layer in group */ +/* returns 'pcb_true' if any paths were added. */ +pcb_bool IronDownAllUnfixedPaths(routedata_t * rd) +{ + pcb_bool changed = pcb_false; + pcb_layer_t *layer; + routebox_t *net, *p; + int i; + LIST_LOOP(rd->first_net, different_net, net); + { + LIST_LOOP(net, same_net, p); + { + if (!p->flags.fixed) { + /* find first on layer in this group */ + assert(PCB->LayerGroups.grp[p->group].len > 0); + assert(is_layer_group_active[p->group]); + for (i = 0, layer = NULL; i < PCB->LayerGroups.grp[p->group].len; i++) { + layer = LAYER_PTR(PCB->LayerGroups.grp[p->group].lid[i]); + if (layer->meta.real.vis) + break; + } + assert(layer && layer->meta.real.vis); /*at least one layer must be on in this group! */ + assert(p->type != EXPANSION_AREA); + if (p->type == LINE) { + pcb_coord_t halfwidth = HALF_THICK(p->style->Thick); + double th = halfwidth * 2 + 1; + pcb_box_t b; + assert(p->parent.line == NULL); + /* orthogonal; thickness is 2*halfwidth */ + /* flip coordinates, if bl_to_ur */ + b = p->sbox; + total_wire_length += sqrt((b.X2 - b.X1 - th) * (b.X2 - b.X1 - th) + (b.Y2 - b.Y1 - th) * (b.Y2 - b.Y1 - th)); + b = pcb_shrink_box(&b, halfwidth); + if (b.X2 == b.X1 + 1) + b.X2 = b.X1; + if (b.Y2 == b.Y1 + 1) + b.Y2 = b.Y1; + if (p->flags.bl_to_ur) { + pcb_coord_t t; + t = b.X1; + b.X1 = b.X2; + b.X2 = t; + } + /* using CreateDrawn instead of CreateNew concatenates sequential lines */ + p->parent.line = pcb_line_new_merge + (layer, p->line.x1, p->line.y1, p->line.x2, p->line.y2, + p->style->Thick, p->style->Clearance * 2, pcb_flag_make(PCB_FLAG_AUTO | (conf_core.editor.clear_line ? PCB_FLAG_CLEARLINE : 0))); + + if (p->parent.line) { + pcb_undo_add_obj_to_create(PCB_OBJ_LINE, layer, p->parent.line, p->parent.line); + changed = pcb_true; + } + } + else if (p->type == VIA || p->type == VIA_SHADOW) { + routebox_t *pp = (p->type == VIA_SHADOW) ? p->parent.via_shadow : p; + pcb_coord_t radius = HALF_THICK(pp->style->Diameter); + pcb_box_t b = shrink_routebox(p); + total_via_count++; + assert(pp->type == VIA); + if (pp->parent.via == NULL) { + assert(labs((b.X1 + radius) - (b.X2 - radius)) < 2); + assert(labs((b.Y1 + radius) - (b.Y2 - radius)) < 2); +TODO("padstack: when style contains proto, remove this") + pp->parent.via = pcb_pstk_new_compat_via(PCB->Data, -1, + b.X1 + radius, b.Y1 + radius, + pp->style->Hole, pp->style->Diameter, 2 * pp->style->Clearance, 0, PCB_PSTK_COMPAT_ROUND, 1); + assert(pp->parent.via); + PCB_FLAG_SET(PCB_FLAG_AUTO, pp->parent.via); + if (pp->parent.via) { + pcb_undo_add_obj_to_create(PCB_OBJ_PSTK, pp->parent.via, pp->parent.via, pp->parent.via); + changed = pcb_true; + } + } + assert(pp->parent.via); + if (p->type == VIA_SHADOW) { + p->type = VIA; + p->parent.via = pp->parent.via; + } + } + else if (p->type == THERMAL) + /* nothing to do because, the via might not be there yet */ ; + else + assert(0); + } + } + PCB_END_LOOP; + /* loop again to place all the thermals now that the vias are down */ + LIST_LOOP(net, same_net, p); + { + if (p->type == THERMAL) { + pcb_pstk_t *pin = NULL; + /* thermals are alread a single point search, no need to shrink */ + int type = FindPin(&p->box, &pin); + if (pin) { + pcb_undo_add_obj_to_clear_poly(type, pin->parent.data, pin, pin, pcb_false); + pcb_poly_restore_to_poly(PCB->Data, PCB_OBJ_PSTK, LAYER_PTR(p->layer), pin); + pcb_undo_add_obj_to_flag(pin); + PCB_FLAG_THERM_ASSIGN(p->layer, autoroute_therm_style, pin); + pcb_undo_add_obj_to_clear_poly(type, pin->parent.data, pin, pin, pcb_true); + pcb_poly_clear_from_poly(PCB->Data, PCB_OBJ_PSTK, LAYER_PTR(p->layer), pin); + changed = pcb_true; + } + } + } + PCB_END_LOOP; + } + PCB_END_LOOP; + return changed; +} + +pcb_bool AutoRoute(pcb_bool selected) +{ + pcb_bool changed = pcb_false; + routedata_t *rd; + int i; + + total_wire_length = 0; + total_via_count = 0; + +#ifdef ROUTE_DEBUG + ddraw = pcb_gui->request_debug_draw(); + if (ddraw != NULL) { + ar_gc = ddraw->make_gc(); + ddraw->set_line_cap(ar_gc, pcb_cap_round); + } +#endif + + for (i = 0; i < vtroutestyle_len(&PCB->RouteStyle); i++) { + if (PCB->RouteStyle.array[i].Thick == 0 || + PCB->RouteStyle.array[i].Diameter == 0 || PCB->RouteStyle.array[i].Hole == 0 || PCB->RouteStyle.array[i].Clearance == 0) { + pcb_message(PCB_MSG_ERROR, "You must define proper routing styles\n" "before auto-routing.\n"); + return pcb_false; + } + } + if (ratlist_length(&PCB->Data->Rat) == 0) + return pcb_false; + rd = CreateRouteData(); + if (rd == NULL) { + pcb_message(PCB_MSG_ERROR, "Failed to initialize data; might be missing\n" "top or bottom copper layer.\n"); + return pcb_false; + } + + if (1) { + routebox_t *net, *rb, *last; + int i = 0; + /* count number of rats selected */ + PCB_RAT_LOOP(PCB->Data); + { + if (!selected || PCB_FLAG_TEST(PCB_FLAG_SELECTED, line)) + i++; + } + PCB_END_LOOP; +#ifdef ROUTE_VERBOSE + printf("%d nets!\n", i); +#endif + if (i == 0) + goto donerouting; /* nothing to do here */ + /* if only one rat selected, do things the quick way. =) */ + if (i == 1) { + PCB_RAT_LOOP(PCB->Data); + if (!selected || PCB_FLAG_TEST(PCB_FLAG_SELECTED, line)) { + /* look up the end points of this rat line */ + routebox_t *a; + routebox_t *b; + a = FindRouteBoxOnLayerGroup(rd, line->Point1.X, line->Point1.Y, line->group1); + b = FindRouteBoxOnLayerGroup(rd, line->Point2.X, line->Point2.Y, line->group2); + assert(a != NULL && b != NULL); + assert(a->style == b->style); +/* + if (a->type != PAD && b->type == PAD) + { + routebox_t *t = a; + a = b; + b = t; + } +*/ + /* route exactly one net, without allowing conflicts */ + InitAutoRouteParameters(0, a->style, pcb_false, pcb_true, pcb_true); + /* hace planes work better as sources than targets */ + changed = RouteOne(rd, a, b, 150000).found_route || changed; + goto donerouting; + } + PCB_END_LOOP; + } + /* otherwise, munge the netlists so that only the selected rats + * get connected. */ + /* first, separate all sub nets into separate nets */ + /* note that this code works because LIST_LOOP is clever enough not to + * be fooled when the list is changing out from under it. */ + last = NULL; + LIST_LOOP(rd->first_net, different_net, net); + { + FOREACH_SUBNET(net, rb); + { + if (last) { + last->different_net.next = rb; + rb->different_net.prev = last; + } + last = rb; + } + END_FOREACH(net, rb); + LIST_LOOP(net, same_net, rb); + { + rb->same_net = rb->same_subnet; + } + PCB_END_LOOP; + /* at this point all nets are equal to their subnets */ + } + PCB_END_LOOP; + if (last) { + last->different_net.next = rd->first_net; + rd->first_net->different_net.prev = last; + } + + /* now merge only those subnets connected by a rat line */ + PCB_RAT_LOOP(PCB->Data); + if (!selected || PCB_FLAG_TEST(PCB_FLAG_SELECTED, line)) { + /* look up the end points of this rat line */ + routebox_t *a; + routebox_t *b; + a = FindRouteBoxOnLayerGroup(rd, line->Point1.X, line->Point1.Y, line->group1); + b = FindRouteBoxOnLayerGroup(rd, line->Point2.X, line->Point2.Y, line->group2); + if (!a || !b) { +#ifdef DEBUG_STALE_RATS + pcb_undo_add_obj_to_flag(line); + PCB_FLAG_ASSIGN(PCB_FLAG_SELECTED, pcb_true, line); + pcb_rat_invalidate_draw(line, 0); +#endif /* DEBUG_STALE_RATS */ + pcb_message(PCB_MSG_ERROR, "The rats nest is stale! Aborting autoroute...\n"); + goto donerouting; + } + /* merge subnets into a net! */ + MergeNets(a, b, NET); + } + PCB_END_LOOP; + /* now 'different_net' may point to too many different nets. Reset. */ + LIST_LOOP(rd->first_net, different_net, net); + { + if (!net->flags.touched) { + LIST_LOOP(net, same_net, rb); + rb->flags.touched = 1; + PCB_END_LOOP; + } + else /* this is not a "different net"! */ + RemoveFromNet(net, DIFFERENT_NET); + } + PCB_END_LOOP; + /* reset "touched" flag */ + LIST_LOOP(rd->first_net, different_net, net); + { + LIST_LOOP(net, same_net, rb); + { + assert(rb->flags.touched); + rb->flags.touched = 0; + } + PCB_END_LOOP; + } + PCB_END_LOOP; + } + /* okay, rd's idea of netlist now corresponds to what we want routed */ + /* auto-route all nets */ + changed = (RouteAll(rd).total_nets_routed > 0) || changed; +donerouting: + pcb_hid_progress(0, 0, NULL); + if (conf_core.editor.live_routing) { + int i; + pcb_box_t big = { 0, 0, PCB_MAX_COORD, PCB_MAX_COORD }; + for (i = 0; i < pcb_max_group(PCB); i++) { + pcb_r_search(rd->layergrouptree[i], &big, NULL, ripout_livedraw_obj_cb, NULL, NULL); + } + } +#ifdef ROUTE_DEBUG + if (ddraw != NULL) + ddraw->finish_debug_draw(); +#endif + + if (changed) + changed = IronDownAllUnfixedPaths(rd); + pcb_message(PCB_MSG_INFO, "Total added wire length = %$mS, %d vias added\n", (pcb_coord_t) total_wire_length, total_via_count); + DestroyRouteData(&rd); + if (changed) { + pcb_undo_save_serial(); + + /* optimize rats, we've changed connectivity a lot. */ + pcb_rats_destroy(pcb_false /*all rats */ ); + pcb_undo_restore_serial(); + pcb_net_add_all_rats(PCB, PCB_RATACC_PRECISE); + pcb_undo_restore_serial(); + + pcb_undo_inc_serial(); + + pcb_redraw(); + } +#if defined (ROUTE_DEBUG) + aabort = 0; +#endif + return changed; +} Index: tags/2.1.2/src_plugins/autoroute/autoroute.h =================================================================== --- tags/2.1.2/src_plugins/autoroute/autoroute.h (nonexistent) +++ tags/2.1.2/src_plugins/autoroute/autoroute.h (revision 24813) @@ -0,0 +1,46 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * Copyright (C) 1998,1999,2000,2001 harry eaton + * + * this file, autoroute.h, was written and is + * Copyright (c) 2001 C. Scott Ananian. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + * + * Old contact info: + * harry eaton, 6697 Buttonhole Ct, Columbia, MD 21044 USA + * haceaton@aplcomm.jhuapl.edu + * + */ + +#ifndef PCB_AUTOROUTE_H +#define PCB_AUTOROUTE_H + +#include "config.h" +#include "board.h" + +pcb_bool AutoRoute(pcb_bool); + +#endif Index: tags/2.1.2/src_plugins/autoroute/autoroute.pup =================================================================== --- tags/2.1.2/src_plugins/autoroute/autoroute.pup (nonexistent) +++ tags/2.1.2/src_plugins/autoroute/autoroute.pup (revision 24813) @@ -0,0 +1,8 @@ +$class feature +$short the original autorouter +$long Automatically route selected or all rats. This is the original autorouter. +$package auto +$state works +default buildin +dep lib_compat_help +autoload 1 Index: tags/2.1.2/src_plugins/autoroute/mtspace.c =================================================================== --- tags/2.1.2/src_plugins/autoroute/mtspace.c (nonexistent) +++ tags/2.1.2/src_plugins/autoroute/mtspace.c (revision 24813) @@ -0,0 +1,525 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * Copyright (C) 1998,1999,2000,2001 harry eaton + * + * this file, mtspace.c, was written and is + * Copyright (c) 2001 C. Scott Ananian. + * Copyright (c) 2006 harry eaton. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + * + * Old contact info: + * harry eaton, 6697 Buttonhole Ct, Columbia, MD 21044 USA + * haceaton@aplcomm.jhuapl.edu + * + */ + + +/* implementation for "empty space" routines (needed for via-space tracking + * in the auto-router. + */ + +#include "config.h" + +#include +#include +#include + +#include "box.h" +#include "heap.h" +#include "rtree.h" +#include "mtspace.h" +#include "vector.h" + +/* mtspace data structures are built on r-trees. */ + +typedef struct mtspacebox { + const pcb_box_t box; + pcb_coord_t clearance; /* the smallest clearance around this box */ +} mtspacebox_t; + +/* this is an mtspace_t */ +struct mtspace { + /* rtrees keeping track of regions expanded by their required clearance. */ + /* one for fixed, even, and odd */ + pcb_rtree_t *ftree, *etree, *otree; +}; + +typedef union { + vector_t *v; + pcb_heap_t *h; +} heap_or_vector; + +/* this is a vetting_t */ +struct vetting { + heap_or_vector untested; + heap_or_vector no_fix; + heap_or_vector no_hi; + heap_or_vector hi_candidate; + pcb_coord_t radius; + pcb_coord_t clearance; + pcb_cheap_point_t desired; +}; + +#define SPECIAL 823157 + +mtspacebox_t *mtspace_create_box(const pcb_box_t * box, pcb_coord_t clearance) +{ + mtspacebox_t *mtsb; + assert(pcb_box_is_good(box)); + mtsb = (mtspacebox_t *) malloc(sizeof(*mtsb)); + /* the box was sent to us pre-bloated by the clearance amount */ + *((pcb_box_t *) & mtsb->box) = *box; + mtsb->clearance = clearance; + assert(pcb_box_is_good(&mtsb->box)); + return mtsb; +} + +/* create an "empty space" representation */ +mtspace_t *mtspace_create(void) +{ + mtspace_t *mtspace; + + /* create mtspace data structure */ + mtspace = (mtspace_t *) malloc(sizeof(*mtspace)); + mtspace->ftree = pcb_r_create_tree(); + mtspace->etree = pcb_r_create_tree(); + mtspace->otree = pcb_r_create_tree(); + /* done! */ + return mtspace; +} + +/* destroy an "empty space" representation. */ +void mtspace_destroy(mtspace_t ** mtspacep) +{ + assert(mtspacep); + pcb_r_free_tree_data((*mtspacep)->ftree, free); + pcb_r_free_tree_data((*mtspacep)->etree, free); + pcb_r_free_tree_data((*mtspacep)->otree, free); + pcb_r_destroy_tree(&(*mtspacep)->ftree); + pcb_r_destroy_tree(&(*mtspacep)->etree); + pcb_r_destroy_tree(&(*mtspacep)->otree); + free(*mtspacep); + *mtspacep = NULL; +} + +struct mts_info { + pcb_coord_t clearance; + pcb_box_t box; + pcb_rtree_t *tree; + jmp_buf env; +}; + +static pcb_r_dir_t mts_remove_one(const pcb_box_t * b, void *cl) +{ + struct mts_info *info = (struct mts_info *) cl; + mtspacebox_t *box = (mtspacebox_t *) b; + + /* there can be duplicate boxes, we just remove one */ + /* the info box is pre-bloated, so just check equality */ + if (b->X1 == info->box.X1 && b->X2 == info->box.X2 && + b->Y1 == info->box.Y1 && b->Y2 == info->box.Y2 && box->clearance == info->clearance) { + pcb_r_delete_entry_free_data(info->tree, b, free); + longjmp(info->env, 1); + } + return PCB_R_DIR_NOT_FOUND; +} + +pcb_rtree_t *which_tree(mtspace_t * mtspace, mtspace_type_t which) +{ + switch (which) { + case FIXED: + return mtspace->ftree; + case EVEN: + return mtspace->etree; + default: + return mtspace->otree; + } +} + +/* add a space-filler to the empty space representation. */ +void mtspace_add(mtspace_t * mtspace, const pcb_box_t * box, mtspace_type_t which, pcb_coord_t clearance) +{ + mtspacebox_t *filler = mtspace_create_box(box, clearance); + pcb_r_insert_entry(which_tree(mtspace, which), (const pcb_box_t *) filler); +} + +/* remove a space-filler from the empty space representation. */ +void mtspace_remove(mtspace_t * mtspace, const pcb_box_t * box, mtspace_type_t which, pcb_coord_t clearance) +{ + struct mts_info cl; + pcb_box_t small_search; + + cl.clearance = clearance; + cl.box = *box; + cl.tree = which_tree(mtspace, which); + small_search = pcb_box_center(box); + if (setjmp(cl.env) == 0) { + pcb_r_search(cl.tree, &small_search, NULL, mts_remove_one, &cl, NULL); + assert(0); /* didn't find it?? */ + } +} + +struct query_closure { + pcb_box_t *cbox; + heap_or_vector checking; + heap_or_vector touching; + pcb_cheap_point_t *desired; + pcb_coord_t radius, clearance; + jmp_buf env; + pcb_bool touch_is_vec; +}; + +static inline void heap_append(pcb_heap_t * heap, pcb_cheap_point_t * desired, pcb_box_t * newone) +{ + pcb_cheap_point_t p = *desired; + assert(desired); + pcb_closest_pcb_point_in_box(&p, newone); + pcb_heap_insert(heap, PCB_ABS(p.X - desired->X) + (p.Y - desired->Y), newone); +} + +static inline void append(struct query_closure *qc, pcb_box_t * newone) +{ + if (qc->desired) + heap_append(qc->checking.h, qc->desired, newone); + else + vector_append(qc->checking.v, newone); +} + +/* we found some space filler that may intersect this query. + * First check if it does intersect, then break it into + * overlaping regions that don't intersect this box. + */ +static pcb_r_dir_t query_one(const pcb_box_t * box, void *cl) +{ + struct query_closure *qc = (struct query_closure *) cl; + mtspacebox_t *mtsb = (mtspacebox_t *) box; + pcb_coord_t shrink; + +#ifndef NDEBUG + { + /* work around rounding errors: grow both boxes by 2 nm */ + pcb_box_t b1 = *qc->cbox, b2 = mtsb->box; + b1.X1--;b1.Y1--;b1.X2++;b1.Y2++; + b2.X1--;b2.Y1--;b2.X2++;b2.Y2++; + assert(pcb_box_intersect(&b1, &b2)); + } +#endif + + /* we need to satisfy the larger of the two clearances */ + if (qc->clearance > mtsb->clearance) + shrink = mtsb->clearance; + else + shrink = qc->clearance; + /* if we shrink qc->box by this amount and it doesn't intersect + * then we didn't actually touch this box */ + if (qc->cbox->X1 + shrink >= mtsb->box.X2 || + qc->cbox->X2 - shrink <= mtsb->box.X1 || qc->cbox->Y1 + shrink >= mtsb->box.Y2 || qc->cbox->Y2 - shrink <= mtsb->box.Y1) + return PCB_R_DIR_NOT_FOUND; + /* ok, we do touch this box, now create up to 4 boxes that don't */ + if (mtsb->box.Y1 > qc->cbox->Y1 + shrink) { /* top region exists */ + pcb_coord_t Y1 = qc->cbox->Y1; + pcb_coord_t Y2 = mtsb->box.Y1 + shrink; + if (Y2 - Y1 >= 2 * (qc->radius + qc->clearance)) { + pcb_box_t *newone = (pcb_box_t *) malloc(sizeof(pcb_box_t)); + newone->X1 = qc->cbox->X1; + newone->X2 = qc->cbox->X2; + newone->Y1 = Y1; + newone->Y2 = Y2; + assert(newone->Y2 < qc->cbox->Y2); + append(qc, newone); + } + } + if (mtsb->box.Y2 < qc->cbox->Y2 - shrink) { /* bottom region exists */ + pcb_coord_t Y1 = mtsb->box.Y2 - shrink; + pcb_coord_t Y2 = qc->cbox->Y2; + if (Y2 - Y1 >= 2 * (qc->radius + qc->clearance)) { + pcb_box_t *newone = (pcb_box_t *) malloc(sizeof(pcb_box_t)); + newone->X1 = qc->cbox->X1; + newone->X2 = qc->cbox->X2; + newone->Y2 = qc->cbox->Y2; + newone->Y1 = Y1; + assert(newone->Y1 > qc->cbox->Y1); + append(qc, newone); + } + } + if (mtsb->box.X1 > qc->cbox->X1 + shrink) { /* left region exists */ + pcb_coord_t X1 = qc->cbox->X1; + pcb_coord_t X2 = mtsb->box.X1 + shrink; + if (X2 - X1 >= 2 * (qc->radius + qc->clearance)) { + pcb_box_t *newone; + newone = (pcb_box_t *) malloc(sizeof(pcb_box_t)); + newone->Y1 = qc->cbox->Y1; + newone->Y2 = qc->cbox->Y2; + newone->X1 = qc->cbox->X1; + newone->X2 = X2; + assert(newone->X2 < qc->cbox->X2); + append(qc, newone); + } + } + if (mtsb->box.X2 < qc->cbox->X2 - shrink) { /* right region exists */ + pcb_coord_t X1 = mtsb->box.X2 - shrink; + pcb_coord_t X2 = qc->cbox->X2; + if (X2 - X1 >= 2 * (qc->radius + qc->clearance)) { + pcb_box_t *newone = (pcb_box_t *) malloc(sizeof(pcb_box_t)); + newone->Y1 = qc->cbox->Y1; + newone->Y2 = qc->cbox->Y2; + newone->X2 = qc->cbox->X2; + newone->X1 = X1; + assert(newone->X1 > qc->cbox->X1); + append(qc, newone); + } + } + if (qc->touching.v) { + if (qc->touch_is_vec || !qc->desired) + vector_append(qc->touching.v, qc->cbox); + else + heap_append(qc->touching.h, qc->desired, qc->cbox); + } + else + free(qc->cbox); /* done with this one */ + longjmp(qc->env, 1); + return PCB_R_DIR_FOUND_CONTINUE; /* never reached */ +} + +/* qloop takes a vector (or heap) of regions to check (checking) if they don't intersect + * anything. If a region does intersect something, it is broken into + * pieces that don't intersect that thing (if possible) which are + * put back into the vector/heap of regions to check. + * qloop returns pcb_false when it finds the first empty region + * it returns pcb_true if it has exhausted the region vector/heap and never + * found an empty area. + */ +static void qloop(struct query_closure *qc, pcb_rtree_t * tree, heap_or_vector res, pcb_bool is_vec) +{ + pcb_box_t *cbox; + int n; + + while (!(qc->desired ? pcb_heap_is_empty(qc->checking.h) : vector_is_empty(qc->checking.v))) { + cbox = qc->desired ? (pcb_box_t *) pcb_heap_remove_smallest(qc->checking.h) : (pcb_box_t *) vector_remove_last(qc->checking.v); + if (setjmp(qc->env) == 0) { + assert(pcb_box_is_good(cbox)); + qc->cbox = cbox; + pcb_r_search(tree, cbox, NULL, query_one, qc, &n); + assert(n == 0); + /* nothing intersected with this tree, put it in the result vector */ + if (is_vec) + vector_append(res.v, cbox); + else { + if (qc->desired) + heap_append(res.h, qc->desired, cbox); + else + vector_append(res.v, cbox); + } + return; /* found one - perhaps one answer is good enough */ + } + } +} + +/* free the memory used by the vetting structure */ +void mtsFreeWork(vetting_t ** w) +{ + vetting_t *work = (*w); + if (work->desired.X != -SPECIAL || work->desired.Y != -SPECIAL) { + pcb_heap_free(work->untested.h, free); + pcb_heap_destroy(&work->untested.h); + pcb_heap_free(work->no_fix.h, free); + pcb_heap_destroy(&work->no_fix.h); + pcb_heap_free(work->no_hi.h, free); + pcb_heap_destroy(&work->no_hi.h); + pcb_heap_free(work->hi_candidate.h, free); + pcb_heap_destroy(&work->hi_candidate.h); + } + else { + while (!vector_is_empty(work->untested.v)) + free(vector_remove_last(work->untested.v)); + vector_destroy(&work->untested.v); + while (!vector_is_empty(work->no_fix.v)) + free(vector_remove_last(work->no_fix.v)); + vector_destroy(&work->no_fix.v); + while (!vector_is_empty(work->no_hi.v)) + free(vector_remove_last(work->no_hi.v)); + vector_destroy(&work->no_hi.v); + while (!vector_is_empty(work->hi_candidate.v)) + free(vector_remove_last(work->hi_candidate.v)); + vector_destroy(&work->hi_candidate.v); + } + free(work); + (*w) = NULL; +} + + +/* returns some empty spaces in 'region' (or former narrowed regions) + * that may hold a feature with the specified radius and clearance + * It tries first to find Completely empty regions (which are appended + * to the free_space_vec vector). If that fails, it looks for regions + * filled only by objects generated by the previous pass (which are + * appended to the lo_conflict_space_vec vector). Then it looks for + * regions that are filled by objects generated during *this* pass + * (which are appended to the hi_conflict_space_vec vector). The + * current pass identity is given by 'is_odd'. As soon as one completely + * free region is found, it returns with that answer. It saves partially + * searched regions in vectors "untested", "no_fix", "no_hi", and + * "hi_candidate" which can be passed to future calls of this function + * to search harder for such regions if the computation becomes + * necessary. + */ +vetting_t *mtspace_query_rect(mtspace_t * mtspace, const pcb_box_t * region, + pcb_coord_t radius, pcb_coord_t clearance, + vetting_t * work, + vector_t * free_space_vec, + vector_t * lo_conflict_space_vec, + vector_t * hi_conflict_space_vec, pcb_bool is_odd, pcb_bool with_conflicts, pcb_cheap_point_t * desired) +{ + struct query_closure qc; + + /* pre-assertions */ + assert(free_space_vec); + assert(lo_conflict_space_vec); + assert(hi_conflict_space_vec); + /* search out to anything that might matter */ + if (region) { + pcb_box_t *cbox; + assert(work == NULL); + assert(pcb_box_is_good(region)); + assert(vector_is_empty(free_space_vec)); + assert(vector_is_empty(lo_conflict_space_vec)); + assert(vector_is_empty(hi_conflict_space_vec)); + work = (vetting_t *) malloc(sizeof(vetting_t)); + work->clearance = clearance; + work->radius = radius; + cbox = (pcb_box_t *) malloc(sizeof(pcb_box_t)); + *cbox = pcb_bloat_box(region, clearance + radius); + if (desired) { + work->untested.h = pcb_heap_create(); + work->no_fix.h = pcb_heap_create(); + work->hi_candidate.h = pcb_heap_create(); + work->no_hi.h = pcb_heap_create(); + assert(work->untested.h && work->no_fix.h && work->no_hi.h && work->hi_candidate.h); + pcb_heap_insert(work->untested.h, 0, cbox); + work->desired = *desired; + } + else { + work->untested.v = vector_create(); + work->no_fix.v = vector_create(); + work->hi_candidate.v = vector_create(); + work->no_hi.v = vector_create(); + assert(work->untested.v && work->no_fix.v && work->no_hi.v && work->hi_candidate.v); + vector_append(work->untested.v, cbox); + work->desired.X = work->desired.Y = -SPECIAL; + } + return work; + } + qc.clearance = work->clearance; + qc.radius = work->radius; + if (work->desired.X == -SPECIAL && work->desired.Y == -SPECIAL) + qc.desired = NULL; + else + qc.desired = &work->desired; + /* do the query */ + do { + heap_or_vector temporary; + temporary.v = free_space_vec; + + /* search the fixed object tree discarding any intersections + * and placing empty regions in the no_fix vector. + */ + qc.checking = work->untested; + qc.touching.v = NULL; + qloop(&qc, mtspace->ftree, work->no_fix, pcb_false); + /* search the hi-conflict tree placing intersectors in the + * hi_candidate vector (if conflicts are allowed) and + * placing empty regions in the no_hi vector. + */ + qc.checking.v = work->no_fix.v; + qc.touching.v = with_conflicts ? work->hi_candidate.v : NULL; + qc.touch_is_vec = pcb_false; + qloop(&qc, is_odd ? mtspace->otree : mtspace->etree, work->no_hi, pcb_false); + /* search the lo-conflict tree placing intersectors in the + * lo-conflict answer vector (if conflicts allowed) and + * placing emptry regions in the free-space answer vector. + */ + qc.checking = work->no_hi; +/* XXX lo_conflict_space_vec will be treated like a heap! */ + qc.touching.v = (with_conflicts ? lo_conflict_space_vec : NULL); + qc.touch_is_vec = pcb_true; + qloop(&qc, is_odd ? mtspace->etree : mtspace->otree, temporary, pcb_true); + + /* qloop (&qc, is_odd ? mtspace->etree : mtspace->otree, (heap_or_vector)free_space_vec, pcb_true); */ + if (!vector_is_empty(free_space_vec)) { + if (qc.desired) { + if (pcb_heap_is_empty(work->untested.h)) + break; + } + else { + if (vector_is_empty(work->untested.v)) + break; + } + return work; + } + /* finally check the hi-conflict intersectors against the + * lo-conflict tree discarding intersectors (two types of conflict is real bad) + * and placing empty regions in the hi-conflict answer vector. + */ + if (with_conflicts) { + heap_or_vector temporary; + temporary.v = hi_conflict_space_vec; + + qc.checking = work->hi_candidate; + qc.touching.v = NULL; + qloop(&qc, is_odd ? mtspace->etree : mtspace->otree, temporary, pcb_true); + + /* qloop (&qc, is_odd ? mtspace->etree : mtspace->otree, */ + /* (heap_or_vector)hi_conflict_space_vec, pcb_true); */ + } + } + while (!(qc.desired ? pcb_heap_is_empty(work->untested.h) : vector_is_empty(work->untested.v))); + if (qc.desired) { + if (pcb_heap_is_empty(work->no_fix.h) && pcb_heap_is_empty(work->no_hi.h) && pcb_heap_is_empty(work->hi_candidate.h)) { + mtsFreeWork(&work); + return NULL; + } + } + else { + if (vector_is_empty(work->no_fix.v) && vector_is_empty(work->no_hi.v) && vector_is_empty(work->hi_candidate.v)) { + mtsFreeWork(&work); + return NULL; + } + } + return work; +} + +int mtsBoxCount(vetting_t * w) +{ +#if 0 + int ans; + ans = 3 * vector_size(w->untested); + ans += 2 * vector_size(w->no_fix); + ans += vector_size(w->no_hi); + ans += vector_size(w->hi_candidate); + return ans; +#endif + return 100; +} Index: tags/2.1.2/src_plugins/autoroute/mtspace.h =================================================================== --- tags/2.1.2/src_plugins/autoroute/mtspace.h (nonexistent) +++ tags/2.1.2/src_plugins/autoroute/mtspace.h (revision 24813) @@ -0,0 +1,81 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * Copyright (C) 1998,1999,2000,2001 harry eaton + * + * this file, mtspace.h, was written and is + * Copyright (c) 2001 C. Scott Ananian. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + * + * Old contact info: + * harry eaton, 6697 Buttonhole Ct, Columbia, MD 21044 USA + * haceaton@aplcomm.jhuapl.edu + * + */ + +/* "empty space" routines (needed for via-space tracking in the auto-router. */ + +#ifndef PCB_MTSPACE_H +#define PCB_MTSPACE_H + +/* mtspace data structures are built on r-trees. */ + +#include "config.h" +#include "vector.h" /* for vector_t in mtspace_query_rect prototype */ + +typedef struct mtspace mtspace_t; +typedef enum { FIXED, ODD, EVEN } mtspace_type_t; +typedef struct vetting vetting_t; + +/* create an "empty space" representation with a shrunken boundary */ +mtspace_t *mtspace_create(void); +/* destroy an "empty space" representation. */ +void mtspace_destroy(mtspace_t ** mtspacep); + +/* -- mutation -- */ + +/* add a space-filler to the empty space representation. The given box + * should *not* be bloated; it should be "true". The feature will fill + * *at least* a radius of clearance around it; + */ +void mtspace_add(mtspace_t * mtspace, const pcb_box_t * box, mtspace_type_t which, pcb_coord_t clearance); +/* remove a space-filler from the empty space representation. The given box + * should *not* be bloated; it should be "true". The feature will fill + * *at least* a radius of clearance around it; + */ +void mtspace_remove(mtspace_t * mtspace, const pcb_box_t * box, mtspace_type_t which, pcb_coord_t clearance); + + +vetting_t *mtspace_query_rect(mtspace_t * mtspace, const pcb_box_t * region, + pcb_coord_t radius, pcb_coord_t clearance, + vetting_t * work, + vector_t * free_space_vec, + vector_t * lo_conflict_space_vec, + vector_t * hi_conflict_space_vec, pcb_bool is_odd, pcb_bool with_conflicts, pcb_cheap_point_t * desired); + +void mtsFreeWork(vetting_t **); +int mtsBoxCount(vetting_t *); + +#endif /* ! PCB_MTSPACE_H */ Index: tags/2.1.2/src_plugins/autoroute/vector.c =================================================================== --- tags/2.1.2/src_plugins/autoroute/vector.c (nonexistent) +++ tags/2.1.2/src_plugins/autoroute/vector.c (revision 24813) @@ -0,0 +1,206 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * Copyright (C) 1998,1999,2000,2001 harry eaton + * + * this file, vector.c, was written and is + * Copyright (c) 2001 C. Scott Ananian. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + * + * Old contact info: + * harry eaton, 6697 Buttonhole Ct, Columbia, MD 21044 USA + * haceaton@aplcomm.jhuapl.edu + * + */ + +/* operations on vectors. */ + +#include "config.h" + +#include +#include +#include + +#include "math_helper.h" +#include "vector.h" +#include "macro.h" + +struct vector_struct { + vector_element_t *element; + int size, max; +}; + +/* helper function for assertions */ +#ifndef NDEBUG +static int __vector_is_good(vector_t * vector) +{ + return vector && (vector->max == 0 || vector->element) && + (vector->max >= 0) && (vector->size >= 0) && (vector->size <= vector->max) && 1; +} +#endif /* !NDEBUG */ + +/* create an empty vector */ +vector_t *vector_create() +{ + vector_t *vector; + /* okay, create empty vector */ + vector = (vector_t *) calloc(1, sizeof(*vector)); + assert(vector); + assert(__vector_is_good(vector)); + return vector; +} + +/* destroy a vector */ +void vector_destroy(vector_t ** vector) +{ + assert(vector && *vector); + assert(__vector_is_good(*vector)); + if ((*vector)->element) + free((*vector)->element); + free(*vector); + *vector = NULL; +} + +/* -- interrogation -- */ +int vector_is_empty(vector_t * vector) +{ + assert(__vector_is_good(vector)); + return (vector->size == 0); +} + +int vector_size(vector_t * vector) +{ + assert(__vector_is_good(vector)); + return (vector->size); +} + +vector_element_t vector_element(vector_t * vector, int N) +{ + assert(__vector_is_good(vector)); + assert(N < vector->size); + return vector->element[N]; +} + +/* return the first element of the vector. */ +vector_element_t vector_element_first(vector_t * vector) +{ + assert(__vector_is_good(vector)); + assert(vector->size > 0); + return vector_element(vector, 0); +} + +/* return the last element of the vector. */ +vector_element_t vector_element_last(vector_t * vector) +{ + assert(__vector_is_good(vector)); + assert(vector->size > 0); + return vector_element(vector, vector->size - 1); +} + +/* -- mutation -- */ +/* add data to end of vector */ +void vector_append(vector_t * vector, vector_element_t data) +{ + vector_insert_many(vector, vector->size, &data, 1); +} + +void vector_append_many(vector_t * vector, vector_element_t data[], int count) +{ + vector_insert_many(vector, vector->size, data, count); +} + +void vector_append_vector(vector_t * vector, vector_t * other_vector) +{ + vector_append_many(vector, other_vector->element, other_vector->size); +} + +void vector_insert(vector_t * vector, int N, vector_element_t data) +{ + vector_insert_many(vector, N, &data, 1); +} + +/* add data at specified position of vector */ +void vector_insert_many(vector_t * vector, int N, vector_element_t data[], int count) +{ + assert(__vector_is_good(vector)); + assert(N <= vector->size); + if (count == 0) + return; + assert(data && count > 0); + if (vector->size + count > vector->max) { + vector->max = MAX(32, MAX(vector->size + count, vector->max * 2)); + vector->element = (void **) realloc(vector->element, vector->max * sizeof(*vector->element)); + } + memmove(vector->element + N + count, vector->element + N, (vector->size - N) * sizeof(*vector->element)); + memmove(vector->element + N, data, count * sizeof(*data)); + vector->size += count; + assert(__vector_is_good(vector)); +} + +vector_t *vector_duplicate(vector_t * orig) +{ + vector_t *newone = vector_create(); + if (!orig) + return newone; + newone->element = (void **) malloc(orig->max * sizeof(*orig->element)); + newone->max = orig->max; + newone->size = orig->size; + memcpy(newone->element, orig->element, orig->size * sizeof(vector_element_t)); + assert(__vector_is_good(newone)); + return newone; +} + +/* return and delete the *last* element of vector */ +vector_element_t vector_remove_last(vector_t * vector) +{ + assert(vector->size > 0); + return vector_remove(vector, vector->size - 1); +} + +/* return and delete data at specified position of vector */ +vector_element_t vector_remove(vector_t * vector, int N) +{ + vector_element_t old; + assert(__vector_is_good(vector)); + assert(N < vector->size); + old = vector->element[N]; + memmove(vector->element + N, vector->element + N + 1, (vector->size - (N + 1)) * sizeof(*vector->element)); + vector->size--; + assert(__vector_is_good(vector)); + return old; +} + +/* replace the data at the specified position with the given data. + * returns the old data. */ +vector_element_t vector_replace(vector_t * vector, vector_element_t data, int N) +{ + vector_element_t old; + assert(__vector_is_good(vector)); + assert(N < vector->size); + old = vector->element[N]; + vector->element[N] = data; + assert(__vector_is_good(vector)); + return old; +} Index: tags/2.1.2/src_plugins/autoroute/vector.h =================================================================== --- tags/2.1.2/src_plugins/autoroute/vector.h (nonexistent) +++ tags/2.1.2/src_plugins/autoroute/vector.h (revision 24813) @@ -0,0 +1,79 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * Copyright (C) 1998,1999,2000,2001 harry eaton + * + * this file, vector.h, was written and is + * Copyright (c) 2001 C. Scott Ananian. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + * + * Old contact info: + * harry eaton, 6697 Buttonhole Ct, Columbia, MD 21044 USA + * haceaton@aplcomm.jhuapl.edu + * + */ + +#ifndef PCB_VECTOR_H +#define PCB_VECTOR_H + +/* what a vector looks like */ +typedef struct vector_struct vector_t; +/* what data in a vector looks like */ +typedef void *vector_element_t; + +/* create an empty vector */ +vector_t *vector_create(); +/* destroy a vector */ +void vector_destroy(vector_t ** vector); +/* copy a vector */ +vector_t *vector_duplicate(vector_t * vector); + +/* -- interrogation -- */ +int vector_is_empty(vector_t * vector); +int vector_size(vector_t * vector); +vector_element_t vector_element(vector_t * vector, int N); +vector_element_t vector_element_first(vector_t * vector); +vector_element_t vector_element_last(vector_t * vector); + +/* -- mutation -- */ +/* add data to end of vector */ +void vector_append(vector_t * vector, vector_element_t data); +/* add multiple elements to end of vector */ +void vector_append_many(vector_t * vector, vector_element_t data[], int count); +/* add a vector of elements to the end of vector */ +void vector_append_vector(vector_t * vector, vector_t * other_vector); +/* add data at specified position of vector */ +void vector_insert(vector_t * vector, int N, vector_element_t data); +/* add multiple elements at specified position of vector */ +void vector_insert_many(vector_t * vector, int N, vector_element_t data[], int count); +/* return and delete the *last* element of vector */ +vector_element_t vector_remove_last(vector_t * vector); +/* return and delete data at specified position of vector */ +vector_element_t vector_remove(vector_t * vector, int N); +/* replace the data at the specified position with the given data. + * returns the old data. */ +vector_element_t vector_replace(vector_t * vector, vector_element_t data, int N); + +#endif /* PCB_VECTOR_H */ Index: tags/2.1.2/src_plugins/cam/Makefile =================================================================== --- tags/2.1.2/src_plugins/cam/Makefile (nonexistent) +++ tags/2.1.2/src_plugins/cam/Makefile (revision 24813) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_cam + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/2.1.2/src_plugins/cam/Plug.tmpasm =================================================================== --- tags/2.1.2/src_plugins/cam/Plug.tmpasm (nonexistent) +++ tags/2.1.2/src_plugins/cam/Plug.tmpasm (revision 24813) @@ -0,0 +1,12 @@ +put /local/pcb/mod {cam} +put /local/pcb/mod/OBJS [@ $(PLUGDIR)/cam/cam.o @] +put /local/pcb/mod/CONF {$(PLUGDIR)/cam/cam_conf.h} +put /local/pcb/mod/CONFFILE {cam.conf} +put /local/pcb/mod/CONFVAR {cam_conf_internal} + +switch /local/pcb/cam/controls + case {buildin} include /local/pcb/tmpasm/buildin; end; + case {plugin} include /local/pcb/tmpasm/plugin; end; + case {disable} include /local/pcb/tmpasm/disable; end; +end + Index: tags/2.1.2/src_plugins/cam/cam.c =================================================================== --- tags/2.1.2/src_plugins/cam/cam.c (nonexistent) +++ tags/2.1.2/src_plugins/cam/cam.c (revision 24813) @@ -0,0 +1,327 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * + * cam export jobs plugin + * pcb-rnd Copyright (C) 2018,2019 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "config.h" + +#include +#include +#include + +#include "board.h" +#include "hid_cam.h" +#include "hid_attrib.h" +#include "hid_init.h" +#include "hid_nogui.h" +#include "plugins.h" +#include "actions.h" +#include "cam_conf.h" +#include "compat_misc.h" +#include "safe_fs.h" +#include "../src_plugins/cam/conf_internal.c" + +static const char *cam_cookie = "cam exporter"; + +const conf_cam_t conf_cam; +#define CAM_CONF_FN "cam.conf" + +#include "cam_compile.c" + +static void cam_init_inst_fn(cam_ctx_t *ctx) +{ + if ((PCB != NULL) && (PCB->Filename != NULL)) { + char *fn = pcb_derive_default_filename_(PCB->Filename, ""); + char *val, *end = strrchr(fn, PCB_DIR_SEPARATOR_C); + if (end != NULL) + val = pcb_strdup(end+1); + else + val = pcb_strdup(fn); + pcb_cam_set_var(ctx->vars, pcb_strdup("base"), val); + free(fn); + } +} + +static void cam_init_inst(cam_ctx_t *ctx) +{ + memset(ctx, 0, sizeof(cam_ctx_t)); + + ctx->vars = pcb_cam_vars_alloc(); + cam_init_inst_fn(ctx); +} + +static void cam_uninit_inst(cam_ctx_t *ctx) +{ + pcb_cam_vars_free(ctx->vars); + cam_free_code(ctx); + free(ctx->prefix); + free(ctx->args); + gds_uninit(&ctx->tmp); +} + +/* look up a job by name in the config */ +static const char *cam_find_job(const char *job) +{ + conf_listitem_t *j; + int idx; + + conf_loop_list(&conf_cam.plugins.cam.jobs, j, idx) + if (strcmp(j->name, job) == 0) + return j->payload; + + return NULL; +} + +/* execute the instructions of a job specified by name */ +static int cam_call(const char *job, cam_ctx_t *ctx) +{ + const char *script = cam_find_job(job); + + if (script != NULL) { + if (cam_compile(ctx, script) != 0) + return -1; + return cam_exec(ctx); + } + + pcb_message(PCB_MSG_ERROR, "cam: can not find job configuration '%s'\n", job); + return -1; +} + +static int cam_parse_opt_outfile(cam_ctx_t *ctx, const char *optval) +{ + char *fn, *tmp = pcb_strdup(optval); + int dirlen = prefix_mkdir(tmp, &fn); + + free(ctx->prefix); + if (dirlen > 0) { + ctx->prefix = malloc(dirlen+2); + memcpy(ctx->prefix, optval, dirlen); + ctx->prefix[dirlen] = PCB_DIR_SEPARATOR_C; + ctx->prefix[dirlen+1] = '\0'; + } + else + ctx->prefix = NULL; + pcb_cam_set_var(ctx->vars, pcb_strdup("base"), pcb_strdup(fn)); + free(tmp); + return 0; +} + +static int cam_parse_set_var(cam_ctx_t *ctx, const char *opt) +{ + char *key, *val, *sep = strchr(opt, '='); + + if (sep == NULL) + return 1; + + key = pcb_strndup(opt, sep-opt); + val = pcb_strdup(sep+1); + pcb_cam_set_var(ctx->vars, key, val); + return 0; +} + +static int cam_parse_opt(cam_ctx_t *ctx, const char *opt) +{ + if (strncmp(opt, "outfile=", 8) == 0) + return cam_parse_opt_outfile(ctx, opt+8); + else + return cam_parse_set_var(ctx, opt); + + return 1; +} + +#include "cam_gui.c" + +static const char pcb_acts_cam[] = "cam(exec, script, [options])\ncam(call, jobname, [options])\ncam([gui])"; +static const char pcb_acth_cam[] = "Export jobs for feeding cam processes"; +static fgw_error_t pcb_act_cam(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + cam_ctx_t ctx; + const char *cmd = "gui", *arg = NULL, *opt; + int n, rs = -1; + + PCB_ACT_MAY_CONVARG(1, FGW_STR, cam, cmd = argv[1].val.str); + PCB_ACT_MAY_CONVARG(2, FGW_STR, cam, arg = argv[2].val.str); + + cam_init_inst(&ctx); + for(n = 3; n < argc; n++) { + PCB_ACT_CONVARG(n, FGW_STR, cam, opt = argv[n].val.str); + if (cam_parse_opt(&ctx, opt) != 0) { + pcb_message(PCB_MSG_ERROR, "cam: invalid action option '%s'\n", opt); + cam_uninit_inst(&ctx); + PCB_ACT_IRES(1); + return 0; + } + } + + if (pcb_strcasecmp(cmd, "gui") == 0) { + rs = cam_gui(arg); + } + else { + if (arg == NULL) { + pcb_message(PCB_MSG_ERROR, "cam: need one more argument for '%s'\n", cmd); + cam_uninit_inst(&ctx); + PCB_ACT_IRES(1); + return 0; + } + if (pcb_strcasecmp(cmd, "exec") == 0) { + rs = cam_compile(&ctx, arg); + if (rs == 0) + rs = cam_exec(&ctx); + } + else if (pcb_strcasecmp(cmd, "call") == 0) + rs = cam_call(arg, &ctx); + } + + cam_uninit_inst(&ctx); + PCB_ACT_IRES(rs); + return 0; +} + + +static pcb_action_t cam_action_list[] = { + {"cam", pcb_act_cam, pcb_acth_cam, pcb_acts_cam} +}; + +PCB_REGISTER_ACTIONS(cam_action_list, cam_cookie) + + +static pcb_hid_attribute_t *export_cam_get_export_options(int *n) +{ + return 0; +} + +static int export_cam_usage(const char *topic) +{ + fprintf(stderr, "\nThe cam exporter shorthand:\n\n"); + fprintf(stderr, "\nUsage: pcb-rnd -x cam jobname [cam-opts] [pcb-rnd-options] filename"); + fprintf(stderr, "\n\ncam-opts:"); + fprintf(stderr, "\n --outfile path set the output file path (affets prefix and %%base%%)"); + fprintf(stderr, "\n -o key=value set %%key%% to value"); + fprintf(stderr, "\n\n"); + return 0; +} + +static char *cam_export_job; +static cam_ctx_t cam_export_ctx; +static int cam_export_has_outfile; +static int export_cam_parse_arguments(int *argc, char ***argv) +{ + int d, s, oargc; + if (*argc < 1) { + pcb_message(PCB_MSG_ERROR, "-x cam needs a job name\n"); + return -1; + } + + cam_export_has_outfile = 0; + cam_init_inst(&cam_export_ctx); + cam_export_job = pcb_strdup((*argv)[0]); + oargc = (*argc); + (*argc)--; + for(d = 0, s = 1; s < oargc; s++) { + char *opt = (*argv)[s]; + if (strcmp(opt, "--outfile") == 0) { + s++; (*argc)--; + cam_parse_opt_outfile(&cam_export_ctx, (*argv)[s]); + cam_export_has_outfile = 1; + } + else if (strcmp(opt, "-o") == 0) { + s++; (*argc)--; + if (cam_parse_set_var(&cam_export_ctx, (*argv)[s]) != 0) { + pcb_message(PCB_MSG_ERROR, "cam -o requires a key=value argument\n"); + goto err; + } + } + else { /* copy over for pcb */ + (*argv)[d] = opt; + d++; + } + } + return 0; + + err:; + cam_uninit_inst(&cam_export_ctx); + free(cam_export_job); + cam_export_job = NULL; + return 1; +} + +static void export_cam_do_export(pcb_hid_attr_val_t *options) +{ + if (!cam_export_has_outfile) + cam_init_inst_fn(&cam_export_ctx); + + if (cam_call(cam_export_job, &cam_export_ctx) != 0) + pcb_message(PCB_MSG_ERROR, "CAM job %s failed\n", cam_export_job); + + cam_uninit_inst(&cam_export_ctx); + free(cam_export_job); + cam_export_job = NULL; +} + +int pplg_check_ver_cam(int ver_needed) { return 0; } + +void pplg_uninit_cam(void) +{ + conf_unreg_file(CAM_CONF_FN, cam_conf_internal); + conf_unreg_fields("plugins/cam/"); + pcb_remove_actions_by_cookie(cam_cookie); + pcb_hid_remove_attributes_by_cookie(cam_cookie); +} + +pcb_hid_t export_cam_hid; + +#include "dolists.h" +int pplg_init_cam(void) +{ + PCB_API_CHK_VER; + conf_reg_file(CAM_CONF_FN, cam_conf_internal); +#define conf_reg(field,isarray,type_name,cpath,cname,desc,flags) \ + conf_reg_field(conf_cam, field,isarray,type_name,cpath,cname,desc,flags); +#include "cam_conf_fields.h" + + PCB_REGISTER_ACTIONS(cam_action_list, cam_cookie) + + memset(&export_cam_hid, 0, sizeof(pcb_hid_t)); + + pcb_hid_nogui_init(&export_cam_hid); + + export_cam_hid.struct_size = sizeof(pcb_hid_t); + export_cam_hid.name = "cam"; + export_cam_hid.description = "Shorthand for exporting by can job name"; + export_cam_hid.exporter = 1; + export_cam_hid.hide_from_gui = 1; + + export_cam_hid.get_export_options = export_cam_get_export_options; + export_cam_hid.do_export = export_cam_do_export; + export_cam_hid.parse_arguments = export_cam_parse_arguments; + + export_cam_hid.usage = export_cam_usage; + + pcb_hid_register_hid(&export_cam_hid); + return 0; + + return 0; +} Index: tags/2.1.2/src_plugins/cam/cam.conf =================================================================== --- tags/2.1.2/src_plugins/cam/cam.conf (nonexistent) +++ tags/2.1.2/src_plugins/cam/cam.conf (revision 24813) @@ -0,0 +1,194 @@ +li:pcb-rnd-conf-v1 { + ha:overwrite { + ha:plugins { + ha:cam { + li:jobs { + doc_png { + desc export top and bottom copper and silk in 600 DPI pngs + plugin png --dpi 600 + write %base%.top.png=top-copper,top-silk + write %base%.bottom.png=bottom-copper,bottom-silk + } + {gerber:eagle} { + desc gerber export compatible with Eagle's gerber file names + plugin gerber --all-layers + write %base%.cmp=top-copper + write %base%.sol=bottom-copper + write %base%.ly%top_offs+1%=intern-copper + write %base%.plc=top-silk + write %base%.pls=bottom-silk + write %base%.stc=top-mask + write %base%.sts=bottom-mask + write %base%.crc=top-paste + write %base%.crs=bottom-paste + write %base%.oln=boundary + write %base%.ast=top-virtual(purpose=assy) + write %base%.asb=bottom-virtual(purpose=assy) + write %base%.fab=virtual(purpose=fab) + plugin excellon + write %base%.drd=virtual(purpose=pdrill) + write %base%.dru=virtual(purpose=udrill) + } + {gerber:fixed_topbottom} { + desc gerber export almost compatible with old 'fixed' naming style, with special casing top and bottom copper + plugin gerber --all-layers + write %base%.top.gbr=top-copper + write %base%.bottom.gbr=bottom-copper + write %base%.group%top_offs%=intern-copper + write %base%.topsilk.gbr=top-silk + write %base%.bottomsilk.gbr=bottom-silk + write %base%.topmask.gbr=top-mask + write %base%.bottommask.gbr=bottom-mask + write %base%.toppaste.gbr=top-paste + write %base%.bottompaste.gbr=bottom-paste + write %base%.outline.gbr=boundary + write %base%.topassy.gbr=top-virtual(purpose=assy) + write %base%.bottomassy.gbr=bottom-virtual(purpose=assy) + write %base%.fab.gbr=virtual(purpose=fab) + plugin excellon + write %base%.plated-drill.cnc=virtual(purpose=pdrill) + write %base%.unplated-drill.cnc=virtual(purpose=udrill) + } + {gerber:fixed} { + desc gerber export almost compatible with old 'fixed' - top and bottom copper are not special cased but numbered from group0 (top) + plugin gerber --all-layers + write %base%.group%top_offs%.gbr=top-copper + write %base%.group%top_offs%.gbr=bottom-copper + write %base%.group%top_offs%.gbr=intern-copper + write %base%.topsilk.gbr=top-silk + write %base%.bottomsilk.gbr=bottom-silk + write %base%.topmask.gbr=top-mask + write %base%.bottommask.gbr=bottom-mask + write %base%.toppaste.gbr=top-paste + write %base%.bottompaste.gbr=bottom-paste + write %base%.outline.gbr=boundary + write %base%.topassy.gbr=top-virtual(purpose=assy) + write %base%.bottomassy.gbr=bottom-virtual(purpose=assy) + write %base%.fab.gbr=virtual(purpose=fab) + plugin excellon + write %base%.plated-drill.cnc=virtual(purpose=pdrill) + write %base%.unplated-drill.cnc=virtual(purpose=udrill) + } + {gerber:universal} { + desc gerber export compatible with old 'univeral' include group name and suffix with eagle-like extensions + plugin gerber --all-layers + write %base%.%name%.gtl=top-copper + write %base%.%name%.gbl=bottom-copper + write %base%.%name%.g%top_offs%=intern-copper + write %base%.%name%.gto=top-silk + write %base%.%name%.gbo=bottom-silk + write %base%.%name%.gts=top-mask + write %base%.%name%.gbs=bottom-mask + write %base%.%name%.gtp=top-paste + write %base%.%name%.gbp=bottom-paste + write %base%.%name%.gko=boundary + write %base%.fab=virtual(purpose=fab) + plugin excellon + write %base%.drl=virtual(purpose=pdrill) + write %base%_NPTH.drl=virtual(purpose=udrill) + } + {gerber:OSH_Park} { + desc gerber export compatible with OSH Park's recommendations + plugin gerber --all-layers + write %base%.gtl=top-copper + write %base%.gbl=bottom-copper + write %base%.g%top_offs+1%l=intern-copper + write %base%.gto=top-silk + write %base%.gbo=bottom-silk + write %base%.gts=top-mask + write %base%.gbs=bottom-mask + write %base%.gtp=top-paste + write %base%.gbp=bottom-paste + write %base%.gko=boundary + write %base%.ast=top-virtual(purpose=assy) + write %base%.asb=bottom-virtual(purpose=assy) + write %base%.fab=virtual(purpose=fab) + plugin excellon + write %base%.xln=virtual(purpose=pdrill),virtual(purpose=udrill) + } + {gerber:Seeed} { + desc gerber export compatible with Seeed Studio's recommendations + plugin gerber + write %base%.GTL=top-copper + write %base%.GBL=bottom-copper + write %base%.GL%top_offs+1%=intern-copper + write %base%.GTO=top-silk + write %base%.GBO=bottom-silk + write %base%.GTS=top-mask + write %base%.GBS=bottom-mask + write %base%.GTP=top-paste + write %base%.GBP=bottom-paste + write %base%.GML=boundary + write %base%.AST=top-virtual(purpose=assy) + write %base%.ASB=bottom-virtual(purpose=assy) + write %base%.FAB=virtual(purpose=fab) + plugin excellon + write %base%.TXT=virtual(purpose=pdrill),virtual(purpose=udrill) + } +# JLC job tested and contributed by keantoken + {gerber:JLC_PCB} { + desc gerber export for JLC PCB's filename convention + plugin gerber + write %base%.gtl=top-copper + write %base%.gbl=bottom-copper + write %base%.g%top_offs+1%l=intern-copper + write %base%.gto=top-silk + write %base%.gbo=bottom-silk + write %base%.gts=top-mask + write %base%.gbs=bottom-mask + write %base%.gtp=top-paste + write %base%.gbp=bottom-paste + write %base%.gko=boundary + write %base%.ast=top-virtual(purpose=assy) + write %base%.asb=bottom-virtual(purpose=assy) + write %base%.fab=virtual(purpose=fab) + plugin excellon + write %base%.xln=virtual(purpose=pdrill),virtual(purpose=udrill) + } + +# protel job tested and contributed by keantoken + {gerber:protel} { + desc gerber export for a filename convention similar to protel's + plugin gerber + write %base%.gtl=top-copper + write %base%.gbl=bottom-copper + write %base%.g%top_offs+1%l=intern-copper + write %base%.gto=top-silk + write %base%.gbo=bottom-silk + write %base%.gts=top-mask + write %base%.gbs=bottom-mask + write %base%.gtp=top-paste + write %base%.gbp=bottom-paste + write %base%.gko=boundary + write %base%.ast=top-virtual(purpose=assy) + write %base%.asb=bottom-virtual(purpose=assy) + write %base%.fab=virtual(purpose=fab) + plugin excellon + write %base%.xln=virtual(purpose=pdrill),virtual(purpose=udrill) + } + + {gerber:orcad} { + desc gerber export compatible with Orcad's gerber file names + plugin gerber --all-layers + write %base%.top=top-copper + write %base%.bot=bottom-copper +# write %base%.ly%top_offs+1%=intern-copper + write %base%.sst=top-silk + write %base%.ssb=bottom-silk + write %base%.smt=top-mask + write %base%.smb=bottom-mask +# write %base%.spt=top-paste +# write %base%.spb=bottom-paste + write %base%.fab=boundary +# write %base%.ast=top-virtual(purpose=assy) +# write %base%.asb=bottom-virtual(purpose=assy) +# write %base%.fab.gbr=virtual(purpose=fab) + plugin excellon + write %base%.thruhole.tap=virtual(purpose=pdrill) + write %base%.thruhole-unplated.tap=virtual(purpose=udrill) + } + } + } + } + } +} Index: tags/2.1.2/src_plugins/cam/cam.pup =================================================================== --- tags/2.1.2/src_plugins/cam/cam.pup (nonexistent) +++ tags/2.1.2/src_plugins/cam/cam.pup (revision 24813) @@ -0,0 +1,7 @@ +$class export +$short cam/job based export +$long Configurable output job based batch exporting +$state WIP +$package export +default buildin +autoload 1 Index: tags/2.1.2/src_plugins/cam/cam_compile.c =================================================================== --- tags/2.1.2/src_plugins/cam/cam_compile.c (nonexistent) +++ tags/2.1.2/src_plugins/cam/cam_compile.c (revision 24813) @@ -0,0 +1,264 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * + * cam export jobs plugin - compile/decompile jobs + * pcb-rnd Copyright (C) 2019 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#define GVT_DONT_UNDEF +#include "cam_compile.h" +#include "layer_vis.h" +#include "event.h" +#include + +/* mkdir -p on arg - changes the string in arg */ +static int prefix_mkdir(char *arg, char **filename) +{ + char *curr, *next, *end; + int res; + + /* mkdir -p if there's a path sep in the prefix */ + end = strrchr(arg, PCB_DIR_SEPARATOR_C); + if (end == NULL) { + if (filename != NULL) + *filename = arg; + return 0; + } + + *end = '\0'; + res = end - arg; + if (filename != NULL) + *filename = end+1; + + for(curr = arg; curr != NULL; curr = next) { + next = strrchr(curr, PCB_DIR_SEPARATOR_C); + if (next != NULL) + *next = '\0'; + pcb_mkdir(arg, 0755); + if (next != NULL) { + *next = PCB_DIR_SEPARATOR_C; + next++; + } + } + return res; +} + +static int cam_exec_inst(cam_ctx_t *ctx, pcb_cam_code_t *code) +{ + int argc; + char **argv; + + switch(code->inst) { + case PCB_CAM_DESC: + /* ignore */ + break; + + case PCB_CAM_WRITE: + if (ctx->exporter == NULL) { + pcb_message(PCB_MSG_ERROR, "cam: no exporter selected before write\n"); + return -1; + } + + /* build the --cam args using the prefix */ + ctx->argv[0] = "--cam"; + gds_truncate(&ctx->tmp, 0); + if (ctx->prefix != NULL) + gds_append_str(&ctx->tmp, ctx->prefix); + gds_append_str(&ctx->tmp, code->op.write.arg); + ctx->argv[1] = ctx->tmp.array; + + argc = ctx->argc; + argv = ctx->argv; + if (ctx->exporter->parse_arguments(&argc, &argv) != 0) { + pcb_message(PCB_MSG_ERROR, "cam: exporter '%s' refused the arguments\n", code->op.write.arg); + return -1; + } + + { /* call the exporter */ + void *old_vars, *tmp; + old_vars = pcb_cam_vars_use(ctx->vars); + ctx->exporter->do_export(0); + tmp = pcb_cam_vars_use(old_vars); + assert(tmp == ctx->vars); /* we must be restoring from our own context else the recursion is broken */ + } + + ctx->argv[0] = NULL; + ctx->argv[1] = NULL; + break; + + case PCB_CAM_PLUGIN: + ctx->exporter = code->op.plugin.exporter; + ctx->argc = code->op.plugin.argc; + ctx->argv = code->op.plugin.argv; + break; + + default: + assert(!"invalid cam code"); + } + return 0; +} + + +static int cam_exec(cam_ctx_t *ctx) +{ + int n, save_ons[PCB_MAX_LAYER + 2], have_gui; + + have_gui = (pcb_gui != NULL) && pcb_gui->gui; + if (have_gui) + pcb_hid_save_and_show_layer_ons(save_ons); + + for(n = 0; n < ctx->code.used; n++) + if (cam_exec_inst(ctx, &ctx->code.array[n]) != 0) + return 1; + + if (have_gui) { + pcb_hid_restore_layer_ons(save_ons); + pcb_event(PCB_EVENT_LAYERVIS_CHANGED, NULL); + } + return 0; +} + +static int cam_compile_line(cam_ctx_t *ctx, char *cmd, char *arg, pcb_cam_code_t *code) +{ + + if (strcmp(cmd, "desc") == 0) { + code->inst = PCB_CAM_DESC; + code->op.desc.arg = pcb_strdup(arg); + } + else if (strcmp(cmd, "write") == 0) { + code->inst = PCB_CAM_WRITE; + code->op.write.arg = pcb_strdup(arg); + } + else if (strcmp(cmd, "plugin") == 0) { + char *curr, *next; + int maxa; + char *s; + + code->inst = PCB_CAM_PLUGIN; + curr = strpbrk(arg, " \t"); + if (curr != NULL) { + *curr = '\0'; + curr++; + } + code->op.plugin.exporter = pcb_hid_find_exporter(arg); + if (code->op.plugin.exporter == NULL) { + pcb_message(PCB_MSG_ERROR, "cam: can not find export plugin: '%s'\n", arg); + return -1; + } + free(ctx->args); + + curr = pcb_strdup(curr == NULL ? "" : curr); + for(maxa = 0, s = curr; *s != '\0'; s++) + if (isspace(*s)) + maxa++; + + code->op.plugin.argc = 2; /* [0] and [1] are reserved for the --cam argument */ + code->op.plugin.argv = malloc(sizeof(char *) * (maxa+3)); + code->op.plugin.argv[0] = NULL; + code->op.plugin.argv[1] = NULL; + if (code->op.plugin.argv == NULL) + return 1; + for(; curr != NULL; curr = next) { + while(isspace(*curr)) curr++; + next = strpbrk(curr, " \t"); + if (next != NULL) { + *next = '\0'; + next++; + } + if (*curr == '\0') + continue; + code->op.plugin.argv[code->op.plugin.argc] = pcb_strdup(curr); + code->op.plugin.argc++; + + } + code->op.plugin.argv[ctx->argc] = NULL; + } + else { + pcb_message(PCB_MSG_ERROR, "cam: syntax error (unknown instruction): '%s'\n", cmd); + return -1; + } + return 0; +} + +static int cam_compile(cam_ctx_t *ctx, const char *script_in) +{ + char *arg, *curr, *next, *script = pcb_strdup(script_in); + int res = 0, r; + + for(curr = script; curr != NULL; curr = next) { + pcb_cam_code_t code; + + while(isspace(*curr)) curr++; + next = strpbrk(curr, ";\r\n"); + if (next != NULL) { + *next = '\0'; + next++; + } + if (*curr == '\0') + continue; + arg = strpbrk(curr, " \t"); + if (arg != NULL) { + *arg = '\0'; + arg++; + } + if ((*curr == '#') || (*curr == '\0')) + continue; + r = cam_compile_line(ctx, curr, arg, &code); + if (r == 0) + vtcc_append(&ctx->code, code); + else + res = 1; + } + + free(script); + return res; +} + +static void cam_free_inst(cam_ctx_t *ctx, pcb_cam_code_t *code) +{ + int n; + + switch(code->inst) { + case PCB_CAM_DESC: + break; + + case PCB_CAM_WRITE: + free(code->op.write.arg); + break; + + case PCB_CAM_PLUGIN: + for(n = 0; n < code->op.plugin.argc; n++) + free(code->op.plugin.argv[n]); + free(code->op.plugin.argv); + break; + } +} + +static void cam_free_code(cam_ctx_t *ctx) +{ + int n; + for(n = 0; n < ctx->code.used; n++) + cam_free_inst(ctx, &ctx->code.array[n]); + vtcc_uninit(&ctx->code); +} Index: tags/2.1.2/src_plugins/cam/cam_compile.h =================================================================== --- tags/2.1.2/src_plugins/cam/cam_compile.h (nonexistent) +++ tags/2.1.2/src_plugins/cam/cam_compile.h (revision 24813) @@ -0,0 +1,85 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * + * cam export jobs plugin - compile/decompile jobs + * pcb-rnd Copyright (C) 2019 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#ifndef PCB_CAM_COMPILE_H +#define PCB_CAM_COMPILE_H + +typedef enum { + PCB_CAM_DESC, + PCB_CAM_PLUGIN, + PCB_CAM_WRITE +} pcb_cam_inst_t; + +typedef struct { + pcb_cam_inst_t inst; + union { + struct { + char *arg; + } desc; + struct { + pcb_hid_t *exporter; + int argc; + char **argv; + } plugin; + struct { + char *arg; + } write; + struct { + char *arg; + } prefix; + } op; +} pcb_cam_code_t; + +#define GVT(x) vtcc_ ## x +#define GVT_ELEM_TYPE pcb_cam_code_t +#define GVT_SIZE_TYPE size_t +#define GVT_DOUBLING_THRS 4096 +#define GVT_START_SIZE 32 +#define GVT_FUNC +#define GVT_SET_NEW_BYTES_TO 0 + +#include +#define GVT_REALLOC(vect, ptr, size) realloc(ptr, size) +#define GVT_FREE(vect, ptr) free(ptr) +#include + +typedef struct { + char *prefix; /* strdup'd file name prefix from the last prefix command */ + pcb_hid_t *exporter; + + char *args; /* strdup'd argument string from the last plugin command - already split up */ + char **argv; /* [0] and [1] are for --cam; the rest point into args */ + int argc; + + vtcc_t code; + void *vars; + + gds_t tmp; +} cam_ctx_t; + +#endif Index: tags/2.1.2/src_plugins/cam/cam_conf.h =================================================================== --- tags/2.1.2/src_plugins/cam/cam_conf.h (nonexistent) +++ tags/2.1.2/src_plugins/cam/cam_conf.h (revision 24813) @@ -0,0 +1,14 @@ +#ifndef PCB_VENDOR_CONF_H +#define PCB_VENDOR_CONF_H + +#include "conf.h" + +typedef struct { + const struct plugins { + const struct cam { + CFT_LIST jobs; /* named cam scripts */ + } cam; + } plugins; +} conf_cam_t; + +#endif Index: tags/2.1.2/src_plugins/cam/cam_gui.c =================================================================== --- tags/2.1.2/src_plugins/cam/cam_gui.c (nonexistent) +++ tags/2.1.2/src_plugins/cam/cam_gui.c (revision 24813) @@ -0,0 +1,356 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * + * cam export jobs plugin: GUI dialog + * pcb-rnd Copyright (C) 2019 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include +#include "hid_dad.h" +#include "hid_dad_tree.h" + +static const char *OUTFILE_HELP = "Output file name sample, which will\nbe split to prefix and base name (%base%)\nto be used in file name templates"; +static const char *PREFIX_HELP = "File name prefix: every output file\npath will start with this prefix.\nIt is derived from outfile."; + +typedef struct { + PCB_DAD_DECL_NOINIT(dlg) + cam_ctx_t cam; + int wjobs, wdigest, wtxt, woutfile, wprefix, wopts; +} cam_dlg_t; + +static void cam_gui_jobs2dlg(cam_dlg_t *ctx) +{ + pcb_hid_attribute_t *attr; + pcb_hid_tree_t *tree; + pcb_hid_row_t *r; + char *cell[2], *cursor_path = NULL; + conf_native_t *cn; + + attr = &ctx->dlg[ctx->wjobs]; + tree = (pcb_hid_tree_t *)attr->enumerations; + + /* remember cursor */ + r = pcb_dad_tree_get_selected(attr); + if (r != NULL) + cursor_path = pcb_strdup(r->cell[0]); + + /* remove existing items */ + pcb_dad_tree_clear(tree); + + /* add all new items */ + cn = conf_get_field("plugins/cam/jobs"); + if (cn != NULL) { + conf_listitem_t *item; + int idx; + + cell[1] = NULL; + conf_loop_list(cn->val.list, item, idx) { + cell[0] = pcb_strdup(item->name); + pcb_dad_tree_append(attr, NULL, cell); + } + } + + /* restore cursor */ + if (cursor_path != NULL) { + pcb_hid_attr_val_t hv; + hv.str_value = cursor_path; + pcb_gui->attr_dlg_set_value(ctx->dlg_hid_ctx, ctx->wjobs, &hv); + } +} + +static void cam_gui_digest2dlg(cam_dlg_t *ctx) +{ + pcb_hid_attribute_t *attr; + pcb_hid_tree_t *tree; + pcb_cam_code_t *c, *plugin = NULL; + char *cell[4], tmp[1024]; + int n; + + attr = &ctx->dlg[ctx->wdigest]; + tree = (pcb_hid_tree_t *)attr->enumerations; + + /* remove existing items */ + pcb_dad_tree_clear(tree); + + /* add all new items */ + for(n = 0, c = ctx->cam.code.array; n < ctx->cam.code.used; n++,c++) { + switch(c->inst) { + case PCB_CAM_DESC: + break; + case PCB_CAM_PLUGIN: + plugin = c; + break; + case PCB_CAM_WRITE: + strncpy(tmp, c->op.write.arg, sizeof(tmp)); + + cell[0] = tmp; + cell[2] = strchr(tmp, '='); + if (cell[2] != NULL) { + *cell[2] = '\0'; + (cell[2])++; + } + else + cell[2] = ""; + + if (plugin != NULL) + cell[1] = pcb_strdup(plugin->op.plugin.exporter->name); + else + cell[1] = ""; + + cell[3] = NULL; + pcb_dad_tree_append(attr, NULL, cell); + break; + } + } +} + + +static void cam_gui_opts2dlg(cam_dlg_t *ctx) +{ + htsp_t *vars = ctx->cam.vars; + htsp_entry_t *e; + pcb_hid_attr_val_t hv; + pcb_hid_attribute_t *attr; + pcb_hid_tree_t *tree; + pcb_hid_row_t *r; + char *cell[3], *cursor_path = NULL; + + cam_parse_opt_outfile(&ctx->cam, ctx->dlg[ctx->woutfile].default_val.str_value); + hv.str_value = ctx->cam.prefix == NULL ? "" : ctx->cam.prefix; + pcb_gui->attr_dlg_set_value(ctx->dlg_hid_ctx, ctx->wprefix, &hv); + + attr = &ctx->dlg[ctx->wopts]; + tree = (pcb_hid_tree_t *)attr->enumerations; + + /* remember cursor */ + r = pcb_dad_tree_get_selected(attr); + if (r != NULL) + cursor_path = pcb_strdup(r->cell[0]); + + /* remove existing items */ + pcb_dad_tree_clear(tree); + + /* add all new items */ + for(e = htsp_first(vars); e != NULL; e = htsp_next(vars, e)) { + cell[0] = pcb_strdup(e->key); + cell[1] = pcb_strdup(e->value); + cell[2] = NULL; + pcb_dad_tree_append(attr, NULL, cell); + } + + /* restore cursor */ + if (cursor_path != NULL) { + pcb_hid_attr_val_t hv; + hv.str_value = cursor_path; + pcb_gui->attr_dlg_set_value(ctx->dlg_hid_ctx, ctx->wopts, &hv); + } +} + +static void cam_gui_outfile_cb(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr_btn) +{ + cam_dlg_t *ctx = caller_data; + cam_gui_opts2dlg(ctx); +} + +static void cam_gui_filter_cb(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr_inp) +{ + cam_dlg_t *ctx = caller_data; + pcb_hid_attribute_t *attr; + pcb_hid_tree_t *tree; + const char *text; + + attr = &ctx->dlg[ctx->wjobs]; + tree = (pcb_hid_tree_t *)attr->enumerations; + text = attr_inp->default_val.str_value; + + pcb_dad_tree_hide_all(tree, &tree->rows, 1); + pcb_dad_tree_unhide_filter(tree, &tree->rows, 0, text); + pcb_dad_tree_update_hide(attr); +} + +static void cam_gui_export_cb(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr_btn) +{ + cam_dlg_t *ctx = caller_data; + pcb_hid_attribute_t *attr = &ctx->dlg[ctx->wjobs]; + pcb_hid_row_t *row = pcb_dad_tree_get_selected(attr); + + if (row != NULL) { + const char *outfile = ctx->dlg[ctx->woutfile].default_val.str_value; + char *tmp = pcb_strdup_printf("outfile=%s", outfile); + pcb_actionl("cam", "call", row->cell[0], tmp, NULL); + free(tmp); + } +} + +static char *kill_tabs(const char *str_in) +{ + char *res, *o; + res = pcb_strdup(str_in); + for(o = res; *o != '\0'; o++) + if (*o == '\t') + *o = ' '; + return res; +} + +static void cam_job_select_cb(pcb_hid_attribute_t *attrib, void *hid_ctx, pcb_hid_row_t *row) +{ + pcb_hid_tree_t *tree = (pcb_hid_tree_t *)attrib->enumerations; + cam_dlg_t *ctx = tree->user_ctx; + + if (row != NULL) { + char *script = kill_tabs(cam_find_job(row->cell[0])); + pcb_hid_attribute_t *atxt = &ctx->dlg[ctx->wtxt]; + pcb_hid_text_t *txt = (pcb_hid_text_t *)atxt->enumerations; + + txt->hid_set_text(atxt, hid_ctx, PCB_HID_TEXT_REPLACE, script); + + cam_free_code(&ctx->cam); + if (script != NULL) + cam_compile(&ctx->cam, script); + cam_gui_digest2dlg(ctx); + + free(script); + } +} + +static void cam_close_cb(void *caller_data, pcb_hid_attr_ev_t ev) +{ + cam_dlg_t *ctx = caller_data; + cam_uninit_inst(&ctx->cam); + PCB_DAD_FREE(ctx->dlg); + free(ctx); +} + +/* center aligned label */ +static void header_label(cam_dlg_t *ctx, const char *text) +{ + PCB_DAD_BEGIN_HBOX(ctx->dlg); + PCB_DAD_BEGIN_VBOX(ctx->dlg); + PCB_DAD_COMPFLAG(ctx->dlg, PCB_HATF_EXPFILL); + PCB_DAD_END(ctx->dlg); + PCB_DAD_LABEL(ctx->dlg, text); + PCB_DAD_BEGIN_VBOX(ctx->dlg); + PCB_DAD_COMPFLAG(ctx->dlg, PCB_HATF_EXPFILL); + PCB_DAD_END(ctx->dlg); + PCB_DAD_END(ctx->dlg); +} + +static int cam_gui(const char *arg) +{ + cam_dlg_t *ctx = calloc(sizeof(cam_dlg_t), 1); + const char *opt_hdr[] = {"key", "option value", NULL}; + const char *script_tabs[] = {"digest", "raw", NULL}; + const char *digest_hdr[] = {"file", "plugin", "layer groups", NULL}; + pcb_hid_dad_buttons_t clbtn[] = {{"Close", 0}, {NULL, 0}}; + + ctx->cam.vars = pcb_cam_vars_alloc(); + + PCB_DAD_BEGIN_VBOX(ctx->dlg); + PCB_DAD_COMPFLAG(ctx->dlg, PCB_HATF_EXPFILL); + PCB_DAD_BEGIN_HPANE(ctx->dlg); + + PCB_DAD_BEGIN_VBOX(ctx->dlg); /* left */ + PCB_DAD_COMPFLAG(ctx->dlg, PCB_HATF_EXPFILL); + PCB_DAD_TREE(ctx->dlg, 1, 0, NULL); + PCB_DAD_COMPFLAG(ctx->dlg, PCB_HATF_EXPFILL | PCB_HATF_SCROLL); + PCB_DAD_TREE_SET_CB(ctx->dlg, selected_cb, cam_job_select_cb); + PCB_DAD_TREE_SET_CB(ctx->dlg, ctx, ctx); + ctx->wjobs = PCB_DAD_CURRENT(ctx->dlg); + PCB_DAD_BEGIN_HBOX(ctx->dlg); /* command section */ + PCB_DAD_STRING(ctx->dlg); + PCB_DAD_HELP(ctx->dlg, "Filter text:\nlist jobs with matching name only"); + PCB_DAD_CHANGE_CB(ctx->dlg, cam_gui_filter_cb); + PCB_DAD_BEGIN_VBOX(ctx->dlg); /* filler */ + PCB_DAD_COMPFLAG(ctx->dlg, PCB_HATF_EXPFILL); + PCB_DAD_END(ctx->dlg); + PCB_DAD_BUTTON(ctx->dlg, "export!"); + PCB_DAD_CHANGE_CB(ctx->dlg, cam_gui_export_cb); + PCB_DAD_HELP(ctx->dlg, "Export the current board using the above selected CAM job\nand the options set on the right"); + PCB_DAD_END(ctx->dlg); + PCB_DAD_END(ctx->dlg); + + PCB_DAD_BEGIN_VBOX(ctx->dlg); /* right */ + PCB_DAD_COMPFLAG(ctx->dlg, PCB_HATF_EXPFILL); + PCB_DAD_BEGIN_VPANE(ctx->dlg); + PCB_DAD_BEGIN_VBOX(ctx->dlg); /* top */ + PCB_DAD_COMPFLAG(ctx->dlg, PCB_HATF_EXPFILL); + header_label(ctx, "CAM job script"); + PCB_DAD_BEGIN_TABBED(ctx->dlg, script_tabs); + + PCB_DAD_TREE(ctx->dlg, 3, 0, digest_hdr); + PCB_DAD_COMPFLAG(ctx->dlg, PCB_HATF_EXPFILL | PCB_HATF_SCROLL); + ctx->wdigest = PCB_DAD_CURRENT(ctx->dlg); + + PCB_DAD_TEXT(ctx->dlg, ctx); + PCB_DAD_COMPFLAG(ctx->dlg, PCB_HATF_EXPFILL | PCB_HATF_SCROLL); + ctx->wtxt = PCB_DAD_CURRENT(ctx->dlg); + PCB_DAD_END(ctx->dlg); + PCB_DAD_END(ctx->dlg); + PCB_DAD_BEGIN_VBOX(ctx->dlg); /* bottom */ + PCB_DAD_COMPFLAG(ctx->dlg, PCB_HATF_EXPFILL); + header_label(ctx, "CAM options"); + PCB_DAD_BEGIN_TABLE(ctx->dlg, 2); /* special options */ + PCB_DAD_LABEL(ctx->dlg, "outfile"); + PCB_DAD_HELP(ctx->dlg, OUTFILE_HELP); + PCB_DAD_STRING(ctx->dlg); + PCB_DAD_CHANGE_CB(ctx->dlg, cam_gui_outfile_cb); + ctx->woutfile = PCB_DAD_CURRENT(ctx->dlg); + PCB_DAD_HELP(ctx->dlg, OUTFILE_HELP); + PCB_DAD_LABEL(ctx->dlg, "prefix"); + PCB_DAD_HELP(ctx->dlg, PREFIX_HELP); + PCB_DAD_LABEL(ctx->dlg, ""); + ctx->wprefix = PCB_DAD_CURRENT(ctx->dlg); + PCB_DAD_HELP(ctx->dlg, PREFIX_HELP); + PCB_DAD_END(ctx->dlg); + + PCB_DAD_TREE(ctx->dlg, 2, 0, opt_hdr); /* option table */ + PCB_DAD_COMPFLAG(ctx->dlg, PCB_HATF_EXPFILL | PCB_HATF_SCROLL); + ctx->wopts = PCB_DAD_CURRENT(ctx->dlg); + PCB_DAD_END(ctx->dlg); + PCB_DAD_END(ctx->dlg); + PCB_DAD_BUTTON_CLOSES(ctx->dlg, clbtn); + PCB_DAD_END(ctx->dlg); + PCB_DAD_END(ctx->dlg); + PCB_DAD_END(ctx->dlg); + + PCB_DAD_NEW("cam", ctx->dlg, "CAM export", ctx, pcb_false, cam_close_cb); + + { /* set default outfile */ + pcb_hid_attr_val_t hv; + hv.str_value = pcb_derive_default_filename_(PCB->Filename, ""); + pcb_gui->attr_dlg_set_value(ctx->dlg_hid_ctx, ctx->woutfile, &hv); + free((char *)hv.str_value); + cam_gui_opts2dlg(ctx); + } + + { /* set right top text read-only */ + pcb_hid_attribute_t *atxt = &ctx->dlg[ctx->wtxt]; + pcb_hid_text_t *txt = (pcb_hid_text_t *)atxt->enumerations; + txt->hid_set_readonly(atxt, ctx->dlg_hid_ctx, 1); + } + + cam_gui_jobs2dlg(ctx); + + return 0; +} Index: tags/2.1.2/src_plugins/ddraft/Makefile =================================================================== --- tags/2.1.2/src_plugins/ddraft/Makefile (nonexistent) +++ tags/2.1.2/src_plugins/ddraft/Makefile (revision 24813) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_ddraft + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/2.1.2/src_plugins/ddraft/Plug.tmpasm =================================================================== --- tags/2.1.2/src_plugins/ddraft/Plug.tmpasm (nonexistent) +++ tags/2.1.2/src_plugins/ddraft/Plug.tmpasm (revision 24813) @@ -0,0 +1,13 @@ +put /local/pcb/mod {ddraft} +put /local/pcb/mod/OBJS [@ + $(PLUGDIR)/ddraft/ddraft.o + $(PLUGDIR)/ddraft/centgeo.o + $(PLUGDIR)/ddraft/fields_sphash.o +@] +put /local/pcb/mod/SPHASH {$(PLUGDIR)/ddraft/fields.sphash} + +switch /local/pcb/ddraft/controls + case {buildin} include /local/pcb/tmpasm/buildin; end; + case {plugin} include /local/pcb/tmpasm/plugin; end; + case {disable} include /local/pcb/tmpasm/disable; end; +end Index: tags/2.1.2/src_plugins/ddraft/centgeo.c =================================================================== --- tags/2.1.2/src_plugins/ddraft/centgeo.c (nonexistent) +++ tags/2.1.2/src_plugins/ddraft/centgeo.c (revision 24813) @@ -0,0 +1,419 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996, 2005 Thomas Nau + * pcb-rnd Copyright (C) 2018 Tibor 'Igor2' Palinkas + * + * 2d drafting plugin: center line geometry + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "config.h" +#include "centgeo.h" + +#include "obj_line.h" +#include "obj_arc.h" +#include "math_helper.h" +#include "compat_misc.h" +#include "search.h" + +/* Note about all intersection code: same basic algo as in find_geo.c - + see comment for the algo description there */ + +int pcb_intersect_cline_cline(pcb_line_t *Line1, pcb_line_t *Line2, pcb_box_t *ip, double offs[2]) +{ + double s, r; + double line1_dx, line1_dy, line2_dx, line2_dy, point1_dx, point1_dy; + + /* setup some constants */ + line1_dx = Line1->Point2.X - Line1->Point1.X; + line1_dy = Line1->Point2.Y - Line1->Point1.Y; + line2_dx = Line2->Point2.X - Line2->Point1.X; + line2_dy = Line2->Point2.Y - Line2->Point1.Y; + point1_dx = Line1->Point1.X - Line2->Point1.X; + point1_dy = Line1->Point1.Y - Line2->Point1.Y; + + /* set s to cross product of Line1 and the line + * Line1.Point1--Line2.Point1 (as vectors) */ + s = point1_dy * line1_dx - point1_dx * line1_dy; + + /* set r to cross product of both lines (as vectors) */ + r = line1_dx * line2_dy - line1_dy * line2_dx; + + /* No cross product means parallel or overlapping lines */ + if (r == 0.0) { + if (s == 0.0) { /* overlap; r and [0] will be Line2's point offset within Line1; s and [1] will be an endpoint of line1 */ + + r = pcb_cline_pt_offs(Line1, Line2->Point1.X, Line2->Point1.Y); + if ((r < 0.0) || (r > 1.0)) + r = pcb_cline_pt_offs(Line1, Line2->Point2.X, Line2->Point2.Y); + + s = pcb_cline_pt_offs(Line2, Line1->Point1.X, Line1->Point1.Y); + if ((s < 0.0) || (s > 1.0)) + s = 0.0; + else + s = 1.0; + + if (ip != NULL) { + ip->X1 = pcb_round((double)Line1->Point1.X + r * line1_dx); + ip->Y1 = pcb_round((double)Line1->Point1.Y + r * line1_dy); + if (s == 1.0) { + ip->X2 = Line1->Point2.X; + ip->Y2 = Line1->Point2.Y; + } + else { + ip->X2 = Line1->Point1.X; + ip->Y2 = Line1->Point1.Y; + } + } + if (offs != NULL) { + offs[0] = r; + offs[1] = s; + } + return 2; + } + return 0; + } + + s /= r; + r = (point1_dy * line2_dx - point1_dx * line2_dy) / r; + + /* intersection is at least on AB */ + if (r >= 0.0 && r <= 1.0) { + if (s >= 0.0 && s <= 1.0) { + if (ip != NULL) { + ip->X1 = pcb_round((double)Line1->Point1.X + r * line1_dx); + ip->Y1 = pcb_round((double)Line1->Point1.Y + r * line1_dy); + } + if (offs != NULL) + offs[0] = r; + return 1; + } + return 0; + } + + /* intersection is at least on CD */ + /* [removed this case since it always returns pcb_false --asp] */ + return 0; +} + +void pcb_cline_offs(pcb_line_t *line, double offs, pcb_coord_t *dstx, pcb_coord_t *dsty) +{ + double line_dx, line_dy; + + line_dx = line->Point2.X - line->Point1.X; + line_dy = line->Point2.Y - line->Point1.Y; + + *dstx = pcb_round((double)line->Point1.X + offs * line_dx); + *dsty = pcb_round((double)line->Point1.Y + offs * line_dy); +} + +double pcb_cline_pt_offs(pcb_line_t *line, pcb_coord_t px, pcb_coord_t py) +{ + double line_dx, line_dy, pt_dx, pt_dy; + + line_dx = line->Point2.X - line->Point1.X; + line_dy = line->Point2.Y - line->Point1.Y; + + pt_dx = px - line->Point1.X; + pt_dy = py - line->Point1.Y; + + return (line_dx * pt_dx + line_dy * pt_dy) / (line_dx*line_dx + line_dy*line_dy); +} + +static int line_ep(pcb_line_t *line, pcb_coord_t x, pcb_coord_t y) +{ + if ((line->Point1.X == x) && (line->Point1.Y == y)) return 1; + if ((line->Point2.X == x) && (line->Point2.Y == y)) return 1; + return 0; +} + +/* Assumme there will be at two intersection points; load ofs/ix/iy in the + next slot of the result, return from the function if both intersections + found */ +#define append(ofs, ix, iy) \ +do { \ + if (ip != NULL) { \ + if (found == 0) { \ + ip->X1 = ix; \ + ip->Y1 = iy; \ + } \ + else { \ + ip->X2 = ix; \ + ip->Y2 = iy; \ + } \ + } \ + if (offs != NULL) \ + offs[found] = ofs; \ + found++; \ + if (found == 2) \ + return found; \ +} while(0) + +static int intersect_cline_carc(pcb_line_t *Line, pcb_arc_t *Arc, pcb_box_t *ip, double offs[2], int oline) +{ + double dx, dy, dx1, dy1, l, d, r, r2, Radius; + pcb_coord_t ex, ey, ix, iy; + int found = 0; + + dx = Line->Point2.X - Line->Point1.X; + dy = Line->Point2.Y - Line->Point1.Y; + dx1 = Line->Point1.X - Arc->X; + dy1 = Line->Point1.Y - Arc->Y; + l = dx * dx + dy * dy; + d = dx * dy1 - dy * dx1; + d *= d; + + /* use the larger diameter circle first */ + Radius = Arc->Width; + Radius *= Radius; + r2 = Radius * l - d; + /* projection doesn't even intersect circle when r2 < 0 */ + if (r2 < 0) + return 0; + + /* line ends on arc? */ + if (pcb_is_point_on_arc(Line->Point1.X, Line->Point1.Y, 0, Arc)) { + if (oline) + append(0, Line->Point1.X, Line->Point1.Y); + else + append(pcb_carc_pt_offs(Arc, Line->Point1.X, Line->Point1.Y), Line->Point1.X, Line->Point1.Y); + } + if (pcb_is_point_on_arc(Line->Point2.X, Line->Point2.Y, 0, Arc)) { + if (oline) + append(1, Line->Point2.X, Line->Point2.Y); + else + append(pcb_carc_pt_offs(Arc, Line->Point2.X, Line->Point2.Y), Line->Point2.X, Line->Point2.Y); + } + + /* if line is a single point, there is no other way an intersection can happen */ + if (l == 0.0) + return found; + + r2 = sqrt(r2); + Radius = -(dx * dx1 + dy * dy1); + r = (Radius + r2) / l; + + if ((r >= 0) && (r <= 1)) { + ix = pcb_round(Line->Point1.X + r * dx); + iy = pcb_round(Line->Point1.Y + r * dy); + if (!line_ep(Line, ix, iy) && pcb_is_point_on_arc(ix, iy, 1, Arc)) { + if (oline) + append(r, ix, iy); + else + append(pcb_carc_pt_offs(Arc, ix, iy), ix, iy); + } + } + + r = (Radius - r2) / l; + if ((r >= 0) && (r <= 1)) { + ix = pcb_round(Line->Point1.X + r * dx); + iy = pcb_round(Line->Point1.Y + r * dy); + if (!line_ep(Line, ix, iy) && pcb_is_point_on_arc(ix, iy, 1, Arc)) { + if (oline) + append(r, ix, iy); + else + append(pcb_carc_pt_offs(Arc, ix, iy), ix, iy); + } + } + + /* check if an arc end point is on the line */ + pcb_arc_get_end(Arc, 0, &ex, &ey); + if (pcb_is_point_in_line(ex, ey, 1, (pcb_any_line_t *) Line)) { + if (oline) { + r = pcb_cline_pt_offs(Line, ex, ey); + append(r, ex, ey); + } + else + append(0, ex, ey); + } + pcb_arc_get_end(Arc, 1, &ex, &ey); + if (pcb_is_point_in_line(ex, ey, 1, (pcb_any_line_t *) Line)) { + if (oline) { + r = pcb_cline_pt_offs(Line, ex, ey); + append(r, ex, ey); + } + else + append(1, ex, ey); + } + + return found; +} + +int pcb_intersect_cline_carc(pcb_line_t *Line, pcb_arc_t *Arc, pcb_box_t *ip, double offs[2]) +{ + return intersect_cline_carc(Line, Arc, ip, offs, 1); +} + +int pcb_intersect_carc_cline(pcb_arc_t *Arc, pcb_line_t *Line, pcb_box_t *ip, double offs[2]) +{ + return intersect_cline_carc(Line, Arc, ip, offs, 0); +} + + +void pcb_carc_offs(pcb_arc_t *arc, double offs, pcb_coord_t *dstx, pcb_coord_t *dsty) +{ + double ang = (arc->StartAngle + offs * arc->Delta) / PCB_RAD_TO_DEG; + + *dstx = arc->X + cos(ang) * arc->Width; + *dsty = arc->Y - sin(ang) * arc->Height; +} + +double pcb_carc_pt_offs(pcb_arc_t *arc, pcb_coord_t px, pcb_coord_t py) +{ + double dx, dy, ang, end; + + /* won't work with elliptical arc - see also pcb_is_point_on_arc */ + dy = (double)(py - arc->Y) / (double)arc->Height; + dx = (double)(px - arc->X) / (double)arc->Width; + ang = (-atan2(dy, dx)) * PCB_RAD_TO_DEG + 180; + end = arc->StartAngle + arc->Delta; + + /* normalize the angle: there are multiple ways an arc can cover the same + angle range, e.g. -10+30 and +20-30 - make sure the angle falls between + the start/end (generic) range */ + if (arc->StartAngle < end) { + if (ang > end) + ang -= 360; + if (ang < arc->StartAngle) + ang += 360; + } + else { + if (ang > arc->StartAngle) + ang -= 360; + if (ang < end) + ang += 360; + } + + ang = (ang - arc->StartAngle) / arc->Delta; + + return ang; +} + + +static void get_arc_ends(pcb_coord_t *box, pcb_arc_t *arc) +{ + box[0] = arc->X - arc->Width * cos(PCB_M180 * arc->StartAngle); + box[1] = arc->Y + arc->Height * sin(PCB_M180 * arc->StartAngle); + box[2] = arc->X - arc->Width * cos(PCB_M180 * (arc->StartAngle + arc->Delta)); + box[3] = arc->Y + arc->Height * sin(PCB_M180 * (arc->StartAngle + arc->Delta)); +} + +/* reduce arc start angle and delta to 0..360 */ +static void normalize_angles(pcb_angle_t *sa, pcb_angle_t *d) +{ + if (*d < 0) { + *sa += *d; + *d = -*d; + } + if (*d > 360) /* full circle */ + *d = 360; + *sa = pcb_normalize_angle(*sa); +} + +static int radius_crosses_arc(double x, double y, pcb_arc_t *arc) +{ + double alpha = atan2(y - arc->Y, -x + arc->X) * PCB_RAD_TO_DEG; + pcb_angle_t sa = arc->StartAngle, d = arc->Delta; + + normalize_angles(&sa, &d); + if (alpha < 0) + alpha += 360; + if (sa <= alpha) + return (sa + d) >= alpha; + return (sa + d - 360) >= alpha; +} + +int pcb_intersect_carc_carc(pcb_arc_t *Arc1, pcb_arc_t *Arc2, pcb_box_t *ip, double offs[2]) +{ + double x, y, dx, dy, r1, r2, a, d, l, dl; + pcb_coord_t pdx, pdy; + pcb_coord_t box[8]; + int found = 0; + + /* try the end points first */ + get_arc_ends(&box[0], Arc1); + get_arc_ends(&box[4], Arc2); + if (pcb_is_point_on_arc(box[0], box[1], 1, Arc2)) append(0, box[0], box[1]); + if (pcb_is_point_on_arc(box[2], box[3], 1, Arc2)) append(1, box[2], box[3]); + if (pcb_is_point_on_arc(box[4], box[5], 1, Arc1)) append(pcb_carc_pt_offs(Arc1, box[4], box[5]), box[4], box[5]); + if (pcb_is_point_on_arc(box[6], box[7], 1, Arc1)) append(pcb_carc_pt_offs(Arc1, box[6], box[7]), box[6], box[7]); + + pdx = Arc2->X - Arc1->X; + pdy = Arc2->Y - Arc1->Y; + dl = pcb_distance(Arc1->X, Arc1->Y, Arc2->X, Arc2->Y); + + /* the original code used to do angle checks for concentric case here but + those cases are already handled by the above endpoint checks. */ + + r1 = Arc1->Width; + r2 = Arc2->Width; + /* arcs centerlines are too far or too near */ + if (dl > r1 + r2 || dl + r1 < r2 || dl + r2 < r1) { + /* check the nearest to the other arc's center point */ + dx = pdx * r1 / dl; + dy = pdy * r1 / dl; + if (dl + r1 < r2) { /* Arc1 inside Arc2 */ + dx = -dx; + dy = -dy; + } + + if (radius_crosses_arc(Arc1->X + dx, Arc1->Y + dy, Arc1) && pcb_is_point_on_arc(Arc1->X + dx, Arc1->Y + dy, 1, Arc2)) + append(pcb_carc_pt_offs(Arc1, Arc1->X + dx, Arc1->Y + dy), Arc1->X + dx, Arc1->Y + dy); + + dx = -pdx * r2 / dl; + dy = -pdy * r2 / dl; + if (dl + r2 < r1) { /* Arc2 inside Arc1 */ + dx = -dx; + dy = -dy; + } + + if (radius_crosses_arc(Arc2->X + dx, Arc2->Y + dy, Arc2) && pcb_is_point_on_arc(Arc2->X + dx, Arc2->Y + dy, 1, Arc1)) + append(pcb_carc_pt_offs(Arc1, Arc2->X + dx, Arc2->Y + dy), Arc2->X + dx, Arc2->Y + dy); + } + + l = dl * dl; + r1 *= r1; + r2 *= r2; + a = 0.5 * (r1 - r2 + l) / l; + r1 = r1 / l; + d = r1 - a * a; + /* the circles are too far apart to touch or probably just touch: + check the nearest point */ + if (d < 0) + d = 0; + else + d = sqrt(d); + x = Arc1->X + a * pdx; + y = Arc1->Y + a * pdy; + dx = d * pdx; + dy = d * pdy; + if ((radius_crosses_arc(x + dy, y - dx, Arc1) && pcb_is_point_on_arc(x + dy, y - dx, 1, Arc2)) || (radius_crosses_arc(x + dy, y - dx, Arc2) && pcb_is_point_on_arc(x + dy, y - dx, 1, Arc1))) + append(pcb_carc_pt_offs(Arc1, x + dy, y - dx), x + dy, y - dx); + + if ((radius_crosses_arc(x - dy, y + dx, Arc1) && pcb_is_point_on_arc(x - dy, y + dx, 1, Arc2)) || (radius_crosses_arc(x - dy, y + dx, Arc2) && pcb_is_point_on_arc(x - dy, y + dx, 1, Arc1))) + append(pcb_carc_pt_offs(Arc1, x - dy, y + dx), x - dy, y + dx); + + return found; +} + Index: tags/2.1.2/src_plugins/ddraft/centgeo.h =================================================================== --- tags/2.1.2/src_plugins/ddraft/centgeo.h (nonexistent) +++ tags/2.1.2/src_plugins/ddraft/centgeo.h (revision 24813) @@ -0,0 +1,41 @@ +#ifndef PCB_CENTGEO_H +#define PCB_CENTGEO_H + +#include "obj_line.h" + +/*** Calculate centerpoint intersections of objects (thickness ignored) ***/ + +/* Calculate the intersection point(s) of two lines and store them in ip + and/or offs (on Line1) if they are not NULL. Returns: + 0 = no intersection + 1 = one intersection (X1;Y1 of ip is loaded) + 2 = overlapping segments (overlap endpoitns are stored in X1;Y1 and X2;Y2 of ip) */ +int pcb_intersect_cline_cline(pcb_line_t *Line1, pcb_line_t *Line2, pcb_box_t *ip, double offs[2]); + +/* Calculate the intersection point(s) of a lines and an arc and store them + in ip and/or offs if they are not NULL. Returns: + 0 = no intersection + 1 = one intersection (X1;Y1 of ip is loaded) + 2 = two intersections (stored in X1;Y1 and X2;Y2 of ip) */ +int pcb_intersect_cline_carc(pcb_line_t *Line, pcb_arc_t *Arc, pcb_box_t *ip, double offs_line[2]); +int pcb_intersect_carc_cline(pcb_arc_t *Arc, pcb_line_t *Line, pcb_box_t *ip, double offs_arc[2]); + +/* Calculate the intersection point(s) of two arcs and store them in ip + and/or offs (on Line1) if they are not NULL. Returns: + 0 = no intersection + 1 = one intersection (X1;Y1 of ip is loaded) + 2 = two intersections or overlapping segments (overlap endpoints are stored in X1;Y1 and X2;Y2 of ip) */ +int pcb_intersect_carc_carc(pcb_arc_t *Arc1, pcb_arc_t *Arc2, pcb_box_t *ip, double offs[2]); + + +/* Calculate the point on an object corresponding to a [0..1] offset and store + the result in dstx;dsty. */ +void pcb_cline_offs(pcb_line_t *line, double offs, pcb_coord_t *dstx, pcb_coord_t *dsty); +void pcb_carc_offs(pcb_arc_t *arc, double offs, pcb_coord_t *dstx, pcb_coord_t *dsty); + +/* Project a point (px;py) onto an object and return the offset from point1 */ +double pcb_cline_pt_offs(pcb_line_t *line, pcb_coord_t px, pcb_coord_t py); +double pcb_carc_pt_offs(pcb_arc_t *arc, pcb_coord_t px, pcb_coord_t py); + + +#endif Index: tags/2.1.2/src_plugins/ddraft/cli.c =================================================================== --- tags/2.1.2/src_plugins/ddraft/cli.c (nonexistent) +++ tags/2.1.2/src_plugins/ddraft/cli.c (revision 24813) @@ -0,0 +1,580 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * + * 2d drafting plugin + * pcb-rnd Copyright (C) 2018 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "hid_inlines.h" +#include "compat_misc.h" +#include "conf_core.h" + +#define CLI_MAX_INS_LEN 128 + +typedef struct cli_node_s cli_node_t; + +typedef struct { + const char *name; + int (*exec)(char *line, int argc, cli_node_t *argv); /* command line entered (finished, accepted) */ + int (*click)(char *line, int cursor, int argc, cli_node_t *argv); /* user clicked on the GUI while editing the command line */ + int (*tab)(char *line, int cursor, int argc, cli_node_t *argv); /* tab completion */ + int (*edit)(char *line, int cursor, int argc, cli_node_t *argv); /* called after editing the line or moving the cursor */ +} ddraft_op_t; + +typedef enum cli_ntype_e { + CLI_INVALID, + CLI_FROM, + CLI_TO, + CLI_ANGLE, + CLI_ABSOLUTE, + CLI_RELATIVE, + + CLI_PERP, + CLI_PARAL, + CLI_TANGENT, + CLI_CENTER, + CLI_START, + CLI_END, + + CLI_DIST, + CLI_OFFS, + CLI_COORD +} cli_ntype_t; + +#define case_object \ + case CLI_PERP: case CLI_PARAL: case CLI_TANGENT: case CLI_CENTER: \ + case CLI_START: case CLI_END + +typedef struct cli_ntname_s { + const char *name; + cli_ntype_t type; +} cli_ntname_t; + +static const cli_ntname_t cli_tnames[] = { + {"from", CLI_FROM}, + {"to", CLI_TO}, + {"angle", CLI_ANGLE}, + {"absolute", CLI_ABSOLUTE}, + {"relative", CLI_RELATIVE}, + {"perpendicular", CLI_PERP}, + {"parallel", CLI_PARAL}, + {"tangential", CLI_TANGENT}, + {"center", CLI_CENTER}, + {"start", CLI_START}, + {"end", CLI_END}, + {"coord", CLI_COORD}, + {"distance", CLI_DIST}, + {"length", CLI_DIST}, + {"offset", CLI_OFFS}, + {NULL, 0} +}; + +struct cli_node_s { + cli_ntype_t type; + int begin, end; /* cursor pos */ + int invalid; + + pcb_coord_t x, y, dist; + pcb_angle_t angle, offs; + pcb_cardinal_t id; +}; + +static const cli_ntype_t find_type(const char *type, int typelen) +{ + const cli_ntname_t *p, *found = NULL; + + if (typelen < 1) + return CLI_INVALID; + + for(p = cli_tnames; p->name != NULL; p++) { + if (pcb_strncasecmp(p->name, type, typelen) == 0) { + if (found != NULL) + return CLI_INVALID; /* multiple match */ + found = p; + } + } + + if (found == NULL) + return CLI_INVALID; + return found->type; +} + +static const char *find_rev_type(cli_ntype_t type) +{ + const cli_ntname_t *p; + + for(p = cli_tnames; p->name != NULL; p++) + if (p->type == type) + return p->name; + + return "INVALID"; +} + +#define APPEND(type_, end_) \ +do { \ + memset(&dst[i], 0, sizeof(cli_node_t)); \ + dst[i].type = type_; \ + dst[i].begin = s - line; \ + dst[i].end = end_ - line; \ + i++; \ + if (i >= dstlen) \ + return i; \ +} while(0) + +#define iscrd(c) ((c == '+') || (c == '-') || (c == '.') || isdigit(c)) +#define last_type ((i > 0) ? dst[i-1].type : CLI_INVALID) + +static int cli_parse(cli_node_t *dst, int dstlen, const char *line) +{ + char tmp[128]; + char *end, *sep, *s = strchr(line, ' '), *next; /* skip the instruction */ + int i; + pcb_bool succ; + + if (s == NULL) + return 0; + + for(i = 0;; s = next) { + while(isspace(*s)) s++; + if (*s == '\0') + break; + switch(*s) { + case '@': + next = s+1; + APPEND(CLI_RELATIVE, next); + continue; + case '*': + next = s+1; + APPEND(CLI_ABSOLUTE, next); + continue; + case '<': + next = s+1; + APPEND(CLI_ANGLE, next); + continue; + case '%': + APPEND(CLI_OFFS, next); + dst[i-1].offs = strtod(s+1, &next); + dst[i-1].invalid = (next == s); + continue; + case '~': + next = s+1; + APPEND(CLI_DIST, next); + break; + default: + next = strchr(s, ' '); + if (next == NULL) + next = s+strlen(s); + if (iscrd(*s)) { + switch(last_type) { + case CLI_INVALID: + case CLI_FROM: + case CLI_TO: + APPEND(CLI_ABSOLUTE, s); + case CLI_RELATIVE: + case CLI_ABSOLUTE: + APPEND(CLI_COORD, next); + sep = strchr(s, ','); + if ((sep == NULL) || ((sep - s) > sizeof(tmp)-2)) { + dst[i-1].invalid = 1; + break; + } + memcpy(tmp, s, sep-s); + tmp[sep-s] = '\0'; + dst[i-1].x = pcb_get_value_ex(tmp, NULL, NULL, NULL, conf_core.editor.grid_unit->suffix, &succ); + if (!succ) + dst[i-1].invalid = 1; + + sep++; + if ((next - sep) > sizeof(tmp)-2) { + dst[i-1].invalid = 1; + break; + } + memcpy(tmp, sep, next-sep); + tmp[next-sep] = '\0'; + dst[i-1].y = pcb_get_value_ex(tmp, NULL, NULL, NULL, conf_core.editor.grid_unit->suffix, &succ); + if (!succ) + dst[i-1].invalid = 1; + break; + case CLI_DIST: + dst[i-1].dist = pcb_get_value_ex(s, NULL, NULL, NULL, conf_core.editor.grid_unit->suffix, &succ); + dst[i-1].invalid = !succ; + dst[i-1].end = next - line; + break; + case CLI_ANGLE: + dst[i-1].angle = strtod(s, &next); + dst[i-1].invalid = (dst[i-1].angle > 360.0) || (dst[i-1].angle < -360.0); + dst[i-1].end = next - line; + break; + case_object : + dst[i-1].id = strtol(s, &next, 10); + dst[i-1].end = next - line; + break; + default: + APPEND(CLI_INVALID, next); + } + } + else + APPEND(find_type(s, next-s), next); + } + if ((next == NULL) || (*next == '\0')) + break; + } + + return i; +} + +#undef APPEND +#undef iscrd +#undef last_type + +static int cli_cursor_arg(int argc, cli_node_t *argv, int cursor) +{ + int n; + for(n = 0; n < argc; n++) + if ((cursor >= argv[n].begin) && (cursor <= argv[n].end)) + return n; + return -1; +} + +static void cli_str_remove(char *str, int from, int to) +{ + if (from >= to) + return; + memmove(str+from, str+to, strlen(str+to)+1); +} + + +static int cli_str_insert(char *str, int from, char *ins, int enforce_space_before) +{ + int inslen = strlen(ins), remain = strlen(str+from), extra = 0; + if (enforce_space_before && (str[from-1] != ' ')) + extra=1; + memmove(str+from+inslen+extra, str+from, remain+1); + if (extra) + str[from] = ' '; + memcpy(str+from+extra, ins, inslen); + return from + inslen + extra; +} + +static int cli_apply_coord(cli_node_t *argv, int start, int end, pcb_coord_t *ox, pcb_coord_t *oy, int annot) +{ + int n, relative = 0, have_angle = 0, have_dist = 0, len = (start > 1); + double angle = 0, dist = 0, lx, ly, x = *ox, y = *oy; + pcb_coord_t tx, ty; + + for(n = start; n < end; n++) { + int moved = 0; + pcb_any_obj_t *to = NULL; + + /* look up the target object for instructions referencing an object */ + switch(argv[n].type) { + case_object : + if (argv[n].id > 0) { + void *p1, *p2, *p3; + int res; + res = pcb_search_obj_by_id_(PCB->Data, &p1, &p2, &p3, argv[n].id, PCB_OBJ_LINE); + if (res == 0) + res = pcb_search_obj_by_id_(PCB->Data, &p1, &p2, &p3, argv[n].id, PCB_OBJ_ARC); + if (res == 0) + res = pcb_search_obj_by_id_(PCB->Data, &p1, &p2, &p3, argv[n].id, PCB_OBJ_POLY); + if (res != 0) + to = p2; + } + if (to == NULL) + return -1; + break; + default:; + } + + switch(argv[n].type) { + case CLI_ABSOLUTE: + relative = 0; + len = 0; + lx = ly = 0; + break; + case CLI_RELATIVE: + relative = 1; + break; + + case CLI_ANGLE: + have_angle = 1; + if (relative) { + angle += argv[n].angle; + relative = 0; + } + else + angle = argv[n].angle; + goto apply; + + case CLI_DIST: + have_dist = 1; + if (relative) { + dist += argv[n].dist; + relative = 0; + } + else + dist = argv[n].dist; + goto apply; + + case CLI_COORD: + if (relative) { + x += argv[n].x; + y += argv[n].y; + relative = 0; + moved = 1; + } + else { + x = argv[n].x; + y = argv[n].y; + len = 0; + lx = ly = 0; + moved = 1; + } + break; + + case CLI_PERP: + pcb_message(PCB_MSG_ERROR, "perp not yet implemented\n"); + return -1; + case CLI_PARAL: + pcb_message(PCB_MSG_ERROR, "paral not yet implemented\n"); + return -1; + case CLI_TANGENT: + pcb_message(PCB_MSG_ERROR, "tangent not yet implemented\n"); + return -1; + + case CLI_CENTER: + switch(to->type) { + case PCB_OBJ_LINE: + x = (((pcb_line_t *)to)->Point1.X + ((pcb_line_t *)to)->Point2.X)/2; + y = (((pcb_line_t *)to)->Point1.Y + ((pcb_line_t *)to)->Point2.Y)/2; + break; + case PCB_OBJ_ARC: + x = ((pcb_arc_t *)to)->X; + y = ((pcb_arc_t *)to)->Y; + break; + default: + return -1; + } + break; + case CLI_START: + switch(to->type) { + case PCB_OBJ_LINE: + x = ((pcb_line_t *)to)->Point1.X; + y = ((pcb_line_t *)to)->Point1.Y; + break; + case PCB_OBJ_ARC: + pcb_arc_get_end((pcb_arc_t *)to, 0, &tx, &ty); + x = tx; + y = ty; + break; + default: + return -1; + } + break; + case CLI_END: + switch(to->type) { + case PCB_OBJ_LINE: + x = ((pcb_line_t *)to)->Point2.X; + y = ((pcb_line_t *)to)->Point2.Y; + break; + case PCB_OBJ_ARC: + pcb_arc_get_end((pcb_arc_t *)to, 1, &tx, &ty); + x = tx; + y = ty; + break; + default: + return -1; + } + break; + + default: + goto over; + apply:; + if (have_angle && have_dist) { + x += cos(angle / PCB_RAD_TO_DEG) * dist; + y += sin(angle / PCB_RAD_TO_DEG) * dist; + have_angle = have_dist = 0; + moved = 1; + } + break; + } + if (argv[n].invalid) + return -1; + + if (moved) { + if ((annot) && (len > 0)) { + pcb_coord_t *c = vtc0_alloc_append(&pcb_ddraft_attached.annot_lines, 4); + c[0] = pcb_round(lx); + c[1] = pcb_round(ly); + c[2] = pcb_round(x); + c[3] = pcb_round(y); + } + angle = atan2(y - ly, x - lx) * PCB_RAD_TO_DEG; + lx = x; + ly = y; + len++; + } + } + + over:; + if (have_angle || have_dist) /* could not apply */ + return -1; + *ox = pcb_round(x); + *oy = pcb_round(y); + return n; +} + +static void cli_print_args(int argc, cli_node_t *argv) +{ + int n; + for(n = 0; n < argc; n++) { + pcb_trace(" [%d] %s/%d {%d..%d}", n, find_rev_type(argv[n].type), argv[n].type, argv[n].begin, argv[n].end); + if (!argv[n].invalid) { + switch(argv[n].type) { + case CLI_COORD: pcb_trace(": %$mm,%$mm", argv[n].x, argv[n].y); break; + case CLI_ANGLE: pcb_trace(": %f", argv[n].angle); break; + case CLI_DIST: pcb_trace(": %$mm", argv[n].dist); break; + case CLI_OFFS: pcb_trace(": %f", argv[n].offs); break; + case_object: pcb_trace(": %ld", (long)argv[n].id); break; + default:; + } + pcb_trace("\n"); + } + else + pcb_trace(": INVALID\n"); + } +} + +#include "cli_line.c" + +static const ddraft_op_t ddraft_ops[] = { + {"line", line_exec, line_click, line_tab, line_edit}, + {NULL, NULL, NULL, NULL, NULL} +}; + +static const ddraft_op_t *find_op(const char *op, int oplen) +{ + const ddraft_op_t *p, *found = NULL; + + if (oplen < 1) + return NULL; + + for(p = ddraft_ops; p->name != NULL; p++) { + if (pcb_strncasecmp(p->name, op, oplen) == 0) { + if (found != NULL) + return NULL; /* multiple match */ + found = p; + } + } + + return found; +} + +static const char pcb_acts_ddraft[] = "ddraft([command])"; +static const char pcb_acth_ddraft[] = "Enter 2d drafting CLI mode or execute command"; +static fgw_error_t pcb_act_ddraft(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + char *args, *cmd, *line, sline[1024], *op; + const char *cline = NULL; + int cursor, len, oplen; + const ddraft_op_t *opp; + cli_node_t nd[128]; + int ndlen; + + if (argc == 1) { + pcb_cli_enter("ddraft", "ddraft"); + PCB_ACT_IRES(0); + return 0; + } + + PCB_ACT_CONVARG(1, FGW_STR, ddraft, cmd = argv[1].val.str); + if (strcmp(cmd, "/exit") == 0) { + pcb_cli_leave(); + PCB_ACT_IRES(0); + return 0; + } + + /* make a safe copy of the command line, either on stack or on heap if too large */ + if ((cmd != NULL) && (*cmd != '/')) + cline = cmd; + else + cline = pcb_hid_command_entry(NULL, &cursor); + if (cline == NULL) + cline = ""; + + while(isspace(*cline)) cline++; + if ((*cline == '\n') || (*cline == '#') || (*cline == '\0')) { /* empty or comment */ + PCB_ACT_IRES(0); + return 0; + } + + len = strlen(cline); + if (len >= sizeof(cline) - CLI_MAX_INS_LEN) + line = malloc(len + 1 + CLI_MAX_INS_LEN); + else + line = sline; + memcpy(line, cline, len+1); + + /* split op and arguments; recalculate cursor so it's within the arguments */ + op = line; + args = strpbrk(op, " \t"); + if (args != NULL) + oplen = args - op; + else + oplen = len; + + /* look up op */ + opp = find_op(op, oplen); + if (opp == NULL) { + if (strcmp(cmd, "/edit") != 0) + pcb_message(PCB_MSG_ERROR, "ddraft: unknown operator '%s'\n", op); + PCB_ACT_IRES(-1); + goto ret0; + } + + reparse:; + ndlen = cli_parse(nd, sizeof(nd) / sizeof(nd[0]), line); + + if (*cmd == '/') { + if (strcmp(cmd, "/click") == 0) { + PCB_ACT_IRES(opp->click(line, cursor, ndlen, nd)); + cmd = "/edit"; + goto reparse; + } + else if (strcmp(cmd, "/tab") == 0) + PCB_ACT_IRES(opp->tab(line, cursor, ndlen, nd)); + else if (strcmp(cmd, "/edit") == 0) + PCB_ACT_IRES(opp->edit(line, cursor, ndlen, nd)); + else + PCB_ACT_IRES(0); /* ignore anything unhandled */ + goto ret0; + } + + PCB_ACT_IRES(opp->exec(line, ndlen, nd)); + + ret0:; + if (line != sline) + free(line); + return 0; +} Index: tags/2.1.2/src_plugins/ddraft/cli_line.c =================================================================== --- tags/2.1.2/src_plugins/ddraft/cli_line.c (nonexistent) +++ tags/2.1.2/src_plugins/ddraft/cli_line.c (revision 24813) @@ -0,0 +1,223 @@ +static int line_parse(char *line, int argc, cli_node_t *argv, pcb_box_t *box, int verbose, int annot) +{ + int n = 0; + + if (argv[n].type == CLI_FROM) + n++; + else if (argv[n].type == CLI_TO) { + pcb_message(PCB_MSG_ERROR, "Incremental line drawing is not yet supported\n"); + return -1; + } + n = cli_apply_coord(argv, n, argc, &box->X1, &box->Y1, annot); + if (n < 0) { + if (verbose) + pcb_message(PCB_MSG_ERROR, "Invalid 'from' coord\n"); + return -1; + } + if (argv[n].type != CLI_TO) { + if (verbose) + pcb_message(PCB_MSG_ERROR, "Missing 'to'\n"); + return -1; + } + n++; + box->X2 = box->X1; + box->Y2 = box->Y1; + n = cli_apply_coord(argv, n, argc, &box->X2, &box->Y2, annot); + if (n < 0) { + if (verbose) + pcb_message(PCB_MSG_ERROR, "Invalid 'to' coord\n"); + return -1; + } + if (n != argc) { + if (verbose) + pcb_message(PCB_MSG_ERROR, "Excess tokens after the to coord\n"); + return -1; + } + return 0; +} + +static int line_exec(char *line, int argc, cli_node_t *argv) +{ + int res; + pcb_box_t box; + + pcb_trace("line e: '%s'\n", line); + + memset(&box, 0, sizeof(box)); + res = line_parse(line, argc, argv, &box, 1, 0); + if (res == 0) { + pcb_trace("line_exec: %mm;%mm -> %mm;%mm\n", box.X1, box.Y1, box.X2, box.Y2); + pcb_line_new(CURRENT, box.X1, box.Y1, box.X2, box.Y2, + conf_core.design.line_thickness, 2 * conf_core.design.clearance, + pcb_flag_make(conf_core.editor.clear_line ? PCB_FLAG_CLEARLINE : 0)); + } + pcb_ddraft_attached_reset(); + return res; +} + +static int line_edit(char *line, int cursor, int argc, cli_node_t *argv) +{ + int res; + pcb_box_t box; + + pcb_ddraft_attached_reset(); + + if (pcb_tool_next_id != pcb_ddraft_tool) + pcb_tool_select_by_id(pcb_ddraft_tool); + + pcb_trace("line e: '%s':%d\n", line, cursor); + memset(&box, 0, sizeof(box)); + res = line_parse(line, argc, argv, &box, 0, 1); + if (res == 0) { + pcb_ddraft_attached.line_valid = 1; + pcb_ddraft_attached.line.Point1.X = box.X1; + pcb_ddraft_attached.line.Point1.Y = box.Y1; + pcb_ddraft_attached.line.Point2.X = box.X2; + pcb_ddraft_attached.line.Point2.Y = box.Y2; + pcb_gui->invalidate_all(); + } + return res; +} + +static int get_rel_coord(int argc, cli_node_t *argv, int argn, pcb_coord_t *ox, pcb_coord_t *oy) +{ + int nto, res; + + for(nto = 0; nto < argc; nto++) + if (argv[nto].type == CLI_TO) + break; + + *ox = *oy = 0; + res = 0; + if (argv[res].type == CLI_FROM) + res++; + if (argn < nto) { + res = cli_apply_coord(argv, res, argn, ox, oy, 0); + } + else { + res = cli_apply_coord(argv, res, nto, ox, oy, 0); /* 'to' may be relative to 'from', so eval 'from' first */ + res |= cli_apply_coord(argv, nto+1, argn, ox, oy, 0); + } + + return res; +} + +static int line_click(char *line, int cursor, int argc, cli_node_t *argv) +{ + int argn = cli_cursor_arg(argc, argv, cursor); + int replace = 0, by, res; + pcb_coord_t ox, oy; + char buff[CLI_MAX_INS_LEN]; + + pcb_trace("line c: '%s':%d (argn=%d)\n", line, cursor, argn); + cli_print_args(argc, argv); + + if (argn < 0) { + /* at the end */ + argn = argc - 1; + if (argn < 0) { + /* empty arg list */ + pcb_snprintf(buff, sizeof(buff), " from %.08$$mm,%.08$$mm", pcb_crosshair.X, pcb_crosshair.Y); + printf("append: '%s'\n", buff); + cursor = cli_str_insert(line, strlen(line), buff, 1); + goto update; + } + } + + *buff = '\0'; + by = argn; + + + retry:; + + switch(argv[by].type) { + case CLI_COORD: + if (by > 0) { + by--; + replace = 1; + goto retry; + } + /* fall through: when clicked at the first coord */ + case CLI_ABSOLUTE: + case CLI_FROM: + case CLI_TO: + pcb_trace("abs"); + pcb_snprintf(buff, sizeof(buff), "%.08$$mm,%.08$$mm", pcb_crosshair.X, pcb_crosshair.Y); + goto maybe_replace_after; + break; + case CLI_RELATIVE: + res = get_rel_coord(argc, argv, argn, &ox, &oy); + if (res < 0) { + pcb_message(PCB_MSG_ERROR, "Failed to interpret coords already entered\n"); + return 0; + } + pcb_trace("rel from %$mm,%$mm", ox, oy); + pcb_snprintf(buff, sizeof(buff), "%.08$$mm,%.08$$mm", pcb_crosshair.X - ox, pcb_crosshair.Y - oy); + maybe_replace_after:; + if ((by+1 < argc) && (argv[by+1].type == CLI_COORD)) { + argn = by+1; + replace = 1; + } + break; + case CLI_ANGLE: + res = get_rel_coord(argc, argv, argn, &ox, &oy); + if (res < 0) { + pcb_message(PCB_MSG_ERROR, "Failed to interpret coords already entered\n"); + return 0; + } + replace=1; + pcb_snprintf(buff, sizeof(buff), "<%f", atan2(pcb_crosshair.Y - oy, pcb_crosshair.X - ox) * PCB_RAD_TO_DEG); + break; + case CLI_DIST: + res = get_rel_coord(argc, argv, argn, &ox, &oy); + if (res < 0) { + pcb_message(PCB_MSG_ERROR, "Failed to interpret coords already entered\n"); + return 0; + } + replace=1; + pcb_snprintf(buff, sizeof(buff), "~%.08$$mm", pcb_distance(pcb_crosshair.X, pcb_crosshair.Y, ox, oy)); + break; + case_object: ; + { + void *p1, *p2, *p3; + pcb_any_obj_t *o; + if (pcb_search_screen(pcb_crosshair.X, pcb_crosshair.Y, PCB_OBJ_LINE | PCB_OBJ_ARC, &p1, &p2, &p3) == 0) + return 0; + o = p2; + replace=1; + pcb_snprintf(buff, sizeof(buff), "%s %ld", find_rev_type(argv[by].type), (long)o->ID); + } + break; + default: + return 0; + } + + if (*buff == '\0') { + pcb_trace("nope...\n"); + return 0; + } + + if (replace) { + pcb_trace(" replace %d: '%s'\n", argn, buff); + cli_str_remove(line, argv[argn].begin, argv[argn].end); + cursor = cli_str_insert(line, argv[argn].begin, buff, 1); + + } + else { + pcb_trace(" insert-after %d: '%s'\n", argn, buff); + cursor = cli_str_insert(line, argv[argn].end, buff, 1); + } + +pcb_trace("line='%s'\n", line); + update:; + pcb_hid_command_entry(line, &cursor); + + return 0; +} + +static int line_tab(char *line, int cursor, int argc, cli_node_t *argv) +{ + pcb_trace("line t: '%s':%d\n", line, cursor); + return -1; +} + Index: tags/2.1.2/src_plugins/ddraft/constraint.c =================================================================== --- tags/2.1.2/src_plugins/ddraft/constraint.c (nonexistent) +++ tags/2.1.2/src_plugins/ddraft/constraint.c (revision 24813) @@ -0,0 +1,183 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * + * 2d drafting plugin: trim objects + * pcb-rnd Copyright (C) 2018 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "crosshair.h" +#include "obj_line.h" +#include "tool.h" + +typedef struct { + double line_angle[32], move_angle[32]; + pcb_coord_t line_length[32], move_length[32]; + double line_angle_mod, move_angle_mod; + pcb_coord_t line_length_mod, move_length_mod; + + int line_angle_len, line_length_len, move_angle_len, move_length_len; +} ddraft_cnst_t; + +static ddraft_cnst_t cons; + +static int find_best_angle(double *out_ang, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2, double *angles, int anglen, double angle_mod) +{ + double diff, ang, best_diff, target_ang; + int n, best; + + ang = atan2(y2 - y1, x2 - x1) * PCB_RAD_TO_DEG; + + if (anglen > 0) { + /* find the best matching constraint angle */ + best = -1; + best_diff = 1000.0; + for(n = 0; n < anglen; n++) { + if (angles[n] < 180) + diff = fabs(ang - angles[n]); + else + diff = fabs(ang + (angles[n]-180)); + if (diff < best_diff) { + best_diff = diff; + best = n; + } + } + if (best < 0) + return -1; + + target_ang = angles[best]; + } + else + target_ang = ang; + + if (angle_mod > 0) + target_ang = floor(target_ang / angle_mod) * angle_mod; + + target_ang /= PCB_RAD_TO_DEG; + *out_ang = target_ang; + return 0; +} + +static int find_best_length(double *out_len, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2, pcb_coord_t *lengths, int lengthlen, pcb_coord_t length_mod) +{ + double len, best_diff, diff, target_len; + int n, best; + + len = pcb_distance(x1, y1, x2, y2); + + if (lengthlen > 0) { + /* find the best matching constraint length */ + best = -1; + best_diff = COORD_MAX; + for(n = 0; n < lengthlen; n++) { + diff = fabs(len - lengths[n]); + if (diff < best_diff) { + best_diff = diff; + best = n; + } + } + if (best < 0) + return -1; + + target_len = lengths[best]; + } + else + target_len = len; + + if (length_mod > 0) + target_len = floor(target_len / (double)length_mod) * (double)length_mod; + + *out_len = target_len; + return 0; +} + +static void cnst_line_anglen(ddraft_cnst_t *cn) +{ + double target_ang, dx, dy, target_len; + pcb_route_object_t *line; + int res; + + if (((cn->line_angle_len == 0) && (cn->line_length_len == 0) && (cn->line_angle_mod <= 0) && (cn->line_length_mod <= 0)) || (pcb_crosshair.Route.size < 1)) + return; + + line = &pcb_crosshair.Route.objects[pcb_crosshair.Route.size-1]; + if (line->type != PCB_OBJ_LINE) + return; + + res = find_best_angle(&target_ang, + line->point1.X, line->point1.Y, pcb_crosshair.X, pcb_crosshair.Y, + cn->line_angle, cn->line_angle_len, cn->line_angle_mod); + if (res < 0) return; + + res = find_best_length(&target_len, + line->point1.X, line->point1.Y, pcb_crosshair.X, pcb_crosshair.Y, + cn->line_length, cn->line_length_len, cn->line_length_mod); + if (res < 0) return; + + dx = target_len * cos(target_ang); + dy = target_len * sin(target_ang); + + line->point2.X = line->point1.X + dx; + line->point2.Y = line->point1.Y + dy; +} + +static void cnst_line2(ddraft_cnst_t *cn) +{ + cnst_line_anglen(cn); +} + +static void cnst_move(ddraft_cnst_t *cn) +{ + double target_ang, dx, dy, target_len; + int res; + + if (((cn->move_angle_len == 0) && (cn->move_length_len == 0) && (cn->move_angle_mod <= 0) && (cn->move_length_mod <= 0))) + return; + + res = find_best_angle(&target_ang, + pcb_crosshair.AttachedObject.X, pcb_crosshair.AttachedObject.Y, pcb_crosshair.X, pcb_crosshair.Y, + cn->move_angle, cn->move_angle_len, cn->move_angle_mod); + if (res < 0) return; + + res = find_best_length(&target_len, + pcb_crosshair.AttachedObject.X, pcb_crosshair.AttachedObject.Y, pcb_crosshair.X, pcb_crosshair.Y, + cn->move_length, cn->move_length_len, cn->move_length_mod); + if (res < 0) return; + + dx = target_len * cos(target_ang); + dy = target_len * sin(target_ang); + + pcb_crosshair.AttachedObject.tx = pcb_crosshair.AttachedObject.X + dx; + pcb_crosshair.AttachedObject.ty = pcb_crosshair.AttachedObject.Y + dy; +} + +static void cnst_enforce(void *user_data, int argc, pcb_event_arg_t argv[]) +{ + if ((pcb_crosshair.AttachedLine.State == PCB_CH_STATE_SECOND) || (pcb_crosshair.AttachedLine.State == PCB_CH_STATE_THIRD)) + cnst_line2(&cons); + else if (pcb_crosshair.AttachedObject.State == PCB_CH_STATE_SECOND) /* normal d&d move or copy */ + cnst_move(&cons); + else if (pcb_tool_note.Moving) /* selected copy (buffer mode) */ + cnst_move(&cons); + +} Index: tags/2.1.2/src_plugins/ddraft/constraint_gui.c =================================================================== --- tags/2.1.2/src_plugins/ddraft/constraint_gui.c (nonexistent) +++ tags/2.1.2/src_plugins/ddraft/constraint_gui.c (revision 24813) @@ -0,0 +1,332 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * + * 2d drafting plugin: trim objects + * pcb-rnd Copyright (C) 2018 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "hid_dad.h" + +typedef struct{ + PCB_DAD_DECL_NOINIT(dlg) + int active; /* already open - allow only one instance */ + + /* widget IDs */ + int alldir; + int line_angle, move_angle; + int line_length, move_length; + int line_angle_mod, move_angle_mod; + int line_length_mod, move_length_mod; + + int inhibit_confchg; +} cnstgui_ctx_t; + +cnstgui_ctx_t cnstgui_ctx; + +static void cnstgui_close_cb(void *caller_data, pcb_hid_attr_ev_t ev) +{ + cnstgui_ctx_t *ctx = caller_data; + PCB_DAD_FREE(ctx->dlg); + memset(ctx, 0, sizeof(cnstgui_ctx_t)); /* reset all states to the initial - includes ctx->active = 0; */ +} + + +#define c2g_array(name, fmt) \ +do { \ + int n, l, len = sizeof(buff)-1; \ + char *end = buff; \ + *end = 0; \ + for(n = 0; n < cons.name ## _len; n++) { \ + if (n > 0) { \ + *end++ = ' '; \ + len--; \ + } \ + l = pcb_snprintf(end, len, fmt, cons.name[n]); \ + len -= l; \ + end += l; \ + } \ + PCB_DAD_SET_VALUE(cnstgui_ctx.dlg_hid_ctx, cnstgui_ctx.name, str_value, pcb_strdup(buff)); \ +} while(0) + +#define c2g_float(name) \ +do { \ + PCB_DAD_SET_VALUE(cnstgui_ctx.dlg_hid_ctx, cnstgui_ctx.name, real_value, cons.name); \ +} while(0) + +#define c2g_coord(name) \ +do { \ + PCB_DAD_SET_VALUE(cnstgui_ctx.dlg_hid_ctx, cnstgui_ctx.name, coord_value, cons.name); \ +} while(0) + +/* copy all cons fields into the GUI struct */ +static void cons_changed(void) +{ + char buff[1024]; + + c2g_array(line_angle, "%f"); + c2g_float(line_angle_mod); + c2g_array(line_length, "%.08$$mH"); + c2g_coord(line_length_mod); + + c2g_array(move_angle, "%f"); + c2g_float(move_angle_mod); + c2g_array(move_length, "%.08$$mH"); + c2g_coord(move_length_mod); +} + +#define g2c_array(name, conv) \ +do { \ + const char *inp = cnstgui_ctx.dlg[cnstgui_ctx.name].default_val.str_value; \ + char *curr, *next; \ + cons.name ## _len = 0; \ + if (inp == NULL) break; \ + strncpy(buff, inp, sizeof(buff)); \ + for(curr = buff; curr != NULL; curr = next) { \ + while(isspace(*curr)) curr++; \ + if (*curr == '\0') break; \ + next = strpbrk(curr, ",; "); \ + if (next != NULL) { \ + *next = '\0'; \ + next++; \ + while(isspace(*next)) next++; \ + } \ + cons.name[cons.name ## _len++] = conv; \ + } \ +} while(0) + +#define g2c_scalar(name, valty) \ +do { \ + cons.name = cnstgui_ctx.dlg[cnstgui_ctx.name].default_val.valty; \ +} while(0) + + +/* copy all GUI fields into the cons struct */ +static void gui2cons(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + char *end, buff[1024]; + pcb_bool succ; + + g2c_array(line_angle, strtod(curr, &end)); + g2c_scalar(line_angle_mod, real_value); + g2c_array(line_length, pcb_get_value(curr, NULL, NULL, &succ)); + g2c_scalar(line_length_mod, coord_value); + + g2c_array(move_angle, strtod(curr, &end)); + g2c_scalar(move_angle_mod, real_value); + g2c_array(move_length, pcb_get_value(curr, NULL, NULL, &succ)); + g2c_scalar(move_length_mod, coord_value); +} + +static void reset_line(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + PCB_DAD_SET_VALUE(cnstgui_ctx.dlg_hid_ctx, cnstgui_ctx.line_angle, str_value, pcb_strdup("")); + PCB_DAD_SET_VALUE(cnstgui_ctx.dlg_hid_ctx, cnstgui_ctx.line_angle_mod, real_value, 0); + PCB_DAD_SET_VALUE(cnstgui_ctx.dlg_hid_ctx, cnstgui_ctx.line_length, str_value, pcb_strdup("")); + PCB_DAD_SET_VALUE(cnstgui_ctx.dlg_hid_ctx, cnstgui_ctx.line_length_mod, coord_value, 0); + gui2cons(hid_ctx, caller_data, attr); +} + +static void reset_move(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + PCB_DAD_SET_VALUE(cnstgui_ctx.dlg_hid_ctx, cnstgui_ctx.move_angle, str_value, pcb_strdup("")); + PCB_DAD_SET_VALUE(cnstgui_ctx.dlg_hid_ctx, cnstgui_ctx.move_angle_mod, real_value, 0); + PCB_DAD_SET_VALUE(cnstgui_ctx.dlg_hid_ctx, cnstgui_ctx.move_length, str_value, pcb_strdup("")); + PCB_DAD_SET_VALUE(cnstgui_ctx.dlg_hid_ctx, cnstgui_ctx.move_length_mod, coord_value, 0); + gui2cons(hid_ctx, caller_data, attr); +} + +static void set_paral(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + pcb_actionl("paral", NULL); +} + +static void set_perp(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + pcb_actionl("perp", NULL); +} + + +static void set_tang(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + pcb_actionl("tang", NULL); +} + +void cons_gui_confchg(conf_native_t *cfg, int arr_idx) +{ + if (!cnstgui_ctx.active || cnstgui_ctx.inhibit_confchg) + return; + + cnstgui_ctx.inhibit_confchg++; + PCB_DAD_SET_VALUE(cnstgui_ctx.dlg_hid_ctx, cnstgui_ctx.alldir, int_value, conf_core.editor.all_direction_lines); + cnstgui_ctx.inhibit_confchg--; +} + +static void set_alldir(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + const char *nv; + if (cnstgui_ctx.inhibit_confchg) + return; + + cnstgui_ctx.inhibit_confchg++; + nv = (cnstgui_ctx.dlg[cnstgui_ctx.alldir].default_val.int_value) ? "1" : "0"; + conf_set(CFR_DESIGN, "editor/all_direction_lines", -1, nv, POL_OVERWRITE); + cnstgui_ctx.inhibit_confchg--; +} + + + +int constraint_gui(void) +{ + const char *tab_names[] = {"line", "move", NULL}; + pcb_hid_dad_buttons_t clbtn[] = {{"Close", 0}, {NULL, 0}}; + if (cnstgui_ctx.active) + return 0; /* do not open another */ + + PCB_DAD_BEGIN_VBOX(cnstgui_ctx.dlg); + PCB_DAD_COMPFLAG(cnstgui_ctx.dlg, PCB_HATF_EXPFILL); + PCB_DAD_BEGIN_TABBED(cnstgui_ctx.dlg, tab_names); + + /* line */ + PCB_DAD_BEGIN_VBOX(cnstgui_ctx.dlg); + PCB_DAD_BEGIN_HBOX(cnstgui_ctx.dlg); + PCB_DAD_LABEL(cnstgui_ctx.dlg, "All direction lines:"); + PCB_DAD_BOOL(cnstgui_ctx.dlg, ""); + cnstgui_ctx.alldir = PCB_DAD_CURRENT(cnstgui_ctx.dlg); + PCB_DAD_CHANGE_CB(cnstgui_ctx.dlg, set_alldir); + PCB_DAD_HELP(cnstgui_ctx.dlg, "Constraints work well only when\nthe all-direction-lines is enabled"); + PCB_DAD_END(cnstgui_ctx.dlg); + PCB_DAD_BEGIN_HBOX(cnstgui_ctx.dlg); + PCB_DAD_LABEL(cnstgui_ctx.dlg, "Fixed angles:"); + PCB_DAD_STRING(cnstgui_ctx.dlg); + cnstgui_ctx.line_angle = PCB_DAD_CURRENT(cnstgui_ctx.dlg); + PCB_DAD_HELP(cnstgui_ctx.dlg, "space separated list of valid line angles in degree"); + PCB_DAD_BUTTON(cnstgui_ctx.dlg, "apply"); + PCB_DAD_CHANGE_CB(cnstgui_ctx.dlg, gui2cons); + PCB_DAD_END(cnstgui_ctx.dlg); + PCB_DAD_BEGIN_HBOX(cnstgui_ctx.dlg); + PCB_DAD_LABEL(cnstgui_ctx.dlg, "Angle modulo:"); + PCB_DAD_REAL(cnstgui_ctx.dlg, ""); + cnstgui_ctx.line_angle_mod = PCB_DAD_CURRENT(cnstgui_ctx.dlg); + PCB_DAD_MINVAL(cnstgui_ctx.dlg, 0); + PCB_DAD_MAXVAL(cnstgui_ctx.dlg, 180); + PCB_DAD_CHANGE_CB(cnstgui_ctx.dlg, gui2cons); + PCB_DAD_HELP(cnstgui_ctx.dlg, "if non-zero:\nline angle must be an integer multiply of this value"); + PCB_DAD_END(cnstgui_ctx.dlg); + PCB_DAD_BEGIN_HBOX(cnstgui_ctx.dlg); + PCB_DAD_LABEL(cnstgui_ctx.dlg, "Fixed lengths:"); + PCB_DAD_STRING(cnstgui_ctx.dlg); + cnstgui_ctx.line_length = PCB_DAD_CURRENT(cnstgui_ctx.dlg); + PCB_DAD_HELP(cnstgui_ctx.dlg, "space separated list of valid line lengths"); + PCB_DAD_BUTTON(cnstgui_ctx.dlg, "apply"); + PCB_DAD_CHANGE_CB(cnstgui_ctx.dlg, gui2cons); + PCB_DAD_END(cnstgui_ctx.dlg); + PCB_DAD_BEGIN_HBOX(cnstgui_ctx.dlg); + PCB_DAD_LABEL(cnstgui_ctx.dlg, "Length modulo:"); + PCB_DAD_COORD(cnstgui_ctx.dlg, ""); + cnstgui_ctx.line_length_mod = PCB_DAD_CURRENT(cnstgui_ctx.dlg); + PCB_DAD_MINVAL(cnstgui_ctx.dlg, 0); + PCB_DAD_MAXVAL(cnstgui_ctx.dlg, PCB_MM_TO_COORD(1000)); + PCB_DAD_CHANGE_CB(cnstgui_ctx.dlg, gui2cons); + PCB_DAD_HELP(cnstgui_ctx.dlg, "if non-zero:\nline length must be an integer multiply of this value"); + PCB_DAD_END(cnstgui_ctx.dlg); + + PCB_DAD_BEGIN_HBOX(cnstgui_ctx.dlg); + PCB_DAD_BUTTON(cnstgui_ctx.dlg, "perpendicular to line"); + PCB_DAD_CHANGE_CB(cnstgui_ctx.dlg, set_perp); + PCB_DAD_HELP(cnstgui_ctx.dlg, "sets the angle constraint perpendicular to a line\nselected on the drawing"); + PCB_DAD_BUTTON(cnstgui_ctx.dlg, "parallel with line"); + PCB_DAD_CHANGE_CB(cnstgui_ctx.dlg, set_paral); + PCB_DAD_HELP(cnstgui_ctx.dlg, "sets the angle constraint parallel to a line\nselected on the drawing"); + PCB_DAD_END(cnstgui_ctx.dlg); + + PCB_DAD_BEGIN_HBOX(cnstgui_ctx.dlg); + PCB_DAD_BUTTON(cnstgui_ctx.dlg, "tangential to arc"); + PCB_DAD_CHANGE_CB(cnstgui_ctx.dlg, set_tang); + PCB_DAD_HELP(cnstgui_ctx.dlg, "sets the angle constraint to be tangential to the circle of an arc\nselected on the drawing"); + PCB_DAD_END(cnstgui_ctx.dlg); + + PCB_DAD_BEGIN_HBOX(cnstgui_ctx.dlg); + PCB_DAD_BUTTON(cnstgui_ctx.dlg, "Reset"); + PCB_DAD_CHANGE_CB(cnstgui_ctx.dlg, reset_line); + PCB_DAD_HELP(cnstgui_ctx.dlg, "clear line constraint values"); + PCB_DAD_END(cnstgui_ctx.dlg); + + PCB_DAD_END(cnstgui_ctx.dlg); + + /* move */ + PCB_DAD_BEGIN_VBOX(cnstgui_ctx.dlg); + PCB_DAD_BEGIN_HBOX(cnstgui_ctx.dlg); + PCB_DAD_LABEL(cnstgui_ctx.dlg, "Fixed angles:"); + PCB_DAD_STRING(cnstgui_ctx.dlg); + cnstgui_ctx.move_angle = PCB_DAD_CURRENT(cnstgui_ctx.dlg); + PCB_DAD_HELP(cnstgui_ctx.dlg, "space separated list of valid move vector angles in degree"); + PCB_DAD_BUTTON(cnstgui_ctx.dlg, "apply"); + PCB_DAD_CHANGE_CB(cnstgui_ctx.dlg, gui2cons); + PCB_DAD_END(cnstgui_ctx.dlg); + PCB_DAD_BEGIN_HBOX(cnstgui_ctx.dlg); + PCB_DAD_LABEL(cnstgui_ctx.dlg, "Angle modulo:"); + PCB_DAD_REAL(cnstgui_ctx.dlg, ""); + cnstgui_ctx.move_angle_mod = PCB_DAD_CURRENT(cnstgui_ctx.dlg); + PCB_DAD_MINVAL(cnstgui_ctx.dlg, 0); + PCB_DAD_MAXVAL(cnstgui_ctx.dlg, 180); + PCB_DAD_CHANGE_CB(cnstgui_ctx.dlg, gui2cons); + PCB_DAD_HELP(cnstgui_ctx.dlg, "if non-zero:\nmove vector angle must be an integer multiply of this value"); + PCB_DAD_END(cnstgui_ctx.dlg); + PCB_DAD_BEGIN_HBOX(cnstgui_ctx.dlg); + PCB_DAD_LABEL(cnstgui_ctx.dlg, "Fixed lengths:"); + PCB_DAD_STRING(cnstgui_ctx.dlg); + cnstgui_ctx.move_length = PCB_DAD_CURRENT(cnstgui_ctx.dlg); + PCB_DAD_HELP(cnstgui_ctx.dlg, "space separated list of valid move distances"); + PCB_DAD_BUTTON(cnstgui_ctx.dlg, "apply"); + PCB_DAD_CHANGE_CB(cnstgui_ctx.dlg, gui2cons); + PCB_DAD_END(cnstgui_ctx.dlg); + PCB_DAD_BEGIN_HBOX(cnstgui_ctx.dlg); + PCB_DAD_LABEL(cnstgui_ctx.dlg, "Length modulo:"); + PCB_DAD_COORD(cnstgui_ctx.dlg, ""); + cnstgui_ctx.move_length_mod = PCB_DAD_CURRENT(cnstgui_ctx.dlg); + PCB_DAD_MINVAL(cnstgui_ctx.dlg, 0); + PCB_DAD_MAXVAL(cnstgui_ctx.dlg, PCB_MM_TO_COORD(1000)); + PCB_DAD_CHANGE_CB(cnstgui_ctx.dlg, gui2cons); + PCB_DAD_HELP(cnstgui_ctx.dlg, "if non-zero:\nmove distance must be an integer multiply of this value"); + PCB_DAD_END(cnstgui_ctx.dlg); + PCB_DAD_BEGIN_HBOX(cnstgui_ctx.dlg); + PCB_DAD_BUTTON(cnstgui_ctx.dlg, "Reset"); + PCB_DAD_CHANGE_CB(cnstgui_ctx.dlg, reset_move); + PCB_DAD_HELP(cnstgui_ctx.dlg, "clear move constraint values"); + PCB_DAD_END(cnstgui_ctx.dlg); + PCB_DAD_END(cnstgui_ctx.dlg); + + PCB_DAD_END(cnstgui_ctx.dlg); + PCB_DAD_BUTTON_CLOSES(cnstgui_ctx.dlg, clbtn); + PCB_DAD_END(cnstgui_ctx.dlg); + + /* set up the context */ + cnstgui_ctx.active = 1; + + PCB_DAD_NEW("constraint", cnstgui_ctx.dlg, "Drawing constraints", &cnstgui_ctx, pcb_false, cnstgui_close_cb); + + cons_changed(); + + return 0; +} Index: tags/2.1.2/src_plugins/ddraft/ddraft.c =================================================================== --- tags/2.1.2/src_plugins/ddraft/ddraft.c (nonexistent) +++ tags/2.1.2/src_plugins/ddraft/ddraft.c (revision 24813) @@ -0,0 +1,454 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * + * 2d drafting plugin + * pcb-rnd Copyright (C) 2018 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "config.h" + +#include +#include +#include +#include + +#include "hid_attrib.h" +#include "hid_init.h" +#include "plugins.h" +#include "event.h" +#include "actions.h" +#include "funchash_core.h" +#include "search.h" +#include "centgeo.h" +#include "misc_util.h" +#include "board.h" +#include "data_it.h" +#include "obj_line.h" +#include "undo.h" +#include "fields_sphash.h" +#include "draw_wireframe.h" +#include "conf_core.h" +#include "conf_hid.h" +#include "vtc0.h" + +static const char *ddraft_cookie = "ddraft plugin"; +static int pcb_ddraft_tool; + +typedef struct { + pcb_line_t line; + int line_valid; + + vtc0_t annot_lines; /* each 4 coords specify a line */ +} pcb_ddraft_attached_t; + +pcb_ddraft_attached_t pcb_ddraft_attached; + +void pcb_ddraft_attached_reset(void) +{ + pcb_ddraft_attached.line_valid = 0; + vtc0_truncate(&pcb_ddraft_attached.annot_lines, 0); +} + +#define EDGE_TYPES (PCB_OBJ_LINE | PCB_OBJ_ARC) +#define CUT_TYPES (PCB_OBJ_LINE | PCB_OBJ_ARC) + +static void list_by_flag(pcb_data_t *data, vtp0_t *dst, unsigned long types, unsigned long flag) +{ + pcb_any_obj_t *o; + pcb_data_it_t it; + + for(o = pcb_data_first(&it, data, types); o != NULL; o = pcb_data_next(&it)) + if (PCB_FLAG_TEST(flag, o)) + vtp0_append(dst, o); +} + +#include "trim.c" +#include "constraint.c" + +static long do_trim_split(vtp0_t *edges, int kwobj, int trim) +{ + pcb_objtype_t type; + void *ptr1, *ptr2, *ptr3; + pcb_coord_t x, y; + long res = 0; + + switch(kwobj) { + case F_Object: + for(;;) { + x = PCB_MAX_COORD; + pcb_hid_get_coords("Select an object to cut or press esc", &x, &y, 1); + if (x == PCB_MAX_COORD) + break; + + type = pcb_search_screen(x, y, CUT_TYPES, &ptr1, &ptr2, &ptr3); + if (type == 0) { + pcb_message(PCB_MSG_ERROR, "Can't cut that object\n"); + continue; + } + res += pcb_trim_split(edges, (pcb_any_obj_t *)ptr2, REMO_INVALID, x, y, trim); + pcb_gui->invalidate_all(); + } + break; + default: + pcb_message(PCB_MSG_ERROR, "Invalid second argument\n"); + return -1; + } + + return res; +} + +static const char pcb_acts_trim_split[] = "trim([selected|found|object], [selected|found|object])\nsplit([selected|found|object], [selected|found|object])"; +static const char pcb_acth_trim_split[] = "Use one or more objects as cutting edge and trim or split other objects. First argument is the cutting edge"; +static fgw_error_t pcb_act_trim_split(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + const char *actname = argv[0].val.func->name; + int kwcut = F_Object, kwobj = F_Object; + pcb_objtype_t type; + void *ptr1, *ptr2, *ptr3; + pcb_coord_t x, y; + vtp0_t edges; + + PCB_ACT_MAY_CONVARG(1, FGW_KEYWORD, trim_split, kwcut = fgw_keyword(&argv[1])); + PCB_ACT_MAY_CONVARG(2, FGW_KEYWORD, trim_split, kwobj = fgw_keyword(&argv[2])); + + vtp0_init(&edges); + + if ((kwobj == kwcut) && (kwobj != F_Object)) { + pcb_message(PCB_MSG_ERROR, "Both cutting edge and objects to cut can't be '%s'\n", kwcut == F_Selected ? "selected" : "found"); + goto err; + } + + switch(kwcut) { + case F_Object: + pcb_hid_get_coords("Select cutting edge object", &x, &y, 0); + type = pcb_search_screen(x, y, EDGE_TYPES, &ptr1, &ptr2, &ptr3); + if (type == 0) { + pcb_message(PCB_MSG_ERROR, "Invalid cutting edge object\n"); + goto err; + } + vtp0_append(&edges, ptr2); + break; + case F_Selected: + list_by_flag(PCB->Data, &edges, EDGE_TYPES, PCB_FLAG_SELECTED); + break; + case F_Found: + list_by_flag(PCB->Data, &edges, EDGE_TYPES, PCB_FLAG_FOUND); + break; + default: + pcb_message(PCB_MSG_ERROR, "Invalid first argument\n"); + goto err; + } + + if (vtp0_len(&edges) < 1) { + pcb_message(PCB_MSG_ERROR, "No cutting edge found\n"); + goto err; + } + + + if (do_trim_split(&edges, kwobj, (*actname == 't')) < 0) + goto err; + + PCB_ACT_IRES(0); + vtp0_uninit(&edges); + return 0; + + err:; + PCB_ACT_IRES(-1); + vtp0_uninit(&edges); + return 0; +} + +#include "constraint_gui.c" + +#define load_arr(arr, ctr, msg, fgw_type_, fgw_val_) \ +do { \ + int n; \ + if (argc-2 >= sizeof(arr) / sizeof(arr[0])) { \ + pcb_message(PCB_MSG_ERROR, "constraint: Too many " msg "\n"); \ + PCB_ACT_IRES(-1); \ + return 0; \ + } \ + ctr = 0; \ + for(n = 2; n < argc; n++) { \ + PCB_ACT_CONVARG(n, fgw_type_, constraint, arr[ctr] = fgw_val_); \ + ctr++; \ + } \ +} while(0) + +static const char pcb_acts_constraint[] = "constraint(type, off)\nconstraint(type, value, [value...])"; +static const char pcb_acth_constraint[] = "Configure or remove a drawing constraint"; +static fgw_error_t pcb_act_constraint(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + char *stype = NULL; + int type; + + PCB_ACT_MAY_CONVARG(1, FGW_STR, constraint, stype = argv[1].val.str); + if (stype == NULL) { + PCB_ACT_IRES(constraint_gui()); + return 0; + } + type = ddraft_fields_sphash(stype); + switch(type) { + case ddraft_fields_line_angle: + load_arr(cons.line_angle, cons.line_angle_len, "line angles", FGW_DOUBLE, argv[n].val.nat_double); + cons_changed(); + break; + case ddraft_fields_move_angle: + load_arr(cons.move_angle, cons.move_angle_len, "move angles", FGW_DOUBLE, argv[n].val.nat_double); + cons_changed(); + break; + case ddraft_fields_line_angle_mod: + cons.line_angle_mod = 0; + PCB_ACT_MAY_CONVARG(2, FGW_DOUBLE, constraint, cons.line_angle_mod = argv[2].val.nat_double); + cons_changed(); + break; + case ddraft_fields_move_angle_mod: + cons.move_angle_mod = 0; + PCB_ACT_MAY_CONVARG(2, FGW_DOUBLE, constraint, cons.move_angle_mod = argv[2].val.nat_double); + cons_changed(); + break; + case ddraft_fields_line_length: + load_arr(cons.line_length, cons.line_length_len, "line lengths", FGW_COORD, fgw_coord(&argv[n])); + cons_changed(); + break; + case ddraft_fields_move_length: + load_arr(cons.move_length, cons.move_length_len, "move lengths", FGW_COORD, fgw_coord(&argv[n])); + cons_changed(); + break; + case ddraft_fields_line_length_mod: + cons.line_length_mod = 0; + PCB_ACT_MAY_CONVARG(2, FGW_COORD, constraint, cons.line_length_mod = fgw_coord(&argv[2])); + cons_changed(); + break; + case ddraft_fields_move_length_mod: + cons.move_length_mod = 0; + PCB_ACT_MAY_CONVARG(2, FGW_COORD, constraint, cons.move_length_mod = fgw_coord(&argv[2])); + cons_changed(); + break; + + case ddraft_fields_reset: + memset(&cons, 0, sizeof(cons)); + cons_changed(); + break; + case ddraft_fields_SPHASH_INVALID: + pcb_message(PCB_MSG_ERROR, "constraint: invalid field '%s'\n", stype); + PCB_ACT_IRES(-1); + return 0; + break; + } + + PCB_ACT_IRES(0); + return 0; +} + +static const char pcb_acts_perp_paral[] = "perp()"; +static const char pcb_acth_perp_paral[] = "Draw a line perpendicular to another line"; +static fgw_error_t pcb_act_perp_paral(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + const char *actname = argv[0].val.func->name; + pcb_objtype_t type; + void *ptr1, *ptr2, *ptr3; + pcb_coord_t x, y; + double dx, dy; + pcb_line_t *line; + + pcb_hid_get_coords("Select target object", &x, &y, 0); + type = pcb_search_screen(x, y, EDGE_TYPES, &ptr1, &ptr2, &ptr3); + + if (type != PCB_OBJ_LINE) { + pcb_hid_get_coords("Select target object", &x, &y, 1); + type = pcb_search_screen(x, y, EDGE_TYPES, &ptr1, &ptr2, &ptr3); + } + + if (type != PCB_OBJ_LINE) { + pcb_message(PCB_MSG_ERROR, "%s: target object must be a line\n", actname); + PCB_ACT_IRES(-1); + return 0; + } + + line = (pcb_line_t *)ptr2; + dx = line->Point2.X - line->Point1.X; + dy = line->Point2.Y - line->Point1.Y; + if ((dx == 0.0) && (dy == 0.0)) { + pcb_message(PCB_MSG_ERROR, "%s: target line must be longer than 0\n", actname); + PCB_ACT_IRES(-1); + return 0; + } + + cons.line_angle_len = 2; + cons.line_angle[0] = atan2(dy, dx) * PCB_RAD_TO_DEG; + if (actname[1] == 'e') /* perp */ + cons.line_angle[0] += 90; + cons.line_angle[1] = fmod(cons.line_angle[0]+180, 360); + cons_changed(); + + PCB_ACT_IRES(0); + return 0; +} + + +static const char pcb_acts_tang[] = "tang()"; +static const char pcb_acth_tang[] = "Draw a line to be tangential to a circle"; +static fgw_error_t pcb_act_tang(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + pcb_objtype_t type; + void *ptr1, *ptr2, *ptr3; + pcb_coord_t x, y; + double d, r, base; + pcb_route_object_t *line; + pcb_arc_t *arc; + + + if (((pcb_crosshair.AttachedLine.State != PCB_CH_STATE_SECOND) && (pcb_crosshair.AttachedLine.State != PCB_CH_STATE_THIRD)) || (pcb_crosshair.Route.size < 1)) { + err_nonline:; + pcb_message(PCB_MSG_ERROR, "tang: must be in line drawing mode with the first point already set\n"); + PCB_ACT_IRES(-1); + return 0; + } + + line = &pcb_crosshair.Route.objects[pcb_crosshair.Route.size-1]; + if (line->type != PCB_OBJ_LINE) + goto err_nonline; + + + pcb_hid_get_coords("Select target arc", &x, &y, 0); + type = pcb_search_screen(x, y, EDGE_TYPES, &ptr1, &ptr2, &ptr3); + + if (type != PCB_OBJ_ARC) { + pcb_hid_get_coords("Select target arc", &x, &y, 1); + type = pcb_search_screen(x, y, EDGE_TYPES, &ptr1, &ptr2, &ptr3); + } + + if (type != PCB_OBJ_ARC) { + pcb_message(PCB_MSG_ERROR, "tang: target object must be an arc\n"); + PCB_ACT_IRES(-1); + return 0; + } + + arc = (pcb_arc_t *)ptr2; + if (fabs(arc->Height - arc->Width) > 100) { + pcb_message(PCB_MSG_ERROR, "tang: elliptical arcs are not supported (%$mm != %$mm)\n", arc->Height, arc->Width); + PCB_ACT_IRES(-1); + return 0; + } + + d = pcb_distance(arc->X, arc->Y, line->point1.X, line->point1.Y); + r = arc->Width; + + if (d <= r) { + pcb_message(PCB_MSG_ERROR, "tang: line must start outside of the circle\n"); + PCB_ACT_IRES(-1); + return 0; + } + + base = atan2(arc->Y - line->point1.Y, arc->X - line->point1.X); + + cons.line_angle_len = 2; + cons.line_angle[0] = (base + asin(r / d)) * PCB_RAD_TO_DEG; + cons.line_angle[1] = (base + asin(-r / d)) * PCB_RAD_TO_DEG; + cons_changed(); + + PCB_ACT_IRES(0); + return 0; +} + +void ddraft_tool_draw_attached(void) +{ + int n; + pcb_gui->set_line_cap(pcb_crosshair.GC, pcb_cap_round); + pcb_gui->set_line_width(pcb_crosshair.GC, 1); + pcb_gui->set_color(pcb_crosshair.GC, pcb_color_grey33); + for(n = 0; n < vtc0_len(&pcb_ddraft_attached.annot_lines); n += 4) { + pcb_coord_t *c = &pcb_ddraft_attached.annot_lines.array[n]; + pcb_gui->draw_line(pcb_crosshair.GC, c[0], c[1], c[2], c[3]); + } + + if (pcb_ddraft_attached.line_valid) { + pcb_gui->set_color(pcb_crosshair.GC, &CURRENT->meta.real.color); + pcb_draw_wireframe_line(pcb_crosshair.GC, + pcb_ddraft_attached.line.Point1.X, pcb_ddraft_attached.line.Point1.Y, pcb_ddraft_attached.line.Point2.X, pcb_ddraft_attached.line.Point2.Y, + conf_core.design.line_thickness, 0); + } +} + +#include "cli.c" + +static pcb_action_t ddraft_action_list[] = { + {"trim", pcb_act_trim_split, pcb_acth_trim_split, pcb_acts_trim_split}, + {"split", pcb_act_trim_split, pcb_acth_trim_split, pcb_acts_trim_split}, + {"constraint", pcb_act_constraint, pcb_acth_constraint, pcb_acts_constraint}, + {"perp", pcb_act_perp_paral, pcb_acth_perp_paral, pcb_acts_perp_paral}, + {"paral", pcb_act_perp_paral, pcb_acth_perp_paral, pcb_acts_perp_paral}, + {"tang", pcb_act_tang, pcb_acth_tang, pcb_acts_tang}, + {"ddraft", pcb_act_ddraft, pcb_acth_ddraft, pcb_acts_ddraft} +}; + +PCB_REGISTER_ACTIONS(ddraft_action_list, ddraft_cookie) + +static pcb_tool_t tool_ddraft = { + "ddraft", NULL, 1000, + NULL, + NULL, + NULL, + NULL, + NULL, + ddraft_tool_draw_attached, + NULL, + NULL, + pcb_false +}; + +int pplg_check_ver_ddraft(int ver_needed) { return 0; } + +void pplg_uninit_ddraft(void) +{ + conf_hid_unreg(ddraft_cookie); + pcb_event_unbind_allcookie(ddraft_cookie); + pcb_remove_actions_by_cookie(ddraft_cookie); + pcb_tool_unreg_by_cookie(ddraft_cookie); +} + + +static const conf_hid_callbacks_t conf_cbs = { NULL, cons_gui_confchg, NULL, NULL }; + +#include "dolists.h" +int pplg_init_ddraft(void) +{ + conf_native_t *cn; + conf_hid_id_t confid; + + PCB_API_CHK_VER; + + PCB_REGISTER_ACTIONS(ddraft_action_list, ddraft_cookie) + pcb_event_bind(PCB_EVENT_DRAW_CROSSHAIR_CHATT, cnst_enforce, NULL, ddraft_cookie); + + pcb_tool_reg(&tool_ddraft, ddraft_cookie); + pcb_ddraft_tool = pcb_tool_lookup(tool_ddraft.name); + + + cn = conf_get_field("editor/all_direction_lines"); + confid = conf_hid_reg(ddraft_cookie, NULL); + conf_hid_set_cb(cn, confid, &conf_cbs); + return 0; +} Index: tags/2.1.2/src_plugins/ddraft/ddraft.pup =================================================================== --- tags/2.1.2/src_plugins/ddraft/ddraft.pup (nonexistent) +++ tags/2.1.2/src_plugins/ddraft/ddraft.pup (revision 24813) @@ -0,0 +1,7 @@ +$class export +$short 2D drafting helper +$long Actions and a command interpreter for supporting advanced/precise 2 dimensional drafting +$state WIP +$package core +default buildin +autoload 1 Index: tags/2.1.2/src_plugins/ddraft/fields.sphash =================================================================== --- tags/2.1.2/src_plugins/ddraft/fields.sphash (nonexistent) +++ tags/2.1.2/src_plugins/ddraft/fields.sphash (revision 24813) @@ -0,0 +1,9 @@ +line_angle +line_length +line_angle_mod +line_length_mod +move_angle +move_length +move_angle_mod +move_length_mod +reset Index: tags/2.1.2/src_plugins/ddraft/trim.c =================================================================== --- tags/2.1.2/src_plugins/ddraft/trim.c (nonexistent) +++ tags/2.1.2/src_plugins/ddraft/trim.c (revision 24813) @@ -0,0 +1,378 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * + * 2d drafting plugin: trim objects + * pcb-rnd Copyright (C) 2018 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "undo_old.h" + +#define REMO_INVALID -1000.0 +#define remo_is_valid(v) ((v) > REMO_INVALID) + +/* Move a line endpoint to a new absoltue coord in an undoable way */ +static void move_lp(pcb_line_t *line, int pt_idx, pcb_coord_t x, pcb_coord_t y) +{ + pcb_point_t *pt; + + switch(pt_idx) { + case 1: pt = &line->Point1; break; + case 2: pt = &line->Point2; break; + default: + abort(); + } + + pcb_undo_add_obj_to_move(PCB_OBJ_LINE_POINT, line->parent.layer, line, pt, x - pt->X, y - pt->Y); + pcb_line_pre(line); + pt->X = x; + pt->Y = y; + pcb_line_post(line); +} + +/* normallize mino and maxo: make sure they are in the [0..1] range */ +#define norm_minmaxo() \ + do { \ + if (mino < 0.0) \ + mino = 0.0; \ + if (maxo > 1.0) \ + mino = 1.0; \ + } while(0) + +static int pcb_trim_line(vtp0_t *cut_edges, pcb_line_t *line, double remo_in, pcb_coord_t rem_x, pcb_coord_t rem_y) +{ + int p, n; + double io[2]; + double mino = 0.0, maxo = 1.0, remo = remo_in; + pcb_coord_t x, y; + + if (!remo_is_valid(remo)) + remo = pcb_cline_pt_offs(line, rem_x, rem_y); + + for(n = 0; n < vtp0_len(cut_edges); n++) { + pcb_any_obj_t *cut_edge = (pcb_any_obj_t *)cut_edges->array[n]; + + p = 0; + switch(cut_edge->type) { + case PCB_OBJ_LINE: + p = pcb_intersect_cline_cline(line, (pcb_line_t *)cut_edge, NULL, io); + break; + case PCB_OBJ_ARC: + p = pcb_intersect_cline_carc(line, (pcb_arc_t *)cut_edge, NULL, io); + break; + default: continue; + } + + switch(p) { + case 0: continue; /* no intersection, skip to the next potential cutting edge */ + case 2: + if (io[1] < remo) { + if (io[1] > mino) mino = io[1]; + } + else { + if (io[1] < maxo) maxo = io[1]; + } + case 1: + if (io[0] < remo) { + if (io[0] > mino) mino = io[0]; + } + else { + if (io[0] < maxo) maxo = io[0]; + } + break; + } + } + + norm_minmaxo(); + + if ((mino == 0.0) && (maxo == 1.0)) + return 0; /* nothing to be done */ + + if (mino == maxo) + return 0; /* refuse to end up with 0-length lines */ + + /* mino and maxo holds the two endpoint offsets after the cuts, in respect + to the original line. Cut/split the line using them. */ + if ((mino > 0.0) && (maxo < 1.0)) { /* remove (shortest) middle section */ + pcb_line_t *new_line = pcb_line_dup(line->parent.layer, line); + + pcb_undo_add_obj_to_create(PCB_OBJ_LINE, new_line->parent.layer, new_line, new_line); + + pcb_cline_offs(line, maxo, &x, &y); + move_lp(line, 1, x, y); + + pcb_cline_offs(new_line, mino, &x, &y); + move_lp(new_line, 2, x, y); + } + else if ((mino == 0.0) && (maxo < 1.0)) { /* truncate at point1 (shortest overdue) */ + pcb_cline_offs(line, maxo, &x, &y); + move_lp(line, 1, x, y); + } + else if ((mino > 0.0) && (maxo == 1.0)) { /* truncate at point2 (shortest overdue) */ + pcb_cline_offs(line, mino, &x, &y); + move_lp(line, 2, x, y); + } + else + return -1; + + return 1; +} + +/* Move arc start or end angle to a specific absolute angle (undoable) */ +static void move_arc_angs(pcb_arc_t *arc, int ep, double offs) +{ + double chg = offs * arc->Delta; + + pcb_undo_add_obj_to_change_angles(PCB_OBJ_ARC, arc->parent.layer, arc, arc); + pcb_arc_pre(arc); + switch(ep) { + case 1: + arc->StartAngle += chg; + arc->Delta -= chg; + break; + case 2: + arc->Delta = chg; + break; + } + pcb_arc_post(arc); +} + + +static int pcb_trim_arc(vtp0_t *cut_edges, pcb_arc_t *arc, double remo_in, pcb_coord_t rem_x, pcb_coord_t rem_y) +{ + int p, n; + double io[2]; + double mino = 0.0, maxo = 1.0, remo = remo_in; + + if (!remo_is_valid(remo)) + remo = pcb_carc_pt_offs(arc, rem_x, rem_y); + + for(n = 0; n < vtp0_len(cut_edges); n++) { + pcb_any_obj_t *cut_edge = (pcb_any_obj_t *)cut_edges->array[n]; + + p = 0; + switch(cut_edge->type) { + case PCB_OBJ_LINE: + p = pcb_intersect_carc_cline(arc, (pcb_line_t *)cut_edge, NULL, io); + break; + case PCB_OBJ_ARC: + p = pcb_intersect_carc_carc(arc, (pcb_arc_t *)cut_edge, NULL, io); + break; + default: continue; + } + + switch(p) { + case 0: continue; /* no intersection, skip to the next potential cutting edge */ + case 2: + if (io[1] < remo) { + if (io[1] > mino) mino = io[1]; + } + else { + if (io[1] < maxo) maxo = io[1]; + } + case 1: + if (io[0] < remo) { + if (io[0] > mino) mino = io[0]; + } + else { + if (io[0] < maxo) maxo = io[0]; + } + break; + } + } + + norm_minmaxo(); + + if ((mino == 0.0) && (maxo == 1.0)) + return 0; /* nothing to be done */ + + if (mino == maxo) + return 0; /* refuse to end up with 0-length lines */ + + /* mino and maxo holds the two endpoint offsets after the cuts, in respect + to the original line. Cut/split the line using them. */ + if ((mino > 0.0) && (maxo < 1.0)) { /* remove (shortest) middle section */ + pcb_arc_t *new_arc = pcb_arc_dup(arc->parent.layer, arc); + + pcb_undo_add_obj_to_create(PCB_OBJ_ARC, new_arc->parent.layer, new_arc, new_arc); + + move_arc_angs(arc, 1, maxo); + move_arc_angs(new_arc, 2, mino); + } + else if ((mino == 0.0) && (maxo < 1.0)) { /* truncate at point1 (shortest overdue) */ + move_arc_angs(arc, 1, maxo); + } + else if ((mino > 0.0) && (maxo == 1.0)) { /* truncate at point2 (shortest overdue) */ + move_arc_angs(arc, 2, mino); + } + else + return -1; + return 1; +} + +/* Split a line in two lines at a specific offset (undoable) */ +static pcb_line_t *split_lp(pcb_line_t *line, double offs) +{ + pcb_coord_t x, y; + pcb_line_t *new_line = pcb_line_dup(line->parent.layer, line); + + pcb_undo_add_obj_to_create(PCB_OBJ_LINE, new_line->parent.layer, new_line, new_line); + + pcb_cline_offs(line, offs, &x, &y); + move_lp(line, 2, x, y); + move_lp(new_line, 1, x, y); + + return new_line; +} + +/* Split an arc in two arcs at a specific offset (undoable) */ +static pcb_arc_t *split_arcp(pcb_arc_t *arc, double offs) +{ + pcb_arc_t *new_arc = pcb_arc_dup(arc->parent.layer, arc); + + pcb_undo_add_obj_to_create(PCB_OBJ_ARC, new_arc->parent.layer, new_arc, new_arc); + + move_arc_angs(arc, 2, offs); + move_arc_angs(new_arc, 1, offs); + + return new_arc; +} + + +static int pcb_split_line(vtp0_t *cut_edges, pcb_line_t *line, double remo_in, pcb_coord_t rem_x, pcb_coord_t rem_y) +{ + int p, n, numsplt = 0, res; + double io[2]; + pcb_line_t *new_line; + + for(n = 0; n < vtp0_len(cut_edges); n++) { + pcb_any_obj_t *cut_edge = (pcb_any_obj_t *)cut_edges->array[n]; + p = 0; + switch(cut_edge->type) { + case PCB_OBJ_LINE: + p = pcb_intersect_cline_cline(line, (pcb_line_t *)cut_edge, NULL, io); + break; + case PCB_OBJ_ARC: + p = pcb_intersect_cline_carc(line, (pcb_arc_t *)cut_edge, NULL, io); + break; + default: continue; + } + switch(p) { + case 0: continue; /* no intersection, skip to the next potential cutting edge */ + case 2: + if ((io[1] != 0.0) && (io[1] != 1.0)) { + new_line = split_lp(line, io[1]); + numsplt++; + res = pcb_split_line(cut_edges, line, remo_in, rem_x, rem_y); + if (res > 0) numsplt += res; + res = pcb_split_line(cut_edges, new_line, remo_in, rem_x, rem_y); + if (res > 0) numsplt += res; + break; /* can't use the other point if we did a split here, because that changes the meaning of offsets */ + } + case 1: + if ((io[0] != 0.0) && (io[0] != 1.0)) { + new_line = split_lp(line, io[0]); + numsplt++; + res = pcb_split_line(cut_edges, line, remo_in, rem_x, rem_y); + if (res > 0) numsplt += res; + res = pcb_split_line(cut_edges, new_line, remo_in, rem_x, rem_y); + if (res > 0) numsplt += res; + } + break; + } + } + + return numsplt; +} + +static int pcb_split_arc(vtp0_t *cut_edges, pcb_arc_t *arc, double remo_in, pcb_coord_t rem_x, pcb_coord_t rem_y) +{ + int p, n, numsplt = 0, res; + double io[2]; + pcb_arc_t *new_arc; + + for(n = 0; n < vtp0_len(cut_edges); n++) { + pcb_any_obj_t *cut_edge = (pcb_any_obj_t *)cut_edges->array[n]; + p = 0; + switch(cut_edge->type) { + case PCB_OBJ_LINE: + p = pcb_intersect_carc_cline(arc, (pcb_line_t *)cut_edge, NULL, io); + break; + case PCB_OBJ_ARC: + p = pcb_intersect_carc_carc(arc, (pcb_arc_t *)cut_edge, NULL, io); + break; + default: continue; + } + switch(p) { + case 0: continue; /* no intersection, skip to the next potential cutting edge */ + case 2: + if ((io[1] != 0.0) && (io[1] != 1.0)) { + new_arc = split_arcp(arc, io[1]); + numsplt++; + res = pcb_split_arc(cut_edges, arc, remo_in, rem_x, rem_y); + if (res > 0) numsplt += res; + res = pcb_split_arc(cut_edges, new_arc, remo_in, rem_x, rem_y); + if (res > 0) numsplt += res; + break; /* can't use the other point if we did a split here, because that changes the meaning of offsets */ + } + case 1: + if ((io[0] != 0.0) && (io[0] != 1.0)) { + new_arc = split_arcp(arc, io[0]); + numsplt++; + res = pcb_split_arc(cut_edges, arc, remo_in, rem_x, rem_y); + if (res > 0) numsplt += res; + res = pcb_split_arc(cut_edges, new_arc, remo_in, rem_x, rem_y); + if (res > 0) numsplt += res; + } + break; + } + } + + return numsplt; +} + +int pcb_trim_split(vtp0_t *cut_edges, pcb_any_obj_t *obj, double remo, pcb_coord_t rem_x, pcb_coord_t rem_y, int trim) +{ + int res = 0; + switch(obj->type) { + case PCB_OBJ_LINE: + if (trim) + res = pcb_trim_line(cut_edges, (pcb_line_t *)obj, remo, rem_x, rem_y); + else + res = pcb_split_line(cut_edges, (pcb_line_t *)obj, remo, rem_x, rem_y); + break; + case PCB_OBJ_ARC: + if (trim) + res = pcb_trim_arc(cut_edges, (pcb_arc_t *)obj, remo, rem_x, rem_y); + else + res = pcb_split_arc(cut_edges, (pcb_arc_t *)obj, remo, rem_x, rem_y); + break; + default: + return -1; + } + + if (res > 0) + pcb_undo_inc_serial(); + return res; +} + Index: tags/2.1.2/src_plugins/diag/Makefile =================================================================== --- tags/2.1.2/src_plugins/diag/Makefile (nonexistent) +++ tags/2.1.2/src_plugins/diag/Makefile (revision 24813) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_diag + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/2.1.2/src_plugins/diag/Plug.tmpasm =================================================================== --- tags/2.1.2/src_plugins/diag/Plug.tmpasm (nonexistent) +++ tags/2.1.2/src_plugins/diag/Plug.tmpasm (revision 24813) @@ -0,0 +1,14 @@ +put /local/pcb/mod {diag} +put /local/pcb/mod/OBJS [@ + $(PLUGDIR)/diag/diag.o + $(PLUGDIR)/diag/diag_conf.o + $(PLUGDIR)/diag/integrity.o +@] +put /local/pcb/mod/CONF {$(PLUGDIR)/diag/diag_conf.h} + + +switch /local/pcb/diag/controls + case {buildin} include /local/pcb/tmpasm/buildin; end; + case {plugin} include /local/pcb/tmpasm/plugin; end; + case {disable} include /local/pcb/tmpasm/disable; end; +end Index: tags/2.1.2/src_plugins/diag/diag.c =================================================================== --- tags/2.1.2/src_plugins/diag/diag.c (nonexistent) +++ tags/2.1.2/src_plugins/diag/diag.c (revision 24813) @@ -0,0 +1,543 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2016 Tibor 'Igor2' Palinkas + * + * This module, diag, was written and is Copyright (C) 2016 by Tibor Palinkas + * this module is also subject to the GNU GPL as described below + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "config.h" +#include "board.h" +#include "data.h" +#include "data_it.h" +#include "flag_str.h" +#include "layer.h" +#include "diag_conf.h" +#include "actions.h" +#include "plugins.h" +#include "conf.h" +#include "error.h" +#include "event.h" +#include "integrity.h" +#include "hid.h" +#include "hid_attrib.h" +#include "hid_dad.h" +#include "search.h" +#include "macro.h" +#include "funchash_core.h" + +conf_diag_t conf_diag; + +static const char pcb_acts_DumpConf[] = + "dumpconf(native, [verbose], [prefix]) - dump the native (binary) config tree to stdout\n" + "dumpconf(lihata, role, [prefix]) - dump in-memory lihata representation of a config tree\n" + ; +static const char pcb_acth_DumpConf[] = "Perform various operations on the configuration tree."; + +extern lht_doc_t *conf_main_root[]; +extern lht_doc_t *conf_plug_root[]; +static fgw_error_t pcb_act_DumpConf(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + int op; + + PCB_ACT_CONVARG(1, FGW_KEYWORD, DumpConf, op = fgw_keyword(&argv[1])); + + switch(op) { + case F_Native: + { + int verbose = 0; + const char *prefix = ""; + PCB_ACT_MAY_CONVARG(2, FGW_INT, DumpConf, verbose = argv[2].val.nat_int); + PCB_ACT_MAY_CONVARG(3, FGW_STR, DumpConf, prefix = argv[3].val.str); + conf_dump(stdout, prefix, verbose, NULL); + } + break; + case F_Lihata: + { + conf_role_t role; + const char *srole, *prefix = ""; + PCB_ACT_CONVARG(2, FGW_STR, DumpConf, srole = argv[2].val.str); + PCB_ACT_MAY_CONVARG(3, FGW_STR, DumpConf, prefix = argv[3].val.str); + role = conf_role_parse(srole); + if (role == CFR_invalid) { + pcb_message(PCB_MSG_ERROR, "Invalid role: '%s'\n", argv[1]); + PCB_ACT_IRES(1); + return 0; + } + if (conf_main_root[role] != NULL) { + printf("%s### main\n", prefix); + if (conf_main_root[role] != NULL) + lht_dom_export(conf_main_root[role]->root, stdout, prefix); + printf("%s### plugin\n", prefix); + if (conf_plug_root[role] != NULL) + lht_dom_export(conf_plug_root[role]->root, stdout, prefix); + } + else + printf("%s \n", prefix); + } + break; + default: + PCB_ACT_FAIL(DumpConf); + return 1; + } + + PCB_ACT_IRES(0); + return 0; +} + +static const char pcb_acts_EvalConf[] = + "EvalConf(path) - evaluate a config path in different config sources to figure how it ended up in the native database\n" + ; +static const char pcb_acth_EvalConf[] = "Perform various operations on the configuration tree."; + +static fgw_error_t pcb_act_EvalConf(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + const char *path; + conf_native_t *nat; + int role; + + PCB_ACT_CONVARG(1, FGW_STR, EvalConf, path = argv[1].val.str); + + nat = conf_get_field(path); + if (nat == NULL) { + pcb_message(PCB_MSG_ERROR, "EvalConf: invalid path %s - no such config setting\n", path); + PCB_ACT_IRES(-1); + return 0; + } + + printf("Conf node %s\n", path); + for(role = 0; role < CFR_max_real; role++) { + lht_node_t *n; + printf(" Role: %s\n", conf_role_name(role)); + n = conf_lht_get_at(role, path, 0); + if (n != NULL) { + conf_policy_t pol = -1; + long prio = conf_default_prio[role]; + + + if (conf_get_policy_prio(n, &pol, &prio) == 0) + printf(" * policy=%s\n * prio=%ld\n", conf_policy_name(pol), prio); + + if (n->file_name != NULL) + printf(" * from=%s:%d.%d\n", n->file_name, n->line, n->col); + else + printf(" * from=(unknown)\n"); + + lht_dom_export(n, stdout, " "); + } + else + printf(" * not present\n"); + } + + printf(" Native:\n"); + conf_print_native((conf_pfn)pcb_fprintf, stdout, " ", 1, nat); + + PCB_ACT_IRES(0); + return 0; +} + +static const char pcb_acts_DumpLayers[] = "dumplayers([all])\n"; +static const char pcb_acth_DumpLayers[] = "Print info about each layer"; + +extern lht_doc_t *conf_main_root[]; +static fgw_error_t pcb_act_DumpLayers(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + int op = -2, g, n, used; + pcb_layer_id_t arr[128]; /* WARNING: this assumes we won't have more than 128 layers */ + pcb_layergrp_id_t garr[128]; /* WARNING: this assumes we won't have more than 128 layers */ + + PCB_ACT_MAY_CONVARG(1, FGW_KEYWORD, DumpLayers, op = fgw_keyword(&argv[1])); + + if (op == F_All) { + printf("Per group:\n"); + for(g = 0; g < PCB->LayerGroups.len; g++) { + pcb_layergrp_t *grp = &PCB->LayerGroups.grp[g]; + printf(" Group %d: '%s' %x\n", g, grp->name, grp->ltype); + for(n = 0; n < grp->len; n++) { + pcb_layer_t *ly = pcb_get_layer(PCB->Data, grp->lid[n]); + if (ly != NULL) { + printf(" layer %d: '%s'\n", n, ly->name); + if (ly->meta.real.grp != g) + printf(" ERROR: invalid back-link to group: %ld should be %d\n", ly->meta.real.grp, g); + } + else + printf(" layer %d: \n", g); + } + } + + printf("Per layer:\n"); + for(n = 0; n < PCB->Data->LayerN; n++) { + pcb_layer_t *ly = &PCB->Data->Layer[n]; + printf(" layer %d: '%s'\n", n, ly->name); + if (ly->meta.real.grp >= 0) { + pcb_layergrp_t *grp = &PCB->LayerGroups.grp[ly->meta.real.grp]; + int i, ok = 0; + for(i = 0; i < grp->len; i++) { + if (grp->lid[i] == n) { + ok = 1; + break; + } + } + if (!ok) + printf(" ERROR: invalid back-link to group: %ld\n", ly->meta.real.grp); + } + } + + PCB_ACT_IRES(0); + return 0; + } + + printf("Max: theoretical=%d current_board=%d\n", PCB_MAX_LAYER+2, pcb_max_layer); + used = pcb_layer_list_any(PCB, PCB_LYT_ANYTHING | PCB_LYT_ANYWHERE | PCB_LYT_VIRTUAL, arr, sizeof(arr)/sizeof(arr[0])); + for(n = 0; n < used; n++) { + pcb_layer_id_t layer_id = arr[n]; + pcb_layergrp_id_t grp = pcb_layer_get_group(PCB, layer_id); + printf(" [%lx] %04x group=%ld %s\n", layer_id, pcb_layer_flags(PCB, layer_id), grp, pcb_layer_name(PCB->Data, layer_id)); + } + + /* query by logical layer: any bottom copper */ + used = pcb_layer_list(PCB, PCB_LYT_COPPER | PCB_LYT_BOTTOM, arr, sizeof(arr)/sizeof(arr[0])); + printf("All %d bottom copper layers are:\n", used); + for(n = 0; n < used; n++) { + pcb_layer_id_t layer_id = arr[n]; + printf(" [%lx] %s \n", layer_id, PCB->Data->Layer[layer_id].name); + } + + /* query by groups (physical layers): any copper in group */ + used = pcb_layergrp_list(PCB, PCB_LYT_COPPER, garr, sizeof(garr)/sizeof(garr[0])); + printf("All %d groups containing copper layers are:\n", used); + for(g = 0; g < used; g++) { + pcb_layergrp_id_t group_id = garr[g]; + printf(" group %ld (%d layers)\n", group_id, PCB->LayerGroups.grp[group_id].len); + for(n = 0; n < PCB->LayerGroups.grp[group_id].len; n++) { + pcb_layer_id_t layer_id = PCB->LayerGroups.grp[group_id].lid[n]; + printf(" [%lx] %s\n", layer_id, PCB->Data->Layer[layer_id].name); + } + } + + PCB_ACT_IRES(0); + return 0; +} + + +static void print_font(pcb_font_t *f, const char *prefix) +{ + int n, g = 0, gletter = 0, gdigit = 0; + const char *name; + + /* count valid glyphs and classes */ + for(n = 0; n < PCB_MAX_FONTPOSITION + 1; n++) { + if (f->Symbol[n].Valid) { + g++; + if (isalpha(n)) gletter++; + if (isdigit(n)) gdigit++; + } + } + + name = f->name == NULL ? "" : f->name; + pcb_printf("%s: %d %s; dim: %$$mm * %$$mm glyphs: %d (letter: %d, digit: %d)\n", prefix, f->id, name, f->MaxWidth, f->MaxHeight, g, gletter, gdigit); +} + +static const char dump_fonts_syntax[] = "dumpfonts()\n"; +static const char dump_fonts_help[] = "Print info about fonts"; +static fgw_error_t pcb_act_DumpFonts(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + printf("Font summary:\n"); + print_font(&PCB->fontkit.dflt, " Default"); + if (PCB->fontkit.hash_inited) { + htip_entry_t *e; + for (e = htip_first(&PCB->fontkit.fonts); e; e = htip_next(&PCB->fontkit.fonts, e)) + print_font(e->value, " Extra "); + } + else + printf(" \n"); + PCB_ACT_IRES(0); + return 0; +} + +#ifndef NDEBUG +extern void undo_dump(void); +static const char dump_undo_syntax[] = "dumpfonts()\n"; +static const char dump_undo_help[] = "Print info about fonts"; +static fgw_error_t pcb_act_DumpUndo(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + printf("Undo:\n"); + undo_dump(); + PCB_ACT_IRES(0); + return 0; +} +#endif + +typedef enum { /* bitfield */ + DD_DRC = 1, + DD_COPPER_ONLY = 2 +} dd_flags; + +static void dump_data(pcb_data_t *data, dd_flags what, int ind, const char *parent) +{ + pcb_any_obj_t *o; + pcb_data_it_t it; + ind++; + for(o = pcb_data_first(&it, data, PCB_OBJ_CLASS_REAL); o != NULL; o = pcb_data_next(&it)) { + const char *type = pcb_obj_type_name(o->type); + pcb_coord_t cx, cy; + + if ((what & DD_COPPER_ONLY) && (o->type == PCB_OBJ_SUBC)) + goto skip; + + if ((what & DD_COPPER_ONLY) && (o->parent_type == PCB_PARENT_LAYER)) { + pcb_layer_type_t lyt = pcb_layer_flags_(o->parent.layer); + if (!(lyt & PCB_LYT_COPPER)) + goto skip; + } + + cx = (o->BoundingBox.X1+o->BoundingBox.X2)/2; + cy = (o->BoundingBox.Y1+o->BoundingBox.Y2)/2; + printf("%*s %s", ind, "", type); + pcb_printf(" #%ld %mm;%mm ", o->ID, cx, cy); + + if (parent != NULL) + printf("%s", parent); + printf("-"); + if (o->term != NULL) + printf("%s", o->term); + + if (what & DD_DRC) + printf(" DRC=%c%c", PCB_FLAG_TEST(PCB_FLAG_FOUND, o) ? 'f':'.', PCB_FLAG_TEST(PCB_FLAG_SELECTED, o) ? 's':'.'); + + printf("\n"); + + skip:; + if (o->type == PCB_OBJ_SUBC) + dump_data(((pcb_subc_t *)o)->data, what, ind, ((pcb_subc_t *)o)->refdes); + } +} + +static const char dump_data_syntax[] = "dumpdata()\n"; +static const char dump_data_help[] = "Dump an aspect of the data"; +static fgw_error_t pcb_act_DumpData(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + dd_flags what = DD_DRC | DD_COPPER_ONLY; + printf("DumpData:\n"); + dump_data(PCB->Data, what, 0, NULL); + printf("\n"); + PCB_ACT_IRES(0); + return 0; +} + +static const char integrity_syntax[] = "integrity()\n"; +static const char integrity_help[] = "perform integrirty check on the current board and generate errors if needed"; +static fgw_error_t pcb_act_integrity(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + pcb_check_integrity(PCB); + PCB_ACT_IRES(0); + return 0; +} + +static int dumpflag_cb(void *ctx, gds_t *s, const char **input) +{ + pcb_flag_bits_t *flag = (pcb_flag_bits_t *)ctx; + switch(**input) { + case 'm': (*input)++; pcb_append_printf(s, "%lx", flag->mask); break; + case 'M': (*input)++; gds_append_str(s, flag->mask_name); break; + case 'N': (*input)++; gds_append_str(s, flag->name); break; + case 't': (*input)++; pcb_append_printf(s, "%lx", flag->object_types); break; + case 'H': (*input)++; gds_append_str(s, flag->name); break; + default: + return -1; + } + return 0; +} + +static const char pcb_acts_dumpflags[] = "dumpflags([fmt])\n"; +static const char pcb_acth_dumpflags[] = "dump flags, optionally using the format string provided by the user"; +static fgw_error_t pcb_act_dumpflags(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + int n; + const char *default_fmt = "%m (%M %N) for %t:\n %H\n"; + const char *fmt = default_fmt; + + PCB_ACT_MAY_CONVARG(1, FGW_STR, dumpflags, fmt = argv[1].val.str); + + for(n = 0; n < pcb_object_flagbits_len; n++) { + char *tmp; + tmp = pcb_strdup_subst(fmt, dumpflag_cb, &pcb_object_flagbits[n], PCB_SUBST_PERCENT /*| PCB_SUBST_BACKSLASH*/); + printf("%s", tmp); + free(tmp); + } + + PCB_ACT_IRES(0); + return 0; +} + +static void ev_ui_post(void *user_data, int argc, pcb_event_arg_t argv[]) +{ + + if (conf_diag.plugins.diag.auto_integrity) { + static int cnt = 0; + if ((cnt++ % 100) == 0) { + pcb_trace("Number of integrity checks so far: %d\n", cnt); + } + pcb_check_integrity(PCB); + } +} + +static const char pcb_acts_d1[] = "d1()\n"; +static const char pcb_acth_d1[] = "debug action for development"; +static fgw_error_t pcb_act_d1(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + PCB_ACT_IRES(0); + return 0; +} + +static const char pcb_acts_DumpIDs[] = "DumpIDs()\n"; +static const char pcb_acth_DumpIDs[] = "Dump the ID hash"; +static fgw_error_t pcb_act_DumpIDs(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + pcb_data_t *data = PCB->Data; + htip_entry_t *e; + + for(e = htip_first(&data->id2obj); e; e = htip_next(&data->id2obj, e)) { + pcb_any_obj_t *o = e->value; + if (o == NULL) + printf("%ld: NULL\n", e->key); + else + printf("%ld: %p %ld %s%s\n", e->key, (void *)o, o->ID, pcb_obj_type_name(o->type), (o->ID == e->key) ? "" : " BROKEN"); + } + + PCB_ACT_IRES(0); + return 0; +} + +#include "find.h" +static const char pcb_acts_Find2Perf[] = "find2perf()\n"; +static const char pcb_acth_Find2Perf[] = "Measure the peformance of find2.c"; +static fgw_error_t pcb_act_Find2Perf(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + double from, now, end, duration = 4.0; + long its = 0, pins = 0; + pcb_find_t fctx; + + memset(&fctx, 0, sizeof(fctx)); + + PCB_SUBC_LOOP(PCB->Data) { + PCB_PADSTACK_LOOP(subc->data) { + pins++; + } + PCB_END_LOOP; + } + PCB_END_LOOP; + + pcb_message(PCB_MSG_INFO, "Measuring find.c peformance for %f seconds starting from %ld pins...\n", duration, pins); + + from = pcb_dtime(); + end = from + duration; + do { + PCB_SUBC_LOOP(PCB->Data) { + PCB_PADSTACK_LOOP(subc->data) { + pcb_find_from_obj(&fctx, PCB->Data, (pcb_any_obj_t *)padstack); + pcb_find_free(&fctx); + } + PCB_END_LOOP; + } + PCB_END_LOOP; + its++; + now = pcb_dtime(); + } while(now < end); + pcb_message(PCB_MSG_INFO, "find2.c peformance: %d %f pin find per second\n", its, (double)its * (double)pins / (now-from)); + PCB_ACT_IRES(0); + return 0; +} + +#define PCB_FORCECOLOR_TYPES \ + (PCB_OBJ_PSTK | PCB_OBJ_TEXT | PCB_OBJ_SUBC | PCB_OBJ_LINE | PCB_OBJ_ARC | PCB_OBJ_POLY | PCB_OBJ_SUBC_PART | PCB_OBJ_SUBC | PCB_OBJ_RAT) + +static const char pcb_acts_forcecolor[] = "forcecolor(#RRGGBB)\n"; +static const char pcb_acth_forcecolor[] = "change selected objects' color to #RRGGBB, reset if does not start with '#'"; +static fgw_error_t pcb_act_forcecolor(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + pcb_coord_t x, y; + int type; + void *ptr1, *ptr2, *ptr3; + const char *new_color; + + pcb_message(PCB_MSG_ERROR, "pcb_acth_forcecolor() is temporarily disabled.\n"); + return -1; + + PCB_ACT_CONVARG(1, FGW_STR, forcecolor, new_color = argv[1].val.str); + + pcb_hid_get_coords("Click on object to change", &x, &y, 0); + + if ((type = pcb_search_screen(x, y, PCB_FORCECOLOR_TYPES, &ptr1, &ptr2, &ptr3)) != PCB_OBJ_VOID){ +TODO("color: figure where to store this"); +/* strncpy(((pcb_any_obj_t *)ptr2)->override_color, new_color, sizeof(((pcb_any_obj_t *)ptr2)->override_color)-1);*/ + } + + PCB_ACT_IRES(0); + return 0; +} + +pcb_action_t diag_action_list[] = { + {"dumpconf", pcb_act_DumpConf, pcb_acth_DumpConf, pcb_acts_DumpConf}, + {"dumplayers", pcb_act_DumpLayers, pcb_acth_DumpLayers, pcb_acts_DumpLayers}, + {"dumpfonts", pcb_act_DumpFonts, dump_fonts_help, dump_fonts_syntax}, + {"dumpdata", pcb_act_DumpData, dump_data_help, dump_data_syntax}, +#ifndef NDEBUG + {"dumpundo", pcb_act_DumpUndo, dump_undo_help, dump_undo_syntax}, +#endif + {"EvalConf", pcb_act_EvalConf, pcb_acth_EvalConf, pcb_acts_EvalConf}, + {"d1", pcb_act_d1, pcb_acth_d1, pcb_acts_d1}, + {"find2perf", pcb_act_Find2Perf, pcb_acth_Find2Perf, pcb_acts_Find2Perf}, + {"integrity", pcb_act_integrity, integrity_help, integrity_syntax}, + {"dumpflags", pcb_act_dumpflags, pcb_acth_dumpflags, pcb_acts_dumpflags}, + {"dumpids", pcb_act_DumpIDs, pcb_acth_DumpIDs, pcb_acts_DumpIDs}, + {"forcecolor", pcb_act_forcecolor, pcb_acth_forcecolor, pcb_acts_forcecolor} +}; + +static const char *diag_cookie = "diag plugin"; + +PCB_REGISTER_ACTIONS(diag_action_list, diag_cookie) + +int pplg_check_ver_diag(int ver_needed) { return 0; } + +void pplg_uninit_diag(void) +{ + pcb_remove_actions_by_cookie(diag_cookie); + conf_unreg_fields("plugins/diag/"); + pcb_event_unbind_allcookie(diag_cookie); +} + +#include "dolists.h" +int pplg_init_diag(void) +{ + PCB_API_CHK_VER; + +#define conf_reg(field,isarray,type_name,cpath,cname,desc,flags) \ + conf_reg_field(conf_diag, field,isarray,type_name,cpath,cname,desc,flags); +#include "diag_conf_fields.h" + + pcb_event_bind(PCB_EVENT_USER_INPUT_POST, ev_ui_post, NULL, diag_cookie); + PCB_REGISTER_ACTIONS(diag_action_list, diag_cookie) + return 0; +} Index: tags/2.1.2/src_plugins/diag/diag.pup =================================================================== --- tags/2.1.2/src_plugins/diag/diag.pup (nonexistent) +++ tags/2.1.2/src_plugins/diag/diag.pup (revision 24813) @@ -0,0 +1,7 @@ +$class feature +$short diagnostic acts. for devs +$long Actions for pcb-rnd core diagnostics, intended for developers. These are not in core because end users normally don't need these. As a plugin, due to dynamic loading, it can be dropped on an existing pcb-rnd installation with minimal risk of scaring away a reproducible bug. +$package debug +$state works +default disable +autoload 1 Index: tags/2.1.2/src_plugins/diag/diag_conf.c =================================================================== --- tags/2.1.2/src_plugins/diag/diag_conf.c (nonexistent) +++ tags/2.1.2/src_plugins/diag/diag_conf.c (revision 24813) @@ -0,0 +1,46 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2016 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "config.h" +#include "conf.h" + +void conf_dump(FILE *f, const char *prefix, int verbose, const char *match_prefix) +{ + htsp_entry_t *e; + int pl; + + if (match_prefix != NULL) + pl = strlen(match_prefix); + + for (e = htsp_first(conf_fields); e; e = htsp_next(conf_fields, e)) { + conf_native_t *node = (conf_native_t *)e->value; + if (match_prefix != NULL) { + if (strncmp(node->hash_path, match_prefix, pl) != 0) + continue; + } + conf_print_native((conf_pfn)pcb_fprintf, f, prefix, verbose, node); + } +} Index: tags/2.1.2/src_plugins/diag/diag_conf.h =================================================================== --- tags/2.1.2/src_plugins/diag/diag_conf.h (nonexistent) +++ tags/2.1.2/src_plugins/diag/diag_conf.h (revision 24813) @@ -0,0 +1,20 @@ +#ifndef PCB_DIAG_CONF_H +#define PCB_DIAG_CONF_H + +#include "conf.h" + +typedef struct { + const struct plugins { + const struct diag { + CFT_BOOLEAN auto_integrity; /* Enable (expensive) automatic integrity check after each user action */ + } diag; + } plugins; +} conf_diag_t; + +extern conf_diag_t conf_diag; + +/* Print all configuration items to f, prefixing each line with prefix + If match_prefix is not NULL, print only items with matching path prefix */ +void conf_dump(FILE *f, const char *prefix, int verbose, const char *match_prefix); + +#endif Index: tags/2.1.2/src_plugins/diag/integrity.c =================================================================== --- tags/2.1.2/src_plugins/diag/integrity.c (nonexistent) +++ tags/2.1.2/src_plugins/diag/integrity.c (revision 24813) @@ -0,0 +1,346 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2017 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "config.h" + +#include "board.h" +#include "data.h" +#include "error.h" +#include "undo.h" + +#define CHK "Broken integrity: " + +#define check_type(obj, exp_type) \ + do { \ + pcb_any_obj_t *__obj__ = (pcb_any_obj_t *)(obj); \ + if (__obj__->type != exp_type) \ + pcb_message(PCB_MSG_ERROR, CHK "%s %ld type broken (%d != %d)\n", pcb_obj_type_name(exp_type), __obj__->ID, __obj__->type, exp_type); \ + } while(0) + +#define check_parent(name, obj, pt, prnt) \ + do { \ + if (obj->parent_type != pt) \ + pcb_message(PCB_MSG_ERROR, CHK "%s " name " %ld parent type broken (%d != %d)\n", whose, obj->ID, obj->parent_type, pt); \ + else if (obj->parent.any != prnt) \ + pcb_message(PCB_MSG_ERROR, CHK "%s " name " %ld parent type broken (%p != %p)\n", whose, obj->ID, obj->parent.any, prnt); \ + } while(0) + +#define check_obj_id(name, data, obj) \ + do { \ + pcb_any_obj_t *__ao__ = htip_get(&data->id2obj, obj->ID); \ + if (__ao__ != (pcb_any_obj_t *)obj) \ + pcb_message(PCB_MSG_ERROR, CHK "%s " name " %ld id hash broken (%p != %p)\n", whose, obj->ID, obj, __ao__); \ + id_chk_cnt++; \ + } while(0) + + +#define chk_attr(name, obj) \ + do { \ + if (((obj)->Attributes.Number > 0) && ((obj)->Attributes.List == NULL)) \ + pcb_message(PCB_MSG_ERROR, CHK "%s " name " %ld broken empty attribute list\n", whose, (obj)->ID); \ + } while(0) + +#define check_field_eq(name, obj, st1, st2, fld, fmt) \ + do { \ + if ((st1)->fld != (st2)->fld) \ + pcb_message(PCB_MSG_ERROR, CHK "%s " name " field ." #fld " value mismatch (" fmt " != " fmt ")\n", whose, obj->ID, (st1)->fld, (st2)->fld); \ + } while(0) + +static void chk_layers(const char *whose, pcb_data_t *data, pcb_parenttype_t pt, void *parent, int name_chk); + +static void chk_term(const char *whose, pcb_any_obj_t *obj) +{ + const char *aterm = pcb_attribute_get(&obj->Attributes, "term"); + const char *s_intconn = pcb_attribute_get(&obj->Attributes, "intconn"); + + if (pcb_obj_id_invalid(aterm)) + pcb_message(PCB_MSG_ERROR, CHK "%s %ld has term attribute '%s' with invalid characters\n", whose, obj->ID, aterm); + + if ((aterm == NULL) && (obj->term == NULL)) + return; + if (obj->term == NULL) { + pcb_message(PCB_MSG_ERROR, CHK "%s %ld has term attribute '%s' but no ->term set\n", whose, obj->ID, aterm); + return; + } + if (aterm == NULL) { + pcb_message(PCB_MSG_ERROR, CHK "%s %ld has ->term '%s' but no attribute term set\n", whose, obj->ID, obj->term); + return; + } + if (aterm != obj->term) { + pcb_message(PCB_MSG_ERROR, CHK "%s %ld has mismatching pointer of ->term ('%s') and attribute term ('%s')\n", whose, obj->ID, obj->term, aterm); + return; + } + + if (s_intconn != NULL) { + char *end; + long intconn = strtol(s_intconn, &end, 10); + if (*end == '\0') { + if (intconn != obj->intconn) { + pcb_message(PCB_MSG_ERROR, CHK "%s %ld has mismatching intconn: cached is %d, attribute is '%s'\n", whose, obj->ID, obj->intconn, s_intconn); + return; + } + } + } +} + +static void chk_subc_cache(pcb_subc_t *subc) +{ + const char *arefdes = pcb_attribute_get(&subc->Attributes, "refdes"); + + if (pcb_obj_id_invalid(arefdes)) + pcb_message(PCB_MSG_ERROR, CHK "subc %ld has refdes attribute '%s' with invalid characters\n", subc->ID, arefdes); + + if ((subc->BoundingBox.X2 < 0) || (subc->BoundingBox.Y2 < 0)) + pcb_message(PCB_MSG_ERROR, CHK "subc %ld is on negative coordinates; its bottom right corner is %$mm;%$mm\n", subc->ID, subc->BoundingBox.X2, subc->BoundingBox.Y2); + + if ((subc->BoundingBox.X1 > PCB->MaxWidth) || (subc->BoundingBox.Y1 > PCB->MaxHeight)) + pcb_message(PCB_MSG_ERROR, CHK "subc %ld is olost beyond board extents; its top left corner is %$mm;%$mm\n", subc->ID, subc->BoundingBox.X1, subc->BoundingBox.Y1); + + if ((arefdes == NULL) && (subc->refdes == NULL)) + return; + if (subc->refdes == NULL) { + pcb_message(PCB_MSG_ERROR, CHK "subc %ld has refdes attribute '%s' but no ->refdes set\n", subc->ID, arefdes); + return; + } + if (arefdes == NULL) { + pcb_message(PCB_MSG_ERROR, CHK "subc %ld has ->refdes '%s' but no attribute refdes set\n", subc->ID, subc->refdes); + return; + } + if (arefdes != subc->refdes) { + pcb_message(PCB_MSG_ERROR, CHK "subc %ld has mismatching pointer of ->refdes ('%s') and attribute refdes ('%s')\n", subc->ID, subc->refdes, arefdes); + return; + } +} + + +static void chk_subc(const char *whose, pcb_subc_t *subc) +{ + int n; + pcb_pstk_t *ps; + + chk_layers("subc", subc->data, PCB_PARENT_SUBC, subc, 0); + chk_subc_cache(subc); + + /* check term chaches */ + for(ps = padstacklist_first(&subc->data->padstack); ps != NULL; ps = padstacklist_next(ps)) + chk_term("padstack", (pcb_any_obj_t *)ps); + + for(n = 0; n < subc->data->LayerN; n++) { + pcb_layer_t *ly = &subc->data->Layer[n]; + pcb_line_t *lin; + pcb_arc_t *arc; + pcb_text_t *txt; + pcb_poly_t *pol; + + if (!ly->is_bound) + pcb_message(PCB_MSG_ERROR, CHK "%ld subc layer %ld is not a bound layer\n", subc->ID, n); + + for(lin = linelist_first(&ly->Line); lin != NULL; lin = linelist_next(lin)) + chk_term("line", (pcb_any_obj_t *)lin); + + for(arc = arclist_first(&ly->Arc); arc != NULL; arc = arclist_next(arc)) + chk_term("arc", (pcb_any_obj_t *)arc); + + for(txt = textlist_first(&ly->Text); txt != NULL; txt = textlist_next(txt)) + chk_term("text", (pcb_any_obj_t *)txt); + + for(pol = polylist_first(&ly->Polygon); pol != NULL; pol = polylist_next(pol)) + chk_term("polygon", (pcb_any_obj_t *)pol); + } +} + +/* Check layers and objects: walk the tree top->down and check ->parent + references from any node */ +static void chk_layers(const char *whose, pcb_data_t *data, pcb_parenttype_t pt, void *parent, int name_chk) +{ + pcb_layer_id_t n; + long id_chk_cnt = 0; + htip_entry_t *e; + + if (data->parent_type != pt) + pcb_message(PCB_MSG_ERROR, CHK "%s data: parent type broken (%d != %d)\n", whose, data->parent_type, pt); + else if (data->parent.any != parent) + pcb_message(PCB_MSG_ERROR, CHK "%s data: parent broken (%p != %p)\n", whose, data->parent, parent); + + + for(n = 0; n < data->LayerN; n++) { + pcb_line_t *lin; + pcb_text_t *txt; + pcb_arc_t *arc; + pcb_poly_t *poly; + pcb_layergrp_t *grp; + + /* check layers */ + if (data->Layer[n].parent.data != data) + pcb_message(PCB_MSG_ERROR, CHK "%s layer %ld/%s parent broken (%p != %p)\n", whose, n, data->Layer[n].name, data->Layer[n].parent, data); + if (name_chk && ((data->Layer[n].name == NULL) || (*data->Layer[n].name == '\0'))) + pcb_message(PCB_MSG_ERROR, CHK "%s layer %ld has invalid name\n", whose, n); + check_type(&data->Layer[n], PCB_OBJ_LAYER); + check_parent("layer", (&data->Layer[n]), PCB_PARENT_DATA, data); + chk_attr("layer", &data->Layer[n]); + + if (!data->Layer[n].is_bound) { + grp = pcb_get_layergrp(data->parent.board, data->Layer[n].meta.real.grp); + if (grp != NULL) { + int i, found = 0; + for(i = 0; i < grp->len; i++) { + if (grp->lid[i] == n) { + found = 1; + break; + } + } + if (!found) + pcb_message(PCB_MSG_ERROR, CHK "%s layer %ld is linked to group %ld but the group does not link back to the layer\n", whose, n, data->Layer[n].meta.real.grp); + } + else + pcb_message(PCB_MSG_ERROR, CHK "%s layer %ld is linked to non-existing group %ld\n", whose, n, data->Layer[n].meta.real.grp); + } + + if (data->Layer[n].is_bound) { + if ((data->Layer[n].meta.bound.type & PCB_LYT_BOUNDARY) && (data->Layer[n].meta.bound.type & PCB_LYT_ANYWHERE)) + pcb_message(PCB_MSG_ERROR, CHK "%s layer %ld/%s is a non-global boundary (bound layer)\n", whose, n, data->Layer[n].name); + } + + /* check layer objects */ + for(lin = linelist_first(&data->Layer[n].Line); lin != NULL; lin = linelist_next(lin)) { + check_parent("line", lin, PCB_PARENT_LAYER, &data->Layer[n]); + check_obj_id("line", data, lin); + check_type(lin, PCB_OBJ_LINE); + chk_attr("line", lin); + } + + for(txt = textlist_first(&data->Layer[n].Text); txt != NULL; txt = textlist_next(txt)) { + check_parent("text", txt, PCB_PARENT_LAYER, &data->Layer[n]); + check_obj_id("text", data, txt); + check_type(txt, PCB_OBJ_TEXT); + chk_attr("text", txt); + } + + for(poly = polylist_first(&data->Layer[n].Polygon); poly != NULL; poly = polylist_next(poly)) { + check_parent("polygon", poly, PCB_PARENT_LAYER, &data->Layer[n]); + check_obj_id("polygon", data, poly); + check_type(poly, PCB_OBJ_POLY); + chk_attr("polygon", poly); + } + + for(arc = arclist_first(&data->Layer[n].Arc); arc != NULL; arc = arclist_next(arc)) { + check_parent("arc", arc, PCB_PARENT_LAYER, &data->Layer[n]); + check_obj_id("arc", data, arc); + check_type(arc, PCB_OBJ_ARC); + chk_attr("arc", arc); + } + } + + /* check global objects */ + { + pcb_subc_t *subc; + pcb_pstk_t *ps; + pcb_rat_t *rat; + + for(ps = padstacklist_first(&data->padstack); ps != NULL; ps = padstacklist_next(ps)) { + check_parent("padstack", ps, PCB_PARENT_DATA, data); + check_obj_id("padstack", data, ps); + check_type(ps, PCB_OBJ_PSTK); + chk_attr("padstack", ps); + chk_term("padstack", (pcb_any_obj_t *)ps); + } + + for(subc = pcb_subclist_first(&data->subc); subc != NULL; subc = pcb_subclist_next(subc)) { + check_parent("subc", subc, PCB_PARENT_DATA, data); + check_obj_id("subc", data, subc); + check_type(subc, PCB_OBJ_SUBC); + chk_subc(whose, subc); + chk_attr("subc", subc); + } + + /* check rat line objects */ + for(rat = ratlist_first(&data->Rat); rat != NULL; rat = ratlist_next(rat)) { + check_parent("rat", rat, PCB_PARENT_DATA, data); + check_obj_id("rat", data, rat); + check_type(rat, PCB_OBJ_RAT); + chk_attr("rat", rat); + } + } + + /* Safe check for the other way around: if the hash contains more entries + than the objects we checked above, we have some garbage left; the check + is safe because it is not needed to dereference the garbage */ + for(e = htip_first(&data->id2obj); e; e = htip_next(&data->id2obj, e)) { + id_chk_cnt--; + } + if (id_chk_cnt != 0) + pcb_message(PCB_MSG_ERROR, CHK "id hash contains %ld excess IDs in %s\n", id_chk_cnt, whose); +} + +static void chk_layergrps(pcb_board_t *pcb) +{ + pcb_layergrp_id_t n; + const char *whose = "board"; + + for(n = 0; n < pcb->LayerGroups.len; n++) { + pcb_layergrp_t *grp = &pcb->LayerGroups.grp[n]; + int i, i2; + + check_parent("layer_group", grp, PCB_PARENT_BOARD, pcb); + check_type(grp, PCB_OBJ_LAYERGRP); + if ((grp->ltype & PCB_LYT_BOUNDARY) && (grp->ltype & PCB_LYT_ANYWHERE)) + pcb_message(PCB_MSG_ERROR, CHK "layer group %ld/%s is a non-global boundary\n", n, grp->name); + + for(i = 0; i < grp->len; i++) { + pcb_layer_t *ly; + + for(i2 = 0; i2 < i; i2++) + if (grp->lid[i] == grp->lid[i2]) + pcb_message(PCB_MSG_ERROR, CHK "layer group %ld/%s has duplicate layer entry: %ld\n", n, grp->name, (long)grp->lid[i]); + + ly = pcb_get_layer(pcb->Data, grp->lid[i]); + if (ly != NULL) { + if (ly->meta.real.grp != n) + pcb_message(PCB_MSG_ERROR, CHK "layer group %ld/%s conains layer %ld/%s but it doesn't link back to the group but links to %ld instead \n", n, grp->name, (long)grp->lid[i], ly->name, ly->meta.real.grp); + } + else + pcb_message(PCB_MSG_ERROR, CHK "layer group %ld/%s contains invalid layer entry: %ld\n", n, grp->name, (long)grp->lid[i]); + } + } +} + + +void pcb_check_integrity(pcb_board_t *pcb) +{ + int n; + + chk_layergrps(pcb); + chk_layers("board", pcb->Data, PCB_PARENT_BOARD, pcb, 1); + + for (n = 0; n < PCB_MAX_BUFFER; n++) { + char bn[16]; + sprintf(bn, "buffer #%d", n); + chk_layers(bn, pcb_buffers[n].Data, PCB_PARENT_INVALID, NULL, 0); + } + + if (undo_check() != 0) + pcb_message(PCB_MSG_ERROR, CHK "undo\n"); +} Index: tags/2.1.2/src_plugins/diag/integrity.h =================================================================== --- tags/2.1.2/src_plugins/diag/integrity.h (nonexistent) +++ tags/2.1.2/src_plugins/diag/integrity.h (revision 24813) @@ -0,0 +1,3 @@ +#include "board.h" +void pcb_check_integrity(pcb_board_t *pcb); + Index: tags/2.1.2/src_plugins/dialogs/Makefile =================================================================== --- tags/2.1.2/src_plugins/dialogs/Makefile (nonexistent) +++ tags/2.1.2/src_plugins/dialogs/Makefile (revision 24813) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_dialogs + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/2.1.2/src_plugins/dialogs/Plug.tmpasm =================================================================== --- tags/2.1.2/src_plugins/dialogs/Plug.tmpasm (nonexistent) +++ tags/2.1.2/src_plugins/dialogs/Plug.tmpasm (revision 24813) @@ -0,0 +1,27 @@ +put /local/pcb/mod {dialogs} +put /local/pcb/mod/OBJS [@ + $(PLUGDIR)/dialogs/dialogs.o + $(PLUGDIR)/dialogs/act_dad.o + $(PLUGDIR)/dialogs/dlg_about.o + $(PLUGDIR)/dialogs/dlg_comm_m.o + $(PLUGDIR)/dialogs/dlg_export.o + $(PLUGDIR)/dialogs/dlg_flag_edit.o + $(PLUGDIR)/dialogs/dlg_fontsel.o + $(PLUGDIR)/dialogs/dlg_layer_binding.o + $(PLUGDIR)/dialogs/dlg_layer_flags.o + $(PLUGDIR)/dialogs/dlg_lib_pstk.o + $(PLUGDIR)/dialogs/dlg_loadsave.o + $(PLUGDIR)/dialogs/dlg_log.o + $(PLUGDIR)/dialogs/dlg_padstack.o + $(PLUGDIR)/dialogs/dlg_pref.o + $(PLUGDIR)/dialogs/dlg_view.o + $(PLUGDIR)/dialogs/xpm.o +@] +put /local/pcb/mod/CONFFILE {dialogs.conf} +put /local/pcb/mod/CONF {$(PLUGDIR)/dialogs/dialogs_conf.h} + +switch /local/pcb/dialogs/controls + case {buildin} include /local/pcb/tmpasm/buildin; end; + case {plugin} include /local/pcb/tmpasm/plugin; end; + case {disable} include /local/pcb/tmpasm/disable; end; +end Index: tags/2.1.2/src_plugins/dialogs/TEMPLATE.c =================================================================== --- tags/2.1.2/src_plugins/dialogs/TEMPLATE.c (nonexistent) +++ tags/2.1.2/src_plugins/dialogs/TEMPLATE.c (revision 24813) @@ -0,0 +1,94 @@ +/* + HOW TO USE THE TEMPLATE: + 1. decide about the name of your dialog box, e.g. foo in this example + 2. svn copy this file to dlg_foo.c - do not use plain fs copy, use svn copy! + 3. rename functions in this file to + 4. add '#include "dlg_foo.c"' in dialogs.c at the end of the list where + all the other dlg_*.c files are included + 5. add an action to pcb_act*_Foo in dialogs.c + 6. edit the parts marked with '<<<- edit this' or 'EDIT THIS' - do not + yet add the implementation + 7. run 'make dep' in src/ + 8. remove this comment block so copyright is on top + 9. edit the copyright message: year and author + 10. test compile + 11. in trunk/: 'svn commit src_plugins/dialogs src/Makefile.dep' + 12. start implementing the dialog box + + This simplistic example is a single-instance non-modal dialog; + there should be only one global variable, created out of the + context struct. This ensures it is easy to convert the dialog + to multi-instance in the future, if needed. + + If you need a multi-instance dialog, there should be no global variable + at all and the context struct should be allocated. A good example + on this is the shape dialog in ../shape/shape_dialog.c +*/ + +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2018 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "core headers this file depends on (even if other dialogs include them)" + +typedef struct{ + PCB_DAD_DECL_NOINIT(dlg) + int active; /* already open - allow only one instance */ + int whatever; +} foo_ctx_t; <<<- rename this + +foo_ctx_t foo_ctx; + +static void foo_close_cb(void *caller_data, pcb_hid_attr_ev_t ev) <<<- rename this +{ + foo_ctx_t *ctx = caller_data; + PCB_DAD_FREE(ctx->dlg); + memset(ctx, 0, sizeof(foo_ctx_t)); /* reset all states to the initial - includes ctx->active = 0; */ +} + +static void pcb_dlg_foo(whatever args) <<<- edit this +{ + pcb_hid_dad_buttons_t clbtn[] = {{"Close", 0}, {NULL, 0}}; + if (foo_ctx.active) + return; /* do not open another */ + + PCB_DAD_BEGIN_VBOX(foo_ctx.dlg); + PCB_DAD_COMPFLAG(foo_ctx.dlg, PCB_HATF_EXPFILL); + PCB_DAD_LABEL(foo_ctx.dlg, "foo"); + PCB_DAD_BUTTON_CLOSES(dlg, clbtn); + PCB_DAD_END(foo_ctx.dlg); + + /* set up the context */ + foo_ctx.active = 1; + + PCB_DAD_NEW("EDIT_THIS_ID", foo_ctx.dlg, "EDIT THIS: title", &foo_ctx, pcb_false, foo_close_cb); +} + +static const char pcb_acts_Foo[] = "Foo(object)\n"; <<<- edit this +static const char pcb_acth_Foo[] = ""; <<<- edit this +static fgw_error_t pcb_act_Foo(fgw_arg_t *res, int argc, fgw_arg_t *argv) <<<- edit this +{ + return 0; +} Index: tags/2.1.2/src_plugins/dialogs/TEMPLATE_MODAL.c =================================================================== --- tags/2.1.2/src_plugins/dialogs/TEMPLATE_MODAL.c (nonexistent) +++ tags/2.1.2/src_plugins/dialogs/TEMPLATE_MODAL.c (revision 24813) @@ -0,0 +1,77 @@ +/* + HOW TO USE THE TEMPLATE: + 0. reconsider: does this dialog have to be modal? + 1. decide about the name of your dialog box, e.g. foo in this example + 2. svn copy this file to dlg_foo.c - do not use plain fs copy, use svn copy! + 3. rename functions in this file to + 4. add '#include "dlg_foo.c"' in dialogs.c at the end of the list where + all the other dlg_*.c files are included + 5. add an action to pcb_act*_Foo in dialogs.c + 6. edit the parts marked with '<<<- edit this' or 'EDIT THIS' - do not + yet add the implementation + 7. run 'make dep' in src/ + 8. remove this comment block so copyright is on top + 9. edit the copyright message: year and author + 10. test compile + 11. in trunk/: 'svn commit src_plugins/dialogs src/Makefile.dep' + 12. start implementing the dialog box +*/ + +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2018 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "core headers this file depends on (even if other dialogs include them)" + +typedef struct{ + pcb_hid_attribute_t *attrs; +} foo_ctx_t; <<<- rename this + +static void pcb_dlg_foo(whatever args) <<<- edit this +{ + foo_ctx_t ctx; + pcb_hid_dad_buttons_t clbtn[] = {{"Cancel", -1}, {"ok", 0}, {NULL, 0}}; + PCB_DAD_DECL(dlg); + + PCB_DAD_BEGIN_VBOX(dlg); + PCB_DAD_COMPFLAG(dlg, PCB_HATF_EXPFILL); + PCB_DAD_LABEL(dlg, "foo"); + PCB_DAD_BUTTON_CLOSES(dlg, clbtn); + PCB_DAD_END(dlg); + + /* set up the context */ + ctx.attrs = dlg; + + PCB_DAD_NEW("EDIT_THIS_ID", dlg, "EDIT THIS: title", &ctx, pcb_true, NULL); + PCB_DAD_RUN(dlg); + PCB_DAD_FREE(dlg); +} + +static const char pcb_acts_Foo[] = "Foo(object)\n"; <<<- edit this +static const char pcb_acth_Foo[] = ""; <<<- edit this +static fgw_error_t pcb_act_Foo(fgw_arg_t *res, int argc, fgw_arg_t *argv) <<<- edit this +{ + return 0; +} Index: tags/2.1.2/src_plugins/dialogs/act_dad.c =================================================================== --- tags/2.1.2/src_plugins/dialogs/act_dad.c (nonexistent) +++ tags/2.1.2/src_plugins/dialogs/act_dad.c (revision 24813) @@ -0,0 +1,566 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2018 Tibor 'Igor2' Palinkas + * + * This module, dialogs, was written and is Copyright (C) 2017 by Tibor Palinkas + * this module is also subject to the GNU GPL as described below + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "config.h" + +#include +#include +#include +#include +#include "actions.h" +#include "compat_misc.h" +#include "hid_dad.h" +#include "hid_dad_tree.h" +#include "error.h" + +#include "act_dad.h" + +#define MAX_ENUM 128 + +typedef union tmp_u tmp_t; + +typedef struct tmp_str_s { + tmp_t *next; + char str[1]; +} tmp_str_t; + +typedef struct tmp_strlist_s { + tmp_t *next; + char *values[MAX_ENUM+1]; +} tmp_strlist_t; + +union tmp_u { + struct { + tmp_t *next; + } list; + tmp_str_t str; + tmp_strlist_t strlist; +}; + +typedef struct { + PCB_DAD_DECL_NOINIT(dlg) + char *name; + const char *row_domain; + int level; + tmp_t *tmp_str_head; + vts0_t change_cb; + unsigned running:1; +} dad_t; + +htsp_t dads; + +static int dad_new(const char *name) +{ + dad_t *dad; + + if (htsp_get(&dads, name) != NULL) { + pcb_message(PCB_MSG_ERROR, "Can't create named DAD dialog %s: already exists\n", name); + return -1; + } + + dad = calloc(sizeof(dad_t), 1); + dad->name = pcb_strdup(name); + dad->row_domain = dad->name; + htsp_set(&dads, dad->name, dad); + return 0; +} + +static void dad_destroy(dad_t *dad) +{ + tmp_t *t, *tnext; + for(t = dad->tmp_str_head; t != NULL; t = tnext) { + tnext = t->list.next; + free(t); + } + htsp_pop(&dads, dad->name); + free(dad->name); + free(dad); +} + +static void dad_close_cb(void *caller_data, pcb_hid_attr_ev_t ev) +{ + dad_t *dad = caller_data; + PCB_DAD_FREE(dad->dlg); + dad_destroy(dad); +} + +static void dad_change_cb(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + dad_t *dad = caller_data; + int idx = attr - dad->dlg; + char **act = vts0_get(&dad->change_cb, idx, 0); + if ((act != NULL) && (*act != NULL)) + pcb_parse_command(*act, 1); +} + +static void dad_row_free_cb(pcb_hid_attribute_t *attrib, void *hid_ctx, pcb_hid_row_t *row) +{ + pcb_hid_tree_t *tree = (pcb_hid_tree_t *)attrib->enumerations; + dad_t *dad = tree->user_ctx; + fgw_arg_t res; + res.type = FGW_PTR | FGW_VOID; + res.val.ptr_void = row; + fgw_ptr_unreg(&pcb_fgw, &res, dad->row_domain); +} + +static char *tmp_str_dup(dad_t *dad, const char *txt) +{ + size_t len = strlen(txt); + tmp_str_t *tmp = malloc(sizeof(tmp_str_t) + len); + tmp->next = dad->tmp_str_head; + dad->tmp_str_head = (tmp_t *)tmp; + memcpy(tmp->str, txt, len+1); + return tmp->str; +} + +static char **tmp_new_strlist(dad_t *dad) +{ + tmp_strlist_t *tmp = malloc(sizeof(tmp_strlist_t)); + tmp->next = dad->tmp_str_head; + dad->tmp_str_head = (tmp_t *)tmp; + return tmp->values; +} + +static int split_tablist(dad_t *dad, char **values, const char *txt, const char *cmd) +{ + char *next, *s = tmp_str_dup(dad, txt); + int len = 0; + + while(isspace(*s)) s++; + + for(len = 0; s != NULL; s = next) { + if (len >= MAX_ENUM) { + pcb_message(PCB_MSG_ERROR, "Too many DAD %s values\n", cmd); + return -1; + } + next = strchr(s, '\t'); + if (next != NULL) { + *next = '\0'; + next++; + while(isspace(*next)) next++; + } + values[len] = s; + len++; + } + values[len] = NULL; + return 0; +} + +const char pcb_acts_dad[] = + "dad(dlgname, new) - create new dialog\n" + "dad(dlgname, label, text) - append a label widget\n" + "dad(dlgname, button, text) - append a button widget\n" + "dad(dlgname, button_closes, label, retval, ...) - standard close buttons\n" + "dad(dlgname, enum, choices) - append an enum (combo box) widget; choices is a tab separated list\n" + "dad(dlgname, bool, [label]) - append an checkbox widget (default off)\n" + "dad(dlgname, integer|real|coord, min, max, [label]) - append an input field\n" + "dad(dlgname, string) - append a single line text input field\n" + "dad(dlgname, progress) - append a progress bar (set to 0)\n" + "dad(dlgname, tree, cols, istree, [header]) - append tree-table widget; header is like enum values\n" + "dad(dlgname, tree_append, row, cells) - append after row (0 means last item of the root); cells is like enum values; returns a row pointer\n" + "dad(dlgname, tree_append_under, row, cells) - append at the end of the list under row (0 means last item of the root); cells is like enum values; returns a row pointer\n" + "dad(dlgname, tree_insert, row, cells) - insert before row (0 means first item of the root); cells is like enum values; returns a row pointer\n" + "dad(dlgname, begin_hbox) - begin horizontal box\n" + "dad(dlgname, begin_vbox) - begin vertical box\n" + "dad(dlgname, begin_hpane) - begin horizontal paned box\n" + "dad(dlgname, begin_vpane) - begin vertical paned box\n" + "dad(dlgname, begin_table, cols) - begin table layout box\n" + "dad(dlgname, begin_tabbed, tabnames) - begin a view with tabs; tabnames are like choices in an enum; must have as many children widgets as many names it has\n" + "dad(dlgname, end) - end the last begin\n" + "dad(dlgname, flags, flg1, flg2, ...) - change the flags of the last created widget\n" + "dad(dlgname, onchange, action) - set the action to be called on widget change\n" + "dad(dlgname, run, title) - present dlgname as a non-modal dialog\n" + "dad(dlgname, run_modal, title) - present dlgname as a modal dialog\n" + "dad(dlgname, exists) - returns wheter the named dialog exists (0 or 1)\n" + "dad(dlgname, set, widgetID, val) - changes the value of a widget in a running dialog \n" + "dad(dlgname, get, widgetID, [unit]) - return the current value of a widget\n" + ; +const char pcb_acth_dad[] = "Manipulate Dynamic Attribute Dialogs"; +fgw_error_t pcb_act_dad(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + char *cmd, *dlgname, *txt; + dad_t *dad; + int rv = 0; + + PCB_ACT_CONVARG(1, FGW_STR, dad, dlgname = argv[1].val.str); + PCB_ACT_CONVARG(2, FGW_STR, dad, cmd = argv[2].val.str); + + if (pcb_strcasecmp(cmd, "new") == 0) { + PCB_ACT_IRES(dad_new(dlgname)); + return 0; + } + + dad = htsp_get(&dads, dlgname); + if (pcb_strcasecmp(cmd, "exists") == 0) { + PCB_ACT_IRES(dad != NULL); + return 0; + } + + if (dad == NULL) { + pcb_message(PCB_MSG_ERROR, "Can't find named DAD dialog %s\n", dlgname); + PCB_ACT_IRES(-1); + return 0; + } + + + if (pcb_strcasecmp(cmd, "label") == 0) { + if (dad->running) goto cant_chg; + PCB_ACT_CONVARG(3, FGW_STR, dad, txt = argv[3].val.str); + PCB_DAD_LABEL(dad->dlg, txt); + rv = PCB_DAD_CURRENT(dad->dlg); + } + else if (pcb_strcasecmp(cmd, "button") == 0) { + if (dad->running) goto cant_chg; + PCB_ACT_CONVARG(3, FGW_STR, dad, txt = argv[3].val.str); + PCB_DAD_BUTTON(dad->dlg, tmp_str_dup(dad, txt)); + rv = PCB_DAD_CURRENT(dad->dlg); + } + else if (pcb_strcasecmp(cmd, "button_closes") == 0) { + int n, ret; + + if (dad->running) goto cant_chg; + + PCB_DAD_BEGIN_HBOX(dad->dlg); + PCB_DAD_BEGIN_HBOX(dad->dlg); + PCB_DAD_COMPFLAG(dad->dlg, PCB_HATF_EXPFILL); + PCB_DAD_END(dad->dlg); + for(n = 3; n < argc; n+=2) { + PCB_ACT_CONVARG(n+0, FGW_STR, dad, txt = argv[n+0].val.str); + PCB_ACT_CONVARG(n+1, FGW_INT, dad, ret = argv[n+1].val.nat_int); + + PCB_DAD_BUTTON_CLOSE(dad->dlg, tmp_str_dup(dad, txt), ret); + rv = PCB_DAD_CURRENT(dad->dlg); + } + PCB_DAD_END(dad->dlg); + } + else if (pcb_strcasecmp(cmd, "bool") == 0) { + if (dad->running) goto cant_chg; + txt = ""; + PCB_ACT_MAY_CONVARG(3, FGW_STR, dad, txt = argv[3].val.str); + PCB_DAD_BOOL(dad->dlg, txt); + rv = PCB_DAD_CURRENT(dad->dlg); + } + else if (pcb_strcasecmp(cmd, "integer") == 0) { + long vmin, vmax; + if (dad->running) goto cant_chg; + txt = ""; + PCB_ACT_CONVARG(3, FGW_LONG, dad, vmin = argv[3].val.nat_long); + PCB_ACT_CONVARG(4, FGW_LONG, dad, vmax = argv[4].val.nat_long); + PCB_ACT_MAY_CONVARG(5, FGW_STR, dad, txt = argv[5].val.str); + PCB_DAD_INTEGER(dad->dlg, txt); + PCB_DAD_MINMAX(dad->dlg, vmin, vmax); + rv = PCB_DAD_CURRENT(dad->dlg); + } + else if (pcb_strcasecmp(cmd, "real") == 0) { + double vmin, vmax; + if (dad->running) goto cant_chg; + txt = ""; + PCB_ACT_CONVARG(3, FGW_DOUBLE, dad, vmin = argv[3].val.nat_double); + PCB_ACT_CONVARG(4, FGW_DOUBLE, dad, vmax = argv[4].val.nat_double); + PCB_ACT_MAY_CONVARG(5, FGW_STR, dad, txt = argv[5].val.str); + PCB_DAD_REAL(dad->dlg, txt); + PCB_DAD_MINMAX(dad->dlg, vmin, vmax); + rv = PCB_DAD_CURRENT(dad->dlg); + } + else if (pcb_strcasecmp(cmd, "coord") == 0) { + pcb_coord_t vmin, vmax; + if (dad->running) goto cant_chg; + txt = ""; + PCB_ACT_CONVARG(3, FGW_COORD_, dad, vmin = fgw_coord(&argv[3])); + PCB_ACT_CONVARG(4, FGW_COORD_, dad, vmax = fgw_coord(&argv[4])); + PCB_ACT_MAY_CONVARG(5, FGW_STR, dad, txt = argv[5].val.str); + PCB_DAD_COORD(dad->dlg, txt); + PCB_DAD_MINMAX(dad->dlg, vmin, vmax); + rv = PCB_DAD_CURRENT(dad->dlg); + } + else if (pcb_strcasecmp(cmd, "string") == 0) { + if (dad->running) goto cant_chg; + PCB_DAD_STRING(dad->dlg); + rv = PCB_DAD_CURRENT(dad->dlg); + } + else if (pcb_strcasecmp(cmd, "progress") == 0) { + if (dad->running) goto cant_chg; + PCB_DAD_PROGRESS(dad->dlg); + rv = PCB_DAD_CURRENT(dad->dlg); + } + else if ((pcb_strcasecmp(cmd, "enum") == 0) || (pcb_strcasecmp(cmd, "begin_tabbed") == 0)) { + char **values = tmp_new_strlist(dad); + + if (dad->running) goto cant_chg; + + PCB_ACT_CONVARG(3, FGW_STR, dad, txt = argv[3].val.str); + + if (split_tablist(dad, values, txt, cmd) == 0) { + if (*cmd == 'b') { + PCB_DAD_BEGIN_TABBED(dad->dlg, (const char **)values); + dad->level++; + } + else + PCB_DAD_ENUM(dad->dlg, (const char **)values); + rv = PCB_DAD_CURRENT(dad->dlg); + } + else + rv = -1; + } + else if (pcb_strcasecmp(cmd, "tree") == 0) { + int cols, istree; + char **values = tmp_new_strlist(dad); + + if (dad->running) goto cant_chg; + + txt = NULL; + PCB_ACT_CONVARG(3, FGW_INT, dad, cols = argv[3].val.nat_int); + PCB_ACT_CONVARG(4, FGW_INT, dad, istree = argv[4].val.nat_int); + PCB_ACT_MAY_CONVARG(5, FGW_STR, dad, txt = argv[5].val.str); + + if ((txt == NULL) || (split_tablist(dad, values, txt, cmd) == 0)) { + PCB_DAD_TREE(dad->dlg, cols, istree, (const char **)values); + PCB_DAD_TREE_SET_CB(dad->dlg, free_cb, dad_row_free_cb); + PCB_DAD_TREE_SET_CB(dad->dlg, ctx, dad); + rv = PCB_DAD_CURRENT(dad->dlg); + } + else + rv = -1; + } + else if ((pcb_strcasecmp(cmd, "tree_append") == 0) || (pcb_strcasecmp(cmd, "tree_append_under") == 0) || (pcb_strcasecmp(cmd, "tree_insert") == 0)) { + void *row, *nrow = NULL; + char **values = tmp_new_strlist(dad); + + if (dad->running) goto cant_chg; + + PCB_ACT_CONVARG(3, FGW_PTR, dad, row = argv[3].val.ptr_void); + PCB_ACT_CONVARG(4, FGW_STR, dad, txt = argv[4].val.str); + + if (row != NULL) { + if (!fgw_ptr_in_domain(&pcb_fgw, &argv[3], dad->row_domain)) { + pcb_message(PCB_MSG_ERROR, "Invalid DAD row pointer\n"); + PCB_ACT_IRES(-1); + return 0; + } + } + + if ((txt == NULL) || (split_tablist(dad, values, txt, cmd) == 0)) { + if (cmd[5] == 'i') + nrow = PCB_DAD_TREE_INSERT(dad->dlg, row, values); + else if (cmd[11] == '_') + nrow = PCB_DAD_TREE_APPEND_UNDER(dad->dlg, row, values); + else + nrow = PCB_DAD_TREE_APPEND(dad->dlg, row, values); + } + else + nrow = NULL; + fgw_ptr_reg(&pcb_fgw, res, dad->row_domain, FGW_PTR, nrow); + return 0; + } + else if (pcb_strcasecmp(cmd, "begin_hbox") == 0) { + if (dad->running) goto cant_chg; + PCB_DAD_BEGIN_HBOX(dad->dlg); + dad->level++; + rv = PCB_DAD_CURRENT(dad->dlg); + } + else if (pcb_strcasecmp(cmd, "begin_vbox") == 0) { + if (dad->running) goto cant_chg; + PCB_DAD_BEGIN_VBOX(dad->dlg); + dad->level++; + rv = PCB_DAD_CURRENT(dad->dlg); + } + else if (pcb_strcasecmp(cmd, "begin_hpane") == 0) { + if (dad->running) goto cant_chg; + PCB_DAD_BEGIN_HPANE(dad->dlg); + dad->level++; + rv = PCB_DAD_CURRENT(dad->dlg); + } + else if (pcb_strcasecmp(cmd, "begin_vpane") == 0) { + if (dad->running) goto cant_chg; + PCB_DAD_BEGIN_VPANE(dad->dlg); + dad->level++; + rv = PCB_DAD_CURRENT(dad->dlg); + } + else if (pcb_strcasecmp(cmd, "begin_table") == 0) { + int cols; + + if (dad->running) goto cant_chg; + + PCB_ACT_CONVARG(3, FGW_INT, dad, cols = argv[3].val.nat_int); + PCB_DAD_BEGIN_TABLE(dad->dlg, cols); + dad->level++; + rv = PCB_DAD_CURRENT(dad->dlg); + } + else if (pcb_strcasecmp(cmd, "end") == 0) { + if (dad->running) goto cant_chg; + + PCB_DAD_END(dad->dlg); + dad->level--; + rv = PCB_DAD_CURRENT(dad->dlg); + } + else if (pcb_strcasecmp(cmd, "flags") == 0) { + int n; + pcb_hatt_compflags_t tmp, flg = 0; + + if (dad->running) goto cant_chg; + + for(n = 3; n < argc; n++) { + PCB_ACT_CONVARG(n, FGW_STR, dad, txt = argv[n].val.str); + if ((*txt == '\0') || (*txt == '0')) + continue; + tmp = pcb_hid_compflag_name2bit(txt); + if (tmp == 0) + pcb_message(PCB_MSG_ERROR, "Invalid DAD flag: %s (ignored)\n", txt); + flg |= tmp; + } + PCB_DAD_COMPFLAG(dad->dlg, flg); + rv = PCB_DAD_CURRENT(dad->dlg); + } + else if (pcb_strcasecmp(cmd, "onchange") == 0) { + PCB_ACT_CONVARG(3, FGW_STR, dad, txt = argv[3].val.str); + PCB_DAD_CHANGE_CB(dad->dlg, dad_change_cb); + vts0_set(&dad->change_cb, PCB_DAD_CURRENT(dad->dlg), tmp_str_dup(dad, txt)); + rv = 0; + } + else if (pcb_strcasecmp(cmd, "set") == 0) { + int wid, i; + double d; + pcb_coord_t c; + + PCB_ACT_CONVARG(3, FGW_INT, dad, wid = argv[3].val.nat_int); + if ((wid < 0) || (wid >= dad->dlg_len)) { + pcb_message(PCB_MSG_ERROR, "Invalid widget ID %d (set ignored)\n", wid); + PCB_ACT_IRES(-1); + return 0; + } + + switch(dad->dlg[wid].type) { + case PCB_HATT_COORD: + PCB_ACT_CONVARG(4, FGW_COORD, dad, c = fgw_coord(&argv[4])); + PCB_DAD_SET_VALUE(dad->dlg_hid_ctx, wid, coord_value, c); + break; + case PCB_HATT_REAL: + case PCB_HATT_PROGRESS: + PCB_ACT_CONVARG(4, FGW_DOUBLE, dad, d = argv[4].val.nat_double); + PCB_DAD_SET_VALUE(dad->dlg_hid_ctx, wid, real_value, d); + break; + case PCB_HATT_INTEGER: + PCB_ACT_CONVARG(4, FGW_INT, dad, i = argv[4].val.nat_int); + PCB_DAD_SET_VALUE(dad->dlg_hid_ctx, wid, int_value, i); + break; + case PCB_HATT_STRING: + case PCB_HATT_LABEL: + case PCB_HATT_BUTTON: + PCB_ACT_CONVARG(4, FGW_STR, dad, txt = argv[4].val.str); + PCB_DAD_SET_VALUE(dad->dlg_hid_ctx, wid, str_value, txt); + break; + default: + pcb_message(PCB_MSG_ERROR, "Invalid widget type %d - can not change value (set ignored)\n", wid); + PCB_ACT_IRES(-1); + return 0; + } + rv = 0; + } + else if (pcb_strcasecmp(cmd, "get") == 0) { + int wid; + + PCB_ACT_CONVARG(3, FGW_INT, dad, wid = argv[3].val.nat_int); + if ((wid < 0) || (wid >= dad->dlg_len)) { + pcb_message(PCB_MSG_ERROR, "Invalid widget ID %d (get ignored)\n", wid); + return FGW_ERR_NOT_FOUND; + } + + switch(dad->dlg[wid].type) { + case PCB_HATT_COORD: + txt = NULL; + PCB_ACT_MAY_CONVARG(4, FGW_STR, dad, txt = argv[4].val.str); + if (txt != NULL) { + const pcb_unit_t *u = get_unit_struct(txt); + if (u == NULL) { + pcb_message(PCB_MSG_ERROR, "Invalid unit %s (get ignored)\n", txt); + return FGW_ERR_NOT_FOUND; + } + res->type = FGW_DOUBLE; + res->val.nat_double = pcb_coord_to_unit(u, dad->dlg[wid].default_val.coord_value); + } + else { + res->type = FGW_COORD; + fgw_coord(res) = dad->dlg[wid].default_val.coord_value; + } + break; + case PCB_HATT_INTEGER: + res->type = FGW_INT; + res->val.nat_int = dad->dlg[wid].default_val.int_value; + break; + case PCB_HATT_STRING: + case PCB_HATT_LABEL: + case PCB_HATT_BUTTON: + res->type = FGW_STR; + res->val.str = (char *)dad->dlg[wid].default_val.str_value; + break; + default: + pcb_message(PCB_MSG_ERROR, "Invalid widget type %d - can not retrieve value (get ignored)\n", wid); + return FGW_ERR_NOT_FOUND; + } + return 0; + } else if ((pcb_strcasecmp(cmd, "run") == 0) || (pcb_strcasecmp(cmd, "run_modal") == 0)) { + if (dad->running) goto cant_chg; + + PCB_ACT_CONVARG(3, FGW_STR, dad, txt = argv[3].val.str); + + if (dad->level != 0) { + pcb_message(PCB_MSG_ERROR, "Invalid DAD dialog structure: %d levels not closed (missing 'end' calls)\n", dad->level); + rv = -1; + } + else { + PCB_DAD_NEW(dlgname, dad->dlg, txt, dad, (cmd[3] == '_'), dad_close_cb); + rv = PCB_DAD_CURRENT(dad->dlg); + } + } + else { + pcb_message(PCB_MSG_ERROR, "Invalid DAD dialog command: '%s'\n", cmd); + rv = -1; + } + + PCB_ACT_IRES(rv); + return 0; + + cant_chg:; + pcb_message(PCB_MSG_ERROR, "Can't find named DAD dialog %s\n", dlgname); + PCB_ACT_IRES(-1); + return 0; +} + +void pcb_act_dad_init(void) +{ + htsp_init(&dads, strhash, strkeyeq); +} + +void pcb_act_dad_uninit(void) +{ + htsp_entry_t *e; + for(e = htsp_first(&dads); e != NULL; e = htsp_next(&dads, e)) + dad_destroy(e->value); + htsp_uninit(&dads); +} Index: tags/2.1.2/src_plugins/dialogs/act_dad.h =================================================================== --- tags/2.1.2/src_plugins/dialogs/act_dad.h (nonexistent) +++ tags/2.1.2/src_plugins/dialogs/act_dad.h (revision 24813) @@ -0,0 +1,8 @@ +extern const char pcb_acts_dad[]; +extern const char pcb_acth_dad[]; +fgw_error_t pcb_act_dad(fgw_arg_t *res, int argc, fgw_arg_t *argv); + + +void pcb_act_dad_init(void); +void pcb_act_dad_uninit(void); + Index: tags/2.1.2/src_plugins/dialogs/dialogs.c =================================================================== --- tags/2.1.2/src_plugins/dialogs/dialogs.c (nonexistent) +++ tags/2.1.2/src_plugins/dialogs/dialogs.c (revision 24813) @@ -0,0 +1,146 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2017..2019 Tibor 'Igor2' Palinkas + * + * This module, dialogs, was written and is Copyright (C) 2017 by Tibor Palinkas + * this module is also subject to the GNU GPL as described below + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "config.h" +#include "hid.h" +#include "hid_attrib.h" +#include "actions.h" +#include "hid_dad.h" +#include "plugins.h" +#include "funchash_core.h" +#include "dialogs_conf.h" + +const conf_dialogs_t conf_dialogs; + +/* include them all for static inlines */ +#include "dlg_test.c" +#include "dlg_about.h" +#include "dlg_comm_m.h" +#include "dlg_export.h" +#include "dlg_flag_edit.h" +#include "dlg_fontsel.h" +#include "dlg_layer_binding.h" +#include "dlg_layer_flags.h" +#include "dlg_lib_pstk.h" +#include "dlg_loadsave.h" +#include "dlg_log.h" +#include "dlg_padstack.h" +#include "dlg_pinout.c" +#include "dlg_undo.c" +#include "dlg_netlist.c" +#include "dlg_plugins.c" +#include "dlg_printcalib.c" +#include "place.c" + +#include "dlg_view.h" +#include "dlg_pref.h" +#include "act_dad.h" + + +static const char pcb_acth_gui[] = "Intenal: GUI frontend action. Do not use directly."; + +pcb_action_t dialogs_action_list[] = { + {"dlg_test", pcb_act_dlg_test, dlg_test_help, dlg_test_syntax}, + {"LayerBinding", pcb_act_LayerBinding, pcb_acth_LayerBinding, pcb_acts_LayerBinding}, + {"FlagEdit", pcb_act_FlagEdit, pcb_acth_FlagEdit, pcb_acts_FlagEdit}, + {"PadstackEdit", pcb_act_PadstackEdit, pcb_acth_PadstackEdit, pcb_acts_PadstackEdit}, + {"About", pcb_act_About, pcb_acth_About, pcb_acts_About}, + {"Pinout", pcb_act_Pinout, pcb_acth_Pinout, pcb_acts_Pinout}, + {"ExportGUI", pcb_act_ExportGUI, pcb_acth_ExportGUI, pcb_acts_ExportGUI}, + {"PrintGUI", pcb_act_PrintGUI, pcb_acth_PrintGUI, pcb_acts_PrintGUI}, + {"GroupPropGui", pcb_act_GroupPropGui, pcb_acth_GroupPropGui, pcb_acts_GroupPropGui}, + {"LayerPropGui", pcb_act_LayerPropGui, pcb_acth_LayerPropGui, pcb_acts_LayerPropGui}, + {"Preferences", pcb_act_Preferences, pcb_acth_Preferences, pcb_acts_Preferences}, + {"pstklib", pcb_act_pstklib, pcb_acth_pstklib, pcb_acts_pstklib}, + {"UndoDialog", pcb_act_UndoDialog, pcb_acth_UndoDialog, pcb_acts_UndoDialog}, + {"NetlistDialog", pcb_act_NetlistDialog, pcb_acth_NetlistDialog, pcb_acts_NetlistDialog}, + {"ManagePlugins", pcb_act_ManagePlugins, pcb_acth_ManagePlugins, pcb_acts_ManagePlugins}, + {"dad", pcb_act_dad, pcb_acth_dad, pcb_acts_dad}, + {"DrcDialog", pcb_act_DrcDialog, pcb_acth_DrcDialog, pcb_acts_DrcDialog}, + {"IOIncompatListDialog", pcb_act_IOIncompatListDialog, pcb_acth_IOIncompatListDialog, pcb_acts_IOIncompatListDialog}, + {"ViewList", pcb_act_ViewList, pcb_acth_ViewList, pcb_acts_ViewList}, + {"Fontsel", pcb_act_Fontsel, pcb_acth_Fontsel, pcb_acts_Fontsel}, + {"PrintCalibrate", pcb_act_PrintCalibrate, pcb_acth_PrintCalibrate, pcb_acts_PrintCalibrate}, + {"Load", pcb_act_Load, pcb_acth_Load, pcb_acts_Load}, + {"Save", pcb_act_Save, pcb_acth_Save, pcb_acts_Save}, + {"ImportGUI", pcb_act_ImportGUI, pcb_acth_ImportGUI, pcb_acts_ImportGUI}, + {"LogDialog", pcb_act_LogDialog, pcb_acth_LogDialog, pcb_acts_LogDialog}, + + {"gui_PromptFor", pcb_act_gui_PromptFor, pcb_acth_gui, NULL}, + {"gui_MessageBox", pcb_act_gui_MessageBox, pcb_acth_gui, NULL}, + {"gui_FallbackColorPick", pcb_act_gui_FallbackColorPick, pcb_acth_gui, NULL} +}; + +static const char *dialogs_cookie = "dialogs plugin"; + +PCB_REGISTER_ACTIONS(dialogs_action_list, dialogs_cookie) + +int pplg_check_ver_dialogs(int ver_needed) { return 0; } + +void pplg_uninit_dialogs(void) +{ + pcb_event_unbind_allcookie(dialogs_cookie); + pcb_dlg_netlist_uninit(); + pcb_dlg_undo_uninit(); + pcb_dlg_pstklib_uninit(); + pcb_dlg_pref_uninit(); + pcb_act_dad_uninit(); + pcb_remove_actions_by_cookie(dialogs_cookie); + pcb_view_dlg_uninit(); + pcb_dialog_place_uninit(); + pcb_dlg_fontsel_uninit(); + conf_unreg_fields("plugins/dialogs/"); + pcb_dlg_log_uninit(); +} + +#include "dolists.h" + +int pplg_init_dialogs(void) +{ + PCB_API_CHK_VER; + +#define conf_reg(field,isarray,type_name,cpath,cname,desc,flags) \ + conf_reg_field(conf_dialogs, field,isarray,type_name,cpath,cname,desc,flags); +#include "dialogs_conf_fields.h" + + pcb_dlg_log_init(); + pcb_dialog_place_init(); + PCB_REGISTER_ACTIONS(dialogs_action_list, dialogs_cookie) + pcb_event_bind(PCB_EVENT_DAD_NEW_DIALOG, pcb_dialog_place, NULL, dialogs_cookie); + pcb_event_bind(PCB_EVENT_DAD_NEW_GEO, pcb_dialog_resize, NULL, dialogs_cookie); + pcb_act_dad_init(); + pcb_dlg_pref_init(); + pcb_dlg_pstklib_init(); + pcb_dlg_undo_init(); + pcb_dlg_netlist_init(); + pcb_view_dlg_init(); + pcb_dlg_fontsel_init(); + + return 0; +} Index: tags/2.1.2/src_plugins/dialogs/dialogs.conf =================================================================== --- tags/2.1.2/src_plugins/dialogs/dialogs.conf (nonexistent) +++ tags/2.1.2/src_plugins/dialogs/dialogs.conf (revision 24813) @@ -0,0 +1,13 @@ +li:pcb-rnd-conf-v1 { + ha:append { + ha:plugins { + ha:dialogs { + ha:auto_save_window_geometry { + to_design = 0 + to_project = 0 + to_user = 0 + } + } + } + } +} Index: tags/2.1.2/src_plugins/dialogs/dialogs.pup =================================================================== --- tags/2.1.2/src_plugins/dialogs/dialogs.pup (nonexistent) +++ tags/2.1.2/src_plugins/dialogs/dialogs.pup (revision 24813) @@ -0,0 +1,9 @@ +$class feature +$short HID-independent GUI dialogs +$long Interactive core functionality: HID-independent GUI dialogs (enabled by GUI HIDs) +$package lib-gui +$state works +dep draw_fontsel +dep draw_csect +default disable +autoload 1 Index: tags/2.1.2/src_plugins/dialogs/dialogs_conf.h =================================================================== --- tags/2.1.2/src_plugins/dialogs/dialogs_conf.h (nonexistent) +++ tags/2.1.2/src_plugins/dialogs/dialogs_conf.h (revision 24813) @@ -0,0 +1,26 @@ +#ifndef PCB_DIALOGS_CONF_H +#define PCB_DIALOGS_CONF_H + +#include "conf.h" + +typedef struct { + const struct plugins { + const struct dialogs { + const struct auto_save_window_geometry { + CFT_BOOLEAN to_design; + CFT_BOOLEAN to_project; + CFT_BOOLEAN to_user; + } auto_save_window_geometry; + const struct window_geometry { + const struct example_template { + CFT_INTEGER x; + CFT_INTEGER y; + CFT_INTEGER width; + CFT_INTEGER height; + } example_template; + } window_geometry; + } dialogs; + } plugins; +} conf_dialogs_t; + +#endif Index: tags/2.1.2/src_plugins/dialogs/dlg_about.c =================================================================== --- tags/2.1.2/src_plugins/dialogs/dlg_about.c (nonexistent) +++ tags/2.1.2/src_plugins/dialogs/dlg_about.c (revision 24813) @@ -0,0 +1,118 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2018 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "config.h" + +#include +#include "actions.h" +#include "build_run.h" +#include "file_loaded.h" +#include "hid_dad.h" +#include "pcb-printf.h" +#include "dlg_about.h" + +typedef struct{ + PCB_DAD_DECL_NOINIT(dlg) + int active; /* already open - allow only one instance */ +} about_ctx_t; + +about_ctx_t about_ctx; + +static void about_close_cb(void *caller_data, pcb_hid_attr_ev_t ev) +{ + about_ctx_t *ctx = caller_data; + PCB_DAD_FREE(ctx->dlg); + memset(ctx, 0, sizeof(about_ctx_t)); /* reset all states to the initial - includes ctx->active = 0; */ +} + + +static void pcb_dlg_about(void) +{ + const char *tabs[] = { "About pcb-rnd", "Options", "Paths", "License", NULL }; + pcb_hid_dad_buttons_t clbtn[] = {{"Close", 0}, {NULL, 0}}; + htsp_entry_t *e; + gds_t s; + + if (about_ctx.active) + return; + + PCB_DAD_BEGIN_VBOX(about_ctx.dlg); + PCB_DAD_COMPFLAG(about_ctx.dlg, PCB_HATF_EXPFILL); + PCB_DAD_BEGIN_TABBED(about_ctx.dlg, tabs); + PCB_DAD_COMPFLAG(about_ctx.dlg, PCB_HATF_EXPFILL); + PCB_DAD_BEGIN_VBOX(about_ctx.dlg); + PCB_DAD_LABEL(about_ctx.dlg, pcb_get_info_program()); + PCB_DAD_LABEL(about_ctx.dlg, pcb_get_info_copyright()); + PCB_DAD_LABEL(about_ctx.dlg, pcb_get_info_websites(NULL)); + PCB_DAD_END(about_ctx.dlg); + + PCB_DAD_BEGIN_VBOX(about_ctx.dlg); + PCB_DAD_COMPFLAG(about_ctx.dlg, /*PCB_HATF_SCROLL |*/ /*PCB_HATF_FRAME |*/ PCB_HATF_EXPFILL); + PCB_DAD_LABEL(about_ctx.dlg, pcb_get_info_compile_options()); + PCB_DAD_COMPFLAG(about_ctx.dlg, PCB_HATF_EXPFILL); + PCB_DAD_END(about_ctx.dlg); + + + PCB_DAD_BEGIN_VBOX(about_ctx.dlg); + PCB_DAD_COMPFLAG(about_ctx.dlg, PCB_HATF_SCROLL); + gds_init(&s); + for (e = htsp_first(&pcb_file_loaded); e; e = htsp_next(&pcb_file_loaded, e)) { + htsp_entry_t *e2; + pcb_file_loaded_t *cat = e->value; + PCB_DAD_LABEL(about_ctx.dlg, cat->name); + gds_truncate(&s, 0); + for (e2 = htsp_first(&cat->data.category.children); e2; e2 = htsp_next(&cat->data.category.children, e2)) { + pcb_file_loaded_t *file = e2->value; + pcb_append_printf(&s, " %s\t%s\t%s\n", file->name, file->data.file.path, file->data.file.desc); + } + PCB_DAD_LABEL(about_ctx.dlg, s.array); + } + gds_uninit(&s); + PCB_DAD_END(about_ctx.dlg); + + PCB_DAD_BEGIN_VBOX(about_ctx.dlg); + PCB_DAD_LABEL(about_ctx.dlg, pcb_get_info_license()); + PCB_DAD_END(about_ctx.dlg); + + PCB_DAD_END(about_ctx.dlg); + PCB_DAD_BUTTON_CLOSES(about_ctx.dlg, clbtn); + PCB_DAD_END(about_ctx.dlg); + + /* set up the context */ + about_ctx.active = 1; + + /* this is the modal version - please consider using the non-modal version */ + PCB_DAD_NEW("about", about_ctx.dlg, "About pcb-rnd", &about_ctx, pcb_false, about_close_cb); +} + +const char pcb_acts_About[] = "About()\n"; +const char pcb_acth_About[] = "Present the about box"; +fgw_error_t pcb_act_About(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + pcb_dlg_about(); + PCB_ACT_IRES(0); + return 0; +} Index: tags/2.1.2/src_plugins/dialogs/dlg_about.h =================================================================== --- tags/2.1.2/src_plugins/dialogs/dlg_about.h (nonexistent) +++ tags/2.1.2/src_plugins/dialogs/dlg_about.h (revision 24813) @@ -0,0 +1,3 @@ +extern const char pcb_acts_About[]; +extern const char pcb_acth_About[]; +fgw_error_t pcb_act_About(fgw_arg_t *res, int argc, fgw_arg_t *argv); Index: tags/2.1.2/src_plugins/dialogs/dlg_comm_m.c =================================================================== --- tags/2.1.2/src_plugins/dialogs/dlg_comm_m.c (nonexistent) +++ tags/2.1.2/src_plugins/dialogs/dlg_comm_m.c (revision 24813) @@ -0,0 +1,208 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2018 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +/* Common dialogs: simple, modal dialogs for all parts of the code, not just + the GUI HIDs. Even the core will run some of these, through a dispatcher. */ + +#include "config.h" +#include "actions.h" +#include "hid_dad.h" +#include "xpm.h" +#include "dlg_comm_m.h" + +static const char nope[] = "Do not use."; + +static void prompt_enter_cb(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + pcb_dad_retovr_t **ro = attr->user_data; + pcb_hid_dad_close(hid_ctx, *ro, 0); +} + +fgw_error_t pcb_act_gui_PromptFor(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + const char *label, *default_str = "", *title = "pcb-rnd user input"; + const char *pcb_acts_gui_PromptFor = nope; + int ws; + pcb_hid_dad_buttons_t clbtn[] = {{"ok", 0}, {NULL, 0}}; + PCB_DAD_DECL(dlg); + + PCB_ACT_CONVARG(1, FGW_STR, gui_PromptFor, label = argv[1].val.str); + PCB_ACT_MAY_CONVARG(2, FGW_STR, gui_PromptFor, default_str = argv[2].val.str); + PCB_ACT_MAY_CONVARG(3, FGW_STR, gui_PromptFor, title = argv[3].val.str); + + PCB_DAD_BEGIN_VBOX(dlg); + PCB_DAD_LABEL(dlg, label); + PCB_DAD_STRING(dlg); + ws = PCB_DAD_CURRENT(dlg); + dlg[ws].default_val.str_value = pcb_strdup(default_str == NULL ? "" : default_str); + PCB_DAD_ENTER_CB(dlg, prompt_enter_cb); + dlg[ws].user_data = &dlg_ret_override; + PCB_DAD_BUTTON_CLOSES(dlg, clbtn); + PCB_DAD_END(dlg); + + PCB_DAD_NEW("prompt_for", dlg, title, NULL, pcb_true, NULL); + if (PCB_DAD_RUN(dlg) != 0) { + PCB_DAD_FREE(dlg); + return -1; + } + + res->type = FGW_STR | FGW_DYN; + res->val.str = pcb_strdup(dlg[ws].default_val.str_value); + PCB_DAD_FREE(dlg); + + return 0; +} + + +fgw_error_t pcb_act_gui_MessageBox(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + const char *icon, *title, *label, *txt; + const char *pcb_acts_gui_MessageBox = nope; + const char **xpm; + int n, ret; + + PCB_DAD_DECL(dlg); + + PCB_ACT_CONVARG(1, FGW_STR, gui_MessageBox, icon = argv[1].val.str); + PCB_ACT_CONVARG(2, FGW_STR, gui_MessageBox, title = argv[2].val.str); + PCB_ACT_CONVARG(3, FGW_STR, gui_MessageBox, label = argv[3].val.str); + + PCB_DAD_BEGIN_VBOX(dlg); + /* icon and label */ + PCB_DAD_BEGIN_HBOX(dlg); + xpm = pcp_dlg_xpm_by_name(icon); + if (xpm != NULL) + PCB_DAD_PICTURE(dlg, xpm); + PCB_DAD_LABEL(dlg, label); + PCB_DAD_END(dlg); + + /* close buttons */ + PCB_DAD_BEGIN_HBOX(dlg); + PCB_DAD_BEGIN_HBOX(dlg); + PCB_DAD_COMPFLAG(dlg, PCB_HATF_EXPFILL); + PCB_DAD_END(dlg); + for(n = 4; n < argc; n+=2) { + PCB_ACT_CONVARG(n+0, FGW_STR, gui_MessageBox, txt = argv[n+0].val.str); + PCB_ACT_CONVARG(n+1, FGW_INT, gui_MessageBox, ret = argv[n+1].val.nat_int); + PCB_DAD_BUTTON_CLOSE(dlg, txt, ret); + } + PCB_DAD_END(dlg); + + PCB_DAD_END(dlg); + + res->type = FGW_INT; + PCB_DAD_AUTORUN("message", dlg, title, NULL, res->val.nat_int); + PCB_DAD_FREE(dlg); + + return 0; +} + +typedef struct { + PCB_DAD_DECL_NOINIT(dlg) + int wclr, wr, wg, wb; + pcb_color_t clr; +} clrpick_t; + +static int clamp(int c) +{ + if (c < 0) + return 0; + if (c > 255) + return 255; + return c; +} + +static void color_change_cb(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + pcb_hid_attr_val_t val; + clrpick_t *ctx = caller_data; + + pcb_color_load_int(&ctx->clr, clamp(ctx->dlg[ctx->wr].default_val.int_value), clamp(ctx->dlg[ctx->wg].default_val.int_value), clamp(ctx->dlg[ctx->wb].default_val.int_value), 255); + val.clr_value = ctx->clr; + pcb_gui->attr_dlg_set_value(hid_ctx, ctx->wclr, &val); +} + +fgw_error_t pcb_act_gui_FallbackColorPick(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + const char *sclr; + const char *pcb_acts_gui_PromptFor = nope; + pcb_hid_dad_buttons_t clbtn[] = {{"ok", 0}, {"cancel", 1}, {NULL, 0}}; + clrpick_t ctx; + pcb_hid_attr_val_t val; + + PCB_ACT_CONVARG(1, FGW_STR, gui_PromptFor, sclr = argv[1].val.str); + + memset(&ctx, 0, sizeof(ctx)); + if (pcb_color_load_str(&ctx.clr, sclr) != 0) + return -1; + + PCB_DAD_BEGIN_VBOX(ctx.dlg); + PCB_DAD_COLOR(ctx.dlg); + ctx.wclr = PCB_DAD_CURRENT(ctx.dlg); + PCB_DAD_COMPFLAG(ctx.dlg, PCB_HATF_CLR_STATIC); + PCB_DAD_BEGIN_TABLE(ctx.dlg, 2); + PCB_DAD_LABEL(ctx.dlg, "red"); + PCB_DAD_INTEGER(ctx.dlg, ""); + PCB_DAD_MINMAX(ctx.dlg, 0, 255); + PCB_DAD_CHANGE_CB(ctx.dlg, color_change_cb); + ctx.wr = PCB_DAD_CURRENT(ctx.dlg); + PCB_DAD_LABEL(ctx.dlg, "green"); + PCB_DAD_INTEGER(ctx.dlg, ""); + PCB_DAD_MINMAX(ctx.dlg, 0, 255); + PCB_DAD_CHANGE_CB(ctx.dlg, color_change_cb); + ctx.wg = PCB_DAD_CURRENT(ctx.dlg); + PCB_DAD_LABEL(ctx.dlg, "blue"); + PCB_DAD_INTEGER(ctx.dlg, ""); + PCB_DAD_MINMAX(ctx.dlg, 0, 255); + PCB_DAD_CHANGE_CB(ctx.dlg, color_change_cb); + ctx.wb = PCB_DAD_CURRENT(ctx.dlg); + PCB_DAD_BUTTON_CLOSES(ctx.dlg, clbtn); + PCB_DAD_END(ctx.dlg); + PCB_DAD_END(ctx.dlg); + + PCB_DAD_NEW("fallback_color_pick", ctx.dlg, "Change color", &ctx, pcb_true, NULL); + + + val.int_value = ctx.clr.r; + pcb_gui->attr_dlg_set_value(ctx.dlg_hid_ctx, ctx.wr, &val); + val.int_value = ctx.clr.g; + pcb_gui->attr_dlg_set_value(ctx.dlg_hid_ctx, ctx.wg, &val); + val.int_value = ctx.clr.b; + pcb_gui->attr_dlg_set_value(ctx.dlg_hid_ctx, ctx.wb, &val); + val.clr_value = ctx.clr; + pcb_gui->attr_dlg_set_value(ctx.dlg_hid_ctx, ctx.wclr, &val); + + if (PCB_DAD_RUN(ctx.dlg) != 0) { + PCB_DAD_FREE(ctx.dlg); + return -1; + } + + res->type = FGW_STR | FGW_DYN; + res->val.str = pcb_strdup_printf("#%02x%02x%02x", ctx.clr.r, ctx.clr.g, ctx.clr.b); + PCB_DAD_FREE(ctx.dlg); + return 0; +} + Index: tags/2.1.2/src_plugins/dialogs/dlg_comm_m.h =================================================================== --- tags/2.1.2/src_plugins/dialogs/dlg_comm_m.h (nonexistent) +++ tags/2.1.2/src_plugins/dialogs/dlg_comm_m.h (revision 24813) @@ -0,0 +1,3 @@ +fgw_error_t pcb_act_gui_PromptFor(fgw_arg_t *res, int argc, fgw_arg_t *argv); +fgw_error_t pcb_act_gui_MessageBox(fgw_arg_t *res, int argc, fgw_arg_t *argv); +fgw_error_t pcb_act_gui_FallbackColorPick(fgw_arg_t *res, int argc, fgw_arg_t *argv); Index: tags/2.1.2/src_plugins/dialogs/dlg_export.c =================================================================== --- tags/2.1.2/src_plugins/dialogs/dlg_export.c (nonexistent) +++ tags/2.1.2/src_plugins/dialogs/dlg_export.c (revision 24813) @@ -0,0 +1,215 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2018 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "config.h" +#include "actions.h" +#include "hid.h" +#include "hid_dad.h" +#include "hid_init.h" +#include "dlg_export.h" + +typedef struct{ + PCB_DAD_DECL_NOINIT(dlg) + int active; /* already open - allow only one instance */ + + int tabs, len; + + /* per exporter data */ + pcb_hid_t **hid; + const char **tab_name; + int **exp_attr; /* widget IDs of the attributes holding the actual data; outer array is indexed by exporter, inner array is by exporter option index from 0*/ + int *button; /* widget ID of the export button for a specific exporter */ + int *numa; /* number of exporter attributes */ + pcb_hid_attribute_t **ea; /* original exporter attribute arrays */ +} export_ctx_t; + +export_ctx_t export_ctx; + +static pcb_hid_attr_val_t *get_results(export_ctx_t *export_ctx, int id) +{ + pcb_hid_attr_val_t *r; + int *exp_attr, n, numa = export_ctx->numa[id]; + + r = malloc(sizeof(pcb_hid_attr_val_t) * numa); + + exp_attr = export_ctx->exp_attr[id]; + for(n = 0; n < numa; n++) { + int src = exp_attr[n]; + memcpy(&r[n], &(export_ctx->dlg[src].default_val), sizeof(pcb_hid_attr_val_t)); + } + return r; +} + +static void export_cb(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + export_ctx_t *export_ctx = caller_data; + int h, wid; + wid = attr - export_ctx->dlg; + for(h = 0; h < export_ctx->len; h++) { + if (export_ctx->button[h] == wid) { + pcb_hid_attr_val_t *results = get_results(export_ctx, h); + export_ctx->hid[h]->do_export(results); + free(results); + pcb_message(PCB_MSG_INFO, "Export done using exporter: %s\n", export_ctx->hid[h]->name); + return; + } + } + + pcb_message(PCB_MSG_ERROR, "Internal error: can not find which exporter to call\n"); +} + +/* copy back the attribute values from the DAD dialog to exporter dialog so + that values are preserved */ +static void copy_attrs_back(export_ctx_t *ctx) +{ + int n, i; + + for(n = 0; n < ctx->len; n++) { + int *exp_attr = export_ctx.exp_attr[n]; + int numa = export_ctx.numa[n]; + pcb_hid_attribute_t *attrs = export_ctx.ea[n]; + + for(i = 0; i < numa; i++) + memcpy(&attrs[i].default_val, &ctx->dlg[exp_attr[i]].default_val, sizeof(pcb_hid_attr_val_t)); + } +} + +static void export_close_cb(void *caller_data, pcb_hid_attr_ev_t ev) +{ + export_ctx_t *ctx = caller_data; + int n; + + copy_attrs_back(ctx); + + PCB_DAD_FREE(ctx->dlg); + free(ctx->hid); + free(ctx->tab_name); + for(n = 0; n < export_ctx.len; n++) + free(ctx->exp_attr[n]); + free(ctx->exp_attr); + free(ctx->button); + free(ctx->numa); + free(ctx->ea); + memset(ctx, 0, sizeof(export_ctx_t)); /* reset all states to the initial - includes ctx->active = 0; */ +} + +static void pcb_dlg_export(const char *title, int exporters, int printers) +{ + pcb_hid_t **hids; + int n, i, *exp_attr; + pcb_hid_dad_buttons_t clbtn[] = {{"Close", 0}, {NULL, 0}}; + + if (export_ctx.active) + return; /* do not open another */ + + hids = pcb_hid_enumerate(); + for(n = 0, export_ctx.len = 0; hids[n] != NULL; n++) { + if (((exporters && hids[n]->exporter) || (printers && hids[n]->printer)) && (!hids[n]->hide_from_gui)) + export_ctx.len++; + } + + if (export_ctx.len == 0) { + pcb_message(PCB_MSG_ERROR, "Can not export: there are no export plugins available\n"); + return; + } + + export_ctx.tab_name = malloc(sizeof(char *) * (export_ctx.len+1)); + export_ctx.hid = malloc(sizeof(pcb_hid_t *) * (export_ctx.len)); + export_ctx.exp_attr = malloc(sizeof(int *) * (export_ctx.len)); + export_ctx.button = malloc(sizeof(int) * (export_ctx.len)); + export_ctx.numa = malloc(sizeof(int) * (export_ctx.len)); + export_ctx.ea = malloc(sizeof(pcb_hid_attribute_t *) * (export_ctx.len)); + + for(i = n = 0; hids[n] != NULL; n++) { + if (((exporters && hids[n]->exporter) || (printers && hids[n]->printer)) && (!hids[n]->hide_from_gui)) { + export_ctx.tab_name[i] = hids[n]->name; + export_ctx.hid[i] = hids[n]; + i++; + } + } + + export_ctx.tab_name[i] = NULL; + + PCB_DAD_BEGIN_VBOX(export_ctx.dlg); + PCB_DAD_COMPFLAG(export_ctx.dlg, PCB_HATF_EXPFILL); + PCB_DAD_BEGIN_TABBED(export_ctx.dlg, export_ctx.tab_name); + PCB_DAD_COMPFLAG(export_ctx.dlg, PCB_HATF_LEFT_TAB); + export_ctx.tabs = PCB_DAD_CURRENT(export_ctx.dlg); + for(n = 0; n < export_ctx.len; n++) { + int numa; + pcb_hid_attribute_t *attrs = export_ctx.hid[n]->get_export_options(&numa); + export_ctx.numa[n] = numa; + export_ctx.ea[n] = attrs; + if (numa < 1) { + PCB_DAD_LABEL(export_ctx.dlg, "Exporter unavailable for direct export"); + continue; + } + PCB_DAD_BEGIN_VBOX(export_ctx.dlg); + if (numa > 12) + PCB_DAD_COMPFLAG(export_ctx.dlg, PCB_HATF_SCROLL); + export_ctx.exp_attr[n] = exp_attr = malloc(sizeof(int) * numa); + for(i = 0; i < numa; i++) { + PCB_DAD_BEGIN_HBOX(export_ctx.dlg) + PCB_DAD_DUP_ATTR(export_ctx.dlg, attrs+i); + exp_attr[i] = PCB_DAD_CURRENT(export_ctx.dlg); + if (attrs[i].name != NULL) + PCB_DAD_LABEL(export_ctx.dlg, attrs[i].name); + PCB_DAD_END(export_ctx.dlg); + } + PCB_DAD_LABEL(export_ctx.dlg, " "); /* ugly way of inserting some vertical spacing */ + PCB_DAD_BEGIN_HBOX(export_ctx.dlg) + PCB_DAD_LABEL(export_ctx.dlg, "Apply attributes and export: "); + PCB_DAD_BUTTON(export_ctx.dlg, "Export!"); + export_ctx.button[n] = PCB_DAD_CURRENT(export_ctx.dlg); + PCB_DAD_CHANGE_CB(export_ctx.dlg, export_cb); + PCB_DAD_END(export_ctx.dlg); + PCB_DAD_END(export_ctx.dlg); + } + PCB_DAD_END(export_ctx.dlg); + PCB_DAD_BUTTON_CLOSES(export_ctx.dlg, clbtn); + PCB_DAD_END(export_ctx.dlg); + + /* set up the context */ + export_ctx.active = 1; + + PCB_DAD_NEW("export", export_ctx.dlg, title, &export_ctx, pcb_false, export_close_cb); +} + +const char pcb_acts_ExportGUI[] = "ExportGUI()\n"; +const char pcb_acth_ExportGUI[] = "Open the export dialog."; +fgw_error_t pcb_act_ExportGUI(fgw_arg_t *ores, int oargc, fgw_arg_t *oargv) +{ + pcb_dlg_export("Export to file", 1, 0); + return 0; +} + +const char pcb_acts_PrintGUI[] = "PrintGUI()\n"; +const char pcb_acth_PrintGUI[] = "Open the print dialog."; +fgw_error_t pcb_act_PrintGUI(fgw_arg_t *ores, int oargc, fgw_arg_t *oargv) +{ + pcb_dlg_export("Print", 0, 1); + return 0; +} Index: tags/2.1.2/src_plugins/dialogs/dlg_export.h =================================================================== --- tags/2.1.2/src_plugins/dialogs/dlg_export.h (nonexistent) +++ tags/2.1.2/src_plugins/dialogs/dlg_export.h (revision 24813) @@ -0,0 +1,7 @@ +extern const char pcb_acts_ExportGUI[]; +extern const char pcb_acth_ExportGUI[]; +fgw_error_t pcb_act_ExportGUI(fgw_arg_t *ores, int oargc, fgw_arg_t *oargv); + +extern const char pcb_acts_PrintGUI[]; +extern const char pcb_acth_PrintGUI[]; +fgw_error_t pcb_act_PrintGUI(fgw_arg_t *ores, int oargc, fgw_arg_t *oargv); Index: tags/2.1.2/src_plugins/dialogs/dlg_flag_edit.c =================================================================== --- tags/2.1.2/src_plugins/dialogs/dlg_flag_edit.c (nonexistent) +++ tags/2.1.2/src_plugins/dialogs/dlg_flag_edit.c (revision 24813) @@ -0,0 +1,163 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2017 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "config.h" +#include "actions.h" +#include "hid_dad.h" +#include "flag.h" +#include "flag_str.h" +#include "change.h" +#include "undo.h" +#include "search.h" +#include "funchash_core.h" +#include "dlg_flag_edit.h" + +typedef struct{ + unsigned long flag_bit[64]; + int wid[64]; + int len; + pcb_board_t *pcb; + int obj_type; + void *ptr1; + pcb_any_obj_t *obj; + pcb_hid_attribute_t *attrs; +} fe_ctx_t; + +#define PCB_FLAGEDIT_TYPES \ + (PCB_OBJ_PSTK | PCB_OBJ_LINE | PCB_OBJ_POLY | \ + PCB_OBJ_TEXT | PCB_OBJ_SUBC | PCB_OBJ_ARC) + +static void fe_attr_chg(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + int n; + fe_ctx_t *ctx = caller_data; + unsigned long set = 0, clr = 0; + + for(n = 0; n < ctx->len; n++) { + int wid = ctx->wid[n]; + if ((ctx->attrs[wid].default_val.int_value) && (!PCB_FLAG_TEST(ctx->flag_bit[n], ctx->obj))) + set |= ctx->flag_bit[n]; + else if (!(ctx->attrs[wid].default_val.int_value) && PCB_FLAG_TEST(ctx->flag_bit[n], ctx->obj)) + clr |= ctx->flag_bit[n]; + } + + if ((set == 0) && (clr == 0)) + return; + + /* Note: this function is called upon each change so only one of these will be non-zero: */ + + if (set != 0) + pcb_flag_change(ctx->pcb, PCB_CHGFLG_SET, set, ctx->obj_type, ctx->ptr1, ctx->obj, ctx->obj); + + if (clr != 0) + pcb_flag_change(ctx->pcb, PCB_CHGFLG_CLEAR, clr, ctx->obj_type, ctx->ptr1, ctx->obj, ctx->obj); + + pcb_gui->invalidate_all(); +} + + + +const char pcb_acts_FlagEdit[] = "FlagEdit(object)\n"; +const char pcb_acth_FlagEdit[] = "Change the layer binding."; +fgw_error_t pcb_act_FlagEdit(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + int op = F_Object; + fe_ctx_t ctx; + pcb_hid_attr_val_t val; + int type; + pcb_hid_dad_buttons_t clbtn[] = {{"Close", 0}, {NULL, 0}}; + + memset(&ctx, 0, sizeof(ctx)); + + PCB_ACT_MAY_CONVARG(1, FGW_KEYWORD, FlagEdit, op = fgw_keyword(&argv[1])); + + if (op == F_Object) { + pcb_coord_t x, y; + void *ptr1, *ptr2, *ptr3; + pcb_hid_get_coords("Click on object to change flags of", &x, &y, 0); + type = pcb_search_screen(x, y, PCB_FLAGEDIT_TYPES | PCB_LOOSE_SUBC, &ptr1, &ptr2, &ptr3); + ctx.ptr1 = ptr1; + ctx.obj = (pcb_any_obj_t *)ptr2; + ctx.obj_type = (type & 0xFFFF) | (type & PCB_OBJ_PSTK); + } + else + PCB_ACT_FAIL(FlagEdit); + + if ((ctx.obj_type != 0) && (PCB_FLAG_TEST(PCB_FLAG_LOCK, ctx.obj))) { + pcb_message(PCB_MSG_ERROR, "Can't edit the flags of a locked object, unlock first.\n"); + PCB_ACT_IRES(-1); + return 0; + } + + if (ctx.obj_type != 0) { /* interactive mode */ + int n; + char tmp[128]; + PCB_DAD_DECL(dlg); + + ctx.pcb = PCB; + ctx.len = 0; + + pcb_undo_save_serial(); + + PCB_DAD_BEGIN_VBOX(dlg); + PCB_DAD_COMPFLAG(dlg, PCB_HATF_EXPFILL); + sprintf(tmp, "Object flags of %s #%ld\n", pcb_obj_type_name(ctx.obj_type), ctx.obj->ID); + PCB_DAD_LABEL(dlg, tmp); + + for(n = 0; n < pcb_object_flagbits_len; n++) { + if (pcb_object_flagbits[n].object_types & ctx.obj_type) { + PCB_DAD_BEGIN_HBOX(dlg); + PCB_DAD_BOOL(dlg, ""); + PCB_DAD_HELP(dlg, pcb_object_flagbits[n].help); + ctx.wid[ctx.len] = PCB_DAD_CURRENT(dlg); + ctx.flag_bit[ctx.len] = pcb_object_flagbits[n].mask; + if (PCB_FLAG_TEST(ctx.flag_bit[ctx.len], ctx.obj)) + PCB_DAD_DEFAULT_NUM(dlg, 1); + PCB_DAD_LABEL(dlg, pcb_object_flagbits[n].name); + ctx.len++; + PCB_DAD_END(dlg); + } + } + PCB_DAD_BUTTON_CLOSES(dlg, clbtn); + PCB_DAD_END(dlg); + + ctx.attrs = dlg; + + PCB_DAD_NEW("flags", dlg, "Edit flags", &ctx, pcb_true, NULL); + + val.func = fe_attr_chg; + pcb_gui->attr_dlg_property(dlg_hid_ctx, PCB_HATP_GLOBAL_CALLBACK, &val); + + PCB_DAD_RUN(dlg); + + PCB_DAD_FREE(dlg); + pcb_undo_restore_serial(); + pcb_undo_inc_serial(); + } + + PCB_ACT_IRES(0); + return 0; +} Index: tags/2.1.2/src_plugins/dialogs/dlg_flag_edit.h =================================================================== --- tags/2.1.2/src_plugins/dialogs/dlg_flag_edit.h (nonexistent) +++ tags/2.1.2/src_plugins/dialogs/dlg_flag_edit.h (revision 24813) @@ -0,0 +1,3 @@ +extern const char pcb_acts_FlagEdit[]; +extern const char pcb_acth_FlagEdit[]; +fgw_error_t pcb_act_FlagEdit(fgw_arg_t *res, int argc, fgw_arg_t *argv); Index: tags/2.1.2/src_plugins/dialogs/dlg_fontsel.c =================================================================== --- tags/2.1.2/src_plugins/dialogs/dlg_fontsel.c (nonexistent) +++ tags/2.1.2/src_plugins/dialogs/dlg_fontsel.c (revision 24813) @@ -0,0 +1,257 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2018,2019 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "config.h" +#include "actions.h" +#include "board.h" +#include "change.h" +#include "conf_core.h" +#include "event.h" +#include "hid_dad.h" +#include "stub_draw.h" +#include "idpath.h" +#include "search.h" +#include "dlg_fontsel.h" + +typedef struct{ + PCB_DAD_DECL_NOINIT(dlg) + pcb_board_t *pcb; + int wprev; + + unsigned active:1; + unsigned alloced:1; + + pcb_idpath_t *txt_id; + gdl_elem_t link; +} fontsel_ctx_t; + +gdl_list_t fontsels; /* object font selectors */ +fontsel_ctx_t fontsel_brd; + +static const char *fontsel_cookie = "dlg_fontsel"; + +static void fontsel_close_cb(void *caller_data, pcb_hid_attr_ev_t ev) +{ + fontsel_ctx_t *ctx = caller_data; + + if (ctx->txt_id != NULL) + pcb_idpath_destroy(ctx->txt_id); + + PCB_DAD_FREE(ctx->dlg); + if (ctx->alloced) { + gdl_remove(&fontsels, ctx, link); + free(ctx); + } + else + memset(ctx, 0, sizeof(fontsel_ctx_t)); +} + +void fontsel_expose_cb(pcb_hid_attribute_t *attrib, pcb_hid_preview_t *prv, pcb_hid_gc_t gc, const pcb_hid_expose_ctx_t *e) +{ + fontsel_ctx_t *ctx = prv->user_ctx; + + if (ctx->txt_id != NULL) { + pcb_text_t *txt = (pcb_text_t *)pcb_idpath2obj(ctx->pcb->Data, ctx->txt_id); + if (txt != NULL) + pcb_stub_draw_fontsel(gc, e, txt); + } + else + pcb_stub_draw_fontsel(gc, e, NULL); +} + +pcb_bool fontsel_mouse_cb(pcb_hid_attribute_t *attrib, pcb_hid_preview_t *prv, pcb_hid_mouse_ev_t kind, pcb_coord_t x, pcb_coord_t y) +{ + fontsel_ctx_t *ctx = prv->user_ctx; + + if (ctx->txt_id != NULL) { + pcb_text_t *txt = (pcb_text_t *)pcb_idpath2obj(ctx->pcb->Data, ctx->txt_id); + if (txt == NULL) + return 0; + return pcb_stub_draw_fontsel_mouse_ev(kind, x, y, txt); + } + return pcb_stub_draw_fontsel_mouse_ev(kind, x, y, NULL); +} + +void fontsel_free_cb(pcb_hid_attribute_t *attrib, void *user_ctx, void *hid_ctx) +{ +} + +static void fontsel_preview_update(fontsel_ctx_t *ctx) +{ + pcb_hid_attr_val_t hv; + + if ((ctx == NULL) || (!ctx->active)) + return; + + hv.str_value = NULL; + pcb_gui->attr_dlg_set_value(ctx->dlg_hid_ctx, ctx->wprev, &hv); +} + + +static void btn_load_cb(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + pcb_actionl("LoadFontFrom", NULL); /* modal, blocking */ + fontsel_preview_update((fontsel_ctx_t *)caller_data); +} + +static void btn_replace_cb(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + char file[1] = "", id[5]; + pcb_snprintf(id, sizeof(id), "%ld", conf_core.design.text_font_id); + pcb_actionl("LoadFontFrom", file, id, NULL); /* modal, blocking */ + fontsel_preview_update((fontsel_ctx_t *)caller_data); +} + +static void btn_remove_cb(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + if (conf_core.design.text_font_id == 0) { + pcb_message(PCB_MSG_ERROR, "Can not remove the default font.\n"); + return; + } + pcb_del_font(&PCB->fontkit, conf_core.design.text_font_id); + conf_set(CFR_DESIGN, "design/text_font_id", 0, "0", POL_OVERWRITE); + fontsel_preview_update((fontsel_ctx_t *)caller_data); +} + + +static void pcb_dlg_fontsel(pcb_board_t *pcb, int modal, int global, pcb_text_t *txt_obj) +{ + pcb_box_t vbox = {0, 0, PCB_MM_TO_COORD(55), PCB_MM_TO_COORD(55)}; + pcb_hid_dad_buttons_t clbtn[] = {{"Close", 0}, {NULL, 0}}; + fontsel_ctx_t *c, *ctx = NULL; + + if (global) { + if (fontsel_brd.active) + return; /* do not open another */ + ctx = &fontsel_brd; + ctx->alloced = 0; + } + else { + for(c = gdl_first(&fontsels); c != NULL; c = gdl_next(&fontsels, c)) { + pcb_text_t *txt = (pcb_text_t *)pcb_idpath2obj(c->pcb->Data, c->txt_id); + if (txt == txt_obj) { + pcb_message(PCB_MSG_ERROR, "There is already anm active fontedit dialog for that object,\nnot going to open a second dialog.\n"); + return; + } + } + ctx = calloc(sizeof(fontsel_ctx_t), 1); + ctx->alloced = 1; + gdl_insert(&fontsels, ctx, link); + } + + ctx->pcb = pcb; + if (txt_obj != NULL) + ctx->txt_id = pcb_obj2idpath((pcb_any_obj_t *)txt_obj); + else + ctx->txt_id = NULL; + PCB_DAD_BEGIN_VBOX(ctx->dlg); + PCB_DAD_COMPFLAG(ctx->dlg, PCB_HATF_EXPFILL); + PCB_DAD_PREVIEW(ctx->dlg, fontsel_expose_cb, fontsel_mouse_cb, fontsel_free_cb, &vbox, 200, 200, ctx); + PCB_DAD_COMPFLAG(ctx->dlg, PCB_HATF_EXPFILL); + ctx->wprev = PCB_DAD_CURRENT(ctx->dlg); + PCB_DAD_BEGIN_HBOX(ctx->dlg); + PCB_DAD_BUTTON(ctx->dlg, "Load font"); + PCB_DAD_CHANGE_CB(ctx->dlg, btn_load_cb); + PCB_DAD_HELP(ctx->dlg, "Load new font from disk"); + PCB_DAD_BUTTON(ctx->dlg, "Replace font"); + PCB_DAD_CHANGE_CB(ctx->dlg, btn_replace_cb); + PCB_DAD_HELP(ctx->dlg, "Replace currently selected font\nwith new font loaded from disk"); + PCB_DAD_BUTTON(ctx->dlg, "Remove font"); + PCB_DAD_CHANGE_CB(ctx->dlg, btn_remove_cb); + PCB_DAD_HELP(ctx->dlg, "Remove currently selected font"); + PCB_DAD_END(ctx->dlg); + PCB_DAD_BUTTON_CLOSES(ctx->dlg, clbtn); + PCB_DAD_END(ctx->dlg); + + ctx->active = 1; + PCB_DAD_NEW("fontsel", ctx->dlg, "Font selection", ctx, modal, fontsel_close_cb); +} + +const char pcb_acts_Fontsel[] = "Fontsel()\n"; +const char pcb_acth_Fontsel[] = "Open the font selection dialog"; +fgw_error_t pcb_act_Fontsel(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + const char *op = NULL; + int modal = 0, global = 1; + pcb_text_t *txt_obj = NULL; + + if (argc > 2) + PCB_ACT_FAIL(Fontsel); + + PCB_ACT_MAY_CONVARG(1, FGW_STR, Fontsel, op = argv[1].val.str); + + if (op != NULL) { + if (pcb_strcasecmp(op, "Object") == 0) { + pcb_coord_t x, y; + int type; + void *ptr1, *ptr2, *ptr3; + pcb_hid_get_coords("Select an Object", &x, &y, 0); + if ((type = pcb_search_screen(x, y, PCB_CHANGENAME_TYPES, &ptr1, &ptr2, &ptr3)) != PCB_OBJ_VOID) { + txt_obj = ptr2; + modal = 0; + global = 0; + } + } + else + PCB_ACT_FAIL(Fontsel); + } + pcb_dlg_fontsel(PCB, modal, global, txt_obj); + return 0; +} + +static void fontsel_mchanged_ev(void *user_data, int argc, pcb_event_arg_t argv[]) +{ + if (fontsel_brd.active) + fontsel_preview_update(&fontsel_brd); +} + +static void fontsel_bchanged_ev(void *user_data, int argc, pcb_event_arg_t argv[]) +{ + fontsel_ctx_t *c, *next; + pcb_dad_retovr_t retovr; + + if (fontsel_brd.active) + fontsel_preview_update(&fontsel_brd); + + for(c = gdl_first(&fontsels); c != NULL; c = next) { + next = gdl_next(&fontsels, c); + pcb_hid_dad_close(c->dlg_hid_ctx, &retovr, 0); + } + +} + + +void pcb_dlg_fontsel_uninit(void) +{ + pcb_event_unbind_allcookie(fontsel_cookie); +} + +void pcb_dlg_fontsel_init(void) +{ + pcb_event_bind(PCB_EVENT_BOARD_CHANGED, fontsel_bchanged_ev, NULL, fontsel_cookie); + pcb_event_bind(PCB_EVENT_BOARD_META_CHANGED, fontsel_mchanged_ev, NULL, fontsel_cookie); +} + Index: tags/2.1.2/src_plugins/dialogs/dlg_fontsel.h =================================================================== --- tags/2.1.2/src_plugins/dialogs/dlg_fontsel.h (nonexistent) +++ tags/2.1.2/src_plugins/dialogs/dlg_fontsel.h (revision 24813) @@ -0,0 +1,6 @@ +extern const char pcb_acts_Fontsel[]; +extern const char pcb_acth_Fontsel[]; +fgw_error_t pcb_act_Fontsel(fgw_arg_t *res, int argc, fgw_arg_t *argv); + +void pcb_dlg_fontsel_uninit(void); +void pcb_dlg_fontsel_init(void); Index: tags/2.1.2/src_plugins/dialogs/dlg_layer_binding.c =================================================================== --- tags/2.1.2/src_plugins/dialogs/dlg_layer_binding.c (nonexistent) +++ tags/2.1.2/src_plugins/dialogs/dlg_layer_binding.c (revision 24813) @@ -0,0 +1,372 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2017 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "config.h" +#include "actions.h" +#include "board.h" +#include "data.h" +#include "event.h" +#include "conf_core.h" +#include "compat_misc.h" +#include "hid_dad.h" +#include "funchash_core.h" +#include "obj_subc.h" +#include "search.h" +#include "dlg_layer_binding.h" + +const char *pcb_lb_comp[] = { "+manual", "-manual", "+auto", "-auto", NULL }; +const char *pcb_lb_types[] = { "UNKNOWN", "paste", "mask", "silk", "copper", "boundary", "mech", "doc", "virtual", NULL }; +const char *pcb_lb_side[] = { "top", "bottom", NULL }; + +typedef struct { + int name, comp, type, offs, from, side, purpose, layer; /* widet indices */ +} lb_widx_t; + +typedef struct { + const char **layer_names; + lb_widx_t *widx; + pcb_data_t *data; + pcb_subc_t *subc; + pcb_board_t *pcb; + int no_layer; /* the "invalid layer" in the layer names enum */ + pcb_hid_attribute_t *attrs; +} lb_ctx_t; + +int pcb_ly_type2enum(pcb_layer_type_t type) +{ + if (type & PCB_LYT_PASTE) return 1; + else if (type & PCB_LYT_MASK) return 2; + else if (type & PCB_LYT_SILK) return 3; + else if (type & PCB_LYT_COPPER) return 4; + else if (type & PCB_LYT_BOUNDARY) return 5; + else if (type & PCB_LYT_MECH) return 6; + else if (type & PCB_LYT_DOC) return 7; + else if (type & PCB_LYT_VIRTUAL) return 8; + return 0; +} + +static void set_ly_type(void *hid_ctx, int wid, pcb_layer_type_t type) +{ + PCB_DAD_SET_VALUE(hid_ctx, wid, int_value, pcb_ly_type2enum(type)); +} + +void pcb_get_ly_type_(int combo_type, pcb_layer_type_t *type) +{ + /* clear relevant flags */ + *type &= ~(PCB_LYT_ANYTHING | PCB_LYT_ANYWHERE | PCB_LYT_VIRTUAL); + + /* set type */ + switch(combo_type) { + case 1: *type |= PCB_LYT_PASTE; break; + case 2: *type |= PCB_LYT_MASK; break; + case 3: *type |= PCB_LYT_SILK; break; + case 4: *type |= PCB_LYT_COPPER; break; + case 5: *type |= PCB_LYT_BOUNDARY; break; + case 6: *type |= PCB_LYT_MECH; break; + case 7: *type |= PCB_LYT_DOC; break; + case 8: *type |= PCB_LYT_VIRTUAL; break; + } +} + + +static void get_ly_type(int combo_type, int combo_side, int dlg_offs, pcb_layer_type_t *type, int *offs) +{ + pcb_get_ly_type_(combo_type, type); + + if (PCB_LAYER_SIDED(*type)) { + /* set side and offset */ + if (dlg_offs == 0) { + if (combo_side == 0) + *type |= PCB_LYT_TOP; + else + *type |= PCB_LYT_BOTTOM; + } + else { + if (combo_side != 0) + dlg_offs = -dlg_offs; + *type |= PCB_LYT_INTERN; + } + } + *offs = dlg_offs; +} + + +#define layer_name_mismatch(w, layer) \ +((ctx->attrs[w->name].default_val.str_value == NULL) || (strcmp(layer->name, ctx->attrs[w->name].default_val.str_value) != 0)) + +#define layer_purpose_mismatch(w, layer) \ +((ctx->attrs[w->purpose].default_val.str_value == NULL) || (layer->meta.bound.purpose == NULL) || (strcmp(layer->meta.bound.purpose, ctx->attrs[w->purpose].default_val.str_value) != 0)) + +static void lb_data2dialog(void *hid_ctx, lb_ctx_t *ctx) +{ + int n; + pcb_bool enable; + + for(n = 0; n < ctx->data->LayerN; n++) { + lb_widx_t *w = ctx->widx + n; + pcb_layer_t *layer = ctx->data->Layer + n; + pcb_layer_id_t lid; + int ofs; + + /* disable comp for copper and outline */ + enable = !(layer->meta.bound.type & PCB_LYT_COPPER) && !(layer->meta.bound.type & PCB_LYT_BOUNDARY); + pcb_gui->attr_dlg_widget_state(hid_ctx, w->comp, enable); + if (!enable) + layer->comb = 0; /* copper and outline must be +manual */ + + /* name and type */ + if (layer_name_mismatch(w, layer)) + PCB_DAD_SET_VALUE(hid_ctx, w->name, str_value, pcb_strdup(layer->name)); + + if (layer_purpose_mismatch(w, layer)) { + char *purp = layer->meta.bound.purpose; + if (purp == NULL) + purp = ""; + PCB_DAD_SET_VALUE(hid_ctx, w->purpose, str_value, pcb_strdup(purp)); + } + + PCB_DAD_SET_VALUE(hid_ctx, w->comp, int_value, layer->comb); + + set_ly_type(hid_ctx, w->type, layer->meta.bound.type); + + /* disable side for non-sided */ + if (PCB_LAYER_SIDED(layer->meta.bound.type)) { + /* side & offset */ + PCB_DAD_SET_VALUE(hid_ctx, w->side, int_value, !!(layer->meta.bound.type & PCB_LYT_BOTTOM)); + pcb_gui->attr_dlg_widget_state(hid_ctx, w->side, 1); + } + else + pcb_gui->attr_dlg_widget_state(hid_ctx, w->side, 0); + + ofs = layer->meta.bound.stack_offs; + if (ofs < 0) { + PCB_DAD_SET_VALUE(hid_ctx, w->side, int_value, 1); + ofs = -layer->meta.bound.stack_offs; + } + PCB_DAD_SET_VALUE(hid_ctx, w->offs, int_value, ofs); + + /* enable offset only for copper */ + enable = (layer->meta.bound.type & PCB_LYT_COPPER); + pcb_gui->attr_dlg_widget_state(hid_ctx, w->offs, enable); + pcb_gui->attr_dlg_widget_state(hid_ctx, w->from, enable); + + /* real layer */ + if (layer->meta.bound.real != NULL) + lid = pcb_layer_id(PCB->Data, layer->meta.bound.real); + else + lid = ctx->no_layer; + PCB_DAD_SET_VALUE(hid_ctx, w->layer, int_value, lid); + pcb_gui->attr_dlg_widget_state(hid_ctx, w->layer, 0); + } +} + +static void lb_dialog2data(void *hid_ctx, lb_ctx_t *ctx) +{ + int n; + + for(n = 0; n < ctx->data->LayerN; n++) { + lb_widx_t *w = ctx->widx + n; + pcb_layer_t *layer = ctx->data->Layer + n; + + if (layer_name_mismatch(w, layer)) { + free((char *)layer->name); + layer->name = pcb_strdup(ctx->attrs[w->name].default_val.str_value); + } + + if (layer_purpose_mismatch(w, layer)) { + const char *purp = ctx->attrs[w->purpose].default_val.str_value; + free((char *)layer->meta.bound.purpose); + if ((purp == NULL) || (*purp == '\0')) + layer->meta.bound.purpose = NULL; + else + layer->meta.bound.purpose = pcb_strdup(purp); + } + + layer->comb = ctx->attrs[w->comp].default_val.int_value; + get_ly_type(ctx->attrs[w->type].default_val.int_value, ctx->attrs[w->side].default_val.int_value, ctx->attrs[w->offs].default_val.int_value, &layer->meta.bound.type, &layer->meta.bound.stack_offs); + + /* enforce some sanity rules */ + if (layer->meta.bound.type & PCB_LYT_BOUNDARY) { + /* outline must be positive global */ + layer->comb = 0; + layer->meta.bound.type &= ~PCB_LYT_ANYWHERE; + } + if (!(layer->meta.bound.type & PCB_LYT_COPPER)) { + /* temporary: offset is useful only for copper layers */ + layer->meta.bound.stack_offs = 0; + } + } +} + + +static void lb_attr_chg(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + lb_ctx_t *ctx = caller_data; + lb_dialog2data(hid_ctx, ctx); + if (ctx->subc != NULL) { + if (pcb_subc_rebind(ctx->pcb, ctx->subc) > 0) + pcb_gui->invalidate_all(); + } + else { /* buffer */ + pcb_data_binding_update(ctx->pcb, ctx->data); + pcb_gui->invalidate_all(); + } + lb_data2dialog(hid_ctx, ctx); /* update disables */ +} + +const char pcb_acts_LayerBinding[] = "LayerBinding(object)\nLayerBinding(selected)\nLayerBinding(buffer)\n"; +const char pcb_acth_LayerBinding[] = "Change the layer binding."; +fgw_error_t pcb_act_LayerBinding(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + int op = F_Object; + lb_ctx_t ctx; + int num_copper; + pcb_hid_attr_val_t val; + + memset(&ctx, 0, sizeof(ctx)); + PCB_ACT_MAY_CONVARG(1, FGW_KEYWORD, LayerBinding, op = fgw_keyword(&argv[1])); + + if (op == F_Object) { + pcb_coord_t x, y; + int type; + void *ptr1, *ptr2, *ptr3; + pcb_hid_get_coords("Click on subc to change the layer binding of", &x, &y, 0); + type = pcb_search_screen(x, y, PCB_OBJ_SUBC, &ptr1, &ptr2, &ptr3); + if (type != PCB_OBJ_SUBC) { + pcb_message(PCB_MSG_ERROR, "No subc under the cursor\n"); + return -1; + } + ctx.subc = ptr2; + ctx.data = ctx.subc->data; + } + else if (op == F_Selected) { +TODO("subc TODO") + pcb_message(PCB_MSG_ERROR, "TODO\n"); + return 1; + } + else if (op == F_Buffer) { + ctx.data = PCB_PASTEBUFFER->Data; + } + else + PCB_ACT_FAIL(LayerBinding); + + { /* interactive mode */ + int n; + pcb_hid_dad_buttons_t clbtn[] = {{"Close", 0}, {NULL, 0}}; + PCB_DAD_DECL(dlg); + + ctx.pcb = PCB; + ctx.widx = malloc(sizeof(lb_widx_t) * ctx.data->LayerN); + ctx.layer_names = calloc(sizeof(char *), PCB->Data->LayerN+2); + for(n = 0; n < PCB->Data->LayerN; n++) + ctx.layer_names[n] = PCB->Data->Layer[n].name; + ctx.no_layer = n; + ctx.layer_names[n] = "invalid/unbound"; + n++; + ctx.layer_names[n] = NULL; + + for(n = 0, num_copper = -1; n < PCB->LayerGroups.len; n++) + if (pcb_layergrp_flags(PCB, n) & PCB_LYT_COPPER) + num_copper++; + + PCB_DAD_BEGIN_VBOX(dlg); + PCB_DAD_COMPFLAG(dlg, PCB_HATF_EXPFILL); + PCB_DAD_BEGIN_TABLE(dlg, 2); + PCB_DAD_COMPFLAG(dlg, PCB_HATF_SCROLL | PCB_HATF_EXPFILL); + for(n = 0; n < ctx.data->LayerN; n++) { + lb_widx_t *w = ctx.widx+n; + /* left side */ + PCB_DAD_BEGIN_VBOX(dlg); + if (n == 0) + PCB_DAD_LABEL(dlg, "RECIPE"); + else + PCB_DAD_LABEL(dlg, "\n"); + + PCB_DAD_BEGIN_HBOX(dlg); + PCB_DAD_LABEL(dlg, "Name:"); + PCB_DAD_STRING(dlg); + w->name = PCB_DAD_CURRENT(dlg); + PCB_DAD_END(dlg); + PCB_DAD_BEGIN_HBOX(dlg); + PCB_DAD_ENUM(dlg, pcb_lb_comp); /* coposite */ + w->comp = PCB_DAD_CURRENT(dlg); + PCB_DAD_ENUM(dlg, pcb_lb_types); /* lyt */ + w->type = PCB_DAD_CURRENT(dlg); + PCB_DAD_END(dlg); + PCB_DAD_BEGIN_HBOX(dlg); + PCB_DAD_INTEGER(dlg, NULL); + PCB_DAD_MINVAL(dlg, 0); + PCB_DAD_MAXVAL(dlg, num_copper); + w->offs = PCB_DAD_CURRENT(dlg); + PCB_DAD_LABEL(dlg, "from"); + w->from = PCB_DAD_CURRENT(dlg); + PCB_DAD_ENUM(dlg, pcb_lb_side); + w->side = PCB_DAD_CURRENT(dlg); + PCB_DAD_END(dlg); + PCB_DAD_BEGIN_HBOX(dlg); + PCB_DAD_LABEL(dlg, "Purpose:"); + PCB_DAD_STRING(dlg); + w->purpose = PCB_DAD_CURRENT(dlg); + PCB_DAD_END(dlg); + + PCB_DAD_END(dlg); + + /* right side */ + PCB_DAD_BEGIN_HBOX(dlg); + PCB_DAD_LABELF(dlg, ("\n\n layer #%d ", n)); + PCB_DAD_BEGIN_VBOX(dlg); + if (n == 0) + PCB_DAD_LABEL(dlg, "BOARD LAYER"); + else + PCB_DAD_LABEL(dlg, "\n\n"); + PCB_DAD_LABEL(dlg, "Automatic"); + PCB_DAD_ENUM(dlg, ctx.layer_names); + w->layer = PCB_DAD_CURRENT(dlg); + PCB_DAD_END(dlg); + PCB_DAD_END(dlg); + } + PCB_DAD_END(dlg); + PCB_DAD_BUTTON_CLOSES(dlg, clbtn); + PCB_DAD_END(dlg); + + ctx.attrs = dlg; + + PCB_DAD_DEFSIZE(dlg, 500, 500); + PCB_DAD_NEW("layer_binding", dlg, "Layer bindings", &ctx, pcb_true, NULL); + val.func = lb_attr_chg; + pcb_gui->attr_dlg_property(dlg_hid_ctx, PCB_HATP_GLOBAL_CALLBACK, &val); + lb_data2dialog(dlg_hid_ctx, &ctx); + + PCB_DAD_RUN(dlg); + + PCB_DAD_FREE(dlg); + free(ctx.widx); + free(ctx.layer_names); + } + + PCB_ACT_IRES(0); + return 0; +} Index: tags/2.1.2/src_plugins/dialogs/dlg_layer_binding.h =================================================================== --- tags/2.1.2/src_plugins/dialogs/dlg_layer_binding.h (nonexistent) +++ tags/2.1.2/src_plugins/dialogs/dlg_layer_binding.h (revision 24813) @@ -0,0 +1,15 @@ +#ifndef PCB_DLG_LAYRE_BINDING_H +#define PCB_DLG_LAYRE_BINDING_H + +extern const char pcb_acts_LayerBinding[]; +extern const char pcb_acth_LayerBinding[]; +fgw_error_t pcb_act_LayerBinding(fgw_arg_t *res, int argc, fgw_arg_t *argv); + +extern const char *pcb_lb_comp[]; +extern const char *pcb_lb_types[]; +extern const char *pcb_lb_side[]; + +int pcb_ly_type2enum(pcb_layer_type_t type); +void pcb_get_ly_type_(int combo_type, pcb_layer_type_t *type); + +#endif Index: tags/2.1.2/src_plugins/dialogs/dlg_layer_flags.c =================================================================== --- tags/2.1.2/src_plugins/dialogs/dlg_layer_flags.c (nonexistent) +++ tags/2.1.2/src_plugins/dialogs/dlg_layer_flags.c (revision 24813) @@ -0,0 +1,220 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2018,2019 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "config.h" +#include "board.h" +#include "actions.h" +#include "event.h" +#include "hid_dad.h" +#include "dlg_layer_binding.h" +#include "dlg_layer_flags.h" + +const char pcb_acts_LayerPropGui[] = "LayerPropGui(layerid)"; +const char pcb_acth_LayerPropGui[] = "Change layer flags and properties"; +fgw_error_t pcb_act_LayerPropGui(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + PCB_DAD_DECL(dlg) + pcb_hid_dad_buttons_t clbtn[] = {{"Cancel", 0}, {"OK", 1}, {NULL, 0}}; + int wname, wsub, wauto, ok, ar = 0; + pcb_layer_t *ly; + pcb_layer_id_t lid; + + + PCB_ACT_MAY_CONVARG(1, FGW_LONG, LayerPropGui, lid = argv[1].val.nat_long); + ly = pcb_get_layer(PCB->Data, lid); + + PCB_DAD_BEGIN_VBOX(dlg); + PCB_DAD_BEGIN_TABLE(dlg, 2); + PCB_DAD_LABEL(dlg, "name"); + PCB_DAD_STRING(dlg); + PCB_DAD_HELP(dlg, "logical layer name"); + wname = PCB_DAD_CURRENT(dlg); + PCB_DAD_LABEL(dlg, "sub"); + PCB_DAD_BOOL(dlg, ""); + PCB_DAD_HELP(dlg, "Layer is drawn negatively in composition\n(will not work on copper)"); + wsub = PCB_DAD_CURRENT(dlg); + PCB_DAD_LABEL(dlg, "auto"); + PCB_DAD_BOOL(dlg, ""); + PCB_DAD_HELP(dlg, "Layer is target for autogenerated objects\nand side effects, e.g. padstack shapes"); + wauto = PCB_DAD_CURRENT(dlg); + PCB_DAD_END(dlg); + PCB_DAD_BUTTON_CLOSES(dlg, clbtn); + PCB_DAD_END(dlg); + + + dlg[wname].default_val.str_value = pcb_strdup(ly->name); + dlg[wsub].default_val.int_value = ly->comb & PCB_LYC_SUB; + dlg[wauto].default_val.int_value = ly->comb & PCB_LYC_AUTO; + + PCB_DAD_AUTORUN("layer_prop", dlg, "Properties of a logical layer", NULL, ok); + + if (ok) { + pcb_layer_combining_t comb = 0; + if (strcmp(ly->name, dlg[wname].default_val.str_value) != 0) { + ar |= pcb_layer_rename_(ly, (char *)dlg[wname].default_val.str_value); + pcb_board_set_changed_flag(pcb_true); + } + if (dlg[wsub].default_val.int_value) comb |= PCB_LYC_SUB; + if (dlg[wauto].default_val.int_value) comb |= PCB_LYC_AUTO; + if (ly->comb != comb) { + ly->comb = comb; + pcb_board_set_changed_flag(pcb_true); + } + } + else + ar = 1; + PCB_DAD_FREE(dlg); + + PCB_ACT_IRES(ar); + return 0; +} + +const char pcb_acts_GroupPropGui[] = "GroupPropGui(groupid)"; +const char pcb_acth_GroupPropGui[] = "Change group flags and properties"; +fgw_error_t pcb_act_GroupPropGui(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + PCB_DAD_DECL(dlg) + pcb_hid_dad_buttons_t clbtn[] = {{"Cancel", 0}, {"OK", 1}, {NULL, 0}}; + int wname, wtype, wpurp, wloc; + int ok, n, ar = 0, orig_type, changed = 0, omit_loc = 0, orig_loc = -1, def_loc; + pcb_layergrp_id_t gid; + pcb_layergrp_t *g; + static const char *ltypes[] = { "top", "bottom", "any intern", "global", NULL }; + pcb_layer_type_t ltype_bits[] = { PCB_LYT_TOP, PCB_LYT_BOTTOM, PCB_LYT_INTERN, 0 }; +#define LOC_TYPES (PCB_LYT_DOC) + + PCB_ACT_MAY_CONVARG(1, FGW_LONG, GroupPropGui, gid = argv[1].val.nat_long); + g = pcb_get_layergrp(PCB, gid); + + if (g->ltype & LOC_TYPES) { + for(n = 0; ltype_bits[n] != 0; n++) + if (g->ltype & ltype_bits[n]) + def_loc = n; + } + else + omit_loc = 1; + + PCB_DAD_BEGIN_VBOX(dlg); + PCB_DAD_BEGIN_TABLE(dlg, 2); + PCB_DAD_LABEL(dlg, "name"); + PCB_DAD_STRING(dlg); + PCB_DAD_HELP(dlg, "group name"); + wname = PCB_DAD_CURRENT(dlg); + PCB_DAD_LABEL(dlg, "type"); + PCB_DAD_ENUM(dlg, pcb_lb_types); + PCB_DAD_HELP(dlg, "type/material of the group"); + wtype = PCB_DAD_CURRENT(dlg); + if (!omit_loc) { + PCB_DAD_LABEL(dlg, "location"); + PCB_DAD_ENUM(dlg, ltypes); + PCB_DAD_HELP(dlg, "location of the group in the stack"); + wloc = PCB_DAD_CURRENT(dlg); + } + PCB_DAD_LABEL(dlg, "purpose"); + PCB_DAD_STRING(dlg); + PCB_DAD_HELP(dlg, "purpose"); + wpurp = PCB_DAD_CURRENT(dlg); + PCB_DAD_HELP(dlg, "subtype of the layer\nmeaning depends on the main type"); + PCB_DAD_END(dlg); + PCB_DAD_BUTTON_CLOSES(dlg, clbtn); + PCB_DAD_END(dlg); + + + dlg[wname].default_val.str_value = pcb_strdup(g->name); + dlg[wtype].default_val.int_value = orig_type = pcb_ly_type2enum(g->ltype); + dlg[wpurp].default_val.str_value = pcb_strdup(g->purpose == NULL ? "" : g->purpose); + if (!omit_loc) + dlg[wloc].default_val.int_value = def_loc; + + if (!omit_loc) { + pcb_layer_type_t loc = g->ltype & PCB_LYT_ANYWHERE; + dlg[wloc].default_val.int_value = 3; + if (loc != 0) { + for(n = 0; ltypes[n] != NULL; n++) { + if ((loc & ltype_bits[n]) == loc) { + dlg[wloc].default_val.int_value = n; + break; + } + } + } + orig_loc = dlg[wloc].default_val.int_value; + } + + PCB_DAD_AUTORUN("layer_grp_prop", dlg, "Edit the properties of a layer group (physical layer)", NULL, ok); + if (ok) { + if (strcmp(g->name, dlg[wname].default_val.str_value) != 0) { + ar |= pcb_layergrp_rename_(g, (char *)dlg[wname].default_val.str_value); + dlg[wname].default_val.str_value = NULL; + pcb_board_set_changed_flag(pcb_true); + } + + if (dlg[wtype].default_val.int_value != orig_type) { + pcb_layer_type_t lyt = 0; + pcb_get_ly_type_(dlg[wtype].default_val.int_value, &lyt); + g->ltype &= ~PCB_LYT_ANYTHING; + g->ltype |= lyt; + changed = 1; + } + + if ((!omit_loc) && (dlg[wloc].default_val.int_value != orig_loc)) { + if (PCB_LAYER_SIDED(g->ltype)) { + g->ltype &= ~PCB_LYT_ANYWHERE; + if (dlg[wloc].default_val.int_value >= 0) + g->ltype |= ltype_bits[dlg[wloc].default_val.int_value]; + changed = 1; + } + else + pcb_message(PCB_MSG_ERROR, "Ignoring location - for this layer group type it is determined by the stackup\n"); + } + + if (dlg[wpurp].default_val.str_value == NULL) { + if (g->purpose != NULL) { + pcb_layergrp_set_purpose__(g, NULL); + changed = 1; + } + } + else if ((g->purpose == NULL) || (strcmp(g->purpose, dlg[wpurp].default_val.str_value) != 0)) { + if (*dlg[wpurp].default_val.str_value == '\0') + pcb_layergrp_set_purpose__(g, NULL); + else + pcb_layergrp_set_purpose__(g, pcb_strdup(dlg[wpurp].default_val.str_value)); + changed = 1; + } + + if (changed) { + pcb_board_set_changed_flag(pcb_true); + pcb_event(PCB_EVENT_LAYERS_CHANGED, NULL); + } + } + else + ar = 1; + + PCB_DAD_FREE(dlg); + + PCB_ACT_IRES(ar); + return 0; +} +#undef LOC_TYPES Index: tags/2.1.2/src_plugins/dialogs/dlg_layer_flags.h =================================================================== --- tags/2.1.2/src_plugins/dialogs/dlg_layer_flags.h (nonexistent) +++ tags/2.1.2/src_plugins/dialogs/dlg_layer_flags.h (revision 24813) @@ -0,0 +1,6 @@ +extern const char pcb_acts_LayerPropGui[]; +extern const char pcb_acth_LayerPropGui[]; +fgw_error_t pcb_act_LayerPropGui(fgw_arg_t *res, int argc, fgw_arg_t *argv); +extern const char pcb_acts_GroupPropGui[]; +extern const char pcb_acth_GroupPropGui[]; +fgw_error_t pcb_act_GroupPropGui(fgw_arg_t *res, int argc, fgw_arg_t *argv); Index: tags/2.1.2/src_plugins/dialogs/dlg_lib_pstk.c =================================================================== --- tags/2.1.2/src_plugins/dialogs/dlg_lib_pstk.c (nonexistent) +++ tags/2.1.2/src_plugins/dialogs/dlg_lib_pstk.c (revision 24813) @@ -0,0 +1,669 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2018 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +/* Padstack library dialog */ + +#include "config.h" +#include "actions.h" +#include "data.h" +#include "obj_subc.h" +#include "vtpadstack.h" +#include "hid_inlines.h" +#include "hid_dad.h" +#include "hid_dad_tree.h" +#include "obj_pstk.h" +#include "obj_pstk_inlines.h" +#include "obj_text_draw.h" +#include "obj_pstk_draw.h" +#include "undo_old.h" +#include "select.h" +#include "search.h" +#include "dlg_padstack.h" +#include "dlg_lib_pstk.h" + +htip_t pstk_libs; /* id -> pstk_lib_ctx_t */ + +typedef struct pstk_lib_ctx_s { + PCB_DAD_DECL_NOINIT(dlg) + pcb_board_t *pcb; + int wlist, wprev, wgrid; + int wlayerv[pcb_proto_num_layers], wlayerc[pcb_proto_num_layers]; /* layer visibility/current */ + long subc_id; + pcb_cardinal_t proto_id; + pcb_cardinal_t *stat; /* temporary usage stat */ + pcb_box_t drawbox; + pcb_bool modal; +} pstk_lib_ctx_t; + +static pcb_cardinal_t pstklib_last_proto_id; /* set on close to preserve the id after free'ing the context; useful only for modal windows because of blocking calls */ + +static pcb_data_t *get_data(pstk_lib_ctx_t *ctx, long id, pcb_subc_t **sc_out) +{ + int type; + void *r1, *r2, *r3; + pcb_subc_t *sc; + + if (id < 0) + return ctx->pcb->Data; + + type = pcb_search_obj_by_id_(ctx->pcb->Data, &r1, &r2, &r3, id, PCB_OBJ_SUBC); + if (type != PCB_OBJ_SUBC) + return NULL; + + sc = r2; + + if (sc_out != NULL) + *sc_out = sc; + + return sc->data; +} + +static int pstklib_data2dlg(pstk_lib_ctx_t *ctx) +{ + pcb_pstk_proto_t *proto; + pcb_data_t *data = get_data(ctx, ctx->subc_id, NULL); + pcb_hid_attribute_t *attr; + pcb_hid_tree_t *tree; + pcb_hid_row_t *r; + char *cell[4], *cursor_path = NULL; + long id; + + if (data == NULL) + return -1; + + attr = &ctx->dlg[ctx->wlist]; + tree = (pcb_hid_tree_t *)attr->enumerations; + + /* remember cursor */ + r = pcb_dad_tree_get_selected(attr); + if (r != NULL) + cursor_path = pcb_strdup(r->cell[0]); + + /* remove existing items */ + pcb_dad_tree_clear(tree); + + /* add all items */ + cell[3] = NULL; + for(id = 0, proto = data->ps_protos.array; id < pcb_vtpadstack_proto_len(&data->ps_protos); proto++,id++) { + if (!proto->in_use) + continue; + cell[0] = pcb_strdup_printf("%ld", id); + cell[1] = pcb_strdup(proto->name == NULL ? "" : proto->name); + if (ctx->stat != NULL) + cell[2] = pcb_strdup_printf("%d", ctx->stat[id]); + else + cell[2] = pcb_strdup(""); + pcb_dad_tree_append(attr, NULL, cell); + } + + /* restore cursor */ + if (cursor_path != NULL) { + pcb_hid_attr_val_t hv; + hv.str_value = cursor_path; + pcb_gui->attr_dlg_set_value(ctx->dlg_hid_ctx, ctx->wlist, &hv); + free(cursor_path); + } + return 0; +} + +static void pstklib_close_cb(void *caller_data, pcb_hid_attr_ev_t ev) +{ + pstk_lib_ctx_t *ctx = caller_data; + + if (!ctx->modal) + htip_pop(&pstk_libs, ctx->subc_id); + pstklib_last_proto_id = ctx->proto_id; + PCB_DAD_FREE(ctx->dlg); + free(ctx); +} + +static void pstklib_setps(pcb_pstk_t *ps, pcb_data_t *data, pcb_cardinal_t proto_id) +{ + memset(ps, 0, sizeof(pcb_pstk_t)); + ps->parent_type = PCB_PARENT_DATA; + ps->parent.data = data; + ps->proto = proto_id; + ps->ID = -1; /* disable undo and clipping */ +} + +static void pstklib_expose(pcb_hid_attribute_t *attrib, pcb_hid_preview_t *prv, pcb_hid_gc_t gc, const pcb_hid_expose_ctx_t *e) +{ + pstk_lib_ctx_t *ctx = prv->user_ctx; + pcb_data_t *data = get_data(ctx, ctx->subc_id, NULL); + pcb_pstk_t ps; + char layers[pcb_proto_num_layers]; + int n; + pcb_coord_t x1, y1, x2, y2, x, y, grid; + + if (data == NULL) { + return; + } + + if (ctx->proto_id == PCB_PADSTACK_INVALID) + return; + + pstklib_setps(&ps, data, ctx->proto_id); + + /* draw the shapes */ + for(n = 0; n < pcb_proto_num_layers; n++) + layers[n] = !!ctx->dlg[ctx->wlayerv[n]].default_val.int_value + !!ctx->dlg[ctx->wlayerc[n]].default_val.int_value; + + pcb_pstk_draw_preview(PCB, &ps, layers, 0, 0, &e->view); + + pcb_gui->set_color(gc, pcb_color_black); + pcb_hid_set_line_cap(gc, pcb_cap_round); + pcb_hid_set_line_width(gc, -1); + + x1 = ctx->drawbox.X1; + y1 = ctx->drawbox.Y1; + x2 = ctx->drawbox.X2; + y2 = ctx->drawbox.Y2; + + grid = ctx->dlg[ctx->wgrid].default_val.coord_value; + for(x = 0; x < x2; x += grid) + pcb_gui->draw_line(gc, x, y1, x, y2); + for(x = -grid; x > x1; x -= grid) + pcb_gui->draw_line(gc, x, y1, x, y2); + for(y = 0; y < y2; y += grid) + pcb_gui->draw_line(gc, x1, y, x2, y); + for(y = -grid; y > y1; y -= grid) + pcb_gui->draw_line(gc, x1, y, x2, y); + + /* draw the mark only */ + for(n = 0; n < pcb_proto_num_layers; n++) + layers[n] = 0; + pcb_pstk_draw_preview(PCB, &ps, layers, 1, 0, &e->view); +} + +static void pstklib_force_redraw(pstk_lib_ctx_t *ctx, pcb_pstk_t *ps) +{ + pcb_pstk_proto_t *proto = pcb_pstk_get_proto(ps); + + if (proto == NULL) + return; + + pcb_pstk_bbox(ps); + ps->BoundingBox.X1 -= PCB_MM_TO_COORD(0.5); + ps->BoundingBox.Y1 -= PCB_MM_TO_COORD(0.5); + ps->BoundingBox.X2 += PCB_MM_TO_COORD(0.5); + ps->BoundingBox.Y2 += PCB_MM_TO_COORD(0.5); + memcpy(&ctx->drawbox, &ps->BoundingBox, sizeof(pcb_box_t)); + pcb_dad_preview_zoomto(&ctx->dlg[ctx->wprev], &ctx->drawbox); +} + +static void pstklib_select(pcb_hid_attribute_t *attrib, void *hid_ctx, pcb_hid_row_t *row) +{ + pcb_hid_attr_val_t hv; + pcb_hid_tree_t *tree = (pcb_hid_tree_t *)attrib->enumerations; + pstk_lib_ctx_t *ctx = tree->user_ctx; + pcb_data_t *data = get_data(ctx, ctx->subc_id, NULL); + pcb_pstk_t ps; + + if ((row != NULL) && (data != NULL)) { + ctx->proto_id = strtol(row->cell[0], NULL, 10); + pstklib_setps(&ps, data, ctx->proto_id); + pstklib_force_redraw(ctx, &ps); + } + else + ctx->proto_id = PCB_PADSTACK_INVALID; + + hv.str_value = NULL; + pcb_gui->attr_dlg_set_value(ctx->dlg_hid_ctx, ctx->wprev, &hv); +} + +static void pstklib_update_prv(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + pstk_lib_ctx_t *ctx = caller_data; + pcb_dad_preview_zoomto(&ctx->dlg[ctx->wprev], &ctx->drawbox); +} + +static void pstklib_update_layerc(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + pstk_lib_ctx_t *ctx = caller_data; + int n, idx = -1, widx = attr - ctx->dlg; + pcb_hid_attr_val_t hv; + + for(n = 0; n < pcb_proto_num_layers; n++) { + if (ctx->wlayerc[n] == widx) { + hv.int_value = 1; + idx = n; + pcb_gui->attr_dlg_set_value(ctx->dlg_hid_ctx, ctx->wlayerv[n], &hv); /* current must be visible as well */ + } + else + hv.int_value = 0; + pcb_gui->attr_dlg_set_value(ctx->dlg_hid_ctx, ctx->wlayerc[n], &hv); + } + if (idx < 0) + return; + + pstklib_update_prv(hid_ctx, caller_data, attr); +} + + +static void pstklib_filter_cb(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr_inp) +{ + pstk_lib_ctx_t *ctx = caller_data; + pcb_data_t *data = get_data(ctx, ctx->subc_id, NULL); + pcb_hid_attribute_t *attr; + pcb_hid_tree_t *tree; + pcb_hid_row_t *r; + const char *text; + + if (data == NULL) + return; + + attr = &ctx->dlg[ctx->wlist]; + tree = (pcb_hid_tree_t *)attr->enumerations; + text = attr_inp->default_val.str_value; + + if ((text == NULL) || (*text == '\0')) { + for(r = gdl_first(&tree->rows); r != NULL; r = gdl_next(&tree->rows, r)) + r->hide = 0; + } + else { + for(r = gdl_first(&tree->rows); r != NULL; r = gdl_next(&tree->rows, r)) + r->hide = (strstr(r->cell[1], text) == NULL); + } + + pcb_dad_tree_update_hide(attr); +} + + +static void pstklib_proto_edit_change_cb(pse_t *pse) +{ + pstklib_force_redraw(pse->user_data, pse->ps); +} + +static void pstklib_proto_edit_common(pstk_lib_ctx_t *ctx, pcb_data_t *data, pcb_cardinal_t proto_id, int tab) +{ + pcb_pstk_t ps; + pse_t pse; + + pstklib_setps(&ps, data, proto_id); + memset(&pse, 0, sizeof(pse)); + pse.pcb = ctx->pcb; + pse.data = data; + pse.ps = &ps; + pse.disable_instance_tab = 1; + pse.user_data = ctx; + pse.change_cb = pstklib_proto_edit_change_cb; + pse.gen_shape_in_place = 1; + + pcb_pstkedit_dialog(&pse, tab); +} + + +static void pstklib_proto_edit(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + pstk_lib_ctx_t *ctx = caller_data; + pcb_data_t *data = get_data(ctx, ctx->subc_id, NULL); + pcb_hid_row_t *row = pcb_dad_tree_get_selected(&ctx->dlg[ctx->wlist]); + + if ((row == NULL) || (data == NULL)) + return; + + pstklib_proto_edit_common(ctx, data, strtol(row->cell[0], NULL, 10), 1); +} + +static void pstklib_proto_new_(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr, int dup) +{ + pstk_lib_ctx_t *ctx = caller_data; + pcb_data_t *data = get_data(ctx, ctx->subc_id, NULL); + pcb_pstk_proto_t proto_, *proto; + pcb_hid_attr_val_t hv; + char tmp[64]; + int tab; + + if (data == NULL) + return; + + if (dup) { + pcb_hid_row_t *row = pcb_dad_tree_get_selected(&ctx->dlg[ctx->wlist]); + if (row == NULL) + return; + proto = pcb_pstk_get_proto_(data, strtol(row->cell[0], NULL, 10)); + ctx->proto_id = pcb_pstk_proto_insert_forcedup(data, proto, 0); + tab = 1; + } + else { + memset(&proto_, 0, sizeof(proto_)); + pcb_pstk_proto_update(&proto_); + proto = &proto_; + ctx->proto_id = pcb_pstk_proto_insert_dup(data, proto, 1); + tab = 2; + } + + /* make sure the new item appears in the list and is selected */ + pstklib_data2dlg(ctx); + sprintf(tmp, "%u", ctx->proto_id); + hv.str_value = tmp; + pcb_gui->attr_dlg_set_value(ctx->dlg_hid_ctx, ctx->wlist, &hv); + + pstklib_proto_edit_common(ctx, data, ctx->proto_id, tab); +} + +static void pstklib_proto_new(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + pstklib_proto_new_(hid_ctx, caller_data, attr, 0); +} + +static void pstklib_proto_dup(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + pstklib_proto_new_(hid_ctx, caller_data, attr, 1); +} + +static void pstklib_proto_switch(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr_btn) +{ + pstk_lib_ctx_t *ctx = caller_data; + pcb_data_t *data = get_data(ctx, ctx->subc_id, NULL); + pcb_hid_attribute_t *attr; + pcb_hid_row_t *r; + pcb_cardinal_t from_pid, to_pid; + pcb_pstk_t *ps; + + if (data == NULL) + return; + + attr = &ctx->dlg[ctx->wlist]; + r = pcb_dad_tree_get_selected(attr); + if (r == NULL) + return; + + from_pid = strtol(r->cell[0], NULL, 10); + to_pid = pcb_dlg_pstklib(ctx->pcb, ctx->subc_id, pcb_true, "Select a prototype to switch to"); + if ((to_pid == PCB_PADSTACK_INVALID) || (to_pid == from_pid)) + return; + + for(ps = padstacklist_first(&data->padstack); ps != NULL; ps = padstacklist_next(ps)) { + if (ps->proto == from_pid) + pcb_pstk_change_instance(ps, &to_pid, NULL, NULL, NULL, NULL); + } + + pcb_gui->invalidate_all(); +} + + +static void pstklib_proto_select(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr_btn) +{ + pstk_lib_ctx_t *ctx = caller_data; + pcb_data_t *data = get_data(ctx, ctx->subc_id, NULL); + pcb_hid_attribute_t *attr; + pcb_hid_row_t *r; + long pid; + pcb_box_t box; + int changed = 0; + pcb_pstk_t *ps; + + if (data == NULL) + return; + + attr = &ctx->dlg[ctx->wlist]; + r = pcb_dad_tree_get_selected(attr); + if (r == NULL) + return; + + pid = strtol(r->cell[0], NULL, 10); + + /* unselect all */ + box.X1 = -PCB_MAX_COORD; + box.Y1 = -PCB_MAX_COORD; + box.X2 = PCB_MAX_COORD; + box.Y2 = PCB_MAX_COORD; + if (pcb_select_block(PCB, &box, pcb_false, pcb_false, pcb_false)) + changed = 1; + + for(ps = padstacklist_first(&data->padstack); ps != NULL; ps = padstacklist_next(ps)) { + if (ps->proto == pid) { + changed = 1; + pcb_undo_add_obj_to_flag(ps); + PCB_FLAG_TOGGLE(PCB_FLAG_SELECTED, ps); + } + } + + if (changed) { + pcb_board_set_changed_flag(pcb_true); + pcb_gui->invalidate_all(); + } +} + +static void pstklib_count_uses(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + pcb_cardinal_t len; + pstk_lib_ctx_t *ctx = caller_data; + pcb_data_t *data = get_data(ctx, ctx->subc_id, NULL); + + if (data == NULL) + return; + + ctx->stat = pcb_pstk_proto_used_all(data, &len); + pstklib_data2dlg(ctx); + free(ctx->stat); + ctx->stat = NULL; +} + +static void pstklib_del_unused(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + pcb_cardinal_t len, n; + pstk_lib_ctx_t *ctx = caller_data; + pcb_data_t *data = get_data(ctx, ctx->subc_id, NULL); + + if (data == NULL) + return; + + ctx->stat = pcb_pstk_proto_used_all(data, &len); + for(n = 0; n < len; n++) { + if (ctx->stat[n] == 0) + pcb_pstk_proto_del(data, n); + } + pstklib_data2dlg(ctx); + free(ctx->stat); + ctx->stat = NULL; +} + +pcb_cardinal_t pcb_dlg_pstklib(pcb_board_t *pcb, long subc_id, pcb_bool modal, const char *hint) +{ + static const char *hdr[] = {"ID", "name", "used", NULL}; + pcb_subc_t *sc; + pcb_data_t *data; + pstk_lib_ctx_t *ctx; + int n; + char *name; + pcb_hid_dad_buttons_t clbtn[] = {{"Close", 0}, {NULL, 0}}; + pcb_hid_dad_buttons_t clbtn_modal[] = {{"Cancel", -1}, {"Use selected", 0}, {NULL, 0}}; + + if (subc_id <= 0) + subc_id = -1; + + if ((!modal) && (htip_get(&pstk_libs, subc_id) != NULL)) + return 0; /* already open - have only one per id */ + + ctx = calloc(sizeof(pstk_lib_ctx_t), 1); + ctx->pcb = pcb; + ctx->subc_id = subc_id; + ctx->proto_id = PCB_PADSTACK_INVALID; + ctx->modal = modal; + + data = get_data(ctx, subc_id, &sc); + if (data == NULL) { + free(ctx); + return PCB_PADSTACK_INVALID; + } + + if (!modal) + htip_set(&pstk_libs, subc_id, ctx); + + PCB_DAD_BEGIN_VBOX(ctx->dlg); + PCB_DAD_COMPFLAG(ctx->dlg, PCB_HATF_EXPFILL); + if (hint != NULL) + PCB_DAD_LABEL(ctx->dlg, hint); + + /* create the dialog box */ + PCB_DAD_BEGIN_HPANE(ctx->dlg); + /* left */ + PCB_DAD_BEGIN_VBOX(ctx->dlg); + PCB_DAD_COMPFLAG(ctx->dlg, PCB_HATF_EXPFILL); + PCB_DAD_TREE(ctx->dlg, 3, 0, hdr); + PCB_DAD_COMPFLAG(ctx->dlg, PCB_HATF_EXPFILL); + PCB_DAD_TREE_SET_CB(ctx->dlg, selected_cb, pstklib_select); + PCB_DAD_TREE_SET_CB(ctx->dlg, ctx, ctx); + ctx->wlist = PCB_DAD_CURRENT(ctx->dlg); + PCB_DAD_STRING(ctx->dlg); + PCB_DAD_HELP(ctx->dlg, "Filter text:\nlist padstacks with matching name only"); + PCB_DAD_CHANGE_CB(ctx->dlg, pstklib_filter_cb); + PCB_DAD_BEGIN_HBOX(ctx->dlg); + PCB_DAD_BUTTON(ctx->dlg, "Edit..."); + PCB_DAD_HELP(ctx->dlg, "Edit the selected prototype\nusing the padstack editor"); + PCB_DAD_CHANGE_CB(ctx->dlg, pstklib_proto_edit); + PCB_DAD_BUTTON(ctx->dlg, "New..."); + PCB_DAD_HELP(ctx->dlg, "Create a new prototype and edit it\nusing the padstack editor"); + PCB_DAD_CHANGE_CB(ctx->dlg, pstklib_proto_new); + PCB_DAD_BUTTON(ctx->dlg, "Switch"); + PCB_DAD_HELP(ctx->dlg, "Find all padstacks using this prototype\nand modify them to use a different prototype\nmaking this prototype unused"); + PCB_DAD_CHANGE_CB(ctx->dlg, pstklib_proto_switch); + PCB_DAD_BUTTON(ctx->dlg, "Select"); + PCB_DAD_HELP(ctx->dlg, "Select all padstack ref. objects that\nreference (use) this prototype"); + PCB_DAD_CHANGE_CB(ctx->dlg, pstklib_proto_select); + PCB_DAD_END(ctx->dlg); + PCB_DAD_BEGIN_HBOX(ctx->dlg); + PCB_DAD_BUTTON(ctx->dlg, "Dup..."); + PCB_DAD_HELP(ctx->dlg, "Create a new prototype by duplicating\nthe currently selected on and\n edit it using the padstack editor"); + PCB_DAD_CHANGE_CB(ctx->dlg, pstklib_proto_dup); + PCB_DAD_BUTTON(ctx->dlg, "Count uses"); + PCB_DAD_HELP(ctx->dlg, "Count how many times each prototype\nis used and update the \"used\"\ncolumn of the table"); + PCB_DAD_CHANGE_CB(ctx->dlg, pstklib_count_uses); + PCB_DAD_BUTTON(ctx->dlg, "Del unused"); + PCB_DAD_HELP(ctx->dlg, "Update prototype usage stats and\nremove prototypes that are not\nused by any padstack"); + PCB_DAD_CHANGE_CB(ctx->dlg, pstklib_del_unused); + PCB_DAD_END(ctx->dlg); + PCB_DAD_END(ctx->dlg); + + /* right */ + PCB_DAD_BEGIN_VBOX(ctx->dlg); + PCB_DAD_COMPFLAG(ctx->dlg, PCB_HATF_EXPFILL); + PCB_DAD_PREVIEW(ctx->dlg, pstklib_expose, NULL, NULL, NULL, 200, 200, ctx); + PCB_DAD_COMPFLAG(ctx->dlg, PCB_HATF_EXPFILL); + ctx->wprev = PCB_DAD_CURRENT(ctx->dlg); + + PCB_DAD_BEGIN_TABLE(ctx->dlg, 2); + PCB_DAD_LABEL(ctx->dlg, "Grid:"); + PCB_DAD_COORD(ctx->dlg, ""); + ctx->wgrid = PCB_DAD_CURRENT(ctx->dlg); + PCB_DAD_MINMAX(ctx->dlg, PCB_MM_TO_COORD(0.01), PCB_MM_TO_COORD(10)); + PCB_DAD_DEFAULT_NUM(ctx->dlg, (pcb_coord_t)PCB_MM_TO_COORD(1)); + PCB_DAD_CHANGE_CB(ctx->dlg, pstklib_update_prv); + + PCB_DAD_LABEL(ctx->dlg, ""); + PCB_DAD_BEGIN_HBOX(ctx->dlg); + PCB_DAD_LABEL(ctx->dlg, "Vis"); + PCB_DAD_HELP(ctx->dlg, "layer is visible"); + PCB_DAD_LABEL(ctx->dlg, "Curr"); + PCB_DAD_HELP(ctx->dlg, "layer is set to current/primary\nfor display (color emphasis)"); + PCB_DAD_END(ctx->dlg); + for(n = 0; n < pcb_proto_num_layers; n++) { + PCB_DAD_LABEL(ctx->dlg, pcb_proto_layers[n].name); + PCB_DAD_BEGIN_HBOX(ctx->dlg); + PCB_DAD_BOOL(ctx->dlg, ""); + PCB_DAD_DEFAULT_NUM(ctx->dlg, 1); + PCB_DAD_CHANGE_CB(ctx->dlg, pstklib_update_prv); + ctx->wlayerv[n] = PCB_DAD_CURRENT(ctx->dlg); + PCB_DAD_BOOL(ctx->dlg, ""); + PCB_DAD_DEFAULT_NUM(ctx->dlg, (pcb_proto_layers[n].mask == (PCB_LYT_TOP | PCB_LYT_COPPER))); + PCB_DAD_CHANGE_CB(ctx->dlg, pstklib_update_layerc); + ctx->wlayerc[n] = PCB_DAD_CURRENT(ctx->dlg); + PCB_DAD_END(ctx->dlg); + } + PCB_DAD_END(ctx->dlg); + PCB_DAD_END(ctx->dlg); + PCB_DAD_END(ctx->dlg); + + PCB_DAD_BUTTON_CLOSES(ctx->dlg, (modal ? clbtn_modal : clbtn)); + PCB_DAD_END(ctx->dlg); + + if (subc_id > 0) { + if (sc->refdes != NULL) + name = pcb_strdup_printf("pcb-rnd padstacks - subcircuit #%ld (%s)", subc_id, sc->refdes); + else + name = pcb_strdup_printf("pcb-rnd padstacks - subcircuit #%ld", subc_id); + } + else + name = pcb_strdup("pcb-rnd padstacks - board"); + + PCB_DAD_NEW("pstk_lib", ctx->dlg, name, ctx, modal, pstklib_close_cb); + + pstklib_data2dlg(ctx); + free(name); + + if (modal) { + if (PCB_DAD_RUN(ctx->dlg) != 0) + return PCB_PADSTACK_INVALID; + return pstklib_last_proto_id; + } + + return 0; +} + +const char pcb_acts_pstklib[] = "pstklib([board|subcid|object])\n"; +const char pcb_acth_pstklib[] = "Present the padstack library dialog on board padstacks or the padstacks of a subcircuit"; +fgw_error_t pcb_act_pstklib(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + long id = -1; + const char *cmd = NULL; + PCB_ACT_MAY_CONVARG(1, FGW_STR, pstklib, cmd = argv[1].val.str); + if ((cmd != NULL) && (strcmp(cmd, "object") == 0)) { + pcb_coord_t x, y; + void *r1, *r2, *r3; + pcb_subc_t *sc; + int type; + pcb_hid_get_coords("Pick a subcircuit for padstack lib editing", &x, &y, 0); + type = pcb_search_obj_by_location(PCB_OBJ_SUBC, &r1, &r2, &r3, x, y, PCB_SLOP * pcb_pixel_slop); + if (type != PCB_OBJ_SUBC) { + PCB_ACT_IRES(-1); + return 0; + } + sc = r2; + id = sc->ID; + } + else + PCB_ACT_MAY_CONVARG(1, FGW_LONG, pstklib, id = argv[1].val.nat_long); + if (pcb_dlg_pstklib(PCB, id, pcb_false, NULL) == PCB_PADSTACK_INVALID) + PCB_ACT_IRES(-1); + else + PCB_ACT_IRES(0); + return 0; +} + +void pcb_dlg_pstklib_init(void) +{ + htip_init(&pstk_libs, longhash, longkeyeq); +} + +void pcb_dlg_pstklib_uninit(void) +{ + htip_entry_t *e; + for(e = htip_first(&pstk_libs); e != NULL; e = htip_next(&pstk_libs, e)) + pstklib_close_cb(e->value, 0); + htip_uninit(&pstk_libs); +} Index: tags/2.1.2/src_plugins/dialogs/dlg_lib_pstk.h =================================================================== --- tags/2.1.2/src_plugins/dialogs/dlg_lib_pstk.h (nonexistent) +++ tags/2.1.2/src_plugins/dialogs/dlg_lib_pstk.h (revision 24813) @@ -0,0 +1,12 @@ +/* Open a padstack library dialog box for a subc (or for the board if subc_id + is 0). If modal, returns the selected prototype or PCB_PADSTACK_INVALID when + nothing is selected or the operation cancelled. In non-modal mode return + 0 on success and PCB_PADSTACK_INVALID on error. */ +pcb_cardinal_t pcb_dlg_pstklib(pcb_board_t *pcb, long subc_id, pcb_bool modal, const char *hint); + +extern const char pcb_acts_pstklib[]; +extern const char pcb_acth_pstklib[]; +fgw_error_t pcb_act_pstklib(fgw_arg_t *res, int argc, fgw_arg_t *argv); + +void pcb_dlg_pstklib_init(void); +void pcb_dlg_pstklib_uninit(void); Index: tags/2.1.2/src_plugins/dialogs/dlg_loadsave.c =================================================================== --- tags/2.1.2/src_plugins/dialogs/dlg_loadsave.c (nonexistent) +++ tags/2.1.2/src_plugins/dialogs/dlg_loadsave.c (revision 24813) @@ -0,0 +1,343 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2019 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "config.h" + +#include +#include "actions.h" +#include "board.h" +#include "data.h" +#include "event.h" +#include "hid_dad.h" +#include "compat_fs.h" +#include "conf_core.h" +#include "plug_io.h" + +#include "dlg_loadsave.h" + +extern fgw_error_t pcb_act_LoadFrom(fgw_arg_t *res, int argc, fgw_arg_t *argv); +extern fgw_error_t pcb_act_SaveTo(fgw_arg_t *res, int argc, fgw_arg_t *argv); + +static char *dup_cwd(void) +{ + char tmp[PCB_PATH_MAX + 1]; + return pcb_strdup(pcb_get_wd(tmp)); +} + +const char pcb_acts_Load[] = "Load()\n" "Load(Layout|LayoutToBuffer|ElementToBuffer|Netlist|Revert)"; +const char pcb_acth_Load[] = "Load layout data from a user-selected file."; +/* DOC: load.html */ +fgw_error_t pcb_act_Load(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + static char *last_footprint = NULL, *last_layout = NULL, *last_netlist = NULL; + const char *function = "Layout"; + char *name = NULL; + + if (last_footprint == NULL) last_footprint = dup_cwd(); + if (last_layout == NULL) last_layout = dup_cwd(); + if (last_netlist == NULL) last_netlist = dup_cwd(); + + /* Called with both function and file name -> no gui */ + if (argc > 2) + return PCB_ACT_CALL_C(pcb_act_LoadFrom, res, argc, argv); + + PCB_ACT_MAY_CONVARG(1, FGW_STR, Load, function = argv[1].val.str); + + if (pcb_strcasecmp(function, "Netlist") == 0) + name = pcb_gui->fileselect("Load netlist file", "Import netlist from file", last_netlist, ".net", NULL, "netlist", PCB_HID_FSD_READ, NULL); + else if ((pcb_strcasecmp(function, "FootprintToBuffer") == 0) || (pcb_strcasecmp(function, "ElementToBuffer") == 0)) + name = pcb_gui->fileselect("Load footprint to buffer", "Import footprint from file", last_footprint, NULL, NULL, "footprint", PCB_HID_FSD_READ, NULL); + else if (pcb_strcasecmp(function, "LayoutToBuffer") == 0) + name = pcb_gui->fileselect("Load layout to buffer", "load layout (board) to buffer", last_layout, NULL, NULL, "board", PCB_HID_FSD_READ, NULL); + else if (pcb_strcasecmp(function, "Layout") == 0) + name = pcb_gui->fileselect("Load layout file", "load layout (board) as board to edit", last_layout, NULL, NULL, "board", PCB_HID_FSD_READ, NULL); + else { + pcb_message(PCB_MSG_ERROR, "Invalid subcommand for Load(): '%s'\n", function); + PCB_ACT_IRES(1); + return 0; + } + + if (name != NULL) { + if (conf_core.rc.verbose) + fprintf(stderr, "Load: Calling LoadFrom(%s, %s)\n", function, name); + pcb_actionl("LoadFrom", function, name, NULL); + free(name); + } + + PCB_ACT_IRES(0); + return 0; +} + +/*** Save ***/ + +typedef struct { + pcb_hid_dad_subdialog_t *fmtsub; + pcb_io_formats_t *avail; + int pick; +} save_t; + +static void fmt_chg(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + pcb_hid_dad_subdialog_t *fmtsub = caller_data; + save_t *save = fmtsub->sub_ctx; + char *bn, *fn, *s; + const char *ext; + pcb_event_arg_t res, argv[4]; + int selection = attr->default_val.int_value;; + + if ((save->avail == NULL) || (save->avail->extension == NULL)) + return; + + if (fmtsub->parent_poke(fmtsub, "get_path", &res, 0, NULL) != 0) + return; + fn = (char *)res.d.s; + + /* find and truncate extension */ + for (s = fn + strlen(fn) - 1; *s != '.'; s--) { + if ((s <= fn) || (*s == PCB_DIR_SEPARATOR_C)) { + free(fn); + return; + } + } + *s = '\0'; + + /* calculate basename in bn */ + bn = strrchr(fn, PCB_DIR_SEPARATOR_C); + if (bn == NULL) + bn = fn; + else + bn++; + + /* fetch the desired extension */ + ext = save->avail->extension[selection]; + if (ext == NULL) + ext = "."; + + /* build a new file name with the right extension */ + + argv[0].type = PCB_EVARG_STR; + argv[0].d.s = pcb_concat(bn, ext, NULL);; + fmtsub->parent_poke(fmtsub, "set_file_name", &res, 1, argv); + free(fn); + + /* remember the selection for the save action */ + save->pick = selection; +} + + +static void setup_fmt_sub(save_t *save) +{ + PCB_DAD_BEGIN_VBOX(save->fmtsub->dlg); + PCB_DAD_BEGIN_HBOX(save->fmtsub->dlg); + PCB_DAD_LABEL(save->fmtsub->dlg, "File format:"); + PCB_DAD_ENUM(save->fmtsub->dlg, (const char **)save->avail->digest); + PCB_DAD_DEFAULT_NUM(save->fmtsub->dlg, save->pick); + PCB_DAD_CHANGE_CB(save->fmtsub->dlg, fmt_chg); + PCB_DAD_END(save->fmtsub->dlg); + PCB_DAD_END(save->fmtsub->dlg); +} + +const char pcb_acts_Save[] = "Save()\n" "Save(Layout|LayoutAs)\n" "Save(AllConnections|AllUnusedPins|ElementConnections)\n" "Save(PasteBuffer)"; +const char pcb_acth_Save[] = "Save layout data to a user-selected file."; +/* DOC: save.html */ +fgw_error_t pcb_act_Save(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + const char *function = "Layout"; + static char *cwd = NULL; + pcb_hid_dad_subdialog_t *fmtsub = NULL, fmtsub_local; + char *final_name, *name_in = NULL; + const char *prompt; + pcb_io_formats_t avail; + const char **extensions_param = NULL; + int fmt, *fmt_param = NULL; + save_t save; + + if (cwd == NULL) cwd = dup_cwd(); + + if (argc > 2) + return PCB_ACT_CALL_C(pcb_act_SaveTo, res, argc, argv); + + PCB_ACT_MAY_CONVARG(1, FGW_STR, Save, function = argv[1].val.str); + + if (pcb_strcasecmp(function, "Layout") == 0) + if (PCB->Filename != NULL) + return pcb_actionl("SaveTo", "Layout", NULL); + + if (pcb_strcasecmp(function, "PasteBuffer") == 0) { + int num_fmts, n; + prompt = "Save element as"; + num_fmts = pcb_io_list(&avail, PCB_IOT_BUFFER, 1, 1, PCB_IOL_EXT_FP); + if (num_fmts > 0) { + const char *default_pattern = conf_core.rc.save_fp_fmt; + extensions_param = (const char **)avail.extension; + fmt_param = &fmt; + fmt = -1; + + if (default_pattern != NULL) { + /* look for exact match, case sensitive */ + for (n = 0; n < num_fmts; n++) + if (strcmp(avail.plug[n]->description, default_pattern) == 0) + fmt = n; + + /* look for exact match, case insensitive */ + if (fmt < 0) + for (n = 0; n < num_fmts; n++) + if (pcb_strcasecmp(avail.plug[n]->description, default_pattern) == 0) + fmt = n; + + /* look for partial match */ + if (fmt < 0) { + for (n = 0; n < num_fmts; n++) { + if (strstr(avail.plug[n]->description, default_pattern) != NULL) { + fmt = n; + break; /* pick the first one, that has the highest prio */ + } + } + } + + if (fmt < 0) { + static int warned = 0; + if (!warned) + pcb_message(PCB_MSG_WARNING, "Could not find an io_ plugin for the preferred footprint save format (configured in rc/save_fp_fmt): '%s'\n", default_pattern); + warned = 1; + } + } + + if (fmt < 0) /* fallback: choose the frist format */ + fmt = 0; + + name_in = pcb_concat("unnamed", avail.plug[fmt]->fp_extension, NULL); + } + else { + pcb_message(PCB_MSG_ERROR, "Error: no IO plugin avaialble for saving a buffer."); + PCB_ACT_IRES(-1); + return 0; + } + } + else { + int num_fmts, n; + prompt = "Save layout as"; + num_fmts = pcb_io_list(&avail, PCB_IOT_PCB, 1, 1, PCB_IOL_EXT_BOARD); + if (num_fmts > 0) { + extensions_param = (const char **)avail.extension; + fmt_param = &fmt; + fmt = 0; + if (PCB->Data->loader != NULL) { + for (n = 0; n < num_fmts; n++) { + if (avail.plug[n] == PCB->Data->loader) { + fmt = n; + break; + } + } + } + fmtsub = &fmtsub_local; + memset(&fmtsub_local, 0, sizeof(fmtsub_local)); + save.avail = &avail; + save.fmtsub = fmtsub; + save.pick = fmt; + fmtsub->sub_ctx = &save; + setup_fmt_sub(&save); + } + else { + pcb_message(PCB_MSG_ERROR, "Error: no IO plugin avaialble for saving a buffer."); + PCB_ACT_IRES(-1); + return 0; + } + } + + /* construct the input file name and run a file selection dialog to get the final file name */ + if (name_in == NULL) { + if (PCB->Filename == NULL) + name_in = pcb_concat("unnamed", extensions_param[fmt], NULL); + else + name_in = pcb_strdup(PCB->Filename); + } + final_name = pcb_gui->fileselect(prompt, NULL, name_in, NULL, NULL, "board", PCB_HID_FSD_MAY_NOT_EXIST, fmtsub); + free(name_in); + + if (final_name == NULL) { /* cancel */ + pcb_io_list_free(&avail); + PCB_ACT_IRES(1); + return 0; + } + + if (conf_core.rc.verbose) + fprintf(stderr, "Save: Calling SaveTo(%s, %s)\n", function, final_name); + + if (pcb_strcasecmp(function, "PasteBuffer") == 0) { + pcb_actionl("PasteBuffer", "Save", final_name, avail.plug[fmt]->description, "1", NULL); + } + else { + const char *sfmt = NULL; + /* + * if we got this far and the function is Layout, then + * we really needed it to be a LayoutAs. Otherwise + * ActionSaveTo() will ignore the new file name we + * just obtained. + */ + if (fmt_param != NULL) + sfmt = avail.plug[save.pick]->description; + if (pcb_strcasecmp(function, "Layout") == 0) + pcb_actionl("SaveTo", "LayoutAs", final_name, sfmt, NULL); + else + pcb_actionl("SaveTo", function, final_name, sfmt, NULL); + } + + free(final_name); + pcb_io_list_free(&avail); + PCB_ACT_IRES(0); + return 0; +} + +const char pcb_acts_ImportGUI[] = "ImportGUI()"; +const char pcb_acth_ImportGUI[] = "Asks user which schematics to import into PCB.\n"; +/* DOC: importgui.html */ +fgw_error_t pcb_act_ImportGUI(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + char *name; + static char *cwd = NULL; + static int lock = 0; + int rv = 0; + + if (cwd == NULL) + cwd = dup_cwd(); + + if (lock) + return 1; + + name = pcb_gui->fileselect("Load schematics", "Import netlist and footprints from schematics", cwd, NULL, NULL, "schematics", PCB_HID_FSD_MAY_NOT_EXIST, NULL); + if (name != NULL) { + pcb_attrib_put(PCB, "import::src0", name); + free(name); + + lock = 1; + rv = pcb_action("Import"); + lock = 0; + } + + PCB_ACT_IRES(rv); + return 0; +} Index: tags/2.1.2/src_plugins/dialogs/dlg_loadsave.h =================================================================== --- tags/2.1.2/src_plugins/dialogs/dlg_loadsave.h (nonexistent) +++ tags/2.1.2/src_plugins/dialogs/dlg_loadsave.h (revision 24813) @@ -0,0 +1,11 @@ +extern const char pcb_acts_Load[]; +extern const char pcb_acth_Load[]; +fgw_error_t pcb_act_Load(fgw_arg_t *res, int argc, fgw_arg_t *argv); + +extern const char pcb_acts_Save[]; +extern const char pcb_acth_Save[]; +fgw_error_t pcb_act_Save(fgw_arg_t *res, int argc, fgw_arg_t *argv); + +extern const char pcb_acts_ImportGUI[]; +extern const char pcb_acth_ImportGUI[]; +fgw_error_t pcb_act_ImportGUI(fgw_arg_t *res, int argc, fgw_arg_t *argv); Index: tags/2.1.2/src_plugins/dialogs/dlg_log.c =================================================================== --- tags/2.1.2/src_plugins/dialogs/dlg_log.c (nonexistent) +++ tags/2.1.2/src_plugins/dialogs/dlg_log.c (revision 24813) @@ -0,0 +1,242 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2019 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "config.h" + +#include "actions.h" +#include "conf_hid.h" +#include "hid_dad.h" +#include "event.h" +#include "error.h" + +#include "dlg_log.h" + +static const char *log_cookie = "dlg_log"; + +typedef struct{ + PCB_DAD_DECL_NOINIT(dlg) + unsigned long last_added; + int active; + int wtxt, wscroll; + int gui_inited; +} log_ctx_t; + +static log_ctx_t log_ctx; + +static void log_close_cb(void *caller_data, pcb_hid_attr_ev_t ev) +{ + log_ctx_t *ctx = caller_data; + ctx->active = 0; +} + +static void log_append(log_ctx_t *ctx, pcb_hid_attribute_t *atxt, pcb_logline_t *line) +{ + pcb_hid_text_t *txt = (pcb_hid_text_t *)atxt->enumerations; + const char *prefix = NULL; + int popup; + + conf_loglevel_props(line->level, &prefix, &popup); + + if (pcb_gui->supports_dad_text_markup) { + if (prefix != NULL) { + gds_t tmp; + gds_init(&tmp); + gds_enlarge(&tmp, line->len+32); + tmp.used = 0; + gds_append_str(&tmp, prefix); + gds_append_len(&tmp, line->str, line->len); + if (*prefix == '<') { + gds_append(&tmp, '<'); + gds_append(&tmp, '/'); + gds_append_str(&tmp, prefix+1); + } + txt->hid_set_text(atxt, ctx->dlg_hid_ctx, PCB_HID_TEXT_APPEND | PCB_HID_TEXT_MARKUP, tmp.array); + gds_uninit(&tmp); + } + else + txt->hid_set_text(atxt, ctx->dlg_hid_ctx, PCB_HID_TEXT_APPEND, line->str); + } + else { + if ((line->prev == NULL) || (line->prev->str[line->prev->len-1] == '\n')) { + switch(line->level) { + case PCB_MSG_DEBUG: prefix = "D: "; break; + case PCB_MSG_INFO: prefix = "I: "; break; + case PCB_MSG_WARNING: prefix = "W: "; break; + case PCB_MSG_ERROR: prefix = "E: "; break; + } + if (prefix != NULL) + txt->hid_set_text(atxt, ctx->dlg_hid_ctx, PCB_HID_TEXT_APPEND | PCB_HID_TEXT_MARKUP, prefix); + } + txt->hid_set_text(atxt, ctx->dlg_hid_ctx, PCB_HID_TEXT_APPEND | PCB_HID_TEXT_MARKUP, line->str); + } + if (popup && (pcb_gui->attr_dlg_raise != NULL)) + pcb_gui->attr_dlg_raise(ctx->dlg_hid_ctx); + if (line->ID > ctx->last_added) + ctx->last_added = line->ID; + line->seen = 1; +} + +static void log_import(log_ctx_t *ctx) +{ + pcb_logline_t *n; + pcb_hid_attribute_t *atxt = &ctx->dlg[ctx->wtxt]; + + for(n = pcb_log_find_min(ctx->last_added); n != NULL; n = n->next) + log_append(ctx, atxt, n); +} + +static void btn_clear_cb(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + pcb_actionl("log", "clear", NULL); +} + +static void btn_export_cb(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + pcb_actionl("log", "export", NULL); +} + +static void log_window_create(void) +{ + log_ctx_t *ctx = &log_ctx; + pcb_hid_attr_val_t hv; + + if (ctx->active) + return; + + memset(ctx, 0, sizeof(log_ctx_t)); + + PCB_DAD_BEGIN_VBOX(ctx->dlg); + PCB_DAD_COMPFLAG(ctx->dlg, PCB_HATF_EXPFILL); + PCB_DAD_TEXT(ctx->dlg, NULL); + PCB_DAD_COMPFLAG(ctx->dlg, PCB_HATF_SCROLL | PCB_HATF_EXPFILL); + ctx->wtxt = PCB_DAD_CURRENT(ctx->dlg); + PCB_DAD_BEGIN_HBOX(ctx->dlg); + PCB_DAD_BUTTON(ctx->dlg, "clear"); + PCB_DAD_CHANGE_CB(ctx->dlg, btn_clear_cb); + PCB_DAD_BUTTON(ctx->dlg, "export"); + PCB_DAD_CHANGE_CB(ctx->dlg, btn_export_cb); + PCB_DAD_BEGIN_HBOX(ctx->dlg); + PCB_DAD_COMPFLAG(ctx->dlg, PCB_HATF_FRAME); + PCB_DAD_BOOL(ctx->dlg, ""); + ctx->wscroll = PCB_DAD_CURRENT(ctx->dlg); + PCB_DAD_LABEL(ctx->dlg, "scroll"); + PCB_DAD_END(ctx->dlg); + PCB_DAD_BEGIN_VBOX(ctx->dlg); + PCB_DAD_COMPFLAG(ctx->dlg, PCB_HATF_EXPFILL); + PCB_DAD_END(ctx->dlg); + PCB_DAD_BUTTON_CLOSE(ctx->dlg, "close", 0); + PCB_DAD_END(ctx->dlg); + PCB_DAD_END(ctx->dlg); + + ctx->active = 1; + ctx->last_added = -1; + PCB_DAD_DEFSIZE(ctx->dlg, 200, 300); + PCB_DAD_NEW("log", ctx->dlg, "pcb-rnd message log", ctx, pcb_false, log_close_cb); + + { + pcb_hid_attribute_t *atxt = &ctx->dlg[ctx->wtxt]; + pcb_hid_text_t *txt = (pcb_hid_text_t *)atxt->enumerations; + txt->hid_set_readonly(atxt, ctx->dlg_hid_ctx, 1); + } + hv.int_value = 1; + pcb_gui->attr_dlg_set_value(ctx->dlg_hid_ctx, ctx->wscroll, &hv); + log_import(ctx); +} + + +const char pcb_acts_LogDialog[] = "LogDialog()\n"; +const char pcb_acth_LogDialog[] = "Open the log dialog."; +fgw_error_t pcb_act_LogDialog(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + log_window_create(); + PCB_ACT_IRES(0); + return 0; +} + +static void log_append_ev(void *user_data, int argc, pcb_event_arg_t argv[]) +{ + pcb_logline_t *line = argv[1].d.p; + + if (log_ctx.active) { + pcb_hid_attribute_t *atxt = &log_ctx.dlg[log_ctx.wtxt]; + pcb_hid_text_t *txt = (pcb_hid_text_t *)atxt->enumerations; + + log_append(&log_ctx, atxt, line); + if ((log_ctx.dlg[log_ctx.wscroll].default_val.int_value) && (txt->hid_scroll_to_bottom != NULL)) + txt->hid_scroll_to_bottom(atxt, log_ctx.dlg_hid_ctx); + } + else if ((PCB_HAVE_GUI_ATTR_DLG) && (log_ctx.gui_inited)) { + const char *prefix; + int popup; + + conf_loglevel_props(line->level, &prefix, &popup); + if (popup) + log_window_create(); + } +} + +static void log_clear_ev(void *user_data, int argc, pcb_event_arg_t argv[]) +{ + if (log_ctx.active) { + pcb_hid_attribute_t *atxt = &log_ctx.dlg[log_ctx.wtxt]; + pcb_hid_text_t *txt = (pcb_hid_text_t *)atxt->enumerations; + + txt->hid_set_text(atxt, log_ctx.dlg_hid_ctx, PCB_HID_TEXT_REPLACE, ""); + log_import(&log_ctx); + } +} + +static void log_gui_init_ev(void *user_data, int argc, pcb_event_arg_t argv[]) +{ + pcb_logline_t *n; + + log_ctx.gui_inited = 1; + + /* if there's pending popup-message in the queue, pop up the dialog */ + for(n = pcb_log_first; n != NULL; n = n->next) { + const char *prefix; + int popup; + + conf_loglevel_props(n->level, &prefix, &popup); + if (popup) { + log_window_create(); + return; + } + } +} + + +void pcb_dlg_log_uninit(void) +{ + pcb_event_unbind_allcookie(log_cookie); +} + +void pcb_dlg_log_init(void) +{ + pcb_event_bind(PCB_EVENT_LOG_APPEND, log_append_ev, NULL, log_cookie); + pcb_event_bind(PCB_EVENT_LOG_CLEAR, log_clear_ev, NULL, log_cookie); + pcb_event_bind(PCB_EVENT_GUI_INIT, log_gui_init_ev, NULL, log_cookie); +} Index: tags/2.1.2/src_plugins/dialogs/dlg_log.h =================================================================== --- tags/2.1.2/src_plugins/dialogs/dlg_log.h (nonexistent) +++ tags/2.1.2/src_plugins/dialogs/dlg_log.h (revision 24813) @@ -0,0 +1,6 @@ +extern const char pcb_acts_LogDialog[]; +extern const char pcb_acth_LogDialog[]; +fgw_error_t pcb_act_LogDialog(fgw_arg_t *res, int argc, fgw_arg_t *argv); + +void pcb_dlg_log_init(void); +void pcb_dlg_log_uninit(void); Index: tags/2.1.2/src_plugins/dialogs/dlg_netlist.c =================================================================== --- tags/2.1.2/src_plugins/dialogs/dlg_netlist.c (nonexistent) +++ tags/2.1.2/src_plugins/dialogs/dlg_netlist.c (revision 24813) @@ -0,0 +1,456 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2019 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "event.h" +#include "netlist2.h" +#include + +const char *dlg_netlist_cookie = "netlist dialog"; + +typedef struct { + PCB_DAD_DECL_NOINIT(dlg) + pcb_board_t *pcb; + pcb_box_t bb_prv; + int wnetlist, wprev, wtermlist; + int wsel, wunsel, wfind, wunfind, wrats, wnorats, wripup, waddrats, wrename, wmerge; + int active; /* already open - allow only one instance */ +} netlist_ctx_t; + +netlist_ctx_t netlist_ctx; + +static void netlist_close_cb(void *caller_data, pcb_hid_attr_ev_t ev) +{ + netlist_ctx_t *ctx = caller_data; + PCB_DAD_FREE(ctx->dlg); + memset(ctx, 0, sizeof(netlist_ctx_t)); + pcb_event(PCB_EVENT_GUI_LEAD_USER, "cci", 0, 0, 0); +} + +/* returns allocated net name for the currently selected net */ +static char *netlist_data2dlg_netlist(netlist_ctx_t *ctx) +{ + pcb_hid_attribute_t *attr; + pcb_hid_tree_t *tree; + pcb_hid_row_t *r; + char *cell[4], *cursor_path = NULL; + pcb_net_t **n, **nets; + + attr = &ctx->dlg[ctx->wnetlist]; + tree = (pcb_hid_tree_t *)attr->enumerations; + + /* remember cursor */ + r = pcb_dad_tree_get_selected(attr); + if (r != NULL) + cursor_path = pcb_strdup(r->cell[0]); + + /* remove existing items */ + pcb_dad_tree_clear(tree); + + nets = pcb_netlist_sort(&ctx->pcb->netlist[1]); + if (nets != NULL) { + cell[2] = NULL; + for(n = nets; *n != NULL; n++) { + cell[0] = pcb_strdup((*n)->name); + cell[1] = pcb_strdup((*n)->inhibit_rats ? "*" : ""); + pcb_dad_tree_append(attr, NULL, cell); + } + free(nets); + + /* restore cursor */ + if (cursor_path != NULL) { + pcb_hid_attr_val_t hv; + hv.str_value = cursor_path; + pcb_gui->attr_dlg_set_value(ctx->dlg_hid_ctx, ctx->wnetlist, &hv); + } + } + return cursor_path; +} + +static void netlist_data2dlg_connlist(netlist_ctx_t *ctx, pcb_net_t *net) +{ + pcb_hid_attribute_t *attr; + pcb_hid_tree_t *tree; + pcb_hid_row_t *r; + char *cell[2], *cursor_path = NULL; + pcb_net_term_t *t; + + attr = &ctx->dlg[ctx->wtermlist]; + tree = (pcb_hid_tree_t *)attr->enumerations; + + /* remember cursor */ + if (net != NULL) { + r = pcb_dad_tree_get_selected(attr); + if (r != NULL) + cursor_path = pcb_strdup(r->cell[0]); + } + + /* remove existing items */ + pcb_dad_tree_clear(tree); + + if (net == NULL) + return; + + cell[1] = NULL; + for(t = pcb_termlist_first(&net->conns); t != NULL; t = pcb_termlist_next(t)) { + cell[0] = pcb_concat(t->refdes, "-", t->term, NULL); + pcb_dad_tree_append(attr, NULL, cell); + } + + /* restore cursor */ + if (cursor_path != NULL) { + pcb_hid_attr_val_t hv; + hv.str_value = cursor_path; + pcb_gui->attr_dlg_set_value(ctx->dlg_hid_ctx, ctx->wtermlist, &hv); + free(cursor_path); + } +} + + +static void netlist_data2dlg(netlist_ctx_t *ctx) +{ + pcb_net_t *curnet = NULL; + char *curnetname = netlist_data2dlg_netlist(ctx); + + if (curnetname != NULL) + curnet = pcb_net_get(ctx->pcb, &ctx->pcb->netlist[PCB_NETLIST_EDITED], curnetname, 0); + free(curnetname); + netlist_data2dlg_connlist(ctx, curnet); +} + +static void netlist_force_redraw(netlist_ctx_t *ctx) +{ + pcb_dad_preview_zoomto(&ctx->dlg[ctx->wprev], &ctx->bb_prv); +} + + +static void netlist_row_selected(pcb_hid_attribute_t *attrib, void *hid_ctx, pcb_hid_row_t *row) +{ + pcb_hid_tree_t *tree = (pcb_hid_tree_t *)attrib->enumerations; + netlist_ctx_t *ctx= tree->user_ctx; + const char *netname = NULL; + pcb_net_t *net = NULL; + + if (row != NULL) + netname = row->cell[0]; + if (netname != NULL) + net = pcb_net_get(ctx->pcb, &ctx->pcb->netlist[PCB_NETLIST_EDITED], netname, 0); + netlist_data2dlg_connlist(ctx, net); + pcb_event(PCB_EVENT_GUI_LEAD_USER, "cci", 0, 0, 0); + netlist_force_redraw(ctx); +} + +static void termlist_row_selected(pcb_hid_attribute_t *attrib, void *hid_ctx, pcb_hid_row_t *row) +{ + pcb_hid_tree_t *tree = (pcb_hid_tree_t *)attrib->enumerations; + netlist_ctx_t *ctx= tree->user_ctx; + char *refdes, *term; + pcb_any_obj_t *obj; + + pcb_event(PCB_EVENT_GUI_LEAD_USER, "cci", 0, 0, 0); + if (row == NULL) + return; + refdes = pcb_strdup(row->cell[0]); + term = strchr(refdes, '-'); + if (term != NULL) { + *term = '\0'; + term++; + obj = pcb_term_find_name(ctx->pcb, ctx->pcb->Data, PCB_LYT_COPPER, refdes, term, NULL, NULL); + if (obj != NULL) { + pcb_coord_t x, y; + pcb_obj_center(obj, &x, &y); + pcb_event(PCB_EVENT_GUI_LEAD_USER, "cci", x, y, 1); + } + } + free(refdes); +} + +static void netlist_button_cb(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + netlist_ctx_t *ctx = caller_data; + pcb_hid_attribute_t *atree; + int w = attr - ctx->dlg; + pcb_hid_row_t *r; + const char *name; + + atree = &ctx->dlg[ctx->wnetlist]; + r = pcb_dad_tree_get_selected(atree); + if (r == NULL) + return; + name = pcb_strdup(r->cell[0]); + + if (w == ctx->wsel) + pcb_actionl("netlist", "select", name, NULL); + else if (w == ctx->wunsel) + pcb_actionl("netlist", "unselect", name, NULL); + else if (w == ctx->wfind) { + pcb_actionl("connection", "reset", NULL); + pcb_actionl("netlist", "find", name, NULL); + } + else if (w == ctx->wunfind) + pcb_actionl("connection", "reset", NULL); + else if (w == ctx->wrats) + pcb_actionl("netlist", "rats", name, NULL); + else if (w == ctx->wnorats) + pcb_actionl("netlist", "norats", name, NULL); + else if (w == ctx->wripup) + pcb_actionl("netlist", "ripup", name, NULL); + else if (w == ctx->waddrats) + pcb_actionl("netlist", "AddRats", name, NULL); + else if (w == ctx->wrename) + pcb_actionl("netlist", "rename", name, NULL); + else if (w == ctx->wmerge) + pcb_actionl("netlist", "merge", name, NULL); + else { + pcb_message(PCB_MSG_ERROR, "Internal error: netlist_button_cb() called from an invalid widget\n"); + return; + } + pcb_gui->invalidate_all(); +} + +static void netlist_claim_obj_cb(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + pcb_actionl("ClaimNet", "object", NULL); +} + +static void netlist_claim_sel_cb(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + pcb_actionl("ClaimNet", "selected", NULL); +} + +static void netlist_claim_fnd_cb(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + pcb_actionl("ClaimNet", "found", NULL); +} + +static vtp0_t netlist_color_save; + +static void netlist_expose(pcb_hid_attribute_t *attrib, pcb_hid_preview_t *prv, pcb_hid_gc_t gc, const pcb_hid_expose_ctx_t *e) +{ + netlist_ctx_t *ctx = prv->user_ctx; + pcb_xform_t xform; + size_t n; + void **p; + pcb_hid_attribute_t *attr; + pcb_hid_row_t *r; + pcb_net_t *net = NULL; + + attr = &ctx->dlg[ctx->wnetlist]; + r = pcb_dad_tree_get_selected(attr); + if (r != NULL) + net = pcb_net_get(ctx->pcb, &ctx->pcb->netlist[PCB_NETLIST_EDITED], r->cell[0], 0); + + if (net != NULL) { /* save term object colors */ + pcb_net_term_t *t; + vtp0_truncate(&netlist_color_save, 0); + for(t = pcb_termlist_first(&net->conns); t != NULL; t = pcb_termlist_next(t)) { + pcb_any_obj_t *obj = pcb_term_find_name(ctx->pcb, ctx->pcb->Data, PCB_LYT_COPPER, t->refdes, t->term, NULL, NULL); + if (obj == NULL) + continue; + + vtp0_append(&netlist_color_save, obj); + if (obj->override_color != NULL) + vtp0_append(&netlist_color_save, (char *)obj->override_color); + else + vtp0_append(&netlist_color_save, NULL); + obj->override_color = pcb_color_magenta; + } + } + + /* draw the board */ + memset(&xform, 0, sizeof(xform)); + xform.layer_faded = 1; + pcb_hid_expose_all(pcb_gui, e, &xform); + + if (net != NULL) {/* restore object color */ + for(n = 0, p = netlist_color_save.array; n < netlist_color_save.used; n+=2,p+=2) { + pcb_any_obj_t *obj = p[0]; + pcb_color_t *s = p[1]; + obj->override_color = s; + } + vtp0_truncate(&netlist_color_save, 0); + } +} + +static pcb_bool netlist_mouse(pcb_hid_attribute_t *attrib, pcb_hid_preview_t *prv, pcb_hid_mouse_ev_t kind, pcb_coord_t x, pcb_coord_t y) +{ + return pcb_false; +} + +static void pcb_dlg_netlist(pcb_board_t *pcb) +{ + static const char *hdr[] = {"network", "FR", NULL}; + static const char *hdr2[] = {"terminals", NULL}; + pcb_hid_dad_buttons_t clbtn[] = {{"Close", 0}, {NULL, 0}}; + + int wvpan; + + if (netlist_ctx.active) + return; /* do not open another */ + + netlist_ctx.bb_prv.X1 = 0; + netlist_ctx.bb_prv.Y1 = 0; + netlist_ctx.bb_prv.X2 = pcb->MaxWidth; + netlist_ctx.bb_prv.Y2 = pcb->MaxHeight; + netlist_ctx.pcb = pcb; + + PCB_DAD_BEGIN_VBOX(netlist_ctx.dlg); /* layout */ + PCB_DAD_COMPFLAG(netlist_ctx.dlg, PCB_HATF_EXPFILL); + + PCB_DAD_BEGIN_HPANE(netlist_ctx.dlg); + PCB_DAD_COMPFLAG(netlist_ctx.dlg, PCB_HATF_EXPFILL); + + PCB_DAD_BEGIN_VBOX(netlist_ctx.dlg); /* left */ + PCB_DAD_COMPFLAG(netlist_ctx.dlg, PCB_HATF_EXPFILL); + PCB_DAD_TREE(netlist_ctx.dlg, 2, 0, hdr); + PCB_DAD_COMPFLAG(netlist_ctx.dlg, PCB_HATF_EXPFILL | PCB_HATF_SCROLL); + netlist_ctx.wnetlist = PCB_DAD_CURRENT(netlist_ctx.dlg); + PCB_DAD_TREE_SET_CB(netlist_ctx.dlg, selected_cb, netlist_row_selected); + PCB_DAD_TREE_SET_CB(netlist_ctx.dlg, ctx, &netlist_ctx); + PCB_DAD_END(netlist_ctx.dlg); + + PCB_DAD_BEGIN_VBOX(netlist_ctx.dlg); /* right */ + PCB_DAD_COMPFLAG(netlist_ctx.dlg, PCB_HATF_EXPFILL); + PCB_DAD_BEGIN_VPANE(netlist_ctx.dlg); + PCB_DAD_COMPFLAG(netlist_ctx.dlg, PCB_HATF_EXPFILL); + wvpan = PCB_DAD_CURRENT(netlist_ctx.dlg); + PCB_DAD_BEGIN_VBOX(netlist_ctx.dlg); /* right-top */ + PCB_DAD_COMPFLAG(netlist_ctx.dlg, PCB_HATF_EXPFILL); + PCB_DAD_PREVIEW(netlist_ctx.dlg, netlist_expose, netlist_mouse, NULL, &netlist_ctx.bb_prv, 100, 100, &netlist_ctx); + PCB_DAD_COMPFLAG(netlist_ctx.dlg, PCB_HATF_EXPFILL); + netlist_ctx.wprev = PCB_DAD_CURRENT(netlist_ctx.dlg); + PCB_DAD_END(netlist_ctx.dlg); + PCB_DAD_BEGIN_VBOX(netlist_ctx.dlg); /* right-bottom */ + PCB_DAD_COMPFLAG(netlist_ctx.dlg, PCB_HATF_EXPFILL); + PCB_DAD_TREE(netlist_ctx.dlg, 1, 0, hdr2); + PCB_DAD_COMPFLAG(netlist_ctx.dlg, PCB_HATF_EXPFILL); + netlist_ctx.wtermlist = PCB_DAD_CURRENT(netlist_ctx.dlg); + PCB_DAD_TREE_SET_CB(netlist_ctx.dlg, selected_cb, termlist_row_selected); + PCB_DAD_TREE_SET_CB(netlist_ctx.dlg, ctx, &netlist_ctx); + PCB_DAD_END(netlist_ctx.dlg); + PCB_DAD_END(netlist_ctx.dlg); + PCB_DAD_END(netlist_ctx.dlg); + PCB_DAD_END(netlist_ctx.dlg); + + PCB_DAD_BEGIN_HBOX(netlist_ctx.dlg); /* bottom button row */ + PCB_DAD_BEGIN_VBOX(netlist_ctx.dlg); + PCB_DAD_BUTTON(netlist_ctx.dlg, "select"); + PCB_DAD_CHANGE_CB(netlist_ctx.dlg, netlist_button_cb); + netlist_ctx.wsel = PCB_DAD_CURRENT(netlist_ctx.dlg); + PCB_DAD_BUTTON(netlist_ctx.dlg, "unsel."); + PCB_DAD_CHANGE_CB(netlist_ctx.dlg, netlist_button_cb); + netlist_ctx.wunsel = PCB_DAD_CURRENT(netlist_ctx.dlg); + PCB_DAD_END(netlist_ctx.dlg); + PCB_DAD_BEGIN_VBOX(netlist_ctx.dlg); + PCB_DAD_BUTTON(netlist_ctx.dlg, "find "); + PCB_DAD_CHANGE_CB(netlist_ctx.dlg, netlist_button_cb); + netlist_ctx.wfind = PCB_DAD_CURRENT(netlist_ctx.dlg); + PCB_DAD_BUTTON(netlist_ctx.dlg, "clear"); + PCB_DAD_CHANGE_CB(netlist_ctx.dlg, netlist_button_cb); + netlist_ctx.wunfind = PCB_DAD_CURRENT(netlist_ctx.dlg); + PCB_DAD_END(netlist_ctx.dlg); + PCB_DAD_BEGIN_VBOX(netlist_ctx.dlg); + PCB_DAD_BUTTON(netlist_ctx.dlg, "rat disable"); + PCB_DAD_CHANGE_CB(netlist_ctx.dlg, netlist_button_cb); + netlist_ctx.wnorats = PCB_DAD_CURRENT(netlist_ctx.dlg); + PCB_DAD_BUTTON(netlist_ctx.dlg, "rat enable"); + netlist_ctx.wrats = PCB_DAD_CURRENT(netlist_ctx.dlg); + PCB_DAD_CHANGE_CB(netlist_ctx.dlg, netlist_button_cb); + PCB_DAD_END(netlist_ctx.dlg); + PCB_DAD_BEGIN_VBOX(netlist_ctx.dlg); + PCB_DAD_BUTTON(netlist_ctx.dlg, "add rats"); + netlist_ctx.waddrats = PCB_DAD_CURRENT(netlist_ctx.dlg); + PCB_DAD_CHANGE_CB(netlist_ctx.dlg, netlist_button_cb); + PCB_DAD_BUTTON(netlist_ctx.dlg, "rip up "); + netlist_ctx.wripup = PCB_DAD_CURRENT(netlist_ctx.dlg); + PCB_DAD_CHANGE_CB(netlist_ctx.dlg, netlist_button_cb); + PCB_DAD_END(netlist_ctx.dlg); + PCB_DAD_BEGIN_VBOX(netlist_ctx.dlg); + PCB_DAD_BUTTON(netlist_ctx.dlg, "rename"); + netlist_ctx.wrename = PCB_DAD_CURRENT(netlist_ctx.dlg); + PCB_DAD_CHANGE_CB(netlist_ctx.dlg, netlist_button_cb); + PCB_DAD_BUTTON(netlist_ctx.dlg, "merge "); + netlist_ctx.wmerge = PCB_DAD_CURRENT(netlist_ctx.dlg); + PCB_DAD_CHANGE_CB(netlist_ctx.dlg, netlist_button_cb); + PCB_DAD_END(netlist_ctx.dlg); + PCB_DAD_END(netlist_ctx.dlg); + + PCB_DAD_BEGIN_HBOX(netlist_ctx.dlg); /* bottom button row */ + PCB_DAD_LABEL(netlist_ctx.dlg, "Claim net:"); + PCB_DAD_BUTTON(netlist_ctx.dlg, "click"); + PCB_DAD_CHANGE_CB(netlist_ctx.dlg, netlist_claim_obj_cb); + PCB_DAD_BUTTON(netlist_ctx.dlg, "select"); + PCB_DAD_CHANGE_CB(netlist_ctx.dlg, netlist_claim_sel_cb); + PCB_DAD_BUTTON(netlist_ctx.dlg, "found"); + PCB_DAD_CHANGE_CB(netlist_ctx.dlg, netlist_claim_fnd_cb); + PCB_DAD_BEGIN_VBOX(netlist_ctx.dlg); /* fill between buttons and close */ + PCB_DAD_COMPFLAG(netlist_ctx.dlg, PCB_HATF_EXPFILL); + PCB_DAD_END(netlist_ctx.dlg); + PCB_DAD_BUTTON_CLOSES(netlist_ctx.dlg, clbtn); + PCB_DAD_END(netlist_ctx.dlg); + PCB_DAD_END(netlist_ctx.dlg); + + /* set up the context */ + netlist_ctx.active = 1; + + PCB_DAD_DEFSIZE(netlist_ctx.dlg, 300, 350); + PCB_DAD_NEW("netlist", netlist_ctx.dlg, "pcb-rnd netlist", &netlist_ctx, pcb_false, netlist_close_cb); + + { + pcb_hid_attr_val_t hv; + hv.real_value = 0.33; + pcb_gui->attr_dlg_set_value(netlist_ctx.dlg_hid_ctx, wvpan, &hv); + } + + netlist_data2dlg(&netlist_ctx); +} + +static const char pcb_acts_NetlistDialog[] = "NetlistDialog()\n"; +static const char pcb_acth_NetlistDialog[] = "Open the netlist dialog."; +static fgw_error_t pcb_act_NetlistDialog(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + pcb_dlg_netlist(PCB); + PCB_ACT_IRES(0); + return 0; +} + +/* update the dialog after a netlist change */ +static void pcb_dlg_netlist_ev(void *user_data, int argc, pcb_event_arg_t argv[]) +{ + netlist_ctx_t *ctx = user_data; + if (!ctx->active) + return; + netlist_data2dlg(ctx); +} +static void pcb_dlg_netlist_init(void) +{ + pcb_event_bind(PCB_EVENT_NETLIST_CHANGED, pcb_dlg_netlist_ev, &netlist_ctx, dlg_netlist_cookie); +} + +static void pcb_dlg_netlist_uninit(void) +{ + pcb_event_unbind_allcookie(dlg_netlist_cookie); + vtp0_uninit(&netlist_color_save); +} Index: tags/2.1.2/src_plugins/dialogs/dlg_padstack.c =================================================================== --- tags/2.1.2/src_plugins/dialogs/dlg_padstack.c (nonexistent) +++ tags/2.1.2/src_plugins/dialogs/dlg_padstack.c (revision 24813) @@ -0,0 +1,982 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2017 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "config.h" +#include "actions.h" +#include "hid_dad.h" +#include "funchash_core.h" +#include "obj_pstk.h" +#include "obj_pstk_op.h" +#include "obj_pstk_inlines.h" +#include "obj_subc_parent.h" +#include "search.h" +#include "operation.h" +#include "dlg_lib_pstk.h" +#include "dlg_padstack.h" + +static const char *shapes[] = { "circle", "square", NULL }; +static const char *sides[] = { "all (top, bottom, intern)", "top & bottom only", "top only", "bottom only", "none", NULL }; +static pcb_layer_type_t sides_lyt[] = { PCB_LYT_TOP | PCB_LYT_BOTTOM | PCB_LYT_INTERN, PCB_LYT_TOP | PCB_LYT_BOTTOM, PCB_LYT_TOP, PCB_LYT_BOTTOM, 0 }; + +/* build a group/layer name string in tmp */ +char *pse_group_string(pcb_board_t *pcb, pcb_layergrp_t *grp, char *out, int size) +{ + const char *lname = "", *gname = ""; + + if (grp != NULL) { + gname = grp->name; + if (grp->len > 0) { + pcb_layer_t *l = pcb_get_layer(pcb->Data, grp->lid[0]); + if (l != NULL) + lname = l->name; + } + } + + pcb_snprintf(out, size, "%s\n[%s]", gname, lname); + return out; +} + +/* Convert from padstack to dialog */ +static void pse_ps2dlg(void *hid_ctx, pse_t *pse) +{ + char tmp[256], *s; + const char *prn = ""; + int n; + pcb_pstk_proto_t *proto; + pcb_layergrp_id_t top_gid, bottom_gid; + pcb_layergrp_t *top_grp, *bottom_grp; + pcb_bb_type_t htype; + char shp_found[32]; + pcb_pstk_tshape_t *ts = pcb_pstk_get_tshape(pse->ps); + + if (ts == NULL) + return; + + htype = pcb_pstk_bbspan(pse->pcb, pse->ps, &top_gid, &bottom_gid, &proto); + top_grp = pcb_get_layergrp(pse->pcb, top_gid); + bottom_grp = pcb_get_layergrp(pse->pcb, bottom_gid); + + /* instance */ + if ((proto != NULL) && (proto->name != NULL)) + prn = proto->name; + pcb_snprintf(tmp, sizeof(tmp), "#%ld:%d (%s)", (long int)pse->ps->proto, pse->ps->protoi, prn); + PCB_DAD_SET_VALUE(hid_ctx, pse->proto_id, str_value, tmp); + PCB_DAD_SET_VALUE(hid_ctx, pse->clearance, coord_value, pse->ps->Clearance); + PCB_DAD_SET_VALUE(hid_ctx, pse->rot, real_value, pse->ps->rot); + PCB_DAD_SET_VALUE(hid_ctx, pse->xmirror, int_value, pse->ps->xmirror); + PCB_DAD_SET_VALUE(hid_ctx, pse->smirror, int_value, pse->ps->smirror); + + /* proto - layers */ + memset(shp_found, 0, sizeof(shp_found)); + for(n = 0; n < pcb_proto_num_layers; n++) { + pcb_pstk_shape_t *shape = pcb_pstk_shape(pse->ps, pcb_proto_layers[n].mask, pcb_proto_layers[n].comb); + + if (shape != NULL) { + int shape_idx = shape - ts->shape; + if ((shape_idx >= 0) && (shape_idx < sizeof(shp_found))) + shp_found[shape_idx] = 1; + switch(shape->shape) { + case PCB_PSSH_HSHADOW: + *tmp = '\0'; + PCB_DAD_SET_VALUE(hid_ctx, pse->proto_shape[n], str_value, "hshadow"); + break; + case PCB_PSSH_CIRC: + PCB_DAD_SET_VALUE(hid_ctx, pse->proto_shape[n], str_value, "circle"); + if ((shape->data.circ.x != 0) || (shape->data.circ.y != 0)) + pcb_snprintf(tmp, sizeof(tmp), "dia=%.06$mm\nat %.06$mm;%.06$mm", shape->data.circ.dia, shape->data.circ.x, shape->data.circ.y); + else + pcb_snprintf(tmp, sizeof(tmp), "dia=%.06$mm", shape->data.circ.dia); + break; + case PCB_PSSH_LINE: + if (shape->data.line.square) + PCB_DAD_SET_VALUE(hid_ctx, pse->proto_shape[n], str_value, "square line"); + else + PCB_DAD_SET_VALUE(hid_ctx, pse->proto_shape[n], str_value, "round line"); + pcb_snprintf(tmp, sizeof(tmp), "thickness=%.06$mm", shape->data.line.thickness); + break; + case PCB_PSSH_POLY: + PCB_DAD_SET_VALUE(hid_ctx, pse->proto_shape[n], str_value, "polygon"); + pcb_snprintf(tmp, sizeof(tmp), "corners=%d", shape->data.poly.len); + break; + default: + PCB_DAD_SET_VALUE(hid_ctx, pse->proto_shape[n], str_value, ""); + strcpy(tmp, ""); + } + PCB_DAD_SET_VALUE(hid_ctx, pse->proto_info[n], str_value, tmp); + PCB_DAD_SET_VALUE(hid_ctx, pse->proto_clr[n], coord_value, shape->clearance); + } + else { + PCB_DAD_SET_VALUE(hid_ctx, pse->proto_shape[n], str_value, ""); + PCB_DAD_SET_VALUE(hid_ctx, pse->proto_info[n], str_value, ""); + PCB_DAD_SET_VALUE(hid_ctx, pse->proto_clr[n], coord_value, 0); + } + } + + { + int not_found = 0; + for(n = 0; n < MIN((int)ts->len, (int)sizeof(shp_found)); n++) + if (shp_found[n] == 0) + not_found++; + if (not_found) + pcb_message(PCB_MSG_ERROR, "This padstack has %d shape(s) that are not listed in the padstack editor\nFor editing all shapes, please break the padstack up\n", not_found); + } + + /* proto - hole */ + if (proto->mech_idx >= 0) { + s = "Slot geometry ():"; + switch(htype) { + case PCB_BB_NONE: s = "Slot geometry (there is no slot in this padstack):"; break; + case PCB_BB_THRU: s = "Slot geometry (all-way-through slot):"; break; + case PCB_BB_BB: s = "Slot geometry (blind and/or buried slot):"; break; + case PCB_BB_INVALID: s = "Slot geometry (INVALID SLOT):"; break; + } + pcb_gui->attr_dlg_widget_state(hid_ctx, pse->hdia, 0); + } + else { + s = "Hole geometry ():"; + switch(htype) { + case PCB_BB_NONE: s = "Hole geometry (there is no hole in this padstack):"; break; + case PCB_BB_THRU: s = "Hole geometry (all-way-through hole):"; break; + case PCB_BB_BB: s = "Hole geometry (blind and/or buried hole):"; break; + case PCB_BB_INVALID: s = "Hole geometry (INVALID HOLE):"; break; + } + pcb_gui->attr_dlg_widget_state(hid_ctx, pse->hdia, 1); + } + PCB_DAD_SET_VALUE(hid_ctx, pse->hole_header, str_value, s); + + free((char *)pse->attrs[pse->prname].default_val.str_value); + pse->attrs[pse->prname].default_val.str_value = NULL; + PCB_DAD_SET_VALUE(hid_ctx, pse->prname, str_value, pcb_strdup(proto->name == NULL ? "" : proto->name)); + PCB_DAD_SET_VALUE(hid_ctx, pse->hdia, coord_value, proto->hdia); + PCB_DAD_SET_VALUE(hid_ctx, pse->hplated, int_value, proto->hplated); + PCB_DAD_SET_VALUE(hid_ctx, pse->htop_val, int_value, proto->htop); + PCB_DAD_SET_VALUE(hid_ctx, pse->hbot_val, int_value, proto->hbottom); + + if (proto->htop == 0) + strcpy(tmp, "top copper group"); + else + sprintf(tmp, "%d groups from\nthe %s copper group", proto->htop, proto->htop > 0 ? "top" : "bottom"); + PCB_DAD_SET_VALUE(hid_ctx, pse->htop_text, str_value, tmp); + PCB_DAD_SET_VALUE(hid_ctx, pse->htop_layer, str_value, pse_group_string(pse->pcb, top_grp, tmp, sizeof(tmp))); + + if (proto->hbottom == 0) + strcpy(tmp, "bottom copper group"); + else + sprintf(tmp, "%d groups from\nthe %s copper group", proto->hbottom, proto->hbottom > 0 ? "bottom" : "top"); + PCB_DAD_SET_VALUE(hid_ctx, pse->hbot_text, str_value, tmp); + PCB_DAD_SET_VALUE(hid_ctx, pse->hbot_layer, str_value, pse_group_string(pse->pcb, bottom_grp, tmp, sizeof(tmp))); + +} + +static void pse_change_callback(pse_t *pse) +{ + if (pse->change_cb != NULL) + pse->change_cb(pse); +} + +static void pse_chg_protoid(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + pse_t *pse = caller_data; + pcb_cardinal_t proto_id; + pcb_subc_t *subc; + static int lock = 0; + + if (lock != 0) + return; + + subc = pcb_obj_parent_subc((pcb_any_obj_t *)pse->ps); + proto_id = pcb_dlg_pstklib(pse->pcb, (subc == NULL ? 0 : subc->ID), pcb_true, "Select a new prototype to be used on the padstack"); + if (proto_id == PCB_PADSTACK_INVALID) + return; + + pcb_pstk_change_instance(pse->ps, &proto_id, NULL, NULL, NULL, NULL); + + lock++; + pse_ps2dlg(hid_ctx, pse); /* to get the button text updated with proto name */ + lock--; + + pse_change_callback(pse); + pcb_gui->invalidate_all(); +} + +static void pse_chg_protodup(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + pse_t *pse = caller_data; + pcb_cardinal_t proto_id; + pcb_pstk_proto_t *proto = pcb_pstk_get_proto(pse->ps); + + assert(pse->ps->parent_type == PCB_PARENT_DATA); + if (proto == NULL) { + pcb_message(PCB_MSG_ERROR, "Internal error: can't determine prototype\n"); + return; + } + proto_id = pcb_pstk_proto_insert_forcedup(pse->ps->parent.data, proto, 0); + pcb_pstk_change_instance(pse->ps, &proto_id, NULL, NULL, NULL, NULL); + pse_ps2dlg(hid_ctx, pse); + pse_change_callback(pse); + pcb_gui->invalidate_all(); +} + +static void pse_chg_instance(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + pse_t *pse = caller_data; + static int lock = 0; + + if (lock != 0) + return; + + pcb_pstk_change_instance(pse->ps, + NULL, + &pse->attrs[pse->clearance].default_val.coord_value, + &pse->attrs[pse->rot].default_val.real_value, + &pse->attrs[pse->xmirror].default_val.int_value, + &pse->attrs[pse->smirror].default_val.int_value); + + lock++; + pse_ps2dlg(hid_ctx, pse); /* to get calculated text fields updated */ + lock--; + + pse_change_callback(pse); + pcb_gui->invalidate_all(); +} + +static void pse_chg_prname(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + pse_t *pse = caller_data; + pcb_pstk_proto_t *proto = pcb_pstk_get_proto(pse->ps); + static int lock = 0; + const char *new_name = pse->attrs[pse->prname].default_val.str_value; + + if ((lock != 0) || (proto == NULL)) + return; + + if (proto->name == NULL) { + if ((new_name == NULL) || (*new_name == '\0')) + return; + } + else { + if (strcmp(proto->name, new_name) == 0) + return; + } + + pcb_pstk_proto_change_name(proto, new_name); + + lock++; + pse_ps2dlg(hid_ctx, pse); /* to get calculated text fields updated */ + lock--; + + pse_change_callback(pse); + pcb_gui->invalidate_all(); +} + +static void pse_chg_hole(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + pse_t *pse = caller_data; + pcb_pstk_proto_t *proto = pcb_pstk_get_proto(pse->ps); + static int lock = 0; + + if (lock != 0) + return; + + if (proto != NULL) { + pcb_pstk_proto_change_hole(proto, + &pse->attrs[pse->hplated].default_val.int_value, + &pse->attrs[pse->hdia].default_val.coord_value, + &pse->attrs[pse->htop_val].default_val.int_value, + &pse->attrs[pse->hbot_val].default_val.int_value); + } + + lock++; + pse_ps2dlg(hid_ctx, pse); /* to get calculated text fields updated */ + lock--; + + pse_change_callback(pse); + pcb_gui->invalidate_all(); +} + +static void pse_chg_proto_clr(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + pse_t *pse = caller_data; + pcb_pstk_proto_t *proto = pcb_pstk_get_proto(pse->ps); + static int lock = 0; + + if (lock != 0) + return; + + if (proto != NULL) { + int n, idx = -1, sidx; + pcb_opctx_t ctx; + + for(n = 0; n < pcb_proto_num_layers; n++) + if (pse->proto_clr[n] == (attr - pse->attrs)) + idx = n; + if (idx < 0) { + pcb_message(PCB_MSG_ERROR, "Can't find shape - clearance unchanged (a)\n"); + return; + } + + sidx = pcb_pstk_get_shape_idx(&proto->tr.array[0], pcb_proto_layers[idx].mask, pcb_proto_layers[idx].comb); + if (sidx < 0) { + pcb_message(PCB_MSG_ERROR, "Can't find shape - clearance unchanged (b)\n"); + return; + } + + ctx.clip.clear = 0; + ctx.clip.restore = 1; + pcb_pstkop_clip(&ctx, pse->ps); + + for(n = 0; n < proto->tr.used; n++) + pcb_pstk_shape_clr_grow(&proto->tr.array[n].shape[sidx], pcb_true, pse->attrs[pse->proto_clr[idx]].default_val.coord_value); + + ctx.clip.clear = 1; + ctx.clip.restore = 0; + pcb_pstkop_clip(&ctx, pse->ps); + } + + lock++; + pse_ps2dlg(hid_ctx, pse); /* to get calculated text fields updated */ + lock--; + + pse_change_callback(pse); + pcb_gui->invalidate_all(); +} + +static void pse_shape_del(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + pse_t *pse = caller_data; + pcb_pstk_proto_t *proto = pcb_pstk_get_proto(pse->ps); + pcb_pstk_proto_del_shape(proto, pcb_proto_layers[pse->editing_shape].mask, pcb_proto_layers[pse->editing_shape].comb); + + pse_ps2dlg(pse->parent_hid_ctx, pse); + + pse_change_callback(pse); + pcb_gui->invalidate_all(); +} + +static void pse_shape_hshadow(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + pse_t *pse = caller_data; + pcb_pstk_proto_t *proto = pcb_pstk_get_proto(pse->ps); + pcb_pstk_proto_del_shape(proto, pcb_proto_layers[pse->editing_shape].mask, pcb_proto_layers[pse->editing_shape].comb); + pcb_pstk_shape_add_hshadow(proto, pcb_proto_layers[pse->editing_shape].mask, pcb_proto_layers[pse->editing_shape].comb); + pse_ps2dlg(pse->parent_hid_ctx, pse); + + pse_change_callback(pse); + pcb_gui->invalidate_all(); +} + +static void pse_shape_auto(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + int n, src_idx = -1; + pse_t *pse = caller_data; + pcb_pstk_proto_t *proto = pcb_pstk_get_proto(pse->ps); + pcb_pstk_tshape_t *ts = &proto->tr.array[0]; + int dst_idx; + char src_shape_names[128]; + char *end = src_shape_names; + + + if (ts == NULL) { + pcb_message(PCB_MSG_ERROR, "Can't derive shape: no shapes (empty padstack)\n"); + return; + } + + dst_idx = pcb_pstk_get_shape_idx(ts, pcb_proto_layers[pse->editing_shape].mask, pcb_proto_layers[pse->editing_shape].comb); + + for(n = 0; n < 2; n++) { + int from = pcb_proto_layers[pse->editing_shape].auto_from[n]; + if (from < 0) + continue; + src_idx = pcb_pstk_get_shape_idx(ts, pcb_proto_layers[from].mask, pcb_proto_layers[from].comb); + if (src_idx >= 0) + break; + strcpy(end, pcb_proto_layers[from].name); + end += strlen(pcb_proto_layers[from].name); + *end = ','; + end++; + } + + if (src_idx < 0) { + if (end > src_shape_names) + end--; + *end = 0; + pcb_message(PCB_MSG_ERROR, "Can't derive shape: source shapes (%s) are empty\n", src_shape_names); + return; + } + + pcb_pstk_shape_derive(proto, dst_idx, src_idx, pcb_proto_layers[pse->editing_shape].auto_bloat, pcb_proto_layers[pse->editing_shape].mask, pcb_proto_layers[pse->editing_shape].comb); + + pse_ps2dlg(pse->parent_hid_ctx, pse); + pse_change_callback(pse); + pcb_gui->invalidate_all(); +} + +static void pse_shape_copy(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + pse_t *pse = caller_data; + pcb_pstk_proto_t *proto = pcb_pstk_get_proto(pse->ps); + pcb_pstk_tshape_t *ts = &proto->tr.array[0]; + int from = pse->shape_chg[pse->copy_from].default_val.int_value; + int dst_idx; + int src_idx; + + if (ts == NULL) { + pcb_message(PCB_MSG_ERROR, "Can't copy shape: no such source shape (empty padstack)\n"); + return; + } + + dst_idx = pcb_pstk_get_shape_idx(ts, pcb_proto_layers[pse->editing_shape].mask, pcb_proto_layers[pse->editing_shape].comb); + src_idx = pcb_pstk_get_shape_idx(ts, pcb_proto_layers[from].mask, pcb_proto_layers[from].comb); + + if (src_idx < 0) { + pcb_message(PCB_MSG_ERROR, "Can't copy shape: source shape (%s) is empty\n", pcb_proto_layers[from].name); + return; + } + + if (src_idx == dst_idx) { + pcb_message(PCB_MSG_ERROR, "Can't copy shape: source shape and destination shape are the same layer type\n"); + return; + } + + pcb_pstk_shape_derive(proto, dst_idx, src_idx, 0, pcb_proto_layers[pse->editing_shape].mask, pcb_proto_layers[pse->editing_shape].comb); + + pse_ps2dlg(pse->parent_hid_ctx, pse); + pse_change_callback(pse); + pcb_gui->invalidate_all(); +} + +static void pse_shape_swap(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + pse_t *pse = caller_data; + pcb_pstk_proto_t *proto = pcb_pstk_get_proto(pse->ps); + pcb_pstk_tshape_t *ts = &proto->tr.array[0]; + int from = pse->shape_chg[pse->copy_from].default_val.int_value; + int dst_idx; + int src_idx; + + if (ts == NULL) { + pcb_message(PCB_MSG_ERROR, "Can't swap shape: no such shapes (empty padstack)\n"); + return; + } + + dst_idx = pcb_pstk_get_shape_idx(ts, pcb_proto_layers[pse->editing_shape].mask, pcb_proto_layers[pse->editing_shape].comb); + src_idx = pcb_pstk_get_shape_idx(ts, pcb_proto_layers[from].mask, pcb_proto_layers[from].comb); + + if (src_idx < 0) { + pcb_message(PCB_MSG_ERROR, "Can't swap shape: source shape (%s) is empty\n", pcb_proto_layers[from].name); + return; + } + + if (src_idx == dst_idx) { + pcb_message(PCB_MSG_ERROR, "Can't swap shape: source shape and destination shape are the same layer type\n"); + return; + } + + pcb_pstk_shape_swap_layer(proto, dst_idx, src_idx); + + pse_ps2dlg(pse->parent_hid_ctx, pse); + pse_change_callback(pse); + pcb_gui->invalidate_all(); +} + + +static void pse_shape_bloat(void *hid_ctx, void *caller_data, pcb_coord_t sign) +{ + pse_t *pse = caller_data; + pcb_pstk_proto_t *proto = pcb_pstk_get_proto(pse->ps); + pcb_pstk_tshape_t *ts = &proto->tr.array[0]; + int n, dst_idx = pcb_pstk_get_shape_idx(ts, pcb_proto_layers[pse->editing_shape].mask, pcb_proto_layers[pse->editing_shape].comb); + pcb_coord_t bloat = pse->shape_chg[pse->amount].default_val.coord_value; + + if (bloat <= 0) + return; + + if (dst_idx < 0) { + pcb_message(PCB_MSG_ERROR, "Can't copy shape: source shape (%s) is empty\n", pcb_proto_layers[pse->editing_shape].name); + return; + } + + bloat *= sign; + for(n = 0; n < proto->tr.used; n++) + pcb_pstk_shape_grow(&proto->tr.array[n].shape[dst_idx], pcb_false, bloat); + + pcb_pstk_proto_update(proto); + + pse_ps2dlg(pse->parent_hid_ctx, pse); + pse_change_callback(pse); + pcb_gui->invalidate_all(); +} + +static void pse_shape_shrink(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + pse_shape_bloat(hid_ctx, caller_data, -1); +} + +static void pse_shape_grow(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + pse_shape_bloat(hid_ctx, caller_data, +1); +} + +static void pse_chg_shape(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + pse_t *pse = caller_data; + int n; + char tmp[256]; + const char *copy_from_names[pcb_proto_num_layers+1]; + pcb_hid_dad_buttons_t clbtn[] = {{"Close", 0}, {NULL, 0}}; + PCB_DAD_DECL(dlg); + + pse->parent_hid_ctx = hid_ctx; + + for(n = 0; n < pcb_proto_num_layers; n++) + copy_from_names[n] = pcb_proto_layers[n].name; + copy_from_names[n] = NULL; + + pse->editing_shape = -1; + for(n = 0; n < pcb_proto_num_layers; n++) { + if (pse->proto_change[n] == (attr - pse->attrs)) { + pse->editing_shape = n; + break; + } + } + + PCB_DAD_BEGIN_VBOX(dlg); + sprintf(tmp, "Automatically generate shape for ..."); + PCB_DAD_LABEL(dlg, tmp); + PCB_DAD_LABEL(dlg, ""); + pse->text_shape = PCB_DAD_CURRENT(dlg); + PCB_DAD_BUTTON(dlg, "Delete (no shape)"); + pse->del = PCB_DAD_CURRENT(dlg); + PCB_DAD_CHANGE_CB(dlg, pse_shape_del); + PCB_DAD_HELP(dlg, "Remove the shape from this layer type"); + PCB_DAD_BUTTON(dlg, "Replace shape with hshadow"); + pse->hshadow = PCB_DAD_CURRENT(dlg); + PCB_DAD_CHANGE_CB(dlg, pse_shape_hshadow); + PCB_DAD_HELP(dlg, "Set shape to hshadow on this layer type\n(invisible shape with the same\ngeometry as the hole or slot, for proper clearance)"); + PCB_DAD_BUTTON(dlg, "Derive automatically"); + pse->derive = PCB_DAD_CURRENT(dlg); + PCB_DAD_CHANGE_CB(dlg, pse_shape_auto); + PCB_DAD_HELP(dlg, "Derive the shape for this layer type\nfrom other, existing shapes of this padstack\n(automatic)"); + PCB_DAD_BEGIN_HBOX(dlg); + PCB_DAD_BEGIN_VBOX(dlg); + PCB_DAD_BUTTON(dlg, "Copy shape from"); + pse->copy_do = PCB_DAD_CURRENT(dlg); + PCB_DAD_CHANGE_CB(dlg, pse_shape_copy); + PCB_DAD_HELP(dlg, "Copy the shape for this layer type\nfrom other, existing shapes of this padstack\nfrom the layer type selected"); + PCB_DAD_BUTTON(dlg, "Swap shape with"); + pse->copy_do = PCB_DAD_CURRENT(dlg); + PCB_DAD_CHANGE_CB(dlg, pse_shape_swap); + PCB_DAD_HELP(dlg, "Swap the shape for this layer type\nwith another, existing shapes of this padstack\nfrom the layer type selected"); + PCB_DAD_HELP(dlg, "Select the other layer type for swapping shape"); + PCB_DAD_END(dlg); + PCB_DAD_ENUM(dlg, copy_from_names); /* coposite */ + pse->copy_from = PCB_DAD_CURRENT(dlg); + PCB_DAD_HELP(dlg, "Select the source layer type for\nmanual shape copy or shape swap"); + PCB_DAD_END(dlg); + + PCB_DAD_BEGIN_HBOX(dlg); + PCB_DAD_BUTTON(dlg, "Shrink"); + pse->shrink = PCB_DAD_CURRENT(dlg); + PCB_DAD_CHANGE_CB(dlg, pse_shape_shrink); + PCB_DAD_HELP(dlg, "Make the shape smaller by the selected amount"); + PCB_DAD_COORD(dlg, ""); + pse->amount = PCB_DAD_CURRENT(dlg); + PCB_DAD_MINMAX(dlg, 1, PCB_MM_TO_COORD(100)); + PCB_DAD_BUTTON(dlg, "Grow"); + pse->grow = PCB_DAD_CURRENT(dlg); + PCB_DAD_CHANGE_CB(dlg, pse_shape_grow); + PCB_DAD_HELP(dlg, "Make the shape larger by the selected amount"); + PCB_DAD_END(dlg); + PCB_DAD_BUTTON_CLOSES(dlg, clbtn); + PCB_DAD_END(dlg); + + PCB_DAD_NEW("padstack_shape", dlg, "Edit padstack shape", pse, pcb_true, NULL); + pse->shape_chg = dlg; + +/* pse_ps2dlg(dlg_hid_ctx, pse);*/ + PCB_DAD_RUN(dlg); + + pse->shape_chg = NULL; + PCB_DAD_FREE(dlg); + pse_change_callback(pse); + pcb_gui->invalidate_all(); +} + +/* Auto gen shape on a single layer */ +static int pse_gen_shape(pcb_pstk_tshape_t *ts, pcb_layer_type_t lyt, int shape, pcb_coord_t size) +{ + int idx = ts->len; + + if (size <= 0) { + pcb_message(PCB_MSG_ERROR, "Invalid size - has to be larger than 0\n"); + return -1; + } + + ts->len++; + ts->shape = realloc(ts->shape, ts->len * sizeof(pcb_pstk_shape_t)); + + ts->shape[idx].layer_mask = lyt; + ts->shape[idx].comb = 0; + ts->shape[idx].clearance = 0; + + switch(shape) { + case 0: + ts->shape[idx].shape = PCB_PSSH_CIRC; + ts->shape[idx].data.circ.x = ts->shape[idx].data.circ.y = 0; + ts->shape[idx].data.circ.dia = size; + break; + case 1: + ts->shape[idx].shape = PCB_PSSH_POLY; + pcb_pstk_shape_alloc_poly(&ts->shape[idx].data.poly, 4); + ts->shape[idx].data.poly.x[0] = -size/2; + ts->shape[idx].data.poly.y[0] = -size/2; + ts->shape[idx].data.poly.x[1] = ts->shape[idx].data.poly.x[0]; + ts->shape[idx].data.poly.y[1] = ts->shape[idx].data.poly.y[0] + size; + ts->shape[idx].data.poly.x[2] = ts->shape[idx].data.poly.x[0] + size; + ts->shape[idx].data.poly.y[2] = ts->shape[idx].data.poly.y[0] + size; + ts->shape[idx].data.poly.x[3] = ts->shape[idx].data.poly.x[0] + size; + ts->shape[idx].data.poly.y[3] = ts->shape[idx].data.poly.y[0]; + break; + } + return 0; +} + +/* Auto derive shape from the related copper layer */ +static void pse_drv_shape(pcb_pstk_proto_t *proto, pcb_pstk_tshape_t *ts, pcb_layer_type_t lyt, int paste) +{ + int srci = (lyt & PCB_LYT_TOP) ? 0 : 1; + pcb_pstk_shape_derive(proto, -1, srci, PCB_PROTO_MASK_BLOAT, lyt | PCB_LYT_MASK, PCB_LYC_SUB|PCB_LYC_AUTO); + if (paste) + pcb_pstk_shape_derive(proto, -1, srci, 0, lyt | PCB_LYT_PASTE, PCB_LYC_AUTO); +} + +/* Auto gen shapes for all layers the user selected on the dialog plus add the hole */ +static void pse_gen(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + int err = 0; + pse_t *pse = caller_data; + pcb_pstk_proto_t proto; + int sides = pse->attrs[pse->gen_sides].default_val.int_value; + int shape = pse->attrs[pse->gen_shp].default_val.int_value; + int expose = pse->attrs[pse->gen_expose].default_val.int_value; + int paste = pse->attrs[pse->gen_paste].default_val.int_value; + pcb_coord_t size = pse->attrs[pse->gen_size].default_val.coord_value; + pcb_layer_type_t lyt = sides_lyt[sides]; + pcb_pstk_tshape_t *ts; + pcb_cardinal_t pid; + + memset(&proto, 0, sizeof(proto)); + + ts = pcb_vtpadstack_tshape_alloc_append(&proto.tr, 1); + ts->rot = 0.0; + ts->xmirror = 0; + ts->smirror = 0; + ts->len = 0; + + if (lyt & PCB_LYT_TOP) err |= pse_gen_shape(ts, PCB_LYT_COPPER | PCB_LYT_TOP, shape, size); + if (lyt & PCB_LYT_BOTTOM) err |= pse_gen_shape(ts, PCB_LYT_COPPER | PCB_LYT_BOTTOM, shape, size); + if (lyt & PCB_LYT_INTERN) err |= pse_gen_shape(ts, PCB_LYT_COPPER | PCB_LYT_INTERN, shape, size); + if (err) + return; + if (expose) { + if (lyt & PCB_LYT_TOP) pse_drv_shape(&proto, ts, PCB_LYT_TOP, paste); + if (lyt & PCB_LYT_BOTTOM) pse_drv_shape(&proto, ts, PCB_LYT_BOTTOM, paste); + } + + proto.hdia = pse->attrs[pse->gen_drill].default_val.coord_value; + proto.hplated = 1; + + pcb_pstk_proto_update(&proto); + if (pse->gen_shape_in_place) { + if (pcb_pstk_proto_replace(pse->data, pse->ps->proto, &proto) == PCB_PADSTACK_INVALID) + pcb_message(PCB_MSG_ERROR, "Internal error: pse_gen() failed to raplace padstack prototype\n"); + } + else { + pid = pcb_pstk_proto_insert_dup(pse->data, &proto, 1); + if (pid == PCB_PADSTACK_INVALID) + pcb_message(PCB_MSG_ERROR, "Internal error: pse_gen() failed to insert padstack prototype\n"); + else + pcb_pstk_change_instance(pse->ps, &pid, NULL, NULL, NULL, NULL); + } + + pse_ps2dlg(hid_ctx, pse); + PCB_DAD_SET_VALUE(hid_ctx, pse->tab, int_value, 1); /* switch to the prototype view where the new attributes are visible */ + pse_change_callback(pse); + pcb_gui->invalidate_all(); +} + +void pcb_pstkedit_dialog(pse_t *pse, int target_tab) +{ + int n; + const char *tabs[] = { "this instance", "prototype", "generate common geometry", NULL }; + pcb_hid_dad_buttons_t clbtn[] = {{"Close", 0}, {NULL, 0}}; + PCB_DAD_DECL(dlg); + + pse->disable_instance_tab = !!pse->disable_instance_tab; + target_tab -= pse->disable_instance_tab; + + PCB_DAD_BEGIN_VBOX(dlg); + PCB_DAD_COMPFLAG(dlg, PCB_HATF_EXPFILL); + PCB_DAD_BEGIN_TABBED(dlg, tabs + pse->disable_instance_tab); + pse->tab = PCB_DAD_CURRENT(dlg); + + if (!pse->disable_instance_tab) { + /* Tab 0: this instance */ + PCB_DAD_BEGIN_VBOX(dlg); + PCB_DAD_BEGIN_VBOX(dlg); + PCB_DAD_COMPFLAG(dlg, PCB_HATF_FRAME); + PCB_DAD_LABEL(dlg, "Settings that affect only this padstack instance"); + PCB_DAD_BEGIN_HBOX(dlg); + PCB_DAD_LABEL(dlg, "prototype"); + PCB_DAD_BUTTON(dlg, "#5"); + pse->proto_id = PCB_DAD_CURRENT(dlg); + PCB_DAD_CHANGE_CB(dlg, pse_chg_protoid); + PCB_DAD_HELP(dlg, "Padstack prototype ID\n(click to use a different prototype)"); + PCB_DAD_BUTTON(dlg, "Duplicate"); + PCB_DAD_HELP(dlg, "Copy padstack prototype to create a new prototype\nfor this padstack instance. Changes to the new\nprototype will not affect other users of the\noriginal prototye."); + PCB_DAD_CHANGE_CB(dlg, pse_chg_protodup); + PCB_DAD_END(dlg); + PCB_DAD_BEGIN_TABLE(dlg, 2); + PCB_DAD_LABEL(dlg, "Clearance"); + PCB_DAD_COORD(dlg, ""); + pse->clearance = PCB_DAD_CURRENT(dlg); + PCB_DAD_MINVAL(dlg, 0); + PCB_DAD_MAXVAL(dlg, PCB_MM_TO_COORD(1000)); + PCB_DAD_CHANGE_CB(dlg, pse_chg_instance); + PCB_DAD_HELP(dlg, "global clearance (affects all layers)"); + PCB_DAD_LABEL(dlg, "Rotation"); + PCB_DAD_REAL(dlg, ""); + pse->rot = PCB_DAD_CURRENT(dlg); + PCB_DAD_MINVAL(dlg, 0); + PCB_DAD_MAXVAL(dlg, 360); + PCB_DAD_CHANGE_CB(dlg, pse_chg_instance); + PCB_DAD_LABEL(dlg, "X-mirror"); + PCB_DAD_BOOL(dlg, ""); + pse->xmirror = PCB_DAD_CURRENT(dlg); + PCB_DAD_CHANGE_CB(dlg, pse_chg_instance); + PCB_DAD_LABEL(dlg, "S-mirror"); + PCB_DAD_BOOL(dlg, ""); + pse->smirror = PCB_DAD_CURRENT(dlg); + PCB_DAD_CHANGE_CB(dlg, pse_chg_instance); + PCB_DAD_END(dlg); + PCB_DAD_END(dlg); + PCB_DAD_END(dlg); + } + + /* Tab 1: prototype */ + PCB_DAD_BEGIN_VBOX(dlg); + PCB_DAD_BEGIN_VBOX(dlg); + PCB_DAD_LABEL(dlg, "Settings that affect all padstacks with the same prototype"); + PCB_DAD_COMPFLAG(dlg, PCB_HATF_FRAME); + PCB_DAD_LABEL(dlg, "Pad geometry per layer type:"); + PCB_DAD_BEGIN_TABLE(dlg, 5); + PCB_DAD_COMPFLAG(dlg, PCB_HATF_FRAME); + for(n = 0; n < pcb_proto_num_layers; n++) { + const char *layname = pcb_proto_layers[n].name; + char *layname_tmp = NULL; + char *help = NULL; + + if (pcb_proto_board_layer_for(PCB->Data, pcb_proto_layers[n].mask, pcb_proto_layers[n].comb) == -1) { + layname = layname_tmp = pcb_strdup_printf("(%s)", pcb_proto_layers[n].name); + help = "No board layer available for this layer type.\nThis shape will not show on the board\nuntil the corresponding layer in the matching layer group type is created."; + } + PCB_DAD_LABEL(dlg, layname); + if (help != NULL) + PCB_DAD_HELP(dlg, help); + PCB_DAD_LABEL(dlg, "-"); + pse->proto_shape[n] = PCB_DAD_CURRENT(dlg); + PCB_DAD_LABEL(dlg, "-"); + pse->proto_info[n] = PCB_DAD_CURRENT(dlg); + PCB_DAD_BUTTON(dlg, "change..."); + pse->proto_change[n] = PCB_DAD_CURRENT(dlg); + PCB_DAD_CHANGE_CB(dlg, pse_chg_shape); + PCB_DAD_HELP(dlg, "Change the shape on this layer type"); + PCB_DAD_COORD(dlg, ""); + pse->proto_clr[n] = PCB_DAD_CURRENT(dlg); + PCB_DAD_MINVAL(dlg, 1); + PCB_DAD_MAXVAL(dlg, PCB_MM_TO_COORD(1000)); + PCB_DAD_CHANGE_CB(dlg, pse_chg_proto_clr); + PCB_DAD_HELP(dlg, "local, per layer type clearance\n(only when global padstack clearance is 0)"); + free(layname_tmp); + } + PCB_DAD_END(dlg); + + PCB_DAD_BEGIN_HBOX(dlg); + PCB_DAD_COMPFLAG(dlg, PCB_HATF_FRAME); + PCB_DAD_LABEL(dlg, "Prototype name:"); + PCB_DAD_STRING(dlg); + PCB_DAD_CHANGE_CB(dlg, pse_chg_prname); + pse->prname = PCB_DAD_CURRENT(dlg); + PCB_DAD_END(dlg); + + PCB_DAD_LABEL(dlg, "Hole properties:"); + pse->hole_header = PCB_DAD_CURRENT(dlg); + + PCB_DAD_BEGIN_TABLE(dlg, 4); + + PCB_DAD_LABEL(dlg, "Diameter:"); + PCB_DAD_COORD(dlg, ""); + pse->hdia = PCB_DAD_CURRENT(dlg); + PCB_DAD_MINVAL(dlg, 0); + PCB_DAD_MAXVAL(dlg, PCB_MM_TO_COORD(1000)); + PCB_DAD_CHANGE_CB(dlg, pse_chg_hole); + PCB_DAD_LABEL(dlg, ""); /* dummy */ + PCB_DAD_LABEL(dlg, ""); /* dummy */ + + PCB_DAD_LABEL(dlg, "Hole/slot plating:"); + PCB_DAD_BOOL(dlg, ""); + pse->hplated = PCB_DAD_CURRENT(dlg); + PCB_DAD_CHANGE_CB(dlg, pse_chg_hole); + PCB_DAD_HELP(dlg, "A plated hole galvanically connects layers"); + PCB_DAD_LABEL(dlg, ""); /* dummy */ + PCB_DAD_LABEL(dlg, ""); /* dummy */ + + PCB_DAD_LABEL(dlg, "Hole/slot top:"); + PCB_DAD_INTEGER(dlg, ""); + pse->htop_val = PCB_DAD_CURRENT(dlg); + PCB_DAD_MINVAL(dlg, -(pse->pcb->LayerGroups.cache.copper_len-1)); + PCB_DAD_MAXVAL(dlg, pse->pcb->LayerGroups.cache.copper_len-1); + PCB_DAD_CHANGE_CB(dlg, pse_chg_hole); + PCB_DAD_HELP(dlg, "Blind/buried via/slot: top end of the hole"); + PCB_DAD_LABEL(dlg, ""); + pse->htop_text = PCB_DAD_CURRENT(dlg); + PCB_DAD_LABEL(dlg, ""); + pse->htop_layer = PCB_DAD_CURRENT(dlg); + + PCB_DAD_LABEL(dlg, "Hole/slot bottom:"); + PCB_DAD_INTEGER(dlg, ""); + pse->hbot_val = PCB_DAD_CURRENT(dlg); + PCB_DAD_MINVAL(dlg, -(pse->pcb->LayerGroups.cache.copper_len-1)); + PCB_DAD_MAXVAL(dlg, pse->pcb->LayerGroups.cache.copper_len-1); + PCB_DAD_CHANGE_CB(dlg, pse_chg_hole); + PCB_DAD_HELP(dlg, "Blind/buried via/slot: bottom end of the hole"); + PCB_DAD_LABEL(dlg, ""); + pse->hbot_text = PCB_DAD_CURRENT(dlg); + PCB_DAD_LABEL(dlg, ""); + pse->hbot_layer = PCB_DAD_CURRENT(dlg); + PCB_DAD_END(dlg); + PCB_DAD_END(dlg); + PCB_DAD_END(dlg); + + /* Tab 2: generate common geometry */ + PCB_DAD_BEGIN_VBOX(dlg); + PCB_DAD_BEGIN_VBOX(dlg); + PCB_DAD_LABEL(dlg, "Generate a new prototype using a few numeric input"); + + PCB_DAD_BEGIN_TABLE(dlg, 2); + PCB_DAD_LABEL(dlg, "Copper shape:"); + PCB_DAD_ENUM(dlg, shapes); + pse->gen_shp = PCB_DAD_CURRENT(dlg); + + PCB_DAD_LABEL(dlg, "Size (circle diameter or square side):"); + PCB_DAD_COORD(dlg, ""); + pse->gen_size = PCB_DAD_CURRENT(dlg); + PCB_DAD_MINVAL(dlg, 1); + PCB_DAD_MAXVAL(dlg, PCB_MM_TO_COORD(1000)); + + PCB_DAD_LABEL(dlg, "Drill diameter (0 means no hole):"); + PCB_DAD_COORD(dlg, ""); + pse->gen_drill = PCB_DAD_CURRENT(dlg); + PCB_DAD_MINVAL(dlg, 1); + PCB_DAD_MAXVAL(dlg, PCB_MM_TO_COORD(1000)); + + PCB_DAD_LABEL(dlg, "Copper shapes on:"); + PCB_DAD_ENUM(dlg, sides); + pse->gen_sides = PCB_DAD_CURRENT(dlg); + + PCB_DAD_LABEL(dlg, "Expose top/bottom copper:"); + PCB_DAD_BOOL(dlg, ""); + pse->gen_expose = PCB_DAD_CURRENT(dlg); + + PCB_DAD_LABEL(dlg, "Paste exposed copper:"); + PCB_DAD_BOOL(dlg, ""); + pse->gen_paste = PCB_DAD_CURRENT(dlg); + + PCB_DAD_LABEL(dlg, ""); + PCB_DAD_BUTTON(dlg, "Generate!"); + pse->gen_do = PCB_DAD_CURRENT(dlg); + PCB_DAD_CHANGE_CB(dlg, pse_gen); + PCB_DAD_END(dlg); + PCB_DAD_END(dlg); + PCB_DAD_END(dlg); + PCB_DAD_END(dlg); + PCB_DAD_BUTTON_CLOSES(dlg, clbtn); + PCB_DAD_END(dlg); + + PCB_DAD_NEW("padstack", dlg, "Edit padstack", pse, pcb_true, NULL); + pse->attrs = dlg; + pse_ps2dlg(dlg_hid_ctx, pse); + if (target_tab > 0) + PCB_DAD_SET_VALUE(dlg_hid_ctx, pse->tab, int_value, target_tab); + PCB_DAD_RUN(dlg); + + free((char *)pse->attrs[pse->prname].default_val.str_value); + + PCB_DAD_FREE(dlg); +} + +const char pcb_acts_PadstackEdit[] = "PadstackEdit(object, [tab])\n"; +const char pcb_acth_PadstackEdit[] = "interactive pad stack editor"; +fgw_error_t pcb_act_PadstackEdit(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + int op = F_Object, target_tab = -1; + pse_t pse; + + memset(&pse, 0, sizeof(pse)); + + PCB_ACT_MAY_CONVARG(1, FGW_KEYWORD, PadstackEdit, op = fgw_keyword(&argv[1])); + PCB_ACT_MAY_CONVARG(2, FGW_INT, PadstackEdit, target_tab = argv[2].val.nat_int); + PCB_ACT_IRES(0); + + if (op == F_Object) { + pcb_coord_t x, y; + void *ptr1, *ptr2 = NULL, *ptr3; + long type; + pcb_hid_get_coords("Click on a padstack to edit", &x, &y, 0); + type = pcb_search_screen(x, y, PCB_OBJ_PSTK | PCB_OBJ_SUBC_PART | PCB_LOOSE_SUBC, &ptr1, &ptr2, &ptr3); + if (type != PCB_OBJ_PSTK) { + pcb_message(PCB_MSG_ERROR, "Need a padstack.\n"); + PCB_ACT_IRES(1); + return 0; + } + pse.ps = ptr2; + } + else + PCB_ACT_FAIL(PadstackEdit); + + pse.pcb = pcb_data_get_top(pse.ps->parent.data); + if (pse.pcb == NULL) + pse.pcb = PCB; + + pse.data = pse.ps->parent.data; + assert(pse.ps->parent_type == PCB_PARENT_DATA); + + pcb_pstkedit_dialog(&pse, target_tab); + + PCB_ACT_IRES(0); + return 0; +} + Index: tags/2.1.2/src_plugins/dialogs/dlg_padstack.h =================================================================== --- tags/2.1.2/src_plugins/dialogs/dlg_padstack.h (nonexistent) +++ tags/2.1.2/src_plugins/dialogs/dlg_padstack.h (revision 24813) @@ -0,0 +1,46 @@ +#include "obj_pstk.h" + +typedef struct pse_s pse_t; +struct pse_s { + /* caller conf */ + int disable_instance_tab, gen_shape_in_place; + pcb_hid_attribute_t *attrs; + pcb_board_t *pcb; + pcb_data_t *data; /* parent data where the proto is sitting; might be a subc */ + pcb_pstk_t *ps; + + /* optional hooks */ + void *user_data; /* owned by the caller who sets up the struct */ + void (*change_cb)(pse_t *pse); + + /* internal states */ + int tab; + + /* widget IDs */ + int but_instance, but_prototype; + int proto_id, clearance, rot, xmirror, smirror; + int proto_shape[pcb_proto_num_layers]; + int proto_info[pcb_proto_num_layers]; + int proto_change[pcb_proto_num_layers]; + pcb_coord_t proto_clr[pcb_proto_num_layers]; + int prname; + int hole_header; + int hdia, hplated; + int htop_val, htop_text, htop_layer; + int hbot_val, hbot_text, hbot_layer; + int gen_shp, gen_size, gen_drill, gen_sides, gen_expose, gen_paste, gen_do; + + /* sub-dialog: shape change */ + void *parent_hid_ctx; + int editing_shape; /* index of the shape being edited */ + pcb_hid_attribute_t *shape_chg; + int text_shape, del, derive, hshadow; + int copy_do, copy_from; + int shrink, amount, grow; +}; + +void pcb_pstkedit_dialog(pse_t *pse, int target_tab); + +extern const char pcb_acts_PadstackEdit[]; +extern const char pcb_acth_PadstackEdit[]; +fgw_error_t pcb_act_PadstackEdit(fgw_arg_t *res, int argc, fgw_arg_t *argv); Index: tags/2.1.2/src_plugins/dialogs/dlg_pinout.c =================================================================== --- tags/2.1.2/src_plugins/dialogs/dlg_pinout.c (nonexistent) +++ tags/2.1.2/src_plugins/dialogs/dlg_pinout.c (revision 24813) @@ -0,0 +1,188 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2018,2019 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include +#include "build_run.h" +#include "pcb-printf.h" +#include "obj_subc_parent.h" +#include "draw.h" +#include "obj_term.h" +#include "rtree.h" +#include "search.h" +#include "search_r.h" +#include "netlist2.h" + +typedef struct{ + PCB_DAD_DECL_NOINIT(dlg) + pcb_board_t *pcb; /* for netlist lookups */ + pcb_data_t *data; + long subc_id; + + int w_lab_num, w_lab_name, w_lab_net; + + pcb_subc_t *tempsc; /* non-persistent, should be used only within the scope of a callback, recirsively down */ +} pinout_ctx_t; + +pinout_ctx_t pinout_ctx; + +static void pinout_close_cb(void *caller_data, pcb_hid_attr_ev_t ev) +{ + pinout_ctx_t *ctx = caller_data; + PCB_DAD_FREE(ctx->dlg); + free(ctx); +} + + +static void pinout_expose(pcb_hid_attribute_t *attrib, pcb_hid_preview_t *prv, pcb_hid_gc_t gc, const pcb_hid_expose_ctx_t *e) +{ + pinout_ctx_t *ctx = prv->user_ctx; + void *r1, *r2, *r3; + + pcb_objtype_t type = pcb_search_obj_by_id_(ctx->data, &r1, &r2, &r3, ctx->subc_id, PCB_OBJ_SUBC); + if (type == PCB_OBJ_SUBC) { + pcb_subc_t *sc = r2; + int orig_po = pcb_draw_force_termlab; + pcb_draw_force_termlab = pcb_true; + pcb_subc_draw_preview(sc, &e->view); + pcb_draw_force_termlab = orig_po; + } + else { + char tmp[128]; + pcb_box_t bbox; + sprintf(tmp, "Subcircuit #%ld not found.", ctx->subc_id); + bbox.X1 = bbox.Y1 = 0; + bbox.X2 = bbox.Y2 = PCB_MM_TO_COORD(10); + pcb_dad_preview_zoomto(attrib, &bbox); + pcb_gui->set_color(gc, pcb_color_red); + pcb_text_draw_string_simple(NULL, tmp, PCB_MM_TO_COORD(1), PCB_MM_TO_COORD(20), 100, 0, 0, 0, 0, 0, 0); + } +} + +static pcb_r_dir_t pinout_mouse_search_cb(void *closure, pcb_any_obj_t *obj, void *box) +{ + pinout_ctx_t *ctx = closure; + pcb_hid_attr_val_t val; + + if ((obj->term != NULL) && (pcb_obj_parent_subc(obj) == ctx->tempsc) && (obj->term != NULL)) { + val.str_value = obj->term; + pcb_gui->attr_dlg_set_value(ctx->dlg_hid_ctx, ctx->w_lab_num, &val); + val.str_value = pcb_attribute_get(&obj->Attributes, "name"); + if (val.str_value != NULL) + pcb_gui->attr_dlg_set_value(ctx->dlg_hid_ctx, ctx->w_lab_name, &val); + if (ctx->pcb != NULL) { + { + pcb_net_term_t *term = pcb_net_find_by_obj(&ctx->pcb->netlist[PCB_NETLIST_EDITED], obj); + if (term != NULL) { + val.str_value = term->parent.net->name; + pcb_gui->attr_dlg_set_value(ctx->dlg_hid_ctx, ctx->w_lab_net, &val); + } + } + } + } + return PCB_R_DIR_NOT_FOUND; +} + +static pcb_bool pinout_mouse(pcb_hid_attribute_t *attrib, pcb_hid_preview_t *prv, pcb_hid_mouse_ev_t kind, pcb_coord_t x, pcb_coord_t y) +{ + if (kind == PCB_HID_MOUSE_RELEASE) { + pinout_ctx_t *ctx = prv->user_ctx; + void *r1, *r2, *r3; + pcb_objtype_t type; + pcb_box_t b; + pcb_hid_attr_val_t val; + + val.str_value = "n/a"; + pcb_gui->attr_dlg_set_value(ctx->dlg_hid_ctx, ctx->w_lab_num, &val); + pcb_gui->attr_dlg_set_value(ctx->dlg_hid_ctx, ctx->w_lab_name, &val); + pcb_gui->attr_dlg_set_value(ctx->dlg_hid_ctx, ctx->w_lab_net, &val); + + type = pcb_search_obj_by_id_(ctx->data, &r1, &r2, &r3, ctx->subc_id, PCB_OBJ_SUBC); + if (type != PCB_OBJ_SUBC) + return pcb_false; + ctx->tempsc = r2; + + b.X1 = x; + b.Y1 = y; + b.X2 = x+1; + b.Y2 = y+1; + pcb_search_data_by_loc(ctx->data, PCB_TERM_OBJ_TYPES, &b, pinout_mouse_search_cb, ctx); + ctx->tempsc = NULL; + } + + return pcb_false; +} + +static void pcb_dlg_pinout(pcb_board_t *pcb, pcb_data_t *data, pcb_subc_t *sc) +{ + char title[64]; + pcb_hid_dad_buttons_t clbtn[] = {{"Close", 0}, {NULL, 0}}; + pinout_ctx_t *ctx = calloc(sizeof(pinout_ctx_t), 1); + + ctx->pcb = pcb; + ctx->data = data; + ctx->subc_id = sc->ID; + PCB_DAD_BEGIN_VBOX(ctx->dlg); + PCB_DAD_COMPFLAG(ctx->dlg, PCB_HATF_EXPFILL); + PCB_DAD_PREVIEW(ctx->dlg, pinout_expose, pinout_mouse, NULL, &sc->BoundingBox, 200, 200, ctx); + PCB_DAD_BEGIN_HBOX(ctx->dlg); + PCB_DAD_LABEL(ctx->dlg, "Term ID:"); + PCB_DAD_LABEL(ctx->dlg, ""); + ctx->w_lab_num = PCB_DAD_CURRENT(ctx->dlg); + PCB_DAD_LABEL(ctx->dlg, "Term name:"); + PCB_DAD_LABEL(ctx->dlg, ""); + ctx->w_lab_name = PCB_DAD_CURRENT(ctx->dlg); + PCB_DAD_END(ctx->dlg); + + PCB_DAD_BEGIN_HBOX(ctx->dlg); + PCB_DAD_LABEL(ctx->dlg, "Net:"); + PCB_DAD_LABEL(ctx->dlg, ""); + ctx->w_lab_net = PCB_DAD_CURRENT(ctx->dlg); + PCB_DAD_END(ctx->dlg); + PCB_DAD_BUTTON_CLOSES(ctx->dlg, clbtn); + PCB_DAD_END(ctx->dlg); + + if (sc->refdes != NULL) + sprintf(title, "Subcircuit #%ld (%s) pinout", sc->ID, sc->refdes); + else + sprintf(title, "Subcircuit #%ld pinout", sc->ID); + PCB_DAD_NEW("pinout", ctx->dlg, title, ctx, pcb_false, pinout_close_cb); +} + +static const char pcb_acts_Pinout[] = "Pinout()\n"; +static const char pcb_acth_Pinout[] = "Present the subcircuit pinout box"; +static fgw_error_t pcb_act_Pinout(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + void *r1, *r2, *r3; + pcb_objtype_t type = pcb_search_obj_by_location(PCB_OBJ_SUBC, &r1, &r2, &r3, pcb_crosshair.X, pcb_crosshair.Y, 1); + if (type == PCB_OBJ_SUBC) { + pcb_subc_t *sc = r2; + pcb_dlg_pinout(PCB, PCB->Data, sc); + PCB_ACT_IRES(0); + } + else + PCB_ACT_IRES(-1); + return 0; +} Index: tags/2.1.2/src_plugins/dialogs/dlg_plugins.c =================================================================== --- tags/2.1.2/src_plugins/dialogs/dlg_plugins.c (nonexistent) +++ tags/2.1.2/src_plugins/dialogs/dlg_plugins.c (revision 24813) @@ -0,0 +1,89 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2015,2018 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +static const char pcb_acts_ManagePlugins[] = "ManagePlugins()\n"; +static const char pcb_acth_ManagePlugins[] = "Manage plugins dialog."; +static fgw_error_t pcb_act_ManagePlugins(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + pup_plugin_t *p; + int nump = 0, numb = 0; + gds_t str; + pcb_hid_dad_buttons_t clbtn[] = {{"Close", 0}, {NULL, 0}}; + PCB_DAD_DECL(dlg); + + gds_init(&str); + + for (p = pcb_pup.plugins; p != NULL; p = p->next) + if (p->flags & PUP_FLG_STATIC) + numb++; + else + nump++; + + gds_append_str(&str, "Plugins loaded:\n"); + if (nump > 0) { + for (p = pcb_pup.plugins; p != NULL; p = p->next) { + if (!(p->flags & PUP_FLG_STATIC)) { + gds_append(&str, ' '); + gds_append_str(&str, p->name); + gds_append(&str, ' '); + gds_append_str(&str, p->path); + gds_append(&str, '\n'); + } + } + } + else + gds_append_str(&str, " (none)\n"); + + gds_append_str(&str, "\n\nBuildins:\n"); + if (numb > 0) { + for (p = pcb_pup.plugins; p != NULL; p = p->next) { + if (p->flags & PUP_FLG_STATIC) { + gds_append(&str, ' '); + gds_append_str(&str, p->name); + gds_append(&str, '\n'); + } + } + } + else + gds_append_str(&str, " (none)\n"); + + gds_append_str(&str, "\n\nNOTE: this is the alpha version, can only list plugins/buildins\n"); + + + PCB_DAD_BEGIN_VBOX(dlg); + PCB_DAD_COMPFLAG(dlg, PCB_HATF_SCROLL | PCB_HATF_EXPFILL); + PCB_DAD_LABEL(dlg, str.array); + PCB_DAD_BUTTON_CLOSES(dlg, clbtn); + PCB_DAD_END(dlg); + + PCB_DAD_NEW("plugins", dlg, "Manage plugins", NULL, pcb_true, NULL); + PCB_DAD_RUN(dlg); + PCB_DAD_FREE(dlg); + + gds_uninit(&str); + PCB_ACT_IRES(0); + return 0; +} Index: tags/2.1.2/src_plugins/dialogs/dlg_pref.c =================================================================== --- tags/2.1.2/src_plugins/dialogs/dlg_pref.c (nonexistent) +++ tags/2.1.2/src_plugins/dialogs/dlg_pref.c (revision 24813) @@ -0,0 +1,394 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2018 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +/* The preferences dialog, invoked by the Preferences() action */ + +#include "config.h" + +#include +#include +#include "actions.h" +#include "build_run.h" +#include "pcb-printf.h" +#include "error.h" +#include "event.h" +#include "conf.h" +#include "conf_hid.h" +#include "hid_dad.h" +#include "hid_dad_tree.h" + +#include "dlg_pref.h" + +#include "dlg_pref_sizes.c" +#include "dlg_pref_board.c" +#include "dlg_pref_general.c" +#include "dlg_pref_lib.c" +#include "dlg_pref_layer.c" +#include "dlg_pref_color.c" +#include "dlg_pref_win.c" +#include "dlg_pref_conf.c" + +pref_ctx_t pref_ctx; +static const char *pref_cookie = "preferences dialog"; +conf_hid_id_t pref_hid; + +static const char *role_names[] = { "user", "project", "design", "cli", NULL }; +static const conf_role_t roles[] = { CFR_USER, CFR_PROJECT, CFR_DESIGN, CFR_CLI, 0 }; + +void pcb_pref_conf2dlg_item(conf_native_t *cn, pref_confitem_t *item) +{ + switch(cn->type) { + case CFN_COORD: + PCB_DAD_SET_VALUE(pref_ctx.dlg_hid_ctx, item->wid, coord_value, cn->val.coord[0]); + break; + case CFN_BOOLEAN: + case CFN_INTEGER: + PCB_DAD_SET_VALUE(pref_ctx.dlg_hid_ctx, item->wid, int_value, cn->val.integer[0]); + break; + case CFN_REAL: + PCB_DAD_SET_VALUE(pref_ctx.dlg_hid_ctx, item->wid, real_value, cn->val.real[0]); + break; + case CFN_STRING: + PCB_DAD_SET_VALUE(pref_ctx.dlg_hid_ctx, item->wid, str_value, cn->val.string[0]); + break; + default: pcb_message(PCB_MSG_ERROR, "pcb_pref_conf2dlg_item(): widget type not handled\n"); + } +} + +void pcb_pref_dlg2conf_item(pref_ctx_t *ctx, pref_confitem_t *item, pcb_hid_attribute_t *attr) +{ + pref_confitem_t *old = ctx->conf_lock; + conf_native_t *cn = conf_get_field(item->confpath); + + if (cn == NULL) + return; + + ctx->conf_lock = item; + switch(cn->type) { + case CFN_COORD: + if (cn->val.coord[0] != attr->default_val.coord_value) + conf_setf(ctx->role, item->confpath, -1, "%.8$mm", attr->default_val.coord_value); + break; + case CFN_BOOLEAN: + case CFN_INTEGER: + if (cn->val.integer[0] != attr->default_val.int_value) + conf_setf(ctx->role, item->confpath, -1, "%d", attr->default_val.int_value); + break; + case CFN_REAL: + if (cn->val.real[0] != attr->default_val.real_value) + conf_setf(ctx->role, item->confpath, -1, "%f", attr->default_val.real_value); + break; + case CFN_STRING: + if (strcmp(cn->val.string[0], attr->default_val.str_value) != 0) + conf_set(ctx->role, item->confpath, -1, attr->default_val.str_value, POL_OVERWRITE); + break; + default: pcb_message(PCB_MSG_ERROR, "pcb_pref_dlg2conf_item(): widget type not handled\n"); + } + ctx->conf_lock = old; +} + +pcb_bool pcb_pref_dlg2conf_table(pref_ctx_t *ctx, pref_confitem_t *list, pcb_hid_attribute_t *attr) +{ + pref_confitem_t *c; + int wid = attr - ctx->dlg; + + for(c = list; c->confpath != NULL; c++) { + if (c->wid == wid) { + pcb_pref_dlg2conf_item(ctx, c, attr); + return 1; + } + } + return 0; +} + + +void pcb_pref_create_conf_item(pref_ctx_t *ctx, pref_confitem_t *item, void (*change_cb)(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr)) +{ + conf_native_t *cn = conf_get_field(item->confpath); + + if (cn == NULL) { + pcb_message(PCB_MSG_ERROR, "Internal error: pcb_pref_create_conf_item(): invalid conf node %s\n", item->confpath); + item->wid = -1; + return; + } + + PCB_DAD_LABEL(ctx->dlg, item->label); + PCB_DAD_HELP(ctx->dlg, cn->description); + + switch(cn->type) { + case CFN_COORD: + PCB_DAD_COORD(ctx->dlg, ""); + item->wid = PCB_DAD_CURRENT(ctx->dlg); + PCB_DAD_MINMAX(ctx->dlg, 0, PCB_MAX_COORD); + PCB_DAD_DEFAULT_NUM(ctx->dlg, cn->val.coord[0]); + PCB_DAD_HELP(ctx->dlg, cn->description); + PCB_DAD_CHANGE_CB(ctx->dlg, change_cb); + break; + case CFN_BOOLEAN: + PCB_DAD_BOOL(ctx->dlg, ""); + item->wid = PCB_DAD_CURRENT(ctx->dlg); + PCB_DAD_DEFAULT_NUM(ctx->dlg, cn->val.integer[0]); + PCB_DAD_HELP(ctx->dlg, cn->description); + PCB_DAD_CHANGE_CB(ctx->dlg, change_cb); + break; + case CFN_INTEGER: + PCB_DAD_INTEGER(ctx->dlg, ""); + item->wid = PCB_DAD_CURRENT(ctx->dlg); + PCB_DAD_MINMAX(ctx->dlg, 0, INT_MAX); + PCB_DAD_DEFAULT_NUM(ctx->dlg, cn->val.integer[0]); + PCB_DAD_HELP(ctx->dlg, cn->description); + PCB_DAD_CHANGE_CB(ctx->dlg, change_cb); + break; + case CFN_REAL: + PCB_DAD_REAL(ctx->dlg, ""); + item->wid = PCB_DAD_CURRENT(ctx->dlg); + PCB_DAD_MINMAX(ctx->dlg, 0, INT_MAX); + ctx->dlg[item->wid].default_val.real_value = cn->val.real[0]; + PCB_DAD_HELP(ctx->dlg, cn->description); + PCB_DAD_CHANGE_CB(ctx->dlg, change_cb); + break; + case CFN_STRING: + PCB_DAD_STRING(ctx->dlg); + item->wid = PCB_DAD_CURRENT(ctx->dlg); + ctx->dlg[item->wid].default_val.str_value = pcb_strdup(cn->val.string[0]); + PCB_DAD_HELP(ctx->dlg, cn->description); + PCB_DAD_CHANGE_CB(ctx->dlg, change_cb); + break; + default: + PCB_DAD_LABEL(ctx->dlg, "Internal error: pcb_pref_create_conf_item(): unhandled type"); + item->wid = -1; + return; + } + + item->cnext = conf_hid_get_data(cn, pref_hid); + conf_hid_set_data(cn, pref_hid, item); +} + +void pcb_pref_create_conftable(pref_ctx_t *ctx, pref_confitem_t *list, void (*change_cb)(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr)) +{ + pref_confitem_t *c; + for(c = list; c->confpath != NULL; c++) + pcb_pref_create_conf_item(ctx, c, change_cb); +} + +void pcb_pref_conflist_remove(pref_ctx_t *ctx, pref_confitem_t *list) +{ + pref_confitem_t *c; + for(c = list; c->confpath != NULL; c++) { + conf_native_t *cn = conf_get_field(c->confpath); + c->cnext = NULL; + if (cn != NULL) + conf_hid_set_data(cn, pref_hid, NULL); + } +} + +static void pref_role_cb(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + pref_ctx_t *ctx = caller_data; + ctx->role = roles[attr->default_val.int_value]; +} + +static void pref_close_cb(void *caller_data, pcb_hid_attr_ev_t ev) +{ + pref_ctx_t *ctx = caller_data; + + pcb_dlg_pref_sizes_close(ctx); + pcb_dlg_pref_board_close(ctx); + pcb_dlg_pref_general_close(ctx); + pcb_dlg_pref_lib_close(ctx); + pcb_dlg_pref_color_close(ctx); + pcb_dlg_pref_win_close(ctx); + + PCB_DAD_FREE(ctx->dlg); + memset(ctx, 0, sizeof(pref_ctx_t)); /* reset all states to the initial - includes ctx->active = 0; */ +} + +/* Compare inp to fixed in case insensitive manner; accept full length match + or if inp contains the first word of fixed. Returns 0 on accept. */ +static int pref_strcmp(const char *fixed, const char *inp) +{ + for(;;) { + if ((*inp == '\0') && ((*fixed == '\0') || (*fixed == ' '))) + return 0; + if (tolower(*fixed) != tolower(*inp)) + return -1; + fixed++; + inp++; + } +} + +static void pcb_dlg_pref(const char *target_tab_str, const char *tabarg) +{ + const char *tabs[] = { "General", "Board meta", "Sizes & DRC", "Library", "Layers", "Colors", "Window", "Config tree", NULL }; + pcb_hid_dad_buttons_t clbtn[] = {{"Close", 0}, {NULL, 0}}; + int target_tab = -1; + + if ((target_tab_str != NULL) && (*target_tab_str != '\0')) { + const char **t; + int tt; + + for(tt = 0, t = tabs; *t != NULL; t++,tt++) { + if (pref_strcmp(*t, target_tab_str) == 0) { + target_tab = tt; + break; + } + } + } + + if (pref_ctx.active) { + if (target_tab >= 0) + PCB_DAD_SET_VALUE(pref_ctx.dlg_hid_ctx, pref_ctx.wtab, int_value, target_tab); + return; + } + + PCB_DAD_BEGIN_VBOX(pref_ctx.dlg); + PCB_DAD_COMPFLAG(pref_ctx.dlg, PCB_HATF_EXPFILL); + PCB_DAD_BEGIN_TABBED(pref_ctx.dlg, tabs); + pref_ctx.wtab = PCB_DAD_CURRENT(pref_ctx.dlg); + PCB_DAD_BEGIN_VBOX(pref_ctx.dlg); /* General */ + pcb_dlg_pref_general_create(&pref_ctx); + PCB_DAD_END(pref_ctx.dlg); + + PCB_DAD_BEGIN_VBOX(pref_ctx.dlg); /* Board meta */ + pcb_dlg_pref_board_create(&pref_ctx); + PCB_DAD_END(pref_ctx.dlg); + + PCB_DAD_BEGIN_VBOX(pref_ctx.dlg); /* Sizes & DRC */ + pcb_dlg_pref_sizes_create(&pref_ctx); + PCB_DAD_END(pref_ctx.dlg); + + PCB_DAD_BEGIN_VBOX(pref_ctx.dlg); /* Library */ + pcb_dlg_pref_lib_create(&pref_ctx); + PCB_DAD_END(pref_ctx.dlg); + + PCB_DAD_BEGIN_VBOX(pref_ctx.dlg); /* Layers */ + pcb_dlg_pref_layer_create(&pref_ctx); + PCB_DAD_END(pref_ctx.dlg); + + PCB_DAD_BEGIN_VBOX(pref_ctx.dlg); /* Colors */ + pcb_dlg_pref_color_create(&pref_ctx); + PCB_DAD_END(pref_ctx.dlg); + + PCB_DAD_BEGIN_VBOX(pref_ctx.dlg); /* Window */ + pcb_dlg_pref_win_create(&pref_ctx); + PCB_DAD_END(pref_ctx.dlg); + + PCB_DAD_BEGIN_VBOX(pref_ctx.dlg); /* Config tree */ + pcb_dlg_pref_conf_create(&pref_ctx); + PCB_DAD_END(pref_ctx.dlg); + + PCB_DAD_END(pref_ctx.dlg); + PCB_DAD_BEGIN_VBOX(pref_ctx.dlg); + PCB_DAD_BEGIN_HBOX(pref_ctx.dlg); + PCB_DAD_COMPFLAG(pref_ctx.dlg, PCB_HATF_EXPFILL); + PCB_DAD_LABEL(pref_ctx.dlg, "All changes are made to role:"); + PCB_DAD_ENUM(pref_ctx.dlg, role_names); + pref_ctx.wrole = PCB_DAD_CURRENT(pref_ctx.dlg); + PCB_DAD_CHANGE_CB(pref_ctx.dlg, pref_role_cb); + PCB_DAD_BUTTON_CLOSES_NAKED(pref_ctx.dlg, clbtn); + PCB_DAD_END(pref_ctx.dlg); + PCB_DAD_END(pref_ctx.dlg); + PCB_DAD_END(pref_ctx.dlg); + + /* set up the context */ + pref_ctx.active = 1; + + PCB_DAD_NEW("preferences", pref_ctx.dlg, "pcb-rnd preferences", &pref_ctx, pcb_false, pref_close_cb); + + PCB_DAD_SET_VALUE(pref_ctx.dlg_hid_ctx, pref_ctx.wrole, int_value, 2); + pref_ctx.role = CFR_DESIGN; + + pcb_dlg_pref_lib_open(&pref_ctx); + pcb_dlg_pref_color_open(&pref_ctx); + pcb_dlg_pref_win_open(&pref_ctx); + pcb_dlg_pref_conf_open(&pref_ctx, (target_tab == sizeof(tabs)/sizeof(tabs[0]) - 2) ? tabarg : NULL); + if (target_tab >= 0) + PCB_DAD_SET_VALUE(pref_ctx.dlg_hid_ctx, pref_ctx.wtab, int_value, target_tab); +} + +static void pref_ev_board_changed(void *user_data, int argc, pcb_event_arg_t argv[]) +{ + pref_ctx_t *ctx = user_data; + if (!pref_ctx.active) + return; + + pref_sizes_brd2dlg(ctx); + pref_board_brd2dlg(ctx); + pref_color_brd2dlg(ctx); + pref_win_brd2dlg(ctx); +} + +static void pref_ev_board_meta_changed(void *user_data, int argc, pcb_event_arg_t argv[]) +{ + pref_ctx_t *ctx = user_data; + if (!pref_ctx.active) + return; + + pref_sizes_brd2dlg(ctx); + pref_board_brd2dlg(ctx); + pref_color_brd2dlg(ctx); + pref_win_brd2dlg(ctx); +} + +void pref_conf_changed(conf_native_t *cfg, int arr_idx) +{ + pref_confitem_t *i; + + for(i = conf_hid_get_data(cfg, pref_hid); i != NULL; i = i->cnext) + if (i != pref_ctx.conf_lock) + pcb_pref_conf2dlg_item(cfg, i); + + pcb_pref_dlg_conf_changed_cb(&pref_ctx, cfg, arr_idx); +} + +static conf_hid_callbacks_t pref_conf_cb; +void pcb_dlg_pref_init(void) +{ + pref_conf_cb.val_change_post = pref_conf_changed; + pcb_event_bind(PCB_EVENT_BOARD_CHANGED, pref_ev_board_changed, &pref_ctx, pref_cookie); + pcb_event_bind(PCB_EVENT_BOARD_META_CHANGED, pref_ev_board_meta_changed, &pref_ctx, pref_cookie); + pref_hid = conf_hid_reg(pref_cookie, &pref_conf_cb); + pcb_dlg_pref_sizes_init(&pref_ctx); + pcb_dlg_pref_lib_init(&pref_ctx); +} + +void pcb_dlg_pref_uninit(void) +{ + pcb_event_unbind_allcookie(pref_cookie); + conf_hid_unreg(pref_cookie); +} + +const char pcb_acts_Preferences[] = "Preferences([tabname])\n"; +const char pcb_acth_Preferences[] = "Present the preferences dialog, optionally opening the tab requested."; +fgw_error_t pcb_act_Preferences(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + const char *tab = NULL, *tabarg = NULL; + PCB_ACT_MAY_CONVARG(1, FGW_STR, Preferences, tab = argv[1].val.str); + PCB_ACT_MAY_CONVARG(2, FGW_STR, Preferences, tabarg = argv[2].val.str); + pcb_dlg_pref(tab, tabarg); + PCB_ACT_IRES(0); + return 0; +} Index: tags/2.1.2/src_plugins/dialogs/dlg_pref.h =================================================================== --- tags/2.1.2/src_plugins/dialogs/dlg_pref.h (nonexistent) +++ tags/2.1.2/src_plugins/dialogs/dlg_pref.h (revision 24813) @@ -0,0 +1,68 @@ +#ifndef PCB_DLG_PREF_H +#define PCB_DLG_PREF_H + +typedef struct pref_ctx_s pref_ctx_t; + +#include "conf.h" +#include "conf_hid.h" +#include "dlg_pref_sizes.h" +#include "dlg_pref_board.h" +#include "dlg_pref_general.h" +#include "dlg_pref_lib.h" +#include "dlg_pref_color.h" +#include "dlg_pref_win.h" +#include "dlg_pref_conf.h" + +typedef struct pref_conflist_s pref_confitem_t; +struct pref_conflist_s { + const char *label; + const char *confpath; + int wid; + pref_confitem_t *cnext; /* linked list for conf callback - should be NULL initially */ +}; + +struct pref_ctx_s { + PCB_DAD_DECL_NOINIT(dlg) + int wtab, wrole; + int active; /* already open - allow only one instance */ + + pref_sizes_t sizes; + pref_board_t board; + pref_general_t general; + pref_lib_t lib; + pref_color_t color; + pref_win_t win; + pref_conf_t conf; + + conf_role_t role; /* where changes are saved to */ + + pref_confitem_t *conf_lock; /* the item being changed - should be ignored in a conf change callback */ +}; + +extern pref_ctx_t pref_ctx; + +/* Create label-input widget pair for editing a conf item, or create whole + list of them */ +void pcb_pref_create_conf_item(pref_ctx_t *ctx, pref_confitem_t *item, void (*change_cb)(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr)); +void pcb_pref_create_conftable(pref_ctx_t *ctx, pref_confitem_t *list, void (*change_cb)(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr)); + +/* Set the config node from the current widget value of a conf item, or + create whole list of them; the table version returns whether the item is found. */ +void pcb_pref_dlg2conf_item(pref_ctx_t *ctx, pref_confitem_t *item, pcb_hid_attribute_t *attr); +pcb_bool pcb_pref_dlg2conf_table(pref_ctx_t *ctx, pref_confitem_t *list, pcb_hid_attribute_t *attr); + +/* Remove conf change binding - shall be called when widgets are removed + (i.e. on dialog box close) */ +void pcb_pref_conflist_remove(pref_ctx_t *ctx, pref_confitem_t *list); + +conf_hid_id_t pref_hid; + +/*** pulbic API for the caller ***/ +void pcb_dlg_pref_init(void); +void pcb_dlg_pref_uninit(void); + +extern const char pcb_acts_Preferences[]; +extern const char pcb_acth_Preferences[]; +fgw_error_t pcb_act_Preferences(fgw_arg_t *res, int argc, fgw_arg_t *argv); + +#endif Index: tags/2.1.2/src_plugins/dialogs/dlg_pref_board.c =================================================================== --- tags/2.1.2/src_plugins/dialogs/dlg_pref_board.c (nonexistent) +++ tags/2.1.2/src_plugins/dialogs/dlg_pref_board.c (revision 24813) @@ -0,0 +1,105 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2018 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +/* Preferences dialog, board tab */ + +#include "dlg_pref.h" +#include "conf.h" +#include "conf_core.h" + +#define PCB_EMPTY(a) ((a) ? (a) : "") + +/* Actual board meta to dialog box */ +static void pref_board_brd2dlg(pref_ctx_t *ctx) +{ + PCB_DAD_SET_VALUE(ctx->dlg_hid_ctx, ctx->board.wname, str_value, PCB_EMPTY(PCB->Name)); + PCB_DAD_SET_VALUE(ctx->dlg_hid_ctx, ctx->board.wthermscale, real_value, PCB->ThermScale); + PCB_DAD_SET_VALUE(ctx->dlg_hid_ctx, ctx->board.wtype, str_value, (PCB->is_footprint ? "footprint" : "PCB board")); +} + +/* Dialog box to actual board meta */ +static void pref_board_dlg2brd(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + int changed = 0; + const char *newname, *oldname; + double newtherm; + pref_ctx_t *ctx = caller_data; + + newname = PCB_EMPTY(ctx->dlg[ctx->board.wname].default_val.str_value); + oldname = PCB_EMPTY(PCB->Name); + if (strcmp(oldname, newname) != 0) { + free(PCB->Name); + PCB->Name = pcb_strdup(newname); + changed = 1; + } + + newtherm = ctx->dlg[ctx->board.wthermscale].default_val.real_value; + if (PCB->ThermScale != newtherm) { + PCB->ThermScale = newtherm; + changed = 1; + } + + if (changed) { + PCB->Changed = 1; + pcb_event(PCB_EVENT_BOARD_META_CHANGED, NULL); /* always generate the event to make sure visible changes are flushed */ + } +} + +static void pref_board_edit_attr(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + pcb_actionl("Propedit", "board", NULL); +} + + +void pcb_dlg_pref_board_close(pref_ctx_t *ctx) +{ + pcb_pref_conflist_remove(ctx, drc_sizes); +} + +void pcb_dlg_pref_board_create(pref_ctx_t *ctx) +{ + PCB_DAD_BEGIN_TABLE(ctx->dlg, 2); + PCB_DAD_LABEL(ctx->dlg, "Board name"); + PCB_DAD_STRING(ctx->dlg); + ctx->board.wname = PCB_DAD_CURRENT(ctx->dlg); + ctx->dlg[ctx->board.wname].default_val.str_value = pcb_strdup(PCB_EMPTY(PCB->Name)); + PCB_DAD_CHANGE_CB(ctx->dlg, pref_board_dlg2brd); + PCB_DAD_LABEL(ctx->dlg, "Thermal scale"); + PCB_DAD_REAL(ctx->dlg, ""); + ctx->board.wthermscale = PCB_DAD_CURRENT(ctx->dlg); + PCB_DAD_MINMAX(ctx->dlg, 0.01, 100); + ctx->dlg[ctx->board.wthermscale].default_val.real_value = PCB->ThermScale; + PCB_DAD_CHANGE_CB(ctx->dlg, pref_board_dlg2brd); + PCB_DAD_LABEL(ctx->dlg, "Type"); + PCB_DAD_LABEL(ctx->dlg, ""); + ctx->board.wtype = PCB_DAD_CURRENT(ctx->dlg); + ctx->dlg[ctx->board.wtype].name = pcb_strdup((PCB->is_footprint ? "footprint" : "PCB board")); + PCB_DAD_CHANGE_CB(ctx->dlg, pref_board_dlg2brd); + PCB_DAD_LABEL(ctx->dlg, "Board attributes"); + PCB_DAD_BUTTON(ctx->dlg, "Edit..."); + PCB_DAD_CHANGE_CB(ctx->dlg, pref_board_edit_attr); + PCB_DAD_END(ctx->dlg); +} Index: tags/2.1.2/src_plugins/dialogs/dlg_pref_board.h =================================================================== --- tags/2.1.2/src_plugins/dialogs/dlg_pref_board.h (nonexistent) +++ tags/2.1.2/src_plugins/dialogs/dlg_pref_board.h (revision 24813) @@ -0,0 +1,11 @@ +#ifndef PCB_DLG_PREF_BOARD_H +#define PCB_DLG_PREF_BOARD_H + +typedef struct { + int wname, wthermscale, wtype; +} pref_board_t; + +void pcb_dlg_pref_board_close(pref_ctx_t *ctx); +void pcb_dlg_pref_board_create(pref_ctx_t *ctx); + +#endif Index: tags/2.1.2/src_plugins/dialogs/dlg_pref_color.c =================================================================== --- tags/2.1.2/src_plugins/dialogs/dlg_pref_color.c (nonexistent) +++ tags/2.1.2/src_plugins/dialogs/dlg_pref_color.c (revision 24813) @@ -0,0 +1,156 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2018 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +/* Preferences dialog, color tab */ + +#include "dlg_pref.h" +#include "conf.h" +#include "conf_core.h" + +static void pref_color_brd2dlg(pref_ctx_t *ctx) +{ + conf_native_t *nat; + int n; + + if (ctx->color.wlayer != NULL) { + nat = conf_get_field("appearance/color/layer"); + for (n = 0; n < nat->used; n++) + PCB_DAD_SET_VALUE(ctx->dlg_hid_ctx, ctx->color.wlayer[n], clr_value, nat->val.color[n]); + } + + for(n = 0; n < ctx->color.ngen; n++) { + int w = ctx->color.wgen[n]; + const char *path = ctx->dlg[w].user_data; + nat = conf_get_field(path); + if (nat != NULL) + PCB_DAD_SET_VALUE(ctx->dlg_hid_ctx, w, clr_value, nat->val.color[0]); + } +} + + +void pcb_dlg_pref_color_open(pref_ctx_t *ctx) +{ + pref_color_brd2dlg(ctx); +} + +void pcb_dlg_pref_color_close(pref_ctx_t *ctx) +{ + int n; + + for(n = 0; n < ctx->color.ngen; n++) { + int w = ctx->color.wgen[n]; + free(ctx->dlg[w].user_data); + } + + free(ctx->color.wgen); + free(ctx->color.wlayer); +} + +static void pref_color_gen_cb(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + pref_ctx_t *ctx = caller_data; + const char *path = attr->user_data; + conf_setf(ctx->role, path, -1, "%s", attr->default_val.clr_value.str); + pcb_gui->invalidate_all(); +} + +static void pref_color_layer_cb(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + pref_ctx_t *ctx = caller_data; + int idx = (int *)attr->user_data - ctx->color.wlayer; + conf_setf(ctx->role, "appearance/color/layer", idx, "%s", attr->default_val.clr_value.str); +} + + +void pcb_dlg_pref_color_create(pref_ctx_t *ctx) +{ + static const char *tabs[] = { "Generic colors", "Default layer colors", NULL }; + conf_native_t *nat; + htsp_entry_t *e; + int n, pl, w; + const char *path_prefix = "appearance/color"; + + + PCB_DAD_COMPFLAG(ctx->dlg, PCB_HATF_EXPFILL); + PCB_DAD_BEGIN_TABBED(ctx->dlg, tabs); + PCB_DAD_COMPFLAG(ctx->dlg, PCB_HATF_EXPFILL | PCB_HATF_LEFT_TAB); + + PCB_DAD_BEGIN_VBOX(ctx->dlg); /* generic */ + PCB_DAD_COMPFLAG(ctx->dlg, PCB_HATF_EXPFILL | PCB_HATF_SCROLL); + pl = strlen(path_prefix); + + ctx->color.ngen = 0; + conf_fields_foreach(e) { + nat = e->value; + if ((strncmp(e->key, path_prefix, pl) == 0) && (nat->type == CFN_COLOR) && (nat->array_size == 1)) + ctx->color.ngen++; + } + ctx->color.wgen = calloc(sizeof(int), ctx->color.ngen); + + n = 0; + conf_fields_foreach(e) { + nat = e->value; + if ((strncmp(e->key, path_prefix, pl) == 0) && (nat->type == CFN_COLOR) && (nat->array_size == 1)) { + PCB_DAD_BEGIN_HBOX(ctx->dlg); + PCB_DAD_BEGIN_VBOX(ctx->dlg); + PCB_DAD_COLOR(ctx->dlg); + ctx->color.wgen[n] = w = PCB_DAD_CURRENT(ctx->dlg); + ctx->dlg[w].user_data = pcb_strdup(e->key); + PCB_DAD_CHANGE_CB(ctx->dlg, pref_color_gen_cb); + PCB_DAD_END(ctx->dlg); + PCB_DAD_LABEL(ctx->dlg, nat->description); + n++; + PCB_DAD_END(ctx->dlg); + } + } + PCB_DAD_END(ctx->dlg); + + PCB_DAD_BEGIN_VBOX(ctx->dlg); /* layer */ + PCB_DAD_COMPFLAG(ctx->dlg, PCB_HATF_EXPFILL | PCB_HATF_SCROLL); + nat = conf_get_field("appearance/color/layer"); + if (nat->type == CFN_COLOR) { + PCB_DAD_LABEL(ctx->dlg, "NOTE: these colors are used only\nwhen creating new layers."); + ctx->color.wlayer = calloc(sizeof(int), nat->used); + PCB_DAD_BEGIN_TABLE(ctx->dlg, 2); + for (n = 0; n < nat->used; n++) { + char tmp[32]; + PCB_DAD_COLOR(ctx->dlg); + ctx->color.wlayer[n] = w = PCB_DAD_CURRENT(ctx->dlg); + ctx->dlg[w].user_data = &ctx->color.wlayer[n]; + PCB_DAD_CHANGE_CB(ctx->dlg, pref_color_layer_cb); + sprintf(tmp, "Layer %d", n); + PCB_DAD_LABEL(ctx->dlg, tmp); + } + PCB_DAD_END(ctx->dlg); + } + else { + ctx->color.wlayer = NULL; + PCB_DAD_LABEL(ctx->dlg, "Broken internal configuration:\nno layer colors"); + } + PCB_DAD_END(ctx->dlg); + + PCB_DAD_END(ctx->dlg); +} Index: tags/2.1.2/src_plugins/dialogs/dlg_pref_color.h =================================================================== --- tags/2.1.2/src_plugins/dialogs/dlg_pref_color.h (nonexistent) +++ tags/2.1.2/src_plugins/dialogs/dlg_pref_color.h (revision 24813) @@ -0,0 +1,11 @@ +#ifndef PCB_DLG_PREF_COLOR_H +#define PCB_DLG_PREF_COLOR_H + +typedef struct { + int *wgen, *wlayer; + int ngen; +} pref_color_t; + +void pcb_dlg_pref_color_create(pref_ctx_t *ctx); + +#endif Index: tags/2.1.2/src_plugins/dialogs/dlg_pref_conf.c =================================================================== --- tags/2.1.2/src_plugins/dialogs/dlg_pref_conf.c (nonexistent) +++ tags/2.1.2/src_plugins/dialogs/dlg_pref_conf.c (revision 24813) @@ -0,0 +1,482 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2018,2019 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +/* Preferences dialog, conf tree tab */ + +#include "dlg_pref.h" +#include "conf.h" +#include "conf_core.h" +#include "misc_util.h" + +static const char *pref_conf_get_val(const lht_node_t *nd, const conf_native_t *nat, int idx); +#include "dlg_pref_confedit.c" + +/* how many chars per line in conf node description (determines window width vs. + window height */ +#define DESC_WRAP_WIDTH 50 + +static const char *type_tabs[CFN_max+2] = /* MUST MATCH conf_native_type_t */ + {"STRING", "BOOLEAN", "INTEGER", "REAL", "COORD", "UNIT", "COLOR", "LIST", "invalid", NULL}; + +static int conf_tree_cmp(const void *v1, const void *v2) +{ + const htsp_entry_t **e1 = (const htsp_entry_t **) v1, **e2 = (const htsp_entry_t **) v2; + return strcmp((*e1)->key, (*e2)->key); +} + +static void setup_tree(pref_ctx_t *ctx) +{ + char *cell[2] = {NULL}; + pcb_hid_attribute_t *attr = &ctx->dlg[ctx->conf.wtree]; + pcb_hid_tree_t *tree = (pcb_hid_tree_t *)attr->enumerations; + htsp_entry_t *e; + htsp_entry_t **sorted; + int num_paths, n; + char path[1024]; + + /* alpha sort keys for the more consistend UI */ + for(e = htsp_first(conf_fields), num_paths = 0; e; e = htsp_next(conf_fields, e)) + num_paths++; + sorted = malloc(sizeof(htsp_entry_t *) * num_paths); + for(e = htsp_first(conf_fields), n = 0; e; e = htsp_next(conf_fields, e), n++) + sorted[n] = e; + qsort(sorted, num_paths, sizeof(htsp_entry_t *), conf_tree_cmp); + + for(n = 0; n < num_paths; n++) { + char *basename, *bnsep; + pcb_hid_row_t *parent; + conf_native_t *nat; + + e = sorted[n]; + if (strlen(e->key) > sizeof(path) - 1) { + pcb_message(PCB_MSG_WARNING, "Warning: can't create config item for %s: path too long\n", e->key); + continue; + } + strcpy(path, e->key); + basename = strrchr(path, '/'); + if ((basename == NULL) || (basename == path)) { + pcb_message(PCB_MSG_WARNING, "Warning: can't create config item for %s: invalid path (node in root)\n", e->key); + continue; + } + bnsep = basename; + *basename = '\0'; + basename++; + + parent = pcb_dad_tree_mkdirp(tree, path, NULL); + if (parent == NULL) { + pcb_message(PCB_MSG_WARNING, "Warning: can't create config item for %s: invalid path\n", e->key); + continue; + } + + nat = e->value; + if (nat->array_size > 1) { + int i; + *bnsep = '/'; + parent = pcb_dad_tree_mkdirp(tree, path, NULL); + for(i = 0; i < nat->array_size; i++) { + cell[0] = pcb_strdup_printf("[%d]", i); + pcb_dad_tree_append_under(attr, parent, cell); + } + } + else { + cell[0] = pcb_strdup(basename); + pcb_dad_tree_append_under(attr, parent, cell); + } + } + free(sorted); +} + +static const char *pref_conf_get_val(const lht_node_t *nd, const conf_native_t *nat, int idx) +{ + lht_node_t *ni; + + switch (nd->type) { + case LHT_TEXT: return nd->data.text.value; break; + case LHT_LIST: + if (nat->array_size > 1) { + int idx2 = idx; + for(ni = nd->data.list.first; ni != NULL; ni = ni->next) { + if (idx2 == 0) { + if (ni->type == LHT_TEXT) + return ni->data.text.value; + return ""; + } + idx2--; + } + } + return ""; + case LHT_HASH: return ""; break; + case LHT_TABLE: return ""; break; + case LHT_SYMLINK: return ""; break; + case LHT_INVALID_TYPE: return ""; break; + } + return ""; +} + +static void setup_intree(pref_ctx_t *ctx, conf_native_t *nat, int idx) +{ + conf_role_t n; + pcb_hid_attribute_t *attr = &ctx->dlg[ctx->conf.wintree]; + pcb_hid_tree_t *tree = (pcb_hid_tree_t *)attr->enumerations; + pcb_hid_row_t *r; + + pcb_dad_tree_clear(tree); + + for(n = 0; n < CFR_max_real; n++) { + char *cell[5]= {NULL}; + cell[0] = pcb_strdup(conf_role_name(n)); + if (nat != NULL) { + lht_node_t *nd; + long prio = conf_default_prio[n]; + conf_policy_t pol = POL_OVERWRITE; + + nd = conf_lht_get_at(n, nat->hash_path, 0); + if (nd != NULL) { /* role, prio, policy, value */ + conf_get_policy_prio(nd, &pol, &prio); + cell[1] = pcb_strdup_printf("%ld", prio); + cell[2] = pcb_strdup(conf_policy_name(pol)); + cell[3] = pcb_strdup(pref_conf_get_val(nd, nat, idx)); + } + } + r = pcb_dad_tree_append(attr, NULL, cell); + r->user_data2.lng = n; + } +} + +static const char *print_conf_val(conf_native_type_t type, const confitem_t *val, char *buf, int sizebuf) +{ + const char *ret = buf; + + *buf = '\0'; + switch(type) { + case CFN_STRING: if (*val->string != NULL) ret = *val->string; break; + case CFN_BOOLEAN: strcpy(buf, *val->boolean ? "true" : "false"); break; + case CFN_INTEGER: sprintf(buf, "%ld", *val->integer); break; + case CFN_REAL: sprintf(buf, "%f", *val->real); break; + case CFN_COORD: pcb_snprintf(buf, sizebuf, "%mH\n%mm\n%ml", *val->coord, *val->coord, *val->coord); break; + case CFN_UNIT: strcpy(buf, (*val->unit)->suffix); break; + case CFN_COLOR: strcpy(buf, val->color->str); break; + case CFN_LIST: strcpy(buf, ""); break; + case CFN_max: strcpy(buf, ""); break; + } + return ret; +} + +static void dlg_conf_select_node(pref_ctx_t *ctx, const char *path, conf_native_t *nat, int idx) +{ + pcb_hid_attr_val_t hv; + char *tmp, buf[128]; + const char *rolename; + lht_node_t *src; + + if ((path != NULL) && (nat == NULL)) + nat = conf_get_field(path); + + if ((path == NULL) && (nat != NULL)) + path = nat->hash_path; + + ctx->conf.selected_nat = nat; + ctx->conf.selected_idx = idx; + + if (nat == NULL) { + hv.str_value = ""; + pcb_gui->attr_dlg_set_value(ctx->dlg_hid_ctx, ctx->conf.wname, &hv); + pcb_gui->attr_dlg_set_value(ctx->dlg_hid_ctx, ctx->conf.wdesc, &hv); + setup_intree(ctx, NULL, 0); + + hv.int_value = CFN_max; + pcb_gui->attr_dlg_set_value(ctx->dlg_hid_ctx, ctx->conf.wnattype, &hv); + + return; + } + + hv.str_value = path == NULL ? "" : path; + pcb_gui->attr_dlg_set_value(ctx->dlg_hid_ctx, ctx->conf.wname, &hv); + + tmp = pcb_strdup(nat->description); + pcb_text_wrap(tmp, DESC_WRAP_WIDTH, '\n', ' '); + hv.str_value = tmp; + pcb_gui->attr_dlg_set_value(ctx->dlg_hid_ctx, ctx->conf.wdesc, &hv); + free(tmp); + + /* display lht value */ + setup_intree(ctx, nat, idx); + + /* display native value */ + hv.int_value = nat->type; + pcb_gui->attr_dlg_set_value(ctx->dlg_hid_ctx, ctx->conf.wnattype, &hv); + + if (nat->type == CFN_LIST) { + /* non-default: lists are manually loaded */ + pcb_hid_attribute_t *attr = &ctx->dlg[ctx->conf.wnatval[CFN_LIST]]; + pcb_hid_tree_t *tree = (pcb_hid_tree_t *)attr->enumerations; + conf_listitem_t *n; + char *cell[4]; + + pcb_dad_tree_clear(tree); + for (n = conflist_first(&nat->val.list[idx]); n != NULL; n = conflist_next(n)) { + rolename = conf_role_name(conf_lookup_role(n->prop.src)); + cell[0] = rolename == NULL ? pcb_strdup("") : pcb_strdup(rolename); + cell[1] = pcb_strdup_printf("%ld", n->prop.prio); + cell[2] = pcb_strdup(print_conf_val(n->type, &n->val, buf, sizeof(buf))); + cell[3] = 0; + pcb_dad_tree_append(attr, NULL, cell); + } + return; + } + + /* default: set the value of the given node from hv loaded above */ + hv.str_value = print_conf_val(nat->type, &nat->val, buf, sizeof(buf)); + pcb_gui->attr_dlg_set_value(ctx->dlg_hid_ctx, ctx->conf.wnatval[nat->type], &hv); + + src = nat->prop[idx].src; + if (src != NULL) { + rolename = conf_role_name(conf_lookup_role(nat->prop[idx].src)); + hv.str_value = tmp = pcb_strdup_printf("prio: %d role: %s\nsource: %s:%d.%d", nat->prop[idx].prio, rolename, src->file_name, src->line, src->col); + } + else + hv.str_value = tmp = pcb_strdup_printf("prio: %d\nsource: ", nat->prop[idx].prio); + pcb_gui->attr_dlg_set_value(ctx->dlg_hid_ctx, ctx->conf.wsrc[nat->type], &hv); + free(tmp); + + return; +} + +static void dlg_conf_select_node_cb(pcb_hid_attribute_t *attrib, void *hid_ctx, pcb_hid_row_t *row) +{ + pcb_hid_tree_t *tree = (pcb_hid_tree_t *)attrib->enumerations; + char *end, *end2; + conf_native_t *nat; + + if (row == NULL) { /* deselect */ + dlg_conf_select_node((pref_ctx_t *)tree->user_ctx, NULL, NULL, 0); + return; + } + + end = strrchr(row->path, '/'); + if ((end != NULL) && (end[1] == '[')) { + int idx = strtol(end+2, &end2, 10); + /* if last segment is an [integer], it is an array */ + if (*end2 == ']') { + char tmp[1024]; + int len = end - row->path; + if ((len <= 0) || (len > sizeof(tmp)-1)) { + pcb_message(PCB_MSG_WARNING, "Warning: can't show array item %s: path too long\n", row->path); + return; + } + memcpy(tmp, row->path, len); + tmp[len] = '\0'; + dlg_conf_select_node((pref_ctx_t *)tree->user_ctx, tmp, NULL, idx); + } + return; + } + + /* non-array selection */ + nat = conf_get_field(row->path); + if ((nat != NULL) && (nat->array_size > 1)) { /* array head: do not display for now */ + dlg_conf_select_node((pref_ctx_t *)tree->user_ctx, NULL, NULL, 0); + return; + } + dlg_conf_select_node((pref_ctx_t *)tree->user_ctx, row->path, nat, 0); +} + + +void pcb_pref_dlg_conf_changed_cb(pref_ctx_t *ctx, conf_native_t *cfg, int arr_idx) +{ + if (ctx->conf.selected_nat == cfg) + dlg_conf_select_node(ctx, NULL, cfg, ctx->conf.selected_idx); +} + + +static void pcb_pref_dlg_conf_filter_cb(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr_inp) +{ + pref_ctx_t *ctx = caller_data; + pcb_hid_attribute_t *attr; + pcb_hid_tree_t *tree; + const char *text; + int have_filter_text; + + attr = &ctx->dlg[ctx->conf.wtree]; + tree = (pcb_hid_tree_t *)attr->enumerations; + text = attr_inp->default_val.str_value; + have_filter_text = (*text != '\0'); + + /* hide or unhide everything */ + pcb_dad_tree_hide_all(tree, &tree->rows, have_filter_text); + + if (have_filter_text) /* unhide hits and all their parents */ + pcb_dad_tree_unhide_filter(tree, &tree->rows, 0, text); + + pcb_dad_tree_update_hide(attr); +} + + +static void build_natval(pref_ctx_t *ctx) +{ + static const char *hdr_nat[] = {"role", "prio", "value", NULL}; + + PCB_DAD_BEGIN_TABBED(pref_ctx.dlg, type_tabs); + PCB_DAD_COMPFLAG(pref_ctx.dlg, PCB_HATF_EXPFILL | PCB_HATF_HIDE_TABLAB); + ctx->conf.wnattype = PCB_DAD_CURRENT(ctx->dlg); + PCB_DAD_BEGIN_VBOX(ctx->dlg); + PCB_DAD_LABEL(ctx->dlg, "Data type: string"); + PCB_DAD_LABEL(ctx->dlg, "role/prio"); + ctx->conf.wsrc[0] = PCB_DAD_CURRENT(ctx->dlg); + PCB_DAD_LABEL(ctx->dlg, "(data)"); + ctx->conf.wnatval[0] = PCB_DAD_CURRENT(ctx->dlg); + PCB_DAD_END(ctx->dlg); + PCB_DAD_BEGIN_VBOX(ctx->dlg); + PCB_DAD_LABEL(ctx->dlg, "Data type: boolean"); + PCB_DAD_LABEL(ctx->dlg, "role/prio"); + ctx->conf.wsrc[1] = PCB_DAD_CURRENT(ctx->dlg); + PCB_DAD_LABEL(ctx->dlg, "(data)"); + ctx->conf.wnatval[1] = PCB_DAD_CURRENT(ctx->dlg); + PCB_DAD_END(ctx->dlg); + PCB_DAD_BEGIN_VBOX(ctx->dlg); + PCB_DAD_LABEL(ctx->dlg, "Data type: integer"); + PCB_DAD_LABEL(ctx->dlg, "role/prio"); + ctx->conf.wsrc[2] = PCB_DAD_CURRENT(ctx->dlg); + PCB_DAD_LABEL(ctx->dlg, "(data)"); + ctx->conf.wnatval[2] = PCB_DAD_CURRENT(ctx->dlg); + PCB_DAD_END(ctx->dlg); + PCB_DAD_BEGIN_VBOX(ctx->dlg); + PCB_DAD_LABEL(ctx->dlg, "Data type: real"); + PCB_DAD_LABEL(ctx->dlg, "role/prio"); + ctx->conf.wsrc[3] = PCB_DAD_CURRENT(ctx->dlg); + PCB_DAD_LABEL(ctx->dlg, "(data)"); + ctx->conf.wnatval[3] = PCB_DAD_CURRENT(ctx->dlg); + PCB_DAD_END(ctx->dlg); + PCB_DAD_BEGIN_VBOX(ctx->dlg); + PCB_DAD_LABEL(ctx->dlg, "Data type: coord"); + PCB_DAD_LABEL(ctx->dlg, "role/prio"); + ctx->conf.wsrc[4] = PCB_DAD_CURRENT(ctx->dlg); + PCB_DAD_LABEL(ctx->dlg, "(data)"); + ctx->conf.wnatval[4] = PCB_DAD_CURRENT(ctx->dlg); + PCB_DAD_END(ctx->dlg); + PCB_DAD_BEGIN_VBOX(ctx->dlg); + PCB_DAD_LABEL(ctx->dlg, "Data type: unit"); + PCB_DAD_LABEL(ctx->dlg, "role/prio"); + ctx->conf.wsrc[5] = PCB_DAD_CURRENT(ctx->dlg); + PCB_DAD_LABEL(ctx->dlg, "(data)"); + ctx->conf.wnatval[5] = PCB_DAD_CURRENT(ctx->dlg); + PCB_DAD_END(ctx->dlg); + PCB_DAD_BEGIN_VBOX(ctx->dlg); + PCB_DAD_LABEL(ctx->dlg, "Data type: color"); + PCB_DAD_LABEL(ctx->dlg, "role/prio"); + ctx->conf.wsrc[6] = PCB_DAD_CURRENT(ctx->dlg); + PCB_DAD_LABEL(ctx->dlg, "(data)"); + ctx->conf.wnatval[6] = PCB_DAD_CURRENT(ctx->dlg); + PCB_DAD_END(ctx->dlg); + PCB_DAD_BEGIN_VBOX(ctx->dlg); + PCB_DAD_COMPFLAG(ctx->dlg, PCB_HATF_EXPFILL); + PCB_DAD_LABEL(ctx->dlg, "Data type: list of strings"); + ctx->conf.wsrc[7] = -1; + PCB_DAD_TREE(ctx->dlg, 3, 0, hdr_nat); /* input state */ + PCB_DAD_COMPFLAG(ctx->dlg, PCB_HATF_EXPFILL | PCB_HATF_SCROLL); + ctx->conf.wnatval[7] = PCB_DAD_CURRENT(ctx->dlg); + PCB_DAD_END(ctx->dlg); + PCB_DAD_BEGIN_VBOX(ctx->dlg); + PCB_DAD_LABEL(ctx->dlg, "(no conf node selected)"); + ctx->conf.wnatval[8] = PCB_DAD_CURRENT(ctx->dlg); + PCB_DAD_END(ctx->dlg); + PCB_DAD_END(ctx->dlg); +} + +void pcb_dlg_pref_conf_create(pref_ctx_t *ctx) +{ + static const char *hdr_intree[] = {"role", "prio", "policy", "value", NULL}; + + PCB_DAD_COMPFLAG(ctx->dlg, PCB_HATF_EXPFILL); + PCB_DAD_BEGIN_HPANE(ctx->dlg); + PCB_DAD_COMPFLAG(ctx->dlg, PCB_HATF_EXPFILL); + ctx->conf.wmainp = PCB_DAD_CURRENT(ctx->dlg); + + /* left: tree */ + PCB_DAD_BEGIN_VBOX(ctx->dlg); + PCB_DAD_COMPFLAG(ctx->dlg, PCB_HATF_EXPFILL); + PCB_DAD_TREE(ctx->dlg, 1, 1, NULL); + PCB_DAD_COMPFLAG(ctx->dlg, PCB_HATF_EXPFILL | PCB_HATF_SCROLL); + ctx->conf.wtree = PCB_DAD_CURRENT(ctx->dlg); + PCB_DAD_TREE_SET_CB(ctx->dlg, selected_cb, dlg_conf_select_node_cb); + PCB_DAD_TREE_SET_CB(ctx->dlg, ctx, ctx); + PCB_DAD_STRING(ctx->dlg); + PCB_DAD_HELP(ctx->dlg, "Filter text:\nlist conf nodes with\nmatching name only"); + PCB_DAD_CHANGE_CB(ctx->dlg, pcb_pref_dlg_conf_filter_cb); + ctx->conf.wfilter = PCB_DAD_CURRENT(ctx->dlg); + PCB_DAD_END(ctx->dlg); + + /* right: details */ + PCB_DAD_BEGIN_VPANE(ctx->dlg); + PCB_DAD_COMPFLAG(ctx->dlg, PCB_HATF_EXPFILL); + + /* right/top: conf file */ + PCB_DAD_BEGIN_VBOX(ctx->dlg); + PCB_DAD_COMPFLAG(ctx->dlg, PCB_HATF_FRAME); + PCB_DAD_LABEL(ctx->dlg, ""); + ctx->conf.wname = PCB_DAD_CURRENT(ctx->dlg); + PCB_DAD_LABEL(ctx->dlg, ""); + ctx->conf.wdesc = PCB_DAD_CURRENT(ctx->dlg); + PCB_DAD_LABEL(ctx->dlg, "INPUT: configuration node (\"file\" version)"); + PCB_DAD_TREE(ctx->dlg, 4, 0, hdr_intree); /* input state */ + ctx->conf.wintree = PCB_DAD_CURRENT(ctx->dlg); + PCB_DAD_BEGIN_HBOX(ctx->dlg); + PCB_DAD_BUTTON(ctx->dlg, "Edit selected..."); + PCB_DAD_CHANGE_CB(ctx->dlg, pref_conf_edit_cb); + PCB_DAD_BUTTON(ctx->dlg, "Remove selected"); + PCB_DAD_CHANGE_CB(ctx->dlg, pref_conf_del_cb); + PCB_DAD_END(ctx->dlg); + PCB_DAD_END(ctx->dlg); + + /* right/bottom: native file */ + PCB_DAD_BEGIN_VBOX(ctx->dlg); + PCB_DAD_COMPFLAG(ctx->dlg, PCB_HATF_EXPFILL | PCB_HATF_FRAME); + PCB_DAD_LABEL(ctx->dlg, "NATIVE: in-memory conf node after the merge"); + build_natval(ctx); + + PCB_DAD_END(ctx->dlg); + PCB_DAD_END(ctx->dlg); + PCB_DAD_END(ctx->dlg); + + setup_tree(ctx); + setup_intree(ctx, NULL, 0); +} + +void pcb_dlg_pref_conf_open(pref_ctx_t *ctx, const char *tabarg) +{ + pcb_hid_attr_val_t hv; + hv.real_value = 0.25; + pcb_gui->attr_dlg_set_value(ctx->dlg_hid_ctx, ctx->conf.wmainp, &hv); + + if (tabarg != NULL) { + pcb_hid_attr_val_t hv; + hv.str_value = pcb_strdup(tabarg); + pcb_gui->attr_dlg_set_value(ctx->dlg_hid_ctx, ctx->conf.wfilter, &hv); + pcb_pref_dlg_conf_filter_cb(ctx->dlg_hid_ctx, ctx, &ctx->dlg[ctx->conf.wfilter]); + pcb_dad_tree_expcoll(&ctx->dlg[ctx->conf.wtree], NULL, 1, 1); + } +} + + Index: tags/2.1.2/src_plugins/dialogs/dlg_pref_conf.h =================================================================== --- tags/2.1.2/src_plugins/dialogs/dlg_pref_conf.h (nonexistent) +++ tags/2.1.2/src_plugins/dialogs/dlg_pref_conf.h (revision 24813) @@ -0,0 +1,19 @@ +#ifndef PCB_DLG_PREF_CONF_H +#define PCB_DLG_PREF_CONF_H + +#include "conf.h" + +typedef struct { + int wtree, wintree, wdesc, wname, wmainp, wnattype, wfilter; + int wnatval[CFN_max+1], wsrc[CFN_max+1]; + conf_native_t *selected_nat; + int selected_idx; +} pref_conf_t; + +void pcb_dlg_pref_conf_close(pref_ctx_t *ctx); +void pcb_dlg_pref_conf_create(pref_ctx_t *ctx); +void pcb_dlg_pref_conf_open(pref_ctx_t *ctx, const char *tabarg); + +void pcb_pref_dlg_conf_changed_cb(pref_ctx_t *ctx, conf_native_t *cfg, int arr_idx); /* global conf change */ + +#endif Index: tags/2.1.2/src_plugins/dialogs/dlg_pref_confedit.c =================================================================== --- tags/2.1.2/src_plugins/dialogs/dlg_pref_confedit.c (nonexistent) +++ tags/2.1.2/src_plugins/dialogs/dlg_pref_confedit.c (revision 24813) @@ -0,0 +1,385 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2018 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +/* Preferences dialog, conf tree tab -> edit conf node (input side) popup */ + +#define is_read_only_(role) ((role == CFR_INTERNAL) || (role == CFR_SYSTEM) || (role == CFR_DEFAULTPCB)) +#define is_read_only(ctx) is_read_only_(ctx->role) + +typedef struct { + PCB_DAD_DECL_NOINIT(dlg) + + conf_native_t *nat; + int idx; + conf_role_t role; + + int wnewval, winsa; +} confedit_ctx_t; + +static void pref_conf_edit_close_cb(void *caller_data, pcb_hid_attr_ev_t ev) +{ + pref_ctx_t *ctx = caller_data; + PCB_DAD_FREE(ctx->dlg); + free(ctx); +} + +static void confedit_brd2dlg(confedit_ctx_t *ctx) +{ + pcb_hid_attr_val_t hv; + lht_node_t *nl, *nd = conf_lht_get_at(ctx->role, ctx->nat->hash_path, 1); + const char *val; + + if (ctx->idx >= ctx->nat->array_size) + return; /* shouldn't ever happen - we have checked this before creating the dialog! */ + + val = pref_conf_get_val(nd, ctx->nat, ctx->idx); + + switch(ctx->nat->type) { + case CFN_STRING: + hv.str_value = val; + pcb_gui->attr_dlg_set_value(ctx->dlg_hid_ctx, ctx->wnewval, &hv); + break; + case CFN_BOOLEAN: + case CFN_INTEGER: + hv.int_value = atoi(val); + pcb_gui->attr_dlg_set_value(ctx->dlg_hid_ctx, ctx->wnewval, &hv); + break; + case CFN_REAL: + hv.real_value = strtod(val, NULL); + pcb_gui->attr_dlg_set_value(ctx->dlg_hid_ctx, ctx->wnewval, &hv); + break; + case CFN_COORD: + hv.coord_value = pcb_get_value(val, NULL, NULL, NULL); + pcb_gui->attr_dlg_set_value(ctx->dlg_hid_ctx, ctx->wnewval, &hv); + break; + case CFN_UNIT: + { + const pcb_unit_t *u = get_unit_struct(val); + if (u != NULL) + hv.int_value = u - pcb_units; + else + hv.int_value = -1; + pcb_gui->attr_dlg_set_value(ctx->dlg_hid_ctx, ctx->wnewval, &hv); + } + break; + case CFN_COLOR: + hv.clr_value = ctx->nat->val.color[ctx->idx]; + pcb_color_load_str(&hv.clr_value, val); + pcb_gui->attr_dlg_set_value(ctx->dlg_hid_ctx, ctx->wnewval, &hv); + break; + case CFN_LIST: + { + pcb_hid_attribute_t *attr = &ctx->dlg[ctx->wnewval]; + pcb_hid_tree_t *tree = (pcb_hid_tree_t *)attr->enumerations; + + pcb_dad_tree_clear(tree); + if (nd->type != LHT_LIST) + return; + for(nl = nd->data.list.first; nl != NULL; nl = nl->next) { + char *cell[2] = {NULL}; + if (nl->type == LHT_TEXT) + cell[0] = pcb_strdup(nl->data.text.value); + pcb_dad_tree_append(attr, NULL, cell); + } + } + break; + case CFN_max: + PCB_DAD_LABEL(ctx->dlg, "ERROR: invalid conf node type"); + } +} + +static void pref_conf_editval_cb(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *trigger_attr) +{ + confedit_ctx_t *ctx = caller_data; + pcb_hid_attribute_t *attr; + char buf[128]; + const char *val = buf; + + if (ctx->idx >= ctx->nat->array_size) + return; /* shouldn't ever happen - we have checked this before creating the dialog! */ + + attr = &ctx->dlg[ctx->wnewval]; + + switch(ctx->nat->type) { + case CFN_STRING: val = attr->default_val.str_value; break; + case CFN_BOOLEAN: + case CFN_INTEGER: sprintf(buf, "%d", attr->default_val.int_value); break; + case CFN_REAL: sprintf(buf, "%f", attr->default_val.real_value); break; + case CFN_COORD: pcb_snprintf(buf, sizeof(buf), "%.08$mH", attr->default_val.coord_value); break; + case CFN_UNIT: + if ((attr->default_val.int_value < 0) || (attr->default_val.int_value >= pcb_get_n_units())) + return; + val = pcb_units[attr->default_val.int_value].suffix; + break; + case CFN_COLOR: val = attr->default_val.clr_value.str; break; + case CFN_LIST: + { + pcb_hid_attribute_t *attr = &ctx->dlg[ctx->wnewval]; + pcb_hid_tree_t *tree = (pcb_hid_tree_t *)attr->enumerations; + pcb_hid_row_t *r; + lht_node_t *nd = conf_lht_get_at(ctx->role, ctx->nat->hash_path, 0); + + if (nd == NULL) { + pcb_message(PCB_MSG_ERROR, "Internal error: can't copy back to non-existing list!\n"); + return; + } + + if (nd->type != LHT_LIST) { + pcb_message(PCB_MSG_ERROR, "Internal error: can't copy back list into non-list!\n"); + return; + } + + /* empty the list so that we insert to an empty list which is overwriting the list */ + while(nd->data.list.first != NULL) + lht_tree_del(nd->data.list.first); + + for(r = gdl_first(&tree->rows); r != NULL; r = gdl_next(&tree->rows, r)) { + lht_node_t *n = lht_dom_node_alloc(LHT_TEXT, NULL); + lht_dom_list_append(nd, n); + n->data.text.value = pcb_strdup(r->cell[0]); + } + conf_makedirty(ctx->role); + conf_update(ctx->nat->hash_path, ctx->idx); + } + return; + case CFN_max: + return; + } + + if (val == NULL) + val = ""; + conf_set(ctx->role, ctx->nat->hash_path, ctx->idx, val, POL_OVERWRITE); + + if ((ctx->role == CFR_USER) || (ctx->role == CFR_PROJECT)) + conf_save_file(NULL, (PCB == NULL ? NULL : PCB->Filename), ctx->role, NULL); + else if (ctx->role == CFR_DESIGN) + pcb_board_set_changed_flag(1); + + pcb_gui->invalidate_all(); +} + +static void pref_conf_editval_del_cb(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *trigger_attr) +{ + confedit_ctx_t *ctx = caller_data; + pcb_hid_attribute_t *attr = &ctx->dlg[ctx->wnewval]; + pcb_hid_row_t *r = pcb_dad_tree_get_selected(attr); + + if (r != NULL) { + pcb_dad_tree_remove(attr, r); + pref_conf_editval_cb(hid_ctx, caller_data, trigger_attr); + } +} + +static void pref_conf_editval_edit(void *hid_ctx, confedit_ctx_t *ctx, pcb_hid_attribute_t *attr, pcb_hid_row_t *r) +{ + char *nv = pcb_hid_prompt_for("list item value:", r->cell[0], "Edit config list item"); + if (nv == NULL) + return; + + if (pcb_dad_tree_modify_cell(attr, r, 0, pcb_strdup(nv)) == 0) + pref_conf_editval_cb(hid_ctx, ctx, attr); +} + +static void pref_conf_editval_edit_cb(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *trigger_attr) +{ + confedit_ctx_t *ctx = caller_data; + pcb_hid_attribute_t *attr = &ctx->dlg[ctx->wnewval]; + pcb_hid_row_t *r = pcb_dad_tree_get_selected(attr); + + if (r != NULL) + pref_conf_editval_edit(hid_ctx, ctx, attr, r); +} + +static void pref_conf_editval_ins_cb(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *trigger_attr) +{ + confedit_ctx_t *ctx = caller_data; + pcb_hid_attribute_t *attr = &ctx->dlg[ctx->wnewval]; + pcb_hid_row_t *r = pcb_dad_tree_get_selected(attr); + char *cols[] = {NULL, NULL}; + + cols[0] = pcb_strdup(""); + + if (trigger_attr == &ctx->dlg[ctx->winsa]) + r = pcb_dad_tree_append(attr, r, cols); + else + r = pcb_dad_tree_insert(attr, r, cols); + if (r != NULL) + pref_conf_editval_edit(hid_ctx, ctx, attr, r); +} + + +static void pref_conf_edit_cb(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + pcb_hid_dad_buttons_t clbtn[] = {{"Close", 0}, {NULL, 0}}; + pref_ctx_t *pctx = caller_data; + confedit_ctx_t *ctx; + pcb_hid_row_t *r; + int b[4] = {0}; + + if (pctx->conf.selected_nat == NULL) { + pcb_message(PCB_MSG_ERROR, "You need to select a conf leaf node to edit\nTry the tree on the left.\n"); + return; + } + + r = pcb_dad_tree_get_selected(&pctx->dlg[pctx->conf.wintree]); + if (r == NULL) { + pcb_message(PCB_MSG_ERROR, "You need to select a role (upper right list)\n"); + return; + } + + if (pctx->conf.selected_idx >= pctx->conf.selected_nat->array_size) { + pcb_message(PCB_MSG_ERROR, "Internal error: array index out of bounds\n"); + return; + } + + ctx = calloc(sizeof(confedit_ctx_t), 1); + ctx->nat = pctx->conf.selected_nat; + ctx->idx = pctx->conf.selected_idx; + ctx->role = r->user_data2.lng; + + PCB_DAD_BEGIN_VBOX(ctx->dlg); + PCB_DAD_COMPFLAG(ctx->dlg, PCB_HATF_EXPFILL); + + PCB_DAD_LABEL(ctx->dlg, ctx->nat->hash_path); + + switch(ctx->nat->type) { + case CFN_STRING: + PCB_DAD_STRING(ctx->dlg); + ctx->wnewval = PCB_DAD_CURRENT(ctx->dlg); + PCB_DAD_BUTTON(ctx->dlg, "apply"); + PCB_DAD_CHANGE_CB(ctx->dlg, pref_conf_editval_cb); + b[0] = PCB_DAD_CURRENT(ctx->dlg); + break; + case CFN_BOOLEAN: + PCB_DAD_BOOL(ctx->dlg, ""); + ctx->wnewval = PCB_DAD_CURRENT(ctx->dlg); + PCB_DAD_CHANGE_CB(ctx->dlg, pref_conf_editval_cb); + break; + case CFN_INTEGER: + PCB_DAD_INTEGER(ctx->dlg, ""); + ctx->wnewval = PCB_DAD_CURRENT(ctx->dlg); + PCB_DAD_MINMAX(ctx->dlg, -(1<<30), +(1<<30)); + PCB_DAD_BUTTON(ctx->dlg, "apply"); + PCB_DAD_CHANGE_CB(ctx->dlg, pref_conf_editval_cb); + b[0] = PCB_DAD_CURRENT(ctx->dlg); + break; + case CFN_REAL: + PCB_DAD_REAL(ctx->dlg, ""); + ctx->wnewval = PCB_DAD_CURRENT(ctx->dlg); + PCB_DAD_MINMAX(ctx->dlg, -(1<<30), +(1<<30)); + PCB_DAD_BUTTON(ctx->dlg, "apply"); + PCB_DAD_CHANGE_CB(ctx->dlg, pref_conf_editval_cb); + b[0] = PCB_DAD_CURRENT(ctx->dlg); + break; + case CFN_COORD: + PCB_DAD_COORD(ctx->dlg, ""); + ctx->wnewval = PCB_DAD_CURRENT(ctx->dlg); + PCB_DAD_MINMAX(ctx->dlg, -PCB_MM_TO_COORD(1000), +PCB_MM_TO_COORD(1000)); + PCB_DAD_BUTTON(ctx->dlg, "apply"); + PCB_DAD_CHANGE_CB(ctx->dlg, pref_conf_editval_cb); + b[0] = PCB_DAD_CURRENT(ctx->dlg); + break; + case CFN_UNIT: + PCB_DAD_UNIT(ctx->dlg); + ctx->wnewval = PCB_DAD_CURRENT(ctx->dlg); + PCB_DAD_CHANGE_CB(ctx->dlg, pref_conf_editval_cb); + break; + case CFN_COLOR: + PCB_DAD_COLOR(ctx->dlg); + ctx->wnewval = PCB_DAD_CURRENT(ctx->dlg); + PCB_DAD_CHANGE_CB(ctx->dlg, pref_conf_editval_cb); + break; + case CFN_LIST: + PCB_DAD_BEGIN_VBOX(ctx->dlg); + PCB_DAD_COMPFLAG(ctx->dlg, PCB_HATF_EXPFILL); + PCB_DAD_TREE(ctx->dlg, 1, 0, NULL); + PCB_DAD_COMPFLAG(ctx->dlg, PCB_HATF_EXPFILL | PCB_HATF_SCROLL); + ctx->wnewval = PCB_DAD_CURRENT(ctx->dlg); + PCB_DAD_BEGIN_HBOX(ctx->dlg); + PCB_DAD_BUTTON(ctx->dlg, "Edit..."); + PCB_DAD_CHANGE_CB(ctx->dlg, pref_conf_editval_edit_cb); + b[0] = PCB_DAD_CURRENT(ctx->dlg); + PCB_DAD_BUTTON(ctx->dlg, "Del"); + PCB_DAD_CHANGE_CB(ctx->dlg, pref_conf_editval_del_cb); + b[1] = PCB_DAD_CURRENT(ctx->dlg); + PCB_DAD_BUTTON(ctx->dlg, "Insert before"); + PCB_DAD_CHANGE_CB(ctx->dlg, pref_conf_editval_ins_cb); + b[2] = PCB_DAD_CURRENT(ctx->dlg); + PCB_DAD_BUTTON(ctx->dlg, "Insert after"); + PCB_DAD_CHANGE_CB(ctx->dlg, pref_conf_editval_ins_cb); + b[3] = ctx->winsa = PCB_DAD_CURRENT(ctx->dlg); + PCB_DAD_END(ctx->dlg); + PCB_DAD_END(ctx->dlg); + break; + case CFN_max: + PCB_DAD_LABEL(ctx->dlg, "ERROR: invalid conf node type"); + } + + PCB_DAD_BUTTON_CLOSES(ctx->dlg, clbtn); + PCB_DAD_END(ctx->dlg); + + PCB_DAD_NEW("pref_confedit", ctx->dlg, "pcb-rnd conf item", ctx, pcb_false, pref_conf_edit_close_cb); + + if (is_read_only(ctx)) { + int n; + pcb_gui->attr_dlg_widget_state(ctx->dlg_hid_ctx, ctx->wnewval, 0); + for(n = 0; n < sizeof(b) / sizeof(b[0]); n++) + if (b[n] != 0) + pcb_gui->attr_dlg_widget_state(ctx->dlg_hid_ctx, b[n], 0); + } + + + confedit_brd2dlg(ctx); +} + +static void pref_conf_del_cb(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + pref_ctx_t *pctx = caller_data; + pcb_hid_row_t *r; + + if (pctx->conf.selected_nat == NULL) { + pcb_message(PCB_MSG_ERROR, "You need to select a conf leaf node to remove\nTry the tree on the left.\n"); + return; + } + + r = pcb_dad_tree_get_selected(&pctx->dlg[pctx->conf.wintree]); + if (r == NULL) { + pcb_message(PCB_MSG_ERROR, "You need to select a role (upper right list)\n"); + return; + } + + if (pctx->conf.selected_idx >= pctx->conf.selected_nat->array_size) { + pcb_message(PCB_MSG_ERROR, "Internal error: array index out of bounds\n"); + return; + } + + if (is_read_only_(r->user_data2.lng)) { + pcb_message(PCB_MSG_ERROR, "Role is read-only, can not remove item\n"); + return; + } + + conf_del(r->user_data2.lng, pctx->conf.selected_nat->hash_path, pctx->conf.selected_idx); +} Index: tags/2.1.2/src_plugins/dialogs/dlg_pref_general.c =================================================================== --- tags/2.1.2/src_plugins/dialogs/dlg_pref_general.c (nonexistent) +++ tags/2.1.2/src_plugins/dialogs/dlg_pref_general.c (revision 24813) @@ -0,0 +1,87 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2018 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +/* Preferences dialog, general tab */ + +#include "dlg_pref.h" + +static pref_confitem_t perf_topwin[] = { + {"Alternate window layout to\nallow smaller size", "appearance/compact", 0, NULL}, + {NULL, NULL, 0} +}; + +static pref_confitem_t perf_backup[] = { + {"Save unsaved layout to\nPCB.%i.save at exit", "editor/save_in_tmp", 0, NULL}, + {"Seconds between auto backups\n(set to zero to disable auto backups)", "rc/backup_interval", 0, NULL}, + {NULL, NULL, 0} +}; + +static pref_confitem_t perf_cli[] = { + {"Number of commands to\nremember in the\nhistory list", "plugins/hid_gtk/history_size", 0, NULL}, + {NULL, NULL, 0} +}; + +static void pref_general_dlg2conf(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + pref_ctx_t *ctx = caller_data; + pcb_pref_dlg2conf_table(ctx, perf_topwin, attr); + pcb_pref_dlg2conf_table(ctx, perf_backup, attr); + pcb_pref_dlg2conf_table(ctx, perf_cli, attr); +} + +void pcb_dlg_pref_general_close(pref_ctx_t *ctx) +{ + pcb_pref_conflist_remove(ctx, perf_topwin); + pcb_pref_conflist_remove(ctx, perf_backup); + pcb_pref_conflist_remove(ctx, perf_cli); +} + +void pcb_dlg_pref_general_create(pref_ctx_t *ctx) +{ + PCB_DAD_BEGIN_VBOX(ctx->dlg); + PCB_DAD_COMPFLAG(ctx->dlg, PCB_HATF_FRAME); + PCB_DAD_LABEL(ctx->dlg, "Top window layout"); + PCB_DAD_BEGIN_TABLE(ctx->dlg, 2); + pcb_pref_create_conftable(ctx, perf_topwin, pref_general_dlg2conf); + PCB_DAD_END(ctx->dlg); + PCB_DAD_END(ctx->dlg); + + PCB_DAD_BEGIN_VBOX(ctx->dlg); + PCB_DAD_COMPFLAG(ctx->dlg, PCB_HATF_FRAME); + PCB_DAD_LABEL(ctx->dlg, "Backup"); + PCB_DAD_BEGIN_TABLE(ctx->dlg, 2); + pcb_pref_create_conftable(ctx, perf_backup, pref_general_dlg2conf); + PCB_DAD_END(ctx->dlg); + PCB_DAD_END(ctx->dlg); + + PCB_DAD_BEGIN_VBOX(ctx->dlg); + PCB_DAD_COMPFLAG(ctx->dlg, PCB_HATF_FRAME); + PCB_DAD_LABEL(ctx->dlg, "Command line entry"); + PCB_DAD_BEGIN_TABLE(ctx->dlg, 2); + pcb_pref_create_conftable(ctx, perf_cli, pref_general_dlg2conf); + PCB_DAD_END(ctx->dlg); + PCB_DAD_END(ctx->dlg); +} Index: tags/2.1.2/src_plugins/dialogs/dlg_pref_general.h =================================================================== --- tags/2.1.2/src_plugins/dialogs/dlg_pref_general.h (nonexistent) +++ tags/2.1.2/src_plugins/dialogs/dlg_pref_general.h (revision 24813) @@ -0,0 +1,12 @@ +#ifndef PCB_DLG_PREF_GENERAL_H +#define PCB_DLG_PREF_GENERAL_H + +typedef struct { + int dummy; +} pref_general_t; + +void pcb_dlg_pref_general_close(pref_ctx_t *ctx); +void pcb_dlg_pref_general_create(pref_ctx_t *ctx); + + +#endif Index: tags/2.1.2/src_plugins/dialogs/dlg_pref_layer.c =================================================================== --- tags/2.1.2/src_plugins/dialogs/dlg_pref_layer.c (nonexistent) +++ tags/2.1.2/src_plugins/dialogs/dlg_pref_layer.c (revision 24813) @@ -0,0 +1,61 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2018 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +/* Preferences dialog, board tab */ + +#include "dlg_pref.h" +#include "conf.h" +#include "conf_core.h" +#include "stub_draw.h" + +#define PCB_EMPTY(a) ((a) ? (a) : "") + + +void layersel_expose_cb(pcb_hid_attribute_t *attrib, pcb_hid_preview_t *prv, pcb_hid_gc_t gc, const pcb_hid_expose_ctx_t *e) +{ + pcb_stub_draw_csect(gc, e); +} + +pcb_bool layersel_mouse_cb(pcb_hid_attribute_t *attrib, pcb_hid_preview_t *prv, pcb_hid_mouse_ev_t kind, pcb_coord_t x, pcb_coord_t y) +{ + return pcb_stub_draw_csect_mouse_ev(kind, x, y); +} + +void layersel_free_cb(pcb_hid_attribute_t *attrib, void *user_ctx, void *hid_ctx) +{ +} + +void pcb_dlg_pref_layer_create(pref_ctx_t *ctx) +{ + pcb_box_t vbox = {0, 0, PCB_MM_TO_COORD(150), PCB_MM_TO_COORD(150)}; + + PCB_DAD_COMPFLAG(ctx->dlg, PCB_HATF_EXPFILL); + PCB_DAD_BEGIN_VBOX(ctx->dlg); + PCB_DAD_COMPFLAG(ctx->dlg, PCB_HATF_EXPFILL); + PCB_DAD_PREVIEW(ctx->dlg, layersel_expose_cb, layersel_mouse_cb, layersel_free_cb, &vbox, 200, 200, ctx); + PCB_DAD_COMPFLAG(ctx->dlg, PCB_HATF_EXPFILL); + PCB_DAD_END(ctx->dlg); +} Index: tags/2.1.2/src_plugins/dialogs/dlg_pref_lib.c =================================================================== --- tags/2.1.2/src_plugins/dialogs/dlg_pref_lib.c (nonexistent) +++ tags/2.1.2/src_plugins/dialogs/dlg_pref_lib.c (revision 24813) @@ -0,0 +1,433 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2018 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +/* Preferences dialog, library tab */ + +#include +#include "dlg_pref.h" +#include "conf.h" +#include "conf_core.h" +#include "paths.h" + +static const char *SRC_BRD = ""; + +static void libhelp_btn(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr); + +static void pref_lib_row_free(pcb_hid_attribute_t *attrib, void *hid_ctx, pcb_hid_row_t *row) +{ + free(row->cell[0]); + free(row->cell[1]); + free(row->cell[2]); + row->cell[0] = row->cell[1] = row->cell[2] = NULL; +} + +/* Current libraries from config to dialog box: remove everything from + the widget first */ +static void pref_lib_conf2dlg_pre(conf_native_t *cfg, int arr_idx) +{ + pcb_hid_attribute_t *attr; + pcb_hid_tree_t *tree; + pcb_hid_row_t *r; + + if ((pref_ctx.lib.lock) || (!pref_ctx.active)) + return; + + attr = &pref_ctx.dlg[pref_ctx.lib.wlist]; + tree = (pcb_hid_tree_t *)attr->enumerations; + + r = pcb_dad_tree_get_selected(attr); + if (r != NULL) { + free(pref_ctx.lib.cursor_path); + pref_ctx.lib.cursor_path = pcb_strdup(r->cell[0]); + } + + /* remove all existing entries */ + for(r = gdl_first(&tree->rows); r != NULL; r = gdl_first(&tree->rows)) { + pcb_dad_tree_remove(attr, r); + } +} + +/* Current libraries from config to dialog box: after the change, fill + in all widget rows from the conf */ +static void pref_lib_conf2dlg_post(conf_native_t *cfg, int arr_idx) +{ + conf_listitem_t *i; + int idx; + const char *s; + char *cell[4]; + pcb_hid_attribute_t *attr; + pcb_hid_attr_val_t hv; + + if ((pref_ctx.lib.lock) || (!pref_ctx.active)) + return; + + attr = &pref_ctx.dlg[pref_ctx.lib.wlist]; + + /* copy everything from the config tree to the dialog */ + conf_loop_list_str(&conf_core.rc.library_search_paths, i, s, idx) { + char *tmp; + cell[0] = pcb_strdup(i->payload); + pcb_path_resolve(cell[0], &tmp, 0, pcb_false); + cell[1] = pcb_strdup(tmp == NULL ? "" : tmp); + cell[2] = pcb_strdup((i->prop.src->file_name == NULL ? SRC_BRD : i->prop.src->file_name)); + cell[3] = NULL; + pcb_dad_tree_append(attr, NULL, cell); + } + + hv.str_value = pref_ctx.lib.cursor_path; + if (pcb_gui->attr_dlg_set_value(pref_ctx.dlg_hid_ctx, pref_ctx.lib.wlist, &hv) == 0) { + free(pref_ctx.lib.cursor_path); + pref_ctx.lib.cursor_path = NULL; + } +} + +TODO(": move this to liblihata") +static void lht_clean_list(lht_node_t * lst) +{ + lht_node_t *n; + while (lst->data.list.first != NULL) { + n = lst->data.list.first; + if (n->doc == NULL) { + if (lst->data.list.last == n) + lst->data.list.last = NULL; + lst->data.list.first = n->next; + } + else + lht_tree_unlink(n); + lht_dom_node_free(n); + } + lst->data.list.last = NULL; +} + +/* Dialog box to current libraries in config */ +static void pref_lib_dlg2conf(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + pref_ctx_t *ctx = caller_data; + pcb_hid_tree_t *tree = (pcb_hid_tree_t *)attr->enumerations; + lht_node_t *m, *lst, *nd; + pcb_hid_row_t *r; + + ctx->lib.lock++; + + /* get the list and clean it */ + m = conf_lht_get_first(ctx->role, 0); + lst = lht_tree_path_(m->doc, m, "rc/library_search_paths", 1, 0, NULL); + if (lst == NULL) + conf_set(ctx->role, "rc/library_search_paths", 0, "", POL_OVERWRITE); + lst = lht_tree_path_(m->doc, m, "rc/library_search_paths", 1, 0, NULL); + assert(lst != NULL); + lht_clean_list(lst); + + /* append items from the widget */ + for(r = gdl_first(&tree->rows); r != NULL; r = gdl_next(&tree->rows, r)) { + nd = lht_dom_node_alloc(LHT_TEXT, ""); + nd->data.text.value = pcb_strdup(r->cell[0]); + nd->doc = m->doc; + lht_dom_list_append(lst, nd); + pcb_dad_tree_modify_cell(attr, r, 2, pcb_strdup(SRC_BRD)); + } + + conf_update("rc/library_search_paths", -1); + + ctx->lib.lock--; +} + +static void lib_btn_remove(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *btn_attr) +{ + pcb_hid_attribute_t *attr = &pref_ctx.dlg[pref_ctx.lib.wlist]; + pcb_hid_row_t *r = pcb_dad_tree_get_selected(attr); + + if (r == NULL) + return; + + if (pcb_dad_tree_remove(attr, r) == 0) + pref_lib_dlg2conf(hid_ctx, caller_data, attr); +} + +static void lib_btn_up(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *btn_attr) +{ + pcb_hid_attribute_t *attr = &pref_ctx.dlg[pref_ctx.lib.wlist]; + pcb_hid_row_t *prev, *r = pcb_dad_tree_get_selected(attr); + pcb_hid_tree_t *tree = (pcb_hid_tree_t *)attr->enumerations; + char *cell[4]; + + if (r == NULL) + return; + + prev = gdl_prev(&tree->rows, r); + if (prev == NULL) + return; + + cell[0] = pcb_strdup(r->cell[0]); /* have to copy because this is also the primary key (path for the hash) */ + cell[1] = r->cell[1]; r->cell[1] = NULL; + cell[2] = r->cell[2]; r->cell[2] = NULL; + cell[3] = NULL; + if (pcb_dad_tree_remove(attr, r) == 0) { + pcb_hid_attr_val_t hv; + pcb_dad_tree_insert(attr, prev, cell); + pref_lib_dlg2conf(hid_ctx, caller_data, attr); + hv.str_value = cell[0]; + pcb_gui->attr_dlg_set_value(pref_ctx.dlg_hid_ctx, pref_ctx.lib.wlist, &hv); + } +} + +static void lib_btn_down(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *btn_attr) +{ + pcb_hid_attribute_t *attr = &pref_ctx.dlg[pref_ctx.lib.wlist]; + pcb_hid_row_t *next, *r = pcb_dad_tree_get_selected(attr); + pcb_hid_tree_t *tree = (pcb_hid_tree_t *)attr->enumerations; + char *cell[4]; + + if (r == NULL) + return; + + next = gdl_next(&tree->rows, r); + if (next == NULL) + return; + + cell[0] = pcb_strdup(r->cell[0]); /* have to copy because this is also the primary key (path for the hash) */ + cell[1] = r->cell[1]; r->cell[1] = NULL; + cell[2] = r->cell[2]; r->cell[2] = NULL; + cell[3] = NULL; + if (pcb_dad_tree_remove(attr, r) == 0) { + pcb_hid_attr_val_t hv; + pcb_dad_tree_append(attr, next, cell); + pref_lib_dlg2conf(hid_ctx, caller_data, attr); + hv.str_value = cell[0]; + pcb_gui->attr_dlg_set_value(pref_ctx.dlg_hid_ctx, pref_ctx.lib.wlist, &hv); + } +} + +typedef struct { + PCB_DAD_DECL_NOINIT(dlg) + int wpath, wexp; +} cell_edit_ctx_t; + +static void lib_cell_edit_update(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *btn_attr) +{ + cell_edit_ctx_t *ctx = caller_data; + char *tmp; + + pcb_path_resolve(ctx->dlg[ctx->wpath].default_val.str_value, &tmp, 0, pcb_true); + if (tmp != NULL) + PCB_DAD_SET_VALUE(hid_ctx, ctx->wexp, str_value, tmp); +} + +static int lib_cell_edit(char **cell) +{ + cell_edit_ctx_t ctx; + pcb_hid_dad_buttons_t clbtn[] = {{"Cancel", -1}, {"ok", 0}, {NULL, 0}}; + + memset(&ctx, 0, sizeof(ctx)); + + PCB_DAD_BEGIN_VBOX(ctx.dlg); + PCB_DAD_BEGIN_TABLE(ctx.dlg, 2); + PCB_DAD_LABEL(ctx.dlg, "Path:"); + PCB_DAD_STRING(ctx.dlg); + ctx.wpath = PCB_DAD_CURRENT(ctx.dlg); + ctx.dlg[ctx.wpath].default_val.str_value = pcb_strdup(cell[0]); + PCB_DAD_CHANGE_CB(ctx.dlg, lib_cell_edit_update); + + PCB_DAD_LABEL(ctx.dlg, "Expanded\nversion:"); + PCB_DAD_LABEL(ctx.dlg, pcb_strdup(cell[1])); + ctx.wexp = PCB_DAD_CURRENT(ctx.dlg); + + PCB_DAD_LABEL(ctx.dlg, ""); + PCB_DAD_BUTTON(ctx.dlg, "Help..."); + PCB_DAD_CHANGE_CB(ctx.dlg, libhelp_btn); + PCB_DAD_END(ctx.dlg); + PCB_DAD_BUTTON_CLOSES(ctx.dlg, clbtn); + PCB_DAD_END(ctx.dlg); + + PCB_DAD_NEW("pref_lib_path", ctx.dlg, "Edit library path", &ctx, pcb_true, NULL); + if (PCB_DAD_RUN(ctx.dlg) != 0) { + PCB_DAD_FREE(ctx.dlg); + return -1; + } + + free(cell[0]); + cell[0] = pcb_strdup(ctx.dlg[ctx.wpath].default_val.str_value); + free(cell[1]); + cell[1] = pcb_strdup(ctx.dlg[ctx.wexp].default_val.str_value); + + PCB_DAD_FREE(ctx.dlg); + return 0; +} + +static void lib_btn_insert(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *btn_attr, int pos) +{ + pcb_hid_attribute_t *attr = &pref_ctx.dlg[pref_ctx.lib.wlist]; + pcb_hid_row_t *r = pcb_dad_tree_get_selected(attr); + char *cell[4]; + + if (r == NULL) + return; + + cell[0] = pcb_strdup(""); + cell[1] = pcb_strdup(""); + cell[2] = pcb_strdup(SRC_BRD); + cell[3] = NULL; + if (lib_cell_edit(cell) != 0) { + free(cell[0]); + free(cell[1]); + free(cell[2]); + return; + } + + switch(pos) { + case -1: /* before */ + pcb_dad_tree_insert(attr, r, cell); + break; + case +1: /* after */ + pcb_dad_tree_append(attr, r, cell); + break; + case 0: /* replace */ + pcb_dad_tree_modify_cell(attr, r, 0, cell[0]); + pcb_dad_tree_modify_cell(attr, r, 1, cell[1]); + pcb_dad_tree_modify_cell(attr, r, 2, cell[2]); + break; + } + pref_lib_dlg2conf(hid_ctx, caller_data, attr); +} + +static void lib_btn_insert_before(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *btn_attr) +{ + lib_btn_insert(hid_ctx, caller_data, btn_attr, -1); +} + +static void lib_btn_insert_after(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *btn_attr) +{ + lib_btn_insert(hid_ctx, caller_data, btn_attr, +1); +} + +static void lib_btn_edit(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *btn_attr) +{ + lib_btn_insert(hid_ctx, caller_data, btn_attr, 0); +} + +void pcb_dlg_pref_lib_close(pref_ctx_t *ctx) +{ + if (ctx->lib.help.active) + PCB_DAD_FREE(ctx->lib.help.dlg); +} + +static void pref_libhelp_close_cb(void *caller_data, pcb_hid_attr_ev_t ev) +{ + pref_libhelp_ctx_t *ctx = caller_data; + + PCB_DAD_FREE(ctx->dlg); + memset(ctx, 0, sizeof(pref_libhelp_ctx_t)); /* reset all states to the initial - includes ctx->active = 0; */ +} + +static void pref_libhelp_open(pref_libhelp_ctx_t *ctx) +{ + htsp_entry_t *e; + pcb_hid_dad_buttons_t clbtn[] = {{"Close", 0}, {NULL, 0}}; + + PCB_DAD_LABEL(ctx->dlg, "The following $(variables) can be used in the path:"); + PCB_DAD_BEGIN_TABLE(ctx->dlg, 2); + conf_fields_foreach(e) { + conf_native_t *nat = e->value; + char tmp[256]; + + if (strncmp(e->key, "rc/path/", 8) != 0) + continue; + + pcb_snprintf(tmp, sizeof(tmp), "$(rc.path.%s)", e->key + 8); + PCB_DAD_LABEL(ctx->dlg, tmp); + PCB_DAD_LABEL(ctx->dlg, nat->val.string[0]); + } + PCB_DAD_BUTTON_CLOSES(ctx->dlg, clbtn); + PCB_DAD_END(ctx->dlg); + + ctx->active = 1; + PCB_DAD_NEW("pref_lib_path_help", ctx->dlg, "pcb-rnd preferences: library help", ctx, pcb_false, pref_libhelp_close_cb); +} + +static void libhelp_btn(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + pref_ctx_t *ctx = caller_data; + if (ctx->lib.help.active) + return; + pref_libhelp_open(&ctx->lib.help); +} + +void pcb_dlg_pref_lib_create(pref_ctx_t *ctx) +{ + static const char *hdr[] = {"configured path", "actual path on the filesystem", "config source", NULL}; + pcb_hid_tree_t *tree; + + PCB_DAD_COMPFLAG(ctx->dlg, PCB_HATF_EXPFILL); /* get the parent vbox, which is the tab's page vbox, to expand and fill */ + + PCB_DAD_LABEL(ctx->dlg, "Ordered list of footprint library search directories."); + + PCB_DAD_BEGIN_VBOX(ctx->dlg); + PCB_DAD_COMPFLAG(ctx->dlg, PCB_HATF_FRAME | PCB_HATF_SCROLL | PCB_HATF_EXPFILL); + PCB_DAD_TREE(ctx->dlg, 3, 0, hdr); + PCB_DAD_COMPFLAG(ctx->dlg, PCB_HATF_EXPFILL); + ctx->lib.wlist = PCB_DAD_CURRENT(ctx->dlg); + tree = (pcb_hid_tree_t *)ctx->dlg[ctx->lib.wlist].enumerations; + tree->user_free_cb = pref_lib_row_free; + PCB_DAD_END(ctx->dlg); + + PCB_DAD_BEGIN_HBOX(ctx->dlg); + PCB_DAD_BUTTON(ctx->dlg, "Move up"); + PCB_DAD_CHANGE_CB(ctx->dlg, lib_btn_up); + PCB_DAD_BUTTON(ctx->dlg, "Move down"); + PCB_DAD_CHANGE_CB(ctx->dlg, lib_btn_down); + PCB_DAD_BUTTON(ctx->dlg, "Insert before"); + PCB_DAD_CHANGE_CB(ctx->dlg, lib_btn_insert_before); + PCB_DAD_BUTTON(ctx->dlg, "Insert after"); + PCB_DAD_CHANGE_CB(ctx->dlg, lib_btn_insert_after); + PCB_DAD_BUTTON(ctx->dlg, "Remove"); + PCB_DAD_CHANGE_CB(ctx->dlg, lib_btn_remove); + PCB_DAD_BUTTON(ctx->dlg, "Edit..."); + PCB_DAD_CHANGE_CB(ctx->dlg, lib_btn_edit); + PCB_DAD_BUTTON(ctx->dlg, "Help..."); + ctx->lib.whsbutton = PCB_DAD_CURRENT(ctx->dlg); + PCB_DAD_CHANGE_CB(ctx->dlg, libhelp_btn); + PCB_DAD_END(ctx->dlg); + +} + +void pcb_dlg_pref_lib_open(pref_ctx_t *ctx) +{ + conf_native_t *cn = conf_get_field("rc/library_search_paths"); + pref_lib_conf2dlg_post(cn, -1); +} + +void pcb_dlg_pref_lib_init(pref_ctx_t *ctx) +{ + static conf_hid_callbacks_t cbs_spth; + conf_native_t *cn = conf_get_field("rc/library_search_paths"); + + if (cn != NULL) { + memset(&cbs_spth, 0, sizeof(conf_hid_callbacks_t)); + cbs_spth.val_change_pre = pref_lib_conf2dlg_pre; + cbs_spth.val_change_post = pref_lib_conf2dlg_post; + conf_hid_set_cb(cn, pref_hid, &cbs_spth); + } +} Index: tags/2.1.2/src_plugins/dialogs/dlg_pref_lib.h =================================================================== --- tags/2.1.2/src_plugins/dialogs/dlg_pref_lib.h (nonexistent) +++ tags/2.1.2/src_plugins/dialogs/dlg_pref_lib.h (revision 24813) @@ -0,0 +1,22 @@ +#ifndef PCB_DLG_PREF_LIB_H +#define PCB_DLG_PREF_LIB_H + +typedef struct pref_libhelp_ctx_s { + PCB_DAD_DECL_NOINIT(dlg) + int active; /* already open - allow only one instance */ +} pref_libhelp_ctx_t; + +typedef struct { + int wlist, whsbutton; + int lock; /* a change in on the dialog box causes a change on the board but this shouldn't in turn casue a changein the dialog */ + char *cursor_path; + pref_libhelp_ctx_t help; +} pref_lib_t; + +void pcb_dlg_pref_lib_close(pref_ctx_t *ctx); +void pcb_dlg_pref_lib_create(pref_ctx_t *ctx); +void pcb_dlg_pref_lib_init(pref_ctx_t *ctx); +void pcb_dlg_pref_lib_open(pref_ctx_t *ctx); + + +#endif Index: tags/2.1.2/src_plugins/dialogs/dlg_pref_sizes.c =================================================================== --- tags/2.1.2/src_plugins/dialogs/dlg_pref_sizes.c (nonexistent) +++ tags/2.1.2/src_plugins/dialogs/dlg_pref_sizes.c (revision 24813) @@ -0,0 +1,145 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2018 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +/* Preferences dialog, sizes tab */ + +#include "board.h" +#include "dlg_pref.h" +#include "conf.h" +#include "conf_core.h" + +/* Actual board size to dialog box */ +static void pref_sizes_brd2dlg(pref_ctx_t *ctx) +{ + if (ctx->sizes.lock) + return; + PCB_DAD_SET_VALUE(ctx->dlg_hid_ctx, ctx->sizes.wwidth, coord_value, PCB->MaxWidth); + PCB_DAD_SET_VALUE(ctx->dlg_hid_ctx, ctx->sizes.wheight, coord_value, PCB->MaxHeight); +} + +/* Dialog box to actual board size */ +static void pref_sizes_dlg2brd(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + pref_ctx_t *ctx = caller_data; + + ctx->sizes.lock++; + if ((PCB->MaxWidth != ctx->dlg[ctx->sizes.wwidth].default_val.coord_value) || (PCB->MaxHeight != ctx->dlg[ctx->sizes.wheight].default_val.coord_value)) + pcb_board_resize(ctx->dlg[ctx->sizes.wwidth].default_val.coord_value, ctx->dlg[ctx->sizes.wheight].default_val.coord_value); + ctx->sizes.lock--; +} + +static pref_confitem_t drc_sizes[] = { + {"Minimum copper spacing", "design/bloat", 0, NULL}, + {"Minimum copper width", "design/min_wid", 0, NULL}, + {"Minimum copper overlap", "design/shrink", 0, NULL}, + {"Minimum silk width", "design/min_slk", 0, NULL}, + {"Minimum drill diameter", "design/min_drill", 0, NULL}, + {"Minimum annular ring", "design/min_ring", 0, NULL}, + {NULL, NULL, 0} +}; + +static void pref_sizes_drc_dlg2conf(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + pref_ctx_t *ctx = caller_data; + pcb_pref_dlg2conf_table(ctx, drc_sizes, attr); +} + +static void pref_isle_brd2dlg(conf_native_t *cfg, int arr_idx) +{ + if ((pref_ctx.sizes.lock) || (!pref_ctx.active)) + return; + PCB_DAD_SET_VALUE(pref_ctx.dlg_hid_ctx, pref_ctx.sizes.wisle, real_value, conf_core.design.poly_isle_area / 1000000.0); +} + +static void pref_isle_dlg2brd(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + pref_ctx_t *ctx = caller_data; + double v = ctx->dlg[ctx->sizes.wisle].default_val.real_value * 1000000.0; + + ctx->sizes.lock++; + conf_setf(ctx->role, "design/poly_isle_area", -1, "%f", v); + ctx->sizes.lock--; +} + +void pcb_dlg_pref_sizes_close(pref_ctx_t *ctx) +{ + pcb_pref_conflist_remove(ctx, drc_sizes); +} + +void pcb_dlg_pref_sizes_create(pref_ctx_t *ctx) +{ + PCB_DAD_BEGIN_VBOX(ctx->dlg); + PCB_DAD_COMPFLAG(ctx->dlg, PCB_HATF_FRAME); + PCB_DAD_LABEL(ctx->dlg, "Board size"); + PCB_DAD_BEGIN_HBOX(ctx->dlg); + PCB_DAD_LABEL(ctx->dlg, "Width="); + PCB_DAD_COORD(ctx->dlg, ""); + ctx->sizes.wwidth = PCB_DAD_CURRENT(ctx->dlg); + PCB_DAD_MINMAX(ctx->dlg, PCB_MM_TO_COORD(1), PCB_MAX_COORD); + PCB_DAD_DEFAULT_NUM(ctx->dlg, PCB->MaxWidth); + PCB_DAD_CHANGE_CB(ctx->dlg, pref_sizes_dlg2brd); + PCB_DAD_LABEL(ctx->dlg, "Height="); + PCB_DAD_COORD(ctx->dlg, ""); + ctx->sizes.wheight = PCB_DAD_CURRENT(ctx->dlg); + PCB_DAD_MINMAX(ctx->dlg, PCB_MM_TO_COORD(1), PCB_MAX_COORD); + PCB_DAD_DEFAULT_NUM(ctx->dlg, PCB->MaxHeight); + PCB_DAD_CHANGE_CB(ctx->dlg, pref_sizes_dlg2brd); + PCB_DAD_END(ctx->dlg); + + PCB_DAD_END(ctx->dlg); + PCB_DAD_BEGIN_VBOX(ctx->dlg); + PCB_DAD_COMPFLAG(ctx->dlg, PCB_HATF_FRAME); + PCB_DAD_LABEL(ctx->dlg, "DRC sizes"); + PCB_DAD_BEGIN_TABLE(ctx->dlg, 2); + pcb_pref_create_conftable(ctx, drc_sizes, pref_sizes_drc_dlg2conf); + PCB_DAD_END(ctx->dlg); + PCB_DAD_END(ctx->dlg); + + PCB_DAD_BEGIN_VBOX(ctx->dlg); + PCB_DAD_COMPFLAG(ctx->dlg, PCB_HATF_FRAME); + PCB_DAD_LABEL(ctx->dlg, "misc sizes"); + PCB_DAD_BEGIN_TABLE(ctx->dlg, 2); + PCB_DAD_LABEL(ctx->dlg, "polygon isle minimum size\n[square um]"); + PCB_DAD_REAL(ctx->dlg, ""); + ctx->sizes.wisle = PCB_DAD_CURRENT(ctx->dlg); + PCB_DAD_MINMAX(ctx->dlg, 0, PCB_MAX_COORD); + ctx->dlg[ctx->sizes.wisle].default_val.real_value = (conf_core.design.poly_isle_area / 1000000.0); + PCB_DAD_CHANGE_CB(ctx->dlg, pref_isle_dlg2brd); + PCB_DAD_END(ctx->dlg); + PCB_DAD_END(ctx->dlg); +} + +void pcb_dlg_pref_sizes_init(pref_ctx_t *ctx) +{ + static conf_hid_callbacks_t cbs_isle; + conf_native_t *cn = conf_get_field("design/poly_isle_area"); + + if (cn != NULL) { + memset(&cbs_isle, 0, sizeof(conf_hid_callbacks_t)); + cbs_isle.val_change_post = pref_isle_brd2dlg; + conf_hid_set_cb(cn, pref_hid, &cbs_isle); + } +} Index: tags/2.1.2/src_plugins/dialogs/dlg_pref_sizes.h =================================================================== --- tags/2.1.2/src_plugins/dialogs/dlg_pref_sizes.h (nonexistent) +++ tags/2.1.2/src_plugins/dialogs/dlg_pref_sizes.h (revision 24813) @@ -0,0 +1,15 @@ +#ifndef PCB_DLG_PREF_SIZES_H +#define PCB_DLG_PREF_SIZES_H + +typedef struct { + int wwidth, wheight; + int wisle; + int lock; /* a change in on the dialog box causes a change on the board but this shouldn't in turn casue a changein the dialog */ +} pref_sizes_t; + +void pcb_dlg_pref_sizes_close(pref_ctx_t *ctx); +void pcb_dlg_pref_sizes_create(pref_ctx_t *ctx); +void pcb_dlg_pref_sizes_init(pref_ctx_t *ctx); + + +#endif Index: tags/2.1.2/src_plugins/dialogs/dlg_pref_win.c =================================================================== --- tags/2.1.2/src_plugins/dialogs/dlg_pref_win.c (nonexistent) +++ tags/2.1.2/src_plugins/dialogs/dlg_pref_win.c (revision 24813) @@ -0,0 +1,189 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2018 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +/* Preferences dialog, window geometry tab */ + +#include "dlg_pref.h" +#include "conf.h" +#include "conf_core.h" +#include "dialogs_conf.h" + +extern const conf_dialogs_t conf_dialogs; +extern void pcb_wplc_save_to_role(conf_role_t role); +extern int pcb_wplc_save_to_file(const char *fn); + +static void pref_win_brd2dlg(pref_ctx_t *ctx) +{ + PCB_DAD_SET_VALUE(ctx->dlg_hid_ctx, ctx->win.wmaster, int_value, conf_core.editor.auto_place); + PCB_DAD_SET_VALUE(ctx->dlg_hid_ctx, ctx->win.wboard, int_value, conf_dialogs.plugins.dialogs.auto_save_window_geometry.to_design); + PCB_DAD_SET_VALUE(ctx->dlg_hid_ctx, ctx->win.wproject, int_value, conf_dialogs.plugins.dialogs.auto_save_window_geometry.to_project); + PCB_DAD_SET_VALUE(ctx->dlg_hid_ctx, ctx->win.wuser, int_value, conf_dialogs.plugins.dialogs.auto_save_window_geometry.to_user); +} + +void pcb_dlg_pref_win_open(pref_ctx_t *ctx) +{ + pref_win_brd2dlg(ctx); +} + +void pcb_dlg_pref_win_close(pref_ctx_t *ctx) +{ +} + +static void pref_win_master_cb(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + pref_ctx_t *ctx = caller_data; + conf_setf(ctx->role, "editor/auto_place", -1, "%d", attr->default_val.int_value); + pref_win_brd2dlg(ctx); +} + +static void pref_win_board_cb(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + pref_ctx_t *ctx = caller_data; + conf_setf(ctx->role, "plugins/dialogs/auto_save_window_geometry/to_design", -1, "%d", attr->default_val.int_value); + pref_win_brd2dlg(ctx); +} + +static void pref_win_project_cb(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + pref_ctx_t *ctx = caller_data; + conf_setf(ctx->role, "plugins/dialogs/auto_save_window_geometry/to_project", -1, "%d", attr->default_val.int_value); + pref_win_brd2dlg(ctx); +} + +static void pref_win_user_cb(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + pref_ctx_t *ctx = caller_data; + conf_setf(ctx->role, "plugins/dialogs/auto_save_window_geometry/to_user", -1, "%d", attr->default_val.int_value); + pref_win_brd2dlg(ctx); +} + + +static void pref_win_board_now_cb(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + pcb_wplc_save_to_role(CFR_USER); +} + +static void pref_win_project_now_cb(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + pcb_wplc_save_to_role(CFR_USER); +} + +static void pref_win_user_now_cb(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + pcb_wplc_save_to_role(CFR_USER); +} + +static void pref_win_file_now_cb(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + char *fname; + + fname = pcb_gui->fileselect("Save window geometry to...", + "Pick a file for saving window geometry to.\n", + "win_geo.lht", ".lht", NULL, "wingeo", PCB_HID_FSD_MAY_NOT_EXIST, NULL); + + if (fname == NULL) + return; + + if (pcb_wplc_save_to_file(fname) != 0) + pcb_message(PCB_MSG_ERROR, "Error saving window geometry to '%s'\n", fname); +} + + +void pcb_dlg_pref_win_create(pref_ctx_t *ctx) +{ + PCB_DAD_COMPFLAG(ctx->dlg, PCB_HATF_EXPFILL); + PCB_DAD_BEGIN_HBOX(ctx->dlg); + PCB_DAD_COMPFLAG(ctx->dlg, PCB_HATF_FRAME); + PCB_DAD_LABEL(ctx->dlg, "Load window geometry and enable window placement:"); + PCB_DAD_BOOL(ctx->dlg, ""); + PCB_DAD_HELP(ctx->dlg, "When enabled, pcb-rnd will load window geometry from config files\nand try to resize and place windows accordingly.\nSizes can be saved once (golden arrangement)\nor at every exit (retrain last setup),\nsee below."); + ctx->win.wmaster = PCB_DAD_CURRENT(ctx->dlg); + PCB_DAD_CHANGE_CB(ctx->dlg, pref_win_master_cb); + PCB_DAD_END(ctx->dlg); + PCB_DAD_BEGIN_VBOX(ctx->dlg); + PCB_DAD_COMPFLAG(ctx->dlg, PCB_HATF_FRAME); + PCB_DAD_LABEL(ctx->dlg, "Save window geometry to..."); + PCB_DAD_BEGIN_TABLE(ctx->dlg, 2); + + PCB_DAD_BEGIN_HBOX(ctx->dlg); + PCB_DAD_BEGIN_HBOX(ctx->dlg); + PCB_DAD_COMPFLAG(ctx->dlg, PCB_HATF_EXPFILL); + PCB_DAD_END(ctx->dlg); + PCB_DAD_LABEL(ctx->dlg, "... in the design (board) file"); + PCB_DAD_END(ctx->dlg); + PCB_DAD_BEGIN_HBOX(ctx->dlg); + PCB_DAD_BUTTON(ctx->dlg, "now"); + PCB_DAD_CHANGE_CB(ctx->dlg, pref_win_board_now_cb); + PCB_DAD_LABEL(ctx->dlg, "before close:"); + PCB_DAD_BOOL(ctx->dlg, ""); + ctx->win.wboard = PCB_DAD_CURRENT(ctx->dlg); + PCB_DAD_CHANGE_CB(ctx->dlg, pref_win_board_cb); + PCB_DAD_END(ctx->dlg); + + PCB_DAD_BEGIN_HBOX(ctx->dlg); + PCB_DAD_BEGIN_HBOX(ctx->dlg); + PCB_DAD_COMPFLAG(ctx->dlg, PCB_HATF_EXPFILL); + PCB_DAD_END(ctx->dlg); + PCB_DAD_LABEL(ctx->dlg, "... in the project file"); + PCB_DAD_END(ctx->dlg); + PCB_DAD_BEGIN_HBOX(ctx->dlg); + PCB_DAD_BUTTON(ctx->dlg, "now"); + PCB_DAD_CHANGE_CB(ctx->dlg, pref_win_project_now_cb); + PCB_DAD_LABEL(ctx->dlg, "before close:"); + PCB_DAD_BOOL(ctx->dlg, ""); + ctx->win.wproject = PCB_DAD_CURRENT(ctx->dlg); + PCB_DAD_CHANGE_CB(ctx->dlg, pref_win_project_cb); + PCB_DAD_END(ctx->dlg); + + PCB_DAD_BEGIN_HBOX(ctx->dlg); + PCB_DAD_BEGIN_HBOX(ctx->dlg); + PCB_DAD_COMPFLAG(ctx->dlg, PCB_HATF_EXPFILL); + PCB_DAD_END(ctx->dlg); + PCB_DAD_LABEL(ctx->dlg, "... in the user config"); + PCB_DAD_END(ctx->dlg); + PCB_DAD_BEGIN_HBOX(ctx->dlg); + PCB_DAD_BUTTON(ctx->dlg, "now"); + PCB_DAD_CHANGE_CB(ctx->dlg, pref_win_user_now_cb); + PCB_DAD_LABEL(ctx->dlg, "before close:"); + PCB_DAD_BOOL(ctx->dlg, ""); + ctx->win.wuser = PCB_DAD_CURRENT(ctx->dlg); + PCB_DAD_CHANGE_CB(ctx->dlg, pref_win_user_cb); + PCB_DAD_END(ctx->dlg); + + PCB_DAD_BEGIN_HBOX(ctx->dlg); + PCB_DAD_BEGIN_HBOX(ctx->dlg); + PCB_DAD_COMPFLAG(ctx->dlg, PCB_HATF_EXPFILL); + PCB_DAD_END(ctx->dlg); + PCB_DAD_LABEL(ctx->dlg, "... in a custom file"); + PCB_DAD_END(ctx->dlg); + PCB_DAD_BEGIN_HBOX(ctx->dlg); + PCB_DAD_BUTTON(ctx->dlg, "now"); + PCB_DAD_CHANGE_CB(ctx->dlg, pref_win_file_now_cb); + PCB_DAD_END(ctx->dlg); + + PCB_DAD_END(ctx->dlg); + PCB_DAD_END(ctx->dlg); +} Index: tags/2.1.2/src_plugins/dialogs/dlg_pref_win.h =================================================================== --- tags/2.1.2/src_plugins/dialogs/dlg_pref_win.h (nonexistent) +++ tags/2.1.2/src_plugins/dialogs/dlg_pref_win.h (revision 24813) @@ -0,0 +1,10 @@ +#ifndef PCB_DLG_PREF_WIN_H +#define PCB_DLG_PREF_WIN_H + +typedef struct { + int wmaster, wboard, wproject, wuser; +} pref_win_t; + +void pcb_dlg_pref_win_create(pref_ctx_t *ctx); + +#endif Index: tags/2.1.2/src_plugins/dialogs/dlg_printcalib.c =================================================================== --- tags/2.1.2/src_plugins/dialogs/dlg_printcalib.c (nonexistent) +++ tags/2.1.2/src_plugins/dialogs/dlg_printcalib.c (revision 24813) @@ -0,0 +1,61 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * Copyright (C) 1997, 1998, 1999, 2000, 2001 Harry Eaton + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "hid_init.h" + +static pcb_hid_attribute_t printer_calibrate_attrs[] = { + {"Enter Values here:", "", + PCB_HATT_LABEL, 0, 0, {0, 0, 0}, 0, 0}, + {"x-calibration", "X scale for calibrating your printer", + PCB_HATT_REAL, 0.5, 25, {0, 0, 1.00}, 0, 0}, + {"y-calibration", "Y scale for calibrating your printer", + PCB_HATT_REAL, 0.5, 25, {0, 0, 1.00}, 0, 0} +}; + +static pcb_hid_attr_val_t printer_calibrate_values[3]; + +const char pcb_acts_PrintCalibrate[] = "PrintCalibrate()"; +const char pcb_acth_PrintCalibrate[] = "Calibrate the printer."; +/* DOC: printcalibrate.html */ +fgw_error_t pcb_act_PrintCalibrate(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + pcb_hid_t *printer = pcb_hid_find_printer(); + + if (printer == NULL) { + pcb_message(PCB_MSG_ERROR, "No printer available\n"); + PCB_ACT_IRES(1); + return 0; + } + printer->calibrate(0.0, 0.0); + + if (pcb_attribute_dialog("printer_calibrate", printer_calibrate_attrs, 3, printer_calibrate_values, "Printer Calibration Values", NULL)) + return 1; + printer->calibrate(printer_calibrate_values[1].real_value, printer_calibrate_values[2].real_value); + PCB_ACT_IRES(0); + return 0; +} Index: tags/2.1.2/src_plugins/dialogs/dlg_test.c =================================================================== --- tags/2.1.2/src_plugins/dialogs/dlg_test.c (nonexistent) +++ tags/2.1.2/src_plugins/dialogs/dlg_test.c (revision 24813) @@ -0,0 +1,542 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2017 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "board.h" +#include "obj_text.h" +#include "hid_dad_tree.h" +#include "hid_dad_spin.h" + +static const char dlg_test_syntax[] = "dlg_test()\n"; +static const char dlg_test_help[] = "test the attribute dialog"; + +typedef struct { + PCB_DAD_DECL_NOINIT(dlg) + int wtab, tt, wprog, whpane, wvpane, wtxt, wtxtpos, wtxtro; + int ttctr, wclr, txtro; + int wspin_int, wspout_int, wspin_double, wspout_double, wspin_coord, wspout_coord; +} test_t; + + +static void pcb_act_attr_chg(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr); +static void pcb_act_spin_reset(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr); +static void pcb_act_spin_upd(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr); +static void cb_tab_chg(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr); +static void cb_jump(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr); +static void cb_color_print(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr); +static void cb_color_reset(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr); +static void cb_ttbl_insert(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr); +static void cb_ttbl_append(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr); +static void cb_ttbl_jump(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr); +static void cb_ttbl_filt(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr); +static void cb_ttbl_select(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr); +static void cb_ttbl_row_selected(pcb_hid_attribute_t *attrib, void *hid_ctx, pcb_hid_row_t *row); +static void cb_ttbl_free_row(pcb_hid_attribute_t *attrib, void *hid_ctx, pcb_hid_row_t *row); +static void cb_pane_set(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr); +static void cb_text_replace(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr); +static void cb_text_insert(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr); +static void cb_text_append(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr); +static void cb_text_get(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr); +static void cb_text_edit(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr); +static void cb_text_offs(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr); +static void cb_text_ro(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr); + +static void prv_expose(pcb_hid_attribute_t *attrib, pcb_hid_preview_t *prv, pcb_hid_gc_t gc, const pcb_hid_expose_ctx_t *e); +static pcb_bool prv_mouse(pcb_hid_attribute_t *attrib, pcb_hid_preview_t *prv, pcb_hid_mouse_ev_t kind, pcb_coord_t x, pcb_coord_t y); + +static const char * test_xpm[] = { +"8 8 4 1", +" c None", +"+ c #550000", +"@ c #ff0000", +"# c #00ff00", +" +##+ ", +" +##+ ", +" ++@@++ ", +" +@ @+ ", +" +@##@+ ", +" +@ @+ ", +" ++@@++ ", +" ++++ " +}; + + +static int attr_idx, attr_idx2; +static fgw_error_t pcb_act_dlg_test(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + const char *vals[] = { "foo", "bar", "baz", NULL }; + const char *tabs[] = { "original test", "new test", "tree-table", "pane", "preview", "text", NULL }; + char *row1[] = {"one", "foo", "FOO", NULL}; + char *row2[] = {"two", "bar", "BAR", NULL}; + char *row2b[] = {"under_two", "ut", "uuut", NULL}; + char *row3[] = {"three", "baz", "BAZ", NULL}; + const char *hdr[] = {"num", "data1", "data2", NULL}; + pcb_hid_dad_buttons_t clbtn[] = {{"Cancel", -1}, {"ok", 0}, {NULL, 0}}; + pcb_hid_row_t *row; + int failed; + + test_t ctx; + memset(&ctx, 0, sizeof(ctx)); + + PCB_DAD_BEGIN_VBOX(ctx.dlg); + PCB_DAD_COMPFLAG(ctx.dlg, PCB_HATF_EXPFILL); + PCB_DAD_BEGIN_TABBED(ctx.dlg, tabs); + PCB_DAD_CHANGE_CB(ctx.dlg, cb_tab_chg); + ctx.wtab = PCB_DAD_CURRENT(ctx.dlg); + + /* tab 0: "original test" */ + PCB_DAD_BEGIN_VBOX(ctx.dlg); + PCB_DAD_LABEL(ctx.dlg, "text1"); + PCB_DAD_BEGIN_TABLE(ctx.dlg, 3); + PCB_DAD_LABEL(ctx.dlg, "text2a"); + PCB_DAD_LABEL(ctx.dlg, "text2b"); + PCB_DAD_LABEL(ctx.dlg, "text2c"); + PCB_DAD_LABEL(ctx.dlg, "text2d"); + PCB_DAD_END(ctx.dlg); + PCB_DAD_LABEL(ctx.dlg, "text3"); + + PCB_DAD_BEGIN_VBOX(ctx.dlg); + PCB_DAD_COMPFLAG(ctx.dlg, PCB_HATF_FRAME); + PCB_DAD_LABEL(ctx.dlg, "spin test"); + PCB_DAD_BUTTON(ctx.dlg, "reset all to 42"); + PCB_DAD_CHANGE_CB(ctx.dlg, pcb_act_spin_reset); + + PCB_DAD_BEGIN_HBOX(ctx.dlg); + PCB_DAD_LABEL(ctx.dlg, "INT:"); + PCB_DAD_SPIN_INT(ctx.dlg); + ctx.wspin_int = PCB_DAD_CURRENT(ctx.dlg); + PCB_DAD_DEFAULT_NUM(ctx.dlg, 42); + PCB_DAD_CHANGE_CB(ctx.dlg, pcb_act_spin_upd); + PCB_DAD_LABEL(ctx.dlg, "->"); + PCB_DAD_LABEL(ctx.dlg, "n/a"); + ctx.wspout_int = PCB_DAD_CURRENT(ctx.dlg); + PCB_DAD_END(ctx.dlg); + + PCB_DAD_BEGIN_HBOX(ctx.dlg); + PCB_DAD_LABEL(ctx.dlg, "DBL:"); + PCB_DAD_SPIN_DOUBLE(ctx.dlg); + ctx.wspin_double = PCB_DAD_CURRENT(ctx.dlg); + PCB_DAD_DEFAULT_NUM(ctx.dlg, 42); + PCB_DAD_CHANGE_CB(ctx.dlg, pcb_act_spin_upd); + PCB_DAD_LABEL(ctx.dlg, "->"); + PCB_DAD_LABEL(ctx.dlg, "n/a"); + ctx.wspout_double = PCB_DAD_CURRENT(ctx.dlg); + PCB_DAD_END(ctx.dlg); + + PCB_DAD_BEGIN_HBOX(ctx.dlg); + PCB_DAD_LABEL(ctx.dlg, "CRD:"); + PCB_DAD_SPIN_COORD(ctx.dlg); + ctx.wspin_coord = PCB_DAD_CURRENT(ctx.dlg); + PCB_DAD_DEFAULT_NUM(ctx.dlg, PCB_MM_TO_COORD(42)); + PCB_DAD_CHANGE_CB(ctx.dlg, pcb_act_spin_upd); + PCB_DAD_LABEL(ctx.dlg, "->"); + PCB_DAD_LABEL(ctx.dlg, "n/a"); + ctx.wspout_coord = PCB_DAD_CURRENT(ctx.dlg); + PCB_DAD_END(ctx.dlg); + + PCB_DAD_END(ctx.dlg); + + PCB_DAD_ENUM(ctx.dlg, vals); + PCB_DAD_CHANGE_CB(ctx.dlg, pcb_act_attr_chg); + attr_idx = PCB_DAD_CURRENT(ctx.dlg); + PCB_DAD_INTEGER(ctx.dlg, "text2e"); + PCB_DAD_MINVAL(ctx.dlg, 1); + PCB_DAD_MAXVAL(ctx.dlg, 10); + PCB_DAD_DEFAULT_NUM(ctx.dlg, 3); + PCB_DAD_CHANGE_CB(ctx.dlg, pcb_act_attr_chg); + attr_idx2 = PCB_DAD_CURRENT(ctx.dlg); + PCB_DAD_BUTTON(ctx.dlg, "update!"); + PCB_DAD_CHANGE_CB(ctx.dlg, pcb_act_attr_chg); + PCB_DAD_END(ctx.dlg); + + /* tab 1: "new test" */ + PCB_DAD_BEGIN_VBOX(ctx.dlg); + PCB_DAD_LABEL(ctx.dlg, "new test."); + PCB_DAD_PICTURE(ctx.dlg, test_xpm); + PCB_DAD_BUTTON(ctx.dlg, "jump to the first tab"); + PCB_DAD_CHANGE_CB(ctx.dlg, cb_jump); + PCB_DAD_PICBUTTON(ctx.dlg, test_xpm); + PCB_DAD_CHANGE_CB(ctx.dlg, cb_color_reset); + PCB_DAD_COLOR(ctx.dlg); + PCB_DAD_CHANGE_CB(ctx.dlg, cb_color_print); + ctx.wclr = PCB_DAD_CURRENT(ctx.dlg); + PCB_DAD_END(ctx.dlg); + + + /* tab 2: tree table widget */ + PCB_DAD_BEGIN_VBOX(ctx.dlg); + PCB_DAD_COMPFLAG(ctx.dlg, PCB_HATF_EXPFILL); + PCB_DAD_TREE(ctx.dlg, 3, 1, hdr); + ctx.tt = PCB_DAD_CURRENT(ctx.dlg); + PCB_DAD_COMPFLAG(ctx.dlg, PCB_HATF_SCROLL); + PCB_DAD_CHANGE_CB(ctx.dlg, cb_ttbl_select); + PCB_DAD_TREE_SET_CB(ctx.dlg, free_cb, cb_ttbl_free_row); + PCB_DAD_TREE_SET_CB(ctx.dlg, selected_cb, cb_ttbl_row_selected); + PCB_DAD_TREE_APPEND(ctx.dlg, NULL, row1); + row = PCB_DAD_TREE_APPEND(ctx.dlg, NULL, row2); + PCB_DAD_TREE_APPEND_UNDER(ctx.dlg, row, row2b); + PCB_DAD_TREE_APPEND(ctx.dlg, NULL, row3); + PCB_DAD_BEGIN_HBOX(ctx.dlg); + PCB_DAD_BUTTON(ctx.dlg, "insert row"); + PCB_DAD_CHANGE_CB(ctx.dlg, cb_ttbl_insert); + PCB_DAD_BUTTON(ctx.dlg, "append row"); + PCB_DAD_CHANGE_CB(ctx.dlg, cb_ttbl_append); + PCB_DAD_BUTTON(ctx.dlg, "jump!"); + PCB_DAD_CHANGE_CB(ctx.dlg, cb_ttbl_jump); + PCB_DAD_BOOL(ctx.dlg, "filter"); + PCB_DAD_CHANGE_CB(ctx.dlg, cb_ttbl_filt); + PCB_DAD_END(ctx.dlg); + PCB_DAD_BEGIN_VBOX(ctx.dlg); + PCB_DAD_PROGRESS(ctx.dlg); + ctx.wprog = PCB_DAD_CURRENT(ctx.dlg); + PCB_DAD_END(ctx.dlg); + PCB_DAD_END(ctx.dlg); + + /* tab 3: pane */ + PCB_DAD_BEGIN_HPANE(ctx.dlg); + ctx.whpane = PCB_DAD_CURRENT(ctx.dlg); + PCB_DAD_BEGIN_VBOX(ctx.dlg); + PCB_DAD_LABEL(ctx.dlg, "left1"); + PCB_DAD_LABEL(ctx.dlg, "left2"); + PCB_DAD_END(ctx.dlg); + PCB_DAD_BEGIN_VPANE(ctx.dlg); + ctx.wvpane = PCB_DAD_CURRENT(ctx.dlg); + PCB_DAD_BEGIN_VBOX(ctx.dlg); + PCB_DAD_LABEL(ctx.dlg, "right top1"); + PCB_DAD_LABEL(ctx.dlg, "right top2"); + PCB_DAD_END(ctx.dlg); + PCB_DAD_BEGIN_VBOX(ctx.dlg); + PCB_DAD_LABEL(ctx.dlg, "right bottom1"); + PCB_DAD_LABEL(ctx.dlg, "right bottom2"); + PCB_DAD_BUTTON(ctx.dlg, "set all to 30%"); + PCB_DAD_CHANGE_CB(ctx.dlg, cb_pane_set); + PCB_DAD_END(ctx.dlg); + PCB_DAD_END(ctx.dlg); + PCB_DAD_END(ctx.dlg); + + /* tab 4: preview */ + PCB_DAD_BEGIN_VBOX(ctx.dlg); + PCB_DAD_PREVIEW(ctx.dlg, prv_expose, prv_mouse, NULL, NULL, 200, 200, NULL); + PCB_DAD_LABEL(ctx.dlg, "This is a cool preview widget."); + PCB_DAD_END(ctx.dlg); + + /* tab 5: text */ + PCB_DAD_BEGIN_VBOX(ctx.dlg); + PCB_DAD_COMPFLAG(ctx.dlg, PCB_HATF_EXPFILL); + PCB_DAD_TEXT(ctx.dlg, NULL); + PCB_DAD_COMPFLAG(ctx.dlg, PCB_HATF_SCROLL | PCB_HATF_EXPFILL); + PCB_DAD_CHANGE_CB(ctx.dlg, cb_text_edit); + ctx.wtxt = PCB_DAD_CURRENT(ctx.dlg); + PCB_DAD_BEGIN_HBOX(ctx.dlg); + PCB_DAD_LABEL(ctx.dlg, ""); + ctx.wtxtpos = PCB_DAD_CURRENT(ctx.dlg); + PCB_DAD_BUTTON(ctx.dlg, "half the offset"); + PCB_DAD_CHANGE_CB(ctx.dlg, cb_text_offs); + PCB_DAD_END(ctx.dlg); + PCB_DAD_BEGIN_HBOX(ctx.dlg); + PCB_DAD_BUTTON(ctx.dlg, "replace"); + PCB_DAD_CHANGE_CB(ctx.dlg, cb_text_replace); + PCB_DAD_BUTTON(ctx.dlg, "insert"); + PCB_DAD_CHANGE_CB(ctx.dlg, cb_text_insert); + PCB_DAD_BUTTON(ctx.dlg, "append"); + PCB_DAD_CHANGE_CB(ctx.dlg, cb_text_append); + PCB_DAD_BUTTON(ctx.dlg, "get"); + PCB_DAD_CHANGE_CB(ctx.dlg, cb_text_get); + PCB_DAD_BUTTON(ctx.dlg, "ro"); + ctx.txtro = 0; + PCB_DAD_CHANGE_CB(ctx.dlg, cb_text_ro); + PCB_DAD_END(ctx.dlg); + PCB_DAD_END(ctx.dlg); + + PCB_DAD_END(ctx.dlg); + PCB_DAD_BUTTON_CLOSES(ctx.dlg, clbtn); + PCB_DAD_END(ctx.dlg); + + PCB_DAD_AUTORUN("dlg_test", ctx.dlg, "attribute dialog test", &ctx, failed); + + if (failed) + pcb_message(PCB_MSG_WARNING, "Test dialog cancelled"); + + PCB_DAD_FREE(ctx.dlg); + + PCB_ACT_IRES(0); + return 0; +} + +static void pcb_act_attr_chg(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + static pcb_hid_attr_val_t val; + static pcb_bool st; + printf("Chg\n"); + + st = !st; + val.int_value = (val.int_value + 1) % 3; +/* pcb_gui->attr_dlg_widget_state(hid_ctx, attr_idx, st);*/ + + pcb_gui->attr_dlg_set_value(hid_ctx, attr_idx, &val); +} + +static void pcb_act_spin_reset(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + test_t *ctx = caller_data; + pcb_hid_attr_val_t hv; + + hv.int_value = 42; + hv.real_value = 42.0; + hv.coord_value = PCB_MM_TO_COORD(42); + + pcb_gui->attr_dlg_set_value(hid_ctx, ctx->wspin_int, &hv); + pcb_gui->attr_dlg_set_value(hid_ctx, ctx->wspin_double, &hv); + pcb_gui->attr_dlg_set_value(hid_ctx, ctx->wspin_coord, &hv); +} + +static void pcb_act_spin_upd(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + test_t *ctx = caller_data; + pcb_hid_attr_val_t hv; + char tmp[256]; + + hv.str_value = tmp; + + sprintf(tmp, "%d", ctx->dlg[ctx->wspin_int].default_val.int_value); + pcb_gui->attr_dlg_set_value(hid_ctx, ctx->wspout_int, &hv); + sprintf(tmp, "%f", ctx->dlg[ctx->wspin_double].default_val.real_value); + pcb_gui->attr_dlg_set_value(hid_ctx, ctx->wspout_double, &hv); + pcb_snprintf(tmp, sizeof(tmp), "%mm\n%ml", ctx->dlg[ctx->wspin_coord].default_val.coord_value, ctx->dlg[ctx->wspin_coord].default_val.coord_value); + pcb_gui->attr_dlg_set_value(hid_ctx, ctx->wspout_coord, &hv); +} + + +static void cb_tab_chg(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + test_t *ctx = caller_data; + printf("Tab switch to %d!\n", ctx->dlg[ctx->wtab].default_val.int_value); +} + +static void cb_jump(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + pcb_hid_attr_val_t val; + test_t *ctx = caller_data; + + printf("Jumping tabs\n"); + val.int_value = 0; + pcb_gui->attr_dlg_set_value(hid_ctx, ctx->wtab, &val); +} + +static void cb_ttbl_insert(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + test_t *ctx = caller_data; + pcb_hid_attribute_t *treea = &ctx->dlg[ctx->tt]; + char *rowdata[] = {NULL, "ins", "dummy", NULL}; + pcb_hid_row_t *new_row, *row = pcb_dad_tree_get_selected(treea); + pcb_hid_attr_val_t val; + + rowdata[0] = pcb_strdup_printf("dyn_%d", ctx->ttctr++); + new_row = pcb_dad_tree_insert(treea, row, rowdata); + new_row->user_data2.lng = 1; + + val.real_value = (double)ctx->ttctr / 20.0; + pcb_gui->attr_dlg_set_value(hid_ctx, ctx->wprog, &val); +} + +static void cb_ttbl_append(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + test_t *ctx = caller_data; + pcb_hid_attribute_t *treea = &ctx->dlg[ctx->tt]; + char *rowdata[] = {NULL, "app", "dummy", NULL}; + pcb_hid_row_t *new_row, *row = pcb_dad_tree_get_selected(treea); + pcb_hid_attr_val_t val; + + rowdata[0] = pcb_strdup_printf("dyn_%d", ctx->ttctr++); + new_row = pcb_dad_tree_append(treea, row, rowdata); + new_row->user_data2.lng = 1; + + val.real_value = (double)ctx->ttctr / 20.0; + pcb_gui->attr_dlg_set_value(hid_ctx, ctx->wprog, &val); +} + +static void cb_ttbl_jump(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + test_t *ctx = caller_data; + pcb_hid_attr_val_t val; + + val.str_value = "two/under_two"; + pcb_gui->attr_dlg_set_value(hid_ctx, ctx->tt, &val); +} + +static void ttbl_filt(gdl_list_t *list, int hide) +{ + pcb_hid_row_t *r; + for(r = gdl_first(list); r != NULL; r = gdl_next(list, r)) { + if (r->user_data2.lng) + r->hide = hide; + ttbl_filt(&r->children, hide); + } +} + +static void cb_ttbl_filt(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + test_t *ctx = caller_data; + pcb_hid_attribute_t *treea = &ctx->dlg[ctx->tt]; + pcb_hid_tree_t *tree = (pcb_hid_tree_t *)treea->enumerations; + + ttbl_filt(&tree->rows, attr->default_val.int_value); + pcb_dad_tree_update_hide(treea); +} + +/* table level selection */ +static void cb_ttbl_select(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + pcb_hid_row_t *row = pcb_dad_tree_get_selected(attr); + if (attr->default_val.str_value != NULL) + pcb_trace("tt tbl selected: path=%s row=%p '%s'\n", attr->default_val.str_value, row, row->cell[0]); + else + pcb_trace("tt tbl selected: \n"); +} + +/* row level selection */ +static void cb_ttbl_row_selected(pcb_hid_attribute_t *attrib, void *hid_ctx, pcb_hid_row_t *row) +{ + if (row != NULL) + pcb_trace("tt row selected: row=%p '%s'\n", row, row->cell[0]); + else + pcb_trace("tt row selected: \n"); +} + +static void cb_ttbl_free_row(pcb_hid_attribute_t *attrib, void *hid_ctx, pcb_hid_row_t *row) +{ + if (row->user_data2.lng) + free(row->cell[0]); +} + +static void cb_pane_set(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + test_t *ctx = caller_data; + pcb_hid_attr_val_t val; + + val.real_value = 0.3; + pcb_gui->attr_dlg_set_value(hid_ctx, ctx->whpane, &val); + pcb_gui->attr_dlg_set_value(hid_ctx, ctx->wvpane, &val); +} + +static void cb_text_replace(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + test_t *ctx = caller_data; + pcb_hid_attribute_t *atxt = &ctx->dlg[ctx->wtxt]; + pcb_hid_text_t *txt = (pcb_hid_text_t *)atxt->enumerations; + txt->hid_set_text(atxt, hid_ctx, PCB_HID_TEXT_REPLACE, "Hello\nworld!\n"); +} + +static void cb_text_insert(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + test_t *ctx = caller_data; + pcb_hid_attribute_t *atxt = &ctx->dlg[ctx->wtxt]; + pcb_hid_text_t *txt = (pcb_hid_text_t *)atxt->enumerations; + txt->hid_set_text(atxt, hid_ctx, PCB_HID_TEXT_INSERT, "ins"); +} + +static void cb_text_append(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + test_t *ctx = caller_data; + pcb_hid_attribute_t *atxt = &ctx->dlg[ctx->wtxt]; + pcb_hid_text_t *txt = (pcb_hid_text_t *)atxt->enumerations; + txt->hid_set_text(atxt, hid_ctx, PCB_HID_TEXT_APPEND | PCB_HID_TEXT_MARKUP, "appred\n"); +} + +static void cb_text_get(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + test_t *ctx = caller_data; + pcb_hid_attribute_t *atxt = &ctx->dlg[ctx->wtxt]; + pcb_hid_text_t *txt = (pcb_hid_text_t *)atxt->enumerations; + char *s; + s = txt->hid_get_text(atxt, hid_ctx); + printf("text: '%s'\n", s); + free(s); +} + +static void cb_text_edit(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + test_t *ctx = caller_data; + pcb_hid_text_t *txt = (pcb_hid_text_t *)attr->enumerations; + long x, y, o; + char buf[256]; + pcb_hid_attr_val_t val; + + txt->hid_get_xy(attr, hid_ctx, &x, &y); + o = txt->hid_get_offs(attr, hid_ctx); + sprintf(buf, "cursor after edit: line %ld col %ld offs %ld", y, x, o); + val.str_value = buf; + pcb_gui->attr_dlg_set_value(hid_ctx, ctx->wtxtpos, &val); +} + +static void cb_text_offs(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + test_t *ctx = caller_data; + pcb_hid_attribute_t *atxt = &ctx->dlg[ctx->wtxt]; + pcb_hid_text_t *txt = (pcb_hid_text_t *)atxt->enumerations; + txt->hid_set_offs(atxt, hid_ctx, txt->hid_get_offs(atxt, hid_ctx) / 2); +} + +static void cb_text_ro(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + test_t *ctx = caller_data; + pcb_hid_attribute_t *atxt = &ctx->dlg[ctx->wtxt]; + pcb_hid_text_t *txt = (pcb_hid_text_t *)atxt->enumerations; + ctx->txtro = !ctx->txtro; + txt->hid_set_readonly(atxt, hid_ctx, ctx->txtro); +} + +static void prv_expose(pcb_hid_attribute_t *attrib, pcb_hid_preview_t *prv, pcb_hid_gc_t gc, const pcb_hid_expose_ctx_t *e) +{ + pcb_gui->set_color(gc, pcb_color_red); + pcb_text_draw_string_simple(NULL, "foo", PCB_MM_TO_COORD(1), PCB_MM_TO_COORD(20), 500, 10.0, 0, 0, 0, 0, 0); + + printf("expose in dlg_test!\n"); +} + + +static pcb_bool prv_mouse(pcb_hid_attribute_t *attrib, pcb_hid_preview_t *prv, pcb_hid_mouse_ev_t kind, pcb_coord_t x, pcb_coord_t y) +{ + pcb_printf("Mouse %d %mm %mm\n", kind, x, y); + return (kind == PCB_HID_MOUSE_PRESS) || (kind == PCB_HID_MOUSE_RELEASE); +} + +static void cb_color_print(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + test_t *ctx = caller_data; + + printf("currenct color: #%02x%02x%02x\n", + ctx->dlg[ctx->wclr].default_val.clr_value.r, ctx->dlg[ctx->wclr].default_val.clr_value.g, ctx->dlg[ctx->wclr].default_val.clr_value.b); +} + +static void cb_color_reset(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + test_t *ctx = caller_data; + pcb_hid_attr_val_t val; + + pcb_color_load_str(&val.clr_value, "#005599"); + pcb_gui->attr_dlg_set_value(hid_ctx, ctx->wclr, &val); +} + Index: tags/2.1.2/src_plugins/dialogs/dlg_undo.c =================================================================== --- tags/2.1.2/src_plugins/dialogs/dlg_undo.c (nonexistent) +++ tags/2.1.2/src_plugins/dialogs/dlg_undo.c (revision 24813) @@ -0,0 +1,191 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2018 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include +#include "event.h" +#include "undo.h" + +const char *dlg_undo_cookie = "undo dialog"; + +typedef struct{ + PCB_DAD_DECL_NOINIT(dlg) + int wlist; + long serial; /* last seen undo serial, for updating the dialog on change */ + int active; /* already open - allow only one instance */ +} undo_ctx_t; + +undo_ctx_t undo_ctx; + +extern uundo_list_t pcb_uundo; + +static void undo_close_cb(void *caller_data, pcb_hid_attr_ev_t ev) +{ + undo_ctx_t *ctx = caller_data; + PCB_DAD_FREE(ctx->dlg); + memset(ctx, 0, sizeof(undo_ctx_t)); +} + +static void cb_undo(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + pcb_undo(pcb_true); +} + +static void cb_redo(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + pcb_redo(pcb_true); +} + +static void cb_clear(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + pcb_undo_clear_list(pcb_true); +} + + +static void undo_data2dlg(undo_ctx_t *ctx) +{ + pcb_hid_attribute_t *attr; + pcb_hid_tree_t *tree; + pcb_hid_row_t *r; + char *cell[4], *cursor_path = NULL; + uundo_item_t *i; + char *payload, buff[8192], mark[2], ser[64]; + + attr = &ctx->dlg[ctx->wlist]; + tree = (pcb_hid_tree_t *)attr->enumerations; + + /* remember cursor */ + r = pcb_dad_tree_get_selected(attr); + if (r != NULL) + cursor_path = pcb_strdup(r->cell[0]); + + /* remove existing items */ + pcb_dad_tree_clear(tree); + + mark[1] = '\0'; + cell[3] = NULL; + for(i = pcb_uundo.head; i != NULL; i = i->next) { + payload = ""; + if (i->oper->item_print != NULL) { + i->oper->item_print(i->udata, buff, sizeof(buff)); + payload = buff; + } + mark[0] = '\0'; + if ((i == pcb_uundo.head) && (i == pcb_uundo.tail)) + mark[0] = '*'; + else if (i == pcb_uundo.head) + mark[0] = 'h'; + else if (i == pcb_uundo.tail) + mark[0] = 't'; + sprintf(ser, "%ld", (long)i->serial); + cell[0] = pcb_strdup(ser); + cell[1] = pcb_strdup(mark); + cell[2] = pcb_strdup(payload); + pcb_dad_tree_append(attr, NULL, cell); + } + + /* restore cursor */ + if (cursor_path != NULL) { + pcb_hid_attr_val_t hv; + hv.str_value = cursor_path; + pcb_gui->attr_dlg_set_value(ctx->dlg_hid_ctx, ctx->wlist, &hv); + free(cursor_path); + } +} + +static void pcb_dlg_undo(void) +{ + static const char *hdr[] = {"serial", "flg", "operation", NULL}; + pcb_hid_dad_buttons_t clbtn[] = {{"Close", 0}, {NULL, 0}}; + + if (undo_ctx.active) + return; /* do not open another */ + + PCB_DAD_BEGIN_VBOX(undo_ctx.dlg); + PCB_DAD_COMPFLAG(undo_ctx.dlg, PCB_HATF_EXPFILL); + PCB_DAD_TREE(undo_ctx.dlg, 3, 0, hdr); + PCB_DAD_COMPFLAG(undo_ctx.dlg, PCB_HATF_EXPFILL | PCB_HATF_SCROLL); + undo_ctx.wlist = PCB_DAD_CURRENT(undo_ctx.dlg); + + PCB_DAD_BEGIN_HBOX(undo_ctx.dlg); + PCB_DAD_BUTTON(undo_ctx.dlg, "Undo"); + PCB_DAD_CHANGE_CB(undo_ctx.dlg, cb_undo); + PCB_DAD_BUTTON(undo_ctx.dlg, "Redo"); + PCB_DAD_CHANGE_CB(undo_ctx.dlg, cb_redo); + PCB_DAD_BUTTON(undo_ctx.dlg, "Clear"); + PCB_DAD_CHANGE_CB(undo_ctx.dlg, cb_clear); + PCB_DAD_END(undo_ctx.dlg); + PCB_DAD_BUTTON_CLOSES(undo_ctx.dlg, clbtn); + PCB_DAD_END(undo_ctx.dlg); + + /* set up the context */ + undo_ctx.active = 1; + + PCB_DAD_DEFSIZE(undo_ctx.dlg, 300, 400); + PCB_DAD_NEW("undo", undo_ctx.dlg, "pcb-rnd undo list", &undo_ctx, pcb_false, undo_close_cb); + undo_data2dlg(&undo_ctx); +} + +static const char pcb_acts_UndoDialog[] = "UndoDialog()\n"; +static const char pcb_acth_UndoDialog[] = "Open the undo dialog."; +static fgw_error_t pcb_act_UndoDialog(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + pcb_dlg_undo(); + PCB_ACT_IRES(0); + return 0; +} + +/* update the dialog after an undo operation */ +static void pcb_dlg_undo_ev(void *user_data, int argc, pcb_event_arg_t argv[]) +{ + undo_ctx_t *ctx = user_data; + if (!ctx->active) + return; + undo_data2dlg(ctx); +} + +/* Check if the serial has changed and update the dialog if so */ +static void pcb_dlg_undo_ev_chk(void *user_data, int argc, pcb_event_arg_t argv[]) +{ + undo_ctx_t *ctx = user_data; + if (!ctx->active) + return; + if (ctx->serial != pcb_uundo.serial) { + undo_data2dlg(ctx); + ctx->serial = pcb_uundo.serial; + } +} + + +static void pcb_dlg_undo_init(void) +{ + pcb_event_bind(PCB_EVENT_UNDO_POST, pcb_dlg_undo_ev, &undo_ctx, dlg_undo_cookie); + pcb_event_bind(PCB_EVENT_USER_INPUT_POST, pcb_dlg_undo_ev_chk, &undo_ctx, dlg_undo_cookie); +} + +static void pcb_dlg_undo_uninit(void) +{ + pcb_event_unbind_allcookie(dlg_undo_cookie); +} Index: tags/2.1.2/src_plugins/dialogs/dlg_view.c =================================================================== --- tags/2.1.2/src_plugins/dialogs/dlg_view.c (nonexistent) +++ tags/2.1.2/src_plugins/dialogs/dlg_view.c (revision 24813) @@ -0,0 +1,814 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2018 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "config.h" + +#include +#include +#include + +#include "actions.h" +#include "board.h" +#include "conf_core.h" +#include "view.h" +#include "draw.h" +#include "drc.h" +#include "event.h" +#include "hid_inlines.h" +#include "hid_dad.h" +#include "hid_dad_tree.h" +#include "undo.h" +#include "safe_fs.h" +#include "misc_util.h" + +static const char *dlg_view_cookie = "dlg_drc"; + +typedef struct view_ctx_s view_ctx_t; +struct view_ctx_s { + PCB_DAD_DECL_NOINIT(dlg) + pcb_board_t *pcb; + pcb_view_list_t *lst; + pcb_view_list_t lst_local; + int alloced, active; + + void (*refresh)(view_ctx_t *ctx); + + unsigned long int selected; + + int wpos, wlist, wcount, wprev, wdescription, wmeasure; + int wbtn_cut; + + unsigned list_alloced:1; +}; + +view_ctx_t view_ctx; + +static void view_close_cb(void *caller_data, pcb_hid_attr_ev_t ev) +{ + view_ctx_t *ctx = caller_data; + + PCB_DAD_FREE(ctx->dlg); + if (ctx->list_alloced) { + pcb_view_list_free(ctx->lst); + ctx->lst = NULL; + } + if (ctx->alloced) + free(ctx); + else + ctx->active = 0; +} + +static void view2dlg_list(view_ctx_t *ctx) +{ + pcb_view_t *v; + pcb_hid_attribute_t *attr; + pcb_hid_tree_t *tree; + pcb_hid_row_t *r; + char *cell[3], *cursor_path = NULL; + + attr = &ctx->dlg[ctx->wlist]; + tree = (pcb_hid_tree_t *)attr->enumerations; + + /* remember cursor */ + r = pcb_dad_tree_get_selected(attr); + if (r != NULL) + cursor_path = pcb_strdup(r->cell[0]); + + /* remove existing items */ + pcb_dad_tree_clear(tree); + + /* add all items */ + cell[2] = NULL; + for(v = pcb_view_list_first(ctx->lst); v != NULL; v = pcb_view_list_next(v)) { + pcb_hid_row_t *r, *rt; + rt = htsp_get(&tree->paths, v->type); + if (rt == NULL) { + cell[0] = pcb_strdup(v->type); + cell[1] = pcb_strdup(""); + rt = pcb_dad_tree_append(attr, NULL, cell); + rt->user_data2.lng = 0; + } + + cell[0] = pcb_strdup_printf("%lu", v->uid); + cell[1] = pcb_strdup(v->title); + r = pcb_dad_tree_append_under(attr, rt, cell); + r->user_data2.lng = v->uid; + pcb_dad_tree_expcoll(attr, rt, 1, 0); + } + + /* restore cursor */ + if (cursor_path != NULL) { + pcb_hid_attr_val_t hv; + hv.str_value = cursor_path; + pcb_gui->attr_dlg_set_value(ctx->dlg_hid_ctx, ctx->wlist, &hv); + free(cursor_path); + } +} + +static void view2dlg_pos(view_ctx_t *ctx) +{ + long cnt; + + pcb_view_by_uid_cnt(ctx->lst, ctx->selected, &cnt); + if (cnt >= 0) { + char tmp[32]; + sprintf(tmp, "%ld", cnt+1); + PCB_DAD_SET_VALUE(ctx->dlg_hid_ctx, ctx->wpos, str_value, pcb_strdup(tmp)); + } + else + PCB_DAD_SET_VALUE(ctx->dlg_hid_ctx, ctx->wpos, str_value, pcb_strdup("")); +} + +static void view2dlg_count(view_ctx_t *ctx) +{ + char tmp[32]; + + sprintf(tmp, "%d", pcb_view_list_length(ctx->lst)); + PCB_DAD_SET_VALUE(ctx->dlg_hid_ctx, ctx->wcount, str_value, pcb_strdup(tmp)); +} + +static void view2dlg(view_ctx_t *ctx) +{ + view2dlg_count(ctx); + + if (ctx->wlist >= 0) + view2dlg_list(ctx); + + if (ctx->wpos >= 0) + view2dlg_pos(ctx); +} + +void view_simple_show(view_ctx_t *ctx) +{ + pcb_view_t *v = pcb_view_by_uid(ctx->lst, ctx->selected); + if (v != NULL) { + pcb_view_goto(v); + PCB_DAD_SET_VALUE(ctx->dlg_hid_ctx, ctx->wdescription, str_value, pcb_text_wrap(pcb_strdup(v->description), 32, '\n', ' ')); + switch(v->data_type) { + case PCB_VIEW_PLAIN: + PCB_DAD_SET_VALUE(ctx->dlg_hid_ctx, ctx->wmeasure, str_value, pcb_strdup("")); + break; + case PCB_VIEW_DRC: + if (v->data.drc.have_measured) + PCB_DAD_SET_VALUE(ctx->dlg_hid_ctx, ctx->wmeasure, str_value, pcb_strdup_printf("DRC: %m+required: %$ms\nmeasured: %$ms\n", conf_core.editor.grid_unit->allow, v->data.drc.required_value, v->data.drc.measured_value)); + else + PCB_DAD_SET_VALUE(ctx->dlg_hid_ctx, ctx->wmeasure, str_value, pcb_strdup_printf("DRC: %m+required: %$ms\n", conf_core.editor.grid_unit->allow, v->data.drc.required_value)); + break; + } + } + + if (v == NULL) { + ctx->selected = 0; + PCB_DAD_SET_VALUE(ctx->dlg_hid_ctx, ctx->wdescription, str_value, pcb_strdup("")); + PCB_DAD_SET_VALUE(ctx->dlg_hid_ctx, ctx->wmeasure, str_value, pcb_strdup("")); + } + else + pcb_dad_preview_zoomto(&ctx->dlg[ctx->wprev], &v->bbox); +} + +static void view_select(pcb_hid_attribute_t *attrib, void *hid_ctx, pcb_hid_row_t *row) +{ + pcb_hid_tree_t *tree = (pcb_hid_tree_t *)attrib->enumerations; + view_ctx_t *ctx = tree->user_ctx; + + if (row != NULL) + ctx->selected = row->user_data2.lng; + view_simple_show(ctx); +} + +static vtp0_t view_color_save; + +static void view_expose_cb(pcb_hid_attribute_t *attrib, pcb_hid_preview_t *prv, pcb_hid_gc_t gc, const pcb_hid_expose_ctx_t *e) +{ + view_ctx_t *ctx = prv->user_ctx; + pcb_xform_t xform; + int old_termlab, g; + static const pcb_color_t *offend_color[2]; + pcb_view_t *v = pcb_view_by_uid(ctx->lst, ctx->selected); + size_t n; + void **p; + + if (v == NULL) + return; + + offend_color[0] = pcb_color_red; + offend_color[1] = pcb_color_blue; + + /* NOTE: zoom box was already set on select */ + + /* save offending object colors */ + vtp0_truncate(&view_color_save, 0); + for(g = 0; g < 2; g++) { + pcb_idpath_t *i; + for(i = pcb_idpath_list_first(&v->objs[g]); i != NULL; i = pcb_idpath_list_next(i)) { + pcb_any_obj_t *obj = pcb_idpath2obj(ctx->pcb->Data, i); + if ((obj != NULL) && (obj->type & PCB_OBJ_CLASS_REAL)) { + vtp0_append(&view_color_save, obj); + if (obj->override_color != NULL) + vtp0_append(&view_color_save, (char *)obj->override_color); + else + vtp0_append(&view_color_save, NULL); + obj->override_color = offend_color[g]; + } + } + } + + /* draw the board */ + old_termlab = pcb_draw_force_termlab; + pcb_draw_force_termlab = 1; + memset(&xform, 0, sizeof(xform)); + xform.layer_faded = 1; + pcb_hid_expose_all(pcb_gui, e, &xform); + pcb_draw_force_termlab = old_termlab; + + /* restore object color */ + for(n = 0, p = view_color_save.array; n < view_color_save.used; n+=2,p+=2) { + pcb_any_obj_t *obj = p[0]; + pcb_color_t *s = p[1]; + obj->override_color = s; + } + vtp0_truncate(&view_color_save, 0); +} + + +static pcb_bool view_mouse_cb(pcb_hid_attribute_t *attrib, pcb_hid_preview_t *prv, pcb_hid_mouse_ev_t kind, pcb_coord_t x, pcb_coord_t y) +{ + return pcb_false; /* don't redraw */ +} + +void view_refresh(view_ctx_t *ctx) +{ + if (ctx->refresh != NULL) + ctx->refresh(ctx); + view2dlg(ctx); +} + +static void view_preview_update(view_ctx_t *ctx) +{ + pcb_hid_attr_val_t hv; + + if ((ctx == NULL) || (!ctx->active) || (ctx->selected == 0)) + return; + + hv.str_value = NULL; + pcb_gui->attr_dlg_set_value(ctx->dlg_hid_ctx, ctx->wprev, &hv); +} + + +static void view_refresh_btn_cb(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + view_refresh((view_ctx_t *)caller_data); +} + +static void view_close_btn_cb(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + view_close_cb(caller_data, 0); +} + +static void view_stepped(view_ctx_t *ctx, pcb_view_t *v) +{ + if (v == NULL) + return; + ctx->selected = v->uid; + view_simple_show(ctx); + view2dlg_pos(ctx); +} + +static void view_del_btn_cb(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr_btn) +{ + view_ctx_t *ctx = caller_data; + pcb_view_t *v, *newv; + + if (ctx->wlist < 0) { /* simplified dialog, no list */ + v = pcb_view_by_uid(ctx->lst, ctx->selected); + if (v == NULL) + return; + newv = pcb_view_list_next(v); + if (newv == NULL) + newv = pcb_view_list_first(ctx->lst); + pcb_view_free(v); + view_stepped(ctx, newv); + view2dlg_count(ctx); + } + else { /* full dialog, go by the list */ + pcb_hid_attribute_t *attr = &ctx->dlg[ctx->wlist]; + pcb_hid_row_t *rc, *r = pcb_dad_tree_get_selected(attr); + + if (r == NULL) + return; + + if (r->user_data2.lng == 0) { + /* remove a whole category - assume a single level */ + for(rc = gdl_first(&r->children); rc != NULL; rc = gdl_next(&r->children, rc)) { + v = pcb_view_by_uid(ctx->lst, rc->user_data2.lng); + pcb_dad_tree_remove(attr, rc); + if (v != NULL) + pcb_view_free(v); + } + pcb_dad_tree_remove(attr, r); + } + else { + /* remove a single item */ + v = pcb_view_by_uid(ctx->lst, r->user_data2.lng); + pcb_dad_tree_remove(attr, r); + if (v != NULL) + pcb_view_free(v); + } + } +} + +static void view_copy_btn_cb(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr_btn) +{ + view_ctx_t *ctx = caller_data; + pcb_view_t *v; + gds_t tmp; + pcb_hid_attribute_t *attr = &ctx->dlg[ctx->wlist]; + pcb_hid_row_t *rc, *r = pcb_dad_tree_get_selected(attr); + int btn_idx = attr_btn - ctx->dlg; + int cut = (ctx->wbtn_cut == btn_idx); + + if (r == NULL) + return; + + /* only full dialog, go by the list */ + + gds_init(&tmp); + + pcb_view_save_list_begin(&tmp, NULL); + if (r->user_data2.lng == 0) { + /* dump a whole category */ + for(rc = gdl_first(&r->children); rc != NULL; rc = gdl_next(&r->children, rc)) { + v = pcb_view_by_uid(ctx->lst, rc->user_data2.lng); + if (v != NULL) { + pcb_view_save(v, &tmp, " "); + if (cut) + pcb_view_free(v); + } + } + } + else { + /* dump a single item */ + v = pcb_view_by_uid(ctx->lst, r->user_data2.lng); + if (v != NULL) { + pcb_view_save(v, &tmp, " "); + if (cut) + pcb_view_free(v); + } + } + pcb_view_save_list_end(&tmp, NULL); + pcb_gui->clip_set(PCB_HID_CLIPFMT_TEXT, tmp.array, tmp.used+1); + gds_uninit(&tmp); + if (cut) + view2dlg_list(ctx); +} + +static void view_paste_btn_cb(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr_btn) +{ + view_ctx_t *ctx = caller_data; + pcb_hid_clipfmt_t cformat; + void *cdata, *load_ctx; + size_t clen; + pcb_view_t *v, *vt = NULL; + pcb_hid_attribute_t *attr = &ctx->dlg[ctx->wlist]; + pcb_hid_row_t *r = pcb_dad_tree_get_selected(attr); + + if (r != NULL) { + /* if cursor is a category */ + if (r->user_data2.lng == 0) { + r = gdl_first(&r->children); + if (r == NULL) + return; + } + vt = pcb_view_by_uid(ctx->lst, r->user_data2.lng); + } + + if (pcb_gui->clip_get(&cformat, &cdata, &clen) != 0) + return; + + if (cformat != PCB_HID_CLIPFMT_TEXT) { + pcb_gui->clip_free(cformat, cdata, clen); + return; + } + + load_ctx = pcb_view_load_start_str(cdata); + pcb_gui->clip_free(cformat, cdata, clen); + if (load_ctx == NULL) + return; + + for(;;) { + v = pcb_view_load_next(load_ctx, NULL); + if (v == NULL) + break; + pcb_view_list_insert_before(ctx->lst, vt, v); + vt = v; + } + + pcb_view_load_end(load_ctx); + view2dlg_list(ctx); +} + +static void view_save_btn_cb(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr_btn) +{ + view_ctx_t *ctx = caller_data; + gds_t tmp; + pcb_view_t *v; + char *fn; + FILE *f; + + fn = pcb_gui->fileselect("Save view list", "Save all views from the list", "view.lht", "lht", NULL, "view", 0, NULL); + if (fn == NULL) + return; + + f = pcb_fopen(fn, "w"); + if (f == NULL) { + pcb_message(PCB_MSG_ERROR, "Can't open %s for write\n", fn); + return; + } + + gds_init(&tmp); + pcb_view_save_list_begin(&tmp, NULL); + for(v = pcb_view_list_first(ctx->lst); v != NULL; v = pcb_view_list_next(v)) + pcb_view_save(v, &tmp, " "); + pcb_view_save_list_end(&tmp, NULL); + + fprintf(f, "%s", tmp.array); + fclose(f); + gds_uninit(&tmp); +} + +static void view_load_btn_cb(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr_btn) +{ + view_ctx_t *ctx = caller_data; + pcb_view_t *v; + char *fn; + FILE *f; + void *load_ctx; + + fn = pcb_gui->fileselect("Load view list", "Load all views from the list", "view.lht", "lht", NULL, "view", PCB_HID_FSD_READ, NULL); + if (fn == NULL) + return; + + f = pcb_fopen(fn, "r"); + if (f == NULL) { + pcb_message(PCB_MSG_ERROR, "Can't open %s for read\n", fn); + return; + } + + load_ctx = pcb_view_load_start_file(f); + if (load_ctx == NULL) { + pcb_message(PCB_MSG_ERROR, "Error parsing %s - is it a view list?\n", fn); + fclose(f); + return; + } + fclose(f); + + pcb_view_list_free_fields(ctx->lst); + for(;;) { + v = pcb_view_load_next(load_ctx, NULL); + if (v == NULL) + break; + pcb_view_list_append(ctx->lst, v); + } + + pcb_view_load_end(load_ctx); + view2dlg_list(ctx); +} + +static void view_select_obj(view_ctx_t *ctx, pcb_view_t *v) +{ + pcb_idpath_t *i; + int chg = 0; + + if (v == NULL) + return; + + for(i = pcb_idpath_list_first(&v->objs[0]); i != NULL; i = pcb_idpath_list_next(i)) { + pcb_any_obj_t *obj = pcb_idpath2obj(ctx->pcb->Data, i); + if ((obj != NULL) && (obj->type & PCB_OBJ_CLASS_REAL)) { + pcb_undo_add_obj_to_flag((void *)obj); + pcb_draw_obj(obj); + PCB_FLAG_ASSIGN(PCB_FLAG_SELECTED, 1, obj); + chg = 1; + } + } + + if (chg) { + pcb_board_set_changed_flag(pcb_true); + view_preview_update(ctx); + } +} + +static void view_select_btn_cb(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr_btn) +{ + view_ctx_t *ctx = caller_data; + pcb_hid_attribute_t *attr = &ctx->dlg[ctx->wlist]; + pcb_hid_row_t *rc, *r = pcb_dad_tree_get_selected(attr); + + if (r == NULL) + return; + + if (r->user_data2.lng == 0) { + /* select a whole category - assume a single level */ + for(rc = gdl_first(&r->children); rc != NULL; rc = gdl_next(&r->children, rc)) { + view_select_obj(ctx, pcb_view_by_uid(ctx->lst, rc->user_data2.lng)); + } + } + else { + /* select a single item */ + view_select_obj(ctx, pcb_view_by_uid(ctx->lst, r->user_data2.lng)); + } +} + +static void simple_rewind(view_ctx_t *ctx) +{ + pcb_view_t *v = pcb_view_list_first(ctx->lst); + if (v != NULL) { + ctx->selected = v->uid; + view_stepped(ctx, v); + } + else + ctx->selected = 0; +} + +static void view_prev_btn_cb(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + view_ctx_t *ctx = caller_data; + pcb_view_t *v = pcb_view_by_uid(ctx->lst, ctx->selected); + + if (v == NULL) + v = pcb_view_list_first(ctx->lst); + else + v = pcb_view_list_prev(v); + view_stepped(ctx, v); +} + +static void view_next_btn_cb(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + view_ctx_t *ctx = caller_data; + pcb_view_t *v = pcb_view_by_uid(ctx->lst, ctx->selected); + + if (v == NULL) + v = pcb_view_list_first(ctx->lst); + else + v = pcb_view_list_next(v); + view_stepped(ctx, v); +} + + +static void pcb_dlg_view_full(const char *id, view_ctx_t *ctx, const char *title) +{ + const char *hdr[] = { "ID", "title", NULL }; + + ctx->wpos = -1; + + PCB_DAD_BEGIN_VBOX(ctx->dlg); + PCB_DAD_COMPFLAG(ctx->dlg, PCB_HATF_EXPFILL); + + PCB_DAD_BEGIN_HPANE(ctx->dlg); + PCB_DAD_COMPFLAG(ctx->dlg, PCB_HATF_EXPFILL); + + /* left */ + PCB_DAD_BEGIN_VBOX(ctx->dlg); + PCB_DAD_COMPFLAG(ctx->dlg, PCB_HATF_EXPFILL); + + PCB_DAD_BEGIN_HBOX(ctx->dlg); + PCB_DAD_LABEL(ctx->dlg, "Number of violations:"); + PCB_DAD_LABEL(ctx->dlg, "n/a"); + ctx->wcount = PCB_DAD_CURRENT(ctx->dlg); + PCB_DAD_END(ctx->dlg); + + PCB_DAD_TREE(ctx->dlg, 2, 1, hdr); + PCB_DAD_COMPFLAG(ctx->dlg, PCB_HATF_SCROLL | PCB_HATF_EXPFILL); + PCB_DAD_TREE_SET_CB(ctx->dlg, selected_cb, view_select); + PCB_DAD_TREE_SET_CB(ctx->dlg, ctx, ctx); + ctx->wlist = PCB_DAD_CURRENT(ctx->dlg); + + PCB_DAD_BEGIN_HBOX(ctx->dlg); + PCB_DAD_BUTTON(ctx->dlg, "Copy"); + PCB_DAD_CHANGE_CB(ctx->dlg, view_copy_btn_cb); + PCB_DAD_BUTTON(ctx->dlg, "Cut"); + ctx->wbtn_cut = PCB_DAD_CURRENT(ctx->dlg); + PCB_DAD_CHANGE_CB(ctx->dlg, view_copy_btn_cb); + PCB_DAD_BUTTON(ctx->dlg, "Paste"); + PCB_DAD_CHANGE_CB(ctx->dlg, view_paste_btn_cb); + PCB_DAD_BUTTON(ctx->dlg, "Del"); + PCB_DAD_CHANGE_CB(ctx->dlg, view_del_btn_cb); + PCB_DAD_BUTTON(ctx->dlg, "Select"); + PCB_DAD_CHANGE_CB(ctx->dlg, view_select_btn_cb); + PCB_DAD_END(ctx->dlg); + PCB_DAD_END(ctx->dlg); + + /* right */ + PCB_DAD_BEGIN_VBOX(ctx->dlg); + PCB_DAD_COMPFLAG(ctx->dlg, PCB_HATF_EXPFILL); + PCB_DAD_PREVIEW(ctx->dlg, view_expose_cb, view_mouse_cb, NULL, NULL, 100, 100, ctx); + ctx->wprev = PCB_DAD_CURRENT(ctx->dlg); + PCB_DAD_COMPFLAG(ctx->dlg, PCB_HATF_EXPFILL); + PCB_DAD_LABEL(ctx->dlg, "(description)"); + ctx->wdescription = PCB_DAD_CURRENT(ctx->dlg); + PCB_DAD_LABEL(ctx->dlg, "(measure)"); + ctx->wmeasure = PCB_DAD_CURRENT(ctx->dlg); + PCB_DAD_END(ctx->dlg); + PCB_DAD_END(ctx->dlg); + + PCB_DAD_BEGIN_HBOX(ctx->dlg); + PCB_DAD_BUTTON(ctx->dlg, "Save all"); + PCB_DAD_CHANGE_CB(ctx->dlg, view_save_btn_cb); + PCB_DAD_BUTTON(ctx->dlg, "Load all"); + PCB_DAD_CHANGE_CB(ctx->dlg, view_load_btn_cb); + if (ctx->refresh != NULL) { + PCB_DAD_BUTTON(ctx->dlg, "Refresh"); + PCB_DAD_CHANGE_CB(ctx->dlg, view_refresh_btn_cb); + } + PCB_DAD_BEGIN_HBOX(ctx->dlg); + PCB_DAD_COMPFLAG(ctx->dlg, PCB_HATF_EXPFILL); + PCB_DAD_END(ctx->dlg); + PCB_DAD_BUTTON(ctx->dlg, "Close"); + PCB_DAD_CHANGE_CB(ctx->dlg, view_close_btn_cb); + PCB_DAD_END(ctx->dlg); + PCB_DAD_END(ctx->dlg); + + PCB_DAD_NEW(id, ctx->dlg, title, ctx, pcb_false, view_close_cb); + + ctx->active = 1; +} + +static void pcb_dlg_view_simplified(const char *id, view_ctx_t *ctx, const char *title) +{ + pcb_view_t *v; + + ctx->wlist = -1; + + PCB_DAD_BEGIN_VBOX(ctx->dlg); + PCB_DAD_COMPFLAG(ctx->dlg, PCB_HATF_EXPFILL); + + PCB_DAD_BEGIN_HBOX(ctx->dlg); + PCB_DAD_COMPFLAG(ctx->dlg, PCB_HATF_EXPFILL); + PCB_DAD_PREVIEW(ctx->dlg, view_expose_cb, view_mouse_cb, NULL, NULL, 100, 100, ctx); + ctx->wprev = PCB_DAD_CURRENT(ctx->dlg); + PCB_DAD_COMPFLAG(ctx->dlg, PCB_HATF_EXPFILL); + PCB_DAD_BEGIN_VBOX(ctx->dlg); + PCB_DAD_LABEL(ctx->dlg, "(description)"); + ctx->wdescription = PCB_DAD_CURRENT(ctx->dlg); + PCB_DAD_LABEL(ctx->dlg, "(measure)"); + ctx->wmeasure = PCB_DAD_CURRENT(ctx->dlg); + PCB_DAD_END(ctx->dlg); + PCB_DAD_END(ctx->dlg); + + PCB_DAD_BEGIN_HBOX(ctx->dlg); + PCB_DAD_BUTTON(ctx->dlg, "Previous"); + PCB_DAD_CHANGE_CB(ctx->dlg, view_prev_btn_cb); + PCB_DAD_BEGIN_HBOX(ctx->dlg); + PCB_DAD_COMPFLAG(ctx->dlg, PCB_HATF_EXPFILL); + PCB_DAD_LABEL(ctx->dlg, "na"); + ctx->wpos = PCB_DAD_CURRENT(ctx->dlg); + PCB_DAD_LABEL(ctx->dlg, "/"); + PCB_DAD_LABEL(ctx->dlg, "na"); + ctx->wcount = PCB_DAD_CURRENT(ctx->dlg); + PCB_DAD_END(ctx->dlg); + PCB_DAD_BUTTON(ctx->dlg, "Del"); + PCB_DAD_CHANGE_CB(ctx->dlg, view_del_btn_cb); + PCB_DAD_BUTTON(ctx->dlg, "Next"); + PCB_DAD_CHANGE_CB(ctx->dlg, view_next_btn_cb); + PCB_DAD_END(ctx->dlg); + + PCB_DAD_BEGIN_HBOX(ctx->dlg); + if (ctx->refresh != NULL) { + PCB_DAD_BUTTON(ctx->dlg, "Refresh"); + PCB_DAD_CHANGE_CB(ctx->dlg, view_refresh_btn_cb); + } + PCB_DAD_BEGIN_HBOX(ctx->dlg); + PCB_DAD_COMPFLAG(ctx->dlg, PCB_HATF_EXPFILL); + PCB_DAD_END(ctx->dlg); + PCB_DAD_BUTTON(ctx->dlg, "Close"); + PCB_DAD_CHANGE_CB(ctx->dlg, view_close_btn_cb); + PCB_DAD_END(ctx->dlg); + + PCB_DAD_END(ctx->dlg); + + PCB_DAD_NEW(id, ctx->dlg, title, ctx, pcb_false, view_close_cb); + + ctx->active = 1; + + v = pcb_view_list_first(ctx->lst); + if (v != NULL) + ctx->selected = v->uid; + else + ctx->selected = 0; + simple_rewind(ctx); +} + +static void drc_refresh(view_ctx_t *ctx) +{ + pcb_drc_all(); + + if (ctx->wlist < 0) + simple_rewind(ctx); +} + +static view_ctx_t drc_gui_ctx = {0}; +const char pcb_acts_DrcDialog[] = "DrcDialog([list|simple])\n"; +const char pcb_acth_DrcDialog[] = "Execute drc checks and invoke a view list dialog box for presenting the results"; +fgw_error_t pcb_act_DrcDialog(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + const char *dlg_type = "list"; + PCB_ACT_MAY_CONVARG(1, FGW_STR, DrcDialog, dlg_type = argv[1].val.str); + + if (!drc_gui_ctx.active) { + drc_gui_ctx.pcb = PCB; + drc_gui_ctx.lst = &pcb_drc_lst; + drc_gui_ctx.refresh = drc_refresh; + pcb_drc_all(); + if (pcb_strcasecmp(dlg_type, "simple") == 0) + pcb_dlg_view_simplified("drc_simple", &drc_gui_ctx, "DRC violations"); + else + pcb_dlg_view_full("drc_full", &drc_gui_ctx, "DRC violations"); + } + + view2dlg(&drc_gui_ctx); + + return 0; +} + +extern pcb_view_list_t pcb_io_incompat_lst; +static view_ctx_t io_gui_ctx = {0}; +const char pcb_acts_IOIncompatListDialog[] = "IOIncompatListDialog([list|simple])\n"; +const char pcb_acth_IOIncompatListDialog[] = "Present the format incompatibilities of the last save to file operation in a GUI dialog."; +fgw_error_t pcb_act_IOIncompatListDialog(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + const char *dlg_type = "list"; + PCB_ACT_MAY_CONVARG(1, FGW_STR, IOIncompatListDialog, dlg_type = argv[1].val.str); + + if (!io_gui_ctx.active) { + io_gui_ctx.pcb = PCB; + io_gui_ctx.lst = &pcb_io_incompat_lst; + io_gui_ctx.refresh = NULL; + if (pcb_strcasecmp(dlg_type, "simple") == 0) + pcb_dlg_view_simplified("io_incompat_simple", &io_gui_ctx, "IO incompatibilities in last save"); + else + pcb_dlg_view_full("io_incompat_full", &io_gui_ctx, "IO incompatibilities in last save"); + } + + view2dlg(&io_gui_ctx); + + return 0; +} + +const char pcb_acts_ViewList[] = "viewlist([name, [winid]])\n"; +const char pcb_acth_ViewList[] = "Present a new empty view list"; +fgw_error_t pcb_act_ViewList(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + view_ctx_t *ctx = calloc(sizeof(view_ctx_t), 1); + const char *name = "view list", *winid = "viewlist"; + PCB_ACT_MAY_CONVARG(1, FGW_STR, ViewList, name = argv[1].val.str); + PCB_ACT_MAY_CONVARG(2, FGW_STR, ViewList, winid = argv[2].val.str); + + ctx->pcb = PCB; + ctx->lst = calloc(sizeof(pcb_view_list_t), 1); + ctx->refresh = NULL; + pcb_dlg_view_full(winid, ctx, name); + view2dlg(ctx); + return 0; +} + +static void view_preview_update_cb(void *user_data, int argc, pcb_event_arg_t argv[]) +{ + if (drc_gui_ctx.active) + view_preview_update(&drc_gui_ctx); + if (io_gui_ctx.active) + view_preview_update(&io_gui_ctx); +} + +void pcb_view_dlg_uninit(void) +{ + pcb_event_unbind_allcookie(dlg_view_cookie); + vtp0_uninit(&view_color_save); +} + +void pcb_view_dlg_init(void) +{ + pcb_event_bind(PCB_EVENT_USER_INPUT_POST, view_preview_update_cb, NULL, dlg_view_cookie); +} Index: tags/2.1.2/src_plugins/dialogs/dlg_view.h =================================================================== --- tags/2.1.2/src_plugins/dialogs/dlg_view.h (nonexistent) +++ tags/2.1.2/src_plugins/dialogs/dlg_view.h (revision 24813) @@ -0,0 +1,15 @@ +extern const char pcb_acts_DrcDialog[]; +extern const char pcb_acth_DrcDialog[]; +fgw_error_t pcb_act_DrcDialog(fgw_arg_t *ores, int oargc, fgw_arg_t *oargv); + +extern const char pcb_acts_IOIncompatListDialog[]; +extern const char pcb_acth_IOIncompatListDialog[]; +fgw_error_t pcb_act_IOIncompatListDialog(fgw_arg_t *res, int argc, fgw_arg_t *argv); + +extern const char pcb_acts_ViewList[]; +extern const char pcb_acth_ViewList[]; +fgw_error_t pcb_act_ViewList(fgw_arg_t *res, int argc, fgw_arg_t *argv); + +void pcb_view_dlg_uninit(void); +void pcb_view_dlg_init(void); + Index: tags/2.1.2/src_plugins/dialogs/place.c =================================================================== --- tags/2.1.2/src_plugins/dialogs/place.c (nonexistent) +++ tags/2.1.2/src_plugins/dialogs/place.c (revision 24813) @@ -0,0 +1,307 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2018 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "config.h" +#include "safe_fs.h" + +static const char *place_cookie = "dialogs/place"; + +typedef struct { + int x, y, w, h; +} wingeo_t; + +wingeo_t wingeo_invalid = {0, 0, 0, 0}; + +typedef const char *htsw_key_t; +typedef wingeo_t htsw_value_t; +#define HT(x) htsw_ ## x +#define HT_INVALID_VALUE wingeo_invalid; +#include +#include +#undef HT +#include + +static htsw_t wingeo; + +static void pcb_dialog_store(const char *id, int x, int y, int w, int h) +{ + htsw_entry_t *e; + wingeo_t wg; + +/* pcb_trace("dialog place set: '%s' %d;%d %d*%d\n", id, x, y, w, h);*/ + + e = htsw_getentry(&wingeo, (char *)id); + if (e != NULL) { + e->value.x = x; + e->value.y = y; + e->value.w = w; + e->value.h = h; + return; + } + + wg.x = x; + wg.y = y; + wg.w = w; + wg.h = h; + htsw_set(&wingeo, pcb_strdup(id), wg); +} + + +static void pcb_dialog_place(void *user_data, int argc, pcb_event_arg_t argv[]) +{ + const char *id; + int *geo; + htsw_entry_t *e; + + if ((argc < 3) || (argv[1].type != PCB_EVARG_PTR) || (argv[2].type != PCB_EVARG_STR)) + return; + + id = argv[2].d.s; + geo = argv[3].d.p; + + e = htsw_getentry(&wingeo, (char *)id); + if (e != NULL) { + geo[0] = e->value.x; + geo[1] = e->value.y; + geo[2] = e->value.w; + geo[3] = e->value.h; + } +/* pcb_trace("dialog place: %p '%s'\n", hid_ctx, id);*/ +} + +static void pcb_dialog_resize(void *user_data, int argc, pcb_event_arg_t argv[]) +{ + if ((argc < 7) || (argv[1].type != PCB_EVARG_PTR) || (argv[2].type != PCB_EVARG_STR)) + return; + +/* hid_ctx = argv[1].d.p;*/ + pcb_dialog_store(argv[2].d.s, argv[3].d.i, argv[4].d.i, argv[5].d.i, argv[6].d.i); +} + +static vtp0_t cleanup_later; +static char *str_cleanup_later(const char *path) +{ + char *s = pcb_strdup(path); + vtp0_append(&cleanup_later, s); + return s; +} + +static void place_conf_set(conf_role_t role, const char *path, int val) +{ + static int dummy; + + if (conf_get_field(path) == NULL) + conf_reg_field_(&dummy, 1, CFN_INTEGER, str_cleanup_later(path), "", 0); + conf_setf(role, path, -1, "%d", val); +} + +static void place_conf_load(conf_role_t role, const char *path, int *val) +{ + conf_native_t *nat = conf_get_field(path); + conf_role_t crole; + static int dummy; + + if (conf_get_field(path) == NULL) { + conf_reg_field_(&dummy, 1, CFN_INTEGER, str_cleanup_later(path), "", 0); + conf_update(path, -1); + } + + nat = conf_get_field(path); + if ((nat == NULL) || (nat->prop->src == NULL) || (nat->prop->src->type != LHT_TEXT)) { + pcb_message(PCB_MSG_ERROR, "Can not load window geometry from invalid node for %s\n", path); + return; + } + + /* there are priorities which is hanled by conf merging. To make sure + only the final value is loaded, check if the final native's source + role matches the role that's being loaded. Else the currently loading + role is lower prio and didn't contribute to the final values and should + be ignored. */ + crole = conf_lookup_role(nat->prop->src); + if (crole != role) + return; + + /* need to atoi() directly from the lihata node because the native value + is dummy and shared among all nodes - cheaper to atoi than to do + a proper allocation for the native value. */ + *val = atoi(nat->prop->src->data.text.value); +} + +#define BASEPATH "plugins/dialogs/window_geometry/" +void pcb_wplc_load(conf_role_t role) +{ + char *end, *end2, path[128 + sizeof(BASEPATH)]; + lht_node_t *nd, *root; + lht_dom_iterator_t it; + int x, y, w, h; + + strcpy(path, BASEPATH); + end = path + strlen(BASEPATH); + + root = conf_lht_get_at(role, path, 0); + if (root == NULL) + return; + + for(nd = lht_dom_first(&it, root); nd != NULL; nd = lht_dom_next(&it)) { + int len; + if (nd->type != LHT_HASH) + continue; + len = strlen(nd->name); + if (len > 64) + continue; + memcpy(end, nd->name, len); + end[len] = '/'; + end2 = end + len+1; + + x = y = -1; + w = h = 0; + strcpy(end2, "x"); place_conf_load(role, path, &x); + strcpy(end2, "y"); place_conf_load(role, path, &y); + strcpy(end2, "width"); place_conf_load(role, path, &w); + strcpy(end2, "height"); place_conf_load(role, path, &h); + pcb_dialog_store(nd->name, x, y, w, h); + } +} + + +static void place_maybe_save(conf_role_t role, int force) +{ + htsw_entry_t *e; + char path[128 + sizeof(BASEPATH)]; + char *end, *end2; + + switch(role) { + case CFR_USER: if (!force && !conf_dialogs.plugins.dialogs.auto_save_window_geometry.to_user) return; break; + case CFR_DESIGN: if (!force && !conf_dialogs.plugins.dialogs.auto_save_window_geometry.to_design) return; break; + case CFR_PROJECT: if (!force && !conf_dialogs.plugins.dialogs.auto_save_window_geometry.to_project) return; break; + default: return; + } + + strcpy(path, BASEPATH); + end = path + strlen(BASEPATH); + for(e = htsw_first(&wingeo); e != NULL; e = htsw_next(&wingeo, e)) { + int len = strlen(e->key); + if (len > 64) + continue; + memcpy(end, e->key, len); + end[len] = '/'; + end2 = end + len+1; + + strcpy(end2, "x"); place_conf_set(role, path, e->value.x); + strcpy(end2, "y"); place_conf_set(role, path, e->value.y); + strcpy(end2, "width"); place_conf_set(role, path, e->value.w); + strcpy(end2, "height"); place_conf_set(role, path, e->value.h); + } + + + if (role != CFR_DESIGN) { + int r = conf_save_file(NULL, (PCB == NULL ? NULL : PCB->Filename), role, NULL); + if (r != 0) + pcb_message(PCB_MSG_ERROR, "Failed to save window geometry in %s\n", conf_role_name(role)); + } +} + +/* event handlers that run before the current pcb is saved to save win geo + in the board conf and after loading a new board to fetch window placement + info. */ +static void place_save_pre(void *user_data, int argc, pcb_event_arg_t argv[]) +{ + place_maybe_save(CFR_PROJECT, 0); + place_maybe_save(CFR_DESIGN, 0); +} + +static void place_load_post(void *user_data, int argc, pcb_event_arg_t argv[]) +{ + pcb_wplc_load(CFR_PROJECT); + pcb_wplc_load(CFR_DESIGN); +} + +void pcb_wplc_save_to_role(conf_role_t role) +{ + place_maybe_save(role, 1); +} + +int pcb_wplc_save_to_file(const char *fn) +{ + htsw_entry_t *e; + FILE *f; + + f = pcb_fopen(fn, "w"); + if (f == NULL) + return -1; + + fprintf(f, "li:pcb-rnd-conf-v1 {\n"); + fprintf(f, " ha:overwrite {\n"); + fprintf(f, " ha:plugins {\n"); + fprintf(f, " ha:dialogs {\n"); + fprintf(f, " ha:window_geometry {\n"); + + + for(e = htsw_first(&wingeo); e != NULL; e = htsw_next(&wingeo, e)) { + fprintf(f, " ha:%s {\n", e->key); + fprintf(f, " x=%d\n", e->value.x); + fprintf(f, " y=%d\n", e->value.x); + fprintf(f, " width=%d\n", e->value.w); + fprintf(f, " height=%d\n", e->value.h); + fprintf(f, " }\n"); + } + + fprintf(f, " }\n"); + fprintf(f, " }\n"); + fprintf(f, " }\n"); + fprintf(f, " }\n"); + fprintf(f, "}\n"); + fclose(f); + return 0; +} + +static void pcb_dialog_place_uninit(void) +{ + htsw_entry_t *e; + int n; + + conf_unreg_fields(BASEPATH); + + place_maybe_save(CFR_USER, 0); + + for(e = htsw_first(&wingeo); e != NULL; e = htsw_next(&wingeo, e)) + free((char *)e->key); + htsw_uninit(&wingeo); + pcb_event_unbind_allcookie(place_cookie); + + for(n = 0; n < cleanup_later.used; n++) + free(cleanup_later.array[n]); + vtp0_uninit(&cleanup_later); +} + +static void pcb_dialog_place_init(void) +{ + htsw_init(&wingeo, strhash, strkeyeq); + pcb_event_bind(PCB_EVENT_SAVE_PRE, place_save_pre, NULL, place_cookie); + pcb_event_bind(PCB_EVENT_LOAD_POST, place_load_post, NULL, place_cookie); + pcb_wplc_load(CFR_SYSTEM); + pcb_wplc_load(CFR_USER); +} Index: tags/2.1.2/src_plugins/dialogs/place.h =================================================================== --- tags/2.1.2/src_plugins/dialogs/place.h (nonexistent) +++ tags/2.1.2/src_plugins/dialogs/place.h (revision 24813) @@ -0,0 +1,3 @@ +#include "conf.h" +void pcb_wplc_load(conf_role_t role); + Index: tags/2.1.2/src_plugins/dialogs/xpm/question.xpm =================================================================== --- tags/2.1.2/src_plugins/dialogs/xpm/question.xpm (nonexistent) +++ tags/2.1.2/src_plugins/dialogs/xpm/question.xpm (revision 24813) @@ -0,0 +1,77 @@ +/* XPM */ +static const char * question_xpm[] = { +"48 48 26 1", +" c None", +". c #000100", +"+ c #000509", +"@ c #020D14", +"# c #000E1A", +"$ c #011321", +"% c #02192B", +"& c #001C32", +"* c #002036", +"= c #00243F", +"- c #012945", +"; c #002D4E", +"> c #003254", +", c #06365E", +"' c #023D69", +") c #004374", +"! c #08497C", +"~ c #004D85", +"{ c #005290", +"] c #005593", +"^ c #005B99", +"/ c #0060A4", +"( c #0065A9", +"_ c #1862A8", +": c #006AB4", +"< c #0E69B5", +" ", +" ", +" ", +" ", +" ", +" ", +" <<<<<<<<<<<< ", +" :<<<<<<<<<<<<<<< ", +" :<<<<<<{)','!/<<<<<< ", +" <<<<('%........$)<<<<<< ", +" <<<<,+............*:<<<<< ", +" <<<<<@....+%=*#.....&:<<<<< ", +" <<<<<<@.+;]<<<<<~$....'<<<<<< ", +" <<<<<<<#>_<<<<<<<<_@...%<<<<<<< ", +" <<<<<<<...><<<<<<<<<<<<<<<<< ", +" <<<<<<<<<<<<<<<;...,<<<<<<<<<<<<<<<<< ", +" <<<<<<<<<<<<<<<;...,<<<<<<<<<<<<<<<< ", +" <<<<<<<<<<<<<<<;...,<<<<<<<<<<<<<<<< ", +" <<<<<<<<<<<<<<^~~~/<<<<<<<<<<<<<<<: ", +" <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ", +" <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ", +" <<<<<<<<<<<<<-@@@><<<<<<<<<<<<<< ", +" <<<<<<<<<<<<*...-<<<<<<<<<<<<<: ", +" :<<<<<<<<<<<*...-<<<<<<<<<<<<< ", +" <<<<<<<<<<<*...-<<<<<<<<<<<< ", +" :<<<<<<<<<*...-<<<<<<<<<<< ", +" <<<<<<<<<<<<<<<<<<<<<<<< ", +" <<<<<<<<<<<<<<<<<<<<<: ", +" :<<<<<<<<<<<<<<<<< ", +" <<<<<<<<<<<<<< ", +" <<<<<<<: ", +" ", +" ", +" ", +" ", +" "}; Index: tags/2.1.2/src_plugins/dialogs/xpm/warning.xpm =================================================================== --- tags/2.1.2/src_plugins/dialogs/xpm/warning.xpm (nonexistent) +++ tags/2.1.2/src_plugins/dialogs/xpm/warning.xpm (revision 24813) @@ -0,0 +1,77 @@ +/* XPM */ +static const char * warning_xpm[] = { +"48 48 26 1", +" c None", +". c #000200", +"+ c #151500", +"@ c #201F00", +"# c #AE0102", +"$ c #363601", +"% c #B92102", +"& c #474501", +"* c #514D00", +"= c #BD3000", +"- c #BF3A00", +"; c #C54D00", +"> c #C95B00", +", c #827C00", +"' c #D06C00", +") c #D47B00", +"! c #D78D00", +"~ c #A5A000", +"{ c #DFA100", +"] c #C8BF00", +"^ c #E5BB00", +"/ c #D4CE00", +"( c #EACA00", +"_ c #ECD000", +": c #ECDC00", +"< c #F5EA00", +" ", +" ", +" ", +" ", +" #### ", +" ###### ", +" ###### ", +" ######## ", +" ######## ", +" ########## ", +" ####;%#### ", +" #####_)##### ", +" ####'<<%#### ", +" ####%:<<{##### ", +" #####!<<<<-#### ", +" ####%<<<<<^##### ", +" #####{<<<<<<;#### ", +" ####=<<<<<<<(##### ", +" #####^<<<<<~..:<<<<%#### ", +" #####_<<<<]..<<<<<{##### ", +" ####)<<<<<]..<<<<<<-#### ", +" ####%:<<<< +#include + +#include "xpm/question.xpm" +#include "xpm/warning.xpm" + +const char **pcp_dlg_xpm_by_name(const char *name) +{ + if (strcmp(name, "question") == 0) return question_xpm; + if (strcmp(name, "warning") == 0) return warning_xpm; + return NULL; +} Index: tags/2.1.2/src_plugins/dialogs/xpm.h =================================================================== --- tags/2.1.2/src_plugins/dialogs/xpm.h (nonexistent) +++ tags/2.1.2/src_plugins/dialogs/xpm.h (revision 24813) @@ -0,0 +1 @@ +const char **pcp_dlg_xpm_by_name(const char *name); Index: tags/2.1.2/src_plugins/distalign/Makefile =================================================================== --- tags/2.1.2/src_plugins/distalign/Makefile (nonexistent) +++ tags/2.1.2/src_plugins/distalign/Makefile (revision 24813) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_distalign + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/2.1.2/src_plugins/distalign/Plug.tmpasm =================================================================== --- tags/2.1.2/src_plugins/distalign/Plug.tmpasm (nonexistent) +++ tags/2.1.2/src_plugins/distalign/Plug.tmpasm (revision 24813) @@ -0,0 +1,8 @@ +put /local/pcb/mod {distalign} +put /local/pcb/mod/OBJS [@ $(PLUGDIR)/distalign/distalign.o @] + +switch /local/pcb/distalign/controls + case {buildin} include /local/pcb/tmpasm/buildin; end; + case {plugin} include /local/pcb/tmpasm/plugin; end; + case {disable} include /local/pcb/tmpasm/disable; end; +end Index: tags/2.1.2/src_plugins/distalign/distalign.c =================================================================== --- tags/2.1.2/src_plugins/distalign/distalign.c (nonexistent) +++ tags/2.1.2/src_plugins/distalign/distalign.c (revision 24813) @@ -0,0 +1,543 @@ +/* Functions to distribute (evenly spread out) and align PCB subcircuits. + * + * Copyright (C) 2007 Ben Jackson + * + * Licensed under the terms of the GNU General Public + * License, version 2 or later. + * + * Ported to pcb-rnd by Tibor 'Igor2' Palinkas in 2016. + * + * Original source was: http://ad7gd.net/geda/distalign.c + * + * Ben Jackson AD7GD + * + * http://www.ben.com/ + */ + +#include +#include + +#include "board.h" +#include "config.h" +#include "data.h" +#include "hid.h" +#include "rtree.h" +#include "undo.h" +#include "error.h" +#include "move.h" +#include "draw.h" +#include "plugins.h" +#include "macro.h" +#include "actions.h" +#include "compat_misc.h" + +enum { + K_X, + K_Y, + K_Lefts, + K_Rights, + K_Tops, + K_Bottoms, + K_Centers, + K_Marks, + K_Gaps, + K_First, + K_Last, + K_Average, + K_Crosshair, + K_Gridless, + K_none, + K_align, + K_distribute +}; + +static const char *keywords[] = { + /*[K_X] */ "X", + /*[K_Y] */ "Y", + /*[K_Lefts] */ "Lefts", + /*[K_Rights] */ "Rights", + /*[K_Tops] */ "Tops", + /*[K_Bottoms] */ "Bottoms", + /*[K_Centers] */ "Centers", + /*[K_Marks] */ "Marks", + /*[K_Gaps] */ "Gaps", + /*[K_First] */ "First", + /*[K_Last] */ "Last", + /*[K_Average] */ "Average", + /*[K_Crosshair] */ "pcb_crosshair", + /*[K_Gridless] */ "Gridless", +}; + +static int keyword(const char *s) +{ + int i; + + if (!s) { + return K_none; + } + for (i = 0; i < PCB_ENTRIES(keywords); ++i) { + if (keywords[i] && pcb_strcasecmp(s, keywords[i]) == 0) + return i; + } + return -1; +} + + +/* this macro produces a function in X or Y that switches on 'point' */ +#define COORD(DIR) \ +static inline pcb_coord_t \ +coord ## DIR(pcb_subc_t *subc, int point) \ +{ \ + pcb_coord_t oX, oY; \ + switch (point) { \ + case K_Marks: \ + oX = oY = 0; \ + pcb_subc_get_origin(subc, &oX, &oY); \ + return o ## DIR; \ + case K_Lefts: \ + case K_Tops: \ + return subc->BoundingBox.DIR ## 1; \ + case K_Rights: \ + case K_Bottoms: \ + return subc->BoundingBox.DIR ## 2; \ + case K_Centers: \ + case K_Gaps: \ + return (subc->BoundingBox.DIR ## 1 + \ + subc->BoundingBox.DIR ## 2) / 2; \ + } \ + return 0; \ +} + +COORD(X) +COORD(Y) + +/* return the subcircuit coordinate associated with the given internal point */ +static pcb_coord_t coord(pcb_subc_t *subc, int dir, int point) +{ + if (dir == K_X) + return coordX(subc, point); + else + return coordY(subc, point); +} + +static struct subc_by_pos { + pcb_subc_t *subc; + pcb_coord_t pos; + pcb_coord_t width; +} *subcs_by_pos; + +static int nsubcs_by_pos; + +static int cmp_ebp(const void *a, const void *b) +{ + const struct subc_by_pos *ea = a; + const struct subc_by_pos *eb = b; + + return ea->pos - eb->pos; +} + +/* + * Find all selected objects, then order them in order by coordinate in + * the 'dir' axis. This is used to find the "First" and "Last" subcircuits + * and also to choose the distribution order. + * + * For alignment, first and last are in the orthogonal axis (imagine if + * you were lining up letters in a sentence, aligning *vertically* to the + * first letter means selecting the first letter *horizontally*). + * + * For distribution, first and last are in the distribution axis. + */ +static int sort_subcs_by_pos(int op, int dir, int point) +{ + int nsel = 0; + + if (nsubcs_by_pos) + return nsubcs_by_pos; + if (op == K_align) + dir = dir == K_X ? K_Y : K_X; /* see above */ + PCB_SUBC_LOOP(PCB->Data); + { + if (!PCB_FLAG_TEST(PCB_FLAG_SELECTED, subc)) + continue; + nsel++; + } + PCB_END_LOOP; + if (!nsel) + return 0; + subcs_by_pos = malloc(nsel * sizeof(*subcs_by_pos)); + nsubcs_by_pos = nsel; + nsel = 0; + PCB_SUBC_LOOP(PCB->Data); + { + if (!PCB_FLAG_TEST(PCB_FLAG_SELECTED, subc)) + continue; + subcs_by_pos[nsel].subc = subc; + subcs_by_pos[nsel++].pos = coord(subc, dir, point); + } + PCB_END_LOOP; + qsort(subcs_by_pos, nsubcs_by_pos, sizeof(*subcs_by_pos), cmp_ebp); + return nsubcs_by_pos; +} + +static void free_subcs_by_pos(void) +{ + if (nsubcs_by_pos) { + free(subcs_by_pos); + subcs_by_pos = NULL; + nsubcs_by_pos = 0; + } +} + +/* Find the reference coordinate from the specified points of all + * selected subcircuits. */ +static pcb_coord_t reference_coord(int op, int x, int y, int dir, int point, int reference) +{ + pcb_coord_t q; + int nsel; + + q = 0; + switch (reference) { + case K_Crosshair: + if (dir == K_X) + q = x; + else + q = y; + break; + case K_Average: /* the average among selected subcircuits */ + nsel = 0; + q = 0; + PCB_SUBC_LOOP(PCB->Data); + { + if (!PCB_FLAG_TEST(PCB_FLAG_SELECTED, subc)) + continue; + q += coord(subc, dir, point); + nsel++; + } + PCB_END_LOOP; + if (nsel) + q /= nsel; + break; + case K_First: /* first or last in the orthogonal direction */ + case K_Last: + if (!sort_subcs_by_pos(op, dir, point)) { + q = 0; + break; + } + if (reference == K_First) { + q = coord(subcs_by_pos[0].subc, dir, point); + } + else { + q = coord(subcs_by_pos[nsubcs_by_pos - 1].subc, dir, point); + } + break; + } + return q; +} + +static const char pcb_acts_align[] = "Align(X/Y, [Lefts/Rights/Tops/Bottoms/Centers/Marks, [First/Last/pcb_crosshair/Average[, Gridless]]])"; +/* DOC: align.html */ +static fgw_error_t pcb_act_align(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + const char *a0, *a1, *a2, *a3; + int dir; + int point; + int reference; + int gridless; + pcb_coord_t q; + int changed = 0; + + if (argc < 2 || argc > 5) { + PCB_ACT_FAIL(align); + } + + PCB_ACT_CONVARG(1, FGW_STR, align, a0 = argv[1].val.str); + PCB_ACT_CONVARG(2, FGW_STR, align, a1 = argv[2].val.str); + PCB_ACT_CONVARG(3, FGW_STR, align, a2 = argv[3].val.str); + PCB_ACT_CONVARG(4, FGW_STR, align, a3 = argv[4].val.str); + + /* parse direction arg */ + switch ((dir = keyword(a0))) { + case K_X: + case K_Y: + break; + default: + PCB_ACT_FAIL(align); + } + /* parse point (within each subcircuit) which will be aligned */ + switch ((point = keyword(a1))) { + case K_Centers: + case K_Marks: + break; + case K_Lefts: + case K_Rights: + if (dir == K_Y) { + PCB_ACT_FAIL(align); + } + break; + case K_Tops: + case K_Bottoms: + if (dir == K_X) { + PCB_ACT_FAIL(align); + } + break; + case K_none: + point = K_Marks; /* default value */ + break; + default: + PCB_ACT_FAIL(align); + } + /* parse reference which will determine alignment coordinates */ + switch ((reference = keyword(a2))) { + case K_First: + case K_Last: + case K_Average: + case K_Crosshair: + break; + case K_none: + reference = K_First; /* default value */ + break; + default: + PCB_ACT_FAIL(align); + } + /* optionally work off the grid (solar cells!) */ + switch (keyword(a3)) { + case K_Gridless: + gridless = 1; + break; + case K_none: + gridless = 0; + break; + default: + PCB_ACT_FAIL(align); + } + /* find the final alignment coordinate using the above options */ + q = reference_coord(K_align, pcb_crosshair.X, pcb_crosshair.Y, dir, point, reference); + /* move all selected subcircuits to the new coordinate */ + PCB_SUBC_LOOP(PCB->Data); + { + pcb_coord_t p, dp, dx, dy; + + if (!PCB_FLAG_TEST(PCB_FLAG_SELECTED, subc)) + continue; + /* find delta from reference point to reference point */ + p = coord(subc, dir, point); + dp = q - p; + /* ...but if we're gridful, keep the mark on the grid */ + if (!gridless) { + dp -= (coord(subc, dir, K_Marks) + dp) % (long) (PCB->Grid); + } + if (dp) { + /* move from generic to X or Y */ + dx = dy = dp; + if (dir == K_X) + dy = 0; + else + dx = 0; + pcb_subc_move(subc, dx, dy, 1); + pcb_undo_add_obj_to_move(PCB_OBJ_SUBC, NULL, NULL, subc, dx, dy); + changed = 1; + } + } + PCB_END_LOOP; + if (changed) { + pcb_undo_inc_serial(); + pcb_redraw(); + pcb_board_set_changed_flag(1); + } + free_subcs_by_pos(); + + PCB_ACT_IRES(0); + return 0; +} + +static const char pcb_acts_distribute[] = "Distribute(X/Y, [Lefts/Rights/Tops/Bottoms/Centers/Marks/Gaps, [First/Last/pcb_crosshair, First/Last/pcb_crosshair[, Gridless]]])"; +/* DOC: distribute.html */ +static fgw_error_t pcb_act_distribute(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + const char *a0, *a1, *a2 = NULL, *a3 = NULL, *a4 = NULL; + int dir; + int point; + int refa, refb; + int gridless; + pcb_coord_t s, e, slack; + int divisor; + int changed = 0; + int i; + + if (argc < 2 || argc == 4 || argc > 6) { + PCB_ACT_FAIL(distribute); + } + + PCB_ACT_CONVARG(1, FGW_STR, distribute, a0 = argv[1].val.str); + PCB_ACT_CONVARG(2, FGW_STR, distribute, a1 = argv[2].val.str); + PCB_ACT_MAY_CONVARG(3, FGW_STR, distribute, a2 = argv[3].val.str); + PCB_ACT_MAY_CONVARG(4, FGW_STR, distribute, a3 = argv[4].val.str); + PCB_ACT_MAY_CONVARG(5, FGW_STR, distribute, a4 = argv[5].val.str); + + + /* parse direction arg */ + switch ((dir = keyword(a0))) { + case K_X: + case K_Y: + break; + default: + PCB_ACT_FAIL(distribute); + } + /* parse point (within each subcircuit) which will be distributed */ + switch ((point = keyword(a1))) { + case K_Centers: + case K_Marks: + case K_Gaps: + break; + case K_Lefts: + case K_Rights: + if (dir == K_Y) { + PCB_ACT_FAIL(distribute); + } + break; + case K_Tops: + case K_Bottoms: + if (dir == K_X) { + PCB_ACT_FAIL(distribute); + } + break; + case K_none: + point = K_Marks; /* default value */ + break; + default: + PCB_ACT_FAIL(distribute); + } + /* parse reference which will determine first distribution coordinate */ + switch ((refa = keyword(a2))) { + case K_First: + case K_Last: + case K_Average: + case K_Crosshair: + break; + case K_none: + refa = K_First; /* default value */ + break; + default: + PCB_ACT_FAIL(distribute); + } + /* parse reference which will determine final distribution coordinate */ + switch ((refb = keyword(a3))) { + case K_First: + case K_Last: + case K_Average: + case K_Crosshair: + break; + case K_none: + refb = K_Last; /* default value */ + break; + default: + PCB_ACT_FAIL(distribute); + } + if (refa == refb) { + PCB_ACT_FAIL(distribute); + } + /* optionally work off the grid (solar cells!) */ + switch (keyword(a4)) { + case K_Gridless: + gridless = 1; + break; + case K_none: + gridless = 0; + break; + default: + PCB_ACT_FAIL(distribute); + } + /* build list of subcircuitss in orthogonal axis order */ + sort_subcs_by_pos(K_distribute, dir, point); + /* find the endpoints given the above options */ + s = reference_coord(K_distribute, pcb_crosshair.X, pcb_crosshair.Y, dir, point, refa); + e = reference_coord(K_distribute, pcb_crosshair.X, pcb_crosshair.Y, dir, point, refb); + slack = e - s; + /* use this divisor to calculate spacing (for 1 elt, avoid 1/0) */ + divisor = (nsubcs_by_pos > 1) ? (nsubcs_by_pos - 1) : 1; + /* even the gaps instead of the edges or whatnot */ + /* find the "slack" in the row */ + if (point == K_Gaps) { + pcb_coord_t w; + + /* subtract all the "widths" from the slack */ + for (i = 0; i < nsubcs_by_pos; ++i) { + pcb_subc_t *subc = subcs_by_pos[i].subc; + /* coord doesn't care if I mix Lefts/Tops */ + w = subcs_by_pos[i].width = coord(subc, dir, K_Rights) - coord(subc, dir, K_Lefts); + /* Gaps distribution is on centers, so half of + * first and last subcircuit don't count */ + if (i == 0 || i == nsubcs_by_pos - 1) { + w /= 2; + } + slack -= w; + } + /* slack could be negative */ + } + /* move all selected subcircuits to the new coordinate */ + for (i = 0; i < nsubcs_by_pos; ++i) { + pcb_subc_t *subc = subcs_by_pos[i].subc; + pcb_coord_t p, q, dp, dx, dy; + + /* find reference point for this subcircuit */ + q = s + slack * i / divisor; + /* find delta from reference point to reference point */ + p = coord(subc, dir, point); + dp = q - p; + /* ...but if we're gridful, keep the mark on the grid */ + if (!gridless) { + dp -= (coord(subc, dir, K_Marks) + dp) % (long) (PCB->Grid); + } + if (dp) { + /* move from generic to X or Y */ + dx = dy = dp; + if (dir == K_X) + dy = 0; + else + dx = 0; + pcb_subc_move(subc, dx, dy, 1); + pcb_undo_add_obj_to_move(PCB_OBJ_SUBC, NULL, NULL, subc, dx, dy); + changed = 1; + } + /* in gaps mode, accumulate part widths */ + if (point == K_Gaps) { + /* move remaining half of our subcircuits */ + s += subcs_by_pos[i].width / 2; + /* move half of next subcircuits */ + if (i < nsubcs_by_pos - 1) + s += subcs_by_pos[i + 1].width / 2; + } + } + if (changed) { + pcb_undo_inc_serial(); + pcb_redraw(); + pcb_board_set_changed_flag(1); + } + free_subcs_by_pos(); + PCB_ACT_IRES(0); + return 0; +} + +static pcb_action_t distalign_action_list[] = { + {"distribute", pcb_act_distribute, "Distribute subcircuits", pcb_acts_distribute}, + {"align", pcb_act_align, "Align subcircuits", pcb_acts_align} +}; + +static char *distalign_cookie = "distalign plugin"; + +PCB_REGISTER_ACTIONS(distalign_action_list, distalign_cookie) + +int pplg_check_ver_distalign(int ver_needed) { return 0; } + +void pplg_uninit_distalign(void) +{ + pcb_remove_actions_by_cookie(distalign_cookie); +} + +#include "dolists.h" +int pplg_init_distalign(void) +{ + PCB_API_CHK_VER; + PCB_REGISTER_ACTIONS(distalign_action_list, distalign_cookie); + return 0; +} Index: tags/2.1.2/src_plugins/distalign/distalign.pup =================================================================== --- tags/2.1.2/src_plugins/distalign/distalign.pup (nonexistent) +++ tags/2.1.2/src_plugins/distalign/distalign.pup (revision 24813) @@ -0,0 +1,7 @@ +$class feature +$short distribute and align objs +$long Introducing Align() and Distribute(), which work much like the similarly named functions in Visio. Given that PCB does not have the concept of "first selected object" to draw on, the reference points can be selected by arguments. +$package extra +$state works +default buildin +autoload 1 Index: tags/2.1.2/src_plugins/distaligntext/Makefile =================================================================== --- tags/2.1.2/src_plugins/distaligntext/Makefile (nonexistent) +++ tags/2.1.2/src_plugins/distaligntext/Makefile (revision 24813) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_distaligntext + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/2.1.2/src_plugins/distaligntext/Plug.tmpasm =================================================================== --- tags/2.1.2/src_plugins/distaligntext/Plug.tmpasm (nonexistent) +++ tags/2.1.2/src_plugins/distaligntext/Plug.tmpasm (revision 24813) @@ -0,0 +1,8 @@ +put /local/pcb/mod {distaligntext} +put /local/pcb/mod/OBJS [@ $(PLUGDIR)/distaligntext/distaligntext.o @] + +switch /local/pcb/distaligntext/controls + case {buildin} include /local/pcb/tmpasm/buildin; end; + case {plugin} include /local/pcb/tmpasm/plugin; end; + case {disable} include /local/pcb/tmpasm/disable; end; +end Index: tags/2.1.2/src_plugins/distaligntext/distaligntext.c =================================================================== --- tags/2.1.2/src_plugins/distaligntext/distaligntext.c (nonexistent) +++ tags/2.1.2/src_plugins/distaligntext/distaligntext.c (revision 24813) @@ -0,0 +1,609 @@ +/* + * distaligntext plug-in for PCB. + * + * Copyright (C) 2012 Dan White + * Functions to distribute (evenly spread out) and align PCB text. + * + * Licensed under the terms of the GNU General Public + * License, version 2 or later. + * + * Substantially from distalign.c + * Copyright (C) 2007 Ben Jackson + * + * Ported to pcb-rnd by Tibor 'Igor2' Palinkas in 2016, 2018. + * + * + * Modifications and internal differences are significant enough warrant + * a new related plugin. + */ + +#include +#include + +#include "config.h" +#include "board.h" +#include "data.h" +#include "hid.h" +#include "rtree.h" +#include "undo.h" +#include "error.h" +#include "move.h" +#include "draw.h" +#include "plugins.h" +#include "actions.h" +#include "conf_core.h" +#include "box.h" +#include "macro.h" +#include "compat_misc.h" + +enum { + K_X, + K_Y, + K_Lefts, + K_Rights, + K_Tops, + K_Bottoms, + K_Centers, + K_Gaps, + K_First, + K_Last, + K_Average, + K_Crosshair, + K_Gridless, + K_none, + K_aligntext, + K_distributetext +}; + +static const char *keywords[] = { + /* [K_X] */ "X", + /* [K_Y] */ "Y", + /* [K_Lefts] */ "Lefts", + /* [K_Rights] */ "Rights", + /* [K_Tops] */ "Tops", + /* [K_Bottoms] */ "Bottoms", + /* [K_Centers] */ "Centers", + /* [K_Gaps] */ "Gaps", + /* [K_First] */ "First", + /* [K_Last] */ "Last", + /* [K_Average] */ "Average", + /* [K_Crosshair] */ "pcb_crosshair", + /* [K_Gridless] */ "Gridless", +}; + +static int keyword(const char *s) +{ + int i; + + if (!s) { + return K_none; + } + for (i = 0; i < PCB_ENTRIES(keywords); ++i) { + if (keywords[i] && pcb_strcasecmp(s, keywords[i]) == 0) + return i; + } + return -1; +} + + +/* this macro produces a function in X or Y that switches on 'point' */ +#define COORD(DIR) \ +static inline pcb_coord_t \ +coord ## DIR(pcb_text_t *text, int point) \ +{ \ + switch (point) { \ + case K_Lefts: \ + case K_Tops: \ + return text->BoundingBox.DIR ## 1; \ + case K_Rights: \ + case K_Bottoms: \ + return text->BoundingBox.DIR ## 2; \ + case K_Centers: \ + case K_Gaps: \ + return (text->BoundingBox.DIR ## 1 + \ + text->BoundingBox.DIR ## 2) / 2; \ + } \ + return 0; \ +} + +COORD(X) + COORD(Y) + +/* Return the text coordinate associated with the given internal point. */ +static pcb_coord_t coord(pcb_text_t * text, int dir, int point) +{ + if (dir == K_X) + return coordX(text, point); + else + return coordY(text, point); +} + +static struct text_by_pos { + pcb_text_t *text; + pcb_coord_t pos; + pcb_coord_t width; +} *texts_by_pos; + +static int ntexts_by_pos; + +static int cmp_tbp(const void *a, const void *b) +{ + const struct text_by_pos *ta = a; + const struct text_by_pos *tb = b; + + return ta->pos - tb->pos; +} + +/* Find all selected text objects, then order them in order by coordinate in + * the 'dir' axis. This is used to find the "First" and "Last" elements + * and also to choose the distribution order. + * + * For alignment, first and last are in the orthogonal axis (imagine if + * you were lining up letters in a sentence, aligning *vertically* to the + * first letter means selecting the first letter *horizontally*). + * + * For distribution, first and last are in the distribution axis. */ +static int sort_texts_by_pos(int op, int dir, int point) +{ + int nsel = 0; + + if (ntexts_by_pos) + return ntexts_by_pos; + if (op == K_aligntext) + dir = dir == K_X ? K_Y : K_X; /* see above */ + + PCB_SUBC_LOOP(PCB->Data); + { + PCB_TEXT_ALL_LOOP(subc->data); + { + if (!PCB_FLAG_TEST(PCB_FLAG_SELECTED, text) || !PCB_FLAG_TEST(PCB_FLAG_FLOATER, text)) + continue; + nsel++; + } + PCB_ENDALL_LOOP; + } + PCB_END_LOOP; + + PCB_TEXT_ALL_LOOP(PCB->Data); + { + if (!PCB_FLAG_TEST(PCB_FLAG_SELECTED, text)) + continue; + nsel++; + } + PCB_ENDALL_LOOP; + if (!nsel) + return 0; + texts_by_pos = malloc(nsel * sizeof(*texts_by_pos)); + ntexts_by_pos = nsel; + nsel = 0; + + PCB_SUBC_LOOP(PCB->Data); + { + PCB_TEXT_ALL_LOOP(subc->data); + { + if (!PCB_FLAG_TEST(PCB_FLAG_SELECTED, text) || !PCB_FLAG_TEST(PCB_FLAG_FLOATER, text)) + continue; + texts_by_pos[nsel].text = text; + texts_by_pos[nsel++].pos = coord(text, dir, point); + } + PCB_ENDALL_LOOP; + } + PCB_END_LOOP; + + PCB_TEXT_ALL_LOOP(PCB->Data); + { + if (!PCB_FLAG_TEST(PCB_FLAG_SELECTED, text)) + continue; + texts_by_pos[nsel].text = text; + texts_by_pos[nsel++].pos = coord(text, dir, point); + } + PCB_ENDALL_LOOP; + qsort(texts_by_pos, ntexts_by_pos, sizeof(*texts_by_pos), cmp_tbp); + return ntexts_by_pos; +} + +static void free_texts_by_pos(void) +{ + if (ntexts_by_pos) { + free(texts_by_pos); + texts_by_pos = NULL; + ntexts_by_pos = 0; + } +} + + +/* Find the reference coordinate from the specified points of all selected text. */ +static pcb_coord_t reference_coord(int op, int x, int y, int dir, int point, int reference) +{ + pcb_coord_t q; + int i, nsel; + + q = 0; + switch (reference) { + case K_Crosshair: + if (dir == K_X) + q = x; + else + q = y; + break; + case K_Average: /* the average among selected text */ + nsel = ntexts_by_pos; + for (i = 0; i < ntexts_by_pos; ++i) { + q += coord(texts_by_pos[i].text, dir, point); + } + if (nsel) + q /= nsel; + break; + case K_First: /* first or last in the orthogonal direction */ + case K_Last: + if (!sort_texts_by_pos(op, dir, point)) { + q = 0; + break; + } + if (reference == K_First) { + q = coord(texts_by_pos[0].text, dir, point); + } + else { + q = coord(texts_by_pos[ntexts_by_pos - 1].text, dir, point); + } + break; + } + return q; +} + +static const char pcb_acts_aligntext[] = "AlignText(X/Y, [Lefts/Rights/Tops/Bottoms/Centers, [First/Last/pcb_crosshair/Average[, Gridless]]])"; +/* DOC: aligntext.html */ +static fgw_error_t pcb_act_aligntext(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + const char *a0, *a1, *a2, *a3; + int dir; + int point; + int reference; + int gridless; + pcb_coord_t q; + pcb_coord_t p, dp, dx, dy; + int changed = 0; + + if (argc < 2 || argc > 5) { + PCB_ACT_FAIL(aligntext); + } + + PCB_ACT_CONVARG(1, FGW_STR, aligntext, a0 = argv[1].val.str); + PCB_ACT_CONVARG(2, FGW_STR, aligntext, a1 = argv[2].val.str); + PCB_ACT_CONVARG(3, FGW_STR, aligntext, a2 = argv[3].val.str); + PCB_ACT_CONVARG(4, FGW_STR, aligntext, a3 = argv[4].val.str); + + /* parse direction arg */ + switch ((dir = keyword(a0))) { + case K_X: + case K_Y: + break; + default: + PCB_ACT_FAIL(aligntext); + } + /* parse point (within each element) which will be aligned */ + switch ((point = keyword(a1))) { + case K_Centers: + break; + case K_Lefts: + case K_Rights: + if (dir == K_Y) { + PCB_ACT_FAIL(aligntext); + } + break; + case K_Tops: + case K_Bottoms: + if (dir == K_X) { + PCB_ACT_FAIL(aligntext); + } + break; + case K_none: /* default value */ + if (dir == K_X) { + point = K_Lefts; + } + else { + point = K_Tops; + } + break; + default: + PCB_ACT_FAIL(aligntext); + } + /* parse reference which will determine alignment coordinates */ + switch ((reference = keyword(a2))) { + case K_First: + case K_Last: + case K_Average: + case K_Crosshair: + break; + case K_none: + reference = K_First; /* default value */ + break; + default: + PCB_ACT_FAIL(aligntext); + } + /* optionally work off the grid (solar cells!) */ + switch (keyword(a3)) { + case K_Gridless: + gridless = 1; + break; + case K_none: + gridless = 0; + break; + default: + PCB_ACT_FAIL(aligntext); + } + pcb_undo_save_serial(); + /* find the final alignment coordinate using the above options */ + q = reference_coord(K_aligntext, pcb_crosshair.X, pcb_crosshair.Y, dir, point, reference); + /* move all selected elements to the new coordinate */ + /* selected text part of an element */ + + PCB_SUBC_LOOP(PCB->Data); + { + PCB_TEXT_ALL_LOOP(subc->data) { + if (!PCB_FLAG_TEST(PCB_FLAG_SELECTED, text) || !PCB_FLAG_TEST(PCB_FLAG_FLOATER, text)) + continue; + /* find delta from reference point to reference point */ + p = coord(text, dir, point); + dp = q - p; + /* ...but if we're gridful, keep the mark on the grid */ + /* TODO re-enable for text, need textcoord() + if (!gridless) + { + dp -= (coord (text, dir, K_Marks) + dp) % (long) (PCB->Grid); + } + */ + if (dp) { + /* move from generic to X or Y */ + dx = dy = dp; + if (dir == K_X) + dy = 0; + else + dx = 0; + pcb_move_obj(PCB_OBJ_TEXT, text->parent.layer, text, text, dx, dy); + changed = 1; + } + } PCB_ENDALL_LOOP; + } + PCB_END_LOOP; + + /* Selected bare text objects */ + PCB_TEXT_ALL_LOOP(PCB->Data); + { + if (PCB_FLAG_TEST(PCB_FLAG_SELECTED, text)) { + /* find delta from reference point to reference point */ + p = coord(text, dir, point); + dp = q - p; + /* ...but if we're gridful, keep the mark on the grid */ + /* TODO re-enable for text, need textcoord() + if (!gridless) + { + dp -= (coord (text, dir, K_Marks) + dp) % (long) (PCB->Grid); + } + */ + if (dp) { + /* move from generic to X or Y */ + dx = dy = dp; + if (dir == K_X) + dy = 0; + else + dx = 0; + pcb_move_obj(PCB_OBJ_TEXT, layer, text, text, dx, dy); + changed = 1; + } + } + } + PCB_ENDALL_LOOP; + if (changed) { + pcb_undo_restore_serial(); + pcb_undo_inc_serial(); + pcb_redraw(); + pcb_board_set_changed_flag(pcb_true); + } + free_texts_by_pos(); + PCB_ACT_IRES(0); + return 0; +} + +static const char pcb_acts_distributetext[] = "DistributeText(Y, [Lefts/Rights/Tops/Bottoms/Centers/Gaps, [First/Last/pcb_crosshair, First/Last/pcb_crosshair[, Gridless]]])"; +/* DOC: distributetext.html */ +static fgw_error_t pcb_act_distributetext(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + const char *a0, *a1, *a2 = NULL, *a3 = NULL, *a4 = NULL; + int dir; + int point; + int refa, refb; + int gridless; + pcb_coord_t s, e, slack; + int divisor; + int changed = 0; + int i; + + if (argc < 2 || argc == 4 || argc > 5) { + PCB_ACT_FAIL(distributetext); + } + + PCB_ACT_CONVARG(1, FGW_STR, distributetext, a0 = argv[1].val.str); + PCB_ACT_CONVARG(2, FGW_STR, distributetext, a1 = argv[2].val.str); + PCB_ACT_MAY_CONVARG(3, FGW_STR, distributetext, a2 = argv[3].val.str); + PCB_ACT_MAY_CONVARG(4, FGW_STR, distributetext, a3 = argv[4].val.str); + PCB_ACT_MAY_CONVARG(5, FGW_STR, distributetext, a4 = argv[5].val.str); + + /* parse direction arg */ + switch ((dir = keyword(a0))) { + case K_X: + case K_Y: + break; + default: + PCB_ACT_FAIL(distributetext); + } + + + /* parse point (within each element) which will be distributed */ + switch ((point = keyword(a1))) { + case K_Centers: + case K_Gaps: + break; + case K_Lefts: + case K_Rights: + if (dir == K_Y) { + PCB_ACT_FAIL(distributetext); + } + break; + case K_Tops: + case K_Bottoms: + if (dir == K_X) { + PCB_ACT_FAIL(distributetext); + } + break; + case K_none: /* default value */ + if (dir == K_X) { + point = K_Lefts; + } + else { + point = K_Tops; + } + break; + default: + PCB_ACT_FAIL(distributetext); + } + /* parse reference which will determine first distribution coordinate */ + switch ((refa = keyword(a2))) { + case K_First: + case K_Last: + case K_Average: + case K_Crosshair: + break; + case K_none: + refa = K_First; /* default value */ + break; + default: + PCB_ACT_FAIL(distributetext); + } + /* parse reference which will determine final distribution coordinate */ + switch ((refb = keyword(a3))) { + case K_First: + case K_Last: + case K_Average: + case K_Crosshair: + break; + case K_none: + refb = K_Last; /* default value */ + break; + default: + PCB_ACT_FAIL(distributetext); + } + if (refa == refb) { + PCB_ACT_FAIL(distributetext); + } + /* optionally work off the grid (solar cells!) */ + switch (keyword(a4)) { + case K_Gridless: + gridless = 1; + break; + case K_none: + gridless = 0; + break; + default: + PCB_ACT_FAIL(distributetext); + } + pcb_undo_save_serial(); + /* build list of texts in orthogonal axis order */ + sort_texts_by_pos(K_distributetext, dir, point); + /* find the endpoints given the above options */ + s = reference_coord(K_distributetext, pcb_crosshair.X, pcb_crosshair.Y, dir, point, refa); + e = reference_coord(K_distributetext, pcb_crosshair.X, pcb_crosshair.Y, dir, point, refb); + slack = e - s; + /* use this divisor to calculate spacing (for 1 elt, avoid 1/0) */ + divisor = (ntexts_by_pos > 1) ? (ntexts_by_pos - 1) : 1; + /* even the gaps instead of the edges or whatnot */ + /* find the "slack" in the row */ + if (point == K_Gaps) { + pcb_coord_t w; + + /* subtract all the "widths" from the slack */ + for (i = 0; i < ntexts_by_pos; ++i) { + pcb_text_t *text = texts_by_pos[i].text; + + /* coord doesn't care if I mix Lefts/Tops */ + w = texts_by_pos[i].width = coord(text, dir, K_Rights) - coord(text, dir, K_Lefts); + /* Gaps distribution is on centers, so half of + * first and last text don't count */ + if (i == 0 || i == ntexts_by_pos - 1) { + w /= 2; + } + slack -= w; + } + /* slack could be negative */ + } + /* move all selected texts to the new coordinate */ + for (i = 0; i < ntexts_by_pos; ++i) { + pcb_text_t *text = texts_by_pos[i].text; + pcb_coord_t p, q, dp, dx, dy; + + /* find reference point for this text */ + q = s + slack * i / divisor; + /* find delta from reference point to reference point */ + p = coord(text, dir, point); + dp = q - p; + /* ...but if we're gridful, keep the mark on the grid */ + /* TODO re-enable grid + if (! gridless) + { + dp -= (coord (text, dir, K_Marks) + dp) % (long) (PCB->Grid); + } + */ + if (dp) { + /* move from generic to X or Y */ + dx = dy = dp; + if (dir == K_X) + dy = 0; + else + dx = 0; + pcb_text_move(text, dx, dy); + pcb_undo_add_obj_to_move(PCB_OBJ_TEXT, NULL, NULL, text, dx, dy); + changed = 1; + } + /* in gaps mode, accumulate part widths */ + if (point == K_Gaps) { + /* move remaining half of our text */ + s += texts_by_pos[i].width / 2; + /* move half of next text */ + if (i < ntexts_by_pos - 1) + s += texts_by_pos[i + 1].width / 2; + } + } + if (changed) { + pcb_undo_restore_serial(); + pcb_undo_inc_serial(); + pcb_redraw(); + pcb_board_set_changed_flag(pcb_true); + } + free_texts_by_pos(); + PCB_ACT_IRES(0); + return 0; +} + +static pcb_action_t distaligntext_action_list[] = { + {"distributetext", pcb_act_distributetext, "Distribute Text Elements", pcb_acts_distributetext}, + {"aligntext", pcb_act_aligntext, "Align Text Elements", pcb_acts_aligntext} +}; + +char *distaligntext_cookie = "distaligntext plugin"; + +PCB_REGISTER_ACTIONS(distaligntext_action_list, distaligntext_cookie) + +int pplg_check_ver_distaligntext(int ver_needed) { return 0; } + +void pplg_uninit_distaligntext(void) +{ + pcb_remove_actions_by_cookie(distaligntext_cookie); +} + +#include "dolists.h" +int pplg_init_distaligntext(void) +{ + PCB_API_CHK_VER; + PCB_REGISTER_ACTIONS(distaligntext_action_list, distaligntext_cookie); + return 0; +} Index: tags/2.1.2/src_plugins/distaligntext/distaligntext.pup =================================================================== --- tags/2.1.2/src_plugins/distaligntext/distaligntext.pup (nonexistent) +++ tags/2.1.2/src_plugins/distaligntext/distaligntext.pup (revision 24813) @@ -0,0 +1,7 @@ +$class feature +$short distribute and align text +$long Same as distalign, operates on text objects. +$package extra +$state works +default buildin +autoload 1 Index: tags/2.1.2/src_plugins/djopt/Makefile =================================================================== --- tags/2.1.2/src_plugins/djopt/Makefile (nonexistent) +++ tags/2.1.2/src_plugins/djopt/Makefile (revision 24813) @@ -0,0 +1,6 @@ +all: + cd ../../src && $(MAKE) mod_djopt + +clean: + rm *.o *.so 2>/dev/null ; true + Index: tags/2.1.2/src_plugins/djopt/Plug.tmpasm =================================================================== --- tags/2.1.2/src_plugins/djopt/Plug.tmpasm (nonexistent) +++ tags/2.1.2/src_plugins/djopt/Plug.tmpasm (revision 24813) @@ -0,0 +1,9 @@ +put /local/pcb/mod {djopt} +append /local/pcb/mod/OBJS [@ $(PLUGDIR)/djopt/djopt.o @] +put /local/pcb/mod/CONF {$(PLUGDIR)/djopt/djopt_conf.h} + +switch /local/pcb/djopt/controls + case {buildin} include /local/pcb/tmpasm/buildin; end; + case {plugin} include /local/pcb/tmpasm/plugin; end; + case {disable} include /local/pcb/tmpasm/disable; end; +end Index: tags/2.1.2/src_plugins/djopt/djopt.c =================================================================== --- tags/2.1.2/src_plugins/djopt/djopt.c (nonexistent) +++ tags/2.1.2/src_plugins/djopt/djopt.c (revision 24813) @@ -0,0 +1,2590 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 2003 DJ Delorie + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + * + * Old contact info: + * DJ Delorie, 334 North Road, Deerfield NH 03037-1110, USA + * dj@delorie.com + * + */ + +#include "config.h" +#include "conf_core.h" +#include "board.h" + +#include +#include + + +#include "data.h" +#include "remove.h" +#include "move.h" +#include "draw.h" +#include "undo.h" +#include "flag_str.h" +#include "find.h" +#include "layer.h" +#include "pcb-printf.h" +#include "compat_misc.h" +#include "plugins.h" +#include "actions.h" +#include "djopt_conf.h" +#include "obj_line.h" +#include "event.h" +#include "macro.h" +#include "obj_pstk_inlines.h" + +conf_djopt_t conf_djopt; + +static const char *djopt_cookie = "djopt"; + +#define dprintf if(0)pcb_printf + +#define selected(x) PCB_FLAG_TEST(PCB_FLAG_SELECTED, (x)) +#define autorouted(x) PCB_FLAG_TEST(PCB_FLAG_AUTO, (x)) + +#define SB (conf_core.design.bloat+1) + +/* must be 2^N-1 */ +#define INC 7 + +#define O_HORIZ 0x10 +#define O_VERT 0x20 +#define LEFT 0x11 +#define RIGHT 0x12 +#define UP 0x24 +#define DOWN 0x28 +#define DIAGONAL 0xf0 +#define ORIENT(x) ((x) & 0xf0) +#define DIRECT(x) ((x) & 0x0f) + +/* Manhattan length of the longest "freckle" */ +#define LONGEST_FRECKLE 2 + +struct line_s; + +typedef struct corner_s { + int layer; + struct corner_s *next; + int x, y; + int net; + pcb_pstk_t *via, *pad, *pin; + int miter; + int n_lines; + struct line_s **lines; +} corner_s; + +typedef struct line_s { + int layer; + struct line_s *next; + corner_s *s, *e; + pcb_line_t *line; + char is_pad; +} line_s; + +typedef struct rect_s { + int x1, y1, x2, y2; +} rect_s; + +#define DELETE(q) (q)->layer = 0xdeadbeef +#define DELETED(q) ((q)->layer == 0xdeadbeef) + +static corner_s *corners, *next_corner = 0; +static line_s *lines; + +static int layer_groupings[PCB_MAX_LAYERGRP]; +static char layer_type[PCB_MAX_LAYER]; +#define LT_COMPONENT 1 +#define LT_SOLDER 2 + +static const char *element_name_for(corner_s * c) +{ + PCB_SUBC_LOOP(PCB->Data); + { + PCB_PADSTACK_LOOP(subc->data); + { + if ((padstack == c->pin) || (padstack == c->pad)) + return subc->refdes; + } + PCB_END_LOOP; + } + PCB_END_LOOP; + + return "unknown"; +} + +static const char *corner_name(corner_s * c) +{ + static char buf[4][100]; + static int bn = 0; + char *bp; + bn = (bn + 1) % 4; + + if (c->net == 0xf1eef1ee) { + sprintf(buf[bn], "\033[31m[%p freed corner]\033[0m", (void *) c); + return buf[bn]; + } + + sprintf(buf[bn], "\033[%dm[%p ", (c->pin || c->pad || c->via) ? 33 : 34, (void *) c); + bp = buf[bn] + strlen(buf[bn]); + + if (c->pin) + pcb_sprintf(bp, "pin %s:%s at %#mD", element_name_for(c), c->pin->term, c->x, c->y); + else if (c->via) + pcb_sprintf(bp, "via at %#mD", c->x, c->y); + else if (c->pad) { + pcb_sprintf(bp, "pad %s:%s at %#mD %#mD-%#mD", + element_name_for(c), c->pad->term, c->x, c->y, + c->pad->BoundingBox.X1, c->pad->BoundingBox.Y1, c->pad->BoundingBox.X2, c->pad->BoundingBox.Y2); + } + else + pcb_sprintf(bp, "at %#mD", c->x, c->y); + sprintf(bp + strlen(bp), " n%d l%d]\033[0m", c->n_lines, c->layer); + return buf[bn]; +} + +static int solder_layer, component_layer; + +static void dj_abort(const char *msg, ...) +{ + va_list a; + va_start(a, msg); + vprintf(msg, a); + va_end(a); + fflush(stdout); + abort(); +} + +#if 1 +#define check(c,l) +#else +#define check(c,l) check2(__LINE__,c,l) +static void check2(int srcline, corner_s * c, line_s * l) +{ + int saw_c = 0, saw_l = 0; + corner_s *cc; + line_s *ll; + int i; + + for (cc = corners; cc; cc = cc->next) { + if (DELETED(cc)) + continue; + if (cc == c) + saw_c = 1; + for (i = 0; i < cc->n_lines; i++) + if (cc->lines[i]->s != cc && cc->lines[i]->e != cc) + dj_abort("check:%d: cc has line without backref\n", srcline); + if (cc->via && (cc->x != cc->via->X || cc->y != cc->via->Y)) + dj_abort("check:%d: via not at corner\n", srcline); + if (cc->pin && (cc->x != cc->pin->X || cc->y != cc->pin->Y)) + dj_abort("check:%d: pin not at corner\n", srcline); + } + if (c && !saw_c) + dj_abort("check:%d: corner not in corners list\n", srcline); + for (ll = lines; ll; ll = ll->next) { + if (DELETED(ll)) + continue; + if (ll == l) + saw_l = 1; + for (i = 0; i < ll->s->n_lines; i++) + if (ll->s->lines[i] == ll) + break; + if (i == ll->s->n_lines) + dj_abort("check:%d: ll->s has no backref\n", srcline); + for (i = 0; i < ll->e->n_lines; i++) + if (ll->e->lines[i] == ll) + break; + if (i == ll->e->n_lines) + dj_abort("check:%d: ll->e has no backref\n", srcline); + if (!ll->is_pad + && (ll->s->x != ll->line->Point1.X + || ll->s->y != ll->line->Point1.Y || ll->e->x != ll->line->Point2.X || ll->e->y != ll->line->Point2.Y)) { + pcb_printf("line: %#mD to %#mD pcbline: %#mD to %#mD\n", + ll->s->x, ll->s->y, + ll->e->x, ll->e->y, ll->line->Point1.X, ll->line->Point1.Y, ll->line->Point2.X, ll->line->Point2.Y); + dj_abort("check:%d: line doesn't match pcbline\n", srcline); + } + } + if (l && !saw_l) + dj_abort("check:%d: line not in lines list\n", srcline); +} + +#endif + +#define SWAP(a,b) { a^=b; b^=a; a^=b; } + +static int gridsnap(pcb_coord_t n) +{ + if (n <= 0) + return 0; + return n - n % (conf_core.editor.grid); +} + +/* Avoid commonly used names. */ + +static int djabs(int x) +{ + return x > 0 ? x : -x; +} + +static int djmax(int x, int y) +{ + return x > y ? x : y; +} + +static int djmin(int x, int y) +{ + return x < y ? x : y; +} + +/* + * Find distance between 2 points. We use floating point math here + * because we can fairly easily overflow a 32 bit integer here. In + * fact it only takes 0.46" to do so. + */ +static int dist(int x1, int y1, int x2, int y2) +{ + double dx1, dy1, dx2, dy2, d; + + dx1 = (double) x1; + dy1 = (double) y1; + dx2 = (double) x2; + dy2 = (double) y2; + + d = sqrt((dx1 - dx2) * (dx1 - dx2) + (dy1 - dy2) * (dy1 - dy2)); + d = pcb_round(d); + + return (int) d; +} + +static int line_length(line_s * l) +{ + if (l->s->x == l->e->x) + return djabs(l->s->y - l->e->y); + if (l->s->y == l->e->y) + return djabs(l->s->x - l->e->x); + return dist(l->s->x, l->s->y, l->e->x, l->e->y); +} + +static int dist_ltp2(int dx, int y, int y1, int y2) +{ + if (y1 > y2) + SWAP(y1, y2); + if (y < y1) + return dist(dx, y, 0, y1); + if (y > y2) + return dist(dx, y, 0, y2); + return djabs(dx); +} + +int sqr(int a) +{ + return a * a; +} + +static int intersecting_layers(int l1, int l2) +{ + if (l1 == -1 || l2 == -1) + return 1; + if (l1 == l2) + return 1; + if (layer_groupings[l1] == layer_groupings[l2]) + return 1; + return 0; +} + +static int dist_line_to_point(line_s * l, corner_s * c) +{ + double len, r, d; + /* We can do this quickly if l is vertical or horizontal. */ + if (l->s->x == l->e->x) + return dist_ltp2(l->s->x - c->x, c->y, l->s->y, l->e->y); + if (l->s->y == l->e->y) + return dist_ltp2(l->s->y - c->y, c->x, l->s->x, l->e->x); + + /* Do it the hard way. See comments for pcb_is_point_on_line() in search.c */ + len = sqrt(sqr(l->s->x - l->e->x) + sqr(l->s->y - l->e->y)); + if (len == 0) + return dist(l->s->x, l->s->y, c->x, c->y); + r = (l->s->y - c->y) * (l->s->y - l->e->y) + (l->s->x - c->x) * (l->s->x - l->e->x); + r /= len * len; + if (r < 0) + return dist(l->s->x, l->s->y, c->x, c->y); + if (r > 1) + return dist(l->e->x, l->e->y, c->x, c->y); + d = (l->e->y - l->s->y) * (c->x * l->s->x) + (l->e->x - l->s->x) * (c->y - l->s->y); + return (int) (d / len); +} + +static int line_orient(line_s * l, corner_s * c) +{ + int x1, y1, x2, y2; + if (c == l->s) { + x1 = l->s->x; + y1 = l->s->y; + x2 = l->e->x; + y2 = l->e->y; + } + else { + x1 = l->e->x; + y1 = l->e->y; + x2 = l->s->x; + y2 = l->s->y; + } + if (x1 == x2) { + if (y1 < y2) + return DOWN; + return UP; + } + else if (y1 == y2) { + if (x1 < x2) + return RIGHT; + return LEFT; + } + return DIAGONAL; +} + +static corner_s *other_corner(line_s * l, corner_s * c) +{ + if (l->s == c) + return l->e; + if (l->e == c) + return l->s; + dj_abort("other_corner: neither corner passed\n"); + return NULL; +} + +static corner_s *find_corner_if(int x, int y, int l) +{ + corner_s *c; + for (c = corners; c; c = c->next) { + if (DELETED(c)) + continue; + if (c->x != x || c->y != y) + continue; + if (!(c->layer == -1 || intersecting_layers(c->layer, l))) + continue; + return c; + } + return 0; +} + +static corner_s *find_corner(int x, int y, int l) +{ + corner_s *c; + for (c = corners; c; c = c->next) { + if (DELETED(c)) + continue; + if (c->x != x || c->y != y) + continue; + if (!(c->layer == -1 || intersecting_layers(c->layer, l))) + continue; + return c; + } + c = (corner_s *) malloc(sizeof(corner_s)); + c->next = corners; + corners = c; + c->x = x; + c->y = y; + c->net = 0; + c->via = 0; + c->pad = 0; + c->pin = 0; + c->layer = l; + c->n_lines = 0; + c->lines = (line_s **) malloc(INC * sizeof(line_s *)); + return c; +} + +static void add_line_to_corner(line_s * l, corner_s * c) +{ + int n; + n = (c->n_lines + 1 + INC) & ~INC; + c->lines = (line_s **) realloc(c->lines, n * sizeof(line_s *)); + c->lines[c->n_lines] = l; + c->n_lines++; + dprintf("add_line_to_corner %#mD\n", c->x, c->y); +} + +static pcb_line_t *create_pcb_line(int layer, int x1, int y1, int x2, int y2, int thick, int clear, pcb_flag_t flags) +{ + char *from, *to; + pcb_line_t *nl; + pcb_layer_t *lyr = LAYER_PTR(layer); + + from = (char *) linelist_first(&lyr->Line); + nl = pcb_line_new(PCB->Data->Layer + layer, x1, y1, x2, y2, thick, clear, flags); + pcb_undo_add_obj_to_create(PCB_OBJ_LINE, lyr, nl, nl); + + to = (char *) linelist_first(&lyr->Line); + if (from != to) { + line_s *lp; + for (lp = lines; lp; lp = lp->next) { + if (DELETED(lp)) + continue; + if ((char *) (lp->line) >= from && (char *) (lp->line) <= from + linelist_length(&lyr->Line) * sizeof(pcb_line_t)) + lp->line = (pcb_line_t *) ((char *) (lp->line) + (to - from)); + } + } + return nl; +} + +static void new_line(corner_s * s, corner_s * e, int layer, pcb_line_t * example) +{ + line_s *ls; + + if (!(pcb_layer_flags(PCB, layer) & PCB_LYT_COPPER)) + dj_abort("layer %d\n", layer); + + if (example == NULL) + dj_abort("NULL example passed to new_line()\n", layer); + + if (s->x == e->x && s->y == e->y) + return; + + ls = (line_s *) malloc(sizeof(line_s)); + ls->next = lines; + lines = ls; + ls->is_pad = 0; + ls->s = s; + ls->e = e; + ls->layer = layer; +#if 0 + if ((example->Point1.X == s->x && example->Point1.Y == s->y && example->Point2.X == e->x && example->Point2.Y == e->y) + || (example->Point2.X == s->x && example->Point2.Y == s->y && example->Point1.X == e->x && example->Point1.Y == e->y)) { + ls->line = example; + } + else +#endif + { + pcb_line_t *nl; + dprintf + ("New line \033[35m%#mD to %#mD from l%d t%#mS c%#mS f%s\033[0m\n", + s->x, s->y, e->x, e->y, layer, example->Thickness, example->Clearance, pcb_strflg_f2s(example->Flags, PCB_OBJ_LINE, NULL, 0)); + nl = create_pcb_line(layer, s->x, s->y, e->x, e->y, example->Thickness, example->Clearance, example->Flags); + + if (!nl) + dj_abort("can't create new line!"); + ls->line = nl; + } + add_line_to_corner(ls, s); + add_line_to_corner(ls, e); + check(s, ls); + check(e, ls); +} + +static line_s *other_line(corner_s * c, line_s * l) +{ + int i; + line_s *rv = 0; + if (c->pin || c->pad || c->via) + return 0; + for (i = 0; i < c->n_lines; i++) { + if (c->lines[i] == l) + continue; + if (rv) + return 0; + rv = c->lines[i]; + } + return rv; +} + +static void empty_rect(rect_s * rect) +{ + rect->x1 = rect->y1 = INT_MAX; + rect->x2 = rect->y2 = INT_MIN; +} + +static void add_point_to_rect(rect_s * rect, int x, int y, int w) +{ + if (rect->x1 > x - w) + rect->x1 = x - w; + if (rect->x2 < x + w) + rect->x2 = x + w; + if (rect->y1 > y - w) + rect->y1 = y - w; + if (rect->y2 < y + w) + rect->y2 = y + w; +} + +static void add_line_to_rect(rect_s * rect, line_s * l) +{ + add_point_to_rect(rect, l->s->x, l->s->y, 0); + add_point_to_rect(rect, l->e->x, l->e->y, 0); +} + +static int pin_in_rect(rect_s * r, int x, int y, int w) +{ + if (x < r->x1 && x + w < r->x1) + return 0; + if (x > r->x2 && x - w > r->x2) + return 0; + if (y < r->y1 && y + w < r->y1) + return 0; + if (y > r->y2 && y - w > r->y2) + return 0; + return 1; +} + +static int line_in_rect(rect_s * r, line_s * l) +{ + rect_s lr; + empty_rect(&lr); + add_point_to_rect(&lr, l->s->x, l->s->y, l->line->Thickness / 2); + add_point_to_rect(&lr, l->e->x, l->e->y, l->line->Thickness / 2); + dprintf("line_in_rect %#mD-%#mD vs %#mD-%#mD\n", r->x1, r->y1, r->x2, r->y2, lr.x1, lr.y1, lr.x2, lr.y2); + /* simple intersection of rectangles */ + if (lr.x1 < r->x1) + lr.x1 = r->x1; + if (lr.x2 > r->x2) + lr.x2 = r->x2; + if (lr.y1 < r->y1) + lr.y1 = r->y1; + if (lr.y2 > r->y2) + lr.y2 = r->y2; + if (lr.x1 < lr.x2 && lr.y1 < lr.y2) + return 1; + return 0; +} + +static int corner_radius(corner_s * c) +{ + pcb_pstk_t *p = NULL; + int diam = 0; + int i; + + if (c->pin) p = c->pin; + if (c->via) p = c->via; + if (c->pad) p = c->pad; + if (p != NULL) + diam = djmax(p->BoundingBox.X2 - p->BoundingBox.X1, p->BoundingBox.Y2 - p->BoundingBox.Y1); + + for (i = 0; i < c->n_lines; i++) + if (c->lines[i]->line) + diam = djmax(c->lines[i]->line->Thickness, diam); + diam = (diam + 1) / 2; + return diam; +} + +static void add_corner_to_rect_if(rect_s * rect, corner_s * c, rect_s * e) +{ + int diam = corner_radius(c); + if (!pin_in_rect(e, c->x, c->y, diam)) + return; + if (c->x < e->x1 && c->y < e->y1 && dist(c->x, c->y, e->x1, e->y1) > diam) + return; + if (c->x > e->x2 && c->y < e->y1 && dist(c->x, c->y, e->x2, e->y1) > diam) + return; + if (c->x < e->x1 && c->y > e->y2 && dist(c->x, c->y, e->x1, e->y2) > diam) + return; + if (c->x > e->x2 && c->y > e->y2 && dist(c->x, c->y, e->x2, e->y2) > diam) + return; + + /*pcb_printf("add point %#mD diam %#mS\n", c->x, c->y, diam); */ + add_point_to_rect(rect, c->x, c->y, diam); +} + +static void remove_line(line_s * l) +{ + int i, j; + pcb_layer_t *layer = &(PCB->Data->Layer[l->layer]); + + check(0, 0); + + if (l->line) + pcb_line_destroy(layer, l->line); + + DELETE(l); + + for (i = 0, j = 0; i < l->s->n_lines; i++) + if (l->s->lines[i] != l) + l->s->lines[j++] = l->s->lines[i]; + l->s->n_lines = j; + + for (i = 0, j = 0; i < l->e->n_lines; i++) + if (l->e->lines[i] != l) + l->e->lines[j++] = l->e->lines[i]; + l->e->n_lines = j; + check(0, 0); +} + +static void move_line_to_layer(line_s * l, int layer) +{ + pcb_layer_t *ls, *ld; + + ls = LAYER_PTR(l->layer); + ld = LAYER_PTR(layer); + + pcb_move_obj_to_layer(PCB_OBJ_LINE, ls, l->line, 0, ld, 0); + l->layer = layer; +} + +static void remove_via_at(corner_s * c) +{ + pcb_remove_object(PCB_OBJ_PSTK, c->via, 0, 0); + c->via = 0; +} + +static void remove_corner(corner_s * c2) +{ + corner_s *c; + dprintf("remove corner %s\n", corner_name(c2)); + if (corners == c2) + corners = c2->next; + for (c = corners; c; c = c->next) { + if (DELETED(c)) + continue; + if (c->next == c2) + c->next = c2->next; + } + if (next_corner == c2) + next_corner = c2->next; + free(c2->lines); + c2->lines = 0; + DELETE(c2); +} + +static void merge_corners(corner_s * c1, corner_s * c2) +{ + int i; + if (c1 == c2) + abort(); + dprintf("merge corners %s %s\n", corner_name(c1), corner_name(c2)); + for (i = 0; i < c2->n_lines; i++) { + add_line_to_corner(c2->lines[i], c1); + if (c2->lines[i]->s == c2) + c2->lines[i]->s = c1; + if (c2->lines[i]->e == c2) + c2->lines[i]->e = c1; + } + if (c1->via && c2->via) + remove_via_at(c2); + else if (c2->via) + c1->via = c2->via; + if (c2->pad) + c1->pad = c2->pad; + if (c2->pin) + c1->pin = c2->pin; + if (c2->layer != c1->layer) + c1->layer = -1; + + remove_corner(c2); +} + +static void move_corner(corner_s * c, int x, int y) +{ + pcb_pstk_t *via; + int i; + corner_s *pad; + + check(c, 0); + if (c->pad || c->pin) + dj_abort("move_corner: has pin or pad\n"); + dprintf("move_corner %p from %#mD to %#mD\n", (void *) c, c->x, c->y, x, y); + pad = find_corner_if(x, y, c->layer); + c->x = x; + c->y = y; + via = c->via; + if (via) { + pcb_move_obj(PCB_OBJ_PSTK, via, via, via, x - via->x, y - via->y); + dprintf("via move %#mD to %#mD\n", via->x, via->y, x, y); + } + for (i = 0; i < c->n_lines; i++) { + pcb_line_t *tl = c->lines[i]->line; + if (tl) { + if (c->lines[i]->s == c) { + pcb_move_obj(PCB_OBJ_LINE_POINT, LAYER_PTR(c->lines[i]->layer), tl, &tl->Point1, x - (tl->Point1.X), y - (tl->Point1.Y)); + } + else { + pcb_move_obj(PCB_OBJ_LINE_POINT, LAYER_PTR(c->lines[i]->layer), tl, &tl->Point2, x - (tl->Point2.X), y - (tl->Point2.Y)); + } + dprintf("Line %p moved to %#mD %#mD\n", (void *) tl, tl->Point1.X, tl->Point1.Y, tl->Point2.X, tl->Point2.Y); + } + } + if (pad && pad != c) + merge_corners(c, pad); + else + for (i = 0; i < c->n_lines; i++) { + if (c->lines[i]->s->x == c->lines[i]->e->x && c->lines[i]->s->y == c->lines[i]->e->y) { + corner_s *c2 = other_corner(c->lines[i], c); + dprintf("move_corner: removing line %#mD %#mD %p %p\n", c->x, c->y, c2->x, c2->y, (void *) c, (void *) c2); + + remove_line(c->lines[i]); + if (c != c2) + merge_corners(c, c2); + check(c, 0); + i--; + break; + } + } + pcb_hid_progress(0, 0, 0); + check(c, 0); +} + +static int any_line_selected() +{ + line_s *l; + for (l = lines; l; l = l->next) { + if (DELETED(l)) + continue; + if (l->line && selected(l->line)) + return 1; + } + return 0; +} + +static int trim_step(int s, int l1, int l2) +{ + dprintf("trim %d %d %d\n", s, l1, l2); + if (s > l1) + s = l1; + if (s > l2) + s = l2; + if (s != l1 && s != l2) + s = gridsnap(s); + return s; +} + +static int canonicalize_line(line_s * l); + +static int split_line(line_s * l, corner_s * c) +{ + int i; + pcb_line_t *pcbline; + line_s *ls; + + if (!intersecting_layers(l->layer, c->layer)) + return 0; + if (l->is_pad) + return 0; + if (c->pad) { + dprintf("split on pad!\n"); + if (l->s->pad == c->pad || l->e->pad == c->pad) + return 0; + dprintf("splitting...\n"); + } + + check(c, l); + pcbline = create_pcb_line(l->layer, c->x, c->y, l->e->x, l->e->y, l->line->Thickness, l->line->Clearance, l->line->Flags); + if (pcbline == 0) + return 0; /* already a line there */ + + check(c, l); + + dprintf("split line from %#mD to %#mD at %#mD\n", l->s->x, l->s->y, l->e->x, l->e->y, c->x, c->y); + ls = (line_s *) malloc(sizeof(line_s)); + + ls->next = lines; + lines = ls; + ls->is_pad = 0; + ls->s = c; + ls->e = l->e; + ls->line = pcbline; + ls->layer = l->layer; + for (i = 0; i < l->e->n_lines; i++) + if (l->e->lines[i] == l) + l->e->lines[i] = ls; + l->e = c; + add_line_to_corner(l, c); + add_line_to_corner(ls, c); + + pcb_move_obj(PCB_OBJ_LINE_POINT, LAYER_PTR(l->layer), l->line, &l->line->Point2, + c->x - (l->line->Point2.X), c->y - (l->line->Point2.Y)); + + return 1; +} + +static int canonicalize_line(line_s * l) +{ + /* This could be faster */ + corner_s *c; + if (l->s->x == l->e->x) { + int y1 = l->s->y; + int y2 = l->e->y; + int x1 = l->s->x - l->line->Thickness / 2; + int x2 = l->s->x + l->line->Thickness / 2; + if (y1 > y2) { + int t = y1; + y1 = y2; + y2 = t; + } + for (c = corners; c; c = c->next) { + if (DELETED(c)) + continue; + if ((y1 < c->y && c->y < y2) + && intersecting_layers(l->layer, c->layer)) { + if (c->x != l->s->x && c->x < x2 && c->x > x1 && !(c->pad || c->pin)) { + move_corner(c, l->s->x, c->y); + } + if (c->x == l->s->x) { + /* FIXME: if the line is split, we have to re-canonicalize + both segments. */ + return split_line(l, c); + } + } + } + } + else if (l->s->y == l->e->y) { + int x1 = l->s->x; + int x2 = l->e->x; + int y1 = l->s->y - l->line->Thickness / 2; + int y2 = l->s->y + l->line->Thickness / 2; + if (x1 > x2) { + int t = x1; + x1 = x2; + x2 = t; + } + for (c = corners; c; c = c->next) { + if (DELETED(c)) + continue; + if ((x1 < c->x && c->x < x2) + && intersecting_layers(l->layer, c->layer)) { + if (c->y != l->s->y && c->y < y2 && c->y > y1 && !(c->pad || c->pin)) { + move_corner(c, c->x, l->s->y); + } + if (c->y == l->s->y) { + /* FIXME: Likewise. */ + return split_line(l, c); + } + } + } + } + else { + /* diagonal lines. Let's try to split them at pins/vias + anyway. */ + int x1 = l->s->x; + int x2 = l->e->x; + int y1 = l->s->y; + int y2 = l->e->y; + if (x1 > x2) { + int t = x1; + x1 = x2; + x2 = t; + } + if (y1 > y2) { + int t = y1; + y1 = y2; + y2 = t; + } + for (c = corners; c; c = c->next) { + if (DELETED(c)) + continue; + if (!c->via && !c->pin) + continue; + if ((x1 < c->x && c->x < x2) + && (y1 < c->y && c->y < y2) + && intersecting_layers(l->layer, c->layer)) { + pcb_pstk_t *p = c->pin ? c->pin : c->via; + int th = djmax(p->BoundingBox.X2 - p->BoundingBox.X1, p->BoundingBox.Y2 - p->BoundingBox.Y1); + th /= 2; + if (dist(l->s->x, l->s->y, c->x, c->y) > th + && dist(l->e->x, l->e->y, c->x, c->y) > th && pcb_isc_pstk_line(p, l->line)) { + return split_line(l, c); + } + } + } + } + return 0; +} + +/* Make sure all vias are at line end points */ +static int canonicalize_lines() +{ + int changes = 0; + int count; + line_s *l; + while (1) { + count = 0; + for (l = lines; l; l = l->next) { + if (DELETED(l)) + continue; + count += canonicalize_line(l); + } + changes += count; + if (count == 0) + break; + } + return changes; +} + +static int simple_optimize_corner(corner_s * c) +{ + int i; + int rv = 0; + + check(c, 0); + if (c->via) { + /* see if no via is needed */ + if (selected(c->via)) + dprintf("via check: line[0] layer %d at %#mD nl %d\n", c->lines[0]->layer, c->x, c->y, c->n_lines); + /* We can't delete vias that connect to power planes, or vias + have terminal name (assume they're test points). */ + if (!PCB_FLAG_THERM_TEST_ANY(c->via) && (c->via->term == NULL)) { + for (i = 1; i < c->n_lines; i++) { + if (selected(c->via)) + dprintf(" line[%d] layer %d %#mD to %#mD\n", + i, c->lines[i]->layer, c->lines[i]->s->x, c->lines[i]->s->y, c->lines[i]->e->x, c->lines[i]->e->y); + if (c->lines[i]->layer != c->lines[0]->layer) + break; + } + if (i == c->n_lines) { + if (selected(c->via)) + dprintf(" remove it\n"); + remove_via_at(c); + rv++; + } + } + } + + check(c, 0); + if (c->n_lines == 2 && !c->via) { + /* see if it is an unneeded corner */ + int o = line_orient(c->lines[0], c); + corner_s *c2 = other_corner(c->lines[1], c); + corner_s *c0 = other_corner(c->lines[0], c); + if (o == line_orient(c->lines[1], c2) && o != DIAGONAL) { + dprintf("straight %#mD to %#mD to %#mD\n", c0->x, c0->y, c->x, c->y, c2->x, c2->y); + if (selected(c->lines[0]->line)) + PCB_FLAG_SET(PCB_FLAG_SELECTED, c->lines[1]->line); + if (selected(c->lines[1]->line)) + PCB_FLAG_SET(PCB_FLAG_SELECTED, c->lines[0]->line); + move_corner(c, c2->x, c2->y); + } + } + check(c, 0); + if (c->n_lines == 1 && !c->via) { + corner_s *c0 = other_corner(c->lines[0], c); + if (abs(c->x - c0->x) + abs(c->y - c0->y) <= LONGEST_FRECKLE) { + /* + * Remove this line, as it is a "freckle". A freckle is an extremely + * short line (around 0.01 thou) that is unconnected at one end. + * Freckles are almost insignificantly small, but are annoying as + * they prevent the mitering optimiser from working. + * Freckles sometimes arise because of a bug in the autorouter that + * causes it to create small overshoots (typically 0.01 thou) at the + * intersections of vertical and horizontal lines. These overshoots + * are converted to freckles as a side effect of canonicalize_line(). + * Note that canonicalize_line() is not at fault, the bug is in the + * autorouter creating overshoots. + * The autorouter bug arose some time between the 20080202 and 20091103 + * releases. + * This code is probably worth keeping even when the autorouter bug is + * fixed, as "freckles" could conceivably arise in other ways. + */ + dprintf("freckle %#mD to %#mD\n", c->x, c->y, c0->x, c0->y); + move_corner(c, c0->x, c0->y); + } + } + check(c, 0); + return rv; +} + +/* We always run these */ +static int simple_optimizations() +{ + corner_s *c; + int rv = 0; + + /* Look for corners that aren't */ + for (c = corners; c; c = c->next) { + if (DELETED(c)) + continue; + if (c->pad || c->pin) + continue; + rv += simple_optimize_corner(c); + } + return rv; +} + +static int is_hole(corner_s * c) +{ + return c->pin || c->pad || c->via; +} + +static int orthopull_1(corner_s * c, int fdir, int rdir, int any_sel) +{ + static corner_s **cs = 0; + static int cm = 0; + static line_s **ls = 0; + static int lm = 0; + int i, li, ln, cn, snap; + line_s *l = 0; + corner_s *c2, *cb; + int adir = 0, sdir = 0, pull; + int saw_sel = 0, saw_auto = 0; + int max, len = 0, r1 = 0, r2; + rect_s rr; + int edir = 0, done; + + if (cs == 0) { + cs = (corner_s **) malloc(10 * sizeof(corner_s)); + cm = 10; + ls = (line_s **) malloc(10 * sizeof(line_s)); + lm = 10; + } + + for (i = 0; i < c->n_lines; i++) { + int o = line_orient(c->lines[i], c); + if (o == rdir) + return 0; + } + + switch (fdir) { + case RIGHT: + adir = DOWN; + sdir = UP; + break; + case DOWN: + adir = RIGHT; + sdir = LEFT; + break; + default: + dj_abort("fdir not right or down\n"); + } + + c2 = c; + cn = 0; + ln = 0; + pull = 0; + while (c2) { + if (c2->pad || c2->pin || c2->n_lines < 2) + return 0; + if (cn >= cm) { + cm = cn + 10; + cs = (corner_s **) realloc(cs, cm * sizeof(corner_s)); + } + cs[cn++] = c2; + r2 = corner_radius(c2); + if (r1 < r2) + r1 = r2; + l = 0; + for (i = 0; i < c2->n_lines; i++) { + int o = line_orient(c2->lines[i], c2); + if (o == DIAGONAL) + return 0; + if (o == fdir) { + if (l) + return 0; /* we don't support overlapping lines yet */ + l = c2->lines[i]; + } + if (o == rdir && c2->lines[i] != ls[ln - 1]) + return 0; /* likewise */ + if (o == adir) + pull++; + if (o == sdir) + pull--; + } + if (!l) + break; + if (selected(l->line)) + saw_sel = 1; + if (autorouted(l->line)) + saw_auto = 1; + if (ln >= lm) { + lm = ln + 10; + ls = (line_s **) realloc(ls, lm * sizeof(line_s)); + } + ls[ln++] = l; + c2 = other_corner(l, c2); + } + if (cn < 2 || pull == 0) + return 0; + if (any_sel && !saw_sel) + return 0; + if (!any_sel && conf_djopt.plugins.djopt.auto_only && !saw_auto) + return 0; + + /* Ok, now look for other blockages. */ + + empty_rect(&rr); + add_point_to_rect(&rr, c->x, c->y, corner_radius(c)); + add_point_to_rect(&rr, c2->x, c2->y, corner_radius(c2)); + + if (fdir == RIGHT && pull < 0) + edir = UP; + else if (fdir == RIGHT && pull > 0) + edir = DOWN; + else if (fdir == DOWN && pull < 0) + edir = LEFT; + else if (fdir == DOWN && pull > 0) + edir = RIGHT; + + max = -1; + for (i = 0; i < cn; i++) + for (li = 0; li < cs[i]->n_lines; li++) { + if (line_orient(cs[i]->lines[li], cs[i]) != edir) + continue; + len = line_length(cs[i]->lines[li]); + if (max > len || max == -1) + max = len; + } + dprintf("c %s %4#mD cn %d pull %3d max %4#mS\n", fdir == RIGHT ? "right" : "down ", c->x, c->y, cn, pull, max); + + switch (edir) { + case UP: + rr.y1 = c->y - r1 - max; + break; + case DOWN: + rr.y2 = c->y + r1 + max; + break; + case LEFT: + rr.x1 = c->x - r1 - max; + break; + case RIGHT: + rr.x2 = c->x + r1 + max; + break; + } + rr.x1 -= SB + 1; + rr.x2 += SB + 1; + rr.y1 -= SB + 1; + rr.y2 += SB + 1; + + snap = 0; + for (cb = corners; cb; cb = cb->next) { + int sep; + if (DELETED(cb)) + continue; + r1 = corner_radius(cb); + if (cb->net == c->net && !cb->pad) + continue; + if (!pin_in_rect(&rr, cb->x, cb->y, r1)) + continue; + switch (edir) { +#define ECHK(X,Y,LT) \ + for (i=0; ilayer, cb->layer)) \ + continue; \ + r2 = corner_radius(cs[i]); \ + if (cb->X + r1 <= cs[i]->X - r2 - SB - 1) \ + continue; \ + if (cb->X - r1 >= cs[i]->X + r2 + SB + 1) \ + continue; \ + if (cb->Y LT cs[i]->Y) \ + continue; \ + sep = djabs(cb->Y - cs[i]->Y) - r1 - r2 - SB - 1; \ + if (max > sep) \ + { max = sep; snap = 1; }\ + } \ + for (i=0; ilayer, cb->layer)) \ + continue; \ + if (cb->X <= cs[i]->X || cb->X >= cs[i+1]->X) \ + continue; \ + sep = (djabs(cb->Y - cs[i]->Y) - ls[i]->line->Thickness/2 \ + - r1 - SB - 1); \ + if (max > sep) \ + { max = sep; snap = 1; }\ + } + case UP: + ECHK(x, y, >=); + break; + case DOWN: + ECHK(x, y, <=); + break; + case LEFT: + ECHK(y, x, >=); + break; + case RIGHT: + ECHK(y, x, <=); + break; + } + } + + /* We must now check every line segment against our corners. */ + for (l = lines; l; l = l->next) { + int o, x1, x2, y1, y2; + if (DELETED(l)) + continue; + dprintf("check line %#mD to %#mD\n", l->s->x, l->s->y, l->e->x, l->e->y); + if (l->s->net == c->net) { + dprintf(" same net\n"); + continue; + } + o = line_orient(l, 0); + /* We don't need to check perpendicular lines, because their + corners already take care of it. */ + if ((fdir == RIGHT && (o == UP || o == DOWN)) + || (fdir == DOWN && (o == RIGHT || o == LEFT))) { + dprintf(" perpendicular\n"); + continue; + } + + /* Choose so that x1,y1 is closest to corner C */ + if ((fdir == RIGHT && l->s->x < l->e->x) + || (fdir == DOWN && l->s->y < l->e->y)) { + x1 = l->s->x; + y1 = l->s->y; + x2 = l->e->x; + y2 = l->e->y; + } + else { + x1 = l->e->x; + y1 = l->e->y; + x2 = l->s->x; + y2 = l->s->y; + } + + /* Eliminate all lines outside our range */ + if ((fdir == RIGHT && (x2 < c->x || x1 > c2->x)) + || (fdir == DOWN && (y2 < c->y || y1 > c2->y))) { + dprintf(" outside our range\n"); + continue; + } + + /* Eliminate all lines on the wrong side of us */ + if ((edir == UP && y1 > c->y && y2 > c->y) + || (edir == DOWN && y1 < c->y && y2 < c->y) + || (edir == LEFT && x1 > c->x && x2 > c->x) + || (edir == RIGHT && x1 < c->x && x2 < c->x)) { + dprintf(" wrong side\n"); + continue; + } + + /* For now, cheat on diagonals */ + switch (edir) { + case RIGHT: + if (x1 > x2) + x1 = x2; + break; + case LEFT: + if (x1 < x2) + x1 = x2; + break; + case DOWN: + if (y1 > y2) + y1 = y2; + break; + case UP: + if (y1 < y2) + y1 = y2; + break; + } + + /* Ok, now see how far we can get for each of our corners. */ + for (i = 0; i < cn; i++) { + int r = l->line->Thickness + SB + corner_radius(cs[i]) + 1; + int len = 0; + if ((fdir == RIGHT && (x2 < cs[i]->x || x1 > cs[i]->x)) + || (fdir == DOWN && (y2 < cs[i]->y || y1 > cs[i]->y))) + continue; + if (!intersecting_layers(cs[i]->layer, l->layer)) + continue; + switch (edir) { + case RIGHT: + len = x1 - c->x; + break; + case LEFT: + len = c->x - x1; + break; + case DOWN: + len = y1 - c->y; + break; + case UP: + len = c->y - y1; + break; + } + len -= r; + dprintf(" len is %#mS vs corner at %#mD\n", len, cs[i]->x, cs[i]->y); + if (len <= 0) + return 0; + if (max > len) + max = len; + } + + } + + /* We must make sure that if a segment isn't being completely + removed, that any vias and/or pads don't overlap. */ + done = 0; + while (!done) { + done = 1; + for (i = 0; i < cn; i++) + for (li = 0; li < cs[i]->n_lines; li++) { + line_s *l = cs[i]->lines[li]; + corner_s *oc = other_corner(l, cs[i]); + if (line_orient(l, cs[i]) != edir) + continue; + len = line_length(l); + if (!oc->pad || !cs[i]->via) { + if (!is_hole(l->s) || !is_hole(l->e)) + continue; + if (len == max) + continue; + } + len -= corner_radius(l->s); + len -= corner_radius(l->e); + len -= SB + 1; + if (max > len) { + max = len; + done = 0; + } + } + } + + if (max <= 0) + return 0; + switch (edir) { + case UP: + len = c->y - max; + break; + case DOWN: + len = c->y + max; + break; + case LEFT: + len = c->x - max; + break; + case RIGHT: + len = c->x + max; + break; + } + if (snap && max > conf_core.editor.grid) { + if (pull < 0) + len += conf_core.editor.grid - 1; + len = gridsnap(len); + } + if ((fdir == RIGHT && len == cs[0]->y) || (fdir == DOWN && len == cs[0]->x)) + return 0; + for (i = 0; i < cn; i++) { + if (fdir == RIGHT) { + max = len - cs[i]->y; + move_corner(cs[i], cs[i]->x, len); + } + else { + max = len - cs[i]->x; + move_corner(cs[i], len, cs[i]->y); + } + } + return max * pull; +} + +static int orthopull() +{ + /* Look for straight runs which could be moved to reduce total trace + length. */ + int any_sel = any_line_selected(); + corner_s *c; + int rv = 0; + + for (c = corners; c;) { + if (DELETED(c)) + continue; + if (c->pin || c->pad) { + c = c->next; + continue; + } + next_corner = c; + rv += orthopull_1(c, RIGHT, LEFT, any_sel); + if (c != next_corner) { + c = next_corner; + continue; + } + rv += orthopull_1(c, DOWN, UP, any_sel); + if (c != next_corner) { + c = next_corner; + continue; + } + c = c->next; + } + if (rv) + pcb_printf("orthopull: %ml mils saved\n", rv); + return rv; +} + +static int debumpify() +{ + /* Look for "U" shaped traces we can shorten (or eliminate) */ + int rv = 0; + int any_selected = any_line_selected(); + line_s *l, *l1, *l2; + corner_s *c, *c1, *c2; + rect_s rr, rp; + int o, o1, o2, step, w; + for (l = lines; l; l = l->next) { + if (DELETED(l)) + continue; + if (!l->line) + continue; + if (any_selected && !selected(l->line)) + continue; + if (!any_selected && conf_djopt.plugins.djopt.auto_only && !autorouted(l->line)) + continue; + if (l->s->pin || l->s->pad || l->e->pin || l->e->pad) + continue; + o = line_orient(l, 0); + if (o == DIAGONAL) + continue; + l1 = other_line(l->s, l); + if (!l1) + continue; + o1 = line_orient(l1, l->s); + l2 = other_line(l->e, l); + if (!l2) + continue; + o2 = line_orient(l2, l->e); + if (ORIENT(o) == ORIENT(o1) || o1 != o2 || o1 == DIAGONAL) + continue; + + dprintf("\nline: %#mD to %#mD\n", l->s->x, l->s->y, l->e->x, l->e->y); + w = l->line->Thickness / 2 + SB + 1; + empty_rect(&rr); + add_line_to_rect(&rr, l1); + add_line_to_rect(&rr, l2); + if (rr.x1 != l->s->x && rr.x1 != l->e->x) + rr.x1 -= w; + if (rr.x2 != l->s->x && rr.x2 != l->e->x) + rr.x2 += w; + if (rr.y1 != l->s->y && rr.y1 != l->e->y) + rr.y1 -= w; + if (rr.y2 != l->s->y && rr.y2 != l->e->y) + rr.y2 += w; + dprintf("range: x %#mS..%#mS y %#mS..%#mS\n", rr.x1, rr.x2, rr.y1, rr.y2); + + c1 = other_corner(l1, l->s); + c2 = other_corner(l2, l->e); + + empty_rect(&rp); + for (c = corners; c; c = c->next) { + if (DELETED(c)) + continue; + if (c->net != l->s->net && intersecting_layers(c->layer, l->s->layer)) + add_corner_to_rect_if(&rp, c, &rr); + } + if (rp.x1 == INT_MAX) { + rp.x1 = rr.x2; + rp.x2 = rr.x1; + rp.y1 = rr.y2; + rp.y2 = rr.y1; + } + dprintf("pin r: x %#mS..%#mS y %#mS..%#mS\n", rp.x1, rp.x2, rp.y1, rp.y2); + + switch (o1) { + case LEFT: + step = l->s->x - rp.x2 - w; + step = gridsnap(step); + if (step > l->s->x - c1->x) + step = l->s->x - c1->x; + if (step > l->s->x - c2->x) + step = l->s->x - c2->x; + if (step > 0) { + dprintf("left step %#mS at %#mD\n", step, l->s->x, l->s->y); + move_corner(l->s, l->s->x - step, l->s->y); + move_corner(l->e, l->e->x - step, l->e->y); + rv += step; + } + break; + case RIGHT: + step = rp.x1 - l->s->x - w; + step = gridsnap(step); + if (step > c1->x - l->s->x) + step = c1->x - l->s->x; + if (step > c2->x - l->s->x) + step = c2->x - l->s->x; + if (step > 0) { + dprintf("right step %#mS at %#mD\n", step, l->s->x, l->s->y); + move_corner(l->s, l->s->x + step, l->s->y); + move_corner(l->e, l->e->x + step, l->e->y); + rv += step; + } + break; + case UP: + if (rp.y2 == INT_MIN) + rp.y2 = rr.y1; + step = trim_step(l->s->y - rp.y2 - w, l->s->y - c1->y, l->s->y - c2->y); + if (step > 0) { + dprintf("up step %#mS at %#mD\n", step, l->s->x, l->s->y); + move_corner(l->s, l->s->x, l->s->y - step); + move_corner(l->e, l->e->x, l->e->y - step); + rv += step; + } + break; + case DOWN: + step = rp.y1 - l->s->y - w; + step = gridsnap(step); + if (step > c1->y - l->s->y) + step = c1->y - l->s->y; + if (step > c2->y - l->s->y) + step = c2->y - l->s->y; + if (step > 0) { + dprintf("down step %#mS at %#mD\n", step, l->s->x, l->s->y); + move_corner(l->s, l->s->x, l->s->y + step); + move_corner(l->e, l->e->x, l->e->y + step); + rv += step; + } + break; + } + check(0, l); + } + + rv += simple_optimizations(); + if (rv) + pcb_printf("debumpify: %ml mils saved\n", rv / 50); + return rv; +} + +static int simple_corner(corner_s * c) +{ + int o1, o2; + if (c->pad || c->pin || c->via) + return 0; + if (c->n_lines != 2) + return 0; + o1 = line_orient(c->lines[0], c); + o2 = line_orient(c->lines[1], c); + if (ORIENT(o1) == ORIENT(o2)) + return 0; + if (ORIENT(o1) == DIAGONAL || ORIENT(o2) == DIAGONAL) + return 0; + return 1; +} + +static int unjaggy_once() +{ + /* Look for sequences of simple corners we can reduce. */ + int rv = 0; + corner_s *c, *c0, *c1, *cc; + int l, w, sel = any_line_selected(); + int o0, o1, s0, s1; + rect_s rr, rp; + for (c = corners; c; c = c->next) { + if (DELETED(c)) + continue; + if (!simple_corner(c)) + continue; + if (!c->lines[0]->line || !c->lines[1]->line) + continue; + if (sel && !(selected(c->lines[0]->line) + || selected(c->lines[1]->line))) + continue; + if (!sel && conf_djopt.plugins.djopt.auto_only && !(autorouted(c->lines[0]->line) + || autorouted(c->lines[1]->line))) + continue; + dprintf("simple at %#mD\n", c->x, c->y); + + c0 = other_corner(c->lines[0], c); + o0 = line_orient(c->lines[0], c); + s0 = simple_corner(c0); + + c1 = other_corner(c->lines[1], c); + o1 = line_orient(c->lines[1], c); + s1 = simple_corner(c1); + + if (!s0 && !s1) + continue; + dprintf("simples at %#mD\n", c->x, c->y); + + w = 1; + for (l = 0; l < c0->n_lines; l++) + if (c0->lines[l] != c->lines[0] + && c0->lines[l]->layer == c->lines[0]->layer) { + int o = line_orient(c0->lines[l], c0); + if (o == o1) + w = 0; + } + for (l = 0; l < c1->n_lines; l++) + if (c1->lines[l] != c->lines[0] + && c1->lines[l]->layer == c->lines[0]->layer) { + int o = line_orient(c1->lines[l], c1); + if (o == o0) + w = 0; + } + if (!w) + continue; + dprintf("orient ok\n"); + + w = c->lines[0]->line->Thickness / 2 + SB + 1; + empty_rect(&rr); + add_line_to_rect(&rr, c->lines[0]); + add_line_to_rect(&rr, c->lines[1]); + if (c->x != rr.x1) + rr.x1 -= w; + else + rr.x2 += w; + if (c->y != rr.y1) + rr.y1 -= w; + else + rr.y2 += w; + + empty_rect(&rp); + for (cc = corners; cc; cc = cc->next) { + if (DELETED(cc)) + continue; + if (cc->net != c->net && intersecting_layers(cc->layer, c->layer)) + add_corner_to_rect_if(&rp, cc, &rr); + } + dprintf("rp x %#mS..%#mS y %#mS..%#mS\n", rp.x1, rp.x2, rp.y1, rp.y2); + if (rp.x1 <= rp.x2) /* something triggered */ + continue; + + dprintf("unjaggy at %#mD layer %d\n", c->x, c->y, c->layer); + if (c->x == c0->x) + move_corner(c, c1->x, c0->y); + else + move_corner(c, c0->x, c1->y); + rv++; + check(c, 0); + } + rv += simple_optimizations(); + check(c, 0); + return rv; +} + +static int unjaggy() +{ + int i, r = 0, j; + for (i = 0; i < 100; i++) { + j = unjaggy_once(); + if (j == 0) + break; + r += j; + } + if (r) + printf("%d unjagg%s \n", r, r == 1 ? "y" : "ies"); + return r; +} + +static int vianudge() +{ + /* Look for vias with all lines leaving the same way, try to nudge + via to eliminate one or more of them. */ + int rv = 0; + corner_s *c, *c2, *c3; + line_s *l; + unsigned char directions[PCB_MAX_LAYER]; + unsigned char counts[PCB_MAX_LAYER]; + + memset(directions, 0, sizeof(directions)); + memset(counts, 0, sizeof(counts)); + + for (c = corners; c; c = c->next) { + int o, i, vr, cr, oboth; + int len = 0, saved = 0; + + if (DELETED(c)) + continue; + + if (!c->via) + continue; + + memset(directions, 0, sizeof(directions)); + memset(counts, 0, sizeof(counts)); + + for (i = 0; i < c->n_lines; i++) { + o = line_orient(c->lines[i], c); + counts[c->lines[i]->layer]++; + directions[c->lines[i]->layer] |= o; + } + for (o = 0, i = 0; i < pcb_max_layer; i++) { + if (!(pcb_layer_flags(PCB, i) & PCB_LYT_COPPER)) + continue; + if (counts[i] == 1) { + o = directions[i]; + break; + } + } + switch (o) { + case LEFT: + case RIGHT: + oboth = LEFT | RIGHT; + break; + case UP: + case DOWN: + oboth = UP | DOWN; + break; + default: + continue; + } + for (i = 0; i < pcb_max_layer; i++) { + if (!(pcb_layer_flags(PCB, i) & PCB_LYT_COPPER)) + continue; + if (counts[i] && directions[i] != o && directions[i] != oboth) + goto vianudge_continue; + } + c2 = 0; + for (i = 0; i < c->n_lines; i++) { + int ll = line_length(c->lines[i]); + if (line_orient(c->lines[i], c) != o) { + saved--; + continue; + } + saved++; + if (c2 == 0 || len > ll) { + len = ll; + c2 = other_corner(c->lines[i], c); + } + } + if (c2->pad || c2->pin || c2->via) + continue; + + /* Now look for clearance in the new position */ + vr = djmax(c->via->BoundingBox.X2 - c->via->BoundingBox.X1, c->via->BoundingBox.Y2 - c->via->BoundingBox.Y1); + vr = vr / 2 + SB + 1; + for (c3 = corners; c3; c3 = c3->next) { + if (DELETED(c3)) + continue; + if ((c3->net != c->net && (c3->pin || c3->via)) || c3->pad) { + cr = corner_radius(c3); + if (dist(c2->x, c2->y, c3->x, c3->y) < vr + cr) + goto vianudge_continue; + } + } + for (l = lines; l; l = l->next) { + if (DELETED(l)) + continue; + if (l->s->net != c->net) { + int ld = dist_line_to_point(l, c2); + if (ld < l->line->Thickness / 2 + vr) + goto vianudge_continue; + } + } + + /* at this point, we know we can move it */ + + dprintf("vianudge: nudging via at %#mD by %#mS saving %#mS\n", c->x, c->y, len, saved); + rv += len * saved; + move_corner(c, c2->x, c2->y); + + check(c, 0); + + vianudge_continue: + continue; + } + + if (rv) + pcb_printf("vianudge: %ml mils saved\n", rv); + return rv; +} + +static int viatrim() +{ + /* Look for traces that can be moved to the other side of the board, + to reduce the number of vias needed. For now, we look for simple + lines, not multi-segmented lines. */ + line_s *l, *l2; + int i, rv = 0, vrm = 0; + int any_sel = any_line_selected(); + + for (l = lines; l; l = l->next) { + rect_s r; + int my_layer, other_layer; + + if (DELETED(l)) + continue; + if (!l->s->via) + continue; + if (!l->e->via) + continue; + if (any_sel && !selected(l->line)) + continue; + if (!any_sel && conf_djopt.plugins.djopt.auto_only && !autorouted(l->line)) + continue; + + my_layer = l->layer; + other_layer = -1; + dprintf("line %p on layer %d from %#mD to %#mD\n", (void *) l, l->layer, l->s->x, l->s->y, l->e->x, l->e->y); + for (i = 0; i < l->s->n_lines; i++) + if (l->s->lines[i] != l) { + if (other_layer == -1) { + other_layer = l->s->lines[i]->layer; + dprintf("noting other line %p on layer %d\n", (void *) (l->s->lines[i]), my_layer); + } + else if (l->s->lines[i]->layer != other_layer) { + dprintf("saw other line %p on layer %d (not %d)\n", (void *) (l->s->lines[i]), l->s->lines[i]->layer, my_layer); + other_layer = -1; + goto viatrim_other_corner; + } + } + viatrim_other_corner: + if (other_layer == -1) + for (i = 0; i < l->e->n_lines; i++) + if (l->e->lines[i] != l) { + if (other_layer == -1) { + other_layer = l->s->lines[i]->layer; + dprintf("noting other line %p on layer %d\n", (void *) (l->s->lines[i]), my_layer); + } + else if (l->e->lines[i]->layer != other_layer) { + dprintf("saw end line on layer %d (not %d)\n", l->e->lines[i]->layer, other_layer); + goto viatrim_continue; + } + } + + /* Now see if any other line intersects us. We don't need to + check corners, because they'd either be pins/vias and + already conflict, or pads, which we'll check here anyway. */ + empty_rect(&r); + add_point_to_rect(&r, l->s->x, l->s->y, l->line->Thickness); + add_point_to_rect(&r, l->e->x, l->e->y, l->line->Thickness); + + for (l2 = lines; l2; l2 = l2->next) { + if (DELETED(l2)) + continue; + if (l2->s->net != l->s->net && l2->layer == other_layer) { + dprintf("checking other line %#mD to %#mD\n", l2->s->x, l2->s->y, l2->e->x, l2->e->y); + if (line_in_rect(&r, l2)) { + dprintf("line from %#mD to %#mD in the way\n", l2->s->x, l2->s->y, l2->e->x, l2->e->y); + goto viatrim_continue; + } + } + } + + if (l->layer == other_layer) + continue; + move_line_to_layer(l, other_layer); + rv++; + + viatrim_continue: + continue; + } + vrm = simple_optimizations(); + if (rv > 0) + printf("viatrim: %d traces moved, %d vias removed\n", rv, vrm); + return rv + vrm; +} + +static int automagic() +{ + int more = 1, oldmore = 0; + int toomany = 100; + while (more != oldmore && --toomany) { + oldmore = more; + more += debumpify(); + more += unjaggy(); + more += orthopull(); + more += vianudge(); + more += viatrim(); + } + return more - 1; +} + +static int miter() +{ + corner_s *c; + int done, progress; + int sel = any_line_selected(); + int saved = 0; + + for (c = corners; c; c = c->next) { + if (DELETED(c)) + continue; + c->miter = 0; + if (c->n_lines == 2 && !c->via && !c->pin && !c->via) { + int o1 = line_orient(c->lines[0], c); + int o2 = line_orient(c->lines[1], c); + if (ORIENT(o1) != ORIENT(o2) + && o1 != DIAGONAL && o2 != DIAGONAL && c->lines[0]->line->Thickness == c->lines[1]->line->Thickness) + c->miter = -1; + } + } + + done = 0; + progress = 1; + while (!done && progress) { + done = 1; + progress = 0; + for (c = corners; c; c = c->next) { + if (DELETED(c)) + continue; + if (c->miter == -1) { + int max = line_length(c->lines[0]); + int len = line_length(c->lines[1]); + int bloat; + int ref, dist; + corner_s *closest_corner = 0, *c2, *oc1, *oc2; + int mx = 0, my = 0, x, y; + int o1 = line_orient(c->lines[0], c); + int o2 = line_orient(c->lines[1], c); + + if (c->pad || c->pin || c->via) { + c->miter = 0; + progress = 1; + continue; + } + + oc1 = other_corner(c->lines[0], c); + oc2 = other_corner(c->lines[1], c); +#if 0 + if (oc1->pad) + oc1 = 0; + if (oc2->pad) + oc2 = 0; +#endif + + if ((sel && !(selected(c->lines[0]->line) + || selected(c->lines[1]->line))) + || (!sel && conf_djopt.plugins.djopt.auto_only && !(autorouted(c->lines[0]->line) + || autorouted(c->lines[1]->line)))) { + c->miter = 0; + progress = 1; + continue; + } + + if (max > len) + max = len; + switch (o1) { + case LEFT: + mx = -1; + break; + case RIGHT: + mx = 1; + break; + case UP: + my = -1; + break; + case DOWN: + my = 1; + break; + } + switch (o2) { + case LEFT: + mx = -1; + break; + case RIGHT: + mx = 1; + break; + case UP: + my = -1; + break; + case DOWN: + my = 1; + break; + } + ref = c->x * mx + c->y * my; + dist = max; + + bloat = (c->lines[0]->line->Thickness / 2 + SB + 1) * 3 / 2; + + for (c2 = corners; c2; c2 = c2->next) { + if (DELETED(c2)) + continue; + if (c2 != c && c2 != oc1 && c2 != oc2 + && c->x * mx <= c2->x * mx + && c->y * my <= c2->y * my && c->net != c2->net && intersecting_layers(c->layer, c2->layer)) { + int cr = corner_radius(c2); + len = c2->x * mx + c2->y * my - ref - cr - bloat; + if (c->x != c2->x && c->y != c2->y) + len -= cr; + if (len < dist || (len == dist && c->miter != -1)) { + dist = len; + closest_corner = c2; + } + } + } + + if (closest_corner && closest_corner->miter == -1) { + done = 0; + continue; + } + +#if 0 + if (dist < conf_core.editor.grid) { + c->miter = 0; + progress = 1; + continue; + } + + dist -= dist % conf_core.editor.grid; +#endif + if (dist <= 0) { + c->miter = 0; + progress = 1; + continue; + } + + x = c->x; + y = c->y; + switch (o1) { + case LEFT: + x -= dist; + break; + case RIGHT: + x += dist; + break; + case UP: + y -= dist; + break; + case DOWN: + y += dist; + break; + } + c2 = find_corner(x, y, c->layer); + if (c2 != other_corner(c->lines[0], c)) + split_line(c->lines[0], c2); + x = c->x; + y = c->y; + switch (o2) { + case LEFT: + x -= dist; + break; + case RIGHT: + x += dist; + break; + case UP: + y -= dist; + break; + case DOWN: + y += dist; + break; + } + move_corner(c, x, y); + c->miter = 0; + c2->miter = 0; + progress = 1; + saved++; + } + } + } + return saved; +} + +static void classify_corner(corner_s * c, int this_net) +{ + int i; + if (c->net == this_net) + return; + c->net = this_net; + for (i = 0; i < c->n_lines; i++) + classify_corner(other_corner(c->lines[i], c), this_net); +} + +static void classify_nets() +{ + static int this_net = 1; + corner_s *c; + + for (c = corners; c; c = c->next) { + if (DELETED(c)) + continue; + if (c->net) + continue; + classify_corner(c, this_net); + this_net++; + } +} + +#if 0 +static void nudge_corner(corner_s * c, int dx, int dy, corner_s * prev_corner) +{ + int ox = c->x; + int oy = c->y; + int l; + if (prev_corner && (c->pin || c->pad)) + return; + move_corner(c, ox + dx, oy + dy); + for (l = 0; l < c->n_lines; l++) { + corner_s *oc = other_corner(c->lines[l], c); + if (oc == prev_corner) + continue; + if (dx && oc->x == ox) + nudge_corner(oc, dx, 0, c); + if (dy && oc->y == oy) + nudge_corner(oc, 0, dy, c); + } +} +#endif + +static line_s *choose_example_line(corner_s * c1, corner_s * c2) +{ + int ci, li; + corner_s *c[2]; + c[0] = c1; + c[1] = c2; + dprintf("choose_example_line\n"); + for (ci = 0; ci < 2; ci++) + for (li = 0; li < c[ci]->n_lines; li++) { + dprintf(" try[%d,%d] \033[36m<%#mD-%#mD t%#mS c%#mS f%s>\033[0m\n", + ci, li, + c[ci]->lines[li]->s->x, c[ci]->lines[li]->s->y, + c[ci]->lines[li]->e->x, c[ci]->lines[li]->e->y, + c[ci]->lines[li]->line->Thickness, + c[ci]->lines[li]->line->Clearance, pcb_strflg_f2s(c[ci]->lines[li]->line->Flags, PCB_OBJ_LINE, NULL, 0)); + /* Pads are disqualified, as we want to mimic a trace line. */ + if (c[ci]->lines[li]->line == (pcb_line_t *) c[ci]->pad) { + dprintf(" bad, pad\n"); + continue; + } + /* Lines on layers that don't connect to the other pad are bad too. */ + if (!intersecting_layers(c[ci]->lines[li]->layer, c[1 - ci]->layer)) { + dprintf(" bad, layers\n"); + continue; + } + dprintf(" good\n"); + return c[ci]->lines[li]; + } + dprintf("choose_example_line: none found!\n"); + return 0; +} + +static int connect_corners(corner_s * c1, corner_s * c2) +{ + int layer; + line_s *ex = choose_example_line(c1, c2); + pcb_line_t *example = ex->line; + + dprintf + ("connect_corners \033[32m%#mD to %#mD, example line %#mD to %#mD l%d\033[0m\n", + c1->x, c1->y, c2->x, c2->y, ex->s->x, ex->s->y, ex->e->x, ex->e->y, ex->layer); + + layer = ex->layer; + + /* Assume c1 is the moveable one. */ + if (!(c1->pin || c1->pad || c1->via) && c1->n_lines == 1) { + int nx, ny; + /* Extend the line */ + if (c1->lines[0]->s->x == c1->lines[0]->e->x) + nx = c1->x, ny = c2->y; + else + nx = c2->x, ny = c1->y; + if (nx != c2->x || ny != c2->y) { + move_corner(c1, nx, ny); + new_line(c1, c2, layer, example); + return 1; + } + else { + move_corner(c1, nx, ny); + return 1; + } + } + else { + corner_s *nc = find_corner(c1->x, c2->y, layer); + new_line(c1, nc, layer, example); + new_line(nc, c2, layer, example); + return 0; + } +} + +static void pinsnap() +{ + corner_s *c; + int best_dist[PCB_MAX_LAYER + 1]; + corner_s *best_c[PCB_MAX_LAYER + 1]; + int l, got_one; + int left = 0, right = 0, top = 0, bottom = 0; + pcb_pstk_t *pin; + int again = 1; + + int close = 0; + corner_s *c2; + + memset(best_c, 0, sizeof(best_c)); + memset(best_dist, 0, sizeof(best_dist)); + + /* Look for pins that have no connections. See if there's a corner + close by that should be connected to it. This usually happens + when the MUCS router needs to route to an off-grid pin. */ + while (again) { + again = 0; + for (c = corners; c; c = c->next) { + if (DELETED(c)) + continue; + if (!(c->pin || c->via || c->pad)) + continue; + + pin = NULL; + + dprintf("\ncorner %s\n", corner_name(c)); + if (c->pin) pin = c->pin; + if (c->via) pin = c->via; + if (c->pad) pin = c->pad; + left = pin->BoundingBox.X1; + right = pin->BoundingBox.X2; + top = pin->BoundingBox.Y1; + bottom = pin->BoundingBox.Y2; + + dprintf("%s x %#mS-%#mS y %#mS-%#mS\n", corner_name(c), left, right, bottom, top); + for (l = 0; l <= pcb_max_layer; l++) { + if (!(pcb_layer_flags(PCB, l) & PCB_LYT_COPPER)) + continue; + best_dist[l] = close * 2; + best_c[l] = 0; + } + got_one = 0; + for (c2 = corners; c2; c2 = c2->next) { + int lt; + pcb_coord_t thick; + + if (DELETED(c2)) + continue; + thick = djmax(pin->BoundingBox.X2 - pin->BoundingBox.X1, pin->BoundingBox.Y2 - pin->BoundingBox.Y1); + lt = corner_radius(c2); + if (c2->n_lines && c2 != c && !(c2->pin || c2->pad || c2->via) + && intersecting_layers(c->layer, c2->layer) + && c2->x >= left - lt && c2->x <= right + lt && c2->y >= bottom - lt && c2->y <= top + lt) { + int d = dist(c->x, c->y, c2->x, c2->y); + if (pin && d > thick / 2 + lt) + continue; + if (c2->n_lines == 1) { + got_one++; + dprintf("found orphan %s vs %s\n", corner_name(c2), corner_name(c)); + connect_corners(c, c2); + again = 1; + continue; + } + if (best_c[c2->layer] == 0 || c2->n_lines < best_c[c2->layer]->n_lines || (d < best_dist[c2->layer] + && c2->n_lines <= + best_c[c2->layer]->n_lines)) { + best_dist[c2->layer] = d; + best_c[c2->layer] = c2; + dprintf("layer %d best now %s\n", c2->layer, corner_name(c2)); + } + } + if (!got_one && c->n_lines == (c->pad ? 1 : 0)) { + for (l = 0; l <= pcb_max_layer; l++) + if (best_c[l]) + dprintf("best[%d] = %s\n", l, corner_name(best_c[l])); + for (l = 0; l <= pcb_max_layer; l++) + if (best_c[l]) { + dprintf("move %s to %s\n", corner_name(best_c[l]), corner_name(c)); + connect_corners(best_c[l], c); + again = 1; + continue; + } + } + } + } + } + + /* Now look for line ends that don't connect, see if they need to be + extended to intersect another line. */ + for (c = corners; c; c = c->next) { + line_s *l, *t; + int lo; + + if (DELETED(c)) + continue; + if (c->pin || c->via || c->pad) + continue; + if (c->n_lines != 1) + continue; + + l = c->lines[0]; + lo = line_orient(l, c); + dprintf("line end %#mD orient %d\n", c->x, c->y, lo); + + for (t = lines; t; t = t->next) { + if (DELETED(t)) + continue; + if (t->layer != c->lines[0]->layer) + continue; + switch (lo) { /* remember, orient is for the line relative to the corner */ + case LEFT: + if (t->s->x == t->e->x + && c->x < t->s->x + && t->s->x < c->x + (l->line->Thickness + t->line->Thickness) / 2 && ((t->s->y < c->y && c->y < t->e->y) + || (t->e->y < c->y && c->y < t->s->y))) { + dprintf("found %#mD - %#mD\n", t->s->x, t->s->y, t->e->x, t->e->y); + move_corner(c, t->s->x, c->y); + } + break; + case RIGHT: + if (t->s->x == t->e->x + && c->x > t->s->x + && t->s->x > c->x - (l->line->Thickness + t->line->Thickness) / 2 && ((t->s->y < c->y && c->y < t->e->y) + || (t->e->y < c->y && c->y < t->s->y))) { + dprintf("found %#mD - %#mD\n", t->s->x, t->s->y, t->e->x, t->e->y); + move_corner(c, t->s->x, c->y); + } + break; + case UP: + if (t->s->y == t->e->y + && c->y < t->s->y + && t->s->y < c->y + (l->line->Thickness + t->line->Thickness) / 2 && ((t->s->x < c->x && c->x < t->e->x) + || (t->e->x < c->x && c->x < t->s->x))) { + dprintf("found %#mD - %#mD\n", t->s->x, t->s->y, t->e->x, t->e->y); + move_corner(c, c->x, t->s->y); + } + break; + case DOWN: + if (t->s->y == t->e->y + && c->y > t->s->y + && t->s->y > c->y - (l->line->Thickness + t->line->Thickness) / 2 && ((t->s->x < c->x && c->x < t->e->x) + || (t->e->x < c->x && c->x < t->s->x))) { + dprintf("found %#mD - %#mD\n", t->s->x, t->s->y, t->e->x, t->e->y); + move_corner(c, c->x, t->s->y); + } + break; + } + } + } +} + +static int pstk_orient(pcb_pstk_t *p) +{ + pcb_coord_t dx = p->BoundingBox.X2 - p->BoundingBox.X1; + pcb_coord_t dy = p->BoundingBox.Y2 - p->BoundingBox.Y1; + if (dx < dy * 3) + return O_VERT; + if (dx > dy * 3) + return O_HORIZ; + return DIAGONAL; +} + +static void padcleaner_(pcb_data_t *data) +{ + line_s *l, *nextl; + rect_s r; + + dprintf("\ndj: padcleaner\n"); + for (l = lines; l; l = nextl) { + nextl = l->next; + + if (l->is_pad) + continue; + + if (DELETED(l)) + continue; + + dprintf("dj: line %p\n", (void *) l); + check(0, l); + + if (l->s->pad && l->s->pad == l->e->pad) + continue; + + PCB_PADSTACK_LOOP(data); + { + pcb_pstk_shape_t *shape = NULL; + + /* check if the padstack has copper on the given side */ + switch(layer_type[l->layer]) { + case LT_SOLDER: shape = pcb_pstk_shape(padstack, PCB_LYT_BOTTOM | PCB_LYT_COPPER, 0); break; + case LT_COMPONENT: shape = pcb_pstk_shape(padstack, PCB_LYT_TOP | PCB_LYT_COPPER, 0); break; + } + if (shape == NULL) + continue; + + empty_rect(&r); + add_point_to_rect(&r, padstack->BoundingBox.X1, padstack->BoundingBox.Y1, 0); + add_point_to_rect(&r, padstack->BoundingBox.X2, padstack->BoundingBox.Y2, 0); + if (pin_in_rect(&r, l->s->x, l->s->y, 0) + && pin_in_rect(&r, l->e->x, l->e->y, 0) + && ORIENT(line_orient(l, 0)) == pstk_orient(padstack)) { + dprintf + ("padcleaner %#mD-%#mD vs line %#mD-%#mD %#mS\n", + padstack->BoundingBox.X1, padstack->BoundingBox.Y1, padstack->BoundingBox.X2, padstack->BoundingBox.Y2, + l->s->x, l->s->y, l->e->x, l->e->y, l->line->Thickness); + remove_line(l); + goto next_line; + } + } + PCB_END_LOOP; + next_line:; + } +} + +static void padcleaner(void) +{ + padcleaner_(PCB->Data); + PCB_SUBC_LOOP(PCB->Data); { + padcleaner_(subc->data); + } PCB_END_LOOP; +} + + +static void grok_layer_groups() +{ + int i, j, f; + pcb_layer_stack_t *l = &(PCB->LayerGroups); + + solder_layer = component_layer = -1; + for (i = 0; i < pcb_max_layer; i++) { + layer_type[i] = 0; + layer_groupings[i] = 0; + } + for (i = 0; i < pcb_max_group(PCB); i++) { + f = 0; + for (j = 0; j < l->grp[i].len; j++) { + unsigned int lflg = pcb_layer_flags(PCB, l->grp[i].lid[j]); + if (lflg & PCB_LYT_BOTTOM) + f |= LT_SOLDER; + if (lflg & PCB_LYT_TOP) + f |= LT_COMPONENT; + } + for (j = 0; j < l->grp[i].len; j++) { + if (l->grp[i].lid[j] < pcb_max_layer) { + layer_type[l->grp[i].lid[j]] |= f; + layer_groupings[l->grp[i].lid[j]] = i; + if (solder_layer == -1 && f == LT_SOLDER) + solder_layer = l->grp[i].lid[j]; + if (component_layer == -1 && f == LT_COMPONENT) + component_layer = l->grp[i].lid[j]; + } + } + } +} + +static const char pcb_acts_DJopt[] = "djopt(debumpify|unjaggy|simple|vianudge|viatrim|orthopull)\n" "djopt(auto) - all of the above\n" "djopt(miter)"; +static const char pcb_acth_DJopt[] = "Perform various optimizations on the current board."; +/* DOC: djopt.html */ +static fgw_error_t pcb_act_DJopt(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + const char *arg = NULL; + int layn, saved = 0; + corner_s *c; + + PCB_ACT_MAY_CONVARG(1, FGW_STR, DJopt, arg = argv[1].val.str); + +#ifdef ENDIF + SwitchDrawingWindow(PCB->Zoom, Output.drawing_area->window, conf_core.editor.show_solder_side, pcb_false); +#endif + + pcb_event(PCB_EVENT_BUSY, NULL); + + lines = 0; + corners = 0; + + grok_layer_groups(); + + PCB_SUBC_LOOP(PCB->Data); + PCB_PADSTACK_LOOP(subc->data); + { + pcb_pstk_proto_t *proto; + proto = pcb_pstk_get_proto(padstack); + if (proto == NULL) + continue; + + c = find_corner(padstack->x, padstack->y, -1); + if (!PCB_PSTK_PROTO_CUTS(proto)) + c->pad = padstack; + else + c->pin = padstack; + } + PCB_END_LOOP; + PCB_END_LOOP; + + PCB_PADSTACK_LOOP(PCB->Data); + /* hace don't mess with vias that have thermals */ + /* but then again don't bump into them if (!PCB_FLAG_TEST(ALLTHERMFLAGS, via)) */ + { + c = find_corner(padstack->x, padstack->y, -1); + c->via = padstack; + } + PCB_END_LOOP; + + check(0, 0); + + if (PCB_NSTRCMP(arg, "splitlines") == 0) { + if (canonicalize_lines()) + pcb_undo_inc_serial(); + return 0; + } + + for (layn = 0; layn < pcb_max_layer; layn++) { + pcb_layer_t *layer = LAYER_PTR(layn); + + if (!(pcb_layer_flags(PCB, layn) & PCB_LYT_COPPER)) + continue; + + PCB_LINE_LOOP(layer); + { + line_s *ls; + + if (conf_djopt.plugins.djopt.auto_only && !autorouted(line)) + continue; + + if (line->Point1.X == line->Point2.X && line->Point1.Y == line->Point2.Y) { + pcb_line_destroy(layer, line); + continue; + } + + ls = (line_s *) malloc(sizeof(line_s)); + ls->next = lines; + lines = ls; + ls->is_pad = 0; + ls->s = find_corner(line->Point1.X, line->Point1.Y, layn); + ls->e = find_corner(line->Point2.X, line->Point2.Y, layn); + ls->line = line; + add_line_to_corner(ls, ls->s); + add_line_to_corner(ls, ls->e); + ls->layer = layn; + } + PCB_END_LOOP; + } + + check(0, 0); + pinsnap(); + canonicalize_lines(); + check(0, 0); + classify_nets(); + /*dump_all(); */ + check(0, 0); + + if (PCB_NSTRCMP(arg, "debumpify") == 0) + saved += debumpify(); + else if (PCB_NSTRCMP(arg, "unjaggy") == 0) + saved += unjaggy(); + else if (PCB_NSTRCMP(arg, "simple") == 0) + saved += simple_optimizations(); + else if (PCB_NSTRCMP(arg, "vianudge") == 0) + saved += vianudge(); + else if (PCB_NSTRCMP(arg, "viatrim") == 0) + saved += viatrim(); + else if (PCB_NSTRCMP(arg, "orthopull") == 0) + saved += orthopull(); + else if (PCB_NSTRCMP(arg, "auto") == 0) + saved += automagic(); + else if (PCB_NSTRCMP(arg, "miter") == 0) + saved += miter(); + else { + printf("unknown command: %s\n", arg); + return 1; + } + + padcleaner(); + + check(0, 0); + if (saved) + pcb_undo_inc_serial(); + + PCB_ACT_IRES(0); + return 0; +} + +pcb_action_t djopt_action_list[] = { + {"djopt", pcb_act_DJopt, pcb_acth_DJopt, pcb_acts_DJopt} +}; + +PCB_REGISTER_ACTIONS(djopt_action_list, djopt_cookie) + +int pplg_check_ver_djopt(int ver_needed) { return 0; } + +void pplg_uninit_djopt(void) +{ + pcb_remove_actions_by_cookie(djopt_cookie); + conf_unreg_fields("plugins/djopt/"); +} + +#include "dolists.h" +int pplg_init_djopt(void) +{ + PCB_API_CHK_VER; + +#define conf_reg(field,isarray,type_name,cpath,cname,desc,flags) \ + conf_reg_field(conf_djopt, field,isarray,type_name,cpath,cname,desc,flags); +#include "djopt_conf_fields.h" + + PCB_REGISTER_ACTIONS(djopt_action_list, djopt_cookie) + return 0; +} Index: tags/2.1.2/src_plugins/djopt/djopt.h =================================================================== --- tags/2.1.2/src_plugins/djopt/djopt.h (nonexistent) +++ tags/2.1.2/src_plugins/djopt/djopt.h (revision 24813) @@ -0,0 +1,41 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 2003 DJ Delorie + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + * + * Old contact info: + * DJ Delorie, 334 North Road, Deerfield NH 03037-1110, USA + * dj@delorie.com + * + */ + +#ifndef PCB_DJOPT_H +#define PCB_DJOPT_H + +#include "config.h" + +fgw_error_t pcb_act_DJopt(int, char **, pcb_coord_t, pcb_coord_t); +int djopt_set_auto_only(int, char **, pcb_coord_t, pcb_coord_t); +#endif Index: tags/2.1.2/src_plugins/djopt/djopt.pup =================================================================== --- tags/2.1.2/src_plugins/djopt/djopt.pup (nonexistent) +++ tags/2.1.2/src_plugins/djopt/djopt.pup (revision 24813) @@ -0,0 +1,7 @@ +$class feature +$short djopt board optimization +$long Various board optimization algorithms. +$package extra +$state works +default buildin +autoload 1 Index: tags/2.1.2/src_plugins/djopt/djopt_conf.h =================================================================== --- tags/2.1.2/src_plugins/djopt/djopt_conf.h (nonexistent) +++ tags/2.1.2/src_plugins/djopt/djopt_conf.h (revision 24813) @@ -0,0 +1,14 @@ +#ifndef PCB_DJOPT_CONF_H +#define PCB_DJOPT_CONF_H + +#include "conf.h" + +typedef struct { + const struct plugins { + const struct djopt { + CFT_BOOLEAN auto_only; /* Operate on autorouted tracks only */ + } djopt; + } plugins; +} conf_djopt_t; + +#endif Index: tags/2.1.2/src_plugins/draw_csect/Makefile =================================================================== --- tags/2.1.2/src_plugins/draw_csect/Makefile (nonexistent) +++ tags/2.1.2/src_plugins/draw_csect/Makefile (revision 24813) @@ -0,0 +1,6 @@ +all: + cd ../../src && $(MAKE) mod_draw_csect + +clean: + rm *.o *.so 2>/dev/null ; true + Index: tags/2.1.2/src_plugins/draw_csect/Plug.tmpasm =================================================================== --- tags/2.1.2/src_plugins/draw_csect/Plug.tmpasm (nonexistent) +++ tags/2.1.2/src_plugins/draw_csect/Plug.tmpasm (revision 24813) @@ -0,0 +1,10 @@ +put /local/pcb/mod {draw_csect} +append /local/pcb/mod/OBJS [@ + $(PLUGDIR)/draw_csect/draw_csect.o +@] + +switch /local/pcb/draw_csect/controls + case {buildin} include /local/pcb/tmpasm/buildin; end; + case {plugin} include /local/pcb/tmpasm/plugin; end; + case {disable} include /local/pcb/tmpasm/disable; end; +end Index: tags/2.1.2/src_plugins/draw_csect/draw_csect.c =================================================================== --- tags/2.1.2/src_plugins/draw_csect/draw_csect.c (nonexistent) +++ tags/2.1.2/src_plugins/draw_csect/draw_csect.c (revision 24813) @@ -0,0 +1,958 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2016 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +/* draw cross section */ +#include "config.h" + + +#include "board.h" +#include "data.h" +#include "draw.h" +#include "plugins.h" +#include "stub_draw.h" +#include "compat_misc.h" +#include "actions.h" +#include "event.h" +#include "layer_vis.h" + +#include "obj_text_draw.h" +#include "obj_line_draw.h" + +extern pcb_layergrp_id_t pcb_actd_EditGroup_gid; + +static const char *COLOR_ANNOT_ = "#000000"; +static const char *COLOR_BG_ = "#f0f0f0"; + +static const char *COLOR_COPPER_ = "#C05020"; +static const char *COLOR_SUBSTRATE_ = "#E0D090"; +static const char *COLOR_SILK_ = "#000000"; +static const char *COLOR_MASK_ = "#30d030"; +static const char *COLOR_PASTE_ = "#60e0e0"; +static const char *COLOR_MISC_ = "#e0e000"; +static const char *COLOR_OUTLINE_ = "#000000"; + + +static pcb_color_t + COLOR_ANNOT, COLOR_BG, COLOR_COPPER, COLOR_SUBSTRATE, COLOR_SILK, COLOR_MASK, + COLOR_PASTE, COLOR_MISC, COLOR_OUTLINE; + +static pcb_layer_id_t drag_lid = -1; +static pcb_layergrp_id_t drag_gid = -1, drag_gid_subst = -1; + +#define GROUP_WIDTH_MM 75 + +/* Draw a text at x;y sized scale percentage */ +static pcb_text_t *dtext(int x, int y, int scale, int dir, const char *txt) +{ + static pcb_text_t t; + + memset(&t, 0, sizeof(t)); + + t.X = PCB_MM_TO_COORD(x); + t.Y = PCB_MM_TO_COORD(y); + t.TextString = (char *)txt; + t.rot = 90.0*dir; + t.Scale = scale; + t.fid = 0; /* use the default font */ + t.Flags = pcb_no_flags(); + pcb_text_draw_(NULL, &t, 0, 0, PCB_TXT_TINY_ACCURATE); + return &t; +} + +/* Draw a text at x;y sized scale percentage */ +static pcb_text_t *dtext_(pcb_coord_t x, pcb_coord_t y, int scale, int dir, const char *txt, pcb_coord_t th) +{ + static pcb_text_t t; + + memset(&t, 0, sizeof(t)); + + t.X = x; + t.Y = y; + t.TextString = (char *)txt; + t.rot = 90.0*dir; + t.Scale = scale; + t.fid = 0; /* use the default font */ + t.Flags = pcb_no_flags(); + pcb_text_draw_(NULL, &t, th, 0, PCB_TXT_TINY_ACCURATE); + return &t; +} + +/* Draw a text at x;y with a background */ +static pcb_text_t *dtext_bg(pcb_hid_gc_t gc, int x, int y, int scale, int dir, const char *txt, const pcb_color_t *bgcolor, const pcb_color_t *fgcolor) +{ + static pcb_text_t t; + + memset(&t, 0, sizeof(t)); + + t.X = PCB_MM_TO_COORD(x); + t.Y = PCB_MM_TO_COORD(y); + t.TextString = (char *)txt; + t.rot = 90.0 * dir; + t.Scale = scale; + t.fid = 0; /* use the default font */ + t.Flags = pcb_no_flags(); + + if (pcb_gui->gui) { /* it is unreadable on black&white and on most exporters */ + pcb_gui->set_color(gc, bgcolor); + pcb_text_draw_(NULL, &t, 1000000, 0, PCB_TXT_TINY_ACCURATE); + } + + pcb_gui->set_color(gc, fgcolor); + pcb_text_draw_(NULL, &t, 0, 0, PCB_TXT_TINY_ACCURATE); + + return &t; +} + +/* draw a line of a specific thickness */ +static void dline(int x1, int y1, int x2, int y2, float thick) +{ + pcb_line_t l; + l.Point1.X = PCB_MM_TO_COORD(x1); + l.Point1.Y = PCB_MM_TO_COORD(y1); + l.Point2.X = PCB_MM_TO_COORD(x2); + l.Point2.Y = PCB_MM_TO_COORD(y2); + l.Thickness = PCB_MM_TO_COORD(thick); + if (l.Thickness == 0) + l.Thickness = 1; + pcb_line_draw_(NULL, &l, 0); +} + +/* draw a line of a specific thickness */ +static void dline_(pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2, float thick) +{ + pcb_line_t l; + l.Point1.X = x1; + l.Point1.Y = y1; + l.Point2.X = x2; + l.Point2.Y = y2; + l.Thickness = PCB_MM_TO_COORD(thick); + if (l.Thickness == 0) + l.Thickness = 1; + pcb_line_draw_(NULL, &l, 0); +} + + +/* draw a line clipped with two imaginary vertical lines at cx1 and cx2 */ +static void dline_vclip(int x1, int y1, int x2, int y2, float thick, int cx1, int cx2) +{ + if (cx2 < cx1) { /* make sure cx2 > cx1 */ + int tmp; + tmp = cx1; + cx1 = cx2; + cx2 = tmp; + } + + if (x2 == x1) { /* do not clip vertical lines */ + if ((x1 >= cx1) && (x1 <= cx2)) + dline(x1, y1, x2, y2, thick); + return; + } + + if (x2 < x1) { /* make sure x2 > x1 */ + int tmp; + tmp = x1; + x1 = x2; + x2 = tmp; + tmp = y1; + y1 = y2; + y2 = tmp; + } + + /* clip */ + if (x2 > cx2) { + y2 = (double)(cx2 - x1) / (double)(x2 - x1) * (double)(y2 - y1) + y1; + x2 = cx2; + } + if (x1 < cx1) { + y1 = (double)(cx1 - x1) / (double)(x2 - x1) * (double)(y2 - y1) + y1; + x1 = cx1; + } + + dline(x1, y1, x2, y2, thick); +} + + +/* Draw a 45-deg hactched box wihtout the rectangle; + if step > 0 use \ hatching, else use / */ +static void hatch_box(int x1, int y1, int x2, int y2, float thick, int step) +{ + int n, h = y2 - y1; + + if (step > 0) + for(n = x1 - h; n <= x2; n += step) + dline_vclip(n, y1, n+h, y2, thick, x1, x2); + else + for(n = x2; n >= x1-h; n += step) + dline_vclip(n+h, y1, n, y2, thick, x1, x2); +} + +enum { + OMIT_NONE = 0, + OMIT_TOP = 1, + OMIT_BOTTOM = 2, + OMIT_LEFT = 4, + OMIT_RIGHT = 8, + OMIT_ALL = 1|2|4|8 +}; + +/* draw a hatched rectangle; to turn off hatching in a directon set the + corresponding step to 0 */ +static void dhrect(int x1, int y1, int x2, int y2, float thick_rect, float thick_hatch, int step_fwd, int step_back, unsigned omit) +{ + if (!(omit & OMIT_TOP)) + dline(x1, y1, x2, y1, thick_rect); + if (!(omit & OMIT_RIGHT)) + dline(x2, y1, x2, y2, thick_rect); + if (!(omit & OMIT_BOTTOM)) + dline(x1, y2, x2, y2, thick_rect); + if (!(omit & OMIT_LEFT)) + dline(x1, y1, x1, y2, thick_rect); + + if (step_fwd > 0) + hatch_box(x1, y1, x2, y2, thick_hatch, +step_fwd); + + if (step_back > 0) + hatch_box(x1, y1, x2, y2, thick_hatch, -step_back); +} + +static pcb_box_t btn_addgrp, btn_delgrp, btn_addlayer, btn_dellayer, btn_addoutline; +static pcb_box_t layer_crd[PCB_MAX_LAYER]; +static pcb_box_t group_crd[PCB_MAX_LAYERGRP]; +static pcb_box_t outline_crd; +static char layer_valid[PCB_MAX_LAYER]; +static char group_valid[PCB_MAX_LAYERGRP]; +static char outline_valid; + +static void reg_layer_coords(pcb_layer_id_t lid, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2) +{ + if ((lid < 0) || (lid >= PCB_MAX_LAYER)) + return; + layer_crd[lid].X1 = x1; + layer_crd[lid].Y1 = y1; + layer_crd[lid].X2 = x2; + layer_crd[lid].Y2 = y2; + layer_valid[lid] = 1; +} + +static void reg_group_coords(pcb_layergrp_id_t gid, pcb_coord_t y1, pcb_coord_t y2) +{ + if ((gid < 0) || (gid >= PCB_MAX_LAYER)) + return; + group_crd[gid].Y1 = y1; + group_crd[gid].Y2 = y2; + group_valid[gid] = 1; +} + +static void reg_outline_coords(pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2) +{ + outline_crd.X1 = x1; + outline_crd.Y1 = y1; + outline_crd.X2 = x2; + outline_crd.Y2 = y2; + outline_valid = 1; +} + +static void reset_layer_coords(void) +{ + memset(layer_valid, 0, sizeof(layer_valid)); + memset(group_valid, 0, sizeof(group_valid)); + outline_valid = 0; +} + +static pcb_layer_id_t get_layer_coords(pcb_coord_t x, pcb_coord_t y) +{ + pcb_layer_id_t n; + + for(n = 0; n < PCB_MAX_LAYER; n++) { + if (!layer_valid[n]) continue; + if ((layer_crd[n].X1 <= x) && (layer_crd[n].Y1 <= y) && + (layer_crd[n].X2 >= x) && (layer_crd[n].Y2 >= y)) + return n; + } + return -1; +} + +static pcb_layergrp_id_t get_group_coords(pcb_coord_t y, pcb_coord_t *y1, pcb_coord_t *y2) +{ + pcb_layergrp_id_t n; + + for(n = 0; n < PCB_MAX_LAYERGRP; n++) { + if (!group_valid[n]) continue; + if ((group_crd[n].Y1 <= y) && (group_crd[n].Y2 >= y)) { + *y1 = group_crd[n].Y1; + *y2 = group_crd[n].Y2; + return n; + } + } + return -1; +} + +static pcb_coord_t create_button(pcb_hid_gc_t gc, int x, int y, const char *label, pcb_box_t *box) +{ + pcb_text_t *t; + t = dtext_bg(gc, x, y, 200, 0, label, &COLOR_BG, &COLOR_ANNOT); + pcb_text_bbox(pcb_font(PCB, 0, 1), t); + dhrect(PCB_COORD_TO_MM(t->BoundingBox.X1), y, PCB_COORD_TO_MM(t->BoundingBox.X2)+1, y+4, 0.25, 0, 0, 0, OMIT_NONE); + box->X1 = t->BoundingBox.X1; + box->Y1 = PCB_MM_TO_COORD(y); + box->X2 = t->BoundingBox.X2+PCB_MM_TO_COORD(1); + box->Y2 = PCB_MM_TO_COORD(y+4); + return PCB_COORD_TO_MM(box->X2); +} + +static int is_button(int x, int y, const pcb_box_t *box) +{ + return (x >= box->X1) && (x <= box->X2) && (y >= box->Y1) && (y <= box->Y2); +} + +static pcb_hid_gc_t csect_gc; + +static pcb_coord_t ox, oy, cx, cy; +static int drag_addgrp, drag_delgrp, drag_addlayer, drag_dellayer, drag_addoutline; +static pcb_layergrp_id_t gactive = -1; +static pcb_layergrp_id_t outline_gactive = -1; +static pcb_layer_id_t lactive = -1; +int lactive_idx = -1; + +/* true if we are dragging somehting */ +#define DRAGGING ((drag_lid >= 0) || (drag_addgrp | drag_delgrp | drag_addlayer | drag_dellayer) || (drag_gid >= 0)) + +typedef enum { + MARK_GRP_FRAME, + MARK_GRP_MIDDLE, + MARK_GRP_TOP +} mark_grp_loc_t; + +static void mark_grp(pcb_coord_t y, unsigned int accept_mask, mark_grp_loc_t loc) +{ + pcb_coord_t y1, y2, x0 = -PCB_MM_TO_COORD(5); + pcb_layergrp_id_t g; + + g = get_group_coords(y, &y1, &y2); + + if ((g >= 0) && ((pcb_layergrp_flags(PCB, g) & accept_mask) & accept_mask)) { + gactive = g; + switch(loc) { + case MARK_GRP_FRAME: + dline_(x0, y1, PCB_MM_TO_COORD(200), y1, 0.1); + dline_(x0, y2, PCB_MM_TO_COORD(200), y2, 0.1); + break; + case MARK_GRP_MIDDLE: + dline_(x0, (y1+y2)/2, PCB_MM_TO_COORD(200), (y1+y2)/2, 0.1); + break; + case MARK_GRP_TOP: + dline_(x0, y1, PCB_MM_TO_COORD(200), y1, 0.1); + break; + } + } + else + gactive = -1; +} + +static void mark_outline_grp(pcb_coord_t x, pcb_coord_t y, pcb_layergrp_id_t gid) +{ + if (outline_valid && + (outline_crd.X1 <= x) && (outline_crd.Y1 <= y) && + (outline_crd.X2 >= x) && (outline_crd.Y2 >= y)) { + outline_gactive = gid; + } + else + outline_gactive = -1; +} + +static void mark_layer(pcb_coord_t x, pcb_coord_t y) +{ + lactive = get_layer_coords(x, y); + if (lactive >= 0) { + dhrect( + PCB_COORD_TO_MM(layer_crd[lactive].X1)-1, PCB_COORD_TO_MM(layer_crd[lactive].Y1)-1, + PCB_COORD_TO_MM(layer_crd[lactive].X2)+1, PCB_COORD_TO_MM(layer_crd[lactive].Y2)+1, + 0.1, 0.1, 3, 3, 0 + ); + } +} + +static void mark_layer_order(pcb_coord_t x) +{ + pcb_layergrp_t *g; + pcb_coord_t tx, ty1, ty2; + lactive_idx = -1; + + if ((gactive < 0) || (PCB->LayerGroups.grp[gactive].len < 1)) + return; + + g = &PCB->LayerGroups.grp[gactive]; + + tx = layer_crd[g->lid[0]].X1 - PCB_MM_TO_COORD(1.5); + ty1 = layer_crd[g->lid[0]].Y1; + ty2 = layer_crd[g->lid[0]].Y2; + + for(lactive_idx = g->len-1; lactive_idx >= 0; lactive_idx--) { + pcb_layer_id_t lid = g->lid[lactive_idx]; + if (x > (layer_crd[lid].X1 + layer_crd[lid].X2)/2) { + tx = layer_crd[lid].X2; + break; + } + } + dline_(tx, ty1-PCB_MM_TO_COORD(1.5), tx-PCB_MM_TO_COORD(0.75), ty2+PCB_MM_TO_COORD(1.5), 0.1); + dline_(tx, ty1-PCB_MM_TO_COORD(1.5), tx+PCB_MM_TO_COORD(0.75), ty2+PCB_MM_TO_COORD(1.5), 0.1); + lactive_idx++; +} + +static void draw_hover_label(const char *str) +{ + int x0 = PCB_MM_TO_COORD(2.5); /* compensate for the mouse cursor (sort of random) */ + dtext_(cx+x0, cy, 250, 0, str, PCB_MM_TO_COORD(0.01)); +} + +/* Draw the cross-section layer */ +static void draw_csect(pcb_hid_gc_t gc, const pcb_hid_expose_ctx_t *e) +{ + pcb_layergrp_id_t gid, outline_gid = -1; + int ystart = 10, x, y, last_copper_step = 5; + + reset_layer_coords(); + csect_gc = gc; + + pcb_gui->set_color(gc, &COLOR_ANNOT); + dtext(0, 0, 500, 0, "Board cross section"); + + /* draw physical layers */ + y = ystart; + for(gid = 0; gid < pcb_max_group(PCB); gid++) { + int i, stepf = 0, stepb = 0, th; + pcb_layergrp_t *g = PCB->LayerGroups.grp + gid; + const pcb_color_t *color; + + if ((!g->valid) || (gid == drag_gid) || (gid == drag_gid_subst)) + continue; + else if (g->ltype & PCB_LYT_COPPER) { + last_copper_step = -last_copper_step; + if (last_copper_step > 0) + stepf = last_copper_step; + else + stepb = -last_copper_step; + th = 5; + color = &COLOR_COPPER; + } + else if (g->ltype & PCB_LYT_SUBSTRATE) { + stepf = stepb = 7; + th = 10; + color = &COLOR_SUBSTRATE; + } + else if (g->ltype & PCB_LYT_SILK) { + th = 5; + color = &COLOR_SILK; + stepb = 3; + } + else if (g->ltype & PCB_LYT_MASK) { + th = 5; + color = &COLOR_MASK; + stepb = 9; + } + else if (g->ltype & PCB_LYT_PASTE) { + th = 5; + color = &COLOR_PASTE; + stepf = 9; + } + else if (g->ltype & PCB_LYT_MISC) { + th = 5; + color = &COLOR_MISC; + stepf = 3; + } + else if (g->ltype & PCB_LYT_BOUNDARY) { +TODO("layer: handle multiple outline layers") + outline_gid = gid; + continue; + } + else + continue; + + pcb_gui->set_color(gc, color); + dhrect(0, y, GROUP_WIDTH_MM, y+th, 1, 0.5, stepf, stepb, OMIT_LEFT | OMIT_RIGHT); + dtext_bg(gc, 5, y, 200, 0, g->name, &COLOR_BG, &COLOR_ANNOT); + reg_group_coords(gid, PCB_MM_TO_COORD(y), PCB_MM_TO_COORD(y+th)); + + + /* draw layer names */ + { + x = GROUP_WIDTH_MM + 3; + for(i = 0; i < g->len; i++) { + pcb_text_t *t; + pcb_layer_id_t lid = g->lid[i]; + pcb_layer_t *l = &PCB->Data->Layer[lid]; + int redraw_text = 0; + + if (lid == drag_lid) + continue; + t = dtext_bg(gc, x, y, 200, 0, l->name, &COLOR_BG, &l->meta.real.color); + pcb_text_bbox(pcb_font(PCB, 0, 1), t); + if (l->comb & PCB_LYC_SUB) { + dhrect(PCB_COORD_TO_MM(t->BoundingBox.X1), y, PCB_COORD_TO_MM(t->BoundingBox.X2)+1, y+4, 1.2, 0, 0, 0, OMIT_NONE); + redraw_text = 1; + } + + if (redraw_text) + t = dtext_bg(gc, x, y, 200, 0, l->name, &COLOR_BG, &l->meta.real.color); + else + dhrect(PCB_COORD_TO_MM(t->BoundingBox.X1), y, PCB_COORD_TO_MM(t->BoundingBox.X2)+1, y+4, 0.25, 0, 0, 0, OMIT_NONE); + + if (l->comb & PCB_LYC_AUTO) + dhrect(PCB_COORD_TO_MM(t->BoundingBox.X1), y, PCB_COORD_TO_MM(t->BoundingBox.X2)+1, y+4, 0.0, 0, 3, 0, OMIT_ALL); + + reg_layer_coords(lid, t->BoundingBox.X1, PCB_MM_TO_COORD(y), t->BoundingBox.X2+PCB_MM_TO_COORD(1), PCB_MM_TO_COORD(y+4)); + x += PCB_COORD_TO_MM(t->BoundingBox.X2 - t->BoundingBox.X1) + 3; + } + } + + /* increment y */ + y += th + 1; + } + + /* draw global/special layers */ + y+=7; + if (outline_gid >= 0) { + pcb_layergrp_t *g = PCB->LayerGroups.grp + outline_gid; + pcb_text_t *t; + if (g->len > 0) { + pcb_layer_t *l = &PCB->Data->Layer[g->lid[0]]; + pcb_gui->set_color(gc, &l->meta.real.color); + t = dtext_bg(gc, 1, y, 200, 0, l->name, &COLOR_BG, &l->meta.real.color); + pcb_text_bbox(pcb_font(PCB, 0, 1), t); + dhrect(PCB_COORD_TO_MM(t->BoundingBox.X1), y, PCB_COORD_TO_MM(t->BoundingBox.X2)+1, y+4, 1, 0, 0, 0, OMIT_NONE); + dtext_bg(gc, 1, y, 200, 0, l->name, &COLOR_BG, &l->meta.real.color); + reg_layer_coords(g->lid[0], t->BoundingBox.X1, PCB_MM_TO_COORD(y), t->BoundingBox.X2+PCB_MM_TO_COORD(1), PCB_MM_TO_COORD(y+4)); + } + else { + pcb_gui->set_color(gc, &COLOR_OUTLINE); + t = dtext_bg(gc, 1, y, 200, 0, "", &COLOR_BG, &COLOR_OUTLINE); + pcb_text_bbox(pcb_font(PCB, 0, 1), t); + dhrect(PCB_COORD_TO_MM(t->BoundingBox.X1), y, PCB_COORD_TO_MM(t->BoundingBox.X2)+1, y+4, 1, 0, 0, 0, OMIT_NONE); + dtext_bg(gc, 1, y, 200, 0, "", &COLOR_BG, &COLOR_OUTLINE); + } + dline(0, ystart, 0, y+4, 1); + reg_outline_coords(t->BoundingBox.X1, PCB_MM_TO_COORD(y), t->BoundingBox.X2, PCB_MM_TO_COORD(y+4)); + } + else { + create_button(gc, 2, y, "Create outline", &btn_addoutline); + } + + x=30; + x = 2 + create_button(gc, x, y, "Add copper group", &btn_addgrp); + x = 2 + create_button(gc, x, y, "Del copper group", &btn_delgrp); + + x += 2; + x = 2 + create_button(gc, x, y, "Add logical layer", &btn_addlayer); + x = 2 + create_button(gc, x, y, "Del logical layer", &btn_dellayer); + + + if (DRAGGING) { + pcb_gui->set_color(gc, pcb_color_black); + + /* draw the actual operation */ + if (drag_addgrp) { + mark_grp(cy, PCB_LYT_SUBSTRATE, MARK_GRP_MIDDLE); + draw_hover_label("INSERT GRP"); + } + if (drag_delgrp) { + mark_grp(cy, PCB_LYT_COPPER | PCB_LYT_INTERN, MARK_GRP_FRAME); + draw_hover_label("DEL GROUP"); + } + if (drag_addlayer) { + mark_grp(cy, PCB_LYT_COPPER | PCB_LYT_MASK | PCB_LYT_PASTE | PCB_LYT_SILK, MARK_GRP_FRAME); + mark_outline_grp(cx, cy, outline_gid); + draw_hover_label("ADD LAYER"); + } + if (drag_dellayer) { + mark_layer(cx, cy); + draw_hover_label("DEL LAYER"); + } + else if (drag_lid >= 0) { + pcb_layer_t *l = &PCB->Data->Layer[drag_lid]; + draw_hover_label(l->name); + mark_grp(cy, PCB_LYT_COPPER | PCB_LYT_MASK | PCB_LYT_PASTE | PCB_LYT_SILK, MARK_GRP_FRAME); + mark_outline_grp(cx, cy, outline_gid); + mark_layer_order(cx); + } + else if (drag_gid >= 0) { + pcb_layergrp_t *g = &PCB->LayerGroups.grp[drag_gid]; + const char *name = g->name == NULL ? "" : g->name; + draw_hover_label(name); + mark_grp(cy, PCB_LYT_COPPER | PCB_LYT_INTERN, MARK_GRP_TOP); + if (gactive < 0) + mark_grp(cy, PCB_LYT_COPPER | PCB_LYT_BOTTOM, MARK_GRP_TOP); + if (gactive < 0) + mark_grp(cy, PCB_LYT_SUBSTRATE, MARK_GRP_TOP); + } + } +} + +/* Returns 0 if gactive can be removed from its current group */ +static int check_layer_del(pcb_layer_id_t lid) +{ + pcb_layergrp_t *grp; + unsigned int tflg; + + tflg = pcb_layer_flags(PCB, lid); + grp = pcb_get_layergrp(PCB, pcb_layer_get_group(PCB, lid)); + + if (grp == NULL) { + pcb_message(PCB_MSG_ERROR, "Invalid source group.\n"); + return -1; + } + + if ((tflg & PCB_LYT_SILK) && (grp->len == 1)) { + pcb_message(PCB_MSG_ERROR, "Can not remove the last layer of this group because this group must have at least one layer.\n"); + return -1; + } + + return 0; +} + +static void do_move_grp() +{ + unsigned int tflg; + + if ((gactive < 0) || (gactive == drag_gid+1)) + return; + + tflg = pcb_layergrp_flags(PCB, gactive); + + pcb_layergrp_move(PCB, drag_gid, gactive); + + if (drag_gid_subst >= 0) { + if ((drag_gid < drag_gid_subst) && (gactive > drag_gid)) + drag_gid_subst--; /* the move shifted this down one slot */ + + if (gactive < drag_gid_subst) + drag_gid_subst++; /* the move shifted this up one slot */ + + if (tflg & PCB_LYT_COPPER) { + if (tflg & PCB_LYT_BOTTOM) + pcb_layergrp_move(PCB, drag_gid_subst, gactive); + else + pcb_layergrp_move(PCB, drag_gid_subst, gactive+1); + } + else if (tflg & PCB_LYT_SUBSTRATE) { + if (gactive < drag_gid) + pcb_layergrp_move(PCB, drag_gid_subst, gactive); + else + pcb_layergrp_move(PCB, drag_gid_subst, gactive-1); + } + } +} + + +static pcb_bool mouse_csect(pcb_hid_mouse_ev_t kind, pcb_coord_t x, pcb_coord_t y) +{ + pcb_bool res = 0; + pcb_layer_id_t lid; + + switch(kind) { + case PCB_HID_MOUSE_PRESS: + if (is_button(x, y, &btn_addoutline)) { + drag_addoutline = 1; + res = 1; + break; + } + + if (is_button(x, y, &btn_addgrp)) { + drag_addgrp = 1; + res = 1; + break; + } + + if (is_button(x, y, &btn_delgrp)) { + drag_delgrp = 1; + res = 1; + break; + } + + if (is_button(x, y, &btn_addlayer)) { + drag_addlayer = 1; + res = 1; + break; + } + + if (is_button(x, y, &btn_dellayer)) { + drag_dellayer = 1; + res = 1; + break; + } + + drag_lid = get_layer_coords(x, y); + if (drag_lid >= 0) { + ox = x; + oy = y; + res = 1; + break; + } + + if ((x > 0) && (x < PCB_MM_TO_COORD(GROUP_WIDTH_MM))) { + pcb_coord_t tmp; + pcb_layergrp_id_t gid; + gid = get_group_coords(y, &tmp, &tmp); + if ((gid >= 0) && (pcb_layergrp_flags(PCB, gid) & PCB_LYT_COPPER) && (pcb_layergrp_flags(PCB, gid) & PCB_LYT_INTERN)) { + drag_gid = gid; + /* temporary workaround for the restricted setup */ + if (pcb_layergrp_flags(PCB, gid - 1) & PCB_LYT_SUBSTRATE) + drag_gid_subst = gid - 1; + else if ((pcb_layergrp_flags(PCB, gid - 1) & PCB_LYT_BOUNDARY) && (pcb_layergrp_flags(PCB, gid - 2) & PCB_LYT_SUBSTRATE)) + drag_gid_subst = gid - 2; + res = 1; + } + } + break; + case PCB_HID_MOUSE_RELEASE: + if (drag_addoutline) { + if (is_button(x, y, &btn_addoutline)) { + pcb_layergrp_t *g = pcb_get_grp_new_misc(PCB); + g->name = pcb_strdup("global_outline"); + g->ltype = PCB_LYT_BOUNDARY; + g->purpose = pcb_strdup("uroute"); + g->valid = 1; + g->open = 1; + + outline_gactive = pcb_layergrp_id(PCB, g); + pcb_layer_create(PCB, outline_gactive, "outline"); + pcb_event(PCB_EVENT_LAYERS_CHANGED, NULL); + } + drag_addoutline = 0; + gactive = -1; + res = 1; + } + else if (drag_addgrp) { + if (gactive >= 0) { + pcb_layergrp_t *g; + g = pcb_layergrp_insert_after(PCB, gactive); + g->name = NULL; + g->ltype = PCB_LYT_INTERN | PCB_LYT_SUBSTRATE; + g->valid = 1; + g = pcb_layergrp_insert_after(PCB, gactive); + g->name = pcb_strdup("Intern"); + g->ltype = PCB_LYT_INTERN | PCB_LYT_COPPER; + g->valid = 1; + } + drag_addgrp = 0; + gactive = -1; + res = 1; + } + else if (drag_delgrp) { + if (gactive >= 0) { + pcb_layergrp_del(PCB, gactive, 1); + if (pcb_layergrp_flags(PCB, gactive) & PCB_LYT_SUBSTRATE) + pcb_layergrp_del(PCB, gactive, 1); + else if (pcb_layergrp_flags(PCB, gactive-1) & PCB_LYT_SUBSTRATE) + pcb_layergrp_del(PCB, gactive-1, 1); + } + drag_delgrp = 0; + gactive = -1; + res = 1; + } + else if (drag_addlayer) { + if (gactive >= 0) { + pcb_layer_create(PCB, gactive, "New Layer"); + pcb_event(PCB_EVENT_LAYERS_CHANGED, NULL); + } + else if (outline_gactive >= 0 && PCB->LayerGroups.grp[outline_gactive].len == 0) { + pcb_layer_create(PCB, outline_gactive, "outline"); + pcb_event(PCB_EVENT_LAYERS_CHANGED, NULL); + } + drag_addlayer = 0; + gactive = -1; + res = 1; + } + else if (drag_dellayer) { + if (lactive >= 0) { + char tmp[32]; + sprintf(tmp, "%ld", lactive); + pcb_actionl("MoveLayer", tmp, "-1", NULL); + } + drag_dellayer = 0; + lactive = -1; + res = 1; + } + else if (drag_lid >= 0) { + if (gactive >= 0) { + pcb_layer_t *l = &PCB->Data->Layer[drag_lid]; + pcb_layergrp_t *g; + if (l->meta.real.grp == gactive) { /* move within the group */ + int d, s, at; + g = &PCB->LayerGroups.grp[gactive]; + + /* move drag_lid to the end of the list within the group */ + for(s = d = 0; s < g->len; s++) { + if (g->lid[s] != drag_lid) { + g->lid[d] = g->lid[s]; + d++; + } + else + at = s; + } + g->lid[g->len-1] = drag_lid; + if (lactive_idx >= at) /* because lactive_idx was calculated with this layer in the middle */ + lactive_idx--; + goto move_layer_to_its_place; + } + else if (check_layer_del(drag_lid) == 0) { + g = &PCB->LayerGroups.grp[gactive]; + pcb_layer_move_to_group(PCB, drag_lid, gactive); + pcb_message(PCB_MSG_INFO, "moved layer %s to group %d\n", l->name, gactive); + move_layer_to_its_place:; + if (lactive_idx < g->len-1) { + memmove(g->lid + lactive_idx + 1, g->lid + lactive_idx, (g->len - 1 - lactive_idx) * sizeof(pcb_layer_id_t)); + g->lid[lactive_idx] = drag_lid; + } + pcb_event(PCB_EVENT_LAYERS_CHANGED, NULL); + } + } + else if (outline_gactive >= 0 && PCB->LayerGroups.grp[outline_gactive].len == 0) { + pcb_layer_t *l = &PCB->Data->Layer[drag_lid]; + pcb_layer_move_to_group(PCB, drag_lid, outline_gactive); + pcb_message(PCB_MSG_INFO, "moved layer %s to group %d\n", l->name, outline_gactive); + } + else + pcb_message(PCB_MSG_ERROR, "Can not move layer into that layer group\n"); + res = 1; + drag_lid = -1; + gactive = -1; + } + else if (drag_gid > 0) { + do_move_grp(); + res = 1; + drag_gid = -1; + drag_gid_subst = -1; + } + break; + case PCB_HID_MOUSE_MOTION: + cx = x; + cy = y; + res = DRAGGING; + break; + case PCB_HID_MOUSE_POPUP: + lid = get_layer_coords(x, y); + if (lid >= 0) { + pcb_layervis_change_group_vis(lid, 1, 1); + pcb_actionl("Popup", "layer", NULL); + } + else if ((x > 0) && (x < PCB_MM_TO_COORD(GROUP_WIDTH_MM))) { + pcb_coord_t tmp; + pcb_actd_EditGroup_gid = get_group_coords(y, &tmp, &tmp); + if (pcb_actd_EditGroup_gid >= 0) + pcb_actionl("Popup", "group", NULL); + } + break; + + } + return res; +} + + + + +static const char pcb_acts_dump_csect[] = "DumpCsect()"; +static const char pcb_acth_dump_csect[] = "Print the cross-section of the board (layer stack)"; + +static fgw_error_t pcb_act_dump_csect(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + pcb_layergrp_id_t gid; + + for(gid = 0; gid < pcb_max_group(PCB); gid++) { + int i; + const char *type_gfx; + pcb_layergrp_t *g = PCB->LayerGroups.grp + gid; + + if (!g->valid) { + if (g->len <= 0) + continue; + type_gfx = "old"; + } + else if (g->ltype & PCB_LYT_VIRTUAL) continue; + else if (g->ltype & PCB_LYT_COPPER) type_gfx = "===="; + else if (g->ltype & PCB_LYT_SUBSTRATE) type_gfx = "xxxx"; + else if (g->ltype & PCB_LYT_SILK) type_gfx = "silk"; + else if (g->ltype & PCB_LYT_MASK) type_gfx = "mask"; + else if (g->ltype & PCB_LYT_PASTE) type_gfx = "pst."; + else if (g->ltype & PCB_LYT_MISC) type_gfx = "misc"; + else if (g->ltype & PCB_LYT_MECH) type_gfx = "mech"; + else if (g->ltype & PCB_LYT_DOC) type_gfx = "doc."; + else if (g->ltype & PCB_LYT_BOUNDARY) type_gfx = "||||"; + else type_gfx = "????"; + + printf("%s {%ld} %s\n", type_gfx, gid, g->name); + for(i = 0; i < g->len; i++) { + pcb_layer_id_t lid = g->lid[i]; + pcb_layer_t *l = &PCB->Data->Layer[lid]; + printf(" [%ld] %s comb=", lid, l->name); + if (l->comb & PCB_LYC_SUB) printf(" sub"); + if (l->comb & PCB_LYC_AUTO) printf(" auto"); + printf("\n"); + if (l->meta.real.grp != gid) + printf(" *** broken layer-to-group cross reference: %ld\n", l->meta.real.grp); + } + } + PCB_ACT_IRES(0); + return 0; +} + +static const char *draw_csect_cookie = "draw_csect"; + +pcb_action_t draw_csect_action_list[] = { + {"DumpCsect", pcb_act_dump_csect, pcb_acth_dump_csect, pcb_acts_dump_csect} +}; + + +PCB_REGISTER_ACTIONS(draw_csect_action_list, draw_csect_cookie) + +int pplg_check_ver_draw_csect(int ver_needed) { return 0; } + +void pplg_uninit_draw_csect(void) +{ + pcb_remove_actions_by_cookie(draw_csect_cookie); +} + +#include "dolists.h" + +int pplg_init_draw_csect(void) +{ + PCB_API_CHK_VER; + PCB_REGISTER_ACTIONS(draw_csect_action_list, draw_csect_cookie) + + pcb_color_load_str(&COLOR_ANNOT, COLOR_ANNOT_); + pcb_color_load_str(&COLOR_BG, COLOR_BG_); + pcb_color_load_str(&COLOR_COPPER, COLOR_COPPER_); + pcb_color_load_str(&COLOR_SUBSTRATE, COLOR_SUBSTRATE_); + pcb_color_load_str(&COLOR_SILK, COLOR_SILK_); + pcb_color_load_str(&COLOR_MASK, COLOR_MASK_); + pcb_color_load_str(&COLOR_PASTE, COLOR_PASTE_); + pcb_color_load_str(&COLOR_MISC, COLOR_MISC_); + pcb_color_load_str(&COLOR_OUTLINE, COLOR_OUTLINE_); + + pcb_stub_draw_csect = draw_csect; + pcb_stub_draw_csect_mouse_ev = mouse_csect; + + return 0; +} Index: tags/2.1.2/src_plugins/draw_csect/draw_csect.pup =================================================================== --- tags/2.1.2/src_plugins/draw_csect/draw_csect.pup (nonexistent) +++ tags/2.1.2/src_plugins/draw_csect/draw_csect.pup (revision 24813) @@ -0,0 +1,6 @@ +$class feature +$short draw cross-section (layers) +$long Draw cross section and layer map. +$package (core) +$state works +default disable Index: tags/2.1.2/src_plugins/draw_fab/Makefile =================================================================== --- tags/2.1.2/src_plugins/draw_fab/Makefile (nonexistent) +++ tags/2.1.2/src_plugins/draw_fab/Makefile (revision 24813) @@ -0,0 +1,6 @@ +all: + cd ../../src && $(MAKE) mod_draw_fab + +clean: + rm *.o *.so 2>/dev/null ; true + Index: tags/2.1.2/src_plugins/draw_fab/Plug.tmpasm =================================================================== --- tags/2.1.2/src_plugins/draw_fab/Plug.tmpasm (nonexistent) +++ tags/2.1.2/src_plugins/draw_fab/Plug.tmpasm (revision 24813) @@ -0,0 +1,11 @@ +put /local/pcb/mod {draw_fab} +append /local/pcb/mod/OBJS [@ + $(PLUGDIR)/draw_fab/draw_fab.o +@] +put /local/pcb/mod/CONF {$(PLUGDIR)/draw_fab/draw_fab_conf.h} + +switch /local/pcb/draw_fab/controls + case {buildin} include /local/pcb/tmpasm/buildin; end; + case {plugin} include /local/pcb/tmpasm/plugin; end; + case {disable} include /local/pcb/tmpasm/disable; end; +end Index: tags/2.1.2/src_plugins/draw_fab/draw_fab.c =================================================================== --- tags/2.1.2/src_plugins/draw_fab/draw_fab.c (nonexistent) +++ tags/2.1.2/src_plugins/draw_fab/draw_fab.c (revision 24813) @@ -0,0 +1,351 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996, 2003 Thomas Nau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +/* printing routines */ +#include "config.h" + +#include + +#include "board.h" +#include "build_run.h" +#include "compat_misc.h" +#include "data.h" +#include "draw.h" +#include "../report/drill.h" +#include "plugins.h" +#include "stub_draw.h" +#include "draw_fab_conf.h" +#include "conf_core.h" +#include "macro.h" +#include "obj_pstk_inlines.h" +#include "hid_inlines.h" +#include "funchash_core.h" + +#include "obj_text_draw.h" + + +conf_draw_fab_t conf_draw_fab; + +/* --------------------------------------------------------------------------- + * prints a FAB drawing. + */ + +#define TEXT_SIZE PCB_MIL_TO_COORD(150) +#define TEXT_LINE PCB_MIL_TO_COORD(150) +#define DRILL_MARK_SIZE PCB_MIL_TO_COORD(16) +#define FAB_LINE_W PCB_MIL_TO_COORD(8) + +static void fab_line(pcb_hid_gc_t gc, int x1, int y1, int x2, int y2) +{ + pcb_gui->draw_line(gc, x1, y1, x2, y2); +} + +static void fab_circle(pcb_hid_gc_t gc, int x, int y, int r) +{ + pcb_gui->draw_arc(gc, x, y, r, r, 0, 180); + pcb_gui->draw_arc(gc, x, y, r, r, 180, 180); +} + +/* align is 0=left, 1=center, 2=right, add 8 for underline */ +static void text_at(pcb_draw_info_t *info, pcb_hid_gc_t gc, int x, int y, int align, const char *fmt, ...) +{ + char tmp[512]; + int w = 0, i; + pcb_text_t t; + va_list a; + pcb_font_t *font = pcb_font(PCB, 0, 1); + va_start(a, fmt); + vsprintf(tmp, fmt, a); + va_end(a); + memset(&t, 0, sizeof(t)); + t.TextString = tmp; + t.Scale = PCB_COORD_TO_MIL(TEXT_SIZE); /* pcnt of 100mil base height */ + t.Flags = pcb_no_flags(); + t.fid = 0; /* use the default font */ + t.X = x; + t.Y = y; + for (i = 0; tmp[i]; i++) + w += (font->Symbol[(int) tmp[i]].Width + font->Symbol[(int) tmp[i]].Delta); + w = PCB_SCALE_TEXT(w, t.Scale); + t.X -= w * (align & 3) / 2; + if (t.X < 0) + t.X = 0; + pcb_text_draw_(info, &t, 0,0, PCB_TXT_TINY_ACCURATE); + if (align & 8) + fab_line(gc, t.X, + t.Y + PCB_SCALE_TEXT(font->MaxHeight, t.Scale) + PCB_MIL_TO_COORD(10), + t.X + w, t.Y + PCB_SCALE_TEXT(font->MaxHeight, t.Scale) + PCB_MIL_TO_COORD(10)); +} + +/* Y, +, X, circle, square */ +static void drill_sym(pcb_hid_gc_t gc, int idx, int x, int y) +{ + int type = idx % 5; + int size = idx / 5; + int s2 = (size + 1) * DRILL_MARK_SIZE; + int i; + switch (type) { + case 0: /* Y */ ; + fab_line(gc, x, y, x, y + s2); + fab_line(gc, x, y, x + s2 * 13 / 15, y - s2 / 2); + fab_line(gc, x, y, x - s2 * 13 / 15, y - s2 / 2); + for (i = 1; i <= size; i++) + fab_circle(gc, x, y, i * DRILL_MARK_SIZE); + break; + case 1: /* + */ + ; + fab_line(gc, x, y - s2, x, y + s2); + fab_line(gc, x - s2, y, x + s2, y); + for (i = 1; i <= size; i++) { + fab_line(gc, x - i * DRILL_MARK_SIZE, y - i * DRILL_MARK_SIZE, x + i * DRILL_MARK_SIZE, y - i * DRILL_MARK_SIZE); + fab_line(gc, x - i * DRILL_MARK_SIZE, y - i * DRILL_MARK_SIZE, x - i * DRILL_MARK_SIZE, y + i * DRILL_MARK_SIZE); + fab_line(gc, x - i * DRILL_MARK_SIZE, y + i * DRILL_MARK_SIZE, x + i * DRILL_MARK_SIZE, y + i * DRILL_MARK_SIZE); + fab_line(gc, x + i * DRILL_MARK_SIZE, y - i * DRILL_MARK_SIZE, x + i * DRILL_MARK_SIZE, y + i * DRILL_MARK_SIZE); + } + break; + case 2: /* X */ ; + fab_line(gc, x - s2 * 3 / 4, y - s2 * 3 / 4, x + s2 * 3 / 4, y + s2 * 3 / 4); + fab_line(gc, x - s2 * 3 / 4, y + s2 * 3 / 4, x + s2 * 3 / 4, y - s2 * 3 / 4); + for (i = 1; i <= size; i++) { + fab_line(gc, x - i * DRILL_MARK_SIZE, y - i * DRILL_MARK_SIZE, x + i * DRILL_MARK_SIZE, y - i * DRILL_MARK_SIZE); + fab_line(gc, x - i * DRILL_MARK_SIZE, y - i * DRILL_MARK_SIZE, x - i * DRILL_MARK_SIZE, y + i * DRILL_MARK_SIZE); + fab_line(gc, x - i * DRILL_MARK_SIZE, y + i * DRILL_MARK_SIZE, x + i * DRILL_MARK_SIZE, y + i * DRILL_MARK_SIZE); + fab_line(gc, x + i * DRILL_MARK_SIZE, y - i * DRILL_MARK_SIZE, x + i * DRILL_MARK_SIZE, y + i * DRILL_MARK_SIZE); + } + break; + case 3: /* circle */ ; + for (i = 0; i <= size; i++) + fab_circle(gc, x, y, (i + 1) * DRILL_MARK_SIZE - DRILL_MARK_SIZE / 2); + break; + case 4: /* square */ + for (i = 1; i <= size + 1; i++) { + fab_line(gc, x - i * DRILL_MARK_SIZE, y - i * DRILL_MARK_SIZE, x + i * DRILL_MARK_SIZE, y - i * DRILL_MARK_SIZE); + fab_line(gc, x - i * DRILL_MARK_SIZE, y - i * DRILL_MARK_SIZE, x - i * DRILL_MARK_SIZE, y + i * DRILL_MARK_SIZE); + fab_line(gc, x - i * DRILL_MARK_SIZE, y + i * DRILL_MARK_SIZE, x + i * DRILL_MARK_SIZE, y + i * DRILL_MARK_SIZE); + fab_line(gc, x + i * DRILL_MARK_SIZE, y - i * DRILL_MARK_SIZE, x + i * DRILL_MARK_SIZE, y + i * DRILL_MARK_SIZE); + } + break; + } +} + +static int count_drill_lines(pcb_drill_info_t *AllDrills) +{ + int n, ds = 0; + for (n = AllDrills->DrillN - 1; n >= 0; n--) { + pcb_drill_t *drill = &(AllDrills->Drill[n]); + if (drill->PinCount + drill->ViaCount > drill->UnplatedCount) + ds++; + if (drill->UnplatedCount) + ds++; + } + return ds; +} + + +static int DrawFab_overhang(void) +{ + pcb_drill_info_t *AllDrills = drill_get_info(PCB->Data); + int ds = count_drill_lines(AllDrills); + if (ds < 4) + ds = 4; + return (ds + 2) * TEXT_LINE; +} + +static void draw_fab_layer(pcb_draw_info_t *info, pcb_hid_gc_t gc, const pcb_hid_expose_ctx_t *e, pcb_layer_t *layer, int found) +{ + pcb_hid_set_line_width(gc, PCB_MIL_TO_COORD(10)); + PCB_LINE_LOOP(layer); + { + pcb_gui->draw_line(gc, line->Point1.X, line->Point1.Y, line->Point2.X, line->Point2.Y); + } + PCB_END_LOOP; + PCB_ARC_LOOP(layer); + { + pcb_gui->draw_arc(gc, arc->X, arc->Y, arc->Width, arc->Height, arc->StartAngle, arc->Delta); + } + PCB_END_LOOP; + PCB_TEXT_LOOP(layer); + { + pcb_text_draw_(info, text, 0, 0, PCB_TXT_TINY_ACCURATE); + } + PCB_END_LOOP; + if (!found) { + pcb_hid_set_line_width(gc, FAB_LINE_W); + text_at(info, gc, PCB->MaxWidth / 2, PCB->MaxHeight + PCB_MIL_TO_COORD(20), 1, "Board outline is the centerline of this path"); + } +} + +static void DrawFab(pcb_draw_info_t *info, pcb_hid_gc_t gc, const pcb_hid_expose_ctx_t *e) +{ + pcb_drill_info_t *AllDrills; + int i, n, yoff, total_drills = 0, ds = 0, found; + char utcTime[64]; + + AllDrills = drill_get_info(PCB->Data); + if (conf_core.editor.grid_unit->family == PCB_UNIT_IMPERIAL) + drill_round_info(AllDrills, PCB_MIL_TO_COORD(1)); + else + drill_round_info(AllDrills, PCB_MM_TO_COORD(0.01)); + yoff = -TEXT_LINE; + + /* count how many drill description lines will be needed */ + ds = count_drill_lines(AllDrills); + + /* + * When we only have a few drill sizes we need to make sure the + * drill table header doesn't fall on top of the board info + * section. + */ + if (ds < 4) { + yoff -= (4 - ds) * TEXT_LINE; + } + + pcb_hid_set_line_width(gc, FAB_LINE_W); + + for (n = AllDrills->DrillN - 1; n >= 0; n--) { + int plated_sym = -1, unplated_sym = -1; + pcb_drill_t *drill = &(AllDrills->Drill[n]); + if (drill->PinCount + drill->ViaCount > drill->UnplatedCount) + plated_sym = --ds; + if (drill->UnplatedCount) + unplated_sym = --ds; + pcb_gui->set_color(gc, &conf_core.appearance.color.pin); + for (i = 0; i < drill->PinN; i++) { + int unplated = 1; + pcb_coord_t x, y; + assert(drill->hole[i]->type == PCB_OBJ_PSTK); + { + pcb_pstk_t *ps = (pcb_pstk_t *)drill->hole[i]; + pcb_pstk_proto_t *proto = pcb_pstk_get_proto(ps); + unplated = !proto->hplated; + x = ps->x; + y = ps->y; + } + drill_sym(gc, unplated ? unplated_sym : plated_sym, x, y); + } + if (plated_sym != -1) { + drill_sym(gc, plated_sym, TEXT_SIZE, yoff + TEXT_SIZE / 4); + text_at(info, gc, PCB_MIL_TO_COORD(1350), yoff, PCB_MIL_TO_COORD(2), "YES"); + text_at(info, gc, PCB_MIL_TO_COORD(980), yoff, PCB_MIL_TO_COORD(2), "%d", drill->PinCount + drill->ViaCount - drill->UnplatedCount); + + if (unplated_sym != -1) + yoff -= TEXT_LINE; + } + if (unplated_sym != -1) { + drill_sym(gc, unplated_sym, TEXT_SIZE, yoff + TEXT_SIZE / 4); + text_at(info, gc, PCB_MIL_TO_COORD(1400), yoff, PCB_MIL_TO_COORD(2), "NO"); + text_at(info, gc, PCB_MIL_TO_COORD(980), yoff, PCB_MIL_TO_COORD(2), "%d", drill->UnplatedCount); + } + pcb_gui->set_color(gc, &conf_core.appearance.color.element); + if (conf_core.editor.grid_unit->family == PCB_UNIT_IMPERIAL) + text_at(info, gc, PCB_MIL_TO_COORD(450), yoff, PCB_MIL_TO_COORD(2), "%0.3f", PCB_COORD_TO_INCH(drill->DrillSize)); + else + text_at(info, gc, PCB_MIL_TO_COORD(450), yoff, PCB_MIL_TO_COORD(2), "%1.2f", PCB_COORD_TO_MM(drill->DrillSize)); + if (plated_sym != -1 && unplated_sym != -1) { + if (conf_core.editor.grid_unit->family == PCB_UNIT_IMPERIAL) + text_at(info, gc, PCB_MIL_TO_COORD(450), yoff + TEXT_LINE, PCB_MIL_TO_COORD(2), "%0.3f", PCB_COORD_TO_INCH(drill->DrillSize)); + else + text_at(info, gc, PCB_MIL_TO_COORD(450), yoff + TEXT_LINE, PCB_MIL_TO_COORD(2), "%1.2f", PCB_COORD_TO_MM(drill->DrillSize)); + } + yoff -= TEXT_LINE; + total_drills += drill->PinCount; + total_drills += drill->ViaCount; + } + + pcb_gui->set_color(gc, &conf_core.appearance.color.element); + text_at(info, gc, 0, yoff, PCB_MIL_TO_COORD(9), "Symbol"); + if (conf_core.editor.grid_unit->family == PCB_UNIT_IMPERIAL) + text_at(info, gc, PCB_MIL_TO_COORD(410), yoff, PCB_MIL_TO_COORD(9), "Diam. (Inch)"); + else + text_at(info, gc, PCB_MIL_TO_COORD(410), yoff, PCB_MIL_TO_COORD(9), "Diam. (mm)"); + text_at(info, gc, PCB_MIL_TO_COORD(950), yoff, PCB_MIL_TO_COORD(9), "Count"); + text_at(info, gc, PCB_MIL_TO_COORD(1300), yoff, PCB_MIL_TO_COORD(9), "Plated?"); + yoff -= TEXT_LINE; + text_at(info, gc, 0, yoff, 0, + "There are %d different drill sizes used in this layout, %d holes total", AllDrills->DrillN, total_drills); + /* Create a portable timestamp. */ + + if (!conf_draw_fab.plugins.draw_fab.omit_date) + pcb_print_utc(utcTime, sizeof(utcTime), 0); + else + strcpy(utcTime, ""); + + yoff = -TEXT_LINE; + for (found = 0, i = 0; i < pcb_max_layer; i++) { + pcb_layer_t *l = LAYER_PTR(i); + pcb_layer_type_t flags = pcb_layer_flags(PCB, i); + int purpi = pcb_layer_purpose(PCB, i, NULL); + if (PCB_LAYER_IS_ROUTE(flags, purpi) && (!PCB_RTREE_EMPTY(l->line_tree) || !PCB_RTREE_EMPTY(l->arc_tree))) { + draw_fab_layer(info, gc, e, l, found); + found = 1; + } + } + if (!found) { + pcb_hid_set_line_width(gc, PCB_MIL_TO_COORD(10)); + pcb_gui->draw_line(gc, 0, 0, PCB->MaxWidth, 0); + pcb_gui->draw_line(gc, 0, 0, 0, PCB->MaxHeight); + pcb_gui->draw_line(gc, PCB->MaxWidth, 0, PCB->MaxWidth, PCB->MaxHeight); + pcb_gui->draw_line(gc, 0, PCB->MaxHeight, PCB->MaxWidth, PCB->MaxHeight); + /*FPrintOutline (); */ + pcb_hid_set_line_width(gc, FAB_LINE_W); + text_at(info, gc, PCB_MIL_TO_COORD(2000), yoff, 0, + "Maximum Dimensions: %f mils wide, %f mils high", PCB_COORD_TO_MIL(PCB->MaxWidth), PCB_COORD_TO_MIL(PCB->MaxHeight)); + text_at(info, gc, PCB->MaxWidth / 2, PCB->MaxHeight + PCB_MIL_TO_COORD(20), 1, + "Board outline is the centerline of this %f mil" + " rectangle - 0,0 to %f,%f mils", + PCB_COORD_TO_MIL(FAB_LINE_W), PCB_COORD_TO_MIL(PCB->MaxWidth), PCB_COORD_TO_MIL(PCB->MaxHeight)); + } + yoff -= TEXT_LINE; + + text_at(info, gc, PCB_MIL_TO_COORD(2000), yoff, 0, "Date: %s", utcTime); + yoff -= TEXT_LINE; + text_at(info, gc, PCB_MIL_TO_COORD(2000), yoff, 0, "Author: %s", pcb_author()); + yoff -= TEXT_LINE; + text_at(info, gc, PCB_MIL_TO_COORD(2000), yoff, 0, "Title: %s - Fabrication Drawing", PCB_UNKNOWN(PCB->Name)); +} + +int pplg_check_ver_draw_fab(int ver_needed) { return 0; } + +void pplg_uninit_draw_fab(void) +{ + conf_unreg_fields("plugins/draw_fab/"); +} + +int pplg_init_draw_fab(void) +{ + PCB_API_CHK_VER; + pcb_stub_draw_fab = DrawFab; + pcb_stub_draw_fab_overhang = DrawFab_overhang; + +#define conf_reg(field,isarray,type_name,cpath,cname,desc,flags) \ + conf_reg_field(conf_draw_fab, field,isarray,type_name,cpath,cname,desc,flags); +#include "draw_fab_conf_fields.h" + + + return 0; +} Index: tags/2.1.2/src_plugins/draw_fab/draw_fab.pup =================================================================== --- tags/2.1.2/src_plugins/draw_fab/draw_fab.pup (nonexistent) +++ tags/2.1.2/src_plugins/draw_fab/draw_fab.pup (revision 24813) @@ -0,0 +1,10 @@ +$class feature +$short fab layer in some exports +$long Draw the fab layer (for various exporters). +$package (core) +$state works +default buildin + +# for drill.[ch] +dep report +autoload 1 Index: tags/2.1.2/src_plugins/draw_fab/draw_fab_conf.h =================================================================== --- tags/2.1.2/src_plugins/draw_fab/draw_fab_conf.h (nonexistent) +++ tags/2.1.2/src_plugins/draw_fab/draw_fab_conf.h (revision 24813) @@ -0,0 +1,14 @@ +#ifndef PCB_DRAW_FAB_CONF_H +#define PCB_DRAW_FAB_CONF_H + +#include "conf.h" + +typedef struct { + const struct plugins { + const struct draw_fab { + CFT_BOOLEAN omit_date; /* do not draw date (useful for testing) */ + } draw_fab; + } plugins; +} conf_draw_fab_t; + +#endif Index: tags/2.1.2/src_plugins/draw_fontsel/Makefile =================================================================== --- tags/2.1.2/src_plugins/draw_fontsel/Makefile (nonexistent) +++ tags/2.1.2/src_plugins/draw_fontsel/Makefile (revision 24813) @@ -0,0 +1,6 @@ +all: + cd ../../src && $(MAKE) mod_draw_fontsel + +clean: + rm *.o *.so 2>/dev/null ; true + Index: tags/2.1.2/src_plugins/draw_fontsel/Plug.tmpasm =================================================================== --- tags/2.1.2/src_plugins/draw_fontsel/Plug.tmpasm (nonexistent) +++ tags/2.1.2/src_plugins/draw_fontsel/Plug.tmpasm (revision 24813) @@ -0,0 +1,10 @@ +put /local/pcb/mod {draw_fontsel} +append /local/pcb/mod/OBJS [@ + $(PLUGDIR)/draw_fontsel/draw_fontsel.o +@] + +switch /local/pcb/draw_fontsel/controls + case {buildin} include /local/pcb/tmpasm/buildin; end; + case {plugin} include /local/pcb/tmpasm/plugin; end; + case {disable} include /local/pcb/tmpasm/disable; end; +end Index: tags/2.1.2/src_plugins/draw_fontsel/draw_fontsel.c =================================================================== --- tags/2.1.2/src_plugins/draw_fontsel/draw_fontsel.c (nonexistent) +++ tags/2.1.2/src_plugins/draw_fontsel/draw_fontsel.c (revision 24813) @@ -0,0 +1,199 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2017,2018 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +/* printing routines */ +#include "config.h" + +#include + +#include "board.h" +#include "build_run.h" +#include "data.h" +#include "draw.h" +#include "font.h" +#include "actions.h" +#include "plugins.h" +#include "stub_draw.h" +#include "pcb-printf.h" +#include "compat_misc.h" +#include "conf_core.h" + +#include "obj_text.h" +#include "obj_text_draw.h" +#include "obj_line_draw.h" + +static pcb_text_t *dtext(int x, int y, int scale, pcb_font_id_t fid, const char *txt) +{ + static pcb_text_t t; + + t.X = PCB_MM_TO_COORD(x); + t.Y = PCB_MM_TO_COORD(y); + t.TextString = (char *)txt; + t.rot = 0; + t.Scale = scale; + t.fid = fid; + t.Flags = pcb_no_flags(); + pcb_text_draw_(NULL, &t, 0, 0, PCB_TXT_TINY_ACCURATE); + return &t; +} + +/* draw a line of a specific thickness */ +static void dline(int x1, int y1, int x2, int y2, float thick) +{ + pcb_line_t l; + l.Point1.X = PCB_MM_TO_COORD(x1); + l.Point1.Y = PCB_MM_TO_COORD(y1); + l.Point2.X = PCB_MM_TO_COORD(x2); + l.Point2.Y = PCB_MM_TO_COORD(y2); + l.Thickness = PCB_MM_TO_COORD(thick); + pcb_line_draw_(NULL, &l, 0); +} + +static void dchkbox(pcb_hid_gc_t gc, int x0, int y0, int checked) +{ + int w = 2, h = 2; + float th = 0.1, th2 = 0.4; + + pcb_gui->set_color(gc, pcb_color_black); + dline(x0, y0, x0+w, y0, th); + dline(x0+w, y0, x0+w, y0+h, th); + dline(x0+w, y0+h, x0, y0+h, th); + dline(x0, y0+h, x0, y0, th); + if (checked) { + pcb_gui->set_color(gc, pcb_color_red); + dline(x0, y0, x0+w, y0+h, th2); + dline(x0, y0+h, x0+w, y0, th2); + } +} + +#define MAX_FONT 128 +typedef struct { + int y1, y2; + pcb_font_id_t fid; +} font_coord_t; + +font_coord_t font_coord[MAX_FONT]; +int font_coords; + +static void pcb_draw_font(pcb_hid_gc_t gc, pcb_font_t *f, int x, int *y, pcb_text_t *txt) +{ + char buf[256]; + pcb_text_t *t; + const char *nm; + int y_old = *y; + pcb_font_id_t target_fid = (txt == NULL) ? conf_core.design.text_font_id : txt->fid; + + nm = (f->name == NULL) ? "" : f->name; + pcb_snprintf(buf, sizeof(buf), "#%d [abc ABC 123] %s", f->id, nm); + + dchkbox(gc, x-4, *y, (f->id == target_fid)); + + pcb_gui->set_color(gc, pcb_color_black); + t = dtext(x, *y, 200, f->id, buf); + pcb_text_bbox(pcb_font(PCB, f->id, 1), t); + + *y += pcb_round(PCB_COORD_TO_MM(t->BoundingBox.Y2 - t->BoundingBox.Y1) + 0.5); + + if (font_coords < MAX_FONT) { + font_coord[font_coords].y1 = y_old; + font_coord[font_coords].y2 = *y; + font_coord[font_coords].fid = f->id; + font_coords++; + } +} + + +static void pcb_draw_fontsel(pcb_hid_gc_t gc, const pcb_hid_expose_ctx_t *e, pcb_text_t *txt) +{ + int y = 0; + + font_coords = 0; + pcb_draw_font(gc, &PCB->fontkit.dflt, 0, &y, txt); + + if (PCB->fontkit.hash_inited) { + htip_entry_t *e; + for (e = htip_first(&PCB->fontkit.fonts); e; e = htip_next(&PCB->fontkit.fonts, e)) + pcb_draw_font(gc, e->value, 0, &y, txt); + } +} + +static pcb_font_id_t lookup_fid_for_coord(int ymm) +{ + int n; + + for(n = 0; n < font_coords; n++) + if ((ymm >= font_coord[n].y1) && (ymm <= font_coord[n].y2)) + return font_coord[n].fid; + return -1; +} + +static pcb_bool pcb_mouse_fontsel(pcb_hid_mouse_ev_t kind, pcb_coord_t x, pcb_coord_t y, pcb_text_t *txt) +{ + pcb_font_id_t fid; + int ymm; + + switch(kind) { + case PCB_HID_MOUSE_PRESS: + ymm = PCB_COORD_TO_MM(y); + fid = lookup_fid_for_coord(ymm); + if (fid >= 0) { + if (txt == NULL) { + char sval[128]; + sprintf(sval, "%ld", fid); + conf_set(CFR_DESIGN, "design/text_font_id", 0, sval, POL_OVERWRITE); + } + else { + switch(txt->type) { + case PCB_OBJ_TEXT: + pcb_text_set_font(txt, fid); + break; + default: + break; + } + pcb_gui->invalidate_all(); + } + return 1; + } + default: + break; + } + return 0; +} + +int pplg_check_ver_draw_fontsel(int ver_needed) { return 0; } + +void pplg_uninit_draw_fontsel(void) +{ +} + +int pplg_init_draw_fontsel(void) +{ + PCB_API_CHK_VER; + pcb_stub_draw_fontsel = pcb_draw_fontsel; + pcb_stub_draw_fontsel_mouse_ev = pcb_mouse_fontsel; + return 0; +} Index: tags/2.1.2/src_plugins/draw_fontsel/draw_fontsel.pup =================================================================== --- tags/2.1.2/src_plugins/draw_fontsel/draw_fontsel.pup (nonexistent) +++ tags/2.1.2/src_plugins/draw_fontsel/draw_fontsel.pup (revision 24813) @@ -0,0 +1,6 @@ +$class feature +$short font selection GUI +$long Draw the font selector GUI +$package lib-gui +$state works +default disable Index: tags/2.1.2/src_plugins/drc_orig/Makefile =================================================================== --- tags/2.1.2/src_plugins/drc_orig/Makefile (nonexistent) +++ tags/2.1.2/src_plugins/drc_orig/Makefile (revision 24813) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_drc_orig + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/2.1.2/src_plugins/drc_orig/Plug.tmpasm =================================================================== --- tags/2.1.2/src_plugins/drc_orig/Plug.tmpasm (nonexistent) +++ tags/2.1.2/src_plugins/drc_orig/Plug.tmpasm (revision 24813) @@ -0,0 +1,8 @@ +put /local/pcb/mod {drc_orig} +put /local/pcb/mod/OBJS [@ $(PLUGDIR)/drc_orig/drc_orig.o @] + +switch /local/pcb/drc_orig/controls + case {buildin} include /local/pcb/tmpasm/buildin; end; + case {plugin} include /local/pcb/tmpasm/plugin; end; + case {disable} include /local/pcb/tmpasm/disable; end; +end Index: tags/2.1.2/src_plugins/drc_orig/drc_orig.c =================================================================== --- tags/2.1.2/src_plugins/drc_orig/drc_orig.c (nonexistent) +++ tags/2.1.2/src_plugins/drc_orig/drc_orig.c (revision 24813) @@ -0,0 +1,460 @@ +/* + * + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996, 2005 Thomas Nau + * Copyright (C) 2018 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +#include "config.h" + +#include "drc.h" +#include "view.h" +#include "data_it.h" +#include "conf_core.h" +#include "find.h" +#include "event.h" +#include "plugins.h" +#include "layer_vis.h" + +#include "obj_arc_draw.h" +#include "obj_rat_draw.h" +#include "obj_line_draw.h" +#include "obj_text_draw.h" +#include "obj_poly_draw.h" +#include "obj_pstk_draw.h" + +#include "obj_subc_list.h" + +static const char *drc_orig_cookie = "drc_orig"; + +TODO("find: get rid of this global state") +extern pcb_coord_t Bloat; + +/* DRC clearance callback */ +static pcb_r_dir_t drc_callback(pcb_data_t *data, pcb_layer_t *layer, pcb_poly_t *polygon, int type, void *ptr1, void *ptr2, void *user_data) +{ + const char *message; + pcb_view_t *violation; + pcb_view_list_t *lst = user_data; + pcb_line_t *line = (pcb_line_t *)ptr2; + pcb_arc_t *arc = (pcb_arc_t *)ptr2; + pcb_pstk_t *ps = (pcb_pstk_t *)ptr2; + + switch (type) { + case PCB_OBJ_LINE: + if (line->Clearance < 2 * conf_core.design.bloat) { + message = "Line with insufficient clearance inside polygon"; + goto doIsBad; + } + break; + case PCB_OBJ_ARC: + if (arc->Clearance < 2 * conf_core.design.bloat) { + message = "Arc with insufficient clearance inside polygon"; + goto doIsBad; + } + break; + case PCB_OBJ_PSTK: + if (pcb_pstk_drc_check_clearance(ps, polygon, 2 * conf_core.design.bloat) != 0) { + message = "Padstack with insufficient clearance inside polygon"; + goto doIsBad; + } + break; + default: + pcb_message(PCB_MSG_ERROR, "hace: Bad Plow object in callback\n"); + } + return PCB_R_DIR_NOT_FOUND; + +doIsBad: + pcb_poly_invalidate_draw(layer, polygon); + pcb_draw_obj((pcb_any_obj_t *)ptr2); + violation = pcb_view_new("short", message, "Circuits that are too close may bridge during imaging, etching,\n" "plating, or soldering processes resulting in a direct short."); + pcb_drc_set_data(violation, NULL, conf_core.design.bloat); + pcb_view_append_obj(violation, 0, (pcb_any_obj_t *)ptr2); + pcb_view_set_bbox_by_objs(PCB->Data, violation); + pcb_view_list_append(lst, violation); + return PCB_R_DIR_NOT_FOUND; +} + +static int drc_text(pcb_view_list_t *lst, pcb_layer_t *layer, pcb_text_t *text, pcb_coord_t min_wid) +{ + pcb_view_t *violation; + + if (text->thickness == 0) + return 0; /* automatic thickness is always valid - ensured by the renderer */ + if (text->thickness < min_wid) { + pcb_text_invalidate_draw(layer, text); + violation = pcb_view_new("thin", "Text thickness is too thin", "Process specifications dictate a minimum feature-width\nthat can reliably be reproduced"); + pcb_drc_set_data(violation, &text->thickness, min_wid); + pcb_view_append_obj(violation, 0, (pcb_any_obj_t *)text); + pcb_view_set_bbox_by_objs(PCB->Data, violation); + pcb_view_list_append(lst, violation); + } + return 0; +} + +typedef struct { + pcb_find_t fa, fb; + pcb_data_t *data; + pcb_view_list_t *lst; + unsigned fast:1; + unsigned shrunk:1; +} drc_ctx_t; + +/* evaluates to true if obj was marked on list (fa or fb) */ +#define IS_FOUND(obj, list) (PCB_DFLAG_TEST(&(obj->Flags), ctx->list.mark)) + +static int drc_broken_cb(pcb_find_t *fctx, pcb_any_obj_t *new_obj, pcb_any_obj_t *arrived_from, pcb_found_conn_type_t ctype) +{ + pcb_view_t *violation; + drc_ctx_t *ctx = fctx->user_data; + + if (arrived_from == NULL) /* ingore the starting object - it must be marked as we started from the same object in the first search */ + return 0; + + /* broken if new object is not marked in the shrunk search (fa) but + the arrived_from object was marked (so we notify direct breaks only) */ + if (!IS_FOUND(new_obj, fa) && IS_FOUND(arrived_from, fa)) { + + if (ctx->shrunk) { + violation = pcb_view_new("broken", "Potential for broken trace", "Insufficient overlap between objects can lead to broken tracks\ndue to registration errors with old wheel style photo-plotters."); + pcb_drc_set_data(violation, NULL, conf_core.design.shrink); + } + else { + violation = pcb_view_new("short", "Copper areas too close", "Circuits that are too close may bridge during imaging, etching,\nplating, or soldering processes resulting in a direct short."); + pcb_drc_set_data(violation, NULL, conf_core.design.bloat); + } + pcb_view_append_obj(violation, 0, (pcb_any_obj_t *)new_obj); + pcb_view_append_obj(violation, 1, (pcb_any_obj_t *)arrived_from); + pcb_view_set_bbox_by_objs(ctx->data, violation); + pcb_view_list_append(ctx->lst, violation); + return ctx->fast; /* if fast is 1, we are aborting the search, returning the first hit only */ + } + return 0; +} + +/* Check for DRC violations on a single net starting from the pad or pin + sees if the connectivity changes when everything is bloated, or shrunk */ +static pcb_bool DRCFind(pcb_view_list_t *lst, pcb_any_obj_t *from) +{ + drc_ctx_t ctx; + + ctx.fast = 1; + ctx.data = PCB->Data; + ctx.lst = lst; + + memset(&ctx.fa, 0, sizeof(ctx.fa)); + memset(&ctx.fb, 0, sizeof(ctx.fb)); + ctx.fa.user_data = ctx.fb.user_data = &ctx; + ctx.fb.found_cb = drc_broken_cb; + + /* Check for minimal overlap: shrink mark all objects on the net in fa; + restart the search without shrink in fb: if anything new is found, it did + not have enough overlap and shrink disconnected it. */ + if (conf_core.design.shrink != 0) { + ctx.shrunk = 1; + Bloat = -conf_core.design.shrink; + pcb_find_from_obj(&ctx.fa, PCB->Data, from); + Bloat = 0; + pcb_find_from_obj(&ctx.fb, PCB->Data, from); + pcb_find_free(&ctx.fa); + pcb_find_free(&ctx.fb); + } + + /* Check for minimal distance: bloat mark all objects on the net in fa; + restart the search without bloat in fb: if anything new is found, it did + not have a connection without the bloat. */ + if (conf_core.design.bloat != 0) { + ctx.shrunk = 0; + Bloat = 0; + pcb_find_from_obj(&ctx.fa, PCB->Data, from); + Bloat = conf_core.design.bloat; + pcb_find_from_obj(&ctx.fb, PCB->Data, from); + pcb_find_free(&ctx.fa); + pcb_find_free(&ctx.fb); + } + + Bloat = 0; + + return pcb_false; +} + +/* search short/breaks from subcircuit terminals; returns non-zero for cancel */ +static int drc_nets_from_subc_term(pcb_view_list_t *lst) +{ + unsigned long sofar = 0, total = pcb_subclist_length(&PCB->Data->subc); + + PCB_SUBC_LOOP(PCB->Data); + { + pcb_any_obj_t *o; + pcb_data_it_t it; + + if (pcb_hid_progress(sofar, total, "drc_orig: Checking nets from subc terminals...") != 0) + return 1; + for(o = pcb_data_first(&it, subc->data, PCB_OBJ_CLASS_REAL); o != NULL; o = pcb_data_next(&it)) { + if (o->term == NULL) /* only terminals can be starting point of DRC net checks */ + continue; + if (o->parent_type == PCB_PARENT_LAYER) { /* for layer objects, care about the ones on copper layers only */ + pcb_layer_type_t lyt = pcb_layer_flags_(o->parent.layer); + if (!(lyt & PCB_LYT_COPPER)) + continue; + } + DRCFind(lst, o); + } + sofar++; + } + PCB_END_LOOP; + return 0; +} + +/* search short/breaks from non-subc padstacks; returns non-zero for cancel */ +static int drc_nets_from_pstk(pcb_view_list_t *lst) +{ + unsigned long sofar = 0, total = pcb_subclist_length(&PCB->Data->subc); + + PCB_PADSTACK_LOOP(PCB->Data); + { + if (pcb_hid_progress(sofar, total, "drc_orig: Checking nets from subc non-terminals...") != 0) + return 1; + + if ((padstack->term == NULL) && DRCFind(lst, (pcb_any_obj_t *)padstack)) + break; + sofar++; + } + PCB_END_LOOP; + return 0; +} + + +/* text: check minimum widths */ +void drc_all_texts(pcb_view_list_t *lst) +{ + PCB_TEXT_COPPER_LOOP(PCB->Data); + { + if (drc_text(lst, layer, text, conf_core.design.min_wid)) + break; + } + PCB_ENDALL_LOOP; + + PCB_SILK_COPPER_LOOP(PCB->Data); + { + if (drc_text(lst, layer, text, conf_core.design.min_slk)) + break; + } + PCB_ENDALL_LOOP; +} + +/* copper lines: check minimum widths and polygon clearances */ +void drc_copper_lines(pcb_view_list_t *lst) +{ + pcb_view_t *violation; + + PCB_LINE_COPPER_LOOP(PCB->Data); + { + /* check line clearances in polygons */ + pcb_poly_plows(PCB->Data, PCB_OBJ_LINE, layer, line, drc_callback, lst); + if (line->Thickness < conf_core.design.min_wid) { + pcb_line_invalidate_draw(layer, line); + violation = pcb_view_new("thin", "Line width is too thin", "Process specifications dictate a minimum feature-width\nthat can reliably be reproduced"); + pcb_drc_set_data(violation, &line->Thickness, conf_core.design.min_wid); + pcb_view_append_obj(violation, 0, (pcb_any_obj_t *)line); + pcb_view_set_bbox_by_objs(PCB->Data, violation); + pcb_view_list_append(lst, violation); + } + } + PCB_ENDALL_LOOP; +} + +/* copper arcs: check minimum widths and polygon clearances */ +void drc_copper_arcs(pcb_view_list_t *lst) +{ + pcb_view_t *violation; + + PCB_ARC_COPPER_LOOP(PCB->Data); + { + pcb_poly_plows(PCB->Data, PCB_OBJ_ARC, layer, arc, drc_callback, lst); + if (arc->Thickness < conf_core.design.min_wid) { + pcb_arc_invalidate_draw(layer, arc); + violation = pcb_view_new("thin", "Arc width is too thin", "Process specifications dictate a minimum feature-width\nthat can reliably be reproduced"); + pcb_drc_set_data(violation, &arc->Thickness, conf_core.design.min_wid); + pcb_view_append_obj(violation, 0, (pcb_any_obj_t *)arc); + pcb_view_set_bbox_by_objs(PCB->Data, violation); + pcb_view_list_append(lst, violation); + } + } + PCB_ENDALL_LOOP; +} + +/* non-subc padstacks: check minimum ring and polygon clearances */ +void drc_global_pstks(pcb_view_list_t *lst) +{ + pcb_view_t *violation; + + PCB_PADSTACK_LOOP(PCB->Data); + { + pcb_coord_t ring = 0, hole = 0; + pcb_poly_plows(PCB->Data, PCB_OBJ_PSTK, padstack, padstack, drc_callback, lst); + pcb_pstk_drc_check_and_warn(padstack, &ring, &hole); + if ((ring > 0) || (hole > 0)) { + pcb_pstk_invalidate_draw(padstack); + if (ring) { + violation = pcb_view_new("thin", "padstack annular ring too small", "Annular rings that are too small may erode during etching,\nresulting in a broken connection"); + pcb_drc_set_data(violation, &ring, conf_core.design.min_ring); + pcb_view_append_obj(violation, 0, (pcb_any_obj_t *)padstack); + pcb_view_set_bbox_by_objs(PCB->Data, violation); + pcb_view_list_append(lst, violation); + } + if (hole > 0) { + violation = pcb_view_new("drill", "Padstack drill size is too small", "Process rules dictate the minimum drill size which can be used"); + pcb_drc_set_data(violation, &hole, conf_core.design.min_drill); + pcb_view_append_obj(violation, 0, (pcb_any_obj_t *)padstack); + pcb_view_set_bbox_by_objs(PCB->Data, violation); + pcb_view_list_append(lst, violation); + } + } + } + PCB_END_LOOP; +} + +/* check silkscreen minimum widths outside of subcircuits */ +void drc_global_silk_lines(pcb_view_list_t *lst) +{ + pcb_view_t *violation; + +TODO("DRC: need to check text and polygons too!") + PCB_LINE_SILK_LOOP(PCB->Data); + { + if (line->Thickness < conf_core.design.min_slk) { + pcb_line_invalidate_draw(layer, line); + violation = pcb_view_new("thin", "Silk line is too thin", "Process specifications dictate a minimum silkscreen feature-width\nthat can reliably be reproduced"); + pcb_drc_set_data(violation, &line->Thickness, conf_core.design.min_slk); + pcb_view_append_obj(violation, 0, (pcb_any_obj_t *)line); + pcb_view_set_bbox_by_objs(PCB->Data, violation); + pcb_view_list_append(lst, violation); + } + } + PCB_ENDALL_LOOP; +} + +static void drc_beyond_extents(pcb_view_list_t *lst, pcb_data_t *data) +{ + pcb_any_obj_t *o; + pcb_data_it_t it; + pcb_view_t *violation; + + for(o = pcb_data_first(&it, data, PCB_OBJ_CLASS_REAL); o != NULL; o = pcb_data_next(&it)) { + const char *message = NULL; + pcb_coord_t measured, required; + + if (o->BoundingBox.X1 > PCB->MaxWidth) { + message = "Beyond the drawing area, to the right"; + measured = o->BoundingBox.X1; + required = PCB->MaxWidth; + } + else if (o->BoundingBox.Y1 > PCB->MaxHeight) { + message = "Beyond the drawing area, to the bottom"; + measured = o->BoundingBox.Y1; + required = PCB->MaxHeight; + } + else if (o->BoundingBox.X2 < 0) { + message = "Beyond the drawing area, to the left"; + measured = o->BoundingBox.X2; + required = 0; + } + else if (o->BoundingBox.Y2 < 0) { + message = "Beyond the drawing area, to the top"; + measured = o->BoundingBox.Y2; + required = 0; + } + + + if (message != NULL) { + violation = pcb_view_new("beyond", message, "Object hard to edit or export because being outside of the drawing area."); + pcb_drc_set_data(violation, &measured, required); + pcb_view_append_obj(violation, 0, o); + pcb_view_set_bbox_by_objs(PCB->Data, violation); + pcb_view_list_append(lst, violation); + } + } +} + +static void pcb_drc_orig(void *user_data, int argc, pcb_event_arg_t argv[]) +{ + pcb_view_list_t *lst = &pcb_drc_lst; + pcb_view_list_free_fields(lst); + + pcb_layervis_save_stack(); + pcb_layervis_reset_stack(); + pcb_event(PCB_EVENT_LAYERVIS_CHANGED, NULL); + + /* actual tests */ + pcb_hid_progress(0, 0, NULL); + if (drc_nets_from_subc_term(lst) != 0) goto out; + pcb_hid_progress(0, 0, NULL); + if (drc_nets_from_pstk(lst)) goto out; + + pcb_hid_progress(0, 0, NULL); + if (pcb_hid_progress(0, 6, "drc_orig: Checking objects: text")) goto out; + drc_all_texts(lst); + pcb_hid_progress(0, 0, NULL); + if (pcb_hid_progress(1, 6, "drc_orig: Checking objects: line")) goto out; + drc_copper_lines(lst); + pcb_hid_progress(0, 0, NULL); + if (pcb_hid_progress(2, 6, "drc_orig: Checking objects: arc")) goto out; + drc_copper_arcs(lst); + pcb_hid_progress(0, 0, NULL); + if (pcb_hid_progress(3, 6, "drc_orig: Checking objects: padstack")) goto out; + drc_global_pstks(lst); + pcb_hid_progress(0, 0, NULL); + if (pcb_hid_progress(4, 6, "drc_orig: Checking objects: extent")) goto out; + drc_beyond_extents(lst, PCB->Data); + pcb_hid_progress(0, 0, NULL); + if (pcb_hid_progress(5, 6, "drc_orig: Checking objects: silk")) goto out; + drc_global_silk_lines(lst); + + out:; + pcb_hid_progress(0, 0, NULL); + pcb_layervis_restore_stack(); + pcb_event(PCB_EVENT_LAYERVIS_CHANGED, NULL); + pcb_gui->invalidate_all(); +} + + + +int pplg_check_ver_drc_orig(int ver_needed) { return 0; } + +void pplg_uninit_drc_orig(void) +{ + pcb_event_unbind_allcookie(drc_orig_cookie); +} + +#include "dolists.h" +int pplg_init_drc_orig(void) +{ + PCB_API_CHK_VER; + pcb_event_bind(PCB_EVENT_DRC_RUN, pcb_drc_orig, NULL, drc_orig_cookie); + return 0; +} + Index: tags/2.1.2/src_plugins/drc_orig/drc_orig.pup =================================================================== --- tags/2.1.2/src_plugins/drc_orig/drc_orig.pup (nonexistent) +++ tags/2.1.2/src_plugins/drc_orig/drc_orig.pup (revision 24813) @@ -0,0 +1,6 @@ +$class feature +$short the original DRC code +$long A few simple, hardwired Design Rule Checks. +$package (core) +default buildin +autoload 1 Index: tags/2.1.2/src_plugins/expfeat/Makefile =================================================================== --- tags/2.1.2/src_plugins/expfeat/Makefile (nonexistent) +++ tags/2.1.2/src_plugins/expfeat/Makefile (revision 24813) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_expfeat + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/2.1.2/src_plugins/expfeat/Plug.tmpasm =================================================================== --- tags/2.1.2/src_plugins/expfeat/Plug.tmpasm (nonexistent) +++ tags/2.1.2/src_plugins/expfeat/Plug.tmpasm (revision 24813) @@ -0,0 +1,8 @@ +put /local/pcb/mod {expfeat} +put /local/pcb/mod/OBJS [@ $(PLUGDIR)/expfeat/expfeat.o @] + +switch /local/pcb/expfeat/controls + case {buildin} include /local/pcb/tmpasm/buildin; end; + case {plugin} include /local/pcb/tmpasm/plugin; end; + case {disable} include /local/pcb/tmpasm/disable; end; +end Index: tags/2.1.2/src_plugins/expfeat/expfeat.c =================================================================== --- tags/2.1.2/src_plugins/expfeat/expfeat.c (nonexistent) +++ tags/2.1.2/src_plugins/expfeat/expfeat.c (revision 24813) @@ -0,0 +1,71 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2018 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "config.h" +#include "conf.h" +#include "data.h" +#include "change.h" +#include "error.h" +#include "undo.h" +#include "plugins.h" +#include "actions.h" + + +static const char pcb_acts_ExpFeatTmp[] = "ExpFeatTmp(...)"; +static const char pcb_acth_ExpFeatTmp[] = "Experimental Feature Template."; +/* DOC: foobar.html */ +/* (change the name of the above reference to the lowercase version of + your action name and create the document in + doc/user/09_appendix/action_src/) */ +static fgw_error_t pcb_act_ExpFeatTmp(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + pcb_message(PCB_MSG_INFO, "Hello world from expfeat!\n"); + PCB_ACT_IRES(0); + return 0; +} + +static const pcb_action_t expfeat_action_list[] = { + {"ExpFeatTmp", pcb_act_ExpFeatTmp, pcb_acth_ExpFeatTmp, pcb_acts_ExpFeatTmp} +}; + +static const char *expfeat_cookie = "experimental features plugin"; + +PCB_REGISTER_ACTIONS(expfeat_action_list, expfeat_cookie) + +int pplg_check_ver_expfeat(int ver_needed) { return 0; } + +void pplg_uninit_expfeat(void) +{ + pcb_remove_actions_by_cookie(expfeat_cookie); +} + +#include "dolists.h" +int pplg_init_expfeat(void) +{ + PCB_API_CHK_VER; + PCB_REGISTER_ACTIONS(expfeat_action_list, expfeat_cookie) + return 0; +} Index: tags/2.1.2/src_plugins/expfeat/expfeat.pup =================================================================== --- tags/2.1.2/src_plugins/expfeat/expfeat.pup (nonexistent) +++ tags/2.1.2/src_plugins/expfeat/expfeat.pup (revision 24813) @@ -0,0 +1,6 @@ +$class feature +$short experimental features +$long Staging plugin for experimenting with new actions and dialogs before getting them into core or other plugins +$state works +default disable +autoload 1 Index: tags/2.1.2/src_plugins/export_bboard/Makefile =================================================================== --- tags/2.1.2/src_plugins/export_bboard/Makefile (nonexistent) +++ tags/2.1.2/src_plugins/export_bboard/Makefile (revision 24813) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_export_bboard + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/2.1.2/src_plugins/export_bboard/Plug.tmpasm =================================================================== --- tags/2.1.2/src_plugins/export_bboard/Plug.tmpasm (nonexistent) +++ tags/2.1.2/src_plugins/export_bboard/Plug.tmpasm (revision 24813) @@ -0,0 +1,16 @@ +put /local/pcb/mod {export_bboard} +put /local/pcb/mod/OBJS [@ $(PLUGDIR)/export_bboard/bboard.o @] + +switch /local/pcb/export_bboard/controls + case {disable} end; + default + put /local/pcb/mod/CFLAGS /target/libs/gui/cairo/cflags + put /local/pcb/mod/LDFLAGS /target/libs/gui/cairo/ldflags + end +end + +switch /local/pcb/export_bboard/controls + case {buildin} include /local/pcb/tmpasm/buildin; end; + case {plugin} include /local/pcb/tmpasm/plugin; end; + case {disable} include /local/pcb/tmpasm/disable; end; +end Index: tags/2.1.2/src_plugins/export_bboard/bboard.c =================================================================== --- tags/2.1.2/src_plugins/export_bboard/bboard.c (nonexistent) +++ tags/2.1.2/src_plugins/export_bboard/bboard.c (revision 24813) @@ -0,0 +1,640 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * + * Breadboard export HID + * This code is based on the GERBER and OpenSCAD export HID + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "config.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "math_helper.h" +#include "board.h" +#include "config.h" +#include "data.h" +#include "error.h" +#include "buffer.h" +#include "layer.h" +#include "layer_grp.h" +#include "layer_vis.h" +#include "plugins.h" +#include "compat_misc.h" +#include "compat_fs.h" +#include "misc_util.h" +#include "funchash_core.h" +#include "rtree.h" + +#include "hid.h" +#include "hid_attrib.h" +#include "hid_nogui.h" +#include "hid_draw_helpers.h" +#include "hid_init.h" +#include "hid_cam.h" + +#include + +static const char *bboard_cookie = "bboard exporter"; + +static cairo_surface_t *bboard_cairo_sfc; +static cairo_t *bboard_cairo_ctx; +#define ASSERT_CAIRO if ((bboard_cairo_ctx == NULL) || (bboard_cairo_sfc == NULL)) \ + return; + +#define DPI_SCALE 150 + +#define BBEXT ".png" +#define MODELBASE "models" +#define BBOARDBASE "bboard" + +/**************************************************************************************************** +* Breadboard export filter parameters and options +****************************************************************************************************/ + +static pcb_hid_t bboard_hid; + +static struct { + int draw; + int exp; + float z_offset; + int solder; + int component; +} group_data[PCB_MAX_LAYERGRP]; + + +#define HA_bboardfile 0 +#define HA_bgcolor 1 +#define HA_skipsolder 2 +#define HA_antialias 3 + +static pcb_hid_attribute_t bboard_options[] = { +/* +%start-doc options "Breadboard Export" +@ftable @code +@item --bbfile +Name of breadboard image output file. +@end ftable +%end-doc +*/ + { + "bbfile", "Braedboard file name", PCB_HATT_STRING, 0, 0, + { + 0, 0, 0}, 0, 0}, +/* +%start-doc options "Breadboard Export" +@ftable @code +@item --bgcolor +Background color. It can be HTML color code (RRGGBB); if left empty or set to 'transparent', transparent background is used. +@end ftable +%end-doc +*/ + { + "bgcolor", "Background color (rrggbb)", PCB_HATT_STRING, 0, 0, + { + 0, 0, 0}, 0, 0}, +/* +%start-doc options "Breadboard Export" +@ftable @code +@item --skipsolder +The solder layer will be ommited (if set to true) from output. +@end ftable +%end-doc +*/ + { + "skipsolder", "Ignore solder layer", PCB_HATT_BOOL, 0, 0, + { + 1, 0, 0}, 0, 0}, +/* +%start-doc options "Breadboard Export" +@ftable @code +@item --antialias +Connections are antialiased. Antialiasing applies only to wires, models are not antialiased.. +@end ftable +%end-doc +*/ + { + "antialias", "Antialiasing", PCB_HATT_BOOL, 0, 0, + { + 1, 0, 0}, 0, 0}, +}; + +#define NUM_OPTIONS (sizeof(bboard_options)/sizeof(bboard_options[0])) + +static pcb_hid_attr_val_t bboard_values[NUM_OPTIONS]; + +/****************************************************************************************************/ +static const char *bboard_filename = 0; +static const char *bboard_bgcolor = 0; + +pcb_coord_t bboard_scale_coord(pcb_coord_t x) +{ + return ((x * DPI_SCALE / 254 / 10000) + 0) / 10; +} + + +/******************************************* +* Export filter implementation starts here +********************************************/ + +static pcb_hid_attribute_t *bboard_get_export_options(int *n) +{ + if ((PCB != NULL) && (bboard_options[HA_bboardfile].default_val.str_value == NULL)) + pcb_derive_default_filename(PCB->Filename, &bboard_options[HA_bboardfile], ".png"); + + bboard_options[HA_bgcolor].default_val.str_value = pcb_strdup("#FFFFFF"); + + if (n) + *n = NUM_OPTIONS; + return bboard_options; +} + +static int bboard_validate_layer(unsigned long flags, int purpi, int group, int skipsolder) +{ + if ((flags & PCB_LYT_INVIS) || PCB_LAYER_IS_ASSY(flags, purpi) || PCB_LAYER_IS_ROUTE(flags, purpi)) + return 0; + + if (group_data[group].solder && skipsolder) + return 0; + + if (group >= 0 && group < pcb_max_group(PCB)) { + if (!group_data[group].draw) + return 0; + group_data[group].exp = 1; + return 1; + } + else + return 0; +} + +static void bboard_get_layer_color(pcb_layer_t * layer, int *clr_r, int *clr_g, int *clr_b) +{ + char *clr; + unsigned int r, g, b; + + if ((clr = pcb_attribute_get(&(layer->Attributes), "BBoard::LayerColor")) != NULL) { + if (clr[0] == '#') { + if (sscanf(&(clr[1]), "%02x%02x%02x", &r, &g, &b) == 3) + goto ok; + } + } + + r = layer->meta.real.color.r; + g = layer->meta.real.color.g; + b = layer->meta.real.color.b; + + /* default color */ + *clr_r = 0xff; + *clr_g = 0xff; + *clr_b = 0xff; + return; + +ok: + *clr_r = r; + *clr_g = g; + *clr_b = b; + return; +} + + +static void bboard_set_color_cairo(int r, int g, int b) +{ + ASSERT_CAIRO; + + cairo_set_source_rgb(bboard_cairo_ctx, ((float) r) / 255., ((float) g) / 255., ((float) b) / 255.); +} + + +static void bboard_draw_line_cairo(pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2, pcb_coord_t thickness) +{ + ASSERT_CAIRO; + + cairo_set_line_cap(bboard_cairo_ctx, CAIRO_LINE_CAP_ROUND); + + cairo_move_to(bboard_cairo_ctx, bboard_scale_coord(x1), bboard_scale_coord(y1)); + cairo_line_to(bboard_cairo_ctx, bboard_scale_coord(x2), bboard_scale_coord(y2)); + + cairo_set_line_width(bboard_cairo_ctx, bboard_scale_coord(thickness)); + cairo_stroke(bboard_cairo_ctx); +} + +static void bboard_draw_arc_cairo(pcb_coord_t x, pcb_coord_t y, pcb_coord_t w, pcb_coord_t h, pcb_angle_t sa, pcb_angle_t a, pcb_coord_t thickness) +{ + ASSERT_CAIRO; + + cairo_set_line_cap(bboard_cairo_ctx, CAIRO_LINE_CAP_ROUND); + + cairo_save(bboard_cairo_ctx); + cairo_translate(bboard_cairo_ctx, bboard_scale_coord(x), bboard_scale_coord(y)); + cairo_scale(bboard_cairo_ctx, bboard_scale_coord(w), -bboard_scale_coord(h)); + if (a < 0) { + cairo_arc_negative(bboard_cairo_ctx, 0., 0., 1., (sa + 180.) * M_PI / 180., (a + sa + 180.) * M_PI / 180.); + } + else { + cairo_arc(bboard_cairo_ctx, 0., 0., 1., (sa + 180.) * M_PI / 180., (a + sa + 180.) * M_PI / 180.); + } + cairo_restore(bboard_cairo_ctx); + + cairo_set_line_width(bboard_cairo_ctx, bboard_scale_coord(thickness)); + cairo_stroke(bboard_cairo_ctx); +} + +static pcb_bool bboard_init_board_cairo(pcb_coord_t x1, pcb_coord_t y1, const char *color, int antialias) +{ + unsigned int r, g, b; + float tr = 1.; /* background transparency */ + + if (color) { + if (strlen(color) == 0 || !strcmp(color, "transparent")) { + tr = 0.; + r = g = b = 0xff; + } + else { + if ((color[0] != '#') + || sscanf(&(color[1]), "%02x%02x%02x", &r, &g, &b) != 3) { + pcb_message(PCB_MSG_ERROR, "BBExport: Invalid background color \"%s\"", color); + r = g = b = 0xff; + } + + } + } + + bboard_cairo_sfc = NULL; + bboard_cairo_ctx = NULL; + bboard_cairo_sfc = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, bboard_scale_coord(x1), bboard_scale_coord(y1)); + if (bboard_cairo_sfc) { + bboard_cairo_ctx = cairo_create(bboard_cairo_sfc); + if (!bboard_cairo_ctx) { + cairo_surface_destroy(bboard_cairo_sfc); + bboard_cairo_sfc = NULL; + } + + } + + if ((bboard_cairo_ctx != NULL) && (bboard_cairo_sfc != NULL)) { + cairo_set_antialias(bboard_cairo_ctx, (antialias) ? CAIRO_ANTIALIAS_DEFAULT : CAIRO_ANTIALIAS_NONE); + cairo_rectangle(bboard_cairo_ctx, 0, 0, bboard_scale_coord(x1), bboard_scale_coord(y1)); + cairo_set_source_rgba(bboard_cairo_ctx, ((float) r) / 255., ((float) g) / 255., ((float) b) / 255., tr); + cairo_fill(bboard_cairo_ctx); + return 1; + } + + return 0; +} + +static void bboard_finish_board_cairo(void) +{ + ASSERT_CAIRO; + + cairo_surface_write_to_png(bboard_cairo_sfc, bboard_filename); + + cairo_destroy(bboard_cairo_ctx); + cairo_surface_destroy(bboard_cairo_sfc); +} + +static char *bboard_get_model_filename(char *basename, char *value, pcb_bool nested) +{ + char *s; + +/* + s = pcb_concat(pcblibdir, PCB_DIR_SEPARATOR_S, MODELBASE, PCB_DIR_SEPARATOR_S, + BBOARDBASE, PCB_DIR_SEPARATOR_S, basename, (value + && nested) ? + PCB_DIR_SEPARATOR_S : "", (value && nested) ? basename : "", (value) ? "-" : "", (value) ? value : "", BBEXT, NULL); +*/ + s = pcb_strdup("TODO_fn1"); + if (s != NULL) { + if (!pcb_file_readable(s)) { + free(s); + s = NULL; + } + } + return s; +} + + +static int bboard_parse_offset(char *s, pcb_coord_t * ox, pcb_coord_t * oy) +{ + pcb_coord_t xx = 0, yy = 0; + int n = 0, ln = 0; + char val[32]; + + while (sscanf(s, "%30s%n", val, &ln) >= 1) { + switch (n) { + case 0: + xx = pcb_get_value_ex(val, NULL, NULL, NULL, "mm", NULL); + break; + case 1: + yy = pcb_get_value_ex(val, NULL, NULL, NULL, "mm", NULL); + break; + } + s = s + ln; + n++; + } + if (n == 2) { + *ox = xx; + *oy = yy; + return pcb_true; + } + else { + return pcb_false; + } + +} + + +static void bboard_export_element_cairo(pcb_subc_t *subc, pcb_bool onsolder) +{ + cairo_surface_t *sfc; + pcb_coord_t ex, ey; + pcb_coord_t ox = 0, oy = 0; + int w, h; + pcb_angle_t tmp_angle = 0.0; + char *model_angle, *s = 0, *s1, *s2, *fname = NULL; + pcb_bool offset_in_model = pcb_false; + + ASSERT_CAIRO; + + s1 = pcb_attribute_get(&(subc->Attributes), "BBoard::Model"); + if (s1) { + s = pcb_strdup(s1); + if (!s) + return; + + if ((s2 = strchr(s, ' ')) != NULL) { + *s2 = 0; + offset_in_model = bboard_parse_offset(s2 + 1, &ox, &oy); + } +TODO("subc: rewrite") +#if 0 + if (!PCB_EMPTY_STRING_P(PCB_ELEM_NAME_VALUE(element))) { + fname = bboard_get_model_filename(s, PCB_ELEM_NAME_VALUE(element), pcb_true); + if (!fname) + fname = bboard_get_model_filename(s, PCB_ELEM_NAME_VALUE(element), pcb_false); + } +#endif + if (!fname) + fname = bboard_get_model_filename(s, NULL, pcb_false); + + if (s) + free(s); + } + if (!fname) { + /* invalidate offset from BBoard::Model, if such model does not exist */ + offset_in_model = pcb_false; + + s = pcb_attribute_get(&(subc->Attributes), "Footprint::File"); + if (s) { +TODO("subc: rewrite") +#if 0 + if (!PCB_EMPTY_STRING_P(PCB_ELEM_NAME_VALUE(element))) { + fname = bboard_get_model_filename(s, PCB_ELEM_NAME_VALUE(element), pcb_true); + if (!fname) + fname = bboard_get_model_filename(s, PCB_ELEM_NAME_VALUE(element), pcb_false); + } +#endif + if (!fname) + fname = bboard_get_model_filename(s, NULL, pcb_false); + } + } + if (!fname) { +TODO("subc: rewrite") +#if 0 + s = PCB_ELEM_NAME_DESCRIPTION(element); + if (!PCB_EMPTY_STRING_P(PCB_ELEM_NAME_DESCRIPTION(element))) { + if (!PCB_EMPTY_STRING_P(PCB_ELEM_NAME_VALUE(element))) { + fname = bboard_get_model_filename(PCB_ELEM_NAME_DESCRIPTION(element), PCB_ELEM_NAME_VALUE(element), pcb_true); + if (!fname) + fname = bboard_get_model_filename(PCB_ELEM_NAME_DESCRIPTION(element), PCB_ELEM_NAME_VALUE(element), pcb_false); + + } + if (!fname) + fname = bboard_get_model_filename(PCB_ELEM_NAME_DESCRIPTION(element), NULL, pcb_false); + } +#endif + } + + if (!fname) + return; + + sfc = cairo_image_surface_create_from_png(fname); + + free(fname); + + if (sfc) { + w = cairo_image_surface_get_width(sfc); + h = cairo_image_surface_get_height(sfc); + + /* read offest from attribute */ + if (!offset_in_model) { + s = pcb_attribute_get(&(subc->Attributes), "BBoard::Offset"); + + /* Parse values with units... */ + if (s) { + bboard_parse_offset(s, &ox, &oy); + } + } + + { + pcb_coord_t ox = 0, oy = 0; + pcb_subc_get_origin(subc, &ox, &oy); + ex = bboard_scale_coord(ox); + ey = bboard_scale_coord(oy); + } + + cairo_save(bboard_cairo_ctx); + + if ((model_angle = pcb_attribute_get(&(subc->Attributes), "Footprint::RotationTracking")) != NULL) { + sscanf(model_angle, "%lf", &tmp_angle); + } + + + cairo_translate(bboard_cairo_ctx, ex, ey); + if (PCB_FLAG_TEST(PCB_FLAG_ONSOLDER, (subc))) { + cairo_scale(bboard_cairo_ctx, 1, -1); + } + cairo_rotate(bboard_cairo_ctx, -tmp_angle * M_PI / 180.); + cairo_set_source_surface(bboard_cairo_ctx, sfc, bboard_scale_coord(ox) - w / 2, bboard_scale_coord(oy) - h / 2); + cairo_paint(bboard_cairo_ctx); + + cairo_restore(bboard_cairo_ctx); + + cairo_surface_destroy(sfc); + } +} + + +static void bboard_do_export(pcb_hid_attr_val_t * options) +{ + int i; + int clr_r, clr_g, clr_b; + pcb_layer_t *layer; + pcb_layergrp_id_t gtop, gbottom; + + if (!options) { + bboard_get_export_options(0); + for (i = 0; i < NUM_OPTIONS; i++) + bboard_values[i] = bboard_options[i].default_val; + options = bboard_values; + } + bboard_filename = options[HA_bboardfile].str_value; + if (!bboard_filename) + bboard_filename = "unknown.png"; + + bboard_bgcolor = options[HA_bgcolor].str_value; + if (!bboard_bgcolor) + bboard_bgcolor = "FFFFFF"; + + memset(group_data, 0, sizeof(group_data)); + + if (pcb_layergrp_list(PCB, PCB_LYT_COPPER | PCB_LYT_BOTTOM, &gbottom, 1) > 0) + group_data[gbottom].solder = 1; + + if (pcb_layergrp_list(PCB, PCB_LYT_COPPER | PCB_LYT_TOP, >op, 1) > 0) + group_data[gtop].component = 1; + + for (i = 0; i < pcb_max_layer; i++) { + layer = PCB->Data->Layer + i; + if (!PCB_RTREE_EMPTY(layer->line_tree)) + group_data[pcb_layer_get_group(PCB, i)].draw = 1; + } + + bboard_init_board_cairo(PCB->MaxWidth, PCB->MaxHeight, bboard_bgcolor, options[HA_antialias].int_value); + +TODO("subc: rewrite") +#if 0 + /* write out components on solder side */ + PCB_ELEMENT_LOOP(PCB->Data); + if (PCB_FLAG_TEST(PCB_FLAG_ONSOLDER, (element))) { + bboard_export_element_cairo(element, 1); + } + PCB_END_LOOP; + + /* write out components on component side */ + PCB_ELEMENT_LOOP(PCB->Data); + if (!PCB_FLAG_TEST(PCB_FLAG_ONSOLDER, (element))) { + bboard_export_element_cairo(element, 0); + } + PCB_END_LOOP; +#endif + + /* draw all wires from all valid layers */ + for (i = pcb_max_layer; i >= 0; i--) { + unsigned int flg = pcb_layer_flags(PCB, i); + pcb_layergrp_id_t gid; + pcb_layergrp_t *grp; + int purpi; + + if (flg & PCB_LYT_SILK) + continue; + + gid = pcb_layer_get_group(PCB, i); + grp = pcb_get_layergrp(PCB, gid); + if (grp == NULL) + purpi = -1; + else + purpi = grp->purpi; + + if (bboard_validate_layer(flg, purpi, gid, options[HA_skipsolder].int_value)) { + bboard_get_layer_color(&(PCB->Data->Layer[i]), &clr_r, &clr_g, &clr_b); + bboard_set_color_cairo(clr_r, clr_g, clr_b); + PCB_LINE_LOOP(&(PCB->Data->Layer[i])); + { + bboard_draw_line_cairo(line->Point1.X, line->Point1.Y, line->Point2.X, line->Point2.Y, line->Thickness); + } + PCB_END_LOOP; + PCB_ARC_LOOP(&(PCB->Data->Layer[i])); + { +TODO(": remove x1;y1;x2;y2") + bboard_draw_arc_cairo(/*arc->Point1.X, arc->Point1.Y, + arc->Point2.X, arc->Point2.Y,*/ + arc->X, arc->Y, arc->Width, arc->Height, arc->StartAngle, arc->Delta, arc->Thickness); + } + PCB_END_LOOP; + } + } + + bboard_finish_board_cairo(); + +} + +static int bboard_parse_arguments(int *argc, char ***argv) +{ + return pcb_hid_parse_command_line(argc, argv); +} + + +static void bboard_calibrate(double xval, double yval) +{ + fprintf(stderr, "HID error: pcb called unimplemented breaboard function bboard_calibrate.\n"); + abort(); +} + +static void bboard_set_crosshair(pcb_coord_t x, pcb_coord_t y, int action) +{ +} + +static pcb_hid_t bboard_hid; + +int pplg_check_ver_export_bboard(int ver_needed) { return 0; } + +void pplg_uninit_export_bboard(void) +{ + pcb_hid_remove_attributes_by_cookie(bboard_cookie); +} + + +int pplg_init_export_bboard(void) +{ + PCB_API_CHK_VER; + memset(&bboard_hid, 0, sizeof(bboard_hid)); + + pcb_hid_nogui_init(&bboard_hid); + + bboard_hid.struct_size = sizeof(bboard_hid); + bboard_hid.name = "bboard"; + bboard_hid.description = "Breadboard export"; + bboard_hid.exporter = 1; + + bboard_hid.get_export_options = bboard_get_export_options; + bboard_hid.do_export = bboard_do_export; + bboard_hid.parse_arguments = bboard_parse_arguments; + bboard_hid.calibrate = bboard_calibrate; + bboard_hid.set_crosshair = bboard_set_crosshair; + pcb_hid_register_hid(&bboard_hid); + + pcb_hid_register_attributes(bboard_options, sizeof(bboard_options) / sizeof(bboard_options[0]), bboard_cookie, 0); + return 0; +} + Index: tags/2.1.2/src_plugins/export_bboard/export_bboard.pup =================================================================== --- tags/2.1.2/src_plugins/export_bboard/export_bboard.pup (nonexistent) +++ tags/2.1.2/src_plugins/export_bboard/export_bboard.pup (revision 24813) @@ -0,0 +1,8 @@ +$class export +$short breadboard pcb_exporter +$long Export breadboard +$state WIP +$fmt-native no +$fmt-feature-w export breadboard assembly drawing in png +default disable-all +autoload 1 Index: tags/2.1.2/src_plugins/export_bom/Makefile =================================================================== --- tags/2.1.2/src_plugins/export_bom/Makefile (nonexistent) +++ tags/2.1.2/src_plugins/export_bom/Makefile (revision 24813) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_export_bom + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/2.1.2/src_plugins/export_bom/Plug.tmpasm =================================================================== --- tags/2.1.2/src_plugins/export_bom/Plug.tmpasm (nonexistent) +++ tags/2.1.2/src_plugins/export_bom/Plug.tmpasm (revision 24813) @@ -0,0 +1,8 @@ +put /local/pcb/mod {export_bom} +put /local/pcb/mod/OBJS [@ $(PLUGDIR)/export_bom/bom.o @] + +switch /local/pcb/export_bom/controls + case {buildin} include /local/pcb/tmpasm/buildin; end; + case {plugin} include /local/pcb/tmpasm/plugin; end; + case {disable} include /local/pcb/tmpasm/disable; end; +end Index: tags/2.1.2/src_plugins/export_bom/bom.c =================================================================== --- tags/2.1.2/src_plugins/export_bom/bom.c (nonexistent) +++ tags/2.1.2/src_plugins/export_bom/bom.c (revision 24813) @@ -0,0 +1,328 @@ +#include "config.h" +#include "conf_core.h" + +#include +#include +#include +#include +#include + +#include "build_run.h" +#include "board.h" +#include "data.h" +#include "error.h" +#include "pcb-printf.h" +#include "plugins.h" +#include "compat_misc.h" +#include "safe_fs.h" + +#include "hid.h" +#include "hid_nogui.h" +#include "hid_attrib.h" +#include "hid_cam.h" +#include "hid_init.h" +#include "macro.h" + +const char *bom_cookie = "bom HID"; + +static pcb_hid_attribute_t bom_options[] = { +/* %start-doc options "8 BOM Creation" +@ftable @code +@item --bomfile +Name of the BOM output file. +@end ftable +%end-doc +*/ + {"bomfile", "Name of the BOM output file", + PCB_HATT_STRING, 0, 0, {0, 0, 0}, 0, 0}, +#define HA_bomfile 0 +/* %start-doc options "8 BOM Creation" +@ftable @code +@item --xyfile +Name of the XY output file. +@end ftable +%end-doc +*/ +}; + +#define NUM_OPTIONS (sizeof(bom_options)/sizeof(bom_options[0])) + +static pcb_hid_attr_val_t bom_values[NUM_OPTIONS]; + +static const char *bom_filename; + +typedef struct _StringList { + char *str; + struct _StringList *next; +} StringList; + +typedef struct _BomList { + char *descr; + char *value; + int num; + StringList *refdes; + struct _BomList *next; +} BomList; + +static pcb_hid_attribute_t *bom_get_export_options(int *n) +{ + if ((PCB != NULL) && (bom_options[HA_bomfile].default_val.str_value == NULL)) + pcb_derive_default_filename(PCB->Filename, &bom_options[HA_bomfile], ".bom"); + + if (n) + *n = NUM_OPTIONS; + return bom_options; +} + +/* --------------------------------------------------------------------------- + * prints a centroid file in a format which includes data needed by a + * pick and place machine. Further formatting for a particular factory setup + * can easily be generated with awk or perl. In addition, a bill of materials + * file is generated which can be used for checking stock and purchasing needed + * materials. + * returns != zero on error + */ +char *CleanBOMString(const char *in) +{ + char *out; + int i; + + if ((out = (char *) malloc((strlen(in) + 1) * sizeof(char))) == NULL) { + fprintf(stderr, "Error: CleanBOMString() malloc() failed\n"); + exit(1); + } + + /* + * copy over in to out with some character conversions. + * Go all the way to then end to get the terminating \0 + */ + for (i = 0; i <= strlen(in); i++) { + switch (in[i]) { + case '"': + out[i] = '\''; + break; + default: + out[i] = in[i]; + } + } + + return out; +} + +static StringList *string_insert(char *str, StringList * list) +{ + StringList *newlist, *cur; + + if ((newlist = (StringList *) malloc(sizeof(StringList))) == NULL) { + fprintf(stderr, "malloc() failed in string_insert()\n"); + exit(1); + } + + newlist->next = NULL; + newlist->str = pcb_strdup(str); + + if (list == NULL) + return newlist; + + cur = list; + while (cur->next != NULL) + cur = cur->next; + + cur->next = newlist; + + return list; +} + +static BomList *bom_insert(char *refdes, char *descr, char *value, BomList * bom) +{ + BomList *newlist, *cur, *prev = NULL; + + if (bom == NULL) { + /* this is the first subcircuit so automatically create an entry */ + if ((newlist = (BomList *) malloc(sizeof(BomList))) == NULL) { + fprintf(stderr, "malloc() failed in bom_insert()\n"); + exit(1); + } + + newlist->next = NULL; + newlist->descr = pcb_strdup(descr); + newlist->value = pcb_strdup(value); + newlist->num = 1; + newlist->refdes = string_insert(refdes, NULL); + return newlist; + } + + /* search and see if we already have used one of these + components */ + cur = bom; + while (cur != NULL) { + if ((PCB_NSTRCMP(descr, cur->descr) == 0) && (PCB_NSTRCMP(value, cur->value) == 0)) { + cur->num++; + cur->refdes = string_insert(refdes, cur->refdes); + break; + } + prev = cur; + cur = cur->next; + } + + if (cur == NULL) { + if ((newlist = (BomList *) malloc(sizeof(BomList))) == NULL) { + fprintf(stderr, "malloc() failed in bom_insert()\n"); + exit(1); + } + + prev->next = newlist; + + newlist->next = NULL; + newlist->descr = pcb_strdup(descr); + newlist->value = pcb_strdup(value); + newlist->num = 1; + newlist->refdes = string_insert(refdes, NULL); + } + + return bom; + +} + +/* + * If fp is not NULL then print out the bill of materials contained in + * bom. Either way, free all memory which has been allocated for bom. + */ +static void print_and_free(FILE * fp, BomList * bom) +{ + BomList *lastb; + StringList *lasts; + char *descr, *value; + + while (bom != NULL) { + if (fp) { + descr = CleanBOMString(bom->descr); + value = CleanBOMString(bom->value); + fprintf(fp, "%d,\"%s\",\"%s\",", bom->num, descr, value); + free(descr); + free(value); + } + + while (bom->refdes != NULL) { + if (fp) { + fprintf(fp, "%s ", bom->refdes->str); + } + free(bom->refdes->str); + lasts = bom->refdes; + bom->refdes = bom->refdes->next; + free(lasts); + } + if (fp) { + fprintf(fp, "\n"); + } + lastb = bom; + bom = bom->next; + free(lastb); + } +} + +static int PrintBOM(void) +{ + char utcTime[64]; + FILE *fp; + BomList *bom = NULL; + + pcb_print_utc(utcTime, sizeof(utcTime), 0); + + PCB_SUBC_LOOP(PCB->Data); + { + /* insert this component into the bill of materials list */ + bom = bom_insert((char *) PCB_UNKNOWN(subc->refdes), + (char *) PCB_UNKNOWN(pcb_subc_name(subc, "bom::footprint")), + (char *) PCB_UNKNOWN(pcb_attribute_get(&subc->Attributes, "value")), + bom); + } + PCB_END_LOOP; + + fp = pcb_fopen(bom_filename, "w"); + if (!fp) { + pcb_message(PCB_MSG_ERROR, "Cannot open file %s for writing\n", bom_filename); + print_and_free(NULL, bom); + return 1; + } + + fprintf(fp, "# $Id"); + fprintf(fp, "$\n"); + fprintf(fp, "# PcbBOM Version 1.0\n"); + fprintf(fp, "# Date: %s\n", utcTime); + fprintf(fp, "# Author: %s\n", pcb_author()); + fprintf(fp, "# Title: %s - PCB BOM\n", PCB_UNKNOWN(PCB->Name)); + fprintf(fp, "# Quantity, Description, Value, RefDes\n"); + fprintf(fp, "# --------------------------------------------\n"); + + print_and_free(fp, bom); + + fclose(fp); + + return 0; +} + +static void bom_do_export(pcb_hid_attr_val_t * options) +{ + int i; + + if (!options) { + bom_get_export_options(0); + for (i = 0; i < NUM_OPTIONS; i++) + bom_values[i] = bom_options[i].default_val; + options = bom_values; + } + + bom_filename = options[HA_bomfile].str_value; + if (!bom_filename) + bom_filename = "pcb-out.bom"; + + PrintBOM(); +} + +static int bom_usage(const char *topic) +{ + fprintf(stderr, "\nbom exporter command line arguments:\n\n"); + pcb_hid_usage(bom_options, sizeof(bom_options) / sizeof(bom_options[0])); + fprintf(stderr, "\nUsage: pcb-rnd [generic_options] -x bom [bom_options] foo.pcb\n\n"); + return 0; +} + + +static int bom_parse_arguments(int *argc, char ***argv) +{ + pcb_hid_register_attributes(bom_options, sizeof(bom_options) / sizeof(bom_options[0]), bom_cookie, 0); + return pcb_hid_parse_command_line(argc, argv); +} + +pcb_hid_t bom_hid; + +int pplg_check_ver_export_bom(int ver_needed) { return 0; } + +void pplg_uninit_export_bom(void) +{ + pcb_hid_remove_attributes_by_cookie(bom_cookie); +} + +int pplg_init_export_bom(void) +{ + PCB_API_CHK_VER; + + memset(&bom_hid, 0, sizeof(pcb_hid_t)); + + pcb_hid_nogui_init(&bom_hid); + + bom_hid.struct_size = sizeof(pcb_hid_t); + bom_hid.name = "bom"; + bom_hid.description = "Exports a Bill of Materials"; + bom_hid.exporter = 1; + + bom_hid.get_export_options = bom_get_export_options; + bom_hid.do_export = bom_do_export; + bom_hid.parse_arguments = bom_parse_arguments; + + bom_hid.usage = bom_usage; + + pcb_hid_register_hid(&bom_hid); + return 0; +} Index: tags/2.1.2/src_plugins/export_bom/export_bom.pup =================================================================== --- tags/2.1.2/src_plugins/export_bom/export_bom.pup (nonexistent) +++ tags/2.1.2/src_plugins/export_bom/export_bom.pup (revision 24813) @@ -0,0 +1,9 @@ +$class export +$short bom pcb_exporter +$long Export bom (Bill of Materials) +$state works +$fmt-native no +$fmt-feature-w export bom (Bill of Materials) in plain text +$package export +default buildin +autoload 1 Index: tags/2.1.2/src_plugins/export_dsn/Makefile =================================================================== --- tags/2.1.2/src_plugins/export_dsn/Makefile (nonexistent) +++ tags/2.1.2/src_plugins/export_dsn/Makefile (revision 24813) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_export_dsn + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/2.1.2/src_plugins/export_dsn/Plug.tmpasm =================================================================== --- tags/2.1.2/src_plugins/export_dsn/Plug.tmpasm (nonexistent) +++ tags/2.1.2/src_plugins/export_dsn/Plug.tmpasm (revision 24813) @@ -0,0 +1,8 @@ +put /local/pcb/mod {export_dsn} +put /local/pcb/mod/OBJS_C99 [@ $(PLUGDIR)/export_dsn/dsn.o @] + +switch /local/pcb/export_dsn/controls + case {buildin} include /local/pcb/tmpasm/buildin; end; + case {plugin} include /local/pcb/tmpasm/plugin; end; + case {disable} include /local/pcb/tmpasm/disable; end; +end Index: tags/2.1.2/src_plugins/export_dsn/dsn.c =================================================================== --- tags/2.1.2/src_plugins/export_dsn/dsn.c (nonexistent) +++ tags/2.1.2/src_plugins/export_dsn/dsn.c (revision 24813) @@ -0,0 +1,623 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * + * Specctra .dsn export HID + * Copyright (C) 2008, 2011 Josh Jordan, Dan McMahill, and Jared Casper + * Copyright (C) 2018,2019 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +/* +This program exports specctra .dsn files. +By Josh Jordan and Dan McMahill, modified from bom.c + -- Updated to use Coord and other fixes by Jared Casper 16 Sep 2011 +*/ + +#include "config.h" + +#include +#include +#include +#include +#include +#include + +#include "board.h" +#include "data.h" +#include "error.h" +#include "buffer.h" +#include "change.h" +#include "draw.h" +#include "undo.h" +#include "pcb-printf.h" +#include "polygon.h" +#include "compat_misc.h" +#include "layer.h" +#include "safe_fs.h" +#include "netlist2.h" + +#include "hid.h" +#include "hid_draw_helpers.h" +#include "hid_nogui.h" +#include "actions.h" +#include "hid_init.h" +#include "hid_attrib.h" +#include "hid_cam.h" +#include "plugins.h" +#include "obj_line.h" +#include "obj_pstk_inlines.h" + +static const char *dsn_cookie = "dsn exporter"; + +#define GRP_NAME(grp_) ((grp_) - PCB->LayerGroups.grp), ((grp_)->name) + +static pcb_coord_t trackwidth = 8; /* user options defined in export dialog */ +static pcb_coord_t clearance = 8; +static pcb_coord_t viawidth = 45; +static pcb_coord_t viadrill = 25; + +static pcb_hid_t dsn_hid; + +static pcb_hid_attribute_t dsn_options[] = { + {"dsnfile", "SPECCTRA output file", + PCB_HATT_STRING, 0, 0, {0, 0, 0}, 0, 0}, +#define HA_dsnfile 0 + {"trackwidth", "track width in mils", + PCB_HATT_COORD, PCB_MIL_TO_COORD(0), PCB_MIL_TO_COORD(100), {0, 0, 0, PCB_MIL_TO_COORD(8)}, 0, 0}, +#define HA_trackwidth 1 + {"clearance", "clearance in mils", + PCB_HATT_COORD, PCB_MIL_TO_COORD(0), PCB_MIL_TO_COORD(100), {0, 0, 0, PCB_MIL_TO_COORD(8)}, 0, 0}, +#define HA_clearance 2 + {"viawidth", "via width in mils", + PCB_HATT_COORD, PCB_MIL_TO_COORD(0), PCB_MIL_TO_COORD(100), {0, 0, 0, PCB_MIL_TO_COORD(27)}, 0, + 0}, +#define HA_viawidth 3 + {"viadrill", "via drill diameter in mils", + PCB_HATT_COORD, PCB_MIL_TO_COORD(0), PCB_MIL_TO_COORD(100), {0, 0, 0, PCB_MIL_TO_COORD(15)}, 0, + 0}, +#define HA_viadrill 4 +}; + +#define NUM_OPTIONS (sizeof(dsn_options)/sizeof(dsn_options[0])) +PCB_REGISTER_ATTRIBUTES(dsn_options, dsn_cookie) + +static pcb_hid_attr_val_t dsn_values[NUM_OPTIONS]; + +static const char *dsn_filename; + +static pcb_hid_attribute_t *dsn_get_export_options(int *n) +{ + if ((PCB != NULL) && (dsn_options[HA_dsnfile].default_val.str_value == NULL)) + pcb_derive_default_filename(PCB->Filename, &dsn_options[HA_dsnfile], ".dsn"); + if (n) + *n = NUM_OPTIONS; + return dsn_options; +} + +static void print_structure(FILE * fp) +{ + pcb_layergrp_id_t group, top_group, bot_group; + + pcb_layergrp_list(PCB, PCB_LYT_TOP | PCB_LYT_COPPER, &top_group, 1); + pcb_layergrp_list(PCB, PCB_LYT_BOTTOM | PCB_LYT_COPPER, &bot_group, 1); + + fprintf(fp, " (structure\n"); + for (group = 0; group < pcb_max_group(PCB); group++) { + htsp_entry_t *e; + pcb_layergrp_t *g = &PCB->LayerGroups.grp[group]; + char *layeropts = pcb_strdup("(type signal)"); + + if (!(g->ltype & PCB_LYT_COPPER)) + continue; + +TODO("revise this; use attributes instead") + /* see if group has same name as a net and make it a power layer */ + /* loop thru all nets */ + for(e = htsp_first(&PCB->netlist[PCB_NETLIST_EDITED]); e != NULL; e = htsp_next(&PCB->netlist[PCB_NETLIST_EDITED], e)) { + pcb_net_t *net = e->value; + if (!strcmp(g->name, net->name)) { + free(layeropts); + layeropts = pcb_strdup_printf("(type power) (use_net \"%s\")", g->name); + } + } + fprintf(fp, " (layer \"%d__%s\"\n", GRP_NAME(g)); + fprintf(fp, " %s\n", layeropts); + fprintf(fp, " )\n"); + free(layeropts); + } + + /* PCB outline */ + pcb_fprintf(fp, " (boundary\n"); + pcb_fprintf(fp, " (rect pcb 0.0 0.0 %.6mm %.6mm)\n", PCB->MaxWidth, PCB->MaxHeight); + pcb_fprintf(fp, " )\n"); + pcb_fprintf(fp, " (via via_%ld_%ld)\n", viawidth, viadrill); + + /* DRC rules */ + pcb_fprintf(fp, " (rule\n"); + pcb_fprintf(fp, " (width %mm)\n", trackwidth); + pcb_fprintf(fp, " (clear %mm)\n", clearance); + pcb_fprintf(fp, " (clear %mm (type wire_area))\n", clearance); + pcb_fprintf(fp, " (clear %mm (type via_smd via_pin))\n", clearance); + pcb_fprintf(fp, " (clear %mm (type smd_smd))\n", clearance); + pcb_fprintf(fp, " (clear %mm (type default_smd))\n", clearance); + pcb_fprintf(fp, " )\n )\n"); +} + +static void print_placement(FILE * fp) +{ + fprintf(fp, " (placement\n"); + + PCB_SUBC_LOOP(PCB->Data); + { + char *ename; + pcb_coord_t ox, oy; + char *side; + int res; + int subc_on_solder = 0; + + pcb_subc_get_side(subc, &subc_on_solder); + side = subc_on_solder ? "back" : "front"; + + res = pcb_subc_get_origin(subc, &ox, &oy); + assert(res == 0); + if (subc->refdes != NULL) + ename = pcb_strdup(subc->refdes); + else + ename = pcb_strdup("null"); + pcb_fprintf(fp, " (component %d\n", subc->ID); + pcb_fprintf(fp, " (place \"%s\" %.6mm %.6mm %s 0 (PN 0))\n", ename, ox, PCB->MaxHeight - oy, side); + pcb_fprintf(fp, " )\n"); + free(ename); + } + PCB_END_LOOP; + +TODO("padstack: check if real shapes are exported") + PCB_PADSTACK_LOOP(PCB->Data); + { /* add mounting holes */ + pcb_fprintf(fp, " (component %d\n", padstack->ID); + pcb_fprintf(fp, " (place %d %.6mm %.6mm %s 0 (PN 0))\n", padstack->ID, padstack->x, (PCB->MaxHeight - padstack->y), "front"); + pcb_fprintf(fp, " )\n"); + } + PCB_END_LOOP; + + fprintf(fp, " )\n"); +} + +static void print_polyshape(gds_t *term_shapes, pcb_pstk_poly_t *ply, pcb_coord_t ox, pcb_coord_t oy, pcb_layergrp_t *grp, int partsidesign) +{ + char tmp[512]; + int fld; + int n; + + pcb_snprintf(tmp, sizeof(tmp), " (polygon \"%d__%s\" 0", GRP_NAME(grp)); + gds_append_str(term_shapes, tmp); + + fld = 0; + for(n = 0; n < ply->len; n++) { + if ((fld % 3) == 0) + gds_append_str(term_shapes, "\n "); + pcb_snprintf(tmp, sizeof(tmp), " %.6mm %.6mm", (ply->x[n] - ox) * partsidesign, -(ply->y[n] - oy)); + gds_append_str(term_shapes, tmp); + fld++; + } + + gds_append_str(term_shapes, "\n )\n"); +} + +static void print_lineshape(gds_t *term_shapes, pcb_pstk_line_t *lin, pcb_coord_t ox, pcb_coord_t oy, pcb_layergrp_t *grp, int partsidesign) +{ + char tmp[512]; + int fld; + pcb_coord_t x[4], y[4]; + int n; + pcb_line_t ltmp; + + pcb_snprintf(tmp, sizeof(tmp), " (polygon \"%d__%s\" 0", GRP_NAME(grp)); + gds_append_str(term_shapes, tmp); + + memset(<mp, 0, sizeof(ltmp)); + ltmp.Point1.X = lin->x1; + ltmp.Point1.Y = lin->y1; + ltmp.Point2.X = lin->x2; + ltmp.Point2.Y = lin->y2; + ltmp.Thickness = lin->thickness; + pcb_sqline_to_rect(<mp, x, y); + +TODO("padstack: this ignores round cap") + + fld = 0; + for(n = 0; n < 4; n++) { + if ((fld % 3) == 0) + gds_append_str(term_shapes, "\n "); + pcb_snprintf(tmp, sizeof(tmp), " %.6mm %.6mm", (x[n] - ox) * partsidesign, -(y[n] - oy)); + gds_append_str(term_shapes, tmp); + fld++; + } + + gds_append_str(term_shapes, "\n )\n"); +} + +static void print_circshape(gds_t *term_shapes, pcb_pstk_circ_t *circ, pcb_coord_t ox, pcb_coord_t oy, pcb_layergrp_t *grp, int partsidesign) +{ + char tmp[512]; + + pcb_snprintf(tmp, sizeof(tmp), " (circle \"%d__%s\"", GRP_NAME(grp)); + gds_append_str(term_shapes, tmp); + +TODO("padstack: this ignores circle center offset") + + pcb_snprintf(tmp, sizeof(tmp), " %.6mm)\n", circ->dia); + gds_append_str(term_shapes, tmp); +} + +static void print_polyline(gds_t *term_shapes, pcb_poly_it_t *it, pcb_pline_t *pl, pcb_coord_t ox, pcb_coord_t oy, pcb_layergrp_t *grp, int partsidesign) +{ + char tmp[512]; + int fld; + pcb_coord_t x, y; + int go; + + if (pl != NULL) { + pcb_snprintf(tmp, sizeof(tmp), "(polygon \"%d__%s\" 0", GRP_NAME(grp)); + gds_append_str(term_shapes, tmp); + + fld = 0; + for(go = pcb_poly_vect_first(it, &x, &y); go; go = pcb_poly_vect_next(it, &x, &y)) { + if ((fld % 3) == 0) + gds_append_str(term_shapes, "\n "); + pcb_snprintf(tmp, sizeof(tmp), " %.6mm %.6mm", (x - ox) * partsidesign, -(y - oy)); + gds_append_str(term_shapes, tmp); + fld++; + } + + gds_append_str(term_shapes, "\n )\n"); + } +} + +static void print_term_poly(FILE *fp, gds_t *term_shapes, pcb_poly_t *poly, pcb_coord_t ox, pcb_coord_t oy, int term_on_bottom, int partsidesign) +{ + if (poly->term != NULL) { + pcb_layergrp_id_t gid = term_on_bottom ? pcb_layergrp_get_bottom_copper() : pcb_layergrp_get_top_copper(); + pcb_layergrp_t *grp = pcb_get_layergrp(PCB, gid); + char *padstack = pcb_strdup_printf("Term_poly_%ld", poly->ID); + pcb_poly_it_t it; + pcb_polyarea_t *pa; + + + pcb_fprintf(fp, " (pin %s \"%s\" %.6mm %.6mm)\n", padstack, poly->term, 0, 0); + + gds_append_str(term_shapes, " (padstack "); + gds_append_str(term_shapes, padstack); + gds_append_str(term_shapes, "\n"); + + gds_append_str(term_shapes, " (shape "); + + for(pa = pcb_poly_island_first(poly, &it); pa != NULL; pa = pcb_poly_island_next(&it)) { + pcb_pline_t *pl; + + pl = pcb_poly_contour(&it); + + print_polyline(term_shapes, &it, pl, ox, oy, grp, partsidesign); + } + + gds_append_str(term_shapes, " )\n"); + gds_append_str(term_shapes, " (attach off)\n"); + gds_append_str(term_shapes, " )\n"); + } +} + +void print_pstk_shape(gds_t *term_shapes, pcb_pstk_t *padstack, pcb_layergrp_id_t gid, pcb_coord_t ox, pcb_coord_t oy, int partsidesign) +{ + pcb_pstk_shape_t *shp; + pcb_layergrp_t *grp = pcb_get_layergrp(PCB, gid); + pcb_layer_type_t lyt = grp->ltype; + + shp = pcb_pstk_shape(padstack, lyt, 0); + if (shp == NULL) + return; + + /* if the subc is placed on the other side, need to invert the output layerstack as well */ + if (partsidesign < 0) { + pcb_layergrp_id_t n, offs = 0; + + /* determine copper offset from the top */ + for(n = 0; (n < PCB->LayerGroups.len) && (n != gid); n++) + if (PCB->LayerGroups.grp[n].type & PCB_LYT_COPPER) + offs++; + + /* count it back from the bottom and set grp */ + for(n = PCB->LayerGroups.len-1; (n > 0) && (n != gid); n--) { + if (PCB->LayerGroups.grp[n].type & PCB_LYT_COPPER) { + if (offs == 0) { + grp = &PCB->LayerGroups.grp[n]; + break; + } + offs--; + } + } + } + + switch(shp->shape) { + case PCB_PSSH_POLY: + print_polyshape(term_shapes, &shp->data.poly, ox, oy, grp, partsidesign); + break; + case PCB_PSSH_LINE: + print_lineshape(term_shapes, &shp->data.line, ox, oy, grp, partsidesign); + break; + case PCB_PSSH_CIRC: + print_circshape(term_shapes, &shp->data.circ, ox, oy, grp, partsidesign); + break; + case PCB_PSSH_HSHADOW: + break; + } +} + +static void print_library(FILE * fp) +{ + gds_t term_shapes; + + gds_init(&term_shapes); + + fprintf(fp, " (library\n"); + + PCB_SUBC_LOOP(PCB->Data); + { + pcb_coord_t ox, oy; + int partsidesign, subc_on_solder = 0; + pcb_layer_type_t lyt_side; + + pcb_subc_get_side(subc, &subc_on_solder); + partsidesign = subc_on_solder ? -1 : 1; + lyt_side = subc_on_solder ? PCB_LYT_BOTTOM : PCB_LYT_TOP; + + pcb_subc_get_origin(subc, &ox, &oy); + + fprintf(fp, " (image %ld\n", subc->ID); /* map every subc by ID */ + PCB_POLY_COPPER_LOOP(subc->data); + { + pcb_layer_type_t lyt = pcb_layer_flags_(layer); + if ((lyt & PCB_LYT_COPPER) && ((lyt & PCB_LYT_TOP) || (lyt & PCB_LYT_BOTTOM))) + print_term_poly(fp, &term_shapes, polygon, ox, oy, !(lyt & lyt_side), partsidesign); + } + PCB_ENDALL_LOOP; + + PCB_PADSTACK_LOOP(subc->data); + { + pcb_layergrp_id_t group; + char *pid = pcb_strdup_printf("Pstk_shape_%ld", padstack->ID); + + pcb_fprintf(fp, " (pin %s \"%s\" %.6mm %.6mm)\n", pid, padstack->term, (padstack->x-ox)*partsidesign, -(padstack->y-oy)); + + gds_append_str(&term_shapes, " (padstack "); + gds_append_str(&term_shapes, pid); + gds_append_str(&term_shapes, "\n"); + + gds_append_str(&term_shapes, " (shape\n"); + + for (group = 0; group < pcb_max_group(PCB); group++) { + pcb_layergrp_t *g = &PCB->LayerGroups.grp[group]; + if (g->ltype & PCB_LYT_COPPER) + print_pstk_shape(&term_shapes, padstack, group, 0, 0, partsidesign); + } + + gds_append_str(&term_shapes, " )\n"); + gds_append_str(&term_shapes, " (attach off)\n"); + gds_append_str(&term_shapes, " )\n"); + } + PCB_END_LOOP; + + fprintf(fp, " )\n"); + } + PCB_END_LOOP; + + /* add padstack for terminals */ + pcb_fprintf(fp, "%s", term_shapes.array); + pcb_fprintf(fp, " )\n"); + + + gds_uninit(&term_shapes); +} + +static void print_quoted_pin(FILE *fp, const pcb_net_term_t *t) +{ + fprintf(fp, " \"%s\"-\"%s\"", t->refdes, t->term); +} + +static void print_network(FILE * fp) +{ + htsp_entry_t *e; + + fprintf(fp, " (network\n"); + + for(e = htsp_first(&PCB->netlist[PCB_NETLIST_EDITED]); e != NULL; e = htsp_next(&PCB->netlist[PCB_NETLIST_EDITED], e)) { + pcb_net_term_t *t; + pcb_net_t *net = e->value; + + fprintf(fp, " (net \"%s\"\n", net->name); + fprintf(fp, " (pins"); + + for(t = pcb_termlist_first(&net->conns); t != NULL; t = pcb_termlist_next(t)) + print_quoted_pin(fp, t); + fprintf(fp, ")\n"); + fprintf(fp, " )\n"); + } + + fprintf(fp, " (class pcb_rnd_default"); + for(e = htsp_first(&PCB->netlist[PCB_NETLIST_EDITED]); e != NULL; e = htsp_next(&PCB->netlist[PCB_NETLIST_EDITED], e)) { + pcb_net_t *net = e->value; + fprintf(fp, " \"%s\"", net->name); + } + pcb_fprintf(fp, "\n"); + pcb_fprintf(fp, " (circuit\n"); + pcb_fprintf(fp, " (use_via via_%ld_%ld)\n", viawidth, viadrill); + pcb_fprintf(fp, " )\n"); + pcb_fprintf(fp, " (rule (width %.6mm))\n )\n )\n", trackwidth); +} + +static void print_wires(FILE * fp) +{ + int group; + fprintf(fp, " (wiring\n"); + + for (group = 0; group < pcb_max_group(PCB); group++) { + pcb_layergrp_t *g = &PCB->LayerGroups.grp[group]; + pcb_cardinal_t n; + if (!(g->ltype & PCB_LYT_COPPER)) + continue; + for(n = 0; n < g->len; n++) { + pcb_layer_t *lay = pcb_get_layer(PCB->Data, g->lid[n]); + + PCB_LINE_LOOP(lay); + { + pcb_fprintf(fp, + " (wire (path %d__%s %.6mm %.6mm %.6mm %.6mm %.6mm)\n", GRP_NAME(g), line->Thickness, + line->Point1.X, (PCB->MaxHeight - line->Point1.Y), + line->Point2.X, (PCB->MaxHeight - line->Point2.Y)); + fprintf(fp, " (type protect))\n"); + } + PCB_END_LOOP; + } + } + fprintf(fp, "\n )\n)\n"); /* close all braces */ +} + +static int PrintSPECCTRA(void) +{ + FILE *fp; + /* Print out the dsn .dsn file. */ + fp = pcb_fopen(dsn_filename, "w"); + if (!fp) { + pcb_message(PCB_MSG_WARNING, "Cannot open file %s for writing\n", dsn_filename); + return 1; + } + + /* pcb [required] */ + fprintf(fp, "(pcb %s\n", ((PCB->Name) && *(PCB->Name) ? (PCB->Name) : "notnamed")); + + /* parser descriptor [optional] */ + fprintf(fp, " (parser\n"); + fprintf(fp, " (string_quote \")\n"); + fprintf(fp, " (space_in_quoted_tokens on)\n"); + fprintf(fp, " (host_cad \"pcb-rnd\")\n"); + fprintf(fp, " (host_version \"%s\")\n", PCB_VERSION); + fprintf(fp, " )\n"); + + /* capacitance resolution descriptor [optional] */ + + /* conductance resolution descriptor [optional] */ + + /* current resolution descriptor [optional] */ + + /* inductance resolution descriptor [optional] */ + + /* resistance resolution descriptor [optional] */ + + /* resolution descriptor [optional] */ + fprintf(fp, " (resolution mm 1000000)\n"); + + /* time resolution descriptor [optional] */ + + /* voltage resolution descriptor [optional] */ + + /* unit descriptor [optional] */ + + /* structure descriptor [required] */ + print_structure(fp); + + /* placement descriptor [optional] */ + print_placement(fp); + + /* library descriptor [required] */ + print_library(fp); + + /* floor plan descriptor [optional] */ + + /* part library descriptor [optional] */ + + /* network descriptor [required] */ + print_network(fp); + + /* wiring descriptor [optional] */ + print_wires(fp); + + /* color descriptor [optional] */ + + fclose(fp); + + return 0; +} + + +static void dsn_do_export(pcb_hid_attr_val_t * options) +{ + int i; + if (!options) { + dsn_get_export_options(0); + for (i = 0; i < NUM_OPTIONS; i++) + dsn_values[i] = dsn_options[i].default_val; + options = dsn_values; + } + dsn_filename = options[HA_dsnfile].str_value; + if (!dsn_filename) + dsn_filename = "pcb-out.dsn"; + + trackwidth = options[HA_trackwidth].coord_value; + clearance = options[HA_clearance].coord_value; + viawidth = options[HA_viawidth].coord_value; + viadrill = options[HA_viadrill].coord_value; + PrintSPECCTRA(); +} + +static int dsn_parse_arguments(int *argc, char ***argv) +{ + return pcb_hid_parse_command_line(argc, argv); +} + +int pplg_check_ver_export_dsn(int ver_needed) { return 0; } + +void pplg_uninit_export_dsn(void) +{ + pcb_hid_remove_attributes_by_cookie(dsn_cookie); +} + +#include "dolists.h" +int pplg_init_export_dsn(void) +{ + PCB_API_CHK_VER; + memset(&dsn_hid, 0, sizeof(pcb_hid_t)); + pcb_hid_nogui_init(&dsn_hid); + + dsn_hid.struct_size = sizeof(pcb_hid_t); + dsn_hid.name = "dsn"; + dsn_hid.description = "Exports DSN format"; + dsn_hid.exporter = 1; + dsn_hid.get_export_options = dsn_get_export_options; + dsn_hid.do_export = dsn_do_export; + dsn_hid.parse_arguments = dsn_parse_arguments; + pcb_hid_register_hid(&dsn_hid); + + pcb_hid_register_attributes(dsn_options, sizeof(dsn_options) / sizeof(dsn_options[0]), dsn_cookie, 0); + return 0; +} + Index: tags/2.1.2/src_plugins/export_dsn/export_dsn.pup =================================================================== --- tags/2.1.2/src_plugins/export_dsn/export_dsn.pup (nonexistent) +++ tags/2.1.2/src_plugins/export_dsn/export_dsn.pup (revision 24813) @@ -0,0 +1,9 @@ +$class export +$short specctra .dsn pcb_exporter +$long Export specctra .dsn files +$state works +$fmt-native no +$fmt-feature-w export specctra .dsn files with padstacks and subcircuits (usable for freerouting) +$package auto +default buildin +autoload 1 Index: tags/2.1.2/src_plugins/export_dxf/Makefile =================================================================== --- tags/2.1.2/src_plugins/export_dxf/Makefile (nonexistent) +++ tags/2.1.2/src_plugins/export_dxf/Makefile (revision 24813) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_export_dxf + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/2.1.2/src_plugins/export_dxf/Makefile.test =================================================================== --- tags/2.1.2/src_plugins/export_dxf/Makefile.test (nonexistent) +++ tags/2.1.2/src_plugins/export_dxf/Makefile.test (revision 24813) @@ -0,0 +1,15 @@ +LHT=../../src_3rd/liblihata +HT=../../src_3rd/genht +CFLAGS = -Wall -g -I../../src_3rd -DTESTER +LDFLAGS = +OBJS = $(LHT)/parser.o $(LHT)/lihata.o $(HT)/htsp.o $(HT)/hash.o \ + $(LHT)/dom.o $(LHT)/dom_list.o $(LHT)/dom_hash.o $(LHT)/dom_table.o \ + $(LHT)/tree_path.o $(LHT)/tree.o $(LHT)/tree_list.o $(LHT)/tree_hash.o \ + $(LHT)/tree_table.o $(LHT)/hash_str.o + +lht_template: lht_template.o $(OBJS) + $(CC) $(LDFLAGS) -o $@ $^ + +lht_template.o: lht_template.c + $(CC) -c -o $@ $(CFLAGS) lht_template.c + Index: tags/2.1.2/src_plugins/export_dxf/Plug.tmpasm =================================================================== --- tags/2.1.2/src_plugins/export_dxf/Plug.tmpasm (nonexistent) +++ tags/2.1.2/src_plugins/export_dxf/Plug.tmpasm (revision 24813) @@ -0,0 +1,21 @@ +put /local/pcb/mod {export_dxf} +put /local/pcb/mod/OBJS [@ + $(PLUGDIR)/export_dxf/dxf.o + $(PLUGDIR)/export_dxf/lht_template.o + $(PLUGDIR)/export_dxf/dxf_templ_lht.o +@] + +switch /local/pcb/export_dxf/controls + case {buildin} include /local/pcb/tmpasm/buildin; end; + case {plugin} include /local/pcb/tmpasm/plugin; end; + case {disable} include /local/pcb/tmpasm/disable; end; +end + +# always generate the template lht rule so make dep can be run +append /local/pcb/CLEANFILES { $(PLUGDIR)/export_dxf/dxf_templ_lht.c } +append /local/pcb/DEPDEPS { $(PLUGDIR)/export_dxf/dxf_templ_lht.c } +append /local/pcb/RULES [@ +### export_dxf: dxf template embed +$(PLUGDIR)/export_dxf/dxf_templ_lht.c: $(PLUGDIR)/export_dxf/dxf_templ.lht $(CQUOTE) + $(CQUOTE) -n dxf_templ_default <$(PLUGDIR)/export_dxf/dxf_templ.lht >$(PLUGDIR)/export_dxf/dxf_templ_lht.c +@] Index: tags/2.1.2/src_plugins/export_dxf/dxf.c =================================================================== --- tags/2.1.2/src_plugins/export_dxf/dxf.c (nonexistent) +++ tags/2.1.2/src_plugins/export_dxf/dxf.c (revision 24813) @@ -0,0 +1,572 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2017,2018 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "config.h" +#include "conf_core.h" + +#include +#include +#include +#include +#include +#include + +#include "math_helper.h" +#include "board.h" +#include "data.h" +#include "draw.h" +#include "error.h" +#include "layer.h" +#include "layer_vis.h" +#include "plugins.h" +#include "pcb-printf.h" +#include "compat_misc.h" +#include "lht_template.h" +#include "safe_fs.h" +#include "funchash_core.h" + +#include "hid.h" +#include "hid_nogui.h" +#include "hid_draw_helpers.h" + +#include "hid_init.h" +#include "hid_attrib.h" +#include "hid_color.h" +#include "hid_cam.h" + +static const char *layer_names[] = { + "outline", + "bottom_copper", "top_copper", + "bottom_silk", "top_silk", + "drill_plated", "drill_unplated", + NULL +}; + +static pcb_hid_t dxf_hid; + +const char *dxf_cookie = "dxf HID"; + +static pcb_cam_t dxf_cam; + + +typedef struct { + FILE *f; + unsigned long handle; + lht_doc_t *temp; + const char *layer_name; + unsigned force_thin:1; + unsigned enable_force_thin:1; + unsigned poly_fill:1; + unsigned poly_contour:1; + unsigned drill_fill:1; + unsigned drill_contour:1; +} dxf_ctx_t; + +static dxf_ctx_t dxf_ctx; + +typedef struct hid_gc_s { + pcb_core_gc_t core_gc; + pcb_hid_t *me_pointer; + pcb_cap_style_t cap; + pcb_coord_t width; + char *color; + int drill; + unsigned warned_elliptical:1; + unsigned drawing_hole:1; +} hid_gc_s; + +static struct hid_gc_s thin = { + {0}, + NULL, + 0, 1, + NULL, 0, 0 +}; + + +#include "dxf_draw.c" + + +pcb_hid_attribute_t dxf_attribute_list[] = { + /* other HIDs expect this to be first. */ + +/* %start-doc options "93 DXF Options" +@ftable @code +@item --outfile +Name of the file to be exported to. Can contain a path. +@end ftable +%end-doc +*/ + {"outfile", "Graphics output file", + PCB_HATT_STRING, 0, 0, {0, 0, 0}, 0, 0}, +#define HA_dxffile 0 + +/* %start-doc options "93 DXF Options" +@ftable @code +@item --template +Name of the lihata template file to be used instead of the default dxf template. Can contain a path. +@end ftable +%end-doc +*/ + {"template", "DXF template (lihata file)", + PCB_HATT_STRING, 0, 0, {0, 0, 0}, 0, 0}, +#define HA_template 1 + +/* %start-doc options "93 DXF Options" +@ftable @code +@item --thin +Draw outline and drills with thin lines. +@end ftable +%end-doc +*/ + {"thin", "Draw outline and drill with thin lines", + PCB_HATT_BOOL, 0, 0, {0, 0, 0}, 0, 0}, +#define HA_thin 2 + +/* %start-doc options "93 DXF Options" +@ftable @code +@item --poly-fill +Fill polygons using hatch +@end ftable +%end-doc +*/ + {"poly-fill", "Fill polygons using hatch", + PCB_HATT_BOOL, 0, 0, {1, (void *)1, 1}, 0, 0}, +#define HA_poly_fill 3 + +/* %start-doc options "93 DXF Options" +@ftable @code +@item --poly-fill +Draw polygons contour with thin line +@end ftable +%end-doc +*/ + {"poly-contour", "Draw polygons contour with thin line", + PCB_HATT_BOOL, 0, 0, {1, (void *)1, 1}, 0, 0}, +#define HA_poly_contour 4 + +/* %start-doc options "93 DXF Options" +@ftable @code +@item --drill-fill +Fill drill (hole) circles using hatch +@end ftable +%end-doc +*/ + {"drill-fill", "Fill drill (hole) circles using hatch", + PCB_HATT_BOOL, 0, 0, {0, 0, 0}, 0, 0}, +#define HA_drill_fill 5 + +/* %start-doc options "93 DXF Options" +@ftable @code +@item --polyfill +Draw drill contour with thin line +@end ftable +%end-doc +*/ + {"drill-contour", "Draw drill contour with thin line", + PCB_HATT_BOOL, 0, 0, {1, (void *)1, 1}, 0, 0}, +#define HA_drill_contour 6 + + {"cam", "CAM instruction", + PCB_HATT_STRING, 0, 0, {0, 0, 0}, 0, 0}, +#define HA_cam 7 + +}; + +#define NUM_OPTIONS (sizeof(dxf_attribute_list)/sizeof(dxf_attribute_list[0])) + +PCB_REGISTER_ATTRIBUTES(dxf_attribute_list, dxf_cookie) + +static pcb_hid_attr_val_t dxf_values[NUM_OPTIONS]; + +static pcb_hid_attribute_t *dxf_get_export_options(int *n) +{ + const char *suffix = ".dxf"; + + if ((PCB != NULL) && (dxf_attribute_list[HA_dxffile].default_val.str_value == NULL)) + pcb_derive_default_filename(PCB->Filename, &dxf_attribute_list[HA_dxffile], suffix); + + if (n) + *n = NUM_OPTIONS; + return dxf_attribute_list; +} + +void dxf_hid_export_to_file(dxf_ctx_t *ctx, pcb_hid_attr_val_t * options) +{ + static int saved_layer_stack[PCB_MAX_LAYER]; + pcb_hid_expose_ctx_t hectx; + + hectx.view.X1 = 0; + hectx.view.Y1 = 0; + hectx.view.X2 = PCB->MaxWidth; + hectx.view.Y2 = PCB->MaxHeight; + + memcpy(saved_layer_stack, pcb_layer_stack, sizeof(pcb_layer_stack)); + + conf_force_set_bool(conf_core.editor.thin_draw, 0); + conf_force_set_bool(conf_core.editor.thin_draw_poly, 0); +/* conf_force_set_bool(conf_core.editor.check_planes, 0);*/ + conf_force_set_bool(conf_core.editor.show_solder_side, 0); + + dxf_ctx.enable_force_thin = options[HA_thin].int_value; + dxf_ctx.poly_fill = options[HA_poly_fill].int_value; + dxf_ctx.poly_contour = options[HA_poly_contour].int_value; + dxf_ctx.drill_fill = options[HA_drill_fill].int_value; + dxf_ctx.drill_contour = options[HA_drill_contour].int_value; + + pcb_hid_expose_all(&dxf_hid, &hectx, NULL); + + conf_update(NULL, -1); /* restore forced sets */ +} + +int insert_hdr(FILE *f, const char *prefix, char *name, lht_err_t *err) +{ + if (strcmp(name, "extmin") == 0) + fprintf(f, "10\n0\n20\n0\n30\n0\n"); + else if (strcmp(name, "extmax") == 0) + pcb_fprintf(f, "10\n%mm\n20\n0\n30\n%mm\n", PCB->MaxWidth, PCB->MaxHeight); + else if (strcmp(name, "layers") == 0) { + const char **s; + for(s = layer_names; *s != NULL; s++) + dxf_gen_layer(&dxf_ctx, *s); + } + else { + pcb_message(PCB_MSG_ERROR, "Invalid header insertion: '%s'\n", name); + return -1; + } + + return 0; +} + +int insert_ftr(FILE *f, const char *prefix, char *name, lht_err_t *err) +{ + pcb_message(PCB_MSG_ERROR, "Invalid footer insertion: '%s'\n", name); + return -1; +} + +extern const char dxf_templ_default_arr[]; +static void dxf_do_export(pcb_hid_attr_val_t * options) +{ + const char *filename; + int save_ons[PCB_MAX_LAYER + 2]; + int i; + const char *fn; + char *errmsg; + lht_err_t err; + + if (!options) { + dxf_get_export_options(0); + for (i = 0; i < NUM_OPTIONS; i++) + dxf_values[i] = dxf_attribute_list[i].default_val; + options = dxf_values; + } + + pcb_cam_begin(PCB, &dxf_cam, options[HA_cam].str_value, dxf_attribute_list, NUM_OPTIONS, options); + + filename = options[HA_dxffile].str_value; + if (!filename) + filename = "pcb.dxf"; + + if (dxf_cam.fn_template == NULL) { + dxf_ctx.f = pcb_fopen(dxf_cam.active ? dxf_cam.fn : filename, "wb"); + if (!dxf_ctx.f) { + perror(filename); + return; + } + } + else + dxf_ctx.f = NULL; + + fn = options[HA_template].str_value; + if (fn == NULL) { + fn = ""; + dxf_ctx.temp = lht_dom_load_string(dxf_templ_default_arr, fn, &errmsg); + } + else { + char *real_fn; + dxf_ctx.temp = NULL; + real_fn = pcb_fopen_check(fn, "r"); + if (real_fn != NULL) + dxf_ctx.temp = lht_dom_load(real_fn, &errmsg); + free(real_fn); + } + + if (dxf_ctx.temp == NULL) { + pcb_message(PCB_MSG_ERROR, "Can't open dxf template: %s\n", fn); + fclose(dxf_ctx.f); + return; + } + + dxf_ctx.handle = 100; + if (dxf_ctx.f != NULL) { + if (lht_temp_exec(dxf_ctx.f, "", dxf_ctx.temp, "header", insert_hdr, &err) != 0) + pcb_message(PCB_MSG_ERROR, "Can't render dxf template header\n"); + } + + if (!dxf_cam.active) + pcb_hid_save_and_show_layer_ons(save_ons); + + dxf_hid_export_to_file(&dxf_ctx, options); + + if (!dxf_cam.active) + pcb_hid_restore_layer_ons(save_ons); + + if (lht_temp_exec(dxf_ctx.f, "", dxf_ctx.temp, "footer", insert_ftr, &err) != 0) + pcb_message(PCB_MSG_ERROR, "Can't render dxf template header\n"); + fclose(dxf_ctx.f); + + if (pcb_cam_end(&dxf_cam) == 0) + pcb_message(PCB_MSG_ERROR, "dxf cam export for '%s' failed to produce any content\n", options[HA_cam].str_value); +} + +static int dxf_parse_arguments(int *argc, char ***argv) +{ + pcb_hid_register_attributes(dxf_attribute_list, sizeof(dxf_attribute_list) / sizeof(dxf_attribute_list[0]), dxf_cookie, 0); + return pcb_hid_parse_command_line(argc, argv); +} + +static int dxf_set_layer_group(pcb_layergrp_id_t group, const char *purpose, int purpi, pcb_layer_id_t layer, unsigned int flags, int is_empty, pcb_xform_t **xform) +{ + if (flags & PCB_LYT_UI) + return 0; + + pcb_cam_set_layer_group(&dxf_cam, group, purpose, purpi, flags, xform); + + if (dxf_cam.fn_changed) { + lht_err_t err; + + if (dxf_ctx.f != NULL) { + if (lht_temp_exec(dxf_ctx.f, "", dxf_ctx.temp, "footer", insert_ftr, &err) != 0) + pcb_message(PCB_MSG_ERROR, "Can't render dxf template header\n"); + fclose(dxf_ctx.f); + } + + dxf_ctx.f = pcb_fopen(dxf_cam.fn, "wb"); + if (!dxf_ctx.f) { + perror(dxf_cam.fn); + return 0; + } + if (lht_temp_exec(dxf_ctx.f, "", dxf_ctx.temp, "header", insert_hdr, &err) != 0) + pcb_message(PCB_MSG_ERROR, "Can't render dxf template header\n"); + } + + if (!dxf_cam.active) { + if (flags & PCB_LYT_INVIS) + return 0; + } + + dxf_ctx.force_thin = 0; + + if (PCB_LAYER_IS_ROUTE(flags, purpi)) { + dxf_ctx.layer_name = "outline"; + dxf_ctx.force_thin = 1; + return 1; + } + + if (dxf_cam.active) { + pcb_layergrp_t *grp = pcb_get_layergrp(PCB, group); + dxf_ctx.layer_name = grp->name; + return 1; + } + + if (PCB_LAYER_IS_PDRILL(flags, purpi)) { + dxf_ctx.layer_name = "drill_plated"; + dxf_ctx.force_thin = 1; + return 1; + } + + if (PCB_LAYER_IS_UDRILL(flags, purpi)) { + dxf_ctx.layer_name = "drill_unplated"; + dxf_ctx.force_thin = 1; + return 1; + } + + if ((flags & PCB_LYT_TOP) && (flags & PCB_LYT_COPPER)) { + dxf_ctx.layer_name = "top_copper"; + return 1; + } + + if ((flags & PCB_LYT_TOP) && (flags & PCB_LYT_SILK)) { + dxf_ctx.layer_name = "top_silk"; + return 1; + } + + if ((flags & PCB_LYT_BOTTOM) && (flags & PCB_LYT_COPPER)) { + dxf_ctx.layer_name = "bottom_copper"; + return 1; + } + + if ((flags & PCB_LYT_BOTTOM) && (flags & PCB_LYT_SILK)) { + dxf_ctx.layer_name = "bottom_silk"; + return 1; + } + + return 0; +} + + +static pcb_hid_gc_t dxf_make_gc(void) +{ + pcb_hid_gc_t rv = (pcb_hid_gc_t) calloc(sizeof(hid_gc_s), 1); + rv->me_pointer = &dxf_hid; + return rv; +} + +static void dxf_destroy_gc(pcb_hid_gc_t gc) +{ + free(gc); +} + +static void dxf_set_drawing_mode(pcb_composite_op_t op, pcb_bool direct, const pcb_box_t *screen) +{ + if (direct) + return; + + switch(op) { + case PCB_HID_COMP_RESET: + break; + + case PCB_HID_COMP_POSITIVE: + case PCB_HID_COMP_POSITIVE_XOR: + case PCB_HID_COMP_NEGATIVE: + break; + + case PCB_HID_COMP_FLUSH: + break; + } +} + +static void dxf_set_color(pcb_hid_gc_t gc, const pcb_color_t *color) +{ + if (pcb_color_is_drill(color) == 0) + gc->drawing_hole = 1; +} + +static void dxf_set_line_cap(pcb_hid_gc_t gc, pcb_cap_style_t style) +{ + gc->cap = style; +} + +static void dxf_set_line_width(pcb_hid_gc_t gc, pcb_coord_t width) +{ + gc->width = width; +} + + +static void dxf_set_draw_xor(pcb_hid_gc_t gc, int xor_) +{ + ; +} + +#define fix_rect_coords() \ + if (x1 > x2) {\ + pcb_coord_t t = x1; \ + x1 = x2; \ + x2 = t; \ + } \ + if (y1 > y2) { \ + pcb_coord_t t = y1; \ + y1 = y2; \ + y2 = t; \ + } + +static void dxf_draw_rect(pcb_hid_gc_t gc, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2) +{ + fix_rect_coords(); +} + +static void dxf_fill_rect(pcb_hid_gc_t gc, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2) +{ + fix_rect_coords(); +} + +static void dxf_calibrate(double xval, double yval) +{ + pcb_message(PCB_MSG_ERROR, "dxf_calibrate() not implemented"); + return; +} + +static void dxf_set_crosshair(pcb_coord_t x, pcb_coord_t y, int a) +{ +} + +static int dxf_usage(const char *topic) +{ + fprintf(stderr, "\ndxf exporter command line arguments:\n\n"); + pcb_hid_usage(dxf_attribute_list, sizeof(dxf_attribute_list) / sizeof(dxf_attribute_list[0])); + fprintf(stderr, "\nUsage: pcb-rnd [generic_options] -x dxf [dxf options] foo.pcb\n\n"); + return 0; +} + +#include "dolists.h" + +int pplg_check_ver_export_dxf(int ver_needed) { return 0; } + +void pplg_uninit_export_dxf(void) +{ + pcb_hid_remove_attributes_by_cookie(dxf_cookie); +} + +int pplg_init_export_dxf(void) +{ + PCB_API_CHK_VER; + + memset(&dxf_hid, 0, sizeof(pcb_hid_t)); + + pcb_hid_nogui_init(&dxf_hid); + pcb_dhlp_draw_helpers_init(&dxf_hid); + + dxf_hid.struct_size = sizeof(pcb_hid_t); + dxf_hid.name = "dxf"; + dxf_hid.description = "Drawing eXchange Format exporter"; + dxf_hid.exporter = 1; + + dxf_hid.get_export_options = dxf_get_export_options; + dxf_hid.do_export = dxf_do_export; + dxf_hid.parse_arguments = dxf_parse_arguments; + dxf_hid.set_layer_group = dxf_set_layer_group; + dxf_hid.make_gc = dxf_make_gc; + dxf_hid.destroy_gc = dxf_destroy_gc; + dxf_hid.set_drawing_mode = dxf_set_drawing_mode; + dxf_hid.set_color = dxf_set_color; + dxf_hid.set_line_cap = dxf_set_line_cap; + dxf_hid.set_line_width = dxf_set_line_width; + dxf_hid.set_draw_xor = dxf_set_draw_xor; + dxf_hid.draw_line = dxf_draw_line; + dxf_hid.draw_arc = dxf_draw_arc; + dxf_hid.draw_rect = dxf_draw_rect; + dxf_hid.fill_circle = dxf_fill_circle; + dxf_hid.fill_polygon = dxf_fill_polygon; + dxf_hid.fill_polygon_offs = dxf_fill_polygon_offs; + dxf_hid.fill_rect = dxf_fill_rect; + dxf_hid.calibrate = dxf_calibrate; + dxf_hid.set_crosshair = dxf_set_crosshair; + + dxf_hid.usage = dxf_usage; + + pcb_hid_register_hid(&dxf_hid); + + return 0; +} Index: tags/2.1.2/src_plugins/export_dxf/dxf_draw.c =================================================================== --- tags/2.1.2/src_plugins/export_dxf/dxf_draw.c (nonexistent) +++ tags/2.1.2/src_plugins/export_dxf/dxf_draw.c (revision 24813) @@ -0,0 +1,202 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2017 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#define TRX(x) (x) +#define TRY(y) (PCB->MaxHeight - (y)) + +static void dxf_draw_handle(dxf_ctx_t *ctx) +{ + ctx->handle++; + fprintf(ctx->f, "5\n%lu\n", ctx->handle); +} + +static void dxf_draw_line_props(dxf_ctx_t *ctx, pcb_hid_gc_t gc) +{ + fprintf(ctx->f, "100\nAcDbEntity\n"); + fprintf(ctx->f, "8\n%s\n", ctx->layer_name); /* layer name */ + fprintf(ctx->f, "6\nByLayer\n"); /* linetype name */ + fprintf(ctx->f, "62\n256\n"); /* color; 256=ByLayer */ + + /* lineweight enum (width in 0.01mm) */ + if (ctx->enable_force_thin && ctx->force_thin) + fprintf(ctx->f, "370\n1\n"); + else + fprintf(ctx->f, "370\n%d\n", (int)pcb_round(PCB_COORD_TO_MM(gc->width)*100.0)); +} + +static void dxf_hatch_pre(dxf_ctx_t *ctx, pcb_hid_gc_t gc, int n_coords) +{ + fprintf(ctx->f, "0\nHATCH\n"); + dxf_draw_handle(ctx); + dxf_draw_line_props(ctx, gc); + fprintf(ctx->f, "100\nAcDbHatch\n"); + fprintf(ctx->f, "10\n0\n20\n0\n30\n0\n"); /* elevation */ + fprintf(ctx->f, "210\n0\n220\n0\n230\n1\n"); /* extrusion */ + fprintf(ctx->f, "2\nSOLID\n"); + fprintf(ctx->f, "70\n1\n"); /* solid fill */ + fprintf(ctx->f, "71\n0\n"); /* associativity: non */ + fprintf(ctx->f, "91\n1\n"); /* number of loops (contours) */ + fprintf(ctx->f, "92\n0\n"); /* boundary path type: default */ + fprintf(ctx->f, "93\n%d\n", n_coords); +} + +static void dxf_hatch_post(dxf_ctx_t *ctx) +{ + fprintf(ctx->f, "97\n0\n"); /* number of source boundaries */ + fprintf(ctx->f, "75\n0\n"); /* hatch style: normal, odd parity */ + fprintf(ctx->f, "76\n1\n"); /* pattern type: predefined */ + fprintf(ctx->f, "98\n0\n"); /* number of seed points */ +} + +static void dxf_draw_line(pcb_hid_gc_t gc, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2) +{ + dxf_ctx_t *ctx = &dxf_ctx; + fprintf(ctx->f, "0\nLINE\n"); + dxf_draw_handle(ctx); + dxf_draw_line_props(ctx, gc); + fprintf(ctx->f, "100\nAcDbLine\n"); + pcb_fprintf(ctx->f, "10\n%mm\n20\n%mm\n", TRX(x1), TRY(y1)); + pcb_fprintf(ctx->f, "11\n%mm\n21\n%mm\n", TRX(x2), TRY(y2)); +} + +static void dxf_fill_circle(pcb_hid_gc_t gc, pcb_coord_t cx, pcb_coord_t cy, pcb_coord_t r) +{ + dxf_ctx_t *ctx = &dxf_ctx; + fprintf(ctx->f, "0\nCIRCLE\n"); + dxf_draw_handle(ctx); + dxf_draw_line_props(ctx, &thin); + + /* contour, just in case the hatch fails */ + if (ctx->drill_contour) { + fprintf(ctx->f, "100\nAcDbCircle\n"); + pcb_fprintf(ctx->f, "10\n%mm\n20\n%mm\n", TRX(cx), TRY(cy)); + pcb_fprintf(ctx->f, "40\n%mm\n", r); + } + + /* hatch for fill circle: use it for copper or if explicitly requested */ + if (ctx->drill_fill || !gc->drawing_hole) { + dxf_hatch_pre(ctx, &thin, 1); + pcb_fprintf(ctx->f, "72\n2\n"); /* circular contour */ + pcb_fprintf(ctx->f, "10\n%mm\n20\n%mm\n", TRX(cx), TRY(cy)); + pcb_fprintf(ctx->f, "40\n%mm\n", r); + pcb_fprintf(ctx->f, "50\n0\n"); + pcb_fprintf(ctx->f, "51\n360\n"); + pcb_fprintf(ctx->f, "73\n1\n"); /* is closed */ + dxf_hatch_post(ctx); + } +} + +static void dxf_draw_arc(pcb_hid_gc_t gc, pcb_coord_t cx, pcb_coord_t cy, pcb_coord_t width, pcb_coord_t height, pcb_angle_t start_angle, pcb_angle_t delta_angle) +{ + pcb_angle_t end_angle, tmp; + dxf_ctx_t *ctx = &dxf_ctx; + + end_angle = start_angle + delta_angle; + + if (delta_angle < 0) { + tmp = start_angle; + start_angle = end_angle; + end_angle = tmp; + } + + start_angle -= 180; + end_angle -= 180; + if (end_angle >= 360) + end_angle -= 360; + if (end_angle < 0) + end_angle += 360; + + fprintf(ctx->f, "0\nARC\n"); + dxf_draw_handle(ctx); + dxf_draw_line_props(ctx, gc); + fprintf(ctx->f, "100\nAcDbCircle\n"); + pcb_fprintf(ctx->f, "10\n%mm\n20\n%mm\n", TRX(cx), TRY(cy)); + pcb_fprintf(ctx->f, "40\n%mm\n", (width + height)/2); + fprintf(ctx->f, "100\nAcDbArc\n"); + fprintf(ctx->f, "50\n%f\n", start_angle); + fprintf(ctx->f, "51\n%f\n", end_angle); +} + +static void dxf_fill_polygon_offs(pcb_hid_gc_t gc, int n_coords, pcb_coord_t *x, pcb_coord_t *y, pcb_coord_t dx, pcb_coord_t dy) +{ + dxf_ctx_t *ctx = &dxf_ctx; + int n, to; + +#if HATCH_NEEDS_BBOX + pcb_coord_t x_min, x_max, y_min, y_max; + x_max = x_min = *x + dx; + y_max = y_min = *y + dy; + for(n = 1; n < n_coords; n++) { + if (x[n] < x_min) x_min = x[n] + dx; + if (x[n] > x_max) x_max = x[n] + dx; + if (y[n] < y_min) y_min = y[n] + dy; + if (y[n] > y_max) y_max = y[n] + dy; + } +#endif + + if (ctx->poly_fill) { + dxf_hatch_pre(ctx, &thin, n_coords); + for(n = 0; n < n_coords; n++) { + to = n+1; + if (to == n_coords) + to = 0; + fprintf(ctx->f, "72\n1\n"); /* edge=line */ + pcb_fprintf(ctx->f, "10\n%mm\n20\n%mm\n", TRX(x[n]+dx), TRY(y[n]+dy)); + pcb_fprintf(ctx->f, "11\n%mm\n21\n%mm\n", TRX(x[to]+dx), TRY(y[to]+dy)); + } + dxf_hatch_post(ctx); + } + + if (ctx->poly_contour) { + for(n = 0; n < n_coords; n++) { + to = n+1; + if (to == n_coords) + to = 0; + dxf_draw_line(&thin, x[n]+dx, y[n]+dy, x[to]+dx, y[to]+dy); + } + } +} + + +static void dxf_fill_polygon(pcb_hid_gc_t gc, int n_coords, pcb_coord_t *x, pcb_coord_t *y) +{ + dxf_fill_polygon_offs(gc, n_coords, x, y, 0, 0); +} + +static void dxf_gen_layer(dxf_ctx_t *ctx, const char *name) +{ + fprintf(ctx->f, "0\nLAYER\n"); + dxf_draw_handle(ctx); + fprintf(ctx->f, "330\n2\n"); /* BLOCK_RECORD handle */ + fprintf(ctx->f, "100\nAcDbSymbolTableRecord\n"); + fprintf(ctx->f, "100\nAcDbLayerTableRecord\n"); + fprintf(ctx->f, "2\n%s\n", name); + fprintf(ctx->f, "70\n0\n"); /* flags */ + fprintf(ctx->f, "62\n7\n"); /* color */ + fprintf(ctx->f, "6\nCONTINUOUS\n"); /* default line type */ + fprintf(ctx->f, "370\n15\n"); /* default line width in 0.01mm */ + fprintf(ctx->f, "390\nF\n"); /* plot style */ +} Index: tags/2.1.2/src_plugins/export_dxf/dxf_templ.lht =================================================================== --- tags/2.1.2/src_plugins/export_dxf/dxf_templ.lht (nonexistent) +++ tags/2.1.2/src_plugins/export_dxf/dxf_templ.lht (revision 24813) @@ -0,0 +1,1554 @@ +ha:template { + trim_indent=1 + ha:template { + li:header { + verbatim { + 999 + dxfrw 0.5.11 + 0 + SECTION + 2 + HEADER + 9 + $ACADVER + 1 + AC1021 + 9 + $HANDSEED + 5 + 20000 + 9 + $DWGCODEPAGE + 3 + ANSI_1252 + 9 + $INSBASE + 10 + 0 + 20 + 0 + 30 + 0 + 9 + $EXTMIN + } + insert {extmin} + verbatim { + 9 + $EXTMAX + } + insert {extmax} + verbatim { + 9 + $LIMMIN + 10 + 0 + 20 + 0 + 9 + $LIMMAX + 10 + 420 + 20 + 297 + 9 + $ORTHOMODE + 70 + 0 + 9 + $LTSCALE + 40 + 1 + 9 + $TEXTSTYLE + 7 + STANDARD + 9 + $CLAYER + 8 + 0 + 9 + $DIMASZ + 40 + 2.5 + 9 + $DIMLFAC + 40 + 1 + 9 + $DIMSCALE + 40 + 1 + 9 + $DIMEXO + 40 + 0.625 + 9 + $DIMEXE + 40 + 1.25 + 9 + $DIMTXT + 40 + 2.5 + 9 + $DIMTSZ + 40 + 0 + 9 + $DIMAUNIT + 70 + 0 + 9 + $DIMADEC + 70 + 0 + 9 + $DIMLUNIT + 70 + 2 + 9 + $DIMSTYLE + 2 + STANDARD + 9 + $DIMGAP + 40 + 0.625 + 9 + $DIMTIH + 70 + 0 + 9 + $LUNITS + 70 + 2 + 9 + $LUPREC + 70 + 4 + 9 + $AUNITS + 70 + 0 + 9 + $AUPREC + 70 + 2 + 9 + $SPLINESEGS + 70 + 8 + 9 + $SNAPSTYLE + 70 + 0 + 9 + $PINSBASE + 10 + 0 + 20 + 0 + 30 + 0 + 9 + $PLIMMIN + 10 + 0 + 20 + 0 + 9 + $PLIMMAX + 10 + 210 + 20 + 297 + 9 + $INSUNITS + 70 + 4 + 9 + $PSVPSCALE + 40 + 1 + 0 + ENDSEC + 0 + SECTION + 2 + CLASSES + 0 + ENDSEC + 0 + SECTION + 2 + TABLES + 0 + TABLE + 2 + VPORT + 5 + 8 + 330 + 0 + 100 + AcDbSymbolTable + 70 + 1 + 0 + VPORT + 5 + 31 + 330 + 2 + 100 + AcDbSymbolTableRecord + 100 + AcDbViewportTableRecord + 2 + *ACTIVE + 70 + 0 + 10 + 0 + 20 + 0 + 11 + 1 + 21 + 1 + 12 + 73.375 + 22 + 51.875 + 13 + 0 + 23 + 0 + 14 + 10 + 24 + 10 + 15 + 10 + 25 + 10 + 16 + 0 + 26 + 0 + 36 + 1 + 17 + 0 + 27 + 0 + 37 + 0 + 40 + 116.25 + 41 + 1.36989247312 + 42 + 50 + 43 + 0 + 44 + 0 + 50 + 0 + 51 + 0 + 71 + 0 + 72 + 100 + 73 + 1 + 74 + 3 + 75 + 0 + 76 + 1 + 77 + 0 + 78 + 0 + 281 + 0 + 65 + 1 + 110 + 0 + 120 + 0 + 130 + 0 + 111 + 1 + 121 + 0 + 131 + 0 + 112 + 0 + 122 + 1 + 132 + 0 + 79 + 0 + 146 + 0 + 348 + 10020 + 60 + 7 + 61 + 5 + 292 + 1 + 282 + 1 + 141 + 0 + 142 + 0 + 63 + 250 + 421 + 3358443 + 0 + ENDTAB + 0 + TABLE + 2 + LTYPE + 5 + 5 + 330 + 0 + 100 + AcDbSymbolTable + 70 + 4 + 0 + LTYPE + 5 + 14 + 330 + 5 + 100 + AcDbSymbolTableRecord + 100 + AcDbLinetypeTableRecord + 2 + ByBlock + 70 + 0 + 3 + + 72 + 65 + 73 + 0 + 40 + 0 + 0 + LTYPE + 5 + 15 + 330 + 5 + 100 + AcDbSymbolTableRecord + 100 + AcDbLinetypeTableRecord + 2 + ByLayer + 70 + 0 + 3 + + 72 + 65 + 73 + 0 + 40 + 0 + 0 + LTYPE + 5 + 16 + 330 + 5 + 100 + AcDbSymbolTableRecord + 100 + AcDbLinetypeTableRecord + 2 + Continuous + 70 + 0 + 3 + Solid line + 72 + 65 + 73 + 0 + 40 + 0 + 0 + LTYPE + 5 + 32 + 330 + 5 + 100 + AcDbSymbolTableRecord + 100 + AcDbLinetypeTableRecord + 2 + DOT + 70 + 0 + 3 + Dot . . . . . . . . . . . . . . . . . . . . . . + 72 + 65 + 73 + 2 + 40 + 6.35 + 49 + 0 + 74 + 0 + 49 + -6.35 + 74 + 0 + 0 + LTYPE + 5 + 33 + 330 + 5 + 100 + AcDbSymbolTableRecord + 100 + AcDbLinetypeTableRecord + 2 + DOT2 + 70 + 0 + 3 + Dot (.5x) ..................................... + 72 + 65 + 73 + 2 + 40 + 3.175 + 49 + 0 + 74 + 0 + 49 + -3.175 + 74 + 0 + 0 + LTYPE + 5 + 34 + 330 + 5 + 100 + AcDbSymbolTableRecord + 100 + AcDbLinetypeTableRecord + 2 + DOTX2 + 70 + 0 + 3 + Dot (2x) . . . . . . . . . . . . . + 72 + 65 + 73 + 2 + 40 + 12.7 + 49 + 0 + 74 + 0 + 49 + -12.7 + 74 + 0 + 0 + LTYPE + 5 + 35 + 330 + 5 + 100 + AcDbSymbolTableRecord + 100 + AcDbLinetypeTableRecord + 2 + DASHED + 70 + 0 + 3 + Dot . . . . . . . . . . . . . . . . . . . . . . + 72 + 65 + 73 + 2 + 40 + 19.05 + 49 + 12.7 + 74 + 0 + 49 + -6.35 + 74 + 0 + 0 + LTYPE + 5 + 36 + 330 + 5 + 100 + AcDbSymbolTableRecord + 100 + AcDbLinetypeTableRecord + 2 + DASHED2 + 70 + 0 + 3 + Dashed (.5x) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + 72 + 65 + 73 + 2 + 40 + 9.525 + 49 + 6.35 + 74 + 0 + 49 + -3.175 + 74 + 0 + 0 + LTYPE + 5 + 37 + 330 + 5 + 100 + AcDbSymbolTableRecord + 100 + AcDbLinetypeTableRecord + 2 + DASHEDX2 + 70 + 0 + 3 + Dashed (2x) ____ ____ ____ ____ ____ ___ + 72 + 65 + 73 + 2 + 40 + 38.1 + 49 + 25.4 + 74 + 0 + 49 + -12.7 + 74 + 0 + 0 + LTYPE + 5 + 38 + 330 + 5 + 100 + AcDbSymbolTableRecord + 100 + AcDbLinetypeTableRecord + 2 + DASHDOT + 70 + 0 + 3 + Dash dot __ . __ . __ . __ . __ . __ . __ . __ + 72 + 65 + 73 + 4 + 40 + 25.4 + 49 + 12.7 + 74 + 0 + 49 + -6.35 + 74 + 0 + 49 + 0 + 74 + 0 + 49 + -6.35 + 74 + 0 + 0 + LTYPE + 5 + 39 + 330 + 5 + 100 + AcDbSymbolTableRecord + 100 + AcDbLinetypeTableRecord + 2 + DASHDOT2 + 70 + 0 + 3 + Dash dot (.5x) _._._._._._._._._._._._._._._. + 72 + 65 + 73 + 4 + 40 + 12.7 + 49 + 6.35 + 74 + 0 + 49 + -3.175 + 74 + 0 + 49 + 0 + 74 + 0 + 49 + -3.175 + 74 + 0 + 0 + LTYPE + 5 + 3A + 330 + 5 + 100 + AcDbSymbolTableRecord + 100 + AcDbLinetypeTableRecord + 2 + DASHDOTX2 + 70 + 0 + 3 + Dash dot (2x) ____ . ____ . ____ . ___ + 72 + 65 + 73 + 4 + 40 + 50.8 + 49 + 25.4 + 74 + 0 + 49 + -12.7 + 74 + 0 + 49 + 0 + 74 + 0 + 49 + -12.7 + 74 + 0 + 0 + LTYPE + 5 + 3B + 330 + 5 + 100 + AcDbSymbolTableRecord + 100 + AcDbLinetypeTableRecord + 2 + DIVIDE + 70 + 0 + 3 + Divide ____ . . ____ . . ____ . . ____ . . ____ + 72 + 65 + 73 + 6 + 40 + 31.75 + 49 + 12.7 + 74 + 0 + 49 + -6.35 + 74 + 0 + 49 + 0 + 74 + 0 + 49 + -6.35 + 74 + 0 + 49 + 0 + 74 + 0 + 49 + -6.35 + 74 + 0 + 0 + LTYPE + 5 + 3C + 330 + 5 + 100 + AcDbSymbolTableRecord + 100 + AcDbLinetypeTableRecord + 2 + DIVIDE2 + 70 + 0 + 3 + Divide (.5x) __..__..__..__..__..__..__..__.._ + 72 + 65 + 73 + 6 + 40 + 15.875 + 49 + 6.35 + 74 + 0 + 49 + -3.175 + 74 + 0 + 49 + 0 + 74 + 0 + 49 + -3.175 + 74 + 0 + 49 + 0 + 74 + 0 + 49 + -3.175 + 74 + 0 + 0 + LTYPE + 5 + 3D + 330 + 5 + 100 + AcDbSymbolTableRecord + 100 + AcDbLinetypeTableRecord + 2 + DIVIDEX2 + 70 + 0 + 3 + Divide (2x) ________ . . ________ . . _ + 72 + 65 + 73 + 6 + 40 + 63.5 + 49 + 25.4 + 74 + 0 + 49 + -12.7 + 74 + 0 + 49 + 0 + 74 + 0 + 49 + -12.7 + 74 + 0 + 49 + 0 + 74 + 0 + 49 + -12.7 + 74 + 0 + 0 + LTYPE + 5 + 3E + 330 + 5 + 100 + AcDbSymbolTableRecord + 100 + AcDbLinetypeTableRecord + 2 + BORDER + 70 + 0 + 3 + Border __ __ . __ __ . __ __ . __ __ . __ __ . + 72 + 65 + 73 + 6 + 40 + 44.45 + 49 + 12.7 + 74 + 0 + 49 + -6.35 + 74 + 0 + 49 + 12.7 + 74 + 0 + 49 + -6.35 + 74 + 0 + 49 + 0 + 74 + 0 + 49 + -6.35 + 74 + 0 + 0 + LTYPE + 5 + 3F + 330 + 5 + 100 + AcDbSymbolTableRecord + 100 + AcDbLinetypeTableRecord + 2 + BORDER2 + 70 + 0 + 3 + Border (.5x) __.__.__.__.__.__.__.__.__.__.__. + 72 + 65 + 73 + 6 + 40 + 22.225 + 49 + 6.35 + 74 + 0 + 49 + -3.175 + 74 + 0 + 49 + 6.35 + 74 + 0 + 49 + -3.175 + 74 + 0 + 49 + 0 + 74 + 0 + 49 + -3.175 + 74 + 0 + 0 + LTYPE + 5 + 40 + 330 + 5 + 100 + AcDbSymbolTableRecord + 100 + AcDbLinetypeTableRecord + 2 + BORDERX2 + 70 + 0 + 3 + Border (2x) ____ ____ . ____ ____ . ___ + 72 + 65 + 73 + 6 + 40 + 88.9 + 49 + 25.4 + 74 + 0 + 49 + -12.7 + 74 + 0 + 49 + 25.4 + 74 + 0 + 49 + -12.7 + 74 + 0 + 49 + 0 + 74 + 0 + 49 + -12.7 + 74 + 0 + 0 + LTYPE + 5 + 41 + 330 + 5 + 100 + AcDbSymbolTableRecord + 100 + AcDbLinetypeTableRecord + 2 + CENTER + 70 + 0 + 3 + Center ____ _ ____ _ ____ _ ____ _ ____ _ ____ + 72 + 65 + 73 + 4 + 40 + 50.8 + 49 + 31.75 + 74 + 0 + 49 + -6.35 + 74 + 0 + 49 + 6.35 + 74 + 0 + 49 + -6.35 + 74 + 0 + 0 + LTYPE + 5 + 42 + 330 + 5 + 100 + AcDbSymbolTableRecord + 100 + AcDbLinetypeTableRecord + 2 + CENTER2 + 70 + 0 + 3 + Center (.5x) ___ _ ___ _ ___ _ ___ _ ___ _ ___ + 72 + 65 + 73 + 4 + 40 + 28.575 + 49 + 19.05 + 74 + 0 + 49 + -3.175 + 74 + 0 + 49 + 3.175 + 74 + 0 + 49 + -3.175 + 74 + 0 + 0 + LTYPE + 5 + 43 + 330 + 5 + 100 + AcDbSymbolTableRecord + 100 + AcDbLinetypeTableRecord + 2 + CENTERX2 + 70 + 0 + 3 + Center (2x) ________ __ ________ __ _____ + 72 + 65 + 73 + 4 + 40 + 101.6 + 49 + 63.5 + 74 + 0 + 49 + -12.7 + 74 + 0 + 49 + 12.7 + 74 + 0 + 49 + -12.7 + 74 + 0 + 0 + ENDTAB + 0 + TABLE + 2 + LAYER + 5 + 2 + 330 + 0 + 100 + AcDbSymbolTable + 70 + 1 + 0 + LAYER + 5 + 10 + 330 + 2 + 100 + AcDbSymbolTableRecord + 100 + AcDbLayerTableRecord + 2 + 0 + 70 + 0 + 62 + 7 + 6 + CONTINUOUS + 370 + 0 + 390 + F + } + insert {layers} + verbatim { + 0 + ENDTAB + 0 + TABLE + 2 + STYLE + 5 + 3 + 330 + 0 + 100 + AcDbSymbolTable + 70 + 3 + 0 + STYLE + 5 + 44 + 330 + 2 + 100 + AcDbSymbolTableRecord + 100 + AcDbTextStyleTableRecord + 2 + Standard + 70 + 0 + 40 + 0 + 41 + 1 + 50 + 0 + 71 + 0 + 42 + 1 + 3 + txt + 4 + + 0 + ENDTAB + 0 + TABLE + 2 + VIEW + 5 + 6 + 330 + 0 + 100 + AcDbSymbolTable + 70 + 0 + 0 + ENDTAB + 0 + TABLE + 2 + UCS + 5 + 7 + 330 + 0 + 100 + AcDbSymbolTable + 70 + 0 + 0 + ENDTAB + 0 + TABLE + 2 + APPID + 5 + 9 + 330 + 0 + 100 + AcDbSymbolTable + 70 + 1 + 0 + APPID + 5 + 12 + 330 + 9 + 100 + AcDbSymbolTableRecord + 100 + AcDbRegAppTableRecord + 2 + ACAD + 70 + 0 + 0 + ENDTAB + 0 + TABLE + 2 + DIMSTYLE + 5 + A + 330 + 0 + 100 + AcDbSymbolTable + 70 + 1 + 100 + AcDbDimStyleTable + 71 + 1 + 0 + DIMSTYLE + 105 + 45 + 330 + A + 100 + AcDbSymbolTableRecord + 100 + AcDbDimStyleTableRecord + 2 + Standard + 70 + 0 + 40 + 1 + 41 + 2.5 + 42 + 0.625 + 43 + 0.38 + 44 + 1.25 + 45 + 0 + 46 + 0 + 47 + 0 + 48 + 0 + 140 + 2.5 + 141 + 0.09 + 142 + 0 + 143 + 25.4 + 144 + 1 + 145 + 0 + 146 + 1 + 147 + 0.625 + 148 + 0 + 71 + 0 + 72 + 0 + 73 + 0 + 74 + 1 + 75 + 0 + 76 + 0 + 77 + 0 + 78 + 0 + 79 + 0 + 170 + 0 + 171 + 2 + 172 + 0 + 173 + 0 + 174 + 0 + 175 + 0 + 176 + 0 + 177 + 0 + 178 + 0 + 179 + 0 + 271 + 4 + 272 + 4 + 273 + 2 + 274 + 2 + 275 + 0 + 276 + 0 + 277 + 2 + 278 + 46 + 279 + 0 + 280 + 0 + 281 + 0 + 282 + 0 + 283 + 1 + 284 + 0 + 285 + 0 + 286 + 0 + 288 + 0 + 289 + 3 + 340 + Standard + 341 + + 371 + -2 + 372 + -2 + 0 + ENDTAB + 0 + TABLE + 2 + BLOCK_RECORD + 5 + 1 + 330 + 0 + 100 + AcDbSymbolTable + 70 + 2 + 0 + BLOCK_RECORD + 5 + 1F + 330 + 1 + 100 + AcDbSymbolTableRecord + 100 + AcDbBlockTableRecord + 2 + *Model_Space + 70 + 0 + 280 + 1 + 281 + 0 + 0 + BLOCK_RECORD + 5 + 1E + 330 + 1 + 100 + AcDbSymbolTableRecord + 100 + AcDbBlockTableRecord + 2 + *Paper_Space + 70 + 0 + 280 + 1 + 281 + 0 + 0 + ENDTAB + 0 + ENDSEC + 0 + SECTION + 2 + BLOCKS + 0 + BLOCK + 5 + 20 + 330 + 1F + 100 + AcDbEntity + 8 + 0 + 100 + AcDbBlockBegin + 2 + *Model_Space + 70 + 0 + 10 + 0 + 20 + 0 + 30 + 0 + 3 + *Model_Space + 1 + + 0 + ENDBLK + 5 + 21 + 330 + 1F + 100 + AcDbEntity + 8 + 0 + 100 + AcDbBlockEnd + 0 + BLOCK + 5 + 1C + 330 + 1B + 100 + AcDbEntity + 8 + 0 + 100 + AcDbBlockBegin + 2 + *Paper_Space + 70 + 0 + 10 + 0 + 20 + 0 + 30 + 0 + 3 + *Paper_Space + 1 + + 0 + ENDBLK + 5 + 1D + 330 + 1F + 100 + AcDbEntity + 8 + 0 + 100 + AcDbBlockEnd + 0 + ENDSEC + 0 + SECTION + 2 + ENTITIES + } + } + li:footer { + verbatim { + 0 + ENDSEC + 0 + SECTION + 2 + OBJECTS + 0 + DICTIONARY + 5 + C + 330 + 0 + 100 + AcDbDictionary + 281 + 1 + 3 + ACAD_GROUP + 350 + D + 0 + DICTIONARY + 5 + D + 330 + C + 100 + AcDbDictionary + 281 + 1 + 0 + ENDSEC + 0 + EOF + } + } + } +} Index: tags/2.1.2/src_plugins/export_dxf/export_dxf.pup =================================================================== --- tags/2.1.2/src_plugins/export_dxf/export_dxf.pup (nonexistent) +++ tags/2.1.2/src_plugins/export_dxf/export_dxf.pup (revision 24813) @@ -0,0 +1,9 @@ +$class export +$short DXF pcb_exporter +$long Export dxf +$state works +$fmt-native no +$fmt-feature-w export to 2D .dxf (for mech CADs) +$package export +default buildin +autoload 1 Index: tags/2.1.2/src_plugins/export_dxf/lht_template.c =================================================================== --- tags/2.1.2/src_plugins/export_dxf/lht_template.c (nonexistent) +++ tags/2.1.2/src_plugins/export_dxf/lht_template.c (revision 24813) @@ -0,0 +1,129 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2017 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +/* Generate output using a lihata template */ + +#ifndef TESTER +#include "config.h" +#endif + + +#include +#include +#include +#include +#include +#include +#include "lht_template.h" + +static void verbatim(FILE *f, const char *prefix, const char *value, int trim_indent) +{ + const char *s, *next; + int indent_len = 0; + if (*value == '\n') + value++; + + if (trim_indent) + for(s = value; isspace(*s); s++) + indent_len++; + + for(s = value; *s != '\0'; s = next) { + if (trim_indent) { + int n; + for(n = 0; (n < indent_len) && (isspace(*s)); n++) s++; + } + next = strpbrk(s, "\r\n"); + if (next == NULL) { + fprintf(f, "%s%s", prefix, s); + break; + } + while((*next == '\r') || (*next == '\n')) next++; + fprintf(f, "%s", prefix); + fwrite(s, 1, next-s, f); + } +} + +int lht_temp_exec(FILE *f, const char *prefix, lht_doc_t *doc, const char *name, lht_temp_insert_t ins, lht_err_t *err) +{ + lht_node_t *t, *n, *cfg; + int trim_indent = 0; + + if (prefix == NULL) + prefix = ""; + + t = lht_tree_path(doc, "/template", name, 1, err); + if (t == NULL) + return -1; + + if (t->type != LHT_LIST) { + *err = LHTE_INVALID_TYPE; + return -1; + } + + cfg = lht_tree_path(doc, "/", "trim_indent", 1, NULL); + if ((cfg != NULL) && (cfg->type == LHT_TEXT) && (cfg->data.text.value != NULL)) + trim_indent = ((strcmp(cfg->data.text.value, "1") == 0) || (strcmp(cfg->data.text.value, "yes") == 0) || (strcmp(cfg->data.text.value, "true") == 0)); + + for(n = t->data.list.first; n != NULL; n = n->next) { + if (strcmp(n->name, "verbatim") == 0) + verbatim(f, prefix, n->data.text.value, trim_indent); + if (strcmp(n->name, "insert") == 0) { + int res = ins(f, prefix, n->data.text.value, err); + if (res != 0) + return res; + } + } + + return 0; +} + +#ifdef TESTER +int ins_(FILE *f, const char *prefix, char *name, lht_err_t *err) +{ + printf("INSERT: %s\n", name); + return 0; +} + +int main() +{ + lht_doc_t *doc; + lht_err_t err; + char *errmsg; + const char *fn = "dxf_templ.lht"; + + /* do not do safe_fs here - it's just a test code that never ends up in pcb_rnd */ + doc = lht_dom_load(fn, &errmsg); + if (doc == NULL) { + fprintf(stderr, "Error loading %s: %s\n", fn, errmsg); + exit(1); + } + + lht_temp_exec(stdout, "", doc, "header", ins_, &err); + + lht_dom_uninit(doc); + return 0; +} +#endif Index: tags/2.1.2/src_plugins/export_dxf/lht_template.h =================================================================== --- tags/2.1.2/src_plugins/export_dxf/lht_template.h (nonexistent) +++ tags/2.1.2/src_plugins/export_dxf/lht_template.h (revision 24813) @@ -0,0 +1,10 @@ +#ifndef PCB_LHT_TEMPLATE_H +#define PCB_LHT_TEMPLATE_H +#include +#include + +typedef int (*lht_temp_insert_t)(FILE *f, const char *prefix, char *name, lht_err_t *err); + +int lht_temp_exec(FILE *f, const char *prefix, lht_doc_t *doc, const char *name, lht_temp_insert_t ins, lht_err_t *err); + +#endif Index: tags/2.1.2/src_plugins/export_fidocadj/Makefile =================================================================== --- tags/2.1.2/src_plugins/export_fidocadj/Makefile (nonexistent) +++ tags/2.1.2/src_plugins/export_fidocadj/Makefile (revision 24813) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_export_fidocadj + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/2.1.2/src_plugins/export_fidocadj/Plug.tmpasm =================================================================== --- tags/2.1.2/src_plugins/export_fidocadj/Plug.tmpasm (nonexistent) +++ tags/2.1.2/src_plugins/export_fidocadj/Plug.tmpasm (revision 24813) @@ -0,0 +1,8 @@ +put /local/pcb/mod {export_fidocadj} +put /local/pcb/mod/OBJS [@ $(PLUGDIR)/export_fidocadj/fidocadj.o @] + +switch /local/pcb/export_fidocadj/controls + case {buildin} include /local/pcb/tmpasm/buildin; end; + case {plugin} include /local/pcb/tmpasm/plugin; end; + case {disable} include /local/pcb/tmpasm/disable; end; +end Index: tags/2.1.2/src_plugins/export_fidocadj/export_fidocadj.pup =================================================================== --- tags/2.1.2/src_plugins/export_fidocadj/export_fidocadj.pup (nonexistent) +++ tags/2.1.2/src_plugins/export_fidocadj/export_fidocadj.pup (revision 24813) @@ -0,0 +1,10 @@ +$class export +$short FidoCadJ .fcd pcb_exporter +$long Export to FidoCadJ format (.fcd) +$state WIP +$fmt-native no +$fmt-feature-w partial export in fidocad .fcd format +$package export-extra +dep lib_compat_help +default buildin +autoload 1 Index: tags/2.1.2/src_plugins/export_fidocadj/fidocadj.c =================================================================== --- tags/2.1.2/src_plugins/export_fidocadj/fidocadj.c (nonexistent) +++ tags/2.1.2/src_plugins/export_fidocadj/fidocadj.c (revision 24813) @@ -0,0 +1,393 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 2017 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +/* + * Based on the png exporter by Dan McMahill + */ + +#include "config.h" +#include "conf_core.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "genht/htsi.h" + +#include "math_helper.h" +#include "board.h" +#include "data.h" +#include "layer_vis.h" +#include "plugins.h" +#include "pcb-printf.h" +#include "compat_misc.h" +#include "plug_io.h" +#include "safe_fs.h" + +#include "hid.h" +#include "hid_nogui.h" +#include "hid_draw_helpers.h" + +#include "hid_init.h" +#include "hid_attrib.h" +#include "hid_color.h" +#include "hid_cam.h" + +#include "../src_plugins/lib_compat_help/pstk_compat.h" + +static pcb_hid_t fidocadj_hid; + +const char *fidocadj_cookie = "fidocadj HID"; + +pcb_hid_attribute_t fidocadj_attribute_list[] = { + /* other HIDs expect this to be first. */ + + {"outfile", "Output file name", + PCB_HATT_STRING, 0, 0, {0, 0, 0}, 0, 0}, +#define HA_fidocadjfile 0 + + {"libfile", "path to PCB.fcl", + PCB_HATT_STRING, 0, 0, {0, 0, 0}, 0, 0}, +#define HA_libfile 1 +}; + +#define NUM_OPTIONS (sizeof(fidocadj_attribute_list)/sizeof(fidocadj_attribute_list[0])) + +PCB_REGISTER_ATTRIBUTES(fidocadj_attribute_list, fidocadj_cookie) + +static pcb_hid_attr_val_t fidocadj_values[NUM_OPTIONS]; + +static pcb_hid_attribute_t *fidocadj_get_export_options(int *n) +{ + const char *suffix = ".fcd"; + + if ((PCB != NULL) && (fidocadj_attribute_list[HA_fidocadjfile].default_val.str_value == NULL)) + pcb_derive_default_filename(PCB->Filename, &fidocadj_attribute_list[HA_fidocadjfile], suffix); + + if (n) + *n = NUM_OPTIONS; + return fidocadj_attribute_list; +} + +/* index PCB.fcl so we have a list of known fidocadj footprints */ +static int load_lib(htsi_t *ht, const char *fn) +{ + FILE *f; + char line[1024]; + f = pcb_fopen(fn, "r"); + if (f == NULL) { + pcb_message(PCB_MSG_ERROR, "Can't open fidocadj PCB library file '%s' for read\n", fn); + return -1; + } + *line = '\0'; + fgets(line, sizeof(line), f); + if (pcb_strncasecmp(line, "[FIDOLIB PCB Footprints]", 24) != 0) { + pcb_message(PCB_MSG_ERROR, "'%s' doesn't have the fidocadj lib header\n", fn); + fclose(f); + return -1; + } + while(fgets(line, sizeof(line), f) != NULL) { + char *end, *s = line; + + if (*line != '[') + continue; + + s++; + end = strchr(s, ' '); + if (end != NULL) { + *end = '\0'; + htsi_set(ht, pcb_strdup(s), 1); + } + } + fclose(f); + return 0; +} + +static long int crd(pcb_coord_t c) +{ + return pcb_round((double)PCB_COORD_TO_MIL(c) / 5.0); +} + +static int layer_map(unsigned int lflg, int *fidoly_next, const char *lyname) +{ + if (lflg & PCB_LYT_COPPER) { + if (lflg & PCB_LYT_BOTTOM) + return 1; + if (lflg & PCB_LYT_TOP) + return 2; + } + if (lflg & PCB_LYT_SILK) + return 3; + + (*fidoly_next)++; + if (*fidoly_next > 15) { + char *msg = pcb_strdup_printf("FidoCadJ can't handle this many layers - layer %s is not exported\n", lyname); + pcb_io_incompat_save(NULL, NULL, "layer", msg, NULL); + free(msg); + return -1; + } + return *fidoly_next; +} + +static void write_custom_subc(FILE *f, pcb_subc_t *sc) +{ + char *msg = pcb_strdup_printf("Can't export custom footprint for %s yet\n", sc->refdes); + pcb_io_incompat_save(sc->parent.data, (pcb_any_obj_t *)sc, msg, "subc", "subcircuit omitted - add the footprint type on the footprint list!"); + free(msg); +} + +static void fidocadj_do_export(pcb_hid_attr_val_t * options) +{ + FILE *f; + const char *filename, *libfile; + int n, fidoly_next, have_lib; + pcb_layer_id_t lid; + htsi_t lib_names; /* hash of names found in the library, if have_lib is 1 */ + + if (!options) { + fidocadj_get_export_options(0); + for (n = 0; n < NUM_OPTIONS; n++) + fidocadj_values[n] = fidocadj_attribute_list[n].default_val; + options = fidocadj_values; + } + + libfile = options[HA_libfile].str_value; + if ((libfile != NULL) && (*libfile != '\0')) { + htsi_init(&lib_names, strhash, strkeyeq); + have_lib = 1; + if (load_lib(&lib_names, libfile) != 0) + goto free_lib; + } + else + have_lib = 0; + + filename = options[HA_fidocadjfile].str_value; + if (!filename) + filename = "pcb-rnd-default.fcd"; + + f = pcb_fopen(filename, "w"); + if (!f) { + perror(filename); + return; + } + + fprintf(f, "[FIDOCAD]\n"); + + fidoly_next = 3; + for(lid = 0; lid < pcb_max_layer; lid++) { + pcb_layer_t *ly = PCB->Data->Layer+lid; + unsigned int lflg = pcb_layer_flags(PCB, lid); + int fidoly = layer_map(lflg, &fidoly_next, ly->name); + + if (fidoly < 0) + continue; + + PCB_LINE_LOOP(ly) { + fprintf(f, "PL %ld %ld %ld %ld %ld %d\n", + crd(line->Point1.X), crd(line->Point1.Y), + crd(line->Point2.X), crd(line->Point2.Y), + crd(line->Thickness), fidoly); + } + PCB_END_LOOP; + + PCB_ARC_LOOP(ly) { +TODO(": fprintf() some curve using arc->*") + ; + } + PCB_END_LOOP; + + PCB_POLY_LOOP(ly) { + pcb_vnode_t *v; + pcb_pline_t *pl = polygon->Clipped->contours; + + if (polygon->HoleIndexN > 0) { + pcb_io_incompat_save(PCB->Data, (pcb_any_obj_t *)polygon, "polygon", "FidoCadJ can't handle holes in polygons, ignoring holes for this export", "(some of the polygons will look different unless you remove the holes or split up the polygons)"); + } + + fprintf(f, "PP %ld %ld", crd(pl->head.point[0]), crd(pl->head.point[1])); + v = pl->head.next; + do { + fprintf(f, " %ld %ld", crd(v->point[0]), crd(v->point[1])); + } while ((v = v->next) != pl->head.next); + fprintf(f, " %d\n", fidoly); + } + PCB_END_LOOP; + + PCB_TEXT_LOOP(ly) { + char *s; + /* default_font 'm' = 4189 wide + * default_font 'l', starts at y = 1000 + * default_font 'p','q', finish at y = 6333 + * default_font stroke thickness = 800 + * giving sx = (4189+800)/(5333+800) ~= 0.813 + */ + pcb_coord_t x0 = text->X; + /*pcb_coord_t sx = text->BoundingBox.X2 - text->BoundingBox.X1; unused */ + pcb_coord_t y0 = text->Y; + /* pcb_coord_t sy = text->BoundingBox.Y2 - text->BoundingBox.Y1; unused */ + pcb_coord_t glyphy = 5789*(text->Scale); /* (ascent+descent)*Scale */ + pcb_coord_t glyphx = 813*(glyphy/1000); /* based on 'm' glyph dimensions */ + glyphy = 10*glyphy/7; /* empirically determined */ + glyphx = 10*glyphx/7; /* scaling voodoo */ + /*switch(text->Direction) { + case 0: + x0 += sx; + break; + case 1: + y0 += sy; + break; + case 2: + x0 -= sx; + break; + case 3: + y0 -= sy; + break; + }*/ +TODO("textrot: can we exprot rotation with %f?") + fprintf(f, "TY %ld %ld %ld %ld %d 1 %d * ", /* 1 = bold */ + crd(x0), crd(y0), crd(glyphy), crd(glyphx), + (int)pcb_round(text->rot), fidoly); + for(s = text->TextString; *s != '\0'; s++) { + if (*s == ' ') + fprintf(f, "++"); + else + fputc(*s, f); + } + fputc('\n', f); + } + PCB_END_LOOP; + } + + PCB_PADSTACK_LOOP(PCB->Data) { + int oshape; + pcb_coord_t x, y, drill_dia, pad_dia, clearance, mask; + pcb_pstk_compshape_t cshape; + pcb_bool plated; + if (!pcb_pstk_export_compat_via(padstack, &x, &y, &drill_dia, &pad_dia, &clearance, &mask, &cshape, &plated)) { + pcb_io_incompat_save(PCB->Data, (pcb_any_obj_t *)padstack, "padstack-uniformity", "can't export non-uniform padstacl", "use a simpler padstack - omiting this one from the export"); + continue; + } + switch(cshape) { + case PCB_PSTK_COMPAT_OCTAGON: + pcb_io_incompat_save(PCB->Data, (pcb_any_obj_t *)padstack, "padstack-shape", "can't export octagonal shape", "use round or square instead; (fallback to round for now)"); + /* fall-through */ + case PCB_PSTK_COMPAT_ROUND: oshape = 0; break; + case PCB_PSTK_COMPAT_SQUARE: oshape = 1; break; /* rectangle with sharp corners */ + default: + pcb_io_incompat_save(PCB->Data, (pcb_any_obj_t *)padstack, "padstack-shape", "can't export shaped padstack", "use round or square instead; (fallback to round for now)"); + oshape = 0; + } + fprintf(f, "pa %ld %ld %ld %ld %ld %d\n", crd(x), crd(y), crd(pad_dia), crd(pad_dia), crd(drill_dia), oshape); + } + PCB_END_LOOP; + + PCB_SUBC_LOOP(PCB->Data) { + const char *fp = pcb_attribute_get(&subc->Attributes, "footprint"); + if ((fp != NULL) && have_lib && (htsi_get(&lib_names, fp))) { + pcb_coord_t x, y; + double rot = 0.0; + int on_bottom = 0; + if (pcb_subc_get_origin(subc, &x, &y)) { + pcb_io_incompat_save(PCB->Data, (pcb_any_obj_t *)subc, "subc", "can't figure subcircuit origin", "omitting this part until the proper subc-aux layer objects are added"); + continue; + } + pcb_subc_get_rotation(subc, &rot); + pcb_subc_get_side(subc, &on_bottom); + +TODO(": figure how to store rotation") +TODO(": figure how to store side") + fprintf(f, "MC %ld %ld %d 0 %s\n", crd(x), crd(y), 0, fp); + } + else + write_custom_subc(f, subc); + } + PCB_END_LOOP; + + + fclose(f); + + free_lib:; + if (have_lib) { + htsi_entry_t *e; + for (e = htsi_first(&lib_names); e; e = htsi_next(&lib_names, e)) + free(e->key); + + htsi_uninit(&lib_names); + } +} + +static int fidocadj_parse_arguments(int *argc, char ***argv) +{ + pcb_hid_register_attributes(fidocadj_attribute_list, sizeof(fidocadj_attribute_list) / sizeof(fidocadj_attribute_list[0]), fidocadj_cookie, 0); + return pcb_hid_parse_command_line(argc, argv); +} + +static int fidocadj_usage(const char *topic) +{ + fprintf(stderr, "\nfidocadj exporter command line arguments:\n\n"); + pcb_hid_usage(fidocadj_attribute_list, sizeof(fidocadj_attribute_list) / sizeof(fidocadj_attribute_list[0])); + fprintf(stderr, "\nUsage: pcb-rnd [generic_options] -x fidocadj [fidocadj options] foo.pcb\n\n"); + return 0; +} + +#include "dolists.h" + +int pplg_check_ver_export_fidocadj(int ver_needed) { return 0; } + +void pplg_uninit_export_fidocadj(void) +{ + pcb_hid_remove_attributes_by_cookie(fidocadj_cookie); +} + +int pplg_init_export_fidocadj(void) +{ + PCB_API_CHK_VER; + + memset(&fidocadj_hid, 0, sizeof(pcb_hid_t)); + + pcb_hid_nogui_init(&fidocadj_hid); + pcb_dhlp_draw_helpers_init(&fidocadj_hid); + + fidocadj_hid.struct_size = sizeof(pcb_hid_t); + fidocadj_hid.name = "fidocadj"; + fidocadj_hid.description = "export board in FidoCadJ .fcd format"; + fidocadj_hid.exporter = 1; + + fidocadj_hid.get_export_options = fidocadj_get_export_options; + fidocadj_hid.do_export = fidocadj_do_export; + fidocadj_hid.parse_arguments = fidocadj_parse_arguments; + + fidocadj_hid.usage = fidocadj_usage; + + pcb_hid_register_hid(&fidocadj_hid); + + return 0; +} Index: tags/2.1.2/src_plugins/export_gcode/Makefile =================================================================== --- tags/2.1.2/src_plugins/export_gcode/Makefile (nonexistent) +++ tags/2.1.2/src_plugins/export_gcode/Makefile (revision 24813) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_export_gcode + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/2.1.2/src_plugins/export_gcode/Plug.tmpasm =================================================================== --- tags/2.1.2/src_plugins/export_gcode/Plug.tmpasm (nonexistent) +++ tags/2.1.2/src_plugins/export_gcode/Plug.tmpasm (revision 24813) @@ -0,0 +1,17 @@ +put /local/pcb/mod {export_gcode} +put /local/pcb/mod/OBJS [@ $(PLUGDIR)/export_gcode/gcode.o $(PLUGDIR)/export_gcode/decompose.o $(PLUGDIR)/export_gcode/trace.o $(PLUGDIR)/export_gcode/curve.o @] + +switch /local/pcb/export_gcode/controls + case {disable} end; + default + put /local/pcb/mod/LDFLAGS libs/gui/gd/ldflags + put /local/pcb/mod/CFLAGS libs/gui/gd/cflags + end +end + + +switch /local/pcb/export_gcode/controls + case {buildin} include /local/pcb/tmpasm/buildin; end; + case {plugin} include /local/pcb/tmpasm/plugin; end; + case {disable} include /local/pcb/tmpasm/disable; end; +end Index: tags/2.1.2/src_plugins/export_gcode/auxiliary.h =================================================================== --- tags/2.1.2/src_plugins/export_gcode/auxiliary.h (nonexistent) +++ tags/2.1.2/src_plugins/export_gcode/auxiliary.h (revision 24813) @@ -0,0 +1,80 @@ +/* Copyright (C) 2001-2007 Peter Selinger. + This file is part of Potrace. It is free software and it is covered + by the GNU General Public License. See the file COPYING for details. */ + +/* This header file collects some general-purpose macros (and static + inline functions) that are used in various places. */ + +#ifndef AUXILIARY_H +#define AUXILIARY_H + +#include "config.h" + +/* ---------------------------------------------------------------------- */ +/* point arithmetic */ + +#include "potracelib.h" + +struct point_s { + long x; + long y; +}; +typedef struct point_s point_t; + +typedef potrace_dpoint_t dpoint_t; + +/* convert point_t to dpoint_t */ +PCB_INLINE dpoint_t dpoint(point_t p) +{ + dpoint_t res; + res.x = p.x; + res.y = p.y; + return res; +} + +/* range over the straight line segment [a,b] when lambda ranges over [0,1] */ +PCB_INLINE dpoint_t interval(double lambda, dpoint_t a, dpoint_t b) +{ + dpoint_t res; + + res.x = a.x + lambda * (b.x - a.x); + res.y = a.y + lambda * (b.y - a.y); + return res; +} + +/* ---------------------------------------------------------------------- */ +/* Note: the "mod" function works correctly for + negative a. Also note that the test for a>=n, while redundant, + speeds up the mod function by 70% in the average case (significant + since the program spends about 16% of its time here - or 40% + without the test). The "floordiv" function returns the largest integer + <= a/n, and again this works correctly for negative a, as long as + a,n are integers and n>0. */ + +/* integer arithmetic */ + +PCB_INLINE int mod(int a, int n) +{ + return a >= n ? a % n : a >= 0 ? a : n - 1 - (-1 - a) % n; +} + +PCB_INLINE int floordiv(int a, int n) +{ + return a >= 0 ? a / n : -1 - (-1 - a) / n; +} + +/* Note: the following work for integers and other numeric types. */ +#undef sign +#undef abs +#undef min +#undef max +#undef sq +#undef cu +#define sign(x) ((x)>0 ? 1 : (x)<0 ? -1 : 0) +#define abs(a) ((a)>0 ? (a) : -(a)) +#define min(a,b) ((a)<(b) ? (a) : (b)) +#define max(a,b) ((a)>(b) ? (a) : (b)) +#define sq(a) ((a)*(a)) +#define cu(a) ((a)*(a)*(a)) + +#endif /* AUXILIARY_H */ Index: tags/2.1.2/src_plugins/export_gcode/bitmap.h =================================================================== --- tags/2.1.2/src_plugins/export_gcode/bitmap.h (nonexistent) +++ tags/2.1.2/src_plugins/export_gcode/bitmap.h (revision 24813) @@ -0,0 +1,104 @@ +/* Copyright (C) 2001-2007 Peter Selinger. + This file is part of Potrace. It is free software and it is covered + by the GNU General Public License. See the file COPYING for details. */ + +#ifndef BITMAP_H +#define BITMAP_H + +#include "config.h" + +#include +#include + +/* The bitmap type is defined in potracelib.h */ +#include "potracelib.h" + +/* The present file defines some convenient macros and static inline + functions for accessing bitmaps. Since they only produce inline + code, they can be conveniently shared by the library and frontends, + if desired */ + +/* ---------------------------------------------------------------------- */ +/* some measurements */ + +#define BM_WORDSIZE ((int)sizeof(potrace_word)) +#define BM_WORDBITS (8*BM_WORDSIZE) +#define BM_HIBIT (((potrace_word)1)<<(BM_WORDBITS-1)) +#define BM_ALLBITS (~(potrace_word)0) + +/* macros for accessing pixel at index (x,y). U* macros omit the + bounds check. */ + +#define bm_scanline(bm, y) ((bm)->map + (y)*(bm)->dy) +#define bm_index(bm, x, y) (&bm_scanline(bm, y)[(x)/BM_WORDBITS]) +#define bm_mask(x) (BM_HIBIT >> ((x) & (BM_WORDBITS-1))) +#define bm_range(x, a) ((int)(x) >= 0 && (int)(x) < (a)) +#define bm_safe(bm, x, y) (bm_range(x, (bm)->w) && bm_range(y, (bm)->h)) +#define BM_UGET(bm, x, y) ((*bm_index(bm, x, y) & bm_mask(x)) != 0) +#define BM_USET(bm, x, y) (*bm_index(bm, x, y) |= bm_mask(x)) +#define BM_UCLR(bm, x, y) (*bm_index(bm, x, y) &= ~bm_mask(x)) +#define BM_UINV(bm, x, y) (*bm_index(bm, x, y) ^= bm_mask(x)) +#define BM_UPUT(bm, x, y, b) ((b) ? BM_USET(bm, x, y) : BM_UCLR(bm, x, y)) +#define BM_GET(bm, x, y) (bm_safe(bm, x, y) ? BM_UGET(bm, x, y) : 0) +#define BM_SET(bm, x, y) (bm_safe(bm, x, y) ? BM_USET(bm, x, y) : 0) +#define BM_CLR(bm, x, y) (bm_safe(bm, x, y) ? BM_UCLR(bm, x, y) : 0) +#define BM_INV(bm, x, y) (bm_safe(bm, x, y) ? BM_UINV(bm, x, y) : 0) +#define BM_PUT(bm, x, y, b) (bm_safe(bm, x, y) ? BM_UPUT(bm, x, y, b) : 0) + +/* free the given bitmap. Leaves errno untouched. */ +PCB_INLINE void bm_free(potrace_bitmap_t * bm) +{ + if (bm) { + free(bm->map); + } + free(bm); +} + +/* return new un-initialized bitmap. NULL with errno on error */ +PCB_INLINE potrace_bitmap_t *bm_new(int w, int h) +{ + potrace_bitmap_t *bm; + int dy = (w + BM_WORDBITS - 1) / BM_WORDBITS; + + bm = (potrace_bitmap_t *) malloc(sizeof(potrace_bitmap_t)); + if (!bm) { + return NULL; + } + bm->w = w; + bm->h = h; + bm->dy = dy; + bm->map = (potrace_word *) malloc(dy * h * BM_WORDSIZE); + if (!bm->map) { + free(bm); + return NULL; + } + return bm; +} + +/* clear the given bitmap. Set all bits to c. */ +PCB_INLINE void bm_clear(potrace_bitmap_t * bm, int c) +{ + memset(bm->map, c ? -1 : 0, bm->dy * bm->h * BM_WORDSIZE); +} + +/* duplicate the given bitmap. Return NULL on error with errno set. */ +PCB_INLINE potrace_bitmap_t *bm_dup(const potrace_bitmap_t * bm) +{ + potrace_bitmap_t *bm1 = bm_new(bm->w, bm->h); + if (!bm1) { + return NULL; + } + memcpy(bm1->map, bm->map, bm->dy * bm->h * BM_WORDSIZE); + return bm1; +} + +/* invert the given bitmap. */ +PCB_INLINE void bm_invert(potrace_bitmap_t * bm) +{ + int i; + for (i = 0; i < bm->dy * bm->h; i++) { + bm->map[i] ^= BM_ALLBITS; + } +} + +#endif /* BITMAP_H */ Index: tags/2.1.2/src_plugins/export_gcode/curve.c =================================================================== --- tags/2.1.2/src_plugins/export_gcode/curve.c (nonexistent) +++ tags/2.1.2/src_plugins/export_gcode/curve.c (revision 24813) @@ -0,0 +1,115 @@ +/* Copyright (C) 2001-2007 Peter Selinger. + This file is part of Potrace. It is free software and it is covered + by the GNU General Public License. See the file COPYING for details. */ + +/* $Id: curve.c 147 2007-04-09 00:44:09Z selinger $ */ +/* private part of the path and curve data structures */ + +#include +#include +#include + +#include "config.h" +#include "potracelib.h" +#include "lists.h" +#include "curve.h" + +#define SAFE_MALLOC(var, n, typ) \ + if ((var = (typ *)malloc((n)*sizeof(typ))) == NULL) goto malloc_error + +/* ---------------------------------------------------------------------- */ +/* allocate and free path objects */ + +path_t *path_new(void) +{ + path_t *p = NULL; + privpath_t *priv = NULL; + + SAFE_MALLOC(p, 1, path_t); + memset(p, 0, sizeof(path_t)); + SAFE_MALLOC(priv, 1, privpath_t); + memset(priv, 0, sizeof(privpath_t)); + p->priv = priv; + return p; + +malloc_error: + free(p); + free(priv); + return NULL; +} + +/* free the members of the given curve structure. Leave errno unchanged. */ +static void privcurve_free_members(privcurve_t * curve) +{ + free(curve->tag); + free(curve->c); + free(curve->vertex); + free(curve->alpha); + free(curve->alpha0); + free(curve->beta); +} + +/* free a path. Leave errno untouched. */ +void path_free(path_t * p) +{ + if (p) { + if (p->priv) { + free(p->priv->pt); + free(p->priv->lon); + free(p->priv->sums); + free(p->priv->po); + privcurve_free_members(&p->priv->curve); + privcurve_free_members(&p->priv->ocurve); + } + free(p->priv); + /* do not free p->fcurve ! */ + } + free(p); +} + +/* free a pathlist, leaving errno untouched. */ +void pathlist_free(path_t * plist) +{ + path_t *p; + + list_forall_unlink(p, plist) { + path_free(p); + } +} + +/* ---------------------------------------------------------------------- */ +/* initialize and finalize curve structures */ + +typedef dpoint_t dpoint3_t[3]; + +/* initialize the members of the given curve structure to size m. + Return 0 on success, 1 on error with errno set. */ +int privcurve_init(privcurve_t * curve, int n) +{ + memset(curve, 0, sizeof(privcurve_t)); + curve->n = n; + SAFE_MALLOC(curve->tag, n, int); + SAFE_MALLOC(curve->c, n, dpoint3_t); + SAFE_MALLOC(curve->vertex, n, dpoint_t); + SAFE_MALLOC(curve->alpha, n, double); + SAFE_MALLOC(curve->alpha0, n, double); + SAFE_MALLOC(curve->beta, n, double); + return 0; + +malloc_error: + free(curve->tag); + free(curve->c); + free(curve->vertex); + free(curve->alpha); + free(curve->alpha0); + free(curve->beta); + return 1; +} + +/* copy private to public curve structure */ +void privcurve_to_curve(privcurve_t * pc, potrace_curve_t * c) +{ + c->n = pc->n; + c->tag = pc->tag; + c->c = pc->c; +} Index: tags/2.1.2/src_plugins/export_gcode/curve.h =================================================================== --- tags/2.1.2/src_plugins/export_gcode/curve.h (nonexistent) +++ tags/2.1.2/src_plugins/export_gcode/curve.h (revision 24813) @@ -0,0 +1,76 @@ +/* Copyright (C) 2001-2007 Peter Selinger. + This file is part of Potrace. It is free software and it is covered + by the GNU General Public License. See the file COPYING for details. */ + +#ifndef CURVE_H +#define CURVE_H + +#include "auxiliary.h" + +/* vertex is c[1] for tag=POTRACE_CORNER, and the intersection of + .c[-1][2]..c[0] and c[1]..c[2] for tag=POTRACE_CURVETO. alpha is only + defined for tag=POTRACE_CURVETO and is the alpha parameter of the curve: + .c[-1][2]..c[0] = alpha*(.c[-1][2]..vertex), and + c[2]..c[1] = alpha*(c[2]..vertex). + Beta is so that (.beta[i])[.vertex[i],.vertex[i+1]] = .c[i][2]. +*/ + +struct privcurve_s { + int n; /* number of segments */ + int *tag; /* tag[n]: POTRACE_CORNER or POTRACE_CURVETO */ + dpoint_t(*c)[3]; /* c[n][i]: control points. + c[n][0] is unused for tag[n]=POTRACE_CORNER */ + /* the remainder of this structure is special to privcurve, and is + used in EPS debug output and special EPS "short coding". These + fields are valid only if "alphacurve" is set. */ + int alphacurve; /* have the following fields been initialized? */ + dpoint_t *vertex; /* for POTRACE_CORNER, this equals c[1] */ + double *alpha; /* only for POTRACE_CURVETO */ + double *alpha0; /* "uncropped" alpha parameter - for debug output only */ + double *beta; +}; +typedef struct privcurve_s privcurve_t; + +struct sums_s { + double x; + double y; + double x2; + double xy; + double y2; +}; +typedef struct sums_s sums_t; + +/* the path structure is filled in with information about a given path + as it is accumulated and passed through the different stages of the + Potrace algorithm. Backends only need to read the fcurve and fm + fields of this data structure, but debugging backends may read + other fields. */ +struct potrace_privpath_s { + int len; + point_t *pt; /* pt[len]: path as extracted from bitmap */ + int *lon; /* lon[len]: (i,lon[i]) = longest straight line from i */ + + int x0, y0; /* origin for sums */ + sums_t *sums; /* sums[len+1]: cache for fast summing */ + + int m; /* length of optimal polygon */ + int *po; /* po[m]: optimal polygon */ + + privcurve_t curve; /* curve[m]: array of curve elements */ + privcurve_t ocurve; /* ocurve[om]: array of curve elements */ + privcurve_t *fcurve; /* final curve: this points to either curve or + ocurve. Do not free this separately. */ +}; +typedef struct potrace_privpath_s potrace_privpath_t; + +/* shorter names */ +typedef potrace_privpath_t privpath_t; +typedef potrace_path_t path_t; + +path_t *path_new(void); +void path_free(path_t * p); +void pathlist_free(path_t * plist); +int privcurve_init(privcurve_t * curve, int n); +void privcurve_to_curve(privcurve_t * pc, potrace_curve_t * c); + +#endif /* CURVE_H */ Index: tags/2.1.2/src_plugins/export_gcode/decompose.c =================================================================== --- tags/2.1.2/src_plugins/export_gcode/decompose.c (nonexistent) +++ tags/2.1.2/src_plugins/export_gcode/decompose.c (revision 24813) @@ -0,0 +1,526 @@ +/* Copyright (C) 2001-2007 Peter Selinger. + This file is part of Potrace. It is free software and it is covered + by the GNU General Public License. See the file COPYING for details. */ + +/* $Id: decompose.c 146 2007-04-09 00:43:46Z selinger $ */ + +#include +#include +#include +#include + +#include "config.h" +#include "potracelib.h" +#include "curve.h" +#include "lists.h" +#include "auxiliary.h" +#include "bitmap.h" +#include "decompose.h" +/*#include "progress.h"*/ + +/* ---------------------------------------------------------------------- */ +/* auxiliary bitmap manipulations */ + +/* set the excess padding to 0 */ +static void bm_clearexcess(potrace_bitmap_t * bm) +{ + potrace_word mask; + int y; + + if (bm->w % BM_WORDBITS != 0) { + mask = BM_ALLBITS << (BM_WORDBITS - (bm->w % BM_WORDBITS)); + for (y = 0; y < bm->h; y++) { + *bm_index(bm, bm->w, y) &= mask; + } + } +} + +struct bbox_s { + int x0, x1, y0, y1; /* bounding box */ +}; +typedef struct bbox_s bbox_t; + +/* clear the bm, assuming the bounding box is set correctly (faster + than clearing the whole bitmap) */ +static void clear_bm_with_bbox(potrace_bitmap_t * bm, bbox_t * bbox) +{ + int imin = (bbox->x0 / BM_WORDBITS); + int imax = ((bbox->x1 + BM_WORDBITS - 1) / BM_WORDBITS); + int i, y; + + for (y = bbox->y0; y < bbox->y1; y++) { + for (i = imin; i < imax; i++) { + bm_scanline(bm, y)[i] = 0; + } + } +} + +/* ---------------------------------------------------------------------- */ +/* auxiliary functions */ + +/* deterministically and efficiently hash (x,y) into a pseudo-random bit */ +static inline int detrand(int x, int y) +{ + unsigned int z; + static const unsigned char t[256] = { + /* non-linear sequence: constant term of inverse in GF(8), + mod x^8+x^4+x^3+x+1 */ + 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, + 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, + 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, + 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, + 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, + 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, + 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, + 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, + 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, + }; + + /* 0x04b3e375 and 0x05a8ef93 are chosen to contain every possible + 5-bit sequence */ + z = ((0x04b3e375 * x) ^ y) * 0x05a8ef93; + z = t[z & 0xff] ^ t[(z >> 8) & 0xff] ^ t[(z >> 16) & 0xff] ^ t[(z >> 24) & 0xff]; + return z & 1; +} + +/* return the "majority" value of bitmap bm at intersection (x,y). We + assume that the bitmap is balanced at "radius" 1. */ +static int majority(potrace_bitmap_t * bm, int x, int y) +{ + int i, a, ct; + + for (i = 2; i < 5; i++) { /* check at "radius" i */ + ct = 0; + for (a = -i + 1; a <= i - 1; a++) { + ct += BM_GET(bm, x + a, y + i - 1) ? 1 : -1; + ct += BM_GET(bm, x + i - 1, y + a - 1) ? 1 : -1; + ct += BM_GET(bm, x + a - 1, y - i) ? 1 : -1; + ct += BM_GET(bm, x - i, y + a) ? 1 : -1; + } + if (ct > 0) { + return 1; + } + else if (ct < 0) { + return 0; + } + } + return 0; +} + +/* ---------------------------------------------------------------------- */ +/* decompose image into paths */ + +/* efficiently invert bits [x,infty) and [xa,infty) in line y. Here xa + must be a multiple of BM_WORDBITS. */ +static void xor_to_ref(potrace_bitmap_t * bm, int x, int y, int xa) +{ + int xhi = x & -BM_WORDBITS; + int xlo = x & (BM_WORDBITS - 1); /* = x % BM_WORDBITS */ + int i; + + if (xhi < xa) { + for (i = xhi; i < xa; i += BM_WORDBITS) { + *bm_index(bm, i, y) ^= BM_ALLBITS; + } + } + else { + for (i = xa; i < xhi; i += BM_WORDBITS) { + *bm_index(bm, i, y) ^= BM_ALLBITS; + } + } + /* note: the following "if" is needed because x86 treats a<priv->len <= 0) { /* a path of length 0 is silly, but legal */ + return; + } + + y1 = p->priv->pt[p->priv->len - 1].y; + + xa = p->priv->pt[0].x & -BM_WORDBITS; + for (k = 0; k < p->priv->len; k++) { + x = p->priv->pt[k].x; + y = p->priv->pt[k].y; + + if (y != y1) { + /* efficiently invert the rectangle [x,xa] x [y,y1] */ + xor_to_ref(bm, x, min(y, y1), xa); + y1 = y; + } + } +} + +/* Find the bounding box of a given path. Path is assumed to be of + non-zero length. */ +static void setbbox_path(bbox_t * bbox, path_t * p) +{ + int x, y; + int k; + + bbox->y0 = INT_MAX; + bbox->y1 = 0; + bbox->x0 = INT_MAX; + bbox->x1 = 0; + + for (k = 0; k < p->priv->len; k++) { + x = p->priv->pt[k].x; + y = p->priv->pt[k].y; + + if (x < bbox->x0) { + bbox->x0 = x; + } + if (x > bbox->x1) { + bbox->x1 = x; + } + if (y < bbox->y0) { + bbox->y0 = y; + } + if (y > bbox->y1) { + bbox->y1 = y; + } + } +} + +/* compute a path in the given pixmap, separating black from white. + Start path at the point (x0,x1), which must be an upper left corner + of the path. Also compute the area enclosed by the path. Return a + new path_t object, or NULL on error (note that a legitimate path + cannot have length 0). Sign is required for correct interpretation + of turnpolicies. */ +static path_t *findpath(potrace_bitmap_t * bm, int x0, int y0, int sign, int turnpolicy) +{ + int x, y, dirx, diry, len, size, area; + int c, d, tmp; + point_t *pt, *pt1; + path_t *p = NULL; + + x = x0; + y = y0; + dirx = 0; + diry = -1; + + len = size = 0; + pt = NULL; + area = 0; + + while (1) { + /* add point to path */ + if (len >= size) { + size += 100; + size = (int) (1.3 * size); + pt1 = (point_t *) realloc(pt, size * sizeof(point_t)); + if (!pt1) { + goto error; + } + pt = pt1; + } + pt[len].x = x; + pt[len].y = y; + len++; + + /* move to next point */ + x += dirx; + y += diry; + area += x * diry; + + /* path complete? */ + if (x == x0 && y == y0) { + break; + } + + /* determine next direction */ + c = BM_GET(bm, x + (dirx + diry - 1) / 2, y + (diry - dirx - 1) / 2); + d = BM_GET(bm, x + (dirx - diry - 1) / 2, y + (diry + dirx - 1) / 2); + + if (c && !d) { /* ambiguous turn */ + if (turnpolicy == POTRACE_TURNPOLICY_RIGHT || (turnpolicy == POTRACE_TURNPOLICY_BLACK && sign == '+') + || (turnpolicy == POTRACE_TURNPOLICY_WHITE && sign == '-') + || (turnpolicy == POTRACE_TURNPOLICY_RANDOM && detrand(x, y)) + || (turnpolicy == POTRACE_TURNPOLICY_MAJORITY && majority(bm, x, y)) + || (turnpolicy == POTRACE_TURNPOLICY_MINORITY && !majority(bm, x, y))) { + tmp = dirx; /* right turn */ + dirx = diry; + diry = -tmp; + } + else { + tmp = dirx; /* left turn */ + dirx = -diry; + diry = tmp; + } + } + else if (c) { /* right turn */ + tmp = dirx; + dirx = diry; + diry = -tmp; + } + else if (!d) { /* left turn */ + tmp = dirx; + dirx = -diry; + diry = tmp; + } + } /* while this path */ + + /* allocate new path object */ + p = path_new(); + if (!p) { + goto error; + } + + p->priv->pt = pt; + p->priv->len = len; + p->area = area; + p->sign = sign; + + return p; + +error: + free(pt); + return NULL; +} + +/* Give a tree structure to the given path list, based on "insideness" + testing. I.e., path A is considered "below" path B if it is inside + path B. The input pathlist is assumed to be ordered so that "outer" + paths occur before "inner" paths. The tree structure is stored in + the "childlist" and "sibling" components of the path_t + structure. The linked list structure is also changed so that + negative path components are listed immediately after their + positive parent. Note: some backends may ignore the tree + structure, others may use it e.g. to group path components. We + assume that in the input, point 0 of each path is an "upper left" + corner of the path, as returned by bm_to_pathlist. This makes it + easy to find an "interior" point. The bm argument should be a + bitmap of the correct size (large enough to hold all the paths), + and will be used as scratch space. Return 0 on success or -1 on + error with errno set. */ + +static void pathlist_to_tree(path_t * plist, potrace_bitmap_t * bm) +{ + path_t *p, *p1; + path_t *heap, *heap1; + path_t *cur; + path_t *head; + path_t **hook, **hook_in, **hook_out; /* for fast appending to linked list */ + bbox_t bbox; + + bm_clear(bm, 0); + + /* save original "next" pointers */ + list_forall(p, plist) { + p->sibling = p->next; + p->childlist = NULL; + } + + heap = plist; + + /* the heap holds a list of lists of paths. Use "childlist" field + for outer list, "next" field for inner list. Each of the sublists + is to be turned into a tree. This code is messy, but it is + actually fast. Each path is rendered exactly once. We use the + heap to get a tail recursive algorithm: the heap holds a list of + pathlists which still need to be transformed. */ + + while (heap) { + /* unlink first sublist */ + cur = heap; + heap = heap->childlist; + cur->childlist = NULL; + + /* unlink first path */ + head = cur; + cur = cur->next; + head->next = NULL; + + /* render path */ + xor_path(bm, head); + setbbox_path(&bbox, head); + + /* now do insideness test for each element of cur; append it to + head->childlist if it's inside head, else append it to + head->next. */ + hook_in = &head->childlist; + hook_out = &head->next; + list_forall_unlink(p, cur) { + if (p->priv->pt[0].y <= bbox.y0) { + list_insert_beforehook(p, hook_out); + /* append the remainder of the list to hook_out */ + *hook_out = cur; + break; + } + if (BM_GET(bm, p->priv->pt[0].x, p->priv->pt[0].y - 1)) { + list_insert_beforehook(p, hook_in); + } + else { + list_insert_beforehook(p, hook_out); + } + } + + /* clear bm */ + clear_bm_with_bbox(bm, &bbox); + + /* now schedule head->childlist and head->next for further + processing */ + if (head->next) { + head->next->childlist = heap; + heap = head->next; + } + if (head->childlist) { + head->childlist->childlist = heap; + heap = head->childlist; + } + } + + /* copy sibling structure from "next" to "sibling" component */ + p = plist; + while (p) { + p1 = p->sibling; + p->sibling = p->next; + p = p1; + } + + /* reconstruct a new linked list ("next") structure from tree + ("childlist", "sibling") structure. This code is slightly messy, + because we use a heap to make it tail recursive: the heap + contains a list of childlists which still need to be + processed. */ + heap = plist; + if (heap) { + heap->next = NULL; /* heap is a linked list of childlists */ + } + plist = NULL; + hook = &plist; + while (heap) { + heap1 = heap->next; + for (p = heap; p; p = p->sibling) { + /* p is a positive path */ + /* append to linked list */ + list_insert_beforehook(p, hook); + + /* go through its children */ + for (p1 = p->childlist; p1; p1 = p1->sibling) { + /* append to linked list */ + list_insert_beforehook(p1, hook); + /* append its childlist to heap, if non-empty */ + if (p1->childlist) { + list_append(path_t, heap1, p1->childlist); + } + } + } + heap = heap1; + } + + return; +} + +/* find the next set pixel in a row <= y. Pixels are searched first + left-to-right, then top-down. In other words, (x,y)<(x',y') if y>y' + or y=y' and x= 0; y--) { + for (x = 0; x < bm->w; x += BM_WORDBITS) { + if (*bm_index(bm, x, y)) { + while (!BM_GET(bm, x, y)) { + x++; + } + /* found */ + *xp = x; + *yp = y; + return 0; + } + } + } + /* not found */ + return 1; +} + +/* Decompose the given bitmap into paths. Returns a linked list of + path_t objects with the fields len, pt, area, sign filled + in. Returns 0 on success with plistp set, or -1 on error with errno + set. */ + +int bm_to_pathlist(const potrace_bitmap_t * bm, path_t ** plistp, const potrace_param_t * param) +{ + int x; + int y; + path_t *p; + path_t *plist = NULL; /* linked list of path objects */ + path_t **hook = &plist; /* used to speed up appending to linked list */ + potrace_bitmap_t *bm1 = NULL; + int sign; + + bm1 = bm_dup(bm); + if (!bm1) { + goto error; + } + + /* be sure the byte padding on the right is set to 0, as the fast + pixel search below relies on it */ + bm_clearexcess(bm1); + + /* iterate through components */ + y = bm1->h - 1; + while (findnext(bm1, &x, &y) == 0) { + /* calculate the sign by looking at the original */ + sign = BM_GET(bm, x, y) ? '+' : '-'; + + /* calculate the path */ + p = findpath(bm1, x, y + 1, sign, param->turnpolicy); + if (p == NULL) { + goto error; + } + + /* update buffered image */ + xor_path(bm1, p); + + /* if it's a turd, eliminate it, else append it to the list */ + if (p->area <= param->turdsize) { + path_free(p); + } + else { + list_insert_beforehook(p, hook); + } + + if (bm1->h > 0) { /* to be sure */ + /*progress_update(1-y/(double)bm1->h, progress); */ + } + } + + pathlist_to_tree(plist, bm1); + bm_free(bm1); + *plistp = plist; + +/* progress_update(1.0, progress);*/ + + return 0; + +error: + bm_free(bm1); + list_forall_unlink(p, plist) { + path_free(p); + } + return -1; +} Index: tags/2.1.2/src_plugins/export_gcode/decompose.h =================================================================== --- tags/2.1.2/src_plugins/export_gcode/decompose.h (nonexistent) +++ tags/2.1.2/src_plugins/export_gcode/decompose.h (revision 24813) @@ -0,0 +1,15 @@ +/* Copyright (C) 2001-2007 Peter Selinger. + This file is part of Potrace. It is free software and it is covered + by the GNU General Public License. See the file COPYING for details. */ + +/* $Id: decompose.h 147 2007-04-09 00:44:09Z selinger $ */ + +#ifndef DECOMPOSE_H +#define DECOMPOSE_H + +#include "potracelib.h" +/*#include "progress.h"*/ + +int bm_to_pathlist(const potrace_bitmap_t * bm, path_t ** plistp, const potrace_param_t * param); + +#endif /* DECOMPOSE_H */ Index: tags/2.1.2/src_plugins/export_gcode/export_gcode.pup =================================================================== --- tags/2.1.2/src_plugins/export_gcode/export_gcode.pup (nonexistent) +++ tags/2.1.2/src_plugins/export_gcode/export_gcode.pup (revision 24813) @@ -0,0 +1,9 @@ +$class export +$short gcode pcb_exporter +$long Export to gcode +$state works +$fmt-native no +$fmt-feature-w export gcode (for milling) +$package export +default buildin +autoload 1 Index: tags/2.1.2/src_plugins/export_gcode/gcode.c =================================================================== --- tags/2.1.2/src_plugins/export_gcode/gcode.c (nonexistent) +++ tags/2.1.2/src_plugins/export_gcode/gcode.c (revision 24813) @@ -0,0 +1,929 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * + * GCODE export HID + * Copyright (C) 2010 Alberto Maccioni + * this code is based on the NELMA export HID, the PNG export HID, + * and potrace, a tracing program by Peter Selinger + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +/* + * This HID exports a PCB layout into: + * one layer mask file (PNG format) per copper layer, + * one G-CODE CNC drill file. + * one G-CODE CNC file per copper layer. + * The latter is used by a CNC milling machine to mill the pcb. + */ + +#include "config.h" +#include "conf_core.h" +#include "plugins.h" + +#include +#include +#include +#include +#include + +#include + +#include "board.h" +#include "error.h" +#include "data.h" +#include "draw.h" +#include "hid_cam.h" +#include "layer.h" +#include "layer_vis.h" +#include "compat_misc.h" +#include "safe_fs.h" + +#include "hid.h" +#include +#include "hid_nogui.h" +#include "hid_draw_helpers.h" +#include "gcode.h" +#include "bitmap.h" +#include "curve.h" +#include "potracelib.h" +#include "trace.h" +#include "decompose.h" +#include "pcb-printf.h" +#include "funchash_core.h" + +#include "hid_init.h" +#include "hid_attrib.h" +#include "hid_color.h" + + +const char *gcode_cookie = "gcode HID"; + +#define CRASH(func) fprintf(stderr, "HID error: pcb called unimplemented GCODE function %s.\n", func); abort() +struct color_struct { + /* the descriptor used by the gd library */ + int c; + + /* so I can figure out what rgb value c refers to */ + unsigned int r, g, b; +}; + +struct hid_gc_s { + pcb_core_gc_t core_gc; + pcb_hid_t *me_pointer; + pcb_cap_style_t cap; + int width; + unsigned char r, g, b; + int erase; + int faded; + struct color_struct *color; + gdImagePtr brush; +}; + +static struct color_struct *black = NULL, *white = NULL; +static int linewidth = -1; +static gdImagePtr lastbrush = (gdImagePtr) ((void *) -1); +static int lastcolor = -1; + +/* gd image and file for PNG export */ +static gdImagePtr gcode_im = NULL; +static FILE *gcode_f = NULL, *gcode_f2 = NULL; + +static int is_mask; +static int is_drill; +static int is_solder; + +/* + * Which groups of layers to export into PNG layer masks. 1 means export, 0 + * means do not export. + */ +static int gcode_export_group[PCB_MAX_LAYERGRP]; + +/* Group that is currently exported. */ +static int gcode_cur_group; + +/* Filename prefix that will be used when saving files. */ +static const char *gcode_basename = NULL; + +/* Horizontal DPI (grid points per inch) */ +static int gcode_dpi = -1; + +static double gcode_cutdepth = 0; /* milling depth (inch) */ +static double gcode_drilldepth = 0; /* drilling depth (inch) */ +static double gcode_safeZ = 100; /* safe Z (inch) */ +static double gcode_toolradius = 0; /* tool radius(inch) */ +static int save_drill = 0; +static int n_drill = 0; +static int nmax_drill = 0; +struct drill_struct { + double x; + double y; +}; + +static struct drill_struct *drill = 0; + +static const char *units[] = { + "mm", + "mil", + "um", + "inch", + NULL +}; + +pcb_hid_attribute_t gcode_attribute_list[] = { + /* other HIDs expect this to be first. */ + {"basename", "File name prefix", + PCB_HATT_STRING, 0, 0, {0, 0, 0}, 0, 0}, +#define HA_basename 0 + + {"dpi", "Resolution of intermediate image (pixels/inch)", + PCB_HATT_INTEGER, 0, 2000, {600, 0, 0}, 0, 0}, +#define HA_dpi 1 + + {"mill-depth", "Milling depth", + PCB_HATT_REAL, -1000, 1000, {0, 0, -0.05}, 0, 0}, +#define HA_cutdepth 2 + + {"safe-Z", "Safe Z for traverse move", + PCB_HATT_REAL, -1000, 10000, {0, 0, 2}, 0, 0}, +#define HA_safeZ 3 + + {"tool-radius", "Milling tool radius compensation", + PCB_HATT_REAL, 0, 10000, {0, 0, 0.1}, 0, 0}, +#define HA_toolradius 4 + + {"drill-depth", "Drilling depth", + PCB_HATT_REAL, -10000, 10000, {0, 0, -2}, 0, 0}, +#define HA_drilldepth 5 + + {"measurement-unit", "Measurement unit", + PCB_HATT_UNIT, 0, 0, {-1, 0, 0}, units, 0}, +#define HA_unit 6 + +}; + +#define NUM_OPTIONS (sizeof(gcode_attribute_list)/sizeof(gcode_attribute_list[0])) + +PCB_REGISTER_ATTRIBUTES(gcode_attribute_list, gcode_cookie) + static pcb_hid_attr_val_t gcode_values[NUM_OPTIONS]; + +/* *** Utility funcions **************************************************** */ + +/* convert from default PCB units to gcode units */ + static int pcb_to_gcode(int pcb) +{ + return pcb_round(PCB_COORD_TO_INCH(pcb) * gcode_dpi); +} + +static char *gcode_get_png_name(const char *basename, const char *suffix) +{ + return pcb_strdup_printf("%s.%s.png", basename, suffix); +} + +/* Sorts drills in order of distance from the origin */ +struct drill_struct *sort_drill(struct drill_struct *drill, int n_drill) +{ + int i, j, imin; + double dmin, d; + struct drill_struct p = { 0, 0 }; + struct drill_struct *temp = (struct drill_struct *) malloc(n_drill * sizeof(struct drill_struct)); + for (j = 0; j < n_drill; j++) { + dmin = 1e20; + imin = 0; + for (i = 0; i < n_drill - j; i++) { + d = (drill[i].x - p.x) * (drill[i].x - p.x) + (drill[i].y - p.y) * (drill[i].y - p.y); + if (d < dmin) { + imin = i; + dmin = d; + } + } + /* printf("j=%d imin=%d dmin=%f p=(%f,%f)\n",j,imin,dmin,p.x,p.y); */ + temp[j] = drill[imin]; + drill[imin] = drill[n_drill - j - 1]; + p = temp[j]; + } + free(drill); + return temp; +} + +/* *** Main export callback ************************************************ */ + +static int gcode_parse_arguments(int *argc, char ***argv) +{ + pcb_hid_register_attributes(gcode_attribute_list, sizeof(gcode_attribute_list) / sizeof(gcode_attribute_list[0]), gcode_cookie, 0); + return pcb_hid_parse_command_line(argc, argv); +} + +static pcb_hid_attribute_t *gcode_get_export_options(int *n) +{ + static int last_unit_value = -1; + + if (gcode_attribute_list[HA_unit].default_val.int_value == last_unit_value) { + if (conf_core.editor.grid_unit) + gcode_attribute_list[HA_unit].default_val.int_value = conf_core.editor.grid_unit->index; + else + gcode_attribute_list[HA_unit].default_val.int_value = get_unit_struct("mil")->index; + last_unit_value = gcode_attribute_list[HA_unit].default_val.int_value; + } + + if ((PCB != NULL) && (gcode_attribute_list[HA_basename].default_val.str_value == NULL)) + pcb_derive_default_filename(PCB->Filename, &gcode_attribute_list[HA_basename], ".gcode"); + if (n) { + *n = NUM_OPTIONS; + } + return gcode_attribute_list; +} + +/* Populates gcode_export_group array */ +void gcode_choose_groups() +{ + int n, m; + pcb_layer_t *layer; + + /* Set entire array to 0 (don't export any layer groups by default */ + memset(gcode_export_group, 0, sizeof(gcode_export_group)); + + for (n = 0; n < pcb_max_layer; n++) { + unsigned int flags = pcb_layer_flags(PCB, n); + if (flags & PCB_LYT_SILK) + continue; + layer = &PCB->Data->Layer[n]; + + if (!pcb_layer_is_empty_(PCB, layer)) { + /* layer isn't empty */ + int purpi = pcb_layer_purpose(PCB, n, NULL); + + /* + * is this check necessary? It seems that special + * layers have negative indexes? + */ + + if ((flags & PCB_LYT_COPPER) || PCB_LAYER_IS_ROUTE(flags, purpi)) { + m = pcb_layer_get_group(PCB, n); + + /* the export layer */ + gcode_export_group[m] = 1; + } + } + } +} + +static void gcode_alloc_colors() +{ + /* + * Allocate white and black -- the first color allocated becomes the + * background color + */ + + white = (struct color_struct *) malloc(sizeof(*white)); + white->r = white->g = white->b = 255; + white->c = gdImageColorAllocate(gcode_im, white->r, white->g, white->b); + + black = (struct color_struct *) malloc(sizeof(*black)); + black->r = black->g = black->b = 0; + black->c = gdImageColorAllocate(gcode_im, black->r, black->g, black->b); +} + +static void gcode_start_png(const char *basename, const char *suffix) +{ + int h, w; + char *buf; + + buf = gcode_get_png_name(basename, suffix); + + h = pcb_to_gcode(PCB->MaxHeight); + w = pcb_to_gcode(PCB->MaxWidth); + + /* Nelma only works with true color images */ + gcode_im = gdImageCreate(w, h); + gcode_f = pcb_fopen(buf, "wb"); + + gcode_alloc_colors(); + + free(buf); +} + +static void gcode_finish_png() +{ +#ifdef HAVE_GDIMAGEPNG + gdImagePng(gcode_im, gcode_f); +#else + pcb_message(PCB_MSG_WARNING, "GCODE: PNG not supported by gd. Can't write layer mask.\n"); +#endif + gdImageDestroy(gcode_im); + fclose(gcode_f); + + free(white); + free(black); + + gcode_im = NULL; + gcode_f = NULL; +} + +void gcode_start_png_export() +{ + pcb_hid_expose_ctx_t ctx; + + ctx.view.X1 = 0; + ctx.view.Y1 = 0; + ctx.view.X2 = PCB->MaxWidth; + ctx.view.Y2 = PCB->MaxHeight; + + linewidth = -1; + lastbrush = (gdImagePtr) ((void *) -1); + lastcolor = -1; + + pcb_hid_expose_all(&gcode_hid, &ctx, NULL); +} + +static void gcode_do_export(pcb_hid_attr_val_t * options) +{ + int save_ons[PCB_MAX_LAYER + 2]; + int i, idx; + time_t t; + const pcb_unit_t *unit; + double scale = 0, d = 0; + int r, c, v, p, metric; + char *filename; + path_t *plist = NULL; + potrace_bitmap_t *bm = NULL; + potrace_param_t param_default = { + 2, /* turnsize */ + POTRACE_TURNPOLICY_MINORITY, /* turnpolicy */ + 1.0, /* alphamax */ + 1, /* opticurve */ + 0.2, /* opttolerance */ + { + NULL, /* callback function */ + NULL, /* callback data */ + 0.0, 1.0, /* progress range */ + 0.0, /* granularity */ + }, + }; + + if (!options) { + gcode_get_export_options(0); + for (i = 0; i < NUM_OPTIONS; i++) { + gcode_values[i] = gcode_attribute_list[i].default_val; + } + options = gcode_values; + } + gcode_basename = options[HA_basename].str_value; + if (!gcode_basename) { + gcode_basename = "pcb-out"; + } + gcode_dpi = options[HA_dpi].int_value; + if (gcode_dpi < 0) { + fprintf(stderr, "ERROR: dpi may not be < 0\n"); + return; + } + unit = &(pcb_units[options[HA_unit].int_value]); + metric = (unit->family == PCB_UNIT_METRIC); + scale = metric ? 1.0 / pcb_coord_to_unit(unit, PCB_MM_TO_COORD(1.0)) + : 1.0 / pcb_coord_to_unit(unit, PCB_INCH_TO_COORD(1.0)); + + gcode_cutdepth = options[HA_cutdepth].real_value * scale; + gcode_drilldepth = options[HA_drilldepth].real_value * scale; + gcode_safeZ = options[HA_safeZ].real_value * scale; + gcode_toolradius = metric ? PCB_MM_TO_COORD(options[HA_toolradius].real_value * scale) + : PCB_INCH_TO_COORD(options[HA_toolradius].real_value * scale); + gcode_choose_groups(); + + for (i = 0; i < PCB_MAX_LAYERGRP; i++) { + if (gcode_export_group[i]) { + char tmp_ln[PCB_PATH_MAX]; + const char *name = pcb_layer_to_file_name(tmp_ln, -1, pcb_layergrp_flags(PCB, i), PCB->LayerGroups.grp[i].purpose, PCB->LayerGroups.grp[i].purpi, PCB_FNS_fixed); + gcode_cur_group = i; + + /* magic */ + idx = (i >= 0 && i < pcb_max_group(PCB)) ? PCB->LayerGroups.grp[i].lid[0] : i; + printf("idx=%d %s\n", idx, name); + is_solder = (pcb_layergrp_flags(PCB, pcb_layer_get_group(PCB, idx)) & PCB_LYT_BOTTOM) ? 1 : 0; + save_drill = is_solder; /* save drills for one layer only */ + gcode_start_png(gcode_basename, name); + pcb_hid_save_and_show_layer_ons(save_ons); + gcode_start_png_export(); + pcb_hid_restore_layer_ons(save_ons); + +/* ***************** gcode conversion *************************** */ +/* potrace uses a different kind of bitmap; for simplicity gcode_im is copied to this format */ + bm = bm_new(gdImageSX(gcode_im), gdImageSY(gcode_im)); + filename = (char *) malloc(PCB_PATH_MAX); + plist = NULL; + if (is_solder) { /* only for back layer */ + gdImagePtr temp_im = gdImageCreate(gdImageSX(gcode_im), gdImageSY(gcode_im)); + gdImageCopy(temp_im, gcode_im, 0, 0, 0, 0, gdImageSX(gcode_im), gdImageSY(gcode_im)); + for (r = 0; r < gdImageSX(gcode_im); r++) { + for (c = 0; c < gdImageSY(gcode_im); c++) { + gdImageSetPixel(gcode_im, r, c, gdImageGetPixel(temp_im, gdImageSX(gcode_im) - 1 - r, c)); + } + } + gdImageDestroy(temp_im); + } + sprintf(filename, "%s.%s.cnc", gcode_basename, name); + for (r = 0; r < gdImageSX(gcode_im); r++) { + for (c = 0; c < gdImageSY(gcode_im); c++) { + v = gdImageGetPixel(gcode_im, r, gdImageSY(gcode_im) - 1 - c); + p = (gcode_im->red[v] || gcode_im->green[v] + || gcode_im->blue[v]) ? 0 : 0xFFFFFF; + BM_PUT(bm, r, c, p); + } + } + gcode_f2 = pcb_fopen(filename, "wb"); + if (!gcode_f2) { + perror(filename); + return; + } + fprintf(gcode_f2, "(Created by G-code exporter)\n"); + t = time(NULL); + sprintf(filename, "%s", ctime(&t)); + filename[strlen(filename) - 1] = 0; + fprintf(gcode_f2, "( %s )\n", filename); + fprintf(gcode_f2, "(%d dpi)\n", gcode_dpi); + fprintf(gcode_f2, "(Unit: %s)\n", metric ? "mm" : "inch"); + if (metric) + pcb_fprintf(gcode_f2, "(Board size: %.2mmx%.2mm mm)", PCB->MaxWidth, PCB->MaxHeight); + else + pcb_fprintf(gcode_f2, "(Board size: %.2mix%.2mi inches)", PCB->MaxWidth, PCB->MaxHeight); + fprintf(gcode_f2, "#100=%f (safe Z)\n", gcode_safeZ); + fprintf(gcode_f2, "#101=%f (cutting depth)\n", gcode_cutdepth); + fprintf(gcode_f2, "(---------------------------------)\n"); + fprintf(gcode_f2, "G17 G%d G90 G64 P0.003 M3 S3000 M7 F%d\n", metric ? 21 : 20, metric ? 25 : 1); + fprintf(gcode_f2, "G0 Z#100\n"); + /* extract contour points from image */ + r = bm_to_pathlist(bm, &plist, ¶m_default); + if (r) { + fprintf(stderr, "ERROR: pathlist function failed\n"); + return; + } + /* generate best polygon and write vertices in g-code format */ + d = process_path(plist, ¶m_default, bm, gcode_f2, metric ? 25.4 / gcode_dpi : 1.0 / gcode_dpi); + if (d < 0) { + fprintf(stderr, "ERROR: path process function failed\n"); + return; + } + if (metric) + fprintf(gcode_f2, "(end, total distance %.2fmm = %.2fin)\n", d, d * 1 / 25.4); + else + fprintf(gcode_f2, "(end, total distance %.2fmm = %.2fin)\n", 25.4 * d, d); + fprintf(gcode_f2, "M5 M9 M2\n"); + pathlist_free(plist); + bm_free(bm); + fclose(gcode_f2); + if (save_drill) { + d = 0; + drill = sort_drill(drill, n_drill); + sprintf(filename, "%s.drill.cnc", gcode_basename); + gcode_f2 = pcb_fopen(filename, "wb"); + if (!gcode_f2) { + perror(filename); + return; + } + fprintf(gcode_f2, "(Created by G-code exporter)\n"); + fprintf(gcode_f2, "(drill file: %d drills)\n", n_drill); + sprintf(filename, "%s", ctime(&t)); + filename[strlen(filename) - 1] = 0; + fprintf(gcode_f2, "( %s )\n", filename); + fprintf(gcode_f2, "(Unit: %s)\n", metric ? "mm" : "inch"); + if (metric) + pcb_fprintf(gcode_f2, "(Board size: %.2mmx%.2mm mm)", PCB->MaxWidth, PCB->MaxHeight); + else + pcb_fprintf(gcode_f2, "(Board size: %.2mix%.2mi inches)", PCB->MaxWidth, PCB->MaxHeight); + fprintf(gcode_f2, "#100=%f (safe Z)\n", gcode_safeZ); + fprintf(gcode_f2, "#101=%f (drill depth)\n", gcode_drilldepth); + fprintf(gcode_f2, "(---------------------------------)\n"); + fprintf(gcode_f2, "G17 G%d G90 G64 P0.003 M3 S3000 M7 F%d\n", metric ? 21 : 20, metric ? 25 : 1); +/* fprintf(gcode_f2,"G0 Z#100\n"); */ + for (r = 0; r < n_drill; r++) { +/* if(metric) fprintf(gcode_f2,"G0 X%f Y%f\n",drill[r].x*25.4,drill[r].y*25.4); */ +/* else fprintf(gcode_f2,"G0 X%f Y%f\n",drill[r].x,drill[r].y); */ + if (metric) + fprintf(gcode_f2, "G81 X%f Y%f Z#101 R#100\n", drill[r].x * 25.4, drill[r].y * 25.4); + else + fprintf(gcode_f2, "G81 X%f Y%f Z#101 R#100\n", drill[r].x, drill[r].y); +/* fprintf(gcode_f2,"G1 Z#101\n"); */ +/* fprintf(gcode_f2,"G0 Z#100\n"); */ + if (r > 0) + d += + sqrt((drill[r].x - drill[r - 1].x) * (drill[r].x - + drill[r - 1].x) + + (drill[r].y - drill[r - 1].y) * (drill[r].y - drill[r - 1].y)); + } + fprintf(gcode_f2, "M5 M9 M2\n"); + fprintf(gcode_f2, "(end, total distance %.2fmm = %.2fin)\n", 25.4 * d, d); + fclose(gcode_f2); + free(drill); + drill = NULL; + n_drill = nmax_drill = 0; + } + free(filename); + +/* ******************* end gcode conversion **************************** */ + gcode_finish_png(); + } + } +} + +/* *** PNG export (slightly modified code from PNG export HID) ************* */ + +static int gcode_set_layer_group(pcb_layergrp_id_t group, const char *purpose, int purpi, pcb_layer_id_t layer, unsigned int flags, int is_empty, pcb_xform_t **xform) +{ + if (flags & PCB_LYT_UI) + return 0; + + if (flags & PCB_LYT_INVIS) + return 0; + + if ((flags & PCB_LYT_ANYTHING) == PCB_LYT_SILK) + return 0; + + is_drill = PCB_LAYER_IS_DRILL(flags, purpi); + is_mask = !!(flags & PCB_LYT_MASK); + + if (is_mask) { + /* Don't print masks */ + return 0; + } + if (is_drill) { + /* + * Print 'holes', so that we can fill gaps in the copper + * layer + */ + return 1; + } + if (group == gcode_cur_group) { + return 1; + } + return 0; +} + +static pcb_hid_gc_t gcode_make_gc(void) +{ + pcb_hid_gc_t rv = (pcb_hid_gc_t) malloc(sizeof(struct hid_gc_s)); + rv->me_pointer = &gcode_hid; + rv->cap = pcb_cap_round; + rv->width = 1; + rv->color = (struct color_struct *) malloc(sizeof(*rv->color)); + rv->color->r = rv->color->g = rv->color->b = 0; + rv->color->c = 0; + return rv; +} + +static void gcode_destroy_gc(pcb_hid_gc_t gc) +{ + free(gc); +} + +static void gcode_set_color(pcb_hid_gc_t gc, const pcb_color_t *color) +{ + if (gcode_im == NULL) { + return; + } +TODO("This is broken - sets color to 0 on everything"); + if (pcb_color_is_drill(color)) { + gc->color = black; + gc->erase = 0; + return; + } + gc->color = black; + gc->erase = 0; + return; +} + +static void gcode_set_line_cap(pcb_hid_gc_t gc, pcb_cap_style_t style) +{ + gc->cap = style; +} + +static void gcode_set_line_width(pcb_hid_gc_t gc, pcb_coord_t width) +{ + gc->width = width; +} + +static void gcode_set_draw_xor(pcb_hid_gc_t gc, int xor_) +{ + ; +} + +static void gcode_set_draw_faded(pcb_hid_gc_t gc, int faded) +{ + gc->faded = faded; +} + +static void use_gc(pcb_hid_gc_t gc) +{ + int need_brush = 0; + + if (gc->me_pointer != &gcode_hid) { + fprintf(stderr, "Fatal: GC from another HID passed to gcode HID\n"); + abort(); + } + if (linewidth != gc->width) { + /* Make sure the scaling doesn't erase lines completely */ + /* + if (SCALE (gc->width) == 0 && gc->width > 0) + gdImageSetThickness (im, 1); + else + */ + gdImageSetThickness(gcode_im, pcb_to_gcode(gc->width + 2 * gcode_toolradius)); + linewidth = gc->width; + need_brush = 1; + } + if (lastbrush != gc->brush || need_brush) { + static void *bcache = 0; + pcb_hidval_t bval; + char name[256]; + char type; + int r; + + switch (gc->cap) { + case pcb_cap_round: + type = 'C'; + r = pcb_to_gcode(gc->width / 2 + gcode_toolradius); + break; + case pcb_cap_square: + r = pcb_to_gcode(gc->width + gcode_toolradius * 2); + type = 'S'; + break; + default: + assert(!"unhandled cap"); + r = 1; + type = 'C'; + } + sprintf(name, "#%.2x%.2x%.2x_%c_%d", gc->color->r, gc->color->g, gc->color->b, type, r); + + if (pcb_hid_cache_color(0, name, &bval, &bcache)) { + gc->brush = (gdImagePtr) bval.ptr; + } + else { + int bg, fg; + if (type == 'C') + gc->brush = gdImageCreate(2 * r + 1, 2 * r + 1); + else + gc->brush = gdImageCreate(r + 1, r + 1); + bg = gdImageColorAllocate(gc->brush, 255, 255, 255); + fg = gdImageColorAllocate(gc->brush, gc->color->r, gc->color->g, gc->color->b); + gdImageColorTransparent(gc->brush, bg); + + /* + * if we shrunk to a radius/box width of zero, then just use + * a single pixel to draw with. + */ + if (r == 0) + gdImageFilledRectangle(gc->brush, 0, 0, 0, 0, fg); + else { + if (type == 'C') + gdImageFilledEllipse(gc->brush, r, r, 2 * r, 2 * r, fg); + else + gdImageFilledRectangle(gc->brush, 0, 0, r, r, fg); + } + bval.ptr = gc->brush; + pcb_hid_cache_color(1, name, &bval, &bcache); + } + + gdImageSetBrush(gcode_im, gc->brush); + lastbrush = gc->brush; + + } +#define CBLEND(gc) (((gc->r)<<24)|((gc->g)<<16)|((gc->b)<<8)|(gc->faded)) + if (lastcolor != CBLEND(gc)) { + if (is_drill || is_mask) { +#ifdef FIXME + fprintf(f, "%d gray\n", gc->erase ? 0 : 1); +#endif + lastcolor = 0; + } + else { + double r, g, b; + r = gc->r; + g = gc->g; + b = gc->b; + if (gc->faded) { + r = 0.8 * 255 + 0.2 * r; + g = 0.8 * 255 + 0.2 * g; + b = 0.8 * 255 + 0.2 * b; + } +#ifdef FIXME + if (gc->r == gc->g && gc->g == gc->b) + fprintf(f, "%g gray\n", r / 255.0); + else + fprintf(f, "%g %g %g rgb\n", r / 255.0, g / 255.0, b / 255.0); +#endif + lastcolor = CBLEND(gc); + } + } +} + +static void gcode_draw_rect(pcb_hid_gc_t gc, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2) +{ + use_gc(gc); + gdImageRectangle(gcode_im, + pcb_to_gcode(x1 - gcode_toolradius), + pcb_to_gcode(y1 - gcode_toolradius), + pcb_to_gcode(x2 + gcode_toolradius), pcb_to_gcode(y2 + gcode_toolradius), gc->color->c); +/* printf("Rect %d %d %d %d\n",x1,y1,x2,y2); */ +} + +static void gcode_fill_rect(pcb_hid_gc_t gc, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2) +{ + use_gc(gc); + gdImageSetThickness(gcode_im, 0); + linewidth = 0; + gdImageFilledRectangle(gcode_im, + pcb_to_gcode(x1 - gcode_toolradius), + pcb_to_gcode(y1 - gcode_toolradius), + pcb_to_gcode(x2 + gcode_toolradius), pcb_to_gcode(y2 + gcode_toolradius), gc->color->c); +/* printf("FillRect %d %d %d %d\n",x1,y1,x2,y2); */ +} + +static void gcode_draw_line(pcb_hid_gc_t gc, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2) +{ + if (x1 == x2 && y1 == y2) { + pcb_coord_t w = gc->width / 2; + gcode_fill_rect(gc, x1 - w, y1 - w, x1 + w, y1 + w); + return; + } + use_gc(gc); + + gdImageSetThickness(gcode_im, 0); + linewidth = 0; + gdImageLine(gcode_im, pcb_to_gcode(x1), pcb_to_gcode(y1), pcb_to_gcode(x2), pcb_to_gcode(y2), gdBrushed); +} + +static void gcode_draw_arc(pcb_hid_gc_t gc, pcb_coord_t cx, pcb_coord_t cy, pcb_coord_t width, pcb_coord_t height, pcb_angle_t start_angle, pcb_angle_t delta_angle) +{ + pcb_angle_t sa, ea; + + /* + * in gdImageArc, 0 degrees is to the right and +90 degrees is down + * in pcb, 0 degrees is to the left and +90 degrees is down + */ + start_angle = 180 - start_angle; + delta_angle = -delta_angle; + if (delta_angle > 0) { + sa = start_angle; + ea = start_angle + delta_angle; + } + else { + sa = start_angle + delta_angle; + ea = start_angle; + } + + /* + * make sure we start between 0 and 360 otherwise gd does strange + * things + */ + sa = pcb_normalize_angle(sa); + ea = pcb_normalize_angle(ea); + +#if 0 + printf("draw_arc %d,%d %dx%d %d..%d %d..%d\n", cx, cy, width, height, start_angle, delta_angle, sa, ea); + printf("gdImageArc (%p, %d, %d, %d, %d, %d, %d, %d)\n", + (void *)im, SCALE_X(cx), SCALE_Y(cy), SCALE(width), SCALE(height), sa, ea, gc->color->c); +#endif + use_gc(gc); + gdImageSetThickness(gcode_im, 0); + linewidth = 0; + gdImageArc(gcode_im, pcb_to_gcode(cx), pcb_to_gcode(cy), + pcb_to_gcode(2 * width + gcode_toolradius * 2), + pcb_to_gcode(2 * height + gcode_toolradius * 2), sa, ea, gdBrushed); +} + +static void gcode_fill_circle(pcb_hid_gc_t gc, pcb_coord_t cx, pcb_coord_t cy, pcb_coord_t radius) +{ + use_gc(gc); + + gdImageSetThickness(gcode_im, 0); + linewidth = 0; + gdImageFilledEllipse(gcode_im, pcb_to_gcode(cx), pcb_to_gcode(cy), + pcb_to_gcode(2 * radius + gcode_toolradius * 2), + pcb_to_gcode(2 * radius + gcode_toolradius * 2), gc->color->c); + if (save_drill && is_drill) { + if (n_drill == nmax_drill) { + drill = (struct drill_struct *) realloc(drill, (nmax_drill + 100) * sizeof(struct drill_struct)); + nmax_drill += 100; + } + drill[n_drill].x = PCB_COORD_TO_INCH(PCB->MaxWidth - cx); /* convert to inch, flip: will drill from bottom side */ + drill[n_drill].y = PCB_COORD_TO_INCH(PCB->MaxHeight - cy); /* PCB reverses y axis */ + n_drill++; +/* printf("Circle %d %d\n",cx,cy); */ + } +} + +static void gcode_fill_polygon_offs(pcb_hid_gc_t gc, int n_coords, pcb_coord_t *x, pcb_coord_t *y, pcb_coord_t dx, pcb_coord_t dy) +{ + int i; + gdPoint *points; + + points = (gdPoint *) malloc(n_coords * sizeof(gdPoint)); + if (points == NULL) { + fprintf(stderr, "ERROR: gcode_fill_polygon(): malloc failed\n"); + exit(1); + } + use_gc(gc); + for (i = 0; i < n_coords; i++) { + points[i].x = pcb_to_gcode(x[i] + dx); + points[i].y = pcb_to_gcode(y[i] + dy); + } + gdImageSetThickness(gcode_im, 0); + linewidth = 0; + gdImageFilledPolygon(gcode_im, points, n_coords, gc->color->c); + free(points); +/* printf("FillPoly\n"); */ +} + +static void gcode_fill_polygon(pcb_hid_gc_t gc, int n_coords, pcb_coord_t *x, pcb_coord_t *y) +{ + gcode_fill_polygon_offs(gc, n_coords, x, y, 0, 0); +} + + +static void gcode_calibrate(double xval, double yval) +{ + CRASH("gcode_calibrate"); +} + +static void gcode_set_crosshair(pcb_coord_t x, pcb_coord_t y, int a) +{ +} + +static int gcode_usage(const char *topic) +{ + fprintf(stderr, "\ngcode exporter command line arguments:\n\n"); + pcb_hid_usage(gcode_attribute_list, sizeof(gcode_attribute_list) / sizeof(gcode_attribute_list[0])); + fprintf(stderr, "\nUsage: pcb-rnd [generic_options] -x gcode [gcode options] foo.pcb\n\n"); + return 0; +} + +/* *** Miscellaneous ******************************************************* */ + +#include "dolists.h" + +pcb_hid_t gcode_hid; + +int pplg_check_ver_export_gcode(int ver_needed) { return 0; } + +void pplg_uninit_export_gcode(void) +{ +} + +int pplg_init_export_gcode(void) +{ + PCB_API_CHK_VER; + memset(&gcode_hid, 0, sizeof(pcb_hid_t)); + + pcb_hid_nogui_init(&gcode_hid); + pcb_dhlp_draw_helpers_init(&gcode_hid); + + gcode_hid.struct_size = sizeof(pcb_hid_t); + gcode_hid.name = "gcode"; + gcode_hid.description = "G-CODE export"; + gcode_hid.exporter = 1; + + gcode_hid.get_export_options = gcode_get_export_options; + gcode_hid.do_export = gcode_do_export; + gcode_hid.parse_arguments = gcode_parse_arguments; + gcode_hid.set_layer_group = gcode_set_layer_group; + gcode_hid.make_gc = gcode_make_gc; + gcode_hid.destroy_gc = gcode_destroy_gc; + gcode_hid.set_color = gcode_set_color; + gcode_hid.set_line_cap = gcode_set_line_cap; + gcode_hid.set_line_width = gcode_set_line_width; + gcode_hid.set_draw_xor = gcode_set_draw_xor; + gcode_hid.set_draw_faded = gcode_set_draw_faded; + gcode_hid.draw_line = gcode_draw_line; + gcode_hid.draw_arc = gcode_draw_arc; + gcode_hid.draw_rect = gcode_draw_rect; + gcode_hid.fill_circle = gcode_fill_circle; + gcode_hid.fill_polygon = gcode_fill_polygon; + gcode_hid.fill_polygon_offs = gcode_fill_polygon_offs; + gcode_hid.fill_rect = gcode_fill_rect; + gcode_hid.calibrate = gcode_calibrate; + gcode_hid.set_crosshair = gcode_set_crosshair; + + gcode_hid.usage = gcode_usage; + + pcb_hid_register_hid(&gcode_hid); + + return 0; +} Index: tags/2.1.2/src_plugins/export_gcode/gcode.h =================================================================== --- tags/2.1.2/src_plugins/export_gcode/gcode.h (nonexistent) +++ tags/2.1.2/src_plugins/export_gcode/gcode.h (revision 24813) @@ -0,0 +1,3 @@ +/* $Id: nelma.h,v 1.2 2007/04/20 11:31:15 danmc Exp $ */ +extern const char *gcode_cookie; +extern pcb_hid_t gcode_hid; Index: tags/2.1.2/src_plugins/export_gcode/lists.h =================================================================== --- tags/2.1.2/src_plugins/export_gcode/lists.h (nonexistent) +++ tags/2.1.2/src_plugins/export_gcode/lists.h (revision 24813) @@ -0,0 +1,285 @@ +/* Copyright (C) 2001-2007 Peter Selinger. + This file is part of Potrace. It is free software and it is covered + by the GNU General Public License. See the file COPYING for details. */ + +/* $Id: lists.h 147 2007-04-09 00:44:09Z selinger $ */ + +#ifndef PCB_HID_GCODE_LISTS_H +#define PCB_HID_GCODE_LISTS_H + +/* here we define some general list macros. Because they are macros, + they should work on any datatype with a "->next" component. Some of + them use a "hook". If elt and list are of type t* then hook is of + type t**. A hook stands for an insertion point in the list, i.e., + either before the first element, or between two elements, or after + the last element. If an operation "sets the hook" for an element, + then the hook is set to just before the element. One can insert + something at a hook. One can also unlink at a hook: this means, + unlink the element just after the hook. By "to unlink", we mean the + element is removed from the list, but not deleted. Thus, it and its + components still need to be freed. */ + +/* Note: these macros are somewhat experimental. Only the ones that + are actually *used* have been tested. So be careful to test any + that you use. Looking at the output of the preprocessor, "gcc -E" + (possibly piped though "indent"), might help too. Also: these + macros define some internal (local) variables that start with + "_". */ + +/* we enclose macro definitions whose body consists of more than one + statement in MACRO_BEGIN and MACRO_END, rather than '{' and '}'. The + reason is that we want to be able to use the macro in a context + such as "if (...) macro(...); else ...". If we didn't use this obscure + trick, we'd have to omit the ";" in such cases. */ + +#define MACRO_BEGIN do { +#define MACRO_END } while (0) + +/* ---------------------------------------------------------------------- */ +/* macros for singly-linked lists */ + +/* traverse list. At the end, elt is set to NULL. */ +#define list_forall(elt, list) for (elt=list; elt!=NULL; elt=elt->next) + +/* set elt to the first element of list satisfying boolean condition + c, or NULL if not found */ +#define list_find(elt, list, c) \ + MACRO_BEGIN list_forall(elt, list) if (c) break; MACRO_END + +/* like forall, except also set hook for elt. */ +#define list_forall2(elt, list, hook) \ + for (elt=list, hook=&list; elt!=NULL; hook=&elt->next, elt=elt->next) + +/* same as list_find, except also set hook for elt. */ +#define list_find2(elt, list, c, hook) \ + MACRO_BEGIN list_forall2(elt, list, hook) if (c) break; MACRO_END + +/* same, except only use hook. */ +#define _list_forall_hook(list, hook) \ + for (hook=&list; *hook!=NULL; hook=&(*hook)->next) + +/* same, except only use hook. Note: c may only refer to *hook, not elt. */ +#define _list_find_hook(list, c, hook) \ + MACRO_BEGIN _list_forall_hook(list, hook) if (c) break; MACRO_END + +/* insert element after hook */ +#define list_insert_athook(elt, hook) \ + MACRO_BEGIN elt->next = *hook; *hook = elt; MACRO_END + +/* insert element before hook */ +#define list_insert_beforehook(elt, hook) \ + MACRO_BEGIN elt->next = *hook; *hook = elt; hook=&elt->next; MACRO_END + +/* unlink element after hook, let elt be unlinked element, or NULL. + hook remains. */ +#define list_unlink_athook(list, elt, hook) \ + MACRO_BEGIN \ + elt = hook ? *hook : NULL; if (elt) { *hook = elt->next; elt->next = NULL; }\ + MACRO_END + +/* unlink the specific element, if it is in the list. Otherwise, set + elt to NULL */ +#define list_unlink(listtype, list, elt) \ + MACRO_BEGIN \ + listtype **_hook; \ + _list_find_hook(list, *_hook==elt, _hook); \ + list_unlink_athook(list, elt, _hook); \ + MACRO_END + +/* prepend elt to list */ +#define list_prepend(list, elt) \ + MACRO_BEGIN elt->next = list; list = elt; MACRO_END + +/* append elt to list. */ +#define list_append(listtype, list, elt) \ + MACRO_BEGIN \ + listtype **_hook; \ + _list_forall_hook(list, _hook) {} \ + list_insert_athook(elt, _hook); \ + MACRO_END + +/* unlink the first element that satisfies the condition. */ +#define list_unlink_cond(listtype, list, elt, c) \ + MACRO_BEGIN \ + listtype **_hook; \ + list_find2(elt, list, c, _hook); \ + list_unlink_athook(list, elt, _hook); \ + MACRO_END + +/* let elt be the nth element of the list, starting to count from 0. + Return NULL if out of bounds. */ +#define list_nth(elt, list, n) \ + MACRO_BEGIN \ + int _x; /* only evaluate n once */ \ + for (_x=(n), elt=list; _x && elt; _x--, elt=elt->next) {} \ + MACRO_END + +/* let elt be the nth element of the list, starting to count from 0. + Return NULL if out of bounds. */ +#define list_nth_hook(elt, list, n, hook) \ + MACRO_BEGIN \ + int _x; /* only evaluate n once */ \ + for (_x=(n), elt=list, hook=&list; _x && elt; _x--, hook=&elt->next, elt=elt->next) {} \ + MACRO_END + +/* set n to the length of the list */ +#define list_length(listtype, list, n) \ + MACRO_BEGIN \ + listtype *_elt; \ + n=0; \ + list_forall(_elt, list) \ + n++; \ + MACRO_END + +/* set n to the index of the first element satisfying cond, or -1 if + none found. Also set elt to the element, or NULL if none found. */ +#define list_index(list, n, elt, c) \ + MACRO_BEGIN \ + n=0; \ + list_forall(elt, list) { \ + if (c) break; \ + n++; \ + } \ + if (!elt) \ + n=-1; \ + MACRO_END + +/* set n to the number of elements in the list that satisfy condition c */ +#define list_count(list, n, elt, c) \ + MACRO_BEGIN \ + n=0; \ + list_forall(elt, list) { \ + if (c) n++; \ + } \ + MACRO_END + +/* let elt be each element of the list, unlinked. At the end, set list=NULL. */ +#define list_forall_unlink(elt, list) \ + for (elt=list; elt ? (list=elt->next, elt->next=NULL), 1 : 0; elt=list) + +/* reverse a list (efficient) */ +#define list_reverse(listtype, list) \ + MACRO_BEGIN \ + listtype *_list1=NULL, *elt; \ + list_forall_unlink(elt, list) \ + list_prepend(_list1, elt); \ + list = _list1; \ + MACRO_END + +/* insert the element ELT just before the first element TMP of the + list for which COND holds. Here COND must be a condition of ELT and + TMP. Typical usage is to insert an element into an ordered list: + for instance, list_insert_ordered(listtype, list, elt, tmp, + elt->size <= tmp->size). Note: if we give a "less than or equal" + condition, the new element will be inserted just before a sequence + of equal elements. If we give a "less than" condition, the new + element will be inserted just after a list of equal elements. + Note: it is much more efficient to construct a list with + list_prepend and then order it with list_merge_sort, than to + construct it with list_insert_ordered. */ +#define list_insert_ordered(listtype, list, elt, tmp, cond) \ + MACRO_BEGIN \ + listtype **_hook; \ + _list_find_hook(list, (tmp=*_hook, (cond)), _hook); \ + list_insert_athook(elt, _hook); \ + MACRO_END + +/* sort the given list, according to the comparison condition. + Typical usage is list_sort(listtype, list, a, b, a->size < + b->size). Note: if we give "less than or equal" condition, each + segment of equal elements will be reversed in order. If we give a + "less than" condition, each segment of equal elements will retain + the original order. The latter is slower but sometimes + prettier. Average running time: n*n/2. */ +#define list_sort(listtype, list, a, b, cond) \ + MACRO_BEGIN \ + listtype *_newlist=NULL; \ + list_forall_unlink(a, list) \ + list_insert_ordered(listtype, _newlist, a, b, cond); \ + list = _newlist; \ + MACRO_END + +/* a much faster sort algorithm (merge sort, n log n worst case). It + is required that the list type has an additional, unused next1 + component. Note there is no curious reversal of order of equal + elements as for list_sort. */ + +#define list_mergesort(listtype, list, a, b, cond) \ + MACRO_BEGIN \ + listtype *_elt, **_hook1; \ + \ + for (_elt=list; _elt; _elt=_elt->next1) { \ + _elt->next1 = _elt->next; \ + _elt->next = NULL; \ + } \ + do { \ + _hook1 = &(list); \ + while ((a = *_hook1) != NULL && (b = a->next1) != NULL ) { \ + _elt = b->next1; \ + _list_merge_cond(listtype, a, b, cond, *_hook1); \ + _hook1 = &((*_hook1)->next1); \ + *_hook1 = _elt; \ + } \ + } while (_hook1 != &(list)); \ + MACRO_END + +/* merge two sorted lists. Store result at &result */ +#define _list_merge_cond(listtype, a, b, cond, result) \ + MACRO_BEGIN \ + listtype **_hook; \ + _hook = &(result); \ + while (1) { \ + if (a==NULL) { \ + *_hook = b; \ + break; \ + } else if (b==NULL) { \ + *_hook = a; \ + break; \ + } else if (cond) { \ + *_hook = a; \ + _hook = &(a->next); \ + a = a->next; \ + } else { \ + *_hook = b; \ + _hook = &(b->next); \ + b = b->next; \ + } \ + } \ + MACRO_END + +/* ---------------------------------------------------------------------- */ +/* macros for doubly-linked lists */ + +#define dlist_append(head, end, elt) \ + MACRO_BEGIN \ + elt->prev = end; \ + elt->next = NULL; \ + if (end) { \ + end->next = elt; \ + } else { \ + head = elt; \ + } \ + end = elt; \ + MACRO_END + +/* let elt be each element of the list, unlinked. At the end, set list=NULL. */ +#define dlist_forall_unlink(elt, head, end) \ + for (elt=head; elt ? (head=elt->next, elt->next=NULL, elt->prev=NULL), 1 : (end=NULL, 0); elt=head) + +/* unlink the first element of the list */ +#define dlist_unlink_first(head, end, elt) \ + MACRO_BEGIN \ + elt = head; \ + if (head) { \ + head = head->next; \ + if (head) { \ + head->prev = NULL; \ + } else { \ + end = NULL; \ + } \ + elt->prev = NULL; \ + elt->next = NULL; \ + } \ + MACRO_END + +#endif /* PCB_HID_GCODE_LISTS_H */ Index: tags/2.1.2/src_plugins/export_gcode/potracelib.h =================================================================== --- tags/2.1.2/src_plugins/export_gcode/potracelib.h (nonexistent) +++ tags/2.1.2/src_plugins/export_gcode/potracelib.h (revision 24813) @@ -0,0 +1,130 @@ +/* Copyright (C) 2001-2007 Peter Selinger. + This file is part of Potrace. It is free software and it is covered + by the GNU General Public License. See the file COPYING for details. */ + +#ifndef POTRACELIB_H +#define POTRACELIB_H + +/* this file defines the API for the core Potrace library. For a more + detailed description of the API, see doc/potracelib.txt */ + +/* ---------------------------------------------------------------------- */ +/* tracing parameters */ + +/* turn policies */ +#define POTRACE_TURNPOLICY_BLACK 0 +#define POTRACE_TURNPOLICY_WHITE 1 +#define POTRACE_TURNPOLICY_LEFT 2 +#define POTRACE_TURNPOLICY_RIGHT 3 +#define POTRACE_TURNPOLICY_MINORITY 4 +#define POTRACE_TURNPOLICY_MAJORITY 5 +#define POTRACE_TURNPOLICY_RANDOM 6 + +/* structure to hold progress bar callback data */ +struct potrace_progress_s { + void (*callback) (double progress, void *privdata); /* callback fn */ + void *data; /* callback function's private data */ + double min, max; /* desired range of progress, e.g. 0.0 to 1.0 */ + double epsilon; /* granularity: can skip smaller increments */ +}; +typedef struct potrace_progress_s potrace_progress_t; + +/* structure to hold tracing parameters */ +struct potrace_param_s { + int turdsize; /* area of largest path to be ignored */ + int turnpolicy; /* resolves ambiguous turns in path decomposition */ + double alphamax; /* corner threshold */ + int opticurve; /* use curve optimization? */ + double opttolerance; /* curve optimization tolerance */ + potrace_progress_t progress; /* progress callback function */ +}; +typedef struct potrace_param_s potrace_param_t; + +/* ---------------------------------------------------------------------- */ +/* bitmaps */ + +/* native word size */ +typedef unsigned long potrace_word; + +/* Internal bitmap format. The n-th scanline starts at scanline(n) = + (map + n*dy). Raster data is stored as a sequence of potrace_words + (NOT bytes). The leftmost bit of scanline n is the most significant + bit of scanline(n)[0]. */ +struct potrace_bitmap_s { + int w, h; /* width and height, in pixels */ + int dy; /* words per scanline (not bytes) */ + potrace_word *map; /* raw data, dy*h words */ +}; +typedef struct potrace_bitmap_s potrace_bitmap_t; + +/* ---------------------------------------------------------------------- */ +/* curves */ + +/* point */ +struct potrace_dpoint_s { + double x, y; +}; +typedef struct potrace_dpoint_s potrace_dpoint_t; + +/* segment tags */ +#define POTRACE_CURVETO 1 +#define POTRACE_CORNER 2 + +/* closed curve segment */ +struct potrace_curve_s { + int n; /* number of segments */ + int *tag; /* tag[n]: POTRACE_CURVETO or POTRACE_CORNER */ + potrace_dpoint_t(*c)[3]; /* c[n][3]: control points. + c[n][0] is unused for tag[n]=POTRACE_CORNER */ +}; +typedef struct potrace_curve_s potrace_curve_t; + +/* Linked list of signed curve segments. Also carries a tree structure. */ +struct potrace_path_s { + int area; /* area of the bitmap path */ + int sign; /* '+' or '-', depending on orientation */ + potrace_curve_t curve; /* this path's vector data */ + + struct potrace_path_s *next; /* linked list structure */ + + struct potrace_path_s *childlist; /* tree structure */ + struct potrace_path_s *sibling; /* tree structure */ + + struct potrace_privpath_s *priv; /* private state */ +}; +typedef struct potrace_path_s potrace_path_t; + +/* ---------------------------------------------------------------------- */ +/* Potrace state */ + +#define POTRACE_STATUS_OK 0 +#define POTRACE_STATUS_INCOMPLETE 1 + +struct potrace_state_s { + int status; + potrace_path_t *plist; /* vector data */ + + struct potrace_privstate_s *priv; /* private state */ +}; +typedef struct potrace_state_s potrace_state_t; + +/* ---------------------------------------------------------------------- */ +/* API functions */ + +/* get default parameters */ +potrace_param_t *potrace_param_default(void); + +/* free parameter set */ +void potrace_param_free(potrace_param_t * p); + +/* trace a bitmap*/ +potrace_state_t *potrace_trace(const potrace_param_t * param, const potrace_bitmap_t * bm); + +/* free a Potrace state */ +void potrace_state_free(potrace_state_t * st); + +/* return a static plain text version string identifying this version + of potracelib */ +char *potrace_version(void); + +#endif /* POTRACELIB_H */ Index: tags/2.1.2/src_plugins/export_gcode/trace.c =================================================================== --- tags/2.1.2/src_plugins/export_gcode/trace.c (nonexistent) +++ tags/2.1.2/src_plugins/export_gcode/trace.c (revision 24813) @@ -0,0 +1,1293 @@ +/* This file was slightly modified by Alberto Maccioni to be used with PCB G-CODE exporter*/ + +/* Copyright (C) 2001-2007 Peter Selinger. + This file is part of Potrace. It is free software and it is covered + by the GNU General Public License. See the file COPYING for details. */ + +/* $Id: trace.c 147 2007-04-09 00:44:09Z selinger $ */ +/* transform jaggy paths into smooth curves */ + +#include +#include +#include +#include + +#include "config.h" +#include "potracelib.h" +#include "curve.h" +#include "lists.h" +#include "auxiliary.h" +#include "trace.h" +#include "compat_cc.h" +/*#include "progress.h"*/ + +#define INFTY 10000000 /* it suffices that this is longer than any + path; it need not be really infinite */ +#define COS179 -0.999847695156 /* the cosine of 179 degrees */ + +/* ---------------------------------------------------------------------- */ +#define SAFE_MALLOC(var, n, typ) \ + if ((var = (typ *)malloc((n)*sizeof(typ))) == NULL) goto malloc_error + +/* ---------------------------------------------------------------------- */ +/* auxiliary functions */ + +/* return a direction that is 90 degrees counterclockwise from p2-p0, + but then restricted to one of the major wind directions (n, nw, w, etc) */ +static inline point_t dorth_infty(dpoint_t p0, dpoint_t p2) +{ + point_t r; + + r.y = sign(p2.x - p0.x); + r.x = -sign(p2.y - p0.y); + + return r; +} + +/* return (p1-p0)x(p2-p0), the area of the parallelogram */ +static inline double dpara(dpoint_t p0, dpoint_t p1, dpoint_t p2) +{ + double x1, y1, x2, y2; + + x1 = p1.x - p0.x; + y1 = p1.y - p0.y; + x2 = p2.x - p0.x; + y2 = p2.y - p0.y; + + return x1 * y2 - x2 * y1; +} + +/* ddenom/dpara have the property that the square of radius 1 centered + at p1 intersects the line p0p2 iff |dpara(p0,p1,p2)| <= ddenom(p0,p2) */ +static inline double ddenom(dpoint_t p0, dpoint_t p2) +{ + point_t r = dorth_infty(p0, p2); + + return r.y * (p2.x - p0.x) - r.x * (p2.y - p0.y); +} + +/* return 1 if a <= b < c < a, in a cyclic sense (mod n) */ +static inline int cyclic(int a, int b, int c) +{ + if (a <= c) { + return (a <= b && b < c); + } + else { + return (a <= b || b < c); + } +} + +/* determine the center and slope of the line i..j. Assume ilen; + sums_t *sums = pp->sums; + + double x, y, x2, xy, y2; + double k; + double a, b, c, lambda2, l; + int r = 0; /* rotations from i to j */ + + while (j >= n) { + j -= n; + r += 1; + } + while (i >= n) { + i -= n; + r -= 1; + } + while (j < 0) { + j += n; + r -= 1; + } + while (i < 0) { + i += n; + r += 1; + } + + x = sums[j + 1].x - sums[i].x + r * sums[n].x; + y = sums[j + 1].y - sums[i].y + r * sums[n].y; + x2 = sums[j + 1].x2 - sums[i].x2 + r * sums[n].x2; + xy = sums[j + 1].xy - sums[i].xy + r * sums[n].xy; + y2 = sums[j + 1].y2 - sums[i].y2 + r * sums[n].y2; + k = j + 1 - i + r * n; + + ctr->x = x / k; + ctr->y = y / k; + + a = (x2 - (double) x * x / k) / k; + b = (xy - (double) x * y / k) / k; + c = (y2 - (double) y * y / k) / k; + + lambda2 = (a + c + sqrt((a - c) * (a - c) + 4 * b * b)) / 2; /* larger e.value */ + + /* now find e.vector for lambda2 */ + a -= lambda2; + c -= lambda2; + + if (fabs(a) >= fabs(c)) { + l = sqrt(a * a + b * b); + if (l != 0) { + dir->x = -b / l; + dir->y = a / l; + } + } + else { + l = sqrt(c * c + b * b); + if (l != 0) { + dir->x = -c / l; + dir->y = b / l; + } + } + if (l == 0) { + dir->x = dir->y = 0; /* sometimes this can happen when k=4: + the two eigenvalues coincide */ + } +} + +/* the type of (affine) quadratic forms, represented as symmetric 3x3 + matrices. The value of the quadratic form at a vector (x,y) is v^t + Q v, where v = (x,y,1)^t. */ +typedef double quadform_t[3][3]; + +/* Apply quadratic form Q to vector w = (w.x,w.y) */ +static inline double quadform(quadform_t Q, dpoint_t w) +{ + double v[3]; + int i, j; + double sum; + + v[0] = w.x; + v[1] = w.y; + v[2] = 1; + sum = 0.0; + + for (i = 0; i < 3; i++) { + for (j = 0; j < 3; j++) { + sum += v[i] * Q[i][j] * v[j]; + } + } + return sum; +} + +/* calculate p1 x p2 */ +static inline int xprod(point_t p1, point_t p2) +{ + return p1.x * p2.y - p1.y * p2.x; +} + +/* calculate (p1-p0)x(p3-p2) */ +static inline double cprod(dpoint_t p0, dpoint_t p1, dpoint_t p2, dpoint_t p3) +{ + double x1, y1, x2, y2; + + x1 = p1.x - p0.x; + y1 = p1.y - p0.y; + x2 = p3.x - p2.x; + y2 = p3.y - p2.y; + + return x1 * y2 - x2 * y1; +} + +/* calculate (p1-p0)*(p2-p0) */ +static inline double iprod(dpoint_t p0, dpoint_t p1, dpoint_t p2) +{ + double x1, y1, x2, y2; + + x1 = p1.x - p0.x; + y1 = p1.y - p0.y; + x2 = p2.x - p0.x; + y2 = p2.y - p0.y; + + return x1 * x2 + y1 * y2; +} + +/* calculate (p1-p0)*(p3-p2) */ +static inline double iprod1(dpoint_t p0, dpoint_t p1, dpoint_t p2, dpoint_t p3) +{ + double x1, y1, x2, y2; + + x1 = p1.x - p0.x; + y1 = p1.y - p0.y; + x2 = p3.x - p2.x; + y2 = p3.y - p2.y; + + return x1 * x2 + y1 * y2; +} + +/* calculate distance between two points */ +static inline double ddist(dpoint_t p, dpoint_t q) +{ + return sqrt(sq(p.x - q.x) + sq(p.y - q.y)); +} + +/* calculate point of a bezier curve */ +static inline dpoint_t bezier(double t, dpoint_t p0, dpoint_t p1, dpoint_t p2, dpoint_t p3) +{ + double s = 1 - t; + dpoint_t res; + + /* Note: a good optimizing compiler (such as gcc-3) reduces the + following to 16 multiplications, using common subexpression + elimination. */ + + res.x = s * s * s * p0.x + 3 * (s * s * t) * p1.x + 3 * (t * t * s) * p2.x + t * t * t * p3.x; + res.y = s * s * s * p0.y + 3 * (s * s * t) * p1.y + 3 * (t * t * s) * p2.y + t * t * t * p3.y; + + return res; +} + +/* calculate the point t in [0..1] on the (convex) bezier curve + (p0,p1,p2,p3) which is tangent to q1-q0. Return -1.0 if there is no + solution in [0..1]. */ +static double tangent(dpoint_t p0, dpoint_t p1, dpoint_t p2, dpoint_t p3, dpoint_t q0, dpoint_t q1) +{ + double A, B, C; /* (1-t)^2 A + 2(1-t)t B + t^2 C = 0 */ + double a, b, c; /* a t^2 + b t + c = 0 */ + double d, s, r1, r2; + + A = cprod(p0, p1, q0, q1); + B = cprod(p1, p2, q0, q1); + C = cprod(p2, p3, q0, q1); + + a = A - 2 * B + C; + b = -2 * A + 2 * B; + c = A; + + d = b * b - 4 * a * c; + + if (a == 0 || d < 0) { + return -1.0; + } + + s = sqrt(d); + + r1 = (-b + s) / (2 * a); + r2 = (-b - s) / (2 * a); + + if (r1 >= 0 && r1 <= 1) { + return r1; + } + else if (r2 >= 0 && r2 <= 1) { + return r2; + } + else { + return -1.0; + } +} + +/* ---------------------------------------------------------------------- */ +/* Preparation: fill in the sum* fields of a path (used for later + rapid summing). Return 0 on success, 1 with errno set on + failure. */ +static int calc_sums(privpath_t * pp) +{ + int i, x, y; + int n = pp->len; + + SAFE_MALLOC(pp->sums, pp->len + 1, sums_t); + + /* origin */ + pp->x0 = pp->pt[0].x; + pp->y0 = pp->pt[0].y; + + /* preparatory computation for later fast summing */ + pp->sums[0].x2 = pp->sums[0].xy = pp->sums[0].y2 = pp->sums[0].x = pp->sums[0].y = 0; + for (i = 0; i < n; i++) { + x = pp->pt[i].x - pp->x0; + y = pp->pt[i].y - pp->y0; + pp->sums[i + 1].x = pp->sums[i].x + x; + pp->sums[i + 1].y = pp->sums[i].y + y; + pp->sums[i + 1].x2 = pp->sums[i].x2 + x * x; + pp->sums[i + 1].xy = pp->sums[i].xy + x * y; + pp->sums[i + 1].y2 = pp->sums[i].y2 + y * y; + } + return 0; + +malloc_error: + return 1; +} + +/* ---------------------------------------------------------------------- */ +/* Stage 1: determine the straight subpaths (Sec. 2.2.1). Fill in the + "lon" component of a path object (based on pt/len). For each i, + lon[i] is the furthest index such that a straight line can be drawn + from i to lon[i]. Return 1 on error with errno set, else 0. */ + +/* this algorithm depends on the fact that the existence of straight + subpaths is a triplewise property. I.e., there exists a straight + line through squares i0,...,in iff there exists a straight line + through i,j,k, for all i0<=i= 0 and xprod(constraint[1], + cur) <= 0. */ + +/* Remark for Potrace 1.1: the current implementation of calc_lon is + more complex than the implementation found in Potrace 1.0, but it + is considerably faster. The introduction of the "nc" data structure + means that we only have to test the constraints for "corner" + points. On a typical input file, this speeds up the calc_lon + function by a factor of 31.2, thereby decreasing its time share + within the overall Potrace algorithm from 72.6% to 7.82%, and + speeding up the overall algorithm by a factor of 3.36. On another + input file, calc_lon was sped up by a factor of 6.7, decreasing its + time share from 51.4% to 13.61%, and speeding up the overall + algorithm by a factor of 1.78. In any case, the savings are + substantial. */ + +/* returns 0 on success, 1 on error with errno set */ +static int calc_lon(privpath_t * pp) +{ + point_t *pt = pp->pt; + int n = pp->len; + int i, j, k, k1; + int ct[4], dir; + point_t constraint[2]; + point_t cur; + point_t off; + int *pivk = NULL; /* pivk[n] */ + int *nc = NULL; /* nc[n]: next corner */ + point_t dk; /* direction of k-k1 */ + int a, b, c, d; + + SAFE_MALLOC(pivk, n, int); + SAFE_MALLOC(nc, n, int); + + /* initialize the nc data structure. Point from each point to the + furthest future point to which it is connected by a vertical or + horizontal segment. We take advantage of the fact that there is + always a direction change at 0 (due to the path decomposition + algorithm). But even if this were not so, there is no harm, as + in practice, correctness does not depend on the word "furthest" + above. */ + k = 0; + for (i = n - 1; i >= 0; i--) { + if (pt[i].x != pt[k].x && pt[i].y != pt[k].y) { + k = i + 1; /* necessarily ilon, n, int); + + /* determine pivot points: for each i, let pivk[i] be the furthest k + such that all j with i= 0; i--) { + ct[0] = ct[1] = ct[2] = ct[3] = 0; + + /* keep track of "directions" that have occurred */ + dir = (3 + 3 * (pt[mod(i + 1, n)].x - pt[i].x) + (pt[mod(i + 1, n)].y - pt[i].y)) / 2; + ct[dir]++; + + constraint[0].x = 0; + constraint[0].y = 0; + constraint[1].x = 0; + constraint[1].y = 0; + + /* find the next k such that no straight line from i to k */ + k = nc[i]; + k1 = i; + while (1) { + + dir = (3 + 3 * sign(pt[k].x - pt[k1].x) + sign(pt[k].y - pt[k1].y)) / 2; + ct[dir]++; + + /* if all four "directions" have occurred, cut this path */ + if (ct[0] && ct[1] && ct[2] && ct[3]) { + pivk[i] = k1; + goto foundk; + } + + cur.x = pt[k].x - pt[i].x; + cur.y = pt[k].y - pt[i].y; + + /* see if current constraint is violated */ + if (xprod(constraint[0], cur) < 0 || xprod(constraint[1], cur) > 0) { + goto constraint_viol; + } + + /* else, update constraint */ + if (abs(cur.x) <= 1 && abs(cur.y) <= 1) { + /* no constraint */ + } + else { + off.x = cur.x + ((cur.y >= 0 && (cur.y > 0 || cur.x < 0)) ? 1 : -1); + off.y = cur.y + ((cur.x <= 0 && (cur.x < 0 || cur.y < 0)) ? 1 : -1); + if (xprod(constraint[0], off) >= 0) { + constraint[0] = off; + } + off.x = cur.x + ((cur.y <= 0 && (cur.y < 0 || cur.x < 0)) ? 1 : -1); + off.y = cur.y + ((cur.x >= 0 && (cur.x > 0 || cur.y < 0)) ? 1 : -1); + if (xprod(constraint[1], off) <= 0) { + constraint[1] = off; + } + } + k1 = k; + k = nc[k1]; + if (!cyclic(k, i, k1)) { + break; + } + } + constraint_viol: + /* k1 was the last "corner" satisfying the current constraint, and + k is the first one violating it. We now need to find the last + point along k1..k which satisfied the constraint. */ + dk.x = sign(pt[k].x - pt[k1].x); + dk.y = sign(pt[k].y - pt[k1].y); + cur.x = pt[k1].x - pt[i].x; + cur.y = pt[k1].y - pt[i].y; + /* find largest integer j such that xprod(constraint[0], cur+j*dk) + >= 0 and xprod(constraint[1], cur+j*dk) <= 0. Use bilinearity + of xprod. */ + a = xprod(constraint[0], cur); + b = xprod(constraint[0], dk); + c = xprod(constraint[1], cur); + d = xprod(constraint[1], dk); + /* find largest integer j such that a+j*b>=0 and c+j*d<=0. This + can be solved with integer arithmetic. */ + j = INFTY; + if (b < 0) { + j = floordiv(a, -b); + } + if (d > 0) { + j = min(j, floordiv(-c, d)); + } + pivk[i] = mod(k1 + j, n); + foundk: + ; + } /* for i */ + + /* clean up: for each i, let lon[i] be the largest k such that for + all i' with i<=i'lon[n - 1] = j; + for (i = n - 2; i >= 0; i--) { + if (cyclic(i + 1, pivk[i], j)) { + j = pivk[i]; + } + pp->lon[i] = j; + } + + for (i = n - 1; cyclic(mod(i + 1, n), j, pp->lon[i]); i--) { + pp->lon[i] = j; + } + + free(pivk); + free(nc); + return 0; + +malloc_error: + free(pivk); + free(nc); + return 1; +} + + +/* ---------------------------------------------------------------------- */ +/* Stage 2: calculate the optimal polygon (Sec. 2.2.2-2.2.4). */ + +/* Auxiliary function: calculate the penalty of an edge from i to j in + the given path. This needs the "lon" and "sum*" data. */ + +static double penalty3(privpath_t * pp, int i, int j) +{ + int n = pp->len; + point_t *pt = pp->pt; + sums_t *sums = pp->sums; + + /* assume 0<=i= n) { + j -= n; + r += 1; + } + + x = sums[j + 1].x - sums[i].x + r * sums[n].x; + y = sums[j + 1].y - sums[i].y + r * sums[n].y; + x2 = sums[j + 1].x2 - sums[i].x2 + r * sums[n].x2; + xy = sums[j + 1].xy - sums[i].xy + r * sums[n].xy; + y2 = sums[j + 1].y2 - sums[i].y2 + r * sums[n].y2; + k = j + 1 - i + r * n; + + px = (pt[i].x + pt[j].x) / 2.0 - pt[0].x; + py = (pt[i].y + pt[j].y) / 2.0 - pt[0].y; + ey = (pt[j].x - pt[i].x); + ex = -(pt[j].y - pt[i].y); + + a = ((x2 - 2 * x * px) / k + px * px); + b = ((xy - x * py - y * px) / k + px * py); + c = ((y2 - 2 * y * py) / k + py * py); + + s = ex * ex * a + 2 * ex * ey * b + ey * ey * c; + + return sqrt(s); +} + +/* find the optimal polygon. Fill in the m and po components. Return 1 + on failure with errno set, else 0. Non-cyclic version: assumes i=0 + is in the polygon. Fixme: ### implement cyclic version. */ +static int bestpolygon(privpath_t * pp) +{ + int i, j, m, k; + int n = pp->len; + double *pen = NULL; /* pen[n+1]: penalty vector */ + int *prev = NULL; /* prev[n+1]: best path pointer vector */ + int *clip0 = NULL; /* clip0[n]: longest segment pointer, non-cyclic */ + int *clip1 = NULL; /* clip1[n+1]: backwards segment pointer, non-cyclic */ + int *seg0 = NULL; /* seg0[m+1]: forward segment bounds, m<=n */ + int *seg1 = NULL; /* seg1[m+1]: backward segment bounds, m<=n */ + double thispen; + double best; + int c; + + SAFE_MALLOC(pen, n + 1, double); + SAFE_MALLOC(prev, n + 1, int); + SAFE_MALLOC(clip0, n, int); + SAFE_MALLOC(clip1, n + 1, int); + SAFE_MALLOC(seg0, n + 1, int); + SAFE_MALLOC(seg1, n + 1, int); + + /* calculate clipped paths */ + for (i = 0; i < n; i++) { + c = mod(pp->lon[mod(i - 1, n)] - 1, n); + if (c == i) { + c = mod(i + 1, n); + } + if (c < i) { + clip0[i] = n; + } + else { + clip0[i] = c; + } + } + + /* calculate backwards path clipping, non-cyclic. j <= clip0[i] iff + clip1[j] <= i, for i,j=0..n. */ + j = 1; + for (i = 0; i < n; i++) { + while (j <= clip0[i]) { + clip1[j] = i; + j++; + } + } + + /* calculate seg0[j] = longest path from 0 with j segments */ + i = 0; + for (j = 0; i < n; j++) { + seg0[j] = i; + i = clip0[i]; + } + seg0[j] = n; + m = j; + + /* calculate seg1[j] = longest path to n with m-j segments */ + i = n; + for (j = m; j > 0; j--) { + seg1[j] = i; + i = clip1[i]; + } + seg1[0] = 0; + + /* now find the shortest path with m segments, based on penalty3 */ + /* note: the outer 2 loops jointly have at most n interations, thus + the worst-case behavior here is quadratic. In practice, it is + close to linear since the inner loop tends to be short. */ + pen[0] = 0; + for (j = 1; j <= m; j++) { + for (i = seg1[j]; i <= seg0[j]; i++) { + best = -1; + for (k = seg0[j - 1]; k >= clip1[i]; k--) { + thispen = penalty3(pp, k, i) + pen[k]; + if (best < 0 || thispen < best) { + prev[i] = k; + best = thispen; + } + } + pen[i] = best; + } + } + + pp->m = m; + SAFE_MALLOC(pp->po, m, int); + + /* read off shortest path */ + for (i = n, j = m - 1; i > 0; j--) { + i = prev[i]; + pp->po[j] = i; + } + + free(pen); + free(prev); + free(clip0); + free(clip1); + free(seg0); + free(seg1); + return 0; + +malloc_error: + free(pen); + free(prev); + free(clip0); + free(clip1); + free(seg0); + free(seg1); + return 1; +} + +/* ---------------------------------------------------------------------- */ +/* Stage 3: vertex adjustment (Sec. 2.3.1). */ + +/* Adjust vertices of optimal polygon: calculate the intersection of + the two "optimal" line segments, then move it into the unit square + if it lies outside. Return 1 with errno set on error; 0 on + success. */ + +static int adjust_vertices(privpath_t * pp) +{ + int m = pp->m; + int *po = pp->po; + int n = pp->len; + point_t *pt = pp->pt; + int x0 = pp->x0; + int y0 = pp->y0; + + dpoint_t *ctr = NULL; /* ctr[m] */ + dpoint_t *dir = NULL; /* dir[m] */ + quadform_t *q = NULL; /* q[m] */ + double v[3]; + double d; + int i, j, k, l; + dpoint_t s; + int r; + + SAFE_MALLOC(ctr, m, dpoint_t); + SAFE_MALLOC(dir, m, dpoint_t); + SAFE_MALLOC(q, m, quadform_t); + + r = privcurve_init(&pp->curve, m); + if (r) { + goto malloc_error; + } + + /* calculate "optimal" point-slope representation for each line + segment */ + for (i = 0; i < m; i++) { + j = po[mod(i + 1, m)]; + j = mod(j - po[i], n) + po[i]; + pointslope(pp, po[i], j, &ctr[i], &dir[i]); + } + + /* represent each line segment as a singular quadratic form; the + distance of a point (x,y) from the line segment will be + (x,y,1)Q(x,y,1)^t, where Q=q[i]. */ + for (i = 0; i < m; i++) { + d = sq(dir[i].x) + sq(dir[i].y); + if (d == 0.0) { + for (j = 0; j < 3; j++) { + for (k = 0; k < 3; k++) { + q[i][j][k] = 0; + } + } + } + else { + v[0] = dir[i].y; + v[1] = -dir[i].x; + v[2] = -v[1] * ctr[i].y - v[0] * ctr[i].x; + for (l = 0; l < 3; l++) { + for (k = 0; k < 3; k++) { + q[i][l][k] = v[l] * v[k] / d; + } + } + } + } + + /* now calculate the "intersections" of consecutive segments. + Instead of using the actual intersection, we find the point + within a given unit square which minimizes the square distance to + the two lines. */ + for (i = 0; i < m; i++) { + quadform_t Q; + dpoint_t w; + double dx, dy; + double det; + double min, cand; /* minimum and candidate for minimum of quad. form */ + double xmin, ymin; /* coordinates of minimum */ + int z; + + /* let s be the vertex, in coordinates relative to x0/y0 */ + s.x = pt[po[i]].x - x0; + s.y = pt[po[i]].y - y0; + + /* intersect segments i-1 and i */ + + j = mod(i - 1, m); + + /* add quadratic forms */ + for (l = 0; l < 3; l++) { + for (k = 0; k < 3; k++) { + Q[l][k] = q[j][l][k] + q[i][l][k]; + } + } + + while (1) { + /* minimize the quadratic form Q on the unit square */ + /* find intersection */ + +#ifdef HAVE_GCC_LOOP_BUG + /* work around gcc bug #12243 */ + free(NULL); +#endif + + det = Q[0][0] * Q[1][1] - Q[0][1] * Q[1][0]; + if (det != 0.0) { + w.x = (-Q[0][2] * Q[1][1] + Q[1][2] * Q[0][1]) / det; + w.y = (Q[0][2] * Q[1][0] - Q[1][2] * Q[0][0]) / det; + break; + } + + /* matrix is singular - lines are parallel. Add another, + orthogonal axis, through the center of the unit square */ + if (Q[0][0] > Q[1][1]) { + v[0] = -Q[0][1]; + v[1] = Q[0][0]; + } + else if (Q[1][1]) { + v[0] = -Q[1][1]; + v[1] = Q[1][0]; + } + else { + v[0] = 1; + v[1] = 0; + } + d = sq(v[0]) + sq(v[1]); + v[2] = -v[1] * s.y - v[0] * s.x; + for (l = 0; l < 3; l++) { + for (k = 0; k < 3; k++) { + Q[l][k] += v[l] * v[k] / d; + } + } + } + dx = fabs(w.x - s.x); + dy = fabs(w.y - s.y); + if (dx <= .5 && dy <= .5) { + pp->curve.vertex[i].x = w.x + x0; + pp->curve.vertex[i].y = w.y + y0; + continue; + } + + /* the minimum was not in the unit square; now minimize quadratic + on boundary of square */ + min = quadform(Q, s); + xmin = s.x; + ymin = s.y; + + if (Q[0][0] == 0.0) { + goto fixx; + } + for (z = 0; z < 2; z++) { /* value of the y-coordinate */ + w.y = s.y - 0.5 + z; + w.x = -(Q[0][1] * w.y + Q[0][2]) / Q[0][0]; + dx = fabs(w.x - s.x); + cand = quadform(Q, w); + if (dx <= .5 && cand < min) { + min = cand; + xmin = w.x; + ymin = w.y; + } + } + fixx: + if (Q[1][1] == 0.0) { + goto corners; + } + for (z = 0; z < 2; z++) { /* value of the x-coordinate */ + w.x = s.x - 0.5 + z; + w.y = -(Q[1][0] * w.x + Q[1][2]) / Q[1][1]; + dy = fabs(w.y - s.y); + cand = quadform(Q, w); + if (dy <= .5 && cand < min) { + min = cand; + xmin = w.x; + ymin = w.y; + } + } + corners: + /* check four corners */ + for (l = 0; l < 2; l++) { + for (k = 0; k < 2; k++) { + w.x = s.x - 0.5 + l; + w.y = s.y - 0.5 + k; + cand = quadform(Q, w); + if (cand < min) { + min = cand; + xmin = w.x; + ymin = w.y; + } + } + } + + pp->curve.vertex[i].x = xmin + x0; + pp->curve.vertex[i].y = ymin + y0; + continue; + } + + free(ctr); + free(dir); + free(q); + return 0; + +malloc_error: + free(ctr); + free(dir); + free(q); + return 1; +} + +/* ---------------------------------------------------------------------- */ +/* Stage 4: smoothing and corner analysis (Sec. 2.3.3) */ + +/* Always succeeds and returns 0 */ +static int +PCB_ATTRIBUTE_UNUSED smooth(privcurve_t * curve, int sign, double alphamax) +{ + int m = curve->n; + + int i, j, k; + double dd, denom, alpha; + dpoint_t p2, p3, p4; + + if (sign == '-') { + /* reverse orientation of negative paths */ + for (i = 0, j = m - 1; i < j; i++, j--) { + dpoint_t tmp; + tmp = curve->vertex[i]; + curve->vertex[i] = curve->vertex[j]; + curve->vertex[j] = tmp; + } + } + + /* examine each vertex and find its best fit */ + for (i = 0; i < m; i++) { + j = mod(i + 1, m); + k = mod(i + 2, m); + p4 = interval(1 / 2.0, curve->vertex[k], curve->vertex[j]); + + denom = ddenom(curve->vertex[i], curve->vertex[k]); + if (denom != 0.0) { + dd = dpara(curve->vertex[i], curve->vertex[j], curve->vertex[k]) / denom; + dd = fabs(dd); + alpha = dd > 1 ? (1 - 1.0 / dd) : 0; + alpha = alpha / 0.75; + } + else { + alpha = 4 / 3.0; + } + curve->alpha0[j] = alpha; /* remember "original" value of alpha */ + + if (alpha > alphamax) { /* pointed corner */ + curve->tag[j] = POTRACE_CORNER; + curve->c[j][1] = curve->vertex[j]; + curve->c[j][2] = p4; + } + else { + if (alpha < 0.55) { + alpha = 0.55; + } + else if (alpha > 1) { + alpha = 1; + } + p2 = interval(.5 + .5 * alpha, curve->vertex[i], curve->vertex[j]); + p3 = interval(.5 + .5 * alpha, curve->vertex[k], curve->vertex[j]); + curve->tag[j] = POTRACE_CURVETO; + curve->c[j][0] = p2; + curve->c[j][1] = p3; + curve->c[j][2] = p4; + } + curve->alpha[j] = alpha; /* store the "cropped" value of alpha */ + curve->beta[j] = 0.5; + } + curve->alphacurve = 1; + + return 0; +} + +/* ---------------------------------------------------------------------- */ +/* Stage 5: Curve optimization (Sec. 2.4) */ + +/* a private type for the result of opti_penalty */ +struct opti_s { + double pen; /* penalty */ + dpoint_t c[2]; /* curve parameters */ + double t, s; /* curve parameters */ + double alpha; /* curve parameter */ +}; +typedef struct opti_s opti_t; + +/* calculate best fit from i+.5 to j+.5. Assume icurve.n; + int k, k1, k2, conv, i1; + double area, alpha, d, d1, d2; + dpoint_t p0, p1, p2, p3, pt; + double A, R, A1, A2, A3, A4; + double s, t; + + /* check convexity, corner-freeness, and maximum bend < 179 degrees */ + + if (i == j) { /* sanity - a full loop can never be an opticurve */ + return 1; + } + + k = i; + i1 = mod(i + 1, m); + k1 = mod(k + 1, m); + conv = convc[k1]; + if (conv == 0) { + return 1; + } + d = ddist(pp->curve.vertex[i], pp->curve.vertex[i1]); + for (k = k1; k != j; k = k1) { + k1 = mod(k + 1, m); + k2 = mod(k + 2, m); + if (convc[k1] != conv) { + return 1; + } + if (sign(cprod(pp->curve.vertex[i], pp->curve.vertex[i1], pp->curve.vertex[k1], pp->curve.vertex[k2])) != conv) { + return 1; + } + if (iprod1 + (pp->curve.vertex[i], pp->curve.vertex[i1], pp->curve.vertex[k1], + pp->curve.vertex[k2]) < d * ddist(pp->curve.vertex[k1], pp->curve.vertex[k2]) * COS179) { + return 1; + } + } + + /* the curve we're working in: */ + p0 = pp->curve.c[mod(i, m)][2]; + p1 = pp->curve.vertex[mod(i + 1, m)]; + p2 = pp->curve.vertex[mod(j, m)]; + p3 = pp->curve.c[mod(j, m)][2]; + + /* determine its area */ + area = areac[j] - areac[i]; + area -= dpara(pp->curve.vertex[0], pp->curve.c[i][2], pp->curve.c[j][2]) / 2; + if (i >= j) { + area += areac[m]; + } + + /* find intersection o of p0p1 and p2p3. Let t,s such that o = + interval(t,p0,p1) = interval(s,p3,p2). Let A be the area of the + triangle (p0,o,p3). */ + + A1 = dpara(p0, p1, p2); + A2 = dpara(p0, p1, p3); + A3 = dpara(p0, p2, p3); + /* A4 = dpara(p1, p2, p3); */ + A4 = A1 + A3 - A2; + + if (A2 == A1) { /* this should never happen */ + return 1; + } + + t = A3 / (A3 - A4); + s = A2 / (A2 - A1); + A = A2 * t / 2.0; + + if (A == 0.0) { /* this should never happen */ + return 1; + } + + R = area / A; /* relative area */ + alpha = 2 - sqrt(4 - R / 0.3); /* overall alpha for p0-o-p3 curve */ + + res->c[0] = interval(t * alpha, p0, p1); + res->c[1] = interval(s * alpha, p3, p2); + res->alpha = alpha; + res->t = t; + res->s = s; + + p1 = res->c[0]; + p2 = res->c[1]; /* the proposed curve is now (p0,p1,p2,p3) */ + + res->pen = 0; + + /* calculate penalty */ + /* check tangency with edges */ + for (k = mod(i + 1, m); k != j; k = k1) { + k1 = mod(k + 1, m); + t = tangent(p0, p1, p2, p3, pp->curve.vertex[k], pp->curve.vertex[k1]); + if (t < -.5) { + return 1; + } + pt = bezier(t, p0, p1, p2, p3); + d = ddist(pp->curve.vertex[k], pp->curve.vertex[k1]); + if (d == 0.0) { /* this should never happen */ + return 1; + } + d1 = dpara(pp->curve.vertex[k], pp->curve.vertex[k1], pt) / d; + if (fabs(d1) > opttolerance) { + return 1; + } + if (iprod(pp->curve.vertex[k], pp->curve.vertex[k1], pt) < 0 || iprod(pp->curve.vertex[k1], pp->curve.vertex[k], pt) < 0) { + return 1; + } + res->pen += sq(d1); + } + + /* check corners */ + for (k = i; k != j; k = k1) { + k1 = mod(k + 1, m); + t = tangent(p0, p1, p2, p3, pp->curve.c[k][2], pp->curve.c[k1][2]); + if (t < -.5) { + return 1; + } + pt = bezier(t, p0, p1, p2, p3); + d = ddist(pp->curve.c[k][2], pp->curve.c[k1][2]); + if (d == 0.0) { /* this should never happen */ + return 1; + } + d1 = dpara(pp->curve.c[k][2], pp->curve.c[k1][2], pt) / d; + d2 = dpara(pp->curve.c[k][2], pp->curve.c[k1][2], pp->curve.vertex[k1]) / d; + d2 *= 0.75 * pp->curve.alpha[k1]; + if (d2 < 0) { + d1 = -d1; + d2 = -d2; + } + if (d1 < d2 - opttolerance) { + return 1; + } + if (d1 < d2) { + res->pen += sq(d1 - d2); + } + } + + return 0; +} + +/* optimize the path p, replacing sequences of Bezier segments by a + single segment when possible. Return 0 on success, 1 with errno set + on failure. */ +static int +PCB_ATTRIBUTE_UNUSED opticurve(privpath_t * pp, double opttolerance) +{ + int m = pp->curve.n; + int *pt = NULL; /* pt[m+1] */ + double *pen = NULL; /* pen[m+1] */ + int *len = NULL; /* len[m+1] */ + opti_t *opt = NULL; /* opt[m+1] */ + int om; + int i, j, r; + opti_t o; + dpoint_t p0; + int i1; + double area; + double alpha; + double *s = NULL; + double *t = NULL; + + int *convc = NULL; /* conv[m]: pre-computed convexities */ + double *areac = NULL; /* cumarea[m+1]: cache for fast area computation */ + + SAFE_MALLOC(pt, m + 1, int); + SAFE_MALLOC(pen, m + 1, double); + SAFE_MALLOC(len, m + 1, int); + SAFE_MALLOC(opt, m + 1, opti_t); + SAFE_MALLOC(convc, m, int); + SAFE_MALLOC(areac, m + 1, double); + + /* pre-calculate convexity: +1 = right turn, -1 = left turn, 0 = corner */ + for (i = 0; i < m; i++) { + if (pp->curve.tag[i] == POTRACE_CURVETO) { + convc[i] = sign(dpara(pp->curve.vertex[mod(i - 1, m)], pp->curve.vertex[i], pp->curve.vertex[mod(i + 1, m)])); + } + else { + convc[i] = 0; + } + } + + /* pre-calculate areas */ + area = 0.0; + areac[0] = 0.0; + p0 = pp->curve.vertex[0]; + for (i = 0; i < m; i++) { + i1 = mod(i + 1, m); + if (pp->curve.tag[i1] == POTRACE_CURVETO) { + alpha = pp->curve.alpha[i1]; + area += 0.3 * alpha * (4 - alpha) * dpara(pp->curve.c[i][2], pp->curve.vertex[i1], pp->curve.c[i1][2]) / 2; + area += dpara(p0, pp->curve.c[i][2], pp->curve.c[i1][2]) / 2; + } + areac[i + 1] = area; + } + + pt[0] = -1; + pen[0] = 0; + len[0] = 0; + + /* Fixme: we always start from a fixed point -- should find the best + curve cyclically ### */ + + for (j = 1; j <= m; j++) { + /* calculate best path from 0 to j */ + pt[j] = j - 1; + pen[j] = pen[j - 1]; + len[j] = len[j - 1] + 1; + + for (i = j - 2; i >= 0; i--) { + r = opti_penalty(pp, i, mod(j, m), &o, opttolerance, convc, areac); + if (r) { + break; + } + if (len[j] > len[i] + 1 || (len[j] == len[i] + 1 && pen[j] > pen[i] + o.pen)) { + pt[j] = i; + pen[j] = pen[i] + o.pen; + len[j] = len[i] + 1; + opt[j] = o; + } + } + } + om = len[m]; + r = privcurve_init(&pp->ocurve, om); + if (r) { + goto malloc_error; + } + SAFE_MALLOC(s, om, double); + SAFE_MALLOC(t, om, double); + + j = m; + for (i = om - 1; i >= 0; i--) { + if (pt[j] == j - 1) { + pp->ocurve.tag[i] = pp->curve.tag[mod(j, m)]; + pp->ocurve.c[i][0] = pp->curve.c[mod(j, m)][0]; + pp->ocurve.c[i][1] = pp->curve.c[mod(j, m)][1]; + pp->ocurve.c[i][2] = pp->curve.c[mod(j, m)][2]; + pp->ocurve.vertex[i] = pp->curve.vertex[mod(j, m)]; + pp->ocurve.alpha[i] = pp->curve.alpha[mod(j, m)]; + pp->ocurve.alpha0[i] = pp->curve.alpha0[mod(j, m)]; + pp->ocurve.beta[i] = pp->curve.beta[mod(j, m)]; + s[i] = t[i] = 1.0; + } + else { + pp->ocurve.tag[i] = POTRACE_CURVETO; + pp->ocurve.c[i][0] = opt[j].c[0]; + pp->ocurve.c[i][1] = opt[j].c[1]; + pp->ocurve.c[i][2] = pp->curve.c[mod(j, m)][2]; + pp->ocurve.vertex[i] = interval(opt[j].s, pp->curve.c[mod(j, m)][2], pp->curve.vertex[mod(j, m)]); + pp->ocurve.alpha[i] = opt[j].alpha; + pp->ocurve.alpha0[i] = opt[j].alpha; + s[i] = opt[j].s; + t[i] = opt[j].t; + } + j = pt[j]; + } + + /* calculate beta parameters */ + for (i = 0; i < om; i++) { + i1 = mod(i + 1, om); + pp->ocurve.beta[i] = s[i] / (s[i] + t[i1]); + } + pp->ocurve.alphacurve = 1; + + free(pt); + free(pen); + free(len); + free(opt); + free(s); + free(t); + free(convc); + free(areac); + return 0; + +malloc_error: + free(pt); + free(pen); + free(len); + free(opt); + free(s); + free(t); + free(convc); + free(areac); + return 1; +} + +/* ---------------------------------------------------------------------- */ +double plotpolygon(privpath_t * pp, FILE * f, double scale) +{ + int i; + int m = pp->m; + int *po = pp->po; + point_t *pt = pp->pt; + /* double scale=1.0/dpi; */ + double dm = 0; + + if (!m) + return 0; + + po = pp->po; + pt = pp->pt; + + fprintf(f, "G0 X%f Y%f (start point)\n", pt[po[0]].x * scale, pt[po[0]].y * scale); + fprintf(f, "G1 Z#101\n"); + for (i = 1; i < m; i++) { + fprintf(f, "G1 X%f Y%f\n", pt[po[i]].x * scale, pt[po[i]].y * scale); + dm += + sqrt((pt[po[i]].x - pt[po[i - 1]].x) * scale * (pt[po[i]].x - + pt[po[i - 1]].x) * + scale + (pt[po[i]].y - pt[po[i - 1]].y) * scale * (pt[po[i]].y - pt[po[i - 1]].y) * scale); + } + fprintf(f, "G1 X%f Y%f\n", pt[po[0]].x * scale, pt[po[0]].y * scale); + fprintf(f, "G0 Z#100\n"); + dm += + sqrt((pt[po[m - 1]].x - pt[po[0]].x) * scale * (pt[po[m - 1]].x - + pt[po[0]].x) * scale + + (pt[po[m - 1]].y - pt[po[0]].y) * scale * (pt[po[m - 1]].y - pt[po[0]].y) * scale); + fprintf(f, "(polygon end, distance %.2f)\n", dm); + return dm; +} + +#define TRY(x) if (x) goto try_error + +/* return distance on success, -1 on error with errno set. */ +double process_path(path_t * plist, const potrace_param_t * param, const potrace_bitmap_t * bm, FILE * f, double scale) +{ + path_t *p; + double dm = 0; + int n = 0; + /* call downstream function with each path */ + list_forall(p, plist) { + TRY(calc_sums(p->priv)); + TRY(calc_lon(p->priv)); + TRY(bestpolygon(p->priv)); + TRY(adjust_vertices(p->priv)); + fprintf(f, "(polygon %d)\n", ++n); + dm += plotpolygon(p->priv, f, scale); +/* No need to extract curves + TRY(smooth(&p->priv->curve, p->sign, param->alphamax)); + if (param->opticurve) { + TRY(opticurve(p->priv, param->opttolerance)); + p->priv->fcurve = &p->priv->ocurve; + } else { + p->priv->fcurve = &p->priv->curve; + } + privcurve_to_curve(p->priv->fcurve, &p->curve);*/ + } +/* fprintf(f,"(end, total distance %.2fmm = %.2fin)\n",25.4*dm,dm); */ + return dm; + +try_error: + return -1; +} Index: tags/2.1.2/src_plugins/export_gcode/trace.h =================================================================== --- tags/2.1.2/src_plugins/export_gcode/trace.h (nonexistent) +++ tags/2.1.2/src_plugins/export_gcode/trace.h (revision 24813) @@ -0,0 +1,14 @@ +/* Copyright (C) 2001-2007 Peter Selinger. + This file is part of Potrace. It is free software and it is covered + by the GNU General Public License. See the file COPYING for details. */ + +/* $Id: trace.h 147 2007-04-09 00:44:09Z selinger $ */ + +#ifndef TRACE_H +#define TRACE_H + +#include "potracelib.h" + +double process_path(path_t * plist, const potrace_param_t * param, const potrace_bitmap_t * bm, FILE * f, double scale); + +#endif /* TRACE_H */ Index: tags/2.1.2/src_plugins/export_gerber/Makefile =================================================================== --- tags/2.1.2/src_plugins/export_gerber/Makefile (nonexistent) +++ tags/2.1.2/src_plugins/export_gerber/Makefile (revision 24813) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_export_gerber + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/2.1.2/src_plugins/export_gerber/Plug.tmpasm =================================================================== --- tags/2.1.2/src_plugins/export_gerber/Plug.tmpasm (nonexistent) +++ tags/2.1.2/src_plugins/export_gerber/Plug.tmpasm (revision 24813) @@ -0,0 +1,14 @@ +put /local/pcb/mod {export_gerber} +put /local/pcb/mod/OBJS [@ + $(PLUGDIR)/export_gerber/gerber.o + $(PLUGDIR)/export_gerber/aperture.o + $(PLUGDIR)/export_gerber/excellon.o +@] +put /local/pcb/mod/CONF {$(PLUGDIR)/export_gerber/gerber_conf.h} + + +switch /local/pcb/export_gerber/controls + case {buildin} include /local/pcb/tmpasm/buildin; end; + case {plugin} include /local/pcb/tmpasm/plugin; end; + case {disable} include /local/pcb/tmpasm/disable; end; +end Index: tags/2.1.2/src_plugins/export_gerber/aperture.c =================================================================== --- tags/2.1.2/src_plugins/export_gerber/aperture.c (nonexistent) +++ tags/2.1.2/src_plugins/export_gerber/aperture.c (revision 24813) @@ -0,0 +1,110 @@ + +#include "config.h" + +#include +#include + +#include "global_typedefs.h" + +#define GVT_DONT_UNDEF +#include "aperture.h" +#include + +void init_aperture_list(aperture_list_t *list) +{ + list->data = NULL; + list->count = 0; +} + +void uninit_aperture_list(aperture_list_t *list) +{ + aperture_t *search = list->data; + aperture_t *next; + while (search) { + next = search->next; + free(search); + search = next; + } + init_aperture_list(list); +} + +aperture_t *add_aperture(aperture_list_t *list, pcb_coord_t width, aperture_shape_t shape) +{ + static int aperture_count; + + aperture_t *app = (aperture_t *) malloc(sizeof *app); + if (app == NULL) + return NULL; + + app->width = width; + app->shape = shape; + app->dCode = DCODE_BASE + aperture_count++; + app->next = list->data; + + list->data = app; + ++list->count; + + return app; +} + +aperture_t *find_aperture(aperture_list_t *list, pcb_coord_t width, aperture_shape_t shape) +{ + aperture_t *search; + + /* we never draw zero-width lines */ + if (width == 0) + return NULL; + + /* Search for an appropriate aperture. */ + for (search = list->data; search; search = search->next) + if (search->width == width && search->shape == shape) + return search; + + /* Failing that, create a new one */ + return add_aperture(list, width, shape); +} + + +/*** drill ***/ + +void pcb_drill_init(pcb_drill_ctx_t *ctx) +{ + vtpdr_init(&ctx->obj); + init_aperture_list(&ctx->apr); +} + +void pcb_drill_uninit(pcb_drill_ctx_t *ctx) +{ + vtpdr_uninit(&ctx->obj); + uninit_aperture_list(&ctx->apr); +} + +pcb_pending_drill_t *pcb_drill_new_pending(pcb_drill_ctx_t *ctx, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2, pcb_coord_t diam) +{ + pcb_pending_drill_t *pd = vtpdr_alloc_append(&ctx->obj, 1); + + pd->x = x1; + pd->y = y1; + pd->x2 = x2; + pd->y2 = y2; + pd->diam = diam; + pd->is_slot = (x1 != x2) || (y1 != y2); + find_aperture(&ctx->apr, diam, ROUND); + return pd; +} + +static int drill_sort_cb(const void *va, const void *vb) +{ + pcb_pending_drill_t *a = (pcb_pending_drill_t *)va; + pcb_pending_drill_t *b = (pcb_pending_drill_t *)vb; + if (a->diam != b->diam) + return a->diam - b->diam; + if (a->x != b->x) + return a->x - a->x; + return b->y - b->y; +} + +void pcb_drill_sort(pcb_drill_ctx_t *ctx) +{ + qsort(ctx->obj.array, ctx->obj.used, sizeof(ctx->obj.array[0]), drill_sort_cb); +} Index: tags/2.1.2/src_plugins/export_gerber/aperture.h =================================================================== --- tags/2.1.2/src_plugins/export_gerber/aperture.h (nonexistent) +++ tags/2.1.2/src_plugins/export_gerber/aperture.h (revision 24813) @@ -0,0 +1,75 @@ +#ifndef PCB_APERTURE_H +#define PCB_APERTURE_H + +/*** generic aperture ***/ + +enum aperture_shape_e { + ROUND, /* Shaped like a circle */ + OCTAGON, /* octagonal shape */ + SQUARE /* Shaped like a square */ +}; +typedef enum aperture_shape_e aperture_shape_t; + +/* This is added to the global aperture array indexes to get gerber + dcode and macro numbers. */ +#define DCODE_BASE 11 + +typedef struct aperture { + int dCode; /* The RS-274X D code */ + pcb_coord_t width; /* Size in pcb units */ + aperture_shape_t shape; /* ROUND/SQUARE etc */ + struct aperture *next; +} aperture_t; + +typedef struct { + aperture_t *data; + int count; +} aperture_list_t; + +void init_aperture_list(aperture_list_t *list); +void uninit_aperture_list(aperture_list_t *list); + +/* Create and add a new aperture to the list */ +aperture_t *add_aperture(aperture_list_t *list, pcb_coord_t width, aperture_shape_t shape); + +/* Fetch an aperture from the list with the specified + * width/shape, creating a new one if none exists */ +aperture_t *find_aperture(aperture_list_t *list, pcb_coord_t width, aperture_shape_t shape); + +/*** drill ***/ + +typedef struct { + pcb_coord_t diam; + pcb_coord_t x; + pcb_coord_t y; + + /* for slots */ + int is_slot; + pcb_coord_t x2; + pcb_coord_t y2; +} pcb_pending_drill_t; + +#define GVT(x) vtpdr_ ## x +#define GVT_ELEM_TYPE pcb_pending_drill_t +#define GVT_SIZE_TYPE size_t +#define GVT_DOUBLING_THRS 2048 +#define GVT_START_SIZE 32 +#define GVT_FUNC +/*#define GVT_SET_NEW_BYTES_TO 0*/ + +#include +#define GVT_REALLOC(vect, ptr, size) realloc(ptr, size) +#define GVT_FREE(vect, ptr) free(ptr) +#include + +typedef struct pcb_drill_ctx_s { + vtpdr_t obj; + aperture_list_t apr; +} pcb_drill_ctx_t; + +void pcb_drill_init(pcb_drill_ctx_t *ctx); +void pcb_drill_uninit(pcb_drill_ctx_t *ctx); +pcb_pending_drill_t *pcb_drill_new_pending(pcb_drill_ctx_t *ctx, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2, pcb_coord_t diam); +void pcb_drill_sort(pcb_drill_ctx_t *ctx); + +#endif Index: tags/2.1.2/src_plugins/export_gerber/excellon.c =================================================================== --- tags/2.1.2/src_plugins/export_gerber/excellon.c (nonexistent) +++ tags/2.1.2/src_plugins/export_gerber/excellon.c (revision 24813) @@ -0,0 +1,472 @@ +#include "config.h" + +#include "board.h" +#include "global_typedefs.h" +#include "pcb-printf.h" +#include "safe_fs.h" +#include "error.h" +#include "draw.h" +#include "compat_misc.h" +#include "layer.h" +#include "layer_vis.h" +#include "hid.h" +#include "hid_attrib.h" +#include "hid_cam.h" +#include "hid_init.h" +#include "hid_nogui.h" +#include "hid_draw_helpers.h" +#include "plugins.h" +#include "funchash_core.h" +#include "conf_core.h" +#include "gerber_conf.h" + +#include "excellon.h" + +extern conf_gerber_t conf_gerber; + +#define gerberDrX(pcb, x) ((pcb_coord_t) (x)) +#define gerberDrY(pcb, y) ((pcb_coord_t) ((pcb)->MaxHeight - (y))) + +static pcb_cardinal_t drill_print_objs(pcb_board_t *pcb, FILE *f, pcb_drill_ctx_t *ctx, int force_g85, int slots, pcb_coord_t *excellon_last_tool_dia) +{ + pcb_cardinal_t i, cnt = 0; + int first = 1; + + for (i = 0; i < ctx->obj.used; i++) { + pcb_pending_drill_t *pd = &ctx->obj.array[i]; + if (slots != (!!pd->is_slot)) + continue; + if (i == 0 || pd->diam != *excellon_last_tool_dia) { + aperture_t *ap = find_aperture(&ctx->apr, pd->diam, ROUND); + fprintf(f, "T%02d\r\n", ap->dCode); + *excellon_last_tool_dia = pd->diam; + } + if (pd->is_slot) { + if (first) { + pcb_fprintf(f, "G00"); + first = 0; + } + if (force_g85) + pcb_fprintf(f, "X%06.0mkY%06.0mkG85X%06.0mkY%06.0mk\r\n", gerberDrX(pcb, pd->x), gerberDrY(PCB, pd->y), gerberDrX(pcb, pd->x2), gerberDrY(PCB, pd->y2)); + else + pcb_fprintf(f, "X%06.0mkY%06.0mk\r\nM15\r\nG01X%06.0mkY%06.0mk\r\nM17\r\n", gerberDrX(pcb, pd->x), gerberDrY(PCB, pd->y), gerberDrX(pcb, pd->x2), gerberDrY(PCB, pd->y2)); + first = 1; /* each new slot will need a G00 for some fabs that ignore M17 and M15 */ + } + else { + if (first) { + pcb_fprintf(f, "G05\r\n"); + first = 0; + } + pcb_fprintf(f, "X%06.0mkY%06.0mk\r\n", gerberDrX(pcb, pd->x), gerberDrY(pcb, pd->y)); + } + cnt++; + } + return cnt; +} + +static pcb_cardinal_t drill_print_holes(pcb_board_t *pcb, FILE *f, pcb_drill_ctx_t *ctx, int force_g85) +{ + aperture_t *search; + pcb_cardinal_t cnt = 0; + pcb_coord_t excellon_last_tool_dia = 0; + + /* We omit the ,TZ here because we are not omitting trailing zeros. Our format is + always six-digit 0.1 mil resolution (i.e. 001100 = 0.11") */ + fprintf(f, "M48\r\n" "INCH\r\n"); + for (search = ctx->apr.data; search; search = search->next) + pcb_fprintf(f, "T%02dC%.3mi\r\n", search->dCode, search->width); + fprintf(f, "%%\r\n"); + + /* dump pending drills in sequence */ + pcb_drill_sort(ctx); + cnt += drill_print_objs(pcb, f, ctx, force_g85, 0, &excellon_last_tool_dia); + cnt += drill_print_objs(pcb, f, ctx, force_g85, 1, &excellon_last_tool_dia); + return cnt; +} + +void pcb_drill_export_excellon(pcb_board_t *pcb, pcb_drill_ctx_t *ctx, int force_g85, const char *fn) +{ + FILE *f = pcb_fopen(fn, "wb"); /* Binary needed to force CR-LF */ + if (f == NULL) { + pcb_message(PCB_MSG_ERROR, "Error: Could not open %s for writing the excellon file.\n", fn); + return; + } + + if (ctx->obj.used > 0) + drill_print_holes(pcb, f, ctx, force_g85); + + fprintf(f, "M30\r\n"); + fclose(f); +} + +/*** HID ***/ +static pcb_hid_t excellon_hid; +static const char *excellon_cookie = "gerber exporter: excellon"; + +#define SUFF_LEN 32 + +/* global exporter states */ +static int is_plated, finding_apertures; +static pcb_drill_ctx_t pdrills, udrills; +static pcb_cam_t excellon_cam; +static pcb_coord_t lastwidth; +static char *filename = NULL; +static struct { + unsigned nonround:1; + unsigned arc:1; + unsigned poly:1; + unsigned comp:1; +} warn; + +typedef struct hid_gc_s { + pcb_core_gc_t core_gc; + pcb_cap_style_t style; + pcb_coord_t width; +} hid_gc_s; + +static pcb_hid_attribute_t excellon_options[] = { + +/* %start-doc options "90 excellon Export" +@ftable @code +@item --excellonfile +excellon output file prefix. Can include a path. +@end ftable +%end-doc +*/ + {"filename", "excellon output file base - used to generate default plated and/or unplated file name in case they are not specified", + PCB_HATT_STRING, 0, 0, {0, 0, 0}, 0, 0}, +#define HA_excellonfile 0 + + {"filename-plated", "excellon output file name for plated features", + PCB_HATT_STRING, 0, 0, {0, 0, 0}, 0, 0}, +#define HA_excellonfile_plated 1 + + {"filename-unplated", "excellon output file name for unplated features", + PCB_HATT_STRING, 0, 0, {0, 0, 0}, 0, 0}, +#define HA_excellonfile_unplated 2 + + {"cam", "CAM instruction", + PCB_HATT_STRING, 0, 0, {0, 0, 0}, 0, 0}, +#define HA_cam 3 +}; + +#define NUM_OPTIONS (sizeof(excellon_options)/sizeof(excellon_options[0])) + +static pcb_hid_attr_val_t excellon_values[NUM_OPTIONS]; + +static pcb_hid_attribute_t *excellon_get_export_options(int *n) +{ + if ((PCB != NULL) && (excellon_options[HA_excellonfile].default_val.str_value == NULL)) + pcb_derive_default_filename(PCB->Filename, &excellon_options[HA_excellonfile], ""); + + if (n) + *n = NUM_OPTIONS; + return excellon_options; +} + +static void excellon_do_export(pcb_hid_attr_val_t * options) +{ + const char *fnbase, *fn; + char *filesuff; + int i; + int save_ons[PCB_MAX_LAYER + 2]; + pcb_hid_expose_ctx_t ctx; + + conf_force_set_bool(conf_core.editor.thin_draw, 0); + conf_force_set_bool(conf_core.editor.thin_draw_poly, 0); + conf_force_set_bool(conf_core.editor.check_planes, 0); + + pcb_drill_init(&pdrills); + pcb_drill_init(&udrills); + memset(&warn, 0, sizeof(warn)); + + if (!options) { + excellon_get_export_options(NULL); + for (i = 0; i < NUM_OPTIONS; i++) + excellon_values[i] = excellon_options[i].default_val; + options = excellon_values; + } + + pcb_cam_begin(PCB, &excellon_cam, options[HA_cam].str_value, excellon_options, NUM_OPTIONS, options); + + fnbase = options[HA_excellonfile].str_value; + if (!fnbase) + fnbase = "pcb-out"; + + i = strlen(fnbase); + filename = (char *) realloc(filename, i + SUFF_LEN); + strcpy(filename, fnbase); + filesuff = filename + strlen(filename); + + if (!excellon_cam.active) + pcb_hid_save_and_show_layer_ons(save_ons); + + ctx.view.X1 = 0; + ctx.view.Y1 = 0; + ctx.view.X2 = PCB->MaxWidth; + ctx.view.Y2 = PCB->MaxHeight; + + lastwidth = -1; + finding_apertures = 1; + pcb_hid_expose_all(&excellon_hid, &ctx, NULL); + + lastwidth = -1; + finding_apertures = 0; + pcb_hid_expose_all(&excellon_hid, &ctx, NULL); + conf_update(NULL, -1); /* resotre forced sets */ + + + if (excellon_cam.active) { + fn = excellon_cam.fn; + pcb_drill_export_excellon(PCB, &pdrills, conf_gerber.plugins.export_gerber.plated_g85_slot, fn); + } + else { + if (options[HA_excellonfile_plated].str_value == NULL) { + strcpy(filesuff, ".plated.cnc"); + fn = filename; + } + else + fn = options[HA_excellonfile_plated].str_value; + pcb_drill_export_excellon(PCB, &pdrills, conf_gerber.plugins.export_gerber.plated_g85_slot, fn); + + if (options[HA_excellonfile_unplated].str_value == NULL) { + strcpy(filesuff, ".unplated.cnc"); + fn = filename; + } + else + fn = options[HA_excellonfile_unplated].str_value; + pcb_drill_export_excellon(PCB, &udrills, conf_gerber.plugins.export_gerber.unplated_g85_slot, fn); + } + + if (pcb_cam_end(&excellon_cam) == 0) + pcb_message(PCB_MSG_ERROR, "excellon cam export for '%s' failed to produce any content\n", options[HA_cam].str_value); + + pcb_drill_uninit(&pdrills); + pcb_drill_uninit(&udrills); +} + + +static int excellon_parse_arguments(int *argc, char ***argv) +{ + pcb_hid_register_attributes(excellon_options, NUM_OPTIONS, excellon_cookie, 0); + return pcb_hid_parse_command_line(argc, argv); +} + +static int excellon_set_layer_group(pcb_layergrp_id_t group, const char *purpose, int purpi, pcb_layer_id_t layer, unsigned int flags, int is_empty, pcb_xform_t **xform) +{ + int is_drill; + + /* before cam lets this happen... */ + if (PCB_LAYER_IS_ASSY(flags, purpi)) + return 0; + + pcb_cam_set_layer_group(&excellon_cam, group, purpose, purpi, flags, xform); + + if (flags & PCB_LYT_UI) + return 0; + + is_drill = PCB_LAYER_IS_DRILL(flags, purpi) || ((flags & PCB_LYT_MECH) && PCB_LAYER_IS_ROUTE(flags, purpi)); + if (!is_drill) + return 0; + + is_plated = PCB_LAYER_IS_PROUTE(flags, purpi) || PCB_LAYER_IS_PDRILL(flags, purpi); + return 1; +} + +static pcb_hid_gc_t excellon_make_gc(void) +{ + pcb_hid_gc_t rv = calloc(1, sizeof(*rv)); + return rv; +} + +static void excellon_destroy_gc(pcb_hid_gc_t gc) +{ + free(gc); +} + +static void excellon_set_drawing_mode(pcb_composite_op_t op, pcb_bool direct, const pcb_box_t *drw_screen) +{ + switch(op) { + case PCB_HID_COMP_RESET: + case PCB_HID_COMP_POSITIVE: + case PCB_HID_COMP_FLUSH: + break; + + case PCB_HID_COMP_POSITIVE_XOR: + case PCB_HID_COMP_NEGATIVE: + if (!warn.comp) { + warn.comp = 1; + pcb_message(PCB_MSG_ERROR, "Excellon: can not draw composite layers (some features may be missing from the export)\n"); + } + } +} + +static void excellon_set_color(pcb_hid_gc_t gc, const pcb_color_t *color) +{ +} + +static void excellon_set_line_cap(pcb_hid_gc_t gc, pcb_cap_style_t style) +{ + gc->style = style; +} + +static void excellon_set_line_width(pcb_hid_gc_t gc, pcb_coord_t width) +{ + gc->width = width; +} + +static void excellon_set_draw_xor(pcb_hid_gc_t gc, int xor_) +{ +} + +pcb_drill_ctx_t *get_drill_ctx(void) +{ + if (excellon_cam.active) + return &pdrills; + + return (is_plated ? &pdrills : &udrills); +} + +static void use_gc(pcb_hid_gc_t gc, pcb_coord_t radius) +{ + if ((gc->style != pcb_cap_round) && (!warn.nonround)) { + warn.nonround = 1; + pcb_message(PCB_MSG_ERROR, "Excellon: can not set non-round aperture (some features may be missing from the export)\n"); + } + + if (radius == 0) + radius = gc->width; + else + radius *= 2; + + if (radius != lastwidth) { + aperture_t *aptr = find_aperture(&(get_drill_ctx()->apr), radius, ROUND); + if (aptr == NULL) + pcb_fprintf(stderr, "error: aperture for radius %$mS type ROUND is null\n", radius); + lastwidth = radius; + } +} + + +static void excellon_draw_line(pcb_hid_gc_t gc, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2) +{ + pcb_coord_t dia = gc->width/2; + + find_aperture(&(get_drill_ctx()->apr), dia*2, ROUND); + + if (!finding_apertures) + pcb_drill_new_pending(get_drill_ctx(), x1, y1, x2, y2, dia*2); +} + +static void excellon_draw_rect(pcb_hid_gc_t gc, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2) +{ + excellon_draw_line(gc, x1, y1, x1, y2); + excellon_draw_line(gc, x1, y1, x2, y1); + excellon_draw_line(gc, x1, y2, x2, y2); + excellon_draw_line(gc, x2, y1, x2, y2); +} + +static void excellon_draw_arc(pcb_hid_gc_t gc, pcb_coord_t cx, pcb_coord_t cy, pcb_coord_t width, pcb_coord_t height, pcb_angle_t start_angle, pcb_angle_t delta_angle) +{ + if (!warn.arc) { + warn.arc = 1; + pcb_message(PCB_MSG_ERROR, "Excellon: can not export arcs (some features may be missing from the export)\n"); + } +} + +static void excellon_fill_circle(pcb_hid_gc_t gc, pcb_coord_t cx, pcb_coord_t cy, pcb_coord_t radius) +{ + if (radius <= 0) + return; + + radius = 50 * pcb_round(radius / 50.0); + use_gc(gc, radius); + if (!finding_apertures) + pcb_drill_new_pending(get_drill_ctx(), cx, cy, cx, cy, radius * 2); +} + +static void excellon_fill_polygon_offs(pcb_hid_gc_t gc, int n_coords, pcb_coord_t *x, pcb_coord_t *y, pcb_coord_t dx, pcb_coord_t dy) +{ + if (!warn.poly) { + warn.poly = 1; + pcb_message(PCB_MSG_ERROR, "Excellon: can not export polygons (some features may be missing from the export)\n"); + } +} + +static void excellon_fill_polygon(pcb_hid_gc_t gc, int n_coords, pcb_coord_t *x, pcb_coord_t *y) +{ + excellon_fill_polygon_offs(gc, n_coords, x, y, 0, 0); +} + + +static void excellon_fill_rect(pcb_hid_gc_t gc, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2) +{ + excellon_fill_polygon(gc, 0, NULL, NULL); +} + +static void excellon_calibrate(double xval, double yval) +{ + pcb_message(PCB_MSG_ERROR, "Excellon internal error: can not calibrate()\n"); +} + +static int excellon_usage(const char *topic) +{ + fprintf(stderr, "\nexcellon exporter command line arguments:\n\n"); + pcb_hid_usage(excellon_options, sizeof(excellon_options) / sizeof(excellon_options[0])); + fprintf(stderr, "\nUsage: pcb-rnd [generic_options] -x excellon [excellon options] foo.pcb\n\n"); + return 0; +} + +static void excellon_set_crosshair(pcb_coord_t x, pcb_coord_t y, int action) +{ +} + + + +int pplg_check_ver_export_excellon(int ver_needed) { return 0; } + +void pplg_uninit_export_excellon(void) +{ + pcb_hid_remove_attributes_by_cookie(excellon_cookie); + free(filename); +} + +int pplg_init_export_excellon(void) +{ + PCB_API_CHK_VER; + + memset(&excellon_hid, 0, sizeof(excellon_hid)); + + pcb_hid_nogui_init(&excellon_hid); + pcb_dhlp_draw_helpers_init(&excellon_hid); + + excellon_hid.struct_size = sizeof(excellon_hid); + excellon_hid.name = "excellon"; + excellon_hid.description = "excellon drill/boundary export"; + excellon_hid.exporter = 1; + + excellon_hid.get_export_options = excellon_get_export_options; + excellon_hid.do_export = excellon_do_export; + excellon_hid.parse_arguments = excellon_parse_arguments; + excellon_hid.set_layer_group = excellon_set_layer_group; + excellon_hid.make_gc = excellon_make_gc; + excellon_hid.destroy_gc = excellon_destroy_gc; + excellon_hid.set_drawing_mode = excellon_set_drawing_mode; + excellon_hid.set_color = excellon_set_color; + excellon_hid.set_line_cap = excellon_set_line_cap; + excellon_hid.set_line_width = excellon_set_line_width; + excellon_hid.set_draw_xor = excellon_set_draw_xor; + excellon_hid.draw_line = excellon_draw_line; + excellon_hid.draw_arc = excellon_draw_arc; + excellon_hid.draw_rect = excellon_draw_rect; + excellon_hid.fill_circle = excellon_fill_circle; + excellon_hid.fill_polygon = excellon_fill_polygon; + excellon_hid.fill_polygon_offs = excellon_fill_polygon_offs; + excellon_hid.fill_rect = excellon_fill_rect; + excellon_hid.calibrate = excellon_calibrate; + excellon_hid.set_crosshair = excellon_set_crosshair; + excellon_hid.usage = excellon_usage; + + pcb_hid_register_hid(&excellon_hid); + return 0; +} Index: tags/2.1.2/src_plugins/export_gerber/excellon.h =================================================================== --- tags/2.1.2/src_plugins/export_gerber/excellon.h (nonexistent) +++ tags/2.1.2/src_plugins/export_gerber/excellon.h (revision 24813) @@ -0,0 +1,12 @@ +#ifndef PCB_DRILL_H +#define PCB_DRILL_H + +#include "aperture.h" + +void pcb_drill_export_excellon(pcb_board_t *pcb, pcb_drill_ctx_t *ctx, int force_g85, const char *fn); + +int pplg_check_ver_export_excellon(int ver_needed); +void pplg_uninit_export_excellon(void); +int pplg_init_export_excellon(void); + +#endif Index: tags/2.1.2/src_plugins/export_gerber/export_gerber.pup =================================================================== --- tags/2.1.2/src_plugins/export_gerber/export_gerber.pup (nonexistent) +++ tags/2.1.2/src_plugins/export_gerber/export_gerber.pup (revision 24813) @@ -0,0 +1,9 @@ +$class export +$short Gerber pcb_exporter +$long Export to gerber +$state works +$fmt-native no +$fmt-feature-w export gerber for PCB fabbing, multiple files (configurable) +$package export +default buildin +autoload 1 Index: tags/2.1.2/src_plugins/export_gerber/gerber.c =================================================================== --- tags/2.1.2/src_plugins/export_gerber/gerber.c (nonexistent) +++ tags/2.1.2/src_plugins/export_gerber/gerber.c (revision 24813) @@ -0,0 +1,1361 @@ +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "math_helper.h" +#include "board.h" +#include "build_run.h" +#include "config.h" +#include "data.h" +#include "error.h" +#include "draw.h" +#include "layer.h" +#include "layer_vis.h" +#include "pcb-printf.h" +#include "plugins.h" +#include "hid_cam.h" +#include "compat_misc.h" +#include "safe_fs.h" +#include "macro.h" +#include "funchash_core.h" +#include "gerber_conf.h" + +#include "hid.h" +#include "hid_nogui.h" +#include "hid_draw_helpers.h" +#include "hid_init.h" +#include "hid_attrib.h" +#include "hid_inlines.h" +#include "conf_core.h" + +#include "aperture.h" +#include "excellon.h" + +const char *gerber_cookie = "gerber HID"; + +conf_gerber_t conf_gerber; + +#define CRASH(func) fprintf(stderr, "HID error: pcb called unimplemented Gerber function %s.\n", func); abort() + +#define SUFF_LEN 256 + +#if SUFF_LEN < PCB_DERIVE_FN_SUFF_LEN +# error SUFF_LEN needs at least PCB_DERIVE_FN_SUFF_LEN +#endif + +static pcb_cam_t gerber_cam; + +static pcb_hid_attribute_t *gerber_get_export_options(int *n); +static void gerber_do_export(pcb_hid_attr_val_t * options); +static int gerber_parse_arguments(int *argc, char ***argv); +static pcb_hid_gc_t gerber_make_gc(void); +static void gerber_destroy_gc(pcb_hid_gc_t gc); +static void gerber_set_color(pcb_hid_gc_t gc, const pcb_color_t *name); +static void gerber_set_line_cap(pcb_hid_gc_t gc, pcb_cap_style_t style); +static void gerber_set_line_width(pcb_hid_gc_t gc, pcb_coord_t width); +static void gerber_set_draw_xor(pcb_hid_gc_t gc, int _xor); +static void gerber_draw_line(pcb_hid_gc_t gc, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2); +static void gerber_draw_arc(pcb_hid_gc_t gc, pcb_coord_t cx, pcb_coord_t cy, pcb_coord_t width, pcb_coord_t height, pcb_angle_t start_angle, pcb_angle_t delta_angle); +static void gerber_draw_rect(pcb_hid_gc_t gc, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2); +static void gerber_fill_circle(pcb_hid_gc_t gc, pcb_coord_t cx, pcb_coord_t cy, pcb_coord_t radius); +static void gerber_fill_rect(pcb_hid_gc_t gc, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2); +static void gerber_calibrate(double xval, double yval); +static void gerber_set_crosshair(pcb_coord_t x, pcb_coord_t y, int action); +static void gerber_fill_polygon_offs(pcb_hid_gc_t gc, int n_coords, pcb_coord_t *x, pcb_coord_t *y, pcb_coord_t dx, pcb_coord_t dy); +static void gerber_fill_polygon(pcb_hid_gc_t gc, int n_coords, pcb_coord_t * x, pcb_coord_t * y); + +/*----------------------------------------------------------------------------*/ +/* Utility routines */ +/*----------------------------------------------------------------------------*/ + +/* These are for films */ +#define gerberX(pcb, x) ((pcb_coord_t) (x)) +#define gerberY(pcb, y) ((pcb_coord_t) ((pcb)->MaxHeight - (y))) +#define gerberXOffset(pcb, x) ((pcb_coord_t) (x)) +#define gerberYOffset(pcb, y) ((pcb_coord_t) (-(y))) + +static int verbose; +static int all_layers; +static int is_mask, was_drill; +static int is_drill, is_plated; +static pcb_composite_op_t gerber_drawing_mode, drawing_mode_issued; +static int flash_drills, line_slots; +static int copy_outline_mode; +static int name_style; +static int want_cross_sect; +static int has_outline; +static int gerber_debug; + + +static aperture_list_t *layer_aptr_list; +static aperture_list_t *curr_aptr_list; +static int layer_list_max; +static int layer_list_idx; + +static pcb_drill_ctx_t pdrills, udrills; + +static void reset_apertures(void) +{ + int i; + for (i = 0; i < layer_list_max; ++i) + uninit_aperture_list(&layer_aptr_list[i]); + free(layer_aptr_list); + layer_aptr_list = NULL; + curr_aptr_list = NULL; + layer_list_max = 0; + layer_list_idx = 0; +} + +static void fprint_aperture(FILE *f, aperture_t *aptr) +{ + switch (aptr->shape) { + case ROUND: + pcb_fprintf(f, "%%ADD%dC,%[5]*%%\r\n", aptr->dCode, aptr->width); + break; + case SQUARE: + pcb_fprintf(f, "%%ADD%dR,%[5]X%[5]*%%\r\n", aptr->dCode, aptr->width, aptr->width); + break; + case OCTAGON: + pcb_fprintf(f, "%%AMOCT%d*5,0,8,0,0,%[5],22.5*%%\r\n" + "%%ADD%dOCT%d*%%\r\n", aptr->dCode, (pcb_coord_t) ((double) aptr->width / PCB_COS_22_5_DEGREE), aptr->dCode, aptr->dCode); + break; + } +} + +#define AUTO_OUTLINE_WIDTH PCB_MIL_TO_COORD(8) /* Auto-geneated outline width of 8 mils */ + +/* Set the aperture list for the current layer, + * expanding the list buffer if needed */ +static aperture_list_t *set_layer_aperture_list(int layer_idx) +{ + if (layer_idx >= layer_list_max) { + int i = layer_list_max; + layer_list_max = 2 * (layer_idx + 1); + layer_aptr_list = (aperture_list_t *) + realloc(layer_aptr_list, layer_list_max * sizeof(*layer_aptr_list)); + for (; i < layer_list_max; ++i) + init_aperture_list(&layer_aptr_list[i]); + } + curr_aptr_list = &layer_aptr_list[layer_idx]; + return curr_aptr_list; +} + +/* --------------------------------------------------------------------------- */ + +static pcb_hid_t gerber_hid; + +typedef struct hid_gc_s { + pcb_core_gc_t core_gc; + pcb_cap_style_t cap; + int width; + int color; + int erase; + int drill; +} hid_gc_s; + +static FILE *f = NULL; +static char *filename = NULL; +static char *filesuff = NULL; +static char *layername = NULL; +static int lncount = 0; + +static int finding_apertures = 0; +static int pagecount = 0; +static int linewidth = -1; +static pcb_layergrp_id_t lastgroup = -1; +static int lastcap = -1; +static int lastcolor = -1; +static int lastX, lastY; /* the last X and Y coordinate */ + +static const char *copy_outline_names[] = { +#define COPY_OUTLINE_NONE 0 + "none", +#define COPY_OUTLINE_MASK 1 + "mask", +#define COPY_OUTLINE_SILK 2 + "silk", +#define COPY_OUTLINE_ALL 3 + "all", + NULL +}; + +static const char *name_style_names[] = { +#define NAME_STYLE_PCB_RND 0 + "pcb-rnd", +#define NAME_STYLE_FIXED 1 + "fixed", +#define NAME_STYLE_SINGLE 2 + "single", +#define NAME_STYLE_FIRST 3 + "first", +#define NAME_STYLE_EAGLE 4 + "eagle", +#define NAME_STYLE_HACKVANA 5 + "hackvana", +#define NAME_STYLE_UNIVERSAL 6 + "universal", + NULL +}; + +typedef struct { + const char *hdr1; + const char *cfmt; /* drawing coordinate format */ + const char *afmt; /* aperture description format */ +} coord_format_t; + +coord_format_t coord_format[] = { + {"%MOIN*%\r\n%FSLAX25Y25*%\r\n", "%.0mc", "%.4mi"}, /* centimil: inch, leading zero suppression, Absolute Data, 2.5 format */ + {"%MOMM*%\r\n%FSLAX43Y43*%\r\n", "%.0mu", "%.3mm"}, /* micrometer: mm, leading zero suppression, Absolute Data, 4.3 format */ + {"%MOMM*%\r\n%FSLAX46Y46*%\r\n", "%.0mn", "%.6mm"} /* nanometer: mm, leading zero suppression, Absolute Data, 4.6 format */ +}; +#define NUM_COORD_FORMATS (sizeof(coord_format)/sizeof(coord_format[0])) + +static coord_format_t *gerber_cfmt; + +static const char *coord_format_names[NUM_COORD_FORMATS+1] = { + "centimil", + "micrometer", + "nanometer", + NULL +}; + +static pcb_hid_attribute_t gerber_options[] = { + +/* %start-doc options "90 Gerber Export" +@ftable @code +@item --gerberfile +Gerber output file prefix. Can include a path. +@end ftable +%end-doc +*/ + {"gerberfile", "Gerber output file base", + PCB_HATT_STRING, 0, 0, {0, 0, 0}, 0, 0}, +#define HA_gerberfile 0 + +/* %start-doc options "90 Gerber Export" +@ftable @code +@item --all-layers +Output contains all layers, even empty ones. +@end ftable +%end-doc +*/ + {"all-layers", "Output all layers, even empty ones", + PCB_HATT_BOOL, 0, 0, {0, 0, 0}, 0, 0}, +#define HA_all_layers 1 + +/* %start-doc options "90 Gerber Export" +@ftable @code +@item --verbose +Print file names and aperture counts on stdout. +@end ftable +%end-doc +*/ + {"verbose", "Print file names and aperture counts on stdout", + PCB_HATT_BOOL, 0, 0, {0, 0, 0}, 0, 0}, +#define HA_verbose 2 + {"copy-outline", "Copy outline onto other layers", + PCB_HATT_ENUM, 0, 0, {0, 0, 0}, copy_outline_names, 0}, +#define HA_copy_outline 3 + {"name-style", "Naming style for individual gerber files", + PCB_HATT_ENUM, 0, 0, {0, 0, 0}, name_style_names, 0}, +#define HA_name_style 4 + {"cross-sect", "Export the cross section layer", + PCB_HATT_BOOL, 0, 0, {0, 0, 0}, 0, 0}, +#define HA_cross_sect 5 + + {"coord-format", "Coordinate format (resolution)", + PCB_HATT_ENUM, 0, 0, {0, 0, 0}, coord_format_names, 0}, +#define HA_coord_format 6 + + {"cam", "CAM instruction", + PCB_HATT_STRING, 0, 0, {0, 0, 0}, 0, 0}, +#define HA_cam 7 +}; + +#define NUM_OPTIONS (sizeof(gerber_options)/sizeof(gerber_options[0])) + +static pcb_hid_attr_val_t gerber_values[NUM_OPTIONS]; + +static pcb_hid_attribute_t *gerber_get_export_options(int *n) +{ + if ((PCB != NULL) && (gerber_options[HA_gerberfile].default_val.str_value == NULL)) + pcb_derive_default_filename(PCB->Filename, &gerber_options[HA_gerberfile], ""); + + if (n) + *n = NUM_OPTIONS; + return gerber_options; +} + +static pcb_layergrp_id_t group_for_layer(int l) +{ + if (l < pcb_max_layer && l >= 0) + return pcb_layer_get_group(PCB, l); + /* else something unique */ + return pcb_max_group(PCB) + 3 + l; +} + +static int layer_sort(const void *va, const void *vb) +{ + int a = *(int *) va; + int b = *(int *) vb; + int d = group_for_layer(b) - group_for_layer(a); + if (d) + return d; + return b - a; +} + +static void maybe_close_f(FILE * f) +{ + if (f) { + if ((was_drill) && (!gerber_cam.active)) { + TODO("excellon split"); + /* Leftover from when we generate excellon from gerber. Remove this. */ + fprintf(f, "M30\r\n"); + } + else + fprintf(f, "M02*\r\n"); + fclose(f); + } +} + +static pcb_box_t region; + +#define fmatch(flags, bits) (((flags) & (bits)) == (bits)) + +/* Very similar to pcb_layer_to_file_name() but appends only a + three-character suffix compatible with Eagle's defaults. */ +static void assign_eagle_file_suffix(char *dest, pcb_layer_id_t lid, unsigned int flags, int purpi) +{ + const char *suff = "out"; + + if (fmatch(flags, PCB_LYT_TOP | PCB_LYT_COPPER)) + suff = "cmp"; + else if (fmatch(flags, PCB_LYT_BOTTOM | PCB_LYT_COPPER)) + suff = "sol"; + else if (fmatch(flags, PCB_LYT_TOP | PCB_LYT_SILK)) + suff = "plc"; + else if (fmatch(flags, PCB_LYT_BOTTOM | PCB_LYT_SILK)) + suff = "pls"; + else if (fmatch(flags, PCB_LYT_TOP | PCB_LYT_MASK)) + suff = "stc"; + else if (fmatch(flags, PCB_LYT_BOTTOM | PCB_LYT_MASK)) + suff = "sts"; + else if (PCB_LAYER_IS_PDRILL(flags, purpi)) + suff = "drd"; + else if (PCB_LAYER_IS_UDRILL(flags, purpi)) + suff = "dru"; + else if (fmatch(flags, PCB_LYT_TOP | PCB_LYT_PASTE)) + suff = "crc"; + else if (fmatch(flags, PCB_LYT_BOTTOM | PCB_LYT_PASTE)) + suff = "crs"; + else if (fmatch(flags, PCB_LYT_INVIS)) + suff = "inv"; + else if (PCB_LAYER_IS_FAB(flags, purpi)) + suff = "fab"; + else if (fmatch(flags, PCB_LYT_TOP) && PCB_LAYER_IS_ASSY(flags, purpi)) + suff = "ast"; + else if (fmatch(flags, PCB_LYT_BOTTOM) && PCB_LAYER_IS_ASSY(flags, purpi)) + suff = "asb"; + else if (PCB_LAYER_IS_ROUTE(flags, purpi)) + suff = "oln"; + else { + static char buf[20]; + pcb_layergrp_id_t group = pcb_layer_get_group(PCB, lid); + sprintf(buf, "ly%ld", group); + suff = buf; + } + strcpy(dest, suff); +} + +/* Very similar to layer_type_to_file_name() but appends only a + three-character suffix compatible with Hackvana's naming requirements */ +static void assign_hackvana_file_suffix(char *dest, pcb_layer_id_t lid, unsigned int flags, int purpi) +{ + char *suff; + + if (fmatch(flags, PCB_LYT_TOP | PCB_LYT_COPPER)) + suff = "gtl"; + else if (fmatch(flags, PCB_LYT_BOTTOM | PCB_LYT_COPPER)) + suff = "gbl"; + else if (fmatch(flags, PCB_LYT_TOP | PCB_LYT_SILK)) + suff = "gto"; + else if (fmatch(flags, PCB_LYT_BOTTOM | PCB_LYT_SILK)) + suff = "gbo"; + else if (fmatch(flags, PCB_LYT_TOP | PCB_LYT_MASK)) + suff = "gts"; + else if (fmatch(flags, PCB_LYT_BOTTOM | PCB_LYT_MASK)) + suff = "gbs"; + else if (PCB_LAYER_IS_PDRILL(flags, purpi)) + suff = "cnc"; + else if (PCB_LAYER_IS_UDRILL(flags, purpi)) + suff = "_NPTH.drl"; + else if (fmatch(flags, PCB_LYT_TOP | PCB_LYT_PASTE)) + suff = "gtp"; + else if (fmatch(flags, PCB_LYT_BOTTOM | PCB_LYT_PASTE)) + suff = "gbp"; + else if (fmatch(flags, PCB_LYT_INVIS)) + suff = "inv"; + else if (PCB_LAYER_IS_FAB(flags, purpi)) + suff = "fab"; + else if (fmatch(flags, PCB_LYT_TOP) && PCB_LAYER_IS_ASSY(flags, purpi)) + suff = "ast"; + else if (fmatch(flags, PCB_LYT_BOTTOM) && PCB_LAYER_IS_ASSY(flags, purpi)) + suff = "asb"; + else if (PCB_LAYER_IS_ROUTE(flags, purpi)) + suff = "gm1"; + else { + static char buf[20]; + pcb_layergrp_id_t group = pcb_layer_get_group(PCB, lid); + sprintf(buf, "g%ld", group); + suff = buf; + } + strcpy(dest, suff); +} + +/* Very similar to layer_type_to_file_name() but appends the group name _and_ the magic suffix */ +static void assign_universal_file_suffix(char *dest, pcb_layergrp_id_t gid, unsigned int flags, int purpi) +{ + char *suff; + int name_len; + pcb_layergrp_t *g; + + if (fmatch(flags, PCB_LYT_TOP | PCB_LYT_COPPER)) + suff = "gtl"; + else if (fmatch(flags, PCB_LYT_BOTTOM | PCB_LYT_COPPER)) + suff = "gbl"; + else if (fmatch(flags, PCB_LYT_TOP | PCB_LYT_SILK)) + suff = "gto"; + else if (fmatch(flags, PCB_LYT_BOTTOM | PCB_LYT_SILK)) + suff = "gbo"; + else if (fmatch(flags, PCB_LYT_TOP | PCB_LYT_MASK)) + suff = "gts"; + else if (fmatch(flags, PCB_LYT_BOTTOM | PCB_LYT_MASK)) + suff = "gbs"; + else if (PCB_LAYER_IS_PDRILL(flags, purpi)) + suff = "drl"; + else if (PCB_LAYER_IS_UDRILL(flags, purpi)) + suff = "_NPTH.drl"; + else if (fmatch(flags, PCB_LYT_TOP | PCB_LYT_PASTE)) + suff = "gtp"; + else if (fmatch(flags, PCB_LYT_BOTTOM | PCB_LYT_PASTE)) + suff = "gbp"; + else if (fmatch(flags, PCB_LYT_INVIS)) + suff = "inv"; + else if (PCB_LAYER_IS_FAB(flags, purpi)) + suff = "fab"; + else if (fmatch(flags, PCB_LYT_TOP) && PCB_LAYER_IS_ASSY(flags, purpi)) + suff = "ast"; + else if (fmatch(flags, PCB_LYT_BOTTOM) && PCB_LAYER_IS_ASSY(flags, purpi)) + suff = "asb"; + else if (PCB_LAYER_IS_ROUTE(flags, purpi)) + suff = "gko"; + else { + static char buf[20]; + sprintf(buf, "g%ld", gid); + suff = buf; + } + + /* insert group name if available */ + g = pcb_get_layergrp(PCB, gid); + if (g != NULL) { + name_len = strlen(g->name); + if (name_len >= SUFF_LEN-5) + name_len = SUFF_LEN-5; /* truncate group name */ + memcpy(dest, g->name, name_len); + dest += name_len; + *dest = '.'; + dest++; + } + strcpy(dest, suff); +} + + +#undef fmatch + +static void assign_file_suffix(char *dest, pcb_layergrp_id_t gid, pcb_layer_id_t lid, unsigned int flags, const char *purpose, int purpi, int drill, int *merge_same) +{ + int fns_style; + const char *sext = ".gbr"; + + if (merge_same != NULL) *merge_same = 0; + + switch (name_style) { + default: + case NAME_STYLE_PCB_RND: + fns_style = PCB_FNS_pcb_rnd; + break; + case NAME_STYLE_FIXED: + fns_style = PCB_FNS_fixed; + break; + case NAME_STYLE_SINGLE: + fns_style = PCB_FNS_single; + break; + case NAME_STYLE_FIRST: + fns_style = PCB_FNS_first; + break; + case NAME_STYLE_EAGLE: + assign_eagle_file_suffix(dest, lid, flags, purpi); + if (merge_same != NULL) *merge_same = 1; + return; + case NAME_STYLE_HACKVANA: + assign_hackvana_file_suffix(dest, lid, flags, purpi); + if (merge_same != NULL) *merge_same = 1; + return; + case NAME_STYLE_UNIVERSAL: + assign_universal_file_suffix(dest, gid, flags, purpi); + if (merge_same != NULL) *merge_same = 1; + return; + } + + if (drill && PCB_LAYER_IS_DRILL(flags, purpi)) + sext = ".cnc"; + pcb_layer_to_file_name(dest, lid, flags, purpose, purpi, fns_style); + strcat(dest, sext); +} + +static void gerber_do_export(pcb_hid_attr_val_t * options) +{ + const char *fnbase; + int i; + static int saved_layer_stack[PCB_MAX_LAYER]; + int save_ons[PCB_MAX_LAYER + 2]; + pcb_hid_expose_ctx_t ctx; + + conf_force_set_bool(conf_core.editor.thin_draw, 0); + conf_force_set_bool(conf_core.editor.thin_draw_poly, 0); + conf_force_set_bool(conf_core.editor.check_planes, 0); + + pcb_drill_init(&pdrills); + pcb_drill_init(&udrills); + + drawing_mode_issued = PCB_HID_COMP_POSITIVE; + + if (!options) { + gerber_get_export_options(NULL); + for (i = 0; i < NUM_OPTIONS; i++) + gerber_values[i] = gerber_options[i].default_val; + options = gerber_values; + } + + /* set up the coord format */ + i = options[HA_coord_format].int_value; + if ((i < 0) || (i >= NUM_COORD_FORMATS)) { + pcb_message(PCB_MSG_ERROR, "Invalid coordinate format (out of bounds)\n"); + return; + } + gerber_cfmt = &coord_format[i]; + pcb_printf_slot[4] = gerber_cfmt->cfmt; + pcb_printf_slot[5] = gerber_cfmt->afmt; + + pcb_cam_begin(PCB, &gerber_cam, options[HA_cam].str_value, gerber_options, NUM_OPTIONS, options); + + fnbase = options[HA_gerberfile].str_value; + if (!fnbase) + fnbase = "pcb-out"; + + verbose = options[HA_verbose].int_value || conf_core.rc.verbose; + all_layers = options[HA_all_layers].int_value; + + copy_outline_mode = options[HA_copy_outline].int_value; + name_style = options[HA_name_style].int_value; + + want_cross_sect = options[HA_cross_sect].int_value; + + has_outline = pcb_has_explicit_outline(PCB); + + i = strlen(fnbase); + filename = (char *) realloc(filename, i + SUFF_LEN); + strcpy(filename, fnbase); + strcat(filename, "."); + filesuff = filename + strlen(filename); + + if (!gerber_cam.active) + pcb_hid_save_and_show_layer_ons(save_ons); + + memcpy(saved_layer_stack, pcb_layer_stack, sizeof(pcb_layer_stack)); + qsort(pcb_layer_stack, pcb_max_layer, sizeof(pcb_layer_stack[0]), layer_sort); + linewidth = -1; + lastcap = -1; + lastgroup = -1; + lastcolor = -1; + + ctx.view.X1 = 0; + ctx.view.Y1 = 0; + ctx.view.X2 = PCB->MaxWidth; + ctx.view.Y2 = PCB->MaxHeight; + + pagecount = 1; + reset_apertures(); + + lastgroup = -1; + layer_list_idx = 0; + finding_apertures = 1; + pcb_hid_expose_all(&gerber_hid, &ctx, NULL); + + lastgroup = -2; + layer_list_idx = 0; + finding_apertures = 0; + pcb_hid_expose_all(&gerber_hid, &ctx, NULL); + + memcpy(pcb_layer_stack, saved_layer_stack, sizeof(pcb_layer_stack)); + + maybe_close_f(f); + f = NULL; + if (!gerber_cam.active) + pcb_hid_restore_layer_ons(save_ons); + conf_update(NULL, -1); /* resotre forced sets */ + + if (!gerber_cam.active) { + int purpi; + const pcb_virt_layer_t *vl; + + maybe_close_f(f); + f = NULL; + + pagecount++; + purpi = F_pdrill; + vl = pcb_vlayer_get_first(PCB_LYT_VIRTUAL, "pdrill", purpi); + assert(vl != NULL); + assign_file_suffix(filesuff, -1, vl->new_id, vl->type, "pdrill", purpi, 1, NULL); + pcb_drill_export_excellon(PCB, &pdrills, conf_gerber.plugins.export_gerber.plated_g85_slot, filename); + + pagecount++; + purpi = F_udrill; + vl = pcb_vlayer_get_first(PCB_LYT_VIRTUAL, "udrill", purpi); + assert(vl != NULL); + assign_file_suffix(filesuff, -1, vl->new_id, vl->type, "udrill", purpi, 1, NULL); + pcb_drill_export_excellon(PCB, &udrills, conf_gerber.plugins.export_gerber.unplated_g85_slot, filename); + } + + if (pcb_cam_end(&gerber_cam) == 0) + pcb_message(PCB_MSG_ERROR, "gerber cam export for '%s' failed to produce any content\n", options[HA_cam].str_value); + + pcb_drill_uninit(&pdrills); + pcb_drill_uninit(&udrills); + + /* in cam mode we have f still open */ + maybe_close_f(f); + f = NULL; +} + +static int gerber_parse_arguments(int *argc, char ***argv) +{ + pcb_hid_register_attributes(gerber_options, NUM_OPTIONS, gerber_cookie, 0); + return pcb_hid_parse_command_line(argc, argv); +} + + + +static int gerber_set_layer_group(pcb_layergrp_id_t group, const char *purpose, int purpi, pcb_layer_id_t layer, unsigned int flags, int is_empty, pcb_xform_t **xform) +{ + int want_outline; + char *cp; + const char *group_name; + + pcb_cam_set_layer_group(&gerber_cam, group, purpose, purpi, flags, xform); + + if ((!gerber_cam.active) && (PCB_LAYER_IS_ASSY(flags, purpi))) + return 0; + + if ((!gerber_cam.active) && (flags & PCB_LYT_DOC)) + return 0; + + if (flags & PCB_LYT_UI) + return 0; + +#if 0 + printf(" Layer %s group %lx drill %d mask %d flags=%lx\n", pcb_layer_name(PCB, layer), group, is_drill, is_mask, flags); +#endif + + + if (!all_layers) { + int stay = 0; + if ((group >= 0) && pcb_layergrp_is_empty(PCB, group) && !(flags & PCB_LYT_SILK)) { + /* layer is empty and the user didn't want to have empty layers; however; + if the user wants to copy the outline to specific layers, those + layers will become non-empty: even an empty outline would bring + the implicit outline rectangle at board extents! */ + + if (copy_outline_mode == COPY_OUTLINE_MASK && (flags & PCB_LYT_MASK)) stay = 1; + if (copy_outline_mode == COPY_OUTLINE_SILK && (flags & PCB_LYT_SILK)) stay = 1; + if (copy_outline_mode == COPY_OUTLINE_ALL && \ + ((flags & PCB_LYT_SILK) || (flags & PCB_LYT_MASK) || + PCB_LAYER_IS_FAB(flags, purpi) || PCB_LAYER_IS_ASSY(flags, purpi) || + PCB_LAYER_IS_OUTLINE(flags, purpi))) stay = 1; + + if (!stay) return 0; + } + } + + if (flags & PCB_LYT_INVIS) { +/* printf(" nope: invis %d or assy %d\n", (flags & PCB_LYT_INVIS), (flags & PCB_LYT_ASSY));*/ + return 0; + } + + if (PCB_LAYER_IS_CSECT(flags, purpi) && (!want_cross_sect)) + return 0; + + if ((group >= 0) && (group < pcb_max_group(PCB))) { + group_name = PCB->LayerGroups.grp[group].name; + if (group_name == NULL) + group_name = ""; + } + else + group_name = ""; + + flash_drills = 0; + line_slots = 0; + if ((flags & PCB_LYT_MECH) && PCB_LAYER_IS_ROUTE(flags, purpi)) { + flash_drills = 1; + line_slots = 1; + } + + is_drill = PCB_LAYER_IS_DRILL(flags, purpi) || ((flags & PCB_LYT_MECH) && PCB_LAYER_IS_ROUTE(flags, purpi)); + is_plated = PCB_LAYER_IS_PROUTE(flags, purpi) || PCB_LAYER_IS_PDRILL(flags, purpi); + is_mask = !!(flags & PCB_LYT_MASK); + if (group < 0 || group != lastgroup) { + char utcTime[64]; + aperture_list_t *aptr_list; + aperture_t *search; + + lastgroup = group; + lastX = -1; + lastY = -1; + lastcolor = 0; + linewidth = -1; + lastcap = -1; + + aptr_list = set_layer_aperture_list(layer_list_idx++); + + if (finding_apertures) + goto emit_outline; + + if (aptr_list->count == 0 && !all_layers && !is_drill) + return 0; + + /* If two adjacent groups end up with the same file name, they are really one group */ + if ((!gerber_cam.active && (f != NULL))) { + char tmp[256]; + int merge_same; + assign_file_suffix(tmp, group, layer, flags, purpose, purpi, 0, &merge_same); + if (merge_same && (strcmp(tmp, filesuff) == 0)) + return 1; + } + + if ((!gerber_cam.active) || (gerber_cam.fn_changed)) { + /* in cam mode we reuse f */ + maybe_close_f(f); + f = NULL; + } + + pagecount++; + assign_file_suffix(filesuff, group, layer, flags, purpose, purpi, 0, NULL); + if (f == NULL) { /* open a new file if we closed the previous (cam mode: only one file) */ + f = pcb_fopen(gerber_cam.active ? gerber_cam.fn : filename, "wb"); /* Binary needed to force CR-LF */ + if (f == NULL) { + pcb_message(PCB_MSG_ERROR, "Error: Could not open %s for writing.\n", filename); + return 1; + } + } + + was_drill = is_drill; + + if (verbose) { + int c = aptr_list->count; + fprintf(stderr, "Gerber: %d aperture%s in %s\n", c, c == 1 ? "" : "s", filename); + } + + fprintf(f, "G04 start of page %d for group %ld layer_idx %ld *\r\n", pagecount, group, layer); + + /* Create a portable timestamp. */ + pcb_print_utc(utcTime, sizeof(utcTime), 0); + + /* Print a cute file header at the beginning of each file. */ + fprintf(f, "G04 Title: %s, %s *\r\n", PCB_UNKNOWN(PCB->Name), PCB_UNKNOWN(group_name)); + fprintf(f, "G04 Creator: pcb-rnd " PCB_VERSION " *\r\n"); + fprintf(f, "G04 CreationDate: %s *\r\n", utcTime); + + /* ID the user. */ + fprintf(f, "G04 For: %s *\r\n", pcb_author()); + + fprintf(f, "G04 Format: Gerber/RS-274X *\r\n"); + pcb_fprintf(f, "G04 PCB-Dimensions: %[4] %[4] *\r\n", PCB->MaxWidth, PCB->MaxHeight); + fprintf(f, "G04 PCB-Coordinate-Origin: lower left *\r\n"); + + /* Unit and coord format */ + fprintf(f, "%s", gerber_cfmt->hdr1); + + /* build a legal identifier. */ + if (layername) + free(layername); + layername = pcb_strdup(filesuff); + if (strrchr(layername, '.')) + *strrchr(layername, '.') = 0; + + for (cp = layername; *cp; cp++) { + if (isalnum((int) *cp)) + *cp = toupper((int) *cp); + else + *cp = '_'; + } + fprintf(f, "%%LN%s*%%\r\n", layername); + lncount = 1; + + for (search = aptr_list->data; search; search = search->next) + fprint_aperture(f, search); + if (aptr_list->count == 0) + /* We need to put *something* in the file to make it be parsed + as RS-274X instead of RS-274D. */ + fprintf(f, "%%ADD11C,0.0100*%%\r\n"); + } + +emit_outline: + /* If we're printing a copper layer other than the outline layer, + and we want to "print outlines", and we have an outline layer, + print the outline layer on this layer also. */ + want_outline = 0; + if (copy_outline_mode == COPY_OUTLINE_MASK && (flags & PCB_LYT_MASK)) + want_outline = 1; + if (copy_outline_mode == COPY_OUTLINE_SILK && (flags & PCB_LYT_SILK)) + want_outline = 1; + + if (copy_outline_mode == COPY_OUTLINE_ALL && ((flags & PCB_LYT_SILK) || (flags & PCB_LYT_MASK) || PCB_LAYER_IS_FAB(flags, purpi) || PCB_LAYER_IS_ASSY(flags, purpi))) + want_outline = 1; + + if (want_outline && !(PCB_LAYER_IS_ROUTE(flags, purpi))) { + if (has_outline) { + pcb_draw_groups(PCB, PCB_LYT_BOUNDARY, F_proute, NULL, ®ion, pcb_color_black, PCB_LYT_MECH, 0, 0); + pcb_draw_groups(PCB, PCB_LYT_BOUNDARY, F_uroute, NULL, ®ion, pcb_color_black, PCB_LYT_MECH, 0, 0); + } + else { + pcb_hid_gc_t gc = pcb_hid_make_gc(); + if (flags & PCB_LYT_SILK) + pcb_hid_set_line_width(gc, conf_core.design.min_slk); + else if (group >= 0) + pcb_hid_set_line_width(gc, conf_core.design.min_wid); + else + pcb_hid_set_line_width(gc, AUTO_OUTLINE_WIDTH); + pcb_gui->draw_line(gc, 0, 0, PCB->MaxWidth, 0); + pcb_gui->draw_line(gc, 0, 0, 0, PCB->MaxHeight); + pcb_gui->draw_line(gc, PCB->MaxWidth, 0, PCB->MaxWidth, PCB->MaxHeight); + pcb_gui->draw_line(gc, 0, PCB->MaxHeight, PCB->MaxWidth, PCB->MaxHeight); + pcb_hid_destroy_gc(gc); + } + } + return 1; +} + +static pcb_hid_gc_t gerber_make_gc(void) +{ + pcb_hid_gc_t rv = (pcb_hid_gc_t) calloc(1, sizeof(*rv)); + rv->cap = pcb_cap_round; + return rv; +} + +static void gerber_destroy_gc(pcb_hid_gc_t gc) +{ + free(gc); +} + +static void gerber_set_drawing_mode(pcb_composite_op_t op, pcb_bool direct, const pcb_box_t *drw_screen) +{ + gerber_drawing_mode = op; + if ((f != NULL) && (gerber_debug)) + fprintf(f, "G04 hid debug composite: %d*\r\n", op); +} + +static void gerber_set_color(pcb_hid_gc_t gc, const pcb_color_t *color) +{ + if (pcb_color_is_drill(color)) { + gc->color = 1; + gc->erase = 0; + gc->drill = 1; + } + else { + gc->color = 0; + gc->erase = 0; + gc->drill = 0; + } +} + +static void gerber_set_line_cap(pcb_hid_gc_t gc, pcb_cap_style_t style) +{ + gc->cap = style; +} + +static void gerber_set_line_width(pcb_hid_gc_t gc, pcb_coord_t width) +{ + gc->width = width; +} + +static void gerber_set_draw_xor(pcb_hid_gc_t gc, int xor_) +{ + ; +} + +static void use_gc(pcb_hid_gc_t gc, int radius) +{ + if ((f != NULL) && (gerber_drawing_mode != drawing_mode_issued)) { + if ((gerber_drawing_mode == PCB_HID_COMP_POSITIVE) || (gerber_drawing_mode == PCB_HID_COMP_POSITIVE_XOR)) { + fprintf(f, "%%LPD*%%\r\n"); + drawing_mode_issued = gerber_drawing_mode; + } + else if (gerber_drawing_mode == PCB_HID_COMP_NEGATIVE) { + fprintf(f, "%%LPC*%%\r\n"); + drawing_mode_issued = gerber_drawing_mode; + } + } + + if (radius) { + radius *= 2; + if (radius != linewidth || lastcap != pcb_cap_round) { + aperture_t *aptr = find_aperture(curr_aptr_list, radius, ROUND); + if (aptr == NULL) + pcb_fprintf(stderr, "error: aperture for radius %$mS type ROUND is null\n", radius); + else if (f != NULL) { + if (gerber_cam.active) { + fprintf(f, "G54D%d*", aptr->dCode); + } + else { + TODO("excellon split"); + /* remove this else part once excellon is removed: when exporting + drill in gerber, we shall always use the above code and generate + G54 */ + if (!is_drill) + fprintf(f, "G54D%d*", aptr->dCode); + } + } + linewidth = radius; + lastcap = pcb_cap_round; + } + } + else if (linewidth != gc->width || lastcap != gc->cap) { + aperture_t *aptr; + aperture_shape_t shape; + + linewidth = gc->width; + lastcap = gc->cap; + switch (gc->cap) { + case pcb_cap_round: + shape = ROUND; + break; + case pcb_cap_square: + shape = SQUARE; + break; + default: + assert(!"unhandled cap"); + shape = ROUND; + } + aptr = find_aperture(curr_aptr_list, linewidth, shape); + if (aptr == NULL) + pcb_fprintf(stderr, "error: aperture for width %$mS type %s is null\n", linewidth, shape == ROUND ? "ROUND" : "SQUARE"); + if (f && aptr) + fprintf(f, "G54D%d*", aptr->dCode); + } + +TODO("gerber: remove this dead code"); +#if 0 + if (lastcolor != gc->color) { + c = gc->color; + if (is_drill) + return; + if (is_mask) + c = (gc->erase ? 0 : 1); + lastcolor = gc->color; + if (f) { + if (c) { + fprintf(f, "%%LN%s_C%d*%%\r\n", layername, lncount++); + fprintf(f, "%%LPC*%%\r\n"); + } + else { + fprintf(f, "%%LN%s_D%d*%%\r\n", layername, lncount++); + fprintf(f, "%%LPD*%%\r\n"); + } + } + } +#endif +} + +static void gerber_draw_rect(pcb_hid_gc_t gc, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2) +{ + gerber_draw_line(gc, x1, y1, x1, y2); + gerber_draw_line(gc, x1, y1, x2, y1); + gerber_draw_line(gc, x1, y2, x2, y2); + gerber_draw_line(gc, x2, y1, x2, y2); +} + +static void gerber_draw_line(pcb_hid_gc_t gc, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2) +{ + pcb_bool m = pcb_false; + + if (line_slots) { + pcb_coord_t dia = gc->width/2; + find_aperture((is_plated ? &pdrills.apr : &udrills.apr), dia*2, ROUND); + find_aperture(curr_aptr_list, dia*2, ROUND); /* for a real gerber export of the BOUNDARY group: place aperture on the per layer aperture list */ + + if (!gerber_cam.active) { + TODO("excellon split"); + /* This is the old, excellon-in-gerber behavior - remove this once the split + is complete: excellon should do new_pending, not gerber */ + if (!finding_apertures) + pcb_drill_new_pending(is_plated ? &pdrills : &udrills, x1, y1, x2, y2, dia*2); + return; + } + else { + if (finding_apertures) + return; + } + } + + if (x1 != x2 && y1 != y2 && gc->cap == pcb_cap_square) { + pcb_coord_t x[5], y[5]; + double tx, ty, theta; + + theta = atan2(y2 - y1, x2 - x1); + + /* T is a vector half a thickness long, in the direction of + one of the corners. */ + tx = gc->width / 2.0 * cos(theta + M_PI / 4) * sqrt(2.0); + ty = gc->width / 2.0 * sin(theta + M_PI / 4) * sqrt(2.0); + + x[0] = x1 - tx; + y[0] = y1 - ty; + x[1] = x2 + ty; + y[1] = y2 - tx; + x[2] = x2 + tx; + y[2] = y2 + ty; + x[3] = x1 - ty; + y[3] = y1 + tx; + + x[4] = x[0]; + y[4] = y[0]; + gerber_fill_polygon(gc, 5, x, y); + return; + } + + use_gc(gc, 0); + if (!f) + return; + + if (x1 != lastX) { + m = pcb_true; + lastX = x1; + pcb_fprintf(f, "X%[4]", gerberX(PCB, lastX)); + } + if (y1 != lastY) { + m = pcb_true; + lastY = y1; + pcb_fprintf(f, "Y%[4]", gerberY(PCB, lastY)); + } + if ((x1 == x2) && (y1 == y2)) + fprintf(f, "D03*\r\n"); + else { + if (m) + fprintf(f, "D02*"); + if (x2 != lastX) { + lastX = x2; + pcb_fprintf(f, "X%[4]", gerberX(PCB, lastX)); + } + if (y2 != lastY) { + lastY = y2; + pcb_fprintf(f, "Y%[4]", gerberY(PCB, lastY)); + + } + fprintf(f, "D01*\r\n"); + } + +} + +static void gerber_draw_arc(pcb_hid_gc_t gc, pcb_coord_t cx, pcb_coord_t cy, pcb_coord_t width, pcb_coord_t height, pcb_angle_t start_angle, pcb_angle_t delta_angle) +{ + pcb_bool m = pcb_false; + double arcStartX, arcStopX, arcStartY, arcStopY; + + /* we never draw zero-width lines */ + if (gc->width == 0) + return; + + use_gc(gc, 0); + if (!f) + return; + + /* full circle is full.... truncate so that the arc split code never needs to + do more than 180 deg */ + if (delta_angle < -360.0) + delta_angle = -360.0; + if (delta_angle > +360.0) + delta_angle = +360.0; + + + /* some gerber interpreters (gerbv for one) have hard time dealing with + full-circle arcs - split large arcs up into 2 smaller ones */ + if (delta_angle < -180.0) { + gerber_draw_arc(gc, cx, cy, width, height, start_angle, -180.0); + gerber_draw_arc(gc, cx, cy, width, height, start_angle-180, delta_angle+180.0); + return; + } + if (delta_angle > +180.0) { + gerber_draw_arc(gc, cx, cy, width, height, start_angle, 180.0); + gerber_draw_arc(gc, cx, cy, width, height, start_angle+180, delta_angle-180.0); + return; + } + + + arcStartX = cx - width * cos(PCB_TO_RADIANS(start_angle)); + arcStartY = cy + height * sin(PCB_TO_RADIANS(start_angle)); + + if (fabs(delta_angle) < 0.01) { + gerber_draw_line(gc, arcStartX, arcStartY, arcStartX, arcStartY); + return; + } + + /* I checked three different gerber viewers, and they all disagreed + on how ellipses should be drawn. The spec just calls G74/G75 + "circular interpolation" so there's a chance it just doesn't + support ellipses at all. Thus, we draw them out with line + segments. Note that most arcs in pcb are circles anyway. */ + if (width != height) { + double step, angle; + pcb_coord_t max = width > height ? width : height; + pcb_coord_t minr = max - gc->width / 10; + int nsteps; + pcb_coord_t x0, y0, x1, y1; + + if (minr >= max) + minr = max - 1; + step = acos((double) minr / (double) max) * 180.0 / M_PI; + if (step > 5) + step = 5; + nsteps = fabs(delta_angle) / step + 1; + step = (double) delta_angle / nsteps; + + x0 = arcStartX; + y0 = arcStartY; + angle = start_angle; + while (nsteps > 0) { + nsteps--; + x1 = cx - width * cos(PCB_TO_RADIANS(angle + step)); + y1 = cy + height * sin(PCB_TO_RADIANS(angle + step)); + gerber_draw_line(gc, x0, y0, x1, y1); + x0 = x1; + y0 = y1; + angle += step; + } + return; + } + + arcStopX = cx - width * cos(PCB_TO_RADIANS(start_angle + delta_angle)); + arcStopY = cy + height * sin(PCB_TO_RADIANS(start_angle + delta_angle)); + if (arcStartX != lastX) { + m = pcb_true; + lastX = arcStartX; + pcb_fprintf(f, "X%[4]", gerberX(PCB, lastX)); + } + if (arcStartY != lastY) { + m = pcb_true; + lastY = arcStartY; + pcb_fprintf(f, "Y%[4]", gerberY(PCB, lastY)); + } + if (m) + fprintf(f, "D02*"); + pcb_fprintf(f, + "G75*G0%1dX%[4]Y%[4]I%[4]J%[4]D01*G01*\r\n", + (delta_angle < 0) ? 2 : 3, + gerberX(PCB, arcStopX), gerberY(PCB, arcStopY), + gerberXOffset(PCB, cx - arcStartX), gerberYOffset(PCB, cy - arcStartY)); + lastX = arcStopX; + lastY = arcStopY; +} + +static void gerber_fill_circle(pcb_hid_gc_t gc, pcb_coord_t cx, pcb_coord_t cy, pcb_coord_t radius) +{ + if (radius <= 0) + return; + if (is_drill) + radius = 50 * pcb_round(radius / 50.0); + use_gc(gc, radius); + if (!f) + return; + if (is_drill) { + if (!gerber_cam.active) { + TODO("excellon split"); + /* This is the old, excellon-in-gerber behavior - remove this once the split + is complete: excellon should do new_pending, not gerber */ + pcb_drill_new_pending(is_plated ? &pdrills : &udrills, cx, cy, cx, cy, radius * 2); + return; + } + else { + if (finding_apertures) + return; + } + } + else if (gc->drill && !flash_drills) + return; + if (cx != lastX) { + lastX = cx; + pcb_fprintf(f, "X%[4]", gerberX(PCB, lastX)); + } + if (cy != lastY) { + lastY = cy; + pcb_fprintf(f, "Y%[4]", gerberY(PCB, lastY)); + } + fprintf(f, "D03*\r\n"); +} + +static void gerber_fill_polygon_offs(pcb_hid_gc_t gc, int n_coords, pcb_coord_t *x, pcb_coord_t *y, pcb_coord_t dx, pcb_coord_t dy) +{ + pcb_bool m = pcb_false; + int i; + int firstTime = 1; + pcb_coord_t startX = 0, startY = 0; + + if (line_slots) { + pcb_message(PCB_MSG_ERROR, "Can't export polygon as G85 slot in excellon cnc files;\nplease use lines for slotting if you export gerber\n"); + return; + } + + if (is_mask && (gerber_drawing_mode != PCB_HID_COMP_POSITIVE) && (gerber_drawing_mode != PCB_HID_COMP_POSITIVE_XOR) && (gerber_drawing_mode != PCB_HID_COMP_NEGATIVE)) + return; + + use_gc(gc, 10 * 100); + if (!f) + return; + fprintf(f, "G36*\r\n"); + for (i = 0; i < n_coords; i++) { + if (x[i]+dx != lastX) { + m = pcb_true; + lastX = x[i]+dx; + pcb_fprintf(f, "X%[4]", gerberX(PCB, lastX)); + } + if (y[i]+dy != lastY) { + m = pcb_true; + lastY = y[i]+dy; + pcb_fprintf(f, "Y%[4]", gerberY(PCB, lastY)); + } + if (firstTime) { + firstTime = 0; + startX = x[i]+dx; + startY = y[i]+dy; + if (m) + fprintf(f, "D02*"); + } + else if (m) + fprintf(f, "D01*\r\n"); + m = pcb_false; + } + if (startX != lastX) { + m = pcb_true; + lastX = startX; + pcb_fprintf(f, "X%[4]", gerberX(PCB, startX)); + } + if (startY != lastY) { + m = pcb_true; + lastY = startY; + pcb_fprintf(f, "Y%[4]", gerberY(PCB, lastY)); + } + if (m) + fprintf(f, "D01*\r\n"); + fprintf(f, "G37*\r\n"); +} + +static void gerber_fill_polygon(pcb_hid_gc_t gc, int n_coords, pcb_coord_t *x, pcb_coord_t *y) +{ + gerber_fill_polygon_offs(gc, n_coords, x, y, 0, 0); +} + + +static void gerber_fill_rect(pcb_hid_gc_t gc, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2) +{ + pcb_coord_t x[5]; + pcb_coord_t y[5]; + x[0] = x[4] = x1; + y[0] = y[4] = y1; + x[1] = x1; + y[1] = y2; + x[2] = x2; + y[2] = y2; + x[3] = x2; + y[3] = y1; + gerber_fill_polygon(gc, 5, x, y); +} + +static void gerber_calibrate(double xval, double yval) +{ + CRASH("gerber_calibrate"); +} + +static int gerber_usage(const char *topic) +{ + fprintf(stderr, "\ngerber exporter command line arguments:\n\n"); + pcb_hid_usage(gerber_options, sizeof(gerber_options) / sizeof(gerber_options[0])); + fprintf(stderr, "\nUsage: pcb-rnd [generic_options] -x gerber [gerber options] foo.pcb\n\n"); + return 0; +} + +static void gerber_set_crosshair(pcb_coord_t x, pcb_coord_t y, int action) +{ +} + +int pplg_check_ver_export_gerber(int ver_needed) { return 0; } + +void pplg_uninit_export_gerber(void) +{ + pcb_hid_remove_attributes_by_cookie(gerber_cookie); + conf_unreg_fields("plugins/export_gerber/"); + pplg_uninit_export_excellon(); +} + +int pplg_init_export_gerber(void) +{ + PCB_API_CHK_VER; + +#define conf_reg(field,isarray,type_name,cpath,cname,desc,flags) \ + conf_reg_field(conf_gerber, field,isarray,type_name,cpath,cname,desc,flags); +#include "gerber_conf_fields.h" + + memset(&gerber_hid, 0, sizeof(gerber_hid)); + + pcb_hid_nogui_init(&gerber_hid); + pcb_dhlp_draw_helpers_init(&gerber_hid); + + gerber_hid.struct_size = sizeof(gerber_hid); + gerber_hid.name = "gerber"; + gerber_hid.description = "RS-274X (Gerber) export"; + gerber_hid.exporter = 1; + + gerber_hid.mask_invert = 1; + + gerber_hid.get_export_options = gerber_get_export_options; + gerber_hid.do_export = gerber_do_export; + gerber_hid.parse_arguments = gerber_parse_arguments; + gerber_hid.set_layer_group = gerber_set_layer_group; + gerber_hid.make_gc = gerber_make_gc; + gerber_hid.destroy_gc = gerber_destroy_gc; + gerber_hid.set_drawing_mode = gerber_set_drawing_mode; + gerber_hid.set_color = gerber_set_color; + gerber_hid.set_line_cap = gerber_set_line_cap; + gerber_hid.set_line_width = gerber_set_line_width; + gerber_hid.set_draw_xor = gerber_set_draw_xor; + gerber_hid.draw_line = gerber_draw_line; + gerber_hid.draw_arc = gerber_draw_arc; + gerber_hid.draw_rect = gerber_draw_rect; + gerber_hid.fill_circle = gerber_fill_circle; + gerber_hid.fill_polygon = gerber_fill_polygon; + gerber_hid.fill_polygon_offs = gerber_fill_polygon_offs; + gerber_hid.fill_rect = gerber_fill_rect; + gerber_hid.calibrate = gerber_calibrate; + gerber_hid.set_crosshair = gerber_set_crosshair; + gerber_hid.usage = gerber_usage; + + pcb_hid_register_hid(&gerber_hid); + return pplg_init_export_excellon(); +} + Index: tags/2.1.2/src_plugins/export_gerber/gerber_conf.h =================================================================== --- tags/2.1.2/src_plugins/export_gerber/gerber_conf.h (nonexistent) +++ tags/2.1.2/src_plugins/export_gerber/gerber_conf.h (revision 24813) @@ -0,0 +1,15 @@ +#ifndef PCB_GERBER_CONF_H +#define PCB_GERBER_CONF_H + +#include "conf.h" + +typedef struct { + const struct plugins { + const struct export_gerber { + CFT_BOOLEAN plated_g85_slot; /* use G85 (drill cycle instead of route) for plated slots */ + CFT_BOOLEAN unplated_g85_slot; /* use G85 (drill cycle instead of route) for unplated slots */ + } export_gerber; + } plugins; +} conf_gerber_t; + +#endif Index: tags/2.1.2/src_plugins/export_ipcd356/Makefile =================================================================== --- tags/2.1.2/src_plugins/export_ipcd356/Makefile (nonexistent) +++ tags/2.1.2/src_plugins/export_ipcd356/Makefile (revision 24813) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_export_ipcd356 + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/2.1.2/src_plugins/export_ipcd356/Plug.tmpasm =================================================================== --- tags/2.1.2/src_plugins/export_ipcd356/Plug.tmpasm (nonexistent) +++ tags/2.1.2/src_plugins/export_ipcd356/Plug.tmpasm (revision 24813) @@ -0,0 +1,8 @@ +put /local/pcb/mod {export_ipcd356} +put /local/pcb/mod/OBJS [@ $(PLUGDIR)/export_ipcd356/ipcd356.o @] + +switch /local/pcb/export_ipcd356/controls + case {buildin} include /local/pcb/tmpasm/buildin; end; + case {plugin} include /local/pcb/tmpasm/plugin; end; + case {disable} include /local/pcb/tmpasm/disable; end; +end Index: tags/2.1.2/src_plugins/export_ipcd356/export_ipcd356.pup =================================================================== --- tags/2.1.2/src_plugins/export_ipcd356/export_ipcd356.pup (nonexistent) +++ tags/2.1.2/src_plugins/export_ipcd356/export_ipcd356.pup (revision 24813) @@ -0,0 +1,10 @@ +$class export +$short IPC-D-356 Netlist pcb_exporter +$long IPC-D-356 Netlist export. +$state works +$fmt-native no +$fmt-feature-w export IPC-D-356 Netlist (for automated testing) +$package export-extra +dep lib_compat_help +default buildin +autoload 1 Index: tags/2.1.2/src_plugins/export_ipcd356/ipcd356.c =================================================================== --- tags/2.1.2/src_plugins/export_ipcd356/ipcd356.c (nonexistent) +++ tags/2.1.2/src_plugins/export_ipcd356/ipcd356.c (revision 24813) @@ -0,0 +1,491 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * + * ipc-d-356 export plugin + * pcb-rnd Copyright (C) 2018 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "config.h" + +#include + +#include "board.h" +#include "data.h" +#include "safe_fs.h" +#include "conf_core.h" +#include "compat_misc.h" +#include "netlist2.h" +#include "math_helper.h" +#include "layer.h" +#include "obj_arc.h" +#include "obj_line.h" +#include "obj_poly.h" +#include "obj_subc.h" +#include "obj_pstk.h" +#include "obj_pstk_inlines.h" + +#include "hid.h" +#include "hid_nogui.h" +#include "hid_cam.h" +#include "hid_attrib.h" +#include "hid_init.h" +#include "plugins.h" + +static const char *ipcd356_cookie = "ipcd356 exporter"; + +/*** low level export code ***/ +typedef struct { + pcb_board_t *pcb; + FILE *f; + int is_mil; +} write_ctx_t; + +typedef struct { + pcb_any_obj_t *o; + const char *netname, *refdes, *term; + int is_plated, access_top, access_bottom, rot, masked_top, masked_bottom; + pcb_coord_t hole, width, height, cx, cy; +} test_feature_t; + +static int getattr(pcb_any_obj_t *o, const char *key) +{ + char *val = pcb_attribute_get(&o->Attributes, key); + if (val == NULL) return 0; + if (pcb_strcasecmp(val, "yes") == 0) return 1; + return 0; +} + +static void fill_field(char *dst, int start, int end, const char *data, const char *name) +{ + int n; + const char *d = data; + + if (data == NULL) + d = ""; + + for(n = start; n <= end; n++) { + if (*d != '\0') + dst[n] = *d++; + else + dst[n] = ' '; + } + if (*d != '\0') + pcb_message(PCB_MSG_WARNING, "Data '%s' is too long for a(n) %s, truncated\n", data, name); +} + +static void fill_field_coord(write_ctx_t *ctx, char *dst, int start, int end, pcb_coord_t crd, int sign, const char *name) +{ + int len = end-start+1; + char tmp[32], fmt[16]; + if (sign) { + dst[start] = (crd >= 0) ? '+' : '-'; + start++; + len--; + } + if (ctx->is_mil) { + sprintf(fmt, "%%0%d.0ml", len); + crd *= 10; + } + else { + sprintf(fmt, "%%0%d.0mm", len); + crd *= 1000; + } + pcb_snprintf(tmp, sizeof(tmp), fmt, crd); + fill_field(dst, start, end, tmp, name); +} + +static void ipcd356_write_head(write_ctx_t *ctx) +{ + char utc[64]; + + pcb_print_utc(utc, sizeof(utc), 0); + + fprintf(ctx->f, "C IPC-D-356 Netlist generated by pcb-rnd " PCB_VERSION "\n"); + fprintf(ctx->f, "C \n"); + fprintf(ctx->f, "C File created on %s\n", utc); + fprintf(ctx->f, "C \n"); + fprintf(ctx->f, "P JOB %s\n", (PCB->Name == NULL) ? PCB->Filename : PCB->Name); + fprintf(ctx->f, "P CODE 00\n"); + fprintf(ctx->f, "P UNITS CUST %d\n", ctx->is_mil ? 0 : 1); + fprintf(ctx->f, "P DIM N\n"); + fprintf(ctx->f, "P VER IPC-D-356\n"); + fprintf(ctx->f, "P IMAGE PRIMARY\n"); + fprintf(ctx->f, "C \n"); +} + +static void ipcd356_write_foot(write_ctx_t *ctx) +{ + fprintf(ctx->f, "999\n\n"); +} + +static void ipcd356_write_feature(write_ctx_t *ctx, test_feature_t *t) +{ + char line[128]; + int is_tooling, is_mid; + + is_tooling = getattr(t->o, "ipcd356::tooling"); + is_mid = getattr(t->o, "ipcd356::mid"); + + line[0] = '3'; + if (is_tooling) + line[1] = '4'; + else if (t->hole > 0) + line[1] = '1'; + else + line[1] = '2'; + line[2] = '7'; + + fill_field(line, 3, 16, t->netname, "netname"); + fill_field(line, 17, 19, NULL, NULL); + fill_field(line, 20, 25, t->refdes, "refdes"); + line[26] = '-'; + fill_field(line, 27, 30, t->term, "term ID"); + line[31] = is_mid ? 'M' : ' '; + + if (t->hole > 0) { + line[32] = 'D'; + fill_field_coord(ctx, line, 33, 36, t->hole, 0, "hole"); + } + else + fill_field(line, 32, 36, NULL, NULL); + + if (t->hole > 0) + line[37] = t->is_plated ? 'P' : 'U'; + else + line[37] = ' '; + + if ((t->access_top) && (t->access_bottom)) + strcpy(line+38, "A00"); + else if (t->access_top) + strcpy(line+38, "A01"); + else if (t->access_bottom) + strcpy(line+38, "A02"); + else + return; /* do not export something that's not accessible from top or bottom */ + + line[41] = 'X'; + fill_field_coord(ctx, line, 42, 48, t->cx, 1, "X coord"); + line[49] = 'Y'; + fill_field_coord(ctx, line, 50, 56, PCB->MaxHeight - t->cy, 1, "Y coord"); + + line[57] = 'X'; + fill_field_coord(ctx, line, 58, 61, t->width, 0, "width"); + line[62] = 'Y'; + fill_field_coord(ctx, line, 63, 66, t->height, 0, "height"); + line[67] = 'R'; + fill_field_coord(ctx, line, 68, 70, t->rot, 0, "rotation"); + + line[71] = ' '; + if ((t->masked_top) && (t->masked_bottom)) + strcpy(line+72, "S3"); + else if (t->masked_top) + strcpy(line+72, "S1"); + else if (t->masked_bottom) + strcpy(line+72, "S2"); + else + strcpy(line+72, "S0"); + fill_field(line, 74, 79, NULL, NULL); + + line[80] = '\n'; + line[81] = '\0'; + fprintf(ctx->f, "%s", line); +} + +/* light terminals */ +static void ipcd356_pstk_shape(test_feature_t *t, pcb_pstk_shape_t *sh) +{ + int n; + pcb_coord_t x1, y1, x2, y2; + switch(sh->shape) { + case PCB_PSSH_HSHADOW: + break; + case PCB_PSSH_CIRC: + t->width = sh->data.circ.dia; + t->height = 0; + t->cx += sh->data.circ.x; + t->cy += sh->data.circ.y; + break; + case PCB_PSSH_LINE: + t->height = t->width = sh->data.line.thickness; + t->cx += (sh->data.line.x1 + sh->data.line.x2)/2; + t->cy += (sh->data.line.y1 + sh->data.line.y2)/2; + break; + case PCB_PSSH_POLY: + t->height = t->width = sh->data.line.thickness; + x1 = x2 = sh->data.poly.x[0]; + y1 = y2 = sh->data.poly.y[0]; + for(n = 1; n < sh->data.poly.len; n++) { + if (sh->data.poly.x[n] < x1) x1 = sh->data.poly.x[n]; + if (sh->data.poly.x[n] > x2) x2 = sh->data.poly.x[n]; + if (sh->data.poly.y[n] < y1) y1 = sh->data.poly.y[n]; + if (sh->data.poly.y[n] > y2) y2 = sh->data.poly.y[n]; + } + + t->cx += (x1 + x2)/2; + t->cy += (y1 + y2)/2; + if (pcb_pline_is_rectangle(sh->data.poly.pa->contours)) { + t->width = (x2 - x1); + t->height = (y2 - y1); + } + else { + t->width = (x2 - x1) / 4 + 1; + t->height = (y2 - y1) / 4 + 1; + } + break; + } +} + +static void ipcd356_write_pstk(write_ctx_t *ctx, pcb_subc_t *subc, pcb_pstk_t *pstk) +{ + test_feature_t t; + pcb_pstk_proto_t *proto; + pcb_pstk_shape_t *st, *sb; + pcb_pstk_tshape_t *tshp; + + if (pstk->term == NULL) + return; + + proto = pcb_pstk_get_proto(pstk); + if (proto == NULL) + return; + + { + pcb_net_term_t *term = pcb_net_find_by_obj(&ctx->pcb->netlist[PCB_NETLIST_EDITED], (pcb_any_obj_t *)pstk); + t.netname = (term == NULL) ? "N/C" : term->parent.net->name; + } + + t.o = (pcb_any_obj_t *)pstk; + t.refdes = subc->refdes; + t.term = pstk->term; + t.is_plated = proto->hplated; + t.access_top = ((st = pcb_pstk_shape(pstk, PCB_LYT_TOP | PCB_LYT_COPPER, 0)) != NULL); + t.access_bottom = ((sb = pcb_pstk_shape(pstk, PCB_LYT_BOTTOM | PCB_LYT_COPPER, 0)) != NULL); + /* this assumes the mask shape will expose all copper */ + t.masked_top = (pcb_pstk_shape(pstk, PCB_LYT_TOP | PCB_LYT_MASK, 0) == NULL); + t.masked_bottom = (pcb_pstk_shape(pstk, PCB_LYT_BOTTOM | PCB_LYT_MASK, 0) == NULL); + t.hole = proto->hdia; + t.cx = pstk->x; + t.cy = pstk->y; + + /* this assumes bottom shape is not smaller than top shape */ + if (st != NULL) ipcd356_pstk_shape(&t, st); + else if (sb != NULL) ipcd356_pstk_shape(&t, sb); + + tshp = pcb_pstk_get_tshape(pstk); + t.rot = tshp->rot; + + ipcd356_write_feature(ctx, &t); +} + +/* heavy terminals: lines, arcs, polygons */ +static int ipcd356_heavy(write_ctx_t *ctx, test_feature_t *t, pcb_subc_t *subc, pcb_layer_t *layer, pcb_any_obj_t *o) +{ + pcb_layer_type_t flg; + + if (o->term == NULL) + return -1; + flg = pcb_layer_flags_(layer); + if (!(flg & PCB_LYT_COPPER)) + return -1; + + memset(t, 0, sizeof(test_feature_t)); + + { + pcb_net_term_t *term = pcb_net_find_by_obj(&ctx->pcb->netlist[PCB_NETLIST_EDITED], (pcb_any_obj_t *)o); + t->netname = (term == NULL) ? "N/C" : term->parent.net->name; + } + + t->o = o; + t->refdes = subc->refdes; + t->term = o->term; + t->access_top = (flg & PCB_LYT_TOP); + t->access_bottom = (flg & PCB_LYT_BOTTOM); + return 0; +} + +static void ipcd356_write_line(write_ctx_t *ctx, pcb_subc_t *subc, pcb_layer_t *layer, pcb_line_t *line) +{ + test_feature_t t; + + if (ipcd356_heavy(ctx, &t, subc, layer, (pcb_any_obj_t *)line) != 0) + return; + + t.cx = (line->Point1.X + line->Point2.X) / 2; + t.cy = (line->Point1.Y + line->Point2.Y) / 2; + t.width = t.height = line->Thickness; + t.rot = atan2(line->Point2.Y - line->Point1.Y, line->Point2.X - line->Point1.X) * PCB_RAD_TO_DEG; + ipcd356_write_feature(ctx, &t); +} + +static void ipcd356_write_arc(write_ctx_t *ctx, pcb_subc_t *subc, pcb_layer_t *layer, pcb_arc_t *arc) +{ + test_feature_t t; + + if (ipcd356_heavy(ctx, &t, subc, layer, (pcb_any_obj_t *)arc) != 0) + return; + + pcb_arc_middle(arc, &t.cx, &t.cy); + t.width = t.height = arc->Thickness; + t.rot = arc->StartAngle + (arc->Delta / 2); + ipcd356_write_feature(ctx, &t); +} + +static void ipcd356_write_poly(write_ctx_t *ctx, pcb_subc_t *subc, pcb_layer_t *layer, pcb_poly_t *poly) +{ + test_feature_t t; + + if (ipcd356_heavy(ctx, &t, subc, layer, (pcb_any_obj_t *)poly) != 0) + return; + + t.cx = (poly->BoundingBox.X1 + poly->BoundingBox.X2) / 2; + t.cy = (poly->BoundingBox.Y1 + poly->BoundingBox.Y2) / 2; + t.width = (poly->BoundingBox.X2 - poly->BoundingBox.X1) / 8 + 1; + t.height = (poly->BoundingBox.Y2 - poly->BoundingBox.Y1) / 8 + 1; + t.rot = 0; + ipcd356_write_feature(ctx, &t); +} + +static void ipcd356_write(pcb_board_t *pcb, FILE *f) +{ + write_ctx_t ctx; + + ctx.pcb = pcb; + ctx.f = f; + ctx.is_mil = (strcmp(conf_core.editor.grid_unit->suffix, "mil") == 0); + + ipcd356_write_head(&ctx); + PCB_SUBC_LOOP(pcb->Data); { +TODO("subc: subc-in-subc") + PCB_PADSTACK_LOOP(subc->data); { + ipcd356_write_pstk(&ctx, subc, padstack); + } PCB_END_LOOP; + PCB_LINE_ALL_LOOP(subc->data); { + ipcd356_write_line(&ctx, subc, layer, line); + } PCB_ENDALL_LOOP; + PCB_ARC_ALL_LOOP(subc->data); { + ipcd356_write_arc(&ctx, subc, layer, arc); + } PCB_ENDALL_LOOP; + PCB_POLY_ALL_LOOP(subc->data); { + ipcd356_write_poly(&ctx, subc, layer, polygon); + } PCB_ENDALL_LOOP; + } PCB_END_LOOP; + ipcd356_write_foot(&ctx); +} + +/*** export hid administration and API/glu ***/ + +static pcb_hid_attribute_t ipcd356_options[] = { +/* %start-doc options "8 IPC-D-356 Netlist Export" +@ftable @code +@item --netlist-file +Name of the IPC-D-356 Netlist output file. +@end ftable +%end-doc +*/ + { + "netlistfile", + "Name of the IPC-D-356 Netlist output file", + PCB_HATT_STRING, + 0, 0, {0, 0, 0}, 0, 0}, +#define HA_ipcd356_filename 0 +}; + +#define NUM_OPTIONS (sizeof(ipcd356_options)/sizeof(ipcd356_options[0])) + +static pcb_hid_attr_val_t ipcd356_values[NUM_OPTIONS]; + +static pcb_hid_attribute_t *ipcd356_get_export_options(int *n) +{ + if ((PCB != NULL) && (ipcd356_options[HA_ipcd356_filename].default_val.str_value == NULL)) + pcb_derive_default_filename(PCB->Filename, &ipcd356_options[HA_ipcd356_filename], ".net"); + + if (n != NULL) + *n = NUM_OPTIONS; + + return ipcd356_options; +} + +static int ipcd356_parse_arguments(int *argc, char ***argv) +{ + return pcb_hid_parse_command_line(argc, argv); +} + +static void ipcd356_do_export(pcb_hid_attr_val_t *options) +{ + int n; + const char *fn; + FILE *f; + + if (!options) { + ipcd356_get_export_options(0); + + for (n = 0; n < NUM_OPTIONS; n++) + ipcd356_values[n] = ipcd356_options[n].default_val; + + options = ipcd356_values; + } + + fn = options[HA_ipcd356_filename].str_value; + if (fn == NULL) + fn = "pcb-rnd-out.net"; + + f = pcb_fopen(fn, "w"); + if (f == NULL) { + pcb_message(PCB_MSG_ERROR, "Can't open %s for write\n", fn); + return; + } + ipcd356_write(PCB, f); + fclose(f); +} + +static pcb_hid_t ipcd356_hid; + +int pplg_check_ver_export_ipcd356(int ver_needed) { return 0; } + +void pplg_uninit_export_ipcd356(void) +{ + pcb_hid_remove_attributes_by_cookie(ipcd356_cookie); +} + +int pplg_init_export_ipcd356(void) +{ + PCB_API_CHK_VER; + memset(&ipcd356_hid, 0, sizeof(pcb_hid_t)); + + pcb_hid_nogui_init(&ipcd356_hid); + + ipcd356_hid.struct_size = sizeof(pcb_hid_t); + ipcd356_hid.name = "IPC-D-356"; + ipcd356_hid.description = "Exports to IPC-D-356 netlist"; + ipcd356_hid.exporter = 1; + + ipcd356_hid.get_export_options = ipcd356_get_export_options; + ipcd356_hid.do_export = ipcd356_do_export; + ipcd356_hid.parse_arguments = ipcd356_parse_arguments; + + pcb_hid_register_hid(&ipcd356_hid); + + pcb_hid_register_attributes(ipcd356_options, sizeof(ipcd356_options) / sizeof(ipcd356_options[0]), ipcd356_cookie, 0); + return 0; +} Index: tags/2.1.2/src_plugins/export_lpr/Makefile =================================================================== --- tags/2.1.2/src_plugins/export_lpr/Makefile (nonexistent) +++ tags/2.1.2/src_plugins/export_lpr/Makefile (revision 24813) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_export_lpr + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/2.1.2/src_plugins/export_lpr/Plug.tmpasm =================================================================== --- tags/2.1.2/src_plugins/export_lpr/Plug.tmpasm (nonexistent) +++ tags/2.1.2/src_plugins/export_lpr/Plug.tmpasm (revision 24813) @@ -0,0 +1,8 @@ +put /local/pcb/mod {export_lpr} +put /local/pcb/mod/OBJS [@ $(PLUGDIR)/export_lpr/lpr.o @] + +switch /local/pcb/export_lpr/controls + case {buildin} include /local/pcb/tmpasm/buildin; end; + case {plugin} include /local/pcb/tmpasm/plugin; end; + case {disable} include /local/pcb/tmpasm/disable; end; +end Index: tags/2.1.2/src_plugins/export_lpr/export_lpr.pup =================================================================== --- tags/2.1.2/src_plugins/export_lpr/export_lpr.pup (nonexistent) +++ tags/2.1.2/src_plugins/export_lpr/export_lpr.pup (revision 24813) @@ -0,0 +1,10 @@ +$class export +$short lpr pcb_exporter (printer) +$long Export to lpr (using export_ps to generate postscript) +$state works +$fmt-native no +$fmt-feature-w use export_ps and lpr to print a board directly +$package export-extra +default buildin +dep export_ps +autoload 1 Index: tags/2.1.2/src_plugins/export_lpr/lpr.c =================================================================== --- tags/2.1.2/src_plugins/export_lpr/lpr.c (nonexistent) +++ tags/2.1.2/src_plugins/export_lpr/lpr.c (revision 24813) @@ -0,0 +1,148 @@ +#include "config.h" + +#include +#include +#include +#include +#include + +#include "data.h" +#include "plugins.h" +#include "compat_misc.h" +#include "safe_fs.h" + +#include "hid.h" +#include "../export_ps/ps.h" +#include "hid_nogui.h" +#include "hid_init.h" +#include "hid_attrib.h" +#include "actions.h" + +const char *lpr_cookie = "lpr HID"; + +static pcb_hid_attribute_t base_lpr_options[] = { + +/* %start-doc options "98 lpr Printing Options" +@ftable @code +@item --lprcommand +Command to use for printing. Defaults to @code{lpr}. This can be used to produce +PDF output with a virtual PDF printer. Example: @* +@code{--lprcommand "lp -d CUPS-PDF-Printer"}. +@end ftable +@noindent In addition, all @ref{Postscript Export} options are valid. +%end-doc +*/ + {"lprcommand", "Command to use for printing", + PCB_HATT_STRING, 0, 0, {0, 0, 0}, 0, 0}, +#define HA_lprcommand 0 +}; + +#define NUM_OPTIONS (sizeof(lpr_options)/sizeof(lpr_options[0])) + +static pcb_hid_attribute_t *lpr_options = 0; +static int num_lpr_options = 0; +static pcb_hid_attr_val_t *lpr_values; + +static pcb_hid_attribute_t *lpr_get_export_options(int *n) +{ + /* + * We initialize the default value in this manner because the GUI + * HID's may want to free() this string value and replace it with a + * new one based on how a user fills out a print dialog. + */ + if (base_lpr_options[HA_lprcommand].default_val.str_value == NULL) { + base_lpr_options[HA_lprcommand].default_val.str_value = pcb_strdup("lpr"); + } + + if (lpr_options == 0) { + pcb_hid_attribute_t *ps_opts = ps_hid.get_export_options(&num_lpr_options); + lpr_options = (pcb_hid_attribute_t *) calloc(num_lpr_options, sizeof(pcb_hid_attribute_t)); + memcpy(lpr_options, ps_opts, num_lpr_options * sizeof(pcb_hid_attribute_t)); + memcpy(lpr_options, base_lpr_options, sizeof(base_lpr_options)); + lpr_values = (pcb_hid_attr_val_t *) calloc(num_lpr_options, sizeof(pcb_hid_attr_val_t)); + } + if (n) + *n = num_lpr_options; + return lpr_options; +} + +static void lpr_do_export(pcb_hid_attr_val_t * options) +{ + FILE *f; + int i; + const char *filename; + + if (!options) { + lpr_get_export_options(0); + for (i = 0; i < num_lpr_options; i++) + lpr_values[i] = lpr_options[i].default_val; + options = lpr_values; + } + + filename = options[HA_lprcommand].str_value; + + printf("LPR: open %s\n", filename); + f = pcb_popen(filename, "w"); + if (!f) { + perror(filename); + return; + } + + ps_hid_export_to_file(f, options); + + pcb_pclose(f); +} + +static int lpr_parse_arguments(int *argc, char ***argv) +{ + lpr_get_export_options(0); + pcb_hid_register_attributes(lpr_options, num_lpr_options, lpr_cookie, 0); + return pcb_hid_parse_command_line(argc, argv); +} + +static void lpr_calibrate(double xval, double yval) +{ + ps_calibrate_1(xval, yval, 1); +} + +static pcb_hid_t lpr_hid; + +static int lpr_usage(const char *topic) +{ + fprintf(stderr, "\nlpr exporter command line arguments:\n\n"); + pcb_hid_usage(base_lpr_options, sizeof(base_lpr_options) / sizeof(base_lpr_options[0])); + fprintf(stderr, "\nUsage: pcb-rnd [generic_options] -x lpr [lpr options] foo.pcb\n\n"); + return 0; +} + +int pplg_check_ver_export_lpr(int ver_needed) { return 0; } + +void pplg_uninit_export_lpr(void) +{ + pcb_remove_actions_by_cookie(lpr_cookie); +} + +int pplg_init_export_lpr(void) +{ + PCB_API_CHK_VER; + memset(&lpr_hid, 0, sizeof(pcb_hid_t)); + + pcb_hid_nogui_init(&lpr_hid); + ps_ps_init(&lpr_hid); + + lpr_hid.struct_size = sizeof(pcb_hid_t); + lpr_hid.name = "lpr"; + lpr_hid.description = "Postscript print"; + lpr_hid.printer = 1; + + lpr_hid.get_export_options = lpr_get_export_options; + lpr_hid.do_export = lpr_do_export; + lpr_hid.parse_arguments = lpr_parse_arguments; + lpr_hid.calibrate = lpr_calibrate; + + lpr_hid.usage = lpr_usage; + + pcb_hid_register_hid(&lpr_hid); + + return 0; +} Index: tags/2.1.2/src_plugins/export_oldconn/Makefile =================================================================== --- tags/2.1.2/src_plugins/export_oldconn/Makefile (nonexistent) +++ tags/2.1.2/src_plugins/export_oldconn/Makefile (revision 24813) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_export_oldconn + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/2.1.2/src_plugins/export_oldconn/Plug.tmpasm =================================================================== --- tags/2.1.2/src_plugins/export_oldconn/Plug.tmpasm (nonexistent) +++ tags/2.1.2/src_plugins/export_oldconn/Plug.tmpasm (revision 24813) @@ -0,0 +1,8 @@ +put /local/pcb/mod {export_oldconn} +put /local/pcb/mod/OBJS [@ $(PLUGDIR)/export_oldconn/oldconn.o @] + +switch /local/pcb/export_oldconn/controls + case {buildin} include /local/pcb/tmpasm/buildin; end; + case {plugin} include /local/pcb/tmpasm/plugin; end; + case {disable} include /local/pcb/tmpasm/disable; end; +end Index: tags/2.1.2/src_plugins/export_oldconn/export_oldconn.pup =================================================================== --- tags/2.1.2/src_plugins/export_oldconn/export_oldconn.pup (nonexistent) +++ tags/2.1.2/src_plugins/export_oldconn/export_oldconn.pup (revision 24813) @@ -0,0 +1,9 @@ +$class export +$short old connection data format +$long Export subc/terminal connection map in an old, custom file format +$state works +$fmt-native no +$fmt-feature-w export a list of terminal connections in an old, custom file format +$package export-extra +default buildin +autoload 1 Index: tags/2.1.2/src_plugins/export_oldconn/oldconn.c =================================================================== --- tags/2.1.2/src_plugins/export_oldconn/oldconn.c (nonexistent) +++ tags/2.1.2/src_plugins/export_oldconn/oldconn.c (revision 24813) @@ -0,0 +1,329 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2018 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "config.h" +#include "conf_core.h" + +#include +#include + +#include "actions.h" +#include "board.h" +#include "compat_fs.h" +#include "data.h" +#include "data_it.h" +#include "draw.h" +#include "plugins.h" +#include "plug_io.h" +#include "safe_fs.h" +#include "find.h" +#include "macro.h" +#include "obj_subc_parent.h" +#include "undo.h" +#include "funchash_core.h" +#include "search.h" + +#include "hid_init.h" +#include "hid_attrib.h" + +const char *oldconn_cookie = "export_oldconn HID"; + +#define SEPARATE(fp) \ + do { \ + int __i__; \ + FILE *__f__ = (fp); \ + fputc('#', __f__); \ + for (__i__ = conf_core.appearance.messages.char_per_line; __i__ > 0; __i__--) \ + fputc('=', __f__); \ + fputc('\n', __f__); \ + } while(0) + +/* writes the several names of a subcircuit to a file */ +static void print_subc_name(FILE *f, pcb_subc_t *subc) +{ + fputc('(', f); + pcb_print_quoted_string(f, (char *)PCB_EMPTY(pcb_attribute_get(&subc->Attributes, "footprint"))); + fputc(' ', f); + pcb_print_quoted_string(f, (char *)PCB_EMPTY(subc->refdes)); + fputc(' ', f); + pcb_print_quoted_string(f, (char *)PCB_EMPTY(pcb_attribute_get(&subc->Attributes, "value"))); + fputs(")\n", f); +} + +static void pcb_print_conn_subc_name(FILE *f, pcb_subc_t *subc) +{ + fputs("Element", f); + print_subc_name(f, subc); + fputs("{\n", f); +} + +static int count_term_cb(pcb_find_t *fctx, pcb_any_obj_t *o, pcb_any_obj_t *arrived_from, pcb_found_conn_type_t ctype) +{ + unsigned long *cnt = fctx->user_data; + + if (o->term == NULL) + return 0; + + (*cnt)++; + if ((*cnt) > 1) + return 1; /* stop searching after the second object - no need to know how many terminals are connected, the fact that it's more than 1 is enough */ + return 0; +} + +/* prints all unused pins of a subcircuit to f */ +static void print_select_unused_subc_terms(FILE *f, pcb_subc_t *subc, int do_select) +{ + unsigned long cnt; + pcb_find_t fctx; + pcb_any_obj_t *o; + pcb_data_it_t it; + int subc_announced = 0; + + memset(&fctx, 0, sizeof(fctx)); + fctx.user_data = &cnt; + fctx.found_cb = count_term_cb; + + for(o = pcb_data_first(&it, subc->data, PCB_OBJ_CLASS_REAL); o != NULL; o = pcb_data_next(&it)) { + if (o->term == NULL) /* consider named terminals only */ + continue; + + cnt = 0; + pcb_find_from_obj(&fctx, PCB->Data, o); + pcb_find_free(&fctx); + + if (cnt <= 1) { + if (!subc_announced) { + pcb_print_conn_subc_name(f, subc); + subc_announced = 1; + } + + fputc('\t', f); + pcb_print_quoted_string(f, (char *)PCB_EMPTY(o->term)); + fputc('\n', f); + if (do_select) { + PCB_FLAG_SET(PCB_FLAG_SELECTED, o); + pcb_draw_obj(o); + } + } + } + + /* print separator if element has unused pins or pads */ + if (subc_announced) { + fputs("}\n\n", f); + SEPARATE(f); + } +} + +typedef struct { + FILE *f; + pcb_any_obj_t *start; +} term_cb_t; + +static int print_term_conn_cb(pcb_find_t *fctx, pcb_any_obj_t *o, pcb_any_obj_t *arrived_from, pcb_found_conn_type_t ctype) +{ + term_cb_t *ctx = fctx->user_data; + pcb_subc_t *sc; + + if (ctx->start == o) + return 0; + + sc = pcb_obj_parent_subc(o); + if (sc == NULL) + return 0; + + fputs("\t\t", ctx->f); + pcb_print_quoted_string(ctx->f, PCB_EMPTY(o->term)); + fputs(" ", ctx->f); + print_subc_name(ctx->f, sc); + return 0; +} + + +/* Find connected terminals to each terminal of subc and write them to f. */ +static void pcb_print_subc_conns(FILE *f, pcb_subc_t *subc) +{ + pcb_any_obj_t *o; + pcb_data_it_t it; + pcb_find_t fctx; + term_cb_t cbctx; + + pcb_print_conn_subc_name(f, subc); + + cbctx.f = f; + memset(&fctx, 0, sizeof(fctx)); + + for(o = pcb_data_first(&it, subc->data, PCB_OBJ_CLASS_REAL); o != NULL; o = pcb_data_next(&it)) { + if (o->term == NULL) /* consider named terminals only */ + continue; + + fputs("\t", f); + pcb_print_quoted_string(f, PCB_EMPTY(o->term)); + fputs("\n\t{\n", f); + + cbctx.start = o; + fctx.user_data = &cbctx; + fctx.found_cb = print_term_conn_cb; + pcb_find_from_obj(&fctx, PCB->Data, o); + pcb_find_free(&fctx); + + fputs("\t}\n", f); + } + fputs("}\n\n", f); +} + +/* Find and print (to f) all unused pins of all subcircuits */ +static void pcb_lookup_unused_pins(FILE *f, int do_select) +{ + PCB_SUBC_LOOP(PCB->Data); + { + print_select_unused_subc_terms(f, subc, do_select); + } + PCB_END_LOOP; + + if (conf_core.editor.beep_when_finished) + pcb_gui->beep(); + + if (do_select) { + pcb_undo_inc_serial(); + pcb_draw(); + } +} + +/* Find and print (to f) all connections from terminals of subc */ +static void pcb_lookup_subc_conns(FILE *f, pcb_subc_t *subc) +{ + pcb_print_subc_conns(f, subc); + if (conf_core.editor.beep_when_finished) + pcb_gui->beep(); +} + +/* Find all connections from all terminals of all subcircuits and print in f. */ +static void pcb_lookup_conns_to_all_subcs(FILE *f) +{ + PCB_SUBC_LOOP(PCB->Data); + { + pcb_print_subc_conns(f, subc); + SEPARATE(f); + } + PCB_END_LOOP; + + if (conf_core.editor.beep_when_finished) + pcb_gui->beep(); + pcb_redraw(); +} + +static FILE *pcb_check_and_open_file(const char *Filename) +{ + FILE *fp = NULL; + + if ((Filename != NULL) && (*Filename != '\0')) { + char message[PCB_PATH_MAX + 80]; + int response; + + if (pcb_file_readable(Filename)) { + sprintf(message, "File '%s' exists, use anyway?", Filename); + response = pcb_hid_message_box("warning", "Overwrite file", message, "cancel", 0, "ok", 1, NULL); + if (response != 1) + return NULL; + } + if ((fp = pcb_fopen(Filename, "w")) == NULL) + pcb_open_error_message(Filename); + } + return fp; +} + +static const char pcb_acts_ExportOldConn[] = "ExportOldConn(AllConnections|AllUnusedPins|ElementConnections,filename)\n"; +static const char pcb_acth_ExportOldConn[] = "Export galvanic connection data in an old, custom file format."; +/* DOC: exportoldconn.html */ +fgw_error_t pcb_act_ExportOldConn(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + int op; + const char *name = NULL; + FILE *f; + void *ptrtmp; + pcb_coord_t x, y; + + PCB_ACT_CONVARG(1, FGW_KEYWORD, ExportOldConn, op = fgw_keyword(&argv[1])); + PCB_ACT_MAY_CONVARG(2, FGW_STR, ExportOldConn, name = argv[2].val.str); + PCB_ACT_IRES(0); + + switch(op) { + case F_AllConnections: + f = pcb_check_and_open_file(name); + if (f != NULL) { + pcb_lookup_conns_to_all_subcs(f); + fclose(f); + } + return 0; + + case F_AllUnusedPins: + f = pcb_check_and_open_file(name); + if (f != NULL) { + pcb_lookup_unused_pins(f, 1); + fclose(f); + pcb_board_set_changed_flag(pcb_true); + } + return 0; + + case F_ElementConnections: + case F_SubcConnections: + pcb_hid_get_coords("Click on a subc", &x, &y, 0); + if (pcb_search_screen(x, y, PCB_OBJ_SUBC, &ptrtmp, &ptrtmp, &ptrtmp) != PCB_OBJ_VOID) { + pcb_subc_t *subc = (pcb_subc_t *) ptrtmp; + f = pcb_check_and_open_file(name); + if (f != NULL) { + pcb_lookup_subc_conns(f, subc); + fclose(f); + } + } + return 0; + } + PCB_ACT_FAIL(ExportOldConn); +} + +static pcb_action_t oldconn_action_list[] = { + {"ExportOldConn", pcb_act_ExportOldConn, pcb_acth_ExportOldConn, pcb_acts_ExportOldConn} +}; + +PCB_REGISTER_ACTIONS(oldconn_action_list, oldconn_cookie) + +int pplg_check_ver_export_oldconn(int ver_needed) { return 0; } + +void pplg_uninit_export_oldconn(void) +{ + pcb_remove_actions_by_cookie(oldconn_cookie); +} + +#include "dolists.h" + +int pplg_init_export_oldconn(void) +{ + PCB_API_CHK_VER; + + PCB_REGISTER_ACTIONS(oldconn_action_list, oldconn_cookie) + + return 0; +} Index: tags/2.1.2/src_plugins/export_openems/Makefile =================================================================== --- tags/2.1.2/src_plugins/export_openems/Makefile (nonexistent) +++ tags/2.1.2/src_plugins/export_openems/Makefile (revision 24813) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_export_openems + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/2.1.2/src_plugins/export_openems/Plug.tmpasm =================================================================== --- tags/2.1.2/src_plugins/export_openems/Plug.tmpasm (nonexistent) +++ tags/2.1.2/src_plugins/export_openems/Plug.tmpasm (revision 24813) @@ -0,0 +1,11 @@ +put /local/pcb/mod {export_openems} +put /local/pcb/mod/OBJS [@ + $(PLUGDIR)/export_openems/export_openems.o + $(PLUGDIR)/export_openems/mesh.o +@] + +switch /local/pcb/export_openems/controls + case {buildin} include /local/pcb/tmpasm/buildin; end; + case {plugin} include /local/pcb/tmpasm/plugin; end; + case {disable} include /local/pcb/tmpasm/disable; end; +end Index: tags/2.1.2/src_plugins/export_openems/excitation.c =================================================================== --- tags/2.1.2/src_plugins/export_openems/excitation.c (nonexistent) +++ tags/2.1.2/src_plugins/export_openems/excitation.c (revision 24813) @@ -0,0 +1,528 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2019 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "config.h" + +#include "hid_dad.h" +#include "event.h" + +#define MAX_EXC 16 +#define FREQ_MAX ((double)(100.0*1000.0*1000.0*1000.0)) +#define AEPREFIX "openems::excitation::" + +typedef struct { + int w[8]; +} exc_data_t; + +typedef struct { + PCB_DAD_DECL_NOINIT(dlg) + int active; /* already open - allow only one instance */ + int wselector, wtab; + int selected; + exc_data_t exc_data[MAX_EXC]; +} exc_ctx_t; + +exc_ctx_t exc_ctx; + +typedef struct { + const char *name; + void (*dad)(int idx); + char *(*get)(int idx); + void (*ser)(int idx, int save); /* serialization: if save is 1, set attributes, else load attributes */ +} exc_t; + + +static void ser_save(const char *data, const char *attrkey) +{ + const char *orig = pcb_attribute_get(&PCB->Attributes, attrkey); + if ((orig == NULL) || (strcmp(orig, data) != 0)) { + pcb_attribute_put(&PCB->Attributes, attrkey, data); + pcb_board_set_changed_flag(pcb_true); + } +} + +static const char *ser_load(const char *attrkey) +{ + return pcb_attribute_get(&PCB->Attributes, attrkey); +} + +#if 0 +/* unused at the moment */ +static void ser_int(int save, int widx, const char *attrkey) +{ + if (save) { + char tmp[128]; + sprintf(tmp, "%d", exc_ctx.dlg[widx].default_val.int_value); + ser_save(tmp, attrkey); + } + else { + pcb_hid_attr_val_t hv; + char *end; + const char *orig = ser_load(attrkey); + + if (orig != NULL) { + hv.int_value = strtol(orig, &end, 10); + if (*end != '\0') { + pcb_message(PCB_MSG_ERROR, "Invalid integer value in board attribute '%s': '%s'\n", attrkey, orig); + hv.int_value = 0; + } + } + else + hv.int_value = 0; + + pcb_gui->attr_dlg_set_value(exc_ctx.dlg_hid_ctx, widx, &hv); + } +} +#endif + +static void ser_hz(int save, int widx, const char *attrkey) +{ + if (save) { + char tmp[128]; + sprintf(tmp, "%f Hz", exc_ctx.dlg[widx].default_val.real_value); + ser_save(tmp, attrkey); + } + else { + pcb_hid_attr_val_t hv; + char *end; + const char *orig = ser_load(attrkey); + + if (orig != NULL) { + hv.real_value = strtod(orig, &end); + if (*end != '\0') { + while(isspace(*end)) end++; + if (pcb_strcasecmp(end, "hz") != 0) { + pcb_message(PCB_MSG_ERROR, "Invalid real value (Hz) in board attribute '%s': '%s'\n", attrkey, orig); + hv.real_value = 0; + } + } + } + else + hv.real_value = 0; + + pcb_gui->attr_dlg_set_value(exc_ctx.dlg_hid_ctx, widx, &hv); + } +} + +static void ser_str(int save, int widx, const char *attrkey) +{ + if (save) { + ser_save(exc_ctx.dlg[widx].default_val.str_value, attrkey); + } + else { + pcb_hid_attr_val_t hv; + hv.str_value = ser_load(attrkey); + if (hv.str_value == NULL) + hv.str_value = ""; + pcb_gui->attr_dlg_set_value(exc_ctx.dlg_hid_ctx, widx, &hv); + } +} + +static void exc_val_chg_cb(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr); + +/*** excitation "micro-plugins" ***/ + +#define I_FC 0 +#define I_F0 1 + +/** gaussian **/ +static void exc_gaus_dad(int idx) +{ + PCB_DAD_BEGIN_TABLE(exc_ctx.dlg, 2); + PCB_DAD_LABEL(exc_ctx.dlg, "fc"); + PCB_DAD_REAL(exc_ctx.dlg, ""); + PCB_DAD_MINMAX(exc_ctx.dlg, 0, FREQ_MAX); + PCB_DAD_HELP(exc_ctx.dlg, "20db Cutoff Frequency [Hz]\nbandwidth is 2*fc"); + PCB_DAD_CHANGE_CB(exc_ctx.dlg, exc_val_chg_cb); + exc_ctx.exc_data[idx].w[I_FC] = PCB_DAD_CURRENT(exc_ctx.dlg); + + PCB_DAD_LABEL(exc_ctx.dlg, "f0"); + PCB_DAD_REAL(exc_ctx.dlg, ""); + PCB_DAD_MINMAX(exc_ctx.dlg, 0, FREQ_MAX); + PCB_DAD_HELP(exc_ctx.dlg, "Center Frequency [Hz]"); + PCB_DAD_CHANGE_CB(exc_ctx.dlg, exc_val_chg_cb); + exc_ctx.exc_data[idx].w[I_F0] = PCB_DAD_CURRENT(exc_ctx.dlg); + + PCB_DAD_END(exc_ctx.dlg); +} + +static char *exc_gaus_get(int idx) +{ + return pcb_strdup_printf( + "FDTD = SetGaussExcite(FDTD, %s, %s);", + pcb_attribute_get(&PCB->Attributes, AEPREFIX "gaussian::f0"), + pcb_attribute_get(&PCB->Attributes, AEPREFIX "gaussian::fc") + ); +} + +static void exc_gaus_ser(int idx, int save) +{ + ser_hz(save, exc_ctx.exc_data[idx].w[I_F0], AEPREFIX "gaussian::f0"); + ser_hz(save, exc_ctx.exc_data[idx].w[I_FC], AEPREFIX "gaussian::fc"); +} + +#undef I_FC +#undef I_F0 + +/** sinusoidal **/ + +#define I_F0 0 + +static void exc_sin_dad(int idx) +{ + PCB_DAD_BEGIN_TABLE(exc_ctx.dlg, 2); + PCB_DAD_LABEL(exc_ctx.dlg, "f0"); + PCB_DAD_REAL(exc_ctx.dlg, ""); + PCB_DAD_MINMAX(exc_ctx.dlg, 0, FREQ_MAX); + PCB_DAD_HELP(exc_ctx.dlg, "Center Frequency [Hz]"); + PCB_DAD_CHANGE_CB(exc_ctx.dlg, exc_val_chg_cb); + exc_ctx.exc_data[idx].w[I_F0] = PCB_DAD_CURRENT(exc_ctx.dlg); + PCB_DAD_END(exc_ctx.dlg); +} + +static char *exc_sin_get(int idx) +{ + return pcb_strdup_printf( + "FDTD = SetSinusExcite(FDTD, %s);", + pcb_attribute_get(&PCB->Attributes, AEPREFIX "sinusoidal::f0") + ); +} + +static void exc_sin_ser(int idx, int save) +{ + ser_hz(save, exc_ctx.exc_data[idx].w[I_F0], AEPREFIX "sinusoidal::f0"); +} + +#undef I_F0 + +/** custom **/ + +#define I_F0 0 +#define I_FUNC 1 + +static void exc_cust_dad(int idx) +{ + PCB_DAD_BEGIN_TABLE(exc_ctx.dlg, 2); + PCB_DAD_LABEL(exc_ctx.dlg, "f0"); + PCB_DAD_REAL(exc_ctx.dlg, ""); + PCB_DAD_MINMAX(exc_ctx.dlg, 0, FREQ_MAX); + PCB_DAD_HELP(exc_ctx.dlg, "Nyquest Rate [Hz]"); + PCB_DAD_CHANGE_CB(exc_ctx.dlg, exc_val_chg_cb); + exc_ctx.exc_data[idx].w[I_F0] = PCB_DAD_CURRENT(exc_ctx.dlg); + + PCB_DAD_LABEL(exc_ctx.dlg, "function"); + PCB_DAD_STRING(exc_ctx.dlg); + PCB_DAD_HELP(exc_ctx.dlg, "Custom function"); + PCB_DAD_CHANGE_CB(exc_ctx.dlg, exc_val_chg_cb); + exc_ctx.exc_data[idx].w[I_FUNC] = PCB_DAD_CURRENT(exc_ctx.dlg); + PCB_DAD_END(exc_ctx.dlg); +} + +static char *exc_cust_get(int idx) +{ + return pcb_strdup_printf( + "FDTD = SetCustomExcite(FDTD, %s, %s)", + pcb_attribute_get(&PCB->Attributes, AEPREFIX "custom::f0"), + pcb_attribute_get(&PCB->Attributes, AEPREFIX "custom::func") + ); +} + +static void exc_cust_ser(int idx, int save) +{ + ser_hz(save, exc_ctx.exc_data[idx].w[I_F0], AEPREFIX "custom::f0"); + ser_str(save, exc_ctx.exc_data[idx].w[I_FUNC], AEPREFIX "custom::func"); +} + +#undef I_F0 +#undef I_FUNC + + +/** user-specified **/ + +#define I_SCRIPT 0 + +static void exc_user_dad(int idx) +{ + PCB_DAD_BEGIN_VBOX(exc_ctx.dlg); + PCB_DAD_COMPFLAG(exc_ctx.dlg, PCB_HATF_EXPFILL); + PCB_DAD_LABEL(exc_ctx.dlg, "Specify the excitation setup script:"); + PCB_DAD_TEXT(exc_ctx.dlg, NULL); + PCB_DAD_COMPFLAG(exc_ctx.dlg, PCB_HATF_EXPFILL | PCB_HATF_SCROLL); + PCB_DAD_CHANGE_CB(exc_ctx.dlg, exc_val_chg_cb); + exc_ctx.exc_data[idx].w[I_SCRIPT] = PCB_DAD_CURRENT(exc_ctx.dlg); + PCB_DAD_END(exc_ctx.dlg); +} + +static char *exc_user_get(int idx) +{ + return pcb_strdup(pcb_attribute_get(&PCB->Attributes, AEPREFIX "user-defined::script")); +} + +static void exc_user_ser(int idx, int save) +{ + int wscript; + pcb_hid_attribute_t *attr; + pcb_hid_text_t *txt; + + wscript = exc_ctx.exc_data[idx].w[I_SCRIPT]; + attr = &exc_ctx.dlg[wscript]; + txt = (pcb_hid_text_t *)attr->enumerations; + + ser_save(txt->hid_get_text(attr, exc_ctx.dlg_hid_ctx), AEPREFIX "user-defined::script"); +} + +#undef I_SCRIPT +/*** generic code ***/ + +static const exc_t excitations[] = { + { "gaussian", exc_gaus_dad, exc_gaus_get, exc_gaus_ser }, + { "sinusoidal", exc_sin_dad, exc_sin_get, exc_sin_ser }, + { "custom", exc_cust_dad, exc_cust_get, exc_cust_ser }, + { "user-defined", exc_user_dad, exc_user_get, exc_user_ser }, + { NULL, NULL} +}; + +static void exc_close_cb(void *caller_data, pcb_hid_attr_ev_t ev) +{ + exc_ctx_t *ctx = caller_data; + PCB_DAD_FREE(ctx->dlg); + memset(ctx, 0, sizeof(exc_ctx_t)); /* reset all states to the initial - includes ctx->active = 0; */ +} + +static void exc_load_all(void) +{ + const exc_t *e; + int n; + for(n = 0, e = excitations; e->name != NULL; n++,e++) + e->ser(n, 0); +} + +static int load_selector(void) +{ + const char *type = pcb_attribute_get(&PCB->Attributes, AEPREFIX "type"); + const exc_t *e; + int n; + + if (type == NULL) { + exc_ctx.selected = 0; + return 0; + } + + for(n = 0, e = excitations; e->name != NULL; n++,e++) { + if (strcmp(e->name, type) == 0) { + exc_ctx.selected = n; + return 0; + } + } + + return -1; +} + +static void select_update(int setattr) +{ + pcb_hid_attr_val_t hv; + hv.int_value = exc_ctx.selected; + + if ((exc_ctx.selected < 0) || (exc_ctx.selected >= sizeof(excitations)/sizeof(excitations[0]))) { + pcb_message(PCB_MSG_ERROR, "Invalid excitation selected\n"); + exc_ctx.selected = 0; + } + + pcb_gui->attr_dlg_set_value(exc_ctx.dlg_hid_ctx, exc_ctx.wtab, &hv); + pcb_gui->attr_dlg_set_value(exc_ctx.dlg_hid_ctx, exc_ctx.wselector, &hv); + if (setattr) { + const char *orig = pcb_attribute_get(&PCB->Attributes, "openems::excitation::type"); + if ((orig == NULL) || (strcmp(orig, excitations[exc_ctx.selected].name) != 0)) { + pcb_attribute_put(&PCB->Attributes, "openems::excitation::type", excitations[exc_ctx.selected].name); + pcb_board_set_changed_flag(pcb_true); + } + } +} + +static void select_cb(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + exc_ctx.selected = attr->default_val.int_value; + select_update(1); +} + +static void exc_val_chg_cb(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + excitations[exc_ctx.selected].ser(exc_ctx.selected, 1); +} + +static void pcb_dlg_exc(void) +{ + static const char *excnames[MAX_EXC+1]; + const exc_t *e; + int n; + pcb_hid_dad_buttons_t clbtn[] = {{"Close", 0}, {NULL, 0}}; + + if (exc_ctx.active) + return; /* do not open another */ + + if (excnames[0] == NULL) { + for(n = 0, e = excitations; e->name != NULL; n++,e++) { + if (n >= MAX_EXC) { + pcb_message(PCB_MSG_ERROR, "internal error: too many excitations"); + break; + } + excnames[n] = e->name; + } + excnames[n] = NULL; + } + + PCB_DAD_BEGIN_VBOX(exc_ctx.dlg); + PCB_DAD_COMPFLAG(exc_ctx.dlg, PCB_HATF_EXPFILL); + PCB_DAD_BEGIN_HBOX(exc_ctx.dlg); + PCB_DAD_LABEL(exc_ctx.dlg, "Excitation type:"); + PCB_DAD_ENUM(exc_ctx.dlg, excnames); + exc_ctx.wselector = PCB_DAD_CURRENT(exc_ctx.dlg); + PCB_DAD_CHANGE_CB(exc_ctx.dlg, select_cb); + PCB_DAD_END(exc_ctx.dlg); + PCB_DAD_BEGIN_TABBED(exc_ctx.dlg, excnames); + PCB_DAD_COMPFLAG(exc_ctx.dlg, PCB_HATF_EXPFILL | PCB_HATF_HIDE_TABLAB); + exc_ctx.wtab = PCB_DAD_CURRENT(exc_ctx.dlg); + for(n = 0, e = excitations; e->name != NULL; n++,e++) { + if (e->dad != NULL) + e->dad(n); + else + PCB_DAD_LABEL(exc_ctx.dlg, "Not yet available."); + } + PCB_DAD_END(exc_ctx.dlg); + PCB_DAD_BUTTON_CLOSES(exc_ctx.dlg, clbtn); + PCB_DAD_END(exc_ctx.dlg); + + /* set up the context */ + exc_ctx.active = 1; + + PCB_DAD_NEW("openems_excitation", exc_ctx.dlg, "openems: excitation", &exc_ctx, pcb_false, exc_close_cb); + + load_selector(); + select_update(1); + exc_load_all(); +} + +static const char pcb_acts_OpenemsExcitation[] = + "OpenemsExcitation([interactive])\n" + "OpenemsExcitation(select, excitationname)\n" + "OpenemsExcitation(set, [excitationnme], paramname, paramval)\n" + "OpenemsExcitation(get, [excitationnme], paramname)\n" + ; +static const char pcb_acth_OpenemsExcitation[] = "Select which openEMS excitation method should be exported and manipulate the associated parameters. When invoked without arguments a dialog box with the same functionality is presented."; +/* DOC: openemsexcication.html */ +static fgw_error_t pcb_act_OpenemsExcitation(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + const char *op = "interactive", *a1 = NULL; + + PCB_ACT_MAY_CONVARG(1, FGW_STR, OpenemsExcitation, op = argv[1].val.str); + PCB_ACT_MAY_CONVARG(2, FGW_STR, OpenemsExcitation, a1 = argv[2].val.str); + + PCB_ACT_IRES(0); + + if (strcmp(op, "interactive") == 0) + pcb_dlg_exc(); + else if (strcmp(op, "select") == 0) { + if (a1 == NULL) { + pcb_message(PCB_MSG_ERROR, "OpenemsExcitation(select) needs a excitation name"); + goto error; + } + pcb_attribute_put(&PCB->Attributes, AEPREFIX "type", a1); + load_selector(); + select_update(1); + } + else if (strcmp(op, "set") == 0) { + int start; + const char *key, *val; + char *attrkey; + switch(argc) { + case 4: a1 = excitations[exc_ctx.selected].name; start = 2; break; + case 5: start = 3; break; + default: + pcb_message(PCB_MSG_ERROR, "OpenemsExcitation(set) needs exactly 2 or 3 more arguments"); + goto error; + } + + PCB_ACT_CONVARG(start+0, FGW_STR, OpenemsExcitation, key = argv[start+0].val.str); + PCB_ACT_CONVARG(start+1, FGW_STR, OpenemsExcitation, val = argv[start+1].val.str); + + attrkey = pcb_strdup_printf(AEPREFIX "%s::%s", a1, key); + pcb_attribute_put(&PCB->Attributes, attrkey, val); + free(attrkey); + + exc_load_all(); + } + else if (strcmp(op, "get") == 0) { + int start; + const char *key; + char *attrkey; + switch(argc) { + case 3: a1 = excitations[exc_ctx.selected].name; start = 2; break; + case 4: start = 3; break; + default: + pcb_message(PCB_MSG_ERROR, "OpenemsExcitation(get) needs exactly 1 or 2 more arguments"); + goto error; + } + + PCB_ACT_CONVARG(start+0, FGW_STR, OpenemsExcitation, key = argv[start+0].val.str); + + attrkey = pcb_strdup_printf(AEPREFIX "%s::%s", a1, key); + res->type = FGW_STR; + res->val.cstr = pcb_attribute_get(&PCB->Attributes, attrkey); + free(attrkey); + } + + return 0; + + error:; + PCB_ACT_IRES(1); + return 0; +} + +static char *pcb_openems_excitation_get(pcb_board_t *pcb) +{ + if ((exc_ctx.selected < 0) || (exc_ctx.selected >= sizeof(excitations)/sizeof(excitations[0]))) { + pcb_message(PCB_MSG_ERROR, "No excitation selected\n"); + return pcb_strdup("%% ERROR: no excitation selected\n"); + } + return excitations[exc_ctx.selected].get(exc_ctx.selected); +} + +static void exc_ev_board_changed(void *user_data, int argc, pcb_event_arg_t argv[]) +{ + load_selector(); + if (exc_ctx.active) + exc_load_all(); +} + +static void pcb_openems_excitation_init(void) +{ + pcb_event_bind(PCB_EVENT_BOARD_CHANGED, exc_ev_board_changed, NULL, openems_cookie); +} + +static void pcb_openems_excitation_uninit(void) +{ + pcb_event_unbind_allcookie(openems_cookie); +} Index: tags/2.1.2/src_plugins/export_openems/export_openems.c =================================================================== --- tags/2.1.2/src_plugins/export_openems/export_openems.c (nonexistent) +++ tags/2.1.2/src_plugins/export_openems/export_openems.c (revision 24813) @@ -0,0 +1,890 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2018,2019 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "config.h" +#include "conf_core.h" + +#include +#include +#include +#include +#include + +#include "board.h" +#include "data.h" +#include "data_it.h" +#include "draw.h" +#include "compat_misc.h" +#include "plugins.h" +#include "safe_fs.h" +#include "layer_vis.h" +#include "obj_subc_parent.h" +#include "obj_pstk_inlines.h" + +#include "hid.h" +#include "actions.h" +#include "hid_nogui.h" +#include "hid_cam.h" +#include "hid_attrib.h" +#include "hid_init.h" +#include "hid_draw_helpers.h" +#include "../src_plugins/lib_polyhelp/topoly.h" +#include "mesh.h" + +static pcb_hid_t openems_hid; + +const char *openems_cookie = "openems HID"; + +#include "excitation.c" + +#define MESH_NAME "openems" + +typedef struct hid_gc_s { + pcb_core_gc_t core_gc; + pcb_hid_t *me_pointer; + pcb_cap_style_t cap; + int width; +} hid_gc_s; + +typedef struct { + /* input/output */ + FILE *f, *fsim; + pcb_board_t *pcb; + pcb_hid_attr_val_t *options; + + /* local cache */ + const char *filename; + int lg_pcb2ems[PCB_MAX_LAYERGRP]; /* indexed by gid, gives 0 or the ems-side layer ID */ + int lg_ems2pcb[PCB_MAX_LAYERGRP]; /* indexed by the ems-side layer ID, gives -1 or a gid */ + int lg_next; + int clayer; /* current layer (lg index really) */ + long oid; /* unique object ID - we need some unique variable names, keep on counting them */ + long port_id; /* unique port ID for similar reasons */ + pcb_coord_t ox, oy; + unsigned warn_subc_term:1; + unsigned warn_port_pstk:1; +} wctx_t; + +static FILE *f = NULL; +static wctx_t *ems_ctx; + +#define THMAX PCB_MM_TO_COORD(100) + +pcb_hid_attribute_t openems_attribute_list[] = { + {"outfile", "Graphics output file", + PCB_HATT_STRING, 0, 0, {0, 0, 0}, 0, 0}, +#define HA_openemsfile 0 + + {"def-copper-thick", "Default copper thickness", + PCB_HATT_COORD, 0, THMAX, {0, 0, 0, PCB_MM_TO_COORD(0.035)}, 0, 0}, +#define HA_def_copper_thick 1 + + {"def-substrate-thick", "Default substrate thickness", + PCB_HATT_COORD, 0, THMAX, {0, 0, 0, PCB_MM_TO_COORD(0.8)}, 0, 0}, +#define HA_def_substrate_thick 2 + + {"def-copper-cond", "Default copper conductivity", + PCB_HATT_STRING, 0, 0, {0, "56*10^6", 0}, 0, 0}, +#define HA_def_copper_cond 3 + + {"def-subst-epsilon", "Default substrate epsilon", + PCB_HATT_STRING, 0, 0, {0, "3.66", 0}, 0, 0}, +#define HA_def_subst_epsilon 4 + + {"def-subst-mue", "Default substrate mue", + PCB_HATT_STRING, 0, 0, {0, "0", 0}, 0, 0}, +#define HA_def_subst_mue 5 + + {"def-subst-kappa", "Default substrate kappa", + PCB_HATT_STRING, 0, 0, {0, "0", 0}, 0, 0}, +#define HA_def_subst_kappa 6 + + {"def-subst-sigma", "Default substrate sigma", + PCB_HATT_STRING, 0, 0, {0, "0", 0}, 0, 0}, +#define HA_def_subst_sigma 7 + + {"void-name", "Name of the void (sorrunding material)", + PCB_HATT_STRING, 0, 0, {0, "AIR", 0}, 0, 0}, +#define HA_void_name 8 + + {"void-epsilon", "epsilon value for the void (sorrunding material)", + PCB_HATT_REAL, 0, 1000, {0, 0, 1}, 0, 0}, +#define HA_void_epsilon 9 + + {"void-mue", "mue value for the void (sorrunding material)", + PCB_HATT_REAL, 0, 1000, {0, 0, 1}, 0, 0}, +#define HA_void_mue 10 + + {"segments", "kludge: number of segments used to approximate round cap trace ends", + PCB_HATT_INTEGER, 0, 100, {10, 0, 0}, 0, 0}, +#define HA_segments 11 + + {"base-prio", "base priority: if the board displaces the chassis", + PCB_HATT_INTEGER, 0, 10, {0, 0, 0}, 0, 0}, +#define HA_base_prio 12 + + {"port-resistance", "default port resistance", + PCB_HATT_REAL, 0, 1000, {0, 0, 50}, 0, 0} +#define HA_def_port_res 13 + +}; + +#define NUM_OPTIONS (sizeof(openems_attribute_list)/sizeof(openems_attribute_list[0])) + +PCB_REGISTER_ATTRIBUTES(openems_attribute_list, openems_cookie) + +static pcb_hid_attr_val_t openems_values[NUM_OPTIONS]; + +static pcb_hid_attribute_t *openems_get_export_options(int *n) +{ + const char *suffix = ".m"; + pcb_mesh_t *mesh = pcb_mesh_get(MESH_NAME); + + if ((PCB != NULL) && (openems_attribute_list[HA_openemsfile].default_val.str_value == NULL)) + pcb_derive_default_filename(PCB->Filename, &openems_attribute_list[HA_openemsfile], suffix); + + if (mesh != NULL) { + openems_attribute_list[HA_def_substrate_thick].default_val.coord_value = mesh->def_subs_thick; + openems_attribute_list[HA_def_copper_thick].default_val.coord_value = mesh->def_copper_thick; + } + +TODO(": when export dialogs change into DAD, this hack to convert the strings to allocated ones will not be needed anymore") + openems_attribute_list[HA_def_copper_cond].default_val.str_value = pcb_strdup(openems_attribute_list[HA_def_copper_cond].default_val.str_value); + openems_attribute_list[HA_def_subst_epsilon].default_val.str_value = pcb_strdup(openems_attribute_list[HA_def_subst_epsilon].default_val.str_value); + openems_attribute_list[HA_def_subst_mue].default_val.str_value = pcb_strdup(openems_attribute_list[HA_def_subst_mue].default_val.str_value); + openems_attribute_list[HA_def_subst_kappa].default_val.str_value = pcb_strdup(openems_attribute_list[HA_def_subst_kappa].default_val.str_value); + openems_attribute_list[HA_def_subst_sigma].default_val.str_value = pcb_strdup(openems_attribute_list[HA_def_subst_sigma].default_val.str_value); + openems_attribute_list[HA_void_name].default_val.str_value = pcb_strdup(openems_attribute_list[HA_void_name].default_val.str_value); + + if (n) + *n = NUM_OPTIONS; + return openems_attribute_list; +} + +/* Find the openems 0;0 mark, if there is any */ +static void find_origin_bump(void *ctx_, pcb_board_t *pcb, pcb_layer_t *layer, pcb_line_t *line) +{ + wctx_t *ctx = ctx_; + if (pcb_attribute_get(&line->Attributes, "openems-origin") != NULL) { + ctx->ox = (line->BoundingBox.X1 + line->BoundingBox.X2) / 2; + ctx->oy = (line->BoundingBox.Y1 + line->BoundingBox.Y2) / 2; + } +} + +static void find_origin(wctx_t *ctx) +{ + pcb_loop_layers(ctx->pcb, ctx, NULL, find_origin_bump, NULL, NULL, NULL); +} + +static void openems_write_tunables(wctx_t *ctx) +{ + fprintf(ctx->f, "%%%%%% User tunables\n"); + fprintf(ctx->f, "\n"); + + fprintf(ctx->f, "%%%% base_priority and offset: chassis for the board to sit in.\n"); + fprintf(ctx->f, "%% base priority: if the board displaces the model of the chassis or the other way around.\n"); + fprintf(ctx->f, "base_priority=%d;\n", ctx->options[HA_base_prio].int_value); + fprintf(ctx->f, "\n"); + fprintf(ctx->f, "%% offset on the whole layout to locate it relative to the simulation origin\n"); + pcb_fprintf(ctx->f, "offset.x = %mm;\n", -ctx->ox); + pcb_fprintf(ctx->f, "offset.y = %mm;\n", ctx->oy); + fprintf(ctx->f, "offset.z = 0;\n"); + fprintf(ctx->f, "\n"); + + fprintf(ctx->f, "%% void is the material used for: fill holes, cutouts in substrate, etc\n"); + fprintf(ctx->f, "void.name = '%s';\n", ctx->options[HA_void_name].str_value); + fprintf(ctx->f, "void.epsilon = %f;\n", ctx->options[HA_void_epsilon].real_value); + fprintf(ctx->f, "void.mue = %f;\n", ctx->options[HA_void_mue].real_value); + fprintf(ctx->f, "%% void.kappa = kappa;\n"); + fprintf(ctx->f, "%% void.sigma = sigma;\n"); + fprintf(ctx->f, "\n"); + + fprintf(ctx->f, "%% how many points should be used to describe the round end of traces.\n"); + fprintf(ctx->f, "kludge.segments = %d;\n", ctx->options[HA_segments].int_value); + fprintf(ctx->f, "\n"); + + fprintf(ctx->f, "\n"); +} + +static void print_lparm(wctx_t *ctx, pcb_layergrp_t *grp, const char *attr, int cop_opt, int subs_opt, int is_str) +{ + int opt; + +TODO(": this needs layer group attributes in core (planned for lihata v5)") +#if 0 +TODO(": try openems::attr first - make a new core call for prefixed get, this will be a real common pattern") + const char *val = pcb_attribute_get(&grp->Attributes, attr); + + if (val != NULL) { + /* specified by a layer group attribute: overrides anything else */ + if (is_str) + fprintf(ctx->f, "%s", val); + else + TODO: getvalue, print as coord + return; + } +#endif + + opt = (grp->ltype & PCB_LYT_COPPER) ? cop_opt : subs_opt; + assert(opt >= 0); + if (is_str) + pcb_fprintf(ctx->f, "%s", ctx->options[opt].str_value); + else + pcb_fprintf(ctx->f, "%mm", ctx->options[opt].coord_value); +} + +static void openems_write_layers(wctx_t *ctx) +{ + pcb_layergrp_id_t gid; + int next = 1; + + for(gid = 0; gid < PCB_MAX_LAYERGRP; gid++) + ctx->lg_ems2pcb[gid] = -1; + + fprintf(ctx->f, "%%%%%% Layer mapping\n"); + + /* linear map of copper and substrate layers */ + for(gid = 0; gid < ctx->pcb->LayerGroups.len; gid++) { + pcb_layergrp_t *grp = &ctx->pcb->LayerGroups.grp[gid]; + int iscop = (grp->ltype & PCB_LYT_COPPER); + + if (!(iscop) && !(grp->ltype & PCB_LYT_SUBSTRATE)) + continue; + ctx->lg_ems2pcb[next] = gid; + ctx->lg_pcb2ems[gid] = next; + + fprintf(ctx->f, "layers(%d).number = %d;\n", next, next); /* type index really */ + fprintf(ctx->f, "layers(%d).name = '%s';\n", next, (grp->name == NULL ? "anon" : grp->name)); + fprintf(ctx->f, "layers(%d).clearn = 0;\n", next); + fprintf(ctx->f, "layer_types(%d).name = '%s_%d';\n", next, iscop ? "COPPER" : "SUBSTRATE", next); + fprintf(ctx->f, "layer_types(%d).subtype = %d;\n", next, iscop ? 2 : 3); + + fprintf(ctx->f, "layer_types(%d).thickness = ", next); + print_lparm(ctx, grp, "thickness", HA_def_copper_thick, HA_def_substrate_thick, 0); + fprintf(ctx->f, ";\n"); + + if (iscop) { + fprintf(ctx->f, "layer_types(%d).conductivity = ", next); + print_lparm(ctx, grp, "conductivity", HA_def_copper_cond, -1, 1); + fprintf(ctx->f, ";\n"); + } + else { /* substrate */ + fprintf(ctx->f, "layer_types(%d).epsilon = ", next); + print_lparm(ctx, grp, "epsilon", -1, HA_def_subst_epsilon, 1); + fprintf(ctx->f, ";\n"); + + fprintf(ctx->f, "layer_types(%d).mue = ", next); + print_lparm(ctx, grp, "mue", -1, HA_def_subst_mue, 1); + fprintf(ctx->f, ";\n"); + + fprintf(ctx->f, "layer_types(%d).kappa = ", next); + print_lparm(ctx, grp, "kappa", -1, HA_def_subst_kappa, 1); + fprintf(ctx->f, ";\n"); + + fprintf(ctx->f, "layer_types(%d).sigma = ", next); + print_lparm(ctx, grp, "sigma", -1, HA_def_subst_sigma, 1); + fprintf(ctx->f, ";\n"); + + } + + next++; + fprintf(ctx->f, "\n"); + } + fprintf(ctx->f, "\n"); + + ctx->lg_next = next; +} + +static void openems_write_init(wctx_t *ctx) +{ + fprintf(ctx->f, "%%%%%% Initialize pcb2csx\n"); + fprintf(ctx->f, "PCBRND = InitPCBRND(layers, layer_types, void, base_priority, offset, kludge);\n"); + fprintf(ctx->f, "CSX = InitPcbrndLayers(CSX, PCBRND);\n"); + fprintf(ctx->f, "\n"); +} + +static void openems_write_outline(wctx_t *ctx) +{ + int n; + pcb_any_obj_t *out1; + + fprintf(ctx->f, "%%%%%% Board outline\n"); + +TODO("layer: consider multiple outline layers instead") + out1 = pcb_topoly_find_1st_outline(ctx->pcb); + if (out1 != NULL) { + long n; + pcb_poly_t *p = pcb_topoly_conn(ctx->pcb, out1, PCB_TOPOLY_KEEP_ORIG | PCB_TOPOLY_FLOATING); + for(n = 0; n < p->PointN; n++) + pcb_fprintf(ctx->f, "outline_xy(1, %ld) = %mm; outline_xy(2, %ld) = %mm;\n", n+1, p->Points[n].X, n+1, -p->Points[n].Y); + pcb_poly_free(p); + } + else { + /* rectangular board size */ + pcb_fprintf(ctx->f, "outline_xy(1, 1) = 0; outline_xy(2, 1) = 0;\n"); + pcb_fprintf(ctx->f, "outline_xy(1, 2) = %mm; outline_xy(2, 2) = 0;\n", ctx->pcb->MaxWidth); + pcb_fprintf(ctx->f, "outline_xy(1, 3) = %mm; outline_xy(2, 3) = %mm;\n", ctx->pcb->MaxWidth, -ctx->pcb->MaxHeight); + pcb_fprintf(ctx->f, "outline_xy(1, 4) = 0; outline_xy(2, 4) = %mm;\n", -ctx->pcb->MaxHeight); + } + + /* create all substrate layers using this polygon*/ + for(n = 1; n < ctx->lg_next; n++) { + pcb_layergrp_t *grp = &ctx->pcb->LayerGroups.grp[ctx->lg_ems2pcb[n]]; + if (grp->ltype & PCB_LYT_SUBSTRATE) + fprintf(ctx->f, "CSX = AddPcbrndPoly(CSX, PCBRND, %d, outline_xy, 1);\n", n); + } + + fprintf(ctx->f, "\n"); +} + +static void openems_vport_write(wctx_t *ctx, pcb_any_obj_t *o, pcb_coord_t x, pcb_coord_t y, pcb_layergrp_id_t gid1, pcb_layergrp_id_t gid2, const char *port_name) +{ + char *end, *s, *safe_name = pcb_strdup(port_name); + const char *att; + double resistance = ctx->options[HA_def_port_res].real_value; + int act = 1; + + ctx->port_id++; + + att = pcb_attribute_get(&o->Attributes, "openems::resistance"); + if (att != NULL) { + double tmp = strtod(att, &end); + if (*end == '\0') + resistance = tmp; + else + pcb_message(PCB_MSG_WARNING, "Ignoring invalid openems::resistance value for port %s: '%s' (must be a number without suffix)\n", port_name, att); + } + + att = pcb_attribute_get(&o->Attributes, "openems::active"); + if (att != NULL) { + if (pcb_strcasecmp(att, "true") == 0) + act = 1; + else if (pcb_strcasecmp(att, "false") == 0) + act = 0; + else + pcb_message(PCB_MSG_WARNING, "Ignoring invalid openems::active value for port %s: '%s' (must be true or false)\n", port_name, att); + } + + for(s = safe_name; *s != '\0'; s++) + if (!isalnum(*s)) + *s = '_'; + + pcb_fprintf(ctx->f, "\npoint%s(1, 1) = %mm; point%s(2, 1) = %mm;\n", safe_name, x, safe_name, -y); + fprintf(ctx->f, "[start%s, stop%s] = CalcPcbrnd2PortV(PCBRND, point%s, %d, %d);\n", safe_name, safe_name, safe_name, ctx->lg_pcb2ems[gid1], ctx->lg_pcb2ems[gid2]); + fprintf(ctx->f, "[CSX, port{%ld}] = AddLumpedPort(CSX, 999, %ld, %f, start%s, stop%s, [0 0 -1]%s);\n", ctx->port_id, ctx->port_id, resistance, safe_name, safe_name, act ? ", true" : ""); + + free(safe_name); +} + +pcb_layergrp_id_t openems_vport_main_group_pstk(pcb_board_t *pcb, pcb_pstk_t *ps, int *gstep, const char *port_name) +{ + int top, bot, intern; + pcb_layergrp_id_t gid1; + + top = (pcb_pstk_shape(ps, PCB_LYT_COPPER | PCB_LYT_TOP, 0) != NULL); + bot = (pcb_pstk_shape(ps, PCB_LYT_COPPER | PCB_LYT_BOTTOM, 0) != NULL); + intern = (pcb_pstk_shape(ps, PCB_LYT_INTERN | PCB_LYT_BOTTOM, 0) != NULL); + if (intern) { + pcb_message(PCB_MSG_ERROR, "Can not export openems vport %s: it has internal copper\n(must be either top or bottom copper)\n", port_name); + return -1; + } + if (top && bot) { + pcb_message(PCB_MSG_ERROR, "Can not export openems vport %s: it has both top and bottom copper\n", port_name); + return -1; + } + if (!top && !bot) { + pcb_message(PCB_MSG_ERROR, "Can not export openems vport %s: it does not have copper either on top or bottom\n", port_name); + return -1; + } + + /* pick main group */ + if (top) { + gid1 = pcb_layergrp_get_top_copper(); + *gstep = +1; + } + else { + gid1 = pcb_layergrp_get_bottom_copper(); + *gstep = -1; + } + if (gid1 < 0) { + pcb_message(PCB_MSG_ERROR, "Can not export openems vport %s: can not find top or bottom layer group ID\n", port_name); + return -1; + } + + return gid1; +} + +pcb_layergrp_id_t openems_vport_aux_group(pcb_board_t *pcb, pcb_layergrp_id_t gid1, int gstep, const char *port_name) +{ + pcb_layergrp_id_t gid2; + + for(gid2 = gid1 + gstep; (gid2 >= 0) && (gid2 <= pcb->LayerGroups.len); gid2 += gstep) + if (pcb->LayerGroups.grp[gid2].ltype & PCB_LYT_COPPER) + return gid2; + + pcb_message(PCB_MSG_ERROR, "Can not export openems vport %s: can not find pair layer\n", port_name); + return -1; +} + + +#define TPMASK (PCB_OBJ_LINE | PCB_OBJ_PSTK | PCB_OBJ_SUBC) +static void openems_write_testpoints(wctx_t *ctx, pcb_data_t *data) +{ + pcb_any_obj_t *o; + pcb_data_it_t it; + + for(o = pcb_data_first(&it, data, TPMASK); o != NULL; o = pcb_data_next(&it)) { + const char *port_name; + if (o->type == PCB_OBJ_SUBC) + openems_write_testpoints(ctx, ((pcb_subc_t *)o)->data); + + port_name = pcb_attribute_get(&o->Attributes, "openems::vport"); + if (port_name == NULL) + continue; + + if (o->type == PCB_OBJ_SUBC) { + if (!ctx->warn_subc_term) + pcb_message(PCB_MSG_ERROR, "Subcircuit being a terminal is not supported.\n"); + ctx->warn_subc_term = 1; + continue; + } + + /* place the vertical port */ + switch(o->type) { + case PCB_OBJ_PSTK: + { + int gstep; + pcb_layergrp_id_t gid1, gid2; + pcb_pstk_t *ps = (pcb_pstk_t *)o; + + if (port_name == NULL) + break; + + gid1 = openems_vport_main_group_pstk(ctx->pcb, ps, &gstep, port_name); + if (gid1 < 0) + break; + + gid2 = openems_vport_aux_group(ctx->pcb, gid1, gstep, port_name); + if (gid2 < 0) + break; + +TODO(": check if there is copper object on hid2 at x;y") + + if (pcb_attribute_get(&o->Attributes, "openems::vport-reverse") == NULL) + openems_vport_write(ctx, (pcb_any_obj_t *)ps, ps->x, ps->y, gid1, gid2, port_name); + else + openems_vport_write(ctx, (pcb_any_obj_t *)ps, ps->x, ps->y, gid2, gid1, port_name); + } + break; + default: + if (!ctx->warn_port_pstk) + pcb_message(PCB_MSG_ERROR, "Only padstacks can be openems ports at the moment\n"); + ctx->warn_port_pstk = 1; + break; + } + } +} + +static void openems_write_mesh_lines(wctx_t *ctx, pcb_mesh_lines_t *l) +{ + pcb_cardinal_t n; + for(n = 0; n < vtc0_len(&l->result); n++) + pcb_fprintf(ctx->f, "%s%mm", (n == 0 ? "" : " "), l->result.array[n]); +} + +static void openems_write_mesh1(wctx_t *ctx) +{ + pcb_mesh_t *mesh = pcb_mesh_get(MESH_NAME); + char *exc = pcb_openems_excitation_get(ctx->pcb); + int n; + + fprintf(ctx->fsim, "%%%%%% Board mesh, part 1\n"); + fprintf(ctx->fsim, "unit = 1.0e-3;\n"); + fprintf(ctx->fsim, "FDTD = InitFDTD();\n"); + fprintf(ctx->fsim, "%% Excitation begin\n"); + fprintf(ctx->fsim, "%s\n", exc); + fprintf(ctx->fsim, "%% Excitation end\n"); + free(exc); + + if (mesh != NULL) { + + fprintf(ctx->fsim, "BC = {"); + + for(n = 0; n < 6; n++) + fprintf(ctx->fsim, "%s'%s'", (n == 0 ? "" : " "), mesh->bnd[n]); + fprintf(ctx->fsim, "};\n"); + + fprintf(ctx->fsim, "FDTD = SetBoundaryCond(FDTD, BC);\n"); + } + fprintf(ctx->fsim, "physical_constants;\n"); + fprintf(ctx->fsim, "CSX = InitCSX();\n"); + fprintf(ctx->fsim, "\n"); +} + +static void openems_write_mesh2(wctx_t *ctx) +{ + pcb_mesh_t *mesh = pcb_mesh_get(MESH_NAME); + + if (mesh == NULL) { + fprintf(ctx->f, "%%%%%% Board mesh (NOT defined in pcb-rnd)\n"); + return; + } + fprintf(ctx->f, "%%%%%% Board mesh, part 2\n"); + + pcb_fprintf(ctx->f, "z_bottom_copper=%mm\n", mesh->z_bottom_copper); + + fprintf(ctx->f, "mesh.y=["); + openems_write_mesh_lines(ctx, &mesh->line[PCB_MESH_HORIZONTAL]); + fprintf(ctx->f, "];\n"); + + fprintf(ctx->f, "mesh.x=["); + openems_write_mesh_lines(ctx, &mesh->line[PCB_MESH_VERTICAL]); + fprintf(ctx->f, "];\n"); + + fprintf(ctx->f, "mesh.z=["); + openems_write_mesh_lines(ctx, &mesh->line[PCB_MESH_Z]); + fprintf(ctx->f, "];\n"); + + fprintf(ctx->f, "mesh.x = mesh.x .+ offset.x;\n"); + fprintf(ctx->f, "mesh.y = offset.y .- mesh.y;\n"); + fprintf(ctx->f, "mesh.z = z_bottom_copper .- mesh.z .+ offset.z;\n"); + if (mesh->pml > 0) + fprintf(ctx->f, "mesh = AddPML(mesh, %d);\n", mesh->pml); + fprintf(ctx->f, "CSX = DefineRectGrid(CSX, unit, mesh);\n"); + fprintf(ctx->f, "\n"); +} + +static void openems_write_sim(wctx_t *wctx) +{ + openems_write_mesh1(wctx); + + fprintf(wctx->fsim, "run %s\n\n", wctx->filename); + + fprintf(wctx->fsim, "Sim_Path = '.';\n"); + fprintf(wctx->fsim, "Sim_CSX = 'csxcad.xml';\n"); + fprintf(wctx->fsim, "WriteOpenEMS( [Sim_Path '/' Sim_CSX], FDTD, CSX );\n"); +} + + +void openems_hid_export_to_file(const char *filename, FILE *the_file, FILE *fsim, pcb_hid_attr_val_t *options) +{ + pcb_hid_expose_ctx_t ctx; + wctx_t wctx; + + memset(&wctx, 0, sizeof(wctx)); + wctx.filename = filename; + wctx.f = the_file; + wctx.fsim = fsim; + wctx.pcb = PCB; + wctx.options = options; + ems_ctx = &wctx; + + ctx.view.X1 = 0; + ctx.view.Y1 = 0; + ctx.view.X2 = PCB->MaxWidth; + ctx.view.Y2 = PCB->MaxHeight; + + f = the_file; + + conf_force_set_bool(conf_core.editor.thin_draw, 0); + conf_force_set_bool(conf_core.editor.thin_draw_poly, 0); +/* conf_force_set_bool(conf_core.editor.check_planes, 0);*/ + conf_force_set_bool(conf_core.editor.show_solder_side, 0); + + find_origin(&wctx); + openems_write_sim(&wctx); + openems_write_tunables(&wctx); + openems_write_mesh2(&wctx); + openems_write_layers(&wctx); + openems_write_init(&wctx); + openems_write_outline(&wctx); + + fprintf(wctx.f, "%%%%%% Copper objects\n"); + pcb_hid_expose_all(&openems_hid, &ctx, NULL); + + fprintf(wctx.f, "%%%%%% Port(s) on terminals\n"); + openems_write_testpoints(&wctx, wctx.pcb->Data); + + conf_update(NULL, -1); /* restore forced sets */ +} + +static void openems_do_export(pcb_hid_attr_val_t * options) +{ + const char *filename; + char *runfn, *end; + int save_ons[PCB_MAX_LAYER + 2]; + int i, len; + FILE *fsim; + + if (!options) { + openems_get_export_options(0); + for (i = 0; i < NUM_OPTIONS; i++) + openems_values[i] = openems_attribute_list[i].default_val; + options = openems_values; + } + + filename = options[HA_openemsfile].str_value; + if (!filename) + filename = "pcb.m"; + + f = pcb_fopen(filename, "wb"); + if (!f) { + perror(filename); + return; + } + + /* create the run.m file */ + len = strlen(filename); + runfn = malloc(len+16); + memcpy(runfn, filename, len+1); + end = runfn + len - 2; + if (strcmp(end, ".m") != 0) + end = runfn + len; + strcpy(end, ".sim.m"); + fsim = pcb_fopen(runfn, "wb"); + if (fsim == NULL) { + perror(runfn); + return; + } + + pcb_hid_save_and_show_layer_ons(save_ons); + + openems_hid_export_to_file(filename, f, fsim, options); + + pcb_hid_restore_layer_ons(save_ons); + + fclose(f); + fclose(fsim); + f = NULL; + free(runfn); +} + +static int openems_parse_arguments(int *argc, char ***argv) +{ + pcb_hid_register_attributes(openems_attribute_list, sizeof(openems_attribute_list) / sizeof(openems_attribute_list[0]), openems_cookie, 0); + return pcb_hid_parse_command_line(argc, argv); +} + +static int openems_set_layer_group(pcb_layergrp_id_t group, const char *purpose, int purpi, pcb_layer_id_t layer, unsigned int flags, int is_empty, pcb_xform_t **xform) +{ + if (flags & PCB_LYT_COPPER) { /* export copper layers only */ + ems_ctx->clayer = ems_ctx->lg_pcb2ems[group]; + return 1; + } + return 0; +} + +static pcb_hid_gc_t openems_make_gc(void) +{ + pcb_hid_gc_t rv = (pcb_hid_gc_t) calloc(sizeof(hid_gc_s), 1); + rv->me_pointer = &openems_hid; + return rv; +} + +static void openems_destroy_gc(pcb_hid_gc_t gc) +{ + free(gc); +} + +static void openems_set_drawing_mode(pcb_composite_op_t op, pcb_bool direct, const pcb_box_t *screen) +{ + switch(op) { + case PCB_HID_COMP_RESET: + break; + case PCB_HID_COMP_POSITIVE: + case PCB_HID_COMP_POSITIVE_XOR: + break; + case PCB_HID_COMP_NEGATIVE: + pcb_message(PCB_MSG_ERROR, "Can't draw composite layer, especially not on copper\n"); + break; + case PCB_HID_COMP_FLUSH: + break; + } +} + +static void openems_set_color(pcb_hid_gc_t gc, const pcb_color_t *name) +{ +} + +static void openems_set_line_cap(pcb_hid_gc_t gc, pcb_cap_style_t style) +{ + gc->cap = style; +} + +static void openems_set_line_width(pcb_hid_gc_t gc, pcb_coord_t width) +{ + gc->width = width; +} + + +static void openems_set_draw_xor(pcb_hid_gc_t gc, int xor_) +{ + ; +} + +static void openems_fill_rect(pcb_hid_gc_t gc, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2) +{ +} + +static void openems_draw_rect(pcb_hid_gc_t gc, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2) +{ +} + +static void openems_draw_arc(pcb_hid_gc_t gc, pcb_coord_t cx, pcb_coord_t cy, pcb_coord_t width, pcb_coord_t height, pcb_angle_t start_angle, pcb_angle_t delta_angle) +{ +} + +static void openems_fill_circle(pcb_hid_gc_t gc, pcb_coord_t cx, pcb_coord_t cy, pcb_coord_t radius) +{ + wctx_t *ctx = ems_ctx; + long oid = ctx->oid++; + + pcb_fprintf(ctx->f, "points%ld(1, 1) = %mm; points%ld(2, 1) = %mm;\n", oid, cx, oid, -cy); + pcb_fprintf(ctx->f, "points%ld(1, 2) = %mm; points%ld(2, 2) = %mm;\n", oid, cx, oid, -cy); + pcb_fprintf(ctx->f, "CSX = AddPcbrndTrace(CSX, PCBRND, %d, points%ld, %mm, 0);\n", ctx->clayer, oid, radius*2); +} + +static void openems_fill_polygon_offs(pcb_hid_gc_t gc, int n_coords, pcb_coord_t *x, pcb_coord_t *y, pcb_coord_t dx, pcb_coord_t dy) +{ + wctx_t *ctx = ems_ctx; + int n; + long oid = ctx->oid++; + + for(n = 0; n < n_coords; n++) + pcb_fprintf(ctx->f, "poly%ld_xy(1, %ld) = %mm; poly%ld_xy(2, %ld) = %mm;\n", oid, n+1, x[n]+dx, oid, n+1, -(y[n]+dy)); + + fprintf(ctx->f, "CSX = AddPcbrndPoly(CSX, PCBRND, %d, poly%ld_xy, 1);\n", ctx->clayer, oid); +} + +static void openems_fill_polygon(pcb_hid_gc_t gc, int n_coords, pcb_coord_t *x, pcb_coord_t *y) +{ + openems_fill_polygon_offs(gc, n_coords, x, y, 0, 0); +} + +static void openems_draw_line(pcb_hid_gc_t gc, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2) +{ + wctx_t *ctx = ems_ctx; + + if (gc->cap == pcb_cap_square) { + pcb_coord_t x[4], y[4]; + pcb_line_t tmp; + tmp.Point1.X = x1; + tmp.Point1.Y = y1; + tmp.Point2.X = x2; + tmp.Point2.Y = y2; + pcb_sqline_to_rect(&tmp, x, y); + openems_fill_polygon_offs(gc, 4, x, y, 0, 0); + } + else { + long oid = ctx->oid++; + pcb_fprintf(ctx->f, "points%ld(1, 1) = %mm; points%ld(2, 1) = %mm;\n", oid, x1, oid, -y1); + pcb_fprintf(ctx->f, "points%ld(1, 2) = %mm; points%ld(2, 2) = %mm;\n", oid, x2, oid, -y2); + pcb_fprintf(ctx->f, "CSX = AddPcbrndTrace(CSX, PCBRND, %d, points%ld, %mm, 0);\n", ctx->clayer, oid, gc->width); + } +} + + +static void openems_calibrate(double xval, double yval) +{ + pcb_message(PCB_MSG_ERROR, "openems_calibrate() not implemented"); + return; +} + +static void openems_set_crosshair(pcb_coord_t x, pcb_coord_t y, int a) +{ +} + +static int openems_usage(const char *topic) +{ + fprintf(stderr, "\nopenems exporter command line arguments:\n\n"); + pcb_hid_usage(openems_attribute_list, sizeof(openems_attribute_list) / sizeof(openems_attribute_list[0])); + fprintf(stderr, "\nUsage: pcb-rnd [generic_options] -x openems [openems options] foo.pcb\n\n"); + return 0; +} + +static pcb_action_t openems_action_list[] = { + {"mesh", pcb_act_mesh, pcb_acth_mesh, pcb_acts_mesh}, + {"OpenemsExcitation", pcb_act_OpenemsExcitation, pcb_acth_OpenemsExcitation, pcb_acts_OpenemsExcitation} +}; + +PCB_REGISTER_ACTIONS(openems_action_list, openems_cookie) + +#include "dolists.h" + +int pplg_check_ver_export_openems(int ver_needed) { return 0; } + +void pplg_uninit_export_openems(void) +{ + pcb_openems_excitation_uninit(); + pcb_remove_actions_by_cookie(openems_cookie); + pcb_hid_remove_attributes_by_cookie(openems_cookie); +} + +int pplg_init_export_openems(void) +{ + PCB_API_CHK_VER; + + memset(&openems_hid, 0, sizeof(pcb_hid_t)); + + pcb_hid_nogui_init(&openems_hid); + pcb_dhlp_draw_helpers_init(&openems_hid); + + openems_hid.struct_size = sizeof(pcb_hid_t); + openems_hid.name = "openems"; + openems_hid.description = "OpenEMS exporter"; + openems_hid.exporter = 1; + + openems_hid.get_export_options = openems_get_export_options; + openems_hid.do_export = openems_do_export; + openems_hid.parse_arguments = openems_parse_arguments; + openems_hid.set_layer_group = openems_set_layer_group; + openems_hid.make_gc = openems_make_gc; + openems_hid.destroy_gc = openems_destroy_gc; + openems_hid.set_drawing_mode = openems_set_drawing_mode; + openems_hid.set_color = openems_set_color; + openems_hid.set_line_cap = openems_set_line_cap; + openems_hid.set_line_width = openems_set_line_width; + openems_hid.set_draw_xor = openems_set_draw_xor; + openems_hid.draw_line = openems_draw_line; + openems_hid.draw_arc = openems_draw_arc; + openems_hid.draw_rect = openems_draw_rect; + openems_hid.fill_circle = openems_fill_circle; + openems_hid.fill_polygon = openems_fill_polygon; + openems_hid.fill_polygon_offs = openems_fill_polygon_offs; + openems_hid.fill_rect = openems_fill_rect; + openems_hid.calibrate = openems_calibrate; + openems_hid.set_crosshair = openems_set_crosshair; + + openems_hid.usage = openems_usage; + + pcb_hid_register_hid(&openems_hid); + + PCB_REGISTER_ACTIONS(openems_action_list, openems_cookie); + + pcb_openems_excitation_init(); + + return 0; +} Index: tags/2.1.2/src_plugins/export_openems/export_openems.pup =================================================================== --- tags/2.1.2/src_plugins/export_openems/export_openems.pup (nonexistent) +++ tags/2.1.2/src_plugins/export_openems/export_openems.pup (revision 24813) @@ -0,0 +1,10 @@ +$class export +$short openems exporter +$long Export copper to OpenEMS simulation +$state WIP +$fmt-native no +$fmt-feature-w export a matlab file suitable for OpenEMS simulation +$package export-sim +dep lib_polyhelp +default disable +autoload 1 Index: tags/2.1.2/src_plugins/export_openems/mesh.c =================================================================== --- tags/2.1.2/src_plugins/export_openems/mesh.c (nonexistent) +++ tags/2.1.2/src_plugins/export_openems/mesh.c (revision 24813) @@ -0,0 +1,1227 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2018,2019 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "config.h" + +#include "mesh.h" +#include "layer.h" +#include "layer_ui.h" +#include "actions.h" +#include "board.h" +#include "data.h" +#include "hid_dad.h" +#include "event.h" +#include "safe_fs.h" + +static pcb_mesh_t mesh; +static const char *mesh_ui_cookie = "mesh ui layer cookie"; + +static const char *bnds[] = { "PEC", "PMC", "MUR", "PML_8", NULL }; +static const char *bnd_names[] = { "xmin", "xmax", "ymin", "ymax", "zmin", "zmax" }; +static const char *subslines[] = { "0", "1", "3", "5", NULL }; +static const int num_subslines[] = { 0, 1, 3, 5 }; + +typedef struct { + PCB_DAD_DECL_NOINIT(dlg) + int dens_obj, dens_gap, min_space, smooth, hor, ver, noimpl; + int bnd[6], pml, subslines, air_top, air_bot, dens_air, smoothz, max_air, def_subs_thick, def_copper_thick; + unsigned active:1; +} mesh_dlg_t; +static mesh_dlg_t ia; + +static void mesh2dlg(void) +{ + int n; + PCB_DAD_SET_VALUE(ia.dlg_hid_ctx, ia.pml, int_value, mesh.pml); + PCB_DAD_SET_VALUE(ia.dlg_hid_ctx, ia.dens_obj, coord_value, PCB_MM_TO_COORD(0.15)); + PCB_DAD_SET_VALUE(ia.dlg_hid_ctx, ia.dens_gap, coord_value, PCB_MM_TO_COORD(0.5)); + PCB_DAD_SET_VALUE(ia.dlg_hid_ctx, ia.min_space, coord_value, PCB_MM_TO_COORD(0.1)); + PCB_DAD_SET_VALUE(ia.dlg_hid_ctx, ia.smooth, int_value, 1); + PCB_DAD_SET_VALUE(ia.dlg_hid_ctx, ia.noimpl, int_value, 0); + PCB_DAD_SET_VALUE(ia.dlg_hid_ctx, ia.hor, int_value, 1); + PCB_DAD_SET_VALUE(ia.dlg_hid_ctx, ia.ver, int_value, 1); +TODO("enum lookup"); + PCB_DAD_SET_VALUE(ia.dlg_hid_ctx, ia.subslines, int_value, 3); + PCB_DAD_SET_VALUE(ia.dlg_hid_ctx, ia.def_subs_thick, coord_value, PCB_MM_TO_COORD(1.5)); +/* PCB_DAD_SET_VALUE(ia.dlg_hid_ctx, ia.def_copper_thick, coord_value, PCB_MM_TO_COORD(1.5));*/ + PCB_DAD_SET_VALUE(ia.dlg_hid_ctx, ia.air_top, int_value, 1); + PCB_DAD_SET_VALUE(ia.dlg_hid_ctx, ia.air_bot, int_value, 1); + PCB_DAD_SET_VALUE(ia.dlg_hid_ctx, ia.dens_air, coord_value, PCB_MM_TO_COORD(0.7)); + PCB_DAD_SET_VALUE(ia.dlg_hid_ctx, ia.smoothz, int_value, 1); + PCB_DAD_SET_VALUE(ia.dlg_hid_ctx, ia.max_air, coord_value, PCB_MM_TO_COORD(4)); + for(n = 0; n < 6; n++) { + const char **a; + int i; + if (mesh.bnd[n] != NULL) + for(i = 0, a = bnds; *a != NULL; a++,i++) + if (strcmp(*a, mesh.bnd[n]) == 0) + PCB_DAD_SET_VALUE(ia.dlg_hid_ctx, ia.bnd[n], int_value, i); + } +} + +static void dlg2mesh(void) +{ + int n; + mesh.pml = ia.dlg[ia.pml].default_val.int_value; + mesh.dens_obj = ia.dlg[ia.dens_obj].default_val.coord_value; + mesh.dens_gap = ia.dlg[ia.dens_gap].default_val.coord_value; + mesh.min_space = ia.dlg[ia.min_space].default_val.coord_value; + mesh.smooth = ia.dlg[ia.smooth].default_val.int_value; + mesh.noimpl = ia.dlg[ia.noimpl].default_val.int_value; + mesh.hor = ia.dlg[ia.hor].default_val.int_value; + mesh.ver = ia.dlg[ia.ver].default_val.int_value; +TODO("enum lookup"); + mesh.subslines = ia.dlg[ia.subslines].default_val.int_value; + mesh.def_subs_thick = ia.dlg[ia.def_subs_thick].default_val.coord_value; + mesh.def_copper_thick = ia.dlg[ia.def_copper_thick].default_val.coord_value; + mesh.air_top = ia.dlg[ia.air_top].default_val.int_value; + mesh.air_bot = ia.dlg[ia.air_top].default_val.int_value; + mesh.dens_air = ia.dlg[ia.dens_air].default_val.coord_value; + mesh.smoothz = ia.dlg[ia.smoothz].default_val.int_value; + mesh.max_air = ia.dlg[ia.max_air].default_val.coord_value; + for(n = 0; n < 6; n++) + mesh.bnd[n] = bnds[ia.dlg[ia.bnd[n]].default_val.int_value]; +} + +#if 1 + static void mesh_trace(const char *fmt, ...) { } +#else +# define mesh_trace pcb_trace +#endif + +TODO("reorder to avoid fwd decl") +static void mesh_auto_add_smooth(vtc0_t *v, pcb_coord_t c1, pcb_coord_t c2, pcb_coord_t d1, pcb_coord_t d, pcb_coord_t d2); + +#define SAVE_INT(name) \ + pcb_append_printf(dst, "%s " #name" = %d\n", prefix, (int)me->dlg[me->name].default_val.int_value); +#define SAVE_COORD(name) \ + pcb_append_printf(dst, "%s " #name" = %.08$$mm\n", prefix, (pcb_coord_t)me->dlg[me->name].default_val.coord_value); +void pcb_mesh_save(const mesh_dlg_t *me, gds_t *dst, const char *prefix) +{ + int n; + + if (prefix == NULL) + prefix = ""; + + pcb_append_printf(dst, "%sha:pcb-rnd-mesh-v1 {\n", prefix); + SAVE_COORD(dens_obj); + SAVE_COORD(dens_gap); + SAVE_COORD(min_space); + SAVE_INT(pml); + SAVE_INT(smooth); + SAVE_INT(hor); + SAVE_INT(ver); + SAVE_INT(noimpl); + SAVE_INT(air_top); + SAVE_INT(air_bot); + SAVE_COORD(dens_air); + SAVE_INT(smoothz); + SAVE_COORD(max_air); + SAVE_COORD(def_subs_thick); + SAVE_COORD(def_copper_thick); + pcb_append_printf(dst, "%s li:boundary = {", prefix); + for(n = 0; n < 6; n++) { + int bidx = me->dlg[me->bnd[n]].default_val.int_value; + const char *bs; + if ((bidx < 0) || (bidx >= sizeof(bnds) / sizeof(bnds[0]))) + bs = "invalid"; + else + bs = bnds[bidx]; + gds_append_str(dst, bs); + gds_append(dst, ';'); + } + gds_append_str(dst, "}\n"); + + { + int sidx = me->dlg[me->subslines].default_val.int_value; + const char *bs; + if ((sidx < 0) || (sidx >= sizeof(subslines) / sizeof(subslines[0]))) + bs = "invalid"; + else + bs = subslines[sidx]; + pcb_append_printf(dst, "%s subslines = %s\n", prefix, bs); + } + + pcb_append_printf(dst, "%s}\n", prefix); +} +#undef SAVE_INT +#undef SAVE_COORD + +#define LOAD_INT(name) \ +do { \ + lht_node_t *n = lht_dom_hash_get(root, #name); \ + if (n != NULL) { \ + int v; \ + char *end; \ + if (n->type != LHT_TEXT) { \ + pcb_message(PCB_MSG_ERROR, "Invalid mesh item: " #name " should be text\n"); \ + return -1; \ + } \ + v = strtol(n->data.text.value, &end, 10); \ + if (*end != '\0') { \ + pcb_message(PCB_MSG_ERROR, "Invalid mesh integer: " #name "\n"); \ + return -1; \ + } \ + PCB_DAD_SET_VALUE(me->dlg_hid_ctx, me->name, int_value, v); \ + } \ +} while(0) + +#define LOAD_COORD(name) \ +do { \ + lht_node_t *n = lht_dom_hash_get(root, #name); \ + if (n != NULL) { \ + double v; \ + pcb_bool succ; \ + if (n->type != LHT_TEXT) { \ + pcb_message(PCB_MSG_ERROR, "Invalid mesh item: " #name " should be text\n"); \ + return -1; \ + } \ + v = pcb_get_value(n->data.text.value, NULL, NULL, &succ); \ + if (!succ) { \ + pcb_message(PCB_MSG_ERROR, "Invalid mesh coord: " #name "\n"); \ + return -1; \ + } \ + PCB_DAD_SET_VALUE(me->dlg_hid_ctx, me->name, coord_value, (pcb_coord_t)v); \ + } \ +} while(0) + +#define LOAD_ENUM_VAL(dst, name, node, arr) \ +do { \ + if (node != NULL) { \ + int __found__ = 0, __n__; \ + const char **__a__; \ + if (node->type != LHT_TEXT) { \ + pcb_message(PCB_MSG_ERROR, "Invalid mesh value: " #name " should be text\n"); \ + return -1; \ + } \ + if (strcmp(node->data.text.value, "invalid") == 0) break; \ + for(__n__ = 0, __a__ = arr; *__a__ != NULL; __a__++,__n__++) { \ + if (strcmp(node->data.text.value, *__a__) == 0) { \ + __found__ = 1; \ + break; \ + } \ + } \ + if (!__found__) { \ + pcb_message(PCB_MSG_ERROR, "Invalid mesh value '%s' for " #name "\n", node->data.text.value); \ + return -1; \ + } \ + PCB_DAD_SET_VALUE(me->dlg_hid_ctx, dst, int_value, __n__); \ + } \ +} while(0) + +static int mesh_load_subtree(mesh_dlg_t *me, lht_node_t *root) +{ + lht_node_t *lst, *nd; + + if ((root->type != LHT_HASH) || (strcmp(root->name, "pcb-rnd-mesh-v1") != 0)) { + pcb_message(PCB_MSG_ERROR, "Input is not a valid mesh save - should be a ha:pcb-rnd-mesh subtree\n"); + return -1; + } + + LOAD_COORD(dens_obj); + LOAD_COORD(dens_gap); + LOAD_COORD(min_space); + LOAD_INT(pml); + LOAD_INT(smooth); + LOAD_INT(hor); + LOAD_INT(ver); + LOAD_INT(noimpl); + LOAD_INT(air_top); + LOAD_INT(air_bot); + LOAD_COORD(dens_air); + LOAD_INT(smoothz); + LOAD_COORD(max_air); + LOAD_COORD(def_subs_thick); + LOAD_COORD(def_copper_thick); + LOAD_ENUM_VAL(me->subslines, subslines, lht_dom_hash_get(root, "subslines"), subslines); + + lst = lht_dom_hash_get(root, "boundary"); + if (lst != NULL) { + int n; + if (lst->type != LHT_LIST) { + pcb_message(PCB_MSG_ERROR, "Boundary shall be a list\n"); + return -1; + } + for(n = 0, nd = lst->data.list.first; (n < 6) && (nd != NULL); n++,nd = nd->next) + LOAD_ENUM_VAL(me->bnd[n], boundary, nd, bnds); + } + + return 0; +} +#undef LOAD_INT +#undef LOAD_COORD + +int mesh_load_file(mesh_dlg_t *me, FILE *f) +{ + int c, res; + lht_doc_t *doc; + + doc = lht_dom_init(); + + while((c = fgetc(f)) != EOF) { + lht_err_t err = lht_dom_parser_char(doc, c); + if ((err != LHTE_SUCCESS) && (err != LHTE_STOP)) { + lht_dom_uninit(doc); + return -1; + } + } + res = mesh_load_subtree(me, doc->root); + lht_dom_uninit(doc); + return res; +} + + +static void mesh_add_edge(pcb_mesh_t *mesh, pcb_mesh_dir_t dir, pcb_coord_t crd) +{ + vtc0_append(&mesh->line[dir].edge, crd); +} + +static void mesh_add_result(pcb_mesh_t *mesh, pcb_mesh_dir_t dir, pcb_coord_t crd) +{ + vtc0_append(&mesh->line[dir].result, crd); +} + +static void mesh_add_range(pcb_mesh_t *mesh, pcb_mesh_dir_t dir, pcb_coord_t c1, pcb_coord_t c2, pcb_coord_t dens) +{ + pcb_range_t *r = vtr0_alloc_append(&mesh->line[dir].dens, 1); + r->begin = c1; + r->end = c2; + r->data[0].c = dens; +} + +static void mesh_add_obj(pcb_mesh_t *mesh, pcb_mesh_dir_t dir, pcb_coord_t c1, pcb_coord_t c2, int aligned) +{ + if (aligned) { + mesh_add_edge(mesh, dir, c1 - mesh->dens_obj * 2 / 3); + mesh_add_edge(mesh, dir, c1 + mesh->dens_obj * 1 / 3); + mesh_add_edge(mesh, dir, c2 - mesh->dens_obj * 1 / 3); + mesh_add_edge(mesh, dir, c2 + mesh->dens_obj * 2 / 3); + } + mesh_add_range(mesh, dir, c1, c2, mesh->dens_obj); +} + +/* generate edges and ranges looking at objects on the given layer */ +static int mesh_gen_obj(pcb_mesh_t *mesh, pcb_layer_t *layer, pcb_mesh_dir_t dir) +{ + pcb_data_t *data = layer->parent.data; + pcb_line_t *line; + pcb_line_t *arc; + pcb_poly_t *poly; + pcb_pstk_t *ps; + gdl_iterator_t it; + + padstacklist_foreach(&data->padstack, &it, ps) { + if (pcb_attribute_get(&ps->Attributes, "openems::vport") != 0) { + switch(dir) { + case PCB_MESH_HORIZONTAL: mesh_add_edge(mesh, dir, ps->y); break; + case PCB_MESH_VERTICAL: mesh_add_edge(mesh, dir, ps->x); break; + } + } + } + + linelist_foreach(&layer->Line, &it, line) { + pcb_coord_t x1 = line->Point1.X, y1 = line->Point1.Y, x2 = line->Point2.X, y2 = line->Point2.Y; + int aligned = (x1 == x2) || (y1 == y2); + + switch(dir) { + case PCB_MESH_HORIZONTAL: + if (y1 < y2) + mesh_add_obj(mesh, dir, y1 - line->Thickness/2, y2 + line->Thickness/2, aligned); + else + mesh_add_obj(mesh, dir, y2 - line->Thickness/2, y1 + line->Thickness/2, aligned); + break; + case PCB_MESH_VERTICAL: + if (x1 < x2) + mesh_add_obj(mesh, dir, x1 - line->Thickness/2, x2 + line->Thickness/2, aligned); + else + mesh_add_obj(mesh, dir, x2 - line->Thickness/2, x1 + line->Thickness/2, aligned); + break; + default: break; + } + } + + arclist_foreach(&layer->Arc, &it, arc) { + /* no point in encorcinf 1/3 2/3 rule, just set the range */ + switch(dir) { + case PCB_MESH_HORIZONTAL: mesh_add_range(mesh, dir, arc->BoundingBox.Y1 + arc->Clearance/2, arc->BoundingBox.Y2 - arc->Clearance/2, mesh->dens_obj); break; + case PCB_MESH_VERTICAL: mesh_add_range(mesh, dir, arc->BoundingBox.X1 + arc->Clearance/2, arc->BoundingBox.X2 - arc->Clearance/2, mesh->dens_obj); break; + default: break; + } + } + +TODO("mesh: text") + + polylist_foreach(&layer->Polygon, &it, poly) { + pcb_poly_it_t it; + pcb_polyarea_t *pa; + + for(pa = pcb_poly_island_first(poly, &it); pa != NULL; pa = pcb_poly_island_next(&it)) { + pcb_coord_t x, y; + pcb_pline_t *pl; + int go; + + pl = pcb_poly_contour(&it); + if (pl != NULL) { + pcb_coord_t lx, ly, minx, miny, maxx, maxy; + + pcb_poly_vect_first(&it, &minx, &miny); + maxx = minx; + maxy = miny; + pcb_poly_vect_peek_prev(&it, &lx, &ly); + /* find axis aligned contour edges for the 2/3 1/3 rule */ + for(go = pcb_poly_vect_first(&it, &x, &y); go; go = pcb_poly_vect_next(&it, &x, &y)) { + switch(dir) { + case PCB_MESH_HORIZONTAL: + if (y == ly) { + int sign = (x > lx) ? +1 : -1; + mesh_add_edge(mesh, dir, y - sign * mesh->dens_obj * 2 / 3); + mesh_add_edge(mesh, dir, y + sign * mesh->dens_obj * 1 / 3); + } + break; + case PCB_MESH_VERTICAL: + if (x == lx) { + int sign = (y < ly) ? +1 : -1; + mesh_add_edge(mesh, dir, x - sign * mesh->dens_obj * 2 / 3); + mesh_add_edge(mesh, dir, x + sign * mesh->dens_obj * 1 / 3); + } + break; + default: break; + } + lx = x; + ly = y; + if (x < minx) minx = x; + if (y < miny) miny = y; + if (x > maxx) maxx = x; + if (y > maxy) maxy = y; + } + switch(dir) { + case PCB_MESH_HORIZONTAL: mesh_add_range(mesh, dir, miny, maxy, mesh->dens_obj); break; + case PCB_MESH_VERTICAL: mesh_add_range(mesh, dir, minx, maxx, mesh->dens_obj); break; + default: break; + } + /* Note: holes can be ignored: holes are sorrunded by polygons, the grid is dense over them already */ + } + } + } + return 0; +} + +/* run mesh_gen_obj on all subc layers that match current board mesh layer */ +static int mesh_gen_obj_subc(pcb_mesh_t *mesh, pcb_mesh_dir_t dir) +{ + pcb_data_t *data = mesh->layer->parent.data; + pcb_subc_t *sc; + gdl_iterator_t it; + + subclist_foreach(&data->subc, &it, sc) { + int n; + pcb_layer_t *ly; + for(n = 0, ly = sc->data->Layer; n < sc->data->LayerN; n++,ly++) { + if (pcb_layer_get_real(ly) == mesh->layer) { + if (mesh_gen_obj(mesh, ly, dir) != 0) + return -1; + } + } + } + return 0; +} + +static int cmp_coord(const void *v1, const void *v2) +{ + const pcb_coord_t *c1 = v1, *c2 = v2; + return *c1 < *c2 ? -1 : +1; +} + +static int cmp_range(const void *v1, const void *v2) +{ + const pcb_range_t *c1 = v1, *c2 = v2; + return c1->begin < c2->begin ? -1 : +1; +} + + +typedef struct { + pcb_coord_t min; + pcb_coord_t max; + int found; +} mesh_maybe_t; + +static int cmp_maybe_add(const void *k, const void *v) +{ + const mesh_maybe_t *ctx = k; + const pcb_coord_t *c = v; + + if ((*c >= ctx->min) && (*c <= ctx->max)) + return 0; + if (*c < ctx->min) + return +1; + return -1; +} + +static void mesh_maybe_add_edge(pcb_mesh_t *mesh, pcb_mesh_dir_t dir, pcb_coord_t at, pcb_coord_t dist) +{ + mesh_maybe_t ctx; + pcb_coord_t *c; + ctx.min = at - dist; + ctx.max = at + dist; + ctx.found = 0; + + c = bsearch(&ctx, mesh->line[dir].edge.array, vtc0_len(&mesh->line[dir].edge), sizeof(pcb_coord_t), cmp_maybe_add); + if (c == NULL) { +TODO(": optimization: run a second bsearch and insert instead of this; testing: 45 deg line (won't have axis aligned edge for the 2/3 1/3 rule)") + vtc0_append(&mesh->line[dir].edge, at); + qsort(mesh->line[dir].edge.array, vtc0_len(&mesh->line[dir].edge), sizeof(pcb_coord_t), cmp_coord); + } +} + +static int mesh_sort(pcb_mesh_t *mesh, pcb_mesh_dir_t dir) +{ + size_t n; + pcb_range_t *r; + + if (vtr0_len(&mesh->line[dir].dens) < 1) { + pcb_message(PCB_MSG_ERROR, "There are not enough objects to do the meshing\n"); + return -1; + } + + qsort(mesh->line[dir].edge.array, vtc0_len(&mesh->line[dir].edge), sizeof(pcb_coord_t), cmp_coord); + qsort(mesh->line[dir].dens.array, vtr0_len(&mesh->line[dir].dens), sizeof(pcb_range_t), cmp_range); + + /* merge edges too close */ + for(n = 0; n < vtc0_len(&mesh->line[dir].edge)-1; n++) { + pcb_coord_t c1 = mesh->line[dir].edge.array[n], c2 = mesh->line[dir].edge.array[n+1]; + if (c2 - c1 < mesh->min_space) { + mesh->line[dir].edge.array[n] = (c1 + c2) / 2; + vtc0_remove(&mesh->line[dir].edge, n+1, 1); + } + } + + + /* merge overlapping ranges of the same density */ + for(n = 0; n < vtr0_len(&mesh->line[dir].dens)-1; n++) { + pcb_range_t *r1 = &mesh->line[dir].dens.array[n], *r2 = &mesh->line[dir].dens.array[n+1]; + if (r1->data[0].c != r2->data[0].c) continue; + if (r2->begin < r1->end) { + if (r2->end > r1->end) + r1->end = r2->end; + vtr0_remove(&mesh->line[dir].dens, n+1, 1); + n--; /* make sure to check the next range against the current one, might be overlapping as well */ + } + } + + /* continous ranges: fill in the gaps */ + for(n = 0; n < vtr0_len(&mesh->line[dir].dens)-1; n++) { + pcb_range_t *r1 = &mesh->line[dir].dens.array[n], *r2 = &mesh->line[dir].dens.array[n+1]; + if (r1->end < r2->begin) { + pcb_coord_t my_end = r2->begin; /* the insert will change r2 pointer */ + pcb_range_t *r = vtr0_alloc_insert(&mesh->line[dir].dens, n+1, 1); + r->begin = r1->end; + r->end = my_end; + r->data[0].c = mesh->dens_gap; + n++; /* no need to check the new block */ + } + } + + /* make sure there's a forced mesh line at region transitions */ + for(n = 0; n < vtr0_len(&mesh->line[dir].dens); n++) { + pcb_range_t *r = &mesh->line[dir].dens.array[n]; + if (n == 0) + mesh_maybe_add_edge(mesh, dir, r->begin, mesh->dens_gap); + mesh_maybe_add_edge(mesh, dir, r->end, mesh->dens_gap); + } + + /* continous ranges: start and end */ + r = vtr0_alloc_insert(&mesh->line[dir].dens, 0, 1); + r->begin = 0; + r->end = mesh->line[dir].dens.array[1].begin; + r->data[0].c = mesh->dens_gap; + + r = vtr0_alloc_append(&mesh->line[dir].dens, 1); + r->begin = mesh->line[dir].dens.array[vtr0_len(&mesh->line[dir].dens)-2].end; + r->end = (dir == PCB_MESH_HORIZONTAL) ? PCB->MaxHeight : PCB->MaxWidth; + r->data[0].c = mesh->dens_gap; + + + return 0; +} + +static int cmp_range_at(const void *key_, const void *v_) +{ + const pcb_coord_t *key = key_; + const pcb_range_t *v = v_; + + if ((*key >= v->begin) && (*key <= v->end)) + return 0; + if (*key < v->begin) return -1; + return +1; +} + +static pcb_range_t *mesh_find_range(const vtr0_t *v, pcb_coord_t at, pcb_coord_t *dens, pcb_coord_t *dens_left, pcb_coord_t *dens_right) +{ + pcb_range_t *r; + r = bsearch(&at, v->array, vtr0_len((vtr0_t *)v), sizeof(pcb_range_t), cmp_range_at); + if (dens != NULL) { + if (r == NULL) + return NULL; + *dens = r->data[0].c; + } + if (dens_left != NULL) { + if (r == v->array) + *dens_left = r->data[0].c; + else + *dens_left = r[-1].data[0].c; + } + if (dens_right != NULL) { + if (r == v->array+v->used-1) + *dens_right = r->data[0].c; + else + *dens_right = r[+1].data[0].c; + } + return r; +} + +static int mesh_auto_z(pcb_mesh_t *mesh) +{ + pcb_layergrp_id_t gid; + pcb_coord_t y = 0, ytop = 0, ybottom, top_dens, bottom_dens; + int n, lns, first = 1; + + vtc0_truncate(&mesh->line[PCB_MESH_Z].result, 0); + + lns = num_subslines[ia.dlg[ia.subslines].default_val.int_value]; + if (lns != 0) lns++; + + for(gid = 0; gid < PCB->LayerGroups.len; gid++) { + pcb_layergrp_t *grp = &PCB->LayerGroups.grp[gid]; + if (grp->ltype & PCB_LYT_COPPER) { + /* Ignore the thickness of copper layers for now: copper sheets are modelled in 2d */ + } + else if (grp->ltype & PCB_LYT_SUBSTRATE) { + pcb_coord_t d, t = mesh->def_subs_thick; + double dens = (double)t/(double)lns; + bottom_dens = pcb_round(dens); + if (lns != 0) { + for(n = 0; n <= lns; n++) { + if (n == 0) { + if (first) { + ytop = y; + top_dens = pcb_round(dens); + first = 0; + } + else + continue; + } + d = pcb_round((double)y+dens*(double)n); + mesh_add_result(mesh, PCB_MESH_Z, d); + } + } + else { + if (first) { + ytop = y; + first = 0; + top_dens = mesh->def_subs_thick; + } + mesh_add_result(mesh, PCB_MESH_Z, y); + } + y += t; + ybottom = y; + } + } + + if (ia.dlg[ia.air_top].default_val.int_value) { + if (ia.dlg[ia.smoothz].default_val.int_value) { + mesh_auto_add_smooth(&mesh->line[PCB_MESH_Z].result, ytop - ia.dlg[ia.max_air].default_val.coord_value, ytop, + ia.dlg[ia.dens_air].default_val.coord_value, ia.dlg[ia.dens_air].default_val.coord_value, top_dens); + } + else { + for(y = ytop; y > ytop - ia.dlg[ia.max_air].default_val.coord_value ; y -= ia.dlg[ia.dens_air].default_val.coord_value) + mesh_add_result(mesh, PCB_MESH_Z, y); + } + } + + if (ia.dlg[ia.air_bot].default_val.int_value) { + if (ia.dlg[ia.smoothz].default_val.int_value) { + mesh_auto_add_smooth(&mesh->line[PCB_MESH_Z].result, ybottom, ybottom + ia.dlg[ia.max_air].default_val.coord_value, + bottom_dens, ia.dlg[ia.dens_air].default_val.coord_value, ia.dlg[ia.dens_air].default_val.coord_value); + } + else { + for(y = ybottom; y < ybottom + ia.dlg[ia.max_air].default_val.coord_value ; y += ia.dlg[ia.dens_air].default_val.coord_value) + mesh_add_result(mesh, PCB_MESH_Z, y); + } + } + + mesh->z_bottom_copper = ybottom; + + return 0; +} + +static void mesh_draw_line(pcb_mesh_t *mesh, pcb_mesh_dir_t dir, pcb_coord_t at, pcb_coord_t aux1, pcb_coord_t aux2, pcb_coord_t thick) +{ + if (dir == PCB_MESH_HORIZONTAL) + pcb_line_new(mesh->ui_layer_xy, aux1, at, aux2, at, thick, 0, pcb_no_flags()); + else + pcb_line_new(mesh->ui_layer_xy, at, aux1, at, aux2, thick, 0, pcb_no_flags()); +} + +static void mesh_draw_range(pcb_mesh_t *mesh, pcb_mesh_dir_t dir, pcb_coord_t at1, pcb_coord_t at2, pcb_coord_t aux, pcb_coord_t thick) +{ + if (dir == PCB_MESH_HORIZONTAL) + pcb_line_new(mesh->ui_layer_xy, aux, at1, aux, at2, thick, 0, pcb_no_flags()); + else + pcb_line_new(mesh->ui_layer_xy, at1, aux, at2, aux, thick, 0, pcb_no_flags()); +} + +static void mesh_draw_label(pcb_mesh_t *mesh, pcb_mesh_dir_t dir, pcb_coord_t aux, const char *label) +{ + aux -= PCB_MM_TO_COORD(0.6); + if (dir == PCB_MESH_HORIZONTAL) + pcb_text_new(mesh->ui_layer_xy, pcb_font(PCB, 0, 0), aux, 0, 90, 75, 0, label, pcb_no_flags()); + else + pcb_text_new(mesh->ui_layer_xy, pcb_font(PCB, 0, 0), 0, aux, 0, 75, 0, label, pcb_no_flags()); + +} + +static int mesh_vis_xy(pcb_mesh_t *mesh, pcb_mesh_dir_t dir) +{ + size_t n; + pcb_coord_t end; + + mesh_draw_label(mesh, dir, PCB_MM_TO_COORD(0.1), "object edge"); + + mesh_trace("%s edges:\n", dir == PCB_MESH_HORIZONTAL ? "horizontal" : "vertical"); + for(n = 0; n < vtc0_len(&mesh->line[dir].edge); n++) { + mesh_trace(" %mm", mesh->line[dir].edge.array[n]); + mesh_draw_line(mesh, dir, mesh->line[dir].edge.array[n], PCB_MM_TO_COORD(0.1), PCB_MM_TO_COORD(0.5), PCB_MM_TO_COORD(0.1)); + } + mesh_trace("\n"); + + mesh_draw_label(mesh, dir, PCB_MM_TO_COORD(2), "density ranges"); + + mesh_trace("%s ranges:\n", dir == PCB_MESH_HORIZONTAL ? "horizontal" : "vertical"); + for(n = 0; n < vtr0_len(&mesh->line[dir].dens); n++) { + pcb_range_t *r = &mesh->line[dir].dens.array[n]; + mesh_trace(" [%mm..%mm=%mm]", r->begin, r->end, r->data[0].c); + mesh_draw_range(mesh, dir, r->begin, r->end, PCB_MM_TO_COORD(2)+r->data[0].c/2, PCB_MM_TO_COORD(0.05)); + } + mesh_trace("\n"); + + mesh_trace("%s result:\n", dir == PCB_MESH_HORIZONTAL ? "horizontal" : "vertical"); + end = (dir == PCB_MESH_HORIZONTAL) ? PCB->MaxWidth : PCB->MaxHeight; + for(n = 0; n < vtc0_len(&mesh->line[dir].result); n++) { + mesh_trace(" %mm", mesh->line[dir].result.array[n]); + mesh_draw_line(mesh, dir, mesh->line[dir].result.array[n], 0, end, PCB_MM_TO_COORD(0.03)); + } + mesh_trace("\n"); + + return 0; +} + +static int mesh_vis_z(pcb_mesh_t *mesh) +{ + int n; + pcb_layergrp_id_t gid; + pcb_coord_t x0 = PCB->MaxWidth/15, y0 = PCB->MaxHeight/3, y = y0, y2; + pcb_coord_t xl = PCB->MaxWidth/5; /* board left */ + pcb_coord_t xr = PCB->MaxWidth/5*3; /* board right */ + pcb_coord_t spen = PCB_MM_TO_COORD(0.3), cpen = PCB_MM_TO_COORD(0.2), mpen = PCB_MM_TO_COORD(0.03); + int mag = 2; + + for(gid = 0; gid < PCB->LayerGroups.len; gid++) { + pcb_layergrp_t *grp = &PCB->LayerGroups.grp[gid]; + if (grp->ltype & PCB_LYT_COPPER) { + y2 = y + mesh->def_copper_thick * mag / 2; + pcb_line_new(mesh->ui_layer_z, xr, y2, xr+PCB_MM_TO_COORD(2), y2, cpen, 0, pcb_no_flags()); + pcb_text_new(mesh->ui_layer_z, pcb_font(PCB, 0, 0), xr+PCB_MM_TO_COORD(3), y2 - PCB_MM_TO_COORD(1), 0, 100, 0, grp->name, pcb_no_flags()); + y += mesh->def_copper_thick * mag; + } + else if (grp->ltype & PCB_LYT_SUBSTRATE) { + y2 = y + mesh->def_subs_thick * mag; + pcb_line_new(mesh->ui_layer_z, xl, y, xr, y, spen, 0, pcb_no_flags()); + pcb_line_new(mesh->ui_layer_z, xl, y2, xr, y2, spen, 0, pcb_no_flags()); + pcb_line_new(mesh->ui_layer_z, xl, y, xl, y2, spen, 0, pcb_no_flags()); + pcb_line_new(mesh->ui_layer_z, xr, y, xr, y2, spen, 0, pcb_no_flags()); + y = y2; + } + } + + mesh_trace("Z lines:\n"); + for(n = 0; n < vtc0_len(&mesh->line[PCB_MESH_Z].result); n++) { + pcb_coord_t y = y0+mesh->line[PCB_MESH_Z].result.array[n]*mag; + mesh_trace(" %mm", y); + pcb_line_new(mesh->ui_layer_z, 0, y, PCB->MaxWidth, y, mpen, 0, pcb_no_flags()); + } + mesh_trace("\n"); + return 0; +} + + +static void mesh_auto_add_even(vtc0_t *v, pcb_coord_t c1, pcb_coord_t c2, pcb_coord_t d) +{ + long num = (c2 - c1) / d; + + if (num < 1) + return; + + d = (c2 - c1)/(num+1); + if (d > 0) { + c2 -= d/4; /* open on the right, minus rounding errors */ + for(; c1 < c2; c1 += d) + vtc0_append(v, c1); + } +} + +static pcb_coord_t mesh_auto_add_interp(vtc0_t *v, pcb_coord_t c, pcb_coord_t d1, pcb_coord_t d2, pcb_coord_t dd) +{ + if (dd > 0) { + for(; d1 <= d2; d1 += dd) { + vtc0_append(v, c); + c += d1; + } + return c; + } + else { + for(; d1 <= d2; d1 -= dd) { + c -= d1; + vtc0_append(v, c); + } + return c; + } + +} + +static void mesh_auto_add_smooth(vtc0_t *v, pcb_coord_t c1, pcb_coord_t c2, pcb_coord_t d1, pcb_coord_t d, pcb_coord_t d2) +{ + pcb_coord_t len = c2 - c1, begin = c1, end = c2, glen; + int lines; + + /* ramp up (if there's room) */ + if (d > d1) { + lines = (d / d1) + 0; + if (lines > 0) { + glen = lines * d; + if (glen < len/4) + begin = mesh_auto_add_interp(v, c1, d1, d, (d-d1)/lines); + } + else + begin = c1; + } + + /* ramp down (if there's room) */ + if (d > d2) { + lines = (d / d2) + 0; + if (lines > 0) { + glen = lines * d; + if (glen < len/4) + end = mesh_auto_add_interp(v, c2, d2, d, -(d-d2)/lines); + } + else + end = c2; + } + + /* middle section: linear */ + mesh_auto_add_even(v, begin, end, d); +} + +static int mesh_auto_build(pcb_mesh_t *mesh, pcb_mesh_dir_t dir) +{ + size_t n; + pcb_coord_t c1, c2; + pcb_coord_t d1, d, d2; + + mesh_trace("build:\n"); + + /* left edge, before the first known line */ + if (!mesh->noimpl) { + c1 = 0; + c2 = mesh->line[dir].edge.array[0]; + mesh_find_range(&mesh->line[dir].dens, (c1+c2)/2, &d, &d1, &d2); + if (mesh->smooth) + mesh_auto_add_smooth(&mesh->line[dir].result, c1, c2, d1, d, d2); + else + mesh_auto_add_even(&mesh->line[dir].result, c1, c2, d); + } + + /* normal, between known lines */ + for(n = 0; n < vtc0_len(&mesh->line[dir].edge); n++) { + c1 = mesh->line[dir].edge.array[n]; + c2 = mesh->line[dir].edge.array[n+1]; + + vtc0_append(&mesh->line[dir].result, c1); + + if (c2 - c1 < mesh->dens_obj / 2) + continue; /* don't attempt to insert lines where it won't fit */ + + mesh_find_range(&mesh->line[dir].dens, (c1+c2)/2, &d, &d1, &d2); + if (c2 - c1 < d * 2) + continue; /* don't attempt to insert lines where it won't fit */ + + mesh_trace(" %mm..%mm %mm,%mm,%mm\n", c1, c2, d1, d, d2); + + if (mesh->noimpl) + continue; + + /* place mesh lines between c1 and c2 */ + if (mesh->smooth) + mesh_auto_add_smooth(&mesh->line[dir].result, c1, c2, d1, d, d2); + else + mesh_auto_add_even(&mesh->line[dir].result, c1, c2, d); + } + + /* right edge, after the last known line */ + if (!mesh->noimpl) { + c1 = mesh->line[dir].edge.array[vtc0_len(&mesh->line[dir].edge)-1]; + c2 = (dir == PCB_MESH_HORIZONTAL) ? PCB->MaxHeight : PCB->MaxWidth; + mesh_find_range(&mesh->line[dir].dens, (c1+c2)/2, &d, &d1, &d2); + if (mesh->smooth) + mesh_auto_add_smooth(&mesh->line[dir].result, c1, c2, d1, d, d2); + else + mesh_auto_add_even(&mesh->line[dir].result, c1, c2, d); + + vtc0_append(&mesh->line[dir].result, c2); /* ranges are open from the end, need to manually place the last */ + } + + mesh_trace("\n"); + return 0; +} + +int mesh_auto(pcb_mesh_t *mesh, pcb_mesh_dir_t dir) +{ + vtc0_truncate(&mesh->line[dir].edge, 0); + vtr0_truncate(&mesh->line[dir].dens, 0); + vtc0_truncate(&mesh->line[dir].result, 0); + + if (mesh_gen_obj(mesh, mesh->layer, dir) != 0) + return -1; + if (mesh_gen_obj_subc(mesh, dir) != 0) + return -1; + if (mesh_sort(mesh, dir) != 0) + return -1; + if (mesh_auto_build(mesh, dir) != 0) + return -1; + + if (mesh->ui_layer_xy != NULL) + mesh_vis_xy(mesh, dir); + + return 0; +} + +static void mesh_layer_reset() +{ + static pcb_color_t clr; + + if (clr.str[0] != '#') + pcb_color_load_str(&clr, "#007733"); + + if (mesh.ui_layer_xy != NULL) + pcb_uilayer_free(mesh.ui_layer_xy); + if (mesh.ui_layer_z != NULL) + pcb_uilayer_free(mesh.ui_layer_z); + mesh.ui_layer_xy = pcb_uilayer_alloc(mesh_ui_cookie, "mesh xy", &clr); + mesh.ui_layer_z = pcb_uilayer_alloc(mesh_ui_cookie, "mesh z", &clr); +} + +static void ia_close_cb(void *caller_data, pcb_hid_attr_ev_t ev) +{ + PCB_DAD_FREE(ia.dlg); + memset(&ia, 0, sizeof(ia)); +} + +static char *default_file = NULL; +static void ia_save_cb(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + char *fname = NULL; + FILE *f; + gds_t tmp; + + fname = pcb_gui->fileselect("Save mesh settings...", + "Picks file for saving mesh settings.\n", + default_file, ".lht", NULL, "mesh", PCB_HID_FSD_MAY_NOT_EXIST, NULL); + if (fname == NULL) + return; /* cancel */ + + if (default_file != NULL) { + free(default_file); + default_file = pcb_strdup(fname); + } + + f = pcb_fopen(fname, "w"); + if (f == NULL) { + pcb_message(PCB_MSG_ERROR, "Can not open '%s' for write\n", fname); + return; + } + + gds_init(&tmp); + pcb_mesh_save(&ia, &tmp, NULL); + fprintf(f, "%s", tmp.array); + gds_uninit(&tmp); + free(fname); + fclose(f); +} + +static void ia_load_cb(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + char *fname = NULL; + FILE *f; + gds_t tmp; + + + fname = pcb_gui->fileselect("Load mesh settings...", + "Picks file for loading mesh settings from.\n", + default_file, ".lht", NULL, "mesh", PCB_HID_FSD_READ, NULL); + if (fname == NULL) + return; /* cancel */ + + if (default_file != NULL) { + free(default_file); + default_file = pcb_strdup(fname); + } + + f = pcb_fopen(fname, "r"); + if (f == NULL) { + pcb_message(PCB_MSG_ERROR, "Can not open '%s' for read\n", fname); + return; + } + if (mesh_load_file(&ia, f) != 0) + pcb_message(PCB_MSG_ERROR, "Loading mesh settings from '%s' failed.\n", fname); + fclose(f); +} + +static void ia_gen_cb(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + int n; + mesh_layer_reset(); + mesh.layer = CURRENT; + + dlg2mesh(); + + if (ia.dlg[ia.hor].default_val.int_value) + mesh_auto(&mesh, PCB_MESH_HORIZONTAL); + if (ia.dlg[ia.ver].default_val.int_value) + mesh_auto(&mesh, PCB_MESH_VERTICAL); + + mesh_auto_z(&mesh); + if (mesh.ui_layer_z != NULL) + mesh_vis_z(&mesh); + + free(mesh.ui_name_xy); + free(mesh.ui_layer_xy->name); + mesh.ui_name_xy = pcb_strdup_printf("mesh 0: %s", mesh.layer->name); + mesh.ui_layer_xy->name = pcb_strdup(mesh.ui_name_xy); + pcb_event(PCB_EVENT_LAYERS_CHANGED, NULL); + + pcb_gui->invalidate_all(); +} + +pcb_mesh_t *pcb_mesh_get(const char *name) +{ + return &mesh; +} + +int pcb_mesh_interactive(void) +{ + int n; + pcb_hid_dad_buttons_t clbtn[] = {{"Close", 0}, {NULL, 0}}; + + if (ia.active) + return 0; + + PCB_DAD_BEGIN_VBOX(ia.dlg); + PCB_DAD_BEGIN_HBOX(ia.dlg); + PCB_DAD_BEGIN_VBOX(ia.dlg); + PCB_DAD_COMPFLAG(ia.dlg, PCB_HATF_FRAME); + PCB_DAD_LABEL(ia.dlg, "XY-mesh"); + PCB_DAD_BEGIN_HBOX(ia.dlg); + PCB_DAD_COORD(ia.dlg, ""); + ia.dens_obj = PCB_DAD_CURRENT(ia.dlg); + PCB_DAD_MINMAX(ia.dlg, 0, PCB_MM_TO_COORD(5)); + PCB_DAD_LABEL(ia.dlg, "copper dens."); + PCB_DAD_HELP(ia.dlg, "mesh density over copper"); + PCB_DAD_END(ia.dlg); + + PCB_DAD_BEGIN_HBOX(ia.dlg); + PCB_DAD_COORD(ia.dlg, ""); + ia.dens_gap = PCB_DAD_CURRENT(ia.dlg); + PCB_DAD_MINMAX(ia.dlg, 0, PCB_MM_TO_COORD(5)); + PCB_DAD_LABEL(ia.dlg, "gap dens."); + PCB_DAD_HELP(ia.dlg, "mesh density over gaps"); + PCB_DAD_END(ia.dlg); + + PCB_DAD_BEGIN_HBOX(ia.dlg); + PCB_DAD_COORD(ia.dlg, ""); + ia.min_space = PCB_DAD_CURRENT(ia.dlg); + PCB_DAD_MINMAX(ia.dlg, 0, PCB_MM_TO_COORD(5)); + PCB_DAD_LABEL(ia.dlg, "min. spacing"); + PCB_DAD_HELP(ia.dlg, "minimum distance between mesh lines"); + PCB_DAD_END(ia.dlg); + + PCB_DAD_BEGIN_HBOX(ia.dlg); + PCB_DAD_BOOL(ia.dlg, ""); + ia.smooth = PCB_DAD_CURRENT(ia.dlg); + PCB_DAD_LABEL(ia.dlg, "smooth mesh"); + PCB_DAD_HELP(ia.dlg, "avoid jumps between different mesh densities,\nuse smooth (gradual) changes"); + PCB_DAD_END(ia.dlg); + + PCB_DAD_BEGIN_HBOX(ia.dlg); + PCB_DAD_BOOL(ia.dlg, ""); + ia.hor = PCB_DAD_CURRENT(ia.dlg); + PCB_DAD_LABEL(ia.dlg, "horizontal"); + PCB_DAD_HELP(ia.dlg, "enable adding horizontal mesh lines"); + PCB_DAD_END(ia.dlg); + + PCB_DAD_BEGIN_HBOX(ia.dlg); + PCB_DAD_BOOL(ia.dlg, ""); + ia.ver = PCB_DAD_CURRENT(ia.dlg); + PCB_DAD_LABEL(ia.dlg, "vertical"); + PCB_DAD_HELP(ia.dlg, "enable adding vertical mesh lines"); + PCB_DAD_END(ia.dlg); + + PCB_DAD_BEGIN_HBOX(ia.dlg); + PCB_DAD_BOOL(ia.dlg, ""); + ia.noimpl = PCB_DAD_CURRENT(ia.dlg); + PCB_DAD_LABEL(ia.dlg, "omit implicit"); + PCB_DAD_HELP(ia.dlg, "add only the mesh lines for boundaries,\nomit in-material meshing"); + PCB_DAD_END(ia.dlg); + PCB_DAD_END(ia.dlg); + + PCB_DAD_BEGIN_VBOX(ia.dlg); + PCB_DAD_COMPFLAG(ia.dlg, PCB_HATF_FRAME); + PCB_DAD_LABEL(ia.dlg, "Z-mesh"); + + PCB_DAD_BEGIN_HBOX(ia.dlg); + PCB_DAD_ENUM(ia.dlg, subslines); + ia.subslines = PCB_DAD_CURRENT(ia.dlg); + PCB_DAD_LABEL(ia.dlg, "num in substrate"); + PCB_DAD_HELP(ia.dlg, "number of mesh lines in substrate"); + PCB_DAD_END(ia.dlg); + + PCB_DAD_BEGIN_HBOX(ia.dlg); + PCB_DAD_COORD(ia.dlg, ""); + ia.def_subs_thick = PCB_DAD_CURRENT(ia.dlg); + PCB_DAD_MINMAX(ia.dlg, 0, PCB_MM_TO_COORD(5)); + PCB_DAD_LABEL(ia.dlg, "def. subst. thick"); + PCB_DAD_HELP(ia.dlg, "default substrate thickness\n(for substrate layer groups without\nthickness specified in attribute)"); + PCB_DAD_END(ia.dlg); + + PCB_DAD_BEGIN_HBOX(ia.dlg); + PCB_DAD_COORD(ia.dlg, ""); + ia.def_copper_thick = PCB_DAD_CURRENT(ia.dlg); + PCB_DAD_MINMAX(ia.dlg, 0, PCB_MM_TO_COORD(5)); + PCB_DAD_LABEL(ia.dlg, "def. copper thick"); + PCB_DAD_HELP(ia.dlg, "default copper thickness\n(for copper layer groups without\nthickness specified in attribute)"); + PCB_DAD_END(ia.dlg); + + PCB_DAD_BEGIN_HBOX(ia.dlg); + PCB_DAD_BOOL(ia.dlg, ""); + ia.air_top = PCB_DAD_CURRENT(ia.dlg); + PCB_DAD_LABEL(ia.dlg, "in air top"); + PCB_DAD_HELP(ia.dlg, "add mesh lines in air above the top of the board"); + PCB_DAD_END(ia.dlg); + + PCB_DAD_BEGIN_HBOX(ia.dlg); + PCB_DAD_BOOL(ia.dlg, ""); + ia.air_bot = PCB_DAD_CURRENT(ia.dlg); + PCB_DAD_LABEL(ia.dlg, "in air bottom"); + PCB_DAD_HELP(ia.dlg, "add mesh lines in air below the bottom of the board"); + PCB_DAD_END(ia.dlg); + + + PCB_DAD_BEGIN_HBOX(ia.dlg); + PCB_DAD_COORD(ia.dlg, ""); + ia.dens_air = PCB_DAD_CURRENT(ia.dlg); + PCB_DAD_MINMAX(ia.dlg, 0, PCB_MM_TO_COORD(5)); + PCB_DAD_LABEL(ia.dlg, "dens. air"); + PCB_DAD_HELP(ia.dlg, "mesh line density (spacing) in air"); + PCB_DAD_END(ia.dlg); + + PCB_DAD_BEGIN_HBOX(ia.dlg); + PCB_DAD_COORD(ia.dlg, ""); + ia.max_air = PCB_DAD_CURRENT(ia.dlg); + PCB_DAD_MINMAX(ia.dlg, 0, PCB_MM_TO_COORD(5)); + PCB_DAD_LABEL(ia.dlg, "air thickness"); + PCB_DAD_HELP(ia.dlg, "how far out to mesh in air"); + PCB_DAD_END(ia.dlg); + + PCB_DAD_BEGIN_HBOX(ia.dlg); + PCB_DAD_BOOL(ia.dlg, ""); + ia.smoothz = PCB_DAD_CURRENT(ia.dlg); + PCB_DAD_LABEL(ia.dlg, "smooth mesh"); + PCB_DAD_HELP(ia.dlg, "avoid jumps between different mesh densities,\nuse smooth (gradual) changes"); + PCB_DAD_END(ia.dlg); + + PCB_DAD_END(ia.dlg); + PCB_DAD_END(ia.dlg); + + PCB_DAD_BEGIN_HBOX(ia.dlg); + PCB_DAD_BEGIN_VBOX(ia.dlg); + PCB_DAD_COMPFLAG(ia.dlg, PCB_HATF_FRAME); + PCB_DAD_LABEL(ia.dlg, "Boundary"); + for(n = 0; n < 6; n+=2) { + char name[64]; + sprintf(name, "%s %s", bnd_names[n], bnd_names[n+1]); + PCB_DAD_BEGIN_HBOX(ia.dlg); + PCB_DAD_ENUM(ia.dlg, bnds); + ia.bnd[n] = PCB_DAD_CURRENT(ia.dlg); + PCB_DAD_LABEL(ia.dlg, name); + PCB_DAD_ENUM(ia.dlg, bnds); + ia.bnd[n+1] = PCB_DAD_CURRENT(ia.dlg); + PCB_DAD_END(ia.dlg); + } + + PCB_DAD_BEGIN_HBOX(ia.dlg); + PCB_DAD_LABEL(ia.dlg, "PML cells:"); + PCB_DAD_INTEGER(ia.dlg, ""); + ia.pml = PCB_DAD_CURRENT(ia.dlg); + PCB_DAD_MINMAX(ia.dlg, 0, 32); + PCB_DAD_DEFAULT_NUM(ia.dlg, 8); + PCB_DAD_END(ia.dlg); + PCB_DAD_END(ia.dlg); + + PCB_DAD_BEGIN_VBOX(ia.dlg); + PCB_DAD_BUTTON(ia.dlg, "Save to file"); + PCB_DAD_CHANGE_CB(ia.dlg, ia_save_cb); + PCB_DAD_BUTTON(ia.dlg, "Load from file"); + PCB_DAD_CHANGE_CB(ia.dlg, ia_load_cb); + PCB_DAD_BUTTON(ia.dlg, "Generate mesh!"); + PCB_DAD_CHANGE_CB(ia.dlg, ia_gen_cb); + PCB_DAD_END(ia.dlg); + PCB_DAD_END(ia.dlg); + PCB_DAD_BUTTON_CLOSES(ia.dlg, clbtn); + PCB_DAD_END(ia.dlg); + + PCB_DAD_NEW("mesh", ia.dlg, "mesher", &ia, 0, ia_close_cb); + ia.active = 1; + + mesh2dlg(); + return 0; +} + +const char pcb_acts_mesh[] = "mesh()"; +const char pcb_acth_mesh[] = "generate a mesh for simulation"; +fgw_error_t pcb_act_mesh(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + pcb_mesh_interactive(); + PCB_ACT_IRES(0); + return 0; +} Index: tags/2.1.2/src_plugins/export_openems/mesh.h =================================================================== --- tags/2.1.2/src_plugins/export_openems/mesh.h (nonexistent) +++ tags/2.1.2/src_plugins/export_openems/mesh.h (revision 24813) @@ -0,0 +1,50 @@ +#include "layer.h" +#include "vtc0.h" +#include "vtr0.h" +#include + +typedef struct { + vtc0_t user_line; /* input: lines forced by the user */ + vtr0_t user_dens; /* input: density forced by the user */ + vtc0_t edge; /* input: around object edge - lines that must be in the mesh */ + vtr0_t dens; /* input: density ranges; data[0].c is the target density */ + vtc0_t result; /* resulting line coordinates */ +} pcb_mesh_lines_t; + +typedef enum { + PCB_MESH_HORIZONTAL, /* variable y coord (horizontal lines) */ + PCB_MESH_VERTICAL, /* variable x coord (vertical lines) */ + PCB_MESH_Z, + PCB_MESH_max +} pcb_mesh_dir_t; + +typedef struct { + pcb_layer_t *layer; /* input layer (objects are picked up from this layer) */ + pcb_layer_t *ui_layer_xy, *ui_layer_z; /* optional UI layers to draw the mesh on */ + char *ui_name_xy; /* name of the UI layer */ + pcb_coord_t dens_obj, dens_gap; /* target density: distance between mesh lines above objects and above gaps */ + pcb_coord_t min_space; /* make sure there's always at least this much space between two mesh lines */ + pcb_coord_t def_subs_thick; /* default substrate thickness */ + pcb_coord_t def_copper_thick; /* default copper thickness */ + pcb_mesh_lines_t line[PCB_MESH_max]; /* actual lines of the mesh */ + const char *bnd[6]; /* temporary: boundary conditions */ + pcb_coord_t z_bottom_copper; /* z coordinate of the bottom copper layer, along the z-mesh (0 is the top copper) */ + int pml; /* add pml cells around the exterior of the existing mesh of "perfectly matched" impedance */ + int subslines; /* number of mesh lines in substrate (z) */ + pcb_coord_t dens_air; /* mesh line density (spacing) in air */ + pcb_coord_t max_air; /* how far out to mesh in air */ + unsigned hor:1; /* enable adding horizontal mesh lines */ + unsigned ver:1; /* enable adding vertical mesh lines */ + unsigned smooth:1; /* if set, avoid jumps in the meshing by gradually changing meshing distance: x and y direction */ + unsigned smoothz:1; /* if set, avoid jumps in the meshing by gradually changing meshing distance: z direction */ + unsigned air_top:1; /* add mesh lines in air above the top of the board */ + unsigned air_bot:1; /* add mesh lines in air below the top of the board */ + unsigned noimpl:1; /* when set, do not add extra implicit mesh lines, keep the explicit ones only */ +} pcb_mesh_t; + +extern const char pcb_acts_mesh[]; +extern const char pcb_acth_mesh[]; +fgw_error_t pcb_act_mesh(fgw_arg_t *res, int oargc, fgw_arg_t *oargv); + +/* Get one of the configured meshes */ +pcb_mesh_t *pcb_mesh_get(const char *name); Index: tags/2.1.2/src_plugins/export_openscad/Makefile =================================================================== --- tags/2.1.2/src_plugins/export_openscad/Makefile (nonexistent) +++ tags/2.1.2/src_plugins/export_openscad/Makefile (revision 24813) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_export_openscad + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/2.1.2/src_plugins/export_openscad/Plug.tmpasm =================================================================== --- tags/2.1.2/src_plugins/export_openscad/Plug.tmpasm (nonexistent) +++ tags/2.1.2/src_plugins/export_openscad/Plug.tmpasm (revision 24813) @@ -0,0 +1,10 @@ +put /local/pcb/mod {export_openscad} +put /local/pcb/mod/OBJS [@ + $(PLUGDIR)/export_openscad/export_openscad.o +@] + +switch /local/pcb/export_openscad/controls + case {buildin} include /local/pcb/tmpasm/buildin; end; + case {plugin} include /local/pcb/tmpasm/plugin; end; + case {disable} include /local/pcb/tmpasm/disable; end; +end Index: tags/2.1.2/src_plugins/export_openscad/export_openscad.c =================================================================== --- tags/2.1.2/src_plugins/export_openscad/export_openscad.c (nonexistent) +++ tags/2.1.2/src_plugins/export_openscad/export_openscad.c (revision 24813) @@ -0,0 +1,705 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2017 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "config.h" +#include "conf_core.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "compat_misc.h" +#include "board.h" +#include "data.h" +#include "draw.h" +#include "error.h" +#include "layer.h" +#include "layer_vis.h" +#include "math_helper.h" +#include "misc_util.h" +#include "plugins.h" +#include "safe_fs.h" +#include "obj_pstk_inlines.h" +#include "funchash_core.h" + +#include "hid.h" +#include "hid_nogui.h" +#include "hid_draw_helpers.h" + +#include "hid_init.h" +#include "actions.h" +#include "hid_attrib.h" +#include "hid_color.h" +#include "hid_cam.h" + + +static pcb_hid_t openscad_hid; + +const char *openscad_cookie = "openscad HID"; + + +typedef struct hid_gc_s { + pcb_core_gc_t core_gc; + pcb_hid_t *me_pointer; + pcb_cap_style_t cap; + int width; +} hid_gc_s; + +static FILE *f = NULL; +static unsigned layer_open; +static double layer_thickness = 0.01, effective_layer_thickness; +static gds_t layer_group_calls, model_calls; +static const char *scad_group_name; +static int scad_group_level; +static const char *scad_group_color; +static int scad_layer_cnt; +static vti0_t scad_comp; + +pcb_hid_attribute_t openscad_attribute_list[] = { + /* other HIDs expect this to be first. */ + +/* %start-doc options "93 DXF Options" +@ftable @code +@item --outfile +Name of the file to be exported to. Can contain a path. +@end ftable +%end-doc +*/ + {"outfile", "Graphics output file", + PCB_HATT_STRING, 0, 0, {0, 0, 0}, 0, 0}, +#define HA_openscadfile 0 + + {"copper", "enable exporting outer copper layers", + PCB_HATT_BOOL, 0, 0, {1, 0, 0}, 0, 0}, +#define HA_copper 1 + + {"silk", "enable exporting silk layers", + PCB_HATT_BOOL, 0, 0, {1, 0, 0}, 0, 0}, +#define HA_silk 2 + + {"mask", "enable exporting mask layers", + PCB_HATT_BOOL, 0, 0, {1, 0, 0}, 0, 0}, +#define HA_mask 3 + + {"models", "enable searching and inserting model files", + PCB_HATT_BOOL, 0, 0, {1, 0, 0}, 0, 0}, +#define HA_models 4 + + {"drill", "enable drilling holes", + PCB_HATT_BOOL, 0, 0, {1, 0, 0}, 0, 0}, +#define HA_drill 5 +}; + +#define NUM_OPTIONS (sizeof(openscad_attribute_list)/sizeof(openscad_attribute_list[0])) + +#include "scad_draw.c" +#include "scad_models.c" + +PCB_REGISTER_ATTRIBUTES(openscad_attribute_list, openscad_cookie) + +static pcb_hid_attr_val_t openscad_values[NUM_OPTIONS]; + +static pcb_hid_attribute_t *openscad_get_export_options(int *n) +{ + const char *suffix = ".scad"; + + if ((PCB != NULL) && (openscad_attribute_list[HA_openscadfile].default_val.str_value == NULL)) + pcb_derive_default_filename(PCB->Filename, &openscad_attribute_list[HA_openscadfile], suffix); + + if (n) + *n = NUM_OPTIONS; + return openscad_attribute_list; +} + +void openscad_hid_export_to_file(FILE * the_file, pcb_hid_attr_val_t * options) +{ + static int saved_layer_stack[PCB_MAX_LAYER]; + pcb_hid_expose_ctx_t ctx; + + ctx.view.X1 = 0; + ctx.view.Y1 = 0; + ctx.view.X2 = PCB->MaxWidth; + ctx.view.Y2 = PCB->MaxHeight; + + f = the_file; + + memcpy(saved_layer_stack, pcb_layer_stack, sizeof(pcb_layer_stack)); + + conf_force_set_bool(conf_core.editor.thin_draw, 0); + conf_force_set_bool(conf_core.editor.thin_draw_poly, 0); +/* conf_force_set_bool(conf_core.editor.check_planes, 0);*/ + conf_force_set_bool(conf_core.editor.show_solder_side, 0); + + pcb_hid_expose_all(&openscad_hid, &ctx, NULL); + + conf_update(NULL, -1); /* restore forced sets */ +} + +static void scad_close_layer() +{ + if (layer_open) { + fprintf(f, " }\n"); + fprintf(f, "}\n\n"); + layer_open = 0; + } +} + +static void scad_dump_comp(void) +{ + int n, closes = 0; + +/* + a layer list like this: +4 -5 -0 +6 -7 + becomes script like this: + + difference() + { + union() { + difference() { + 4 + 5 + 0 + } + 6 + } + 7 + } + +*/ + + /* add an union or difference on polarity change */ + for(n = vti0_len(&scad_comp)-2; n >= 0; n--) { + int p1 = (scad_comp.array[n]) > 0, p2 = (scad_comp.array[n+1] > 0); + if (p2 && !p1) { + fprintf(f, " union() {\n"); + closes++; + } + if (!p2 && p1) { + fprintf(f, " difference() {\n"); + closes++; + } + } + + /* list layer calls, add a close on polarity change */ + for(n = 0; n < vti0_len(&scad_comp); n++) { + int id = scad_comp.array[n], is_pos = id > 0; + if (id < 0) + id = -id; + fprintf(f, " layer_%s_%s_%d();\n", scad_group_name, is_pos ? "pos" : "neg", id); + if ((n > 0) && (n < vti0_len(&scad_comp)-1)) { + int id2 = scad_comp.array[n+1]; + int p1 = is_pos, p2 = (id2 > 0); + if (p2 != p1) { + fprintf(f, "}\n"); + closes--; + } + } + } + + /* the first open needs to be closed manually */ + if (closes) + fprintf(f, "}\n"); +} + +static void scad_close_layer_group() +{ + if (scad_group_name != NULL) { + fprintf(f, "module layer_group_%s() {\n", scad_group_name); + scad_dump_comp(); + fprintf(f, "}\n\n"); + + pcb_append_printf(&layer_group_calls, " layer_group_%s();\n", scad_group_name); + scad_group_name = NULL; + scad_group_color = NULL; + scad_group_level = 0; + vti0_truncate(&scad_comp, 0); + } +} + +static void scad_new_layer(int is_pos) +{ + double h; + scad_layer_cnt++; + + if (is_pos) + vti0_append(&scad_comp, scad_layer_cnt); + else + vti0_append(&scad_comp, -scad_layer_cnt); + + scad_close_layer(); + + if (is_pos) { + effective_layer_thickness = layer_thickness; + if (scad_group_level > 0) + h = 0.8+((double)scad_group_level*1.1) * effective_layer_thickness; + else + h = -0.8+((double)scad_group_level*1.1) * effective_layer_thickness; + } + else { + double mult = 2.0; + effective_layer_thickness = layer_thickness * mult; + if (scad_group_level > 0) + h = 0.8+((double)scad_group_level*1.1) * layer_thickness; + else + h = -0.8+((double)scad_group_level*1.1) * layer_thickness; + h -= effective_layer_thickness/2.0; + effective_layer_thickness+=1.0; + } + fprintf(f, "module layer_%s_%s_%d() {\n", scad_group_name, is_pos ? "pos" : "neg", scad_layer_cnt); + fprintf(f, " color([%s])\n", scad_group_color); + fprintf(f, " translate([0,0,%f]) {\n", h); + layer_open = 1; + +} + + +static void scad_new_layer_group(const char *group_name, int level, const char *color) +{ + scad_close_layer_group(); + + scad_group_name = group_name; + scad_group_level = level; + scad_group_color = color; + scad_group_level = level; +} + + +static void openscad_do_export(pcb_hid_attr_val_t * options) +{ + const char *filename; + int save_ons[PCB_MAX_LAYER + 2]; + int i; + + if (!options) { + openscad_get_export_options(0); + for (i = 0; i < NUM_OPTIONS; i++) + openscad_values[i] = openscad_attribute_list[i].default_val; + options = openscad_values; + } + + filename = options[HA_openscadfile].str_value; + if (!filename) + filename = "pcb.openscad"; + + f = pcb_fopen(filename, "wb"); + if (!f) { + perror(filename); + return; + } + + pcb_hid_save_and_show_layer_ons(save_ons); + + scad_layer_cnt = 0; + scad_draw_primitives(); + + if (scad_draw_outline() < 0) + return; + + gds_init(&layer_group_calls); + gds_init(&model_calls); + vti0_init(&scad_comp); + + if (openscad_attribute_list[HA_models].default_val.int_value) + scad_insert_models(); + + openscad_hid_export_to_file(f, options); + scad_close_layer_group(); + + if (openscad_attribute_list[HA_drill].default_val.int_value) + scad_draw_drills(); + + scad_draw_finish(); + + pcb_hid_restore_layer_ons(save_ons); + + gds_uninit(&layer_group_calls); + gds_uninit(&model_calls); + vti0_uninit(&scad_comp); + + fclose(f); + f = NULL; +} + +static int openscad_parse_arguments(int *argc, char ***argv) +{ + pcb_hid_register_attributes(openscad_attribute_list, sizeof(openscad_attribute_list) / sizeof(openscad_attribute_list[0]), openscad_cookie, 0); + return pcb_hid_parse_command_line(argc, argv); +} + + + +static int openscad_set_layer_group(pcb_layergrp_id_t group, const char *purpose, int purpi, pcb_layer_id_t layer, unsigned int flags, int is_empty, pcb_xform_t **xform) +{ + if (flags & PCB_LYT_UI) + return 0; + + if (flags & PCB_LYT_INVIS) + return 0; + + if (PCB_LAYER_IS_ROUTE(flags, purpi)) { + return 0; + } + + if (PCB_LAYER_IS_DRILL(flags, purpi)) + return 0; + + if (flags & PCB_LYT_MASK) { + if (!openscad_attribute_list[HA_mask].default_val.int_value) + return 0; + if (flags & PCB_LYT_TOP) { + scad_new_layer_group("top_mask", +2, "0,0.7,0,0.5"); + return 1; + } + if (flags & PCB_LYT_BOTTOM) { + scad_new_layer_group("bottom_mask", -2, "0,0.7,0,0.5"); + return 1; + } + } + + if (flags & PCB_LYT_SILK) { + if (!openscad_attribute_list[HA_silk].default_val.int_value) + return 0; + if (flags & PCB_LYT_TOP) { + scad_new_layer_group("top_silk", +3, "0,0,0"); + return 1; + } + if (flags & PCB_LYT_BOTTOM) { + scad_new_layer_group("bottom_silk", -3, "0,0,0"); + return 1; + } + } + + if (flags & PCB_LYT_COPPER) { + if (!openscad_attribute_list[HA_copper].default_val.int_value) + return 0; + if (flags & PCB_LYT_TOP) { + scad_new_layer_group("top_copper", +1, "1,0.4,0.2"); + return 1; + } + if (flags & PCB_LYT_BOTTOM) { + scad_new_layer_group("bottom_copper", -1, "1,0.4,0.2"); + return 1; + } + } + + return 0; +} + + +static pcb_hid_gc_t openscad_make_gc(void) +{ + pcb_hid_gc_t rv = (pcb_hid_gc_t) calloc(sizeof(hid_gc_s), 1); + rv->me_pointer = &openscad_hid; + return rv; +} + +static void openscad_destroy_gc(pcb_hid_gc_t gc) +{ + free(gc); +} + +static void openscad_set_drawing_mode(pcb_composite_op_t op, pcb_bool direct, const pcb_box_t *screen) +{ + switch(op) { + case PCB_HID_COMP_RESET: + break; + + case PCB_HID_COMP_POSITIVE: + case PCB_HID_COMP_POSITIVE_XOR: + scad_new_layer(1); + break; + case PCB_HID_COMP_NEGATIVE: + scad_new_layer(0); + break; + + case PCB_HID_COMP_FLUSH: + scad_close_layer(); + break; + } +} + +static void openscad_set_color(pcb_hid_gc_t gc, const pcb_color_t *name) +{ +} + +static void openscad_set_line_cap(pcb_hid_gc_t gc, pcb_cap_style_t style) +{ + gc->cap = style; +} + +static void openscad_set_line_width(pcb_hid_gc_t gc, pcb_coord_t width) +{ + gc->width = width; +} + + +static void openscad_set_draw_xor(pcb_hid_gc_t gc, int xor_) +{ + ; +} + +#define fix_rect_coords() \ + if (x1 > x2) {\ + pcb_coord_t t = x1; \ + x1 = x2; \ + x2 = t; \ + } \ + if (y1 > y2) { \ + pcb_coord_t t = y1; \ + y1 = y2; \ + y2 = t; \ + } + + +static void openscad_fill_rect(pcb_hid_gc_t gc, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2) +{ + TRX(x1); TRY(y1); + TRX(x2); TRY(y2); + + fix_rect_coords(); + pcb_fprintf(f, " pcb_fill_rect(%mm, %mm, %mm, %mm, %f, %f);\n", + x1, y1, x2, y2, 0.0, effective_layer_thickness); +} + +static void openscad_draw_line(pcb_hid_gc_t gc, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2) +{ + double length, angle; + const char *cap_style; + + TRX(x1); TRY(y1); + TRX(x2); TRY(y2); + + length = pcb_distance(x1, y1, x2, y2); + angle = atan2((double)y2-y1, (double)x2-x1); + + if (gc->cap == pcb_cap_square) + cap_style = "sc"; + else + cap_style = "rc"; + + pcb_fprintf(f, " pcb_line_%s(%mm, %mm, %mm, %f, %mm, %f);\n", cap_style, + x1, y1, (pcb_coord_t)pcb_round(length), angle * PCB_RAD_TO_DEG, gc->width, effective_layer_thickness); +} + +static void openscad_draw_rect(pcb_hid_gc_t gc, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2) +{ + TRX(x1); TRY(y1); + TRX(x2); TRY(y2); + + fix_rect_coords(); + openscad_draw_line(gc, x1, y1, x2, y1); + openscad_draw_line(gc, x2, y1, x2, y2); + openscad_draw_line(gc, x2, y2, x1, y2); + openscad_draw_line(gc, x1, y2, x1, y1); +} + +static void openscad_draw_arc(pcb_hid_gc_t gc, pcb_coord_t cx, pcb_coord_t cy, pcb_coord_t width, pcb_coord_t height, pcb_angle_t start_angle, pcb_angle_t delta_angle) +{ + double a, step = delta_angle/10.0, end_angle = start_angle + delta_angle; + int first; + pcb_coord_t lx, ly, x, y; + + if (step < 1) + step = 1; + if (step > 10) + step = 10; + + /* only recent versions support angle for rotate_extrude(), so use line approximation for now */ + fprintf(f, " // line-approx arc %f .. %f by %f\n", start_angle, end_angle, step); + + for(first = 1, a = start_angle; step > 0 ? (a < end_angle) : (a > end_angle); a += step) { + x = (double)cx + cos((180-a) / PCB_RAD_TO_DEG) * (double)width; + y = (double)cy + sin((180-a) / PCB_RAD_TO_DEG) * (double)height; + if (!first) { + fprintf(f, "\t"); + openscad_draw_line(gc, lx, ly, x, y); + } + lx = x; + ly = y; + first = 0; + } + x = (double)cx + cos((180 - end_angle) / PCB_RAD_TO_DEG) * (double)width; + y = (double)cy + sin((180 - end_angle) / PCB_RAD_TO_DEG) * (double)height; + fprintf(f, "\t"); + openscad_draw_line(gc, lx, ly, x, y); +} + +static void openscad_fill_circle(pcb_hid_gc_t gc, pcb_coord_t cx, pcb_coord_t cy, pcb_coord_t radius) +{ + TRX(cx); TRY(cy); + + pcb_fprintf(f, " pcb_fcirc(%mm, %mm, %mm, %f);\n", cx, cy, radius, effective_layer_thickness); +} + +static void openscad_fill_polygon_offs(pcb_hid_gc_t gc, int n_coords, pcb_coord_t *x, pcb_coord_t *y, pcb_coord_t dx, pcb_coord_t dy) +{ + int n; + fprintf(f, " pcb_fill_poly(["); + for(n = 0; n < n_coords-1; n++) + pcb_fprintf(f, "[%mm,%mm],", TRX_(x[n]+dx), TRY_(y[n]+dy)); + pcb_fprintf(f, "[%mm,%mm]], %f);\n", TRX_(x[n]+dx), TRY_(y[n]+dy), effective_layer_thickness); +} + +static void openscad_fill_polygon(pcb_hid_gc_t gc, int n_coords, pcb_coord_t *x, pcb_coord_t *y) +{ + openscad_fill_polygon_offs(gc, n_coords, x, y, 0, 0); +} + +static void openscad_calibrate(double xval, double yval) +{ + pcb_message(PCB_MSG_ERROR, "openscad_calibrate() not implemented"); + return; +} + +static void openscad_set_crosshair(pcb_coord_t x, pcb_coord_t y, int a) +{ +} + +static int openscad_usage(const char *topic) +{ + fprintf(stderr, "\nopenscad exporter command line arguments:\n\n"); + pcb_hid_usage(openscad_attribute_list, sizeof(openscad_attribute_list) / sizeof(openscad_attribute_list[0])); + fprintf(stderr, "\nUsage: pcb-rnd [generic_options] -x openscad [openscad options] foo.pcb\n\n"); + return 0; +} + + +static const char pcb_acts_scad_export_poly[] = "ScadExportPoly(filename)\n"; +static const char pcb_acth_scad_export_poly[] = "exports all selected polygons to an openscad script; only the outmost contour of each poly is exported"; +static fgw_error_t pcb_act_scad_export_poly(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + FILE *f; + const char *name; + + PCB_ACT_CONVARG(1, FGW_STR, scad_export_poly, name = argv[1].val.str); + + f = pcb_fopen(name, "w"); + if (f == NULL) { + pcb_message(PCB_MSG_ERROR, "Failed to open %s for writing\n", name); + PCB_ACT_IRES(-1); + return 0; + } + + + PCB_POLY_ALL_LOOP(PCB->Data); { + pcb_poly_it_t it; + pcb_polyarea_t *pa; + + if (!PCB_FLAG_TEST(PCB_FLAG_SELECTED, polygon)) + continue; + + /* iterate over all islands of a polygon */ + for(pa = pcb_poly_island_first(polygon, &it); pa != NULL; pa = pcb_poly_island_next(&it)) { + pcb_coord_t x, y; + pcb_pline_t *pl; + int go; + + /* check if we have a contour for the given island */ + pl = pcb_poly_contour(&it); + if (pl != NULL) { + int cnt; + + fprintf(f, "polygon(["); + /* iterate over the vectors of the contour */ + for(go = pcb_poly_vect_first(&it, &x, &y),cnt = 0; go; go = pcb_poly_vect_next(&it, &x, &y), cnt++) + pcb_fprintf(f, "%s[%mm,%mm]", (cnt > 0 ? "," : ""), x, y); + fprintf(f, "]);\n"); + } + } + } PCB_ENDALL_LOOP; + + fclose(f); + + PCB_ACT_IRES(0); + return 0; +} + + +static pcb_action_t scad_action_list[] = { + {"ExportScadPoly", pcb_act_scad_export_poly, pcb_acth_scad_export_poly, pcb_acts_scad_export_poly} +}; + +PCB_REGISTER_ACTIONS(scad_action_list, openscad_cookie) + +#include "dolists.h" + +int pplg_check_ver_export_openscad(int ver_needed) { return 0; } + +void pplg_uninit_export_openscad(void) +{ + pcb_hid_remove_attributes_by_cookie(openscad_cookie); + pcb_remove_actions_by_cookie(openscad_cookie); +} + +int pplg_init_export_openscad(void) +{ + PCB_API_CHK_VER; + + memset(&openscad_hid, 0, sizeof(pcb_hid_t)); + + pcb_hid_nogui_init(&openscad_hid); + pcb_dhlp_draw_helpers_init(&openscad_hid); + + openscad_hid.struct_size = sizeof(pcb_hid_t); + openscad_hid.name = "openscad"; + openscad_hid.description = "OpenSCAD exporter"; + openscad_hid.exporter = 1; + + openscad_hid.get_export_options = openscad_get_export_options; + openscad_hid.do_export = openscad_do_export; + openscad_hid.parse_arguments = openscad_parse_arguments; + openscad_hid.set_layer_group = openscad_set_layer_group; + openscad_hid.make_gc = openscad_make_gc; + openscad_hid.destroy_gc = openscad_destroy_gc; + openscad_hid.set_drawing_mode = openscad_set_drawing_mode; + openscad_hid.set_color = openscad_set_color; + openscad_hid.set_line_cap = openscad_set_line_cap; + openscad_hid.set_line_width = openscad_set_line_width; + openscad_hid.set_draw_xor = openscad_set_draw_xor; + openscad_hid.draw_line = openscad_draw_line; + openscad_hid.draw_arc = openscad_draw_arc; + openscad_hid.draw_rect = openscad_draw_rect; + openscad_hid.fill_circle = openscad_fill_circle; + openscad_hid.fill_polygon = openscad_fill_polygon; + openscad_hid.fill_polygon_offs = openscad_fill_polygon_offs; + openscad_hid.fill_rect = openscad_fill_rect; + openscad_hid.calibrate = openscad_calibrate; + openscad_hid.set_crosshair = openscad_set_crosshair; + + openscad_hid.usage = openscad_usage; + + pcb_hid_register_hid(&openscad_hid); + + PCB_REGISTER_ACTIONS(scad_action_list, openscad_cookie) + + return 0; +} Index: tags/2.1.2/src_plugins/export_openscad/export_openscad.pup =================================================================== --- tags/2.1.2/src_plugins/export_openscad/export_openscad.pup (nonexistent) +++ tags/2.1.2/src_plugins/export_openscad/export_openscad.pup (revision 24813) @@ -0,0 +1,10 @@ +$class export +$short openscad pcb_exporter +$long Export openscad +$state WIP +$fmt-native no +$fmt-feature-w export a colored 3D model as an openscad script +$package export +dep lib_polyhelp +default buildin +autoload 1 Index: tags/2.1.2/src_plugins/export_openscad/scad_draw.c =================================================================== --- tags/2.1.2/src_plugins/export_openscad/scad_draw.c (nonexistent) +++ tags/2.1.2/src_plugins/export_openscad/scad_draw.c (revision 24813) @@ -0,0 +1,171 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2017 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "../lib_polyhelp/topoly.h" +#include "plug_io.h" + +#define TRX_(x) (x) +#define TRY_(y) (PCB->MaxHeight - (y)) + +#define TRX(x) +#define TRY(y) y = TRY_(y) + +static void scad_draw_primitives(void) +{ + fprintf(f, "// Round cap line\n"); + fprintf(f, "module pcb_line_rc(x1, y1, length, angle, width, thick) {\n"); + fprintf(f, " translate([x1,y1,0]) {\n"); + fprintf(f, " rotate([0,0,angle]) {\n"); + fprintf(f, " translate([length/2, 0, 0])\n"); + fprintf(f, " cube([length, width, thick], center=true);\n"); + fprintf(f, " cylinder(r=width/2, h=thick, center=true, $fn=30);\n"); + fprintf(f, " translate([length, 0, 0])\n"); + fprintf(f, " cylinder(r=width/2, h=thick, center=true, $fn=30);\n"); + fprintf(f, " }\n"); + fprintf(f, " }\n"); + fprintf(f, "}\n"); + + fprintf(f, "// Square cap line\n"); + fprintf(f, "module pcb_line_sc(x1, y1, length, angle, width, thick) {\n"); + fprintf(f, " translate([x1,y1,0]) {\n"); + fprintf(f, " rotate([0,0,angle]) {\n"); + fprintf(f, " translate([length/2, 0, 0])\n"); + fprintf(f, " cube([length + width, width, thick], center=true);\n"); + fprintf(f, " }\n"); + fprintf(f, " }\n"); + fprintf(f, "}\n"); + + fprintf(f, "// filled rectangle\n"); + fprintf(f, "module pcb_fill_rect(x1, y1, x2, y2, angle, thick) {\n"); + fprintf(f, " translate([(x1+x2)/2,(y1+y2)/2,0])\n"); + fprintf(f, " rotate([0,0,angle])\n"); + fprintf(f, " cube([x2-x1, y2-y1, thick], center=true);\n"); + fprintf(f, "}\n"); + + fprintf(f, "// filled polygon\n"); + fprintf(f, "module pcb_fill_poly(coords, thick) {\n"); + fprintf(f, " linear_extrude(height=thick)\n"); + fprintf(f, " polygon(coords);\n"); + fprintf(f, "}\n"); + + fprintf(f, "// filled circle\n"); + fprintf(f, "module pcb_fcirc(x1, y1, radius, thick) {\n"); + fprintf(f, " translate([x1,y1,0])\n"); + fprintf(f, " cylinder(r=radius, h=thick, center=true, $fn=30);\n"); + fprintf(f, "}\n"); +} + +static int scad_draw_outline(void) +{ + pcb_any_obj_t *start = pcb_topoly_find_1st_outline(PCB); + pcb_poly_t *poly; + int n; + + if (start == NULL) { + poly = pcb_poly_alloc(PCB->Data->Layer); + pcb_poly_point_new(poly, 0, 0); + pcb_poly_point_new(poly, PCB->MaxWidth, 0); + pcb_poly_point_new(poly, PCB->MaxWidth, PCB->MaxHeight); + pcb_poly_point_new(poly, 0, PCB->MaxHeight); + } + else { + poly = pcb_topoly_conn(PCB, start, PCB_TOPOLY_FLOATING); + if (poly == NULL) + return -1; + } + + fprintf(f, "module pcb_outline() {\n"); + fprintf(f, " polygon([\n\t\t"); + /* we need the as-drawn polygon and we know there are no holes */ + for(n = 0; n < poly->PointN; n++) + pcb_fprintf(f, "[%mm,%mm]%s", TRX_(poly->Points[n].X), TRY_(poly->Points[n].Y), ((n < (poly->PointN-1)) ? "," : "\n")); + fprintf(f, " ]);\n"); + fprintf(f, "}\n"); + + pcb_poly_free(poly); + return 0; +} + +static void scad_draw_pstk(const pcb_pstk_t *ps) +{ + pcb_pstk_proto_t *proto = pcb_pstk_get_proto(ps); + + if (proto == NULL) { + pcb_io_incompat_save(ps->parent.data, (pcb_any_obj_t *)ps, "padstack-proto", "failed to retrieve padstack prototype", "internal pcb-rnd error, please file a bugreport"); + return; + } + +TODO("padstack: this ignores bbvias") +TODO("slot: this ignores slots") + if (proto->hdia > 0) { + pcb_fprintf(f, " translate([%mm,%mm,0])\n", TRX_(ps->x), TRY_(ps->y)); + pcb_fprintf(f, " cylinder(r=%mm, h=4, center=true, $fn=30);\n", proto->hdia/2); + } +} + +static void scad_draw_drills(void) +{ + pcb_rtree_it_t it; + pcb_box_t *obj; + + fprintf(f, "module pcb_drill() {\n"); + + for(obj = pcb_r_first(PCB->Data->padstack_tree, &it); obj != NULL; obj = pcb_r_next(&it)) + scad_draw_pstk((pcb_pstk_t *)obj); + pcb_r_end(&it); + + fprintf(f, "}\n"); +} + +static void scad_draw_finish() +{ + fprintf(f, "module pcb_board_main() {\n"); + fprintf(f, " translate ([0, 0, -0.8])\n"); + fprintf(f, " linear_extrude(height=1.6)\n"); + fprintf(f, " pcb_outline();\n"); + fprintf(f, "%s", layer_group_calls.array); + fprintf(f, "}\n"); + fprintf(f, "\n"); + + fprintf(f, "module pcb_board() {\n"); + fprintf(f, " intersection() {\n"); + fprintf(f, " translate ([0, 0, -4])\n"); + fprintf(f, " linear_extrude(height=8)\n"); + fprintf(f, " pcb_outline();\n"); + fprintf(f, " union() {\n"); + fprintf(f, " difference() {\n"); + fprintf(f, " pcb_board_main();\n"); + if (openscad_attribute_list[HA_drill].default_val.int_value) + fprintf(f, " pcb_drill();\n"); + fprintf(f, " }\n"); + fprintf(f, " }\n"); + fprintf(f, " }\n"); + fprintf(f, "%s", model_calls.array); + fprintf(f, "}\n"); + fprintf(f, "\n"); + + fprintf(f, "pcb_board();\n"); +} Index: tags/2.1.2/src_plugins/export_openscad/scad_models.c =================================================================== --- tags/2.1.2/src_plugins/export_openscad/scad_models.c (nonexistent) +++ tags/2.1.2/src_plugins/export_openscad/scad_models.c (revision 24813) @@ -0,0 +1,135 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2017 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "conf_core.h" + +static void scad_insert_model(htsp_t *models, const char *name, pcb_coord_t x0, pcb_coord_t y0, double rot, int on_bottom, const char *transf, const char *param) +{ + FILE *fin; + char *ref; + + if (!htsp_has(models, name)) { + char buff[1024], *full_path; + fin = pcb_fopen_first(&conf_core.rc.library_search_paths, name, "r", &full_path, pcb_true); + + if (fin != NULL) { + char *s, *safe_name = pcb_strdup(name); + for(s = safe_name; *s != '\0'; s++) + if (!isalnum(*s)) + *s = '_'; + + fprintf(f, "// Model loaded from '%s'\n", full_path); + free(full_path); + + /* replace the module line */ + while(fgets(buff, sizeof(buff), fin) != NULL) { + if (strstr(buff, "module") != NULL) { + fprintf(f, "module pcb_part_%s()", safe_name); + if (strchr(buff, '{') != NULL) + fprintf(f, "{\n"); + else + fprintf(f, "\n"); + break; + } + fprintf(f, "%s", buff); + } + + /* copy the rest */ + while(fgets(buff, sizeof(buff), fin) != NULL) { + fprintf(f, "%s", buff); + } + fclose(fin); + pcb_snprintf(buff, sizeof(buff), "pcb_part_%s", safe_name); + htsp_set(models, (char *)name, pcb_strdup(buff)); + free(safe_name); + } + else { + htsp_set(models, (char *)name, NULL); + pcb_message(PCB_MSG_WARNING, "openscad: can't find model file for %s in the footprint library\n", name); + } + } + ref = htsp_get(models, (char *)name); + if (ref != NULL) { + char tab[] = "\t\t\t\t\t\t\t\t"; + int ind = 0; + pcb_append_printf(&model_calls, " translate([%mm,%mm,%c0.8])\n", x0, y0, on_bottom ? '-' : '+'); + ind++; + tab[ind] = '\0'; + + if (on_bottom) { + pcb_append_printf(&model_calls, " %smirror([0,0,1])\n", tab); + tab[ind] = '\t'; ind++; tab[ind] = '\0'; + } + if (rot != 0) { + pcb_append_printf(&model_calls, " %srotate([0,0,%f])\n", tab, rot); + tab[ind] = '\t'; ind++; tab[ind] = '\0'; + } + if (transf != NULL) { + pcb_append_printf(&model_calls, " %s%s\n", tab, transf); + tab[ind] = '\t'; ind++; tab[ind] = '\0'; + } + + + if (param != NULL) + pcb_append_printf(&model_calls, " %s%s(%s);\n", tab, ref, param); + else + pcb_append_printf(&model_calls, " %s%s();\n", tab, ref); + } +} + +static void scad_insert_models(void) +{ + htsp_t models; + const char *mod, *transf, *param; + htsp_entry_t *e; + + htsp_init(&models, strhash, strkeyeq); + + PCB_SUBC_LOOP(PCB->Data); { + mod = pcb_attribute_get(&subc->Attributes, "openscad"); + if (mod != NULL) { + pcb_coord_t ox, oy; + double rot = 0; + int on_bottom = 0; + + if (pcb_subc_get_origin(subc, &ox, &oy) != 0) { + pcb_io_incompat_save(PCB->Data, (pcb_any_obj_t *)subc, "subc-place", "Failed to get origin of subcircuit", "fix the missing subc-aux layer"); + continue; + } + pcb_subc_get_rotation(subc, &rot); + pcb_subc_get_side(subc, &on_bottom); + + transf = pcb_attribute_get(&subc->Attributes, "openscad-transformation"); + param = pcb_attribute_get(&subc->Attributes, "openscad-param"); + scad_insert_model(&models, mod, TRX_(ox), TRY_(oy), rot, on_bottom, transf, param); + } + } PCB_END_LOOP; + + for (e = htsp_first(&models); e; e = htsp_next(&models, e)) + free(e->value); + + htsp_uninit(&models); +} Index: tags/2.1.2/src_plugins/export_png/Makefile =================================================================== --- tags/2.1.2/src_plugins/export_png/Makefile (nonexistent) +++ tags/2.1.2/src_plugins/export_png/Makefile (revision 24813) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_export_png + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/2.1.2/src_plugins/export_png/Plug.tmpasm =================================================================== --- tags/2.1.2/src_plugins/export_png/Plug.tmpasm (nonexistent) +++ tags/2.1.2/src_plugins/export_png/Plug.tmpasm (revision 24813) @@ -0,0 +1,16 @@ +put /local/pcb/mod {export_png} +put /local/pcb/mod/OBJS [@ $(PLUGDIR)/export_png/png.o @] + +switch /local/pcb/export_png/controls + case {disable} end; + default + put /local/pcb/mod/LDFLAGS libs/gui/gd/ldflags + put /local/pcb/mod/CFLAGS libs/gui/gd/cflags + end +end + +switch /local/pcb/export_png/controls + case {buildin} include /local/pcb/tmpasm/buildin; end; + case {plugin} include /local/pcb/tmpasm/plugin; end; + case {disable} include /local/pcb/tmpasm/disable; end; +end Index: tags/2.1.2/src_plugins/export_png/export_png.pup =================================================================== --- tags/2.1.2/src_plugins/export_png/export_png.pup (nonexistent) +++ tags/2.1.2/src_plugins/export_png/export_png.pup (revision 24813) @@ -0,0 +1,11 @@ +$class export +$short png/gif/jpg pcb_exporter +$long Export to png, gif and jpeg +$state works +$fmt-native no +$fmt-feature-w render the on-screen version or emulated photo mode version in .png +$fmt-feature-w render the on-screen version or emulated photo mode version in .gif +$fmt-feature-w render the on-screen version or emulated photo mode version in .jpeg +$package export +default buildin +autoload 1 Index: tags/2.1.2/src_plugins/export_png/png.c =================================================================== --- tags/2.1.2/src_plugins/export_png/png.c (nonexistent) +++ tags/2.1.2/src_plugins/export_png/png.c (revision 24813) @@ -0,0 +1,1959 @@ + /* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 2006 Dan McMahill + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +/* + * Heavily based on the ps HID written by DJ Delorie + */ + +#include "config.h" +#include "conf_core.h" + +#include +#include +#include +#include +#include +#include + +#include "board.h" +#include "data.h" +#include "draw.h" +#include "error.h" +#include "layer.h" +#include "layer_vis.h" +#include "misc_util.h" +#include "compat_misc.h" +#include "plugins.h" +#include "safe_fs.h" +#include "funchash_core.h" + +#include "hid.h" +#include "hid_nogui.h" +#include "hid_draw_helpers.h" +#include "png.h" + +/* the gd library which makes this all so easy */ +#include + +#include "hid_init.h" +#include "hid_attrib.h" +#include "hid_color.h" +#include "hid_cam.h" + +#define PNG_SCALE_HACK1 0 +#include "compat_misc.h" +#define pcb_hack_round(d) pcb_round(d) + +#define CRASH(func) fprintf(stderr, "HID error: pcb called unimplemented PNG function %s.\n", func); abort() + +static pcb_hid_t png_hid; + +const char *png_cookie = "png HID"; + +static pcb_cam_t png_cam; + +static void *color_cache = NULL; +static void *brush_cache = NULL; + +static double bloat = 0; +static double scale = 1; +static pcb_coord_t x_shift = 0; +static pcb_coord_t y_shift = 0; +static int show_solder_side; +#define SCALE(w) ((int)pcb_round((w)/scale)) +#define SCALE_X(x) ((int)pcb_hack_round(((x) - x_shift)/scale)) +#define SCALE_Y(y) ((int)pcb_hack_round(((show_solder_side ? (PCB->MaxHeight-(y)) : (y)) - y_shift)/scale)) +#define SWAP_IF_SOLDER(a,b) do { int c; if (show_solder_side) { c=a; a=b; b=c; }} while (0) + +/* Used to detect non-trivial outlines */ +#define NOT_EDGE_X(x) ((x) != 0 && (x) != PCB->MaxWidth) +#define NOT_EDGE_Y(y) ((y) != 0 && (y) != PCB->MaxHeight) +#define NOT_EDGE(x,y) (NOT_EDGE_X(x) || NOT_EDGE_Y(y)) + +static void png_fill_circle(pcb_hid_gc_t gc, pcb_coord_t cx, pcb_coord_t cy, pcb_coord_t radius); + +/* The result of a failed gdImageColorAllocate() call */ +#define BADC -1 + +typedef struct color_struct { + /* the descriptor used by the gd library */ + int c; + + /* so I can figure out what rgb value c refers to */ + unsigned int r, g, b, a; + +} color_struct; + +typedef struct hid_gc_s { + pcb_core_gc_t core_gc; + pcb_hid_t *me_pointer; + pcb_cap_style_t cap; + int width; + unsigned char r, g, b; + color_struct *color; + gdImagePtr brush; + int is_erase; +} hid_gc_s; + +static color_struct *black = NULL, *white = NULL; +static gdImagePtr im = NULL, master_im, comp_im = NULL, erase_im = NULL; +static FILE *f = 0; +static int linewidth = -1; +static int lastgroup = -1; +static gdImagePtr lastbrush = (gdImagePtr) ((void *) -1); +static int lastcap = -1; +static int last_color_r, last_color_g, last_color_b, last_cap; + +/* For photo-mode we need the following layers as monochrome masks: + + top soldermask + top silk + copper layers + drill +*/ + +#define PHOTO_FLIP_X 1 +#define PHOTO_FLIP_Y 2 + +static int photo_mode, photo_flip; +static gdImagePtr photo_copper[PCB_MAX_LAYER + 2]; +static gdImagePtr photo_silk, photo_mask, photo_drill, *photo_im; +static gdImagePtr photo_outline; +static int photo_groups[PCB_MAX_LAYERGRP + 2], photo_ngroups; +static int photo_has_inners; + +static int doing_outline, have_outline; + +#define FMT_gif "GIF" +#define FMT_jpg "JPEG" +#define FMT_png "PNG" + +/* If this table has no elements in it, then we have no reason to + register this HID and will refrain from doing so at the end of this + file. */ + +#undef HAVE_SOME_FORMAT + +static const char *filetypes[] = { +#ifdef HAVE_GDIMAGEPNG + FMT_png, +#define HAVE_SOME_FORMAT 1 +#endif + +#ifdef HAVE_GDIMAGEGIF + FMT_gif, +#define HAVE_SOME_FORMAT 1 +#endif + +#ifdef HAVE_GDIMAGEJPEG + FMT_jpg, +#define HAVE_SOME_FORMAT 1 +#endif + + NULL +}; + +static const char *mask_colour_names[] = { + "green", + "red", + "blue", + "purple", + "black", + "white", + NULL +}; + +/* These values were arrived at through trial and error. + One potential improvement (especially for white) is + to use separate color_structs for the multiplication + and addition parts of the mask math. + */ +static const color_struct mask_colours[] = { +#define MASK_COLOUR_GREEN 0 + {0x3CA03CFF, 60, 160, 60, 255}, +#define MASK_COLOUR_RED 1 + {0x8C1919FF, 140, 25, 25, 255}, +#define MASK_COLOUR_BLUE 2 + {0x3232A0FF, 50, 50, 160, 255}, +#define MASK_COLOUR_PURPLE 3 + {0x3C1446FF, 60, 20, 70, 255}, +#define MASK_COLOUR_BLACK 4 + {0x141414FF, 20, 20, 20, 255}, +#define MASK_COLOUR_WHITE 5 + {0xA7E6A2FF, 167, 230, 162, 255} /* <-- needs improvement over FR4 */ +}; + +static const char *plating_type_names[] = { +#define PLATING_TIN 0 + "tinned", +#define PLATING_GOLD 1 + "gold", +#define PLATING_SILVER 2 + "silver", +#define PLATING_COPPER 3 + "copper", + NULL +}; + +static const char *silk_colour_names[] = { + "white", + "black", + "yellow", + NULL +}; + +static const color_struct silk_colours[] = { +#define SILK_COLOUR_WHITE 0 + {0xE0E0E0FF, 224, 224, 224, 255}, +#define SILK_COLOUR_BLACK 1 + {0x0E0E0EFF, 14, 14, 14, 255}, +#define SILK_COLOUR_YELLOW 2 + {0xB9B90AFF, 185, 185, 10, 255} +}; + +static const color_struct silk_top_shadow = {0x151515FF, 21, 21, 21, 255}; +static const color_struct silk_bottom_shadow = {0x0E0E0EFF, 14, 14, 14, 255}; + +pcb_hid_attribute_t png_attribute_list[] = { + /* other HIDs expect this to be first. */ + +/* %start-doc options "93 PNG Options" +@ftable @code +@item --outfile +Name of the file to be exported to. Can contain a path. +@end ftable +%end-doc +*/ + {"outfile", "Graphics output file", + PCB_HATT_STRING, 0, 0, {0, 0, 0}, 0, 0}, +#define HA_pngfile 0 + +/* %start-doc options "93 PNG Options" +@ftable @code +@item --dpi +Scale factor in pixels/inch. Set to 0 to scale to size specified in the layout. +@end ftable +%end-doc +*/ + {"dpi", "Scale factor (pixels/inch). 0 to scale to specified size", + PCB_HATT_INTEGER, 0, 10000, {100, 0, 0}, 0, 0}, +#define HA_dpi 1 + +/* %start-doc options "93 PNG Options" +@ftable @code +@item --x-max +Width of the png image in pixels. No constraint, when set to 0. +@end ftable +%end-doc +*/ + {"x-max", "Maximum width (pixels). 0 to not constrain", + PCB_HATT_INTEGER, 0, 10000, {0, 0, 0}, 0, 0}, +#define HA_xmax 2 + +/* %start-doc options "93 PNG Options" +@ftable @code +@item --y-max +Height of the png output in pixels. No constraint, when set to 0. +@end ftable +%end-doc +*/ + {"y-max", "Maximum height (pixels). 0 to not constrain", + PCB_HATT_INTEGER, 0, 10000, {0, 0, 0}, 0, 0}, +#define HA_ymax 3 + +/* %start-doc options "93 PNG Options" +@ftable @code +@item --xy-max +Maximum width and height of the PNG output in pixels. No constraint, when set to 0. +@end ftable +%end-doc +*/ + {"xy-max", "Maximum width and height (pixels). 0 to not constrain", + PCB_HATT_INTEGER, 0, 10000, {0, 0, 0}, 0, 0}, +#define HA_xymax 4 + +/* %start-doc options "93 PNG Options" +@ftable @code +@item --as-shown +Export layers as shown on screen. +@end ftable +%end-doc +*/ + {"as-shown", "Export layers as shown on screen", + PCB_HATT_BOOL, 0, 0, {0, 0, 0}, 0, 0}, +#define HA_as_shown 5 + +/* %start-doc options "93 PNG Options" +@ftable @code +@item --monochrome +Convert output to monochrome. +@end ftable +%end-doc +*/ + {"monochrome", "Convert to monochrome", + PCB_HATT_BOOL, 0, 0, {0, 0, 0}, 0, 0}, +#define HA_mono 6 + +/* %start-doc options "93 PNG Options" +@ftable @code +@item --only-vivible +Limit the bounds of the exported PNG image to the visible items. +@end ftable +%end-doc +*/ + {"only-visible", "Limit the bounds of the PNG image to the visible items", + PCB_HATT_BOOL, 0, 0, {0, 0, 0}, 0, 0}, +#define HA_only_visible 7 + +/* %start-doc options "93 PNG Options" +@ftable @code +@item --use-alpha +Make the background and any holes transparent. +@end ftable +%end-doc +*/ + {"use-alpha", "Make the background and any holes transparent", + PCB_HATT_BOOL, 0, 0, {0, 0, 0}, 0, 0}, +#define HA_use_alpha 8 + +/* %start-doc options "93 PNG Options" +@ftable @code +@item --format +File format to be exported. Parameter @code{} can be @samp{PNG}, +@samp{GIF}, or @samp{JPEG}. +@end ftable +%end-doc +*/ + {"format", "Export file format", + PCB_HATT_ENUM, 0, 0, {0, 0, 0}, filetypes, 0}, +#define HA_filetype 9 + +/* %start-doc options "93 PNG Options" +@ftable @code +@item --png-bloat +Amount of extra thickness to add to traces, pads, or pin edges. The parameter +@samp{} is a number, appended by a dimension @samp{mm}, @samp{mil}, or +@samp{pix}. If no dimension is given, the default dimension is 1/100 mil. +OBSOLETE - do not use this feature! +@end ftable +%end-doc +*/ + {"png-bloat", "Amount (in/mm/mil/pix) to add to trace/pad/pin edges (1 = 1/100 mil) (OBSOLETE - do not use this feature!)", + PCB_HATT_STRING, 0, 0, {0, 0, 0}, 0, 0}, +#define HA_bloat 10 + +/* %start-doc options "93 PNG Options" +@ftable @code +@cindex photo-mode +@item --photo-mode +Export a photo realistic image of the layout. +@end ftable +%end-doc +*/ + {"photo-mode", "Photo-realistic export mode", + PCB_HATT_BOOL, 0, 0, {0, 0, 0}, 0, 0}, +#define HA_photo_mode 11 + +/* %start-doc options "93 PNG Options" +@ftable @code +@item --photo-flip-x +In photo-realistic mode, export the reverse side of the layout. Left-right flip. +@end ftable +%end-doc +*/ + {"photo-flip-x", "Show reverse side of the board, left-right flip", + PCB_HATT_BOOL, 0, 0, {0, 0, 0}, 0, 0}, +#define HA_photo_flip_x 12 + +/* %start-doc options "93 PNG Options" +@ftable @code +@item --photo-flip-y +In photo-realistic mode, export the reverse side of the layout. Up-down flip. +@end ftable +%end-doc +*/ + {"photo-flip-y", "Show reverse side of the board, up-down flip", + PCB_HATT_BOOL, 0, 0, {0, 0, 0}, 0, 0}, +#define HA_photo_flip_y 13 + +/* %start-doc options "93 PNG Options" +@ftable @code +@cindex photo-mask-colour +@item --photo-mask-colour +In photo-realistic mode, export the solder mask as this colour. Parameter +@code{} can be @samp{green}, @samp{red}, @samp{blue}, or @samp{purple}. +@end ftable +%end-doc +*/ + {"photo-mask-colour", "Colour for the exported colour mask (green, red, blue, purple)", + PCB_HATT_ENUM, 0, 0, {0, 0, 0}, mask_colour_names, 0}, +#define HA_photo_mask_colour 14 + +/* %start-doc options "93 PNG Options" +@ftable @code +@cindex photo-plating +@item --photo-plating +In photo-realistic mode, export the exposed copper as though it has this type +of plating. Parameter @code{} can be @samp{tinned}, @samp{gold}, +@samp{silver}, or @samp{copper}. +@end ftable +%end-doc +*/ + {"photo-plating", "Type of plating applied to exposed copper in photo-mode (tinned, gold, silver, copper)", + PCB_HATT_ENUM, 0, 0, {0, 0, 0}, plating_type_names, 0}, +#define HA_photo_plating 15 + +/* %start-doc options "93 PNG Options" +@ftable @code +@cindex photo-silk-colour +@item --photo-silk-colour +In photo-realistic mode, export the silk screen as this colour. Parameter +@code{} can be @samp{white}, @samp{black}, or @samp{yellow}. +@end ftable +%end-doc +*/ + {"photo-silk-colour", "Colour for the exported colour silk (white, black, yellow)", + PCB_HATT_ENUM, 0, 0, {0, 0, 0}, silk_colour_names, 0}, +#define HA_photo_silk_colour 16 + + {"cam", "CAM instruction", + PCB_HATT_STRING, 0, 0, {0, 0, 0}, 0, 0}, +#define HA_cam 17 + + {"ben-mode", ATTR_UNDOCUMENTED, + PCB_HATT_BOOL, 0, 0, {0, 0, 0}, 0, 0}, +#define HA_ben_mode 11 + + {"ben-flip-x", ATTR_UNDOCUMENTED, + PCB_HATT_BOOL, 0, 0, {0, 0, 0}, 0, 0}, +#define HA_ben_flip_x 12 + + {"ben-flip-y", ATTR_UNDOCUMENTED, + PCB_HATT_BOOL, 0, 0, {0, 0, 0}, 0, 0} +#define HA_ben_flip_y 13 + +}; + +#define NUM_OPTIONS (sizeof(png_attribute_list)/sizeof(png_attribute_list[0])) + +PCB_REGISTER_ATTRIBUTES(png_attribute_list, png_cookie) + +static pcb_hid_attr_val_t png_values[NUM_OPTIONS]; + +static const char *get_file_suffix(void) +{ + const char *result = NULL; + const char *fmt; + + fmt = filetypes[png_attribute_list[HA_filetype].default_val.int_value]; + + if (fmt == NULL) { /* Do nothing */ } + else if (strcmp(fmt, FMT_gif) == 0) + result = ".gif"; + else if (strcmp(fmt, FMT_jpg) == 0) + result = ".jpg"; + else if (strcmp(fmt, FMT_png) == 0) + result = ".png"; + + if (result == NULL) { + fprintf(stderr, "Error: Invalid graphic file format\n"); + result = ".???"; + } + return result; +} + +static pcb_hid_attribute_t *png_get_export_options(int *n) +{ + const char *suffix = get_file_suffix(); + + if ((PCB != NULL) && (png_attribute_list[HA_pngfile].default_val.str_value == NULL)) + pcb_derive_default_filename(PCB->Filename, &png_attribute_list[HA_pngfile], suffix); + + if (n) + *n = NUM_OPTIONS; + return png_attribute_list; +} + + +static pcb_layergrp_id_t group_for_layer(int l) +{ + if (l < pcb_max_layer && l >= 0) + return pcb_layer_get_group(PCB, l); + /* else something unique */ + return pcb_max_group(PCB) + 3 + l; +} + +static int is_solder(pcb_layergrp_id_t grp) { return pcb_layergrp_flags(PCB, grp) & PCB_LYT_BOTTOM; } +static int is_component(pcb_layergrp_id_t grp) { return pcb_layergrp_flags(PCB, grp) & PCB_LYT_TOP; } + +static int layer_sort(const void *va, const void *vb) +{ + int a = *(int *) va; + int b = *(int *) vb; + pcb_layergrp_id_t al = group_for_layer(a); + pcb_layergrp_id_t bl = group_for_layer(b); + int d = bl - al; + + if (a >= 0 && a < pcb_max_layer) { + int aside = (is_solder(al) ? 0 : is_component(al) ? 2 : 1); + int bside = (is_solder(bl) ? 0 : is_component(bl) ? 2 : 1); + + if (bside != aside) + return bside - aside; + } + if (d) + return d; + return b - a; +} + +static const char *filename; +static pcb_box_t *bounds; +static int in_mono, as_shown; +static pcb_layergrp_id_t photo_last_grp; + +static void parse_bloat(const char *str) +{ + int n; + pcb_unit_list_t extra_units = { + {"pix", 0, 0}, + {"px", 0, 0}, + {"", 0, 0} + }; + for(n = 0; n < (sizeof(extra_units)/sizeof(extra_units[0]))-1; n++) + extra_units[n].scale = scale; + if (str == NULL) + return; + bloat = pcb_get_value_ex(str, NULL, NULL, extra_units, "", NULL); +} + +static int smshadows[3][3] = { + {1, 0, -1}, + {0, 0, -1}, + {-1, -1, -1}, +}; + +static int shadows[5][5] = { + {1, 1, 0, 0, -1}, + {1, 1, 1, -1, 0}, + {0, 1, 0, -1, 0}, + {0, -1, -1, -1, 0}, + {-1, 0, 0, 0, -1}, +}; + +/* black and white are 0 and 1 */ +#define TOP_SHADOW 2 +#define BOTTOM_SHADOW 3 + +static void ts_bs(gdImagePtr im) +{ + int x, y, sx, sy, si; + for (x = 0; x < gdImageSX(im); x++) + for (y = 0; y < gdImageSY(im); y++) { + si = 0; + for (sx = -2; sx < 3; sx++) + for (sy = -2; sy < 3; sy++) + if (!gdImageGetPixel(im, x + sx, y + sy)) + si += shadows[sx + 2][sy + 2]; + if (gdImageGetPixel(im, x, y)) { + if (si > 1) + gdImageSetPixel(im, x, y, TOP_SHADOW); + else if (si < -1) + gdImageSetPixel(im, x, y, BOTTOM_SHADOW); + } + } +} + +static void ts_bs_sm(gdImagePtr im) +{ + int x, y, sx, sy, si; + for (x = 0; x < gdImageSX(im); x++) + for (y = 0; y < gdImageSY(im); y++) { + si = 0; + for (sx = -1; sx < 2; sx++) + for (sy = -1; sy < 2; sy++) + if (!gdImageGetPixel(im, x + sx, y + sy)) + si += smshadows[sx + 1][sy + 1]; + if (gdImageGetPixel(im, x, y)) { + if (si > 1) + gdImageSetPixel(im, x, y, TOP_SHADOW); + else if (si < -1) + gdImageSetPixel(im, x, y, BOTTOM_SHADOW); + } + } +} + +static void clip(color_struct * dest, color_struct * source) +{ +#define CLIP(var) \ + dest->var = source->var; \ + if (dest->var > 255) dest->var = 255; \ + if (dest->var < 0) dest->var = 0; + + CLIP(r); + CLIP(g); + CLIP(b); +#undef CLIP +} + +static void blend(color_struct * dest, float a_amount, color_struct * a, color_struct * b) +{ + dest->r = a->r * a_amount + b->r * (1 - a_amount); + dest->g = a->g * a_amount + b->g * (1 - a_amount); + dest->b = a->b * a_amount + b->b * (1 - a_amount); +} + +static void multiply(color_struct * dest, color_struct * a, color_struct * b) +{ + dest->r = (a->r * b->r) / 255; + dest->g = (a->g * b->g) / 255; + dest->b = (a->b * b->b) / 255; +} + +static void add(color_struct * dest, double a_amount, const color_struct * a, double b_amount, const color_struct * b) +{ + dest->r = a->r * a_amount + b->r * b_amount; + dest->g = a->g * a_amount + b->g * b_amount; + dest->b = a->b * a_amount + b->b * b_amount; + + clip(dest, dest); +} + +static void subtract(color_struct * dest, double a_amount, const color_struct * a, double b_amount, const color_struct * b) +{ + dest->r = a->r * a_amount - b->r * b_amount; + dest->g = a->g * a_amount - b->g * b_amount; + dest->b = a->b * a_amount - b->b * b_amount; + + clip(dest, dest); +} + +static void rgb(color_struct * dest, int r, int g, int b) +{ + dest->r = r; + dest->g = g; + dest->b = b; +} + +static pcb_hid_attr_val_t *png_options; + +static void png_head(void) +{ + linewidth = -1; + lastbrush = (gdImagePtr) ((void *) -1); + lastcap = -1; + lastgroup = -1; + photo_last_grp = -1; + show_solder_side = conf_core.editor.show_solder_side; + last_color_r = last_color_g = last_color_b = last_cap = -1; + + gdImageFilledRectangle(im, 0, 0, gdImageSX(im), gdImageSY(im), white->c); +} + +static void png_foot(void) +{ + const char *fmt; + pcb_bool format_error = pcb_false; + + if (photo_mode) { + int x, y, darken, lg; + color_struct white, black, fr4; + + rgb(&white, 255, 255, 255); + rgb(&black, 0, 0, 0); + rgb(&fr4, 70, 70, 70); + + im = master_im; + + ts_bs(photo_copper[photo_groups[0]]); + if (photo_silk != NULL) + ts_bs(photo_silk); + if (photo_mask != NULL) + ts_bs_sm(photo_mask); + + if (photo_outline && have_outline) { + int black = gdImageColorResolve(photo_outline, 0x00, 0x00, 0x00); + + /* go all the way around the image, trying to fill the outline */ + for (x = 0; x < gdImageSX(im); x++) { + gdImageFillToBorder(photo_outline, x, 0, black, black); + gdImageFillToBorder(photo_outline, x, gdImageSY(im) - 1, black, black); + } + for (y = 1; y < gdImageSY(im) - 1; y++) { + gdImageFillToBorder(photo_outline, 0, y, black, black); + gdImageFillToBorder(photo_outline, gdImageSX(im) - 1, y, black, black); + + } + } + + + for (x = 0; x < gdImageSX(im); x++) { + for (y = 0; y < gdImageSY(im); y++) { + color_struct p, cop; + color_struct mask_colour, silk_colour; + int cc, mask, silk; + int transparent; + + if (photo_outline && have_outline) { + transparent = gdImageGetPixel(photo_outline, x, y); + } + else { + transparent = 0; + } + + mask = photo_mask ? gdImageGetPixel(photo_mask, x, y) : 0; + silk = photo_silk ? gdImageGetPixel(photo_silk, x, y) : 0; + + darken = 0; + for(lg = 1; lg < photo_ngroups; lg++) { + if (photo_copper[photo_groups[lg]] && gdImageGetPixel(photo_copper[photo_groups[lg]], x, y)) { + darken = 1; + break; + } + } + + if (darken) + rgb(&cop, 40, 40, 40); + else + rgb(&cop, 100, 100, 110); + + blend(&cop, 0.3, &cop, &fr4); + + cc = gdImageGetPixel(photo_copper[photo_groups[0]], x, y); + if (cc) { + int r; + + if (mask) + rgb(&cop, 220, 145, 230); + else { + + if (png_options[HA_photo_plating].int_value == PLATING_GOLD) { + /* ENIG */ + rgb(&cop, 185, 146, 52); + + /* increase top shadow to increase shininess */ + if (cc == TOP_SHADOW) + blend(&cop, 0.7, &cop, &white); + } + else if (png_options[HA_photo_plating].int_value == PLATING_TIN) { + /* tinned */ + rgb(&cop, 140, 150, 160); + + /* add some variation to make it look more matte */ + r = (rand() % 5 - 2) * 2; + cop.r += r; + cop.g += r; + cop.b += r; + } + else if (png_options[HA_photo_plating].int_value == PLATING_SILVER) { + /* silver */ + rgb(&cop, 192, 192, 185); + + /* increase top shadow to increase shininess */ + if (cc == TOP_SHADOW) + blend(&cop, 0.7, &cop, &white); + } + else if (png_options[HA_photo_plating].int_value == PLATING_COPPER) { + /* copper */ + rgb(&cop, 184, 115, 51); + + /* increase top shadow to increase shininess */ + if (cc == TOP_SHADOW) + blend(&cop, 0.7, &cop, &white); + } + /*FIXME: old code...can be removed after validation. rgb(&cop, 140, 150, 160); + r = (pcb_rand() % 5 - 2) * 2; + cop.r += r; + cop.g += r; + cop.b += r; */ + } + + if (cc == TOP_SHADOW) { + cop.r = 255 - (255 - cop.r) * 0.7; + cop.g = 255 - (255 - cop.g) * 0.7; + cop.b = 255 - (255 - cop.b) * 0.7; + } + if (cc == BOTTOM_SHADOW) { + cop.r *= 0.7; + cop.g *= 0.7; + cop.b *= 0.7; + } + } + + if (photo_drill && !gdImageGetPixel(photo_drill, x, y)) { + rgb(&p, 0, 0, 0); + transparent = 1; + } + else if (silk) { + silk_colour = silk_colours[png_options[HA_photo_silk_colour].int_value]; + blend(&p, 1.0, &silk_colour, &silk_colour); + + if (silk == TOP_SHADOW) + add(&p, 1.0, &p, 1.0, &silk_top_shadow); + else if (silk == BOTTOM_SHADOW) + subtract(&p, 1.0, &p, 1.0, &silk_bottom_shadow); + } + else if (mask) { + p = cop; + mask_colour = mask_colours[png_options[HA_photo_mask_colour].int_value]; + multiply(&p, &p, &mask_colour); + add(&p, 1, &p, 0.2, &mask_colour); + if (mask == TOP_SHADOW) + blend(&p, 0.7, &p, &white); + if (mask == BOTTOM_SHADOW) + blend(&p, 0.7, &p, &black); + } + else + p = cop; + + if (png_options[HA_use_alpha].int_value) { + + cc = (transparent) ? gdImageColorResolveAlpha(im, 0, 0, 0, 127) : gdImageColorResolveAlpha(im, p.r, p.g, p.b, 0); + + } + else { + cc = (transparent) ? gdImageColorResolve(im, 0, 0, 0) : gdImageColorResolve(im, p.r, p.g, p.b); + } + + if (photo_flip == PHOTO_FLIP_X) + gdImageSetPixel(im, gdImageSX(im) - x - 1, y, cc); + else if (photo_flip == PHOTO_FLIP_Y) + gdImageSetPixel(im, x, gdImageSY(im) - y - 1, cc); + else + gdImageSetPixel(im, x, y, cc); + } + } + } + + /* actually write out the image */ + fmt = filetypes[png_options[HA_filetype].int_value]; + + if (fmt == NULL) + format_error = pcb_true; + else if (strcmp(fmt, FMT_gif) == 0) +#ifdef HAVE_GDIMAGEGIF + gdImageGif(im, f); +#else + format_error = pcb_true; +#endif + else if (strcmp(fmt, FMT_jpg) == 0) +#ifdef HAVE_GDIMAGEJPEG + gdImageJpeg(im, f, -1); +#else + format_error = pcb_true; +#endif + else if (strcmp(fmt, FMT_png) == 0) +#ifdef HAVE_GDIMAGEPNG + gdImagePng(im, f); +#else + format_error = pcb_true; +#endif + else + format_error = pcb_true; + + if (format_error) + fprintf(stderr, "Error: Invalid graphic file format." " This is a bug. Please report it.\n"); +} + +void png_hid_export_to_file(FILE * the_file, pcb_hid_attr_val_t * options) +{ + static int saved_layer_stack[PCB_MAX_LAYER]; + pcb_box_t tmp, region; + pcb_hid_expose_ctx_t ctx; + + f = the_file; + + region.X1 = 0; + region.Y1 = 0; + region.X2 = PCB->MaxWidth; + region.Y2 = PCB->MaxHeight; + + png_options = options; + if (options[HA_only_visible].int_value) + bounds = pcb_data_bbox(&tmp, PCB->Data, pcb_false); + else + bounds = ®ion; + + memcpy(saved_layer_stack, pcb_layer_stack, sizeof(pcb_layer_stack)); + + as_shown = options[HA_as_shown].int_value; + if (!options[HA_as_shown].int_value) { + conf_force_set_bool(conf_core.editor.thin_draw, 0); + conf_force_set_bool(conf_core.editor.thin_draw_poly, 0); +/* conf_force_set_bool(conf_core.editor.check_planes, 0);*/ + conf_force_set_bool(conf_core.editor.show_solder_side, 0); + + qsort(pcb_layer_stack, pcb_max_layer, sizeof(pcb_layer_stack[0]), layer_sort); + + if (photo_mode) { + int i, n = 0; + pcb_layergrp_id_t solder_layer = -1, comp_layer = -1; + + pcb_layergrp_list(PCB, PCB_LYT_BOTTOM | PCB_LYT_COPPER, &solder_layer, 1); + pcb_layergrp_list(PCB, PCB_LYT_TOP | PCB_LYT_COPPER, &comp_layer, 1); + assert(solder_layer >= 0); + assert(comp_layer >= 0); + + photo_has_inners = 0; + if (comp_layer < solder_layer) + for (i = comp_layer; i <= solder_layer; i++) { + photo_groups[n++] = i; + if (i != comp_layer && i != solder_layer && !pcb_layergrp_is_empty(PCB, i)) + photo_has_inners = 1; + } + else + for (i = comp_layer; i >= solder_layer; i--) { + photo_groups[n++] = i; + if (i != comp_layer && i != solder_layer && !pcb_layergrp_is_empty(PCB, i)) + photo_has_inners = 1; + } + if (!photo_has_inners) { + photo_groups[1] = photo_groups[n - 1]; + n = 2; + } + photo_ngroups = n; + + if (photo_flip) { + for (i = 0, n = photo_ngroups - 1; i < n; i++, n--) { + int tmp = photo_groups[i]; + photo_groups[i] = photo_groups[n]; + photo_groups[n] = tmp; + } + } + } + } + + in_mono = options[HA_mono].int_value; + png_head(); + + if (!photo_mode && conf_core.editor.show_solder_side) { + int i, j; + for (i = 0, j = pcb_max_layer - 1; i < j; i++, j--) { + int k = pcb_layer_stack[i]; + pcb_layer_stack[i] = pcb_layer_stack[j]; + pcb_layer_stack[j] = k; + } + } + + ctx.view = *bounds; + pcb_hid_expose_all(&png_hid, &ctx, NULL); + + memcpy(pcb_layer_stack, saved_layer_stack, sizeof(pcb_layer_stack)); + conf_update(NULL, -1); /* restore forced sets */ +} + + + +static void png_brush_free(void **vcache, const char *name, pcb_hidval_t *val) +{ + gdImage *brush = (gdImage *)val->ptr; + if (brush != NULL) + gdImageDestroy(brush); +} + +static void png_color_free(void **vcache, const char *name, pcb_hidval_t *val) +{ + color_struct *color = (color_struct *)val->ptr; + free(color); +} + +static void png_free_cache(void) +{ + if (color_cache) + pcb_hid_cache_color_destroy(&color_cache, png_color_free); + if (brush_cache != NULL) + pcb_hid_cache_color_destroy(&brush_cache, png_brush_free); +} + +static void png_do_export(pcb_hid_attr_val_t * options) +{ + int save_ons[PCB_MAX_LAYER + 2]; + int i; + pcb_box_t tmp, *bbox; + int w, h; + int xmax, ymax, dpi; + + png_free_cache(); + + if (!options) { + png_get_export_options(0); + for (i = 0; i < NUM_OPTIONS; i++) + png_values[i] = png_attribute_list[i].default_val; + options = png_values; + } + + pcb_cam_begin(PCB, &png_cam, options[HA_cam].str_value, png_attribute_list, NUM_OPTIONS, options); + + if (options[HA_photo_mode].int_value || options[HA_ben_mode].int_value) { + photo_mode = 1; + options[HA_mono].int_value = 1; + options[HA_as_shown].int_value = 0; + memset(photo_copper, 0, sizeof(photo_copper)); + photo_silk = photo_mask = photo_drill = 0; + photo_outline = 0; + if (options[HA_photo_flip_x].int_value || options[HA_ben_flip_x].int_value) + photo_flip = PHOTO_FLIP_X; + else if (options[HA_photo_flip_y].int_value || options[HA_ben_flip_y].int_value) + photo_flip = PHOTO_FLIP_Y; + else + photo_flip = 0; + } + else + photo_mode = 0; + + filename = options[HA_pngfile].str_value; + if (!filename) + filename = "pcb-out.png"; + + /* figure out width and height of the board */ + if (options[HA_only_visible].int_value) { + bbox = pcb_data_bbox(&tmp, PCB->Data, pcb_false); + x_shift = bbox->X1; + y_shift = bbox->Y1; + h = bbox->Y2 - bbox->Y1; + w = bbox->X2 - bbox->X1; + } + else { + x_shift = 0; + y_shift = 0; + h = PCB->MaxHeight; + w = PCB->MaxWidth; + } + + /* + * figure out the scale factor we need to make the image + * fit in our specified PNG file size + */ + xmax = ymax = dpi = 0; + if (options[HA_dpi].int_value != 0) { + dpi = options[HA_dpi].int_value; + if (dpi < 0) { + fprintf(stderr, "ERROR: dpi may not be < 0\n"); + return; + } + } + + if (options[HA_xmax].int_value > 0) { + xmax = options[HA_xmax].int_value; + dpi = 0; + } + + if (options[HA_ymax].int_value > 0) { + ymax = options[HA_ymax].int_value; + dpi = 0; + } + + if (options[HA_xymax].int_value > 0) { + dpi = 0; + if (options[HA_xymax].int_value < xmax || xmax == 0) + xmax = options[HA_xymax].int_value; + if (options[HA_xymax].int_value < ymax || ymax == 0) + ymax = options[HA_xymax].int_value; + } + + if (xmax < 0 || ymax < 0) { + fprintf(stderr, "ERROR: xmax and ymax may not be < 0\n"); + return; + } + + if (dpi > 0) { + /* + * a scale of 1 means 1 pixel is 1 inch + * a scale of 10 means 1 pixel is 10 inches + */ + scale = PCB_INCH_TO_COORD(1) / dpi; + w = pcb_round(w / scale) - PNG_SCALE_HACK1; + h = pcb_round(h / scale) - PNG_SCALE_HACK1; + } + else if (xmax == 0 && ymax == 0) { + fprintf(stderr, "ERROR: You may not set both xmax, ymax," "and xy-max to zero\n"); + return; + } + else { + if (ymax == 0 || ((xmax > 0) + && ((w / xmax) > (h / ymax)))) { + h = (h * xmax) / w; + scale = w / xmax; + w = xmax; + } + else { + w = (w * ymax) / h; + scale = h / ymax; + h = ymax; + } + } + + im = gdImageCreate(w, h); + if (im == NULL) { + pcb_message(PCB_MSG_ERROR, "png_do_export(): gdImageCreate(%d, %d) returned NULL. Aborting export.\n", w, h); + return; + } + +#ifdef HAVE_GD_RESOLUTION + gdImageSetResolution(im, dpi, dpi); +#endif + + master_im = im; + + parse_bloat(options[HA_bloat].str_value); + + /* + * Allocate white and black -- the first color allocated + * becomes the background color + */ + + white = (color_struct *) malloc(sizeof(color_struct)); + white->r = white->g = white->b = 255; + if (options[HA_use_alpha].int_value) + white->a = 127; + else + white->a = 0; + white->c = gdImageColorAllocateAlpha(im, white->r, white->g, white->b, white->a); + if (white->c == BADC) { + pcb_message(PCB_MSG_ERROR, "png_do_export(): gdImageColorAllocateAlpha() returned NULL. Aborting export.\n"); + return; + } + + + black = (color_struct *) malloc(sizeof(color_struct)); + black->r = black->g = black->b = black->a = 0; + black->c = gdImageColorAllocate(im, black->r, black->g, black->b); + if (black->c == BADC) { + pcb_message(PCB_MSG_ERROR, "png_do_export(): gdImageColorAllocateAlpha() returned NULL. Aborting export.\n"); + return; + } + + if (!png_cam.fn_template) { + f = pcb_fopen(png_cam.active ? png_cam.fn : filename, "wb"); + if (!f) { + perror(filename); + return; + } + } + else + f = NULL; + + png_hid.force_compositing = !!photo_mode; + + if ((!png_cam.active) && (!options[HA_as_shown].int_value)) + pcb_hid_save_and_show_layer_ons(save_ons); + + png_hid_export_to_file(f, options); + + if ((!png_cam.active) && (!options[HA_as_shown].int_value)) + pcb_hid_restore_layer_ons(save_ons); + + png_foot(); + fclose(f); + + if (master_im != NULL) { + gdImageDestroy(master_im); + master_im = NULL; + } + if (comp_im != NULL) { + gdImageDestroy(comp_im); + comp_im = NULL; + } + if (erase_im != NULL) { + gdImageDestroy(erase_im); + erase_im = NULL; + } + if (photo_silk != NULL) { + gdImageDestroy(photo_silk); + photo_silk = NULL; + } + if (photo_mask != NULL) { + gdImageDestroy(photo_mask); + photo_mask = NULL; + } + if (photo_drill != NULL) { + gdImageDestroy(photo_drill); + photo_drill = NULL; + } + if (photo_outline != NULL) { + gdImageDestroy(photo_outline); + photo_outline = NULL; + } + for(i = 0; i < PCB_MAX_LAYER + 2; i++) { + if (photo_copper[i] != NULL) { + gdImageDestroy(photo_copper[i]); + photo_copper[i] = NULL; + } + } + png_free_cache(); + free(white); + free(black); + + if (pcb_cam_end(&png_cam) == 0) + pcb_message(PCB_MSG_ERROR, "png cam export for '%s' failed to produce any content\n", options[HA_cam].str_value); +} + +static int png_parse_arguments(int *argc, char ***argv) +{ + pcb_hid_register_attributes(png_attribute_list, sizeof(png_attribute_list) / sizeof(png_attribute_list[0]), png_cookie, 0); + return pcb_hid_parse_command_line(argc, argv); +} + + +static int is_mask; +static int is_photo_drill; + + +static int png_set_layer_group_photo(pcb_layergrp_id_t group, const char *purpose, int purpi, pcb_layer_id_t layer, unsigned int flags, int is_empty, pcb_xform_t **xform) +{ + + /* workaround: the outline layer vs. alpha breaks if set twice and the draw + code may set it twice (if there's no mech layer), but always in a row */ + if (group == photo_last_grp) + return 1; + photo_last_grp = group; + + is_photo_drill = (PCB_LAYER_IS_DRILL(flags, purpi) || ((flags & PCB_LYT_MECH) && PCB_LAYER_IS_ROUTE(flags, purpi))); + if (((flags & PCB_LYT_ANYTHING) == PCB_LYT_SILK) && (flags & PCB_LYT_TOP)) { + if (photo_flip) + return 0; + photo_im = &photo_silk; + } + else if (((flags & PCB_LYT_ANYTHING) == PCB_LYT_SILK) && (flags & PCB_LYT_BOTTOM)) { + if (!photo_flip) + return 0; + photo_im = &photo_silk; + } + else if ((flags & PCB_LYT_MASK) && (flags & PCB_LYT_TOP)) { + if (photo_flip) + return 0; + photo_im = &photo_mask; + } + else if ((flags & PCB_LYT_MASK) && (flags & PCB_LYT_BOTTOM)) { + if (!photo_flip) + return 0; + photo_im = &photo_mask; + } + else if (is_photo_drill) { + photo_im = &photo_drill; + } + else { + if (PCB_LAYER_IS_OUTLINE(flags, purpi)) { + doing_outline = 1; + have_outline = 0; + photo_im = &photo_outline; + } + else if (flags & PCB_LYT_COPPER) { + photo_im = photo_copper + group; + } + else + return 0; + } + + if (!*photo_im) { + static color_struct *black = NULL, *white = NULL; + *photo_im = gdImageCreate(gdImageSX(im), gdImageSY(im)); + if (photo_im == NULL) { + pcb_message(PCB_MSG_ERROR, "png_set_layer(): gdImageCreate(%d, %d) returned NULL. Aborting export.\n", gdImageSX(im), gdImageSY(im)); + return 0; + } + + + white = (color_struct *) malloc(sizeof(color_struct)); + white->r = white->g = white->b = 255; + white->a = 0; + white->c = gdImageColorAllocate(*photo_im, white->r, white->g, white->b); + if (white->c == BADC) { + pcb_message(PCB_MSG_ERROR, "png_set_layer(): gdImageColorAllocate() returned NULL. Aborting export.\n"); + return 0; + } + + black = (color_struct *) malloc(sizeof(color_struct)); + black->r = black->g = black->b = black->a = 0; + black->c = gdImageColorAllocate(*photo_im, black->r, black->g, black->b); + if (black->c == BADC) { + pcb_message(PCB_MSG_ERROR, "png_set_layer(): gdImageColorAllocate() returned NULL. Aborting export.\n"); + return 0; + } + + if (is_photo_drill) + gdImageFilledRectangle(*photo_im, 0, 0, gdImageSX(im), gdImageSY(im), black->c); + } + im = *photo_im; + return 1; +} + +static int png_set_layer_group(pcb_layergrp_id_t group, const char *purpose, int purpi, pcb_layer_id_t layer, unsigned int flags, int is_empty, pcb_xform_t **xform) +{ + doing_outline = 0; + + if (flags & PCB_LYT_UI) + return 0; + + pcb_cam_set_layer_group(&png_cam, group, purpose, purpi, flags, xform); + if (png_cam.fn_changed) { + if (f != NULL) { + png_foot(); + fclose(f); + } + f = pcb_fopen(png_cam.fn, "wb"); + if (!f) { + perror(filename); + return 0; + } + png_head(); + } + + if (!png_cam.active) { + if (flags & PCB_LYT_NOEXPORT) + return 0; + + if (PCB_LAYER_IS_ASSY(flags, purpi) || PCB_LAYER_IS_FAB(flags, purpi) || (flags & PCB_LYT_PASTE) || (flags & PCB_LYT_INVIS) || PCB_LAYER_IS_CSECT(flags, purpi)) + return 0; + } + + is_mask = (flags & PCB_LYT_MASK); + + if (photo_mode) + return png_set_layer_group_photo(group, purpose, purpi, layer, flags, is_empty, xform); + + if (PCB_LAYER_IS_OUTLINE(flags, purpi)) { + doing_outline = 1; + have_outline = 0; + } + + if (as_shown) { + if ((flags & PCB_LYT_ANYTHING) == PCB_LYT_SILK) { + if (PCB_LAYERFLG_ON_VISIBLE_SIDE(flags)) + return pcb_silk_on(PCB); + return 0; + } + + if ((flags & PCB_LYT_ANYTHING) == PCB_LYT_MASK) + return PCB->LayerGroups.grp[group].vis && PCB_LAYERFLG_ON_VISIBLE_SIDE(flags); + } + else { + if (is_mask) + return 0; + + if ((flags & PCB_LYT_ANYTHING) == PCB_LYT_SILK) + return !!(flags & PCB_LYT_TOP); + } + + return 1; +} + + +static pcb_hid_gc_t png_make_gc(void) +{ + pcb_hid_gc_t rv = (pcb_hid_gc_t) calloc(sizeof(hid_gc_s), 1); + rv->me_pointer = &png_hid; + rv->cap = pcb_cap_round; + rv->width = 1; + rv->color = (color_struct *) malloc(sizeof(color_struct)); + rv->color->r = rv->color->g = rv->color->b = rv->color->a = 0; + rv->color->c = 0; + rv->is_erase = 0; + return rv; +} + +static void png_destroy_gc(pcb_hid_gc_t gc) +{ + free(gc); +} + +static pcb_composite_op_t drawing_mode; +static void png_set_drawing_mode(pcb_composite_op_t op, pcb_bool direct, const pcb_box_t *screen) +{ + static gdImagePtr dst_im; + drawing_mode = op; + if ((direct) || (is_photo_drill)) /* photo drill is a special layer, no copositing on that */ + return; + switch(op) { + case PCB_HID_COMP_RESET: + + /* the main pixel buffer; drawn with color */ + if (comp_im == NULL) { + comp_im = gdImageCreate(gdImageSX(im), gdImageSY(im)); + if (!comp_im) { + pcb_message(PCB_MSG_ERROR, "png_set_drawing_mode(): gdImageCreate(%d, %d) returned NULL on comp_im. Corrupt export!\n", gdImageSY(im), gdImageSY(im)); + return; + } + } + + /* erase mask: for composite layers, tells whether the color pixel + should be combined back to the master image; white means combine back, + anything else means cut-out/forget/ignore that pixel */ + if (erase_im == NULL) { + erase_im = gdImageCreate(gdImageSX(im), gdImageSY(im)); + if (!erase_im) { + pcb_message(PCB_MSG_ERROR, "png_set_drawing_mode(): gdImageCreate(%d, %d) returned NULL on erase_im. Corrupt export!\n", gdImageSY(im), gdImageSY(im)); + return; + } + } + gdImagePaletteCopy(comp_im, im); + dst_im = im; + gdImageFilledRectangle(comp_im, 0, 0, gdImageSX(comp_im), gdImageSY(comp_im), white->c); + + gdImagePaletteCopy(erase_im, im); + gdImageFilledRectangle(erase_im, 0, 0, gdImageSX(erase_im), gdImageSY(erase_im), black->c); + break; + + case PCB_HID_COMP_POSITIVE: + case PCB_HID_COMP_POSITIVE_XOR: + im = comp_im; + break; + case PCB_HID_COMP_NEGATIVE: + im = erase_im; + break; + + case PCB_HID_COMP_FLUSH: + { + int x, y, c, e; + im = dst_im; + gdImagePaletteCopy(im, comp_im); + for (x = 0; x < gdImageSX(im); x++) { + for (y = 0; y < gdImageSY(im); y++) { + e = gdImageGetPixel(erase_im, x, y); + c = gdImageGetPixel(comp_im, x, y); + if ((e == white->c) && (c)) + gdImageSetPixel(im, x, y, c); + } + } + break; + } + } +} + +static void png_set_color(pcb_hid_gc_t gc, const pcb_color_t *color) +{ + pcb_hidval_t cval; + + if (im == NULL) + return; + + if (color == NULL) + color = pcb_color_red; + + if (pcb_color_is_drill(color)) { + gc->color = white; + gc->is_erase = 1; + return; + } + gc->is_erase = 0; + + if (in_mono || (strcmp(color->str, "#000000") == 0)) { + gc->color = black; + return; + } + + if (pcb_hid_cache_color(0, color->str, &cval, &color_cache)) { + gc->color = (color_struct *) cval.ptr; + } + else if (color->str[0] == '#') { + gc->color = (color_struct *) malloc(sizeof(color_struct)); + gc->color->r = color->r; + gc->color->g = color->g; + gc->color->b = color->b; + gc->color->c = gdImageColorAllocate(im, gc->color->r, gc->color->g, gc->color->b); + if (gc->color->c == BADC) { + pcb_message(PCB_MSG_ERROR, "png_set_color(): gdImageColorAllocate() returned NULL. Aborting export.\n"); + return; + } + cval.ptr = gc->color; + pcb_hid_cache_color(1, color->str, &cval, &color_cache); + } + else { + fprintf(stderr, "WE SHOULD NOT BE HERE!!!\n"); + gc->color = black; + } + +} + +static void png_set_line_cap(pcb_hid_gc_t gc, pcb_cap_style_t style) +{ + gc->cap = style; +} + +static void png_set_line_width(pcb_hid_gc_t gc, pcb_coord_t width) +{ + gc->width = width; +} + +static void png_set_draw_xor(pcb_hid_gc_t gc, int xor_) +{ + ; +} + +static int unerase_override = 0; +static void use_gc(gdImagePtr im, pcb_hid_gc_t gc) +{ + int need_brush = 0; + unsigned int gc_r = gc->color->r, gc_g = gc->color->g, gc_b = gc->color->b; + + if (unerase_override) { + gc_r = -1; + gc_g = -1; + gc_b = -1; + } + else { + gc_r = gc->color->r; + gc_g = gc->color->g; + gc_b = gc->color->b; + } + + if (gc->me_pointer != &png_hid) { + fprintf(stderr, "Fatal: GC from another HID passed to png HID\n"); + abort(); + } + + if (linewidth != gc->width) { + /* Make sure the scaling doesn't erase lines completely */ + if (SCALE(gc->width) == 0 && gc->width > 0) + gdImageSetThickness(im, 1); + else + gdImageSetThickness(im, SCALE(gc->width + 2 * bloat)); + linewidth = gc->width; + need_brush = 1; + } + + need_brush |= (gc_r != last_color_r) || (gc_g != last_color_g) || (gc_b != last_color_b) || (gc->cap != last_cap); + + if (lastbrush != gc->brush || need_brush) { + pcb_hidval_t bval; + char name[256]; + char type; + int r; + + switch (gc->cap) { + case pcb_cap_round: + type = 'C'; + break; + case pcb_cap_square: + type = 'S'; + break; + default: + assert(!"unhandled cap"); + type = 'C'; + } + if (gc->width) + r = SCALE(gc->width + 2 * bloat); + else + r = 1; + + /* do not allow a brush size that is zero width. In this case limit to a single pixel. */ + if (r == 0) { + r = 1; + } + + sprintf(name, "#%.2x%.2x%.2x_%c_%d", gc_r, gc_g, gc_b, type, r); + + last_color_r = gc_r; + last_color_g = gc_g; + last_color_b = gc_b; + last_cap = gc->cap; + + if (pcb_hid_cache_color(0, name, &bval, &brush_cache)) { + gc->brush = (gdImagePtr) bval.ptr; + } + else { + int bg, fg; + gc->brush = gdImageCreate(r, r); + if (gc->brush == NULL) { + pcb_message(PCB_MSG_ERROR, "use_gc(): gdImageCreate(%d, %d) returned NULL. Aborting export.\n", r, r); + return; + } + + bg = gdImageColorAllocate(gc->brush, 255, 255, 255); + if (bg == BADC) { + pcb_message(PCB_MSG_ERROR, "use_gc(): gdImageColorAllocate() returned NULL. Aborting export.\n"); + return; + } + if (unerase_override) + fg = gdImageColorAllocateAlpha(gc->brush, 255, 255, 255, 0); + else + fg = gdImageColorAllocateAlpha(gc->brush, gc_r, gc_g, gc_b, 0); + if (fg == BADC) { + pcb_message(PCB_MSG_ERROR, "use_gc(): gdImageColorAllocate() returned NULL. Aborting export.\n"); + return; + } + gdImageColorTransparent(gc->brush, bg); + + /* + * if we shrunk to a radius/box width of zero, then just use + * a single pixel to draw with. + */ + if (r <= 1) + gdImageFilledRectangle(gc->brush, 0, 0, 0, 0, fg); + else { + if (type == 'C') { + gdImageFilledEllipse(gc->brush, r / 2, r / 2, r, r, fg); + /* Make sure the ellipse is the right exact size. */ + gdImageSetPixel(gc->brush, 0, r / 2, fg); + gdImageSetPixel(gc->brush, r - 1, r / 2, fg); + gdImageSetPixel(gc->brush, r / 2, 0, fg); + gdImageSetPixel(gc->brush, r / 2, r - 1, fg); + } + else + gdImageFilledRectangle(gc->brush, 0, 0, r - 1, r - 1, fg); + } + bval.ptr = gc->brush; + pcb_hid_cache_color(1, name, &bval, &brush_cache); + } + + gdImageSetBrush(im, gc->brush); + lastbrush = gc->brush; + + } +} + + +static void png_fill_rect_(gdImagePtr im, pcb_hid_gc_t gc, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2) +{ + use_gc(im, gc); + gdImageSetThickness(im, 0); + linewidth = 0; + + if (x1 > x2) { + pcb_coord_t t = x1; + x2 = x2; + x2 = t; + } + if (y1 > y2) { + pcb_coord_t t = y1; + y2 = y2; + y2 = t; + } + y1 -= bloat; + y2 += bloat; + SWAP_IF_SOLDER(y1, y2); + + gdImageFilledRectangle(im, SCALE_X(x1 - bloat), SCALE_Y(y1), SCALE_X(x2 + bloat) - 1, SCALE_Y(y2) - 1, unerase_override ? white->c : gc->color->c); + have_outline |= doing_outline; +} + +static void png_fill_rect(pcb_hid_gc_t gc, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2) +{ + png_fill_rect_(im, gc, x1, y1, x2, y2); + if ((im != erase_im) && (erase_im != NULL)) { + unerase_override = 1; + png_fill_rect_(erase_im, gc, x1, y1, x2, y2); + unerase_override = 0; + } +} + + +static void png_draw_line_(gdImagePtr im, pcb_hid_gc_t gc, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2) +{ + int x1o = 0, y1o = 0, x2o = 0, y2o = 0; + if (x1 == x2 && y1 == y2 && !photo_mode) { + pcb_coord_t w = gc->width / 2; + if (gc->cap != pcb_cap_square) + png_fill_circle(gc, x1, y1, w); + else + png_fill_rect(gc, x1 - w, y1 - w, x1 + w, y1 + w); + return; + } + use_gc(im, gc); + + if (NOT_EDGE(x1, y1) || NOT_EDGE(x2, y2)) + have_outline |= doing_outline; + if (doing_outline) { + /* Special case - lines drawn along the bottom or right edges + are brought in by a pixel to make sure we have contiguous + outlines. */ + if (x1 == PCB->MaxWidth && x2 == PCB->MaxWidth) { + x1o = -1; + x2o = -1; + } + if (y1 == PCB->MaxHeight && y2 == PCB->MaxHeight) { + y1o = -1; + y2o = -1; + } + } + + gdImageSetThickness(im, 0); + linewidth = 0; + if (gc->cap != pcb_cap_square || x1 == x2 || y1 == y2) { + gdImageLine(im, SCALE_X(x1) + x1o, SCALE_Y(y1) + y1o, SCALE_X(x2) + x2o, SCALE_Y(y2) + y2o, gdBrushed); + } + else { + /* + * if we are drawing a line with a square end cap and it is + * not purely horizontal or vertical, then we need to draw + * it as a filled polygon. + */ + int fg, w = gc->width, dx = x2 - x1, dy = y2 - y1, dwx, dwy; + gdPoint p[4]; + double l = sqrt((double)dx * (double)dx + (double)dy * (double)dy) * 2.0; + + if (unerase_override) + fg = gdImageColorResolve(im, 255, 255, 255); + else + fg = gdImageColorResolve(im, gc->color->r, gc->color->g, gc->color->b); + + w += 2 * bloat; + dwx = -w / l * dy; + dwy = w / l * dx; + p[0].x = SCALE_X(x1 + dwx - dwy); + p[0].y = SCALE_Y(y1 + dwy + dwx); + p[1].x = SCALE_X(x1 - dwx - dwy); + p[1].y = SCALE_Y(y1 - dwy + dwx); + p[2].x = SCALE_X(x2 - dwx + dwy); + p[2].y = SCALE_Y(y2 - dwy - dwx); + p[3].x = SCALE_X(x2 + dwx + dwy); + p[3].y = SCALE_Y(y2 + dwy - dwx); + gdImageFilledPolygon(im, p, 4, fg); + } +} + +static void png_draw_line(pcb_hid_gc_t gc, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2) +{ + png_draw_line_(im, gc, x1, y1, x2, y2); + if ((im != erase_im) && (erase_im != NULL)) { + unerase_override = 1; + png_draw_line_(erase_im, gc, x1, y1, x2, y2); + unerase_override = 0; + } +} + +static void png_draw_rect(pcb_hid_gc_t gc, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2) +{ + png_draw_line(gc, x1, y1, x2, y1); + png_draw_line(gc, x2, y1, x2, y2); + png_draw_line(gc, x2, y2, x1, y2); + png_draw_line(gc, x1, y2, x1, y1); +} + + +static void png_draw_arc_(gdImagePtr im, pcb_hid_gc_t gc, pcb_coord_t cx, pcb_coord_t cy, pcb_coord_t width, pcb_coord_t height, pcb_angle_t start_angle, pcb_angle_t delta_angle) +{ + pcb_angle_t sa, ea; + + use_gc(im, gc); + gdImageSetThickness(im, 0); + linewidth = 0; + + /* + * zero angle arcs need special handling as gd will output either + * nothing at all or a full circle when passed delta angle of 0 or 360. + */ + if (delta_angle == 0) { + pcb_coord_t x = (width * cos(start_angle * M_PI / 180)); + pcb_coord_t y = (width * sin(start_angle * M_PI / 180)); + x = cx - x; + y = cy + y; + png_fill_circle(gc, x, y, gc->width / 2); + return; + } + + if ((delta_angle >= 360) || (delta_angle <= -360)) { + /* save some expensive calculations if we are going to draw a full circle anyway */ + sa = 0; + ea = 360; + } + else { + /* + * in gdImageArc, 0 degrees is to the right and +90 degrees is down + * in pcb, 0 degrees is to the left and +90 degrees is down + */ + start_angle = 180 - start_angle; + delta_angle = -delta_angle; + if (show_solder_side) { + start_angle = -start_angle; + delta_angle = -delta_angle; + } + if (delta_angle > 0) { + sa = start_angle; + ea = start_angle + delta_angle; + } + else { + sa = start_angle + delta_angle; + ea = start_angle; + } + + /* + * make sure we start between 0 and 360 otherwise gd does + * strange things + */ + sa = pcb_normalize_angle(sa); + ea = pcb_normalize_angle(ea); + } + + have_outline |= doing_outline; + +#if 0 + printf("draw_arc %d,%d %dx%d %d..%d %d..%d\n", cx, cy, width, height, start_angle, delta_angle, sa, ea); + printf("gdImageArc (%p, %d, %d, %d, %d, %d, %d, %d)\n", + (void *)im, SCALE_X(cx), SCALE_Y(cy), SCALE(width), SCALE(height), sa, ea, gc->color->c); +#endif + gdImageArc(im, SCALE_X(cx), SCALE_Y(cy), SCALE(2 * width), SCALE(2 * height), sa, ea, gdBrushed); +} + +static void png_draw_arc(pcb_hid_gc_t gc, pcb_coord_t cx, pcb_coord_t cy, pcb_coord_t width, pcb_coord_t height, pcb_angle_t start_angle, pcb_angle_t delta_angle) +{ + png_draw_arc_(im, gc, cx, cy, width, height, start_angle, delta_angle); + if ((im != erase_im) && (erase_im != NULL)) { + unerase_override = 1; + png_draw_arc_(erase_im, gc, cx, cy, width, height, start_angle, delta_angle); + unerase_override = 0; + } +} + +static void png_fill_circle_(gdImagePtr im, pcb_hid_gc_t gc, pcb_coord_t cx, pcb_coord_t cy, pcb_coord_t radius) +{ + pcb_coord_t my_bloat; + + use_gc(im, gc); + + if (gc->is_erase) + my_bloat = -2 * bloat; + else + my_bloat = 2 * bloat; + + have_outline |= doing_outline; + + gdImageSetThickness(im, 0); + linewidth = 0; + gdImageFilledEllipse(im, SCALE_X(cx), SCALE_Y(cy), SCALE(2 * radius + my_bloat), SCALE(2 * radius + my_bloat), unerase_override ? white->c : gc->color->c); +} + +static void png_fill_circle(pcb_hid_gc_t gc, pcb_coord_t cx, pcb_coord_t cy, pcb_coord_t radius) +{ + png_fill_circle_(im, gc, cx, cy, radius); + if ((im != erase_im) && (erase_im != NULL)) { + unerase_override = 1; + png_fill_circle_(erase_im, gc, cx, cy, radius); + unerase_override = 0; + } +} + + +static void png_fill_polygon_offs_(gdImagePtr im, pcb_hid_gc_t gc, int n_coords, pcb_coord_t *x, pcb_coord_t *y, pcb_coord_t dx, pcb_coord_t dy) +{ + int i; + gdPoint *points; + + points = (gdPoint *) malloc(n_coords * sizeof(gdPoint)); + if (points == NULL) { + fprintf(stderr, "ERROR: png_fill_polygon(): malloc failed\n"); + exit(1); + } + + use_gc(im, gc); + for (i = 0; i < n_coords; i++) { + if (NOT_EDGE(x[i], y[i])) + have_outline |= doing_outline; + points[i].x = SCALE_X(x[i]+dx); + points[i].y = SCALE_Y(y[i]+dy); + } + gdImageSetThickness(im, 0); + linewidth = 0; + gdImageFilledPolygon(im, points, n_coords, unerase_override ? white->c : gc->color->c); + free(points); +} + +static void png_fill_polygon_offs(pcb_hid_gc_t gc, int n_coords, pcb_coord_t *x, pcb_coord_t *y, pcb_coord_t dx, pcb_coord_t dy) +{ + png_fill_polygon_offs_(im, gc, n_coords, x, y, dx, dy); + if ((im != erase_im) && (erase_im != NULL)) { + unerase_override = 1; + png_fill_polygon_offs_(erase_im, gc, n_coords, x, y, dx, dy); + unerase_override = 0; + } +} + + +static void png_fill_polygon(pcb_hid_gc_t gc, int n_coords, pcb_coord_t *x, pcb_coord_t *y) +{ + png_fill_polygon_offs(gc, n_coords, x, y, 0, 0); +} + + +static void png_calibrate(double xval, double yval) +{ + CRASH("png_calibrate"); +} + +static void png_set_crosshair(pcb_coord_t x, pcb_coord_t y, int a) +{ +} + +static int png_usage(const char *topic) +{ + fprintf(stderr, "\npng exporter command line arguments:\n\n"); + pcb_hid_usage(png_attribute_list, sizeof(png_attribute_list) / sizeof(png_attribute_list[0])); + fprintf(stderr, "\nUsage: pcb-rnd [generic_options] -x png [png options] foo.pcb\n\n"); + return 0; +} + +#include "dolists.h" + +int pplg_check_ver_export_png(int ver_needed) { return 0; } + +void pplg_uninit_export_png(void) +{ + pcb_hid_remove_attributes_by_cookie(png_cookie); +} + +int pplg_init_export_png(void) +{ + PCB_API_CHK_VER; + + memset(&png_hid, 0, sizeof(pcb_hid_t)); + + pcb_hid_nogui_init(&png_hid); + pcb_dhlp_draw_helpers_init(&png_hid); + + png_hid.struct_size = sizeof(pcb_hid_t); + png_hid.name = "png"; + png_hid.description = "GIF/JPEG/PNG export"; + png_hid.exporter = 1; + + png_hid.get_export_options = png_get_export_options; + png_hid.do_export = png_do_export; + png_hid.parse_arguments = png_parse_arguments; + png_hid.set_layer_group = png_set_layer_group; + png_hid.make_gc = png_make_gc; + png_hid.destroy_gc = png_destroy_gc; + png_hid.set_drawing_mode = png_set_drawing_mode; + png_hid.set_color = png_set_color; + png_hid.set_line_cap = png_set_line_cap; + png_hid.set_line_width = png_set_line_width; + png_hid.set_draw_xor = png_set_draw_xor; + png_hid.draw_line = png_draw_line; + png_hid.draw_arc = png_draw_arc; + png_hid.draw_rect = png_draw_rect; + png_hid.fill_circle = png_fill_circle; + png_hid.fill_polygon = png_fill_polygon; + png_hid.fill_polygon_offs = png_fill_polygon_offs; + png_hid.fill_rect = png_fill_rect; + png_hid.calibrate = png_calibrate; + png_hid.set_crosshair = png_set_crosshair; + + png_hid.usage = png_usage; + +#ifdef HAVE_SOME_FORMAT + pcb_hid_register_hid(&png_hid); + +#endif + return 0; +} Index: tags/2.1.2/src_plugins/export_png/png.h =================================================================== --- tags/2.1.2/src_plugins/export_png/png.h (nonexistent) +++ tags/2.1.2/src_plugins/export_png/png.h (revision 24813) @@ -0,0 +1,2 @@ +extern const char *png_cookie; +extern void png_hid_export_to_file(FILE *, pcb_hid_attr_val_t *); Index: tags/2.1.2/src_plugins/export_ps/Makefile =================================================================== --- tags/2.1.2/src_plugins/export_ps/Makefile (nonexistent) +++ tags/2.1.2/src_plugins/export_ps/Makefile (revision 24813) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_export_ps + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/2.1.2/src_plugins/export_ps/Plug.tmpasm =================================================================== --- tags/2.1.2/src_plugins/export_ps/Plug.tmpasm (nonexistent) +++ tags/2.1.2/src_plugins/export_ps/Plug.tmpasm (revision 24813) @@ -0,0 +1,8 @@ +put /local/pcb/mod {export_ps} +put /local/pcb/mod/OBJS [@ $(PLUGDIR)/export_ps/ps.o $(PLUGDIR)/export_ps/eps.o @] + +switch /local/pcb/export_ps/controls + case {buildin} include /local/pcb/tmpasm/buildin; end; + case {plugin} include /local/pcb/tmpasm/plugin; end; + case {disable} include /local/pcb/tmpasm/disable; end; +end Index: tags/2.1.2/src_plugins/export_ps/eps.c =================================================================== --- tags/2.1.2/src_plugins/export_ps/eps.c (nonexistent) +++ tags/2.1.2/src_plugins/export_ps/eps.c (revision 24813) @@ -0,0 +1,708 @@ +#include "config.h" +#include "conf_core.h" + +#include +#include +#include +#include +#include + +#include "math_helper.h" +#include "board.h" +#include "data.h" +#include "draw.h" +#include "layer.h" +#include "layer_vis.h" +#include "pcb-printf.h" +#include "safe_fs.h" + +#include "hid.h" +#include "hid_nogui.h" +#include "hid_draw_helpers.h" +#include "ps.h" +#include "hid_init.h" +#include "hid_attrib.h" +#include "hid_cam.h" +#include "hid_color.h" +#include "funchash_core.h" + +#define CRASH(func) fprintf(stderr, "HID error: pcb called unimplemented EPS function %s.\n", func); abort() + +/*----------------------------------------------------------------------------*/ +/* Function prototypes */ +/*----------------------------------------------------------------------------*/ +static pcb_hid_attribute_t *eps_get_export_options(int *n); +static void eps_do_export(pcb_hid_attr_val_t * options); +static int eps_parse_arguments(int *argc, char ***argv); +static int eps_set_layer_group(pcb_layergrp_id_t group, const char *purpose, int purpi, pcb_layer_id_t layer, unsigned int flags, int is_empty, pcb_xform_t **xform); +static pcb_hid_gc_t eps_make_gc(void); +static void eps_destroy_gc(pcb_hid_gc_t gc); +static void eps_set_color(pcb_hid_gc_t gc, const pcb_color_t *name); +static void eps_set_line_cap(pcb_hid_gc_t gc, pcb_cap_style_t style); +static void eps_set_line_width(pcb_hid_gc_t gc, pcb_coord_t width); +static void eps_set_draw_xor(pcb_hid_gc_t gc, int _xor); +static void eps_draw_rect(pcb_hid_gc_t gc, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2); +static void eps_draw_line(pcb_hid_gc_t gc, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2); +static void eps_draw_arc(pcb_hid_gc_t gc, pcb_coord_t cx, pcb_coord_t cy, pcb_coord_t width, pcb_coord_t height, pcb_angle_t start_angle, pcb_angle_t delta_angle); +static void eps_fill_rect(pcb_hid_gc_t gc, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2); +static void eps_fill_circle(pcb_hid_gc_t gc, pcb_coord_t cx, pcb_coord_t cy, pcb_coord_t radius); +static void eps_fill_polygon(pcb_hid_gc_t gc, int n_coords, pcb_coord_t * x, pcb_coord_t * y); +static void eps_fill_polygon_offs(pcb_hid_gc_t gc, int n_coords, pcb_coord_t *x, pcb_coord_t *y, pcb_coord_t dx, pcb_coord_t dy); +static void eps_calibrate(double xval, double yval); +static void eps_set_crosshair(pcb_coord_t x, pcb_coord_t y, int action); +/*----------------------------------------------------------------------------*/ + +static pcb_cam_t eps_cam; + +typedef struct hid_gc_s { + pcb_core_gc_t core_gc; + pcb_cap_style_t cap; + pcb_coord_t width; + int color; + int erase; + +} hid_gc_s; + +static pcb_hid_t eps_hid; + +static FILE *f = 0; +static pcb_coord_t linewidth = -1; +static int lastcap = -1; +static int lastcolor = -1; +static int print_group[PCB_MAX_LAYERGRP]; +static int print_layer[PCB_MAX_LAYER]; +static int fast_erase = -1; +static pcb_composite_op_t drawing_mode; + +static pcb_hid_attribute_t eps_attribute_list[] = { + /* other HIDs expect this to be first. */ + +/* %start-doc options "92 Encapsulated Postscript Export" +@ftable @code +@item --eps-file +Name of the encapsulated postscript output file. Can contain a path. +@end ftable +%end-doc +*/ + {"eps-file", "Encapsulated Postscript output file", + PCB_HATT_STRING, 0, 0, {0, 0, 0}, 0, 0}, +#define HA_psfile 0 + +/* %start-doc options "92 Encapsulated Postscript Export" +@ftable @code +@item --eps-scale +Scale EPS output by the parameter @samp{num}. +@end ftable +%end-doc +*/ + {"eps-scale", "EPS scale", + PCB_HATT_REAL, 0, 100, {0, 0, 1.0}, 0, 0}, +#define HA_scale 1 + +/* %start-doc options "92 Encapsulated Postscript Export" +@ftable @code +@cindex as-shown (EPS) +@item --as-shown +Export layers as shown on screen. +@end ftable +%end-doc +*/ + {"as-shown", "Export layers as shown on screen", + PCB_HATT_BOOL, 0, 0, {0, 0, 0}, 0, 0}, +#define HA_as_shown 2 + +/* %start-doc options "92 Encapsulated Postscript Export" +@ftable @code +@item --monochrome +Convert output to monochrome. +@end ftable +%end-doc +*/ + {"monochrome", "Convert to monochrome", + PCB_HATT_BOOL, 0, 0, {0, 0, 0}, 0, 0}, +#define HA_mono 3 + +/* %start-doc options "92 Encapsulated Postscript Export" +@ftable @code +@cindex only-visible +@item --only-visible +Limit the bounds of the EPS file to the visible items. +@end ftable +%end-doc +*/ + {"only-visible", "Limit the bounds of the EPS file to the visible items", + PCB_HATT_BOOL, 0, 0, {0, 0, 0}, 0, 0}, +#define HA_only_visible 4 + + {"cam", "CAM instruction", + PCB_HATT_STRING, 0, 0, {0, 0, 0}, 0, 0}, +#define HA_cam 5 + +}; + +#define NUM_OPTIONS (sizeof(eps_attribute_list)/sizeof(eps_attribute_list[0])) + +PCB_REGISTER_ATTRIBUTES(eps_attribute_list, ps_cookie) + +static pcb_hid_attr_val_t eps_values[NUM_OPTIONS]; + +static pcb_hid_attribute_t *eps_get_export_options(int *n) +{ + if ((PCB != NULL) && (eps_attribute_list[HA_psfile].default_val.str_value == NULL)) + pcb_derive_default_filename(PCB->Filename, &eps_attribute_list[HA_psfile], ".eps"); + + if (n) + *n = NUM_OPTIONS; + return eps_attribute_list; +} + +static pcb_layergrp_id_t group_for_layer(int l) +{ + if (l < pcb_max_layer && l >= 0) + return pcb_layer_get_group(PCB, l); + /* else something unique */ + return pcb_max_group(PCB) + 3 + l; +} + +static int is_solder(pcb_layergrp_id_t grp) { return pcb_layergrp_flags(PCB, grp) & PCB_LYT_BOTTOM; } +static int is_component(pcb_layergrp_id_t grp) { return pcb_layergrp_flags(PCB, grp) & PCB_LYT_TOP; } + +static int layer_sort(const void *va, const void *vb) +{ + int a = *(int *) va; + int b = *(int *) vb; + pcb_layergrp_id_t al = group_for_layer(a); + pcb_layergrp_id_t bl = group_for_layer(b); + int d = bl - al; + + if (a >= 0 && a < pcb_max_layer) { + int aside = (is_solder(al) ? 0 : is_component(al) ? 2 : 1); + int bside = (is_solder(bl) ? 0 : is_component(bl) ? 2 : 1); + if (bside != aside) + return bside - aside; + } + if (d) + return d; + return b - a; +} + +static const char *filename; +static pcb_box_t *bounds; +static int in_mono, as_shown; + +static pcb_hid_attr_val_t *options_; +static void eps_print_header(FILE *f, const char *outfn) +{ + linewidth = -1; + lastcap = -1; + lastcolor = -1; + + fprintf(f, "%%!PS-Adobe-3.0 EPSF-3.0\n"); + +#define pcb2em(x) 1 + PCB_COORD_TO_INCH (x) * 72.0 * options_[HA_scale].real_value + fprintf(f, "%%%%BoundingBox: 0 0 %f %f\n", pcb2em(bounds->X2 - bounds->X1), pcb2em(bounds->Y2 - bounds->Y1)); +#undef pcb2em + fprintf(f, "%%%%Pages: 1\n"); + fprintf(f, "save countdictstack mark newpath /showpage {} def /setpagedevice {pop} def\n"); + fprintf(f, "%%%%EndProlog\n"); + fprintf(f, "%%%%Page: 1 1\n"); + + fprintf(f, "%%%%BeginDocument: %s\n\n", outfn); + + fprintf(f, "72 72 scale\n"); + fprintf(f, "1 dup neg scale\n"); + fprintf(f, "%g dup scale\n", options_[HA_scale].real_value); + pcb_fprintf(f, "%mi %mi translate\n", -bounds->X1, -bounds->Y2); + if (options_[HA_as_shown].int_value && conf_core.editor.show_solder_side) + pcb_fprintf(f, "-1 1 scale %mi 0 translate\n", bounds->X1 - bounds->X2); + +#define Q (pcb_coord_t) PCB_MIL_TO_COORD(10) + pcb_fprintf(f, + "/nclip { %mi %mi moveto %mi %mi lineto %mi %mi lineto %mi %mi lineto %mi %mi lineto eoclip newpath } def\n", + bounds->X1 - Q, bounds->Y1 - Q, bounds->X1 - Q, bounds->Y2 + Q, + bounds->X2 + Q, bounds->Y2 + Q, bounds->X2 + Q, bounds->Y1 - Q, bounds->X1 - Q, bounds->Y1 - Q); +#undef Q + fprintf(f, "/t { moveto lineto stroke } bind def\n"); + fprintf(f, "/tc { moveto lineto strokepath nclip } bind def\n"); + fprintf(f, "/r { /y2 exch def /x2 exch def /y1 exch def /x1 exch def\n"); + fprintf(f, " x1 y1 moveto x1 y2 lineto x2 y2 lineto x2 y1 lineto closepath fill } bind def\n"); + fprintf(f, "/c { 0 360 arc fill } bind def\n"); + fprintf(f, "/cc { 0 360 arc nclip } bind def\n"); + fprintf(f, "/a { gsave setlinewidth translate scale 0 0 1 5 3 roll arc stroke grestore} bind def\n"); +} + +static void eps_print_footer(FILE *f) +{ + fprintf(f, "showpage\n"); + + fprintf(f, "%%%%EndDocument\n"); + fprintf(f, "%%%%Trailer\n"); + fprintf(f, "cleartomark countdictstack exch sub { end } repeat restore\n"); + fprintf(f, "%%%%EOF\n"); +} + +void eps_hid_export_to_file(FILE * the_file, pcb_hid_attr_val_t *options) +{ + int i; + static int saved_layer_stack[PCB_MAX_LAYER]; + pcb_box_t tmp, region; + pcb_hid_expose_ctx_t ctx; + + options_ = options; + + conf_force_set_bool(conf_core.editor.thin_draw, 0); + conf_force_set_bool(conf_core.editor.thin_draw_poly, 0); + conf_force_set_bool(conf_core.editor.check_planes, 0); + + f = the_file; + + region.X1 = 0; + region.Y1 = 0; + region.X2 = PCB->MaxWidth; + region.Y2 = PCB->MaxHeight; + + if (options[HA_only_visible].int_value) + bounds = pcb_data_bbox(&tmp, PCB->Data, pcb_false); + else + bounds = ®ion; + + memset(print_group, 0, sizeof(print_group)); + memset(print_layer, 0, sizeof(print_layer)); + + /* Figure out which layers actually have stuff on them. */ + for (i = 0; i < pcb_max_layer; i++) { + pcb_layer_t *layer = PCB->Data->Layer + i; + if (pcb_layer_flags(PCB, i) & PCB_LYT_SILK) + continue; + if (layer->meta.real.vis) + if (!pcb_layer_is_empty_(PCB, layer)) + print_group[pcb_layer_get_group(PCB, i)] = 1; + } + + /* Now, if only one layer has real stuff on it, we can use the fast + erase logic. Otherwise, we have to use the expensive multi-mask + erase. */ + fast_erase = 0; + for (i = 0; i < pcb_max_group(PCB); i++) + if (print_group[i]) + fast_erase++; + + /* If NO layers had anything on them, at least print the component + layer to get the pins. */ + if (fast_erase == 0) { + pcb_layergrp_id_t comp_copp; + if (pcb_layergrp_list(PCB, PCB_LYT_TOP | PCB_LYT_COPPER, &comp_copp, 1) > 0) { + print_group[pcb_layer_get_group(PCB, comp_copp)] = 1; + fast_erase = 1; + } + } + + /* "fast_erase" is 1 if we can just paint white to erase. */ + fast_erase = fast_erase == 1 ? 1 : 0; + + /* Now, for each group we're printing, mark its layers for + printing. */ + for (i = 0; i < pcb_max_layer; i++) { + if (pcb_layer_flags(PCB, i) & PCB_LYT_SILK) + continue; + if (print_group[pcb_layer_get_group(PCB, i)]) + print_layer[i] = 1; + } + + memcpy(saved_layer_stack, pcb_layer_stack, sizeof(pcb_layer_stack)); + as_shown = options[HA_as_shown].int_value; + if (!options[HA_as_shown].int_value) { + qsort(pcb_layer_stack, pcb_max_layer, sizeof(pcb_layer_stack[0]), layer_sort); + } + linewidth = -1; + lastcap = -1; + lastcolor = -1; + + in_mono = options[HA_mono].int_value; + + if (f != NULL) + eps_print_header(f, pcb_hid_export_fn(filename)); + + ctx.view = *bounds; + pcb_hid_expose_all(&eps_hid, &ctx, NULL); + + eps_print_footer(f); + + memcpy(pcb_layer_stack, saved_layer_stack, sizeof(pcb_layer_stack)); + conf_update(NULL, -1); /* restore forced sets */ + options_ = NULL; +} + +static void eps_do_export(pcb_hid_attr_val_t * options) +{ + int i; + int save_ons[PCB_MAX_LAYER + 2]; + + if (!options) { + eps_get_export_options(0); + for (i = 0; i < NUM_OPTIONS; i++) + eps_values[i] = eps_attribute_list[i].default_val; + options = eps_values; + } + + pcb_cam_begin(PCB, &eps_cam, options[HA_cam].str_value, eps_attribute_list, NUM_OPTIONS, options); + + filename = options[HA_psfile].str_value; + if (!filename) + filename = "pcb-out.eps"; + + if (eps_cam.fn_template == NULL) { + f = pcb_fopen(eps_cam.active ? eps_cam.fn : filename, "w"); + if (!f) { + perror(filename); + return; + } + } + else + f = NULL; + + if ((!eps_cam.active) && (!options[HA_as_shown].int_value)) + pcb_hid_save_and_show_layer_ons(save_ons); + eps_hid_export_to_file(f, options); + if ((!eps_cam.active) && (!options[HA_as_shown].int_value)) + pcb_hid_restore_layer_ons(save_ons); + + fclose(f); + + if (pcb_cam_end(&eps_cam) == 0) + pcb_message(PCB_MSG_ERROR, "eps cam export for '%s' failed to produce any content\n", options[HA_cam].str_value); +} + +static int eps_parse_arguments(int *argc, char ***argv) +{ + pcb_hid_register_attributes(eps_attribute_list, sizeof(eps_attribute_list) / sizeof(eps_attribute_list[0]), ps_cookie, 0); + return pcb_hid_parse_command_line(argc, argv); +} + +static int is_mask; +static int is_paste; +static int is_drill; + +static int eps_set_layer_group(pcb_layergrp_id_t group, const char *purpose, int purpi, pcb_layer_id_t layer, unsigned int flags, int is_empty, pcb_xform_t **xform) +{ + char tmp_ln[PCB_PATH_MAX]; + const char *name; + + if (flags & PCB_LYT_UI) + return 0; + + pcb_cam_set_layer_group(&eps_cam, group, purpose, purpi, flags, xform); + + if (eps_cam.fn_changed) { + if (f != NULL) { + eps_print_footer(f); + fclose(f); + } + f = pcb_fopen(eps_cam.fn, "w"); + eps_print_header(f, eps_cam.fn); + } + + if (!eps_cam.active) { + if (flags & PCB_LYT_NOEXPORT) + return 0; + + if (PCB_LAYER_IS_ASSY(flags, purpi) || PCB_LAYER_IS_FAB(flags, purpi) || PCB_LAYER_IS_CSECT(flags, purpi) || (flags & PCB_LYT_INVIS)) + return 0; + + if ((group >= 0) && pcb_layergrp_is_empty(PCB, group) && PCB_LAYER_IS_ROUTE(flags, purpi)) + return 0; + } + + is_drill = PCB_LAYER_IS_DRILL(flags, purpi); + is_mask = (flags & PCB_LYT_MASK); + is_paste = !!(flags & PCB_LYT_PASTE); + + if (is_mask || is_paste) + return 0; + + name = pcb_layer_to_file_name(tmp_ln, layer, flags, purpose, purpi, PCB_FNS_fixed); + +#if 0 + printf("Layer %s group %d drill %d mask %d\n", name, group, is_drill, is_mask); +#endif + fprintf(f, "%% Layer %s group %ld drill %d mask %d\n", name, group, is_drill, is_mask); + + if (as_shown) { + if (PCB_LAYERFLG_ON_VISIBLE_SIDE(flags)) + return pcb_silk_on(PCB); + else + return 0; + } + else { + if (((flags & PCB_LYT_ANYTHING) == PCB_LYT_SILK) && (flags & PCB_LYT_TOP)) + return 1; + if (((flags & PCB_LYT_ANYTHING) == PCB_LYT_SILK) && (flags & PCB_LYT_BOTTOM)) + return 0; + } + + return 1; +} + +static pcb_hid_gc_t eps_make_gc(void) +{ + pcb_hid_gc_t rv = (pcb_hid_gc_t) malloc(sizeof(hid_gc_s)); + rv->cap = pcb_cap_round; + rv->width = 0; + rv->color = 0; + return rv; +} + +static void eps_destroy_gc(pcb_hid_gc_t gc) +{ + free(gc); +} + +static void eps_set_drawing_mode(pcb_composite_op_t op, pcb_bool direct, const pcb_box_t *screen) +{ + if (direct) + return; + drawing_mode = op; + switch(op) { + case PCB_HID_COMP_RESET: + fprintf(f, "gsave\n"); + break; + + case PCB_HID_COMP_POSITIVE: + case PCB_HID_COMP_POSITIVE_XOR: + case PCB_HID_COMP_NEGATIVE: + break; + + case PCB_HID_COMP_FLUSH: + fprintf(f, "grestore\n"); + lastcolor = -1; + break; + } +} + + +static void eps_set_color(pcb_hid_gc_t gc, const pcb_color_t *color) +{ + static void *cache = 0; + pcb_hidval_t cval; + + if (drawing_mode == PCB_HID_COMP_NEGATIVE) { + gc->color = 0xffffff; + gc->erase = 1; + return; + } + if (pcb_color_is_drill(color)) { + gc->color = 0xffffff; + gc->erase = 0; + return; + } + gc->erase = 0; + if (pcb_hid_cache_color(0, color->str, &cval, &cache)) { + gc->color = cval.lval; + } + else if (in_mono) { + gc->color = 0; + } + else if (color->str[0] == '#') { + gc->color = (color->r << 16) + (color->g << 8) + color->b; + } + else + gc->color = 0; +} + +static void eps_set_line_cap(pcb_hid_gc_t gc, pcb_cap_style_t style) +{ + gc->cap = style; +} + +static void eps_set_line_width(pcb_hid_gc_t gc, pcb_coord_t width) +{ + gc->width = width; +} + +static void eps_set_draw_xor(pcb_hid_gc_t gc, int xor_) +{ + ; +} + +static void use_gc(pcb_hid_gc_t gc) +{ + if (linewidth != gc->width) { + pcb_fprintf(f, "%mi setlinewidth\n", gc->width); + linewidth = gc->width; + } + if (lastcap != gc->cap) { + int c; + switch (gc->cap) { + case pcb_cap_round: + c = 1; + break; + case pcb_cap_square: + c = 2; + break; + default: + assert(!"unhandled cap"); + c = 1; + } + fprintf(f, "%d setlinecap\n", c); + lastcap = gc->cap; + } + if (lastcolor != gc->color) { + int c = gc->color; +#define CV(x,b) (((x>>b)&0xff)/255.0) + fprintf(f, "%g %g %g setrgbcolor\n", CV(c, 16), CV(c, 8), CV(c, 0)); + lastcolor = gc->color; + } +} + +static void eps_fill_rect(pcb_hid_gc_t gc, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2); +static void eps_fill_circle(pcb_hid_gc_t gc, pcb_coord_t cx, pcb_coord_t cy, pcb_coord_t radius); + +static void eps_draw_rect(pcb_hid_gc_t gc, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2) +{ + use_gc(gc); + pcb_fprintf(f, "%mi %mi %mi %mi r\n", x1, y1, x2, y2); +} + +static void eps_draw_line(pcb_hid_gc_t gc, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2) +{ + pcb_coord_t w = gc->width / 2; + if (x1 == x2 && y1 == y2) { + if (gc->cap == pcb_cap_square) + eps_fill_rect(gc, x1 - w, y1 - w, x1 + w, y1 + w); + else + eps_fill_circle(gc, x1, y1, w); + return; + } + use_gc(gc); + if (gc->erase && gc->cap != pcb_cap_square) { + double ang = atan2(y2 - y1, x2 - x1); + double dx = w * sin(ang); + double dy = -w * cos(ang); + double deg = ang * 180.0 / M_PI; + pcb_coord_t vx1 = x1 + dx; + pcb_coord_t vy1 = y1 + dy; + + pcb_fprintf(f, "%mi %mi moveto ", vx1, vy1); + pcb_fprintf(f, "%mi %mi %mi %g %g arc\n", x2, y2, w, deg - 90, deg + 90); + pcb_fprintf(f, "%mi %mi %mi %g %g arc\n", x1, y1, w, deg + 90, deg + 270); + fprintf(f, "nclip\n"); + + return; + } + pcb_fprintf(f, "%mi %mi %mi %mi %s\n", x1, y1, x2, y2, gc->erase ? "tc" : "t"); +} + +static void eps_draw_arc(pcb_hid_gc_t gc, pcb_coord_t cx, pcb_coord_t cy, pcb_coord_t width, pcb_coord_t height, pcb_angle_t start_angle, pcb_angle_t delta_angle) +{ + pcb_angle_t sa, ea; + double w; + + if ((width == 0) && (height == 0)) { + /* degenerate case, draw dot */ + eps_draw_line(gc, cx, cy, cx, cy); + return; + } + + if (delta_angle > 0) { + sa = start_angle; + ea = start_angle + delta_angle; + } + else { + sa = start_angle + delta_angle; + ea = start_angle; + } +#if 0 + printf("draw_arc %d,%d %dx%d %d..%d %d..%d\n", cx, cy, width, height, start_angle, delta_angle, sa, ea); +#endif + use_gc(gc); + w = width; + if (w == 0) /* make sure not to div by zero; this hack will have very similar effect */ + w = 0.0001; + pcb_fprintf(f, "%ma %ma %mi %mi %mi %mi %f a\n", sa, ea, -width, height, cx, cy, (double) linewidth / w); +} + +static void eps_fill_circle(pcb_hid_gc_t gc, pcb_coord_t cx, pcb_coord_t cy, pcb_coord_t radius) +{ + use_gc(gc); + pcb_fprintf(f, "%mi %mi %mi %s\n", cx, cy, radius, gc->erase ? "cc" : "c"); +} + +static void eps_fill_polygon_offs(pcb_hid_gc_t gc, int n_coords, pcb_coord_t *x, pcb_coord_t *y, pcb_coord_t dx, pcb_coord_t dy) +{ + int i; + const char *op = "moveto"; + use_gc(gc); + for (i = 0; i < n_coords; i++) { + pcb_fprintf(f, "%mi %mi %s\n", x[i] + dx, y[i] + dy, op); + op = "lineto"; + } + + fprintf(f, "fill\n"); +} + +static void eps_fill_polygon(pcb_hid_gc_t gc, int n_coords, pcb_coord_t *x, pcb_coord_t *y) +{ + eps_fill_polygon_offs(gc, n_coords, x, y, 0, 0); +} + + +static void eps_fill_rect(pcb_hid_gc_t gc, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2) +{ + use_gc(gc); + pcb_fprintf(f, "%mi %mi %mi %mi r\n", x1, y1, x2, y2); +} + +static void eps_calibrate(double xval, double yval) +{ + CRASH("eps_calibrate"); +} + +static void eps_set_crosshair(pcb_coord_t x, pcb_coord_t y, int action) +{ +} + +static int eps_usage(const char *topic) +{ + fprintf(stderr, "\neps exporter command line arguments:\n\n"); + pcb_hid_usage(eps_attribute_list, sizeof(eps_attribute_list) / sizeof(eps_attribute_list[0])); + fprintf(stderr, "\nUsage: pcb-rnd [generic_options] -x eps [eps options] foo.pcb\n\n"); + return 0; +} + +void hid_eps_init() +{ + memset(&eps_hid, 0, sizeof(pcb_hid_t)); + + pcb_hid_nogui_init(&eps_hid); + pcb_dhlp_draw_helpers_init(&eps_hid); + + eps_hid.struct_size = sizeof(pcb_hid_t); + eps_hid.name = "eps"; + eps_hid.description = "Encapsulated Postscript"; + eps_hid.exporter = 1; + + eps_hid.get_export_options = eps_get_export_options; + eps_hid.do_export = eps_do_export; + eps_hid.parse_arguments = eps_parse_arguments; + eps_hid.set_layer_group = eps_set_layer_group; + eps_hid.make_gc = eps_make_gc; + eps_hid.destroy_gc = eps_destroy_gc; + eps_hid.set_drawing_mode = eps_set_drawing_mode; + eps_hid.set_color = eps_set_color; + eps_hid.set_line_cap = eps_set_line_cap; + eps_hid.set_line_width = eps_set_line_width; + eps_hid.set_draw_xor = eps_set_draw_xor; + eps_hid.draw_line = eps_draw_line; + eps_hid.draw_arc = eps_draw_arc; + eps_hid.draw_rect = eps_draw_rect; + eps_hid.fill_circle = eps_fill_circle; + eps_hid.fill_polygon = eps_fill_polygon; + eps_hid.fill_polygon_offs = eps_fill_polygon_offs; + eps_hid.fill_rect = eps_fill_rect; + eps_hid.calibrate = eps_calibrate; + eps_hid.set_crosshair = eps_set_crosshair; + + eps_hid.usage = eps_usage; + + pcb_hid_register_hid(&eps_hid); +} Index: tags/2.1.2/src_plugins/export_ps/export_ps.pup =================================================================== --- tags/2.1.2/src_plugins/export_ps/export_ps.pup (nonexistent) +++ tags/2.1.2/src_plugins/export_ps/export_ps.pup (revision 24813) @@ -0,0 +1,11 @@ +$class export +$short postscript pcb_exporter +$long Export postscript or embedded postscript. +$state works +$fmt-native no +$fmt-feature-w render black&white postscript (single or multiple files) +$fmt-feature-w render black&white or color embedded postscript (single file) +$package export +dep lib_compat_help +default buildin +autoload 1 Index: tags/2.1.2/src_plugins/export_ps/ps.c =================================================================== --- tags/2.1.2/src_plugins/export_ps/ps.c (nonexistent) +++ tags/2.1.2/src_plugins/export_ps/ps.c (revision 24813) @@ -0,0 +1,1513 @@ +#include "config.h" + +#include +#include /* not used */ +#include +#include +#include /* not used */ +#include + +#include "math_helper.h" +#include "board.h" +#include "data.h" +#include "layer.h" +#include "error.h" +#include "draw.h" +#include "pcb-printf.h" +#include "plugins.h" +#include "hid_cam.h" +#include "safe_fs.h" +#include "funchash_core.h" +#include "layer_vis.h" + +#include "hid.h" +#include "hid_nogui.h" +#include "hid_draw_helpers.h" +#include "ps.h" +#include "hid_init.h" +#include "hid_attrib.h" +#include "actions.h" +#include "conf_core.h" +#include "compat_misc.h" +#include "stub_draw.h" +#include "../src_plugins/lib_compat_help/media.h" + +const char *ps_cookie = "ps HID"; + +static int ps_set_layer_group(pcb_layergrp_id_t group, const char *purpose, int purpi, pcb_layer_id_t layer, unsigned int flags, int is_empty, pcb_xform_t **xform); +static void use_gc(pcb_hid_gc_t gc); + +typedef struct hid_gc_s { + pcb_core_gc_t core_gc; + pcb_hid_t *me_pointer; + pcb_cap_style_t cap; + pcb_coord_t width; + unsigned char r, g, b; + int erase; + int faded; +} hid_gc_s; + +static pcb_cam_t ps_cam; + +pcb_hid_attribute_t ps_attribute_list[] = { + /* other HIDs expect this to be first. */ + +/* %start-doc options "91 Postscript Export" +@ftable @code +@item --psfile +Name of the postscript output file. Can contain a path. +@end ftable +%end-doc +*/ + {"psfile", "Postscript output file", + PCB_HATT_STRING, 0, 0, {0, 0, 0}, 0, 0}, +#define HA_psfile 0 + +/* %start-doc options "91 Postscript Export" +@ftable @code +@cindex drill-helper +@item --drill-helper +Draw small holes to center drill but in copper +@end ftable +%end-doc +*/ + {"drill-helper", "Draw small holes to center drill but in copper", + PCB_HATT_BOOL, 0, 0, {0, 0, 0}, 0, 0}, +#define HA_drillhelper 1 + +/* %start-doc options "91 Postscript Export" +@ftable @code +@cindex align-marks +@item --align-marks +Print alignment marks on each sheet. This is meant to ease alignment during exposure. +@end ftable +%end-doc +*/ + {"align-marks", "Print alignment marks on each sheet", + PCB_HATT_BOOL, 0, 0, {1, 0, 0}, 0, 0}, +#define HA_alignmarks 2 + +/* %start-doc options "91 Postscript Export" +@ftable @code +@item --outline +Print the contents of the outline layer on each sheet. +@end ftable +%end-doc +*/ + {"outline", "Print outline on each sheet", + PCB_HATT_BOOL, 0, 0, {1, 0, 0}, 0, 0}, +#define HA_outline 3 +/* %start-doc options "91 Postscript Export" +@ftable @code +@item --mirror +Print mirror image. +@end ftable +%end-doc +*/ + {"mirror", "Print mirror image of every page", + PCB_HATT_BOOL, 0, 0, {0, 0, 0}, 0, 0}, +#define HA_mirror 4 + +/* %start-doc options "91 Postscript Export" +@ftable @code +@item --fill-page +Scale output to make the board fit the page. +@end ftable +%end-doc +*/ + {"fill-page", "Scale board to fill page", + PCB_HATT_BOOL, 0, 0, {0, 0, 0}, 0, 0}, +#define HA_fillpage 5 + +/* %start-doc options "91 Postscript Export" +@ftable @code +@item --auto-mirror +Print mirror image of appropriate layers. +@end ftable +%end-doc +*/ + {"auto-mirror", "Print mirror image of appropriate layers", + PCB_HATT_BOOL, 0, 0, {1, 0, 0}, 0, 0}, +#define HA_automirror 6 + +/* %start-doc options "91 Postscript Export" +@ftable @code +@item --ps-color +Postscript output in color. +@end ftable +%end-doc +*/ + {"ps-color", "Prints in color", + PCB_HATT_BOOL, 0, 0, {0, 0, 0}, 0, 0}, +#define HA_color 7 + +/* %start-doc options "91 Postscript Export" +@ftable @code +@cindex ps-invert +@item --ps-invert +Draw objects as white-on-black. +@end ftable +%end-doc +*/ + {"ps-invert", "Draw objects as white-on-black", + PCB_HATT_BOOL, 0, 0, {0, 0, 0}, 0, 0}, +#define HA_psinvert 8 + +/* %start-doc options "91 Postscript Export" +@ftable @code +@item --media +Size of the media, the postscript is fitted to. The parameter +@code{} can be any of the standard names for paper size: @samp{A0} +to @samp{A10}, @samp{B0} to @samp{B10}, @samp{Letter}, @samp{11x17}, +@samp{Ledger}, @samp{Legal}, @samp{Executive}, @samp{A-Size}, @samp{B-size}, +@samp{C-Size}, @samp{D-size}, @samp{E-size}, @samp{US-Business_Card}, +@samp{Intl-Business_Card}. +@end ftable +%end-doc +*/ + {"media", "media type", + PCB_HATT_ENUM, 0, 0, {22, 0, 0}, pcb_medias, 0}, +#define HA_media 9 + +/* %start-doc options "91 Postscript Export" +@ftable @code +@cindex psfade +@item --psfade +Fade amount for assembly drawings (0.0=missing, 1.0=solid). +@end ftable +%end-doc +*/ + {"psfade", "Fade amount for assembly drawings (0.0=missing, 1.0=solid)", + PCB_HATT_REAL, 0, 1, {0, 0, 0.40}, 0, 0}, +#define HA_psfade 10 + +/* %start-doc options "91 Postscript Export" +@ftable @code +@item --scale +Scale value to compensate for printer sizing errors (1.0 = full scale). +@end ftable +%end-doc +*/ + {"scale", "Scale value to compensate for printer sizing errors (1.0 = full scale)", + PCB_HATT_REAL, 0.01, 4, {0, 0, 1.00}, 0, 0}, +#define HA_scale 11 + +/* %start-doc options "91 Postscript Export" +@ftable @code +@cindex multi-file +@item --multi-file +Produce multiple files, one per page, instead of a single multi page file. +@end ftable +%end-doc +*/ + {"multi-file", "Produce multiple files, one per page, instead of a single file", + PCB_HATT_BOOL, 0, 0, {0, 0, 0.40}, 0, 0}, +#define HA_multifile 12 + +/* %start-doc options "91 Postscript Export" +@ftable @code +@item --xcalib +Paper width. Used for x-Axis calibration. +@end ftable +%end-doc +*/ + {"xcalib", "Paper width. Used for x-Axis calibration", + PCB_HATT_REAL, 0, 2, {0, 0, 1.0}, 0, 0}, +#define HA_xcalib 13 + +/* %start-doc options "91 Postscript Export" +@ftable @code +@item --ycalib +Paper height. Used for y-Axis calibration. +@end ftable +%end-doc +*/ + {"ycalib", "Paper height. Used for y-Axis calibration", + PCB_HATT_REAL, 0, 2, {0, 0, 1.0}, 0, 0}, +#define HA_ycalib 14 + +/* %start-doc options "91 Postscript Export" +@ftable @code +@item --drill-copper +Draw drill holes in pins / vias, instead of leaving solid copper. +@end ftable +%end-doc +*/ + {"drill-copper", "Draw drill holes in pins / vias, instead of leaving solid copper", + PCB_HATT_BOOL, 0, 0, {1, 0, 0}, 0, 0}, +#define HA_drillcopper 15 + +/* %start-doc options "91 Postscript Export" +@ftable @code +@cindex show-legend +@item --show-legend +Print file name and scale on printout. +@end ftable +%end-doc +*/ + {"show-legend", "Print file name and scale on printout", + PCB_HATT_BOOL, 0, 0, {1, 0, 0}, 0, 0}, +#define HA_legend 16 + +/* %start-doc options "91 Postscript Export" +@ftable @code +@cindex show-toc +@item --show-toc +Generate Table of Contents +@end ftable +%end-doc +*/ + {"show-toc", "Print Table of Content", + PCB_HATT_BOOL, 0, 0, {1, 0, 0}, 0, 0}, +#define HA_toc 17 + + +/* %start-doc options "91 Postscript Export" +@ftable @code +@cindex single-page +@item --single-page +Merge all drawings on a single page +@end ftable +%end-doc +*/ + {"single-page", "Merge all drawings on a single page", + PCB_HATT_BOOL, 0, 0, {0, 0, 0}, 0, 0}, +#define HA_single_page 18 + +/* %start-doc options "91 Postscript Export" +@ftable @code +@cindex drill-helper-size +@item --drill-helper-size +Diameter of the small hole when drill-helper is on +@end ftable +%end-doc +*/ + {"drill-helper-size", "Diameter of the small hole when drill-helper is on", + PCB_HATT_COORD, 0, 0, {0, 0, 0, PCB_MIN_PINORVIAHOLE}, 0, 0}, +#define HA_drillhelpersize 19 + + + {"cam", "CAM instruction", + PCB_HATT_STRING, 0, 0, {0, 0, 0}, 0, 0}, +#define HA_cam 20 + +}; + +#define NUM_OPTIONS (sizeof(ps_attribute_list)/sizeof(ps_attribute_list[0])) + +PCB_REGISTER_ATTRIBUTES(ps_attribute_list, ps_cookie) + +/* All file-scope data is in global struct */ +static struct { + double calibration_x, calibration_y; + + FILE *f; + int pagecount; + pcb_coord_t linewidth; + double fade_ratio; + pcb_bool multi_file; + pcb_bool multi_file_cam; + pcb_coord_t media_width, media_height, ps_width, ps_height; + + const char *filename; + pcb_bool drill_helper; + pcb_coord_t drill_helper_size; + pcb_bool align_marks; + pcb_bool outline; + pcb_bool mirror; + pcb_bool fillpage; + pcb_bool automirror; + pcb_bool incolor; + pcb_bool doing_toc; + pcb_bool invert; + int media_idx; + pcb_bool drillcopper; + pcb_bool legend; + pcb_bool single_page; + + int has_outline; + double scale_factor; + + pcb_hid_expose_ctx_t exps; + + pcb_hid_attr_val_t ps_values[NUM_OPTIONS]; + + pcb_bool is_mask; + pcb_bool is_drill; + pcb_bool is_assy; + pcb_bool is_copper; + pcb_bool is_paste; + + pcb_composite_op_t drawing_mode; +} global; + +static pcb_hid_attribute_t *ps_get_export_options(int *n) +{ + if ((PCB != NULL) && (ps_attribute_list[HA_psfile].default_val.str_value == NULL)) + pcb_derive_default_filename(PCB->Filename, &ps_attribute_list[HA_psfile], ".ps"); + + if (n) + *n = NUM_OPTIONS; + return ps_attribute_list; +} + +static pcb_layergrp_id_t group_for_layer(int l) +{ + if (l < pcb_max_layer && l >= 0) + return pcb_layer_get_group(PCB, l); + /* else something unique */ + return pcb_max_group(PCB) + 3 + l; +} + +static int layer_sort(const void *va, const void *vb) +{ + int a = *(int *) va; + int b = *(int *) vb; + int d = group_for_layer(b) - group_for_layer(a); + if (d) + return d; + return b - a; +} + +void ps_start_file(FILE * f) +{ + time_t currenttime = time(NULL); + + fprintf(f, "%%!PS-Adobe-3.0\n"); + + /* Document Structuring Conventions (DCS): */ + + /* Start General Header Comments: */ + + /* + * %%Title DCS provides text title for the document that is useful + * for printing banner pages. + */ + fprintf(f, "%%%%Title: %s\n", pcb_hid_export_fn(PCB->Filename)); + + /* + * %%CreationDate DCS indicates the date and time the document was + * created. Neither the date nor time need be in any standard + * format. This comment is meant to be used purely for informational + * purposes, such as printing on banner pages. + */ + fprintf(f, "%%%%CreationDate: %s", asctime(localtime(¤ttime))); + + /* + * %%Creator DCS indicates the document creator, usually the name of + * the document composition software. + */ + fprintf(f, "%%%%Creator: PCB release: pcb-rnd " PCB_VERSION "\n"); + + /* + * %%Version DCS comment can be used to note the version and + * revision number of a document or resource. A document manager may + * wish to provide version control services, or allow substitution + * of compatible versions/revisions of a resource or document. + * + * The format should be in the form of 'procname': + * ::= < name> < version> < revision> + * < name> ::= < text> + * < version> ::= < real> + * < revision> ::= < uint> + * + * If a version numbering scheme is not used, these fields should + * still be filled with a dummy value of 0. + * + * There is currently no code in PCB to manage this revision number. + * + */ + fprintf(f, "%%%%Version: (PCB pcb-rnd " PCB_VERSION ") 0.0 0\n"); + + + /* + * %%PageOrder DCS is intended to help document managers determine + * the order of pages in the document file, which in turn enables a + * document manager optionally to reorder the pages. 'Ascend'-The + * pages are in ascending order for example, 1-2-3-4-5-6. + */ + fprintf(f, "%%%%PageOrder: Ascend\n"); + + /* + * %%Pages: < numpages> | (atend) < numpages> ::= < uint> (Total + * %%number of pages) + * + * %%Pages DCS defines the number of virtual pages that a document + * will image. (atend) defers the count until the end of the file, + * which is useful for dynamically generated contents. + */ + fprintf(f, "%%%%Pages: (atend)\n"); + + /* + * %%DocumentMedia: + * + * Substitute 0 or "" for N/A. Width and height are in points + * (1/72"). + * + * Media sizes are in PCB units + */ + pcb_fprintf(f, "%%%%DocumentMedia: %s %f %f 0 \"\" \"\"\n", + pcb_media_data[global.media_idx].name, + 72 * PCB_COORD_TO_INCH(pcb_media_data[global.media_idx].width), + 72 * PCB_COORD_TO_INCH(pcb_media_data[global.media_idx].height)); + pcb_fprintf(f, "%%%%DocumentPaperSizes: %s\n", pcb_media_data[global.media_idx].name); + + /* End General Header Comments. */ + + /* General Body Comments go here. Currently there are none. */ + + /* + * %%EndComments DCS indicates an explicit end to the header + * comments of the document. All global DCS's must preceded + * this. A blank line gives an implicit end to the comments. + */ + fprintf(f, "%%%%EndComments\n\n"); +} + +static void ps_end_file(FILE * f) +{ + /* + * %%Trailer DCS must only occur once at the end of the document + * script. Any post-processing or cleanup should be contained in + * the trailer of the document, which is anything that follows the + * %%Trailer comment. Any of the document level structure comments + * that were deferred by using the (atend) convention must be + * mentioned in the trailer of the document after the %%Trailer + * comment. + */ + fprintf(f, "%%%%Trailer\n"); + + /* + * %%Pages was deferred until the end of the document via the + * (atend) mentioned, in the General Header section. + */ + fprintf(f, "%%%%Pages: %d\n", global.pagecount); + + /* + * %%EOF DCS signifies the end of the document. When the document + * manager sees this comment, it issues an end-of-file signal to the + * PostScript interpreter. This is done so system-dependent file + * endings, such as Control-D and end-of-file packets, do not + * confuse the PostScript interpreter. + */ + fprintf(f, "%%%%EOF\n"); +} + +static FILE *psopen(const char *base, const char *which) +{ + FILE *ps_open_file; + char *buf, *suff, *buf2; + + if (base == NULL) /* cam, file name template case */ + return NULL; + + if (!global.multi_file) + return pcb_fopen(base, "w"); + + buf = (char *) malloc(strlen(base) + strlen(which) + 5); + + suff = (char *) strrchr(base, '.'); + if (suff) { + strcpy(buf, base); + buf2 = strrchr(buf, '.'); + sprintf(buf2, ".%s.%s", which, suff + 1); + } + else { + sprintf(buf, "%s.%s.ps", base, which); + } + ps_open_file = pcb_fopen(buf, "w"); + free(buf); + return ps_open_file; +} + +/* This is used by other HIDs that use a postscript format, like lpr + or eps. */ +void ps_hid_export_to_file(FILE * the_file, pcb_hid_attr_val_t * options) +{ + static int saved_layer_stack[PCB_MAX_LAYER]; + + conf_force_set_bool(conf_core.editor.thin_draw, 0); + conf_force_set_bool(conf_core.editor.thin_draw_poly, 0); + conf_force_set_bool(conf_core.editor.check_planes, 0); + + global.f = the_file; + global.drill_helper = options[HA_drillhelper].int_value; + global.drill_helper_size = options[HA_drillhelpersize].coord_value; + global.align_marks = options[HA_alignmarks].int_value; + global.outline = options[HA_outline].int_value; + global.mirror = options[HA_mirror].int_value; + global.fillpage = options[HA_fillpage].int_value; + global.automirror = options[HA_automirror].int_value; + global.incolor = options[HA_color].int_value; + global.invert = options[HA_psinvert].int_value; + global.fade_ratio = PCB_CLAMP(options[HA_psfade].real_value, 0, 1); + global.media_idx = options[HA_media].int_value; + global.media_width = pcb_media_data[global.media_idx].width; + global.media_height = pcb_media_data[global.media_idx].height; + global.ps_width = global.media_width - 2.0 * pcb_media_data[global.media_idx].margin_x; + global.ps_height = global.media_height - 2.0 * pcb_media_data[global.media_idx].margin_y; + global.scale_factor = options[HA_scale].real_value; + global.calibration_x = options[HA_xcalib].real_value; + global.calibration_y = options[HA_ycalib].real_value; + global.drillcopper = options[HA_drillcopper].int_value; + global.legend = options[HA_legend].int_value; + global.single_page = options[HA_single_page].int_value; + + if (the_file) + ps_start_file(the_file); + + if (global.fillpage) { + double zx, zy; + if (PCB->MaxWidth > PCB->MaxHeight) { + zx = global.ps_height / PCB->MaxWidth; + zy = global.ps_width / PCB->MaxHeight; + } + else { + zx = global.ps_height / PCB->MaxHeight; + zy = global.ps_width / PCB->MaxWidth; + } + global.scale_factor *= MIN(zx, zy); + } + + global.has_outline = pcb_has_explicit_outline(PCB); + memcpy(saved_layer_stack, pcb_layer_stack, sizeof(pcb_layer_stack)); + qsort(pcb_layer_stack, pcb_max_layer, sizeof(pcb_layer_stack[0]), layer_sort); + + global.linewidth = -1; + /* reset static vars */ + ps_set_layer_group(-1, NULL, -1, -1, 0, -1, NULL); + use_gc(NULL); + + global.exps.view.X1 = 0; + global.exps.view.Y1 = 0; + global.exps.view.X2 = PCB->MaxWidth; + global.exps.view.Y2 = PCB->MaxHeight; + + if ((!global.multi_file && !global.multi_file_cam) && (options[HA_toc].int_value)) { + /* %%Page DSC requires both a label and an ordinal */ + fprintf(the_file, "%%%%Page: TableOfContents 1\n"); + fprintf(the_file, "/Times-Roman findfont 24 scalefont setfont\n"); + fprintf(the_file, "/rightshow { /s exch def s stringwidth pop -1 mul 0 rmoveto s show } def\n"); + fprintf(the_file, "/y 72 9 mul def /toc { 100 y moveto show /y y 24 sub def } bind def\n"); + fprintf(the_file, "/tocp { /y y 12 sub def 90 y moveto rightshow } bind def\n"); + + global.doing_toc = 1; + global.pagecount = 1; /* 'pagecount' is modified by pcb_hid_expose_all() call */ + pcb_hid_expose_all(&ps_hid, &global.exps, NULL); + } + + global.pagecount = 1; /* Reset 'pagecount' if single file */ + global.doing_toc = 0; + ps_set_layer_group(-1, NULL, -1, -1, 0, -1, NULL); /* reset static vars */ + pcb_hid_expose_all(&ps_hid, &global.exps, NULL); + + if (the_file) + fprintf(the_file, "showpage\n"); + + memcpy(pcb_layer_stack, saved_layer_stack, sizeof(pcb_layer_stack)); + conf_update(NULL, -1); /* restore forced sets */ +} + +static void ps_do_export(pcb_hid_attr_val_t * options) +{ + FILE *fh; + int save_ons[PCB_MAX_LAYER + 2]; + int i; + + if (!options) { + ps_get_export_options(0); + for (i = 0; i < NUM_OPTIONS; i++) + global.ps_values[i] = ps_attribute_list[i].default_val; + options = global.ps_values; + } + + pcb_cam_begin(PCB, &ps_cam, options[HA_cam].str_value, ps_attribute_list, NUM_OPTIONS, options); + + global.filename = options[HA_psfile].str_value; + if (!global.filename) + global.filename = "pcb-out.ps"; + + /* cam mode shall result in a single file, no matter what other attributes say */ + if (ps_cam.active) { + global.multi_file = options[HA_multifile].int_value; + global.multi_file_cam = (ps_cam.fn_template != NULL); /* template means multiple files potentially */ + } + else { + global.multi_file = options[HA_multifile].int_value; + global.multi_file_cam = 0; + } + + if (global.multi_file || global.multi_file_cam) + fh = 0; + else { + const char *fn = ps_cam.active ? ps_cam.fn : global.filename; + fh = psopen(fn, "toc"); + if (!fh) { + perror(fn); + return; + } + } + + if (!ps_cam.active) + pcb_hid_save_and_show_layer_ons(save_ons); + ps_hid_export_to_file(fh, options); + if (!ps_cam.active) + pcb_hid_restore_layer_ons(save_ons); + + global.multi_file = 0; + if (fh) { + ps_end_file(fh); + fclose(fh); + } + + if (pcb_cam_end(&ps_cam) == 0) + pcb_message(PCB_MSG_ERROR, "eps cam export for '%s' failed to produce any content\n", options[HA_cam].str_value); +} + +static int ps_parse_arguments(int *argc, char ***argv) +{ + pcb_hid_register_attributes(ps_attribute_list, NUM_OPTIONS, ps_cookie, 0); + return pcb_hid_parse_command_line(argc, argv); +} + +static void corner(FILE * fh, pcb_coord_t x, pcb_coord_t y, int dx, int dy) +{ + pcb_coord_t len = PCB_MIL_TO_COORD(2000); + pcb_coord_t len2 = PCB_MIL_TO_COORD(200); + pcb_coord_t thick = 0; + /* + * Originally 'thick' used thicker lines. Currently is uses + * Postscript's "device thin" line - i.e. zero width means one + * device pixel. The code remains in case you want to make them + * thicker - it needs to offset everything so that the *edge* of the + * thick line lines up with the edge of the board, not the *center* + * of the thick line. + */ + + pcb_fprintf(fh, "gsave %mi setlinewidth %mi %mi translate %d %d scale\n", thick * 2, x, y, dx, dy); + pcb_fprintf(fh, "%mi %mi moveto %mi %mi %mi 0 90 arc %mi %mi lineto\n", len, thick, thick, thick, len2 + thick, thick, len); + if (dx < 0 && dy < 0) + pcb_fprintf(fh, "%mi %mi moveto 0 %mi rlineto\n", len2 * 2 + thick, thick, -len2); + fprintf(fh, "stroke grestore\n"); +} + +static int ps_set_layer_group(pcb_layergrp_id_t group, const char *purpose, int purpi, pcb_layer_id_t layer, unsigned int flags, int is_empty, pcb_xform_t **xform) +{ + char tmp_fn[PCB_PATH_MAX]; + char tmp_ln[PCB_PATH_MAX]; + static int lastgroup = -1; + time_t currenttime; + const char *name; + int newpage; + + if (is_empty == -1) { + lastgroup = -1; + return 0; + } + + + if (flags & PCB_LYT_UI) + return 0; + + pcb_cam_set_layer_group(&ps_cam, group, purpose, purpi, flags, xform); + + if (!ps_cam.active) { + if (flags & PCB_LYT_NOEXPORT) + return 0; + + if (is_empty) + return 0; + + if ((group >= 0) && pcb_layergrp_is_empty(PCB, group)) + return 0; + + if (flags & PCB_LYT_INVIS) + return 0; + + if (PCB_LAYER_IS_CSECT(flags, purpi)) /* not yet finished */ + return 0; + } + + + name = pcb_layer_to_file_name(tmp_ln, layer, flags, purpose, purpi, PCB_FNS_fixed); + + global.is_drill = PCB_LAYER_IS_DRILL(flags, purpi); + global.is_mask = !!(flags & PCB_LYT_MASK); + global.is_assy = PCB_LAYER_IS_ASSY(flags, purpi); + global.is_copper = !!(flags & PCB_LYT_COPPER); + global.is_paste = !!(flags & PCB_LYT_PASTE); + +#if 0 + printf("Layer %s group %d drill %d mask %d\n", name, group, global.is_drill, global.is_mask); +#endif + + if (global.doing_toc) { + if (group < 0 || group != lastgroup) { + if (global.pagecount == 1) { + currenttime = time(NULL); + fprintf(global.f, "30 30 moveto (%s) show\n", pcb_hid_export_fn(PCB->Filename)); + + fprintf(global.f, "(%d.) tocp\n", global.pagecount); + fprintf(global.f, "(Table of Contents \\(This Page\\)) toc\n"); + + fprintf(global.f, "(Created on %s) toc\n", asctime(localtime(¤ttime))); + fprintf(global.f, "( ) tocp\n"); + } + + global.pagecount++; + lastgroup = group; + fprintf(global.f, "(%d.) tocp\n", global.single_page ? 2 : global.pagecount); + } + fprintf(global.f, "(%s) toc\n", name); + return 0; + } + + if (ps_cam.active) + newpage = ps_cam.fn_changed; + else + newpage = (group < 0 || group != lastgroup); + if ((global.pagecount > 1) && global.single_page) + newpage = 0; + if (newpage) { + double boffset; + int mirror_this = 0; + lastgroup = group; + + if (global.pagecount != 0) { + pcb_fprintf(global.f, "showpage\n"); + } + global.pagecount++; + if ((!ps_cam.active && global.multi_file) || (ps_cam.active && ps_cam.fn_changed)) { + const char *fn = ps_cam.active ? ps_cam.fn : pcb_layer_to_file_name(tmp_fn, layer, flags, purpose, purpi, PCB_FNS_fixed); + if (global.f) { + ps_end_file(global.f); + fclose(global.f); + } + global.f = psopen(ps_cam.active ? fn : global.filename, fn); + if (!global.f) { + perror(global.filename); + return 0; + } + + ps_start_file(global.f); + } + + /* + * %%Page DSC comment marks the beginning of the PostScript + * language instructions that describe a particular + * page. %%Page: requires two arguments: a page label and a + * sequential page number. The label may be anything, but the + * ordinal page number must reflect the position of that page in + * the body of the PostScript file and must start with 1, not 0. + */ + fprintf(global.f, "%%%%Page: %s %d\n", pcb_layer_to_file_name(tmp_fn, layer, flags, purpose, purpi, PCB_FNS_fixed), global.pagecount); + + if (global.mirror) + mirror_this = !mirror_this; + if (global.automirror && (flags & PCB_LYT_BOTTOM)) + mirror_this = !mirror_this; + + fprintf(global.f, "/Helvetica findfont 10 scalefont setfont\n"); + if (global.legend) { + fprintf(global.f, "30 30 moveto (%s) show\n", pcb_hid_export_fn(PCB->Filename)); + if (PCB->Name) + fprintf(global.f, "30 41 moveto (%s, %s) show\n", PCB->Name, pcb_layer_to_file_name(tmp_fn, layer, flags, purpose, purpi, PCB_FNS_fixed)); + else + fprintf(global.f, "30 41 moveto (%s) show\n", pcb_layer_to_file_name(tmp_fn, layer, flags, purpose, purpi, PCB_FNS_fixed)); + if (mirror_this) + fprintf(global.f, "( \\(mirrored\\)) show\n"); + + if (global.fillpage) + fprintf(global.f, "(, not to scale) show\n"); + else + fprintf(global.f, "(, scale = 1:%.3f) show\n", global.scale_factor); + } + fprintf(global.f, "newpath\n"); + + pcb_fprintf(global.f, "72 72 scale %mi %mi translate\n", global.media_width / 2, global.media_height / 2); + + boffset = global.media_height / 2; + if (PCB->MaxWidth > PCB->MaxHeight) { + fprintf(global.f, "90 rotate\n"); + boffset = global.media_width / 2; + fprintf(global.f, "%g %g scale %% calibration\n", global.calibration_y, global.calibration_x); + } + else + fprintf(global.f, "%g %g scale %% calibration\n", global.calibration_x, global.calibration_y); + + if (mirror_this) + fprintf(global.f, "1 -1 scale\n"); + + fprintf(global.f, "%g dup neg scale\n", PCB_LAYER_IS_FAB(flags, purpi) ? 1.0 : global.scale_factor); + pcb_fprintf(global.f, "%mi %mi translate\n", -PCB->MaxWidth / 2, -PCB->MaxHeight / 2); + + /* Keep the drill list from falling off the left edge of the paper, + * even if it means some of the board falls off the right edge. + * If users don't want to make smaller boards, or use fewer drill + * sizes, they can always ignore this sheet. */ + if (PCB_LAYER_IS_FAB(flags, purpi)) { + pcb_coord_t natural = boffset - PCB_MIL_TO_COORD(500) - PCB->MaxHeight / 2; + pcb_coord_t needed = pcb_stub_draw_fab_overhang(); + pcb_fprintf(global.f, "%% PrintFab overhang natural %mi, needed %mi\n", natural, needed); + if (needed > natural) + pcb_fprintf(global.f, "0 %mi translate\n", needed - natural); + } + + if (global.invert) { + fprintf(global.f, "/gray { 1 exch sub setgray } bind def\n"); + fprintf(global.f, "/rgb { 1 1 3 { pop 1 exch sub 3 1 roll } for setrgbcolor } bind def\n"); + } + else { + fprintf(global.f, "/gray { setgray } bind def\n"); + fprintf(global.f, "/rgb { setrgbcolor } bind def\n"); + } + + if (!global.has_outline || global.invert) { + if ((PCB_LAYER_IS_ROUTE(flags, purpi)) || (global.outline)) { + pcb_fprintf(global.f, + "0 setgray %mi setlinewidth 0 0 moveto 0 " + "%mi lineto %mi %mi lineto %mi 0 lineto closepath %s\n", + conf_core.design.min_wid, + PCB->MaxHeight, PCB->MaxWidth, PCB->MaxHeight, PCB->MaxWidth, global.invert ? "fill" : "stroke"); + } + } + + if (global.align_marks) { + corner(global.f, 0, 0, -1, -1); + corner(global.f, PCB->MaxWidth, 0, 1, -1); + corner(global.f, PCB->MaxWidth, PCB->MaxHeight, 1, 1); + corner(global.f, 0, PCB->MaxHeight, -1, 1); + } + + global.linewidth = -1; + use_gc(NULL); /* reset static vars */ + + fprintf(global.f, + "/ts 1 def\n" + "/ty ts neg def /tx 0 def /Helvetica findfont ts scalefont setfont\n" + "/t { moveto lineto stroke } bind def\n" + "/dr { /y2 exch def /x2 exch def /y1 exch def /x1 exch def\n" + " x1 y1 moveto x1 y2 lineto x2 y2 lineto x2 y1 lineto closepath stroke } bind def\n"); + fprintf(global.f,"/r { /y2 exch def /x2 exch def /y1 exch def /x1 exch def\n" + " x1 y1 moveto x1 y2 lineto x2 y2 lineto x2 y1 lineto closepath fill } bind def\n" + "/c { 0 360 arc fill } bind def\n" + "/a { gsave setlinewidth translate scale 0 0 1 5 3 roll arc stroke grestore} bind def\n"); + if (global.drill_helper) + pcb_fprintf(global.f, + "/dh { gsave %mi setlinewidth 0 gray %mi 0 360 arc stroke grestore} bind def\n", + (pcb_coord_t) global.drill_helper_size, (pcb_coord_t) (global.drill_helper_size * 3 / 2)); + } +#if 0 + /* Try to outsmart ps2pdf's heuristics for page rotation, by putting + * text on all pages -- even if that text is blank */ + if (!(PCB_LAYER_IS_FAB(flags, purpi))) + fprintf(global.f, "gsave tx ty translate 1 -1 scale 0 0 moveto (Layer %s) show grestore newpath /ty ty ts sub def\n", name); + else + fprintf(global.f, "gsave tx ty translate 1 -1 scale 0 0 moveto ( ) show grestore newpath /ty ty ts sub def\n"); +#endif + + /* If we're printing a layer other than an outline layer, and + we want to "print outlines", and we have an outline layer, + print the outline layer on this layer also. */ + if (global.outline && + global.has_outline && + !(PCB_LAYER_IS_ROUTE(flags, purpi))) { + int save_drill = global.is_drill; + global.is_drill = 0; + pcb_draw_groups(PCB, PCB_LYT_BOUNDARY, F_proute, NULL, &global.exps.view, pcb_color_black, PCB_LYT_MECH, 0, 0); + pcb_draw_groups(PCB, PCB_LYT_BOUNDARY, F_uroute, NULL, &global.exps.view, pcb_color_black, PCB_LYT_MECH, 0, 0); + global.is_drill = save_drill; + } + + return 1; +} + +static pcb_hid_gc_t ps_make_gc(void) +{ + pcb_hid_gc_t rv = (pcb_hid_gc_t) calloc(1, sizeof(hid_gc_s)); + rv->me_pointer = &ps_hid; + rv->cap = pcb_cap_round; + return rv; +} + +static void ps_destroy_gc(pcb_hid_gc_t gc) +{ + free(gc); +} + +static void ps_set_drawing_mode(pcb_composite_op_t op, pcb_bool direct, const pcb_box_t *screen) +{ + global.drawing_mode = op; +} + + +static void ps_set_color(pcb_hid_gc_t gc, const pcb_color_t *color) +{ + if (global.drawing_mode == PCB_HID_COMP_NEGATIVE) { + gc->r = gc->g = gc->b = 255; + gc->erase = 0; + } + else if (pcb_color_is_drill(color)) { + gc->r = gc->g = gc->b = 255; + gc->erase = 1; + } + else if (global.incolor) { + gc->r = color->r; + gc->g = color->g; + gc->b = color->b; + gc->erase = 0; + } + else { + gc->r = gc->g = gc->b = 0; + gc->erase = 0; + } +} + +static void ps_set_line_cap(pcb_hid_gc_t gc, pcb_cap_style_t style) +{ + gc->cap = style; +} + +static void ps_set_line_width(pcb_hid_gc_t gc, pcb_coord_t width) +{ + gc->width = width; +} + +static void ps_set_draw_xor(pcb_hid_gc_t gc, int xor_) +{ + ; +} + +static void ps_set_draw_faded(pcb_hid_gc_t gc, int faded) +{ + gc->faded = faded; +} + +static void use_gc(pcb_hid_gc_t gc) +{ + static int lastcap = -1; + static int lastcolor = -1; + + if (gc == NULL) { + lastcap = lastcolor = -1; + return; + } + if (gc->me_pointer != &ps_hid) { + fprintf(stderr, "Fatal: GC from another HID passed to ps HID\n"); + abort(); + } + if (global.linewidth != gc->width) { + pcb_fprintf(global.f, "%mi setlinewidth\n", gc->width); + global.linewidth = gc->width; + } + if (lastcap != gc->cap) { + int c; + switch (gc->cap) { + case pcb_cap_round: + c = 1; + break; + case pcb_cap_square: + c = 2; + break; + default: + assert(!"unhandled cap"); + c = 1; + } + fprintf(global.f, "%d setlinecap %d setlinejoin\n", c, c); + lastcap = gc->cap; + } +#define CBLEND(gc) (((gc->r)<<24)|((gc->g)<<16)|((gc->b)<<8)|(gc->faded)) + if (lastcolor != CBLEND(gc)) { + if (global.is_drill || global.is_mask) { + fprintf(global.f, "%d gray\n", (gc->erase || global.is_mask) ? 0 : 1); + lastcolor = 0; + } + else { + double r, g, b; + r = gc->r; + g = gc->g; + b = gc->b; + if (gc->faded) { + r = (1 - global.fade_ratio) *255 + global.fade_ratio * r; + g = (1 - global.fade_ratio) *255 + global.fade_ratio * g; + b = (1 - global.fade_ratio) *255 + global.fade_ratio * b; + } + if (gc->r == gc->g && gc->g == gc->b) + fprintf(global.f, "%g gray\n", r / 255.0); + else + fprintf(global.f, "%g %g %g rgb\n", r / 255.0, g / 255.0, b / 255.0); + lastcolor = CBLEND(gc); + } + } +} + +static void ps_draw_rect(pcb_hid_gc_t gc, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2) +{ + use_gc(gc); + pcb_fprintf(global.f, "%mi %mi %mi %mi dr\n", x1, y1, x2, y2); +} + +static void ps_fill_rect(pcb_hid_gc_t gc, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2); +static void ps_fill_circle(pcb_hid_gc_t gc, pcb_coord_t cx, pcb_coord_t cy, pcb_coord_t radius); + +static void ps_draw_line(pcb_hid_gc_t gc, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2) +{ +#if 0 + /* If you're etching your own paste mask, this will reduce the + amount of brass you need to etch by drawing outlines for large + pads. See also ps_fill_rect. */ + if (is_paste && gc->width > 2500 && gc->cap == pcb_cap_square && (x1 == x2 || y1 == y2)) { + pcb_coord_t t, w; + if (x1 > x2) { + t = x1; + x1 = x2; + x2 = t; + } + if (y1 > y2) { + t = y1; + y1 = y2; + y2 = t; + } + w = gc->width / 2; + ps_fill_rect(gc, x1 - w, y1 - w, x2 + w, y2 + w); + return; + } +#endif + if (x1 == x2 && y1 == y2) { + pcb_coord_t w = gc->width / 2; + if (gc->cap == pcb_cap_square) + ps_fill_rect(gc, x1 - w, y1 - w, x1 + w, y1 + w); + else + ps_fill_circle(gc, x1, y1, w); + return; + } + use_gc(gc); + pcb_fprintf(global.f, "%mi %mi %mi %mi t\n", x1, y1, x2, y2); +} + +static void ps_draw_arc(pcb_hid_gc_t gc, pcb_coord_t cx, pcb_coord_t cy, pcb_coord_t width, pcb_coord_t height, pcb_angle_t start_angle, pcb_angle_t delta_angle) +{ + pcb_angle_t sa, ea; + double w; + + if ((width == 0) && (height == 0)) { + /* degenerate case, draw dot */ + ps_draw_line(gc, cx, cy, cx, cy); + return; + } + + if (delta_angle > 0) { + sa = start_angle; + ea = start_angle + delta_angle; + } + else { + sa = start_angle + delta_angle; + ea = start_angle; + } +#if 0 + printf("draw_arc %d,%d %dx%d %d..%d %d..%d\n", cx, cy, width, height, start_angle, delta_angle, sa, ea); +#endif + use_gc(gc); + w = width; + if (w == 0) /* make sure not to div by zero; this hack will have very similar effect */ + w = 0.0001; + pcb_fprintf(global.f, "%ma %ma %mi %mi %mi %mi %f a\n", + sa, ea, -width, height, cx, cy, (double)(global.linewidth) / w); +} + +static void ps_fill_circle(pcb_hid_gc_t gc, pcb_coord_t cx, pcb_coord_t cy, pcb_coord_t radius) +{ + use_gc(gc); + if (!gc->erase || !global.is_copper || global.drillcopper) { + if (gc->erase && global.is_copper && global.drill_helper && radius >= global.drill_helper_size) + radius = global.drill_helper_size; + pcb_fprintf(global.f, "%mi %mi %mi c\n", cx, cy, radius); + } +} + +static void ps_fill_polygon_offs(pcb_hid_gc_t gc, int n_coords, pcb_coord_t *x, pcb_coord_t *y, pcb_coord_t dx, pcb_coord_t dy) +{ + int i; + const char *op = "moveto"; + use_gc(gc); + for (i = 0; i < n_coords; i++) { + pcb_fprintf(global.f, "%mi %mi %s\n", x[i]+dx, y[i]+dy, op); + op = "lineto"; + } + fprintf(global.f, "fill\n"); +} + +static void ps_fill_polygon(pcb_hid_gc_t gc, int n_coords, pcb_coord_t *x, pcb_coord_t *y) +{ + ps_fill_polygon_offs(gc, n_coords, x, y, 0, 0); +} + + +typedef struct { + pcb_coord_t x1, y1, x2, y2; +} lseg_t; + +typedef struct { + pcb_coord_t x, y; +} lpoint_t; + +#define minmax(val, min, max) \ +do { \ + if (val < min) min = val; \ + if (val > max) max = val; \ +} while(0) + +#define lsegs_append(x1_, y1_, x2_, y2_) \ +do { \ + if (y1_ < y2_) { \ + lsegs[lsegs_used].x1 = x1_; \ + lsegs[lsegs_used].y1 = y1_; \ + lsegs[lsegs_used].x2 = x2_; \ + lsegs[lsegs_used].y2 = y2_; \ + } \ + else { \ + lsegs[lsegs_used].x2 = x1_; \ + lsegs[lsegs_used].y2 = y1_; \ + lsegs[lsegs_used].x1 = x2_; \ + lsegs[lsegs_used].y1 = y2_; \ + } \ + lsegs_used++; \ + minmax(y1_, lsegs_ymin, lsegs_ymax); \ + minmax(y2_, lsegs_ymin, lsegs_ymax); \ + minmax(x1_, lsegs_xmin, lsegs_xmax); \ + minmax(x2_, lsegs_xmin, lsegs_xmax); \ +} while(0) + +#define lseg_line(x1_, y1_, x2_, y2_) \ + do { \ + fprintf(global.f, "newpath\n"); \ + pcb_fprintf(global.f, "%mi %mi moveto\n", x1_, y1_); \ + pcb_fprintf(global.f, "%mi %mi lineto\n", x2_, y2_); \ + fprintf (global.f, "stroke\n"); \ + } while(0) + +int coord_comp(const void *c1_, const void *c2_) +{ + const pcb_coord_t *c1 = c1_, *c2 = c2_; + return *c1 < *c2; +} + +static void ps_fill_pcb_polygon(pcb_hid_gc_t gc, pcb_poly_t * poly, const pcb_box_t * clip_box) +{ + /* Ignore clip_box, just draw everything */ + + pcb_vnode_t *v; + pcb_pline_t *pl; + const char *op; + int len; + + use_gc(gc); + + pl = poly->Clipped->contours; + len = 0; + + do { + v = pl->head.next; + op = "moveto"; + do { + pcb_fprintf(global.f, "%mi %mi %s\n", v->point[0], v->point[1], op); + op = "lineto"; + len++; + } + while ((v = v->next) != pl->head.next); + len++; + } + while ((pl = pl->next) != NULL); + + fprintf(global.f, "fill\n"); +} + +static void ps_fill_rect(pcb_hid_gc_t gc, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2) +{ + use_gc(gc); + if (x1 > x2) { + pcb_coord_t t = x1; + x1 = x2; + x2 = t; + } + if (y1 > y2) { + pcb_coord_t t = y1; + y1 = y2; + y2 = t; + } +#if 0 + /* See comment in ps_draw_line. */ + if (is_paste && (x2 - x1) > 2500 && (y2 - y1) > 2500) { + linewidth = 1000; + lastcap = pcb_cap_round; + fprintf(f, "1000 setlinewidth 1 setlinecap 1 setlinejoin\n"); + fprintf(f, "%d %d moveto %d %d lineto %d %d lineto %d %d lineto closepath stroke\n", + x1 + 500 - bloat, y1 + 500 - bloat, + x1 + 500 - bloat, y2 - 500 + bloat, x2 - 500 + bloat, y2 - 500 + bloat, x2 - 500 + bloat, y1 + 500 - bloat); + return; + } +#endif + pcb_fprintf(global.f, "%mi %mi %mi %mi r\n", x1, y1, x2, y2); +} + +pcb_hid_attribute_t ps_calib_attribute_list[] = { + {"lprcommand", "Command to print", + PCB_HATT_STRING, 0, 0, {0, 0, 0}, 0, 0}, +}; + +static const char *const calib_lines[] = { + "%!PS-Adobe-3.0\n", + "%%Title: Calibration Page\n", + "%%PageOrder: Ascend\n", + "%%Pages: 1\n", + "%%EndComments\n", + "\n", + "%%Page: Calibrate 1\n", + "72 72 scale\n", + "\n", + "0 setlinewidth\n", + "0.375 0.375 moveto\n", + "8.125 0.375 lineto\n", + "8.125 10.625 lineto\n", + "0.375 10.625 lineto\n", + "closepath stroke\n", + "\n", + "0.5 0.5 translate\n", + "0.001 setlinewidth\n", + "\n", + "/Times-Roman findfont 0.2 scalefont setfont\n", + "\n", + "/sign {\n", + " 0 lt { -1 } { 1 } ifelse\n", + "} def\n", + "\n", + "/cbar {\n", + " /units exch def\n", + " /x exch def\n", + " /y exch def \n", + "\n", + " /x x sign 0.5 mul def\n", + "\n", + " 0 setlinewidth\n", + " newpath x y 0.25 0 180 arc gsave 0.85 setgray fill grestore closepath stroke\n", + " newpath x 0 0.25 180 360 arc gsave 0.85 setgray fill grestore closepath stroke\n", + " 0.001 setlinewidth\n", + "\n", + " x 0 moveto\n", + " x y lineto\n", + "% -0.07 -0.2 rlineto 0.14 0 rmoveto -0.07 0.2 rlineto\n", + " x y lineto\n", + " -0.1 0 rlineto 0.2 0 rlineto\n", + " stroke\n", + " x 0 moveto\n", + "% -0.07 0.2 rlineto 0.14 0 rmoveto -0.07 -0.2 rlineto\n", + " x 0 moveto\n", + " -0.1 0 rlineto 0.2 0 rlineto\n", + " stroke\n", + "\n", + " x 0.1 add\n", + " y 0.2 sub moveto\n", + " units show\n", + "} bind def\n", + "\n", + "/y 9 def\n", + "/t {\n", + " /str exch def\n", + " 1.5 y moveto str show\n", + " /y y 0.25 sub def\n", + "} bind def\n", + "\n", + "(Please measure ONE of the horizontal lines, in the units indicated for)t\n", + "(that line, and enter that value as X. Similarly, measure ONE of the)t\n", + "(vertical lines and enter that value as Y. Measurements should be)t\n", + "(between the flat faces of the semicircles.)t\n", + "()t\n", + "(The large box is 10.25 by 7.75 inches)t\n", + "\n", + "/in { } bind def\n", + "/cm { 2.54 div } bind def\n", + "/mm { 25.4 div } bind def\n", + "\n", + 0 +}; + +static int guess(double val, double close_to, double *calib) +{ + if (val >= close_to * 0.9 && val <= close_to * 1.1) { + *calib = close_to / val; + return 0; + } + return 1; +} + +void ps_calibrate_1(double xval, double yval, int use_command) +{ + pcb_hid_attr_val_t vals[3]; + FILE *ps_cal_file; + int used_popen = 0, c; + + if (xval > 0 && yval > 0) { + if (guess(xval, 4, &global.calibration_x)) + if (guess(xval, 15, &global.calibration_x)) + if (guess(xval, 7.5, &global.calibration_x)) { + if (xval < 2) + ps_attribute_list[HA_xcalib].default_val.real_value = global.calibration_x = xval; + else + pcb_message(PCB_MSG_ERROR, "X value of %g is too far off.\n" "Expecting it near: 1.0, 4.0, 15.0, 7.5\n", xval); + } + if (guess(yval, 4, &global.calibration_y)) + if (guess(yval, 20, &global.calibration_y)) + if (guess(yval, 10, &global.calibration_y)) { + if (yval < 2) + ps_attribute_list[HA_ycalib].default_val.real_value = global.calibration_y = yval; + else + pcb_message(PCB_MSG_ERROR, "Y value of %g is too far off.\n" "Expecting it near: 1.0, 4.0, 20.0, 10.0\n", yval); + } + return; + } + + if (ps_calib_attribute_list[0].default_val.str_value == NULL) { + ps_calib_attribute_list[0].default_val.str_value = pcb_strdup("lpr"); + } + + if (pcb_attribute_dialog("ps_calibrate", ps_calib_attribute_list, 1, vals, "Print Calibration Page", NULL)) + return; + + if (vals[0].str_value == NULL) + return; + + if (use_command || strchr(vals[0].str_value, '|')) { + const char *cmd = vals[0].str_value; + while (*cmd == ' ' || *cmd == '|') + cmd++; + ps_cal_file = pcb_popen(cmd, "w"); + used_popen = 1; + } + else + ps_cal_file = pcb_fopen(vals[0].str_value, "w"); + + for (c = 0; calib_lines[c]; c++) + fputs(calib_lines[c], ps_cal_file); + + fprintf(ps_cal_file, "4 in 0.5 (Y in) cbar\n"); + fprintf(ps_cal_file, "20 cm 1.5 (Y cm) cbar\n"); + fprintf(ps_cal_file, "10 in 2.5 (Y in) cbar\n"); + fprintf(ps_cal_file, "-90 rotate\n"); + fprintf(ps_cal_file, "4 in -0.5 (X in) cbar\n"); + fprintf(ps_cal_file, "15 cm -1.5 (X cm) cbar\n"); + fprintf(ps_cal_file, "7.5 in -2.5 (X in) cbar\n"); + + fprintf(ps_cal_file, "showpage\n"); + + fprintf(ps_cal_file, "%%%%EOF\n"); + + if (used_popen) + pcb_pclose(ps_cal_file); + else + fclose(ps_cal_file); +} + +static void ps_calibrate(double xval, double yval) +{ + ps_calibrate_1(xval, yval, 0); +} + +static void ps_set_crosshair(pcb_coord_t x, pcb_coord_t y, int action) +{ +} + +static fgw_error_t pcb_act_PSCalib(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + ps_calibrate(0.0, 0.0); + return 0; +} + +pcb_action_t hidps_action_list[] = { + {"pscalib", pcb_act_PSCalib, NULL, NULL} +}; + +PCB_REGISTER_ACTIONS(hidps_action_list, ps_cookie) + + +#include "dolists.h" + +pcb_hid_t ps_hid; +static int ps_inited = 0; +void ps_ps_init(pcb_hid_t * hid) +{ + if (ps_inited) + return; + + hid->get_export_options = ps_get_export_options; + hid->do_export = ps_do_export; + hid->parse_arguments = ps_parse_arguments; + hid->set_layer_group = ps_set_layer_group; + hid->make_gc = ps_make_gc; + hid->destroy_gc = ps_destroy_gc; + hid->set_drawing_mode = ps_set_drawing_mode; + hid->set_color = ps_set_color; + hid->set_line_cap = ps_set_line_cap; + hid->set_line_width = ps_set_line_width; + hid->set_draw_xor = ps_set_draw_xor; + hid->set_draw_faded = ps_set_draw_faded; + hid->draw_line = ps_draw_line; + hid->draw_arc = ps_draw_arc; + hid->draw_rect = ps_draw_rect; + hid->fill_circle = ps_fill_circle; + hid->fill_polygon_offs = ps_fill_polygon_offs; + hid->fill_polygon = ps_fill_polygon; + hid->fill_pcb_polygon = ps_fill_pcb_polygon; + hid->fill_rect = ps_fill_rect; + hid->calibrate = ps_calibrate; + hid->set_crosshair = ps_set_crosshair; + + PCB_REGISTER_ACTIONS(hidps_action_list, ps_cookie) + + ps_inited = 1; +} + +static int ps_usage(const char *topic) +{ + fprintf(stderr, "\nps exporter command line arguments:\n\n"); + pcb_hid_usage(ps_attribute_list, sizeof(ps_attribute_list) / sizeof(ps_attribute_list[0])); + fprintf(stderr, "\nUsage: pcb-rnd [generic_options] -x ps [ps options] foo.pcb\n\n"); + return 0; +} + +static void plugin_ps_uninit(void) +{ + pcb_remove_actions_by_cookie(ps_cookie); + pcb_hid_remove_attributes_by_cookie(ps_cookie); + ps_inited = 0; +} + + +int pplg_check_ver_export_ps(int ver_needed) { return 0; } + +void pplg_uninit_export_ps(void) +{ + plugin_ps_uninit(); +} + +int pplg_init_export_ps(void) +{ + PCB_API_CHK_VER; + memset(&ps_hid, 0, sizeof(pcb_hid_t)); + + pcb_hid_nogui_init(&ps_hid); + pcb_dhlp_draw_helpers_init(&ps_hid); + ps_ps_init(&ps_hid); + + ps_hid.struct_size = sizeof(pcb_hid_t); + ps_hid.name = "ps"; + ps_hid.description = "Postscript export"; + ps_hid.exporter = 1; + ps_hid.mask_invert = 1; + + ps_hid.usage = ps_usage; + + pcb_hid_register_hid(&ps_hid); + + hid_eps_init(); + return 0; +} Index: tags/2.1.2/src_plugins/export_ps/ps.h =================================================================== --- tags/2.1.2/src_plugins/export_ps/ps.h (nonexistent) +++ tags/2.1.2/src_plugins/export_ps/ps.h (revision 24813) @@ -0,0 +1,7 @@ +extern const char *ps_cookie; +extern pcb_hid_t ps_hid; +extern void ps_hid_export_to_file(FILE *, pcb_hid_attr_val_t *); +extern void ps_start_file(FILE *); +extern void ps_calibrate_1(double, double, int); +extern void hid_eps_init(); +void ps_ps_init(pcb_hid_t * hid); Index: tags/2.1.2/src_plugins/export_stat/Makefile =================================================================== --- tags/2.1.2/src_plugins/export_stat/Makefile (nonexistent) +++ tags/2.1.2/src_plugins/export_stat/Makefile (revision 24813) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_export_stat + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/2.1.2/src_plugins/export_stat/Plug.tmpasm =================================================================== --- tags/2.1.2/src_plugins/export_stat/Plug.tmpasm (nonexistent) +++ tags/2.1.2/src_plugins/export_stat/Plug.tmpasm (revision 24813) @@ -0,0 +1,8 @@ +put /local/pcb/mod {export_stat} +put /local/pcb/mod/OBJS [@ $(PLUGDIR)/export_stat/stat.o @] + +switch /local/pcb/export_stat/controls + case {buildin} include /local/pcb/tmpasm/buildin; end; + case {plugin} include /local/pcb/tmpasm/plugin; end; + case {disable} include /local/pcb/tmpasm/disable; end; +end Index: tags/2.1.2/src_plugins/export_stat/export_stat.pup =================================================================== --- tags/2.1.2/src_plugins/export_stat/export_stat.pup (nonexistent) +++ tags/2.1.2/src_plugins/export_stat/export_stat.pup (revision 24813) @@ -0,0 +1,9 @@ +$class export +$short export board statistics +$long Export various board statistics in lihata format +$state works +$fmt-native no +$fmt-feature-w export a lihata file with anonimized statistics of the board +$package export +default buildin +autoload 1 Index: tags/2.1.2/src_plugins/export_stat/stat.c =================================================================== --- tags/2.1.2/src_plugins/export_stat/stat.c (nonexistent) +++ tags/2.1.2/src_plugins/export_stat/stat.c (revision 24813) @@ -0,0 +1,423 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 2006 Dan McMahill + * Copyright (C) 2016 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +/* + * Based on the png exporter by Dan McMahill + */ + +#include "config.h" +#include "conf_core.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "math_helper.h" +#include "board.h" +#include "data.h" +#include "data_it.h" +#include "netlist2.h" +#include "plugins.h" +#include "pcb-printf.h" +#include "compat_misc.h" +#include "plug_io.h" +#include "safe_fs.h" +#include "obj_pstk_inlines.h" + +#include "hid.h" +#include "hid_nogui.h" +#include "hid_draw_helpers.h" + +#include "hid_init.h" +#include "hid_attrib.h" +#include "hid_color.h" +#include "hid_cam.h" + + +static pcb_hid_t stat_hid; + +const char *stat_cookie = "stat HID"; + +pcb_hid_attribute_t stat_attribute_list[] = { + /* other HIDs expect this to be first. */ + + {"outfile", "Output file name", + PCB_HATT_STRING, 0, 0, {0, 0, 0}, 0, 0}, +#define HA_statfile 0 + + {"board_id", "Short name of the board so it can be identified for updates", + PCB_HATT_STRING, 0, 0, {0, 0, 0}, 0, 0}, +#define HA_board_id 1 + + {"orig", "This design started its life in pcb-rnd", + PCB_HATT_BOOL, 0, 0, {0, 0, 0}, 0, 0}, +#define HA_orig 2 + + {"lht_built", "This design was already in lihata when real boards got built", + PCB_HATT_BOOL, 0, 0, {0, 0, 0}, 0, 0}, +#define HA_lht_built 3 + + + {"built", "how many actual/physical boards got built", + PCB_HATT_INTEGER, 0, 1000000, {0, 0, 0}, 0, 0}, +#define HA_built 4 + + {"first_ver", "the version of pcb-rnd you first used on this board", + PCB_HATT_STRING, 0, 0, {0, NULL, 0}, 0, 0}, +#define HA_first_ver 5 + + {"license", "license of the design", + PCB_HATT_STRING, 0, 0, {0, NULL, 0}, 0, 0}, +#define HA_license 6 + +}; + +#define NUM_OPTIONS (sizeof(stat_attribute_list)/sizeof(stat_attribute_list[0])) + +PCB_REGISTER_ATTRIBUTES(stat_attribute_list, stat_cookie) + +static pcb_hid_attr_val_t stat_values[NUM_OPTIONS]; + +static pcb_hid_attribute_t *stat_get_export_options(int *n) +{ + const char *suffix = ".stat.lht"; + + if ((PCB != NULL) && (stat_attribute_list[HA_statfile].default_val.str_value == NULL)) + pcb_derive_default_filename(PCB->Filename, &stat_attribute_list[HA_statfile], suffix); + + if (n) + *n = NUM_OPTIONS; + return stat_attribute_list; +} + +typedef struct layer_stat_s { + pcb_coord_t trace_len; + double copper_area; + unsigned long int lines, arcs, polys, elements; +} layer_stat_t; + +static void stat_do_export(pcb_hid_attr_val_t * options) +{ + FILE *f; + const char *filename; + int i, lid; + pcb_layergrp_id_t lgid; + char buff[1024]; + layer_stat_t ls, *lgs, lgss[PCB_MAX_LAYERGRP]; + int nl, phg, hp, hup, group_not_empty[PCB_MAX_LAYERGRP]; + pcb_cardinal_t num_etop = 0, num_ebottom = 0, num_esmd = 0, num_epads = 0, num_epins = 0, num_terms = 0, num_slots = 0; + pcb_coord_t width, height; + + memset(lgss, 0, sizeof(lgss)); + memset(group_not_empty, 0, sizeof(group_not_empty)); + + if (!options) { + stat_get_export_options(0); + for (i = 0; i < NUM_OPTIONS; i++) + stat_values[i] = stat_attribute_list[i].default_val; + options = stat_values; + } + + filename = options[HA_statfile].str_value; + if (!filename) + filename = "pcb.stat.lht"; + + f = pcb_fopen(filename, "w"); + if (!f) { + perror(filename); + return; + } + + pcb_board_count_holes(PCB, &hp, &hup, NULL); + pcb_print_utc(buff, sizeof(buff), 0); + + fprintf(f, "ha:pcb-rnd-board-stats-v2 {\n"); + fprintf(f, " ha:meta {\n"); + fprintf(f, " date={%s}\n", buff); + fprintf(f, " built=%d\n", options[HA_built].int_value); + fprintf(f, " lht_built=%s\n", (options[HA_lht_built].int_value ? "yes" : "no")); + fprintf(f, " orig_rnd=%s\n", (options[HA_orig].int_value ? "yes" : "no")); + fprintf(f, " first_ver=%s\n", options[HA_first_ver].str_value); + fprintf(f, " curr_ver=%s\n", PCB_VERSION); +#ifdef PCB_REVISION + fprintf(f, " curr_rev=%s\n", PCB_REVISION); +#endif + + fprintf(f, " }\n"); + + fprintf(f, " li:logical_layers {\n"); + for(lid = 0; lid < pcb_max_layer; lid++) { + pcb_layer_t *l = PCB->Data->Layer+lid; + int empty = pcb_layer_is_empty_(PCB, l); + unsigned int lflg = pcb_layer_flags(PCB, lid); + + lgid = pcb_layer_get_group(PCB, lid); + lgs = lgss + lgid; + + fprintf(f, " ha:layer_%d {\n", lid); + fprintf(f, " name={%s}\n", l->name); + fprintf(f, " empty=%s\n", empty ? "yes" : "no"); + fprintf(f, " flags=%x\n", lflg); + fprintf(f, " grp=%ld\n", lgid); + + if (lflg & PCB_LYT_COPPER) { + memset(&ls, 0, sizeof(ls)); + + PCB_LINE_LOOP(l) { + pcb_coord_t v; + double d; + lgs->lines++; + ls.lines++; + v = pcb_line_length(line); + ls.trace_len += v; + lgs->trace_len += v; + d = pcb_line_area(line); + ls.copper_area += d; + lgs->copper_area += d; + + } + PCB_END_LOOP; + + PCB_ARC_LOOP(l) { + pcb_coord_t v; + double d; + lgs->arcs++; + ls.arcs++; + v = pcb_arc_length(arc); + ls.trace_len += v; + lgs->trace_len += v; + d = pcb_arc_area(arc); + ls.copper_area += d; + lgs->copper_area += d; + } + PCB_END_LOOP; + + PCB_POLY_LOOP(l) { + double v; + lgs->polys++; + ls.polys++; + v = pcb_poly_area(polygon); + ls.copper_area += v; + lgs->copper_area += v; + } + PCB_END_LOOP; + + if (!empty) + group_not_empty[lgid] = 1; + + fprintf(f, " lines=%lu\n", ls.lines); + fprintf(f, " arcs=%lu\n", ls.arcs); + fprintf(f, " polys=%lu\n", ls.polys); + pcb_fprintf(f, " trace_len=%$mm\n", ls.trace_len); + fprintf(f, " copper_area={%f mm^2}\n", (double)ls.copper_area / (double)PCB_MM_TO_COORD(1) / (double)PCB_MM_TO_COORD(1)); + } + fprintf(f, " }\n"); + } + fprintf(f, " }\n"); + + phg = 0; + fprintf(f, " li:physical_layers {\n"); + for(lgid = 0; lgid < pcb_max_group(PCB); lgid++) { + if (group_not_empty[lgid]) { + phg++; + fprintf(f, " ha:layergroup_%ld {\n", lgid); + fprintf(f, " lines=%lu\n", lgss[lgid].lines); + fprintf(f, " arcs=%lu\n", lgss[lgid].arcs); + fprintf(f, " polys=%lu\n", lgss[lgid].polys); + pcb_fprintf(f, " trace_len=%$mm\n", lgss[lgid].trace_len); + fprintf(f, " copper_area={%f mm^2}\n", (double)lgss[lgid].copper_area / (double)PCB_MM_TO_COORD(1) / (double)PCB_MM_TO_COORD(1)); + fprintf(f, " }\n"); + } + } + fprintf(f, " }\n"); + + fprintf(f, " li:netlist {\n"); + for(nl = 0; nl < PCB_NUM_NETLISTS; nl++) { + htsp_entry_t *e; + pcb_cardinal_t terms = 0, best_terms = 0; + fprintf(f, " ha:%s {\n", pcb_netlist_names[nl]); + + for(e = htsp_first(&PCB->netlist[nl]); e != NULL; e = htsp_next(&PCB->netlist[nl], e)) { + pcb_net_t *net = e->value; + long numt = pcb_termlist_length(&net->conns); + + terms += numt; + if (numt > best_terms) + best_terms = numt; + } + fprintf(f, " nets=%ld\n", (long int)PCB->netlist[nl].used); + fprintf(f, " terminals=%ld\n", (long int)terms); + fprintf(f, " max_term_per_net=%ld\n", (long int)best_terms); + fprintf(f, " }\n"); + } + fprintf(f, " }\n"); + + PCB_SUBC_LOOP(PCB->Data) { + int bott; + pcb_cardinal_t slot = 0, hole = 0, all = 0; + pcb_any_obj_t *o; + pcb_data_it_t it; + htsi_t t; + htsi_entry_t *e; + + if (pcb_subc_get_side(subc, &bott) == 0) { + if (bott) + num_ebottom++; + else + num_etop++; + } + + /* count each terminal ID only once, because of heavy terminals */ + htsi_init(&t, strhash, strkeyeq); + for(o = pcb_data_first(&it, subc->data, PCB_OBJ_CLASS_REAL); o != NULL; o = pcb_data_next(&it)) { + if (o->term != NULL) { + htsi_set(&t, (char *)o->term, 1); + if (o->type == PCB_OBJ_PSTK) { + pcb_pstk_proto_t *proto = pcb_pstk_get_proto((pcb_pstk_t *)o); + if ((proto != NULL) && (proto->hdia > 0)) + hole++; + if ((proto != NULL) && (proto->mech_idx >= 0)) { + hole++; + slot++; + num_slots++; + } + } + } + } + + for (e = htsi_first(&t); e != NULL; e = htsi_next(&t, e)) { + num_terms++; + all++; + } + + /* a part is considered smd if it has at most half as many holes as terminals total */ + if ((hole*2 + slot*2) < all) + num_esmd++; + + htsi_uninit(&t); + } + PCB_END_LOOP; + + if (pcb_has_explicit_outline(PCB)) { + pcb_box_t bb; + pcb_data_bbox_naked(&bb, PCB->Data, pcb_true); + width = bb.X2 - bb.X1; + height = bb.Y2 - bb.Y1; + } + else { + width = PCB->MaxWidth; + height = PCB->MaxHeight; + } + + fprintf(f, " ha:board {\n"); + fprintf(f, " id={%s}\n", options[HA_board_id].str_value == NULL ? "" : options[HA_board_id].str_value); + fprintf(f, " license={%s}\n", options[HA_license].str_value); + fprintf(f, " format={%s}\n", PCB->Data->loader == NULL ? "unknown" : PCB->Data->loader->description); + pcb_fprintf(f, " width=%$mm\n", width); + pcb_fprintf(f, " height=%$mm\n", height); + fprintf(f, " gross_area={%.4f mm^2}\n", (double)PCB_COORD_TO_MM(width) * (double)PCB_COORD_TO_MM(height)); + fprintf(f, " holes_plated=%d\n", hp); + fprintf(f, " holes_unplated=%d\n", hup); + fprintf(f, " physical_copper_layers=%d\n", phg); + fprintf(f, " ha:subcircuits {\n"); + fprintf(f, " total=%ld\n", (long int)num_ebottom + num_etop); + fprintf(f, " top_side=%ld\n", (long int)num_etop); + fprintf(f, " bottom_side=%ld\n", (long int)num_ebottom); + fprintf(f, " smd=%ld\n", (long int)num_esmd); + fprintf(f, " pads=%ld\n", (long int)num_epads); + fprintf(f, " pins=%ld\n", (long int)num_epins); + fprintf(f, " terms=%ld\n", (long int)num_terms); + fprintf(f, " slots=%ld\n", (long int)num_slots); + fprintf(f, " }\n"); + fprintf(f, " }\n"); + + fprintf(f, "}\n"); + fclose(f); +} + +static int stat_parse_arguments(int *argc, char ***argv) +{ + pcb_hid_register_attributes(stat_attribute_list, sizeof(stat_attribute_list) / sizeof(stat_attribute_list[0]), stat_cookie, 0); + return pcb_hid_parse_command_line(argc, argv); +} + +static int stat_usage(const char *topic) +{ + fprintf(stderr, "\nstat exporter command line arguments:\n\n"); + pcb_hid_usage(stat_attribute_list, sizeof(stat_attribute_list) / sizeof(stat_attribute_list[0])); + fprintf(stderr, "\nUsage: pcb-rnd [generic_options] -x stat [stat options] foo.pcb\n\n"); + return 0; +} + +#include "dolists.h" + +int pplg_check_ver_export_stat(int ver_needed) { return 0; } + +void pplg_uninit_export_stat(void) +{ + free((char *)stat_attribute_list[HA_first_ver].default_val.str_value); + free((char *)stat_attribute_list[HA_license].default_val.str_value); + stat_attribute_list[HA_first_ver].default_val.str_value = NULL; + stat_attribute_list[HA_license].default_val.str_value = NULL; + pcb_hid_remove_attributes_by_cookie(stat_cookie); +} + +int pplg_init_export_stat(void) +{ + PCB_API_CHK_VER; + + memset(&stat_hid, 0, sizeof(pcb_hid_t)); + + pcb_hid_nogui_init(&stat_hid); + pcb_dhlp_draw_helpers_init(&stat_hid); + + stat_hid.struct_size = sizeof(pcb_hid_t); + stat_hid.name = "stat"; + stat_hid.description = "board statistics"; + stat_hid.exporter = 1; + + stat_hid.get_export_options = stat_get_export_options; + stat_hid.do_export = stat_do_export; + stat_hid.parse_arguments = stat_parse_arguments; + + stat_hid.usage = stat_usage; + + stat_attribute_list[HA_first_ver].default_val.str_value = pcb_strdup(PCB_VERSION); + stat_attribute_list[HA_license].default_val.str_value = pcb_strdup("proprietary/private"); + + pcb_hid_register_hid(&stat_hid); + + return 0; +} Index: tags/2.1.2/src_plugins/export_svg/Makefile =================================================================== --- tags/2.1.2/src_plugins/export_svg/Makefile (nonexistent) +++ tags/2.1.2/src_plugins/export_svg/Makefile (revision 24813) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_export_svg + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/2.1.2/src_plugins/export_svg/Plug.tmpasm =================================================================== --- tags/2.1.2/src_plugins/export_svg/Plug.tmpasm (nonexistent) +++ tags/2.1.2/src_plugins/export_svg/Plug.tmpasm (revision 24813) @@ -0,0 +1,8 @@ +put /local/pcb/mod {export_svg} +put /local/pcb/mod/OBJS [@ $(PLUGDIR)/export_svg/svg.o @] + +switch /local/pcb/export_svg/controls + case {buildin} include /local/pcb/tmpasm/buildin; end; + case {plugin} include /local/pcb/tmpasm/plugin; end; + case {disable} include /local/pcb/tmpasm/disable; end; +end Index: tags/2.1.2/src_plugins/export_svg/export_svg.pup =================================================================== --- tags/2.1.2/src_plugins/export_svg/export_svg.pup (nonexistent) +++ tags/2.1.2/src_plugins/export_svg/export_svg.pup (revision 24813) @@ -0,0 +1,9 @@ +$class export +$short SVG pcb_exporter +$long Scalable Vector Graphics (SVG) exporter +$fmt-native no +$fmt-feature-w write an svg (Scalable Vector Graphics) +$state works +$package export +default buildin +autoload 1 Index: tags/2.1.2/src_plugins/export_svg/svg.c =================================================================== --- tags/2.1.2/src_plugins/export_svg/svg.c (nonexistent) +++ tags/2.1.2/src_plugins/export_svg/svg.c (revision 24813) @@ -0,0 +1,902 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 2006 Dan McMahill + * Copyright (C) 2016 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +/* + * Based on the png exporter by Dan McMahill + */ + +#include "config.h" +#include "conf_core.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "math_helper.h" +#include "board.h" +#include "data.h" +#include "draw.h" +#include "error.h" +#include "layer.h" +#include "layer_vis.h" +#include "misc_util.h" +#include "compat_misc.h" +#include "plugins.h" +#include "safe_fs.h" +#include "funchash_core.h" + +#include "hid.h" +#include "hid_nogui.h" +#include "hid_draw_helpers.h" + +#include "hid_init.h" +#include "hid_attrib.h" +#include "hid_color.h" +#include "hid_cam.h" + + +static pcb_hid_t svg_hid; + +const char *svg_cookie = "svg HID"; + +static pcb_cam_t svg_cam; + +typedef struct hid_gc_s { + pcb_core_gc_t core_gc; + pcb_hid_t *me_pointer; + pcb_cap_style_t cap; + int width; + char *color; + int drill; + unsigned warned_elliptical:1; +} hid_gc_s; + +static const char *CAPS(pcb_cap_style_t cap) +{ + switch (cap) { + case pcb_cap_round: + return "round"; + case pcb_cap_square: + return "square"; + default: + assert(!"unhandled cap"); + return "round"; + } + return ""; +} + +static FILE *f = NULL; +static int group_open = 0; +static int opacity = 100, drawing_mask, drawing_hole, photo_mode, flip; + +static gds_t sbright, sdark, snormal, sclip; +static pcb_composite_op_t drawing_mode; +static int comp_cnt; + +/* Photo mode colors and hacks */ +static const char *board_color = "#464646"; +static const char *mask_color = "#00ff00"; +static float mask_opacity_factor = 0.5; + +static enum { + PHOTO_MASK, + PHOTO_SILK, + PHOTO_COPPER, + PHOTO_INNER +} photo_color; + +static struct { + const char *bright; + const char *normal; + const char *dark; + pcb_coord_t offs; +} photo_palette[] = { + /* MASK */ { "#00ff00", "#00ff00", "#00ff00", PCB_MM_TO_COORD(0) }, + /* SILK */ { "#ffffff", "#eeeeee", "#aaaaaa", PCB_MM_TO_COORD(0) }, + /* COPPER */ { "#bbbbbb", "#707090", "#555555", PCB_MM_TO_COORD(0.05) }, + /* INNER */ { "#222222", "#111111", "#000000", PCB_MM_TO_COORD(0) } +}; + +pcb_hid_attribute_t svg_attribute_list[] = { + /* other HIDs expect this to be first. */ + +/* %start-doc options "93 SVG Options" +@ftable @code +@item --outfile +Name of the file to be exported to. Can contain a path. +@end ftable +%end-doc +*/ + {"outfile", "Graphics output file", + PCB_HATT_STRING, 0, 0, {0, 0, 0}, 0, 0}, +#define HA_svgfile 0 + +/* %start-doc options "93 SVG Options" +@ftable @code +@cindex photo-mode +@item --photo-mode +Export a photo realistic image of the layout. +@end ftable +%end-doc +*/ + {"photo-mode", "Photo-realistic export mode", + PCB_HATT_BOOL, 0, 0, {0, 0, 0}, 0, 0}, +#define HA_photo_mode 1 + +/* %start-doc options "93 SVG Options" +@ftable @code +@cindex opacity +@item --opacity +Layer opacity +@end ftable +%end-doc +*/ + {"opacity", "Layer opacity", + PCB_HATT_INTEGER, 0, 100, {100, 0, 0}, 0, 0}, +#define HA_opacity 2 + +/* %start-doc options "93 SVG Options" +@ftable @code +@cindex flip +@item --flip +Flip board, look at it from the bottom side +@end ftable +%end-doc +*/ + {"flip", "Flip board", + PCB_HATT_BOOL, 0, 0, {0, 0, 0}, 0, 0}, +#define HA_flip 3 + + {"cam", "CAM instruction", + PCB_HATT_STRING, 0, 0, {0, 0, 0}, 0, 0} +#define HA_cam 4 +}; + +#define NUM_OPTIONS (sizeof(svg_attribute_list)/sizeof(svg_attribute_list[0])) + +#define TRX(x) +#define TRY(y) \ +do { \ + if (flip) \ + y = PCB->MaxHeight - y; \ +} while(0) + + +PCB_REGISTER_ATTRIBUTES(svg_attribute_list, svg_cookie) + +static pcb_hid_attr_val_t svg_values[NUM_OPTIONS]; + +static pcb_hid_attribute_t *svg_get_export_options(int *n) +{ + const char *suffix = ".svg"; + + if ((PCB != NULL) && (svg_attribute_list[HA_svgfile].default_val.str_value == NULL)) + pcb_derive_default_filename(PCB->Filename, &svg_attribute_list[HA_svgfile], suffix); + + if (n) + *n = NUM_OPTIONS; + return svg_attribute_list; +} + +void svg_hid_export_to_file(FILE * the_file, pcb_hid_attr_val_t * options) +{ + static int saved_layer_stack[PCB_MAX_LAYER]; + pcb_hid_expose_ctx_t ctx; + + ctx.view.X1 = 0; + ctx.view.Y1 = 0; + ctx.view.X2 = PCB->MaxWidth; + ctx.view.Y2 = PCB->MaxHeight; + + f = the_file; + + memcpy(saved_layer_stack, pcb_layer_stack, sizeof(pcb_layer_stack)); + + { + conf_force_set_bool(conf_core.editor.thin_draw, 0); + conf_force_set_bool(conf_core.editor.thin_draw_poly, 0); +/* conf_force_set_bool(conf_core.editor.check_planes, 0);*/ + conf_force_set_bool(conf_core.editor.show_solder_side, 0); + + if (options[HA_photo_mode].int_value) { + photo_mode = 1; + } + else + photo_mode = 0; + + if (options[HA_flip].int_value) { + flip = 1; + conf_force_set_bool(conf_core.editor.show_solder_side, 1); + } + else + flip = 0; + } + + if (photo_mode) { + pcb_fprintf(f, "\n", + 0, 0, PCB->MaxWidth, PCB->MaxHeight, board_color); + } + + opacity = options[HA_opacity].int_value; + + gds_init(&sbright); + gds_init(&sdark); + gds_init(&snormal); + pcb_hid_expose_all(&svg_hid, &ctx, NULL); + + conf_update(NULL, -1); /* restore forced sets */ +} + +static void group_close() +{ + if (group_open == 1) { + if (gds_len(&sdark) > 0) { + fprintf(f, "\n"); + fprintf(f, "%s", sdark.array); + gds_truncate(&sdark, 0); + } + + if (gds_len(&sbright) > 0) { + fprintf(f, "\n"); + fprintf(f, "%s", sbright.array); + gds_truncate(&sbright, 0); + } + + if (gds_len(&snormal) > 0) { + fprintf(f, "\n"); + fprintf(f, "%s", snormal.array); + gds_truncate(&snormal, 0); + } + + } + fprintf(f, "\n"); +} + +static void svg_header(void) +{ + pcb_coord_t w, h, x1, y1, x2, y2; + + fprintf(f, "\n"); + w = PCB->MaxWidth; + h = PCB->MaxHeight; + while((w < PCB_MM_TO_COORD(1024)) && (h < PCB_MM_TO_COORD(1024))) { + w *= 2; + h *= 2; + } + + x1 = PCB_MM_TO_COORD(2); + y1 = PCB_MM_TO_COORD(2); + x2 = PCB->MaxWidth; + y2 = PCB->MaxHeight; + x2 += PCB_MM_TO_COORD(5); + y2 += PCB_MM_TO_COORD(5); + pcb_fprintf(f, "\n", w, h, x1, y1, x2, y2); +} + +static void svg_footer(void) +{ + while(group_open) { + group_close(); + group_open--; + } + + fprintf(f, "\n"); +} + +static void svg_do_export(pcb_hid_attr_val_t * options) +{ + const char *filename; + int save_ons[PCB_MAX_LAYER + 2]; + int i; + + comp_cnt = 0; + + if (!options) { + svg_get_export_options(0); + for (i = 0; i < NUM_OPTIONS; i++) + svg_values[i] = svg_attribute_list[i].default_val; + options = svg_values; + } + + pcb_cam_begin(PCB, &svg_cam, options[HA_cam].str_value, svg_attribute_list, NUM_OPTIONS, options); + + if (svg_cam.fn_template == NULL) { + filename = options[HA_svgfile].str_value; + if (!filename) + filename = "pcb.svg"; + + f = pcb_fopen(svg_cam.active ? svg_cam.fn : filename, "wb"); + if (!f) { + perror(filename); + return; + } + svg_header(); + } + else + f = NULL; + + if (!svg_cam.active) + pcb_hid_save_and_show_layer_ons(save_ons); + + svg_hid_export_to_file(f, options); + + if (!svg_cam.active) + pcb_hid_restore_layer_ons(save_ons); + + svg_footer(); + fclose(f); + f = NULL; + + if (pcb_cam_end(&svg_cam) == 0) + pcb_message(PCB_MSG_ERROR, "svg cam export for '%s' failed to produce any content\n", options[HA_cam].str_value); +} + +static int svg_parse_arguments(int *argc, char ***argv) +{ + pcb_hid_register_attributes(svg_attribute_list, sizeof(svg_attribute_list) / sizeof(svg_attribute_list[0]), svg_cookie, 0); + return pcb_hid_parse_command_line(argc, argv); +} + +static int svg_set_layer_group(pcb_layergrp_id_t group, const char *purpose, int purpi, pcb_layer_id_t layer, unsigned int flags, int is_empty, pcb_xform_t **xform) +{ + int opa, is_our_mask = 0, is_our_silk = 0; + + if (is_empty) + return 0; + + if (flags & PCB_LYT_UI) + return 0; + + pcb_cam_set_layer_group(&svg_cam, group, purpose, purpi, flags, xform); + + if (svg_cam.fn_changed) { + if (f != NULL) { + svg_footer(); + fclose(f); + } + + f = pcb_fopen(svg_cam.fn, "wb"); + if (f == NULL) { + perror(svg_cam.fn); + return 0; + } + svg_header(); + } + + if (!svg_cam.active) { + if (flags & PCB_LYT_INVIS) + return 0; + + if (flags & PCB_LYT_MASK) { + if ((!photo_mode) && (!PCB->LayerGroups.grp[group].vis)) + return 0; /* not in photo mode or not visible */ + } + } + + switch(flags & PCB_LYT_ANYTHING) { + case PCB_LYT_MASK: is_our_mask = PCB_LAYERFLG_ON_VISIBLE_SIDE(flags); break; + case PCB_LYT_SILK: is_our_silk = PCB_LAYERFLG_ON_VISIBLE_SIDE(flags); break; + default:; + } + + if (!(flags & PCB_LYT_COPPER) && (!is_our_silk) && (!is_our_mask) && !(PCB_LAYER_IS_DRILL(flags, purpi)) && !(PCB_LAYER_IS_ROUTE(flags, purpi))) + return 0; + + while(group_open) { + group_close(); + group_open--; + } + + { + char tmp_ln[PCB_PATH_MAX]; + const char *name = name = pcb_layer_to_file_name(tmp_ln, layer, flags, purpose, purpi, PCB_FNS_fixed); + fprintf(f, "\n"); + group_open = 1; + + if (photo_mode) { + if (is_our_silk) + photo_color = PHOTO_SILK; + else if (is_our_mask) + photo_color = PHOTO_MASK; + else if (group >= 0) { + if (PCB_LAYERFLG_ON_VISIBLE_SIDE(flags)) + photo_color = PHOTO_COPPER; + else + photo_color = PHOTO_INNER; + } + } + + drawing_hole = PCB_LAYER_IS_DRILL(flags, purpi); + + return 1; +} + + +static pcb_hid_gc_t svg_make_gc(void) +{ + pcb_hid_gc_t rv = (pcb_hid_gc_t) calloc(sizeof(hid_gc_s), 1); + rv->me_pointer = &svg_hid; + rv->cap = pcb_cap_round; + rv->width = 1; + rv->color = NULL; + return rv; +} + +static void svg_destroy_gc(pcb_hid_gc_t gc) +{ + free(gc); +} + +static void svg_set_drawing_mode(pcb_composite_op_t op, pcb_bool direct, const pcb_box_t *screen) +{ + drawing_mode = op; + + if (direct) + return; + + switch(op) { + case PCB_HID_COMP_RESET: + comp_cnt++; + gds_init(&sclip); + pcb_append_printf(&snormal, "\n"); + pcb_append_printf(&snormal, "\n"); + pcb_append_printf(&snormal, "\n", comp_cnt); + pcb_append_printf(&sclip, "\n", comp_cnt, PCB->MaxWidth, PCB->MaxHeight); + break; + + case PCB_HID_COMP_POSITIVE: + case PCB_HID_COMP_POSITIVE_XOR: + case PCB_HID_COMP_NEGATIVE: + break; + + case PCB_HID_COMP_FLUSH: + pcb_append_printf(&snormal, "\n"); + pcb_append_printf(&sclip, "\n"); + gds_append_str(&snormal, sclip.array); + pcb_append_printf(&snormal, "\n"); + pcb_append_printf(&snormal, "\n", comp_cnt, comp_cnt); + pcb_append_printf(&snormal, "\n"); + gds_uninit(&sclip); + break; + } +} + +static const char *svg_color(pcb_hid_gc_t gc) +{ + return gc->color; +} + +static const char *svg_clip_color(pcb_hid_gc_t gc) +{ + if ((drawing_mode == PCB_HID_COMP_POSITIVE) || (drawing_mode == PCB_HID_COMP_POSITIVE_XOR)) + return "#FFFFFF"; + if (drawing_mode == PCB_HID_COMP_NEGATIVE) + return "#000000"; + return NULL; +} + +static void svg_set_color(pcb_hid_gc_t gc, const pcb_color_t *color) +{ + const char *name; + gc->drill = 0; + + if (color == NULL) + name = "#ff0000"; + else + name = color->str; + + if (pcb_color_is_drill(color)) { + name = "#ffffff"; + gc->drill = 1; + } + if (drawing_mask) + name = mask_color; + if ((gc->color != NULL) && (strcmp(gc->color, name) == 0)) + return; + free(gc->color); + gc->color = pcb_strdup(name); +} + +static void svg_set_line_cap(pcb_hid_gc_t gc, pcb_cap_style_t style) +{ + gc->cap = style; +} + +static void svg_set_line_width(pcb_hid_gc_t gc, pcb_coord_t width) +{ + gc->width = width; +} + +static void indent(gds_t *s) +{ + static char ind[] = " "; + if (group_open < sizeof(ind)-1) { + ind[group_open] = '\0'; + if (s == NULL) + pcb_fprintf(f, ind); + else + pcb_append_printf(s, ind); + ind[group_open] = ' '; + return; + } + + if (s == NULL) + pcb_fprintf(f, ind); + else + pcb_append_printf(s, ind); +} + +static void svg_set_draw_xor(pcb_hid_gc_t gc, int xor_) +{ + ; +} + +#define fix_rect_coords() \ + if (x1 > x2) {\ + pcb_coord_t t = x1; \ + x1 = x2; \ + x2 = t; \ + } \ + if (y1 > y2) { \ + pcb_coord_t t = y1; \ + y1 = y2; \ + y2 = t; \ + } + +static void draw_rect(pcb_hid_gc_t gc, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t w, pcb_coord_t h, pcb_coord_t stroke) +{ + const char *clip_color = svg_clip_color(gc); + + indent(&snormal); + pcb_append_printf(&snormal, "\n", + x1, y1, w, h, stroke, svg_color(gc), CAPS(gc->cap)); + if (clip_color != NULL) { + indent(&sclip); + pcb_append_printf(&sclip, "\n", + x1, y1, w, h, stroke, clip_color, CAPS(gc->cap)); + } +} + +static void svg_draw_rect(pcb_hid_gc_t gc, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2) +{ + fix_rect_coords(); + draw_rect(gc, x1, y1, x2-x1, y2-y1, gc->width); +} + +static void draw_fill_rect(pcb_hid_gc_t gc, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t w, pcb_coord_t h) +{ + const char *clip_color = svg_clip_color(gc); + if ((photo_mode) && (clip_color == NULL)) { + pcb_coord_t photo_offs = photo_palette[photo_color].offs; + if (photo_offs != 0) { + indent(&sdark); + pcb_append_printf(&sdark, "\n", + x1+photo_offs, y1+photo_offs, w, h, photo_palette[photo_color].dark); + indent(&sbright); + pcb_append_printf(&sbright, "\n", + x1-photo_offs, y1-photo_offs, w, h, photo_palette[photo_color].bright); + } + indent(&snormal); + pcb_append_printf(&snormal, "\n", + x1, y1, w, h, photo_palette[photo_color].normal); + } + else { + indent(&snormal); + pcb_append_printf(&snormal, "\n", + x1, y1, w, h, svg_color(gc)); + if (clip_color != NULL) + pcb_append_printf(&sclip, "\n", + x1, y1, w, h, clip_color); + } +} + +static void svg_fill_rect(pcb_hid_gc_t gc, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2) +{ + TRX(x1); TRY(y1); TRX(x2); TRY(y2); + fix_rect_coords(); + draw_fill_rect(gc, x1, y1, x2-x1, y2-y1); +} + +static void pcb_line_draw(pcb_hid_gc_t gc, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2) +{ + const char *clip_color = svg_clip_color(gc); + if ((photo_mode) && (clip_color == NULL)) { + pcb_coord_t photo_offs = photo_palette[photo_color].offs; + if (photo_offs != 0) { + indent(&sbright); + pcb_append_printf(&sbright, "\n", + x1-photo_offs, y1-photo_offs, x2-photo_offs, y2-photo_offs, gc->width, photo_palette[photo_color].bright, CAPS(gc->cap)); + indent(&sdark); + pcb_append_printf(&sdark, "\n", + x1+photo_offs, y1+photo_offs, x2+photo_offs, y2+photo_offs, gc->width, photo_palette[photo_color].dark, CAPS(gc->cap)); + } + indent(&snormal); + pcb_append_printf(&snormal, "\n", + x1, y1, x2, y2, gc->width, photo_palette[photo_color].normal, CAPS(gc->cap)); + } + else { + indent(&snormal); + pcb_append_printf(&snormal, "\n", + x1, y1, x2, y2, gc->width, svg_color(gc), CAPS(gc->cap)); + if (clip_color != NULL) { + pcb_append_printf(&sclip, "\n", + x1, y1, x2, y2, gc->width, clip_color, CAPS(gc->cap)); + } + } +} + +static void svg_draw_line(pcb_hid_gc_t gc, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2) +{ + TRX(x1); TRY(y1); TRX(x2); TRY(y2); + pcb_line_draw(gc, x1, y1, x2, y2); +} + +static void pcb_arc_draw(pcb_hid_gc_t gc, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t r, pcb_coord_t x2, pcb_coord_t y2, pcb_coord_t stroke, int large, int sweep) +{ + const char *clip_color = svg_clip_color(gc); + if ((photo_mode) && (clip_color == NULL)) { + pcb_coord_t photo_offs = photo_palette[photo_color].offs; + if (photo_offs != 0) { + indent(&sbright); + pcb_append_printf(&sbright, "\n", + x1-photo_offs, y1-photo_offs, r, r, large, sweep, x2-photo_offs, y2-photo_offs, gc->width, photo_palette[photo_color].bright, CAPS(gc->cap)); + indent(&sdark); + pcb_append_printf(&sdark, "\n", + x1+photo_offs, y1+photo_offs, r, r, large, sweep, x2+photo_offs, y2+photo_offs, gc->width, photo_palette[photo_color].dark, CAPS(gc->cap)); + } + indent(&snormal); + pcb_append_printf(&snormal, "\n", + x1, y1, r, r, large, sweep, x2, y2, gc->width, photo_palette[photo_color].normal, CAPS(gc->cap)); + } + else { + indent(&snormal); + pcb_append_printf(&snormal, "\n", + x1, y1, r, r, large, sweep, x2, y2, gc->width, svg_color(gc), CAPS(gc->cap)); + if (clip_color != NULL) + pcb_append_printf(&sclip, "\n", + x1, y1, r, r, large, sweep, x2, y2, gc->width, clip_color, CAPS(gc->cap)); + } +} + +static void svg_draw_arc(pcb_hid_gc_t gc, pcb_coord_t cx, pcb_coord_t cy, pcb_coord_t width, pcb_coord_t height, pcb_angle_t start_angle, pcb_angle_t delta_angle) +{ + pcb_coord_t x1, y1, x2, y2, diff = 0, diff2, maxdiff; + pcb_angle_t sa, ea; + + /* degenerate case: r=0 means a single dot */ + if ((width == 0) && (height == 0)) { + pcb_line_draw(gc, cx, cy, cx, cy); + return; + } + + /* detect elliptical arcs: if diff between radii is above 0.1% */ + diff2 = width - height; + if (diff2 < 0) + diff2 = -diff2; + maxdiff = width; + if (height > maxdiff) + maxdiff = height; + if (diff2 > maxdiff / 1000) { + if (!gc->warned_elliptical) { + pcb_message(PCB_MSG_ERROR, "Can't draw elliptical arc on svg; object omitted; expect BROKEN TRACE\n"); + gc->warned_elliptical = 1; + } + return; + } + + TRX(cx); TRY(cy); + + /* calculate start and end angles considering flip */ + start_angle = 180 - start_angle; + delta_angle = -delta_angle; + if (flip) { + start_angle = -start_angle; + delta_angle = -delta_angle; + } + + /* workaround for near-360 deg rendering bugs */ + if ((delta_angle >= +360.0) || (delta_angle <= -360.0)) { + svg_draw_arc(gc, cx, cy, width, height, 0, 180); + svg_draw_arc(gc, cx, cy, width, height, 180, 180); + return; + } + + if (fabs(delta_angle) <= 0.001) { delta_angle = 0.001; diff=1; } + + sa = start_angle; + ea = start_angle + delta_angle; + + /* calculate the endpoints */ + x2 = pcb_round((double)cx + ((double)width * cos(sa * M_PI / 180))); + y2 = pcb_round((double)cy + ((double)width * sin(sa * M_PI / 180))); + x1 = pcb_round((double)cx + ((double)width * cos(ea * M_PI / 180))+diff); + y1 = pcb_round((double)cy + ((double)width * sin(ea * M_PI / 180))+diff); + + pcb_arc_draw(gc, x1, y1, width, x2, y2, gc->width, (fabs(delta_angle) > 180), (delta_angle < 0.0)); +} + +static void draw_fill_circle(pcb_hid_gc_t gc, pcb_coord_t cx, pcb_coord_t cy, pcb_coord_t r, pcb_coord_t stroke) +{ + const char *clip_color = svg_clip_color(gc); + if ((photo_mode) && (clip_color == NULL)) { + if (!drawing_hole) { + pcb_coord_t photo_offs = photo_palette[photo_color].offs; + if ((!gc->drill) && (photo_offs != 0)) { + indent(&sbright); + pcb_append_printf(&sbright, "\n", + cx-photo_offs, cy-photo_offs, r, stroke, photo_palette[photo_color].bright); + + indent(&sdark); + pcb_append_printf(&sdark, "\n", + cx+photo_offs, cy+photo_offs, r, stroke, photo_palette[photo_color].dark); + } + indent(&snormal); + pcb_append_printf(&snormal, "\n", + cx, cy, r, stroke, photo_palette[photo_color].normal); + } + else { + indent(&snormal); + pcb_append_printf(&snormal, "\n", + cx, cy, r, stroke, "#000000"); + } + } + else{ + indent(&snormal); + pcb_append_printf(&snormal, "\n", + cx, cy, r, stroke, svg_color(gc)); + if (clip_color != NULL) + pcb_append_printf(&sclip, "\n", + cx, cy, r, stroke, clip_color); + } +} + +static void svg_fill_circle(pcb_hid_gc_t gc, pcb_coord_t cx, pcb_coord_t cy, pcb_coord_t radius) +{ + TRX(cx); TRY(cy); + draw_fill_circle(gc, cx, cy, radius, gc->width); +} + +static void draw_poly(gds_t *s, pcb_hid_gc_t gc, int n_coords, pcb_coord_t * x, pcb_coord_t * y, pcb_coord_t dx, pcb_coord_t dy, const char *clr) +{ + int i; + float poly_bloat = 0.01; + + indent(s); + gds_append_str(s, "\n", poly_bloat, clr, clr); +} + +static void svg_fill_polygon_offs(pcb_hid_gc_t gc, int n_coords, pcb_coord_t *x, pcb_coord_t *y, pcb_coord_t dx, pcb_coord_t dy) +{ + const char *clip_color = svg_clip_color(gc); + if ((photo_mode) && (clip_color == NULL)) { + pcb_coord_t photo_offs = photo_palette[photo_color].offs; + if (photo_offs != 0) { + draw_poly(&sbright, gc, n_coords, x, y, dx-photo_offs, dy-photo_offs, photo_palette[photo_color].bright); + draw_poly(&sdark, gc, n_coords, x, y, dx+photo_offs, dy+photo_offs, photo_palette[photo_color].dark); + } + draw_poly(&snormal, gc, n_coords, x, y, dx, dy, photo_palette[photo_color].normal); + } + else { + draw_poly(&snormal, gc, n_coords, x, y, dx, dy, svg_color(gc)); + if (clip_color != NULL) + draw_poly(&sclip, gc, n_coords, x, y, dx, dy, clip_color); + } +} + +static void svg_fill_polygon(pcb_hid_gc_t gc, int n_coords, pcb_coord_t *x, pcb_coord_t *y) +{ + svg_fill_polygon_offs(gc, n_coords, x, y, 0, 0); +} + + +static void svg_calibrate(double xval, double yval) +{ + pcb_message(PCB_MSG_ERROR, "svg_calibrate() not implemented"); + return; +} + +static void svg_set_crosshair(pcb_coord_t x, pcb_coord_t y, int a) +{ +} + +static int svg_usage(const char *topic) +{ + fprintf(stderr, "\nsvg exporter command line arguments:\n\n"); + pcb_hid_usage(svg_attribute_list, sizeof(svg_attribute_list) / sizeof(svg_attribute_list[0])); + fprintf(stderr, "\nUsage: pcb-rnd [generic_options] -x svg [svg options] foo.pcb\n\n"); + return 0; +} + +#include "dolists.h" + +int pplg_check_ver_export_svg(int ver_needed) { return 0; } + +void pplg_uninit_export_svg(void) +{ + pcb_hid_remove_attributes_by_cookie(svg_cookie); +} + +int pplg_init_export_svg(void) +{ + PCB_API_CHK_VER; + + memset(&svg_hid, 0, sizeof(pcb_hid_t)); + + pcb_hid_nogui_init(&svg_hid); + pcb_dhlp_draw_helpers_init(&svg_hid); + + svg_hid.struct_size = sizeof(pcb_hid_t); + svg_hid.name = "svg"; + svg_hid.description = "Scalable Vector Graphics export"; + svg_hid.exporter = 1; + + svg_hid.get_export_options = svg_get_export_options; + svg_hid.do_export = svg_do_export; + svg_hid.parse_arguments = svg_parse_arguments; + svg_hid.set_layer_group = svg_set_layer_group; + svg_hid.make_gc = svg_make_gc; + svg_hid.destroy_gc = svg_destroy_gc; + svg_hid.set_drawing_mode = svg_set_drawing_mode; + svg_hid.set_color = svg_set_color; + svg_hid.set_line_cap = svg_set_line_cap; + svg_hid.set_line_width = svg_set_line_width; + svg_hid.set_draw_xor = svg_set_draw_xor; + svg_hid.draw_line = svg_draw_line; + svg_hid.draw_arc = svg_draw_arc; + svg_hid.draw_rect = svg_draw_rect; + svg_hid.fill_circle = svg_fill_circle; + svg_hid.fill_polygon = svg_fill_polygon; + svg_hid.fill_polygon_offs = svg_fill_polygon_offs; + svg_hid.fill_rect = svg_fill_rect; + svg_hid.calibrate = svg_calibrate; + svg_hid.set_crosshair = svg_set_crosshair; + + svg_hid.usage = svg_usage; + + pcb_hid_register_hid(&svg_hid); + + return 0; +} Index: tags/2.1.2/src_plugins/export_test/Makefile =================================================================== --- tags/2.1.2/src_plugins/export_test/Makefile (nonexistent) +++ tags/2.1.2/src_plugins/export_test/Makefile (revision 24813) @@ -0,0 +1,6 @@ +all: + cd ../../src && $(MAKE) mod_export_test + + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/2.1.2/src_plugins/export_test/Plug.tmpasm =================================================================== --- tags/2.1.2/src_plugins/export_test/Plug.tmpasm (nonexistent) +++ tags/2.1.2/src_plugins/export_test/Plug.tmpasm (revision 24813) @@ -0,0 +1,8 @@ +put /local/pcb/mod {export_test} +put /local/pcb/mod/OBJS [@ $(PLUGDIR)/export_test/export_test.o @] + +switch /local/pcb/export_test/controls + case {buildin} include /local/pcb/tmpasm/buildin; end; + case {plugin} include /local/pcb/tmpasm/plugin; end; + case {disable} include /local/pcb/tmpasm/disable; end; +end Index: tags/2.1.2/src_plugins/export_test/export_test.c =================================================================== --- tags/2.1.2/src_plugins/export_test/export_test.c (nonexistent) +++ tags/2.1.2/src_plugins/export_test/export_test.c (revision 24813) @@ -0,0 +1,134 @@ +#include "config.h" +#include "conf_core.h" + +#include +#include +#include +#include +#include + +#include "build_run.h" +#include "board.h" +#include "data.h" +#include "error.h" +#include "pcb-printf.h" +#include "plugins.h" + +#include "hid.h" +#include "hid_nogui.h" +#include "hid_attrib.h" +#include "hid_cam.h" +#include "hid_init.h" + +const char *export_test_cookie = "export_test HID"; + +static pcb_hid_attribute_t export_test_options[] = { +/* %start-doc options "8 export_test Creation" +@ftable @code +@item --export_testfile +Name of the export_test output file. Use stdout if not specified. +@end ftable +%end-doc +*/ + {"export_testfile", "Name of the export_test output file", + PCB_HATT_STRING, 0, 0, {0, 0, 0}, 0, 0}, +#define HA_export_testfile 0 +}; + +#define NUM_OPTIONS (sizeof(export_test_options)/sizeof(export_test_options[0])) + +static pcb_hid_attr_val_t export_test_values[NUM_OPTIONS]; + +static const char *export_test_filename; + +static pcb_hid_attribute_t *export_test_get_export_options(int *n) +{ + if ((PCB != NULL) && (export_test_options[HA_export_testfile].default_val.str_value == NULL)) + pcb_derive_default_filename(PCB->Filename, &export_test_options[HA_export_testfile], ".export_test"); + + if (n) + *n = NUM_OPTIONS; + return export_test_options; +} + + +/* + * If fp is not NULL then print out the bill of materials contained in + * export_test. Either way, free all memory which has been allocated for export_test. + */ +static void print_and_free(FILE * fp, /*export_testList*/ void * export_test) +{ +} + +static int Printexport_test(void) +{ + return 0; +} + +static void export_test_do_export(pcb_hid_attr_val_t * options) +{ + int i; + + if (!options) { + export_test_get_export_options(0); + for (i = 0; i < NUM_OPTIONS; i++) + export_test_values[i] = export_test_options[i].default_val; + options = export_test_values; + } + + export_test_filename = options[HA_export_testfile].str_value; + if (!export_test_filename) + export_test_filename = "pcb-out.export_test"; + else { +TODO(": set some FILE *fp to stdout") + } + + Printexport_test(); +} + +static int export_test_usage(const char *topic) +{ + fprintf(stderr, "\nexport_test exporter command line arguments:\n\n"); + pcb_hid_usage(export_test_options, sizeof(export_test_options) / sizeof(export_test_options[0])); + fprintf(stderr, "\nUsage: pcb-rnd [generic_options] -x export_test [export_test_options] foo.pcb\n\n"); + return 0; +} + + +static int export_test_parse_arguments(int *argc, char ***argv) +{ + pcb_hid_register_attributes(export_test_options, sizeof(export_test_options) / sizeof(export_test_options[0]), export_test_cookie, 0); + return pcb_hid_parse_command_line(argc, argv); +} + +pcb_hid_t export_test_hid; + +int pplg_check_ver_export_test(int ver_needed) { return 0; } + +void pplg_uninit_export_test(void) +{ +} + +int pplg_init_export_test(void) +{ + PCB_API_CHK_VER; + + memset(&export_test_hid, 0, sizeof(pcb_hid_t)); + + pcb_hid_nogui_init(&export_test_hid); + + export_test_hid.struct_size = sizeof(pcb_hid_t); + export_test_hid.name = "export_test"; + export_test_hid.description = "Exports a dump of HID calls"; + export_test_hid.exporter = 1; + export_test_hid.hide_from_gui = 1; + + export_test_hid.get_export_options = export_test_get_export_options; + export_test_hid.do_export = export_test_do_export; + export_test_hid.parse_arguments = export_test_parse_arguments; + + export_test_hid.usage = export_test_usage; + + pcb_hid_register_hid(&export_test_hid); + return 0; +} Index: tags/2.1.2/src_plugins/export_test/export_test.pup =================================================================== --- tags/2.1.2/src_plugins/export_test/export_test.pup (nonexistent) +++ tags/2.1.2/src_plugins/export_test/export_test.pup (revision 24813) @@ -0,0 +1,6 @@ +$class export +$short dummy test pcb_exporter +$long A thin layer of code to dump exporter calls for testing the HID exporter API. +$state WIP +default disable +autoload 1 Index: tags/2.1.2/src_plugins/export_vfs_fuse/Makefile =================================================================== --- tags/2.1.2/src_plugins/export_vfs_fuse/Makefile (nonexistent) +++ tags/2.1.2/src_plugins/export_vfs_fuse/Makefile (revision 24813) @@ -0,0 +1,6 @@ +all: + cd ../../src && $(MAKE) mod_export_vfs_fuse + + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/2.1.2/src_plugins/export_vfs_fuse/Plug.tmpasm =================================================================== --- tags/2.1.2/src_plugins/export_vfs_fuse/Plug.tmpasm (nonexistent) +++ tags/2.1.2/src_plugins/export_vfs_fuse/Plug.tmpasm (revision 24813) @@ -0,0 +1,17 @@ +put /local/pcb/mod {export_vfs_fuse} +put /local/pcb/mod/OBJS [@ $(PLUGDIR)/export_vfs_fuse/export_vfs_fuse.o @] + +switch /local/pcb/export_vfs_fuse/controls + case {disable} end; + default + put /local/pcb/mod/CFLAGS [@@/target/libs/sul/fuse/cflags@@] + put /local/pcb/mod/LDFLAGS [@@/target/libs/sul/fuse/ldflags@@] + append /local/pcb/mod/DISTCLEANFILES { $(PLUGDIR)/export_vfs_fuse/fuse_includes.h } + end +end + +switch /local/pcb/export_vfs_fuse/controls + case {buildin} include /local/pcb/tmpasm/buildin; end; + case {plugin} include /local/pcb/tmpasm/plugin; end; + case {disable} include /local/pcb/tmpasm/disable; end; +end Index: tags/2.1.2/src_plugins/export_vfs_fuse/README =================================================================== --- tags/2.1.2/src_plugins/export_vfs_fuse/README (nonexistent) +++ tags/2.1.2/src_plugins/export_vfs_fuse/README (revision 24813) @@ -0,0 +1,20 @@ +1. Mounting a board + + mkdir /tmp/mntpt + pcb-rnd -x vfs_fuse board.lht /tmp/mntpt + +This will start a pcb-rnd process in the background. The proces will load +board.lht, just like if it was a normal GUI or CLI user session, until the +unmount. + +Make sure /dev/fuse has the right permissions and your user has write access +to it. A typical setup is: + - /dev/fuse having group +rw with group owner set to 'fuse' + - the user added in the 'fuse' group + +2. Unmounting a board + + fusermount -u /tmp/mntpt + +This is when the board is saved if there was any change (write) while it +was mounted. Index: tags/2.1.2/src_plugins/export_vfs_fuse/export_vfs_fuse.c =================================================================== --- tags/2.1.2/src_plugins/export_vfs_fuse/export_vfs_fuse.c (nonexistent) +++ tags/2.1.2/src_plugins/export_vfs_fuse/export_vfs_fuse.c (revision 24813) @@ -0,0 +1,385 @@ +#define _XOPEN_SOURCE 500 + +#include "fuse_includes.h" + +#include "config.h" +#include "conf_core.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "build_run.h" +#include "board.h" +#include "data.h" +#include "error.h" +#include "pcb-printf.h" +#include "plugins.h" +#include "plug_io.h" +#include "safe_fs.h" +#include "compat_fs.h" + +#include "hid.h" +#include "hid_attrib.h" +#include "hid_init.h" +#include "hid_nogui.h" + +#include "../src_plugins/lib_vfs/lib_vfs.h" + +static const char *export_vfs_fuse_cookie = "export_vfs_fuse HID"; +static int pcb_fuse_changed; +static char fuse_cwd[PCB_PATH_MAX]; + +static pcb_hid_attribute_t *export_vfs_fuse_get_export_options(int *n) +{ + return 0; +} + +typedef struct { + const char *path; + void *buf; + fuse_fill_dir_t filler; + int pathlen; +} pcb_fuse_list_t; + +static void pcb_fuse_list_cb(void *ctx_, const char *path, int isdir) +{ + pcb_fuse_list_t *ctx = ctx_; + int child, direct, pl; + + pl = strlen(path); + if (pl <= ctx->pathlen) + return; + + if (ctx->pathlen > 0) { + child = memcmp(path, ctx->path, ctx->pathlen) == 0; + path += ctx->pathlen; + if (*path == '/') + path++; + else if (*path != '\0') + child = 0; + } + else + child = 1; + + if ((child) && (*path != '\0')) { + direct = (strchr(path, '/') == NULL); + if (direct) { + struct stat st; + memset(&st, 0, sizeof(struct stat)); + st.st_mode = (isdir ? (S_IFDIR | 0755) : (S_IFREG | 0644)); + st.st_nlink = 1 + !!isdir; + ctx->filler(ctx->buf, path, &st, 0); + } + } +} + +static int pcb_fuse_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *fi) +{ + pcb_fuse_list_t ctx; + + if (*path == '/') + path++; + + ctx.path = path; + ctx.buf = buf; + ctx.filler = filler; + ctx.pathlen = strlen(path); + + filler(buf, ".", NULL, 0); + filler(buf, "..", NULL, 0); + pcb_vfs_list(PCB, pcb_fuse_list_cb, &ctx); + + return 0; +} + +static int pcb_fuse_getattr(const char *path, struct stat *stbuf) +{ + int isdir; + gds_t data; + + gds_init(&data); + if (strcmp(path, "/") != 0) { + if (*path == '/') + path++; + if (pcb_vfs_access(PCB, path, &data, 0, &isdir) != 0) { + gds_uninit(&data); + return -ENOENT; + } + } + else + isdir = 1; + + memset(stbuf, 0, sizeof(struct stat)); + stbuf->st_mode = (isdir ? (S_IFDIR | 0755) : (S_IFREG | 0644)); + stbuf->st_nlink = 1 + !!isdir; + stbuf->st_size = data.used; + + gds_uninit(&data); + return 0; +} + +static int pcb_fuse_access(const char *path, int mask) +{ + return 0; +} + +static int pcb_fuse_read(const char *path, char *buf, size_t size, off_t offset, struct fuse_file_info *fi) +{ + gds_t data; + int len; + + if (*path == '/') + path++; + gds_init(&data); + if (pcb_vfs_access(PCB, path, &data, 0, NULL) != 0) { + gds_uninit(&data); + return -ENOENT; + } + + len = data.used; + len -= offset; + if (len > 0) + memcpy(buf, data.array + offset, len); + else + len = 0; + gds_uninit(&data); + + return len; +} + +static int pcb_fuse_write(const char *path, const char *buf, size_t size, off_t offset, struct fuse_file_info *fi) +{ + gds_t data, src; + + if (*path == '/') + path++; + + gds_init(&data); + + if (offset > 0) { + if (pcb_vfs_access(PCB, path, &data, 0, NULL) != 0) { + gds_uninit(&data); + return -ENOENT; + } + src.array = (char *)buf; + src.used = src.alloced = size; + src.no_realloc = 1; + gds_copy(&data, offset, &src, 0, size); + } + else + gds_append_len(&data, buf, size); + + if ((data.used > 0) && (data.array[data.used-1] == '\n')) + data.array[data.used-1] = '\0'; + + if (pcb_vfs_access(PCB, path, &data, 1, NULL) != 0) { + gds_uninit(&data); + return -EIO; + } + + gds_uninit(&data); + pcb_fuse_changed = 1; + return size; +} + +static int pcb_fuse_truncate(const char *path, off_t size) +{ + gds_t data; + + if (*path == '/') + path++; + gds_init(&data); + if (pcb_vfs_access(PCB, path, &data, 0, NULL) != 0) { + gds_uninit(&data); + return -ENOENT; + } + + if ((size == data.used) || (size < 0)) + return 0; + + if (size < data.used) { + data.used = size; + data.array[size] = '\0'; + } + else { + size_t old = data.used; + gds_enlarge(&data, size); + if ((old > 0)&& (data.array[old-1] == '\n')) + data.array[old-1] = ' '; + memset(&data.array[old-1], ' ', size-old-1); + data.array[size] = '\0'; + } + + if (pcb_vfs_access(PCB, path, &data, 1, NULL) != 0) { + gds_uninit(&data); + return -EIO; + } + + gds_uninit(&data); + pcb_fuse_changed = 1; + return 0; +} + + +static int pcb_fuse_open(const char *path, struct fuse_file_info *fi) +{ + return 0; +} + +static void pcb_fuse_destroy(void *private_data) +{ + char *fn = PCB->Filename; + + if (!pcb_fuse_changed) + return; + + /* pwd is lost during daemonisation */ + if (!pcb_is_path_abs(PCB->Filename)) + fn = pcb_strdup_printf("%s%c%s", fuse_cwd, PCB_DIR_SEPARATOR_C, PCB->Filename); + + if (pcb_save_pcb(fn, NULL) != 0) { + fprintf(stderr, "Failed to save the modified board file\n"); + exit(1); + } +} + + +static char **fuse_argv; +static int fuse_argc = 0; +static void export_vfs_fuse_do_export(pcb_hid_attr_val_t *options) +{ + static struct fuse_operations oper; + + pcb_get_wd(fuse_cwd); + + oper.readdir = pcb_fuse_readdir; + oper.open = pcb_fuse_open; + oper.read = pcb_fuse_read; + oper.write = pcb_fuse_write; + oper.truncate = pcb_fuse_truncate; + oper.getattr = pcb_fuse_getattr; + oper.access = pcb_fuse_access; + oper.destroy = pcb_fuse_destroy; + + pcb_fuse_changed = 0; + if (fuse_main(fuse_argc, fuse_argv, &oper, NULL) != 0) + fprintf(stderr, "fuse_main() returned error.\n"); +} + +static int export_vfs_fuse_usage(const char *topic) +{ + fprintf(stderr, "\nexport_vfs_fuse exporter command line arguments are plain fuse aguments.\n\n"); + fprintf(stderr, "\nUsage: pcb-rnd [pcb-rnd-options] [-o fuse-options] foo.pcb mountpoint\n\n"); + return 0; +} + +#define arg_append(dst_argc, dst_argv, str) dst_argv[dst_argc++] = str + +#define arg_copy_to_fuse(cnt) \ +do { \ + int __i__; \ + for(__i__ = 0; __i__ < (cnt); __i__++,n++) \ + arg_append(fuse_argc, fuse_argv, in_argv[n]); \ + n--; \ +} while(0) + +#define arg_copy_to_pcb(cnt) \ +do { \ + int __i__; \ + for(__i__ = 0; __i__ < (cnt); __i__++,n++) \ + arg_append(fuse_ret_argc, fuse_ret_argv, in_argv[n]); \ + n--; \ +} while(0) + +static char **fuse_ret_argv; +static int fuse_ret_argc = 0; +static int export_vfs_fuse_parse_arguments(int *argc, char ***argv) +{ + int n, in_argc = *argc; + char **in_argv = *argv; + char *board = NULL, *dir = NULL; + + fuse_argv = malloc(sizeof(char *) * (*argc+1)); + fuse_argc = 0; + fuse_ret_argv = malloc(sizeof(char *) * (*argc+1)); + fuse_ret_argc = 0; + + arg_append(fuse_argc, fuse_argv, "pcb-rnd"); /* program name */ + arg_append(fuse_argc, fuse_argv, "?"); /* make room for the mount point */ + + for(n = 0; n < in_argc; n++) { + if (strcmp(in_argv[n], "-o") == 0) arg_copy_to_fuse(2); + else if (*in_argv[n] == '-') arg_copy_to_pcb(2); + else { + if (board == NULL) board = in_argv[n]; + else if (dir == NULL) dir = in_argv[n]; + else { + fprintf(stderr, "export_vfs_fuse: excess unrecognized argument: '%s'\n", in_argv[n]); + exit(1); + } + } + } + + if (board == NULL) { + fprintf(stderr, "export_vfs_fuse: board name is required\n"); + exit(1); + } + + if (dir == NULL) { + fprintf(stderr, "export_vfs_fuse: mount point is required\n"); + exit(1); + } + + arg_append(fuse_ret_argc, fuse_ret_argv, board); + fuse_argv[1] = dir; + + fuse_argv[fuse_argc] = NULL; + fuse_ret_argv[fuse_ret_argc] = NULL; + + argc = &fuse_ret_argc; + *argv = fuse_ret_argv; + return 0; +} + +pcb_hid_t export_vfs_fuse_hid; + +int pplg_check_ver_export_vfs_fuse(int ver_needed) { return 0; } + +void pplg_uninit_export_vfs_fuse(void) +{ + pcb_hid_remove_attributes_by_cookie(export_vfs_fuse_cookie); + free(fuse_argv); + fuse_argv = NULL; + free(fuse_ret_argv); + fuse_ret_argv = NULL; +} + +int pplg_init_export_vfs_fuse(void) +{ + PCB_API_CHK_VER; + + memset(&export_vfs_fuse_hid, 0, sizeof(pcb_hid_t)); + + pcb_hid_nogui_init(&export_vfs_fuse_hid); + + export_vfs_fuse_hid.struct_size = sizeof(pcb_hid_t); + export_vfs_fuse_hid.name = "vfs_fuse"; + export_vfs_fuse_hid.description = "Handler of FUSE calls, serving board data"; + export_vfs_fuse_hid.exporter = 1; + export_vfs_fuse_hid.hide_from_gui = 1; + + export_vfs_fuse_hid.get_export_options = export_vfs_fuse_get_export_options; + export_vfs_fuse_hid.do_export = export_vfs_fuse_do_export; + export_vfs_fuse_hid.parse_arguments = export_vfs_fuse_parse_arguments; + + export_vfs_fuse_hid.usage = export_vfs_fuse_usage; + + pcb_hid_register_hid(&export_vfs_fuse_hid); + return 0; +} Index: tags/2.1.2/src_plugins/export_vfs_fuse/export_vfs_fuse.pup =================================================================== --- tags/2.1.2/src_plugins/export_vfs_fuse/export_vfs_fuse.pup (nonexistent) +++ tags/2.1.2/src_plugins/export_vfs_fuse/export_vfs_fuse.pup (revision 24813) @@ -0,0 +1,7 @@ +$class export +$short FUSE VFS server +$long Export all data and config of a board to a FUSE mountable filesystem +$state WIP +dep lib_vfs +default disable +autoload 1 Index: tags/2.1.2/src_plugins/export_vfs_fuse/fuse_includes.h.in =================================================================== --- tags/2.1.2/src_plugins/export_vfs_fuse/fuse_includes.h.in (nonexistent) +++ tags/2.1.2/src_plugins/export_vfs_fuse/fuse_includes.h.in (revision 24813) @@ -0,0 +1,12 @@ +if ?libs/sul/fuse/presents +then +put /local/tmp ?libs/sul/fuse/includes +gsub /local/tmp {\\\\n *} {\n} +print [@ +@/local/tmp@ +@] +else +print [@ +#error Fuse is not configured, can not compile export_vfs_fuse +@] +end Index: tags/2.1.2/src_plugins/export_vfs_mc/Makefile =================================================================== --- tags/2.1.2/src_plugins/export_vfs_mc/Makefile (nonexistent) +++ tags/2.1.2/src_plugins/export_vfs_mc/Makefile (revision 24813) @@ -0,0 +1,6 @@ +all: + cd ../../src && $(MAKE) mod_export_vfs_mc + + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/2.1.2/src_plugins/export_vfs_mc/Plug.tmpasm =================================================================== --- tags/2.1.2/src_plugins/export_vfs_mc/Plug.tmpasm (nonexistent) +++ tags/2.1.2/src_plugins/export_vfs_mc/Plug.tmpasm (revision 24813) @@ -0,0 +1,8 @@ +put /local/pcb/mod {export_vfs_mc} +put /local/pcb/mod/OBJS [@ $(PLUGDIR)/export_vfs_mc/export_vfs_mc.o @] + +switch /local/pcb/export_vfs_mc/controls + case {buildin} include /local/pcb/tmpasm/buildin; end; + case {plugin} include /local/pcb/tmpasm/plugin; end; + case {disable} include /local/pcb/tmpasm/disable; end; +end Index: tags/2.1.2/src_plugins/export_vfs_mc/README =================================================================== --- tags/2.1.2/src_plugins/export_vfs_mc/README (nonexistent) +++ tags/2.1.2/src_plugins/export_vfs_mc/README (revision 24813) @@ -0,0 +1 @@ +For instructions, see the top comments in upcb. Index: tags/2.1.2/src_plugins/export_vfs_mc/export_vfs_mc.c =================================================================== --- tags/2.1.2/src_plugins/export_vfs_mc/export_vfs_mc.c (nonexistent) +++ tags/2.1.2/src_plugins/export_vfs_mc/export_vfs_mc.c (revision 24813) @@ -0,0 +1,175 @@ +#include "config.h" +#include "conf_core.h" + +#include +#include +#include +#include +#include + +#include "build_run.h" +#include "board.h" +#include "data.h" +#include "error.h" +#include "pcb-printf.h" +#include "plugins.h" +#include "plug_io.h" + +#include "hid.h" +#include "hid_attrib.h" +#include "hid_init.h" +#include "hid_nogui.h" + +#include "../src_plugins/lib_vfs/lib_vfs.h" + +const char *export_vfs_mc_cookie = "export_vfs_mc HID"; + +static pcb_hid_attribute_t export_vfs_mc_options[] = { + {"cmd", "mc command", + PCB_HATT_STRING, 0, 0, {0, 0, 0}, 0, 0}, +#define HA_export_vfs_mc_cmd 0 + + {"qpath", "query path", + PCB_HATT_STRING, 0, 0, {0, 0, 0}, 0, 0}, +#define HA_export_vfs_mc_qpath 1 +}; + +#define NUM_OPTIONS (sizeof(export_vfs_mc_options)/sizeof(export_vfs_mc_options[0])) + +PCB_REGISTER_ATTRIBUTES(export_vfs_mc_options, export_vfs_mc_cookie) + +static pcb_hid_attr_val_t export_vfs_mc_values[NUM_OPTIONS]; + +static pcb_hid_attribute_t *export_vfs_mc_get_export_options(int *n) +{ + if (n) + *n = NUM_OPTIONS; + return export_vfs_mc_options; +} + +static void mc_list_cb(void *ctx, const char *path, int isdir) +{ + const char *attrs = isdir ? "drwxr-xr-x" : "-rw-r--r--"; + printf("%s 1 pcb-rnd pcb-rnd 0 01/01/01 01:01 %s\n", attrs, path); +} + +static void mc_list(void) +{ + pcb_vfs_list(PCB, mc_list_cb, NULL); +} + +static void mc_copyout(const char *path) +{ + gds_t res; + + gds_init(&res); + if (pcb_vfs_access(PCB, path, &res, 0, NULL) == 0) { + printf("%s", res.array); + } + else { + fprintf(stderr, "Can not access that field for read\n"); + exit(1); + } + gds_uninit(&res); +} + +static void mc_copyin(const char *path) +{ + gds_t inp; + char buf[256]; + int len; + + gds_init(&inp); + while((len = read(0, buf, 256)) > 0) { + gds_append_len(&inp, buf, len); + if (inp.used > 1024*1024) { + fprintf(stderr, "Data too large\n"); + exit(1); + } + } + + if ((inp.used > 0) && (inp.array[inp.used-1] == '\n')) { + inp.used--; /* remove exactly one trailing newline */ + inp.array[inp.used] = '\0'; + } + + if (pcb_vfs_access(PCB, path, &inp, 1, NULL) != 0) { + fprintf(stderr, "Can not access that field for write\n"); + exit(1); + } + gds_uninit(&inp); + if (pcb_save_pcb(PCB->Filename, NULL) != 0) { + fprintf(stderr, "Failed to save the modified board file\n"); + exit(1); + } +} + +static void export_vfs_mc_do_export(pcb_hid_attr_val_t * options) +{ + const char *cmd; + int i; + + if (!options) { + export_vfs_mc_get_export_options(0); + for (i = 0; i < NUM_OPTIONS; i++) + export_vfs_mc_values[i] = export_vfs_mc_options[i].default_val; + options = export_vfs_mc_values; + } + + cmd = options[HA_export_vfs_mc_cmd].str_value; + if (strcmp(cmd, "list") == 0) mc_list(); + else if (strcmp(cmd, "copyout") == 0) mc_copyout(options[HA_export_vfs_mc_qpath].str_value); + else if (strcmp(cmd, "copyin") == 0) mc_copyin(options[HA_export_vfs_mc_qpath].str_value); + else { + fprintf(stderr, "Unknown vfs_mc command: '%s'\n", cmd); + exit(1); + } +} + +static int export_vfs_mc_usage(const char *topic) +{ + fprintf(stderr, "\nexport_vfs_mc exporter command line arguments:\n\n"); + pcb_hid_usage(export_vfs_mc_options, sizeof(export_vfs_mc_options) / sizeof(export_vfs_mc_options[0])); + fprintf(stderr, "\nUsage: pcb-rnd [generic_options] -x export_vfs_mc [export_vfs_mc_options] foo.pcb\n\n"); + return 0; +} + + +static int export_vfs_mc_parse_arguments(int *argc, char ***argv) +{ + pcb_hid_register_attributes(export_vfs_mc_options, sizeof(export_vfs_mc_options) / sizeof(export_vfs_mc_options[0]), export_vfs_mc_cookie, 0); + return pcb_hid_parse_command_line(argc, argv); +} + +pcb_hid_t export_vfs_mc_hid; + +int pplg_check_ver_export_vfs_mc(int ver_needed) { return 0; } + +void pplg_uninit_export_vfs_mc(void) +{ + pcb_hid_remove_attributes_by_cookie(export_vfs_mc_cookie); +} + +int pplg_init_export_vfs_mc(void) +{ + PCB_API_CHK_VER; + + memset(&export_vfs_mc_hid, 0, sizeof(pcb_hid_t)); + + pcb_hid_nogui_init(&export_vfs_mc_hid); + + export_vfs_mc_hid.struct_size = sizeof(pcb_hid_t); + export_vfs_mc_hid.name = "vfs_mc"; + export_vfs_mc_hid.description = "Handler of mc VFS calls, serving board data"; + export_vfs_mc_hid.exporter = 1; + export_vfs_mc_hid.hide_from_gui = 1; + + export_vfs_mc_hid.get_export_options = export_vfs_mc_get_export_options; + export_vfs_mc_hid.do_export = export_vfs_mc_do_export; + export_vfs_mc_hid.parse_arguments = export_vfs_mc_parse_arguments; + + export_vfs_mc_hid.usage = export_vfs_mc_usage; + + pcb_hid_register_hid(&export_vfs_mc_hid); + return 0; +} Index: tags/2.1.2/src_plugins/export_vfs_mc/export_vfs_mc.pup =================================================================== --- tags/2.1.2/src_plugins/export_vfs_mc/export_vfs_mc.pup (nonexistent) +++ tags/2.1.2/src_plugins/export_vfs_mc/export_vfs_mc.pup (revision 24813) @@ -0,0 +1,7 @@ +$class export +$short GNU mc VFS server +$long Export all data and config of a board to GNU mc +$state WIP +dep lib_vfs +default disable +autoload 1 Index: tags/2.1.2/src_plugins/export_vfs_mc/upcb =================================================================== --- tags/2.1.2/src_plugins/export_vfs_mc/upcb (nonexistent) +++ tags/2.1.2/src_plugins/export_vfs_mc/upcb (revision 24813) @@ -0,0 +1,29 @@ +#!/bin/sh + +# GNU mc VFS glue for printed circuit boards using pcb-rnd +# This file is placed in the public domain by the author, +# Tibor 'Igor2' Palinkas, in 2019. +# +# Install this file in /usr/lib/mc/extfs.d +# +# Then add this in mc.ext (e.g. in /etc/mc/mc.ext): +# +# # PCB files +# shell/.pcb +# Open=%cd %p/upcb:// +# + +PCBRND="pcb-rnd -x vfs_mc" + +cmd=$1 +shift 1 +case "$cmd" in + list) $PCBRND --cmd list "$1" ;; + copyout) $PCBRND --cmd copyout "$1" --qpath "$2" > $3;; + copyin) $PCBRND --cmd copyin "$1" --qpath "$2" < $3;; +# rm) +# rmdir) +# mkdir) + *) exit 1 ;; +esac +exit 0 Property changes on: tags/2.1.2/src_plugins/export_vfs_mc/upcb ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/2.1.2/src_plugins/export_xy/Makefile =================================================================== --- tags/2.1.2/src_plugins/export_xy/Makefile (nonexistent) +++ tags/2.1.2/src_plugins/export_xy/Makefile (revision 24813) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_export_xy + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/2.1.2/src_plugins/export_xy/Plug.tmpasm =================================================================== --- tags/2.1.2/src_plugins/export_xy/Plug.tmpasm (nonexistent) +++ tags/2.1.2/src_plugins/export_xy/Plug.tmpasm (revision 24813) @@ -0,0 +1,11 @@ +put /local/pcb/mod {export_xy} +put /local/pcb/mod/OBJS [@ $(PLUGDIR)/export_xy/xy.o @] +put /local/pcb/mod/CONF {$(PLUGDIR)/export_xy/xy_conf.h} +put /local/pcb/mod/CONFFILE {export_xy.conf} +put /local/pcb/mod/CONFVAR {export_xy_conf_internal} + +switch /local/pcb/export_xy/controls + case {buildin} include /local/pcb/tmpasm/buildin; end; + case {plugin} include /local/pcb/tmpasm/plugin; end; + case {disable} include /local/pcb/tmpasm/disable; end; +end Index: tags/2.1.2/src_plugins/export_xy/export_xy.conf =================================================================== --- tags/2.1.2/src_plugins/export_xy/export_xy.conf (nonexistent) +++ tags/2.1.2/src_plugins/export_xy/export_xy.conf (revision 24813) @@ -0,0 +1,97 @@ +### conf file header (compacted) +li:pcb-rnd-conf-v1 { ha:overwrite { ha:plugins { ha:export_xy { li:templates { + +### tempalates + +# classis gEDA/PCB xy ######################################################### +xy.name = pcb xy +xy.hdr = {# $Id$ +# PcbXY Version 1.0 +# Date: %UTC% +# Author: %author% +# Title: %title% - PCB X-Y +# RefDes, Description, Value, X, Y, rotation, top/bottom +# X,Y in %suffix%. rotation in degrees. +# -------------------------------------------- +} +xy.subc = {%subc.refdes%,"%subc.footprint%","%subc.value%",%subc.x%,%subc.y%,%subc.rot%,%subc.side% +} + +# gxyrs ####################################################################### +gxyrs.name = gxyrs +gxyrs.hdr = {#gxyrs version 1.0 +#Date: %UTC% +#Author: %author% +#Title: %title% - pcb-rnd gxyrs +#Placement data: +#Designator X-Loc Y-Loc Rotation Side Type X-Size Y-Size Value Footprint +# -------------------------------------------- +} + +gxyrs.subc = {%subc.refdes_% %subc.x% %subc.y% %subc.rot% %subc.side% %subc.pad_width% %subc.pad_height% %subc.value_% %subc.footprint_% +} + + +# macrofab #################################################################### +macrofab.name = Macrofab +macrofab.hdr = {#pcb-rnd Macrofab export version 1.0 +#Date: %UTC% +#Author: %author% +#Title: %title% - pcb-rnd Macrofab export +#Placement data: +#Designator X-Loc Y-Loc Rotation Side Type X-Size Y-Size Value Footprint +# -------------------------------------------- +} +macrofab.subc = {%subc.refdes_% %subc.padcx% %subc.padcy% %subc.rot% %subc.num-side% %subc.smdvsthrunum% %subc.pad_width_prerot% %subc.pad_height_prerot% %subc.value_% %subc.footprint_% %subc.a.macrofab::DNP?0:1% %subc.a.macrofab::MPN|% +} + +# TM220/TM240 ################################################################# +tm220.name = TM220/TM240 +tm220.hdr = {#pcb-rnd TM220A/TM240A xyrs version 1.0 +#Date: %UTC% +#Author: %author% +#Title: %title% - pcb-rnd gxyrs +#Placement data: +#RefDes, top/bottom, X, Y, rotation +# X,Y in %suffix%. rotation in degrees. +# -------------------------------------------- +} + +tm220.subc = {%subc.refdes%,%subc.side%,%subc.x%,%subc.y%,%subc.rot% +} + +# KiCad .pos file ############################################################# +kicad_pos.name = {KiCad .pos} +kicad_pos.hdr = {###pcb-rnd KiCad .pos compatible xyrs version 1.0 +###Date: %UTC%, Author: %author%, Title: %title% - pcb-rnd gxyrs +## Unit = %suffix%., Angle = degrees. +#, Ref, Val, Package, PosX, PosY, Rot, Side +} +kicad_pos.subc = {,"%subc.refdes%","%subc.value%","%subc.footprint%",%subc.x%,%subc.y%,%subc.rot%,%subc.side% +} + +# ncap (work in progress) ##################################################### +ncap.name = {ncap export (WIP)} +ncap.hdr = {ncapture 0 +4 +%boardw% +%boardh% +80hmmm +-30hmmm; +} + +ncap.subc = {%subc.count% +0 +%subc.pincount% +1 +%subc.refdes% +%subc.90rot% +%subc.x% +%subc.y% +0 +} +ncap.term = {%term.netname% +} + +### conf file footer (compacted) +} } } } } Index: tags/2.1.2/src_plugins/export_xy/export_xy.pup =================================================================== --- tags/2.1.2/src_plugins/export_xy/export_xy.pup (nonexistent) +++ tags/2.1.2/src_plugins/export_xy/export_xy.pup (revision 24813) @@ -0,0 +1,14 @@ +$class export +$short xy (centroid) pcb_exporter +$long Template based export of XY centroid subcircuit data e.g. for pick & place. +$state works +$fmt-native no +$fmt-feature-w geda/PCB xy +$fmt-feature-w gxyrs +$fmt-feature-w Macrofab's pick&place +$fmt-feature-w pick&place file for the TM220/TM240 device +$fmt-feature-w KiCad .pos file +$package export +default buildin +dep export_bom +autoload 1 Index: tags/2.1.2/src_plugins/export_xy/xy.c =================================================================== --- tags/2.1.2/src_plugins/export_xy/xy.c (nonexistent) +++ tags/2.1.2/src_plugins/export_xy/xy.c (revision 24813) @@ -0,0 +1,871 @@ +#include "config.h" +#include "conf_core.h" + +#include +#include +#include +#include +#include +#include + +#include "math_helper.h" +#include "build_run.h" +#include "board.h" +#include "data.h" +#include "data_it.h" +#include "error.h" +#include "pcb-printf.h" +#include "plugins.h" +#include "compat_misc.h" +#include "obj_pstk_inlines.h" +#include "obj_subc_op.h" +#include "layer.h" +#include "netlist2.h" +#include "safe_fs.h" +#include "macro.h" +#include "operation.h" +#include "xy_conf.h" + +#include "hid.h" +#include "hid_nogui.h" +#include "hid_attrib.h" +#include "hid_cam.h" +#include "hid_init.h" + +#include "../src_plugins/lib_compat_help/elem_rot.h" +#include "../src_plugins/export_xy/conf_internal.c" + +#define CONF_FN "export_xy.conf" + +conf_xy_t conf_xy; + +extern char *CleanBOMString(const char *in); + +const char *xy_cookie = "XY HID"; + +/* Maximum length of a template name (in the config file, in the enum) */ +#define MAX_TEMP_NAME_LEN 128 + + +static pcb_hid_attribute_t xy_options[] = { +/* %start-doc options "8 XY Creation" +@ftable @code +@item --xyfile +Name of the XY output file. +@end ftable +%end-doc +*/ + {"xyfile", "Name of the XY output file", + PCB_HATT_STRING, 0, 0, {0, 0, 0}, 0, 0}, +#define HA_xyfile 0 + +/* %start-doc options "8 XY Creation" +@ftable @code +@item --xy-unit +Unit of XY dimensions. Defaults to mil. +@end ftable +%end-doc +*/ + {"xy-unit", "XY units", + PCB_HATT_UNIT, 0, 0, {-1, 0, 0}, NULL, 0}, +#define HA_unit 1 + {"xy-in-mm", ATTR_UNDOCUMENTED, + PCB_HATT_BOOL, 0, 0, {0, 0, 0}, 0, 0}, +#define HA_xymm 2 + {"format", "file format (template)", + PCB_HATT_ENUM, 0, 0, {0, 0, 0}, NULL, 0}, +#define HA_format 3 +}; + +#define NUM_OPTIONS (sizeof(xy_options)/sizeof(xy_options[0])) + +static pcb_hid_attr_val_t xy_values[NUM_OPTIONS]; + +static const char *xy_filename; +static const pcb_unit_t *xy_unit; +vts0_t fmt_names; /* array of const char * long name of each format, pointing into the conf database */ +vts0_t fmt_ids; /* array of strdup'd short name (ID) of each format */ + +static void free_fmts(void) +{ + int n; + for(n = 0; n < fmt_ids.used; n++) { + free(fmt_ids.array[n]); + fmt_ids.array[n] = NULL; + } +} + +static pcb_hid_attribute_t *xy_get_export_options(int *n) +{ + static int last_unit_value = -1; + conf_listitem_t *li; + int idx; + + /* load all formats from the config */ + fmt_names.used = 0; + fmt_ids.used = 0; + + free_fmts(); + conf_loop_list(&conf_xy.plugins.export_xy.templates, li, idx) { + char id[MAX_TEMP_NAME_LEN]; + const char *sep = strchr(li->name, '.'); + int len; + + if (sep == NULL) { + pcb_message(PCB_MSG_ERROR, "export_xy: ignoring invalid template name (missing period): '%s'\n", li->name); + continue; + } + if (strcmp(sep+1, "name") != 0) + continue; + len = sep - li->name; + if (len > sizeof(id)-1) { + pcb_message(PCB_MSG_ERROR, "export_xy: ignoring invalid template name (too long): '%s'\n", li->name); + continue; + } + memcpy(id, li->name, len); + id[len] = '\0'; + vts0_append(&fmt_names, (char *)li->payload); + vts0_append(&fmt_ids, pcb_strdup(id)); + } + + if (fmt_names.used == 0) { + pcb_message(PCB_MSG_ERROR, "export_xy: can not set up export options: no template available\n"); + return NULL; + } + + xy_options[HA_format].enumerations = (const char **)fmt_names.array; + + /* set default unit and filename */ + if (xy_options[HA_unit].default_val.int_value == last_unit_value) { + if (conf_core.editor.grid_unit) + xy_options[HA_unit].default_val.int_value = conf_core.editor.grid_unit->index; + else + xy_options[HA_unit].default_val.int_value = get_unit_struct("mil")->index; + last_unit_value = xy_options[HA_unit].default_val.int_value; + } + if ((PCB != NULL) && (xy_options[HA_xyfile].default_val.str_value == NULL)) + pcb_derive_default_filename(PCB->Filename, &xy_options[HA_xyfile], ".xy"); + + if (n) + *n = NUM_OPTIONS; + return xy_options; +} + +/* --------------------------------------------------------------------------- + * prints a centroid file in a format which includes data needed by a + * pick and place machine. Further formatting for a particular factory setup + * can easily be generated with awk or perl. + * returns != zero on error + */ + +typedef struct { + char utcTime[64]; + char *name, *descr, *value; + const char *pad_netname; + pcb_coord_t x, y; + double theta, xray_theta; + pcb_subc_t *subc; + pcb_coord_t pad_cx, pad_cy; + pcb_coord_t pad_w, pad_h; + pcb_coord_t prpad_w, prpad_h; + pcb_cardinal_t count; + pcb_coord_t ox, oy; + int origin_score; + char *origin_tmp; + pcb_bool front; +} subst_ctx_t; + +/* Find the pick and place 0;0 mark, if there is any */ +static void find_origin(subst_ctx_t *ctx, const char *format_name) +{ + char tmp[128]; + pcb_data_it_t it; + pcb_any_obj_t *obj; + + pcb_snprintf(tmp, sizeof(tmp), "pnp-origin-%s", format_name); + + ctx->origin_score = 0; + ctx->ox = ctx->oy = 0; + ctx->origin_tmp = tmp; + + for(obj = pcb_data_first(&it, PCB->Data, PCB_OBJ_CLASS_REAL); obj != NULL; obj = pcb_data_next(&it)) { + int score; + + if (pcb_attribute_get(&obj->Attributes, ctx->origin_tmp) != NULL) + score = 2; /* first look for the format-specific attribute */ + else if (pcb_attribute_get(&obj->Attributes, "pnp-origin") != NULL) + score = 1; /* then for the generic pnp-specific attribute */ + else + continue; + + if (score > ctx->origin_score) { + ctx->origin_score = score; + pcb_obj_center(obj, &ctx->ox, &ctx->oy); + } + } +} + +static void calc_pad_bbox_(subst_ctx_t *ctx, pcb_coord_t *pw, pcb_coord_t *ph, pcb_coord_t *pcx, pcb_coord_t *pcy) +{ + pcb_box_t box; + box.X1 = box.Y1 = PCB_MAX_COORD; + box.X2 = box.Y2 = -PCB_MAX_COORD; + + if (ctx->subc != NULL) { + pcb_any_obj_t *o; + pcb_data_it_t it; + + for(o = pcb_data_first(&it, ctx->subc->data, PCB_OBJ_CLASS_REAL); o != NULL; o = pcb_data_next(&it)) { + if (o->term != NULL) { + if ((o->type != PCB_OBJ_PSTK) && (o->type != PCB_OBJ_SUBC)) { /* layer objects */ + pcb_layer_t *ly = o->parent.layer; + assert(o->parent_type == PCB_PARENT_LAYER); + if (!(pcb_layer_flags_(ly) & PCB_LYT_COPPER)) + continue; + } +TODO(": we should have the copper bbox only, but this bbox includes the clearance!") + pcb_box_bump_box(&box, &o->BoundingBox); + } + } + } + + *pw = box.X2 - box.X1; + *ph = box.Y2 - box.Y1; + *pcx = (box.X2 + box.X1)/2; + *pcy = (box.Y2 + box.Y1)/2; +} + +static void count_pins_pads(subst_ctx_t *ctx, int *pins, int *pads) +{ + *pins = *pads = 0; + + if (ctx->subc != NULL) { + pcb_any_obj_t *o; + pcb_data_it_t it; + for(o = pcb_data_first(&it, ctx->subc->data, PCB_OBJ_CLASS_REAL); o != NULL; o = pcb_data_next(&it)) { + pcb_layer_type_t lyt; + + if (o->term == NULL) + continue; + + /* light terminals */ + if (o->type == PCB_OBJ_PSTK) { + pcb_pstk_t *ps = (pcb_pstk_t *)o; + pcb_pstk_proto_t *proto = pcb_pstk_get_proto(ps); + + if (proto->hdia > 0) { /* through-hole */ + (*pins)++; + continue; + } + + /* smd */ + if (pcb_pstk_shape(ps, PCB_LYT_TOP | PCB_LYT_COPPER, 0)) + (*pads)++; + if (pcb_pstk_shape(ps, PCB_LYT_BOTTOM | PCB_LYT_COPPER, 0)) + (*pads)++; + continue; + } + + /* heavy terminal */ + if (o->type == PCB_OBJ_SUBC) { +TODO("subc: subc-in-subc") + assert(!"no subc-in-subc support yet"); + continue; + } + assert(o->parent_type == PCB_PARENT_LAYER); + lyt = pcb_layer_flags_(o->parent.layer); + if ((lyt & PCB_LYT_COPPER) && (lyt & (PCB_LYT_TOP || PCB_LYT_TOP))) + (*pads)++; + } + } +} + +static void calc_pad_bbox(subst_ctx_t *ctx, int prerot, pcb_coord_t *pw, pcb_coord_t *ph, pcb_coord_t *pcx, pcb_coord_t *pcy) +{ + if (prerot) { + pcb_subc_t *save, *sc_rot0; + pcb_data_t *tmp = pcb_buffers[PCB_MAX_BUFFER-1].Data; + double ang; + pcb_opctx_t op; + + /* this is what we would do if we wanted to return the pre-rotation state */ + if ((ctx->theta == 0) || (ctx->theta == 180) || (ctx->theta == -180)) { + calc_pad_bbox_(ctx, pw, ph, pcx, pcy); + return; + } + if ((ctx->theta == 90) || (ctx->theta == 270) || (ctx->theta == -90) || (ctx->theta == -270)) { + calc_pad_bbox_(ctx, ph, pw, pcx, pcy); + return; + } + + sc_rot0 = pcb_subc_dup_at(NULL, tmp, ctx->subc, 0, 0, 0); + ang = ctx->theta / PCB_RAD_TO_DEG; + pcb_subc_rotate(sc_rot0, 0, 0, cos(ang), sin(ang), ctx->theta); + + save = ctx->subc; + ctx->subc = sc_rot0; + calc_pad_bbox_(ctx, pw, ph, pcx, pcy); + ctx->subc = save; + + op.remove.pcb = PCB; + op.remove.destroy_target = tmp; + pcb_subcop_destroy(&op, sc_rot0); + return; + } + + calc_pad_bbox_(ctx, pw, ph, pcx, pcy); +} + +static void append_clean(gds_t *dst, const char *text) +{ + const char *s; + for(s = text; *s != '\0'; s++) + if (isalnum(*s) || (*s == '.') || (*s == '-') || (*s == '+')) + gds_append(dst, *s); + else + gds_append(dst, '_'); +} + +static int is_val_true(const char *val) +{ + if (val == NULL) return 0; + if (strcmp(val, "yes") == 0) return 1; + if (strcmp(val, "on") == 0) return 1; + if (strcmp(val, "true") == 0) return 1; + if (strcmp(val, "1") == 0) return 1; + return 0; +} + +static int subst_cb(void *ctx_, gds_t *s, const char **input) +{ + int pin_cnt = 0; + int pad_cnt = 0; + subst_ctx_t *ctx = ctx_; + if (strncmp(*input, "UTC%", 4) == 0) { + *input += 4; + gds_append_str(s, ctx->utcTime); + return 0; + } + if (strncmp(*input, "author%", 7) == 0) { + *input += 7; + gds_append_str(s, pcb_author()); + return 0; + } + if (strncmp(*input, "title%", 6) == 0) { + *input += 6; + gds_append_str(s, PCB_UNKNOWN(PCB->Name)); + return 0; + } + if (strncmp(*input, "suffix%", 7) == 0) { + *input += 7; + gds_append_str(s, xy_unit->in_suffix); + return 0; + } + if (strncmp(*input, "boardw%", 7) == 0) { + *input += 7; + pcb_append_printf(s, "%m+%mN", xy_unit->allow, PCB->MaxWidth); + return 0; + } + if (strncmp(*input, "boardh%", 7) == 0) { + *input += 7; + pcb_append_printf(s, "%m+%mN", xy_unit->allow, PCB->MaxHeight); + return 0; + } + if (strncmp(*input, "subc.", 5) == 0) { + *input += 5; + + /* elem attribute print: + subc.a.attribute - print the attribute if exists, "n/a" if not + subc.a.attribute|unk - print the attribute if exists, unk if not + subc.a.attribute?yes - print yes if attribute is true, "n/a" if not + subc.a.attribute?yes:nope - print yes if attribute is true, nope if not + */ + if (strncmp(*input, "a.", 2) == 0) { + char aname[256], unk_buf[256], *nope; + const char *val, *end, *unk = "n/a"; + long len; + + *input += 2; + end = strpbrk(*input, "?|%"); + len = end - *input; + if (len >= sizeof(aname) - 1) { + pcb_message(PCB_MSG_ERROR, "xy tempalte error: attribute name '%s' too long\n", *input); + return 1; + } + memcpy(aname, *input, len); + aname[len] = '\0'; + if (*end == '|') { /* "or unknown" */ + *input = end+1; + end = strchr(*input, '%'); + len = end - *input; + if (len >= sizeof(unk_buf) - 1) { + pcb_message(PCB_MSG_ERROR, "xy tempalte error: elem atribute '|unknown' field '%s' too long\n", *input); + return 1; + } + memcpy(unk_buf, *input, len); + unk_buf[len] = '\0'; + unk = unk_buf; + *input = end; + } + else if (*end == '?') { /* trenary */ + *input = end+1; + end = strchr(*input, '%'); + len = end - *input; + if (len >= sizeof(unk_buf) - 1) { + pcb_message(PCB_MSG_ERROR, "xy tempalte error: elem atribute trenary field '%s' too long\n", *input); + return 1; + } + + memcpy(unk_buf, *input, len); + unk_buf[len] = '\0'; + *input = end+1; + + nope = strchr(unk_buf, ':'); + if (nope != NULL) { + *nope = '\0'; + nope++; + } + else /* only '?' is given, no ':' */ + nope = "n/a"; + + val = pcb_attribute_get(&ctx->subc->Attributes, aname); + if (is_val_true(val)) + gds_append_str(s, unk_buf); + else + gds_append_str(s, nope); + + return 0; + } + else + *input = end; + (*input)++; + + val = pcb_attribute_get(&ctx->subc->Attributes, aname); + if (val == NULL) + val = unk; + gds_append_str(s, val); + return 0; + } + if (strncmp(*input, "refdes%", 7) == 0) { + *input += 7; + gds_append_str(s, ctx->name); + return 0; + } + if (strncmp(*input, "refdes_%", 8) == 0) { + *input += 8; + append_clean(s, ctx->name); + return 0; + } + if (strncmp(*input, "footprint%", 10) == 0) { + *input += 10; + gds_append_str(s, ctx->descr); + return 0; + } + if (strncmp(*input, "footprint_%", 11) == 0) { + *input += 11; + append_clean(s, ctx->descr); + return 0; + } + if (strncmp(*input, "value%", 6) == 0) { + *input += 6; + gds_append_str(s, ctx->value); + return 0; + } + if (strncmp(*input, "value_%", 7) == 0) { + *input += 7; + append_clean(s, ctx->value); + return 0; + } + if (strncmp(*input, "x%", 2) == 0) { + *input += 2; + pcb_append_printf(s, "%m+%mN", xy_unit->allow, ctx->x); + return 0; + } + if (strncmp(*input, "y%", 2) == 0) { + *input += 2; + pcb_append_printf(s, "%m+%mN", xy_unit->allow, ctx->y); + return 0; + } + if (strncmp(*input, "padcx%", 6) == 0) { + *input += 6; + pcb_append_printf(s, "%m+%mN", xy_unit->allow, ctx->pad_cx); + return 0; + } + if (strncmp(*input, "padcy%", 6) == 0) { + *input += 6; + pcb_append_printf(s, "%m+%mN", xy_unit->allow, ctx->pad_cy); + return 0; + } + if (strncmp(*input, "rot%", 4) == 0) { + *input += 4; + pcb_append_printf(s, "%g", ctx->theta); + return 0; + } + if (strncmp(*input, "siderot%", 8) == 0) { + *input += 8; + pcb_append_printf(s, "%g", ctx->xray_theta); + return 0; + } + if (strncmp(*input, "270-rot%", 8) == 0) { + *input += 8; + pcb_append_printf(s, "%g", (270-ctx->theta)); + return 0; + } + if (strncmp(*input, "side270-rot%", 12) == 0) { + *input += 12; + pcb_append_printf(s, "%g", (270-ctx->theta)); + return 0; + } + if (strncmp(*input, "90rot%", 6) == 0) { + *input += 6; + if (ctx->theta == 0) { + pcb_append_printf(s, "0"); + } else if (ctx->theta == 90) { + pcb_append_printf(s, "1"); + } else if (ctx->theta == 180) { + pcb_append_printf(s, "2"); + } else { + pcb_append_printf(s, "3"); + } + return 0; + } + if (strncmp(*input, "ncapbbox%", 9) == 0) { + *input += 9; + /* need to calculate element bounding box */ + return 0; + } + if (strncmp(*input, "side%", 5) == 0) { + *input += 5; + gds_append_str(s, ctx->front ? "top" : "bottom"); + return 0; + } + if (strncmp(*input, "count%", 6) == 0) { + *input += 6; + pcb_append_printf(s, "%d", ctx->count); + return 0; + } + if (strncmp(*input, "num-side%", 9) == 0) { + *input += 9; + gds_append_str(s, ctx->front ? "1" : "2"); + return 0; + } + if (strncmp(*input, "pad_width%", 10) == 0) { + *input += 10; + pcb_append_printf(s, "%m+%mN", xy_unit->allow, ctx->pad_w); + return 0; + } + if (strncmp(*input, "pad_height%", 11) == 0) { + *input += 11; + pcb_append_printf(s, "%m+%mN", xy_unit->allow, ctx->pad_h); + return 0; + } + if (strncmp(*input, "pad_width_prerot%", 17) == 0) { + *input += 17; + pcb_append_printf(s, "%m+%mN", xy_unit->allow, ctx->prpad_w); + return 0; + } + if (strncmp(*input, "pad_height_prerot%", 18) == 0) { + *input += 18; + pcb_append_printf(s, "%m+%mN", xy_unit->allow, ctx->prpad_h); + return 0; + } + if (strncmp(*input, "smdvsthru%", 10) == 0) { + *input += 10; + count_pins_pads(ctx, &pin_cnt, &pad_cnt); + if (pin_cnt > 0) { + pcb_append_printf(s, "PTH"); + } else if (pad_cnt > 0) { + pcb_append_printf(s, "SMD"); + } else { + pcb_append_printf(s, "0"); + } + return 0; + } + if (strncmp(*input, "smdvsthrunum%", 13) == 0) { + *input += 13; + count_pins_pads(ctx, &pin_cnt, &pad_cnt); + if (pin_cnt > 0) { + pcb_append_printf(s, "2"); + } else if (pad_cnt > 0) { + pcb_append_printf(s, "1"); + } else { + pcb_append_printf(s, "0"); + } + return 0; + } + if (strncmp(*input, "pincount%", 9) == 0) { + *input += 9; + count_pins_pads(ctx, &pin_cnt, &pad_cnt); + if (pin_cnt > 0) { + pcb_append_printf(s, "%d", pin_cnt); + } else if (pad_cnt > 0) { + pcb_append_printf(s, "%d", pad_cnt); + } else { + pcb_append_printf(s, "0"); + } + return 0; + } + } + if (strncmp(*input, "term.", 5) == 0) { + *input += 5; + if (strncmp(*input, "netname%", 8) == 0) { + *input += 8; + if (*ctx->pad_netname != '\0') + pcb_append_printf(s, "%s", ctx->pad_netname); + else + pcb_append_printf(s, "NC"); + return 0; + } + } + return -1; +} + +static void fprintf_templ(FILE *f, subst_ctx_t *ctx, const char *templ) +{ + if (templ != NULL) { + char *tmp = pcb_strdup_subst(templ, subst_cb, ctx, PCB_SUBST_PERCENT); + fprintf(f, "%s", tmp); + free(tmp); + } +} + +static void xy_translate(subst_ctx_t *ctx, pcb_coord_t *x, pcb_coord_t *y) +{ + /* translate the xy coords using explicit or implicit origin; implicit origin + is lower left corner (looking from top) of board extents */ + if (ctx->origin_score > 0) { + *y = ctx->oy - *y; + *x = *x - ctx->ox; + } + else + *y = PCB->MaxHeight - *y; +} + +typedef struct { + const char *hdr, *subc, *term, *foot; +} template_t; + + +static int PrintXY(const template_t *templ, const char *format_name) +{ + FILE *fp; + subst_ctx_t ctx; + + fp = pcb_fopen(xy_filename, "w"); + if (!fp) { + pcb_message(PCB_MSG_ERROR, "Cannot open file %s for writing\n", xy_filename); + return 1; + } + + ctx.count = 0; + + pcb_print_utc(ctx.utcTime, sizeof(ctx.utcTime), 0); + + find_origin(&ctx, format_name); + + fprintf_templ(fp, &ctx, templ->hdr); + + /* For each subcircuit we calculate the centroid of the footprint. */ + PCB_SUBC_LOOP(PCB->Data); + { + pcb_any_obj_t *o; + pcb_data_it_t it; + int bott; + ctx.count++; + + ctx.pad_w = ctx.pad_h = 0; + ctx.theta = ctx.xray_theta = 0.0; + + ctx.name = CleanBOMString((char *) PCB_UNKNOWN(pcb_attribute_get(&subc->Attributes, "refdes"))); + ctx.descr = CleanBOMString((char *) PCB_UNKNOWN(pcb_subc_name(subc, "export_xy::footprint"))); + ctx.value = CleanBOMString((char *) PCB_UNKNOWN(pcb_attribute_get(&subc->Attributes, "value"))); + + /* prefer the pnp-origin but if that doesn't exist, pick the subc origin */ + if (!pcb_subc_find_aux_point(subc, "pnp-origin", &ctx.x, &ctx.y)) + if (pcb_subc_get_origin(subc, &ctx.x, &ctx.y) != 0) + pcb_message(PCB_MSG_ERROR, "xy: can't get subc origin for %s\n", ctx.name); + + if (pcb_subc_get_rotation(subc, &ctx.theta) != 0) pcb_message(PCB_MSG_ERROR, "xy: can't get subc rotation for %s\n", ctx.name); + if (pcb_subc_get_side(subc, &bott) != 0) pcb_message(PCB_MSG_ERROR, "xy: can't get subc side for %s\n", ctx.name); + + ctx.theta = -ctx.theta; + if (ctx.theta == -0) + ctx.theta = 0; + + xy_translate(&ctx, &ctx.x, &ctx.y); + + ctx.subc = subc; + ctx.front = !bott; + +TODO("padstack: do not depend on this, just use the normal bbox and rotate that back") + calc_pad_bbox(&ctx, 0, &ctx.pad_w, &ctx.pad_h, &ctx.pad_cx, &ctx.pad_cy); + calc_pad_bbox(&ctx, 1, &ctx.prpad_w, &ctx.prpad_h, &ctx.pad_cx, &ctx.pad_cy); + xy_translate(&ctx, &ctx.pad_cx, &ctx.pad_cy); + + fprintf_templ(fp, &ctx, templ->subc); + + for(o = pcb_data_first(&it, subc->data, PCB_OBJ_CLASS_REAL); o != NULL; o = pcb_data_next(&it)) { + if (o->term != NULL) { + ctx.pad_netname = NULL; + { + pcb_net_term_t *t = pcb_net_find_by_obj(&PCB->netlist[PCB_NETLIST_EDITED], o); + if (t != NULL) + ctx.pad_netname = t->parent.net->name; + } + if (ctx.pad_netname == NULL) + ctx.pad_netname = ""; + fprintf_templ(fp, &ctx, templ->term); + } + } + + ctx.pad_netname = NULL; + + free(ctx.name); + free(ctx.descr); + free(ctx.value); + } + PCB_END_LOOP; + + fprintf_templ(fp, &ctx, templ->foot); + + fclose(fp); + + return 0; +} + +static void gather_templates(void) +{ + conf_listitem_t *i; + int n; + + conf_loop_list(&conf_xy.plugins.export_xy.templates, i, n) { + char buff[256], *id, *sect; + int nl = strlen(i->name); + if (nl > sizeof(buff)-1) { + pcb_message(PCB_MSG_ERROR, "export_xy: ignoring template '%s': name too long\n", i->name); + continue; + } + memcpy(buff, i->name, nl+1); + id = buff; + sect = strchr(id, '.'); + if (sect == NULL) { + pcb_message(PCB_MSG_ERROR, "export_xy: ignoring template '%s': does not have a .section suffix\n", i->name); + continue; + } + *sect = '\0'; + sect++; + } +} + +static const char *get_templ(const char *tid, const char *type) +{ + char path[MAX_TEMP_NAME_LEN + 16]; + conf_listitem_t *li; + int idx; + + sprintf(path, "%s.%s", tid, type); /* safe: tid's length is checked before it was put in the vector, type is hardwired in code and is never longer than a few chars */ + conf_loop_list(&conf_xy.plugins.export_xy.templates, li, idx) + if (strcmp(li->name, path) == 0) + return li->payload; + return NULL; +} + +static void xy_do_export(pcb_hid_attr_val_t * options) +{ + int i; + template_t templ; + char **tid; + + memset(&templ, 0, sizeof(templ)); + + gather_templates(); + + if (!options) { + xy_get_export_options(0); + for (i = 0; i < NUM_OPTIONS; i++) + xy_values[i] = xy_options[i].default_val; + options = xy_values; + } + + xy_filename = options[HA_xyfile].str_value; + if (!xy_filename) + xy_filename = "pcb-out.xy"; + + if (options[HA_unit].int_value == -1) + xy_unit = options[HA_xymm].int_value ? get_unit_struct("mm") + : get_unit_struct("mil"); + else + xy_unit = &pcb_units[options[HA_unit].int_value]; + + tid = vts0_get(&fmt_ids, options[HA_format].int_value, 0); + if ((tid == NULL) || (*tid == NULL)) { + pcb_message(PCB_MSG_ERROR, "export_xy: invalid template selected\n"); + return; + } + templ.hdr = get_templ(*tid, "hdr"); + templ.subc = get_templ(*tid, "subc"); + templ.term = get_templ(*tid, "term"); + + PrintXY(&templ, options[HA_format].str_value); +} + +static int xy_usage(const char *topic) +{ + fprintf(stderr, "\nXY exporter command line arguments:\n\n"); + pcb_hid_usage(xy_options, sizeof(xy_options) / sizeof(xy_options[0])); + fprintf(stderr, "\nUsage: pcb-rnd [generic_options] -x xy [xy_options] foo.pcb\n\n"); + return 0; +} + +static int xy_parse_arguments(int *argc, char ***argv) +{ + pcb_hid_register_attributes(xy_options, sizeof(xy_options) / sizeof(xy_options[0]), xy_cookie, 0); + return pcb_hid_parse_command_line(argc, argv); +} + +pcb_hid_t xy_hid; + +int pplg_check_ver_export_xy(int ver_needed) { return 0; } + +void pplg_uninit_export_xy(void) +{ + pcb_hid_remove_attributes_by_cookie(xy_cookie); + conf_unreg_file(CONF_FN, export_xy_conf_internal); + conf_unreg_fields("plugins/export_xy/"); + free_fmts(); + vts0_uninit(&fmt_names); + vts0_uninit(&fmt_ids); +} + + +int pplg_init_export_xy(void) +{ + PCB_API_CHK_VER; + + conf_reg_file(CONF_FN, export_xy_conf_internal); + + memset(&xy_hid, 0, sizeof(pcb_hid_t)); + +#define conf_reg(field,isarray,type_name,cpath,cname,desc,flags) \ + conf_reg_field(conf_xy, field,isarray,type_name,cpath,cname,desc,flags); +#include "xy_conf_fields.h" + + pcb_hid_nogui_init(&xy_hid); + + xy_hid.struct_size = sizeof(pcb_hid_t); + xy_hid.name = "XY"; + xy_hid.description = "Exports a XY (centroid)"; + xy_hid.exporter = 1; + + xy_hid.get_export_options = xy_get_export_options; + xy_hid.do_export = xy_do_export; + xy_hid.parse_arguments = xy_parse_arguments; + + xy_hid.usage = xy_usage; + + pcb_hid_register_hid(&xy_hid); + + vts0_init(&fmt_names); + vts0_init(&fmt_ids); + return 0; +} Index: tags/2.1.2/src_plugins/export_xy/xy_conf.h =================================================================== --- tags/2.1.2/src_plugins/export_xy/xy_conf.h (nonexistent) +++ tags/2.1.2/src_plugins/export_xy/xy_conf.h (revision 24813) @@ -0,0 +1,14 @@ +#ifndef PCB_VENDOR_CONF_H +#define PCB_VENDOR_CONF_H + +#include "conf.h" + +typedef struct { + const struct plugins { + const struct export_xy { + CFT_LIST templates; + } export_xy; + } plugins; +} conf_xy_t; + +#endif Index: tags/2.1.2/src_plugins/extedit/Makefile =================================================================== --- tags/2.1.2/src_plugins/extedit/Makefile (nonexistent) +++ tags/2.1.2/src_plugins/extedit/Makefile (revision 24813) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_extedit + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/2.1.2/src_plugins/extedit/Plug.tmpasm =================================================================== --- tags/2.1.2/src_plugins/extedit/Plug.tmpasm (nonexistent) +++ tags/2.1.2/src_plugins/extedit/Plug.tmpasm (revision 24813) @@ -0,0 +1,10 @@ +put /local/pcb/mod {extedit} +put /local/pcb/mod/OBJS [@ + $(PLUGDIR)/extedit/extedit.o +@] + +switch /local/pcb/extedit/controls + case {buildin} include /local/pcb/tmpasm/buildin; end; + case {plugin} include /local/pcb/tmpasm/plugin; end; + case {disable} include /local/pcb/tmpasm/disable; end; +end Index: tags/2.1.2/src_plugins/extedit/extedit.c =================================================================== --- tags/2.1.2/src_plugins/extedit/extedit.c (nonexistent) +++ tags/2.1.2/src_plugins/extedit/extedit.c (revision 24813) @@ -0,0 +1,345 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2017 Tibor 'Igor2' Palinkas + * + * This module, dialogs, was written and is Copyright (C) 2017 by Tibor Palinkas + * this module is also subject to the GNU GPL as described below + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "config.h" + +#include "hid.h" +#include "hid_attrib.h" +#include "actions.h" +#include "hid_dad.h" +#include "plugins.h" + +#include "board.h" +#include "compat_fs.h" +#include "compat_misc.h" +#include "conf_core.h" +#include "data.h" +#include "buffer.h" +#include "paths.h" +#include "remove.h" +#include "safe_fs.h" +#include "search.h" +#include "undo.h" +#include "../src_plugins/io_lihata/io_lihata.h" +#include "../src_plugins/io_lihata/write.h" +#include "../src_plugins/io_lihata/read.h" + +/* List of all available external edit methods */ +typedef enum { + EEF_LIHATA, + EEF_max +} extedit_fmt_t; + +const char *extedit_fmt_names[EEF_max+1] = { + "lihata", + NULL +}; + +typedef struct extedit_method_s { + char *name; + long types; + extedit_fmt_t fmt; + char *command; +} extedit_method_t; + +static extedit_method_t methods[] = { + {"pcb-rnd", PCB_OBJ_SUBC, EEF_LIHATA, "pcb-rnd \"%f\""}, + {"editor", PCB_OBJ_SUBC, EEF_LIHATA, "xterm -e editor \"%f\""}, + {NULL, 0, 0, NULL} +}; + +/* accept these objects for external editing */ +#define EXTEDIT_TYPES (PCB_OBJ_SUBC) + +#include "extedit_dad.c" + +/* HID-dependent, portable watch of child process */ +typedef struct { + FILE *fc; + int stay; + pcb_hidval_t wid; +} extedit_wait_t; + +pcb_bool extedit_fd_watch(pcb_hidval_t watch, int fd, unsigned int condition, pcb_hidval_t user_data) +{ + char tmp[128]; + int res; + extedit_wait_t *ctx = user_data.ptr; + + /* excess callbacks */ + if (!ctx->stay) + return pcb_true; + + res = fread(tmp, 1, sizeof(tmp), ctx->fc); + if (res <= 0) { + ctx->stay = 0; + return pcb_false; /* also disables/removes the watch */ + } + return pcb_true; +} + +/* Invoke the child process, display a "progress bar" or some other indication + while it's running and wait for it to exit (preferrably keeping the gui + refreshed, even if the process is blocking) */ +static void invoke(extedit_method_t *mth, const char *fn) +{ + pcb_build_argfn_t subs; + char *cmd; + FILE *fc; + + memset(&subs, 0, sizeof(subs)); + subs.params['f' - 'a'] = fn; + cmd = pcb_build_argfn(mth->command, &subs); + + /* Don't use pcb_system() because that blocks the current process and the + GUI toolkit won't have a chance to handle expose events */ + fc = pcb_popen(cmd, "r"); + + if (pcb_gui != NULL) { + int fd = pcb_fileno(fc); + if (fd > 0) { + int n = 0; + pcb_hidval_t hd; + extedit_wait_t ctx; + + ctx.stay = 1; + ctx.fc = fc; + hd.ptr = &ctx; + ctx.wid = pcb_gui->watch_file(fd, PCB_WATCH_READABLE | PCB_WATCH_HANGUP, extedit_fd_watch, hd); + while(ctx.stay) { + if (pcb_gui != NULL) { + n++; + pcb_hid_progress(50+sin((double)n/10.0)*40, 100, "Invoked external editor. Please edit, save and close there to finish this operation"); + } + pcb_ms_sleep(50); + } + } + else + goto old_wait; + } + else { + old_wait:; + + if (pcb_gui != NULL) { + pcb_hid_progress(50, 100, "Invoked external editor. Please edit, save and close there to finish this operation"); + pcb_ms_sleep(1000); /* ugly hack: give the GUI some time to flush */ + } + while(!(feof(fc))) { + char tmp[128]; + fread(tmp, 1, sizeof(tmp), fc); + } + } + pclose(fc); + + if (pcb_gui != NULL) + pcb_hid_progress(0, 0, NULL); + free(cmd); +} + + + +static const char pcb_acts_extedit[] = "extedit(object|selected|buffer, [interactive|method])\n"; +static const char pcb_acth_extedit[] = "Invoke an external program to edit a specific part of the current board."; +static fgw_error_t pcb_act_extedit(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + const char *cmd = NULL, *method = NULL; + long type; + void *ptr1, *ptr2, *ptr3; + extedit_method_t *mth = NULL; + char *tmp_fn; + int ret = 1; + FILE *f; + int bn = PCB_MAX_BUFFER - 1, load_bn = PCB_MAX_BUFFER - 1; + int obn = conf_core.editor.buffer_number; + int paste = 0, del_selected = 0; + pcb_coord_t pastex = 0, pastey = 0; + + PCB_ACT_MAY_CONVARG(1, FGW_STR, extedit, cmd = argv[1].val.str); + PCB_ACT_MAY_CONVARG(2, FGW_STR, extedit, method = argv[2].val.str); + + /* pick up the object to edit */ + if ((cmd == NULL) || (pcb_strcasecmp(cmd, "object") == 0)) { + pcb_coord_t x, y; + pcb_hid_get_coords("Click on object to edit", &x, &y, 0); + type = pcb_search_screen(x, y, EXTEDIT_TYPES, &ptr1, &ptr2, &ptr3); + + pcb_buffer_set_number(bn); + pcb_buffer_clear(PCB, PCB_PASTEBUFFER); + if (pcb_copy_obj_to_buffer(PCB, pcb_buffers[bn].Data, PCB->Data, type, ptr1, ptr2, ptr3) == NULL) { + pcb_message(PCB_MSG_ERROR, "Failed to copy target objects to temporary paste buffer\n"); + goto quit0; + } + paste = 1; + } + else if ((argc > 1) && (pcb_strcasecmp(cmd, "selected") == 0)) { + pcb_buffer_set_number(bn); + pcb_buffer_clear(PCB, PCB_PASTEBUFFER); + pcb_buffer_add_selected(PCB, PCB_PASTEBUFFER, pcb_crosshair.X, pcb_crosshair.Y, pcb_false); + pastex = pcb_crosshair.X; + pastey = pcb_crosshair.Y; + del_selected = 1; + paste = 1; + if (pcb_data_is_empty(PCB_PASTEBUFFER->Data)) { + pcb_message(PCB_MSG_WARNING, "Nothing is selected, can't ext-edit selection\n"); + goto quit0; + } + } + else if ((argc > 1) && (pcb_strcasecmp(cmd, "buffer") == 0)) { + load_bn = bn = conf_core.editor.buffer_number; + if (pcb_data_is_empty(PCB_PASTEBUFFER->Data)) { + pcb_message(PCB_MSG_WARNING, "Nothing in current buffer, can't ext-edit selection\n"); + goto quit0; + } + } + else { + pcb_message(PCB_MSG_ERROR, "Wrong 1st argument '%s'\n", cmd); + ret = 1; + goto quit0; + } + + /* determine the method */ + if (argc > 2) { + for(mth = methods; mth->name != NULL; mth++) { + if (pcb_strcasecmp(mth->name, method) == 0) + break; + } + if (mth->name == NULL) { + pcb_message(PCB_MSG_ERROR, "unknown method '%s'; available methods:\n", method); + for(mth = methods; mth->name != NULL; mth++) { + if (mth != methods) + pcb_message(PCB_MSG_ERROR, ", ", mth->name); + pcb_message(PCB_MSG_ERROR, "%s", mth->name); + } + pcb_message(PCB_MSG_ERROR, "\n"); + ret = 1; + goto quit0; + } + } + if (mth == NULL) { + mth = extedit_interactive(); + if (mth == NULL) { /* no method selected */ + ret = 1; + goto quit0; + } + } + + tmp_fn = pcb_tempfile_name_new("extedit"); + if (tmp_fn == NULL) { + pcb_message(PCB_MSG_ERROR, "Failed to create temporary file\n"); + ret = 1; + goto quit0; + } + + /* export */ + switch(mth->fmt) { + case EEF_LIHATA: + { + f = pcb_fopen(tmp_fn, "w"); + if (f == NULL) { + pcb_message(PCB_MSG_ERROR, "Failed to open temporary file\n"); + goto quit1; + } + + if (io_lihata_write_element(plug_io_lihata_default, f, pcb_buffers[bn].Data) != 0) { + fclose(f); + pcb_message(PCB_MSG_ERROR, "Failed to export target objects to lihata footprint.\n"); + goto quit1; + } + fclose(f); + } + break; + case EEF_max: + break; + } + + /* invoke external program */ + invoke(mth, tmp_fn); + + /* load the result */ + switch(mth->fmt) { + case EEF_LIHATA: + { + int bn = load_bn; + + pcb_buffer_set_number(bn); + pcb_buffer_clear(PCB, PCB_PASTEBUFFER); + + if (io_lihata_parse_element(plug_io_lihata_default, pcb_buffers[bn].Data, tmp_fn) != 0) { + pcb_message(PCB_MSG_ERROR, "Failed to load the edited footprint. File left at '%s'.\n", tmp_fn); + ret = 1; + goto quit1; + } + + if (del_selected) + pcb_remove_selected(pcb_true); + if (paste) { + pcb_undo_save_serial(); + pcb_buffer_copy_to_layout(PCB, pastex, pastey); + pcb_undo_restore_serial(); + pcb_remove_object(type, ptr1, ptr2, ptr3); + pcb_undo_inc_serial(); + } + ret = 0; + } + case EEF_max: + break; + } + if (pcb_gui != NULL) + pcb_gui->invalidate_all(); + + quit1:; + pcb_tempfile_unlink(tmp_fn); + quit0:; + pcb_buffer_set_number(obn); + PCB_ACT_IRES(ret); + return 0; +} + +static pcb_action_t extedit_action_list[] = { + {"extedit", pcb_act_extedit, pcb_acts_extedit, pcb_acth_extedit} +}; + +static const char *extedit_cookie = "extedit plugin"; + +PCB_REGISTER_ACTIONS(extedit_action_list, extedit_cookie) + +int pplg_check_ver_extedit(int ver_needed) { return 0; } + +void pplg_uninit_extedit(void) +{ + pcb_remove_actions_by_cookie(extedit_cookie); +} + +#include "dolists.h" +int pplg_init_extedit(void) +{ + PCB_API_CHK_VER; + PCB_REGISTER_ACTIONS(extedit_action_list, extedit_cookie) + return 0; +} Index: tags/2.1.2/src_plugins/extedit/extedit.pup =================================================================== --- tags/2.1.2/src_plugins/extedit/extedit.pup (nonexistent) +++ tags/2.1.2/src_plugins/extedit/extedit.pup (revision 24813) @@ -0,0 +1,8 @@ +$class feature +$short edit with external program +$long invoke external program to edit parts of the current board +$state works +$package (core) +dep io_lihata +default buildin +autoload 1 Index: tags/2.1.2/src_plugins/extedit/extedit_dad.c =================================================================== --- tags/2.1.2/src_plugins/extedit/extedit_dad.c (nonexistent) +++ tags/2.1.2/src_plugins/extedit/extedit_dad.c (revision 24813) @@ -0,0 +1,132 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2017 Tibor 'Igor2' Palinkas + * + * This module, dialogs, was written and is Copyright (C) 2017 by Tibor Palinkas + * this module is also subject to the GNU GPL as described below + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "hid_dad.h" + +typedef struct { + PCB_DAD_DECL_NOINIT(dlg) + int mthi; + + int wmethod, wfmt, wcmd; +} ee_t; + +#define NUM_METHODS (sizeof(methods) / sizeof(methods[0])) + +static void ee_data2dialog(ee_t *ee) +{ + PCB_DAD_SET_VALUE(ee->dlg_hid_ctx, ee->wmethod, int_value, ee->mthi); + PCB_DAD_SET_VALUE(ee->dlg_hid_ctx, ee->wfmt, int_value, methods[ee->mthi].fmt); + PCB_DAD_SET_VALUE(ee->dlg_hid_ctx, ee->wcmd, str_value, pcb_strdup(methods[ee->mthi].command)); + + /* we have only one format, so disable the combo box for selecting it */ + pcb_gui->attr_dlg_widget_state(ee->dlg_hid_ctx, ee->wfmt, pcb_false); +} + +static void ee_chg_method(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + static int lock = 0; + ee_t *ee = caller_data; + + if (lock) + return; + + ee->mthi = ee->dlg[ee->wmethod].default_val.int_value; + + lock = 1; + ee_data2dialog(ee); + lock = 0; +} + +static void ee_chg_cmd(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + static int lock = 0; + ee_t *ee = caller_data; + + if (lock) + return; + + methods[ee->mthi].command = pcb_strdup(ee->dlg[ee->wcmd].default_val.str_value); + + lock = 1; + ee_data2dialog(ee); + lock = 0; +} + + +/* DAD-based interactive method editor */ +static extedit_method_t *extedit_interactive(void) +{ + ee_t ee; + char tmp[256]; + const char *names[NUM_METHODS+1]; + int n, res; + pcb_hid_dad_buttons_t clbtn[] = {{"Cancel", -1}, {"Edit!", 0}, {NULL, 0}}; + + for(n = 0; n < NUM_METHODS; n++) + names[n] = methods[n].name; + names[n] = NULL; + + memset(&ee, 0, sizeof(ee)); + + PCB_DAD_BEGIN_VBOX(ee.dlg); + sprintf(tmp, "Select external editor..."); + PCB_DAD_LABEL(ee.dlg, tmp); + + PCB_DAD_BEGIN_HBOX(ee.dlg); + PCB_DAD_LABEL(ee.dlg, "Method name:"); + PCB_DAD_ENUM(ee.dlg, names); + ee.wmethod = PCB_DAD_CURRENT(ee.dlg); + PCB_DAD_CHANGE_CB(ee.dlg, ee_chg_method); + PCB_DAD_END(ee.dlg); + + PCB_DAD_BEGIN_HBOX(ee.dlg); + PCB_DAD_LABEL(ee.dlg, "File format:"); + PCB_DAD_ENUM(ee.dlg, extedit_fmt_names); + ee.wfmt = PCB_DAD_CURRENT(ee.dlg); + PCB_DAD_END(ee.dlg); + + PCB_DAD_BEGIN_HBOX(ee.dlg); + PCB_DAD_LABEL(ee.dlg, "Command template:"); + PCB_DAD_STRING(ee.dlg); + ee.wcmd = PCB_DAD_CURRENT(ee.dlg); + PCB_DAD_CHANGE_CB(ee.dlg, ee_chg_cmd); + PCB_DAD_END(ee.dlg); + PCB_DAD_BUTTON_CLOSES(ee.dlg, clbtn); + PCB_DAD_END(ee.dlg); + + PCB_DAD_NEW("extedit", ee.dlg, "External editor", &ee, pcb_true, NULL); + + ee_data2dialog(&ee); + res = PCB_DAD_RUN(ee.dlg); + + PCB_DAD_FREE(ee.dlg); + if (res != 0) + return NULL; + return &methods[ee.mthi]; +} Index: tags/2.1.2/src_plugins/fontmode/Makefile =================================================================== --- tags/2.1.2/src_plugins/fontmode/Makefile (nonexistent) +++ tags/2.1.2/src_plugins/fontmode/Makefile (revision 24813) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_fontmode + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/2.1.2/src_plugins/fontmode/Plug.tmpasm =================================================================== --- tags/2.1.2/src_plugins/fontmode/Plug.tmpasm (nonexistent) +++ tags/2.1.2/src_plugins/fontmode/Plug.tmpasm (revision 24813) @@ -0,0 +1,8 @@ +put /local/pcb/mod {fontmode} +put /local/pcb/mod/OBJS [@ $(PLUGDIR)/fontmode/fontmode.o @] + +switch /local/pcb/fontmode/controls + case {buildin} include /local/pcb/tmpasm/buildin; end; + case {plugin} include /local/pcb/tmpasm/plugin; end; + case {disable} include /local/pcb/tmpasm/disable; end; +end Index: tags/2.1.2/src_plugins/fontmode/fontmode.c =================================================================== --- tags/2.1.2/src_plugins/fontmode/fontmode.c (nonexistent) +++ tags/2.1.2/src_plugins/fontmode/fontmode.c (revision 24813) @@ -0,0 +1,369 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 2006 DJ Delorie + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + * + * Old contact info: + * DJ Delorie, 334 North Road, Deerfield NH 03037-1110, USA + * dj@delorie.com + * + */ + +#include "config.h" +#include "conf_core.h" + +#include "board.h" + +#include +#include +#include +#include + +#include "data.h" +#include "draw.h" +#include "flag.h" +#include "layer.h" +#include "move.h" +#include "remove.h" +#include "rtree.h" +#include "flag_str.h" +#include "undo.h" +#include "pcb-printf.h" +#include "plugins.h" +#include "actions.h" +#include "compat_misc.h" +#include "event.h" +#include "polygon.h" +#include "obj_poly_draw.h" + +/* FIXME - we currently hardcode the grid and PCB size. What we + should do in the future is scan the font for its extents, and size + the grid appropriately. Also, when we convert back to a font, we + should search the grid for the gridlines and use them to figure out + where the symbols are. */ + +#define CELL_SIZE ((pcb_coord_t)(PCB_MIL_TO_COORD (100))) + +#define XYtoSym(x,y) (((x) / CELL_SIZE - 1) + (16 * ((y) / CELL_SIZE - 1))) + +static const char pcb_acts_fontedit[] = "FontEdit()"; +static const char pcb_acth_fontedit[] = "Convert the current font to a PCB for editing."; +static pcb_layer_t *make_layer(pcb_layergrp_id_t grp, const char *lname) +{ + pcb_layer_id_t lid; + + assert(grp >= 0); + lid = pcb_layer_create(PCB, grp, lname); + assert(lid >= 0); + PCB->Data->Layer[lid].meta.real.vis = 1; + PCB->Data->Layer[lid].meta.real.color = *pcb_layer_default_color(lid, 0); + return &PCB->Data->Layer[lid]; +} + +static void add_poly(pcb_layer_t *layer, pcb_poly_t *poly, pcb_coord_t ox, pcb_coord_t oy) +{ + pcb_poly_t *np; + + /* alloc */ + np = pcb_poly_new(layer, 0, pcb_no_flags()); + pcb_poly_copy(np, poly, ox, oy); + + /* add */ + pcb_add_poly_on_layer(layer, np); + pcb_poly_init_clip(PCB->Data, layer, np); + pcb_poly_invalidate_draw(layer, np); +} + +static fgw_error_t pcb_act_FontEdit(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + pcb_font_t *font; + pcb_symbol_t *symbol; + pcb_layer_t *lfont, *lorig, *lwidth, *lgrid, *lsilk; + pcb_layergrp_id_t grp[4]; + pcb_poly_t *poly; + pcb_arc_t *arc, *newarc; + int s, l; + + font = pcb_font_unlink(PCB, conf_core.design.text_font_id); + if (font == NULL) { + pcb_message(PCB_MSG_ERROR, "Can't fetch font id %d\n", conf_core.design.text_font_id); + return 1; + } + + if (pcb_actionl("New", "Font", 0)) + return 1; + + conf_set(CFR_DESIGN, "editor/grid_unit", -1, "mil", POL_OVERWRITE); + conf_set_design("design/min_wid", "%s", "1"); + conf_set_design("design/min_slk", "%s", "1"); + conf_set_design("design/text_font_id", "%s", "0"); + + + PCB->MaxWidth = CELL_SIZE * 18; + PCB->MaxHeight = CELL_SIZE * ((PCB_MAX_FONTPOSITION + 15) / 16 + 2); + PCB->Grid = PCB_MIL_TO_COORD(5); + + /* create the layer stack and logical layers */ + pcb_layergrp_inhibit_inc(); + pcb_layers_reset(PCB); + pcb_layer_group_setup_default(PCB); + pcb_get_grp_new_intern(PCB, 1); + pcb_get_grp_new_intern(PCB, 2); + + assert(pcb_layergrp_list(PCB, PCB_LYT_COPPER, grp, 4) == 4); + lfont = make_layer(grp[0], "Font"); + lorig = make_layer(grp[1], "OrigFont"); + lwidth = make_layer(grp[2], "Width"); + lgrid = make_layer(grp[3], "Grid"); + + assert(pcb_layergrp_list(PCB, PCB_LYT_SILK, grp, 2) == 2); + make_layer(grp[0], "Silk"); + lsilk = make_layer(grp[1], "Silk"); + + pcb_layergrp_inhibit_dec(); + + /* Inform the rest about the board change (layer stack, size) */ + pcb_event(PCB_EVENT_BOARD_CHANGED, NULL); + pcb_event(PCB_EVENT_LAYERS_CHANGED, NULL); + + for (s = 0; s <= PCB_MAX_FONTPOSITION; s++) { + char txt[32]; + pcb_coord_t ox = (s % 16 + 1) * CELL_SIZE; + pcb_coord_t oy = (s / 16 + 1) * CELL_SIZE; + pcb_coord_t w, miny, maxy, maxx = 0; + + symbol = &font->Symbol[s]; + + miny = PCB_MIL_TO_COORD(5); + maxy = font->MaxHeight; + + if ((s > 32) && (s < 127)) { + sprintf(txt, "%c", s); + pcb_text_new(lsilk, pcb_font(PCB, 0, 0), ox+CELL_SIZE-CELL_SIZE/3, oy+CELL_SIZE-CELL_SIZE/3, 0, 50, 0, txt, pcb_no_flags()); + } + sprintf(txt, "%d", s); + pcb_text_new(lsilk, pcb_font(PCB, 0, 0), ox+CELL_SIZE/20, oy+CELL_SIZE-CELL_SIZE/3, 0, 50, 0, txt, pcb_no_flags()); + + for (l = 0; l < symbol->LineN; l++) { + pcb_line_new_merge(lfont, + symbol->Line[l].Point1.X + ox, + symbol->Line[l].Point1.Y + oy, + symbol->Line[l].Point2.X + ox, + symbol->Line[l].Point2.Y + oy, symbol->Line[l].Thickness, symbol->Line[l].Thickness, pcb_no_flags()); + pcb_line_new_merge(lorig, symbol->Line[l].Point1.X + ox, + symbol->Line[l].Point1.Y + oy, + symbol->Line[l].Point2.X + ox, + symbol->Line[l].Point2.Y + oy, symbol->Line[l].Thickness, symbol->Line[l].Thickness, pcb_no_flags()); + if (maxx < symbol->Line[l].Point1.X) + maxx = symbol->Line[l].Point1.X; + if (maxx < symbol->Line[l].Point2.X) + maxx = symbol->Line[l].Point2.X; + } + + + for(arc = arclist_first(&symbol->arcs); arc != NULL; arc = arclist_next(arc)) { + pcb_arc_new(lfont, arc->X + ox, arc->Y + oy, arc->Width, arc->Height, arc->StartAngle, arc->Delta, arc->Thickness, 0, pcb_no_flags(), pcb_true); + newarc = pcb_arc_new(lorig, arc->X + ox, arc->Y + oy, arc->Width, arc->Height, arc->StartAngle, arc->Delta, arc->Thickness, 0, pcb_no_flags(), pcb_true); + if (newarc != NULL) { + if (maxx < newarc->BoundingBox.X2 - ox) + maxx = newarc->BoundingBox.X2 - ox; + if (maxy < newarc->BoundingBox.Y2 - oy) + maxy = newarc->BoundingBox.Y2 - oy; + } + } + + for(poly = polylist_first(&symbol->polys); poly != NULL; poly = polylist_next(poly)) { + int n; + pcb_point_t *pnt; + + add_poly(lfont, poly, ox, oy); + add_poly(lorig, poly, ox, oy); + + for(n = 0, pnt = poly->Points; n < poly->PointN; n++,pnt++) { + if (maxx < pnt->X) + maxx = pnt->X; + if (maxy < pnt->Y) + maxy = pnt->Y; + } + } + + w = maxx + symbol->Delta + ox; + pcb_line_new_merge(lwidth, w, miny + oy, w, maxy + oy, PCB_MIL_TO_COORD(1), PCB_MIL_TO_COORD(1), pcb_no_flags()); + } + + for (l = 0; l < 16; l++) { + int x = (l + 1) * CELL_SIZE; + pcb_line_new_merge(lgrid, x, 0, x, PCB->MaxHeight, PCB_MIL_TO_COORD(1), PCB_MIL_TO_COORD(1), pcb_no_flags()); + } + for (l = 0; l <= PCB_MAX_FONTPOSITION / 16 + 1; l++) { + int y = (l + 1) * CELL_SIZE; + pcb_line_new_merge(lgrid, 0, y, PCB->MaxWidth, y, PCB_MIL_TO_COORD(1), PCB_MIL_TO_COORD(1), pcb_no_flags()); + } + PCB_ACT_IRES(0); + return 0; +} + +static const char pcb_acts_fontsave[] = "FontSave()"; +static const char pcb_acth_fontsave[] = "Convert the current PCB back to a font."; +static fgw_error_t pcb_act_FontSave(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + pcb_font_t *font; + pcb_symbol_t *symbol; + int i; + pcb_line_t *l; + pcb_arc_t *a; + pcb_poly_t *p, *np; + gdl_iterator_t it; + pcb_layer_t *lfont, *lwidth; + + font = pcb_font(PCB, 0, 1); + lfont = PCB->Data->Layer + 0; + lwidth = PCB->Data->Layer + 2; + + for (i = 0; i <= PCB_MAX_FONTPOSITION; i++) { + font->Symbol[i].LineN = 0; + font->Symbol[i].Valid = 0; + font->Symbol[i].Width = 0; + } + + /* pack lines */ + linelist_foreach(&lfont->Line, &it, l) { + int x1 = l->Point1.X; + int y1 = l->Point1.Y; + int x2 = l->Point2.X; + int y2 = l->Point2.Y; + int ox, oy, s; + + s = XYtoSym(x1, y1); + ox = (s % 16 + 1) * CELL_SIZE; + oy = (s / 16 + 1) * CELL_SIZE; + symbol = &font->Symbol[s]; + + x1 -= ox; + y1 -= oy; + x2 -= ox; + y2 -= oy; + + if (symbol->Width < x1) + symbol->Width = x1; + if (symbol->Width < x2) + symbol->Width = x2; + symbol->Valid = 1; + + pcb_font_new_line_in_sym(symbol, x1, y1, x2, y2, l->Thickness); + } + + /* pack arcs */ + arclist_foreach(&lfont->Arc, &it, a) { + int cx = a->X; + int cy = a->Y; + int ox, oy, s; + + s = XYtoSym(cx, cy); + ox = (s % 16 + 1) * CELL_SIZE; + oy = (s / 16 + 1) * CELL_SIZE; + symbol = &font->Symbol[s]; + + cx -= ox; + cy -= oy; + + pcb_arc_bbox(a); + if (symbol->Width < a->BoundingBox.X2 - ox) + symbol->Width = a->BoundingBox.X2 - ox; + + if (symbol->Width < cx) + symbol->Width = cx; + symbol->Valid = 1; + + pcb_font_new_arc_in_sym(symbol, cx, cy, a->Width, a->StartAngle, a->Delta, a->Thickness); + } + + /* pack polygons */ + polylist_foreach(&lfont->Polygon, &it, p) { + pcb_coord_t x1 = p->Points[0].X; + pcb_coord_t y1 = p->Points[0].Y; + pcb_coord_t s, ox, oy; + int n; + + s = XYtoSym(x1, y1); + ox = (s % 16 + 1) * CELL_SIZE; + oy = (s / 16 + 1) * CELL_SIZE; + symbol = &font->Symbol[s]; + + np = pcb_font_new_poly_in_sym(symbol, p->PointN); + + for(n = 0; n < p->PointN; n++) { + np->Points[n].X = p->Points[n].X - ox; + np->Points[n].Y = p->Points[n].Y - oy; + if (symbol->Width < np->Points[n].X) + symbol->Width = np->Points[n].X; + } + } + + /* recalc delta */ + linelist_foreach(&lwidth->Line, &it, l) { + pcb_coord_t x1 = l->Point1.X; + pcb_coord_t y1 = l->Point1.Y; + pcb_coord_t ox, s; + + s = XYtoSym(x1, y1); + ox = (s % 16 + 1) * CELL_SIZE; + symbol = &font->Symbol[s]; + + x1 -= ox; + + symbol->Delta = x1 - symbol->Width; + } + + pcb_font_set_info(font); + pcb_actionl("SaveFontTo", NULL); + + PCB_ACT_IRES(0); + return 0; +} + +pcb_action_t fontmode_action_list[] = { + {"FontEdit", pcb_act_FontEdit, pcb_acth_fontedit, pcb_acts_fontedit}, + {"FontSave", pcb_act_FontSave, pcb_acth_fontsave, pcb_acts_fontsave} +}; + +static const char *fontmode_cookie = "fontmode plugin"; + +PCB_REGISTER_ACTIONS(fontmode_action_list, fontmode_cookie) + +int pplg_check_ver_fontmode(int ver_needed) { return 0; } + +void pplg_uninit_fontmode(void) +{ + pcb_remove_actions_by_cookie(fontmode_cookie); +} + +#include "dolists.h" +int pplg_init_fontmode(void) +{ + PCB_API_CHK_VER; + PCB_REGISTER_ACTIONS(fontmode_action_list, fontmode_cookie) + return 0; +} Index: tags/2.1.2/src_plugins/fontmode/fontmode.pup =================================================================== --- tags/2.1.2/src_plugins/fontmode/fontmode.pup (nonexistent) +++ tags/2.1.2/src_plugins/fontmode/fontmode.pup (revision 24813) @@ -0,0 +1,7 @@ +$class feature +$short font editor +$long Font editing actions. +$state works +$package extra +default buildin +autoload 1 Index: tags/2.1.2/src_plugins/fp_board/Makefile =================================================================== --- tags/2.1.2/src_plugins/fp_board/Makefile (nonexistent) +++ tags/2.1.2/src_plugins/fp_board/Makefile (revision 24813) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_fp_board + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/2.1.2/src_plugins/fp_board/Plug.tmpasm =================================================================== --- tags/2.1.2/src_plugins/fp_board/Plug.tmpasm (nonexistent) +++ tags/2.1.2/src_plugins/fp_board/Plug.tmpasm (revision 24813) @@ -0,0 +1,8 @@ +put /local/pcb/mod {fp_board} +put /local/pcb/mod/OBJS [@ $(PLUGDIR)/fp_board/fp_board.o @] + +switch /local/pcb/fp_board/controls + case {buildin} include /local/pcb/tmpasm/buildin; end; + case {plugin} include /local/pcb/tmpasm/plugin; end; + case {disable} include /local/pcb/tmpasm/disable; end; +end Index: tags/2.1.2/src_plugins/fp_board/fp_board.c =================================================================== --- tags/2.1.2/src_plugins/fp_board/fp_board.c (nonexistent) +++ tags/2.1.2/src_plugins/fp_board/fp_board.c (revision 24813) @@ -0,0 +1,163 @@ + +#include "config.h" + +#include "plugins.h" +#include "plug_footprint.h" +#include "board.h" +#include "buffer.h" +#include "data.h" +#include "error.h" +#include "obj_subc.h" +#include "obj_subc_list.h" +#include "obj_subc_op.h" +#include "compat_misc.h" +#include "pcb-printf.h" +#include "operation.h" +#include "plug_io.h" +#include "safe_fs.h" + +#define REQUIRE_PATH_PREFIX "board@" + +static int fp_board_load_dir(pcb_plug_fp_t *ctx, const char *path, int force) +{ + const char *fpath; + pcb_fplibrary_t *l; + pcb_buffer_t buff; + unsigned long int id; + int old_dedup; + pcb_subclist_dedup_initializer(dedup); + + if (strncmp(path, REQUIRE_PATH_PREFIX, strlen(REQUIRE_PATH_PREFIX)) != 0) + return -1; + + fpath = path + strlen(REQUIRE_PATH_PREFIX); + + /* load file */ + memset(&buff, 0, sizeof(buff)); + if (pcb_buffer_load_layout(PCB, &buff, fpath, NULL) != pcb_true) { + pcb_message(PCB_MSG_ERROR, "Warning: failed to load %s\n", fpath); + return -1; + } + + /* make sure lib dir is ready */ + l = pcb_fp_lib_search(&pcb_library, path); + if (l == NULL) + l = pcb_fp_mkdir_len(&pcb_library, path, -1); + + /* add unique elements */ + old_dedup = pcb_subc_hash_ignore_uid; + pcb_subc_hash_ignore_uid = 1; + id = 0; + PCB_SUBC_LOOP(buff.Data) { + const char *ename; + pcb_fplibrary_t *e; + + id++; + pcb_subclist_dedup_skip(dedup, subc); + + ename = pcb_attribute_get(&subc->Attributes, "footprint"); + if (ename == NULL) + ename = subc->refdes; + if (ename == NULL) + ename = "anonymous"; + e = pcb_fp_append_entry(l, ename, PCB_FP_FILE, NULL); + + /* remember location by ID - because of the dedup search by name is unsafe */ + if (e != NULL) + e->data.fp.loc_info = pcb_strdup_printf("%s@%lu", path, id); + + } PCB_END_LOOP; + + pcb_subc_hash_ignore_uid = old_dedup; + pcb_subclist_dedup_free(dedup); + + /* clean up buffer */ + pcb_buffer_clear(PCB, &buff); + free(buff.Data); + + return 0; +} + +static FILE *fp_board_fopen(pcb_plug_fp_t *ctx, const char *path, const char *name, pcb_fp_fopen_ctx_t *fctx, pcb_data_t *dst) +{ + char *fpath, *ids, *end; + unsigned long int id, req_id; + pcb_buffer_t buff; + pcb_opctx_t op; + + if (dst == NULL) + return NULL; + + if (strncmp(name, REQUIRE_PATH_PREFIX, strlen(REQUIRE_PATH_PREFIX)) != 0) + return NULL; + + /* split file name and ID */ + fpath = pcb_strdup(name + strlen(REQUIRE_PATH_PREFIX)); + ids = strchr(fpath, '@'); + if (ids == NULL) + goto err; + + *ids = '\0'; + ids++; + + req_id = strtoul(ids, &end, 10); + if (*end != '\0') + goto err; + + /* load file */ + memset(&buff, 0, sizeof(buff)); + if (pcb_buffer_load_layout(PCB, &buff, fpath, NULL) != pcb_true) { + pcb_message(PCB_MSG_ERROR, "Warning: failed to load %s\n", fpath); + goto err; + } + + /* find the reuqested footprint in the file */ + id = 0; + PCB_SUBC_LOOP(buff.Data) { + id++; + if (id == req_id) { + memset(&op, 0, sizeof(op)); + op.buffer.dst = dst; + pcb_data_set_layer_parents(op.buffer.dst); + pcb_subcop_add_to_buffer(&op, subc); + + return PCB_FP_FOPEN_IN_DST; + } + } PCB_END_LOOP; + + /* clean up buffer */ + + pcb_buffer_clear(PCB, &buff); + free(buff.Data); + return NULL; + +err:; + free(fpath); + return NULL; +} + +static void fp_board_fclose(pcb_plug_fp_t *ctx, FILE * f, pcb_fp_fopen_ctx_t *fctx) +{ + pcb_message(PCB_MSG_ERROR, "Internal error: fp_board_fclose() shouldn't have been called. Please report this bug.\n"); +} + + +static pcb_plug_fp_t fp_board; + +int pplg_check_ver_fp_board(int ver_needed) { return 0; } + +void pplg_uninit_fp_board(void) +{ + PCB_HOOK_UNREGISTER(pcb_plug_fp_t, pcb_plug_fp_chain, &fp_board); +} + +int pplg_init_fp_board(void) +{ + PCB_API_CHK_VER; + fp_board.plugin_data = NULL; + fp_board.load_dir = fp_board_load_dir; + fp_board.fp_fopen = fp_board_fopen; + fp_board.fp_fclose = fp_board_fclose; + PCB_HOOK_REGISTER(pcb_plug_fp_t, pcb_plug_fp_chain, &fp_board); + return 0; +} Index: tags/2.1.2/src_plugins/fp_board/fp_board.pup =================================================================== --- tags/2.1.2/src_plugins/fp_board/fp_board.pup (nonexistent) +++ tags/2.1.2/src_plugins/fp_board/fp_board.pup (revision 24813) @@ -0,0 +1,7 @@ +$class fp +$short footprint library from boards +$long Footprint: load a board and expose all the unique subcircuits on that board as a footprint library +$state WIP +$package (core) +default buildin +autoload 1 Index: tags/2.1.2/src_plugins/fp_fs/Makefile =================================================================== --- tags/2.1.2/src_plugins/fp_fs/Makefile (nonexistent) +++ tags/2.1.2/src_plugins/fp_fs/Makefile (revision 24813) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_fp_fs + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/2.1.2/src_plugins/fp_fs/Plug.tmpasm =================================================================== --- tags/2.1.2/src_plugins/fp_fs/Plug.tmpasm (nonexistent) +++ tags/2.1.2/src_plugins/fp_fs/Plug.tmpasm (revision 24813) @@ -0,0 +1,8 @@ +put /local/pcb/mod {fp_fs} +put /local/pcb/mod/OBJS [@ $(PLUGDIR)/fp_fs/fp_fs.o @] + +switch /local/pcb/fp_fs/controls + case {buildin} include /local/pcb/tmpasm/buildin; end; + case {plugin} include /local/pcb/tmpasm/plugin; end; + case {disable} include /local/pcb/tmpasm/disable; end; +end Index: tags/2.1.2/src_plugins/fp_fs/fp_fs.c =================================================================== --- tags/2.1.2/src_plugins/fp_fs/fp_fs.c (nonexistent) +++ tags/2.1.2/src_plugins/fp_fs/fp_fs.c (revision 24813) @@ -0,0 +1,569 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ +#include "config.h" + +#ifdef HAVE_UNISTD_H +#include +#endif + +#include +#include +#include +#include + +#include "data.h" +#include "paths.h" +#include "plugins.h" +#include "plug_footprint.h" +#include "compat_fs.h" +#include "compat_misc.h" +#include "error.h" +#include "conf.h" +#include "conf_core.h" +#include "macro.h" +#include "safe_fs.h" + +/* opendir, readdir */ +#include "compat_inc.h" + +static pcb_fptype_t pcb_fp_file_type(const char *fn, void ***tags); + +/* --------------------------------------------------------------------------- + * Parse the directory tree where newlib footprints are found + */ +typedef struct list_dir_s list_dir_t; + +struct list_dir_s { + char *parent; + char *subdir; + list_dir_t *next; +}; + +typedef struct { + pcb_fplibrary_t *menu; + list_dir_t *subdirs; + int children; +} list_st_t; + +static int list_cb(void *cookie, const char *subdir, const char *name, pcb_fptype_t type, void *tags[]) +{ + list_st_t *l = (list_st_t *) cookie; + pcb_fplibrary_t *e; + + if (type == PCB_FP_DIR) { + list_dir_t *d; + /* can not recurse directly from here because that would ruin the menu + pointer: pcb_lib_menu_new(&Library) calls realloc()! + Build a list of directories to be visited later, instead. */ + d = malloc(sizeof(list_dir_t)); + d->subdir = pcb_strdup(name); + d->parent = pcb_strdup(subdir); + d->next = l->subdirs; + l->subdirs = d; + return 0; + } + + l->children++; + e = pcb_fp_append_entry(l->menu, name, type, tags); + +/* Avoid using pcb_concat() - would be a new dependency for gsch2pcb-rnd */ + { + int sl = strlen(subdir); + int nl = strlen(name); + char *end; + + end = e->data.fp.loc_info = malloc(sl+nl+3); + memcpy(end, subdir, sl); end += sl; + *end = '/'; end++; + memcpy(end, name, nl+1); end += nl; + } + + return 0; +} + +static int fp_fs_list(pcb_fplibrary_t *pl, const char *subdir, int recurse, + int (*cb) (void *cookie, const char *subdir, const char *name, pcb_fptype_t type, void *tags[]), void *cookie, + int subdir_may_not_exist, int need_tags) +{ + char olddir[PCB_PATH_MAX + 1]; /* The directory we start out in (cwd) */ + char new_subdir[PCB_PATH_MAX + 1]; + char fn[PCB_PATH_MAX + 1], *fn_end; + DIR *subdirobj; /* Interable object holding all subdir entries */ + struct dirent *subdirentry; /* Individual subdir entry */ + struct stat buffer; /* Buffer used in stat */ + size_t l; + int n_footprints = 0; /* Running count of footprints found in this subdir */ + + /* Cache old dir, then cd into subdir because stat is given relative file names. */ + memset(olddir, 0, sizeof olddir); + if (pcb_get_wd(olddir) == NULL) { + pcb_message(PCB_MSG_ERROR, "fp_fs_list(): Could not determine initial working directory\n"); + return 0; + } + + if (strcmp(subdir, ".svn") == 0) + return 0; + + if (chdir(subdir)) { + if (!subdir_may_not_exist) + pcb_chdir_error_message(subdir); + return 0; + } + + + /* Determine subdir's abs path */ + if (pcb_get_wd(new_subdir) == NULL) { + pcb_message(PCB_MSG_ERROR, "fp_fs_list(): Could not determine new working directory\n"); + if (chdir(olddir)) + pcb_chdir_error_message(olddir); + return 0; + } + + l = strlen(new_subdir); + memcpy(fn, new_subdir, l); + fn[l] = PCB_DIR_SEPARATOR_C; + fn_end = fn + l + 1; + + /* First try opening the directory specified by path */ + if ((subdirobj = opendir(new_subdir)) == NULL) { + pcb_opendir_error_message(new_subdir); + if (chdir(olddir)) + pcb_chdir_error_message(olddir); + return 0; + } + + /* Now loop over files in this directory looking for files. + * We ignore certain files which are not footprints. + */ + while ((subdirentry = readdir(subdirobj)) != NULL) { +#ifdef DEBUG +/* printf("... Examining file %s ... \n", subdirentry->d_name); */ +#endif + + /* Ignore non-footprint files found in this directory + * We're skipping .png and .html because those + * may exist in a library tree to provide an html browsable + * index of the library. + */ +TODO("fp: make this a configurable list") + l = strlen(subdirentry->d_name); + if (!stat(subdirentry->d_name, &buffer) + && subdirentry->d_name[0] != '.' + && PCB_NSTRCMP(subdirentry->d_name, "CVS") != 0 + && PCB_NSTRCMP(subdirentry->d_name, "Makefile") != 0 + && PCB_NSTRCMP(subdirentry->d_name, "Makefile.am") != 0 + && PCB_NSTRCMP(subdirentry->d_name, "Makefile.in") != 0 && (l < 4 || PCB_NSTRCMP(subdirentry->d_name + (l - 4), ".png") != 0) + && (l < 5 || PCB_NSTRCMP(subdirentry->d_name + (l - 5), ".html") != 0) + && (l < 4 || PCB_NSTRCMP(subdirentry->d_name + (l - 4), ".pcb") != 0)) { + +#ifdef DEBUG +/* printf("... Found a footprint %s ... \n", subdirentry->d_name); */ +#endif + strcpy(fn_end, subdirentry->d_name); + if ((S_ISREG(buffer.st_mode)) || (WRAP_S_ISLNK(buffer.st_mode))) { + pcb_fptype_t ty; + void **tags = NULL; + ty = pcb_fp_file_type(subdirentry->d_name, (need_tags ? &tags : NULL)); + if ((ty == PCB_FP_FILE) || (ty == PCB_FP_PARAMETRIC)) { + n_footprints++; + if (cb(cookie, new_subdir, subdirentry->d_name, ty, tags)) + break; + continue; + } + else + if (tags != NULL) + free(tags); + } + + if ((S_ISDIR(buffer.st_mode)) || (WRAP_S_ISLNK(buffer.st_mode))) { + cb(cookie, new_subdir, subdirentry->d_name, PCB_FP_DIR, NULL); + if (recurse) { + n_footprints += fp_fs_list(pl, fn, recurse, cb, cookie, 0, need_tags); + } + continue; + } + + } + } + /* Done. Clean up, cd back into old dir, and return */ + closedir(subdirobj); + if (chdir(olddir)) + pcb_chdir_error_message(olddir); + return n_footprints; +} + +static int fp_fs_load_dir_(pcb_fplibrary_t *pl, const char *subdir, const char *toppath, int is_root) +{ + list_st_t l; + list_dir_t *d, *nextd; + char working_[PCB_PATH_MAX + 1]; + const char *visible_subdir; + char *working; /* String holding abs path to working dir */ + + + + sprintf(working_, "%s%c%s", toppath, PCB_DIR_SEPARATOR_C, subdir); + pcb_path_resolve(working_, &working, 0, pcb_false); + + /* Return error if the root is not a directory, to give other fp_ plugins a chance */ + if ((is_root) && (!pcb_is_dir(working))) { + free(working); + return -1; + } + + if (strcmp(subdir, ".") == 0) + visible_subdir = toppath; + else + visible_subdir = subdir; + + l.menu = pcb_fp_lib_search(pl, visible_subdir); + if (l.menu == NULL) + l.menu = pcb_fp_mkdir_len(pl, visible_subdir, -1); + l.subdirs = NULL; + l.children = 0; + + fp_fs_list(l.menu, working, 0, list_cb, &l, is_root, 1); + + /* now recurse to each subdirectory mapped in the previous call; + by now we don't care if menu is ruined by the realloc() in pcb_lib_menu_new() */ + for (d = l.subdirs; d != NULL; d = nextd) { + l.children += fp_fs_load_dir_(l.menu, d->subdir, d->parent, 0); + nextd = d->next; + free(d->subdir); + free(d->parent); + free(d); + } + if ((l.children == 0) && (l.menu->data.dir.children.used == 0)) + pcb_fp_rmdir(l.menu); + free(working); + return l.children; +} + + +static int fp_fs_load_dir(pcb_plug_fp_t *ctx, const char *path, int force) +{ + int res; + + res = fp_fs_load_dir_(&pcb_library, ".", path, 1); + if (res >= 0) { + pcb_fplibrary_t *l = pcb_fp_lib_search(&pcb_library, path); + if ((l != NULL) && (l->type == LIB_DIR)) + l->data.dir.backend = ctx; + } + return res; +} + +typedef struct { + const char *target; + int target_len; + int parametric; + char *path; + char *real_name; +} fp_search_t; + +static int fp_search_cb(void *cookie, const char *subdir, const char *name, pcb_fptype_t type, void *tags[]) +{ + fp_search_t *ctx = (fp_search_t *) cookie; + if ((strncmp(ctx->target, name, ctx->target_len) == 0) && ((! !ctx->parametric) == (type == PCB_FP_PARAMETRIC))) { + const char *suffix = name + ctx->target_len; + /* ugly heuristics: footprint names may end in .fp or .ele or .subc.lht or .lht */ + if ((*suffix == '\0') || (pcb_strcasecmp(suffix, ".fp") == 0) || (pcb_strcasecmp(suffix, ".ele") == 0) || (pcb_strcasecmp(suffix, ".subc.lht") == 0) || (pcb_strcasecmp(suffix, ".lht") == 0)) { + ctx->path = pcb_strdup(subdir); + ctx->real_name = pcb_strdup(name); + return 1; + } + } + return 0; +} + +/* walk the search_path for finding the first footprint for basename (shall not contain "(") */ +static char *fp_fs_search(const char *search_path, const char *basename, int parametric) +{ + const char *p, *end; + char path[PCB_PATH_MAX + 1]; + fp_search_t ctx; + + if ((*basename == '/') || (*basename == PCB_DIR_SEPARATOR_C)) + return pcb_strdup(basename); + + ctx.target = basename; + ctx.target_len = strlen(ctx.target); + ctx.parametric = parametric; + ctx.path = NULL; + +/* fprintf("Looking for %s\n", ctx.target);*/ + + for (p = search_path; *p != '\0'; p = end + 1) { + char *fpath; + end = strchr(p, ':'); + if (end != NULL) { + memcpy(path, p, end - p); + path[end - p] = '\0'; + } + else + strcpy(path, p); + + pcb_path_resolve(path, &fpath, 0, pcb_false); +/* fprintf(stderr, " in '%s'\n", fpath);*/ + + fp_fs_list(&pcb_library, fpath, 1, fp_search_cb, &ctx, 1, 0); + if (ctx.path != NULL) { + sprintf(path, "%s%c%s", ctx.path, PCB_DIR_SEPARATOR_C, ctx.real_name); + free(ctx.path); + free(ctx.real_name); +/* fprintf(" found '%s'\n", path);*/ + free(fpath); + return pcb_strdup(path); + } + free(fpath); + if (end == NULL) + break; + } + return NULL; +} + +TODO("subc: should be handled in io_*") +/* Decide about the type of a footprint file: + - it is a file element if the first non-comment is "Element(" or "Element[" + - else it is a parametric element (footprint generator) if it contains + "@@" "purpose" + - else it's not an element. + - if a line of a file element starts with ## and doesn't contain @, it's a tag + - if tags is not NULL, it's a pointer to a void *tags[] - an array of tag IDs +*/ +static pcb_fptype_t pcb_fp_file_type(const char *fn, void ***tags) +{ + int c, comment_len; + int first_element = 1; + FILE *f; + enum { + ST_WS, + ST_COMMENT, + ST_ELEMENT, + ST_TAG + } state = ST_WS; + char *tag = NULL; + int talloced = 0, tused = 0; + int Talloced = 0, Tused = 0; + pcb_fptype_t ret = PCB_FP_INVALID; + +TODO("fp: rather call plug_io if it is not parametric") + if (tags != NULL) + *tags = NULL; + + f = pcb_fopen(fn, "r"); + if (f == NULL) + return PCB_FP_INVALID; + + while ((c = fgetc(f)) != EOF) { + switch (state) { + case ST_ELEMENT: + if (isspace(c)) + break; + if ((c == '(') || (c == '[')) { + ret = PCB_FP_FILE; + goto out; + } + case ST_WS: + if (isspace(c)) + break; + if (c == '#') { + comment_len = 0; + state = ST_COMMENT; + break; + } + else if ((first_element) && (c == 'l')) { +TODO("fp: rather call plug_io if it is not parametric") + char s[23]; + /* li:pcb-rnd-subcircuit */ + fgets(s, 21, f); + s[20] = '\0'; + if (strcmp(s, "i:pcb-rnd-subcircuit") == 0) { + ret = PCB_FP_FILE; + goto out; + } + } + else if ((first_element) && (c == 'E')) { + char s[8]; + /* Element */ + fgets(s, 7, f); + s[6] = '\0'; + if (strcmp(s, "lement") == 0) { + state = ST_ELEMENT; + break; + } + } + else if ((first_element) && (c == '(')) { + char s[8]; + /* module */ + fgets(s, 7, f); + s[6] = '\0'; + if (strcmp(s, "module") == 0) { + state = ST_ELEMENT; + break; + } + } + first_element = 0; + /* fall-thru for detecting @ */ + case ST_COMMENT: + comment_len++; + if ((c == '#') && (comment_len == 1)) { + state = ST_TAG; + break; + } + if ((c == '\r') || (c == '\n')) + state = ST_WS; + if (c == '@') { + char s[10]; + maybe_purpose:; + /* "@@" "purpose" */ + fgets(s, 9, f); + s[8] = '\0'; + if (strcmp(s, "@purpose") == 0) { + ret = PCB_FP_PARAMETRIC; + goto out; + } + } + break; + case ST_TAG: + if ((c == '\r') || (c == '\n')) { /* end of a tag */ + if ((tags != NULL) && (tag != NULL)) { + tag[tused] = '\0'; + if (Tused >= Talloced) { + Talloced += 8; + *tags = realloc(*tags, (Talloced + 1) * sizeof(void *)); + } + (*tags)[Tused] = (void *) pcb_fp_tag(tag, 1); + Tused++; + (*tags)[Tused] = NULL; + } + + tused = 0; + state = ST_WS; + break; + } + if (c == '@') + goto maybe_purpose; + if (tused >= talloced) { + talloced += 64; + tag = realloc(tag, talloced + 1); /* always make room for an extra \0 */ + } + tag[tused] = c; + tused++; + } + } + +out:; + if (tag != NULL) + free(tag); + fclose(f); + return ret; +} + +#define F_IS_PARAMETRIC 0 +#define F_TMPNAME 1 +static FILE *fp_fs_fopen(pcb_plug_fp_t *ctx, const char *path, const char *name, pcb_fp_fopen_ctx_t *fctx, pcb_data_t *dst) +{ + char *basename, *params, *fullname; + FILE *fp, *f = NULL; + const char *libshell; + + fctx->field[F_TMPNAME].p = NULL; + fctx->field[F_IS_PARAMETRIC].i = pcb_fp_dupname(name, &basename, ¶ms); + if (basename == NULL) + return NULL; + + fctx->backend = ctx; + + fullname = fp_fs_search(path, basename, fctx->field[F_IS_PARAMETRIC].i); +/* fprintf(stderr, "basename=%s fullname=%s\n", basename, fullname);*/ +/* printf("pcb_fp_fopen: %d '%s' '%s' fullname='%s'\n", fctx->field[F_IS_PARAMETRIC].i, basename, params, fullname);*/ + + + if (fullname != NULL) { +/*fprintf(stderr, "fullname=%s param=%d\n", fullname, fctx->field[F_IS_PARAMETRIC].i);*/ + if (fctx->field[F_IS_PARAMETRIC].i) { + char *cmd; + const char *sep = " "; + libshell = conf_core.rc.library_shell; + if (libshell == NULL) { + libshell = ""; + sep = ""; + } + cmd = malloc(strlen(libshell) + strlen(fullname) + strlen(params) + 16); + sprintf(cmd, "%s%s%s %s", libshell, sep, fullname, params); +/*fprintf(stderr, " cmd=%s\n", cmd);*/ + fctx->field[F_TMPNAME].p = pcb_tempfile_name_new("pcb-rnd-pfp"); + f = pcb_fopen((char *)fctx->field[F_TMPNAME].p, "w+"); + if (f != NULL) { + char buff[4096]; + int len; + fp = pcb_popen(cmd, "r"); + while((len = fread(buff, 1, sizeof(buff), fp)) > 0) + fwrite(buff, 1, len, f); + pcb_pclose(fp); + rewind(f); + } + free(cmd); + } + else + f = pcb_fopen(fullname, "r"); + free(fullname); + } + + free(basename); + return f; +} + +static void fp_fs_fclose(pcb_plug_fp_t *ctx, FILE * f, pcb_fp_fopen_ctx_t *fctx) +{ + fclose(f); + if (fctx->field[F_TMPNAME].p != NULL) + pcb_tempfile_unlink((char *)fctx->field[F_TMPNAME].p); +} + + +static pcb_plug_fp_t fp_fs; + +int pplg_check_ver_fp_fs(int ver_needed) { return 0; } + +void pplg_uninit_fp_fs(void) +{ + PCB_HOOK_UNREGISTER(pcb_plug_fp_t, pcb_plug_fp_chain, &fp_fs); +} + +int pplg_init_fp_fs(void) +{ + PCB_API_CHK_VER; + fp_fs.plugin_data = NULL; + fp_fs.load_dir = fp_fs_load_dir; + fp_fs.fp_fopen = fp_fs_fopen; + fp_fs.fp_fclose = fp_fs_fclose; + PCB_HOOK_REGISTER(pcb_plug_fp_t, pcb_plug_fp_chain, &fp_fs); + return 0; +} Index: tags/2.1.2/src_plugins/fp_fs/fp_fs.pup =================================================================== --- tags/2.1.2/src_plugins/fp_fs/fp_fs.pup (nonexistent) +++ tags/2.1.2/src_plugins/fp_fs/fp_fs.pup (revision 24813) @@ -0,0 +1,7 @@ +$class fp +$short filesystem footprints +$long Footprint: file system based implementation. Used to be called Newlib: load footprints from directories. Run external processes for the parametric footprints. +$state works +$package (core) +default buildin +autoload 1 Index: tags/2.1.2/src_plugins/fp_wget/Makefile =================================================================== --- tags/2.1.2/src_plugins/fp_wget/Makefile (nonexistent) +++ tags/2.1.2/src_plugins/fp_wget/Makefile (revision 24813) @@ -0,0 +1,12 @@ +all: + cd ../../src && $(MAKE) mod_fp_wget + +CFLAGS = -Wall -g -I../../src -I../.. -I../../src_3rd -I../../src_3rd/liblihata + +test: tester + +tester: tester.o gedasymbols.o wget_common.o ../../src_3rd/genvector/gds_char.o + +clean: + rm *.o *.so 2>/dev/null ; true + Index: tags/2.1.2/src_plugins/fp_wget/Plug.tmpasm =================================================================== --- tags/2.1.2/src_plugins/fp_wget/Plug.tmpasm (nonexistent) +++ tags/2.1.2/src_plugins/fp_wget/Plug.tmpasm (revision 24813) @@ -0,0 +1,16 @@ +put /local/pcb/mod {fp_wget} +put /local/pcb/mod/OBJS [@ + $(PLUGDIR)/fp_wget/fp_wget.o + $(PLUGDIR)/fp_wget/wget_common.o + $(PLUGDIR)/fp_wget/gedasymbols.o + $(PLUGDIR)/fp_wget/edakrill.o +@] +put /local/pcb/mod/CONF {$(PLUGDIR)/fp_wget/fp_wget_conf.h} +put /local/pcb/mod/CONFFILE {fp_wget.conf} +put /local/pcb/mod/CONFVAR {fp_wget_conf_internal} + +switch /local/pcb/fp_wget/controls + case {buildin} include /local/pcb/tmpasm/buildin; end; + case {plugin} include /local/pcb/tmpasm/plugin; end; + case {disable} include /local/pcb/tmpasm/disable; end; +end Index: tags/2.1.2/src_plugins/fp_wget/edakrill.c =================================================================== --- tags/2.1.2/src_plugins/fp_wget/edakrill.c (nonexistent) +++ tags/2.1.2/src_plugins/fp_wget/edakrill.c (revision 24813) @@ -0,0 +1,306 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2017, 2018 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include "error.h" +#include "wget_common.h" +#include "edakrill.h" +#include "plugins.h" +#include "plug_footprint.h" +#include "compat_misc.h" +#include "safe_fs.h" +#include "fp_wget_conf.h" +#include "globalconst.h" + +#define REQUIRE_PATH_PREFIX "wget@edakrill" + +#define ROOT_URL "http://www.repo.hu/projects/edakrill/" +#define FP_URL ROOT_URL "user/" + +static const char *url_idx_md5 = ROOT_URL "tags.idx.md5"; +static const char *url_idx_list = ROOT_URL "tags.idx"; + +struct { + char *name; + char *fname; + int fp; + long date; + void **tags; + int tags_used, tags_alloced; +} krill; + +static void tag_add_(const char *kv) +{ + if (krill.tags_used >= krill.tags_alloced) { + krill.tags_alloced += 16; + krill.tags = realloc(krill.tags, sizeof(void *) * krill.tags_alloced); + } + krill.tags[krill.tags_used] = (void *)(kv == NULL ? NULL : pcb_fp_tag(kv, 1)); + krill.tags_used++; +} + +static void tag_add(const char *key, const char *val) +{ + char *next, *tmp; + for(; val != NULL; val = next) { + next = strchr(val, ','); + if (next != NULL) { + *next = '\0'; + next++; + } + while(*val == ' ') val++; + if (*val == '\0') + break; + tmp = pcb_strdup_printf("%s:%s", key, val); + tag_add_(tmp); + free(tmp); + } +} + +static void krill_flush(pcb_plug_fp_t *ctx, gds_t *vpath, int base_len) +{ + if ((krill.fp) && (krill.fname != NULL)) { + char *end, *fn; + pcb_fplibrary_t *l; + +/* printf("Krill %s: %s [%ld]\n", krill.name, krill.fname, krill.date);*/ + + /* split path and fn; path stays in vpath.array, fn is a ptr to the file name */ + gds_truncate(vpath, base_len); + gds_append_str(vpath, krill.fname); + end = vpath->array + vpath->used - 1; + while((end > vpath->array) && (*end != '/')) { end--; vpath->used--; } + *end = '\0'; + vpath->used--; + end++; + fn = end; + + /* add to the database */ + l = pcb_fp_mkdir_p(vpath->array); + if (krill.tags != NULL) + tag_add_(NULL); + l = pcb_fp_append_entry(l, fn, PCB_FP_FILE, krill.tags); + fn[-1] = '/'; + l->data.fp.loc_info = pcb_strdup(vpath->array); + + krill.tags = NULL; + krill.tags_used = 0; + } + + krill.tags_used = 0; + + free(krill.name); + free(krill.fname); + free(krill.tags); + krill.name = NULL; + krill.fname = NULL; + krill.fp = 0; + krill.date = 0; + krill.tags = NULL; + krill.tags_alloced = 0; +} + +int fp_edakrill_load_dir(pcb_plug_fp_t *ctx, const char *path, int force) +{ + FILE *f; + int fctx; + char *md5_last, *md5_new; + char line[1024]; + fp_get_mode mode; + gds_t vpath; + int vpath_base_len; + fp_get_mode wmode = FP_WGET_OFFLINE; + pcb_fplibrary_t *l; + char last_sum_fn[PCB_PATH_MAX]; + + if (strncmp(path, REQUIRE_PATH_PREFIX, strlen(REQUIRE_PATH_PREFIX)) != 0) + return -1; + + pcb_snprintf(last_sum_fn, sizeof(last_sum_fn), "%s" PCB_DIR_SEPARATOR_S "edakrill.last", conf_fp_wget.plugins.fp_wget.cache_dir); + + gds_init(&vpath); + gds_append_str(&vpath, REQUIRE_PATH_PREFIX); + + l = pcb_fp_mkdir_p(vpath.array); + if (l != NULL) + l->data.dir.backend = ctx; + + if (force || (conf_fp_wget.plugins.fp_wget.auto_update_edakrill)) + wmode &= ~FP_WGET_OFFLINE; + + if (fp_wget_open(url_idx_md5, conf_fp_wget.plugins.fp_wget.cache_dir, &f, &fctx, wmode) != 0) { + if (wmode & FP_WGET_OFFLINE) /* accept that we don't have the index in offline mode */ + goto quit; + goto err; + } + + md5_new = load_md5_sum(f); + fp_wget_close(&f, &fctx); + + if (md5_new == NULL) + goto err; + + f = pcb_fopen(last_sum_fn, "r"); + md5_last = load_md5_sum(f); + if (f != NULL) + fclose(f); + +/* printf("old='%s' new='%s'\n", md5_last, md5_new);*/ + + if (!md5_cmp_free(last_sum_fn, md5_last, md5_new)) { +/* printf("no chg.\n");*/ + mode = FP_WGET_OFFLINE; /* use the cache */ + } + else + mode = 0; + + if (fp_wget_open(url_idx_list, conf_fp_wget.plugins.fp_wget.cache_dir, &f, &fctx, mode) != 0) { + pcb_message(PCB_MSG_ERROR, "edakrill: failed to download the new list\n"); + pcb_remove(last_sum_fn); /* make sure it is downloaded next time */ + goto err; + } + + gds_append(&vpath, '/'); + vpath_base_len = vpath.used; + + while(fgets(line, sizeof(line), f) != NULL) { + char *end; + if ((*line == '#') || (line[1] != ' ')) + continue; + + end = line + strlen(line) - 1; + *end = '\0'; + if (*line == 'f') { + krill_flush(ctx, &vpath, vpath_base_len); + krill.name = pcb_strdup(line+2); + } + if (strncmp(line, "t type=", 7) == 0) { + if (strcmp(line+7, "footprint") == 0) + krill.fp = 1; + } + if (*line == 't') { + char *val, *key = line+2; + val = strchr(key, '='); + if (val != NULL) { + *val = '\0'; + val++; + if ((strcmp(key, "auto/file") != 0) && (strcmp(key, "type") != 0)) { + tag_add(key, val); + } + } + } + if (*line == 'm') { + end = strstr(line, ".cnv.fp "); + if (end != NULL) { + end += 7; + *end = '\0'; + end++; + krill.fname = pcb_strdup(line+2); + krill.date = strtol(end, NULL, 10); + } + } + + } + krill_flush(ctx, &vpath, vpath_base_len); + fp_wget_close(&f, &fctx); + + quit:; + gds_uninit(&vpath); + return 0; + + err:; + gds_uninit(&vpath); + return -1; +} + +#define FIELD_WGET_CTX 0 + +FILE *fp_edakrill_fopen(pcb_plug_fp_t *ctx, const char *path, const char *name, pcb_fp_fopen_ctx_t *fctx, pcb_data_t *dst) +{ + gds_t s; + char tmp[1024]; + FILE *f; + int from_path = (path != NULL) && (strcmp(path, REQUIRE_PATH_PREFIX) == 0); + + if (!from_path) { + if (strncmp(name, REQUIRE_PATH_PREFIX, strlen(REQUIRE_PATH_PREFIX)) == 0) + name+=strlen(REQUIRE_PATH_PREFIX); + else + return NULL; + } + + if (*name == '/') + name++; + + if (from_path) { + if (fp_wget_search(tmp, sizeof(tmp), name, !conf_fp_wget.plugins.fp_wget.auto_update_edakrill, url_idx_list, conf_fp_wget.plugins.fp_wget.cache_dir) != 0) + goto bad; + name = tmp; + } + + gds_init(&s); + gds_append_str(&s, FP_URL); + gds_append_str(&s, name); + + fp_wget_open(s.array, conf_fp_wget.plugins.fp_wget.cache_dir, &f, &(fctx->field[FIELD_WGET_CTX].i), FP_WGET_UPDATE); + + gds_uninit(&s); + + bad:; + fctx->backend = ctx; + + return f; +} + +void fp_edakrill_fclose(pcb_plug_fp_t *ctx, FILE * f, pcb_fp_fopen_ctx_t *fctx) +{ + fp_wget_close(&f, &(fctx->field[FIELD_WGET_CTX].i)); +} + + +static pcb_plug_fp_t fp_edakrill; + +void fp_edakrill_uninit(void) +{ + PCB_HOOK_UNREGISTER(pcb_plug_fp_t, pcb_plug_fp_chain, &fp_edakrill); +} + +void fp_edakrill_init(void) +{ + fp_edakrill.plugin_data = NULL; + fp_edakrill.load_dir = fp_edakrill_load_dir; + fp_edakrill.fp_fopen = fp_edakrill_fopen; + fp_edakrill.fp_fclose = fp_edakrill_fclose; + + PCB_HOOK_REGISTER(pcb_plug_fp_t, pcb_plug_fp_chain, &fp_edakrill); +} Index: tags/2.1.2/src_plugins/fp_wget/edakrill.h =================================================================== --- tags/2.1.2/src_plugins/fp_wget/edakrill.h (nonexistent) +++ tags/2.1.2/src_plugins/fp_wget/edakrill.h (revision 24813) @@ -0,0 +1,8 @@ +#include "plug_footprint.h" +#include "fp_wget_conf.h" +int fp_edakrill_load_dir(pcb_plug_fp_t *ctx, const char *path, int force); +FILE *fp_edakrill_fopen(pcb_plug_fp_t *ctx, const char *path, const char *name, pcb_fp_fopen_ctx_t *fctx, pcb_data_t *dst); +void fp_edakrill_fclose(pcb_plug_fp_t *ctx, FILE * f, pcb_fp_fopen_ctx_t *fctx); +void fp_edakrill_init(void); +void fp_edakrill_uninit(void); + Index: tags/2.1.2/src_plugins/fp_wget/fp_wget.c =================================================================== --- tags/2.1.2/src_plugins/fp_wget/fp_wget.c (nonexistent) +++ tags/2.1.2/src_plugins/fp_wget/fp_wget.c (revision 24813) @@ -0,0 +1,36 @@ +#include "config.h" +#include "gedasymbols.h" +#include "edakrill.h" +#include "plugins.h" +#include "fp_wget_conf.h" +#include "../src_plugins/fp_wget/conf_internal.c" + + +conf_fp_wget_t conf_fp_wget; + +#define FP_WGET_CONF_FN "fp_wget.conf" + +int pplg_check_ver_fp_wget(int ver_needed) { return 0; } + +void pplg_uninit_fp_wget(void) +{ + conf_unreg_file(FP_WGET_CONF_FN, fp_wget_conf_internal); + fp_gedasymbols_uninit(); + fp_edakrill_uninit(); + conf_unreg_fields("plugins/fp_wget/"); +} + +int pplg_init_fp_wget(void) +{ + PCB_API_CHK_VER; + +#define conf_reg(field,isarray,type_name,cpath,cname,desc,flags) \ + conf_reg_field(conf_fp_wget, field,isarray,type_name,cpath,cname,desc,flags); +#include "fp_wget_conf_fields.h" + + conf_reg_file(FP_WGET_CONF_FN, fp_wget_conf_internal); + + fp_gedasymbols_init(); + fp_edakrill_init(); + return 0; +} Index: tags/2.1.2/src_plugins/fp_wget/fp_wget.conf =================================================================== --- tags/2.1.2/src_plugins/fp_wget/fp_wget.conf (nonexistent) +++ tags/2.1.2/src_plugins/fp_wget/fp_wget.conf (revision 24813) @@ -0,0 +1,9 @@ +li:pcb-rnd-conf-v1 { + ha:overwrite { + ha:plugins { + ha:fp_wget { + cache_dir=fp_wget_cache + } + } + } +} Index: tags/2.1.2/src_plugins/fp_wget/fp_wget.pup =================================================================== --- tags/2.1.2/src_plugins/fp_wget/fp_wget.pup (nonexistent) +++ tags/2.1.2/src_plugins/fp_wget/fp_wget.pup (revision 24813) @@ -0,0 +1,8 @@ +$class fp +$short web footprints +$long Footprint: get static (file) footprints from the web, e.g. from http://gedasymbols.org +$state works +$package cloud +default buildin +dep fp_fs +autoload 1 Index: tags/2.1.2/src_plugins/fp_wget/fp_wget_conf.h =================================================================== --- tags/2.1.2/src_plugins/fp_wget/fp_wget_conf.h (nonexistent) +++ tags/2.1.2/src_plugins/fp_wget/fp_wget_conf.h (revision 24813) @@ -0,0 +1,18 @@ +#ifndef PCB_FP_WGET_CONF_H +#define PCB_FP_WGET_CONF_H + +#include "conf.h" + +typedef struct { + const struct plugins { + const struct fp_wget { + CFT_BOOLEAN auto_update_gedasymbols; /* update the index of gedasymbols on startup automatically */ + CFT_BOOLEAN auto_update_edakrill; /* update the index of edakrill on startup automatically */ + CFT_STRING cache_dir; /* where to build the cache */ + } fp_wget; + } plugins; +} conf_fp_wget_t; + +extern conf_fp_wget_t conf_fp_wget; + +#endif Index: tags/2.1.2/src_plugins/fp_wget/gedasymbols.c =================================================================== --- tags/2.1.2/src_plugins/fp_wget/gedasymbols.c (nonexistent) +++ tags/2.1.2/src_plugins/fp_wget/gedasymbols.c (revision 24813) @@ -0,0 +1,215 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2016, 2017, 2018 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include "error.h" +#include "wget_common.h" +#include "gedasymbols.h" +#include "plugins.h" +#include "plug_footprint.h" +#include "compat_misc.h" +#include "safe_fs.h" +#include "fp_wget_conf.h" +#include "globalconst.h" + +#define REQUIRE_PATH_PREFIX "wget@gedasymbols" + +#define CGI_URL "http://www.gedasymbols.org/scripts/global_list.cgi" +#define FP_URL "http://www.gedasymbols.org/" +#define FP_DL "?dl" +static const char *url_idx_md5 = CGI_URL "?md5"; +static const char *url_idx_list = CGI_URL; + + +int fp_gedasymbols_load_dir(pcb_plug_fp_t *ctx, const char *path, int force) +{ + FILE *f; + int fctx; + char *md5_last, *md5_new; + char line[1024]; + fp_get_mode mode; + gds_t vpath; + int vpath_base_len; + fp_get_mode wmode = FP_WGET_OFFLINE; + pcb_fplibrary_t *l; + char last_sum_fn[PCB_PATH_MAX]; + + if (strncmp(path, REQUIRE_PATH_PREFIX, strlen(REQUIRE_PATH_PREFIX)) != 0) + return -1; + + pcb_snprintf(last_sum_fn, sizeof(last_sum_fn), "%s" PCB_DIR_SEPARATOR_S "gedasymbols.last", conf_fp_wget.plugins.fp_wget.cache_dir); + + gds_init(&vpath); + gds_append_str(&vpath, REQUIRE_PATH_PREFIX); + + l = pcb_fp_mkdir_p(vpath.array); + if (l != NULL) + l->data.dir.backend = ctx; + + if (force || (conf_fp_wget.plugins.fp_wget.auto_update_gedasymbols)) + wmode &= ~FP_WGET_OFFLINE; + + if (fp_wget_open(url_idx_md5, conf_fp_wget.plugins.fp_wget.cache_dir, &f, &fctx, wmode) != 0) { + if (wmode & FP_WGET_OFFLINE) /* accept that we don't have the index in offline mode */ + goto quit; + goto err; + } + + md5_new = load_md5_sum(f); + fp_wget_close(&f, &fctx); + + if (md5_new == NULL) + goto err; + + f = pcb_fopen(last_sum_fn, "r"); + md5_last = load_md5_sum(f); + if (f != NULL) + fclose(f); + +/* printf("old='%s' new='%s'\n", md5_last, md5_new);*/ + + if (!md5_cmp_free(last_sum_fn, md5_last, md5_new)) { +/* printf("no chg.\n");*/ + mode = FP_WGET_OFFLINE; /* use the cache */ + } + else + mode = 0; + + if (fp_wget_open(url_idx_list, conf_fp_wget.plugins.fp_wget.cache_dir, &f, &fctx, mode) != 0) { + pcb_message(PCB_MSG_ERROR, "gedasymbols: failed to download the new list\n"); + pcb_remove(last_sum_fn); /* make sure it is downloaded next time */ + goto err; + } + + gds_append(&vpath, '/'); + vpath_base_len = vpath.used; + + while(fgets(line, sizeof(line), f) != NULL) { + char *end, *fn; + + if (*line == '#') + continue; + end = strchr(line, '|'); + if (end == NULL) + continue; + *end = '\0'; + + /* split path and fn; path stays in vpath.array, fn is a ptr to the file name */ + gds_truncate(&vpath, vpath_base_len); + gds_append_str(&vpath, line); + end = vpath.array + vpath.used - 1; + while((end > vpath.array) && (*end != '/')) { end--; vpath.used--; } + *end = '\0'; + vpath.used--; + end++; + fn = end; + + /* add to the database */ + l = pcb_fp_mkdir_p(vpath.array); + l = pcb_fp_append_entry(l, fn, PCB_FP_FILE, NULL); + fn[-1] = '/'; + l->data.fp.loc_info = pcb_strdup(vpath.array); + } + fp_wget_close(&f, &fctx); + + quit:; + gds_uninit(&vpath); + return 0; + + err:; + gds_uninit(&vpath); + return -1; +} + +#define FIELD_WGET_CTX 0 + +FILE *fp_gedasymbols_fopen(pcb_plug_fp_t *ctx, const char *path, const char *name, pcb_fp_fopen_ctx_t *fctx, pcb_data_t *dst) +{ + gds_t s; + char tmp[1024]; + FILE *f = NULL; + int from_path = (path != NULL) && (strcmp(path, REQUIRE_PATH_PREFIX) == 0); + + if (!from_path) { + if (strncmp(name, REQUIRE_PATH_PREFIX, strlen(REQUIRE_PATH_PREFIX)) == 0) + name+=strlen(REQUIRE_PATH_PREFIX); + else + return NULL; + } + + if (*name == '/') + name++; + + if (from_path) { + if (fp_wget_search(tmp, sizeof(tmp), name, !conf_fp_wget.plugins.fp_wget.auto_update_gedasymbols, url_idx_list, conf_fp_wget.plugins.fp_wget.cache_dir) != 0) + goto bad; + name = tmp; + } + + gds_init(&s); + gds_append_str(&s, FP_URL); + gds_append_str(&s, name); + gds_append_str(&s, FP_DL); + + fp_wget_open(s.array, conf_fp_wget.plugins.fp_wget.cache_dir, &f, &(fctx->field[FIELD_WGET_CTX].i), FP_WGET_UPDATE); + + gds_uninit(&s); + + bad:; + fctx->backend = ctx; + + return f; +} + +void fp_gedasymbols_fclose(pcb_plug_fp_t *ctx, FILE * f, pcb_fp_fopen_ctx_t *fctx) +{ + fp_wget_close(&f, &(fctx->field[FIELD_WGET_CTX].i)); +} + + +static pcb_plug_fp_t fp_gedasymbols; + +void fp_gedasymbols_uninit(void) +{ + PCB_HOOK_UNREGISTER(pcb_plug_fp_t, pcb_plug_fp_chain, &fp_gedasymbols); +} + +void fp_gedasymbols_init(void) +{ + fp_gedasymbols.plugin_data = NULL; + fp_gedasymbols.load_dir = fp_gedasymbols_load_dir; + fp_gedasymbols.fp_fopen = fp_gedasymbols_fopen; + fp_gedasymbols.fp_fclose = fp_gedasymbols_fclose; + + PCB_HOOK_REGISTER(pcb_plug_fp_t, pcb_plug_fp_chain, &fp_gedasymbols); +} Index: tags/2.1.2/src_plugins/fp_wget/gedasymbols.h =================================================================== --- tags/2.1.2/src_plugins/fp_wget/gedasymbols.h (nonexistent) +++ tags/2.1.2/src_plugins/fp_wget/gedasymbols.h (revision 24813) @@ -0,0 +1,8 @@ +#include "plug_footprint.h" +#include "fp_wget_conf.h" +int fp_gedasymbols_load_dir(pcb_plug_fp_t *ctx, const char *path, int force); +FILE *fp_gedasymbols_fopen(pcb_plug_fp_t *ctx, const char *path, const char *name, pcb_fp_fopen_ctx_t *fctx, pcb_data_t *dst); +void fp_gedasymbols_fclose(pcb_plug_fp_t *ctx, FILE * f, pcb_fp_fopen_ctx_t *fctx); +void fp_gedasymbols_init(void); +void fp_gedasymbols_uninit(void); + Index: tags/2.1.2/src_plugins/fp_wget/tester.c =================================================================== --- tags/2.1.2/src_plugins/fp_wget/tester.c (nonexistent) +++ tags/2.1.2/src_plugins/fp_wget/tester.c (revision 24813) @@ -0,0 +1,39 @@ +#include +#include +#include "config.h" +#include "gedasymbols.h" + +#undef strdup +char *pcb_strdup(const char *s) { return strdup(s); } + +pcb_plug_fp_t *pcb_plug_fp_chain = NULL; + +pcb_library_t ltmp; +pcb_library_t *pcb_fp_mkdir_p(const char *path) +{ + printf("lib mkdir: '%s'\n", path); + return (library_t *)<mp; +} + +pcb_library_t *pcb_fp_append_entry(library_t *parent, const char *name, pcb_fp_type_t type, void *tags[]) +{ + printf("lib entry: '%s'\n", name); + return (library_t *)<mp; +} + +int main() +{ + pcb_fp_fopen_ctx_t fctx; + FILE *f; + char line[1024]; + +/* fp_gedasymbols_load_dir(NULL, "gedasymbols://", 1); */ + f = fp_gedasymbols_fopen(NULL, NULL, "wget@gedasymbols/user/sean_depagnier/footprints/HDMI_CONN.fp", &fctx); + + while(fgets(line, sizeof(line), f) != NULL) + printf("|%s", line); + + fp_gedasymbols_fclose(NULL, f, &fctx); + +} + Index: tags/2.1.2/src_plugins/fp_wget/wget_common.c =================================================================== --- tags/2.1.2/src_plugins/fp_wget/wget_common.c (nonexistent) +++ tags/2.1.2/src_plugins/fp_wget/wget_common.c (revision 24813) @@ -0,0 +1,229 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2016, 2017, 2018 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include +#include +#include +#include "config.h" +#include "wget_common.h" +#include "compat_misc.h" +#include "safe_fs.h" + +enum { + FCTX_INVALID = 0, + FCTX_POPEN, + FCTX_FOPEN, + FCTX_NOP +}; + +const char *wget_cmd = "wget -U 'pcb-rnd-fp_wget'"; +int fp_wget_offline = 0; + +static int mkdirp(const char *dir) +{ +/* TODO */ + char buff[8192]; + sprintf(buff, "mkdir -p '%s'", dir); + return pcb_system(buff); +} + +int fp_wget_open(const char *url, const char *cache_path, FILE **f, int *fctx, fp_get_mode mode) +{ + char *cmd; + const char *upds; + int wl = strlen(wget_cmd), ul = strlen(url), cl = strlen(cache_path); + cmd = malloc(wl+ul*2+cl+32); + + *fctx = FCTX_INVALID; + + if (mode & FP_WGET_UPDATE) + upds = "-c"; + else + upds = ""; + + if (cache_path == NULL) { + sprintf(cmd, "%s -O - %s '%s'", wget_cmd, upds, url); + if (f == NULL) + goto error; + if (!fp_wget_offline) + *f = pcb_popen(cmd, "r"); + if (*f == NULL) + goto error; + *fctx = FCTX_POPEN; + } + else { + char *cdir; + cdir = strstr(url, "://"); + if (cdir == NULL) + goto error; + cdir += 3; + + { + char *end; + sprintf(cmd, "%s/%s", cache_path, cdir); + end = strrchr(cmd, '/'); + if (end != NULL) { + *end = '\0'; + if (mkdirp(cmd) != 0) + goto error; + *end = '/'; + } + } + + if ((!fp_wget_offline) && !(mode & FP_WGET_OFFLINE)) { + int res; + sprintf(cmd, "%s -O '%s/%s' %s '%s'", wget_cmd, cache_path, cdir, upds, url); + res = pcb_system(cmd); +/* pcb_trace("------res=%d\n", res); */ + if ((res != 0) && (res != 768)) { /* some versions of wget will return error on -c if the file doesn't need update; try to guess whether it's really an error */ + /* when wget fails, a 0-long file might be left there - remove it so it won't block new downloads */ + sprintf(cmd, "%s/%s", cache_path, cdir); + pcb_remove(cmd); + } + } + if (f != NULL) { + sprintf(cmd, "%s/%s", cache_path, cdir); + *f = pcb_fopen(cmd, "r"); + if (*f == NULL) + goto error; + *fctx = FCTX_FOPEN; + } + else + *fctx = FCTX_NOP; + } + free(cmd); + return 0; + + error:; + free(cmd); + return -1; +} + +int fp_wget_close(FILE **f, int *fctx) +{ + if (*fctx == FCTX_NOP) + return 0; + + if (*f == NULL) + return -1; + + switch(*fctx) { + case FCTX_POPEN: pcb_pclose(*f); *f = NULL; return 0; + case FCTX_FOPEN: fclose(*f); *f = NULL; return 0; + } + + return -1; +} + + +char *load_md5_sum(FILE *f) +{ + char *s, sum[64]; + + if (f == NULL) + return NULL; + + *sum = '\0'; + fgets(sum, sizeof(sum), f); + sum[sizeof(sum)-1] = '\0'; + + for(s = sum;; s++) { + if ((*s == '\0') || (isspace(*s))) { + if ((s - sum) == 32) { + *s = '\0'; + return pcb_strdup(sum); + } + else + return NULL; + } + if (isdigit(*s)) + continue; + if ((*s >= 'a') && (*s <= 'f')) + continue; + if ((*s >= 'A') && (*s <= 'F')) + continue; + return NULL; + } +} + +int md5_cmp_free(const char *last_fn, char *md5_last, char *md5_new) +{ + int changed = 0; + + if ((md5_last == NULL) || (strcmp(md5_last, md5_new) != 0)) { + FILE *f; + f = pcb_fopen(last_fn, "w"); + fputs(md5_new, f); + fclose(f); + changed = 1; + } + if (md5_last != NULL) + free(md5_last); + free(md5_new); + return changed; +} + +int fp_wget_search_(char *out, int out_len, FILE *f, const char *fn) +{ + char *line, line_[8192]; + + *out = '\0'; + + if (f == NULL) + return -1; + + while((line = fgets(line_, sizeof(line_), f)) != NULL) { + char *sep; + sep = strchr(line, '|'); + if (sep == NULL) + continue; + *sep = '\0'; + if ((strstr(line, fn) != NULL) && (strlen(line) < out_len)) { + strcpy(out, line); + return 0; + } + } + return -1; +} + + +int fp_wget_search(char *out, int out_len, const char *name, int offline, const char *url, const char *cache) +{ + FILE *f_idx; + int fctx; + fp_get_mode mode = offline ? FP_WGET_OFFLINE : 0; + + if (fp_wget_open(url, cache, &f_idx, &fctx, mode) == 0) { + if (fp_wget_search_(out, out_len, f_idx, name) != 0) { + fp_wget_close(&f_idx, &fctx); + return -1; + } + } + else + return -1; + fp_wget_close(&f_idx, &fctx); + return 0; +} Index: tags/2.1.2/src_plugins/fp_wget/wget_common.h =================================================================== --- tags/2.1.2/src_plugins/fp_wget/wget_common.h (nonexistent) +++ tags/2.1.2/src_plugins/fp_wget/wget_common.h (revision 24813) @@ -0,0 +1,21 @@ +#include + +typedef enum { + FP_WGET_UPDATE = 1, /* wget -c: update existing file, don't replace (a.k.a. cache) */ + FP_WGET_OFFLINE = 2 /* do not wget, open cached file or fail */ +} fp_get_mode; + +int fp_wget_open(const char *url, const char *cache_path, FILE **f, int *fctx, fp_get_mode mode); +int fp_wget_close(FILE **f, int *fctx); + +char *load_md5_sum(FILE *f); +int md5_cmp_free(const char *last_fn, char *md5_last, char *md5_new); + +/* search fn in an auto updated index file; return 0 on success and + fill in out with the full path from the index. */ +int fp_wget_search(char *out, int out_len, const char *fn, int offline, const char *idx_url, const char *idx_cache); + +/* search fn in an index file; return 0 on success and fill in out with the + full path from the index. */ +int fp_wget_search_(char *out, int out_len, FILE *f_idx, const char *fn); + Index: tags/2.1.2/src_plugins/hid_batch/Makefile =================================================================== --- tags/2.1.2/src_plugins/hid_batch/Makefile (nonexistent) +++ tags/2.1.2/src_plugins/hid_batch/Makefile (revision 24813) @@ -0,0 +1,6 @@ +all: + cd ../../src && $(MAKE) mod_hid_batch + +clean: + rm *.o *.so 2>/dev/null ; true + Index: tags/2.1.2/src_plugins/hid_batch/Plug.tmpasm =================================================================== --- tags/2.1.2/src_plugins/hid_batch/Plug.tmpasm (nonexistent) +++ tags/2.1.2/src_plugins/hid_batch/Plug.tmpasm (revision 24813) @@ -0,0 +1,8 @@ +put /local/pcb/mod {hid_batch} +append /local/pcb/mod/OBJS [@ $(PLUGDIR)/hid_batch/batch.o @] + +switch /local/pcb/hid_batch/controls + case {buildin} include /local/pcb/tmpasm/buildin; end; + case {plugin} include /local/pcb/tmpasm/plugin; end; + case {disable} include /local/pcb/tmpasm/disable; end; +end Index: tags/2.1.2/src_plugins/hid_batch/batch.c =================================================================== --- tags/2.1.2/src_plugins/hid_batch/batch.c (nonexistent) +++ tags/2.1.2/src_plugins/hid_batch/batch.c (revision 24813) @@ -0,0 +1,405 @@ +#include "config.h" + +#include +#include +#include +#include + +#include "board.h" +#include "hid.h" +#include "data.h" +#include "layer.h" +#include "pcb-printf.h" +#include "plugins.h" +#include "compat_misc.h" +#include "event.h" +#include "conf_core.h" + +#include "hid_draw_helpers.h" +#include "hid_nogui.h" +#include "actions.h" +#include "hid_init.h" +#include "hid_attrib.h" + +static const char *batch_cookie = "batch HID"; + +static int batch_active = 0; +static void batch_begin(void); +static void batch_end(void); + +/* This is a text-line "batch" HID, which exists for scripting and + non-GUI needs. */ + +typedef struct hid_gc_s { + pcb_core_gc_t core_gc; +} hid_gc_s; + +static pcb_hid_attribute_t *batch_get_export_options(int *n_ret) +{ + if (n_ret != NULL) + *n_ret = 0; + return NULL; +} + +static int batch_usage(const char *topic) +{ + fprintf(stderr, "\nbatch GUI command line arguments: none\n\n"); + fprintf(stderr, "\nInvocation: pcb-rnd --gui batch [options]\n"); + return 0; +} + + +/* ----------------------------------------------------------------------------- */ + +static char *prompt = NULL; + +static void uninit_batch(void) +{ + pcb_remove_actions_by_cookie(batch_cookie); + pcb_event_unbind_allcookie(batch_cookie); + if (prompt != NULL) { + free(prompt); + prompt = NULL; + } +} + +static void ev_pcb_changed(void *user_data, int argc, pcb_event_arg_t argv[]) +{ + if (prompt != NULL) + free(prompt); + if (PCB && PCB->Filename) { + prompt = strrchr(PCB->Filename, '/'); + if (prompt) + prompt++; + else + prompt = PCB->Filename; + if (prompt != NULL) + prompt = pcb_strdup(prompt); + } + else + prompt = pcb_strdup("no-board"); +} + +static void log_append(pcb_logline_t *line) +{ + if ((line->level < PCB_MSG_INFO) && !conf_core.rc.verbose) + return; + + if ((line->prev == NULL) || (line->prev->str[line->prev->len-1] == '\n')) { + switch(line->level) { + case PCB_MSG_DEBUG: printf("D: "); break; + case PCB_MSG_INFO: printf("I: "); break; + case PCB_MSG_WARNING: printf("W: "); break; + case PCB_MSG_ERROR: printf("E: "); break; + } + } + printf("%s", line->str); + line->seen = 1; +} + +static void ev_log_append(void *user_data, int argc, pcb_event_arg_t argv[]) +{ + if (!batch_active) + return; + + log_append((pcb_logline_t *)argv[1].d.p); +} + +static void log_import(void) +{ + pcb_logline_t *n; + for(n = pcb_log_first; n != NULL; n = n->next) + log_append(n); +} + +static fgw_error_t pcb_act_help(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + pcb_print_actions(); + PCB_ACT_IRES(0); + return 0; +} + +static fgw_error_t pcb_act_info(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + int i, j; + if (!PCB || !PCB->Data || !PCB->Filename) { + printf("No PCB loaded.\n"); + return 0; + } + printf("Filename: %s\n", PCB->Filename); + pcb_printf("Size: %ml x %ml mils, %mm x %mm mm\n", PCB->MaxWidth, PCB->MaxHeight, PCB->MaxWidth, PCB->MaxHeight); + for (i = 0; i < PCB_MAX_LAYER; i++) { + pcb_layergrp_id_t lg = pcb_layer_get_group(PCB, i); + unsigned int gflg = pcb_layergrp_flags(PCB, lg); + for (j = 0; j < PCB_MAX_LAYER; j++) + putchar(j == lg ? '#' : '-'); + printf(" %c %s\n", (gflg & PCB_LYT_TOP) ? 'c' : (gflg & PCB_LYT_BOTTOM) ? 's' : '-', PCB->Data->Layer[i].name); + } + PCB_ACT_IRES(0); + return 0; +} + +pcb_action_t batch_action_list[] = { + {"Help", pcb_act_help}, + {"Info", pcb_act_info} +}; + +PCB_REGISTER_ACTIONS(batch_action_list, batch_cookie) + +extern int isatty(); + +/* ----------------------------------------------------------------------------- */ +static int batch_stay; +static void batch_do_export(pcb_hid_attr_val_t * options) +{ + int interactive; + char line[1000]; + + batch_begin(); + + if (isatty(0)) + interactive = 1; + else + interactive = 0; + + log_import(); + + if ((interactive) && (!conf_core.rc.quiet)) { + printf("Entering %s version %s batch mode.\n", PCB_PACKAGE, PCB_VERSION); + printf("See http://repo.hu/projects/pcb-rnd for project information\n"); + } + + batch_stay = 1; + while (batch_stay) { + if ((interactive) && (!conf_core.rc.quiet)) { + printf("%s:%s> ", prompt, pcb_cli_prompt(NULL)); + fflush(stdout); + } + if (fgets(line, sizeof(line) - 1, stdin) == NULL) { + uninit_batch(); + goto quit; + } + pcb_parse_command(line, pcb_false); + } + + quit:; + batch_end(); +} + +static void batch_do_exit(pcb_hid_t *hid) +{ + batch_stay = 0; +} + +static int batch_parse_arguments(int *argc, char ***argv) +{ + return pcb_hid_parse_command_line(argc, argv); +} + +static void batch_invalidate_lr(pcb_coord_t l, pcb_coord_t r, pcb_coord_t t, pcb_coord_t b) +{ +} + +static void batch_invalidate_all(void) +{ +} + +static int batch_set_layer_group(pcb_layergrp_id_t group, const char *purpose, int purpi, pcb_layer_id_t layer, unsigned int flags, int is_empty, pcb_xform_t **xform) +{ + return 0; +} + +static pcb_hid_gc_t batch_make_gc(void) +{ + static pcb_core_gc_t hc; + return (pcb_hid_gc_t)&hc; +} + +static void batch_destroy_gc(pcb_hid_gc_t gc) +{ +} + +static void batch_set_color(pcb_hid_gc_t gc, const pcb_color_t *name) +{ +} + +static void batch_set_line_cap(pcb_hid_gc_t gc, pcb_cap_style_t style) +{ +} + +static void batch_set_line_width(pcb_hid_gc_t gc, pcb_coord_t width) +{ +} + +static void batch_set_draw_xor(pcb_hid_gc_t gc, int xor_set) +{ +} + +static void batch_draw_line(pcb_hid_gc_t gc, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2) +{ +} + +static void batch_draw_arc(pcb_hid_gc_t gc, pcb_coord_t cx, pcb_coord_t cy, pcb_coord_t width, pcb_coord_t height, pcb_angle_t start_angle, pcb_angle_t end_angle) +{ +} + +static void batch_draw_rect(pcb_hid_gc_t gc, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2) +{ +} + +static void batch_fill_circle(pcb_hid_gc_t gc, pcb_coord_t cx, pcb_coord_t cy, pcb_coord_t radius) +{ +} + +static void batch_fill_polygon(pcb_hid_gc_t gc, int n_coords, pcb_coord_t * x, pcb_coord_t * y) +{ +} + +static void batch_fill_polygon_offs(pcb_hid_gc_t gc, int n_coords, pcb_coord_t *x, pcb_coord_t *y, pcb_coord_t dx, pcb_coord_t dy) +{ +} + +static void batch_fill_rect(pcb_hid_gc_t gc, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2) +{ +} + +static void batch_calibrate(double xval, double yval) +{ +} + +static int batch_shift_is_pressed(void) +{ + return 0; +} + +static int batch_control_is_pressed(void) +{ + return 0; +} + +static int batch_mod1_is_pressed(void) +{ + return 0; +} + +static void batch_get_coords(const char *msg, pcb_coord_t *x, pcb_coord_t *y, int force) +{ +} + +static void batch_get_view_size(pcb_coord_t *width, pcb_coord_t *height) +{ + *width = PCB->MaxWidth; + *height = PCB->MaxHeight; +} + +static void batch_set_crosshair(pcb_coord_t x, pcb_coord_t y, int action) +{ +} + +static pcb_hidval_t batch_add_timer(void (*func) (pcb_hidval_t user_data), unsigned long milliseconds, pcb_hidval_t user_data) +{ + pcb_hidval_t rv; + rv.lval = 0; + return rv; +} + +static void batch_stop_timer(pcb_hidval_t timer) +{ +} + +pcb_hidval_t +batch_watch_file(int fd, unsigned int condition, pcb_bool (*func) (pcb_hidval_t watch, int fd, unsigned int condition, pcb_hidval_t user_data), + pcb_hidval_t user_data) +{ + pcb_hidval_t ret; + ret.ptr = NULL; + return ret; +} + +void batch_unwatch_file(pcb_hidval_t data) +{ +} + +static void batch_create_menu(const char *menu_path, const pcb_menu_prop_t *props) +{ +} + +#include "dolists.h" + +static pcb_hid_t batch_hid; + +int pplg_check_ver_hid_batch(int ver_needed) { return 0; } + +void pplg_uninit_hid_batch(void) +{ + pcb_event_unbind_allcookie(batch_cookie); + pcb_hid_remove_attributes_by_cookie(batch_cookie); +} + +int pplg_init_hid_batch(void) +{ + PCB_API_CHK_VER; + memset(&batch_hid, 0, sizeof(pcb_hid_t)); + + pcb_hid_nogui_init(&batch_hid); + pcb_dhlp_draw_helpers_init(&batch_hid); + + batch_hid.struct_size = sizeof(pcb_hid_t); + batch_hid.name = "batch"; + batch_hid.description = "Batch-mode GUI for non-interactive use."; + batch_hid.gui = 1; + + batch_hid.get_export_options = batch_get_export_options; + batch_hid.do_export = batch_do_export; + batch_hid.do_exit = batch_do_exit; + batch_hid.parse_arguments = batch_parse_arguments; + batch_hid.invalidate_lr = batch_invalidate_lr; + batch_hid.invalidate_all = batch_invalidate_all; + batch_hid.set_layer_group = batch_set_layer_group; + batch_hid.make_gc = batch_make_gc; + batch_hid.destroy_gc = batch_destroy_gc; + batch_hid.set_color = batch_set_color; + batch_hid.set_line_cap = batch_set_line_cap; + batch_hid.set_line_width = batch_set_line_width; + batch_hid.set_draw_xor = batch_set_draw_xor; + batch_hid.draw_line = batch_draw_line; + batch_hid.draw_arc = batch_draw_arc; + batch_hid.draw_rect = batch_draw_rect; + batch_hid.fill_circle = batch_fill_circle; + batch_hid.fill_polygon = batch_fill_polygon; + batch_hid.fill_polygon_offs = batch_fill_polygon_offs; + batch_hid.fill_rect = batch_fill_rect; + batch_hid.calibrate = batch_calibrate; + batch_hid.shift_is_pressed = batch_shift_is_pressed; + batch_hid.control_is_pressed = batch_control_is_pressed; + batch_hid.mod1_is_pressed = batch_mod1_is_pressed; + batch_hid.get_coords = batch_get_coords; + batch_hid.get_view_size = batch_get_view_size; + batch_hid.set_crosshair = batch_set_crosshair; + batch_hid.add_timer = batch_add_timer; + batch_hid.stop_timer = batch_stop_timer; + batch_hid.watch_file = batch_watch_file; + batch_hid.unwatch_file = batch_unwatch_file; + batch_hid.create_menu = batch_create_menu; + batch_hid.usage = batch_usage; + + pcb_event_bind(PCB_EVENT_BOARD_CHANGED, ev_pcb_changed, NULL, batch_cookie); + pcb_event_bind(PCB_EVENT_LOG_APPEND, ev_log_append, NULL, batch_cookie); + + pcb_hid_register_hid(&batch_hid); + return 0; +} + + +static void batch_begin(void) +{ + PCB_REGISTER_ACTIONS(batch_action_list, batch_cookie) + batch_active = 1; +} + +static void batch_end(void) +{ + pcb_remove_actions_by_cookie(batch_cookie); + batch_active = 0; +} + Index: tags/2.1.2/src_plugins/hid_batch/hid_batch.pup =================================================================== --- tags/2.1.2/src_plugins/hid_batch/hid_batch.pup (nonexistent) +++ tags/2.1.2/src_plugins/hid_batch/hid_batch.pup (revision 24813) @@ -0,0 +1,7 @@ +$class hid +$short batch process (no-gui HID) +$long HID without GUI: read actions from stdin. +$state works +$package (core) +default buildin +autoload 1 Index: tags/2.1.2/src_plugins/hid_gtk2_gdk/Makefile =================================================================== --- tags/2.1.2/src_plugins/hid_gtk2_gdk/Makefile (nonexistent) +++ tags/2.1.2/src_plugins/hid_gtk2_gdk/Makefile (revision 24813) @@ -0,0 +1,6 @@ +all: + cd ../../src && $(MAKE) mod_hid_gtk2_gdk + +clean: + rm *.o *.so 2>/dev/null ; true + Index: tags/2.1.2/src_plugins/hid_gtk2_gdk/Plug.tmpasm =================================================================== --- tags/2.1.2/src_plugins/hid_gtk2_gdk/Plug.tmpasm (nonexistent) +++ tags/2.1.2/src_plugins/hid_gtk2_gdk/Plug.tmpasm (revision 24813) @@ -0,0 +1,19 @@ +put /local/pcb/mod {hid_gtk2_gdk} +put /local/pcb/mod/OBJS_C99 [@ + $(PLUGDIR)/hid_gtk2_gdk/gtkhid-main.o + $(PLUGDIR)/hid_gtk2_gdk/gtkhid-gdk.o +@] + +switch /local/pcb/hid_gtk2_gdk/controls + case {disable} end; + default + put /local/pcb/mod/CFLAGS /target/libs/gui/gtk2/cflags + put /local/pcb/mod/LDFLAGS /target/libs/gui/gtk2/ldflags + end +end + +switch /local/pcb/hid_gtk2_gdk/controls + case {buildin} include /local/pcb/tmpasm/buildin; end; + case {plugin} include /local/pcb/tmpasm/plugin; end; + case {disable} include /local/pcb/tmpasm/disable; end; +end Index: tags/2.1.2/src_plugins/hid_gtk2_gdk/gtkhid-gdk.c =================================================================== --- tags/2.1.2/src_plugins/hid_gtk2_gdk/gtkhid-gdk.c (nonexistent) +++ tags/2.1.2/src_plugins/hid_gtk2_gdk/gtkhid-gdk.c (revision 24813) @@ -0,0 +1,1585 @@ +#include "config.h" +#include "conf_core.h" + +#include + +#include "crosshair.h" +#include "data.h" +#include "draw.h" +#include "layer.h" +#include "grid.h" +#include "hid_draw_helpers.h" +#include "hid_attrib.h" +#include "hid_color.h" +#include "funchash_core.h" + +#include "../src_plugins/lib_gtk_hid/gui.h" +#include "../src_plugins/lib_gtk_hid/coord_conv.h" +#include "../src_plugins/lib_gtk_hid/preview_helper.h" + +#include "../src_plugins/lib_gtk_common/hid_gtk_conf.h" +#include "../src_plugins/lib_gtk_common/lib_gtk_config.h" + +#include "../src_plugins/lib_hid_common/clip.h" + +extern pcb_hid_t gtk2_gdk_hid; +static void ghid_gdk_screen_update(void); + +/* Sets priv->u_gc to the "right" GC to use (wrt mask or window) +*/ +#define USE_GC(gc) if (!use_gc(gc, 1)) return +#define USE_GC_NOPEN(gc) if (!use_gc(gc, 0)) return + +typedef struct render_priv_s { + GdkGC *bg_gc; + GdkColor bg_color; + GdkGC *offlimits_gc; + GdkColor offlimits_color; + GdkGC *grid_gc; + GdkGC *clear_gc, *copy_gc; + GdkColor grid_color; + GdkRectangle clip_rect; + pcb_bool clip_rect_valid; + pcb_bool direct; + int attached_invalidate_depth; + int mark_invalidate_depth; + + /* available canvases */ + GdkPixmap *base_pixel; /* base canvas, pixel colors only */ + GdkPixmap *sketch_pixel, *sketch_clip; /* sketch canvas for compositing (non-direct) */ + + /* currently active: drawing routines draw to these*/ + GdkDrawable *out_pixel, *out_clip; + GdkGC *pixel_gc, *clip_gc; + GdkColor clip_color; +} render_priv_t; + + +typedef struct hid_gc_s { + pcb_core_gc_t core_gc; + pcb_hid_t *me_pointer; + GdkGC *pixel_gc; + GdkGC *clip_gc; + + pcb_color_t pcolor; + pcb_coord_t width; + gint cap, join; + gchar xor_mask; + gint sketch_seq; +} hid_gc_s; + +static const gchar *get_color_name(pcb_gtk_color_t * color) +{ + static char tmp[16]; + + if (!color) + return "#000000"; + + sprintf(tmp, "#%2.2x%2.2x%2.2x", (color->red >> 8) & 0xff, (color->green >> 8) & 0xff, (color->blue >> 8) & 0xff); + return tmp; +} + +/* Returns TRUE only if color_string has been allocated to color. */ +static pcb_bool map_color_string(const char *color_string, pcb_gtk_color_t * color) +{ + static GdkColormap *colormap = NULL; + pcb_bool parsed; + + if (!color || !gport->top_window) + return FALSE; + if (colormap == NULL) + colormap = gtk_widget_get_colormap(gport->top_window); + if (color->red || color->green || color->blue) + gdk_colormap_free_colors(colormap, color, 1); + parsed = gdk_color_parse(color_string, color); + if (parsed) + gdk_color_alloc(colormap, color); + + return parsed; +} + + +static int ghid_gdk_set_layer_group(pcb_layergrp_id_t group, const char *purpose, int purpi, pcb_layer_id_t layer, unsigned int flags, int is_empty, pcb_xform_t **xform) +{ + int idx = group; + if (idx >= 0 && idx < pcb_max_group(PCB)) { + int n = PCB->LayerGroups.grp[group].len; + for (idx = 0; idx < n - 1; idx++) { + int ni = PCB->LayerGroups.grp[group].lid[idx]; + if (ni >= 0 && ni < pcb_max_layer && PCB->Data->Layer[ni].meta.real.vis) + break; + } + idx = PCB->LayerGroups.grp[group].lid[idx]; + } + + /* non-virtual layers with group visibility */ + switch (flags & PCB_LYT_ANYTHING) { + case PCB_LYT_MASK: + case PCB_LYT_PASTE: + return (PCB_LAYERFLG_ON_VISIBLE_SIDE(flags) && PCB->LayerGroups.grp[group].vis); + } + + if (idx >= 0 && idx < pcb_max_layer && ((flags & PCB_LYT_ANYTHING) != PCB_LYT_SILK)) + return PCB->Data->Layer[idx].meta.real.vis; + + if (PCB_LAYER_IS_ASSY(flags, purpi)) + return 0; + + /* virtual layers */ + { + if (PCB_LAYER_IS_DRILL(flags, purpi)) + return 1; + + switch (flags & PCB_LYT_ANYTHING) { + case PCB_LYT_INVIS: + return PCB->InvisibleObjectsOn; + case PCB_LYT_SILK: + if (PCB_LAYERFLG_ON_VISIBLE_SIDE(flags)) + return pcb_silk_on(PCB); + return 0; + case PCB_LYT_UI: + return 1; + case PCB_LYT_RAT: + return PCB->RatOn; + } + } + return 0; +} + +static void ghid_gdk_destroy_gc(pcb_hid_gc_t gc) +{ + if (gc->pixel_gc) + g_object_unref(gc->pixel_gc); + if (gc->clip_gc) + g_object_unref(gc->clip_gc); + g_free(gc); +} + +static pcb_hid_gc_t ghid_gdk_make_gc(void) +{ + pcb_hid_gc_t rv; + + rv = g_new0(hid_gc_s, 1); + rv->me_pointer = >k2_gdk_hid; + rv->pcolor = conf_core.appearance.color.background; + return rv; +} + +static void set_clip(render_priv_t *priv, GdkGC *gc) +{ + if (gc == NULL) + return; + if (priv->clip_rect_valid) + gdk_gc_set_clip_rectangle(gc, &priv->clip_rect); + else + gdk_gc_set_clip_mask(gc, NULL); +} + +static inline void ghid_gdk_draw_grid_global(void) +{ + render_priv_t *priv = gport->render_priv; + pcb_coord_t x, y, x1, y1, x2, y2, grd; + int n, i; + static GdkPoint *points = NULL; + static int npoints = 0; + + x1 = pcb_grid_fit(MAX(0, SIDE_X(gport->view.x0)), PCB->Grid, PCB->GridOffsetX); + y1 = pcb_grid_fit(MAX(0, SIDE_Y(gport->view.y0)), PCB->Grid, PCB->GridOffsetY); + x2 = pcb_grid_fit(MIN(PCB->MaxWidth, SIDE_X(gport->view.x0 + gport->view.width - 1)), PCB->Grid, PCB->GridOffsetX); + y2 = pcb_grid_fit(MIN(PCB->MaxHeight, SIDE_Y(gport->view.y0 + gport->view.height - 1)), PCB->Grid, PCB->GridOffsetY); + + grd = PCB->Grid; + + if (Vz(grd) < conf_hid_gtk.plugins.hid_gtk.global_grid.min_dist_px) { + if (!conf_hid_gtk.plugins.hid_gtk.global_grid.sparse) + return; + grd *= (conf_hid_gtk.plugins.hid_gtk.global_grid.min_dist_px / Vz(grd)); + } + + if (x1 > x2) { + pcb_coord_t tmp = x1; + x1 = x2; + x2 = tmp; + } + if (y1 > y2) { + pcb_coord_t tmp = y1; + y1 = y2; + y2 = tmp; + } + if (Vx(x1) < 0) + x1 += grd; + if (Vy(y1) < 0) + y1 += grd; + if (Vx(x2) >= gport->view.canvas_width) + x2 -= grd; + if (Vy(y2) >= gport->view.canvas_height) + y2 -= grd; + + + n = (x2 - x1) / grd + 1; + if (n > npoints) { + npoints = n + 10; + points = (GdkPoint *) realloc(points, npoints * sizeof(GdkPoint)); + } + n = 0; + for (x = x1; x <= x2; x += grd) { + points[n].x = Vx(x); + n++; + } + if (n == 0) + return; + for (y = y1; y <= y2; y += grd) { + int vy = Vy(y); + for (i = 0; i < n; i++) + points[i].y = vy; + gdk_draw_points(priv->out_pixel, priv->grid_gc, points, n); + } +} + +static void ghid_gdk_draw_grid_local_(pcb_coord_t cx, pcb_coord_t cy, int radius) +{ + render_priv_t *priv = gport->render_priv; + static GdkPoint *points_base = NULL; + static GdkPoint *points_abs = NULL; + static int apoints = 0, npoints = 0, old_radius = 0; + static pcb_coord_t last_grid = 0; + int recalc = 0, n, r2; + pcb_coord_t x, y; + + /* PI is approximated with 3.25 here - allows a minimal overallocation, speeds up calculations */ + r2 = radius * radius; + n = r2 * 3 + r2 / 4 + 1; + if (n > apoints) { + apoints = n; + points_base = (GdkPoint *) realloc(points_base, apoints * sizeof(GdkPoint)); + points_abs = (GdkPoint *) realloc(points_abs, apoints * sizeof(GdkPoint)); + } + + if (radius != old_radius) { + old_radius = radius; + recalc = 1; + } + + if (last_grid != PCB->Grid) { + last_grid = PCB->Grid; + recalc = 1; + } + + /* reclaculate the 'filled circle' mask (base relative coords) if grid or radius changed */ + if (recalc) { + + npoints = 0; + for(y = -radius; y <= radius; y++) { + int y2 = y*y; + for(x = -radius; x <= radius; x++) { + if (x*x + y2 < r2) { + points_base[npoints].x = x*PCB->Grid; + points_base[npoints].y = y*PCB->Grid; + npoints++; + } + } + } + } + + /* calculate absolute positions */ + for(n = 0; n < npoints; n++) { + points_abs[n].x = Vx(points_base[n].x + cx); + points_abs[n].y = Vy(points_base[n].y + cy); + } + + gdk_draw_points(priv->out_pixel, priv->grid_gc, points_abs, npoints); +} + + +static int grid_local_have_old = 0, grid_local_old_r = 0; +static pcb_coord_t grid_local_old_x, grid_local_old_y; + +static void ghid_gdk_draw_grid_local(pcb_coord_t cx, pcb_coord_t cy) +{ + if (grid_local_have_old) { + ghid_gdk_draw_grid_local_(grid_local_old_x, grid_local_old_y, grid_local_old_r); + grid_local_have_old = 0; + } + + if (!conf_hid_gtk.plugins.hid_gtk.local_grid.enable) + return; + + if ((Vz(PCB->Grid) < PCB_MIN_GRID_DISTANCE) || (!conf_core.editor.draw_grid)) + return; + + /* cx and cy are the actual cursor snapped to wherever - round them to the nearest real grid point */ + cx = (cx / PCB->Grid) * PCB->Grid + PCB->GridOffsetX; + cy = (cy / PCB->Grid) * PCB->Grid + PCB->GridOffsetY; + + grid_local_have_old = 1; + ghid_gdk_draw_grid_local_(cx, cy, conf_hid_gtk.plugins.hid_gtk.local_grid.radius); + grid_local_old_x = cx; + grid_local_old_y = cy; + grid_local_old_r = conf_hid_gtk.plugins.hid_gtk.local_grid.radius; +} + +static void ghid_gdk_draw_grid(void) +{ + static GdkColormap *colormap = NULL; + render_priv_t *priv = gport->render_priv; + + grid_local_have_old = 0; + + if (!conf_core.editor.draw_grid) + return; + if (colormap == NULL) + colormap = gtk_widget_get_colormap(gport->top_window); + + if (!priv->grid_gc) { + if (gdk_color_parse(conf_core.appearance.color.grid.str, &priv->grid_color)) { + priv->grid_color.red ^= priv->bg_color.red; + priv->grid_color.green ^= priv->bg_color.green; + priv->grid_color.blue ^= priv->bg_color.blue; + gdk_color_alloc(colormap, &priv->grid_color); + } + priv->grid_gc = gdk_gc_new(priv->out_pixel); + gdk_gc_set_function(priv->grid_gc, GDK_XOR); + gdk_gc_set_foreground(priv->grid_gc, &priv->grid_color); + gdk_gc_set_clip_origin(priv->grid_gc, 0, 0); + set_clip(priv, priv->grid_gc); + } + + if (conf_hid_gtk.plugins.hid_gtk.local_grid.enable) { + ghid_gdk_draw_grid_local(grid_local_old_x, grid_local_old_y); + return; + } + + ghid_gdk_draw_grid_global(); +} + +/* ------------------------------------------------------------ */ +static void ghid_gdk_draw_bg_image(void) +{ + static GdkPixbuf *pixbuf; + GdkInterpType interp_type; + gint src_x, src_y, dst_x, dst_y, w, h, w_src, h_src; + static gint w_scaled, h_scaled; + render_priv_t *priv = gport->render_priv; + + if (!ghidgui->bg_pixbuf) + return; + + src_x = gport->view.x0; + src_y = gport->view.y0; + dst_x = 0; + dst_y = 0; + + if (src_x < 0) { + dst_x = -src_x; + src_x = 0; + } + if (src_y < 0) { + dst_y = -src_y; + src_y = 0; + } + + w = PCB->MaxWidth / gport->view.coord_per_px; + h = PCB->MaxHeight / gport->view.coord_per_px; + src_x = src_x / gport->view.coord_per_px; + src_y = src_y / gport->view.coord_per_px; + dst_x = dst_x / gport->view.coord_per_px; + dst_y = dst_y / gport->view.coord_per_px; + + if (w_scaled != w || h_scaled != h) { + if (pixbuf) + g_object_unref(G_OBJECT(pixbuf)); + + w_src = gdk_pixbuf_get_width(ghidgui->bg_pixbuf); + h_src = gdk_pixbuf_get_height(ghidgui->bg_pixbuf); + if (w > w_src && h > h_src) + interp_type = GDK_INTERP_NEAREST; + else + interp_type = GDK_INTERP_BILINEAR; + + pixbuf = gdk_pixbuf_scale_simple(ghidgui->bg_pixbuf, w, h, interp_type); + w_scaled = w; + h_scaled = h; + } + + if (pixbuf) + gdk_pixbuf_render_to_drawable(pixbuf, priv->out_pixel, priv->bg_gc, src_x, src_y, dst_x, dst_y, w - src_x, h - src_y, GDK_RGB_DITHER_NORMAL, 0, 0); +} + +static pcb_composite_op_t curr_drawing_mode; + +static void ghid_sketch_setup(render_priv_t *priv) +{ + if (priv->sketch_pixel == NULL) + priv->sketch_pixel = gdk_pixmap_new(gtk_widget_get_window(gport->drawing_area), gport->view.canvas_width, gport->view.canvas_height, -1); + if (priv->sketch_clip == NULL) + priv->sketch_clip = gdk_pixmap_new(0, gport->view.canvas_width, gport->view.canvas_height, 1); + + priv->out_pixel = priv->sketch_pixel; + priv->out_clip = priv->sketch_clip; +} + +static void ghid_gdk_set_drawing_mode(pcb_composite_op_t op, pcb_bool direct, const pcb_box_t *screen) +{ + render_priv_t *priv = gport->render_priv; + + if (!priv->base_pixel) { + abort(); + return; + } + + priv->direct = direct; + + if (direct) { + priv->out_pixel = priv->base_pixel; + priv->out_clip = NULL; + curr_drawing_mode = PCB_HID_COMP_POSITIVE; + return; + } + + switch(op) { + case PCB_HID_COMP_RESET: + ghid_sketch_setup(priv); + + /* clear the canvas */ + priv->clip_color.pixel = 0; + if (priv->clear_gc == NULL) + priv->clear_gc = gdk_gc_new(priv->out_clip); + gdk_gc_set_foreground(priv->clear_gc, &priv->clip_color); + set_clip(priv, priv->clear_gc); + gdk_draw_rectangle(priv->out_clip, priv->clear_gc, TRUE, 0, 0, gport->view.canvas_width, gport->view.canvas_height); + break; + + case PCB_HID_COMP_POSITIVE: + case PCB_HID_COMP_POSITIVE_XOR: + priv->clip_color.pixel = 1; + break; + + case PCB_HID_COMP_NEGATIVE: + priv->clip_color.pixel = 0; + break; + + case PCB_HID_COMP_FLUSH: + if (priv->copy_gc == NULL) + priv->copy_gc = gdk_gc_new(priv->out_pixel); + gdk_gc_set_clip_mask(priv->copy_gc, priv->sketch_clip); + gdk_gc_set_clip_origin(priv->copy_gc, 0, 0); + gdk_draw_drawable(priv->base_pixel, priv->copy_gc, priv->sketch_pixel, 0, 0, 0, 0, gport->view.canvas_width, gport->view.canvas_height); + + priv->out_pixel = priv->base_pixel; + priv->out_clip = NULL; + break; + } + curr_drawing_mode = op; +} + +static void ghid_gdk_render_burst(pcb_burst_op_t op, const pcb_box_t *screen) +{ + pcb_gui->coord_per_pix = gport->view.coord_per_px; +} + +typedef struct { + int color_set; + GdkColor color; + int xor_set; + GdkColor xor_color; +} ColorCache; + + + /* Config helper functions for when the user changes color preferences. + | set_special colors used in the gtkhid. + */ +static void set_special_grid_color(void) +{ + render_priv_t *priv = gport->render_priv; + + /* The color grid is combined with background color */ + map_color_string(conf_core.appearance.color.grid.str, &priv->grid_color); + priv->grid_color.red = (priv->grid_color.red ^ priv->bg_color.red) & 0xFF; + priv->grid_color.green = (priv->grid_color.green ^ priv->bg_color.green) & 0xFF; + priv->grid_color.blue = (priv->grid_color.blue ^ priv->bg_color.blue) & 0xFF; + + if (priv->grid_gc) + gdk_gc_set_foreground(priv->grid_gc, &priv->grid_color); +} + +static void ghid_gdk_set_special_colors(conf_native_t *cfg) +{ + render_priv_t *priv = gport->render_priv; + + if (((CFT_COLOR *)cfg->val.color == &conf_core.appearance.color.background) && priv->bg_gc) { + if (map_color_string(cfg->val.color[0].str, &priv->bg_color)) { + gdk_gc_set_foreground(priv->bg_gc, &priv->bg_color); + set_special_grid_color(); + } + } + else if (((CFT_COLOR *)cfg->val.color == &conf_core.appearance.color.off_limit) && priv->offlimits_gc) { + if (map_color_string(cfg->val.color[0].str, &priv->offlimits_color)) + gdk_gc_set_foreground(priv->offlimits_gc, &priv->offlimits_color); + } + else if (((CFT_COLOR *)cfg->val.color == &conf_core.appearance.color.grid) && priv->grid_gc) { + if (map_color_string(cfg->val.color[0].str, &priv->grid_color)) + set_special_grid_color(); + } +} + +static void ghid_gdk_set_color(pcb_hid_gc_t gc, const pcb_color_t *color) +{ + static void *cache = 0; + static GdkColormap *colormap = NULL; + render_priv_t *priv = gport->render_priv; + pcb_hidval_t cval; + const char *name = color->str; + + if (name == NULL) { + fprintf(stderr, "ghid_gdk_set_color(): name = NULL, setting to magenta\n"); + name = "magenta"; + } + + gc->pcolor = *color; + + if (!gc->pixel_gc) + return; + if (colormap == NULL) + colormap = gtk_widget_get_colormap(gport->top_window); + + if (pcb_color_is_drill(color)) { + gdk_gc_set_foreground(gc->pixel_gc, &priv->offlimits_color); + } + else { + ColorCache *cc; + if (pcb_hid_cache_color(0, name, &cval, &cache)) + cc = (ColorCache *) cval.ptr; + else { + cc = (ColorCache *) malloc(sizeof(ColorCache)); + memset(cc, 0, sizeof(*cc)); + cval.ptr = cc; + pcb_hid_cache_color(1, name, &cval, &cache); + } + + if (!cc->color_set) { + if (gdk_color_parse(name, &cc->color)) + gdk_color_alloc(colormap, &cc->color); + else + gdk_color_white(colormap, &cc->color); + cc->color_set = 1; + } + if (gc->xor_mask) { + if (!cc->xor_set) { + cc->xor_color.red = cc->color.red ^ priv->bg_color.red; + cc->xor_color.green = cc->color.green ^ priv->bg_color.green; + cc->xor_color.blue = cc->color.blue ^ priv->bg_color.blue; + gdk_color_alloc(colormap, &cc->xor_color); + cc->xor_set = 1; + } + gdk_gc_set_foreground(gc->pixel_gc, &cc->xor_color); + } + else { + gdk_gc_set_foreground(gc->pixel_gc, &cc->color); + } + } +} + +static void ghid_gdk_set_line_cap(pcb_hid_gc_t gc, pcb_cap_style_t style) +{ + switch (style) { + case pcb_cap_round: + gc->cap = GDK_CAP_ROUND; + gc->join = GDK_JOIN_ROUND; + break; + case pcb_cap_square: + gc->cap = GDK_CAP_PROJECTING; + gc->join = GDK_JOIN_MITER; + break; + default: + assert(!"unhandled cap"); + gc->cap = GDK_CAP_ROUND; + gc->join = GDK_JOIN_ROUND; + } + if (gc->pixel_gc) + gdk_gc_set_line_attributes(gc->pixel_gc, Vz(gc->width), GDK_LINE_SOLID, (GdkCapStyle) gc->cap, (GdkJoinStyle) gc->join); +} + +static void ghid_gdk_set_line_width(pcb_hid_gc_t gc, pcb_coord_t width) +{ + /* If width is negative then treat it as pixel width, otherwise it is world coordinates. */ + if(width < 0) { + gc->width = -width; + width = -width; + } + else { + gc->width = width; + width = Vz(width); + } + + if (gc->pixel_gc) + gdk_gc_set_line_attributes(gc->pixel_gc, width, GDK_LINE_SOLID, (GdkCapStyle) gc->cap, (GdkJoinStyle) gc->join); + if (gc->clip_gc) + gdk_gc_set_line_attributes(gc->clip_gc, width, GDK_LINE_SOLID, (GdkCapStyle) gc->cap, (GdkJoinStyle) gc->join); +} + +static void ghid_gdk_set_draw_xor(pcb_hid_gc_t gc, int xor_mask) +{ + render_priv_t *priv = gport->render_priv; + + gc->xor_mask = xor_mask; + if (gc->pixel_gc != NULL) + gdk_gc_set_function(gc->pixel_gc, xor_mask ? GDK_XOR : GDK_COPY); + if (gc->clip_gc != NULL) + gdk_gc_set_function(gc->clip_gc, xor_mask ? GDK_XOR : GDK_COPY); + ghid_gdk_set_color(gc, &gc->pcolor); + + /* If not in direct mode then select the correct drawables so that the sketch and clip + * drawables are not drawn to in XOR mode */ + if (!priv->direct) { + /* If xor mode then draw directly to the base drawable */ + if (xor_mask) { + priv->out_pixel = priv->base_pixel; + priv->out_clip = NULL; + } + else /* If not in direct mode then draw to the sketch and clip drawables */ + ghid_sketch_setup(priv); + } +} + +static int use_gc(pcb_hid_gc_t gc, int need_pen) +{ + render_priv_t *priv = gport->render_priv; + GdkWindow *window = gtk_widget_get_window(gport->top_window); + int need_setup = 0; + + assert((curr_drawing_mode == PCB_HID_COMP_POSITIVE) || (curr_drawing_mode == PCB_HID_COMP_POSITIVE_XOR) || (curr_drawing_mode == PCB_HID_COMP_NEGATIVE)); + + if (gc->me_pointer != >k2_gdk_hid) { + fprintf(stderr, "Fatal: GC from another HID passed to GTK HID\n"); + abort(); + } + + if (!priv->base_pixel) + return 0; + + if ((!gc->clip_gc) && (priv->out_clip != NULL)) { + gc->clip_gc = gdk_gc_new(priv->out_clip); + need_setup = 1; + } + + if (!gc->pixel_gc) { + gc->pixel_gc = gdk_gc_new(window); + need_setup = 1; + } + + if (need_setup) { + ghid_gdk_set_color(gc, &gc->pcolor); + ghid_gdk_set_line_width(gc, gc->core_gc.width); + if ((need_pen) || (gc->core_gc.cap != pcb_cap_invalid)) + ghid_gdk_set_line_cap(gc, (pcb_cap_style_t) gc->core_gc.cap); + ghid_gdk_set_draw_xor(gc, gc->xor_mask); + gdk_gc_set_clip_origin(gc->pixel_gc, 0, 0); + } + + if (priv->out_clip != NULL) + gdk_gc_set_foreground(gc->clip_gc, &priv->clip_color); + + priv->pixel_gc = gc->pixel_gc; + priv->clip_gc = gc->clip_gc; + return 1; +} + +static void ghid_gdk_draw_line(pcb_hid_gc_t gc, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2) +{ + double dx1, dy1, dx2, dy2; + render_priv_t *priv = gport->render_priv; + + assert((curr_drawing_mode == PCB_HID_COMP_POSITIVE) || (curr_drawing_mode == PCB_HID_COMP_POSITIVE_XOR) || (curr_drawing_mode == PCB_HID_COMP_NEGATIVE)); + + dx1 = Vx((double) x1); + dy1 = Vy((double) y1); + + /* optimization: draw a single dot if object is too small */ + if ((gc->core_gc.width > 0) && (pcb_gtk_1dot(gc->width, x1, y1, x2, y2))) { + if (pcb_gtk_dot_in_canvas(gc->width, dx1, dy1)) { + USE_GC(gc); + gdk_draw_point(priv->out_pixel, priv->pixel_gc, dx1, dy1); + if (priv->out_clip != NULL) + gdk_draw_point(priv->out_clip, priv->clip_gc, dx1, dy1); + } + return; + } + + dx2 = Vx((double) x2); + dy2 = Vy((double) y2); + + if (!pcb_line_clip(0, 0, gport->view.canvas_width, gport->view.canvas_height, &dx1, &dy1, &dx2, &dy2, gc->width / gport->view.coord_per_px)) + return; + + USE_GC(gc); + gdk_draw_line(priv->out_pixel, priv->pixel_gc, dx1, dy1, dx2, dy2); + + if (priv->out_clip != NULL) + gdk_draw_line(priv->out_clip, priv->clip_gc, dx1, dy1, dx2, dy2); +} + +static void ghid_gdk_draw_arc(pcb_hid_gc_t gc, pcb_coord_t cx, pcb_coord_t cy, pcb_coord_t xradius, pcb_coord_t yradius, pcb_angle_t start_angle, pcb_angle_t delta_angle) +{ + gint vrx2, vry2; + double w, h, radius; + render_priv_t *priv = gport->render_priv; + + assert((curr_drawing_mode == PCB_HID_COMP_POSITIVE) || (curr_drawing_mode == PCB_HID_COMP_POSITIVE_XOR) || (curr_drawing_mode == PCB_HID_COMP_NEGATIVE)); + + w = gport->view.canvas_width * gport->view.coord_per_px; + h = gport->view.canvas_height * gport->view.coord_per_px; + radius = (xradius > yradius) ? xradius : yradius; + if (SIDE_X(cx) < gport->view.x0 - radius + || SIDE_X(cx) > gport->view.x0 + w + radius + || SIDE_Y(cy) < gport->view.y0 - radius || SIDE_Y(cy) > gport->view.y0 + h + radius) + return; + + USE_GC(gc); + vrx2 = Vz(xradius*2.0); + vry2 = Vz(yradius*2.0); + + if ((delta_angle > 360.0) || (delta_angle < -360.0)) { + start_angle = 0; + delta_angle = 360; + } + + if (conf_core.editor.view.flip_x) { + start_angle = 180 - start_angle; + delta_angle = -delta_angle; + } + if (conf_core.editor.view.flip_y) { + start_angle = -start_angle; + delta_angle = -delta_angle; + } + /* make sure we fall in the -180 to +180 range */ + start_angle = pcb_normalize_angle(start_angle); + if (start_angle >= 180) + start_angle -= 360; + + gdk_draw_arc(priv->out_pixel, priv->pixel_gc, 0, + pcb_round(Vxd(cx) - Vzd(xradius) + 0.5), pcb_round(Vyd(cy) - Vzd(yradius) + 0.5), + pcb_round(vrx2), pcb_round(vry2), + (start_angle + 180) * 64, delta_angle * 64); + + if (priv->out_clip != NULL) + gdk_draw_arc(priv->out_clip, priv->clip_gc, 0, + pcb_round(Vxd(cx) - Vzd(xradius) + 0.5), pcb_round(Vyd(cy) - Vzd(yradius) + 0.5), + pcb_round(vrx2), pcb_round(vry2), + (start_angle + 180) * 64, delta_angle * 64); +} + +static void ghid_gdk_draw_rect(pcb_hid_gc_t gc, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2) +{ + gint w, h, lw, sx1, sy1; + render_priv_t *priv = gport->render_priv; + + assert((curr_drawing_mode == PCB_HID_COMP_POSITIVE) || (curr_drawing_mode == PCB_HID_COMP_POSITIVE_XOR) || (curr_drawing_mode == PCB_HID_COMP_NEGATIVE)); + + lw = gc->width; + w = gport->view.canvas_width * gport->view.coord_per_px; + h = gport->view.canvas_height * gport->view.coord_per_px; + + if ((SIDE_X(x1) < gport->view.x0 - lw && SIDE_X(x2) < gport->view.x0 - lw) + || (SIDE_X(x1) > gport->view.x0 + w + lw && SIDE_X(x2) > gport->view.x0 + w + lw) + || (SIDE_Y(y1) < gport->view.y0 - lw && SIDE_Y(y2) < gport->view.y0 - lw) + || (SIDE_Y(y1) > gport->view.y0 + h + lw && SIDE_Y(y2) > gport->view.y0 + h + lw)) + return; + + sx1 = Vx(x1); + sy1 = Vy(y1); + + /* optimization: draw a single dot if object is too small */ + if (pcb_gtk_1dot(gc->width, x1, y1, x2, y2)) { + if (pcb_gtk_dot_in_canvas(gc->width, sx1, sy1)) { + USE_GC(gc); + gdk_draw_point(priv->out_pixel, priv->pixel_gc, sx1, sy1); + } + return; + } + + x1 = sx1; + y1 = sy1; + x2 = Vx(x2); + y2 = Vy(y2); + + if (x1 > x2) { + gint xt = x1; + x1 = x2; + x2 = xt; + } + if (y1 > y2) { + gint yt = y1; + y1 = y2; + y2 = yt; + } + + USE_GC(gc); + gdk_draw_rectangle(priv->out_pixel, priv->pixel_gc, FALSE, x1, y1, x2 - x1 + 1, y2 - y1 + 1); + + if (priv->out_clip != NULL) + gdk_draw_rectangle(priv->out_clip, priv->clip_gc, FALSE, x1, y1, x2 - x1 + 1, y2 - y1 + 1); +} + + +static void ghid_gdk_fill_circle(pcb_hid_gc_t gc, pcb_coord_t cx, pcb_coord_t cy, pcb_coord_t radius) +{ + gint w, h, vr; + render_priv_t *priv = gport->render_priv; + + assert((curr_drawing_mode == PCB_HID_COMP_POSITIVE) || (curr_drawing_mode == PCB_HID_COMP_POSITIVE_XOR) || (curr_drawing_mode == PCB_HID_COMP_NEGATIVE)); + + w = gport->view.canvas_width * gport->view.coord_per_px; + h = gport->view.canvas_height * gport->view.coord_per_px; + if (SIDE_X(cx) < gport->view.x0 - radius + || SIDE_X(cx) > gport->view.x0 + w + radius + || SIDE_Y(cy) < gport->view.y0 - radius || SIDE_Y(cy) > gport->view.y0 + h + radius) + return; + + USE_GC(gc); + + /* optimization: draw a single dot if object is too small */ + if (pcb_gtk_1dot(radius*2, cx, cy, cx, cy)) { + pcb_coord_t sx1 = Vx(cx), sy1 = Vy(cy); + if (pcb_gtk_dot_in_canvas(radius*2, sx1, sy1)) { + USE_GC(gc); + gdk_draw_point(priv->out_pixel, priv->pixel_gc, sx1, sy1); + } + return; + } + + vr = Vz(radius); + gdk_draw_arc(priv->out_pixel, priv->pixel_gc, TRUE, Vx(cx) - vr, Vy(cy) - vr, vr * 2, vr * 2, 0, 360 * 64); + + if (priv->out_clip != NULL) + gdk_draw_arc(priv->out_clip, priv->clip_gc, TRUE, Vx(cx) - vr, Vy(cy) - vr, vr * 2, vr * 2, 0, 360 * 64); +} + +/* Decide if a polygon is an axis aligned rectangle; if so, return non-zero + and save the corners in b */ +static int poly_is_aligned_rect(pcb_box_t *b, int n_coords, pcb_coord_t *x, pcb_coord_t *y) +{ + int n, xi1 = 0, yi1 = 0, xi2 = 0, yi2 = 0, xs1 = 0, ys1 = 0, xs2 = 0, ys2 = 0; + if (n_coords != 4) + return 0; + b->X1 = b->Y1 = PCB_MAX_COORD; + b->X2 = b->Y2 = -PCB_MAX_COORD; + for(n = 0; n < 4; n++) { + if (x[n] == b->X1) + xs1++; + else if (x[n] < b->X1) { + b->X1 = x[n]; + xi1++; + } + else if (x[n] == b->X2) + xs2++; + else if (x[n] > b->X2) { + b->X2 = x[n]; + xi2++; + } + else + return 0; + if (y[n] == b->Y1) + ys1++; + else if (y[n] < b->Y1) { + b->Y1 = y[n]; + yi1++; + } + else if (y[n] == b->Y2) + ys2++; + else if (y[n] > b->Y2) { + b->Y2 = y[n]; + yi2++; + } + else + return 0; + } + return (xi1 == 1) && (yi1 == 1) && (xi2 == 1) && (yi2 == 1) && \ + (xs1 == 1) && (ys1 == 1) && (xs2 == 1) && (ys2 == 1); +} + +/* Intentional code duplication for performance */ +static void ghid_gdk_fill_polygon(pcb_hid_gc_t gc, int n_coords, pcb_coord_t * x, pcb_coord_t * y) +{ + pcb_box_t b; + static GdkPoint *points = 0; + static int npoints = 0; + int i, len, sup = 0; + pcb_coord_t lsx, lsy, lastx = PCB_MAX_COORD, lasty = PCB_MAX_COORD, mindist = gport->view.coord_per_px * 2; + + render_priv_t *priv = gport->render_priv; + USE_GC_NOPEN(gc); + + assert((curr_drawing_mode == PCB_HID_COMP_POSITIVE) || (curr_drawing_mode == PCB_HID_COMP_POSITIVE_XOR) || (curr_drawing_mode == PCB_HID_COMP_NEGATIVE)); + + /* optimization: axis aligned rectangles can be drawn cheaper than polygons and they are common because of smd pads */ + if (poly_is_aligned_rect(&b, n_coords, x, y)) { + gint x1 = Vx(b.X1), y1 = Vy(b.Y1), x2 = Vx(b.X2), y2 = Vy(b.Y2), tmp; + + if (x1 > x2) { tmp = x1; x1 = x2; x2 = tmp; } + if (y1 > y2) { tmp = y1; y1 = y2; y2 = tmp; } + gdk_draw_rectangle(priv->out_pixel, priv->pixel_gc, TRUE, x1, y1, x2 - x1, y2 - y1); + if (priv->out_clip != NULL) + gdk_draw_rectangle(priv->out_clip, priv->clip_gc, TRUE, x1, y1, x2 - x1, y2 - y1); + return; + } + + if (npoints < n_coords) { + npoints = n_coords + 1; + points = (GdkPoint *) realloc(points, npoints * sizeof(GdkPoint)); + } + for (len = i = 0; i < n_coords; i++) { + if ((i != n_coords-1) && (PCB_ABS(x[i] - lastx) < mindist) && (PCB_ABS(y[i] - lasty) < mindist)) { + lsx = x[i]; + lsy = y[i]; + sup = 1; + continue; + } + if (sup) { /* before a big jump, make sure to use the accurate coords of the last (suppressed) point of the crowd */ + points[len].x = Vx(lsx); + points[len].y = Vy(lsy); + len++; + sup = 0; + } + points[len].x = Vx(x[i]); + points[len].y = Vy(y[i]); + len++; + lastx = x[i]; + lasty = y[i]; + } + if (len < 3) { + gdk_draw_point(priv->out_pixel, priv->pixel_gc, points[0].x, points[0].y); + if (priv->out_clip != NULL) + gdk_draw_point(priv->out_clip, priv->pixel_gc, points[0].x, points[0].y); + return; + } + gdk_draw_polygon(priv->out_pixel, priv->pixel_gc, 1, points, len); + if (priv->out_clip != NULL) + gdk_draw_polygon(priv->out_clip, priv->clip_gc, 1, points, len); +} + +/* Intentional code duplication for performance */ +static void ghid_gdk_fill_polygon_offs(pcb_hid_gc_t gc, int n_coords, pcb_coord_t *x, pcb_coord_t *y, pcb_coord_t dx, pcb_coord_t dy) +{ + pcb_box_t b; + static GdkPoint *points = 0; + static int npoints = 0; + int i, len, sup = 0; + render_priv_t *priv = gport->render_priv; + pcb_coord_t lsx, lsy, lastx = PCB_MAX_COORD, lasty = PCB_MAX_COORD, mindist = gport->view.coord_per_px * 2; + USE_GC_NOPEN(gc); + + assert((curr_drawing_mode == PCB_HID_COMP_POSITIVE) || (curr_drawing_mode == PCB_HID_COMP_POSITIVE_XOR) || (curr_drawing_mode == PCB_HID_COMP_NEGATIVE)); + + /* optimization: axis aligned rectangles can be drawn cheaper than polygons and they are common because of smd pads */ + if (poly_is_aligned_rect(&b, n_coords, x, y)) { + gint x1 = Vx(b.X1+dx), y1 = Vy(b.Y1+dy), x2 = Vx(b.X2+dx), y2 = Vy(b.Y2+dy), tmp; + + if (x1 > x2) { tmp = x1; x1 = x2; x2 = tmp; } + if (y1 > y2) { tmp = y1; y1 = y2; y2 = tmp; } + gdk_draw_rectangle(priv->out_pixel, priv->pixel_gc, TRUE, x1, y1, x2 - x1, y2 - y1); + if (priv->out_clip != NULL) + gdk_draw_rectangle(priv->out_clip, priv->clip_gc, TRUE, x1, y1, x2 - x1, y2 - y1); + return; + } + + if (npoints < n_coords) { + npoints = n_coords + 1; + points = (GdkPoint *) realloc(points, npoints * sizeof(GdkPoint)); + } + for (len = i = 0; i < n_coords; i++) { + if ((i != n_coords-1) && (PCB_ABS(x[i] - lastx) < mindist) && (PCB_ABS(y[i] - lasty) < mindist)) { + lsx = x[i]; + lsy = y[i]; + sup = 1; + continue; + } + if (sup) { /* before a big jump, make sure to use the accurate coords of the last (suppressed) point of the crowd */ + points[len].x = Vx(lsx+dx); + points[len].y = Vy(lsy+dy); + len++; + sup = 0; + } + points[len].x = Vx(x[i]+dx); + points[len].y = Vy(y[i]+dy); + len++; + lastx = x[i]; + lasty = y[i]; + } + if (len < 3) { + gdk_draw_point(priv->out_pixel, priv->pixel_gc, points[0].x, points[0].y); + if (priv->out_clip != NULL) + gdk_draw_point(priv->out_clip, priv->pixel_gc, points[0].x, points[0].y); + return; + } + gdk_draw_polygon(priv->out_pixel, priv->pixel_gc, 1, points, len); + if (priv->out_clip != NULL) + gdk_draw_polygon(priv->out_clip, priv->clip_gc, 1, points, len); +} + +static void ghid_gdk_fill_rect(pcb_hid_gc_t gc, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2) +{ + gint w, h, lw, xx, yy, sx1, sy1; + render_priv_t *priv = gport->render_priv; + + assert((curr_drawing_mode == PCB_HID_COMP_POSITIVE) || (curr_drawing_mode == PCB_HID_COMP_POSITIVE_XOR) || (curr_drawing_mode == PCB_HID_COMP_NEGATIVE)); + + lw = gc->width; + w = gport->view.canvas_width * gport->view.coord_per_px; + h = gport->view.canvas_height * gport->view.coord_per_px; + + if ((SIDE_X(x1) < gport->view.x0 - lw && SIDE_X(x2) < gport->view.x0 - lw) + || (SIDE_X(x1) > gport->view.x0 + w + lw && SIDE_X(x2) > gport->view.x0 + w + lw) + || (SIDE_Y(y1) < gport->view.y0 - lw && SIDE_Y(y2) < gport->view.y0 - lw) + || (SIDE_Y(y1) > gport->view.y0 + h + lw && SIDE_Y(y2) > gport->view.y0 + h + lw)) + return; + + sx1 = Vx(x1); + sy1 = Vy(y1); + + /* optimization: draw a single dot if object is too small */ + if (pcb_gtk_1dot(gc->width, x1, y1, x2, y2)) { + if (pcb_gtk_dot_in_canvas(gc->width, sx1, sy1)) { + USE_GC_NOPEN(gc); + gdk_draw_point(priv->out_pixel, priv->pixel_gc, sx1, sy1); + } + return; + } + + x1 = sx1; + y1 = sy1; + x2 = Vx(x2); + y2 = Vy(y2); + if (x2 < x1) { + xx = x1; + x1 = x2; + x2 = xx; + } + if (y2 < y1) { + yy = y1; + y1 = y2; + y2 = yy; + } + USE_GC(gc); + gdk_draw_rectangle(priv->out_pixel, priv->pixel_gc, TRUE, x1, y1, x2 - x1 + 1, y2 - y1 + 1); + + if (priv->out_clip != NULL) + gdk_draw_rectangle(priv->out_clip, priv->clip_gc, TRUE, x1, y1, x2 - x1 + 1, y2 - y1 + 1); +} + +static void redraw_region(GdkRectangle * rect) +{ + int eleft, eright, etop, ebottom; + pcb_hid_expose_ctx_t ctx; + render_priv_t *priv = gport->render_priv; + + if (!priv->base_pixel) + return; + + if (rect != NULL) { + priv->clip_rect = *rect; + priv->clip_rect_valid = pcb_true; + } + else { + priv->clip_rect.x = 0; + priv->clip_rect.y = 0; + priv->clip_rect.width = gport->view.canvas_width; + priv->clip_rect.height = gport->view.canvas_height; + priv->clip_rect_valid = pcb_false; + } + + set_clip(priv, priv->bg_gc); + set_clip(priv, priv->offlimits_gc); + set_clip(priv, priv->grid_gc); + + ctx.view.X1 = MIN(Px(priv->clip_rect.x), Px(priv->clip_rect.x + priv->clip_rect.width + 1)); + ctx.view.Y1 = MIN(Py(priv->clip_rect.y), Py(priv->clip_rect.y + priv->clip_rect.height + 1)); + ctx.view.X2 = MAX(Px(priv->clip_rect.x), Px(priv->clip_rect.x + priv->clip_rect.width + 1)); + ctx.view.Y2 = MAX(Py(priv->clip_rect.y), Py(priv->clip_rect.y + priv->clip_rect.height + 1)); + + ctx.view.X1 = MAX(0, MIN(PCB->MaxWidth, ctx.view.X1)); + ctx.view.X2 = MAX(0, MIN(PCB->MaxWidth, ctx.view.X2)); + ctx.view.Y1 = MAX(0, MIN(PCB->MaxHeight, ctx.view.Y1)); + ctx.view.Y2 = MAX(0, MIN(PCB->MaxHeight, ctx.view.Y2)); + + eleft = Vx(0); + eright = Vx(PCB->MaxWidth); + etop = Vy(0); + ebottom = Vy(PCB->MaxHeight); + if (eleft > eright) { + int tmp = eleft; + eleft = eright; + eright = tmp; + } + if (etop > ebottom) { + int tmp = etop; + etop = ebottom; + ebottom = tmp; + } + + if (eleft > 0) + gdk_draw_rectangle(priv->out_pixel, priv->offlimits_gc, 1, 0, 0, eleft, gport->view.canvas_height); + else + eleft = 0; + if (eright < gport->view.canvas_width) + gdk_draw_rectangle(priv->out_pixel, priv->offlimits_gc, 1, eright, 0, gport->view.canvas_width - eright, gport->view.canvas_height); + else + eright = gport->view.canvas_width; + if (etop > 0) + gdk_draw_rectangle(priv->out_pixel, priv->offlimits_gc, 1, eleft, 0, eright - eleft + 1, etop); + else + etop = 0; + if (ebottom < gport->view.canvas_height) + gdk_draw_rectangle(priv->out_pixel, priv->offlimits_gc, 1, eleft, ebottom, eright - eleft + 1, gport->view.canvas_height - ebottom); + else + ebottom = gport->view.canvas_height; + + gdk_draw_rectangle(priv->out_pixel, priv->bg_gc, 1, eleft, etop, eright - eleft + 1, ebottom - etop + 1); + + ghid_gdk_draw_bg_image(); + + pcb_hid_expose_all(>k2_gdk_hid, &ctx, NULL); + ghid_gdk_draw_grid(); + + /* In some cases we are called with the crosshair still off */ + if (priv->attached_invalidate_depth == 0) + pcb_draw_attached(0); + + /* In some cases we are called with the mark still off */ + if (priv->mark_invalidate_depth == 0) + pcb_draw_mark(0); + + priv->clip_rect_valid = pcb_false; + + /* Rest the clip for bg_gc, as it is used outside this function */ + gdk_gc_set_clip_mask(priv->bg_gc, NULL); +} + +static void ghid_gdk_invalidate_lr(pcb_coord_t left, pcb_coord_t right, pcb_coord_t top, pcb_coord_t bottom) +{ + int dleft, dright, dtop, dbottom; + int minx, maxx, miny, maxy; + GdkRectangle rect; + + dleft = Vx(left); + dright = Vx(right); + dtop = Vy(top); + dbottom = Vy(bottom); + + minx = MIN(dleft, dright); + maxx = MAX(dleft, dright); + miny = MIN(dtop, dbottom); + maxy = MAX(dtop, dbottom); + + rect.x = minx; + rect.y = miny; + rect.width = maxx - minx; + rect.height = maxy - miny; + + redraw_region(&rect); + ghid_gdk_screen_update(); +} + + +static void ghid_gdk_invalidate_all() +{ + if (ghidgui && ghidgui->topwin.menu.menu_bar) { + redraw_region(NULL); + ghid_gdk_screen_update(); + } +} + +static void ghid_gdk_notify_crosshair_change(pcb_bool changes_complete) +{ + render_priv_t *priv = gport->render_priv; + + /* We sometimes get called before the GUI is up */ + if (gport->drawing_area == NULL) + return; + + if (changes_complete) + priv->attached_invalidate_depth--; + + assert(priv->attached_invalidate_depth >= 0); + if (priv->attached_invalidate_depth < 0) { + priv->attached_invalidate_depth = 0; + /* A mismatch of changes_complete == pcb_false and == pcb_true notifications + * is not expected to occur, but we will try to handle it gracefully. + * As we know the crosshair will have been shown already, we must + * repaint the entire view to be sure not to leave an artaefact. + */ + ghid_gdk_invalidate_all(); + return; + } + + if (priv->attached_invalidate_depth == 0) + pcb_draw_attached(0); + + if (!changes_complete) { + priv->attached_invalidate_depth++; + } + else if (gport->drawing_area != NULL) { + /* Queue a GTK expose when changes are complete */ + ghid_draw_area_update(gport, NULL); + } +} + +static void ghid_gdk_notify_mark_change(pcb_bool changes_complete) +{ + render_priv_t *priv = gport->render_priv; + + /* We sometimes get called before the GUI is up */ + if (gport->drawing_area == NULL) + return; + + if (changes_complete) + priv->mark_invalidate_depth--; + + if (priv->mark_invalidate_depth < 0) { + priv->mark_invalidate_depth = 0; + /* A mismatch of changes_complete == pcb_false and == pcb_true notifications + * is not expected to occur, but we will try to handle it gracefully. + * As we know the mark will have been shown already, we must + * repaint the entire view to be sure not to leave an artaefact. + */ + ghid_gdk_invalidate_all(); + return; + } + + if (priv->mark_invalidate_depth == 0) + pcb_draw_mark(0); + + if (!changes_complete) { + priv->mark_invalidate_depth++; + } + else if (gport->drawing_area != NULL) { + /* Queue a GTK expose when changes are complete */ + ghid_draw_area_update(gport, NULL); + } +} + +static void draw_right_cross(GdkGC * xor_gc, gint x, gint y) +{ + GdkWindow *window = gtk_widget_get_window(gport->drawing_area); + + gdk_draw_line(window, xor_gc, x, 0, x, gport->view.canvas_height); + gdk_draw_line(window, xor_gc, 0, y, gport->view.canvas_width, y); +} + +static void draw_slanted_cross(GdkGC * xor_gc, gint x, gint y) +{ + GdkWindow *window = gtk_widget_get_window(gport->drawing_area); + gint x0, y0, x1, y1; + + x0 = x + (gport->view.canvas_height - y); + x0 = MAX(0, MIN(x0, gport->view.canvas_width)); + x1 = x - y; + x1 = MAX(0, MIN(x1, gport->view.canvas_width)); + y0 = y + (gport->view.canvas_width - x); + y0 = MAX(0, MIN(y0, gport->view.canvas_height)); + y1 = y - x; + y1 = MAX(0, MIN(y1, gport->view.canvas_height)); + gdk_draw_line(window, xor_gc, x0, y0, x1, y1); + + x0 = x - (gport->view.canvas_height - y); + x0 = MAX(0, MIN(x0, gport->view.canvas_width)); + x1 = x + y; + x1 = MAX(0, MIN(x1, gport->view.canvas_width)); + y0 = y + x; + y0 = MAX(0, MIN(y0, gport->view.canvas_height)); + y1 = y - (gport->view.canvas_width - x); + y1 = MAX(0, MIN(y1, gport->view.canvas_height)); + gdk_draw_line(window, xor_gc, x0, y0, x1, y1); +} + +static void draw_dozen_cross(GdkGC * xor_gc, gint x, gint y) +{ + GdkWindow *window = gtk_widget_get_window(gport->drawing_area); + gint x0, y0, x1, y1; + gdouble tan60 = sqrt(3); + + x0 = x + (gport->view.canvas_height - y) / tan60; + x0 = MAX(0, MIN(x0, gport->view.canvas_width)); + x1 = x - y / tan60; + x1 = MAX(0, MIN(x1, gport->view.canvas_width)); + y0 = y + (gport->view.canvas_width - x) * tan60; + y0 = MAX(0, MIN(y0, gport->view.canvas_height)); + y1 = y - x * tan60; + y1 = MAX(0, MIN(y1, gport->view.canvas_height)); + gdk_draw_line(window, xor_gc, x0, y0, x1, y1); + + x0 = x + (gport->view.canvas_height - y) * tan60; + x0 = MAX(0, MIN(x0, gport->view.canvas_width)); + x1 = x - y * tan60; + x1 = MAX(0, MIN(x1, gport->view.canvas_width)); + y0 = y + (gport->view.canvas_width - x) / tan60; + y0 = MAX(0, MIN(y0, gport->view.canvas_height)); + y1 = y - x / tan60; + y1 = MAX(0, MIN(y1, gport->view.canvas_height)); + gdk_draw_line(window, xor_gc, x0, y0, x1, y1); + + x0 = x - (gport->view.canvas_height - y) / tan60; + x0 = MAX(0, MIN(x0, gport->view.canvas_width)); + x1 = x + y / tan60; + x1 = MAX(0, MIN(x1, gport->view.canvas_width)); + y0 = y + x * tan60; + y0 = MAX(0, MIN(y0, gport->view.canvas_height)); + y1 = y - (gport->view.canvas_width - x) * tan60; + y1 = MAX(0, MIN(y1, gport->view.canvas_height)); + gdk_draw_line(window, xor_gc, x0, y0, x1, y1); + + x0 = x - (gport->view.canvas_height - y) * tan60; + x0 = MAX(0, MIN(x0, gport->view.canvas_width)); + x1 = x + y * tan60; + x1 = MAX(0, MIN(x1, gport->view.canvas_width)); + y0 = y + x / tan60; + y0 = MAX(0, MIN(y0, gport->view.canvas_height)); + y1 = y - (gport->view.canvas_width - x) / tan60; + y1 = MAX(0, MIN(y1, gport->view.canvas_height)); + gdk_draw_line(window, xor_gc, x0, y0, x1, y1); +} + +static void draw_crosshair(GdkGC * xor_gc, gint x, gint y) +{ + static enum pcb_crosshair_shape_e prev = pcb_ch_shape_basic; + + draw_right_cross(xor_gc, x, y); + if (prev == pcb_ch_shape_union_jack) + draw_slanted_cross(xor_gc, x, y); + if (prev == pcb_ch_shape_dozen) + draw_dozen_cross(xor_gc, x, y); + prev = pcb_crosshair.shape; +} + +static void show_crosshair(gboolean paint_new_location) +{ + render_priv_t *priv = gport->render_priv; + GdkWindow *window = gtk_widget_get_window(gport->drawing_area); + GtkStyle *style = gtk_widget_get_style(gport->drawing_area); + gint x, y; + static gint x_prev = -1, y_prev = -1; + static GdkGC *xor_gc; + static GdkColor cross_color; + + if (gport->view.crosshair_x < 0 || !ghidgui->topwin.active || !gport->view.has_entered) { + x_prev = y_prev = -1; /* if leaving the drawing area, invalidate last known coord to make sure we redraw on reenter, even on the same coords */ + return; + } + + if (!xor_gc) { + xor_gc = gdk_gc_new(window); + gdk_gc_copy(xor_gc, style->white_gc); + gdk_gc_set_function(xor_gc, GDK_XOR); + gdk_gc_set_clip_origin(xor_gc, 0, 0); + set_clip(priv, xor_gc); + /* FIXME: when CrossColor changed from config */ + map_color_string(conf_core.appearance.color.cross.str, &cross_color); + } + x = Vx(gport->view.crosshair_x); + y = Vy(gport->view.crosshair_y); + + gdk_gc_set_foreground(xor_gc, &cross_color); + + if (x_prev >= 0 && !paint_new_location) + draw_crosshair(xor_gc, x_prev, y_prev); + + if (x >= 0 && paint_new_location) { + draw_crosshair(xor_gc, x, y); + x_prev = x; + y_prev = y; + } + else + x_prev = y_prev = -1; +} + +static void ghid_gdk_init_renderer(int *argc, char ***argv, void *vport) +{ + GHidPort *port = vport; + /* Init any GC's required */ + port->render_priv = g_new0(render_priv_t, 1); +} + +static void ghid_gdk_shutdown_renderer(void *vport) +{ + GHidPort *port = vport; + g_free(port->render_priv); + port->render_priv = NULL; +} + +static void ghid_gdk_init_drawing_widget(GtkWidget * widget, void * port) +{ +} + +static void ghid_gdk_drawing_area_configure_hook(void *vport) +{ + GHidPort *port = vport; + static int done_once = 0; + render_priv_t *priv = port->render_priv; + + if (priv->base_pixel) + gdk_pixmap_unref(priv->base_pixel); + + priv->base_pixel = gdk_pixmap_new(gtk_widget_get_window(gport->drawing_area), + gport->view.canvas_width, gport->view.canvas_height, -1); + priv->out_pixel = priv->base_pixel; + gport->drawing_allowed = pcb_true; + + if (!done_once) { + priv->bg_gc = gdk_gc_new(priv->out_pixel); + if (!map_color_string(conf_core.appearance.color.background.str, &priv->bg_color)) + map_color_string("white", &priv->bg_color); + gdk_gc_set_foreground(priv->bg_gc, &priv->bg_color); + gdk_gc_set_clip_origin(priv->bg_gc, 0, 0); + + priv->offlimits_gc = gdk_gc_new(priv->out_pixel); + if (!map_color_string(conf_core.appearance.color.off_limit.str, &priv->offlimits_color)) + map_color_string("white", &priv->offlimits_color); + gdk_gc_set_foreground(priv->offlimits_gc, &priv->offlimits_color); + gdk_gc_set_clip_origin(priv->offlimits_gc, 0, 0); + done_once = 1; + } + + if (priv->sketch_pixel) { + gdk_pixmap_unref(priv->sketch_pixel); + priv->sketch_pixel = gdk_pixmap_new(gtk_widget_get_window(gport->drawing_area), port->view.canvas_width, port->view.canvas_height, -1); + } + if (priv->sketch_clip) { + gdk_pixmap_unref(priv->sketch_clip); + priv->sketch_clip = gdk_pixmap_new(0, port->view.canvas_width, port->view.canvas_height, 1); + } +} + +static void ghid_gdk_screen_update(void) +{ + render_priv_t *priv = gport->render_priv; + GdkWindow *window = gtk_widget_get_window(gport->drawing_area); + + if (priv->base_pixel == NULL) + return; + + gdk_draw_drawable(window, priv->bg_gc, priv->base_pixel, 0, 0, 0, 0, gport->view.canvas_width, gport->view.canvas_height); + show_crosshair(TRUE); +} + +static gboolean ghid_gdk_drawing_area_expose_cb(GtkWidget * widget, pcb_gtk_expose_t *ev, void *vport) +{ + GHidPort *port = vport; + render_priv_t *priv = port->render_priv; + GdkWindow *window = gtk_widget_get_window(gport->drawing_area); + + gdk_draw_drawable(window, priv->bg_gc, priv->base_pixel, + ev->area.x, ev->area.y, ev->area.x, ev->area.y, ev->area.width, ev->area.height); + show_crosshair(TRUE); + return FALSE; +} + +static void ghid_gdk_port_drawing_realize_cb(GtkWidget * widget, gpointer data) +{ +} + +static gboolean ghid_gdk_preview_expose(GtkWidget * widget, pcb_gtk_expose_t *ev, pcb_hid_expose_t expcall, pcb_hid_expose_ctx_t *ctx) +{ + GdkWindow *window = gtk_widget_get_window(widget); + GdkDrawable *save_drawable; + GtkAllocation allocation; + pcb_gtk_view_t save_view; + int save_width, save_height; + double xz, yz, vw, vh; + render_priv_t *priv = gport->render_priv; + pcb_coord_t ox1 = ctx->view.X1, oy1 = ctx->view.Y1, ox2 = ctx->view.X2, oy2 = ctx->view.Y2; + + vw = ctx->view.X2 - ctx->view.X1; + vh = ctx->view.Y2 - ctx->view.Y1; + + /* Setup drawable and zoom factor for drawing routines + */ + save_drawable = priv->base_pixel; + save_view = gport->view; + save_width = gport->view.canvas_width; + save_height = gport->view.canvas_height; + + gtk_widget_get_allocation(widget, &allocation); + xz = vw / (double)allocation.width; + yz = vh / (double)allocation.height; + if (xz > yz) + gport->view.coord_per_px = xz; + else + gport->view.coord_per_px = yz; + + priv->base_pixel = priv->out_pixel = window; + gport->view.canvas_width = allocation.width; + gport->view.canvas_height = allocation.height; + gport->view.width = allocation.width * gport->view.coord_per_px; + gport->view.height = allocation.height * gport->view.coord_per_px; + gport->view.x0 = (vw - gport->view.width) / 2 + ctx->view.X1; + gport->view.y0 = (vh - gport->view.height) / 2 + ctx->view.Y1; + + /* clear background */ + gdk_draw_rectangle(window, priv->bg_gc, TRUE, 0, 0, allocation.width, allocation.height); + + PCB_GTK_PREVIEW_TUNE_EXTENT(ctx, allocation); + + /* call the drawing routine */ + expcall(>k2_gdk_hid, ctx); + + /* restore the original context and priv */ + ctx->view.X1 = ox1; ctx->view.X2 = ox2; ctx->view.Y1 = oy1; ctx->view.Y2 = oy2; + priv->out_pixel = priv->base_pixel = save_drawable; + gport->view = save_view; + gport->view.canvas_width = save_width; + gport->view.canvas_height = save_height; + + return FALSE; +} + +static GtkWidget *ghid_gdk_new_drawing_widget(pcb_gtk_common_t *common) +{ + GtkWidget *w = gtk_drawing_area_new(); + + g_signal_connect(G_OBJECT(w), "expose_event", G_CALLBACK(common->drawing_area_expose), common->gport); + + return w; +} + + +void ghid_gdk_install(pcb_gtk_common_t *common, pcb_hid_t *hid) +{ + if (common != NULL) { + common->new_drawing_widget = ghid_gdk_new_drawing_widget; + common->init_drawing_widget = ghid_gdk_init_drawing_widget; + common->drawing_realize = ghid_gdk_port_drawing_realize_cb; + common->drawing_area_expose = ghid_gdk_drawing_area_expose_cb; + common->preview_expose = ghid_gdk_preview_expose; + common->invalidate_all = ghid_gdk_invalidate_all; + common->set_special_colors = ghid_gdk_set_special_colors; + common->init_renderer = ghid_gdk_init_renderer; + common->screen_update = ghid_gdk_screen_update; + common->draw_grid_local = ghid_gdk_draw_grid_local; + common->drawing_area_configure_hook = ghid_gdk_drawing_area_configure_hook; + common->shutdown_renderer = ghid_gdk_shutdown_renderer; + common->get_color_name = get_color_name; + common->map_color_string = map_color_string; + } + + if (hid != NULL) { + hid->invalidate_lr = ghid_gdk_invalidate_lr; + hid->invalidate_all = ghid_gdk_invalidate_all; + hid->notify_crosshair_change = ghid_gdk_notify_crosshair_change; + hid->notify_mark_change = ghid_gdk_notify_mark_change; + hid->set_layer_group = ghid_gdk_set_layer_group; + hid->make_gc = ghid_gdk_make_gc; + hid->destroy_gc = ghid_gdk_destroy_gc; + hid->set_drawing_mode = ghid_gdk_set_drawing_mode; + hid->render_burst = ghid_gdk_render_burst; + hid->set_color = ghid_gdk_set_color; + hid->set_line_cap = ghid_gdk_set_line_cap; + hid->set_line_width = ghid_gdk_set_line_width; + hid->set_draw_xor = ghid_gdk_set_draw_xor; + hid->draw_line = ghid_gdk_draw_line; + hid->draw_arc = ghid_gdk_draw_arc; + hid->draw_rect = ghid_gdk_draw_rect; + hid->fill_circle = ghid_gdk_fill_circle; + hid->fill_polygon = ghid_gdk_fill_polygon; + hid->fill_polygon_offs = ghid_gdk_fill_polygon_offs; + hid->fill_rect = ghid_gdk_fill_rect; + } +} Index: tags/2.1.2/src_plugins/hid_gtk2_gdk/gtkhid-main.c =================================================================== --- tags/2.1.2/src_plugins/hid_gtk2_gdk/gtkhid-main.c (nonexistent) +++ tags/2.1.2/src_plugins/hid_gtk2_gdk/gtkhid-main.c (revision 24813) @@ -0,0 +1,67 @@ +#include "config.h" + +#include + +#include "error.h" +#include "pcb-printf.h" +#include "plugins.h" +#include "hid_init.h" +#include "conf_core.h" + +#include "../src_plugins/lib_gtk_common/glue.h" +#include "../src_plugins/lib_gtk_common/lib_gtk_config.h" +#include "../src_plugins/lib_gtk_common/hid_gtk_conf.h" + +#include "../src_plugins/lib_gtk_hid/gui.h" +#include "../src_plugins/lib_gtk_hid/glue_common.h" +#include "../src_plugins/lib_gtk_hid/glue_hid.h" +#include "../src_plugins/lib_gtk_hid/glue_conf.h" +#include "../src_plugins/lib_gtk_hid/glue_event.h" +#include "../src_plugins/lib_gtk_hid/glue_win32.h" +#include "../src_plugins/lib_gtk_hid/common.h" +#include "../src_plugins/lib_gtk_hid/render.h" + +const char *ghid_cookie = "gtk2 hid, gdk"; +const char *ghid_menu_cookie = "gtk2 hid menu, gdk"; + +pcb_hid_t gtk2_gdk_hid; + +int gtk2_gdk_parse_arguments(int *argc, char ***argv) +{ + ghid_gdk_install(&ghidgui->common, NULL); + return gtkhid_parse_arguments(argc, argv); +} + +int pplg_check_ver_hid_gtk2_gdk(int ver_needed) { return 0; } + +void pplg_uninit_hid_gtk2_gdk(void) +{ + pcb_event_unbind_allcookie(ghid_cookie); + conf_hid_unreg(ghid_cookie); + conf_hid_unreg(ghid_menu_cookie); +} + +int pplg_init_hid_gtk2_gdk(void) +{ + PCB_API_CHK_VER; + ghid_win32_init(); + + ghid_glue_hid_init(>k2_gdk_hid); + ghid_glue_common_init(); + + gtk2_gdk_hid.parse_arguments = gtk2_gdk_parse_arguments; + ghid_gdk_install(NULL, >k2_gdk_hid); + + gtk2_gdk_hid.name = "gtk2_gdk"; + gtk2_gdk_hid.description = "Gtk2 - The Gimp Toolkit, with GDK software pixmap rendering"; + + ghidgui->topwin.menu.ghid_menuconf_id = conf_hid_reg(ghid_menu_cookie, NULL); + ghidgui->topwin.menu.confchg_checkbox = ghid_confchg_checkbox; + ghid_conf_regs(ghid_cookie); + + pcb_hid_register_hid(>k2_gdk_hid); + + glue_event_init(ghid_cookie); + + return 0; +} Index: tags/2.1.2/src_plugins/hid_gtk2_gdk/hid_gtk2_gdk.pup =================================================================== --- tags/2.1.2/src_plugins/hid_gtk2_gdk/hid_gtk2_gdk.pup (nonexistent) +++ tags/2.1.2/src_plugins/hid_gtk2_gdk/hid_gtk2_gdk.pup (revision 24813) @@ -0,0 +1,10 @@ +$class hid +$short GTK2 GUI, software render +$long GUI: GTK2 HID with GDK software rendering. +$state works +$package hid-gtk2-gdk +$hidlib 1 +default buildin +dep lib_gtk_common +dep lib_gtk_hid +autoload 1 Index: tags/2.1.2/src_plugins/hid_gtk2_gdk/pcb.rc =================================================================== --- tags/2.1.2/src_plugins/hid_gtk2_gdk/pcb.rc (nonexistent) +++ tags/2.1.2/src_plugins/hid_gtk2_gdk/pcb.rc (revision 24813) @@ -0,0 +1 @@ +1 ICON "pcb_icon.ico" Index: tags/2.1.2/src_plugins/hid_gtk2_gl/Makefile =================================================================== --- tags/2.1.2/src_plugins/hid_gtk2_gl/Makefile (nonexistent) +++ tags/2.1.2/src_plugins/hid_gtk2_gl/Makefile (revision 24813) @@ -0,0 +1,6 @@ +all: + cd ../../src && $(MAKE) mod_hid_gtk2_gl + +clean: + rm *.o *.so 2>/dev/null ; true + Index: tags/2.1.2/src_plugins/hid_gtk2_gl/Plug.tmpasm =================================================================== --- tags/2.1.2/src_plugins/hid_gtk2_gl/Plug.tmpasm (nonexistent) +++ tags/2.1.2/src_plugins/hid_gtk2_gl/Plug.tmpasm (revision 24813) @@ -0,0 +1,19 @@ +put /local/pcb/mod {hid_gtk2_gl} +put /local/pcb/mod/OBJS_C99 [@ + $(PLUGDIR)/hid_gtk2_gl/gtkhid-main.o + $(PLUGDIR)/hid_gtk2_gl/gtkhid-gl.o +@] + +switch /local/pcb/hid_gtk2_gl/controls + case {disable} end; + default + put /local/pcb/mod/CFLAGS [@@/target/libs/gui/gtk2gl/cflags@ @libs/gui/glu/cflags@@] + put /local/pcb/mod/LDFLAGS [@@/target/libs/gui/gtk2gl/ldflags@ @libs/gui/glu/ldflags@@] + end +end + +switch /local/pcb/hid_gtk2_gl/controls + case {buildin} include /local/pcb/tmpasm/buildin; end; + case {plugin} include /local/pcb/tmpasm/plugin; end; + case {disable} include /local/pcb/tmpasm/disable; end; +end Index: tags/2.1.2/src_plugins/hid_gtk2_gl/gtkhid-gl.c =================================================================== --- tags/2.1.2/src_plugins/hid_gtk2_gl/gtkhid-gl.c (nonexistent) +++ tags/2.1.2/src_plugins/hid_gtk2_gl/gtkhid-gl.c (revision 24813) @@ -0,0 +1,1169 @@ +#include "config.h" + +#include + +#include "crosshair.h" +#include "data.h" +#include "draw.h" +#include "layer.h" +#include "hid_draw_helpers.h" +#include "hid_attrib.h" +#include "hid_color.h" +#include "funchash_core.h" + +#include "../src_plugins/lib_hid_common/clip.h" +#include "../src_plugins/lib_gtk_common/hid_gtk_conf.h" +#include "../src_plugins/lib_gtk_common/lib_gtk_config.h" + +#include "../src_plugins/lib_gtk_hid/gui.h" +#include "../src_plugins/lib_gtk_hid/coord_conv.h" +#include "../src_plugins/lib_gtk_hid/render.h" +#include "../src_plugins/lib_gtk_hid/preview_helper.h" + +#include "../src_plugins/lib_hid_gl/opengl.h" +#include "../src_plugins/lib_hid_gl/draw_gl.h" +#include +#include "../src_plugins/lib_hid_gl/hidgl.h" +#include "hid_draw_helpers.h" +#include "../src_plugins/lib_hid_gl/stencil_gl.h" + +#include "../src_plugins/lib_gtk_common/hid_gtk_conf.h" + +#define Z_NEAR 3.0 +extern pcb_hid_t gtk2_gl_hid; + +static pcb_hid_gc_t current_gc = NULL; +/* Sets gport->u_gc to the "right" GC to use (wrt mask or window) +*/ +#define USE_GC(gc) if (!use_gc(gc)) return + +static pcb_coord_t grid_local_x = 0, grid_local_y = 0, grid_local_radius = 0; + +/*static int cur_mask = -1;*/ + +typedef struct render_priv_s { + GdkGLConfig *glconfig; + pcb_gtk_color_t bg_color; + pcb_gtk_color_t offlimits_color; + pcb_gtk_color_t grid_color; + pcb_bool trans_lines; + pcb_bool in_context; + int subcomposite_stencil_bit; + char *current_colorname; + double current_alpha_mult; +} render_priv_t; + + +typedef struct hid_gc_s { + pcb_core_gc_t core_gc; + pcb_hid_t *me_pointer; + + const pcb_color_t *pcolor; + double alpha_mult; + pcb_coord_t width; + gchar xor; +} hid_gc_s; + +void ghid_gl_render_burst(pcb_burst_op_t op, const pcb_box_t *screen) +{ + pcb_gui->coord_per_pix = gport->view.coord_per_px; +} + +static const gchar *get_color_name(pcb_gtk_color_t *color) +{ + static char tmp[16]; + + if (!color) + return "#000000"; + + sprintf(tmp, "#%2.2x%2.2x%2.2x", (color->red >> 8) & 0xff, (color->green >> 8) & 0xff, (color->blue >> 8) & 0xff); + return tmp; +} + +/* Returns TRUE only if color_string has been allocated to color. */ +static pcb_bool map_color_string(const char *color_string, pcb_gtk_color_t *color) +{ + static GdkColormap *colormap = NULL; + GHidPort *out = &ghid_port; + pcb_bool parsed; + + if (!color || !out->top_window) + return FALSE; + if (colormap == NULL) + colormap = gtk_widget_get_colormap(out->top_window); + if (color->red || color->green || color->blue) + gdk_colormap_free_colors(colormap, color, 1); + parsed = gdk_color_parse(color_string, color); + if (parsed) + gdk_color_alloc(colormap, color); + + return parsed; +} + + +#if 0 +static void start_subcomposite(void) +{ + render_priv_t *priv = gport->render_priv; + int stencil_bit; + + /* Flush out any existing geometry to be rendered */ + hidgl_flush_triangles(); + + glEnable(GL_STENCIL_TEST); /* Enable Stencil test */ + glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); /* Stencil pass => replace stencil value (with 1) */ + + stencil_bit = hidgl_assign_clear_stencil_bit(); /* Get a new (clean) bitplane to stencil with */ + glStencilMask(stencil_bit); /* Only write to our subcompositing stencil bitplane */ + glStencilFunc(GL_GREATER, stencil_bit, stencil_bit); /* Pass stencil test if our assigned bit is clear */ + + priv->subcomposite_stencil_bit = stencil_bit; +} + +static void end_subcomposite(void) +{ + render_priv_t *priv = gport->render_priv; + + /* Flush out any existing geometry to be rendered */ + hidgl_flush_triangles(); + + hidgl_return_stencil_bit(priv->subcomposite_stencil_bit); /* Relinquish any bitplane we previously used */ + + glStencilMask(0); + glStencilFunc(GL_ALWAYS, 0, 0); /* Always pass stencil test */ + glDisable(GL_STENCIL_TEST); /* Disable Stencil test */ + + priv->subcomposite_stencil_bit = 0; +} +#endif + +int ghid_gl_set_layer_group(pcb_layergrp_id_t group, const char *purpose, int purpi, pcb_layer_id_t layer, unsigned int flags, int is_empty, pcb_xform_t **xform) +{ + render_priv_t *priv = gport->render_priv; + int idx = group; + + if (idx >= 0 && idx < pcb_max_group(PCB)) { + int n = PCB->LayerGroups.grp[group].len; + for(idx = 0; idx < n - 1; idx++) { + int ni = PCB->LayerGroups.grp[group].lid[idx]; + if (ni >= 0 && ni < pcb_max_layer && PCB->Data->Layer[ni].meta.real.vis) + break; + } + idx = PCB->LayerGroups.grp[group].lid[idx]; + } + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glTranslatef(0.0f, 0.0f, -Z_NEAR); + + glScalef((conf_core.editor.view.flip_x ? -1. : 1.) / gport->view.coord_per_px, (conf_core.editor.view.flip_y ? -1. : 1.) / gport->view.coord_per_px, ((conf_core.editor.view.flip_x == conf_core.editor.view.flip_y) ? 1. : -1.) / gport->view.coord_per_px); + glTranslatef(conf_core.editor.view.flip_x ? gport->view.x0 - PCB->MaxWidth : -gport->view.x0, conf_core.editor.view.flip_y ? gport->view.y0 - PCB->MaxHeight : -gport->view.y0, 0); + + /* Put the renderer into a good state so that any drawing is done in standard mode */ + + drawgl_flush(); + drawgl_reset(); + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + glDisable(GL_STENCIL_TEST); + +/* + end_subcomposite(); + start_subcomposite(); +*/ + priv->trans_lines = pcb_true; + + /* non-virtual layers with group visibility */ + switch (flags & PCB_LYT_ANYTHING) { + case PCB_LYT_MASK: + case PCB_LYT_PASTE: + return (PCB_LAYERFLG_ON_VISIBLE_SIDE(flags) && PCB->LayerGroups.grp[group].vis); + } + + /* normal layers */ + if (idx >= 0 && idx < pcb_max_layer && ((flags & PCB_LYT_ANYTHING) != PCB_LYT_SILK)) { + priv->trans_lines = pcb_true; + return PCB->Data->Layer[idx].meta.real.vis; + } + + if (PCB_LAYER_IS_ASSY(flags, purpi)) + return 0; + + if (PCB_LAYER_IS_CSECT(flags, purpi)) { + /* Opaque draw */ + priv->trans_lines = pcb_false; + /* Disable stencil for cross-section drawing; that code + * relies on overdraw doing the right thing and doesn't + * use layers */ + /*glDisable(GL_STENCIL_TEST); */ + return 0; + } + + /* virtual layers */ + { + if (PCB_LAYER_IS_DRILL(flags, purpi)) + return 1; + + switch (flags & PCB_LYT_ANYTHING) { + case PCB_LYT_INVIS: + return PCB->InvisibleObjectsOn; + case PCB_LYT_SILK: + if (PCB_LAYERFLG_ON_VISIBLE_SIDE(flags)) + return pcb_silk_on(PCB); + return 0; + case PCB_LYT_UI: + return 1; + case PCB_LYT_RAT: + return PCB->RatOn; + } + } + return 0; +} + +static void ghid_gl_end_layer(void) +{ + drawgl_flush(); + drawgl_reset(); +} + +void ghid_gl_destroy_gc(pcb_hid_gc_t gc) +{ + g_free(gc); +} + +pcb_hid_gc_t ghid_gl_make_gc(void) +{ + pcb_hid_gc_t rv; + + rv = g_new0(hid_gc_s, 1); + rv->me_pointer = >k2_gl_hid; + rv->pcolor = &conf_core.appearance.color.background; + rv->alpha_mult = 1.0; + return rv; +} + +void ghid_gl_draw_grid_local(pcb_coord_t cx, pcb_coord_t cy) +{ + /* cx and cy are the actual cursor snapped to wherever - round them to the nearest real grid point */ + grid_local_x = (cx / PCB->Grid) * PCB->Grid + PCB->GridOffsetX; + grid_local_y = (cy / PCB->Grid) * PCB->Grid + PCB->GridOffsetY; + grid_local_radius = conf_hid_gtk.plugins.hid_gtk.local_grid.radius; +} + +static void ghid_gl_draw_grid(pcb_box_t *drawn_area) +{ + render_priv_t *priv = gport->render_priv; + + if ((Vz(PCB->Grid) < PCB_MIN_GRID_DISTANCE) || (!conf_core.editor.draw_grid)) + return; + + glEnable(GL_COLOR_LOGIC_OP); + glLogicOp(GL_XOR); + + glColor3f(priv->grid_color.red / 65535., priv->grid_color.green / 65535., priv->grid_color.blue / 65535.); + + if (conf_hid_gtk.plugins.hid_gtk.local_grid.enable) + hidgl_draw_local_grid(grid_local_x, grid_local_y, grid_local_radius); + else + hidgl_draw_grid(drawn_area); + + glDisable(GL_COLOR_LOGIC_OP); +} + +void pcb_gl_draw_texture(GLuint texture_handle) +{ + glBindTexture(GL_TEXTURE_2D, texture_handle); + + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); + glEnable(GL_TEXTURE_2D); + + /* Render a quad with the background as a texture */ + + glBegin(GL_QUADS); + glTexCoord2d(0., 0.); + glVertex3i(0, 0, 0); + glTexCoord2d(1., 0.); + glVertex3i(PCB->MaxWidth, 0, 0); + glTexCoord2d(1., 1.); + glVertex3i(PCB->MaxWidth, PCB->MaxHeight, 0); + glTexCoord2d(0., 1.); + glVertex3i(0, PCB->MaxHeight, 0); + glEnd(); + + glDisable(GL_TEXTURE_2D); +} + +static void ghid_gl_draw_bg_image(void) +{ + static GLuint texture_handle = 0; + + if (!ghidgui->bg_pixbuf) + return; + + if (texture_handle == 0) { + int width = gdk_pixbuf_get_width(ghidgui->bg_pixbuf); + int height = gdk_pixbuf_get_height(ghidgui->bg_pixbuf); + int rowstride = gdk_pixbuf_get_rowstride(ghidgui->bg_pixbuf); + int bits_per_sample = gdk_pixbuf_get_bits_per_sample(ghidgui->bg_pixbuf); + int n_channels = gdk_pixbuf_get_n_channels(ghidgui->bg_pixbuf); + unsigned char *pixels = gdk_pixbuf_get_pixels(ghidgui->bg_pixbuf); + + g_warn_if_fail(bits_per_sample == 8); + g_warn_if_fail(rowstride == width * n_channels); + + glGenTextures(1, &texture_handle); + glBindTexture(GL_TEXTURE_2D, texture_handle); + + /* XXX: We should probably determine what the maximum texture supported is, + * and if our image is larger, shrink it down using GDK pixbuf routines + * rather than having it fail below. + */ + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, (n_channels == 4) ? GL_RGBA : GL_RGB, GL_UNSIGNED_BYTE, pixels); + } + + pcb_gl_draw_texture(texture_handle); +} + + /* Config helper functions for when the user changes color preferences. + | set_special colors used in the gtkhid. + */ +static void set_special_grid_color(void) +{ + render_priv_t *priv = gport->render_priv; + + priv->grid_color.red ^= priv->bg_color.red; + priv->grid_color.green ^= priv->bg_color.green; + priv->grid_color.blue ^= priv->bg_color.blue; +} + +void ghid_gl_set_special_colors(conf_native_t *cfg) +{ + render_priv_t *priv = gport->render_priv; + + if (((CFT_COLOR *) cfg->val.color == &conf_core.appearance.color.background)) { + if (map_color_string(cfg->val.color[0].str, &priv->bg_color)) + set_special_grid_color(); + } + else if (((CFT_COLOR *) cfg->val.color == &conf_core.appearance.color.grid)) { + if (map_color_string(cfg->val.color[0].str, &priv->grid_color)) + set_special_grid_color(); + } +TODO("set the offlimits color or place a comment here why it is not set; see the gdk version"); +} + +typedef struct { + int color_set; + pcb_gtk_color_t color; + int xor_set; + pcb_gtk_color_t xor_color; + double red; + double green; + double blue; +} ColorCache; + +static void set_gl_color_for_gc(pcb_hid_gc_t gc) +{ + render_priv_t *priv = gport->render_priv; + static void *cache = NULL; + static GdkColormap *colormap = NULL; + pcb_hidval_t cval; + ColorCache *cc; + double r, g, b, a; + + if (gc->pcolor == NULL) { + fprintf(stderr, "set_gl_color_for_gc: gc->colorname = NULL, setting to magenta\n"); + gc->pcolor = pcb_color_magenta; + } + + if (priv->current_colorname != NULL && strcmp(priv->current_colorname, gc->pcolor->str) == 0 && priv->current_alpha_mult == gc->alpha_mult) + return; + + free(priv->current_colorname); + priv->current_colorname = pcb_strdup(gc->pcolor->str); + priv->current_alpha_mult = gc->alpha_mult; + + if (colormap == NULL) + colormap = gtk_widget_get_colormap(gport->top_window); + TODO("color: Do not depend on manual strcmp here - use pcb_color_is_drill()"); + if (pcb_color_is_drill(gc->pcolor)) { + r = priv->offlimits_color.red / 65535.; + g = priv->offlimits_color.green / 65535.; + b = priv->offlimits_color.blue / 65535.; + a = conf_core.appearance.drill_alpha; + } + else { + if (pcb_hid_cache_color(0, gc->pcolor->str, &cval, &cache)) + cc = (ColorCache *) cval.ptr; + else { + cc = (ColorCache *) malloc(sizeof(ColorCache)); + memset(cc, 0, sizeof(*cc)); + cval.ptr = cc; + pcb_hid_cache_color(1, gc->pcolor->str, &cval, &cache); + } + + if (!cc->color_set) { + if (gdk_color_parse(gc->pcolor->str, &cc->color)) + gdk_color_alloc(colormap, &cc->color); + else + gdk_color_white(colormap, &cc->color); + cc->red = cc->color.red / 65535.; + cc->green = cc->color.green / 65535.; + cc->blue = cc->color.blue / 65535.; + cc->color_set = 1; + } + if (gc->xor) { + if (!cc->xor_set) { + cc->xor_color.red = cc->color.red ^ priv->bg_color.red; + cc->xor_color.green = cc->color.green ^ priv->bg_color.green; + cc->xor_color.blue = cc->color.blue ^ priv->bg_color.blue; + gdk_color_alloc(colormap, &cc->xor_color); + cc->red = cc->color.red / 65535.; + cc->green = cc->color.green / 65535.; + cc->blue = cc->color.blue / 65535.; + cc->xor_set = 1; + } + } + r = cc->red; + g = cc->green; + b = cc->blue; + a = conf_core.appearance.layer_alpha; + } + if (1) { + double maxi, mult; + a *= gc->alpha_mult; + if (!priv->trans_lines) + a = 1.0; + maxi = r; + if (g > maxi) + maxi = g; + if (b > maxi) + maxi = b; + mult = MIN(1 / a, 1 / maxi); +#if 1 + r = r * mult; + g = g * mult; + b = b * mult; +#endif + } + + if (!priv->in_context) + return; + + + /* We need to flush the draw buffer when changing colour so that new primitives + * don't get merged. This actually isn't a problem with the colour but due to + * way that the final render pass iterates through the primitive buffer in + * reverse order. If the new primitives are merged with previous ones then they + * will be drawn in the wrong order. + */ + drawgl_flush(); + + drawgl_set_colour(r, g, b, a); +} + +void ghid_gl_set_color(pcb_hid_gc_t gc, const pcb_color_t *color) +{ + if (color == NULL) { + fprintf(stderr, "ghid_gl_set_color(): name = NULL, setting to magenta\n"); + color = pcb_color_magenta; + } + + gc->pcolor = color; + set_gl_color_for_gc(gc); +} + +void ghid_gl_set_alpha_mult(pcb_hid_gc_t gc, double alpha_mult) +{ + gc->alpha_mult = alpha_mult; + set_gl_color_for_gc(gc); +} + +void ghid_gl_set_line_cap(pcb_hid_gc_t gc, pcb_cap_style_t style) +{ +} + +void ghid_gl_set_line_width(pcb_hid_gc_t gc, pcb_coord_t width) +{ + gc->width = width < 0 ? (-width) * gport->view.coord_per_px : width; +} + + +void ghid_gl_set_draw_xor(pcb_hid_gc_t gc, int xor) +{ + /* NOT IMPLEMENTED */ + + /* Only presently called when setting up a crosshair GC. + * We manage our own drawing model for that anyway. */ +} + +void ghid_gl_set_draw_faded(pcb_hid_gc_t gc, int faded) +{ + printf("ghid_gl_set_draw_faded(%p,%d) -- not implemented\n", (void *)gc, faded); +} + +void ghid_gl_set_line_cap_angle(pcb_hid_gc_t gc, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2) +{ + printf("ghid_gl_set_line_cap_angle() -- not implemented\n"); +} + +static void ghid_gl_invalidate_current_gc(void) +{ + current_gc = NULL; +} + +static int use_gc(pcb_hid_gc_t gc) +{ + if (gc->me_pointer != >k2_gl_hid) { + fprintf(stderr, "Fatal: GC from another HID passed to GTK HID\n"); + abort(); + } + + if (current_gc == gc) + return 1; + + current_gc = gc; + + set_gl_color_for_gc(gc); + return 1; +} + + +static void ghid_gl_draw_line(pcb_hid_gc_t gc, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2) +{ + USE_GC(gc); + + hidgl_draw_line(gc->core_gc.cap, gc->width, x1, y1, x2, y2, gport->view.coord_per_px); +} + +static void ghid_gl_draw_arc(pcb_hid_gc_t gc, pcb_coord_t cx, pcb_coord_t cy, pcb_coord_t xradius, pcb_coord_t yradius, pcb_angle_t start_angle, pcb_angle_t delta_angle) +{ + USE_GC(gc); + + hidgl_draw_arc(gc->width, cx, cy, xradius, yradius, start_angle, delta_angle, gport->view.coord_per_px); +} + +static void ghid_gl_draw_rect(pcb_hid_gc_t gc, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2) +{ + USE_GC(gc); + + hidgl_draw_rect(x1, y1, x2, y2); +} + + +static void ghid_gl_fill_circle(pcb_hid_gc_t gc, pcb_coord_t cx, pcb_coord_t cy, pcb_coord_t radius) +{ + USE_GC(gc); + + hidgl_fill_circle(cx, cy, radius, gport->view.coord_per_px); +} + + +static void ghid_gl_fill_polygon(pcb_hid_gc_t gc, int n_coords, pcb_coord_t *x, pcb_coord_t *y) +{ + USE_GC(gc); + + hidgl_fill_polygon(n_coords, x, y); +} + +static void ghid_gl_fill_polygon_offs(pcb_hid_gc_t gc, int n_coords, pcb_coord_t *x, pcb_coord_t *y, pcb_coord_t dx, pcb_coord_t dy) +{ + USE_GC(gc); + + hidgl_fill_polygon_offs(n_coords, x, y, dx, dy); +} + +static void ghid_gl_fill_pcb_polygon(pcb_hid_gc_t gc, pcb_poly_t *poly, const pcb_box_t *clip_box) +{ + USE_GC(gc); + + hidgl_fill_pcb_polygon(poly, clip_box, gport->view.coord_per_px); +} + +static void ghid_gl_thindraw_pcb_polygon(pcb_hid_gc_t gc, pcb_poly_t *poly, const pcb_box_t *clip_box) +{ + pcb_dhlp_thindraw_pcb_polygon(gc, poly, clip_box); + /* Disable thindraw poly filling until it is fixed. The poly fill overwrites lines and + * arcs that are drawn underneath. + * + ghid_gl_set_alpha_mult(gc, 0.25); + ghid_gl_fill_pcb_polygon(gc, poly, clip_box); + ghid_gl_set_alpha_mult(gc, 1.0); + */ +} + +static void ghid_gl_fill_rect(pcb_hid_gc_t gc, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2) +{ + USE_GC(gc); + + hidgl_fill_rect(x1, y1, x2, y2); +} + +void ghid_gl_invalidate_all() +{ + if (ghidgui && ghidgui->topwin.menu.menu_bar) + ghid_draw_area_update(gport, NULL); +} + +void ghid_gl_invalidate_lr(pcb_coord_t left, pcb_coord_t right, pcb_coord_t top, pcb_coord_t bottom) +{ + ghid_gl_invalidate_all(); +} + +static void ghid_gl_notify_crosshair_change(pcb_bool changes_complete) +{ + /* We sometimes get called before the GUI is up */ + if (gport->drawing_area == NULL) + return; + + /* FIXME: We could just invalidate the bounds of the crosshair attached objects? */ + ghid_gl_invalidate_all(); +} + +static void ghid_gl_notify_mark_change(pcb_bool changes_complete) +{ + /* We sometimes get called before the GUI is up */ + if (gport->drawing_area == NULL) + return; + + /* FIXME: We could just invalidate the bounds of the mark? */ + ghid_gl_invalidate_all(); +} + +static void pcb_gl_draw_right_cross(GLint x, GLint y, GLint z) +{ + glVertex3i(x, 0, z); + glVertex3i(x, PCB->MaxHeight, z); + glVertex3i(0, y, z); + glVertex3i(PCB->MaxWidth, y, z); +} + +static void pcb_gl_draw_slanted_cross(GLint x, GLint y, GLint z) +{ + GLint x0, y0, x1, y1; + + x0 = x + (PCB->MaxHeight - y); + x0 = MAX(0, MIN(x0, PCB->MaxWidth)); + x1 = x - y; + x1 = MAX(0, MIN(x1, PCB->MaxWidth)); + y0 = y + (PCB->MaxWidth - x); + y0 = MAX(0, MIN(y0, PCB->MaxHeight)); + y1 = y - x; + y1 = MAX(0, MIN(y1, PCB->MaxHeight)); + glVertex3i(x0, y0, z); + glVertex3i(x1, y1, z); + + x0 = x - (PCB->MaxHeight - y); + x0 = MAX(0, MIN(x0, PCB->MaxWidth)); + x1 = x + y; + x1 = MAX(0, MIN(x1, PCB->MaxWidth)); + y0 = y + x; + y0 = MAX(0, MIN(y0, PCB->MaxHeight)); + y1 = y - (PCB->MaxWidth - x); + y1 = MAX(0, MIN(y1, PCB->MaxHeight)); + glVertex3i(x0, y0, z); + glVertex3i(x1, y1, z); +} + +static void pcb_gl_draw_dozen_cross(GLint x, GLint y, GLint z) +{ + GLint x0, y0, x1, y1; + gdouble tan60 = sqrt(3); + + x0 = x + (PCB->MaxHeight - y) / tan60; + x0 = MAX(0, MIN(x0, PCB->MaxWidth)); + x1 = x - y / tan60; + x1 = MAX(0, MIN(x1, PCB->MaxWidth)); + y0 = y + (PCB->MaxWidth - x) * tan60; + y0 = MAX(0, MIN(y0, PCB->MaxHeight)); + y1 = y - x * tan60; + y1 = MAX(0, MIN(y1, PCB->MaxHeight)); + glVertex3i(x0, y0, z); + glVertex3i(x1, y1, z); + + x0 = x + (PCB->MaxHeight - y) * tan60; + x0 = MAX(0, MIN(x0, PCB->MaxWidth)); + x1 = x - y * tan60; + x1 = MAX(0, MIN(x1, PCB->MaxWidth)); + y0 = y + (PCB->MaxWidth - x) / tan60; + y0 = MAX(0, MIN(y0, PCB->MaxHeight)); + y1 = y - x / tan60; + y1 = MAX(0, MIN(y1, PCB->MaxHeight)); + glVertex3i(x0, y0, z); + glVertex3i(x1, y1, z); + + x0 = x - (PCB->MaxHeight - y) / tan60; + x0 = MAX(0, MIN(x0, PCB->MaxWidth)); + x1 = x + y / tan60; + x1 = MAX(0, MIN(x1, PCB->MaxWidth)); + y0 = y + x * tan60; + y0 = MAX(0, MIN(y0, PCB->MaxHeight)); + y1 = y - (PCB->MaxWidth - x) * tan60; + y1 = MAX(0, MIN(y1, PCB->MaxHeight)); + glVertex3i(x0, y0, z); + glVertex3i(x1, y1, z); + + x0 = x - (PCB->MaxHeight - y) * tan60; + x0 = MAX(0, MIN(x0, PCB->MaxWidth)); + x1 = x + y * tan60; + x1 = MAX(0, MIN(x1, PCB->MaxWidth)); + y0 = y + x / tan60; + y0 = MAX(0, MIN(y0, PCB->MaxHeight)); + y1 = y - (PCB->MaxWidth - x) / tan60; + y1 = MAX(0, MIN(y1, PCB->MaxHeight)); + glVertex3i(x0, y0, z); + glVertex3i(x1, y1, z); +} + +void pcb_gl_draw_crosshair(GLint x, GLint y, GLint z) +{ + static enum pcb_crosshair_shape_e prev = pcb_ch_shape_basic; + + if (gport->view.crosshair_x < 0 || !ghidgui->topwin.active || !gport->view.has_entered) + return; + + pcb_gl_draw_right_cross(x, y, z); + if (prev == pcb_ch_shape_union_jack) + pcb_gl_draw_slanted_cross(x, y, z); + if (prev == pcb_ch_shape_dozen) + pcb_gl_draw_dozen_cross(x, y, z); + prev = pcb_crosshair.shape; +} + +static void ghid_gl_show_crosshair(gboolean paint_new_location) +{ + GLint x, y, z; + static int done_once = 0; + static pcb_gtk_color_t cross_color; + + if (!paint_new_location) + return; + + if (!done_once) { + done_once = 1; + /* FIXME: when CrossColor changed from config */ + map_color_string(conf_core.appearance.color.cross.str, &cross_color); + } + x = gport->view.crosshair_x; + y = gport->view.crosshair_y; + z = 0; + + glEnable(GL_COLOR_LOGIC_OP); + glLogicOp(GL_XOR); + + glColor3f(cross_color.red / 65535., cross_color.green / 65535., cross_color.blue / 65535.); + + if (x >= 0 && paint_new_location) { + glBegin(GL_LINES); + pcb_gl_draw_crosshair(x, y, z); + glEnd(); + } + + glDisable(GL_COLOR_LOGIC_OP); +} + +static void ghid_gl_init_renderer(int *argc, char ***argv, void *vport) +{ + GHidPort *port = vport; + render_priv_t *priv; + + port->render_priv = priv = g_new0(render_priv_t, 1); + + gtk_gl_init(argc, argv); + + /* setup GL-context */ + priv->glconfig = gdk_gl_config_new_by_mode(GDK_GL_MODE_RGBA | GDK_GL_MODE_STENCIL | GDK_GL_MODE_DOUBLE); + if (!priv->glconfig) { + printf("Could not setup GL-context!\n"); + return; /* Should we abort? */ + } + + /* Setup HID function pointers specific to the GL renderer */ + gtk2_gl_hid.end_layer = ghid_gl_end_layer; + gtk2_gl_hid.fill_pcb_polygon = ghid_gl_fill_pcb_polygon; + gtk2_gl_hid.thindraw_pcb_polygon = ghid_gl_thindraw_pcb_polygon; +} + +static void ghid_gl_shutdown_renderer(void *p) +{ + GHidPort *port = p; + + g_free(port->render_priv); + port->render_priv = NULL; +} + +static void ghid_gl_init_drawing_widget(GtkWidget *widget, void *port_) +{ + GHidPort *port = port_; + render_priv_t *priv = port->render_priv; + + gtk_widget_set_gl_capability(widget, priv->glconfig, NULL, TRUE, GDK_GL_RGBA_TYPE); +} + +static void ghid_gl_drawing_area_configure_hook(void *port) +{ + static int done_once = 0; + GHidPort *p = port; + render_priv_t *priv = p->render_priv; + + gport->drawing_allowed = pcb_true; + + if (!done_once) { + if (!map_color_string(conf_core.appearance.color.background.str, &priv->bg_color)) + map_color_string("white", &priv->bg_color); + + if (!map_color_string(conf_core.appearance.color.off_limit.str, &priv->offlimits_color)) + map_color_string("white", &priv->offlimits_color); + + if (!map_color_string(conf_core.appearance.color.grid.str, &priv->grid_color)) + map_color_string("blue", &priv->grid_color); + set_special_grid_color(); + + done_once = 1; + } +} + +static gboolean ghid_gl_start_drawing(GHidPort *port) +{ + GtkWidget *widget = port->drawing_area; + GdkGLContext *pGlContext = gtk_widget_get_gl_context(widget); + GdkGLDrawable *pGlDrawable = gtk_widget_get_gl_drawable(widget); + + /* make GL-context "current" */ + if (!gdk_gl_drawable_gl_begin(pGlDrawable, pGlContext)) + return FALSE; + + port->render_priv->in_context = pcb_true; + + return TRUE; +} + +static void ghid_gl_end_drawing(GHidPort *port) +{ + GtkWidget *widget = port->drawing_area; + GdkGLDrawable *pGlDrawable = gtk_widget_get_gl_drawable(widget); + + if (gdk_gl_drawable_is_double_buffered(pGlDrawable)) + gdk_gl_drawable_swap_buffers(pGlDrawable); + else + glFlush(); + + port->render_priv->in_context = pcb_false; + + /* end drawing to current GL-context */ + gdk_gl_drawable_gl_end(pGlDrawable); +} + +static void ghid_gl_screen_update(void) +{ +} + +/* Settles background color + inital GL configuration, to allow further drawing in GL area. + (w, h) describes the total area concerned, while (xr, yr, wr, hr) describes area requested by an expose event. + The color structure holds the wanted solid back-ground color, used to first paint the exposed drawing area. + */ +static void pcb_gl_draw_expose_init(pcb_hid_t *hid, int w, int h, int xr, int yr, int wr, int hr, pcb_gl_color_t *bg_c) +{ + hidgl_init(); + + /* If we don't have any stencil bits available, + we can't use the hidgl polygon drawing routine */ + /* TODO: We could use the GLU tessellator though */ + if (stencilgl_bit_count() == 0) + hid->fill_pcb_polygon = pcb_dhlp_fill_pcb_polygon; + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glViewport(0, 0, w, h); + + glEnable(GL_SCISSOR_TEST); + glScissor(xr, yr, wr, hr); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(0, w, h, 0, 0, 100); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glTranslatef(0.0f, 0.0f, -Z_NEAR); + + glEnable(GL_STENCIL_TEST); + glClearColor(bg_c->red, bg_c->green, bg_c->blue, 1.); + glStencilMask(~0); + glClearStencil(0); + glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + stencilgl_reset_stencil_usage(); + + /* Disable the stencil test until we need it - otherwise it gets dirty */ + glDisable(GL_STENCIL_TEST); + glStencilMask(0); + glStencilFunc(GL_ALWAYS, 0, 0); +} + +/* alpha component is not part of GdkColor structure. Can't derive it from GTK2 pcb_gtk_color_t */ +static void gtk2gl_color(pcb_gl_color_t *gl_c, pcb_gtk_color_t *gtk_c) +{ + gl_c->red = gtk_c->red / 65535.; + gl_c->green = gtk_c->green / 65535.; + gl_c->blue = gtk_c->blue / 65535.; +} + +static gboolean ghid_gl_drawing_area_expose_cb(GtkWidget *widget, pcb_gtk_expose_t *ev, void *vport) +{ + GHidPort *port = vport; + render_priv_t *priv = port->render_priv; + GtkAllocation allocation; + pcb_hid_expose_ctx_t ctx; + pcb_gl_color_t off_c, bg_c; + + gtk_widget_get_allocation(widget, &allocation); + + ghid_gl_start_drawing(port); + + ctx.view.X1 = MIN(Px(ev->area.x), Px(ev->area.x + ev->area.width + 1)); + ctx.view.X2 = MAX(Px(ev->area.x), Px(ev->area.x + ev->area.width + 1)); + ctx.view.Y1 = MIN(Py(ev->area.y), Py(ev->area.y + ev->area.height + 1)); + ctx.view.Y2 = MAX(Py(ev->area.y), Py(ev->area.y + ev->area.height + 1)); + + ctx.view.X1 = MAX(0, MIN(PCB->MaxWidth, ctx.view.X1)); + ctx.view.X2 = MAX(0, MIN(PCB->MaxWidth, ctx.view.X2)); + ctx.view.Y1 = MAX(0, MIN(PCB->MaxHeight, ctx.view.Y1)); + ctx.view.Y2 = MAX(0, MIN(PCB->MaxHeight, ctx.view.Y2)); + + gtk2gl_color(&off_c, &priv->offlimits_color); + gtk2gl_color(&bg_c, &priv->bg_color); + + pcb_gl_draw_expose_init(>k2_gl_hid, allocation.width, allocation.height, ev->area.x, allocation.height - ev->area.height - ev->area.y, ev->area.width, ev->area.height, &off_c); + + glScalef((conf_core.editor.view.flip_x ? -1. : 1.) / port->view.coord_per_px, (conf_core.editor.view.flip_y ? -1. : 1.) / port->view.coord_per_px, ((conf_core.editor.view.flip_x == conf_core.editor.view.flip_y) ? 1. : -1.) / port->view.coord_per_px); + glTranslatef(conf_core.editor.view.flip_x ? port->view.x0 - PCB->MaxWidth : -port->view.x0, conf_core.editor.view.flip_y ? port->view.y0 - PCB->MaxHeight : -port->view.y0, 0); + + /* Draw PCB background, before PCB primitives */ + glColor3f(bg_c.red, bg_c.green, bg_c.blue); + glBegin(GL_QUADS); + glVertex3i(0, 0, 0); + glVertex3i(PCB->MaxWidth, 0, 0); + glVertex3i(PCB->MaxWidth, PCB->MaxHeight, 0); + glVertex3i(0, PCB->MaxHeight, 0); + glEnd(); + + ghid_gl_draw_bg_image(); + + ghid_gl_invalidate_current_gc(); + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + pcb_hid_expose_all(>k2_gl_hid, &ctx, NULL); + drawgl_flush(); + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + + ghid_gl_draw_grid(&ctx.view); + + ghid_gl_invalidate_current_gc(); + + pcb_draw_attached(0); + pcb_draw_mark(0); + drawgl_flush(); + + ghid_gl_show_crosshair(TRUE); + + drawgl_flush(); + + ghid_gl_end_drawing(port); + + return FALSE; +} + +/* This realize callback is used to work around a crash bug in some mesa + * versions (observed on a machine running the intel i965 driver. It isn't + * obvious why it helps, but somehow fiddling with the GL context here solves + * the issue. The problem appears to have been fixed in recent mesa versions. + */ +static void ghid_gl_port_drawing_realize_cb(GtkWidget *widget, gpointer data) +{ + GdkGLContext *glcontext = gtk_widget_get_gl_context(widget); + GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable(widget); + + if (!gdk_gl_drawable_gl_begin(gldrawable, glcontext)) + return; + + gdk_gl_drawable_gl_end(gldrawable); + return; +} + +static gboolean ghid_gl_preview_expose(GtkWidget *widget, pcb_gtk_expose_t *ev, pcb_hid_expose_t expcall, pcb_hid_expose_ctx_t *ctx) +{ +/* GdkWindow *window = gtk_widget_get_window(widget);*/ + GdkGLContext *pGlContext = gtk_widget_get_gl_context(widget); + GdkGLDrawable *pGlDrawable = gtk_widget_get_gl_drawable(widget); + GtkAllocation allocation; + render_priv_t *priv = gport->render_priv; + pcb_gtk_view_t save_view; + int save_width, save_height; + double xz, yz, vw, vh; + double xr, yr, wr, hr; + pcb_coord_t ox1 = ctx->view.X1, oy1 = ctx->view.Y1, ox2 = ctx->view.X2, oy2 = ctx->view.Y2; + pcb_gl_color_t bg_c; + + vw = ctx->view.X2 - ctx->view.X1; + vh = ctx->view.Y2 - ctx->view.Y1; + + save_view = gport->view; + save_width = gport->view.canvas_width; + save_height = gport->view.canvas_height; + + /* Setup zoom factor for drawing routines */ + + gtk_widget_get_allocation(widget, &allocation); + xz = vw / (double)allocation.width; + yz = vh / (double)allocation.height; + + if (xz > yz) + gport->view.coord_per_px = xz; + else + gport->view.coord_per_px = yz; + + gport->view.canvas_width = allocation.width; + gport->view.canvas_height = allocation.height; + gport->view.width = allocation.width * gport->view.coord_per_px; + gport->view.height = allocation.height * gport->view.coord_per_px; + gport->view.x0 = (vw - gport->view.width) / 2 + ctx->view.X1; + gport->view.y0 = (vh - gport->view.height) / 2 + ctx->view.Y1; + + PCB_GTK_PREVIEW_TUNE_EXTENT(ctx, allocation); + + /* make GL-context "current" */ + if (!gdk_gl_drawable_gl_begin(pGlDrawable, pGlContext)) { + return FALSE; + } + gport->render_priv->in_context = pcb_true; + + if (ev) { + xr = ev->area.x; + yr = allocation.height - ev->area.height - ev->area.y; + wr = ev->area.width; + hr = ev->area.height; + } + else { + xr = yr = 0; + wr = allocation.width; + hr = allocation.height; + } + + gtk2gl_color(&bg_c, &priv->bg_color); + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glViewport(0, 0, allocation.width, allocation.height); + + glEnable(GL_SCISSOR_TEST); + glScissor(xr, yr, wr, hr); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(0, allocation.width, allocation.height, 0, 0, 100); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glTranslatef(0.0f, 0.0f, -Z_NEAR); + + glEnable(GL_STENCIL_TEST); + glClearColor(bg_c.red, bg_c.green, bg_c.blue, 1.); + glStencilMask(~0); + glClearStencil(0); + glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + + stencilgl_reset_stencil_usage(); + glDisable(GL_STENCIL_TEST); + glStencilMask(0); + glStencilFunc(GL_ALWAYS, 0, 0); + + /* call the drawing routine */ + ghid_gl_invalidate_current_gc(); + glPushMatrix(); + glScalef((conf_core.editor.view.flip_x ? -1. : 1.) / gport->view.coord_per_px, (conf_core.editor.view.flip_y ? -1. : 1.) / gport->view.coord_per_px, 1); + glTranslatef(conf_core.editor.view.flip_x ? gport->view.x0 - PCB->MaxWidth : -gport->view.x0, conf_core.editor.view.flip_y ? gport->view.y0 - PCB->MaxHeight : -gport->view.y0, 0); + + expcall(>k2_gl_hid, ctx); + + drawgl_flush(); + glPopMatrix(); + + if (gdk_gl_drawable_is_double_buffered(pGlDrawable)) + gdk_gl_drawable_swap_buffers(pGlDrawable); + else + glFlush(); + + /* end drawing to current GL-context */ + gport->render_priv->in_context = pcb_false; + gdk_gl_drawable_gl_end(pGlDrawable); + + /* restore the original context and priv */ + ctx->view.X1 = ox1; + ctx->view.X2 = ox2; + ctx->view.Y1 = oy1; + ctx->view.Y2 = oy2; + gport->view = save_view; + gport->view.canvas_width = save_width; + gport->view.canvas_height = save_height; + + return FALSE; +} + +static GtkWidget *ghid_gl_new_drawing_widget(pcb_gtk_common_t *common) +{ + GtkWidget *w = gtk_drawing_area_new(); + + g_signal_connect(G_OBJECT(w), "expose_event", G_CALLBACK(common->drawing_area_expose), common->gport); + + return w; +} + + +void ghid_gl_install(pcb_gtk_common_t *common, pcb_hid_t *hid) +{ + + if (common != NULL) { + common->new_drawing_widget = ghid_gl_new_drawing_widget; + common->init_drawing_widget = ghid_gl_init_drawing_widget; + common->drawing_realize = ghid_gl_port_drawing_realize_cb; + common->drawing_area_expose = ghid_gl_drawing_area_expose_cb; + common->preview_expose = ghid_gl_preview_expose; + common->invalidate_all = ghid_gl_invalidate_all; + common->set_special_colors = ghid_gl_set_special_colors; + common->init_renderer = ghid_gl_init_renderer; + common->screen_update = ghid_gl_screen_update; + common->draw_grid_local = ghid_gl_draw_grid_local; + common->drawing_area_configure_hook = ghid_gl_drawing_area_configure_hook; + common->shutdown_renderer = ghid_gl_shutdown_renderer; + common->get_color_name = get_color_name; + common->map_color_string = map_color_string; + } + + if (hid != NULL) { + hid->invalidate_lr = ghid_gl_invalidate_lr; + hid->invalidate_all = ghid_gl_invalidate_all; + hid->notify_crosshair_change = ghid_gl_notify_crosshair_change; + hid->notify_mark_change = ghid_gl_notify_mark_change; + hid->set_layer_group = ghid_gl_set_layer_group; + hid->make_gc = ghid_gl_make_gc; + hid->destroy_gc = ghid_gl_destroy_gc; + hid->set_color = ghid_gl_set_color; + hid->set_line_cap = ghid_gl_set_line_cap; + hid->set_line_width = ghid_gl_set_line_width; + hid->set_draw_xor = ghid_gl_set_draw_xor; + hid->draw_line = ghid_gl_draw_line; + hid->draw_arc = ghid_gl_draw_arc; + hid->draw_rect = ghid_gl_draw_rect; + hid->fill_circle = ghid_gl_fill_circle; + hid->fill_polygon = ghid_gl_fill_polygon; + hid->fill_polygon_offs = ghid_gl_fill_polygon_offs; + hid->fill_rect = ghid_gl_fill_rect; + + hid->set_drawing_mode = hidgl_set_drawing_mode; + hid->render_burst = ghid_gl_render_burst; + } +} Index: tags/2.1.2/src_plugins/hid_gtk2_gl/gtkhid-main.c =================================================================== --- tags/2.1.2/src_plugins/hid_gtk2_gl/gtkhid-main.c (nonexistent) +++ tags/2.1.2/src_plugins/hid_gtk2_gl/gtkhid-main.c (revision 24813) @@ -0,0 +1,70 @@ +#include "config.h" + +#include + +#include "error.h" +#include "pcb-printf.h" +#include "plugins.h" +#include "hid_init.h" +#include "conf_core.h" + +#include "../src_plugins/lib_hid_gl/draw_gl.h" + +#include "../src_plugins/lib_gtk_common/glue.h" +#include "../src_plugins/lib_gtk_common/lib_gtk_config.h" +#include "../src_plugins/lib_gtk_common/hid_gtk_conf.h" + +#include "../src_plugins/lib_gtk_hid/gui.h" +#include "../src_plugins/lib_gtk_hid/glue_common.h" +#include "../src_plugins/lib_gtk_hid/glue_hid.h" +#include "../src_plugins/lib_gtk_hid/glue_conf.h" +#include "../src_plugins/lib_gtk_hid/glue_event.h" +#include "../src_plugins/lib_gtk_hid/glue_win32.h" +#include "../src_plugins/lib_gtk_hid/common.h" +#include "../src_plugins/lib_gtk_hid/render.h" + +const char *ghid_gl_cookie = "gtk2 hid, gl"; +const char *ghid_gl_menu_cookie = "gtk2 hid menu, gl"; + +pcb_hid_t gtk2_gl_hid; + +int gtk2_gl_parse_arguments(int *argc, char ***argv) +{ + ghid_gl_install(&ghidgui->common, NULL); + return gtkhid_parse_arguments(argc, argv); +} + +int pplg_check_ver_hid_gtk2_gl(int ver_needed) { return 0; } + +void pplg_uninit_hid_gtk2_gl(void) +{ + pcb_event_unbind_allcookie(ghid_gl_cookie); + conf_hid_unreg(ghid_gl_cookie); + conf_hid_unreg(ghid_gl_menu_cookie); + drawgl_uninit(); +} + +int pplg_init_hid_gtk2_gl(void) +{ + PCB_API_CHK_VER; + ghid_win32_init(); + + ghid_glue_hid_init(>k2_gl_hid); + ghid_glue_common_init(); + + gtk2_gl_hid.parse_arguments = gtk2_gl_parse_arguments; + ghid_gl_install(NULL, >k2_gl_hid); + + gtk2_gl_hid.name = "gtk2_gl"; + gtk2_gl_hid.description = "Gtk2 - The Gimp Toolkit, with opengl rendering"; + + ghidgui->topwin.menu.ghid_menuconf_id = conf_hid_reg(ghid_gl_menu_cookie, NULL); + ghidgui->topwin.menu.confchg_checkbox = ghid_confchg_checkbox; + ghid_conf_regs(ghid_gl_cookie); + + pcb_hid_register_hid(>k2_gl_hid); + + glue_event_init(ghid_gl_cookie); + + return 0; +} Index: tags/2.1.2/src_plugins/hid_gtk2_gl/hid_gtk2_gl.pup =================================================================== --- tags/2.1.2/src_plugins/hid_gtk2_gl/hid_gtk2_gl.pup (nonexistent) +++ tags/2.1.2/src_plugins/hid_gtk2_gl/hid_gtk2_gl.pup (revision 24813) @@ -0,0 +1,10 @@ +$class hid +$short GTK2 GUI, opengl render +$long GUI: GTK2 with opengl rendering +$state works +$package hid-gtk2-gl +default buildin +dep lib_gtk_common +dep lib_gtk_hid +dep lib_hid_gl +autoload 1 Index: tags/2.1.2/src_plugins/hid_gtk2_gl/pcb.rc =================================================================== --- tags/2.1.2/src_plugins/hid_gtk2_gl/pcb.rc (nonexistent) +++ tags/2.1.2/src_plugins/hid_gtk2_gl/pcb.rc (revision 24813) @@ -0,0 +1 @@ +1 ICON "pcb_icon.ico" Index: tags/2.1.2/src_plugins/hid_gtk3_cairo/Makefile =================================================================== --- tags/2.1.2/src_plugins/hid_gtk3_cairo/Makefile (nonexistent) +++ tags/2.1.2/src_plugins/hid_gtk3_cairo/Makefile (revision 24813) @@ -0,0 +1,6 @@ +all: + cd ../../src && $(MAKE) mod_hid_gtk3_cairo + +clean: + rm *.o *.so 2>/dev/null ; true + Index: tags/2.1.2/src_plugins/hid_gtk3_cairo/Plug.tmpasm =================================================================== --- tags/2.1.2/src_plugins/hid_gtk3_cairo/Plug.tmpasm (nonexistent) +++ tags/2.1.2/src_plugins/hid_gtk3_cairo/Plug.tmpasm (revision 24813) @@ -0,0 +1,20 @@ +put /local/pcb/mod {hid_gtk3_cairo} +put /local/pcb/mod/OBJS_C99 [@ + $(PLUGDIR)/hid_gtk3_cairo/gtkhid-main.o + $(PLUGDIR)/hid_gtk3_cairo/gtkhid-cairo.o +@] + +switch /local/pcb/hid_gtk3_cairo/controls + case {disable} end; + default + put /local/pcb/mod/CFLAGS /target/libs/gui/gtk3/cflags + put /local/pcb/mod/LDFLAGS /target/libs/gui/gtk3/ldflags + append /local/pcb/CFLAGS { -DPCB_GTK3=1 } + end +end + +switch /local/pcb/hid_gtk3_cairo/controls + case {buildin} include /local/pcb/tmpasm/buildin; end; + case {plugin} include /local/pcb/tmpasm/plugin; end; + case {disable} include /local/pcb/tmpasm/disable; end; +end Index: tags/2.1.2/src_plugins/hid_gtk3_cairo/gtkhid-cairo.c =================================================================== --- tags/2.1.2/src_plugins/hid_gtk3_cairo/gtkhid-cairo.c (nonexistent) +++ tags/2.1.2/src_plugins/hid_gtk3_cairo/gtkhid-cairo.c (revision 24813) @@ -0,0 +1,1614 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 1994,1995,1996 Thomas Nau + * pcb-rnd Copyright (C) 2017,2018 Alain Vigne + * + * 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, see . + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + * + */ + +#include "config.h" +#include "conf_core.h" + +#include + +#include "crosshair.h" +#include "data.h" +#include "layer.h" +#include "grid.h" +#include "hid_draw_helpers.h" +#include "hid_attrib.h" +#include "hid_color.h" +#include "funchash_core.h" + +#include "../src_plugins/lib_gtk_hid/gui.h" +#include "../src_plugins/lib_gtk_hid/coord_conv.h" +#include "../src_plugins/lib_gtk_hid/preview_helper.h" + +#include "../src_plugins/lib_gtk_common/hid_gtk_conf.h" +#include "../src_plugins/lib_gtk_common/lib_gtk_config.h" + +#include "../src_plugins/lib_hid_common/clip.h" + +extern pcb_hid_t gtk3_cairo_hid; +static void ghid_cairo_screen_update(void); + +/* Sets priv->u_gc to the "right" GC to use (wrt mask or window) +*/ +#define USE_GC(gc) if (!use_gc(gc)) return + +//static int cur_mask = -1; +//static int mask_seq = 0; +static pcb_composite_op_t curr_drawing_mode; + +typedef struct render_priv_s { + GdkRGBA bg_color; /* cached back-ground color */ + GdkRGBA offlimits_color; /* cached external board color */ + GdkRGBA grid_color; /* cached grid color */ + GdkRGBA crosshair_color; /* cached crosshair color */ + + cairo_t *cr; /* pointer to current drawing context */ + cairo_t *cr_target; /* pointer to destination widget drawing context */ + + cairo_surface_t *surf_da; /* cairo surface connected to gport->drawing_area */ + cairo_t *cr_drawing_area; /* cairo context created from surf_da */ + + cairo_surface_t *surf_layer; /* cairo surface for temporary layer composition */ + cairo_t *cr_layer; /* cairo context created from surf_layer */ + + //GdkPixmap *pixmap, *mask; + + //GdkGC *bg_gc; + //GdkGC *offlimits_gc; + //GdkGC *mask_gc; + //GdkGC *u_gc; + //GdkGC *grid_gc; + pcb_bool clip; + GdkRectangle clip_rect; + int xor_mode; /* 1 if drawn in XOR mode, 0 otherwise*/ + int attached_invalidate_depth; + int mark_invalidate_depth; +} render_priv_t; + +typedef struct hid_gc_s { + pcb_core_gc_t core_gc; + pcb_hid_t *me_pointer; + + pcb_color_t pcolor; + GdkRGBA color; /* current color for this GC. */ + + pcb_coord_t width; + cairo_line_cap_t cap; + cairo_line_join_t join; + gchar xor_mask; + //gint mask_seq; +} hid_gc_s; + +static void copy_color(GdkRGBA * dest, GdkRGBA * source) +{ + dest->red = source->red; + dest->green = source->green; + dest->blue = source->blue; + dest->alpha = source->alpha; +} + +static const gchar *get_color_name(pcb_gtk_color_t * color) +{ + static char tmp[16]; + + if (!color) + return "#000000"; + + sprintf(tmp, "#%2.2x%2.2x%2.2x", + (int) (color->red * 255) & 0xff, (int) (color->green * 255) & 0xff, (int) (color->blue * 255) & 0xff); + return tmp; +} + +/* Returns TRUE if color_string has been successfully parsed to color. */ +static pcb_bool map_color_string(const char *color_string, pcb_gtk_color_t * color) +{ + pcb_bool parsed; + + if (!color) + return FALSE; + + parsed = gdk_rgba_parse(color, color_string); + + return parsed; +} + +static void cr_draw_line(cairo_t * cr, int fill, double x1, double y1, double x2, double y2) +{ + if (cr == NULL) + return; + + cairo_move_to(cr, x1, y1); + cairo_line_to(cr, x2, y2); +TODO("gtk3: What means 'fill a line'? cairo_fill is not appropriate if path is only a line.") + if (fill) + cairo_fill(cr); + else + cairo_stroke(cr); +} + +static void cr_destroy_surf_and_context(cairo_surface_t ** psurf, cairo_t ** pcr) +{ + if (*psurf) + cairo_surface_destroy(*psurf); + if (*pcr) + cairo_destroy(*pcr); + + *psurf = NULL; + *pcr = NULL; +} + +/* First, frees previous surface and context, then creates new ones, similar to drawing_area. */ +static void cr_create_similar_surface_and_context(cairo_surface_t ** psurf, cairo_t ** pcr, void *vport) +{ + GHidPort *port = vport; + cairo_surface_t *surface; + cairo_t *cr; + + cr_destroy_surf_and_context(psurf, pcr); + + surface = gdk_window_create_similar_surface(gtk_widget_get_window(port->drawing_area), + CAIRO_CONTENT_COLOR_ALPHA, + gtk_widget_get_allocated_width(port->drawing_area), + gtk_widget_get_allocated_height(port->drawing_area)); + cr = cairo_create(surface); + *psurf = surface; + *pcr = cr; +} + +/* Creates or reuses a context to render a single layer group with "union" type of shape rendering. */ +static void start_subcomposite(void) +{ + render_priv_t *priv = gport->render_priv; + cairo_t *cr; + + if (priv->surf_layer == NULL) + cr_create_similar_surface_and_context(&priv->surf_layer, &priv->cr_layer, gport); + cr = priv->cr_layer; + cairo_save(cr); + cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR); + cairo_paint(cr); + cairo_restore(cr); + cairo_set_operator(priv->cr, CAIRO_OPERATOR_SOURCE); + priv->cr = priv->cr_layer; +} + +/* Applies the layer composited so far, to the target, using translucency. */ +static void end_subcomposite(void) +{ + render_priv_t *priv = gport->render_priv; + + cairo_set_operator(priv->cr_target, CAIRO_OPERATOR_OVER); + cairo_set_source_surface(priv->cr_target, priv->surf_layer, 0, 0); + cairo_paint_with_alpha(priv->cr_target, conf_core.appearance.layer_alpha); + priv->cr = priv->cr_target; +} + +static int ghid_cairo_set_layer_group(pcb_layergrp_id_t group, const char *purpose, int purpi, pcb_layer_id_t layer, unsigned int flags, int is_empty, pcb_xform_t **xform) +{ + int idx = group; + if (idx >= 0 && idx < pcb_max_group(PCB)) { + int n = PCB->LayerGroups.grp[group].len; + for (idx = 0; idx < n - 1; idx++) { + int ni = PCB->LayerGroups.grp[group].lid[idx]; + if (ni >= 0 && ni < pcb_max_layer && PCB->Data->Layer[ni].meta.real.vis) + break; + } + idx = PCB->LayerGroups.grp[group].lid[idx]; + } + + start_subcomposite(); + + /* non-virtual layers with group visibility */ + switch (flags & PCB_LYT_ANYTHING) { + case PCB_LYT_MASK: + case PCB_LYT_PASTE: + return (PCB_LAYERFLG_ON_VISIBLE_SIDE(flags) && PCB->LayerGroups.grp[group].vis); + } + + /* normal layers */ + if (idx >= 0 && idx < pcb_max_layer && ((flags & PCB_LYT_ANYTHING) != PCB_LYT_SILK)) + return PCB->Data->Layer[idx].meta.real.vis; + + if (PCB_LAYER_IS_ASSY(flags, purpi)) + return 0; + + /* virtual layers */ + { + if (PCB_LAYER_IS_DRILL(flags, purpi)) + return 1; + + switch (flags & PCB_LYT_ANYTHING) { + case PCB_LYT_INVIS: + return PCB->InvisibleObjectsOn; + case PCB_LYT_SILK: + if (PCB_LAYERFLG_ON_VISIBLE_SIDE(flags)) + return pcb_silk_on(PCB); + return 0; + case PCB_LYT_UI: + return 1; + case PCB_LYT_RAT: + return PCB->RatOn; + } + } + return 0; +} + +static void ghid_cairo_end_layer_group(void) +{ + end_subcomposite(); +} + +TODO(": misleading comment or broken code") +/* Do not clean up internal structures, as they will be used probably elsewhere. */ +static void ghid_cairo_destroy_gc(pcb_hid_gc_t gc) +{ + g_free(gc); +} + +/* called from pcb_hid_t->make_gc() . Use only this to hold pointers, do not + own references, avoid costly memory allocation that needs to be destroyed with + ghid_cairo_destroy_gc(). */ +static pcb_hid_gc_t ghid_cairo_make_gc(void) +{ + pcb_hid_gc_t rv; + + rv = g_new0(hid_gc_s, 1); + rv->me_pointer = >k3_cairo_hid; + rv->pcolor = conf_core.appearance.color.background; + return rv; +} + +TODO("gtk3: check if clipping is not necessary") +//static void set_clip(render_priv_t * priv, cairo_t * cr) +//{ +// if (cr == NULL) +// return; +// +// if (priv->clip) { +// gdk_cairo_rectangle(cr, &priv->clip_rect); +// cairo_clip(cr); +// } +// else { +// /*FIXME: do nothing if no clipping ? */ +// //cairo_mask(cr, NULL); +// //gdk_gc_set_clip_mask(gc, NULL); +// } +//} + +static inline void ghid_cairo_draw_grid_global(cairo_t *cr) +{ + //render_priv_t *priv = gport->render_priv; + pcb_coord_t x, y, x1, y1, x2, y2, grd; + int n, i; + static GdkPoint *points = NULL; + static int npoints = 0; + + x1 = pcb_grid_fit(MAX(0, SIDE_X(gport->view.x0)), PCB->Grid, PCB->GridOffsetX); + y1 = pcb_grid_fit(MAX(0, SIDE_Y(gport->view.y0)), PCB->Grid, PCB->GridOffsetY); + x2 = pcb_grid_fit(MIN(PCB->MaxWidth, SIDE_X(gport->view.x0 + gport->view.width - 1)), PCB->Grid, PCB->GridOffsetX); + y2 = pcb_grid_fit(MIN(PCB->MaxHeight, SIDE_Y(gport->view.y0 + gport->view.height - 1)), PCB->Grid, PCB->GridOffsetY); + + grd = PCB->Grid; + + if (Vz(grd) < conf_hid_gtk.plugins.hid_gtk.global_grid.min_dist_px) { + if (!conf_hid_gtk.plugins.hid_gtk.global_grid.sparse) + return; + grd *= (conf_hid_gtk.plugins.hid_gtk.global_grid.min_dist_px / Vz(grd)); + } + + if (x1 > x2) { + pcb_coord_t tmp = x1; + x1 = x2; + x2 = tmp; + } + if (y1 > y2) { + pcb_coord_t tmp = y1; + y1 = y2; + y2 = tmp; + } + if (Vx(x1) < 0) + x1 += grd; + if (Vy(y1) < 0) + y1 += grd; + if (Vx(x2) >= gport->view.canvas_width) + x2 -= grd; + if (Vy(y2) >= gport->view.canvas_height) + y2 -= grd; + + + n = (x2 - x1) / grd + 1; + if (n > npoints) { + npoints = n + 10; + points = (GdkPoint *) realloc(points, npoints * sizeof(GdkPoint)); + } + n = 0; + for (x = x1; x <= x2; x += grd) { + points[n].x = Vx(x); + n++; + } + if (n == 0) + return; + + /* Draw N points... is this the most efficient ? At least, it works. + From cairo development : + " cairo_move_to (cr, x, y); + . cairo_line_to (cr, x, y); + . .. repeat for each point .. + . + . cairo_stroke (cr); + . + . Within the implementation (and test suite) we call these "degenerate" + . paths and we explicitly support drawing round caps for such degenerate + . paths. So this should work perfectly for the case of + . CAIRO_LINE_CAP_ROUND and you'll get the diameter controlled by + . cairo_set_line_width just like you want. + " + */ + for (y = y1; y <= y2; y += grd) { + for (i = 0; i < n; i++) { + points[i].y = Vy(y); + cairo_move_to(cr, points[i].x, points[i].y); + cairo_line_to(cr, points[i].x, points[i].y); + } + cairo_stroke(cr); + } +} + +static void ghid_cairo_draw_grid_local_(pcb_coord_t cx, pcb_coord_t cy, int radius) +{ + render_priv_t *priv = gport->render_priv; + cairo_t *cr = priv->cr_target; + static GdkPoint *points_base = NULL; + static GdkPoint *points_abs = NULL; + static int apoints = 0, npoints = 0, old_radius = 0; + static pcb_coord_t last_grid = 0; + int recalc = 0, n, r2; + pcb_coord_t x, y; + + /* PI is approximated with 3.25 here - allows a minimal overallocation, speeds up calculations */ + r2 = radius * radius; + n = r2 * 3 + r2 / 4 + 1; + if (n > apoints) { + apoints = n; + points_base = (GdkPoint *) realloc(points_base, apoints * sizeof(GdkPoint)); + points_abs = (GdkPoint *) realloc(points_abs, apoints * sizeof(GdkPoint)); + } + + if (radius != old_radius) { + old_radius = radius; + recalc = 1; + } + + if (last_grid != PCB->Grid) { + last_grid = PCB->Grid; + recalc = 1; + } + + /* recaculate the 'filled circle' mask (base relative coords) if grid or radius changed */ + if (recalc) { + + npoints = 0; + for (y = -radius; y <= radius; y++) { + int y2 = y * y; + for (x = -radius; x <= radius; x++) { + if (x * x + y2 < r2) { + points_base[npoints].x = x * PCB->Grid; + points_base[npoints].y = y * PCB->Grid; + npoints++; + } + } + } + } + + /* calculate absolute positions */ + for (n = 0; n < npoints; n++) { + points_abs[n].x = Vx(points_base[n].x + cx); + points_abs[n].y = Vy(points_base[n].y + cy); + cairo_move_to(cr, points_abs[n].x, points_abs[n].y); + cairo_line_to(cr, points_abs[n].x, points_abs[n].y); + } + cairo_stroke(cr); + //gdk_draw_points(gport->drawable, priv->grid_gc, points_abs, npoints); +} + +static int grid_local_have_old = 0, grid_local_old_r = 0; +static pcb_coord_t grid_local_old_x, grid_local_old_y; + +static void ghid_cairo_draw_grid_local(pcb_coord_t cx, pcb_coord_t cy) +{ + if (grid_local_have_old) { + ghid_cairo_draw_grid_local_(grid_local_old_x, grid_local_old_y, grid_local_old_r); + grid_local_have_old = 0; + } + + if (!conf_hid_gtk.plugins.hid_gtk.local_grid.enable) + return; + + if ((Vz(PCB->Grid) < PCB_MIN_GRID_DISTANCE) || (!conf_core.editor.draw_grid)) + return; + + /* cx and cy are the actual cursor snapped to wherever - round them to the nearest real grid point */ + cx = (cx / PCB->Grid) * PCB->Grid + PCB->GridOffsetX; + cy = (cy / PCB->Grid) * PCB->Grid + PCB->GridOffsetY; + + grid_local_have_old = 1; + ghid_cairo_draw_grid_local_(cx, cy, conf_hid_gtk.plugins.hid_gtk.local_grid.radius); + grid_local_old_x = cx; + grid_local_old_y = cy; + grid_local_old_r = conf_hid_gtk.plugins.hid_gtk.local_grid.radius; +} + +static void ghid_cairo_draw_grid(void) +{ + render_priv_t *priv = gport->render_priv; + cairo_t *cr = priv->cr_target; + + if (cr == NULL) + return; + + grid_local_have_old = 0; + + if (!conf_core.editor.draw_grid) + return; + //if (!priv->grid_gc) { + // if (gdk_color_parse(conf_core.appearance.color.grid, &gport->grid_color)) { + // gport->grid_color.red ^= gport->bg_color.red; + // gport->grid_color.green ^= gport->bg_color.green; + // gport->grid_color.blue ^= gport->bg_color.blue; + // gdk_color_alloc(gport->colormap, &gport->grid_color); + // } + // priv->grid_gc = gdk_gc_new(gport->drawable); + // gdk_gc_set_function(priv->grid_gc, GDK_XOR); + // gdk_gc_set_foreground(priv->grid_gc, &gport->grid_color); + // gdk_gc_set_clip_origin(priv->grid_gc, 0, 0); + // set_clip(priv, priv->grid_gc); + //} + + cairo_save(cr); +TODO("gtk3: deal with gc") + cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND); + cairo_set_line_width(cr, 1.0); + gdk_cairo_set_source_rgba(cr, &priv->grid_color); + + if (conf_hid_gtk.plugins.hid_gtk.local_grid.enable) { + ghid_cairo_draw_grid_local(grid_local_old_x, grid_local_old_y); + cairo_restore(cr); + return; + } + + ghid_cairo_draw_grid_global(cr); + cairo_restore(cr); +} + +/* ------------------------------------------------------------ */ +static void ghid_cairo_draw_bg_image(void) +{ + static GdkPixbuf *pixbuf; + GdkInterpType interp_type; + gint src_x, src_y, dst_x, dst_y, w, h, w_src, h_src; + static gint w_scaled, h_scaled; + render_priv_t *priv = gport->render_priv; + + if (!ghidgui->bg_pixbuf) + return; + + src_x = gport->view.x0; + src_y = gport->view.y0; + dst_x = 0; + dst_y = 0; + + if (src_x < 0) { + dst_x = -src_x; + src_x = 0; + } + if (src_y < 0) { + dst_y = -src_y; + src_y = 0; + } + + w = PCB->MaxWidth / gport->view.coord_per_px; + h = PCB->MaxHeight / gport->view.coord_per_px; + src_x = src_x / gport->view.coord_per_px; + src_y = src_y / gport->view.coord_per_px; + dst_x = dst_x / gport->view.coord_per_px; + dst_y = dst_y / gport->view.coord_per_px; + + if (w_scaled != w || h_scaled != h) { + if (pixbuf) + g_object_unref(G_OBJECT(pixbuf)); + + w_src = gdk_pixbuf_get_width(ghidgui->bg_pixbuf); + h_src = gdk_pixbuf_get_height(ghidgui->bg_pixbuf); + if (w > w_src && h > h_src) + interp_type = GDK_INTERP_NEAREST; + else + interp_type = GDK_INTERP_BILINEAR; + + pixbuf = gdk_pixbuf_scale_simple(ghidgui->bg_pixbuf, w, h, interp_type); + w_scaled = w; + h_scaled = h; + } + + if (pixbuf) { + gdk_cairo_set_source_pixbuf(priv->cr, pixbuf, src_x, src_y); + cairo_rectangle(priv->cr, dst_x, dst_y, gport->view.canvas_width, gport->view.canvas_height); + cairo_fill(priv->cr); + //gdk_pixbuf_render_to_drawable(pixbuf, gport->drawable, priv->bg_gc, + // src_x, src_y, dst_x, dst_y, w - src_x, h - src_y, GDK_RGB_DITHER_NORMAL, 0, 0); + } +} + +static void ghid_cairo_render_burst(pcb_burst_op_t op, const pcb_box_t *screen) +{ + pcb_gui->coord_per_pix = gport->view.coord_per_px; +} + +/* Drawing modes usually cycle from RESET to (POSITIVE | NEGATIVE) to FLUSH. screen is not used in this HID. */ +static void ghid_cairo_set_drawing_mode(pcb_composite_op_t op, pcb_bool direct, const pcb_box_t *screen) +{ + render_priv_t *priv = gport->render_priv; + + if (!priv->cr) { + //abort(); + return; + } + + switch(op) { + case PCB_HID_COMP_RESET: + //ghid_sketch_setup(priv); + start_subcomposite(); + + /* clear the canvas */ + //priv->clip_color.pixel = 0; + //if (priv->clear_gc == NULL) + // priv->clear_gc = gdk_gc_new(priv->out_clip); + //gdk_gc_set_foreground(priv->clear_gc, &priv->clip_color); + //set_clip(priv, priv->clear_gc); + //gdk_draw_rectangle(priv->out_clip, priv->clear_gc, TRUE, 0, 0, gport->view.canvas_width, gport->view.canvas_height); + break; + + case PCB_HID_COMP_POSITIVE: + case PCB_HID_COMP_POSITIVE_XOR: + //priv->clip_color.pixel = 1; + cairo_set_operator(priv->cr, CAIRO_OPERATOR_SOURCE); + break; + + case PCB_HID_COMP_NEGATIVE: + //priv->clip_color.pixel = 0; + cairo_set_operator(priv->cr, CAIRO_OPERATOR_CLEAR); + break; + + case PCB_HID_COMP_FLUSH: + if (direct) + end_subcomposite(); + else { + priv->cr = priv->cr_target; + cairo_mask_surface(priv->cr, priv->surf_layer, 0, 0); + cairo_fill(priv->cr); + } + //cairo_paint_with_alpha(priv->cr, conf_core.appearance.layer_alpha); + //cairo_paint_with_alpha(priv->cr, 1.0); + + //if (priv->copy_gc == NULL) + // priv->copy_gc = gdk_gc_new(priv->out_pixel); + //gdk_gc_set_clip_mask(priv->copy_gc, priv->sketch_clip); + //gdk_gc_set_clip_origin(priv->copy_gc, 0, 0); + //gdk_draw_drawable(priv->base_pixel, priv->copy_gc, priv->sketch_pixel, 0, 0, 0, 0, gport->view.canvas_width, gport->view.canvas_height); + // + //priv->out_pixel = priv->base_pixel; + //priv->out_clip = NULL; + break; + } + curr_drawing_mode = op; +} + +typedef struct { + int color_set; + GdkRGBA color; + int xor_set; + GdkRGBA xor_color; +} ColorCache; + + +/* Config helper functions for when the user changes color preferences. + set_special colors used in the gtkhid. + */ +//static void set_special_grid_color(void) +//{ +// render_priv_t *priv = gport->render_priv; +// int red, green, blue; +// +// //if (!gport->colormap) +// // return; +// +// red = priv->grid_color.red; +// green = priv->grid_color.green; +// blue = priv->grid_color.blue; +// conf_setf(CFR_DESIGN, "appearance/color/grid", -1, "#%02x%02x%02x", red, green, blue); +// map_color_string(conf_core.appearance.color.grid, &priv->grid_color); +// +// config_color_button_update(&ghidgui->common, conf_get_field("appearance/color/grid"), -1); +// +// //if (priv->grid_gc) +// // gdk_gc_set_foreground(priv->grid_gc, &gport->grid_color); +//} + +static void ghid_cairo_set_special_colors(conf_native_t * cfg) +{ + render_priv_t *priv = gport->render_priv; + + if (((CFT_COLOR *) cfg->val.color == &conf_core.appearance.color.background) /*&& priv->bg_gc */ ) { + if (map_color_string(cfg->val.color[0].str, &priv->bg_color)) { + //gdk_gc_set_foreground(priv->bg_gc, &priv->bg_color); + //set_special_grid_color(); + } + } + else if (((CFT_COLOR *) cfg->val.color == &conf_core.appearance.color.off_limit) /*&& priv->offlimits_gc */ ) { + if (map_color_string(cfg->val.color[0].str, &priv->offlimits_color)) { + //gdk_gc_set_foreground(priv->offlimits_gc, &priv->offlimits_color); + } + } + else if (((CFT_COLOR *) cfg->val.color == &conf_core.appearance.color.grid) /*&& priv->grid_gc */ ) { + if (map_color_string(cfg->val.color[0].str, &priv->grid_color)) { + conf_setf(CFR_DESIGN, "appearance/color/grid", -1, "%s", get_color_name(&priv->grid_color)); + //set_special_grid_color(); + } + } +} + +static void ghid_cairo_set_color(pcb_hid_gc_t gc, const pcb_color_t *color) +{ + static void *cache = 0; + pcb_hidval_t cval; + render_priv_t *priv = gport->render_priv; + const char *name; + + if (color == NULL) { + fprintf(stderr, "ghid_cairo_set_color(): name = NULL, setting to magenta\n"); + color = &pcb_color_magenta; + } + + gc->pcolor = *color; + name = color->str; + + //if (!gc->gc) + // return; + //if (gport->colormap == 0) + // gport->colormap = gtk_widget_get_colormap(gport->top_window); + + if (pcb_color_is_drill(color)) { + copy_color(&gc->color, &priv->offlimits_color); + //gdk_cairo_set_source_rgba(cr, &priv->offlimits_color); + //gdk_gc_set_foreground(gc->gc, &gport->offlimits_color); + } + else { + ColorCache *cc; + if (pcb_hid_cache_color(0, name, &cval, &cache)) + cc = (ColorCache *) cval.ptr; + else { + cc = (ColorCache *) malloc(sizeof(ColorCache)); + memset(cc, 0, sizeof(*cc)); + cval.ptr = cc; + pcb_hid_cache_color(1, name, &cval, &cache); + } + + if (!cc->color_set) { + if (! gdk_rgba_parse(&cc->color, name)) + gdk_rgba_parse(&cc->color, "white"); + //gdk_color_white(gport->colormap, &cc->color); + //else + //gdk_color_alloc(gport->colormap, &cc->color); + cc->color_set = 1; + } + //if (gc->xor_mask) { + // if (!cc->xor_set) { + // cc->xor_color.red = cc->color.red ^ gport->bg_color.red; + // cc->xor_color.green = cc->color.green ^ gport->bg_color.green; + // cc->xor_color.blue = cc->color.blue ^ gport->bg_color.blue; + // gdk_color_alloc(gport->colormap, &cc->xor_color); + // cc->xor_set = 1; + // } + // gdk_gc_set_foreground(gc->gc, &cc->xor_color); + //} + //else { + // gdk_gc_set_foreground(gc->gc, &cc->color); + //} + cc->color.alpha = 1.0; + copy_color(&gc->color, &cc->color); + } +} + +static void ghid_cairo_set_line_cap(pcb_hid_gc_t gc, pcb_cap_style_t style) +{ + cairo_line_cap_t cap = CAIRO_LINE_CAP_BUTT; + cairo_line_join_t join = CAIRO_LINE_JOIN_MITER; + + switch (style) { + case pcb_cap_round: + cap = CAIRO_LINE_CAP_ROUND; + join = CAIRO_LINE_JOIN_ROUND; + break; + case pcb_cap_square: + cap = CAIRO_LINE_CAP_SQUARE; + join = CAIRO_LINE_JOIN_MITER; + break; + default: + assert(!"unhandled cap"); + } + gc->cap = cap; + gc->join = join; + + //if (gc->gc) + // gdk_gc_set_line_attributes(WHICH_GC(gc), Vz(gc->width), GDK_LINE_SOLID, (GdkCapStyle) gc->cap, (GdkJoinStyle) gc->join); +} + +static void ghid_cairo_set_line_width(pcb_hid_gc_t gc, pcb_coord_t width) +{ + //render_priv_t *priv = gport->render_priv; + + //if (priv->cr == NULL) + // return; + + gc->width = width; + //cairo_set_line_width(priv->cr, Vz(gc->width)); + //if (gc->gc) + // gdk_gc_set_line_attributes(WHICH_GC(gc), Vz(gc->width), GDK_LINE_SOLID, (GdkCapStyle) gc->cap, (GdkJoinStyle) gc->join); +} + +static void ghid_cairo_set_draw_xor(pcb_hid_gc_t gc, int xor_mask) +{ + render_priv_t *priv = gport->render_priv; + + priv->xor_mode = (xor_mask) ? 1 : 0; + //gc->xor_mask = xor_mask; + //if (!gc->gc) + // return; + //gdk_gc_set_function(gc->gc, xor_mask ? GDK_XOR : GDK_COPY); + //ghid_cairo_set_color(gc, gc->pcolor.str); +} + +static int use_gc(pcb_hid_gc_t gc) +{ + render_priv_t *priv = gport->render_priv; + cairo_t *cr = priv->cr; + //GdkWindow *window = gtk_widget_get_window(gport->top_window); + + if (gc->me_pointer != >k3_cairo_hid) { + fprintf(stderr, "Fatal: GC from another HID passed to GTK HID\n"); + abort(); + } + + if (cr == NULL) + return 0; + + //ghid_cairo_set_color(gc, gc->pcolor.str); + gdk_cairo_set_source_rgba(cr, &gc->color); + + /* negative line width means "unit is pixels", so -1 is "1 pixel", -5 is "5 pixels", regardless of the zoom. */ + if (gc->width <= 0) + cairo_set_line_width(cr, 1.0 - gc->width); + else + cairo_set_line_width(cr, Vz(gc->width)); + + //ghid_cairo_set_line_cap(gc, (pcb_cap_style_t) gc->cap); + cairo_set_line_cap(cr, gc->cap); + cairo_set_line_join(cr, gc->join); + + + //if (!gc->gc) { + // gc->gc = gdk_gc_new(window); + // ghid_cairo_set_color(gc, gc->colorname); + // ghid_cairo_set_line_width(gc, gc->width); + // ghid_cairo_set_line_cap(gc, (pcb_cap_style_t) gc->cap); + // ghid_cairo_set_draw_xor(gc, gc->xor_mask); + // gdk_gc_set_clip_origin(gc->gc, 0, 0); + //} + //if (gc->mask_seq != mask_seq) { + // if (mask_seq) + // gdk_gc_set_clip_mask(gc->gc, gport->mask); + // else + // set_clip(priv, gc->gc); + // gc->mask_seq = mask_seq; + //} + //priv->u_gc = WHICH_GC(gc); + return 1; +} + +static void ghid_cairo_draw_line(pcb_hid_gc_t gc, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2) +{ + double dx1, dy1, dx2, dy2; + render_priv_t *priv = gport->render_priv; + + dx1 = Vx((double) x1); + dy1 = Vy((double) y1); + dx2 = Vx((double) x2); + dy2 = Vy((double) y2); + + if (!pcb_line_clip + (0, 0, gport->view.canvas_width, gport->view.canvas_height, &dx1, &dy1, &dx2, &dy2, gc->width / gport->view.coord_per_px)) + return; + + USE_GC(gc); + cr_draw_line(priv->cr, FALSE, dx1, dy1, dx2, dy2); + //gdk_draw_line(gport->drawable, priv->u_gc, dx1, dy1, dx2, dy2); +} + +/* Draws an arc from center (cx, cy), cx>0 to the right, cy>0 to the bottom, using + xradius on X axis, and yradius on Y axis, sweeping a delta_angle from start_angle. + + Angles (in degres) originate at 9 o'clock and are positive CCW (counter clock wise). + delta_angle sweeps the angle from start_angle, CW if negative. */ +static void ghid_cairo_draw_arc(pcb_hid_gc_t gc, pcb_coord_t cx, pcb_coord_t cy, + pcb_coord_t xradius, pcb_coord_t yradius, pcb_angle_t start_angle, pcb_angle_t delta_angle) +{ + double w, h, radius, angle1, angle2; + render_priv_t *priv = gport->render_priv; + + w = gport->view.canvas_width * gport->view.coord_per_px; + h = gport->view.canvas_height * gport->view.coord_per_px; + radius = (xradius > yradius) ? xradius : yradius; + if (SIDE_X(cx) < gport->view.x0 - radius + || SIDE_X(cx) > gport->view.x0 + w + radius + || SIDE_Y(cy) < gport->view.y0 - radius || SIDE_Y(cy) > gport->view.y0 + h + radius) + return; + + USE_GC(gc); + + if ((delta_angle > 360.0) || (delta_angle < -360.0)) { + start_angle = 0; + delta_angle = 360; + } + + if (conf_core.editor.view.flip_x) { + start_angle = 180 - start_angle; + delta_angle = -delta_angle; + } + if (conf_core.editor.view.flip_y) { + start_angle = -start_angle; + delta_angle = -delta_angle; + } + /* make sure we fall in the -180 to +180 range */ + start_angle = pcb_normalize_angle(start_angle); + if (start_angle >= 180) + start_angle -= 360; + + /* cairo lib. originates angles at 3 o'clock, positive traveling CW, requires angle1 < angle2 */ + angle1 = (180.0 - start_angle); + angle2 = (delta_angle < 0) ? (angle1 - delta_angle) : angle1; + if (delta_angle > 0) { + angle1 = (180.0 - start_angle - delta_angle); + } + angle1 *= (M_PI / 180.0); + angle2 *= (M_PI / 180.0); + cairo_save(priv->cr); +TODO("gtk3: this will draw an arc of a circle, not an ellipse! Explore matrix transformation here.") + cairo_arc(priv->cr, pcb_round(Vxd(cx)), pcb_round(Vyd(cy)), Vzd(radius), angle1, angle2); + cairo_stroke(priv->cr); + cairo_restore(priv->cr); + //gdk_draw_arc(gport->drawable, priv->u_gc, 0, + // pcb_round(Vxd(cx) - Vzd(xradius) + 0.5), pcb_round(Vyd(cy) - Vzd(yradius) + 0.5), + // pcb_round(vrx2), pcb_round(vry2), (start_angle + 180) * 64, delta_angle * 64); +} + +static void cr_draw_rect(pcb_hid_gc_t gc, int fill, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2) +{ + gint w, h, lw; + render_priv_t *priv = gport->render_priv; + + if (priv->cr == NULL) + return; + + lw = gc->width; + w = gport->view.canvas_width * gport->view.coord_per_px; + h = gport->view.canvas_height * gport->view.coord_per_px; + + if ((SIDE_X(x1) < gport->view.x0 - lw && SIDE_X(x2) < gport->view.x0 - lw) + || (SIDE_X(x1) > gport->view.x0 + w + lw && SIDE_X(x2) > gport->view.x0 + w + lw) + || (SIDE_Y(y1) < gport->view.y0 - lw && SIDE_Y(y2) < gport->view.y0 - lw) + || (SIDE_Y(y1) > gport->view.y0 + h + lw && SIDE_Y(y2) > gport->view.y0 + h + lw)) + return; + + x1 = Vx(x1); + y1 = Vy(y1); + x2 = Vx(x2); + y2 = Vy(y2); + + if (x1 > x2) { + gint xt = x1; + x1 = x2; + x2 = xt; + } + if (y1 > y2) { + gint yt = y1; + y1 = y2; + y2 = yt; + } + + USE_GC(gc); + cairo_rectangle(priv->cr, x1, y1, x2 - x1 + 1, y2 - y1 + 1); + //gdk_draw_rectangle(gport->drawable, priv->u_gc, FALSE, x1, y1, x2 - x1 + 1, y2 - y1 + 1); + + if (fill) + cairo_fill(priv->cr); + else + cairo_stroke(priv->cr); +} + +static void cr_paint_from_surface(cairo_t * cr, cairo_surface_t * surface) +{ + cairo_set_source_surface(cr, surface, 0, 0); + cairo_set_operator(cr, CAIRO_OPERATOR_OVER); + cairo_paint_with_alpha(cr, 1.0); +} + +static void ghid_cairo_draw_rect(pcb_hid_gc_t gc, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2) +{ + cr_draw_rect(gc, FALSE, x1, y1,x2, y2); +} + +static void ghid_cairo_fill_rect(pcb_hid_gc_t gc, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2) +{ + cr_draw_rect(gc, TRUE, x1, y1,x2, y2); +} + +static void ghid_cairo_fill_circle(pcb_hid_gc_t gc, pcb_coord_t cx, pcb_coord_t cy, pcb_coord_t radius) +{ + gint w, h, vr; + render_priv_t *priv = gport->render_priv; + + if (priv->cr == NULL) + return; + + w = gport->view.canvas_width * gport->view.coord_per_px; + h = gport->view.canvas_height * gport->view.coord_per_px; + if (SIDE_X(cx) < gport->view.x0 - radius + || SIDE_X(cx) > gport->view.x0 + w + radius + || SIDE_Y(cy) < gport->view.y0 - radius || SIDE_Y(cy) > gport->view.y0 + h + radius) + return; + + USE_GC(gc); + vr = Vz(radius); + cairo_arc(priv->cr, Vx(cx), Vy(cy), vr, 0.0, 2 * M_PI); + cairo_fill(priv->cr); + //gdk_draw_arc(gport->drawable, priv->u_gc, TRUE, Vx(cx) - vr, Vy(cy) - vr, vr * 2, vr * 2, 0, 360 * 64); +} + +/* Intentional code duplication from ghid_cairo_fill_polygon_offs(), for performance */ +static void ghid_cairo_fill_polygon(pcb_hid_gc_t gc, int n_coords, pcb_coord_t * x, pcb_coord_t * y) +{ + int i; + render_priv_t *priv = gport->render_priv; + cairo_t *cr = priv->cr; + int _x, _y; + + if (priv->cr == NULL) + return; + + USE_GC(gc); + + for (i = 0; i < n_coords; i++) { + _x = Vx(x[i]); + _y = Vy(y[i]); + if (i == 0) + cairo_move_to(cr, _x, _y); + else + cairo_line_to(cr, _x, _y); + } + cairo_fill(cr); +} + +static void ghid_cairo_fill_polygon_offs(pcb_hid_gc_t gc, int n_coords, pcb_coord_t *x, pcb_coord_t *y, pcb_coord_t dx, pcb_coord_t dy) +{ + int i; + render_priv_t *priv = gport->render_priv; + cairo_t *cr = priv->cr; + int _x, _y; + + if (priv->cr == NULL) + return; + + USE_GC(gc); + + for (i = 0; i < n_coords; i++) { + _x = Vx(x[i]); + _y = Vy(y[i]); + if (i == 0) + cairo_move_to(cr, _x + Vz(dx), _y + Vz(dy)); + else + cairo_line_to(cr, _x + Vz(dx), _y + Vz(dy)); + } + cairo_fill(cr); +} + +/* Fills the drawing with only bg_color */ +static void erase_with_background_color(cairo_t * cr, GdkRGBA * bg_color) +{ + gdk_cairo_set_source_rgba(cr, bg_color); + cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); + cairo_paint_with_alpha(cr, 1.0); +} + +static void redraw_region(GdkRectangle * rect) +{ + int eleft, eright, etop, ebottom; + pcb_hid_expose_ctx_t ctx; + render_priv_t *priv = gport->render_priv; + + if (priv->cr_drawing_area == NULL) + return; + + if (rect != NULL) { + priv->clip_rect = *rect; + priv->clip = pcb_true; + } + else { + priv->clip_rect.x = 0; + priv->clip_rect.y = 0; + priv->clip_rect.width = gport->view.canvas_width; + priv->clip_rect.height = gport->view.canvas_height; + priv->clip = pcb_false; + } + + //set_clip(priv, priv->bg_gc); + //set_clip(priv, priv->offlimits_gc); + //set_clip(priv, priv->mask_gc); + //set_clip(priv, priv->grid_gc); + + ctx.view.X1 = MIN(Px(priv->clip_rect.x), Px(priv->clip_rect.x + priv->clip_rect.width + 1)); + ctx.view.Y1 = MIN(Py(priv->clip_rect.y), Py(priv->clip_rect.y + priv->clip_rect.height + 1)); + ctx.view.X2 = MAX(Px(priv->clip_rect.x), Px(priv->clip_rect.x + priv->clip_rect.width + 1)); + ctx.view.Y2 = MAX(Py(priv->clip_rect.y), Py(priv->clip_rect.y + priv->clip_rect.height + 1)); + + ctx.view.X1 = MAX(0, MIN(PCB->MaxWidth, ctx.view.X1)); + ctx.view.X2 = MAX(0, MIN(PCB->MaxWidth, ctx.view.X2)); + ctx.view.Y1 = MAX(0, MIN(PCB->MaxHeight, ctx.view.Y1)); + ctx.view.Y2 = MAX(0, MIN(PCB->MaxHeight, ctx.view.Y2)); + + eleft = Vx(0); + eright = Vx(PCB->MaxWidth); + etop = Vy(0); + ebottom = Vy(PCB->MaxHeight); + if (eleft > eright) { + int tmp = eleft; + eleft = eright; + eright = tmp; + } + if (etop > ebottom) { + int tmp = etop; + etop = ebottom; + ebottom = tmp; + } + + /* Paints only on the drawing_area */ + priv->cr = priv->cr_drawing_area; + priv->cr_target = priv->cr_drawing_area; + + erase_with_background_color(priv->cr, &priv->bg_color); + + gdk_cairo_set_source_rgba(priv->cr, &priv->offlimits_color); + if (eleft > 0) { + cairo_rectangle(priv->cr, 0.0, 0.0, eleft, gport->view.canvas_height); + } + else + eleft = 0; + if (eright < gport->view.canvas_width) { + cairo_rectangle(priv->cr, eright, 0.0, gport->view.canvas_width - eright, gport->view.canvas_height); + } + else + eright = gport->view.canvas_width; + if (etop > 0) { + cairo_rectangle(priv->cr, eleft, 0.0, eright - eleft + 1, etop); + } + else + etop = 0; + if (ebottom < gport->view.canvas_height) { + cairo_rectangle(priv->cr, eleft, ebottom, eright - eleft + 1, gport->view.canvas_height - ebottom); + } + else + ebottom = gport->view.canvas_height; + + cairo_fill(priv->cr); + //gdk_draw_rectangle(gport->drawable, priv->bg_gc, 1, eleft, etop, eright - eleft + 1, ebottom - etop + 1); + + ghid_cairo_draw_bg_image(); + + pcb_hid_expose_all(pcb_gui, &ctx, NULL); + ghid_cairo_draw_grid(); + + /* Draws "GUI" information on top of design */ + priv->cr = priv->cr_drawing_area; + pcb_draw_attached(0); + pcb_draw_mark(0); + + priv->clip = pcb_false; + + /* Rest the clip for bg_gc, as it is used outside this function */ + //gdk_gc_set_clip_mask(priv->bg_gc, NULL); + ghid_cairo_screen_update(); +} + +static void ghid_cairo_invalidate_lr(pcb_coord_t left, pcb_coord_t right, pcb_coord_t top, pcb_coord_t bottom) +{ + int dleft, dright, dtop, dbottom; + int minx, maxx, miny, maxy; + GdkRectangle rect; + + dleft = Vx(left); + dright = Vx(right); + dtop = Vy(top); + dbottom = Vy(bottom); + + minx = MIN(dleft, dright); + maxx = MAX(dleft, dright); + miny = MIN(dtop, dbottom); + maxy = MAX(dtop, dbottom); + + rect.x = minx; + rect.y = miny; + rect.width = maxx - minx; + rect.height = maxy - miny; + + redraw_region(&rect); +} + +static void ghid_cairo_invalidate_all() +{ + if (ghidgui && ghidgui->topwin.menu.menu_bar) { + redraw_region(NULL); + } +} + +static void ghid_cairo_notify_crosshair_change(pcb_bool changes_complete) +{ + render_priv_t *priv = gport->render_priv; + + /* We sometimes get called before the GUI is up */ + if (gport->drawing_area == NULL) + return; + + /* Keeps track of calls (including XOR draw mode), and draws only when complete and final. */ + if (changes_complete) + priv->attached_invalidate_depth--; + else + priv->attached_invalidate_depth = 1 + priv->xor_mode; + + if (changes_complete && gport->drawing_area != NULL && priv->attached_invalidate_depth <= 0) { + /* Queues a GTK redraw when changes are complete */ + ghid_cairo_invalidate_all(); + priv->attached_invalidate_depth = 0; + } +} + +static void ghid_cairo_notify_mark_change(pcb_bool changes_complete) +{ + render_priv_t *priv = gport->render_priv; + + /* We sometimes get called before the GUI is up */ + if (gport->drawing_area == NULL) + return; + + if (changes_complete) + priv->mark_invalidate_depth--; + + if (priv->mark_invalidate_depth < 0) { + priv->mark_invalidate_depth = 0; + /* A mismatch of changes_complete == pcb_false and == pcb_true notifications + is not expected to occur, but we will try to handle it gracefully. + As we know the mark will have been shown already, we must + repaint the entire view to be sure not to leave an artefact. + */ + ghid_cairo_invalidate_all(); + return; + } + + if (priv->mark_invalidate_depth == 0) + pcb_draw_mark(0); + + if (!changes_complete) { + priv->mark_invalidate_depth++; + } + else if (gport->drawing_area != NULL) { + /* Queue a GTK expose when changes are complete */ + ghid_draw_area_update(gport, NULL); + } +} + +static void draw_right_cross(cairo_t * cr, gint x, gint y) +{ + //GdkWindow *window = gtk_widget_get_window(gport->drawing_area); + + cr_draw_line(cr, FALSE, x, 0, x, gport->view.canvas_height); + cr_draw_line(cr, FALSE, 0, y, gport->view.canvas_width, y); + //gdk_draw_line(window, xor_gc, x, 0, x, gport->view.canvas_height); + //gdk_draw_line(window, xor_gc, 0, y, gport->view.canvas_width, y); +} + +static void draw_slanted_cross(cairo_t * xor_gc, gint x, gint y) +{ + //GdkWindow *window = gtk_widget_get_window(gport->drawing_area); + gint x0, y0, x1, y1; + + x0 = x + (gport->view.canvas_height - y); + x0 = MAX(0, MIN(x0, gport->view.canvas_width)); + x1 = x - y; + x1 = MAX(0, MIN(x1, gport->view.canvas_width)); + y0 = y + (gport->view.canvas_width - x); + y0 = MAX(0, MIN(y0, gport->view.canvas_height)); + y1 = y - x; + y1 = MAX(0, MIN(y1, gport->view.canvas_height)); + cr_draw_line(gport->render_priv->cr, FALSE, x0, y0, x1, y1); + //gdk_draw_line(window, xor_gc, x0, y0, x1, y1); + + x0 = x - (gport->view.canvas_height - y); + x0 = MAX(0, MIN(x0, gport->view.canvas_width)); + x1 = x + y; + x1 = MAX(0, MIN(x1, gport->view.canvas_width)); + y0 = y + x; + y0 = MAX(0, MIN(y0, gport->view.canvas_height)); + y1 = y - (gport->view.canvas_width - x); + y1 = MAX(0, MIN(y1, gport->view.canvas_height)); + cr_draw_line(gport->render_priv->cr, FALSE, x0, y0, x1, y1); + //gdk_draw_line(window, xor_gc, x0, y0, x1, y1); +} + +static void draw_dozen_cross(cairo_t * xor_gc, gint x, gint y) +{ + //GdkWindow *window = gtk_widget_get_window(gport->drawing_area); + gint x0, y0, x1, y1; + gdouble tan60 = sqrt(3); + + x0 = x + (gport->view.canvas_height - y) / tan60; + x0 = MAX(0, MIN(x0, gport->view.canvas_width)); + x1 = x - y / tan60; + x1 = MAX(0, MIN(x1, gport->view.canvas_width)); + y0 = y + (gport->view.canvas_width - x) * tan60; + y0 = MAX(0, MIN(y0, gport->view.canvas_height)); + y1 = y - x * tan60; + y1 = MAX(0, MIN(y1, gport->view.canvas_height)); + cr_draw_line(gport->render_priv->cr, FALSE, x0, y0, x1, y1); + //gdk_draw_line(window, xor_gc, x0, y0, x1, y1); + + x0 = x + (gport->view.canvas_height - y) * tan60; + x0 = MAX(0, MIN(x0, gport->view.canvas_width)); + x1 = x - y * tan60; + x1 = MAX(0, MIN(x1, gport->view.canvas_width)); + y0 = y + (gport->view.canvas_width - x) / tan60; + y0 = MAX(0, MIN(y0, gport->view.canvas_height)); + y1 = y - x / tan60; + y1 = MAX(0, MIN(y1, gport->view.canvas_height)); + cr_draw_line(gport->render_priv->cr, FALSE, x0, y0, x1, y1); + //gdk_draw_line(window, xor_gc, x0, y0, x1, y1); + + x0 = x - (gport->view.canvas_height - y) / tan60; + x0 = MAX(0, MIN(x0, gport->view.canvas_width)); + x1 = x + y / tan60; + x1 = MAX(0, MIN(x1, gport->view.canvas_width)); + y0 = y + x * tan60; + y0 = MAX(0, MIN(y0, gport->view.canvas_height)); + y1 = y - (gport->view.canvas_width - x) * tan60; + y1 = MAX(0, MIN(y1, gport->view.canvas_height)); + cr_draw_line(gport->render_priv->cr, FALSE, x0, y0, x1, y1); + //gdk_draw_line(window, xor_gc, x0, y0, x1, y1); + + x0 = x - (gport->view.canvas_height - y) * tan60; + x0 = MAX(0, MIN(x0, gport->view.canvas_width)); + x1 = x + y * tan60; + x1 = MAX(0, MIN(x1, gport->view.canvas_width)); + y0 = y + x / tan60; + y0 = MAX(0, MIN(y0, gport->view.canvas_height)); + y1 = y - (gport->view.canvas_width - x) / tan60; + y1 = MAX(0, MIN(y1, gport->view.canvas_height)); + cr_draw_line(gport->render_priv->cr, FALSE, x0, y0, x1, y1); + //gdk_draw_line(window, xor_gc, x0, y0, x1, y1); +} + +static void draw_crosshair(cairo_t * xor_gc, gint x, gint y) +{ + static enum pcb_crosshair_shape_e prev = pcb_ch_shape_basic; + + if (gport->view.crosshair_x < 0 || !ghidgui->topwin.active || !gport->view.has_entered) + return; + + draw_right_cross(xor_gc, x, y); + if (prev == pcb_ch_shape_union_jack) + draw_slanted_cross(xor_gc, x, y); + if (prev == pcb_ch_shape_dozen) + draw_dozen_cross(xor_gc, x, y); + prev = pcb_crosshair.shape; +} + +static void show_crosshair(gboolean paint_new_location) +{ + render_priv_t *priv = gport->render_priv; + //GdkWindow *window = gtk_widget_get_window(gport->drawing_area); + //GtkStyle *style = gtk_widget_get_style(gport->drawing_area); + gint x, y; + static gint x_prev = -1, y_prev = -1; + //static cairo_t *xor_gc; + //static GdkColor cross_color; + cairo_t *cr; + + if (gport->view.crosshair_x < 0 || !ghidgui->topwin.active || !gport->view.has_entered) { + x_prev = y_prev = -1; /* if leaving the drawing area, invalidate last known coord to make sure we redraw on reenter, even on the same coords */ + return; + } + +TODO("gtk3: when CrossColor changed from config") + map_color_string(conf_core.appearance.color.cross.str, &priv->crosshair_color); + //cr = priv->cr_drawing_area; + cr = priv->cr; + gdk_cairo_set_source_rgba(cr, &priv->crosshair_color); + cairo_set_line_width(cr, 1.0); + + //if (!xor_gc) { + // xor_gc = gdk_gc_new(window); + // gdk_gc_copy(xor_gc, style->white_gc); + // gdk_gc_set_function(xor_gc, GDK_XOR); + // gdk_gc_set_clip_origin(xor_gc, 0, 0); + // set_clip(priv, xor_gc); +TODO("gtk3:FIXME: when CrossColor changed from config") + // map_color_string(conf_core.appearance.color.cross, &cross_color); + //} + x = Vx(gport->view.crosshair_x); + y = Vy(gport->view.crosshair_y); + + //gdk_gc_set_foreground(xor_gc, &cross_color); + + if (x_prev >= 0 && !paint_new_location) + draw_crosshair(cr, x_prev, y_prev); + + if (x >= 0 && paint_new_location) { + draw_crosshair(cr, x, y); + x_prev = x; + y_prev = y; + } + else + x_prev = y_prev = -1; +} + +static void ghid_cairo_init_renderer(int *argc, char ***argv, void *vport) +{ + GHidPort *port = vport; + + /* Init any GC's required */ + port->render_priv = g_new0(render_priv_t, 1); + port->render_priv->cr = NULL; + port->render_priv->surf_da = NULL; + port->render_priv->cr_drawing_area = NULL; +} + +static void ghid_cairo_shutdown_renderer(void *vport) +{ + GHidPort *port = vport; + render_priv_t *priv = port->render_priv; + + cairo_surface_destroy(priv->surf_da); + priv->surf_da = NULL; + cairo_destroy(priv->cr_drawing_area); + priv->cr_drawing_area = NULL; + priv->cr = NULL; + + g_free(port->render_priv); + port->render_priv = NULL; +} + +static void ghid_cairo_init_drawing_widget(GtkWidget * widget, void *vport) +{ +} + +/* Callback function only applied to drawing_area, after some resizing or initialisation. */ +static void ghid_cairo_drawing_area_configure_hook(void *vport) +{ + GHidPort *port = vport; + static int done_once = 0; + render_priv_t *priv = port->render_priv; + cairo_t *cr; + + gport->drawing_allowed = pcb_true; + + if (!done_once) { + //priv->bg_gc = gdk_gc_new(port->drawable); + //gdk_gc_set_foreground(priv->bg_gc, &port->bg_color); + //gdk_gc_set_clip_origin(priv->bg_gc, 0, 0); + // + //priv->offlimits_gc = gdk_gc_new(port->drawable); + //gdk_gc_set_foreground(priv->offlimits_gc, &port->offlimits_color); + //gdk_gc_set_clip_origin(priv->offlimits_gc, 0, 0); + + if (!map_color_string(conf_core.appearance.color.background.str, &priv->bg_color)) + map_color_string("white", &priv->bg_color); + + if (!map_color_string(conf_core.appearance.color.off_limit.str, &priv->offlimits_color)) + map_color_string("white", &priv->offlimits_color); + + if (!map_color_string(conf_core.appearance.color.grid.str, &priv->grid_color)) + map_color_string("blue", &priv->grid_color); + //set_special_grid_color(); + + //if (port->mask) { + // gdk_pixmap_unref(port->mask); + // port->mask = gdk_pixmap_new(0, port->view.canvas_width, port->view.canvas_height, 1); + //} + done_once = 1; + } + + /* Creates a single cairo surface/context for off-line painting */ + cr_create_similar_surface_and_context(&priv->surf_da, &priv->cr_drawing_area, port); + cr_create_similar_surface_and_context(&priv->surf_layer, &priv->cr_layer, port); + priv->cr = priv->cr_drawing_area; +} + +/* GtkDrawingArea -> GtkWidget "draw" signal Call-Back function */ +static gboolean ghid_cairo_drawing_area_expose_cb(GtkWidget * widget, pcb_gtk_expose_t * p, void *vport) +{ + GHidPort *port = vport; + render_priv_t *priv = port->render_priv; + //GdkWindow *window = gtk_widget_get_window(gport->drawing_area); + + //gdk_draw_drawable(window, priv->bg_gc, port->pixmap, + // ev->area.x, ev->area.y, ev->area.x, ev->area.y, ev->area.width, ev->area.height); + + cr_paint_from_surface(p, priv->surf_da); + + priv->cr = p; + show_crosshair(TRUE); + priv->cr = priv->cr_drawing_area; + + return FALSE; +} + +static void ghid_cairo_screen_update(void) +{ + render_priv_t *priv = gport->render_priv; + //GdkWindow *window = gtk_widget_get_window(gport->drawing_area); + + if (priv->cr == NULL) + return; + + //gdk_draw_drawable(window, priv->bg_gc, gport->pixmap, 0, 0, 0, 0, gport->view.canvas_width, gport->view.canvas_height); + //show_crosshair(TRUE); + gtk_widget_queue_draw(gport->drawing_area); +} + +static void ghid_cairo_port_drawing_realize_cb(GtkWidget * widget, gpointer data) +{ +} + +static gboolean ghid_cairo_preview_expose(GtkWidget * widget, pcb_gtk_expose_t * p, + pcb_hid_expose_t expcall, pcb_hid_expose_ctx_t *ctx) +{ + //GdkWindow *window = gtk_widget_get_window(widget); + //GdkDrawable *save_drawable; + GtkAllocation allocation; /* Assuming widget is a drawing widget, get the Rectangle allowed for drawing. */ + pcb_gtk_view_t save_view; + int save_width, save_height; + double xz, yz, vw, vh; + render_priv_t *priv = gport->render_priv; + pcb_coord_t ox1 = ctx->view.X1, oy1 = ctx->view.Y1, ox2 = ctx->view.X2, oy2 = ctx->view.Y2; + + vw = ctx->view.X2 - ctx->view.X1; + vh = ctx->view.Y2 - ctx->view.Y1; + + /* Setup drawable and zoom factor for drawing routines + */ + //save_drawable = gport->drawable; + save_view = gport->view; + save_width = gport->view.canvas_width; + save_height = gport->view.canvas_height; + + gtk_widget_get_allocation(widget, &allocation); + xz = vw / (double) allocation.width; + yz = vh / (double) allocation.height; + if (xz > yz) + gport->view.coord_per_px = xz; + else + gport->view.coord_per_px = yz; + + //gport->drawable = window; + gport->view.canvas_width = allocation.width; + gport->view.canvas_height = allocation.height; + gport->view.width = allocation.width * gport->view.coord_per_px; + gport->view.height = allocation.height * gport->view.coord_per_px; + gport->view.x0 = (vw - gport->view.width) / 2 + ctx->view.X1; + gport->view.y0 = (vh - gport->view.height) / 2 + ctx->view.Y1; + + PCB_GTK_PREVIEW_TUNE_EXTENT(ctx, allocation); + + /* Change current pointer to draw in this widget, draws, then come back to pointer to drawing_area. */ + priv->cr_target = p; + priv->cr = p; + cairo_save(p); + /* clear background */ + erase_with_background_color(p, &priv->bg_color); + /* calls the off-line drawing routine */ + expcall(>k3_cairo_hid, ctx); + cairo_restore(p); + priv->cr = priv->cr_drawing_area; + //gport->drawable = save_drawable; + + /* restore the original context and priv */ + ctx->view.X1 = ox1; ctx->view.X2 = ox2; ctx->view.Y1 = oy1; ctx->view.Y2 = oy2; + gport->view = save_view; + gport->view.canvas_width = save_width; + gport->view.canvas_height = save_height; + + return FALSE; +} + +static GtkWidget *ghid_cairo_new_drawing_widget(pcb_gtk_common_t *common) +{ + GtkWidget *w = gtk_drawing_area_new(); + + g_signal_connect(G_OBJECT(w), "draw", G_CALLBACK(common->drawing_area_expose), common->gport); + + return w; +} + + +void ghid_cairo_install(pcb_gtk_common_t * common, pcb_hid_t * hid) +{ + if (common != NULL) { + common->new_drawing_widget = ghid_cairo_new_drawing_widget; + common->init_drawing_widget = ghid_cairo_init_drawing_widget; + common->drawing_realize = ghid_cairo_port_drawing_realize_cb; + common->drawing_area_expose = ghid_cairo_drawing_area_expose_cb; + common->preview_expose = ghid_cairo_preview_expose; + common->invalidate_all = ghid_cairo_invalidate_all; + common->set_special_colors = ghid_cairo_set_special_colors; + common->init_renderer = ghid_cairo_init_renderer; + common->screen_update = ghid_cairo_screen_update; + common->draw_grid_local = ghid_cairo_draw_grid_local; + common->drawing_area_configure_hook = ghid_cairo_drawing_area_configure_hook; + common->shutdown_renderer = ghid_cairo_shutdown_renderer; + common->get_color_name = get_color_name; + common->map_color_string = map_color_string; + } + + if (hid != NULL) { + hid->invalidate_lr = ghid_cairo_invalidate_lr; + hid->invalidate_all = ghid_cairo_invalidate_all; + hid->notify_crosshair_change = ghid_cairo_notify_crosshair_change; + hid->notify_mark_change = ghid_cairo_notify_mark_change; + hid->set_layer_group = ghid_cairo_set_layer_group; + hid->end_layer = ghid_cairo_end_layer_group; + hid->make_gc = ghid_cairo_make_gc; + hid->destroy_gc = ghid_cairo_destroy_gc; + hid->render_burst = ghid_cairo_render_burst; + hid->set_drawing_mode = ghid_cairo_set_drawing_mode; + hid->set_color = ghid_cairo_set_color; + hid->set_line_cap = ghid_cairo_set_line_cap; + hid->set_line_width = ghid_cairo_set_line_width; + hid->set_draw_xor = ghid_cairo_set_draw_xor; + hid->draw_line = ghid_cairo_draw_line; + hid->draw_arc = ghid_cairo_draw_arc; + hid->draw_rect = ghid_cairo_draw_rect; + hid->fill_circle = ghid_cairo_fill_circle; + hid->fill_polygon = ghid_cairo_fill_polygon; + hid->fill_polygon_offs = ghid_cairo_fill_polygon_offs; + hid->fill_rect = ghid_cairo_fill_rect; + } +} Index: tags/2.1.2/src_plugins/hid_gtk3_cairo/gtkhid-main.c =================================================================== --- tags/2.1.2/src_plugins/hid_gtk3_cairo/gtkhid-main.c (nonexistent) +++ tags/2.1.2/src_plugins/hid_gtk3_cairo/gtkhid-main.c (revision 24813) @@ -0,0 +1,70 @@ +#include "config.h" + +#include + +#include "error.h" +#include "pcb-printf.h" +#include "plugins.h" +#include "hid_init.h" +#include "conf_core.h" + +#include "../src_plugins/lib_gtk_common/glue.h" +#include "../src_plugins/lib_gtk_common/lib_gtk_config.h" +#include "../src_plugins/lib_gtk_common/hid_gtk_conf.h" + +#include "../src_plugins/lib_gtk_hid/gui.h" +#include "../src_plugins/lib_gtk_hid/glue_common.h" +#include "../src_plugins/lib_gtk_hid/glue_hid.h" +#include "../src_plugins/lib_gtk_hid/glue_conf.h" +#include "../src_plugins/lib_gtk_hid/glue_event.h" +#include "../src_plugins/lib_gtk_hid/glue_win32.h" +#include "../src_plugins/lib_gtk_hid/common.h" +#include "../src_plugins/lib_gtk_hid/render.h" + +const char *ghid_cairo_cookie = "gtk3 hid, cairo"; +const char *ghid_cairo_menu_cookie = "gtk3 hid menu, cairo"; + +pcb_hid_t gtk3_cairo_hid; + +void ghid_cairo_install(pcb_gtk_common_t * common, pcb_hid_t * hid); + +int gtk3_cairo_parse_arguments(int *argc, char ***argv) +{ + ghid_cairo_install(&ghidgui->common, NULL); + return gtkhid_parse_arguments(argc, argv); +} + +int pplg_check_ver_hid_gtk3_cairo(int ver_needed) { return 0; } + +void pplg_uninit_hid_gtk3_cairo(void) +{ + pcb_event_unbind_allcookie(ghid_cairo_cookie); + conf_hid_unreg(ghid_cairo_cookie); + conf_hid_unreg(ghid_cairo_menu_cookie); +} + +int pplg_init_hid_gtk3_cairo(void) +{ + PCB_API_CHK_VER; + + ghid_win32_init(); + + ghid_glue_hid_init(>k3_cairo_hid); + ghid_glue_common_init(); + + gtk3_cairo_hid.parse_arguments = gtk3_cairo_parse_arguments; + ghid_cairo_install(NULL, >k3_cairo_hid); + + gtk3_cairo_hid.name = "gtk3_cairo"; + gtk3_cairo_hid.description = "Gtk3 - The Gimp Toolkit, with cairo rendering"; + + ghidgui->topwin.menu.ghid_menuconf_id = conf_hid_reg(ghid_cairo_menu_cookie, NULL); + ghidgui->topwin.menu.confchg_checkbox = ghid_confchg_checkbox; + ghid_conf_regs(ghid_cairo_cookie); + + pcb_hid_register_hid(>k3_cairo_hid); + + glue_event_init(ghid_cairo_cookie); + + return 0; +} Index: tags/2.1.2/src_plugins/hid_gtk3_cairo/hid_gtk3_cairo.pup =================================================================== --- tags/2.1.2/src_plugins/hid_gtk3_cairo/hid_gtk3_cairo.pup (nonexistent) +++ tags/2.1.2/src_plugins/hid_gtk3_cairo/hid_gtk3_cairo.pup (revision 24813) @@ -0,0 +1,8 @@ +$class hid +$short #GTK3 GUI, cairo render +$long GUI: the GTK3 HID, using cairo for rendering +$state WIP +default disable-all +dep lib_gtk_common +dep lib_gtk_hid +autoload 1 Index: tags/2.1.2/src_plugins/hid_lesstif/FillBox.c =================================================================== --- tags/2.1.2/src_plugins/hid_lesstif/FillBox.c (nonexistent) +++ tags/2.1.2/src_plugins/hid_lesstif/FillBox.c (revision 24813) @@ -0,0 +1,984 @@ +/* + * FillBox widget for Motif + * + * Copyright (c) 1987-2012, The Open Group. All rights reserved. + * Copyright (c) 2019, Tibor 'Igor2' Palinkas + * (widget code based on Exm Grid) + * + * These libraries and programs are free software; you can + * redistribute them and/or modify them under the terms of the GNU + * Lesser General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * These libraries and programs are distributed in the hope that + * they will be useful, but WITHOUT ANY WARRANTY; without even the + * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with these librararies and programs; if not, write + * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth + * Floor, Boston, MA 02110-1301 USA + */ + +/****************************************************************************** + * + * FillBox.c - PxmFillBox widget. This widget manages its children in + * a horizontal or vertical box. Any of the child widget + * may have the fill flag set to get a share of excess space. + * +******************************************************************************/ + +#include "config.h" + +/* Include appropriate header files. */ +#include "FillBoxP.h" /* private header file for the PxmFillBox widget */ +#include /* for gadget management functions */ + +#ifdef HAVE_XM_TRAIT +#include /* for trait access functions */ +#include /* for XmQTdialogSavvy trait */ +#include /* for XmQTspecifyRenderTable trait */ +#endif + +#include "pxm_helper.h" + +/* Define macros. */ +#define Max(x, y) (((x) > (y)) ? (x) : (y)) +#define WARNING_TOO_MANY_ROWS "Too many rows specified for PxmFillBox.\n" +#define WARNING_TOO_MANY_COLUMNS "Too many columns specified for PxmFillBox.\n" + + +/* Declare static functions. */ +static void ClassPartInitialize(WidgetClass widgetClass); +static void Initialize(Widget request_w, Widget new_w, ArgList args, Cardinal *num_args); +static void Destroy(Widget wid); +static void Resize(Widget w); +static void Redisplay(Widget w, XEvent *event, Region region); +static Boolean SetValues(Widget old_w, Widget request_w, Widget new_w, ArgList args, Cardinal *num_args); +static void SetValuesAlmost(Widget cw, Widget nw, XtWidgetGeometry *request, XtWidgetGeometry *reply); +static XtGeometryResult QueryGeometry(Widget w, XtWidgetGeometry *request, XtWidgetGeometry *reply); +static XtGeometryResult GeometryManager(Widget w, XtWidgetGeometry *request, XtWidgetGeometry *reply); +static void ChangeManaged(Widget w); +static Boolean ConstraintSetValues(Widget cw, Widget rw, Widget nw, ArgList args, Cardinal *num_args); +static void Layout(Widget wid, Widget instigator); +static void CalcSize(Widget wid, Widget instigator, Dimension *fillBoxWidth, Dimension *fillBoxHeight); +static Boolean NeedRelayout(Widget new, Widget cur); + +#ifdef HAVE_XM_TRAIT +static void CallMapUnmap(Widget wid, Boolean map_unmap); +static XmRenderTable GetTable(Widget wid, XtEnum type); +#endif + +/* No translations and no actions. */ + + +/* Define the resources for the PxmFillBox widget. */ +static XtResource resources[] = { + { + XmNmarginWidth, + XmCMarginWidth, + XmRHorizontalDimension, + sizeof(Dimension), + XtOffsetOf(PxmFillBoxRec, fillBox.margin_width), + XmRImmediate, + (XtPointer) 10} + , + { + XmNmarginHeight, + XmCMarginHeight, + XmRVerticalDimension, + sizeof(Dimension), + XtOffsetOf(PxmFillBoxRec, fillBox.margin_height), + XmRImmediate, + (XtPointer) 10} + , + { + XmNmapCallback, + XmCCallback, + XmRCallback, + sizeof(XtCallbackList), + XtOffsetOf(PxmFillBoxRec, fillBox.map_callback), + XmRImmediate, + (XtPointer) NULL} + , + { + XmNunmapCallback, + XmCCallback, + XmRCallback, + sizeof(XtCallbackList), + XtOffsetOf(PxmFillBoxRec, fillBox.unmap_callback), + XmRImmediate, + (XtPointer) NULL} + , + { + PxmNfillBoxVertical, + PxmCFillBoxVertical, + XmRBoolean, sizeof(Boolean), + XtOffsetOf(PxmFillBoxRec, fillBox.vertical), + XmRImmediate, + (XtPointer) False} + , +#ifdef HAVE_XM_TRAIT + { + XmNbuttonRenderTable, + XmCButtonRenderTable, + XmRButtonRenderTable, + sizeof(XmRenderTable), + XtOffsetOf(PxmFillBoxRec, fillBox.button_render_table), + XmRCallProc, (XtPointer) NULL} + , + { + XmNlabelRenderTable, + XmCLabelRenderTable, + XmRLabelRenderTable, + sizeof(XmRenderTable), + XtOffsetOf(PxmFillBoxRec, fillBox.label_render_table), + XmRCallProc, (XtPointer) NULL} + , + { + XmNtextRenderTable, + XmCTextRenderTable, + XmRTextRenderTable, + sizeof(XmRenderTable), + XtOffsetOf(PxmFillBoxRec, fillBox.text_render_table), + XmRCallProc, (XtPointer) NULL} + , +#endif +}; + +/* Three of the preceding resources will be handled as synthetic + resources. */ +static XmSyntheticResource syn_resources[] = { +#if HAVE_XM_SYNTHETIC_RESOURCE + { + XmNmarginWidth, + sizeof(Dimension), + XtOffsetOf(PxmFillBoxRec, fillBox.margin_width), + XmeFromHorizontalPixels, + XmeToHorizontalPixels} + , + { + XmNmarginHeight, + sizeof(Dimension), + XtOffsetOf(PxmFillBoxRec, fillBox.margin_height), + XmeFromVerticalPixels, + XmeToVerticalPixels} + , +#endif +0 +}; + + +/* Define the two constraints of PxmFillBox. */ +static XtResource constraints[] = { + { + PxmNfillBoxFill, + PxmCFillBoxFill, + XmRPacking, + sizeof(Boolean), + XtOffsetOf(PxmFillBoxConstraintRec, fillBox.fill), + XmRImmediate, + (XtPointer) 0} + , +}; + +/* The preceding constraint will be handled as synthetic constraint. */ +static XmSyntheticResource syn_constraints[] = { +#if 0 + { + PxmNfillBoxFill, + sizeof(Boolean), + XtOffsetOf(PxmFillBoxConstraintRec, fillBox.fill), + XmeFromHorizontalPixels, + XmeToHorizontalPixels} + , +#endif +0 +}; + + + +/* Define the widget class record. See Chapter 4 of the + "OSF/Motif Widget Writer's Guide" for details. */ +externaldef(pxmfillBoxclassrec) + PxmFillBoxClassRec pxmFillBoxClassRec = { + { /* Here is the Core class record. */ + /* superclass */ (WidgetClass) & xmManagerClassRec, + /* class_name */ "PxmFillBox", + /* widget_size */ sizeof(PxmFillBoxRec), + /* class_initialize */ NULL, + /* class_part_initialize */ ClassPartInitialize, + /* class_inited */ FALSE, + /* initialize */ Initialize, + /* initialize_hook */ NULL, + /* realize */ XtInheritRealize, + /* actions */ NULL, + /* num_actions */ 0, + /* resources */ resources, + /* num_resources */ XtNumber(resources), + /* xrm_class */ NULLQUARK, + /* compress_motion */ TRUE, + /* compress_exposure */ XtExposeCompressMaximal, + /* compress_enterleave */ TRUE, + /* visible_interest */ FALSE, + /* destroy */ Destroy, + /* resize */ Resize, + /* expose */ Redisplay, + /* set_values */ SetValues, + /* set_values_hook */ NULL, + /* set_values_almost */ SetValuesAlmost, + /* get_values_hook */ NULL, + /* accept_focus */ NULL, + /* version */ XtVersion, + /* callback_private */ NULL, + /* tm_table */ XtInheritTranslations, + /* query_geometry */ QueryGeometry, + /* display_accelerator */ NULL, + /* extension */ NULL, + } + , + { /* Here is the Composite class record. */ + /* geometry_manager */ GeometryManager, + /* change_managed */ ChangeManaged, + /* insert_child */ XtInheritInsertChild, + /* delete_child */ XtInheritDeleteChild, + /* extension */ NULL, + } + , + { /* Here is the Constaint class record. */ + /* constraint_resources */ constraints, + /* constraint_num_resources */ XtNumber(constraints), + /* constraint_size */ sizeof(PxmFillBoxConstraintRec), + /* constraint_initialize */ NULL, + /* constraint_destroy */ NULL, + /* constraint_set_values */ ConstraintSetValues, + /* extension */ NULL, + } + , + { /* Here is the XmManager class record. */ + /* translations */ XtInheritTranslations, + /* syn_resources */ syn_resources, + /* num_syn_resources */ XtNumber(syn_resources), + /* syn_constraint_resources */ syn_constraints, + /* num_syn_constraint_resources */ XtNumber(syn_constraints), + /* parent_process */ XmInheritParentProcess, + /* extension */ NULL, + } + , + { /* Here is the PxmFillBox class record. */ + /* layout */ Layout, + /* calc_size */ CalcSize, + /* need_relayout */ NeedRelayout, + /* extension */ NULL, + } + }; + +/* Establish the widget class name as an externally accessible symbol. + Use the "externaldef" macro rather than the "extern" keyword. */ +externaldef(pxmfillBoxwidgetclass) WidgetClass pxmFillBoxWidgetClass = (WidgetClass) & pxmFillBoxClassRec; + +#ifdef HAVE_XM_TRAIT +/* Define trait record variables. */ + +/* Here is the trait record variable for the XmQTdialogSavvy trait. */ +static XmConst XmDialogSavvyTraitRec fillBoxDST = { + 0, /* version */ + CallMapUnmap, /* trait method */ +}; + + +/* Here is the trait record variable for the XmQTspecifyRenderTable trait. */ +static XmConst XmSpecRenderTraitRec fillBoxSRTT = { + 0, /* version */ + GetTable, /* trait method */ +}; +#endif + + +/**************************************************************************** + * + * ClassPartInitialize: + * Called when this widget or a subclass of this widget is instantiated. + * + ****************************************************************************/ +static void ClassPartInitialize(WidgetClass widgetClass) +{ + PxmFillBoxWidgetClass wc = (PxmFillBoxWidgetClass) widgetClass; + PxmFillBoxWidgetClass sc = (PxmFillBoxWidgetClass) wc->core_class.superclass; + + /* The following code allows subclasses of PxmFillBox to inherit three of + PxmFillBox's methods. */ + if (wc->fillBox_class.layout == PxmInheritLayout) + wc->fillBox_class.layout = sc->fillBox_class.layout; + if (wc->fillBox_class.calc_size == PxmInheritCalcSize) + wc->fillBox_class.calc_size = sc->fillBox_class.calc_size; + if (wc->fillBox_class.need_relayout == PxmInheritNeedRelayout) + wc->fillBox_class.need_relayout = sc->fillBox_class.need_relayout; + +#ifdef HAVE_XM_TRAIT + /* Install the XmQTdialogShellSavyy trait on this class and on + all its future subclasses. */ + XmeTraitSet(widgetClass, XmQTdialogShellSavvy, (XtPointer) & fillBoxDST); + + /* Install the XmQTspecifyRenderTable trait on this class and on + all its future subclasses. */ + XmeTraitSet(widgetClass, XmQTspecifyRenderTable, (XtPointer) & fillBoxSRTT); +#endif +} + + +/************************************************************************** + * + * Initialize: + * Called when this widget is first instantiated. + * + ***************************************************************************/ +static void Initialize(Widget request_w, Widget new_w, ArgList args, Cardinal *num_args) +{ +/* PxmFillBoxWidget rw = (PxmFillBoxWidget) request_w;*/ + PxmFillBoxWidget nw = (PxmFillBoxWidget) new_w; + + /* Initialize internal fields of the PxmFillBox widget. */ + nw->fillBox.processing_constraints = False; + nw->core.width = nw->core.height = 0; + nw->fillBox.margin_width = nw->fillBox.margin_height = 0; +} + + +/**************************************************************************** + * + * Destroy: + * Called when the widget is destroyed. + * + ****************************************************************************/ +static void Destroy(Widget wid) +{ +/* PxmFillBoxWidget fillBox = (PxmFillBoxWidget) wid;*/ +} + + +/**************************************************************************** + * + * Resize: + * + ****************************************************************************/ +static void Resize(Widget w) +{ + PxmFillBoxWidgetClass gwc = (PxmFillBoxWidgetClass) XtClass(w); + + /* Configure the children by calling Layout. */ + if (gwc->fillBox_class.layout) + (*(gwc->fillBox_class.layout)) (w, NULL); + else + Layout(w, NULL); +} + + + + +/**************************************************************************** + * + * Redisplay: + * Called by the Intrinsics in response to an exposure event. + * + ***************************************************************************/ +static void Redisplay(Widget w, XEvent *event, Region region) +{ + /* Pass exposure event down to gadget children. */ + PxmRedisplayGadgets(w, event, region); +} + + + +/***************************************************************************** + * + * SetValues: + * Called by the Intrinsics whenever any of the resource values change. + * + ****************************************************************************/ +static Boolean SetValues(Widget old_w, Widget request_w, Widget new_w, ArgList args, Cardinal *num_args) +{ + PxmFillBoxWidget cw = (PxmFillBoxWidget) old_w; +/* PxmFillBoxWidget rw = (PxmFillBoxWidget) request_w;*/ + PxmFillBoxWidget nw = (PxmFillBoxWidget) new_w; + Boolean redisplay = False; + Boolean need_relayout; + PxmFillBoxWidgetClass gwc = (PxmFillBoxWidgetClass) XtClass(new_w); + + /* See if any class or subclass resources have changed. */ + if (gwc->fillBox_class.need_relayout) + need_relayout = (*(gwc->fillBox_class.need_relayout)) (old_w, new_w); + else + need_relayout = NeedRelayout(old_w, new_w); + + /* If any geometry resources changed and a new size wasn't specified, + recalculate a new ideal size. */ + if (need_relayout) { + /* Reset the widget size so that CalcSize can affect them. */ + if (nw->core.width == cw->core.width) + nw->core.width = 0; + if (nw->core.height == cw->core.height) + nw->core.height = 0; + + /* Call CalcSize. */ + if (gwc->fillBox_class.calc_size) + (*(gwc->fillBox_class.calc_size)) (new_w, NULL, &nw->core.width, &nw->core.height); + else + CalcSize(new_w, NULL, &nw->core.width, &nw->core.height); + + + /* If the geometry resources have changed but the size hasn't, + we need to relayout manually, because Xt won't generate a + Resize at this point. */ + if ((nw->core.width == cw->core.width) && (nw->core.height == cw->core.height)) { + + /* Call Layout to configure the children. */ + if (gwc->fillBox_class.layout) + (*(gwc->fillBox_class.layout)) (new_w, NULL); + else + Layout(new_w, NULL); + redisplay = True; + } + } + +#ifdef HAVE_XM_TRAIT + /* PxmFillBox installs the XmQTdialogShellSavvy trait. Therefore, PxmFillBox + has to process the Xm_DIALOG_SAVVY_FORCE_ORIGIN case, which is as + follows. A DialogShell always mimics the child position on itself. + That is, the "current" position of an PxmFillBox within a DialogShell is + always 0. Therefore, if an application tries to set PxmFillBox's x or + y position to 0, the Intrinsics will not detect a position change and + wll not trigger a geometry request. PxmFillBox has to detect this special + request and set core.x and core.y to the special value, + XmDIALOG_SAVVY_FORCE_ORIGIN. That is, XmDIALOG_SAVVY_FORCE_ORIGIN + tells DialogShell that PxmFillBox really does want to move to an x or y + position of 0. */ + + if (XmIsDialogShell(XtParent(new_w))) { /* Is parent a DialogShell? */ + Cardinal i; + + /* We have to look in the arglist since old_w->core.x is always 0, and + if new_w->core.x is also set to 0, we see no change. */ + for(i = 0; i < *num_args; i++) { + if (strcmp(args[i].name, XmNx) == 0) { + if ((args[i].value == 0) && (new_w->core.x == 0)) + new_w->core.x = XmDIALOG_SAVVY_FORCE_ORIGIN; + } + if (strcmp(args[i].name, XmNy) == 0) { + if ((args[i].value == 0) && (new_w->core.y == 0)) + new_w->core.y = XmDIALOG_SAVVY_FORCE_ORIGIN; + } + } /* end for */ + } /* end of if */ +#endif + + return (redisplay); +} + + + +/************************************************************************* + * + * SetValuesAlmost: + * Called by the Intrinsics when an XtMakeGeometryRequest call + * returns either XmGeometryAlmost or XtGeometryNo. + * + ***************************************************************************/ +static void SetValuesAlmost(Widget cw, /* unused */ + Widget nw, XtWidgetGeometry *request, XtWidgetGeometry *reply) +{ + PxmFillBoxWidgetClass gwc = (PxmFillBoxWidgetClass) XtClass(nw); + + /* PxmFillBox's parent said XtGeometryNo to PxmFillBox's geometry request. + Therefore, we need to relayout because this request + was due to a change in internal geometry resource of the PxmFillBox */ + if (!reply->request_mode) { + if (gwc->fillBox_class.layout) + (*(gwc->fillBox_class.layout)) (nw, NULL); + else + Layout(nw, NULL); + } + + *request = *reply; +} + + +/************************************************************************* + * + * QueryGeometry: + * Called by a parent of FillBox when the parent needs to find out FillBox's + * preferred size. QueryGeometry calls CalcSize to do find the + * preferred size. + * + ***************************************************************************/ +static XtGeometryResult QueryGeometry(Widget w, XtWidgetGeometry *request, XtWidgetGeometry *reply) +{ + PxmFillBoxWidgetClass gwc = (PxmFillBoxWidgetClass) XtClass(w); + + /* If PxmFillBox's parent calls XtQueryGeometry before PxmFillBox has been + realized, use the current size of PxmFillBox as the preferred size. */ + /* Deal with user initial size setting */ + if (!XtIsRealized(w)) { /* Widget is not yet realized. */ + reply->width = XtWidth(w); /* might be 0 */ + reply->height = XtHeight(w); /* might be 0 */ + } + else { /* Widget is realized. */ + /* always computes natural size afterwards */ + reply->width = 0; + reply->height = 0; + } + + /* Call CalcSize to figure out what the preferred size really is. */ + if (gwc->fillBox_class.calc_size) + (*(gwc->fillBox_class.calc_size)) (w, NULL, &reply->width, &reply->height); + else + CalcSize(w, NULL, &reply->width, &reply->height); + + /* This function handles CWidth and CHeight */ + return PxmReplyToQueryGeometry(w, request, reply); +} + + +/**************************************************************************** + * + * GeometryManager: + * Called by Intrinsics in response to a geometry change request from + * one of the children of PxmFillBox. + * + ***************************************************************************/ +static XtGeometryResult GeometryManager(Widget w, /* instigator */ + XtWidgetGeometry *request, XtWidgetGeometry *reply) +{ + PxmFillBoxWidget gw = (PxmFillBoxWidget) XtParent(w); + XtWidgetGeometry parentRequest; + XtGeometryResult result; + Dimension curWidth, curHeight, curBW; + PxmFillBoxWidgetClass gwc = (PxmFillBoxWidgetClass) XtClass((Widget) gw); + + /* If the request was caused by ConstraintSetValues reset the flag */ + if (gw->fillBox.processing_constraints) { + gw->fillBox.processing_constraints = False; + /* The ConstraintSetValues added one to border_width; + This is the Xt trick used to fire the GM when a non core + geometry resource (like a constraint) changes. + now take it away. */ + request->border_width -= 1; + } + + /* Save the original child resources. */ + curWidth = w->core.width; + curHeight = w->core.height; + curBW = w->core.border_width; + + /* Deny any requests for a new position. */ + if ((request->request_mode & CWX) || (request->request_mode & CWY)) + return XtGeometryNo; + + if (request->request_mode & CWWidth) + w->core.width = request->width; + if (request->request_mode & CWHeight) + w->core.height = request->height; + if (request->request_mode & CWBorderWidth) + w->core.border_width = request->border_width; + + /* Calculate a new ideal size based on these requests. */ + /* Setting width and height to 0 tells CalcSize to override these + fields with the calculated width and height. */ + parentRequest.width = 0; + parentRequest.height = 0; + if (gwc->fillBox_class.calc_size) + (*(gwc->fillBox_class.calc_size)) ((Widget) gw, w, &parentRequest.width, &parentRequest.height); + else + CalcSize((Widget) gw, w, &parentRequest.width, &parentRequest.height); + + + /* Ask the FillBox's parent if new calculated size is acceptable. */ + parentRequest.request_mode = CWWidth | CWHeight; + if (request->request_mode & XtCWQueryOnly) + parentRequest.request_mode |= XtCWQueryOnly; + result = XtMakeGeometryRequest((Widget) gw, &parentRequest, NULL); + + /* Turn XtGeometryAlmost into XtGeometryNo. */ + if (result == XtGeometryAlmost) + result = XtGeometryNo; + + if (result == XtGeometryNo || request->request_mode & XtCWQueryOnly) { + /* Restore original geometry. */ + w->core.width = curWidth; + w->core.height = curHeight; + w->core.border_width = curBW; + } + else { + /* result == XtGeometryYes and this wasn't just a query */ + if (gwc->fillBox_class.layout) + (*(gwc->fillBox_class.layout)) ((Widget) gw, w); + else + Layout((Widget) gw, w); /* Layout with this child as the instigator, + so that we don't resize this child. */ + } + + return (result); +} + + + +/************************************************************************** + * + * ChangeManaged: + * Called by the Intrinsics whenever either of the following happens: + * * a managed child becomes unmanaged. + * * an unmanaged child becomes managed. + * + *************************************************************************/ +static void ChangeManaged(Widget w) +{ + Dimension fillBoxWidth, fillBoxHeight; + PxmFillBoxWidgetClass gwc = (PxmFillBoxWidgetClass) XtClass(w); + + /* If you get an initial (C) size from the user or application, keep it. + Otherwise, just force width and height to 0 so that CalcSize will + overwrite the appropriate fields. */ + if (!XtIsRealized(w)) { + /* The first time, only attempts to change non specified sizes */ + fillBoxWidth = XtWidth(w); /* might be 0 */ + fillBoxHeight = XtHeight(w); /* might be 0 */ + } + else { + fillBoxWidth = 0; + fillBoxHeight = 0; + } + + /* Determine the ideal size of FillBox. */ + if (gwc->fillBox_class.calc_size) + (*(gwc->fillBox_class.calc_size)) (w, NULL, &fillBoxWidth, &fillBoxHeight); + else + CalcSize(w, NULL, &fillBoxWidth, &fillBoxHeight); + + /* Ask parent of FillBox if FillBox's new size is acceptable. Keep asking until + parent returns either XtGeometryYes or XtGeometryNo. */ + while(XtMakeResizeRequest(w, fillBoxWidth, fillBoxHeight, &fillBoxWidth, &fillBoxHeight) == XtGeometryAlmost); + + /* Now that we have a size for the FillBox, we can layout the children + of the fillBox. */ + if (gwc->fillBox_class.layout) + (*(gwc->fillBox_class.layout)) (w, NULL); + else + Layout(w, NULL); + +#ifdef HAVE_XME + /* Update keyboard traversal */ + XmeNavigChangeManaged(w); +#endif +} + + + + +/************************************************************************** + * + * ConstraintSetValues: + * Called by Intrinsics if there is any change in any of the constraint + * resources. + * + **************************************************************************/ +static Boolean ConstraintSetValues(Widget cw, Widget rw, Widget nw, ArgList args, Cardinal *num_args) +{ + PxmFillBoxConstraint nc; + PxmFillBoxConstraint cc; + PxmFillBoxWidget gw; + + if (!XtIsRectObj(nw)) + return (False); + + gw = (PxmFillBoxWidget) XtParent(nw); + nc = PxmFillBoxCPart(nw); + cc = PxmFillBoxCPart(cw); + + /* Check for change in PxmNfillBoxMarginWidth or PxmNfillBoxMarginHeight */ + if ((nc->fill != cc->fill) && XtIsManaged(nw)) { + /* Tell the Intrinsics and the GeometryManager method that a + reconfigure is needed. */ + gw->fillBox.processing_constraints = True; + /* A trick: by altering one of the core geometry fields, Xt will + call the parent's geometry_manager method. */ + nw->core.border_width += 1; + } + + return (False); +} + + +/*************************************************************************** + * + * Layout: + * Does all the placement of children. + * Instigator tells whether or not to resize all children. + * + *************************************************************************/ +static void Layout(Widget wid, Widget instigator) +{ + PxmFillBoxWidget gw = (PxmFillBoxWidget) wid; + Dimension mw = gw->fillBox.margin_width; + Dimension mh = gw->fillBox.margin_height; + Dimension TotalWidthOfFillBoxWidget = gw->core.width; + Dimension TotalHeightOfFillBoxWidget = gw->core.height; + long AvailWidthForChildren, AvailHeightForChildren; + long pos, extra = 0, total = 0, wextra = 0; + unsigned int i; + int numfills, vert = gw->fillBox.vertical; + + AvailWidthForChildren = (long)TotalWidthOfFillBoxWidget - 2 * (long)mw; + AvailHeightForChildren = (long)TotalHeightOfFillBoxWidget - 2 * (long)mh; + + + /* calculate the extra space we need to allocate and reset width/height of each widget temporarily */ + total = 0; + numfills = 0; + for(i = 0; i < gw->composite.num_children; i++) { + Widget ic = gw->composite.children[i]; + Dimension cb = ic->core.border_width; + PxmFillBoxConstraint glc = PxmFillBoxCPart(ic); + Boolean gmf = glc->fill; + Dimension cw, ch; + XtWidgetGeometry reply; + + if (!XtIsManaged(ic)) + continue; + + XtQueryGeometry(ic, NULL, &reply); + cw = (reply.request_mode & CWWidth) ? reply.width : ic->core.width; + ch = (reply.request_mode & CWHeight) ? reply.height : ic->core.height; + ic->core.width = cw; + ic->core.height = ch; + + if (vert) + total += ch + 2*cb; + else + total += cw + 2*cb; + +/*printf("[%d] %d %d cw=%d\n", i, gmf, ic->core.width + 2*cb, cw);*/ + if (gmf) + numfills++; + } + if (numfills != 0) { + if (vert) + extra = AvailHeightForChildren - total; + else + extra = AvailWidthForChildren - total; + if (extra < 0) + extra = 0; + wextra = extra / numfills; + } + + /* printf("avail=%ld:%ld total=%ld extra=%ld numfills=%d wextra=%ld vert=%d\n", AvailWidthForChildren, AvailHeightForChildren, total, extra, numfills, wextra, gw->fillBox.vertical); */ + + /* sequential layout, insert extra space in children with fill turned on */ + pos = mw; + for(i = 0; i < gw->composite.num_children; i++) { + Widget ic = gw->composite.children[i]; + PxmFillBoxConstraint glc = PxmFillBoxCPart(ic); + Boolean gmf = glc->fill; + Position ChildsStartingX, ChildsStartingY; + Dimension ChildsActualWidth, ChildsActualHeight, cb; + + if (!XtIsManaged(ic)) + continue; /* ignored unmanaged children */ + + cb = ic->core.border_width; + + ChildsActualWidth = ic->core.width; + ChildsActualHeight = ic->core.height; + + if (vert) { + ChildsStartingX = mw+cb; + ChildsStartingY = pos+cb; + ChildsActualWidth = AvailWidthForChildren; + } + else { + ChildsStartingX = pos+cb; + ChildsStartingY = mh+cb; + ChildsActualHeight = AvailHeightForChildren; + } + + if (gmf) { + numfills--; + if (numfills > 0) { + if (vert) + ChildsActualHeight += wextra; + else + ChildsActualWidth += wextra; + extra -= wextra; + } + else { /* the last fill widget gets whatever remains - this fixes rounding errors */ + if (vert) + ChildsActualHeight += extra; + else + ChildsActualWidth += extra; + extra = 0; + } + } + + /* If layout is instigated by the GeometryManager don't + configure the requesting child, just set its geometry and + let Xt configure it. */ + if (ic != instigator) { + PxmConfigureObject(ic, ChildsStartingX, ChildsStartingY, ChildsActualWidth, ChildsActualHeight, cb); + } + else { + ic->core.x = ChildsStartingX; + ic->core.y = ChildsStartingY; +/* printf(" {%d %d}\n", ic->core.x, ic->core.y);*/ + ic->core.width = ChildsActualWidth; + ic->core.height = ChildsActualHeight; + ic->core.border_width = cb; + } + + if (vert) + pos += ChildsActualHeight + cb*2; + else + pos += ChildsActualWidth + cb*2; + } +} + + + +/****************************************************************************** + * + * CalcSize: + * Called by QueryGeometry, SetValues, GeometryManager, and ChangeManaged. + * Calculate the ideal size of the PxmFillBox widget. + * Only affects the returned size if it is 0. + * + ****************************************************************************/ +static void CalcSize(Widget wid, Widget instigator, Dimension *TotalWidthOfFillBoxWidget, Dimension *TotalHeightOfFillBoxWidget) +{ + PxmFillBoxWidget gw = (PxmFillBoxWidget) wid; + Dimension mw = gw->fillBox.margin_width; + Dimension mh = gw->fillBox.margin_height; + Dimension maxWidth = 1; + Dimension maxHeight = 1; + unsigned int i; + int vert = gw->fillBox.vertical; + + /* minimal size is a sequential placement of children plus the margins */ + for(i = 0; i < gw->composite.num_children; i++) { + Widget ic = gw->composite.children[i]; + Dimension width, height; + Dimension cw, ch, cb; + XtWidgetGeometry reply; + + if (!XtIsManaged(ic)) + continue; + + /* Get child's preferred geometry if not the instigator. */ + if (ic != instigator) { + XtQueryGeometry(ic, NULL, &reply); + cw = (reply.request_mode & CWWidth) ? reply.width : ic->core.width; + ch = (reply.request_mode & CWHeight) ? reply.height : ic->core.height; + } + else { + cw = ic->core.width; + ch = ic->core.height; + } + cb = ic->core.border_width; + + width = cw + 2 * cb; + height = ch + 2 * cb; + + if (vert) { + maxWidth = Max(width, maxWidth); + maxHeight += height; + } + else { + maxWidth += width; + maxHeight = Max(height, maxHeight); + } + } + + *TotalWidthOfFillBoxWidget = maxWidth + 2*mw; + *TotalHeightOfFillBoxWidget = maxHeight + 2*mh; +} + + +/**************************************************************************** + * + * NeedRelayout: + * Called by SetValues. + * Returns True if a relayout is needed. + * based on this class and all superclass resources' changes. + * + ***************************************************************************/ +static Boolean NeedRelayout(Widget old_w, Widget new_w) +{ +#if 0 + PxmFillBoxWidget cw = (PxmFillBoxWidget) old_w; + PxmFillBoxWidget nw = (PxmFillBoxWidget) new_w; +#endif + + return False; +} + + +#ifdef HAVE_XM_TRAIT +/*-- Trait methods --*/ + + +/**************************************************************** + * + * Trait method for XmQTdialogShellSavvy trait. + * + **************************************************************/ +static void CallMapUnmap(Widget wid, Boolean map_unmap) +{ + PxmFillBoxWidget fillBox = (PxmFillBoxWidget) wid; + XmAnyCallbackStruct call_data; + + call_data.reason = (map_unmap) ? XmCR_MAP : XmCR_UNMAP; + call_data.event = NULL; + + if (map_unmap) { + XtCallCallbackList(wid, fillBox->fillBox.map_callback, &call_data); + } + else { + XtCallCallbackList(wid, fillBox->fillBox.unmap_callback, &call_data); + } +} + +/***************************************************************** + * + * Trait method for XmQTspecifyRenderTable. + * +*****************************************************************/ + +static XmRenderTable GetTable(Widget wid, XtEnum type) +{ + PxmFillBoxWidget fillBox = (PxmFillBoxWidget) wid; + + switch (type) { + case XmLABEL_RENDER_TABLE: + return fillBox->fillBox.label_render_table; + case XmBUTTON_RENDER_TABLE: + return fillBox->fillBox.button_render_table; + case XmTEXT_RENDER_TABLE: + return fillBox->fillBox.text_render_table; + } + + return NULL; +} +#endif + +/******************************************************************************* + * + * PxmCreateFillBox: + * Called by an application. + * + ******************************************************************************/ +Widget PxmCreateFillBox(Widget parent, char *name, ArgList arglist, Cardinal argcount) +{ + /* This is a convenience function to instantiate an PxmFillBox widget. */ + return (XtCreateWidget(name, pxmFillBoxWidgetClass, parent, arglist, argcount)); +} + Index: tags/2.1.2/src_plugins/hid_lesstif/FillBox.h =================================================================== --- tags/2.1.2/src_plugins/hid_lesstif/FillBox.h (nonexistent) +++ tags/2.1.2/src_plugins/hid_lesstif/FillBox.h (revision 24813) @@ -0,0 +1,66 @@ +/* + * FillBox widget for Motif + * + * Copyright (c) 1987-2012, The Open Group. All rights reserved. + * Copyright (c) 2019, Tibor 'Igor2' Palinkas + * (widget code based on Exm Grid) + * + * These libraries and programs are free software; you can + * redistribute them and/or modify them under the terms of the GNU + * Lesser General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * These libraries and programs are distributed in the hope that + * they will be useful, but WITHOUT ANY WARRANTY; without even the + * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with these librararies and programs; if not, write + * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth + * Floor, Boston, MA 02110-1301 USA + */ + + +#ifndef _PxmFillBox_h +#define _PxmFillBox_h + + +#include /* widget public header file for XmManager */ + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Define the widget class and widget record. */ +externalref WidgetClass pxmFillBoxWidgetClass; + +typedef struct _PxmFillBoxClassRec *PxmFillBoxWidgetClass; +typedef struct _PxmFillBoxRec *PxmFillBoxWidget; + + +/* Define an IsSubclass macro. */ +#ifndef PxmIsFillBox +#define PxmIsFillBox(w) XtIsSubclass(w, pxmFillBoxWidgetClass) +#endif + + +/* Define string equivalents of new resource names. */ +#define PxmNfillBoxFill "fillBoxFill" +#define PxmNfillBoxVertical "fillBoxVertical" + +#define PxmCFillBoxFill "FillBoxFill" +#define PxmCFillBoxVertical "FillBoxVertical" + +/* Specify the API for this widget. */ +extern Widget PxmCreateFillBox(Widget parent, char *name, ArgList arglist, Cardinal argcount); + +#ifdef __cplusplus +} +#endif + +#endif /* _PxmFillBox_h */ + Index: tags/2.1.2/src_plugins/hid_lesstif/FillBoxP.h =================================================================== --- tags/2.1.2/src_plugins/hid_lesstif/FillBoxP.h (nonexistent) +++ tags/2.1.2/src_plugins/hid_lesstif/FillBoxP.h (revision 24813) @@ -0,0 +1,131 @@ +/* + * FillBox widget for Motif + * + * Copyright (c) 1987-2012, The Open Group. All rights reserved. + * Copyright (c) 2019, Tibor 'Igor2' Palinkas + * (widget code based on Exm Grid) + * + * These libraries and programs are free software; you can + * redistribute them and/or modify them under the terms of the GNU + * Lesser General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * These libraries and programs are distributed in the hope that + * they will be useful, but WITHOUT ANY WARRANTY; without even the + * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with these librararies and programs; if not, write + * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth + * Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _PxmFillBoxP_h +#define _PxmFillBoxP_h + + +#include "FillBox.h" /* public header file for PxmFillBox */ +#include /* private header file for XmManager */ + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Make the following two methods inheritable by subclasses of PxmFillBox. */ +#define PxmInheritLayout ((PxmLayoutProc) _XtInherit) +#define PxmInheritCalcSize ((PxmCalcSizeProc) _XtInherit) +#define PxmInheritNeedRelayout ((PxmNeedRelayoutProc) _XtInherit) + + +/* Define new data types for these two inheritable methods. */ +typedef void (*PxmLayoutProc) (Widget, Widget); +typedef void (*PxmCalcSizeProc) (Widget, Widget, Dimension *, Dimension *); +typedef Boolean(*PxmNeedRelayoutProc) (Widget, Widget); + +/* Define the widget class part. */ +typedef struct { + PxmLayoutProc layout; + PxmCalcSizeProc calc_size; + PxmNeedRelayoutProc need_relayout; + XtPointer extension; +} PxmFillBoxClassPart; + + +/* Define the full class record. */ +typedef struct _PxmFillBoxClassRec { + CoreClassPart core_class; + CompositeClassPart composite_class; + ConstraintClassPart constraint_class; + XmManagerClassPart manager_class; + PxmFillBoxClassPart fillBox_class; +} PxmFillBoxClassRec; + +externalref PxmFillBoxClassRec pxmFillBoxClassRec; + + +/* Define the widget instance part. */ +typedef struct { + /* Provide space for the values of the four resources of PxmFillBox. */ + Dimension margin_width; + Dimension margin_height; + XtCallbackList map_callback; + XtCallbackList unmap_callback; + Boolean vertical; +#ifdef HAVE_XM_TRAIT + XmRenderTable button_render_table; + XmRenderTable label_render_table; + XmRenderTable text_render_table; +#endif + + /* processing_constraints is a flag. If its value is True, then + it means that the ConstraintSetValues method is requesting a + geometry change. */ + Boolean processing_constraints; + +} PxmFillBoxPart; + +/* Establish an arbitrary limit */ +#define EXM_GRID_MAX_NUMBER_OF_ROWS 100 +#define EXM_GRID_MAX_NUMBER_OF_COLUMNS 100 + +/* Define the full instance record. */ +typedef struct _PxmFillBoxRec { + CorePart core; + CompositePart composite; + ConstraintPart constraint; + XmManagerPart manager; + PxmFillBoxPart fillBox; +} PxmFillBoxRec; + +/* Define the subclassing level index to be used with ResolvePartOffset */ +#define PxmFillBoxIndex (XmManagerIndex + 1) + +/* Define the constraint part structure. */ +typedef struct _PxmFillBoxConstraintPart { + Boolean fill; +} PxmFillBoxConstraintPart, *PxmFillBoxConstraint; + + +/* Define the full constraint structure. */ +typedef struct _PxmFillBoxConstraintRec { + XmManagerConstraintPart manager; + PxmFillBoxConstraintPart fillBox; +} PxmFillBoxConstraintRec, *PxmFillBoxConstraintPtr; + + +/* Define macros for this class. */ +#define PxmFillBoxCPart(w) \ + (&((PxmFillBoxConstraintPtr) (w)->core.constraints)->fillBox) + + + +#ifdef __cplusplus +} +#endif + +#endif /* _PxmFillBoxP_h */ Index: tags/2.1.2/src_plugins/hid_lesstif/Makefile =================================================================== --- tags/2.1.2/src_plugins/hid_lesstif/Makefile (nonexistent) +++ tags/2.1.2/src_plugins/hid_lesstif/Makefile (revision 24813) @@ -0,0 +1,6 @@ +all: + cd ../../src && $(MAKE) mod_hid_lesstif + +clean: + rm *.o *.so 2>/dev/null ; true + Index: tags/2.1.2/src_plugins/hid_lesstif/Pages.c =================================================================== --- tags/2.1.2/src_plugins/hid_lesstif/Pages.c (nonexistent) +++ tags/2.1.2/src_plugins/hid_lesstif/Pages.c (revision 24813) @@ -0,0 +1,801 @@ +/* + * Pages widget for Motif + * + * Copyright (c) 1987-2012, The Open Group. All rights reserved. + * Copyright (c) 2019, Tibor 'Igor2' Palinkas + * (widget code based on Exm Grid) + * + * These libraries and programs are free software; you can + * redistribute them and/or modify them under the terms of the GNU + * Lesser General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * These libraries and programs are distributed in the hope that + * they will be useful, but WITHOUT ANY WARRANTY; without even the + * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with these librararies and programs; if not, write + * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth + * Floor, Boston, MA 02110-1301 USA + */ + +/****************************************************************************** + * + * Pages.c - PxmPages widget. This widget manages its children in + * a notebook-like setup. Each child is a page, only one page + * is shown at a time. There's no tab button system, the caller + * needs to set that up. +******************************************************************************/ + +#include "config.h" + +/* Include appropriate header files. */ +#include "PagesP.h" /* private header file for the PxmPages widget */ +#include /* for gadget management functions */ + +#ifdef HAVE_XM_TRAIT +#include /* for trait access functions */ +#include /* for XmQTdialogSavvy trait */ +#include /* for XmQTspecifyRenderTable trait */ +#endif + +#include "pxm_helper.h" + +/* Declare static functions. */ +static void ClassPartInitialize(WidgetClass widgetClass); +static void Initialize(Widget request_w, Widget new_w, ArgList args, Cardinal *num_args); +static void Destroy(Widget wid); +static void Resize(Widget w); +static void Redisplay(Widget w, XEvent *event, Region region); +static Boolean SetValues(Widget old_w, Widget request_w, Widget new_w, ArgList args, Cardinal *num_args); +static void SetValuesAlmost(Widget cw, Widget nw, XtWidgetGeometry *request, XtWidgetGeometry *reply); +static XtGeometryResult QueryGeometry(Widget w, XtWidgetGeometry *request, XtWidgetGeometry *reply); +static XtGeometryResult GeometryManager(Widget w, XtWidgetGeometry *request, XtWidgetGeometry *reply); +static void ChangeManaged(Widget w); +static Boolean ConstraintSetValues(Widget cw, Widget rw, Widget nw, ArgList args, Cardinal *num_args); +static void Layout(Widget wid, Widget instigator); +static void CalcSize(Widget wid, Widget instigator, Dimension *pagesWidth, Dimension *pagesHeight); +static Boolean NeedRelayout(Widget new, Widget cur); + +#ifdef HAVE_XM_TRAIT +static void CallMapUnmap(Widget wid, Boolean map_unmap); +static XmRenderTable GetTable(Widget wid, XtEnum type); +#endif + +/* No translations and no actions. */ + + +/* Define the resources for the PxmPages widget. */ +static XtResource resources[] = { + { + XmNmarginWidth, + XmCMarginWidth, + XmRHorizontalDimension, + sizeof(Dimension), + XtOffsetOf(PxmPagesRec, pages.margin_width), + XmRImmediate, + (XtPointer) 10} + , + { + XmNmarginHeight, + XmCMarginHeight, + XmRVerticalDimension, + sizeof(Dimension), + XtOffsetOf(PxmPagesRec, pages.margin_height), + XmRImmediate, + (XtPointer) 10} + , + { + XmNmapCallback, + XmCCallback, + XmRCallback, + sizeof(XtCallbackList), + XtOffsetOf(PxmPagesRec, pages.map_callback), + XmRImmediate, + (XtPointer) NULL} + , + { + XmNunmapCallback, + XmCCallback, + XmRCallback, + sizeof(XtCallbackList), + XtOffsetOf(PxmPagesRec, pages.unmap_callback), + XmRImmediate, + (XtPointer) NULL} + , + { + PxmNpagesAt, + PxmCPagesAt, + XmRCardinal, sizeof(Cardinal), + XtOffsetOf(PxmPagesRec, pages.at), + XmRImmediate, + (XtPointer) False} + , +#ifdef HAVE_XM_TRAIT + { + XmNbuttonRenderTable, + XmCButtonRenderTable, + XmRButtonRenderTable, + sizeof(XmRenderTable), + XtOffsetOf(PxmPagesRec, pages.button_render_table), + XmRCallProc, (XtPointer) NULL} + , + { + XmNlabelRenderTable, + XmCLabelRenderTable, + XmRLabelRenderTable, + sizeof(XmRenderTable), + XtOffsetOf(PxmPagesRec, pages.label_render_table), + XmRCallProc, (XtPointer) NULL} + , + { + XmNtextRenderTable, + XmCTextRenderTable, + XmRTextRenderTable, + sizeof(XmRenderTable), + XtOffsetOf(PxmPagesRec, pages.text_render_table), + XmRCallProc, (XtPointer) NULL} + , +#endif +}; + +/* Three of the preceding resources will be handled as synthetic + resources. */ +static XmSyntheticResource syn_resources[] = { +#if HAVE_XM_SYNTHETIC_RESOURCE + { + XmNmarginWidth, + sizeof(Dimension), + XtOffsetOf(PxmPagesRec, pages.margin_width), + XmeFromHorizontalPixels, + XmeToHorizontalPixels} + , + { + XmNmarginHeight, + sizeof(Dimension), + XtOffsetOf(PxmPagesRec, pages.margin_height), + XmeFromVerticalPixels, + XmeToVerticalPixels} + , +#endif +0 +}; + + +/* Define the two constraints of PxmPages. */ +static XtResource constraints[] = { 0 }; + +/* The preceding constraint will be handled as synthetic constraint. */ +static XmSyntheticResource syn_constraints[] = { 0 }; + +/* Define the widget class record. See Chapter 4 of the + "OSF/Motif Widget Writer's Guide" for details. */ +externaldef(pxmpagesclassrec) + PxmPagesClassRec pxmPagesClassRec = { + { /* Here is the Core class record. */ + /* superclass */ (WidgetClass) & xmManagerClassRec, + /* class_name */ "PxmPages", + /* widget_size */ sizeof(PxmPagesRec), + /* class_initialize */ NULL, + /* class_part_initialize */ ClassPartInitialize, + /* class_inited */ FALSE, + /* initialize */ Initialize, + /* initialize_hook */ NULL, + /* realize */ XtInheritRealize, + /* actions */ NULL, + /* num_actions */ 0, + /* resources */ resources, + /* num_resources */ XtNumber(resources), + /* xrm_class */ NULLQUARK, + /* compress_motion */ TRUE, + /* compress_exposure */ XtExposeCompressMaximal, + /* compress_enterleave */ TRUE, + /* visible_interest */ FALSE, + /* destroy */ Destroy, + /* resize */ Resize, + /* expose */ Redisplay, + /* set_values */ SetValues, + /* set_values_hook */ NULL, + /* set_values_almost */ SetValuesAlmost, + /* get_values_hook */ NULL, + /* accept_focus */ NULL, + /* version */ XtVersion, + /* callback_private */ NULL, + /* tm_table */ XtInheritTranslations, + /* query_geometry */ QueryGeometry, + /* display_accelerator */ NULL, + /* extension */ NULL, + } + , + { /* Here is the Composite class record. */ + /* geometry_manager */ GeometryManager, + /* change_managed */ ChangeManaged, + /* insert_child */ XtInheritInsertChild, + /* delete_child */ XtInheritDeleteChild, + /* extension */ NULL, + } + , + { /* Here is the Constaint class record. */ + /* constraint_resources */ constraints, + /* constraint_num_resources */ XtNumber(constraints), + /* constraint_size */ sizeof(PxmPagesConstraintRec), + /* constraint_initialize */ NULL, + /* constraint_destroy */ NULL, + /* constraint_set_values */ ConstraintSetValues, + /* extension */ NULL, + } + , + { /* Here is the XmManager class record. */ + /* translations */ XtInheritTranslations, + /* syn_resources */ syn_resources, + /* num_syn_resources */ XtNumber(syn_resources), + /* syn_constraint_resources */ syn_constraints, + /* num_syn_constraint_resources */ XtNumber(syn_constraints), + /* parent_process */ XmInheritParentProcess, + /* extension */ NULL, + } + , + { /* Here is the PxmPages class record. */ + /* layout */ Layout, + /* calc_size */ CalcSize, + /* need_relayout */ NeedRelayout, + /* extension */ NULL, + } + }; + +/* Establish the widget class name as an externally accessible symbol. + Use the "externaldef" macro rather than the "extern" keyword. */ +externaldef(pxmpageswidgetclass) WidgetClass pxmPagesWidgetClass = (WidgetClass) & pxmPagesClassRec; + +#ifdef HAVE_XM_TRAIT +/* Define trait record variables. */ + +/* Here is the trait record variable for the XmQTdialogSavvy trait. */ +static XmConst XmDialogSavvyTraitRec pagesDST = { + 0, /* version */ + CallMapUnmap, /* trait method */ +}; + + +/* Here is the trait record variable for the XmQTspecifyRenderTable trait. */ +static XmConst XmSpecRenderTraitRec pagesSRTT = { + 0, /* version */ + GetTable, /* trait method */ +}; +#endif + + +/**************************************************************************** + * + * ClassPartInitialize: + * Called when this widget or a subclass of this widget is instantiated. + * + ****************************************************************************/ +static void ClassPartInitialize(WidgetClass widgetClass) +{ + PxmPagesWidgetClass wc = (PxmPagesWidgetClass) widgetClass; + PxmPagesWidgetClass sc = (PxmPagesWidgetClass) wc->core_class.superclass; + + /* The following code allows subclasses of PxmPages to inherit three of + PxmPages's methods. */ + if (wc->pages_class.layout == PxmInheritLayout) + wc->pages_class.layout = sc->pages_class.layout; + if (wc->pages_class.calc_size == PxmInheritCalcSize) + wc->pages_class.calc_size = sc->pages_class.calc_size; + if (wc->pages_class.need_relayout == PxmInheritNeedRelayout) + wc->pages_class.need_relayout = sc->pages_class.need_relayout; + +#ifdef HAVE_XM_TRAIT + /* Install the XmQTdialogShellSavyy trait on this class and on + all its future subclasses. */ + XmeTraitSet(widgetClass, XmQTdialogShellSavvy, (XtPointer) & pagesDST); + + /* Install the XmQTspecifyRenderTable trait on this class and on + all its future subclasses. */ + XmeTraitSet(widgetClass, XmQTspecifyRenderTable, (XtPointer) & pagesSRTT); +#endif +} + + +/************************************************************************** + * + * Initialize: + * Called when this widget is first instantiated. + * + ***************************************************************************/ +static void Initialize(Widget request_w, Widget new_w, ArgList args, Cardinal *num_args) +{ + PxmPagesWidget nw = (PxmPagesWidget)new_w; + + /* Initialize one of the internal fields of the PxmPages widget. */ + nw->pages.processing_constraints = False; +} + + +/**************************************************************************** + * + * Destroy: + * Called when the widget is destroyed. + * + ****************************************************************************/ +static void Destroy(Widget wid) +{ +} + + +/**************************************************************************** + * + * Resize: + * + ****************************************************************************/ +static void Resize(Widget w) +{ + PxmPagesWidgetClass gwc = (PxmPagesWidgetClass) XtClass(w); + + /* Configure the children by calling Layout. */ + if (gwc->pages_class.layout) + (*(gwc->pages_class.layout)) (w, NULL); + else + Layout(w, NULL); +} + + + + +/**************************************************************************** + * + * Redisplay: + * Called by the Intrinsics in response to an exposure event. + * + ***************************************************************************/ +static void Redisplay(Widget w, XEvent *event, Region region) +{ + /* Pass exposure event down to gadget children. */ + PxmRedisplayGadgets(w, event, region); +} + + + +/***************************************************************************** + * + * SetValues: + * Called by the Intrinsics whenever any of the resource values change. + * + ****************************************************************************/ +static Boolean SetValues(Widget old_w, Widget request_w, Widget new_w, ArgList args, Cardinal *num_args) +{ + PxmPagesWidget cw = (PxmPagesWidget) old_w; + PxmPagesWidget nw = (PxmPagesWidget) new_w; + Boolean redisplay = False; + Boolean need_relayout; + PxmPagesWidgetClass gwc = (PxmPagesWidgetClass) XtClass(new_w); + + if (cw->pages.at != nw->pages.at) { + Layout(new_w, NULL); + return 0; + } + + /* See if any class or subclass resources have changed. */ + if (gwc->pages_class.need_relayout) + need_relayout = (*(gwc->pages_class.need_relayout)) (old_w, new_w); + else + need_relayout = NeedRelayout(old_w, new_w); + + /* If any geometry resources changed and a new size wasn't specified, + recalculate a new ideal size. */ + if (need_relayout) { + /* Reset the widget size so that CalcSize can affect them. */ + if (nw->core.width == cw->core.width) + nw->core.width = 0; + if (nw->core.height == cw->core.height) + nw->core.height = 0; + + /* Call CalcSize. */ + if (gwc->pages_class.calc_size) + (*(gwc->pages_class.calc_size)) (new_w, NULL, &nw->core.width, &nw->core.height); + else + CalcSize(new_w, NULL, &nw->core.width, &nw->core.height); + + + /* If the geometry resources have changed but the size hasn't, + we need to relayout manually, because Xt won't generate a + Resize at this point. */ + if ((nw->core.width == cw->core.width) && (nw->core.height == cw->core.height)) { + + /* Call Layout to configure the children. */ + if (gwc->pages_class.layout) + (*(gwc->pages_class.layout)) (new_w, NULL); + else + Layout(new_w, NULL); + redisplay = True; + } + } + +#ifdef HAVE_XM_TRAIT + /* PxmPages installs the XmQTdialogShellSavvy trait. Therefore, PxmPages + has to process the Xm_DIALOG_SAVVY_FORCE_ORIGIN case, which is as + follows. A DialogShell always mimics the child position on itself. + That is, the "current" position of an PxmPages within a DialogShell is + always 0. Therefore, if an application tries to set PxmPages's x or + y position to 0, the Intrinsics will not detect a position change and + wll not trigger a geometry request. PxmPages has to detect this special + request and set core.x and core.y to the special value, + XmDIALOG_SAVVY_FORCE_ORIGIN. That is, XmDIALOG_SAVVY_FORCE_ORIGIN + tells DialogShell that PxmPages really does want to move to an x or y + position of 0. */ + + if (XmIsDialogShell(XtParent(new_w))) { /* Is parent a DialogShell? */ + Cardinal i; + + /* We have to look in the arglist since old_w->core.x is always 0, and + if new_w->core.x is also set to 0, we see no change. */ + for(i = 0; i < *num_args; i++) { + if (strcmp(args[i].name, XmNx) == 0) { + if ((args[i].value == 0) && (new_w->core.x == 0)) + new_w->core.x = XmDIALOG_SAVVY_FORCE_ORIGIN; + } + if (strcmp(args[i].name, XmNy) == 0) { + if ((args[i].value == 0) && (new_w->core.y == 0)) + new_w->core.y = XmDIALOG_SAVVY_FORCE_ORIGIN; + } + } /* end for */ + } /* end of if */ +#endif + + return (redisplay); +} + + + +/************************************************************************* + * + * SetValuesAlmost: + * Called by the Intrinsics when an XtMakeGeometryRequest call + * returns either XmGeometryAlmost or XtGeometryNo. + * + ***************************************************************************/ +static void SetValuesAlmost(Widget cw, /* unused */ + Widget nw, XtWidgetGeometry *request, XtWidgetGeometry *reply) +{ + PxmPagesWidgetClass gwc = (PxmPagesWidgetClass) XtClass(nw); + + /* PxmPages's parent said XtGeometryNo to PxmPages's geometry request. + Therefore, we need to relayout because this request + was due to a change in internal geometry resource of the PxmPages */ + if (!reply->request_mode) { + if (gwc->pages_class.layout) + (*(gwc->pages_class.layout)) (nw, NULL); + else + Layout(nw, NULL); + } + + *request = *reply; +} + + +/************************************************************************* + * + * QueryGeometry: + * Called by a parent of Pages when the parent needs to find out Pages's + * preferred size. QueryGeometry calls CalcSize to do find the + * preferred size. + * + ***************************************************************************/ +static XtGeometryResult QueryGeometry(Widget w, XtWidgetGeometry *request, XtWidgetGeometry *reply) +{ + PxmPagesWidgetClass gwc = (PxmPagesWidgetClass) XtClass(w); + + /* If PxmPages's parent calls XtQueryGeometry before PxmPages has been + realized, use the current size of PxmPages as the preferred size. */ + /* Deal with user initial size setting */ + if (!XtIsRealized(w)) { /* Widget is not yet realized. */ + reply->width = XtWidth(w); /* might be 0 */ + reply->height = XtHeight(w); /* might be 0 */ + } + else { /* Widget is realized. */ + /* always computes natural size afterwards */ + reply->width = 0; + reply->height = 0; + } + + /* Call CalcSize to figure out what the preferred size really is. */ + if (gwc->pages_class.calc_size) + (*(gwc->pages_class.calc_size)) (w, NULL, &reply->width, &reply->height); + else + CalcSize(w, NULL, &reply->width, &reply->height); + + /* This function handles CWidth and CHeight */ + return PxmReplyToQueryGeometry(w, request, reply); +} + + +/**************************************************************************** + * + * GeometryManager: + * Called by Intrinsics in response to a geometry change request from + * one of the children of PxmPages. + * + ***************************************************************************/ +static XtGeometryResult GeometryManager(Widget w, /* instigator */ + XtWidgetGeometry *request, XtWidgetGeometry *reply) +{ + PxmPagesWidget gw = (PxmPagesWidget) XtParent(w); + XtWidgetGeometry parentRequest; + XtGeometryResult result; + Dimension curWidth, curHeight, curBW; + PxmPagesWidgetClass gwc = (PxmPagesWidgetClass) XtClass((Widget) gw); + + /* If the request was caused by ConstraintSetValues reset the flag */ + if (gw->pages.processing_constraints) { + gw->pages.processing_constraints = False; + /* The ConstraintSetValues added one to border_width; + This is the Xt trick used to fire the GM when a non core + geometry resource (like a constraint) changes. + now take it away. */ + request->border_width -= 1; + } + + /* Save the original child resources. */ + curWidth = w->core.width; + curHeight = w->core.height; + curBW = w->core.border_width; + + /* Deny any requests for a new position. */ + if ((request->request_mode & CWX) || (request->request_mode & CWY)) + return XtGeometryNo; + + if (request->request_mode & CWWidth) + w->core.width = request->width; + if (request->request_mode & CWHeight) + w->core.height = request->height; + if (request->request_mode & CWBorderWidth) + w->core.border_width = request->border_width; + + /* Calculate a new ideal size based on these requests. */ + /* Setting width and height to 0 tells CalcSize to override these + fields with the calculated width and height. */ + parentRequest.width = 0; + parentRequest.height = 0; + if (gwc->pages_class.calc_size) + (*(gwc->pages_class.calc_size)) ((Widget) gw, w, &parentRequest.width, &parentRequest.height); + else + CalcSize((Widget) gw, w, &parentRequest.width, &parentRequest.height); + + + /* Ask the Pages's parent if new calculated size is acceptable. */ + parentRequest.request_mode = CWWidth | CWHeight; + if (request->request_mode & XtCWQueryOnly) + parentRequest.request_mode |= XtCWQueryOnly; + result = XtMakeGeometryRequest((Widget) gw, &parentRequest, NULL); + + /* Turn XtGeometryAlmost into XtGeometryNo. */ + if (result == XtGeometryAlmost) + result = XtGeometryNo; + + if (result == XtGeometryNo || request->request_mode & XtCWQueryOnly) { + /* Restore original geometry. */ + w->core.width = curWidth; + w->core.height = curHeight; + w->core.border_width = curBW; + } + else { + /* result == XtGeometryYes and this wasn't just a query */ + if (gwc->pages_class.layout) + (*(gwc->pages_class.layout)) ((Widget) gw, w); + else + Layout((Widget) gw, w); /* Layout with this child as the instigator, + so that we don't resize this child. */ + } + + return (result); +} + +/************************************************************************** + * + * ChangeManaged: + * Called by the Intrinsics whenever either of the following happens: + * * a managed child becomes unmanaged. + * * an unmanaged child becomes managed. + * + *************************************************************************/ +static void ChangeManaged(Widget w) +{ +#ifdef HAVE_XME + /* Update keyboard traversal */ + XmeNavigChangeManaged(w); +#endif +} + +/************************************************************************** + * + * ConstraintSetValues: + * Called by Intrinsics if there is any change in any of the constraint + * resources. + * + **************************************************************************/ +static Boolean ConstraintSetValues(Widget cw, Widget rw, Widget nw, ArgList args, Cardinal *num_args) +{ + PxmPagesWidget gw; + + if (!XtIsRectObj(nw)) + return (False); + + gw = (PxmPagesWidget) XtParent(nw); + + if (XtIsManaged(nw)) { + /* Tell the Intrinsics and the GeometryManager method that a + reconfigure is needed. */ + gw->pages.processing_constraints = True; + /* A trick: by altering one of the core geometry fields, Xt will + call the parent's geometry_manager method. */ + nw->core.border_width += 1; + } + + return (False); +} + + +/*************************************************************************** + * + * Layout: + * Does all the placement of children. + * Instigator tells whether or not to resize all children. + * + *************************************************************************/ +static void Layout(Widget wid, Widget instigator) +{ + PxmPagesWidget gw = (PxmPagesWidget) wid; + Dimension mw = gw->pages.margin_width; + Dimension mh = gw->pages.margin_height; + Cardinal i; + + /* show only one page */ + for(i = 0; i < gw->composite.num_children; i++) { + Dimension x0, y0, xs, ys, cb = 0; + Widget ic = gw->composite.children[i]; + + xs = gw->core.width - 2*mw; + ys = gw->core.height - 2*mh; + + if (i == gw->pages.at) { /* show */ + x0 = mw; + y0 = mh; + } + else { /* hide */ + x0 = -(ic->core.width + 100); + y0 = -(ic->core.height + 100); + } + + /* If layout is instigated by the GeometryManager don't + configure the requesting child, just set its geometry and + let Xt configure it. */ + if (ic != instigator) { + PxmConfigureObject(ic, x0, y0, xs, ys, cb); + } + else { + ic->core.x = x0; + ic->core.y = y0; + ic->core.width = xs; + ic->core.height = ys; + ic->core.border_width = cb; + } + + } +} + + + +/****************************************************************************** + * + * CalcSize: + * Called by QueryGeometry, SetValues, GeometryManager, and ChangeManaged. + * Calculate the ideal size of the PxmPages widget. + * Only affects the returned size if it is 0. + * + ****************************************************************************/ +static void CalcSize(Widget wid, Widget instigator, Dimension *TotalWidthOfPagesWidget, Dimension *TotalHeightOfPagesWidget) +{ + PxmPagesWidget gw = (PxmPagesWidget)wid; + Dimension maxcw = 0, mw = gw->pages.margin_width; + Dimension maxch = 0, mh = gw->pages.margin_height; + Cardinal i; + + /* calculate the maximum dims we need to allocate for children */ + for(i = 0; i < gw->composite.num_children; i++) { + Widget ic = gw->composite.children[i]; + Dimension cb = ic->core.border_width; + Dimension cw, ch; + XtWidgetGeometry reply; + + XtQueryGeometry(ic, NULL, &reply); + cw = 2*cb + (reply.request_mode & CWWidth) ? reply.width : 0; + ch = 2*cb + (reply.request_mode & CWHeight) ? reply.height : 0; + if (cw > maxcw) + maxcw = cw; + if (ch > maxch) + maxch = ch; + } + + *TotalWidthOfPagesWidget = maxcw + 2*mw; + *TotalHeightOfPagesWidget = maxch + 2*mh; +} + + +/**************************************************************************** + * + * NeedRelayout: + * Called by SetValues. + * Returns True if a relayout is needed. + * based on this class and all superclass resources' changes. + * + ***************************************************************************/ +static Boolean NeedRelayout(Widget old_w, Widget new_w) +{ + return False; +} + + +#ifdef HAVE_XM_TRAIT +/*-- Trait methods --*/ + + +/**************************************************************** + * + * Trait method for XmQTdialogShellSavvy trait. + * + **************************************************************/ +static void CallMapUnmap(Widget wid, Boolean map_unmap) +{ + PxmPagesWidget pages = (PxmPagesWidget) wid; + XmAnyCallbackStruct call_data; + + call_data.reason = (map_unmap) ? XmCR_MAP : XmCR_UNMAP; + call_data.event = NULL; + + if (map_unmap) { + XtCallCallbackList(wid, pages->pages.map_callback, &call_data); + } + else { + XtCallCallbackList(wid, pages->pages.unmap_callback, &call_data); + } +} + +/***************************************************************** + * + * Trait method for XmQTspecifyRenderTable. + * +*****************************************************************/ + +static XmRenderTable GetTable(Widget wid, XtEnum type) +{ + PxmPagesWidget pages = (PxmPagesWidget) wid; + + switch (type) { + case XmLABEL_RENDER_TABLE: + return pages->pages.label_render_table; + case XmBUTTON_RENDER_TABLE: + return pages->pages.button_render_table; + case XmTEXT_RENDER_TABLE: + return pages->pages.text_render_table; + } + + return NULL; +} +#endif + +/******************************************************************************* + * + * PxmCreatePages: + * Called by an application. + * + ******************************************************************************/ +Widget PxmCreatePages(Widget parent, char *name, ArgList arglist, Cardinal argcount) +{ + /* This is a convenience function to instantiate an PxmPages widget. */ + return (XtCreateWidget(name, pxmPagesWidgetClass, parent, arglist, argcount)); +} + Index: tags/2.1.2/src_plugins/hid_lesstif/Pages.h =================================================================== --- tags/2.1.2/src_plugins/hid_lesstif/Pages.h (nonexistent) +++ tags/2.1.2/src_plugins/hid_lesstif/Pages.h (revision 24813) @@ -0,0 +1,63 @@ +/* + * Pages widget for Motif + * + * Copyright (c) 1987-2012, The Open Group. All rights reserved. + * Copyright (c) 2019, Tibor 'Igor2' Palinkas + * (widget code based on Exm Grid) + * + * These libraries and programs are free software; you can + * redistribute them and/or modify them under the terms of the GNU + * Lesser General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * These libraries and programs are distributed in the hope that + * they will be useful, but WITHOUT ANY WARRANTY; without even the + * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with these librararies and programs; if not, write + * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth + * Floor, Boston, MA 02110-1301 USA + */ + + +#ifndef _PxmPages_h +#define _PxmPages_h + + +#include /* widget public header file for XmManager */ + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Define the widget class and widget record. */ +externalref WidgetClass pxmPagesWidgetClass; + +typedef struct _PxmPagesClassRec *PxmPagesWidgetClass; +typedef struct _PxmPagesRec *PxmPagesWidget; + + +/* Define an IsSubclass macro. */ +#ifndef PxmIsPages +#define PxmIsPages(w) XtIsSubclass(w, pxmPagesWidgetClass) +#endif + + +/* Define string equivalents of new resource names. */ +#define PxmNpagesAt "pagesAt" +#define PxmCPagesAt "PagesAt" + +/* Specify the API for this widget. */ +extern Widget PxmCreatePages(Widget parent, char *name, ArgList arglist, Cardinal argcount); + +#ifdef __cplusplus +} +#endif + +#endif /* _PxmPages_h */ + Index: tags/2.1.2/src_plugins/hid_lesstif/PagesP.h =================================================================== --- tags/2.1.2/src_plugins/hid_lesstif/PagesP.h (nonexistent) +++ tags/2.1.2/src_plugins/hid_lesstif/PagesP.h (revision 24813) @@ -0,0 +1,131 @@ +/* + * Pages widget for Motif + * + * Copyright (c) 1987-2012, The Open Group. All rights reserved. + * Copyright (c) 2019, Tibor 'Igor2' Palinkas + * (widget code based on Exm Grid) + * + * These libraries and programs are free software; you can + * redistribute them and/or modify them under the terms of the GNU + * Lesser General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * These libraries and programs are distributed in the hope that + * they will be useful, but WITHOUT ANY WARRANTY; without even the + * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with these librararies and programs; if not, write + * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth + * Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _PxmPagesP_h +#define _PxmPagesP_h + + +#include "Pages.h" /* public header file for PxmPages */ +#include /* private header file for XmManager */ + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Make the following two methods inheritable by subclasses of PxmPages. */ +#define PxmInheritLayout ((PxmLayoutProc) _XtInherit) +#define PxmInheritCalcSize ((PxmCalcSizeProc) _XtInherit) +#define PxmInheritNeedRelayout ((PxmNeedRelayoutProc) _XtInherit) + + +/* Define new data types for these two inheritable methods. */ +typedef void (*PxmLayoutProc) (Widget, Widget); +typedef void (*PxmCalcSizeProc) (Widget, Widget, Dimension *, Dimension *); +typedef Boolean(*PxmNeedRelayoutProc) (Widget, Widget); + +/* Define the widget class part. */ +typedef struct { + PxmLayoutProc layout; + PxmCalcSizeProc calc_size; + PxmNeedRelayoutProc need_relayout; + XtPointer extension; +} PxmPagesClassPart; + + +/* Define the full class record. */ +typedef struct _PxmPagesClassRec { + CoreClassPart core_class; + CompositeClassPart composite_class; + ConstraintClassPart constraint_class; + XmManagerClassPart manager_class; + PxmPagesClassPart pages_class; +} PxmPagesClassRec; + +externalref PxmPagesClassRec pxmPagesClassRec; + + +/* Define the widget instance part. */ +typedef struct { + /* Provide space for the values of the four resources of PxmPages. */ + Dimension margin_width; + Dimension margin_height; + XtCallbackList map_callback; + XtCallbackList unmap_callback; + Cardinal at; /* current page shown */ +#ifdef HAVE_XM_TRAIT + XmRenderTable button_render_table; + XmRenderTable label_render_table; + XmRenderTable text_render_table; +#endif + + /* processing_constraints is a flag. If its value is True, then + it means that the ConstraintSetValues method is requesting a + geometry change. */ + Boolean processing_constraints; + +} PxmPagesPart; + +/* Establish an arbitrary limit */ +#define EXM_GRID_MAX_NUMBER_OF_ROWS 100 +#define EXM_GRID_MAX_NUMBER_OF_COLUMNS 100 + +/* Define the full instance record. */ +typedef struct _PxmPagesRec { + CorePart core; + CompositePart composite; + ConstraintPart constraint; + XmManagerPart manager; + PxmPagesPart pages; +} PxmPagesRec; + +/* Define the subclassing level index to be used with ResolvePartOffset */ +#define PxmPagesIndex (XmManagerIndex + 1) + +/* Define the constraint part structure. */ +typedef struct _PxmPagesConstraintPart { + Boolean dummy; +} PxmPagesConstraintPart, *PxmPagesConstraint; + + +/* Define the full constraint structure. */ +typedef struct _PxmPagesConstraintRec { + XmManagerConstraintPart manager; + PxmPagesConstraintPart pages; +} PxmPagesConstraintRec, *PxmPagesConstraintPtr; + + +/* Define macros for this class. */ +#define PxmPagesCPart(w) \ + (&((PxmPagesConstraintPtr) (w)->core.constraints)->pages) + + + +#ifdef __cplusplus +} +#endif + +#endif /* _PxmPagesP_h */ Index: tags/2.1.2/src_plugins/hid_lesstif/Plug.tmpasm =================================================================== --- tags/2.1.2/src_plugins/hid_lesstif/Plug.tmpasm (nonexistent) +++ tags/2.1.2/src_plugins/hid_lesstif/Plug.tmpasm (revision 24813) @@ -0,0 +1,41 @@ +put /local/pcb/mod {hid_lesstif} +put /local/pcb/mod/OBJS [@ + $(PLUGDIR)/hid_lesstif/dialogs.o + $(PLUGDIR)/hid_lesstif/dlg_fileselect.o + $(PLUGDIR)/hid_lesstif/library.o + $(PLUGDIR)/hid_lesstif/main.o + $(PLUGDIR)/hid_lesstif/menu.o + $(PLUGDIR)/hid_lesstif/netlist.o + $(PLUGDIR)/hid_lesstif/styles.o + $(PLUGDIR)/hid_lesstif/stdarg.o + $(PLUGDIR)/hid_lesstif/wt_colorbtn.o + $(PLUGDIR)/hid_lesstif/wt_xpm.o + $(PLUGDIR)/hid_lesstif/xm_tree_table_pixmaps.o + $(PLUGDIR)/hid_lesstif/xm_tree_table_priv.o + $(PLUGDIR)/hid_lesstif/xm_tree_table_widget.o + $(PLUGDIR)/hid_lesstif/FillBox.o + $(PLUGDIR)/hid_lesstif/Pages.o +@] + +switch /local/pcb/hid_lesstif/controls + case {disable} end; + default + put /local/pcb/mod/CFLAGS [@ + @?/target/libs/gui/lesstif2/cflags@ + @?/target/libs/gui/xinerama/cflags@ + @?/target/libs/gui/xrender/cflags@ + @] + + put /local/pcb/mod/LDFLAGS [@ + @?/target/libs/gui/lesstif2/ldflags@ + @?/target/libs/gui/xinerama/ldflags@ + @?/target/libs/gui/xrender/ldflags@ + @] + end +end + +switch /local/pcb/hid_lesstif/controls + case {buildin} include /local/pcb/tmpasm/buildin; end; + case {plugin} include /local/pcb/tmpasm/plugin; end; + case {disable} include /local/pcb/tmpasm/disable; end; +end Index: tags/2.1.2/src_plugins/hid_lesstif/dialogs.c =================================================================== --- tags/2.1.2/src_plugins/hid_lesstif/dialogs.c (nonexistent) +++ tags/2.1.2/src_plugins/hid_lesstif/dialogs.c (revision 24813) @@ -0,0 +1,1188 @@ +#include "xincludes.h" + +#include "config.h" +#include "conf_core.h" + +#include +#include +#include +#include + +#include "FillBox.h" + +#include "compat_misc.h" +#include "data.h" +#include "event.h" +#include "build_run.h" +#include "crosshair.h" +#include "layer.h" +#include "pcb-printf.h" + +#include "hid.h" +#include "lesstif.h" +#include "hid_attrib.h" +#include "actions.h" +#include "hid_init.h" +#include "stdarg.h" +#include "misc_util.h" +#include "search.h" +#include "change.h" +#include "conf_core.h" + +#include "plug_io.h" + +int pcb_ltf_ok; + +#define COMPONENT_SIDE_NAME "(top)" +#define SOLDER_SIDE_NAME "(bottom)" + +void pcb_ltf_winplace(Display *dsp, Window w, const char *id, int defx, int defy) +{ + int plc[4] = {-1, -1, -1, -1}; + + plc[2] = defx; + plc[3] = defy; + + pcb_event(PCB_EVENT_DAD_NEW_DIALOG, "psp", NULL, id, plc); + + if (conf_core.editor.auto_place) { + if ((plc[2] > 0) && (plc[3] > 0) && (plc[0] >= 0) && (plc[1] >= 0)) { + XMoveResizeWindow(dsp, w, plc[0], plc[1], plc[2], plc[3]); + } + else { + if ((plc[2] > 0) && (plc[3] > 0)) + XResizeWindow(dsp, w, plc[2], plc[3]); + if ((plc[0] >= 0) && (plc[1] >= 0)) + XMoveWindow(dsp, w, plc[0], plc[1]); + } + } +} + +static void ltf_winplace_cfg(Display *dsp, Window win, void *ctx, const char *id) +{ + + Window rw; + int x = -1, y = -1; + unsigned int w, h, brd, depth; + +#if 0 + Window cw; + rw = DefaultRootWindow(dsp); + XTranslateCoordinates(dsp, win, rw, 0, 0, &x, &y, &cw); + printf("plc1: %s: %d %d\n", id, x, y); +#endif + + XGetGeometry(dsp, win, &rw, &x, &y, &w, &h, &brd, &depth); + pcb_event(PCB_EVENT_DAD_NEW_GEO, "psiiii", ctx, id, (int)x, (int)y, (int)w, (int)h); +} + + +void pcb_ltf_wplc_config_cb(Widget shell, XtPointer data, XEvent *xevent, char *dummy) +{ + char *id = data; + Display *dsp; + Window win; + XConfigureEvent *cevent = (XConfigureEvent *)xevent; + + if (cevent->type != ConfigureNotify) + return; + + win = XtWindow(shell); + dsp = XtDisplay(shell); + ltf_winplace_cfg(dsp, win, NULL, id); +} + + +/* ------------------------------------------------------------ */ + +static void dialog_callback_ok_value(Widget w, void *v, void *cbs) +{ + pcb_ltf_ok = (int) (size_t) v; +} + +#define DAD_CLOSED 4242 + +int pcb_ltf_wait_for_dialog(Widget w) +{ + pcb_ltf_ok = -1; + XtManageChild(w); + for(;;) { + XEvent e; + + if (pcb_ltf_ok != -1) + break; + if (!XtIsManaged(w)) + break; + XtAppNextEvent(app_context, &e); + XtDispatchEvent(&e); + } + if ((pcb_ltf_ok != DAD_CLOSED) && (XtIsManaged(w))) + XtUnmanageChild(w); + return pcb_ltf_ok; +} + +/* ------------------------------------------------------------ */ + +typedef struct { + pcb_hid_attribute_t *attrs; + int n_attrs, actual_nattrs; + Widget *wl; /* content widget */ + Widget *wltop;/* the parent widget, which is different from wl if reparenting (extra boxes, e.g. for framing or scrolling) was needed */ + Widget **btn; /* enum value buttons */ + pcb_hid_attr_val_t *results; + void *caller_data; + Widget dialog; + pcb_hid_attr_val_t property[PCB_HATP_max]; + Dimension minw, minh; + void (*close_cb)(void *caller_data, pcb_hid_attr_ev_t ev); + char *id; + unsigned close_cb_called:1; + unsigned already_closing:1; + unsigned already_destroying:1; + unsigned inhibit_valchg:1; + unsigned widget_destroyed:1; + unsigned set_ok:1; +} lesstif_attr_dlg_t; + +static void attribute_dialog_readres(lesstif_attr_dlg_t *ctx, int widx) +{ + char *cp; + + if (ctx->attrs[widx].help_text == ATTR_UNDOCUMENTED) + return; + + switch(ctx->attrs[widx].type) { + case PCB_HATT_BOOL: + ctx->attrs[widx].default_val.int_value = XmToggleButtonGetState(ctx->wl[widx]); + break; + case PCB_HATT_STRING: + free((char *)ctx->attrs[widx].default_val.str_value); + ctx->attrs[widx].default_val.str_value = pcb_strdup(XmTextGetString(ctx->wl[widx])); + if (ctx->results != NULL) { + TODO("this is a memory leak at the moment, because ctx->results[widx].str_value may be const char * in some cases; will be gone when result is gone"); +/* free((char *)ctx->results[widx].str_value);*/ + ctx->results[widx].str_value = ctx->attrs[widx].default_val.str_value; + } + return; /* can't rely on central copy because of the allocation */ + case PCB_HATT_INTEGER: + cp = XmTextGetString(ctx->wl[widx]); + sscanf(cp, "%d", &ctx->attrs[widx].default_val.int_value); + break; + case PCB_HATT_COORD: + cp = XmTextGetString(ctx->wl[widx]); + ctx->attrs[widx].default_val.coord_value = pcb_get_value(cp, NULL, NULL, NULL); + break; + case PCB_HATT_REAL: + cp = XmTextGetString(ctx->wl[widx]); + sscanf(cp, "%lg", &ctx->results[widx].real_value); + break; + case PCB_HATT_ENUM: + { + const char **uptr; + Widget btn; + + stdarg_n = 0; + stdarg(XmNmenuHistory, &btn); + XtGetValues(ctx->wl[widx], stdarg_args, stdarg_n); + stdarg_n = 0; + stdarg(XmNuserData, &uptr); + XtGetValues(btn, stdarg_args, stdarg_n); + ctx->attrs[widx].default_val.int_value = uptr - ctx->attrs[widx].enumerations; + } + break; + default: + break; + } + + if (ctx->results != NULL) + ctx->results[widx] = ctx->attrs[widx].default_val; +} + +static int attr_get_idx(XtPointer dlg_widget_, lesstif_attr_dlg_t **ctx_out) +{ + lesstif_attr_dlg_t *ctx; + Widget dlg_widget = (Widget)dlg_widget_; /* ctx->wl[i] */ + int widx; + + if (dlg_widget == NULL) + return -1; + + XtVaGetValues(dlg_widget, XmNuserData, &ctx, NULL); + + if (ctx == NULL) { + *ctx_out = NULL; + return -1; + } + *ctx_out = ctx; + + if (ctx->inhibit_valchg) + return -1; + + for(widx = 0; widx < ctx->n_attrs; widx++) + if (ctx->wl[widx] == dlg_widget) + break; + + if (widx >= ctx->n_attrs) + return -1; + + return widx; +} + +static void valchg(Widget w, XtPointer dlg_widget_, XtPointer call_data) +{ + lesstif_attr_dlg_t *ctx; + int widx = attr_get_idx(dlg_widget_, &ctx); + if (widx < 0) + return; + + ctx->attrs[widx].changed = 1; + + attribute_dialog_readres(ctx, widx); + + if ((ctx->attrs[widx].change_cb == NULL) && (ctx->property[PCB_HATP_GLOBAL_CALLBACK].func == NULL)) + return; + + if (ctx->property[PCB_HATP_GLOBAL_CALLBACK].func != NULL) + ctx->property[PCB_HATP_GLOBAL_CALLBACK].func(ctx, ctx->caller_data, &ctx->attrs[widx]); + if (ctx->attrs[widx].change_cb != NULL) + ctx->attrs[widx].change_cb(ctx, ctx->caller_data, &ctx->attrs[widx]); +} + +static void activated(Widget w, XtPointer dlg_widget_, XtPointer call_data) +{ + lesstif_attr_dlg_t *ctx; + int widx = attr_get_idx(dlg_widget_, &ctx); + if (widx < 0) + return; + + if (ctx->attrs[widx].enter_cb != NULL) + ctx->attrs[widx].enter_cb(ctx, ctx->caller_data, &ctx->attrs[widx]); +} + +static int attribute_dialog_add(lesstif_attr_dlg_t *ctx, Widget parent, int start_from); + +#include "dlg_attr_misc.c" +#include "dlg_attr_box.c" +#include "dlg_attr_tree.c" + +/* returns the index of HATT_END where the loop had to stop */ +static int attribute_dialog_add(lesstif_attr_dlg_t *ctx, Widget parent, int start_from) +{ + int len, i, numch, numcol; + static XmString empty = 0; + + if (!empty) + empty = XmStringCreatePCB(" "); + + for (i = start_from; i < ctx->n_attrs; i++) { + char buf[30]; + Widget w; + + if (ctx->attrs[i].type == PCB_HATT_END) + break; + + if (ctx->attrs[i].help_text == ATTR_UNDOCUMENTED) + continue; + + /* Add content */ + stdarg_n = 0; + stdarg(XmNalignment, XmALIGNMENT_END); + if (ctx->attrs[i].pcb_hatt_flags & PCB_HATF_EXPFILL) + stdarg(PxmNfillBoxFill, 1); + stdarg(XmNuserData, ctx); + + switch(ctx->attrs[i].type) { + case PCB_HATT_BEGIN_HBOX: + w = pcb_motif_box(parent, XmStrCast(ctx->attrs[i].name), 'h', 0, (ctx->attrs[i].pcb_hatt_flags & PCB_HATF_FRAME), (ctx->attrs[i].pcb_hatt_flags & PCB_HATF_SCROLL)); + XtManageChild(w); + ctx->wl[i] = w; + i = attribute_dialog_add(ctx, w, i+1); + break; + + case PCB_HATT_BEGIN_VBOX: + w = pcb_motif_box(parent, XmStrCast(ctx->attrs[i].name), 'v', 0, (ctx->attrs[i].pcb_hatt_flags & PCB_HATF_FRAME), (ctx->attrs[i].pcb_hatt_flags & PCB_HATF_SCROLL)); + XtManageChild(w); + ctx->wl[i] = w; + i = attribute_dialog_add(ctx, w, i+1); + break; + + case PCB_HATT_BEGIN_HPANE: + case PCB_HATT_BEGIN_VPANE: + i = ltf_pane_create(ctx, i, parent, (ctx->attrs[i].type == PCB_HATT_BEGIN_HPANE)); + break; + + case PCB_HATT_BEGIN_TABLE: + /* create content table */ + numcol = ctx->attrs[i].pcb_hatt_table_cols; + len = pcb_hid_attrdlg_num_children(ctx->attrs, i+1, ctx->n_attrs); + numch = len / numcol + !!(len % numcol); + w = pcb_motif_box(parent, XmStrCast(ctx->attrs[i].name), 't', numch, (ctx->attrs[i].pcb_hatt_flags & PCB_HATF_FRAME), (ctx->attrs[i].pcb_hatt_flags & PCB_HATF_SCROLL)); + + ctx->wl[i] = w; + + i = attribute_dialog_add(ctx, w, i+1); + while((len % numcol) != 0) { + Widget pad; + + stdarg_n = 0; + stdarg(XmNalignment, XmALIGNMENT_END); + pad = XmCreateLabel(w, XmStrCast("."), stdarg_args, stdarg_n); + XtManageChild(pad); + len++; + } + XtManageChild(w); + break; + + case PCB_HATT_BEGIN_TABBED: + i = ltf_tabbed_create(ctx, parent, &ctx->attrs[i], i); + break; + + case PCB_HATT_BEGIN_COMPOUND: + i = attribute_dialog_add(ctx, parent, i+1); + break; + + case PCB_HATT_PREVIEW: + ctx->wl[i] = ltf_preview_create(ctx, parent, &ctx->attrs[i]); + break; + + case PCB_HATT_TEXT: + ctx->wl[i] = ltf_text_create(ctx, parent, &ctx->attrs[i]); + break; + + case PCB_HATT_TREE: + ctx->wl[i] = ltf_tree_create(ctx, parent, &ctx->attrs[i]); + break; + + case PCB_HATT_PICTURE: + ctx->wl[i] = ltf_picture_create(ctx, parent, &ctx->attrs[i]); + break; + + case PCB_HATT_PICBUTTON: + ctx->wl[i] = ltf_picbutton_create(ctx, parent, &ctx->attrs[i]); + XtAddCallback(ctx->wl[i], XmNactivateCallback, valchg, ctx->wl[i]); + XtSetValues(ctx->wl[i], stdarg_args, stdarg_n); + break; + + case PCB_HATT_COLOR: + ctx->wl[i] = ltf_colorbtn_create(ctx, parent, &ctx->attrs[i], (ctx->attrs[i].pcb_hatt_flags & PCB_HATF_CLR_STATIC)); + /* callback handled internally */ + XtSetValues(ctx->wl[i], stdarg_args, stdarg_n); + break; + + case PCB_HATT_LABEL: + stdarg_n = 0; + stdarg(XmNalignment, XmALIGNMENT_BEGINNING); + ctx->wl[i] = XmCreateLabel(parent, XmStrCast(ctx->attrs[i].name), stdarg_args, stdarg_n); + break; + case PCB_HATT_BOOL: + stdarg(XmNlabelString, empty); + stdarg(XmNset, ctx->results[i].int_value); + ctx->wl[i] = XmCreateToggleButton(parent, XmStrCast(ctx->attrs[i].name), stdarg_args, stdarg_n); + XtAddCallback(ctx->wl[i], XmNvalueChangedCallback, valchg, ctx->wl[i]); + break; + case PCB_HATT_STRING: + stdarg(XmNcolumns, 40); + stdarg(XmNresizeWidth, True); + stdarg(XmNvalue, ctx->results[i].str_value); + ctx->wl[i] = XmCreateTextField(parent, XmStrCast(ctx->attrs[i].name), stdarg_args, stdarg_n); + XtAddCallback(ctx->wl[i], XmNvalueChangedCallback, valchg, ctx->wl[i]); + XtAddCallback(ctx->wl[i], XmNactivateCallback, activated, ctx->wl[i]); + break; + case PCB_HATT_INTEGER: + stdarg(XmNcolumns, 13); + stdarg(XmNresizeWidth, True); + sprintf(buf, "%d", ctx->results[i].int_value); + stdarg(XmNvalue, buf); + ctx->wl[i] = XmCreateTextField(parent, XmStrCast(ctx->attrs[i].name), stdarg_args, stdarg_n); + XtAddCallback(ctx->wl[i], XmNvalueChangedCallback, valchg, ctx->wl[i]); + break; + case PCB_HATT_COORD: + stdarg(XmNcolumns, 13); + stdarg(XmNresizeWidth, True); + pcb_snprintf(buf, sizeof(buf), "%$mS", ctx->results[i].coord_value); + stdarg(XmNvalue, buf); + ctx->wl[i] = XmCreateTextField(parent, XmStrCast(ctx->attrs[i].name), stdarg_args, stdarg_n); + XtAddCallback(ctx->wl[i], XmNvalueChangedCallback, valchg, ctx->wl[i]); + break; + case PCB_HATT_REAL: + stdarg(XmNcolumns, 16); + stdarg(XmNresizeWidth, True); + pcb_snprintf(buf, sizeof(buf), "%g", ctx->results[i].real_value); + stdarg(XmNvalue, buf); + ctx->wl[i] = XmCreateTextField(parent, XmStrCast(ctx->attrs[i].name), stdarg_args, stdarg_n); + XtAddCallback(ctx->wl[i], XmNvalueChangedCallback, valchg, ctx->wl[i]); + break; + case PCB_HATT_PROGRESS: + ctx->wl[i] = ltf_progress_create(ctx, parent); + break; + case PCB_HATT_ENUM: + { + static XmString empty = 0; + Widget submenu, default_button = 0; + int sn = stdarg_n; + + if (empty == 0) + empty = XmStringCreatePCB(""); + + submenu = XmCreatePulldownMenu(parent, XmStrCast(ctx->attrs[i].name == NULL ? "anon" : ctx->attrs[i].name), stdarg_args + sn, stdarg_n - sn); + + stdarg_n = sn; + stdarg(XmNlabelString, empty); + stdarg(XmNsubMenuId, submenu); + ctx->wl[i] = XmCreateOptionMenu(parent, XmStrCast(ctx->attrs[i].name), stdarg_args, stdarg_n); + for (sn = 0; ctx->attrs[i].enumerations[sn]; sn++); + ctx->btn[i] = calloc(sizeof(Widget), sn); + for (sn = 0; ctx->attrs[i].enumerations[sn]; sn++) { + Widget btn; + XmString label; + stdarg_n = 0; + label = XmStringCreatePCB(ctx->attrs[i].enumerations[sn]); + stdarg(XmNuserData, &ctx->attrs[i].enumerations[sn]); + stdarg(XmNlabelString, label); + btn = XmCreatePushButton(submenu, XmStrCast("menubutton"), stdarg_args, stdarg_n); + XtManageChild(btn); + XmStringFree(label); + if (sn == ctx->attrs[i].default_val.int_value) + default_button = btn; + XtAddCallback(btn, XmNactivateCallback, valchg, ctx->wl[i]); + (ctx->btn[i])[sn] = btn; + } + if (default_button) { + stdarg_n = 0; + stdarg(XmNmenuHistory, default_button); + XtSetValues(ctx->wl[i], stdarg_args, stdarg_n); + } + } + break; + case PCB_HATT_BUTTON: + stdarg(XmNlabelString, XmStringCreatePCB(ctx->attrs[i].default_val.str_value)); + ctx->wl[i] = XmCreatePushButton(parent, XmStrCast(ctx->attrs[i].name), stdarg_args, stdarg_n); + XtAddCallback(ctx->wl[i], XmNactivateCallback, valchg, ctx->wl[i]); + break; + default: + ctx->wl[i] = XmCreateLabel(parent, XmStrCast("UNIMPLEMENTED"), stdarg_args, stdarg_n); + break; + } + if (ctx->wl[i] != NULL) + XtManageChild(ctx->wl[i]); + if (ctx->wltop[i] == NULL) + ctx->wltop[i] = ctx->wl[i]; + } + return i; +} + + +static int attribute_dialog_set(lesstif_attr_dlg_t *ctx, int idx, const pcb_hid_attr_val_t *val) +{ + char buf[30]; + int save, n, copied = 0; + + save = ctx->inhibit_valchg; + ctx->inhibit_valchg = 1; + switch(ctx->attrs[idx].type) { + case PCB_HATT_BEGIN_HBOX: + case PCB_HATT_BEGIN_VBOX: + case PCB_HATT_BEGIN_TABLE: + case PCB_HATT_BEGIN_COMPOUND: + goto err; + case PCB_HATT_END: + { + pcb_hid_compound_t *cmp = (pcb_hid_compound_t *)ctx->attrs[idx].enumerations; + if ((cmp != NULL) && (cmp->set_value != NULL)) + cmp->set_value(&ctx->attrs[idx], ctx, idx, val); + else + goto err; + } + break; + case PCB_HATT_BEGIN_TABBED: + ltf_tabbed_set(ctx->wl[idx], val->int_value); + break; + case PCB_HATT_BEGIN_HPANE: + case PCB_HATT_BEGIN_VPANE: + /* not possible to change the pane with the default motif widget */ + break; + case PCB_HATT_BUTTON: + XtVaSetValues(ctx->wl[idx], XmNlabelString, XmStringCreatePCB(val->str_value), NULL); + break; + case PCB_HATT_LABEL: + XtVaSetValues(ctx->wl[idx], XmNlabelString, XmStringCreatePCB(val->str_value), NULL); + break; + case PCB_HATT_BOOL: + XtVaSetValues(ctx->wl[idx], XmNset, val->int_value, NULL); + break; + case PCB_HATT_STRING: + XtVaSetValues(ctx->wl[idx], XmNvalue, XmStrCast(val->str_value), NULL); + ctx->attrs[idx].default_val.str_value = pcb_strdup(val->str_value); + copied = 1; + break; + case PCB_HATT_INTEGER: + sprintf(buf, "%d", val->int_value); + XtVaSetValues(ctx->wl[idx], XmNvalue, XmStrCast(buf), NULL); + break; + case PCB_HATT_COORD: + pcb_snprintf(buf, sizeof(buf), "%$mS", val->coord_value); + XtVaSetValues(ctx->wl[idx], XmNvalue, XmStrCast(buf), NULL); + break; + case PCB_HATT_REAL: + pcb_snprintf(buf, sizeof(buf), "%g", val->real_value); + XtVaSetValues(ctx->wl[idx], XmNvalue, XmStrCast(buf), NULL); + break; + case PCB_HATT_PROGRESS: + ltf_progress_set(ctx, idx, val->real_value); + break; + case PCB_HATT_COLOR: + ltf_colorbtn_set(ctx, idx, &val->clr_value); + break; + case PCB_HATT_PREVIEW: + ltf_preview_set(ctx, idx, val->real_value); + break; + case PCB_HATT_TEXT: + ltf_text_set(ctx, idx, val->str_value); + break; + case PCB_HATT_TREE: + ltf_tree_set(ctx, idx, val->str_value); + break; + case PCB_HATT_ENUM: + for (n = 0; ctx->attrs[idx].enumerations[n]; n++) { + if (n == val->int_value) { + stdarg_n = 0; + stdarg(XmNmenuHistory, (ctx->btn[idx])[n]); + XtSetValues(ctx->wl[idx], stdarg_args, stdarg_n); + goto ok; + } + } + goto err; + default: + goto err; + } + + ok:; + if (!copied) + ctx->attrs[idx].default_val = *val; + ctx->inhibit_valchg = save; + return 0; + + err:; + ctx->inhibit_valchg = save; + return -1; +} + +static void ltf_attr_destroy_cb(Widget w, void *v, void *cbs) +{ + lesstif_attr_dlg_t *ctx = v; + + if (ctx->set_ok) + pcb_ltf_ok = DAD_CLOSED; + + if ((!ctx->close_cb_called) && (ctx->close_cb != NULL)) { + ctx->close_cb_called = 1; + ctx->already_destroying = 1; + ctx->close_cb(ctx->caller_data, PCB_HID_ATTR_EV_WINCLOSE); + } + if (!ctx->widget_destroyed) { + ctx->widget_destroyed = 1; + XtUnmanageChild(w); + XtDestroyWidget(w); + free(ctx->wl); + free(ctx->wltop); + free(ctx->id); + free(ctx); + } +} + +static void ltf_attr_config_cb(Widget shell, XtPointer data, XEvent *xevent, char *dummy) +{ + lesstif_attr_dlg_t *ctx = data; + Window win; + Display *dsp; + XConfigureEvent *cevent = (XConfigureEvent *)xevent; + + if (cevent->type != ConfigureNotify) + return; + + win = XtWindow(shell); + dsp = XtDisplay(shell); + + ltf_winplace_cfg(dsp, XtWindow(XtParent(XtParent(ctx->dialog))), ctx, ctx->id); +} + +static void ltf_initial_wstates(lesstif_attr_dlg_t *ctx) +{ + int n; + for(n = 0; n < ctx->n_attrs; n++) + if (ctx->attrs[n].pcb_hatt_flags & PCB_HATF_HIDE) + XtUnmanageChild(ctx->wltop[n]); +} + +void *lesstif_attr_dlg_new(const char *id, pcb_hid_attribute_t *attrs, int n_attrs, pcb_hid_attr_val_t *results, const char *title, void *caller_data, pcb_bool modal, void (*button_cb)(void *caller_data, pcb_hid_attr_ev_t ev), int defx, int defy) +{ + Widget topform, main_tbl; + int i; + lesstif_attr_dlg_t *ctx; + + ctx = calloc(sizeof(lesstif_attr_dlg_t), 1); + ctx->attrs = attrs; + ctx->results = results; + ctx->n_attrs = n_attrs; + ctx->caller_data = caller_data; + ctx->minw = ctx->minh = 32; + ctx->close_cb = button_cb; + ctx->close_cb_called = 0; + ctx->widget_destroyed = 0; + ctx->id = pcb_strdup(id); + + for (i = 0; i < n_attrs; i++) { + if (attrs[i].help_text != ATTR_UNDOCUMENTED) + ctx->actual_nattrs++; + results[i] = attrs[i].default_val; + if (PCB_HAT_IS_STR(attrs[i].type) && (results[i].str_value)) + results[i].str_value = pcb_strdup(results[i].str_value); + else + results[i].str_value = NULL; + } + + ctx->wl = (Widget *) calloc(n_attrs, sizeof(Widget)); + ctx->wltop = (Widget *)calloc(n_attrs, sizeof(Widget)); + ctx->btn = (Widget **) calloc(n_attrs, sizeof(Widget *)); + + stdarg_n = 0; + topform = XmCreateFormDialog(mainwind, XmStrCast(title), stdarg_args, stdarg_n); + XtManageChild(topform); + + pcb_ltf_winplace(XtDisplay(topform), XtWindow(XtParent(topform)), id, defx, defy); + + ctx->dialog = XtParent(topform); + XtAddCallback(topform, XmNunmapCallback, ltf_attr_destroy_cb, ctx); + XtAddEventHandler(XtParent(topform), StructureNotifyMask, False, ltf_attr_config_cb, ctx); + + + stdarg_n = 0; + stdarg(XmNfractionBase, ctx->n_attrs); + XtSetValues(topform, stdarg_args, stdarg_n); + + + if (!PCB_HATT_IS_COMPOSITE(attrs[0].type)) { + stdarg_n = 0; + main_tbl = pcb_motif_box(topform, XmStrCast("layout"), 't', pcb_hid_attrdlg_num_children(ctx->attrs, 0, ctx->n_attrs), 0, 0); + XtManageChild(main_tbl); + attribute_dialog_add(ctx, main_tbl, 0); + } + else { + stdarg_n = 0; + stdarg(XmNtopAttachment, XmATTACH_FORM); + stdarg(XmNbottomAttachment, XmATTACH_FORM); + stdarg(XmNleftAttachment, XmATTACH_FORM); + stdarg(XmNrightAttachment, XmATTACH_FORM); + main_tbl = pcb_motif_box(topform, XmStrCast("layout"), 'v', 0, 0, 0); + XtManageChild(main_tbl); + attribute_dialog_add(ctx, main_tbl, 0); + } + + /* don't expect screens larger than 800x600 */ + if (ctx->minw > 750) + ctx->minw = 750; + if (ctx->minw > 550) + ctx->minw = 550; + + /* set top form's minimum width/height to content request */ + stdarg_n = 0; + stdarg(XmNminWidth, ctx->minw); + stdarg(XmNminHeight, ctx->minh); + XtSetValues(XtParent(ctx->dialog), stdarg_args, stdarg_n); + + + if (!modal) + XtManageChild(ctx->dialog); + + ltf_initial_wstates(ctx); + + return ctx; +} + +void *lesstif_attr_sub_new(Widget parent_box, pcb_hid_attribute_t *attrs, int n_attrs, void *caller_data) +{ + int i; + lesstif_attr_dlg_t *ctx; + + ctx = calloc(sizeof(lesstif_attr_dlg_t), 1); + ctx->attrs = attrs; + ctx->n_attrs = n_attrs; + ctx->caller_data = caller_data; + + for (i = 0; i < n_attrs; i++) { + if (attrs[i].help_text != ATTR_UNDOCUMENTED) + ctx->actual_nattrs++; + } + + ctx->wl = (Widget *) calloc(n_attrs, sizeof(Widget)); + ctx->wltop = (Widget *)calloc(n_attrs, sizeof(Widget)); + ctx->btn = (Widget **) calloc(n_attrs, sizeof(Widget *)); + + attribute_dialog_add(ctx, parent_box, 0); + ltf_initial_wstates(ctx); + + return ctx; +} + +int lesstif_attr_dlg_run(void *hid_ctx) +{ + lesstif_attr_dlg_t *ctx = hid_ctx; + ctx->set_ok = 1; + return pcb_ltf_wait_for_dialog(ctx->dialog); +} + +void lesstif_attr_dlg_raise(void *hid_ctx) +{ + lesstif_attr_dlg_t *ctx = hid_ctx; + XRaiseWindow(XtDisplay(ctx->dialog), XtWindow(ctx->dialog)); +} + +void lesstif_attr_dlg_free(void *hid_ctx) +{ + lesstif_attr_dlg_t *ctx = hid_ctx; + int i; + + if (ctx->set_ok) + pcb_ltf_ok = DAD_CLOSED; + + if (ctx->already_closing) + return; + + ctx->already_closing = 1; + for (i = 0; i < ctx->n_attrs; i++) { + attribute_dialog_readres(ctx, i); + free(ctx->btn[i]); + } + + if ((!ctx->close_cb_called) && (ctx->close_cb != NULL)) { + ctx->close_cb_called = 1; + ctx->close_cb(ctx->caller_data, PCB_HID_ATTR_EV_CODECLOSE); + } + + if (!ctx->already_destroying) { + if (!ctx->widget_destroyed) { + ctx->widget_destroyed = 1; + XtDestroyWidget(ctx->dialog); + } + free(ctx->wl); + free(ctx->wltop); + free(ctx->id); + TODO("#51: free(ctx);"); + } +} + +void lesstif_attr_dlg_property(void *hid_ctx, pcb_hat_property_t prop, const pcb_hid_attr_val_t *val) +{ + lesstif_attr_dlg_t *ctx = hid_ctx; + if ((prop >= 0) && (prop < PCB_HATP_max)) + ctx->property[prop] = *val; +} + +int lesstif_attr_dlg_widget_state(void *hid_ctx, int idx, pcb_bool enabled) +{ + lesstif_attr_dlg_t *ctx = hid_ctx; + + if ((idx < 0) || (idx >= ctx->n_attrs) || (ctx->wl[idx] == NULL)) + return -1; + + if (ctx->attrs[idx].type == PCB_HATT_BEGIN_COMPOUND) + return -1; + + if (ctx->attrs[idx].type == PCB_HATT_END) { + pcb_hid_compound_t *cmp = (pcb_hid_compound_t *)ctx->attrs[idx].enumerations; + if ((cmp != NULL) && (cmp->widget_state != NULL)) + cmp->widget_state(&ctx->attrs[idx], ctx, idx, enabled); + else + return -1; + } + + XtSetSensitive(ctx->wl[idx], enabled); + return 0; +} + +int lesstif_attr_dlg_widget_hide(void *hid_ctx, int idx, pcb_bool hide) +{ + lesstif_attr_dlg_t *ctx = hid_ctx; + + if ((idx < 0) || (idx >= ctx->n_attrs) || (ctx->wl[idx] == NULL)) + return -1; + + if (ctx->attrs[idx].type == PCB_HATT_BEGIN_COMPOUND) + return -1; + if (ctx->attrs[idx].type == PCB_HATT_END) { + pcb_hid_compound_t *cmp = (pcb_hid_compound_t *)ctx->attrs[idx].enumerations; + if ((cmp != NULL) && (cmp->widget_hide != NULL)) + cmp->widget_hide(&ctx->attrs[idx], ctx, idx, hide); + else + return -1; + } + + if (hide) + XtUnmanageChild(ctx->wltop[idx]); + else + XtManageChild(ctx->wltop[idx]); + + return 0; +} + +int lesstif_attr_dlg_set_value(void *hid_ctx, int idx, const pcb_hid_attr_val_t *val) +{ + lesstif_attr_dlg_t *ctx = hid_ctx; + + if ((idx < 0) || (idx >= ctx->n_attrs)) + return -1; + + if (attribute_dialog_set(ctx, idx, val) == 0) { + ctx->results[idx] = *val; + return 0; + } + + return -1; +} + + +static const char pcb_acts_DoWindows[] = "DoWindows(1|2|3|4)\n" "DoWindows(Layout|Library|Log|Netlist)"; +static const char pcb_acth_DoWindows[] = "Open various GUI windows."; +/* DOC: dowindows.html */ +static fgw_error_t pcb_act_DoWindows(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + const char *a = ""; + PCB_ACT_MAY_CONVARG(1, FGW_STR, DoWindows, a = argv[1].val.str); + if (strcmp(a, "1") == 0 || pcb_strcasecmp(a, "Layout") == 0) { + } + else if (strcmp(a, "2") == 0 || pcb_strcasecmp(a, "Library") == 0) { + lesstif_show_library(); + } + else if (strcmp(a, "3") == 0 || pcb_strcasecmp(a, "Log") == 0) { + pcb_actionl("LogDialog", NULL); + } + else if (strcmp(a, "4") == 0 || pcb_strcasecmp(a, "Netlist") == 0) { + lesstif_show_netlist(); + } + else { + PCB_ACT_FAIL(DoWindows); + PCB_ACT_IRES(1); + return 1; + } + PCB_ACT_IRES(0); + return 0; +} + +static const char pcb_acts_AdjustSizes[] = "AdjustSizes()"; +static const char pcb_acth_AdjustSizes[] = "not supported, please use Preferences() instead"; +static fgw_error_t pcb_act_AdjustSizes(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + pcb_message(PCB_MSG_ERROR, "AdjustSizes() is not supported anymore, please use the Preferences() action\n"); + PCB_ACT_IRES(1); + return 0; +} + +void lesstif_update_layer_groups() +{ +TODO("layer: call a redraw on the edit group") +} + +/* ------------------------------------------------------------ */ + +typedef struct { + Widget del; + Widget w_name; + Widget w_value; +} AttrRow; + +static AttrRow *attr_row = 0; +static int attr_num_rows = 0; +static int attr_max_rows = 0; +static Widget attr_dialog = NULL, f_top; +static pcb_attribute_list_t *attributes_list; + +static void attributes_delete_callback(Widget w, void *v, void *cbs); + +static void fiddle_with_bb_layout() +{ + int i; + int max_height = 0; + int max_del_width = 0; + int max_name_width = 0; + int max_value_width = 0; + short ncolumns = 20; + short vcolumns = 20; + + for (i = 0; i < attr_num_rows; i++) { + String v; + + stdarg_n = 0; + stdarg(XmNvalue, &v); + XtGetValues(attr_row[i].w_name, stdarg_args, stdarg_n); + if (ncolumns < strlen(v)) + ncolumns = strlen(v); + + stdarg_n = 0; + stdarg(XmNvalue, &v); + XtGetValues(attr_row[i].w_value, stdarg_args, stdarg_n); + if (vcolumns < strlen(v)) + vcolumns = strlen(v); + } + + for (i = 0; i < attr_num_rows; i++) { + stdarg_n = 0; + stdarg(XmNcolumns, ncolumns); + XtSetValues(attr_row[i].w_name, stdarg_args, stdarg_n); + + stdarg_n = 0; + stdarg(XmNcolumns, vcolumns); + XtSetValues(attr_row[i].w_value, stdarg_args, stdarg_n); + } + + for (i = 0; i < attr_num_rows; i++) { + Dimension w, h; + stdarg_n = 0; + stdarg(XmNwidth, &w); + stdarg(XmNheight, &h); + + XtGetValues(attr_row[i].del, stdarg_args, stdarg_n); + if (max_height < h) + max_height = h; + if (max_del_width < w) + max_del_width = w; + + XtGetValues(attr_row[i].w_name, stdarg_args, stdarg_n); + if (max_height < h) + max_height = h; + if (max_name_width < w) + max_name_width = w; + + XtGetValues(attr_row[i].w_value, stdarg_args, stdarg_n); + if (max_height < h) + max_height = h; + if (max_value_width < w) + max_value_width = w; + } + + for (i = 0; i < attr_num_rows; i++) { + stdarg_n = 0; + stdarg(XmNx, 0); + stdarg(XmNy, i * max_height); + stdarg(XmNwidth, max_del_width); + stdarg(XmNheight, max_height); + XtSetValues(attr_row[i].del, stdarg_args, stdarg_n); + + stdarg_n = 0; + stdarg(XmNx, max_del_width); + stdarg(XmNy, i * max_height); + stdarg(XmNwidth, max_name_width); + stdarg(XmNheight, max_height); + XtSetValues(attr_row[i].w_name, stdarg_args, stdarg_n); + + stdarg_n = 0; + stdarg(XmNx, max_del_width + max_name_width); + stdarg(XmNy, i * max_height); + stdarg(XmNwidth, max_value_width); + stdarg(XmNheight, max_height); + XtSetValues(attr_row[i].w_value, stdarg_args, stdarg_n); + } + + stdarg_n = 0; + stdarg(XmNwidth, max_del_width + max_name_width + max_value_width + 1); + stdarg(XmNheight, max_height * attr_num_rows + 1); + XtSetValues(f_top, stdarg_args, stdarg_n); +} + +static void lesstif_attributes_need_rows(int new_max) +{ + if (attr_max_rows < new_max) { + if (attr_row) + attr_row = (AttrRow *) realloc(attr_row, new_max * sizeof(AttrRow)); + else + attr_row = (AttrRow *) malloc(new_max * sizeof(AttrRow)); + } + + while (attr_max_rows < new_max) { + stdarg_n = 0; + attr_row[attr_max_rows].del = XmCreatePushButton(f_top, XmStrCast("del"), stdarg_args, stdarg_n); + XtManageChild(attr_row[attr_max_rows].del); + XtAddCallback(attr_row[attr_max_rows].del, XmNactivateCallback, + (XtCallbackProc) attributes_delete_callback, (XtPointer) (size_t) attr_max_rows); + + stdarg_n = 0; + stdarg(XmNresizeWidth, True); + attr_row[attr_max_rows].w_name = XmCreateTextField(f_top, XmStrCast("name"), stdarg_args, stdarg_n); + XtManageChild(attr_row[attr_max_rows].w_name); + XtAddCallback(attr_row[attr_max_rows].w_name, XmNvalueChangedCallback, (XtCallbackProc) fiddle_with_bb_layout, NULL); + + stdarg_n = 0; + stdarg(XmNresizeWidth, True); + attr_row[attr_max_rows].w_value = XmCreateTextField(f_top, XmStrCast("value"), stdarg_args, stdarg_n); + XtManageChild(attr_row[attr_max_rows].w_value); + XtAddCallback(attr_row[attr_max_rows].w_value, XmNvalueChangedCallback, (XtCallbackProc) fiddle_with_bb_layout, NULL); + + attr_max_rows++; + } + + /* Manage any previously unused rows we now need to show. */ + while (attr_num_rows < new_max) { + XtManageChild(attr_row[attr_num_rows].del); + XtManageChild(attr_row[attr_num_rows].w_name); + XtManageChild(attr_row[attr_num_rows].w_value); + attr_num_rows++; + } +} + +static void lesstif_attributes_revert() +{ + int i; + + lesstif_attributes_need_rows(attributes_list->Number); + + /* Unmanage any previously used rows we don't need. */ + while (attr_num_rows > attributes_list->Number) { + attr_num_rows--; + XtUnmanageChild(attr_row[attr_num_rows].del); + XtUnmanageChild(attr_row[attr_num_rows].w_name); + XtUnmanageChild(attr_row[attr_num_rows].w_value); + } + + /* Fill in values */ + for (i = 0; i < attributes_list->Number; i++) { + XmTextFieldSetString(attr_row[i].w_name, attributes_list->List[i].name); + XmTextFieldSetString(attr_row[i].w_value, attributes_list->List[i].value); + } + + fiddle_with_bb_layout(); +} + +static void attributes_new_callback(Widget w, void *v, void *cbs) +{ + lesstif_attributes_need_rows(attr_num_rows + 1); /* also bumps attr_num_rows */ + XmTextFieldSetString(attr_row[attr_num_rows - 1].w_name, XmStrCast("")); + XmTextFieldSetString(attr_row[attr_num_rows - 1].w_value, XmStrCast("")); + + fiddle_with_bb_layout(); +} + +static void attributes_delete_callback(Widget w, void *v, void *cbs) +{ + int i, n; + Widget wn, wv; + + n = (int) (size_t) v; + + wn = attr_row[n].w_name; + wv = attr_row[n].w_value; + + for (i = n; i < attr_num_rows - 1; i++) { + attr_row[i].w_name = attr_row[i + 1].w_name; + attr_row[i].w_value = attr_row[i + 1].w_value; + } + attr_row[attr_num_rows - 1].w_name = wn; + attr_row[attr_num_rows - 1].w_value = wv; + attr_num_rows--; + + XtUnmanageChild(wn); + XtUnmanageChild(wv); + + fiddle_with_bb_layout(); +} + +static void attributes_revert_callback(Widget w, void *v, void *cbs) +{ + lesstif_attributes_revert(); +} + +void lesstif_attributes_dialog(const char *owner, pcb_attribute_list_t * attrs_list) +{ + Widget bform, sw, b_ok, b_cancel, b_revert, b_new; + Widget sep; + + if (attr_dialog == NULL) { + stdarg_n = 0; + stdarg(XmNautoUnmanage, False); + stdarg(XmNtitle, owner); + stdarg(XmNwidth, 400); + stdarg(XmNheight, 300); + attr_dialog = XmCreateFormDialog(mainwind, XmStrCast("attributes"), stdarg_args, stdarg_n); + + stdarg_n = 0; + stdarg(XmNrightAttachment, XmATTACH_FORM); + stdarg(XmNbottomAttachment, XmATTACH_FORM); + stdarg(XmNorientation, XmHORIZONTAL); + stdarg(XmNentryAlignment, XmALIGNMENT_CENTER); + stdarg(XmNpacking, XmPACK_COLUMN); + bform = XmCreateRowColumn(attr_dialog, XmStrCast("attributes"), stdarg_args, stdarg_n); + XtManageChild(bform); + + stdarg_n = 0; + b_ok = XmCreatePushButton(bform, XmStrCast("OK"), stdarg_args, stdarg_n); + XtManageChild(b_ok); + XtAddCallback(b_ok, XmNactivateCallback, (XtCallbackProc) dialog_callback_ok_value, (XtPointer) 0); + + stdarg_n = 0; + b_new = XmCreatePushButton(bform, XmStrCast("New"), stdarg_args, stdarg_n); + XtManageChild(b_new); + XtAddCallback(b_new, XmNactivateCallback, (XtCallbackProc) attributes_new_callback, NULL); + + stdarg_n = 0; + b_revert = XmCreatePushButton(bform, XmStrCast("Revert"), stdarg_args, stdarg_n); + XtManageChild(b_revert); + XtAddCallback(b_revert, XmNactivateCallback, (XtCallbackProc) attributes_revert_callback, NULL); + + stdarg_n = 0; + b_cancel = XmCreatePushButton(bform, XmStrCast("Cancel"), stdarg_args, stdarg_n); + XtManageChild(b_cancel); + XtAddCallback(b_cancel, XmNactivateCallback, (XtCallbackProc) dialog_callback_ok_value, (XtPointer) 1); + + stdarg_n = 0; + stdarg(XmNleftAttachment, XmATTACH_FORM); + stdarg(XmNrightAttachment, XmATTACH_FORM); + stdarg(XmNbottomAttachment, XmATTACH_WIDGET); + stdarg(XmNbottomWidget, bform); + sep = XmCreateSeparator(attr_dialog, XmStrCast("attributes"), stdarg_args, stdarg_n); + XtManageChild(sep); + + stdarg_n = 0; + stdarg(XmNtopAttachment, XmATTACH_FORM); + stdarg(XmNleftAttachment, XmATTACH_FORM); + stdarg(XmNrightAttachment, XmATTACH_FORM); + stdarg(XmNbottomAttachment, XmATTACH_WIDGET); + stdarg(XmNbottomWidget, sep); + stdarg(XmNscrollingPolicy, XmAUTOMATIC); + sw = XmCreateScrolledWindow(attr_dialog, XmStrCast("attributes"), stdarg_args, stdarg_n); + XtManageChild(sw); + + stdarg_n = 0; + stdarg(XmNmarginHeight, 0); + stdarg(XmNmarginWidth, 0); + f_top = XmCreateBulletinBoard(sw, XmStrCast("f_top"), stdarg_args, stdarg_n); + XtManageChild(f_top); + } + else { + stdarg_n = 0; + stdarg(XmNtitle, owner); + XtSetValues(XtParent(attr_dialog), stdarg_args, stdarg_n); + } + + attributes_list = attrs_list; + lesstif_attributes_revert(); + + fiddle_with_bb_layout(); + + if (pcb_ltf_wait_for_dialog(attr_dialog) == 0) { + int i; + /* Copy the values back */ + pcb_attribute_copyback_begin(attributes_list); + for (i = 0; i < attr_num_rows; i++) + pcb_attribute_copyback(attributes_list, XmTextFieldGetString(attr_row[i].w_name), XmTextFieldGetString(attr_row[i].w_value)); + pcb_attribute_copyback_end(attributes_list); + } + + return; +} + +/* ------------------------------------------------------------ */ + +pcb_action_t lesstif_dialog_action_list[] = { + {"DoWindows", pcb_act_DoWindows, pcb_acth_DoWindows, pcb_acts_DoWindows}, + {"AdjustSizes", pcb_act_AdjustSizes, pcb_acth_AdjustSizes, pcb_acts_AdjustSizes} +}; + +PCB_REGISTER_ACTIONS(lesstif_dialog_action_list, lesstif_cookie) Index: tags/2.1.2/src_plugins/hid_lesstif/dlg_attr_box.c =================================================================== --- tags/2.1.2/src_plugins/hid_lesstif/dlg_attr_box.c (nonexistent) +++ tags/2.1.2/src_plugins/hid_lesstif/dlg_attr_box.c (revision 24813) @@ -0,0 +1,236 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2018,2019 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +/* Boxes and group widgets */ + +#include +#include "Pages.h" +#include "brave.h" + +static int ltf_pane_create(lesstif_attr_dlg_t *ctx, int j, Widget parent, int ishor) +{ + Widget pane; + + stdarg_n = 0; + stdarg(XmNorientation, (ishor ? XmHORIZONTAL : XmVERTICAL)); + ctx->wl[j] = pane = XmCreatePanedWindow(parent, "pane", stdarg_args, stdarg_n); + XtManageChild(pane); + + return attribute_dialog_add(ctx, pane, j+1); +} + +static Widget pcb_motif_box(Widget parent, char *name, char type, int num_table_rows, int want_frame, int want_scroll) +{ + Widget cnt; + + if (want_frame) { + /* create and insert frame around the content table */ + stdarg(XmNalignment, XmALIGNMENT_END); + stdarg(XmNmarginWidth, 0); + stdarg(XmNmarginHeight, 0); + parent = XmCreateFrame(parent, XmStrCast("box-frame"), stdarg_args, stdarg_n); + XtManageChild(parent); + stdarg_n = 0; + } + + if (want_scroll) { + stdarg(XmNscrollingPolicy, XmAUTOMATIC); + stdarg(XmNvisualPolicy, XmVARIABLE); + + stdarg(XmNleftAttachment, XmATTACH_FORM); + stdarg(XmNtopAttachment, XmATTACH_FORM); + stdarg(XmNrightAttachment, XmATTACH_FORM); + stdarg(XmNbottomAttachment, XmATTACH_FORM); + + parent = XmCreateScrolledWindow(parent, "scrolled_box", stdarg_args, stdarg_n); + XtManageChild(parent); + stdarg_n = 0; + } + + switch(type) { + case 'h': /* "hbox" */ + stdarg(PxmNfillBoxVertical, 0); + stdarg(XmNmarginWidth, 0); + stdarg(XmNmarginHeight, 0); + cnt = PxmCreateFillBox(parent, name, stdarg_args, stdarg_n); + break; + case 'v': /* "vbox" */ + stdarg(PxmNfillBoxVertical, 1); + stdarg(XmNmarginWidth, 0); + stdarg(XmNmarginHeight, 0); + cnt = PxmCreateFillBox(parent, name, stdarg_args, stdarg_n); + break; + case 't': /* "table" */ + stdarg(XmNorientation, XmHORIZONTAL); + stdarg(XmNpacking, XmPACK_COLUMN); + stdarg(XmNnumColumns, num_table_rows); + stdarg(XmNisAligned, True); + stdarg(XmNentryAlignment, XmALIGNMENT_END); + cnt = XmCreateRowColumn(parent, name, stdarg_args, stdarg_n); + break; + default: + abort(); + } + return cnt; +} + +typedef struct ltf_tab_s ltf_tab_t; + +typedef struct { + Widget w; + ltf_tab_t *tctx; +} ltf_tabbtn_t; + +struct ltf_tab_s { + Widget wpages; + int len, at; + ltf_tabbtn_t btn[1]; +}; + +static int ltf_tabbed_set_(ltf_tab_t *tctx, int page) +{ + if ((page < 0) || (page >= tctx->len)) + return -1; + + if (page == tctx->at) + return 0; + + XtVaSetValues(tctx->wpages, PxmNpagesAt, page, NULL); + + if ((tctx->btn == NULL) || (tctx->btn[tctx->at].w == NULL)) + return 0; + + if (tctx->at >= 0) + XtVaSetValues(tctx->btn[tctx->at].w, XmNshadowThickness, 1, NULL); + + tctx->at = page; + if (tctx->btn[tctx->at].w == NULL) + return 0; + + XtVaSetValues(tctx->btn[tctx->at].w, XmNshadowThickness, 3, NULL); + + return 0; +} + +static int ltf_tabbed_set(Widget tabbed, int page) +{ + ltf_tab_t *tctx; + XtVaGetValues(tabbed, XmNuserData, &tctx, NULL); + return ltf_tabbed_set_(tctx, page); +} + +static void tabsw_cb(Widget w, XtPointer client_data, XtPointer call_data) +{ + ltf_tabbtn_t *bctx = client_data; + ltf_tabbed_set_(bctx->tctx, bctx - bctx->tctx->btn); +} + +static void tabbed_destroy_cb(Widget tabbed, void *v, void *cbs) +{ + ltf_tab_t *tctx; + XtVaGetValues(tabbed, XmNuserData, &tctx, NULL); + free(tctx); + XtVaSetValues(tabbed, XmNuserData, NULL, NULL); +} + +static int ltf_tabbed_create(lesstif_attr_dlg_t *ctx, Widget parent, pcb_hid_attribute_t *attr, int i) +{ + Widget wtop, wtab, wframe, t; + int res, add_top = 0, numtabs; + ltf_tab_t *tctx; + const char **l; + + + for(l = ctx->attrs[i].enumerations, numtabs = 0; *l != NULL; l++, numtabs++) ; + tctx = calloc(1, sizeof(ltf_tab_t) + sizeof(ltf_tabbtn_t) * numtabs-1); + tctx->len = numtabs; + + if (!(ctx->attrs[i].pcb_hatt_flags & PCB_HATF_HIDE_TABLAB)) { + int n; + + /* create the boxing for the labels */ + if (ctx->attrs[i].pcb_hatt_flags & PCB_HATF_LEFT_TAB) { + wtop = pcb_motif_box(parent, "tabbed_top", 'h', 0, 0, 0); + wtab = pcb_motif_box(wtop, "tabbed_tabs", 'v', 0, 0, 0); + } + else { + wtop = pcb_motif_box(parent, "tabbed_top", 'v', 0, 0, 0); + wtab = pcb_motif_box(wtop, "tabbed_tabs", 'h', 0, 0, 0); + } + + /* create the label buttons */ + for(n = 0, l = ctx->attrs[i].enumerations; *l != NULL; l++,n++) { + stdarg_n = 0; + stdarg(XmNshadowThickness, 1); + t = XmCreatePushButton(wtab, (char *)*l, stdarg_args, stdarg_n); + tctx->btn[n].w = t; + tctx->btn[n].tctx = tctx; + XtAddCallback(t, XmNactivateCallback, tabsw_cb, (XtPointer)&tctx->btn[n]); + XtManageChild(t); + } + + XtVaSetValues(wtab, XmNmarginWidth, 0, XmNmarginHeight, 0, NULL); + XtManageChild(wtop); + XtManageChild(wtab); + add_top = 1; + } + else + wtop = parent; + + stdarg_n = 0; + + /* create and insert frame around the content table */ + stdarg_n = 0; + stdarg(PxmNfillBoxFill, 1); + wframe = XmCreateFrame(wtop, XmStrCast("pages-frame"), stdarg_args, stdarg_n); + XtManageChild(wframe); + + stdarg_n = 0; + stdarg(XmNuserData, tctx); + tctx->wpages = PxmCreatePages(wframe, "pages", stdarg_args, stdarg_n); + XtAddCallback(tctx->wpages, XmNunmapCallback, tabbed_destroy_cb, ctx); + XtManageChild(tctx->wpages); + + ctx->wltop[i] = wtop; + if (add_top) + ctx->wl[i] = wtop; + else + ctx->wl[i] = wframe; + + XtVaSetValues(ctx->wl[i], PxmNfillBoxFill, 1, XmNuserData, tctx, NULL); + + res = attribute_dialog_add(ctx, tctx->wpages, i+1); + + /* make sure no page is taken as shown */ + tctx->at = -1; + + /* make sure one of the pages is shown */ + if (ltf_tabbed_set_(tctx, ctx->attrs[i].default_val.int_value) != 0) + ltf_tabbed_set_(tctx, 0); + + return res; +} + Index: tags/2.1.2/src_plugins/hid_lesstif/dlg_attr_misc.c =================================================================== --- tags/2.1.2/src_plugins/hid_lesstif/dlg_attr_misc.c (nonexistent) +++ tags/2.1.2/src_plugins/hid_lesstif/dlg_attr_misc.c (revision 24813) @@ -0,0 +1,497 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2018 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +/* Boxes and group widgets */ + +#define PB_SCALE_UP 10000.0 + +#include +#include "wt_xpm.h" +#include "wt_colorbtn.h" +#include "../src_plugins/lib_hid_common/dad_markup.h" + +static void ltf_progress_set(lesstif_attr_dlg_t *ctx, int idx, double val) +{ + Widget bar = ctx->wl[idx]; + + if (val < 0.0) val = 0.0; + else if (val > 1.0) val = 1.0; + + if ((val >= 0.0) && (val <= 1.0)) { /* extra case for NaN */ + stdarg_n = 0; + stdarg(XmNsliderSize, (val * PB_SCALE_UP)+1); + XtSetValues(bar, stdarg_args, stdarg_n); + } +} + +static Widget ltf_progress_create(lesstif_attr_dlg_t *ctx, Widget parent) +{ + Widget bar; + + stdarg_n = 0; + stdarg(XmNminimum, 0); + stdarg(XmNvalue, 0); + stdarg(XmNmaximum, (int)PB_SCALE_UP+1); + stdarg(XmNsliderSize, 1); + stdarg(XmNorientation, XmHORIZONTAL); + stdarg(XmNshowArrows, pcb_false); + stdarg_do_color_str("#000099", XmNforeground); + stdarg(XmNsliderVisual, XmFOREGROUND_COLOR); + + bar = XmCreateScrollBar(parent, XmStrCast("scale"), stdarg_args, stdarg_n); + XtManageChild(bar); + return bar; +} + + +#include "wt_preview.h" + +/* called back from core (which is called from wt_preview) to get the user + expose function called */ +static void ltf_preview_expose(pcb_hid_gc_t gc, const pcb_hid_expose_ctx_t *e) +{ + pcb_ltf_preview_t *pd = e->draw_data; + pcb_hid_attribute_t *attr = pd->attr; + pcb_hid_preview_t *prv = (pcb_hid_preview_t *)attr->enumerations; + prv->user_expose_cb(attr, prv, gc, e); +} + +static void ltf_preview_set(lesstif_attr_dlg_t *ctx, int idx, double val) +{ + Widget pw = ctx->wl[idx]; + pcb_ltf_preview_t *pd; + + stdarg_n = 0; + stdarg(XmNuserData, &pd); + XtGetValues(pw, stdarg_args, stdarg_n); + + pcb_ltf_preview_redraw(pd); +} + +static void ltf_preview_zoomto(pcb_hid_attribute_t *attr, void *hid_ctx, const pcb_box_t *view) +{ + pcb_hid_preview_t *prv = (pcb_hid_preview_t *)attr->enumerations; + pcb_ltf_preview_t *pd = prv->hid_wdata; + + pd->x1 = view->X1; + pd->y1 = view->Y1; + pd->x2 = view->X2; + pd->y2 = view->Y2; + + pcb_ltf_preview_zoom_update(pd); + pcb_ltf_preview_redraw(pd); +} + +static void ltf_preview_motion_callback(Widget w, XtPointer pd_, XEvent *e, Boolean *ctd) +{ + pcb_ltf_preview_t *pd = pd_; + pcb_hid_attribute_t *attr = pd->attr; + pcb_hid_preview_t *prv = (pcb_hid_preview_t *)attr->enumerations; + pcb_coord_t x, y; + Window root, child; + unsigned int keys_buttons; + int root_x, root_y, pos_x, pos_y; + + if (prv->user_mouse_cb == NULL) + return; + + XQueryPointer(display, e->xmotion.window, &root, &child, &root_x, &root_y, &pos_x, &pos_y, &keys_buttons); + pcb_ltf_preview_getxy(pd, pos_x, pos_y, &x, &y); + + if (prv->user_mouse_cb(attr, prv, PCB_HID_MOUSE_MOTION, x, y)) + pcb_ltf_preview_redraw(pd); +} + +static void ltf_preview_input_callback(Widget w, XtPointer pd_, XmDrawingAreaCallbackStruct *cbs) +{ + pcb_ltf_preview_t *pd = pd_; + pcb_hid_attribute_t *attr = pd->attr; + pcb_hid_preview_t *prv = (pcb_hid_preview_t *)attr->enumerations; + pcb_coord_t x, y; + pcb_hid_mouse_ev_t kind = -1; + + if (prv->user_mouse_cb == NULL) + return; + + if (cbs->event->xbutton.button == 1) { + if (cbs->event->type == ButtonPress) kind = PCB_HID_MOUSE_PRESS; + if (cbs->event->type == ButtonRelease) kind = PCB_HID_MOUSE_RELEASE; + } + else if (cbs->event->xbutton.button == 3) { + if (cbs->event->type == ButtonRelease) kind = PCB_HID_MOUSE_POPUP; + } + + if (kind < 0) + return; + + pcb_ltf_preview_getxy(pd, cbs->event->xbutton.x, cbs->event->xbutton.y, &x, &y); + + if (prv->user_mouse_cb(attr, prv, kind, x, y)) + pcb_ltf_preview_redraw(pd); +} + + +static Widget ltf_preview_create(lesstif_attr_dlg_t *ctx, Widget parent, pcb_hid_attribute_t *attr) +{ + Widget pw; + pcb_ltf_preview_t *pd; + pcb_hid_preview_t *prv = (pcb_hid_preview_t *)attr->enumerations; + + pd = calloc(1, sizeof(pcb_ltf_preview_t)); + prv->hid_wdata = pd; + + pd->attr = attr; + memset(&pd->exp_ctx, 0, sizeof(pd->exp_ctx)); + pd->exp_ctx.draw_data = pd; + pd->exp_ctx.expose_cb = ltf_preview_expose; + + pd->hid_ctx = ctx; + prv->hid_zoomto_cb = ltf_preview_zoomto; + + pd->resized = 0; + if (prv->initial_view_valid) { + pd->x1 = prv->initial_view.X1; + pd->y1 = prv->initial_view.Y1; + pd->x2 = prv->initial_view.X2; + pd->y2 = prv->initial_view.Y2; + prv->initial_view_valid = 0; + } + else { + pd->x1 = 0; + pd->y1 = 0; + pd->x2 = PCB_MM_TO_COORD(100); + pd->y2 = PCB_MM_TO_COORD(100); + } + + stdarg_n = 0; + stdarg(XmNwidth, prv->min_sizex_px); + stdarg(XmNheight, prv->min_sizey_px); + stdarg(XmNresizePolicy, XmRESIZE_GROW); + stdarg(XmNleftAttachment, XmATTACH_FORM); + stdarg(XmNrightAttachment, XmATTACH_FORM); + stdarg(XmNtopAttachment, XmATTACH_FORM); + stdarg(XmNbottomAttachment, XmATTACH_FORM); + stdarg(XmNuserData, pd); + pw = XmCreateDrawingArea(parent, XmStrCast("dad_preview"), stdarg_args, stdarg_n); + XtManageChild(pw); + + pd->window = XtWindow(pw); + pd->pw = pw; + + XtAddCallback(pw, XmNexposeCallback, (XtCallbackProc)pcb_ltf_preview_callback, (XtPointer)pd); + XtAddCallback(pw, XmNresizeCallback, (XtCallbackProc)pcb_ltf_preview_callback, (XtPointer)pd); + XtAddCallback(pw, XmNinputCallback, (XtCallbackProc)ltf_preview_input_callback, (XtPointer)pd); + XtAddEventHandler(pw, PointerMotionMask | PointerMotionHintMask | EnterWindowMask | LeaveWindowMask, 0, ltf_preview_motion_callback, (XtPointer)pd); + + + XtManageChild(pw); + return pw; +} + + +static Widget ltf_picture_create(lesstif_attr_dlg_t *ctx, Widget parent, pcb_hid_attribute_t *attr) +{ + Widget pic = pcb_ltf_xpm_label(display, parent, XmStrCast("dad_picture"), attr->enumerations); + XtManageChild(pic); + return pic; +} + +static Widget ltf_picbutton_create(lesstif_attr_dlg_t *ctx, Widget parent, pcb_hid_attribute_t *attr) +{ + Widget pic = pcb_ltf_xpm_button(display, parent, XmStrCast("dad_picture"), attr->enumerations); + XtManageChild(pic); + return pic; +} + +static void ltf_colorbtn_set(lesstif_attr_dlg_t *ctx, int idx, const pcb_color_t *clr) +{ + Widget btn = ctx->wl[idx]; + ctx->attrs[idx].default_val.clr_value = *clr; + pcb_ltf_color_button_recolor(display, btn, clr); +} + +#define CPACT "gui_FallbackColorPick" + +static void ltf_colorbtn_valchg(Widget w, XtPointer dlg_widget_, XtPointer call_data) +{ + fgw_error_t rs; + fgw_arg_t res, argv[2]; + lesstif_attr_dlg_t *ctx; + const pcb_color_t *clr; + pcb_color_t nclr; + int r, widx = attr_get_idx(w, &ctx); + if (widx < 0) + return; + + clr = &ctx->attrs[widx].default_val.clr_value; + + argv[0].type = FGW_VOID; + argv[1].type = FGW_STR | FGW_DYN; + argv[1].val.str = pcb_strdup_printf("#%02x%02x%02x", clr->r, clr->g, clr->b); + rs = pcb_actionv_bin(CPACT, &res, 2, argv); + if (rs != 0) + return; + + if (!(res.type & FGW_STR)) { + pcb_message(PCB_MSG_ERROR, CPACT " returned non-string\n"); + fgw_arg_free(&pcb_fgw, &res); + return; + } + + r = pcb_color_load_str(&nclr, res.val.str); + fgw_arg_free(&pcb_fgw, &res); + if (r != 0) { + pcb_message(PCB_MSG_ERROR, CPACT " returned invalid color string\n"); + return; + } + + fgw_arg_free(&pcb_fgw, &res); + pcb_ltf_color_button_recolor(display, w, &nclr); + ctx->attrs[widx].default_val.clr_value = nclr; + valchg(w, dlg_widget_, w); +} + + +static Widget ltf_colorbtn_create(lesstif_attr_dlg_t *ctx, Widget parent, pcb_hid_attribute_t *attr, int readonly) +{ + Widget pic = pcb_ltf_color_button(display, parent, XmStrCast("dad_picture"), &attr->default_val.clr_value); + if (!readonly) + XtAddCallback(pic, XmNactivateCallback, ltf_colorbtn_valchg, NULL); + XtManageChild(pic); + return pic; +} + +static void ltf_txt_changed_callback(Widget w, XtPointer attr_, XEvent *e, Boolean *ctd) +{ + valchg(w, w, NULL); +} + +static long ltf_text_get_offs(pcb_hid_attribute_t *attrib, void *hid_ctx) +{ + lesstif_attr_dlg_t *ctx = hid_ctx; + int idx = attrib - ctx->attrs; + Widget wtxt = ctx->wl[idx]; + XmTextPosition pos; + + stdarg_n = 0; + stdarg(XmNcursorPosition, &pos); + XtGetValues(wtxt, stdarg_args, stdarg_n); + return pos; +} + +void ltf_text_set_offs(pcb_hid_attribute_t *attrib, void *hid_ctx, long offs) +{ + lesstif_attr_dlg_t *ctx = hid_ctx; + int idx = attrib - ctx->attrs; + Widget wtxt = ctx->wl[idx]; + XmTextSetInsertionPosition(wtxt, offs); +} + +static void ltf_text_set_text_(Widget wtxt, unsigned how, const char *txt) +{ + XmTextPosition pos; + + switch(how & 0x0F) { /* ignore flags - no markup support */ + case PCB_HID_TEXT_INSERT: + stdarg_n = 0; + stdarg(XmNcursorPosition, &pos); + XtGetValues(wtxt, stdarg_args, stdarg_n); + XmTextInsert(wtxt, pos, XmStrCast(txt)); + break; + case PCB_HID_TEXT_REPLACE: + XmTextSetString(wtxt, XmStrCast(txt)); + break; + case PCB_HID_TEXT_APPEND: + pos = 1<<30; + XmTextInsert(wtxt, pos, XmStrCast(txt)); + break; + } +} + +static void ltf_text_set_text(pcb_hid_attribute_t *attrib, void *hid_ctx, pcb_hid_text_set_t how, const char *txt) +{ + lesstif_attr_dlg_t *ctx = hid_ctx; + int idx = attrib - ctx->attrs; + Widget wtxt = ctx->wl[idx]; + + if (how & PCB_HID_TEXT_MARKUP) { + char *orig, *tmp = pcb_strdup(txt); + pcb_markup_state_t st = 0; + char *seg; + long seglen; + + orig = tmp; + while((seg = (char *)pcb_markup_next(&st, (const char **)&tmp, &seglen)) != NULL) { + char save = seg[seglen]; + seg[seglen] = '\0'; + ltf_text_set_text_(wtxt, how, seg); + seg[seglen] = save; + } + free(orig); + } + else + ltf_text_set_text_(wtxt, how, txt); +} + + +static void ltf_text_set(lesstif_attr_dlg_t *ctx, int idx, const char *val) +{ + ltf_text_set_text(&ctx->attrs[idx], ctx, PCB_HID_TEXT_REPLACE, val); +} + + +static char *ltf_text_get_text_(pcb_hid_attribute_t *attrib, void *hid_ctx) +{ + lesstif_attr_dlg_t *ctx = hid_ctx; + int idx = attrib - ctx->attrs; + Widget wtxt = ctx->wl[idx]; + return XmTextGetString(wtxt); +} + +char *ltf_text_get_text(pcb_hid_attribute_t *attrib, void *hid_ctx) +{ + char *orig = ltf_text_get_text_(attrib, hid_ctx); + char *s = pcb_strdup(orig); + XtFree(orig); + return s; +} + +static void ltf_text_get_xy(pcb_hid_attribute_t *attrib, void *hid_ctx, long *x, long *y) +{ + char *orig, *s = ltf_text_get_text_(attrib, hid_ctx); + long to, n, lines = 0, cols = 0; + + if (s == NULL) { + *x = *y = 0; + return; + } + + orig = s; + to = ltf_text_get_offs(attrib, hid_ctx); + for(n = 0; n < to; n++,s++) { + if (*s == '\n') { + lines++; + cols = 0; + } + else + cols++; + } + + XtFree(orig); + *x = cols; + *y = lines; +} + +void ltf_text_set_xy(pcb_hid_attribute_t *attrib, void *hid_ctx, long x, long y) +{ + char *orig, *s = ltf_text_get_text_(attrib, hid_ctx); + long offs; + + if (s == NULL) + return; + + orig = s; + for(offs = 0; *s != '\0'; s++,offs++) { + if (*s == '\n') { + y--; + if (y < 0) { + offs--; + break; + } + } + else if (y == 0) { + if (x == 0) + break; + x--; + } + } + ltf_text_set_offs(attrib, hid_ctx, offs); + XtFree(orig); +} + +void ltf_text_set_readonly(pcb_hid_attribute_t *attrib, void *hid_ctx, pcb_bool readonly) +{ + lesstif_attr_dlg_t *ctx = hid_ctx; + int idx = attrib - ctx->attrs; + Widget wtxt = ctx->wl[idx]; + + stdarg_n = 0; + stdarg(XmNeditable, !readonly); + XtSetValues(wtxt, stdarg_args, stdarg_n); +} + +static void ltf_text_scroll_to_bottom(pcb_hid_attribute_t *attrib, void *hid_ctx) +{ + lesstif_attr_dlg_t *ctx = hid_ctx; + int idx = attrib - ctx->attrs; + Widget wtxt = ctx->wl[idx]; + char *buf; + int offs, len; + + buf = XmTextGetString(wtxt); + len = strlen(buf); + + if (len < 3) + return; + + for(offs = len-2; offs > 0; offs--) { + if (buf[offs] == '\n') { + offs++; + break; + } + } + XmTextSetCursorPosition(wtxt, offs); + free(buf); +} + +static Widget ltf_text_create(lesstif_attr_dlg_t *ctx, Widget parent, pcb_hid_attribute_t *attr) +{ + Widget wtxt; + pcb_hid_text_t *txt = (pcb_hid_text_t *)attr->enumerations; + + stdarg(XmNresizePolicy, XmRESIZE_GROW); + stdarg(XmNeditMode, XmMULTI_LINE_EDIT); + stdarg(XmNuserData, ctx); + if (attr->pcb_hatt_flags & PCB_HATF_SCROLL) + wtxt = XmCreateScrolledText(parent, XmStrCast("dad_text"), stdarg_args, stdarg_n); + else + wtxt = XmCreateText(parent, XmStrCast("dad_text"), stdarg_args, stdarg_n); + XtManageChild(wtxt); + XtAddCallback(wtxt, XmNvalueChangedCallback, (XtCallbackProc)ltf_txt_changed_callback, (XtPointer)attr); + + + txt->hid_get_xy = ltf_text_get_xy; + txt->hid_get_offs = ltf_text_get_offs; + txt->hid_set_xy = ltf_text_set_xy; + txt->hid_set_offs = ltf_text_set_offs; + txt->hid_scroll_to_bottom = ltf_text_scroll_to_bottom; + txt->hid_get_text = ltf_text_get_text; + txt->hid_set_text = ltf_text_set_text; + txt->hid_set_readonly = ltf_text_set_readonly; + + return wtxt; +} + Index: tags/2.1.2/src_plugins/hid_lesstif/dlg_attr_tree.c =================================================================== --- tags/2.1.2/src_plugins/hid_lesstif/dlg_attr_tree.c (nonexistent) +++ tags/2.1.2/src_plugins/hid_lesstif/dlg_attr_tree.c (revision 24813) @@ -0,0 +1,446 @@ +#include "brave.h" +#include "xm_tree_table_widget.h" +#include "hid_dad_tree.h" + +typedef struct { + lesstif_attr_dlg_t *ctx; + pcb_hid_attribute_t *attr; + gdl_list_t model; + Widget w; + pcb_hid_tree_t *ht; + tt_entry_t *cursor; +} ltf_tree_t; + +#define REDRAW() xm_draw_tree_table_widget(lt->w); + +static int is_hidden(tt_entry_t *et) +{ + return et->flags.is_thidden || et->flags.is_uhidden; +} + +static tt_entry_t *ltf_tt_lookup_row(const tt_table_event_data_t *data, unsigned row_index) +{ + tt_entry_t *e; + for(e = gdl_first(data->root_entry); e != NULL; e = gdl_next(data->root_entry, e)) { + if (e->row_index == row_index) + return e; + } + return NULL; +} + +static void ltf_tt_insert_row(ltf_tree_t *lt, pcb_hid_row_t *new_row) +{ + tt_entry_t *e, *at; + pcb_hid_row_t *prev, *next, *parent; + gdl_list_t *parlist; + int n; + + e = tt_entry_alloc(new_row->cols); + + parent = pcb_dad_tree_parent_row(lt->ht, new_row); + if (parent != NULL) { + parlist = &parent->children; + at = parent->hid_data; + e->level = at->level+1; + } + else { + parlist = <->ht->rows; + e->level = 1; /* the tree-table widget doesn't like level 0 */ + } + + prev = gdl_prev(parlist, new_row); + next = gdl_next(parlist, new_row); + + /* insert in the model at the right place (in the flat sense) */ + if (next != NULL) { + /* there is a known node after the new one, insert before that */ + gdl_insert_before(<->model, next->hid_data, e, gdl_linkfield); + } + else if (prev != NULL) { + tt_entry_t *pe, *ne; + + /* there is a known node before the new one; seek the last children + in its subtree */ + pe = prev->hid_data; + for(ne = gdl_next(<->model, pe); (ne != NULL) && (ne->level > pe->level); ne = gdl_next(<->model, ne)) ; + + if (ne != NULL) + gdl_insert_before(<->model, ne, e, gdl_linkfield); + else + gdl_append(<->model, e, gdl_linkfield); + } + else if (parent != NULL) { + /* no siblings, first node under the parent, insert right after the parent */ + gdl_insert_after(<->model, parent->hid_data, e, gdl_linkfield); + } + else { + /* no siblings, no parent: first node in the tree */ + gdl_append(<->model, e, gdl_linkfield); + } + + + new_row->hid_data = e; + e->user_data = new_row; + e->flags.is_branch = gdl_length(&new_row->children) > 0; + for(n = 0; n < new_row->cols; n++) + tt_get_cell(e, n)[0] = new_row->cell[n]; + + /* update parent's branch flag */ + if (parent != NULL) { + e = parent->hid_data; + e->flags.is_branch = 1; + } +} + + +static void ltf_tree_insert_cb(pcb_hid_attribute_t *attrib, void *hid_wdata, pcb_hid_row_t *new_row) +{ + pcb_hid_tree_t *ht = (pcb_hid_tree_t *)attrib->enumerations; + ltf_tree_t *lt = ht->hid_wdata; + + ltf_tt_insert_row(lt, new_row); + xm_extent_prediction(lt->w); + REDRAW(); +} + +static void ltf_tree_modify_cb(pcb_hid_attribute_t *attrib, void *hid_wdata, pcb_hid_row_t *row, int col) +{ + pcb_hid_tree_t *ht = (pcb_hid_tree_t *)attrib->enumerations; + ltf_tree_t *lt = ht->hid_wdata; + + /* the caller modifies data strings directly, no need to do anything just flush */ + REDRAW(); + +} + +static void cursor_changed(ltf_tree_t *lt) +{ + pcb_hid_tree_t *ht = lt->ht; + pcb_hid_row_t *c_row = NULL; + + if (lt->cursor != NULL) + c_row = lt->cursor->user_data; + + valchg(lt->w, lt->w, lt->w); + if (ht->user_selected_cb != NULL) + ht->user_selected_cb(lt->attr, lt->ctx, c_row); +} + +static void ltf_tree_remove_cb(pcb_hid_attribute_t *attrib, void *hid_wdata, pcb_hid_row_t *row) +{ + pcb_hid_tree_t *ht = (pcb_hid_tree_t *)attrib->enumerations; + ltf_tree_t *lt = ht->hid_wdata; + tt_entry_t *e = row->hid_data; + int changed = 0; + + if (lt->cursor == e) { + lt->cursor = NULL; + changed = 1; + } + +/* gdl_remove(<->model, e, gdl_linkfield);*/ + delete_tt_entry(<->model, e); + xm_extent_prediction(lt->w); + REDRAW(); + + if (changed) + cursor_changed(lt); +} + +static void ltf_tree_free_cb(pcb_hid_attribute_t *attrib, void *hid_wdata, pcb_hid_row_t *row) +{ + pcb_hid_tree_t *ht = (pcb_hid_tree_t *)attrib->enumerations; + ltf_tree_t *lt = ht->hid_wdata; + tt_entry_t *i; + + if (lt == NULL) + return; + + for(i = gdl_first(<->model); i != NULL; i = gdl_first(<->model)) + delete_tt_entry(<->model, i); + + free(lt); + ht->hid_wdata = NULL; +} + +static pcb_hid_row_t *ltf_tree_get_selected_cb(pcb_hid_attribute_t *attrib, void *hid_wdata) +{ + pcb_hid_tree_t *ht = (pcb_hid_tree_t *)attrib->enumerations; + ltf_tree_t *lt = ht->hid_wdata; + + if (lt->cursor == NULL) + return NULL; + return lt->cursor->user_data; +} + +static void ltf_tt_jumpto(ltf_tree_t *lt, tt_entry_t *e, int inhibit_cb) +{ + int changed = 0; + + if (lt->cursor != NULL) + lt->cursor->flags.is_selected = 0; + changed = (lt->cursor != e); + lt->cursor = e; + lt->cursor->flags.is_selected = 1; + if (e != NULL) + xm_tree_table_focus_row(lt->w, e->row_index); + REDRAW(); + + if ((changed) && (!inhibit_cb)) + cursor_changed(lt); +} + +static void ltf_tt_jumprel(ltf_tree_t *lt, int dir) +{ + tt_entry_t *e; + int changed = 0; + + if (lt->cursor != NULL) + lt->cursor->flags.is_selected = 0; + + e = lt->cursor; + if (e == NULL) { /* pick first if there is no cursor */ + changed = 1; + lt->cursor = e = gdl_first(<->model); + if (is_hidden(e)) /* if first is hidden, step downward until the first visible */ + dir = 1; + } + + for(;;) { + if (e == NULL) + break; + e = (dir > 0 ? gdl_next(<->model, e) : gdl_prev(<->model, e)); + if ((e == NULL) || (!is_hidden(e))) + break; + } + + if (e != NULL) { + if (lt->cursor != e) + changed = 1; + lt->cursor = e; + } + if (lt->cursor != NULL) { + lt->cursor->flags.is_selected = 1; + xm_tree_table_focus_row(lt->w, lt->cursor->row_index); + } + REDRAW(); + if (changed) + cursor_changed(lt); +} + +static void ltf_tree_jumpto_cb(pcb_hid_attribute_t *attrib, void *hid_wdata, pcb_hid_row_t *row) +{ + pcb_hid_tree_t *ht = (pcb_hid_tree_t *)attrib->enumerations; + ltf_tree_t *lt = ht->hid_wdata; + if (row != NULL) { + tt_entry_t *e = row->hid_data; + ltf_tt_jumpto(lt, e, 1); + } + else { + TODO("remove cursor"); + } +} + +static void ltf_hide_rows(ltf_tree_t *lt, tt_entry_t *root, int val, int user, int parent, int children) +{ + if (parent) { + if (user) + root->flags.is_uhidden = val; + else + root->flags.is_thidden = val; + } + if (children) { + tt_entry_t *e; + for(e = gdl_next(<->model, root); e != NULL; e = gdl_next(<->model, e)) { + if (e->level <= root->level) + break; + if (user) + e->flags.is_uhidden = val; + else + e->flags.is_thidden = val; + } + } +} + +static void ltf_tree_expcoll(ltf_tree_t *lt, tt_entry_t *e, int expanded) +{ + ltf_hide_rows(lt, e, !expanded, 0, 0, 1); + e->flags.is_unfolded = expanded; +} + +static void ltf_tree_set(lesstif_attr_dlg_t *ctx, int idx, const char *val) +{ + pcb_hid_attribute_t *attr = &ctx->attrs[idx]; + pcb_hid_tree_t *ht = (pcb_hid_tree_t *)attr->enumerations; + ltf_tree_t *lt = ht->hid_wdata; + pcb_hid_row_t *r, *row; + tt_entry_t *e; + + if (val == NULL) { + /* remove the cursor */ + if (lt->cursor != NULL) + lt->cursor->flags.is_selected = 0; + REDRAW(); + return; + } + + row = htsp_get(<->ht->paths, val); + if (row == NULL) + return; + + e = row->hid_data; + e->flags.is_uhidden = 0; + e->flags.is_thidden = 0; + + /* make sure the path is visible: expand all parent, but not all + children of those parents */ + for(r = pcb_dad_tree_parent_row(lt->ht, row); r != NULL; r = pcb_dad_tree_parent_row(lt->ht, r)) { + e = r->hid_data; + e->flags.is_thidden = 0; + e->flags.is_uhidden = 0; + e->flags.is_unfolded = 1; + } + + ltf_tt_jumpto(lt, row->hid_data, 1); /* implies a REDRAW() */ +} + +static void ltf_tree_expcoll_cb(pcb_hid_attribute_t *attrib, void *hid_wdata, pcb_hid_row_t *row, int expanded) +{ + pcb_hid_tree_t *ht = (pcb_hid_tree_t *)attrib->enumerations; + ltf_tree_t *lt = ht->hid_wdata; + ltf_tree_expcoll(lt, row->hid_data, expanded); + REDRAW(); +} + +static void ltf_tree_update_hide_cb(pcb_hid_attribute_t *attrib, void *hid_wdata) +{ + pcb_hid_tree_t *ht = (pcb_hid_tree_t *)attrib->enumerations; + ltf_tree_t *lt = ht->hid_wdata; + tt_entry_t *e; + for(e = gdl_first(<->model); e != NULL; e = gdl_next(<->model, e)) { + pcb_hid_row_t *row = e->user_data; + e->flags.is_uhidden = row->hide; + } + REDRAW(); +} + +static void ltf_tt_append_row(ltf_tree_t *lt, pcb_hid_row_t *new_row, int level) +{ + tt_entry_t *e; + int n; + + e = tt_entry_alloc(new_row->cols); + new_row->hid_data = e; + e->user_data = new_row; + e->flags.is_branch = gdl_length(&new_row->children) > 0; + e->level = level; + for(n = 0; n < new_row->cols; n++) + tt_get_cell(e, n)[0] = new_row->cell[n]; + + gdl_append(<->model, e, gdl_linkfield); +} + + +static void ltf_tt_import(ltf_tree_t *lt, gdl_list_t *lst, int level) +{ + pcb_hid_row_t *r; + + for(r = gdl_first(lst); r != NULL; r = gdl_next(lst, r)) { + ltf_tt_append_row(lt, r, level); + ltf_tt_import(lt, &r->children, level+1); + } +} + +static void ltf_tt_xevent_cb(const tt_table_event_data_t *data) +{ + tt_entry_t *e; + ltf_tree_t *lt = data->user_data; + char text[64]; + KeySym key; + + switch(data->type) { + case ett_none: + case ett_mouse_btn_up: + case ett_mouse_btn_drag: + break; + case ett_mouse_btn_down: + XtSetKeyboardFocus(lt->ctx->dialog, lt->w); + e = ltf_tt_lookup_row(data, data->current_row); + if (e == NULL) + return; + if (e == lt->cursor) { /* second click */ + ltf_tree_expcoll(lt, lt->cursor, !lt->cursor->flags.is_unfolded); + REDRAW(); + } + else + ltf_tt_jumpto(lt, e, 0); + break; + case ett_key: + XLookupString(&(data->event->xkey), text, sizeof(text), &key, 0); + switch(key) { + case XK_Up: ltf_tt_jumprel(lt, -1); break; + case XK_Down: ltf_tt_jumprel(lt, +1); break; + case XK_Return: + case XK_KP_Enter: + if (lt->cursor != NULL) { + ltf_tree_expcoll(lt, lt->cursor, !lt->cursor->flags.is_unfolded); + REDRAW(); + } + pcb_trace("tree key {enter}\n"); + break; + default: pcb_trace("tree key %s\n", text); + } + break; + } +} + +static Widget ltf_tree_create_(lesstif_attr_dlg_t *ctx, Widget parent, pcb_hid_attribute_t *attr) +{ + pcb_hid_tree_t *ht = (pcb_hid_tree_t *)attr->enumerations; + ltf_tree_t *lt = calloc(sizeof(ltf_tree_t), 1); + Widget table = xm_create_tree_table_widget_cb(parent, <->model, lt, ltf_tt_xevent_cb, NULL, NULL); + + lt->w = table; + lt->ht = ht; + ht->hid_wdata = lt; + lt->ctx = ctx; + lt->attr = attr; + + ht->hid_insert_cb = ltf_tree_insert_cb; + ht->hid_modify_cb = ltf_tree_modify_cb; + ht->hid_remove_cb = ltf_tree_remove_cb; + ht->hid_free_cb = ltf_tree_free_cb; + ht->hid_get_selected_cb = ltf_tree_get_selected_cb; + ht->hid_jumpto_cb = ltf_tree_jumpto_cb; + ht->hid_expcoll_cb = ltf_tree_expcoll_cb; + ht->hid_update_hide_cb = ltf_tree_update_hide_cb; + + xm_tree_table_tree_mode(lt->w, !!(attr->pcb_hatt_flags & PCB_HATF_TREE_COL)); + + if (ht->hdr != NULL) { + int n; + const char **s; + for(n = 0, s = ht->hdr; *s != NULL; s++, n++) ; + xm_attach_tree_table_header(lt->w, n, ht->hdr); + } + + ltf_tt_import(lt, &ht->rows, 1); + + XtManageChild(table); + return table; +} + +static Widget ltf_tree_create(lesstif_attr_dlg_t *ctx, Widget parent, pcb_hid_attribute_t *attr) +{ + Widget w; + + if (pcb_brave & PCB_BRAVE_LESSTIF_TREETABLE) + return ltf_tree_create_(ctx, parent, attr); + + stdarg_n = 0; + stdarg(XmNalignment, XmALIGNMENT_BEGINNING); + stdarg(XmNlabelString, XmStringCreatePCB("TODO: tree table")); + w = XmCreateLabel(parent, XmStrCast("TODO"), stdarg_args, stdarg_n); + + return w; +} Index: tags/2.1.2/src_plugins/hid_lesstif/dlg_fileselect.c =================================================================== --- tags/2.1.2/src_plugins/hid_lesstif/dlg_fileselect.c (nonexistent) +++ tags/2.1.2/src_plugins/hid_lesstif/dlg_fileselect.c (revision 24813) @@ -0,0 +1,188 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2019 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +#include "config.h" + +#include "xincludes.h" +#include "lesstif.h" +#include "stdarg.h" + +#include "hid.h" +#include "hid_dad.h" +#include "event.h" + +#include "dlg_fileselect.h" + +typedef struct { + Widget dialog; + int active; + void *hid_ctx; /* DAD subdialog context */ +} pcb_ltf_fsd_t; + +static void fsb_ok_value(Widget w, void *v, void *cbs) +{ + pcb_ltf_ok = (int)(size_t)v; +} + +static char *pcb_ltf_get_path(pcb_ltf_fsd_t *pctx) +{ + char *res, *name; + XmString xmname; + + stdarg_n = 0; + stdarg(XmNdirSpec, &xmname); + XtGetValues(pctx->dialog, stdarg_args, stdarg_n); + + XmStringGetLtoR(xmname, XmFONTLIST_DEFAULT_TAG, &name); + res = pcb_strdup(name); + XtFree(name); + return res; +} + +static void pcb_ltf_set_fn(pcb_ltf_fsd_t *pctx, int append, const char *fn) +{ + XmString xms_path; + + if ((*fn != PCB_DIR_SEPARATOR_C) && (append)) { + char *end, *path, *dir = pcb_ltf_get_path(pctx); + + end = strrchr(dir, PCB_DIR_SEPARATOR_C); + if (end == NULL) { + path = pcb_concat(dir, "/", fn, NULL); + } + else if (end[1] == '\0') { + /* dir is a directory, ending in /, append fn */ + path = pcb_concat(dir, fn, NULL); + } + else { + /* dir is a full path, with file name included, replace that */ + end[1] = '\0'; + path = pcb_concat(dir, fn, NULL); + } + + xms_path = XmStringCreatePCB(path); + stdarg_n = 0; + stdarg(XmNdirSpec, xms_path); + XtSetValues(pctx->dialog, stdarg_args, stdarg_n); + + XmStringFree(xms_path); + free(path); + free(dir); + return; + } + + xms_path = XmStringCreatePCB(fn); + stdarg_n = 0; + stdarg(XmNdirSpec, xms_path); + XtSetValues(pctx->dialog, stdarg_args, stdarg_n); + XmStringFree(xms_path); +} + +static int pcb_ltf_fsd_poke(pcb_hid_dad_subdialog_t *sub, const char *cmd, pcb_event_arg_t *res, int argc, pcb_event_arg_t *argv) +{ + pcb_ltf_fsd_t *pctx = sub->parent_ctx; + + if (strcmp(cmd, "close") == 0) { + if (pctx->active) { + pctx->active = 0; + XtDestroyWidget(pctx->dialog); + } + return 0; + } + + if (strcmp(cmd, "get_path") == 0) { + res->type = PCB_EVARG_STR; + res->d.s = pcb_ltf_get_path(pctx); + return 0; + } + + if ((strcmp(cmd, "set_file_name") == 0) && (argc == 1) && (argv[0].type == PCB_EVARG_STR)) { + pcb_ltf_set_fn(pctx, 1, argv[0].d.s); + return 0; + } + + return -1; +} + +char *pcb_ltf_fileselect(const char *title, const char *descr, const char *default_file, const char *default_ext, const pcb_hid_fsd_filter_t *flt, const char *history_tag, pcb_hid_fsd_flags_t flags, pcb_hid_dad_subdialog_t *sub) +{ + XmString xms_ext = NULL, xms_load = NULL; + pcb_ltf_fsd_t pctx; + char *res; + + stdarg_n = 0; + pctx.dialog = XmCreateFileSelectionDialog(mainwind, XmStrCast("file"), stdarg_args, stdarg_n); + + XtAddCallback(pctx.dialog, XmNokCallback, (XtCallbackProc)fsb_ok_value, (XtPointer)1); + XtAddCallback(pctx.dialog, XmNcancelCallback, (XtCallbackProc)fsb_ok_value, (XtPointer)0); + + if (sub != NULL) { + Widget subbox; + stdarg_n = 0; + stdarg(XmNorientation, XmVERTICAL); + stdarg(XmNpacking, XmPACK_COLUMN); + subbox = XmCreateRowColumn(pctx.dialog, "extra", stdarg_args, stdarg_n); + + sub->parent_ctx = &pctx; + sub->parent_poke = pcb_ltf_fsd_poke; + + pctx.hid_ctx = lesstif_attr_sub_new(subbox, sub->dlg, sub->dlg_len, sub); + XtManageChild(subbox); + } + + + stdarg_n = 0; + stdarg(XmNtitle, title); + XtSetValues(XtParent(pctx.dialog), stdarg_args, stdarg_n); + + if (flags & PCB_HID_FSD_READ) { + xms_load = XmStringCreatePCB("Load From"); + stdarg_n = 0; + stdarg(XmNselectionLabelString, xms_load); + XtSetValues(pctx.dialog, stdarg_args, stdarg_n); + } + + if (default_ext != NULL) { + xms_ext = XmStringCreatePCB(default_ext); + stdarg_n = 0; + stdarg(XmNpattern, xms_ext); + stdarg(XmNmustMatch, True); + XtSetValues(pctx.dialog, stdarg_args, stdarg_n); + } + + if (default_file != 0) + pcb_ltf_set_fn(&pctx, 1, default_file); + + if (pcb_ltf_wait_for_dialog(pctx.dialog)) + res = pcb_ltf_get_path(&pctx); + else + res = NULL; + + if (xms_load != NULL) XmStringFree(xms_load); + if (xms_ext != NULL) XmStringFree(xms_ext); + return res; +} + Index: tags/2.1.2/src_plugins/hid_lesstif/dlg_fileselect.h =================================================================== --- tags/2.1.2/src_plugins/hid_lesstif/dlg_fileselect.h (nonexistent) +++ tags/2.1.2/src_plugins/hid_lesstif/dlg_fileselect.h (revision 24813) @@ -0,0 +1,2 @@ +#include "global_typedefs.h" +char *pcb_ltf_fileselect(const char *title, const char *descr, const char *default_file, const char *default_ext, const pcb_hid_fsd_filter_t *flt, const char *history_tag, pcb_hid_fsd_flags_t flags, pcb_hid_dad_subdialog_t *sub); Index: tags/2.1.2/src_plugins/hid_lesstif/hid_lesstif.pup =================================================================== --- tags/2.1.2/src_plugins/hid_lesstif/hid_lesstif.pup (nonexistent) +++ tags/2.1.2/src_plugins/hid_lesstif/hid_lesstif.pup (revision 24813) @@ -0,0 +1,9 @@ +$class hid +$short the lesstif gui +$long GUI: the lesstif HID. +$state works +$package hid-lesstif +default buildin +dep lib_hid_common +dep dialogs +autoload 1 Index: tags/2.1.2/src_plugins/hid_lesstif/lesstif.h =================================================================== --- tags/2.1.2/src_plugins/hid_lesstif/lesstif.h (nonexistent) +++ tags/2.1.2/src_plugins/hid_lesstif/lesstif.h (revision 24813) @@ -0,0 +1,89 @@ +#include "hid_cfg_input.h" +#include "board.h" + +#define app_context lesstif_app_context +#define appwidget lesstif_appwidget +#define display lesstif_display +#define screen_s lesstif_screen_s +#define screen lesstif_screen +#define mainwind lesstif_mainwind +#define work_area lesstif_work_area +#define messages lesstif_messages +#define command lesstif_command +#define hscroll lesstif_hscroll +#define vscroll lesstif_vscroll +#define m_click lesstif_message_click + +extern XtAppContext app_context; +extern Widget appwidget; +extern Display *display; +extern Screen *screen_s; +extern int screen; + +extern pcb_hid_cfg_mouse_t lesstif_mouse; +extern pcb_hid_cfg_keys_t lesstif_keymap; + +extern Widget mainwind, work_area, command, hscroll, vscroll; +extern Widget m_click; + +extern Widget lesstif_menu(Widget, const char *, Arg *, int); +extern int lesstif_key_event(XKeyEvent *); +extern int lesstif_button_event(Widget w, XEvent * e); + +/* Returns TRUE if the point mapped to the PCB region, FALSE (=0) if + we're off-board. Note that *pcbxy is always written to, even if + out of range. */ +extern int lesstif_winxy_to_pcbxy(int winx, int winy, int *pcbx, int *pcby); + +/* Returns TRUE if the point is in the window, FALSE (=0) otherwise. */ +extern int lesstif_pcbxy_to_winxy(int pcbx, int pcby, int *winx, int *winy); + +extern void lesstif_need_idle_proc(void); +extern void lesstif_show_crosshair(int); +extern void lesstif_invalidate_all(void); +extern void lesstif_coords_to_pcb(int, int, pcb_coord_t *, pcb_coord_t *); +extern void lesstif_get_xy(const char *msg); +extern void lesstif_update_widget_flags(const char *cookie); +extern int lesstif_call_action(const char *, int, char **); +extern void lesstif_pan_fixup(void); +extern void lesstif_show_library(void); +extern void lesstif_show_netlist(void); +extern Pixel lesstif_parse_color(const pcb_color_t *value); +extern Pixel lesstif_parse_color_str(const char *value); +extern void lesstif_styles_update_values(); +extern void lesstif_update_layer_groups(); +extern void lesstif_update_status_line(); +extern void lesstif_attributes_dialog(const char *, pcb_attribute_list_t *); +void *lesstif_attr_sub_new(Widget parent_box, pcb_hid_attribute_t *attrs, int n_attrs, void *caller_data); +char *pcb_ltf_fileselect(const char *title, const char *descr, const char *default_file, const char *default_ext, const pcb_hid_fsd_filter_t *flt, const char *history_tag, pcb_hid_fsd_flags_t flags, pcb_hid_dad_subdialog_t *sub); + +extern int pcb_ltf_ok; +int pcb_ltf_wait_for_dialog(Widget w); + + +#ifndef XtRPCBCoord +#define XtRPCBCoord "PCBCoord" +#endif + +#define need_idle_proc lesstif_need_idle_proc +#define show_crosshair lesstif_show_crosshair + +/* + * Motif comes from a time when even constant strings where + * passed as char*. These days, this requires to do ugly + * type-casting. To better identify all the places where this + * is necessary, we make this cast even more ugly but unique + * enough that it is simple to grep. + */ +#define XmStrCast(s) ((char*)(s)) + +static XmString XmStringCreatePCB(const char *x) +{ + return XmStringCreateLtoR(XmStrCast(x), XmFONTLIST_DEFAULT_TAG); +} + +extern const char *lesstif_cookie; + +void pcb_ltf_winplace(Display *dsp, Window w, const char *id, int defx, int defy); +void pcb_ltf_wplc_config_cb(Widget shell, XtPointer data, XEvent *xevent, char *dummy); + Index: tags/2.1.2/src_plugins/hid_lesstif/library.c =================================================================== --- tags/2.1.2/src_plugins/hid_lesstif/library.c (nonexistent) +++ tags/2.1.2/src_plugins/hid_lesstif/library.c (revision 24813) @@ -0,0 +1,185 @@ +#include "xincludes.h" + +#include "config.h" +#include "conf_core.h" + +#include +#include +#include +#include + +#include "compat_misc.h" +#include "data.h" +#include "actions.h" +#include "buffer.h" +#include +#include "plug_footprint.h" + +#include "hid.h" +#include "lesstif.h" +#include "stdarg.h" +#include "event.h" +#include "tool.h" + +static Widget library_dialog = 0; +static Widget library_list, libnode_list; + +static XmString *library_strings = 0; +static XmString *libnode_strings = 0; +static int last_pick = -1; + +vtp0_t picks; /* of pcb_fplibrary_t * */ +vtp0_t pick_names; /* of char * */ + +static void pick_net(int pick) +{ + pcb_fplibrary_t *menu = (pcb_fplibrary_t *)picks.array[pick]; + int i, found; + + if (pick == last_pick) + return; + last_pick = pick; + + if (libnode_strings) + free(libnode_strings); + + libnode_strings = (XmString *) malloc(menu->data.dir.children.used * sizeof(XmString)); + for (found = 0, i = 0; i < menu->data.dir.children.used; i++) { + if (menu->data.dir.children.array[i].type == LIB_FOOTPRINT) { + libnode_strings[i] = XmStringCreatePCB(menu->data.dir.children.array[i].name); + found++; + } + } + + stdarg_n = 0; + stdarg(XmNitems, libnode_strings); + stdarg(XmNitemCount, found); + XtSetValues(libnode_list, stdarg_args, stdarg_n); +} + +static void library_browse(Widget w, void *v, XmListCallbackStruct * cbs) +{ + pick_net(cbs->item_position - 1); +} + +static void libnode_select(Widget w, void *v, XmListCallbackStruct * cbs) +{ + pcb_fplibrary_t *e = picks.array[last_pick]; + e = &e->data.dir.children.array[cbs->item_position - 1]; + if (pcb_buffer_load_footprint(PCB_PASTEBUFFER, e->data.fp.loc_info, NULL)) + pcb_tool_select_by_id(PCB_MODE_PASTE_BUFFER); +} + +static int build_library_dialog() +{ + if (!mainwind) + return 1; + if (library_dialog) + return 0; + + stdarg_n = 0; + stdarg(XmNresizePolicy, XmRESIZE_GROW); + stdarg(XmNtitle, "Element Library"); + library_dialog = XmCreateFormDialog(mainwind, XmStrCast("library"), stdarg_args, stdarg_n); + + stdarg_n = 0; + stdarg(XmNtopAttachment, XmATTACH_FORM); + stdarg(XmNbottomAttachment, XmATTACH_FORM); + stdarg(XmNleftAttachment, XmATTACH_FORM); + stdarg(XmNvisibleItemCount, 10); + library_list = XmCreateScrolledList(library_dialog, XmStrCast("nets"), stdarg_args, stdarg_n); + XtManageChild(library_list); + XtAddCallback(library_list, XmNbrowseSelectionCallback, (XtCallbackProc) library_browse, 0); + + stdarg_n = 0; + stdarg(XmNtopAttachment, XmATTACH_FORM); + stdarg(XmNbottomAttachment, XmATTACH_FORM); + stdarg(XmNrightAttachment, XmATTACH_FORM); + stdarg(XmNleftAttachment, XmATTACH_WIDGET); + stdarg(XmNleftWidget, library_list); + libnode_list = XmCreateScrolledList(library_dialog, XmStrCast("nodes"), stdarg_args, stdarg_n); + XtManageChild(libnode_list); + XtAddCallback(libnode_list, XmNbrowseSelectionCallback, (XtCallbackProc) libnode_select, 0); + + return 0; +} + +static void lib_dfs(pcb_fplibrary_t *parent, int level) +{ + pcb_fplibrary_t *l; + char *s; + int n, len; + + if (parent->type != LIB_DIR) + return; + + if (parent->name != NULL) { + vtp0_append(&picks, parent); + len = strlen(parent->name); + s = malloc(len+level+1); + for(n = 0; n < level-1; n++) s[n] = ' '; + strcpy(s+level-1, parent->name); + vtp0_append(&pick_names, s); + } + + for(l = parent->data.dir.children.array, n = 0; n < parent->data.dir.children.used; n++,l++) + lib_dfs(l, level+1); +} + +void LesstifLibraryChanged(void *user_data, int argc, pcb_event_arg_t argv[]) +{ + int i; + if (pcb_library.data.dir.children.used == 0) + return; + if (build_library_dialog()) + return; + last_pick = -1; + + for (i = 0; i < pick_names.used; i++) + free(pick_names.array[i]); + + vtp0_truncate(&picks, 0); + vtp0_truncate(&pick_names, 0); + + lib_dfs(&pcb_library, 0); + + + if (library_strings) + free(library_strings); + library_strings = (XmString *) malloc(picks.used * sizeof(XmString)); + for (i = 0; i < picks.used; i++) + library_strings[i] = XmStringCreatePCB(pick_names.array[i]); + + stdarg_n = 0; + stdarg(XmNitems, library_strings); + stdarg(XmNitemCount, picks.used); + XtSetValues(library_list, stdarg_args, stdarg_n); + + pick_net(0); + return; +} + +static const char pcb_acts_LibraryShow[] = "LibraryShow()"; +static const char pcb_acth_LibraryShow[] = "[DEPRECATED] Displays the library window."; +static fgw_error_t pcb_act_LibraryShow(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + PCB_ACT_IRES(build_library_dialog()); + return 0; +} + +void lesstif_show_library() +{ + if (mainwind) { + if (!library_dialog) + LesstifLibraryChanged(0, 0, 0); + XtManageChild(library_dialog); + pcb_ltf_winplace(display, XtWindow(XtParent(library_dialog)), "library", 300, 300); + XtAddEventHandler(XtParent(library_dialog), StructureNotifyMask, False, pcb_ltf_wplc_config_cb, "library"); + } +} + +pcb_action_t lesstif_library_action_list[] = { + {"LibraryShow", pcb_act_LibraryShow, pcb_acth_LibraryShow, pcb_acts_LibraryShow} +}; + +PCB_REGISTER_ACTIONS(lesstif_library_action_list, lesstif_cookie) Index: tags/2.1.2/src_plugins/hid_lesstif/main.c =================================================================== --- tags/2.1.2/src_plugins/hid_lesstif/main.c (nonexistent) +++ tags/2.1.2/src_plugins/hid_lesstif/main.c (revision 24813) @@ -0,0 +1,3682 @@ +#include "xincludes.h" + +#include "config.h" +#include "math_helper.h" +#include "conf_core.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "data.h" +#include "draw.h" +#include "crosshair.h" +#include "conf_hid.h" +#include "layer.h" +#include "pcb-printf.h" +#include "event.h" +#include "error.h" +#include "plugins.h" +#include "macro.h" +#include "safe_fs.h" +#include "funchash_core.h" + +#include "hid.h" +#include "hid_nogui.h" +#include "hid_draw_helpers.h" +#include "hid_cfg.h" +#include "lesstif.h" +#include "hid_cfg_input.h" +#include "hid_attrib.h" +#include "hid_init.h" +#include "hid_color.h" +#include "actions.h" +#include "stdarg.h" +#include "grid.h" +#include "misc_util.h" +#include "compat_misc.h" +#include "layer_vis.h" +#include "tool.h" + +#include "dlg_fileselect.h" + +#include "../src_plugins/lib_hid_common/clip.h" +#include "../src_plugins/lib_hid_common/util.h" +#include "../src_plugins/lib_hid_common/cli_history.h" + +#include + +const char *lesstif_cookie = "lesstif HID"; + +pcb_hid_cfg_mouse_t lesstif_mouse; +pcb_hid_cfg_keys_t lesstif_keymap; +int lesstif_active = 0; + +static int idle_proc_set = 0; +static int need_redraw = 0; + +#ifndef XtRDouble +#define XtRDouble "Double" +#endif + +/* How big the viewport can be relative to the pcb size. */ +#define MAX_ZOOM_SCALE 10 +#define UUNIT conf_core.editor.grid_unit->allow + +typedef struct hid_gc_s { + pcb_core_gc_t core_gc; + pcb_hid_t *me_pointer; + Pixel color; + char *colorname; + int width; + pcb_cap_style_t cap; + char xor_set; + char erase; +} hid_gc_s; + +pcb_hid_t lesstif_hid; + +#define CRASH(func) fprintf(stderr, "HID error: pcb called unimplemented GUI function %s\n", func), abort() + +XtAppContext app_context; +Widget appwidget; +Display *display; +static Window window = 0; +static Cursor my_cursor = 0; +static int old_cursor_mode = -1; +static int over_point = 0; + +static Pixmap pixmap = 0; /* Current pixmap we are drawing to (either main_pixmap in direct mode or mask_pixmap when drawing the sketch) */ +static Pixmap main_pixmap = 0; /* 'Base pixmap', the final output all sketches are composed onto (then drawn) */ +static Pixmap mask_pixmap = 0; /* 'Sketch pixmap' for compositing: color array */ +static Pixmap mask_bitmap = 0; /* 'Sketch transparency bitmap' for compositing: tells which pixels shall be copied and which one are transparent/erased */ + +static int use_xrender = 0; +#ifdef HAVE_XRENDER +static Picture main_picture; +static Picture mask_picture; +static Pixmap pale_pixmap; +static Picture pale_picture; +#endif /* HAVE_XRENDER */ + +static int pixmap_w = 0, pixmap_h = 0; +Screen *screen_s; +int screen; +Colormap lesstif_colormap; +static GC my_gc = 0, bg_gc, clip_gc = 0, bset_gc = 0, bclear_gc = 0, mask_gc = 0; +static Pixel bgcolor, offlimit_color, grid_color; +static int bgred, bggreen, bgblue; + +static GC arc1_gc, arc2_gc; + +typedef struct PreviewData { + struct PreviewData *prev, *next; + Widget form; + Window window; + pcb_coord_t left, right, top, bottom; /* PCB extents of item */ + pcb_coord_t x, y; /* PCB coordinates of upper right corner of window */ + double zoom; /* PCB units per screen pixel */ + int v_width, v_height; /* pixels */ + + pcb_hid_expose_ctx_t ctx; + pcb_bool (*mouse_ev)(void *widget, void *draw_data, pcb_hid_mouse_ev_t kind, pcb_coord_t x, pcb_coord_t y); + void (*pre_close)(struct PreviewData *pd); + pcb_hid_expose_t overlay_draw; + unsigned pan:1; + int pan_ox, pan_oy; + pcb_coord_t pan_opx, pan_opy; +} PreviewData; + +static pcb_coord_t crosshair_x = 0, crosshair_y = 0; +static int in_move_event = 0, crosshair_in_window = 1; + +Widget mainwind; +Widget work_area, messages, command, hscroll, vscroll; +static Widget m_mark, m_crosshair, m_grid, m_zoom, m_mode, m_status; +static Widget m_rats; +Widget lesstif_m_layer; +Widget m_click; + +/* This is the size, in pixels, of the viewport. */ +static int view_width, view_height; +/* This is the PCB location represented by the upper left corner of + the viewport. Note that PCB coordinates put 0,0 in the upper left, + much like X does. */ +static pcb_coord_t view_left_x = 0, view_top_y = 0; +/* Denotes PCB units per screen pixel. Larger numbers mean zooming + out - the largest value means you are looking at the whole + board. */ +static double view_zoom = PCB_MIL_TO_COORD(10), prev_view_zoom = PCB_MIL_TO_COORD(10); +static pcb_bool autofade = 0; +static pcb_bool crosshair_on = pcb_true; + +static void lesstif_reg_attrs(void); +static void lesstif_begin(void); +static void lesstif_end(void); + +static void ShowCrosshair(pcb_bool show) +{ + if (crosshair_on == show) + return; + + pcb_notify_crosshair_change(pcb_false); + if (pcb_marked.status) + pcb_notify_mark_change(pcb_false); + + crosshair_on = show; + + pcb_notify_crosshair_change(pcb_true); + if (pcb_marked.status) + pcb_notify_mark_change(pcb_true); +} + +/* This is the size of the current PCB work area. */ +/* Use PCB->MaxWidth, PCB->MaxHeight. */ +/* static int pcb_width, pcb_height; */ +static int use_private_colormap = 0; +static int stdin_listen = 0; +static char *background_image_file = 0; + +pcb_hid_attribute_t lesstif_attribute_list[] = { + {"install", "Install private colormap", + PCB_HATT_BOOL, 0, 0, {0, 0, 0}, 0, &use_private_colormap}, +#define HA_colormap 0 + +/* %start-doc options "22 lesstif GUI Options" +@ftable @code +@item --listen +Listen for actions on stdin. +@end ftable +%end-doc +*/ + {"listen", "Listen on standard input for actions", + PCB_HATT_BOOL, 0, 0, {0, 0, 0}, 0, &stdin_listen}, +#define HA_listen 1 + +/* %start-doc options "22 lesstif GUI Options" +@ftable @code +@item --bg-image +File name of an image to put into the background of the GUI canvas. The image must +be a color PPM image, in binary (not ASCII) format. It can be any size, and will be +automatically scaled to fit the canvas. +@end ftable +%end-doc +*/ + {"bg-image", "Background Image", + PCB_HATT_STRING, 0, 0, {0, 0, 0}, 0, &background_image_file}, +#define HA_bg_image 2 +}; + +TODO("menu: pcb-menu should be generic and not depend on the HID") + +PCB_REGISTER_ATTRIBUTES(lesstif_attribute_list, lesstif_cookie) + +static int lesstif_direct = 0; +static pcb_composite_op_t lesstif_drawing_mode = 0; +#define use_mask() ((!lesstif_direct) && ((lesstif_drawing_mode == PCB_HID_COMP_POSITIVE) || (lesstif_drawing_mode == PCB_HID_COMP_POSITIVE_XOR) || (lesstif_drawing_mode == PCB_HID_COMP_NEGATIVE))) + +static void zoom_max(); +static void zoom_to(double factor, pcb_coord_t x, pcb_coord_t y); +static void zoom_win(pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2, int setch); +static void zoom_by(double factor, pcb_coord_t x, pcb_coord_t y); +static void zoom_toggle(pcb_coord_t x, pcb_coord_t y); +static void Pan(int mode, pcb_coord_t x, pcb_coord_t y); + +/* Px converts view->pcb, Vx converts pcb->view */ + +static inline int Vx(pcb_coord_t x) +{ + int rv = (x - view_left_x) / view_zoom + 0.5; + if (conf_core.editor.view.flip_x) + rv = view_width - rv; + return rv; +} + +static inline int Vy(pcb_coord_t y) +{ + int rv = (y - view_top_y) / view_zoom + 0.5; + if (conf_core.editor.view.flip_y) + rv = view_height - rv; + return rv; +} + +static inline int Vz(pcb_coord_t z) +{ + return z / view_zoom + 0.5; +} + +static inline int Vw(pcb_coord_t w) +{ + return w < 0 ? -w : w / view_zoom + 0.5; +} + +static inline pcb_coord_t Px(int x) +{ + if (conf_core.editor.view.flip_x) + x = view_width - x; + return x * view_zoom + view_left_x; +} + +static inline pcb_coord_t Py(int y) +{ + if (conf_core.editor.view.flip_y) + y = view_height - y; + return y * view_zoom + view_top_y; +} + +static inline pcb_coord_t Pz(int z) +{ + return z * view_zoom; +} + +void lesstif_coords_to_pcb(int vx, int vy, pcb_coord_t * px, pcb_coord_t * py) +{ + *px = Px(vx); + *py = Py(vy); +} + +Pixel lesstif_parse_color(const pcb_color_t *value) +{ + XColor color; + if (XParseColor(display, lesstif_colormap, value->str, &color)) + if (XAllocColor(display, lesstif_colormap, &color)) + return color.pixel; + return 0; +} + +Pixel lesstif_parse_color_str(const char *value) +{ + XColor color; + if (XParseColor(display, lesstif_colormap, value, &color)) + if (XAllocColor(display, lesstif_colormap, &color)) + return color.pixel; + return 0; +} + +/* ------------------------------------------------------------ */ + +static const char *cur_clip() +{ + if (conf_core.editor.orthogonal_moves) + return "+"; + if (conf_core.editor.all_direction_lines) + return "*"; + if (conf_core.editor.line_refraction == 0) + return "X"; + if (conf_core.editor.line_refraction == 1) + return "_/"; + return "\\_"; +} + +/* Called from the core when it's busy doing something and we need to + indicate that to the user. */ +static void LesstifBusy(void *user_data, int argc, pcb_event_arg_t argv[]) +{ + static Cursor busy_cursor = 0; + if (!lesstif_active) + return; + if (busy_cursor == 0) + busy_cursor = XCreateFontCursor(display, XC_watch); + XDefineCursor(display, window, busy_cursor); + XFlush(display); + old_cursor_mode = -1; + return; +} + +/* ---------------------------------------------------------------------- */ + +/* Local actions. */ + +static void PointCursor(pcb_bool grabbed) +{ + if (grabbed > 0) + over_point = 1; + else + over_point = 0; + old_cursor_mode = -1; +} + +extern void LesstifNetlistChanged(void *user_data, int argc, pcb_event_arg_t argv[]); +extern void LesstifRouteStylesChanged(void *user_data, int argc, pcb_event_arg_t argv[]); +extern void LesstifLibraryChanged(void *user_data, int argc, pcb_event_arg_t argv[]); + + +static void ev_pcb_changed(void *user_data, int argc, pcb_event_arg_t argv[]) +{ + if (work_area == 0) + return; + /*pcb_printf("PCB Changed! %$mD\n", PCB->MaxWidth, PCB->MaxHeight); */ + stdarg_n = 0; + stdarg(XmNminimum, 0); + stdarg(XmNvalue, 0); + stdarg(XmNsliderSize, PCB->MaxWidth ? PCB->MaxWidth : 1); + stdarg(XmNmaximum, PCB->MaxWidth ? PCB->MaxWidth : 1); + XtSetValues(hscroll, stdarg_args, stdarg_n); + stdarg_n = 0; + stdarg(XmNminimum, 0); + stdarg(XmNvalue, 0); + stdarg(XmNsliderSize, PCB->MaxHeight ? PCB->MaxHeight : 1); + stdarg(XmNmaximum, PCB->MaxHeight ? PCB->MaxHeight : 1); + XtSetValues(vscroll, stdarg_args, stdarg_n); + zoom_max(); + + LesstifNetlistChanged(NULL, 0, NULL); + LesstifRouteStylesChanged(NULL, 0, NULL); + lesstif_update_layer_groups(); + if (PCB->Filename) { + char *cp = strrchr(PCB->Filename, '/'); + stdarg_n = 0; + stdarg(XmNtitle, cp ? cp + 1 : PCB->Filename); + XtSetValues(appwidget, stdarg_args, stdarg_n); + } + return; +} + +static const char pcb_acts_Zoom[] = "Zoom()\n" "Zoom(factor)"; +static const char pcb_acth_Zoom[] = "Various zoom factor changes."; +/* DOC: zoom.html */ +static fgw_error_t pcb_act_Zoom(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + pcb_coord_t x, y; + const char *vp, *ovp; + double v; + + PCB_ACT_IRES(0); + + if ((argc > 1) && ((argv[1].type & FGW_STR) == FGW_STR)) { + if (pcb_strcasecmp(argv[1].val.str, "selected") == 0) { + pcb_box_t sb; + if (pcb_get_selection_bbox(&sb, PCB->Data) > 0) + zoom_win(sb.X1, sb.Y1, sb.X2, sb.Y2, 1); + else + pcb_message(PCB_MSG_ERROR, "Can't zoom to selection: nothing selected\n"); + return 0; + } + if (pcb_strcasecmp(argv[1].val.str, "found") == 0) { + pcb_box_t sb; + if (pcb_get_found_bbox(&sb, PCB->Data) > 0) + zoom_win(sb.X1, sb.Y1, sb.X2, sb.Y2, 1); + else + pcb_message(PCB_MSG_ERROR, "Can't zoom to 'found': nothing is found\n"); + return 0; + } + if (pcb_strcasecmp(argv[1].val.str, "?") == 0) { + pcb_message(PCB_MSG_INFO, "Current lesstif zoom level: %f\n", view_zoom); + return 0; + } + if (pcb_strcasecmp(argv[1].val.str, "get") == 0) { + res->type = FGW_DOUBLE; + res->val.nat_double = view_zoom; + return 0; + } + } + + if (argc > 3) { + pcb_coord_t x1, y1, x2, y2; + PCB_ACT_CONVARG(1, FGW_COORD, Zoom, x1 = fgw_coord(&argv[1])); + PCB_ACT_CONVARG(2, FGW_COORD, Zoom, y1 = fgw_coord(&argv[2])); + PCB_ACT_CONVARG(3, FGW_COORD, Zoom, x2 = fgw_coord(&argv[3])); + PCB_ACT_CONVARG(4, FGW_COORD, Zoom, y2 = fgw_coord(&argv[4])); + zoom_win(x1, y1, x2, y2, 1); + return 0; + } + + pcb_hid_get_coords("Click on a place to zoom in", &x, &y, 0); + + if (x == 0 && y == 0) { + x = view_width / 2; + y = view_height / 2; + } + else { + x = Vx(x); + y = Vy(y); + } + if (argc < 2) { + zoom_max(); + return 0; + } + PCB_ACT_CONVARG(1, FGW_STR, Zoom, ovp = vp = argv[1].val.str); + if (pcb_strcasecmp(vp, "toggle") == 0) { + zoom_toggle(x, y); + return 0; + } + if (*vp == '+' || *vp == '-' || *vp == '=') + vp++; + + v = strtod(vp, NULL); + + if (v <= 0) + return 1; + switch (ovp[0]) { + case '-': + zoom_by(1 / v, x, y); + break; + default: + case '+': + zoom_by(v, x, y); + break; + case '=': + zoom_to(v, x, y); + break; + } + PCB_ACT_IRES(0); + return 0; +} + +static int pan_thumb_mode; + +static const char pcb_acts_Pan[] = "Pan([thumb], mode)"; +static const char pcb_acth_Pan[] = "TODO"; +/* DOC: pan.html */ +static fgw_error_t pcb_act_Pan(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + const char *a0, *a1; + pcb_coord_t x, y; + int mode; + + pcb_hid_get_coords("Click on a place to pan", &x, &y, 0); + + PCB_ACT_MAY_CONVARG(1, FGW_STR, Pan, a0 = argv[1].val.str); + PCB_ACT_MAY_CONVARG(2, FGW_STR, Pan, a1 = argv[2].val.str); + + if (argc == 3) { + pan_thumb_mode = (pcb_strcasecmp(a0, "thumb") == 0) ? 1 : 0; + mode = atoi(a1); + } + else { + pan_thumb_mode = 0; + mode = atoi(a0); + } + Pan(mode, Vx(x), Vy(y)); + + PCB_ACT_IRES(0); + return 0; +} + +static const char pcb_acts_SwapSides[] = "SwapSides(|v|h|r, [S])"; +static const char pcb_acth_SwapSides[] = "Swaps the side of the board you're looking at."; +/* DOC: swapsides.html */ +static int group_showing(int g, int *c) +{ + int i, l; + *c = PCB->LayerGroups.grp[g].lid[0]; + for (i = 0; i < PCB->LayerGroups.grp[g].len; i++) { + l = PCB->LayerGroups.grp[g].lid[i]; + if (l >= 0 && l < pcb_max_layer && (!(pcb_layer_flags(PCB, l) & PCB_LYT_SILK))) { + *c = l; + if (PCB->Data->Layer[l].meta.real.vis) + return 1; + } + } + return 0; +} + +TODO(": ui_zoomplan.c does the same, maybe make the code common?") +static fgw_error_t pcb_act_SwapSides(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + const char *op = NULL, *b = ""; + int old_shown_side = conf_core.editor.show_solder_side; + pcb_layergrp_id_t comp_group = -1, solder_group = -1; + pcb_layergrp_id_t active_group = pcb_layer_get_group(PCB, pcb_layer_stack[0]); + int comp_layer; + int solder_layer; + int comp_showing = 0, solder_showing = 0; + pcb_layer_id_t lid; + pcb_layer_type_t lyt; + + if (pcb_layergrp_list(PCB, PCB_LYT_BOTTOM | PCB_LYT_COPPER, &solder_group, 1) > 0) + solder_showing = group_showing(solder_group, &solder_layer); + + if (pcb_layergrp_list(PCB, PCB_LYT_TOP | PCB_LYT_COPPER, &comp_group, 1) > 0) + comp_showing = group_showing(comp_group, &comp_layer); + + PCB_ACT_MAY_CONVARG(1, FGW_STR, SwapSides, op = argv[1].val.str); + PCB_ACT_MAY_CONVARG(2, FGW_STR, SwapSides, b = argv[2].val.str); + + if (op != NULL) { + switch (op[0]) { + case 'h': + case 'H': + conf_toggle_editor_("view/flip_x", view.flip_x); + break; + case 'v': + case 'V': + conf_toggle_editor_("view/flip_y", view.flip_y); + break; + case 'r': + case 'R': + conf_toggle_editor_("view/flip_x", view.flip_x); + conf_toggle_editor_("view/flip_y", view.flip_y); + break; + default: + return 1; + } + + switch (b[0]) { + case 'S': + case 's': + lyt = (pcb_layer_flags_(CURRENT) & PCB_LYT_ANYTHING) | (!conf_core.editor.show_solder_side ? PCB_LYT_BOTTOM : PCB_LYT_TOP); + lid = pcb_layer_vis_last_lyt(lyt); + if (lid >= 0) + pcb_layervis_change_group_vis(lid, 1, 1); + } + + /* SwapSides will swap this */ + conf_set_editor(show_solder_side, (conf_core.editor.view.flip_x == conf_core.editor.view.flip_y)); + } + + stdarg_n = 0; + if (conf_core.editor.view.flip_x) + stdarg(XmNprocessingDirection, XmMAX_ON_LEFT); + else + stdarg(XmNprocessingDirection, XmMAX_ON_RIGHT); + XtSetValues(hscroll, stdarg_args, stdarg_n); + + stdarg_n = 0; + if (conf_core.editor.view.flip_y) + stdarg(XmNprocessingDirection, XmMAX_ON_TOP); + else + stdarg(XmNprocessingDirection, XmMAX_ON_BOTTOM); + XtSetValues(vscroll, stdarg_args, stdarg_n); + + conf_toggle_editor(show_solder_side); + + /* The idea is that if we're looking at the front side and the front + layer is active (or visa versa), switching sides should switch + layers too. We used to only do this if the other layer wasn't + shown, but we now do it always. Change it back if users get + confused. */ + if (conf_core.editor.show_solder_side != old_shown_side) { + if (conf_core.editor.show_solder_side) { + if (active_group == comp_group) { + if (comp_showing && !solder_showing) + pcb_layervis_change_group_vis(comp_layer, 0, 0); + pcb_layervis_change_group_vis(solder_layer, 1, 1); + } + } + else { + if (active_group == solder_group) { + if (solder_showing && !comp_showing) + pcb_layervis_change_group_vis(solder_layer, 0, 0); + pcb_layervis_change_group_vis(comp_layer, 1, 1); + } + } + } + lesstif_invalidate_all(); + PCB_ACT_IRES(0); + return 0; +} + +static Widget m_cmd = 0, m_cmd_label; +static int cmd_is_active = 0; + +static void command_callback(Widget w, XtPointer uptr, XmTextVerifyCallbackStruct * cbs) +{ + char *s; + switch (cbs->reason) { + case XmCR_ACTIVATE: + s = XmTextGetString(w); + lesstif_show_crosshair(0); + pcb_clihist_append(s, NULL, NULL, NULL); + pcb_parse_command(s, pcb_false); + XtFree(s); + XmTextSetString(w, XmStrCast("")); + + XtUnmanageChild(m_cmd); + XtUnmanageChild(m_cmd_label); + cmd_is_active = 0; + break; + } +} + +static int panning = 0; +static int shift_pressed; +static int ctrl_pressed; +static int alt_pressed; + +static void ltf_mod_key(XKeyEvent *e, int set, int mainloop) +{ + switch (XKeycodeToKeysym(display, e->keycode, 0)) { + case XK_Shift_L: + case XK_Shift_R: + shift_pressed = set; + break; + case XK_Control_L: + case XK_Control_R: + ctrl_pressed = set; + break; +#ifdef __APPLE__ + case XK_Mode_switch: +#else + case XK_Alt_L: + case XK_Alt_R: +#endif + alt_pressed = set; + break; + default: + /* to include the Apple keyboard left and right command keys use XK_Meta_L and XK_Meta_R respectivly. */ + if (mainloop) + return; + } + + if (!mainloop) + return; + + in_move_event = 1; + pcb_notify_crosshair_change(pcb_false); + if (panning) + Pan(2, e->x, e->y); + pcb_event_move_crosshair(Px(e->x), Py(e->y)); + pcb_tool_adjust_attached_objects(); + pcb_notify_crosshair_change(pcb_true); + in_move_event = 0; +} + +static void command_event_handler(Widget w, XtPointer p, XEvent * e, Boolean * cont) +{ + const char *hist; + char buf[10]; + KeySym sym; + + switch (e->type) { + case KeyRelease: + if (cmd_is_active) + pcb_cli_edit(); + break; + case KeyPress: + + /* update mod keys */ + switch (e->type) { + case KeyPress: ltf_mod_key((XKeyEvent *)e, 1, 0); + case KeyRelease: ltf_mod_key((XKeyEvent *)e, 0, 0); + } + + XLookupString((XKeyEvent *) e, buf, sizeof(buf), &sym, NULL); + switch (sym) { + case XK_Up: + hist = pcb_clihist_prev(); + if (hist != NULL) + XmTextSetString(w, XmStrCast(hist)); + else + XmTextSetString(w, XmStrCast("")); + break; + case XK_Down: + hist = pcb_clihist_next(); + if (hist != NULL) + XmTextSetString(w, XmStrCast(hist)); + else + XmTextSetString(w, XmStrCast("")); + break; + case XK_Tab: + pcb_cli_tab(); + *cont = False; + break; + case XK_Escape: + XtUnmanageChild(m_cmd); + XtUnmanageChild(m_cmd_label); + XmTextSetString(w, XmStrCast("")); + cmd_is_active = 0; + *cont = False; + break; + } + break; + } +} + + +static const char *lesstif_command_entry(const char *ovr, int *cursor) +{ + if (!cmd_is_active) { + if (cursor != NULL) + *cursor = -1; + return NULL; + } + + if (ovr != NULL) { + XmTextSetString(m_cmd, XmStrCast(ovr)); + if (cursor != NULL) + XtVaSetValues(m_cmd, XmNcursorPosition, *cursor, NULL); + } + + if (cursor != NULL) { + XmTextPosition pos; + stdarg_n = 0; + stdarg(XmNcursorPosition, &pos); + XtGetValues(m_cmd, stdarg_args, stdarg_n); + *cursor = pos; + } + + return XmTextGetString(m_cmd); +} + +static const char pcb_acts_Command[] = "Command()"; +static const char pcb_acth_Command[] = "Displays the command line input window."; +/* DOC: command */ +static fgw_error_t pcb_act_Command(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + pcb_clihist_init(); + pcb_clihist_reset(); + XtManageChild(m_cmd_label); + XtManageChild(m_cmd); + XmProcessTraversal(m_cmd, XmTRAVERSE_CURRENT); + cmd_is_active = 1; + PCB_ACT_IRES(0); + return 0; +} + +static double ltf_benchmark(void) +{ + int i = 0; + time_t start, end; + pcb_hid_expose_ctx_t ctx; + Drawable save_main; + + + save_main = main_pixmap; + main_pixmap = window; + + ctx.view.X1 = 0; + ctx.view.Y1 = 0; + ctx.view.X2 = PCB->MaxWidth; + ctx.view.Y2 = PCB->MaxHeight; + + pixmap = window; + XSync(display, 0); + time(&start); + do { + XFillRectangle(display, pixmap, bg_gc, 0, 0, view_width, view_height); + pcb_hid_expose_all(&lesstif_hid, &ctx, NULL); + XSync(display, 0); + time(&end); + i++; + } + while (end - start < 10); + + main_pixmap = save_main; + return i/10.0; +} + +/* DOC: center.html */ +static fgw_error_t pcb_act_Center(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + pcb_coord_t x, y; + + pcb_hid_get_coords("Click on a location to center", &x, &y, 0); + + x = pcb_grid_fit(x, PCB->Grid, PCB->GridOffsetX); + y = pcb_grid_fit(y, PCB->Grid, PCB->GridOffsetY); + view_left_x = x - (view_width * view_zoom) / 2; + view_top_y = y - (view_height * view_zoom) / 2; + lesstif_pan_fixup(); + XWarpPointer(display, window, window, 0, 0, view_width, view_height, Vx(x), Vy(y)); + PCB_ACT_IRES(0); + return 0; +} + +pcb_action_t lesstif_main_action_list[] = { + {"Zoom", pcb_act_Zoom, pcb_acth_Zoom, pcb_acts_Zoom}, + {"ZoomTo", pcb_act_Zoom, pcb_acth_Zoom, pcb_acts_Zoom}, + {"Pan", pcb_act_Pan, pcb_acth_Pan, pcb_acts_Pan}, + {"SwapSides", pcb_act_SwapSides, pcb_acth_SwapSides, pcb_acts_SwapSides}, + {"Command", pcb_act_Command, pcb_acth_Command, pcb_acts_Command}, + {"Center", pcb_act_Center} +}; + +PCB_REGISTER_ACTIONS(lesstif_main_action_list, lesstif_cookie) + + +/* ---------------------------------------------------------------------- + * redraws the background image + */ +static int bg_w, bg_h, bgi_w, bgi_h; +static Pixel **bg = 0; +static XImage *bgi = 0; +static enum { + PT_unknown, + PT_RGB565, + PT_RGB888 +} pixel_type = PT_unknown; + +static void LoadBackgroundFile(FILE *f, char *filename) +{ + XVisualInfo vinfot, *vinfo; + Visual *vis; + int c, r, b; + int i, nret; + int p[3], rows, cols, maxval; + + if (fgetc(f) != 'P') { + printf("bgimage: %s signature not P6\n", filename); + return; + } + if (fgetc(f) != '6') { + printf("bgimage: %s signature not P6\n", filename); + return; + } + for (i = 0; i < 3; i++) { + do { + b = fgetc(f); + if (feof(f)) + return; + if (b == '#') + while (!feof(f) && b != '\n') + b = fgetc(f); + } while (!isdigit(b)); + p[i] = b - '0'; + while (isdigit(b = fgetc(f))) + p[i] = p[i] * 10 + b - '0'; + } + bg_w = cols = p[0]; + bg_h = rows = p[1]; + maxval = p[2]; + + setbuf(stdout, 0); + bg = (Pixel **) malloc(rows * sizeof(Pixel *)); + if (!bg) { + printf("Out of memory loading %s\n", filename); + return; + } + for (i = 0; i < rows; i++) { + bg[i] = (Pixel *) malloc(cols * sizeof(Pixel)); + if (!bg[i]) { + printf("Out of memory loading %s\n", filename); + while (--i >= 0) + free(bg[i]); + free(bg); + bg = 0; + return; + } + } + + vis = DefaultVisual(display, DefaultScreen(display)); + + vinfot.visualid = XVisualIDFromVisual(vis); + vinfo = XGetVisualInfo(display, VisualIDMask, &vinfot, &nret); + +#if 0 + /* If you want to support more visuals below, you'll probably need + this. */ + printf("vinfo: rm %04x gm %04x bm %04x depth %d class %d\n", + vinfo->red_mask, vinfo->green_mask, vinfo->blue_mask, vinfo->depth, vinfo->class); +#endif + +#if !defined(__cplusplus) +#define c_class class +#endif + + if (vinfo->c_class == TrueColor + && vinfo->depth == 16 && vinfo->red_mask == 0xf800 && vinfo->green_mask == 0x07e0 && vinfo->blue_mask == 0x001f) + pixel_type = PT_RGB565; + + if (vinfo->c_class == TrueColor + && vinfo->depth == 24 && vinfo->red_mask == 0xff0000 && vinfo->green_mask == 0x00ff00 && vinfo->blue_mask == 0x0000ff) + pixel_type = PT_RGB888; + + for (r = 0; r < rows; r++) { + for (c = 0; c < cols; c++) { + XColor pix; + unsigned int pr = (unsigned) fgetc(f); + unsigned int pg = (unsigned) fgetc(f); + unsigned int pb = (unsigned) fgetc(f); + + switch (pixel_type) { + case PT_unknown: + pix.red = pr * 65535 / maxval; + pix.green = pg * 65535 / maxval; + pix.blue = pb * 65535 / maxval; + pix.flags = DoRed | DoGreen | DoBlue; + XAllocColor(display, lesstif_colormap, &pix); + bg[r][c] = pix.pixel; + break; + case PT_RGB565: + bg[r][c] = (pr >> 3) << 11 | (pg >> 2) << 5 | (pb >> 3); + break; + case PT_RGB888: + bg[r][c] = (pr << 16) | (pg << 8) | (pb); + break; + } + } + } +} + +void LoadBackgroundImage(char *filename) +{ + FILE *f = pcb_fopen(filename, "rb"); + if (!f) { + if (PCB_NSTRCMP(filename, "pcb-background.ppm")) + perror(filename); + return; + } + LoadBackgroundFile(f, filename); + fclose(f); +} + +static void DrawBackgroundImage() +{ + int x, y, w, h; + double xscale, yscale; + int pcbwidth = PCB->MaxWidth / view_zoom; + int pcbheight = PCB->MaxHeight / view_zoom; + + if (!window || !bg) + return; + + if (!bgi || view_width != bgi_w || view_height != bgi_h) { + if (bgi) + XDestroyImage(bgi); + /* Cheat - get the image, which sets up the format too. */ + bgi = XGetImage(XtDisplay(work_area), window, 0, 0, view_width, view_height, -1, ZPixmap); + bgi_w = view_width; + bgi_h = view_height; + } + + w = MIN(view_width, pcbwidth); + h = MIN(view_height, pcbheight); + + xscale = (double) bg_w / PCB->MaxWidth; + yscale = (double) bg_h / PCB->MaxHeight; + + for (y = 0; y < h; y++) { + int pr = Py(y); + int ir = pr * yscale; + for (x = 0; x < w; x++) { + int pc = Px(x); + int ic = pc * xscale; + XPutPixel(bgi, x, y, bg[ir][ic]); + } + } + XPutImage(display, main_pixmap, bg_gc, bgi, 0, 0, 0, 0, w, h); +} + +/* ---------------------------------------------------------------------- */ + +static pcb_hid_attribute_t *lesstif_get_export_options(int *n) +{ + if (n != NULL) + *n = sizeof(lesstif_attribute_list) / sizeof(pcb_hid_attribute_t); + return lesstif_attribute_list; +} + +static void set_scroll(Widget s, int pos, int view, int pcb) +{ + unsigned int sz = view * view_zoom; + if (sz > pcb) + sz = pcb; + if (pos > pcb - sz) + pos = pcb - sz; + if (pos < 0) + pos = 0; + stdarg_n = 0; + stdarg(XmNvalue, pos); + stdarg(XmNsliderSize, sz); + stdarg(XmNincrement, view_zoom); + stdarg(XmNpageIncrement, sz); + stdarg(XmNmaximum, pcb); + XtSetValues(s, stdarg_args, stdarg_n); +} + +void lesstif_pan_fixup() +{ + if (view_left_x > PCB->MaxWidth + (view_width * view_zoom)) + view_left_x = PCB->MaxWidth + (view_width * view_zoom); + if (view_top_y > PCB->MaxHeight + (view_height * view_zoom)) + view_top_y = PCB->MaxHeight + (view_height * view_zoom); + if (view_left_x < -(view_width * view_zoom)) + view_left_x = -(view_width * view_zoom); + if (view_top_y < -(view_height * view_zoom)) + view_top_y = -(view_height * view_zoom); + + set_scroll(hscroll, view_left_x, view_width, PCB->MaxWidth); + set_scroll(vscroll, view_top_y, view_height, PCB->MaxHeight); + + lesstif_invalidate_all(); +} + +static void zoom_max() +{ + double new_zoom = PCB->MaxWidth / view_width; + if (new_zoom < PCB->MaxHeight / view_height) + new_zoom = PCB->MaxHeight / view_height; + + view_left_x = -(view_width * new_zoom - PCB->MaxWidth) / 2; + view_top_y = -(view_height * new_zoom - PCB->MaxHeight) / 2; + view_zoom = new_zoom; + pcb_pixel_slop = view_zoom; + lesstif_pan_fixup(); +} + + +static void zoom_to(double new_zoom, pcb_coord_t x, pcb_coord_t y) +{ + double max_zoom, xfrac, yfrac; + pcb_coord_t cx, cy; + + if (PCB == NULL) + return; + + xfrac = (double) x / (double) view_width; + yfrac = (double) y / (double) view_height; + + if (conf_core.editor.view.flip_x) + xfrac = 1 - xfrac; + if (conf_core.editor.view.flip_y) + yfrac = 1 - yfrac; + + max_zoom = PCB->MaxWidth / view_width; + if (max_zoom < PCB->MaxHeight / view_height) + max_zoom = PCB->MaxHeight / view_height; + + max_zoom *= MAX_ZOOM_SCALE; + + if (new_zoom < 1) + new_zoom = 1; + if (new_zoom > max_zoom) + new_zoom = max_zoom; + + cx = view_left_x + view_width * xfrac * view_zoom; + cy = view_top_y + view_height * yfrac * view_zoom; + + if (view_zoom != new_zoom) { + view_zoom = new_zoom; + pcb_pixel_slop = view_zoom; + + view_left_x = cx - view_width * xfrac * view_zoom; + view_top_y = cy - view_height * yfrac * view_zoom; + } + lesstif_pan_fixup(); +} + +static void zoom_win(pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2, int setch) +{ + pcb_coord_t w = x2 - x1, h = y2 - y1; + double new_zoom = w / view_width; + if (new_zoom < h / view_height) + new_zoom = h / view_height; + + if (new_zoom < 1) + new_zoom = 1; + + if (view_zoom != new_zoom) { + view_zoom = new_zoom; + pcb_pixel_slop = view_zoom; + } + + view_left_x = x1; + view_top_y = y1; + + lesstif_pan_fixup(); + if (setch) + pcb_crosshair_move_absolute((x1+x2)/2, (y1+y2)/2); +} + +static void zoom_toggle(pcb_coord_t x, pcb_coord_t y) +{ + double tmp; + + tmp = prev_view_zoom; + prev_view_zoom = view_zoom; + zoom_to(tmp, x, y); +} + +void zoom_by(double factor, pcb_coord_t x, pcb_coord_t y) +{ + zoom_to(view_zoom * factor, x, y); +} + +/* X and Y are in screen coordinates. */ +static void Pan(int mode, pcb_coord_t x, pcb_coord_t y) +{ + static pcb_coord_t ox, oy; + static pcb_coord_t opx, opy; + + panning = mode; + /* This is for ctrl-pan, where the viewport's position is directly + proportional to the cursor position in the window (like the Xaw + thumb panner) */ + if (pan_thumb_mode) { + opx = x * PCB->MaxWidth / view_width; + opy = y * PCB->MaxHeight / view_height; + if (conf_core.editor.view.flip_x) + opx = PCB->MaxWidth - opx; + if (conf_core.editor.view.flip_y) + opy = PCB->MaxHeight - opy; + view_left_x = opx - view_width / 2 * view_zoom; + view_top_y = opy - view_height / 2 * view_zoom; + lesstif_pan_fixup(); + } + /* This is the start of a regular pan. On the first click, we + remember the coordinates where we "grabbed" the screen. */ + else if (mode == 1) { + ox = x; + oy = y; + opx = view_left_x; + opy = view_top_y; + } + /* continued drag, we calculate how far we've moved the cursor and + set the position accordingly. */ + else { + if (conf_core.editor.view.flip_x) + view_left_x = opx + (x - ox) * view_zoom; + else + view_left_x = opx - (x - ox) * view_zoom; + if (conf_core.editor.view.flip_y) + view_top_y = opy + (y - oy) * view_zoom; + else + view_top_y = opy - (y - oy) * view_zoom; + lesstif_pan_fixup(); + } +} + + +static void mod_changed(XKeyEvent *e, int set) +{ + ltf_mod_key(e, set, 1); +} + +static pcb_hid_cfg_mod_t lesstif_mb2cfg(int but) +{ + switch(but) { + case 1: return PCB_MB_LEFT; + case 2: return PCB_MB_MIDDLE; + case 3: return PCB_MB_RIGHT; + case 4: return PCB_MB_SCROLL_UP; + case 5: return PCB_MB_SCROLL_DOWN; + } + return 0; +} + +static void work_area_input(Widget w, XtPointer v, XEvent * e, Boolean * ctd) +{ + static int pressed_button = 0; + + show_crosshair(0); + switch (e->type) { + case KeyPress: + mod_changed(&(e->xkey), 1); + if (lesstif_key_event(&(e->xkey))) + return; + break; + + case KeyRelease: + mod_changed(&(e->xkey), 0); + break; + + case ButtonPress: + { + int mods; + if (pressed_button) + return; + /*printf("click %d\n", e->xbutton.button); */ + if (lesstif_button_event(w, e)) + return; + + pcb_notify_crosshair_change(pcb_false); + pressed_button = e->xbutton.button; + mods = ((e->xbutton.state & ShiftMask) ? PCB_M_Shift : 0) + + ((e->xbutton.state & ControlMask) ? PCB_M_Ctrl : 0) +#ifdef __APPLE__ + + ((e->xbutton.state & (1 << 13)) ? PCB_M_Alt : 0); +#else + + ((e->xbutton.state & Mod1Mask) ? PCB_M_Alt : 0); +#endif + hid_cfg_mouse_action(&lesstif_mouse, lesstif_mb2cfg(e->xbutton.button) | mods, cmd_is_active); + + pcb_notify_crosshair_change(pcb_true); + break; + } + + case ButtonRelease: + { + int mods; + if (e->xbutton.button != pressed_button) + return; + lesstif_button_event(w, e); + pcb_notify_crosshair_change(pcb_false); + pressed_button = 0; + mods = ((e->xbutton.state & ShiftMask) ? PCB_M_Shift : 0) + + ((e->xbutton.state & ControlMask) ? PCB_M_Ctrl : 0) +#ifdef __APPLE__ + + ((e->xbutton.state & (1 << 13)) ? PCB_M_Alt : 0) +#else + + ((e->xbutton.state & Mod1Mask) ? PCB_M_Alt : 0) +#endif + + PCB_M_Release; + hid_cfg_mouse_action(&lesstif_mouse, lesstif_mb2cfg(e->xbutton.button) | mods, cmd_is_active); + pcb_notify_crosshair_change(pcb_true); + break; + } + + case MotionNotify: + { + Window root, child; + unsigned int keys_buttons; + int root_x, root_y, pos_x, pos_y; + while (XCheckMaskEvent(display, PointerMotionMask, e)); + XQueryPointer(display, e->xmotion.window, &root, &child, &root_x, &root_y, &pos_x, &pos_y, &keys_buttons); + shift_pressed = (keys_buttons & ShiftMask); + ctrl_pressed = (keys_buttons & ControlMask); +#ifdef __APPLE__ + alt_pressed = (keys_buttons & (1 << 13)); +#else + alt_pressed = (keys_buttons & Mod1Mask); +#endif + /*pcb_printf("m %#mS %#mS\n", Px(e->xmotion.x), Py(e->xmotion.y)); */ + crosshair_in_window = 1; + in_move_event = 1; + if (panning) + Pan(2, pos_x, pos_y); + pcb_event_move_crosshair(Px(pos_x), Py(pos_y)); + in_move_event = 0; + } + break; + + case LeaveNotify: + crosshair_in_window = 0; + if (crosshair_on) + pcb_draw_attached(1); + pcb_draw_mark(1); + ShowCrosshair(pcb_false); + need_idle_proc(); + break; + + case EnterNotify: + crosshair_in_window = 1; + in_move_event = 1; + pcb_event_move_crosshair(Px(e->xcrossing.x), Py(e->xcrossing.y)); + ShowCrosshair(pcb_true); + in_move_event = 0; + need_redraw = 1; + need_idle_proc(); + break; + + default: + printf("work_area: unknown event %d\n", e->type); + break; + } + + if (cmd_is_active) + XmProcessTraversal(m_cmd, XmTRAVERSE_CURRENT); +} + +static void draw_right_cross(GC xor_gc, int x, int y, int view_width, int view_height) +{ + XDrawLine(display, window, xor_gc, 0, y, view_width, y); + XDrawLine(display, window, xor_gc, x, 0, x, view_height); +} + +static void draw_slanted_cross(GC xor_gc, int x, int y, int view_width, int view_height) +{ + int x0, y0, x1, y1; + + x0 = x + (view_height - y); + x0 = MAX(0, MIN(x0, view_width)); + x1 = x - y; + x1 = MAX(0, MIN(x1, view_width)); + y0 = y + (view_width - x); + y0 = MAX(0, MIN(y0, view_height)); + y1 = y - x; + y1 = MAX(0, MIN(y1, view_height)); + XDrawLine(display, window, xor_gc, x0, y0, x1, y1); + x0 = x - (view_height - y); + x0 = MAX(0, MIN(x0, view_width)); + x1 = x + y; + x1 = MAX(0, MIN(x1, view_width)); + y0 = y + x; + y0 = MAX(0, MIN(y0, view_height)); + y1 = y - (view_width - x); + y1 = MAX(0, MIN(y1, view_height)); + XDrawLine(display, window, xor_gc, x0, y0, x1, y1); +} + +static void draw_dozen_cross(GC xor_gc, int x, int y, int view_width, int view_height) +{ + int x0, y0, x1, y1; + double tan60 = sqrt(3); + + x0 = x + (view_height - y) / tan60; + x0 = MAX(0, MIN(x0, view_width)); + x1 = x - y / tan60; + x1 = MAX(0, MIN(x1, view_width)); + y0 = y + (view_width - x) * tan60; + y0 = MAX(0, MIN(y0, view_height)); + y1 = y - x * tan60; + y1 = MAX(0, MIN(y1, view_height)); + XDrawLine(display, window, xor_gc, x0, y0, x1, y1); + + x0 = x + (view_height - y) * tan60; + x0 = MAX(0, MIN(x0, view_width)); + x1 = x - y * tan60; + x1 = MAX(0, MIN(x1, view_width)); + y0 = y + (view_width - x) / tan60; + y0 = MAX(0, MIN(y0, view_height)); + y1 = y - x / tan60; + y1 = MAX(0, MIN(y1, view_height)); + XDrawLine(display, window, xor_gc, x0, y0, x1, y1); + + x0 = x - (view_height - y) / tan60; + x0 = MAX(0, MIN(x0, view_width)); + x1 = x + y / tan60; + x1 = MAX(0, MIN(x1, view_width)); + y0 = y + x * tan60; + y0 = MAX(0, MIN(y0, view_height)); + y1 = y - (view_width - x) * tan60; + y1 = MAX(0, MIN(y1, view_height)); + XDrawLine(display, window, xor_gc, x0, y0, x1, y1); + + x0 = x - (view_height - y) * tan60; + x0 = MAX(0, MIN(x0, view_width)); + x1 = x + y * tan60; + x1 = MAX(0, MIN(x1, view_width)); + y0 = y + x / tan60; + y0 = MAX(0, MIN(y0, view_height)); + y1 = y - (view_width - x) / tan60; + y1 = MAX(0, MIN(y1, view_height)); + XDrawLine(display, window, xor_gc, x0, y0, x1, y1); +} + +static void draw_crosshair(GC xor_gc, int x, int y, int view_width, int view_height) +{ + draw_right_cross(xor_gc, x, y, view_width, view_height); + if (pcb_crosshair.shape == pcb_ch_shape_union_jack) + draw_slanted_cross(xor_gc, x, y, view_width, view_height); + if (pcb_crosshair.shape == pcb_ch_shape_dozen) + draw_dozen_cross(xor_gc, x, y, view_width, view_height); +} + +void lesstif_show_crosshair(int show) +{ + static int showing = 0; + static int sx, sy; + static GC xor_gc = 0; + Pixel crosshair_color; + + if (!crosshair_in_window || !window) + return; + if (xor_gc == 0) { + crosshair_color = lesstif_parse_color(&conf_core.appearance.color.crosshair) ^ bgcolor; + xor_gc = XCreateGC(display, window, 0, 0); + XSetFunction(display, xor_gc, GXxor); + XSetForeground(display, xor_gc, crosshair_color); + } + if (show == showing) + return; + if (show) { + sx = Vx(crosshair_x); + sy = Vy(crosshair_y); + } + else + need_idle_proc(); + draw_crosshair(xor_gc, sx, sy, view_width, view_height); + showing = show; +} + +static void work_area_expose(Widget work_area, void *me, XmDrawingAreaCallbackStruct * cbs) +{ + XExposeEvent *e; + + show_crosshair(0); + e = &(cbs->event->xexpose); + XSetFunction(display, my_gc, GXcopy); + XCopyArea(display, main_pixmap, window, my_gc, e->x, e->y, e->width, e->height, e->x, e->y); + show_crosshair(1); +} + +static void scroll_callback(Widget scroll, int *view_dim, XmScrollBarCallbackStruct * cbs) +{ + *view_dim = cbs->value; + lesstif_invalidate_all(); +} + +static void work_area_make_pixmaps(Dimension width, Dimension height) +{ + if (main_pixmap) + XFreePixmap(display, main_pixmap); + main_pixmap = XCreatePixmap(display, window, width, height, XDefaultDepth(display, screen)); + + if (mask_pixmap) + XFreePixmap(display, mask_pixmap); + mask_pixmap = XCreatePixmap(display, window, width, height, XDefaultDepth(display, screen)); +#ifdef HAVE_XRENDER + if (main_picture) { + XRenderFreePicture(display, main_picture); + main_picture = 0; + } + if (mask_picture) { + XRenderFreePicture(display, mask_picture); + mask_picture = 0; + } + if (use_xrender) { + main_picture = XRenderCreatePicture(display, main_pixmap, + XRenderFindVisualFormat(display, DefaultVisual(display, screen)), 0, 0); + mask_picture = XRenderCreatePicture(display, mask_pixmap, + XRenderFindVisualFormat(display, DefaultVisual(display, screen)), 0, 0); + if (!main_picture || !mask_picture) + use_xrender = 0; + } +#endif /* HAVE_XRENDER */ + + if (mask_bitmap) + XFreePixmap(display, mask_bitmap); + mask_bitmap = XCreatePixmap(display, window, width, height, 1); + + pixmap = use_mask() ? main_pixmap : mask_pixmap; + pixmap_w = width; + pixmap_h = height; +} + +static void work_area_resize(Widget work_area, void *me, XmDrawingAreaCallbackStruct * cbs) +{ + XColor color; + Dimension width, height; + + show_crosshair(0); + + stdarg_n = 0; + stdarg(XtNwidth, &width); + stdarg(XtNheight, &height); + stdarg(XmNbackground, &bgcolor); + XtGetValues(work_area, stdarg_args, stdarg_n); + view_width = width; + view_height = height; + + color.pixel = bgcolor; + XQueryColor(display, lesstif_colormap, &color); + bgred = color.red; + bggreen = color.green; + bgblue = color.blue; + + if (!window) + return; + + work_area_make_pixmaps(view_width, view_height); + + zoom_by(1, 0, 0); +} + +static void work_area_first_expose(Widget work_area, void *me, XmDrawingAreaCallbackStruct * cbs) +{ + int c; + Dimension width, height; + static char dashes[] = { 4, 4 }; + + window = XtWindow(work_area); + my_gc = XCreateGC(display, window, 0, 0); + + arc1_gc = XCreateGC(display, window, 0, 0); + c = lesstif_parse_color_str("#804000"); + XSetForeground(display, arc1_gc, c); + arc2_gc = XCreateGC(display, window, 0, 0); + c = lesstif_parse_color_str("#004080"); + XSetForeground(display, arc2_gc, c); + XSetLineAttributes(display, arc1_gc, 1, LineOnOffDash, 0, 0); + XSetLineAttributes(display, arc2_gc, 1, LineOnOffDash, 0, 0); + XSetDashes(display, arc1_gc, 0, dashes, 2); + XSetDashes(display, arc2_gc, 0, dashes, 2); + + stdarg_n = 0; + stdarg(XtNwidth, &width); + stdarg(XtNheight, &height); + stdarg(XmNbackground, &bgcolor); + XtGetValues(work_area, stdarg_args, stdarg_n); + view_width = width; + view_height = height; + + offlimit_color = lesstif_parse_color(&conf_core.appearance.color.off_limit); + grid_color = lesstif_parse_color(&conf_core.appearance.color.grid); + + bg_gc = XCreateGC(display, window, 0, 0); + XSetForeground(display, bg_gc, bgcolor); + + work_area_make_pixmaps(width, height); + +#ifdef HAVE_XRENDER + if (use_xrender) { + double l_alpha = conf_core.appearance.layer_alpha; + XRenderPictureAttributes pa; + XRenderColor a = { 0, 0, 0, 0x8000}; + + if (l_alpha < 0) + l_alpha = 0; + else if (l_alpha > 1) + l_alpha = 1; + a.alpha = (int)(l_alpha * (double)0xFFFF); + + pale_pixmap = XCreatePixmap(display, window, 1, 1, 8); + pa.repeat = True; + pale_picture = XRenderCreatePicture(display, pale_pixmap, + XRenderFindStandardFormat(display, PictStandardA8), CPRepeat, &pa); + if (pale_picture) + XRenderFillRectangle(display, PictOpSrc, pale_picture, &a, 0, 0, 1, 1); + else + use_xrender = 0; + } +#endif /* HAVE_XRENDER */ + + clip_gc = XCreateGC(display, window, 0, 0); + bset_gc = XCreateGC(display, mask_bitmap, 0, 0); + XSetForeground(display, bset_gc, 1); + bclear_gc = XCreateGC(display, mask_bitmap, 0, 0); + XSetForeground(display, bclear_gc, 0); + + XtRemoveCallback(work_area, XmNexposeCallback, (XtCallbackProc) work_area_first_expose, 0); + XtAddCallback(work_area, XmNexposeCallback, (XtCallbackProc) work_area_expose, 0); + lesstif_invalidate_all(); +} + +static Widget make_message(const char *name, Widget left, int resizeable) +{ + Widget w, f; + stdarg_n = 0; + if (left) { + stdarg(XmNleftAttachment, XmATTACH_WIDGET); + stdarg(XmNleftWidget, XtParent(left)); + } + else { + stdarg(XmNleftAttachment, XmATTACH_FORM); + } + stdarg(XmNtopAttachment, XmATTACH_FORM); + stdarg(XmNbottomAttachment, XmATTACH_FORM); + stdarg(XmNshadowType, XmSHADOW_IN); + stdarg(XmNshadowThickness, 1); + stdarg(XmNalignment, XmALIGNMENT_CENTER); + stdarg(XmNmarginWidth, 4); + stdarg(XmNmarginHeight, 1); + if (!resizeable) + stdarg(XmNresizePolicy, XmRESIZE_GROW); + f = XmCreateForm(messages, XmStrCast(name), stdarg_args, stdarg_n); + XtManageChild(f); + stdarg_n = 0; + stdarg(XmNtopAttachment, XmATTACH_FORM); + stdarg(XmNbottomAttachment, XmATTACH_FORM); + stdarg(XmNleftAttachment, XmATTACH_FORM); + stdarg(XmNrightAttachment, XmATTACH_FORM); + w = XmCreateLabel(f, XmStrCast(name), stdarg_args, stdarg_n); + XtManageChild(w); + return w; +} + +static unsigned short int lesstif_translate_key(const char *desc, int len) +{ + KeySym key; + + if (pcb_strcasecmp(desc, "enter") == 0) desc = "Return"; + + key = XStringToKeysym(desc); + if (key == NoSymbol && len > 1) { + pcb_message(PCB_MSG_INFO, "lesstif_translate_key: no symbol for %s\n", desc); + return 0; + } + return key; +} + +int lesstif_key_name(unsigned short int key_raw, char *out, int out_len) +{ +TODO("TODO#3: do not ingore key_tr (either of them is 0)") + char *name = XKeysymToString(key_raw); + if (name == NULL) + return -1; + strncpy(out, name, out_len); + out[out_len-1] = '\0'; + return 0; +} + +void lesstif_uninit_menu(void); +void lesstif_init_menu(void); + +extern Widget lesstif_menubar; +static int lesstif_hid_inited = 0; + +static void lesstif_do_export(pcb_hid_attr_val_t * options) +{ + Dimension width, height; + Widget menu; + Widget work_area_frame; + + /* this only registers in core, safe to call before anything else */ + lesstif_init_menu(); + + lesstif_begin(); + + pcb_hid_cfg_keys_init(&lesstif_keymap); + lesstif_keymap.translate_key = lesstif_translate_key; + lesstif_keymap.key_name = lesstif_key_name; + lesstif_keymap.auto_chr = 1; + lesstif_keymap.auto_tr = hid_cfg_key_default_trans; + + stdarg_n = 0; + stdarg(XtNwidth, &width); + stdarg(XtNheight, &height); + XtGetValues(appwidget, stdarg_args, stdarg_n); + + if (width < 1) + width = 640; + if (width > XDisplayWidth(display, screen)) + width = XDisplayWidth(display, screen); + if (height < 1) + height = 480; + if (height > XDisplayHeight(display, screen)) + height = XDisplayHeight(display, screen); + + stdarg_n = 0; + stdarg(XmNwidth, width); + stdarg(XmNheight, height); + XtSetValues(appwidget, stdarg_args, stdarg_n); + + stdarg(XmNspacing, 0); + mainwind = XmCreateMainWindow(appwidget, XmStrCast("mainWind"), stdarg_args, stdarg_n); + XtManageChild(mainwind); + + stdarg_n = 0; + stdarg(XmNmarginWidth, 0); + stdarg(XmNmarginHeight, 0); + menu = lesstif_menu(mainwind, "menubar", stdarg_args, stdarg_n); + XtManageChild(menu); + + stdarg_n = 0; + stdarg(XmNshadowType, XmSHADOW_IN); + work_area_frame = XmCreateFrame(mainwind, XmStrCast("work_area_frame"), stdarg_args, stdarg_n); + XtManageChild(work_area_frame); + + stdarg_n = 0; + stdarg_do_color(&conf_core.appearance.color.background, XmNbackground); + work_area = XmCreateDrawingArea(work_area_frame, XmStrCast("work_area"), stdarg_args, stdarg_n); + XtManageChild(work_area); + XtAddCallback(work_area, XmNexposeCallback, (XtCallbackProc) work_area_first_expose, 0); + XtAddCallback(work_area, XmNresizeCallback, (XtCallbackProc) work_area_resize, 0); + /* A regular callback won't work here, because lesstif swallows any + Ctrl
    +
    name internal dependencies description +' + +awk ' +function out() +{ + if (pkg == "") + return + print "
    " pkg "" deps "" desc + pkg="" + deps="" + desc="" + para=0 +} + +/^Package:/ { + out(); + pkg=$2 + para=0 +} +#Depends: ${misc:Depends}, ${shlibs:Depends}, pcb-rnd-core, pcb-rnd-gtk +/^Depends:/ { + deps=$0 + sub("Depends: *", "", deps) + gsub("[$][{][^}]*[}],?", "", deps) +} + +/^ [.]/ { + if (para > 0) + desc = desc "

    " + para++ + next +} + +(para > 0) { + desc = desc " " $0 +} + +END { + out() +} +' + + +echo ' +

    +' \ No newline at end of file Property changes on: tags/2.1.2/util/devhelpers/deblist.sh ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/2.1.2/util/devhelpers/font2c.sh =================================================================== --- tags/2.1.2/util/devhelpers/font2c.sh (nonexistent) +++ tags/2.1.2/util/devhelpers/font2c.sh (revision 24813) @@ -0,0 +1,96 @@ +#!/bin/sh +# font2c - convert a pcb font to simplified embedded font structs for pcb-rnd +# Copyright (C) 2016 Tibor 'Igor2' Palinkas +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# http://repo.hu/projects/pcb-rnd + +awk ' + +BEGIN { + minx = 100000 + miny = 100000 + maxx = 0 + maxy = 0 + print "/* This file is autogenerated by font2c.sh - DO NOT EDIT */" + print "" + print "/* Internal copy of the default font; used when no font file is found */" + print "" +} + +function bump(x, y) +{ + if (x < minx) minx = x + if (y < miny) miny = y + if (x > maxx) maxx = x + if (y > maxy) maxy = y +} + +/Symbol[(]/ { + sym=substr($0, 9, 1) + ADV[sym]=int(substr($0, 11, length($0))) + NLINE[sym] = 0 +} + +/SymbolLine[(]/ { + sub("[ \t]*SymbolLine[(]", "", $0) + X1[sym, NLINE[sym]] = int($1) + Y1[sym, NLINE[sym]] = int($2) + X2[sym, NLINE[sym]] = int($3) + Y2[sym, NLINE[sym]] = int($4) + TH[sym, NLINE[sym]] = int($5) + bump(int($1), int($2)) + bump(int($3), int($4)) + NLINE[sym]++ +} + +END { + for(n = 0; n < 128; n++) { + c = sprintf("%c", n) + if (c in ADV) { + if ((n > 32) && !(c ~ "[{}()]")) + annot = " /* " c " */" + else + annot = "" + print "static embf_line_t embf_line_" n "[] = {" annot + for(l = 0; l < NLINE[c]; l++) + print " {" X1[c, l] ", " Y1[c, l] ",\t\t" X2[c, l] ", " Y2[c, l] ",\t\t" TH[c, l] "}" ((l < NLINE[c]-1) ? "," : "") + if (NLINE[c] == 0) + print " {0,0,0,0}" + print "};" + }; + } + + print "/***************************************************************/" + print "static int embf_minx = " minx ";" + print "static int embf_miny = " miny ";" + print "static int embf_maxx = " maxx ";" + print "static int embf_maxy = " maxy ";" + + print "static embf_font_t embf_font[] = {" + for(n = 0; n < 128; n++) { + c = sprintf("%c", n) + comma = ((n < 127) ? "," : "") + if (c in ADV) { + print " {" ADV[c] ", embf_line_" n ", " NLINE[c] "}" comma + } + else { + print " {0, NULL, 0}" comma + } + } + print "};" +} +' Property changes on: tags/2.1.2/util/devhelpers/font2c.sh ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/2.1.2/util/devhelpers/inc_valid.sh =================================================================== --- tags/2.1.2/util/devhelpers/inc_valid.sh (nonexistent) +++ tags/2.1.2/util/devhelpers/inc_valid.sh (revision 24813) @@ -0,0 +1,56 @@ +#!/bin/sh +# inc_weed_out - check whether a source file has valid #includes for pcb-rnd +# Copyright (C) 2016 Tibor 'Igor2' Palinkas +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# http://repo.hu/projects/pcb-rnd + +# include validation: +# - in .c files config.h must be included +# - warn for duplicate #includes + +# Usage: +# 1. compile the whole project so that all dependencies of the target file are compiled +# 2. inc_valid.sh foo.c +# 3. check the output, fix #includes +# 4. compile by hand to check +# +# NOTE: conditional code also requires manual examination + +# set up file names +fn_c=$1 + +# comment one #include (index is $1, save output in $2, print the #include line to stdout) +valid() +{ + awk -v "fn=$1" ' + /^#[ \t]*include/ { + SEEN[$2]++ + } + END { + for(h in SEEN) + if (SEEN[h] > 1) + print "W " fn ": multiple include of " h + if ((fn ~ "[.]c$") && (! ("\"config.h\"" in SEEN))) + print "E " fn ": missing config.h" + } + ' < "$1" +} + +for n in "$@" +do + valid "$n" +done Property changes on: tags/2.1.2/util/devhelpers/inc_valid.sh ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/2.1.2/util/devhelpers/inc_weed_out.sh =================================================================== --- tags/2.1.2/util/devhelpers/inc_weed_out.sh (nonexistent) +++ tags/2.1.2/util/devhelpers/inc_weed_out.sh (revision 24813) @@ -0,0 +1,94 @@ +#!/bin/sh +# inc_weed_out - list #includes that can be removed without introducing warnings +# Copyright (C) 2016 Tibor 'Igor2' Palinkas +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# http://repo.hu/projects/pcb-rnd + +# include weed-out: attempt to compile an object with each #include lines +# commented out one by one; if commenting an #include doesn't change compiler +# warnings, that include is potentially unneeded. + +# Usage: +# 1. compile the whole project so that all dependencies of the target file are compiled +# 2. inc_weed_out.sh foo.c +# 3. check the output, remove #includes +# 4. compile by hand to check +# +# NOTE: the script runs 'make foo.o' - your local Makefile needs to be able +# to compile foo.o +# NOTE: sometimes disabling multiple #includes have different effect than +# disabling them one by one - always check manually. +# NOTE: conditional code also requires manual examination - the script may +# find an #include can be removed with the current settings but the +# same include may be needed with different ./configure settings + +# set up file names +fn_c=$1 +fn_o=${1%.c}.o +fn_c_backup=$fn_c.inc_weed_out +fn_refo=$1.refo +fn_tmpo=$1.tmpo + +# comment one #include (index is $1, save output in $2, print the #include line to stdout) +weed_out() +{ + awk -v "target=$1" -v "outf=$2" ' + /^#[ \t]*include/ { + count++ + if (count == target) { + print "/*" $0 "*/" > outf + print $0 + found=1 + next + } + } + { print $0 > outf } + END { + exit(found!=1) + } + ' +} + +# make a backup +cp $fn_c $fn_c_backup + +# generate initial/reference warning text +touch $fn_c +make $fn_o >/dev/null 2>$fn_refo + +# loop over #include indices +cnt=1 +while true +do + # comment out the next #include or break if there's no more + name=`weed_out $cnt < $fn_c_backup $fn_c` + if test -z "$name" + then + break + fi + + # test compile to see if we got new warnings compared to the reference + make $fn_o 2>$fn_tmpo >/dev/null + diff $fn_refo $fn_tmpo >/dev/null && echo REMOVE: $fn_c $cnt $name + + # start over + cnt=$(($cnt+1)) +done + +# clean up +mv $fn_c_backup $fn_c +rm $fn_refo $fn_tmpo Property changes on: tags/2.1.2/util/devhelpers/inc_weed_out.sh ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/2.1.2/util/devhelpers/list_dialogs.sh =================================================================== --- tags/2.1.2/util/devhelpers/list_dialogs.sh (nonexistent) +++ tags/2.1.2/util/devhelpers/list_dialogs.sh (revision 24813) @@ -0,0 +1,34 @@ +#!/bin/sh + +# assumes running from the source tree + +trunk=$(dirname $0)/../.. + +grep PCB_DAD_NEW $trunk/src/*.c $trunk/src_plugins/*/*.c | awk ' + ($1 ~ "TEMPLATE") { next } + { + file=$1 + name=$0 + sub(":$", "", file) + sub(".*src/", "src/", file) + sub(".*src_plugins/", "src_plugins/", file) + sub(".*PCB_DAD_NEW[^(]*[(]", "", name) + title=name + if (name ~ "^\"") { + sub("\"", "", name) + sub("\".*", "", name) + } + else + name = "" + + sub("[^,]*,[^,]*, *", "", title) + if (title ~ "^\"") { + sub("\"", "", title) + sub("\".*", "", title) + } + else + title = "" + + print name "\t" title "\t" file + } +' Property changes on: tags/2.1.2/util/devhelpers/list_dialogs.sh ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/2.1.2/util/devhelpers/pcb-rtrip =================================================================== --- tags/2.1.2/util/devhelpers/pcb-rtrip (nonexistent) +++ tags/2.1.2/util/devhelpers/pcb-rtrip (revision 24813) @@ -0,0 +1,122 @@ +#!/bin/sh +# pcb-rtrip - load-save-load round trip tester +# Copyright (C) 2016 Tibor 'Igor2' Palinkas +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# http://repo.hu/projects/pcb-rnd + +pcb_rtrip() +{ + rm -f "$fn.new.pcb" + + if test ! -z "$remtgt" + then + rm -f "$fn.trgt.$ext" + fi + +echo ' +SaveTo(LayoutAs, '$fn'.orig.pcb, pcb) +LoadFrom(Layout, '$fn'.orig.pcb) +SaveTo(LayoutAs, '$fn'.trgt.'$ext', '$fmt') +LoadFrom(Layout, '$fn'.trgt.'$ext', '$fmt') +SaveTo(LayoutAs, '$fn'.new.pcb, pcb) +' | $valg $pcb_rnd_bin --gui batch "$fn" + + if test -f "$fn.orig.pcb" -a -f "$fn.new.pcb" + then + diff -u "$fn.orig.pcb" "$fn.new.pcb" + else + if test ! -f "$fn.orig.pcb" + then + echo "Failed to load $fn" + else + echo "Failed to load $fn.trgt.$ext" + fi + fi +} + +set_ext() +{ + case "$fmt" + in + lihata) ext="lht";; + pcb) ext="pcb";; + *) ext="$fmt";; + esac +} + +help() +{ + echo "pcb-rtrip - load-save-load round trip tester" + echo "" + echo "Load a board, save it (*.orig.pcb), load it, save it in the target" + echo "format (*.trgt.*), load it again and save it (*.new.pcb). Calculate" + echo "the diff between *.orig.pcb and *.new.pcb; if load-save-load round trip" + echo "of a target format is lossles, the diff is empty." + echo "" + echo "Invocation: $0 [-f fmt] [input.pcb]" + echo "Switches:" + echo " -f fmt format (e.g. lihata)" + echo " -r remove target before overwrite" + echo " -b bin run bin instead of \"pcb-rnd\"" + echo " -V wrap the binary in valgrind" + echo "" +} + + +# defaults +fmt="lihata" +fn="" +remtgt="" +if test -z "$pcb_rnd_bin" +then + pcb_rnd_bin="pcb-rnd" +fi +valg="" + +while test $# -gt 0 +do + case "$1" + in + --help) help "$0"; exit 0;; + -f) fmt=$2; shift 1;; + -b) pcb_rnd_bin=$2; shift 1;; + -V) valg="valgrind -v";; + -r) remtgt=1;; + *) + if test -z "$fn" + then + fn="$1" + else + echo "unknown switch $1; try --help" >&2 + exit 1 + fi + ;; + -*) echo "unknown switch $1; try --help" >&2; exit 1;; + esac + shift 1 +done + +if test -z "$fn" +then + echo "no fn" + exit 1 + fn="pcb-rtrip.pcb" + cat >$fn +fi + +set_ext +pcb_rtrip Property changes on: tags/2.1.2/util/devhelpers/pcb-rtrip ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/2.1.2/util/devhelpers/rename.sh =================================================================== --- tags/2.1.2/util/devhelpers/rename.sh (nonexistent) +++ tags/2.1.2/util/devhelpers/rename.sh (revision 24813) @@ -0,0 +1,4 @@ +#!/bin/sh + +find . -name '*.[chly]' -exec sed -i "$@" {} \; + Property changes on: tags/2.1.2/util/devhelpers/rename.sh ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/2.1.2/util/devhelpers/renamea.sh =================================================================== --- tags/2.1.2/util/devhelpers/renamea.sh (nonexistent) +++ tags/2.1.2/util/devhelpers/renamea.sh (revision 24813) @@ -0,0 +1,10 @@ +#!/bin/sh +echo "Renaming action $1" >&2 + +na=`echo $1 | sed "s/^Action//"` +lc=`echo $na | tr "[A-Z]" "[a-z]"` + +./renameo.sh "$1" "pcb_act_$na" +./renameo.sh "${lc}_help" "pcb_acth_$na" +./renameo.sh "${lc}_syntax" "pcb_acts_$na" +./rename.sh "s/\\([^a-zA-Z0-9_]\\)AFAIL[(]${lc}[)]/\\1PCB_ACT_FAIL($na)/g" Property changes on: tags/2.1.2/util/devhelpers/renamea.sh ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/2.1.2/util/devhelpers/renamef.sh =================================================================== --- tags/2.1.2/util/devhelpers/renamef.sh (nonexistent) +++ tags/2.1.2/util/devhelpers/renamef.sh (revision 24813) @@ -0,0 +1,8 @@ +#!/bin/sh + +# Rename a function and log + +./rename.sh "s/\\([^a-zA-Z0-9_>.]\\)${1}[ \t]*[(]/\\1$2(/g" +./rename.sh "s/^${1}[ \t]*[(]/$2(/g" + +echo "$1 -> $2" >> doc/developer/renames Property changes on: tags/2.1.2/util/devhelpers/renamef.sh ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/2.1.2/util/devhelpers/renameo.sh =================================================================== --- tags/2.1.2/util/devhelpers/renameo.sh (nonexistent) +++ tags/2.1.2/util/devhelpers/renameo.sh (revision 24813) @@ -0,0 +1,9 @@ +#!/bin/sh + +./rename.sh " + s/\\([^a-zA-Z0-9_]\\)${1}\\([^a-zA-Z0-9_]\\)/\\1$2\\2/g; + s/^${1}\\([^a-zA-Z0-9_]\\)/$2\\1/g; + s/\\([^a-zA-Z0-9_]\\)${1}$/\\1$2/g; +" + +echo "$1 -> $2" >> doc/developer/renames Property changes on: tags/2.1.2/util/devhelpers/renameo.sh ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/2.1.2/util/devhelpers/subst/README =================================================================== --- tags/2.1.2/util/devhelpers/subst/README (nonexistent) +++ tags/2.1.2/util/devhelpers/subst/README (revision 24813) @@ -0,0 +1,3 @@ +Scripts to convert mainline code to pcb-rnd after the namespace cleanups in +trunk/ + Index: tags/2.1.2/util/devhelpers/subst/subst_const.sh =================================================================== --- tags/2.1.2/util/devhelpers/subst/subst_const.sh (nonexistent) +++ tags/2.1.2/util/devhelpers/subst/subst_const.sh (revision 24813) @@ -0,0 +1,25 @@ +#!/bin/sh +for n in `find . -name "*.[chly]"` +do +sed ' +{ + +s/COORD_TO_MIL/PCB_COORD_TO_MIL/g +s/MIL_TO_COORD/PCB_MIL_TO_COORD/g +s/COORD_TO_MM/PCB_COORD_TO_MM/g +s/MM_TO_COORD/PCB_MM_TO_COORD/g +s/COORD_TO_INCH/PCB_COORD_TO_INCH/g +s/INCH_TO_COORD/PCB_INCH_TO_COORD/g + +s/RAD_TO_DEG/PCB_RAD_TO_DEG/g +s/TAN_22_5_DEGREE_2/PCB_TAN_22_5_DEGREE_2/g +s/COS_22_5_DEGREE/PCB_COS_22_5_DEGREE/g +s/TAN_30_DEGREE/PCB_TAN_30_DEGREE/g +s/TAN_60_DEGREE/PCB_TAN_60_DEGREE/g +s/LN_2_OVER_2/PCB_LN_2_OVER_2/g +s/UNSCALE_TEXT/PCB_UNSCALE_TEXT/g +s/SCALE_TEXT/PCB_SCALE_TEXT/g +s/M180/PCB_M180/g +} +' -i $n +done Property changes on: tags/2.1.2/util/devhelpers/subst/subst_const.sh ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/2.1.2/util/devhelpers/subst/subst_flags.sh =================================================================== --- tags/2.1.2/util/devhelpers/subst/subst_flags.sh (nonexistent) +++ tags/2.1.2/util/devhelpers/subst/subst_flags.sh (revision 24813) @@ -0,0 +1,38 @@ +#!/bin/sh +for n in `find . -name "*.[chly]"` +do +sed ' +{ +s/NOPASTEFLAG/PCB_FLAG_NOPASTE/g +s/PININPOLYFLAG/PCB_FLAG_PININPOLY/g +s/CLEARPOLYFLAG/PCB_FLAG_CLEARPOLY/g +s/HIDENAMEFLAG/PCB_FLAG_HIDENAME/g +s/DISPLAYNAMEFLAG/PCB_FLAG_DISPLAYNAME/g +s/CLEARLINEFLAG/PCB_FLAG_CLEARLINE/g +s/FULLPOLYFLAG/PCB_FLAG_FULLPOLY/g +s/SELECTEDFLAG/PCB_FLAG_SELECTED/g +s/ONSOLDERFLAG/PCB_FLAG_ONSOLDER/g +s/SQUAREFLAG/PCB_FLAG_SQUARE/g +s/RUBBERENDFLAG/PCB_FLAG_RUBBEREND/g +s/USETHERMALFLAG/PCB_FLAG_USETHERMAL/g +s/ONSILKFLAG/PCB_FLAG_ONSILK/g +s/OCTAGONFLAG/PCB_FLAG_OCTAGON/g +s/LOCKFLAG/PCB_FLAG_LOCK/g +s/EDGE2FLAG/PCB_FLAG_EDGE2/g +s/VISITFLAG/PCB_FLAG_VISIT/g +s/NONETLISTFLAG/PCB_FLAG_NONETLIST/g +s/MINCUTFLAG/PCB_FLAG_MINCUT/g +s/ONPOINTFLAG/PCB_FLAG_ONPOINT/g +s/NOCOPY_FLAGS/PCB_FLAG_NOCOPY/g +s/FOUNDFLAG/PCB_FLAG_FOUND/g +s/HOLEFLAG/PCB_FLAG_HOLE/g +s/AUTOFLAG/PCB_FLAG_AUTO/g +s/WARNFLAG/PCB_FLAG_WARN/g +s/RATFLAG/PCB_FLAG_RAT/g +s/PINFLAG/PCB_FLAG_PIN/g +s/VIAFLAG/PCB_FLAG_VIA/g +s/DRCFLAG/PCB_FLAG_DRC/g +s/NOFLAG/PCB_FLAG_NO/g +} +' -i $n +done Property changes on: tags/2.1.2/util/devhelpers/subst/subst_flags.sh ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/2.1.2/util/devhelpers/subst/subst_mode.sh =================================================================== --- tags/2.1.2/util/devhelpers/subst/subst_mode.sh (nonexistent) +++ tags/2.1.2/util/devhelpers/subst/subst_mode.sh (revision 24813) @@ -0,0 +1,27 @@ +#!/bin/sh +for n in `find . -name "*.[chly]"` +do +sed ' +{ + s/RECTANGLE_MODE/PCB_MODE_RECTANGLE/g + s/POLYGON_MODE/PCB_MODE_POLYGON/g + s/PASTEBUFFER_MODE/PCB_MODE_PASTE_BUFFER/g + s/ROTATE_MODE/PCB_MODE_ROTATE/g + s/REMOVE_MODE/PCB_MODE_REMOVE/g + s/INSERTPOINT_MODE/PCB_MODE_INSERT_POINT/g + s/RUBBERBANDMOVE_MODE/PCB_MODE_RUBBERBAND_MOVE/g + s/THERMAL_MODE/PCB_MODE_THERMAL/g + s/ARROW_MODE/PCB_MODE_ARROW/g + s/LOCK_MODE/PCB_MODE_LOCK/g + s/POLYGONHOLE_MODE/PCB_MODE_POLYGON_HOLE/g + s/ARC_MODE/PCB_MODE_ARC/g + s/PAN_MODE/PCB_MODE_PAN/g + s/MOVE_MODE/PCB_MODE_MOVE/g + s/COPY_MODE/PCB_MODE_COPY/g + s/TEXT_MODE/PCB_MODE_TEXT/g + s/NO_MODE/PCB_MODE_NO/g + s/VIA_MODE/PCB_MODE_VIA/g + s/LINE_MODE/PCB_MODE_LINE/g +} +' -i $n +done Property changes on: tags/2.1.2/util/devhelpers/subst/subst_mode.sh ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/2.1.2/util/devhelpers/subst/subst_objtype.sh =================================================================== --- tags/2.1.2/util/devhelpers/subst/subst_objtype.sh (nonexistent) +++ tags/2.1.2/util/devhelpers/subst/subst_objtype.sh (revision 24813) @@ -0,0 +1,30 @@ +#!/bin/sh +for n in `find . -name *.[chly]` +do +sed ' +{ +s/PIN_TYPES/PCB_TYPEMASK_PIN/g; +s/LOCK_TYPES/PCB_TYPEMASK_LOCK/g; +s/ALL_TYPES/PCB_TYPEMASK_ALL/g; + +s/RATLINE_TYPE/PCB_TYPE_RATLINE/g; +s/ELEMENTNAME_TYPE/PCB_TYPE_ELEMENT_NAME/g; +s/POLYGONPOINT_TYPE/PCB_TYPE_POLYGON_POINT/g; +s/LINEPOINT_TYPE/PCB_TYPE_LINE_POINT/g; +s/ELEMENTLINE_TYPE/PCB_TYPE_ELEMENT_LINE/g; +s/ELEMENTARC_TYPE/PCB_TYPE_ELEMENT_ARC/g; + +s/NO_TYPE/PCB_TYPE_NONE/g; +s/VIA_TYPE/PCB_TYPE_VIA/g; +s/ELEMENT_TYPE/PCB_TYPE_ELEMENT/g; +s/LINE_TYPE/PCB_TYPE_LINE/g; +s/POLYGON_TYPE/PCB_TYPE_POLYGON/g; +s/TEXT_TYPE/PCB_TYPE_TEXT/g; +s/PIN_TYPE/PCB_TYPE_PIN/g; +s/PAD_TYPE/PCB_TYPE_PAD/g; +s/ARC_TYPE/PCB_TYPE_ARC/g; +s/LOCKED_TYPE/PCB_TYPE_LOCKED/g; +s/NET_TYPE/PCB_TYPE_NET/g; +} +' -i $n +done Property changes on: tags/2.1.2/util/devhelpers/subst/subst_objtype.sh ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/2.1.2/util/devhelpers/todo.sh =================================================================== --- tags/2.1.2/util/devhelpers/todo.sh (nonexistent) +++ tags/2.1.2/util/devhelpers/todo.sh (revision 24813) @@ -0,0 +1,3 @@ +#!/bin/sh +files=`find ../.. -name *.[chly]` +grep "^[ \t]*TODO[(]" $files Property changes on: tags/2.1.2/util/devhelpers/todo.sh ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/2.1.2/util/fp2anim =================================================================== --- tags/2.1.2/util/fp2anim (nonexistent) +++ tags/2.1.2/util/fp2anim (revision 24813) @@ -0,0 +1,703 @@ +#!/bin/sh + +photo=0 +grid_unit="mil" + +annotation=pins + +while test $# -gt 0 +do + case $1 in + --photo|p) photo=1;; + --grid-unit|g) grid_unit=$2; shift 1;; + --mm) grid_unit="mm";; + --diamond) diamond=1;; + --annotation) annotation=$2; shift 1;; + esac + shift 1 +done + + + +awk -v "photo=$photo" -v "grid_unit=$grid_unit" -v "diamond=$diamond" -v "annotation=$annotation" ' + +BEGIN { + diamond_x = 0 + diamond_y = 0 + + dim_arrow_len = 2000 + + q="\"" + + ds = 100*20 + offs_3d = 150 + + if (photo) { + clr_board[-1] = "#003300" + clr_board[0] = "#006600" + clr_board[1] = "#22AA22" + + clr_plated[-1] = "#555555" + clr_plated[0] = "#777777" + clr_plated[1] = "#999999" + + clr_silk[-1] = "#AAAAAA" + clr_silk[0] = "#CCCCCC" + clr_silk[1] = "#FFFFFF" + + clr_solderstop[0] = "#00BB00" + + + clr_hole[0] = "black" + clr_grid[0] = "blue" + } + else { + clr_board[0] = "darkgreen" + clr_plated[0] = "#777777" + clr_hole[0] = "white" + clr_silk[0] = "black" + clr_solderstop[0] = "white" + clr_grid[0] = "blue" + } + + clr_annotation[0] = "#ff0000" + clr_annotationbg[0] = "#ffffff" + + marg=100000 + + if (annotation != "none") { + enable_annot = 1 + if (annotation ~ "pins") + enable_pinnum = 1 + if (annotation ~ "dimname") + enable_dim_name = 1 + if (annotation ~ "dimvalue") + enable_dim_value = 1 + if (annotation ~ "background") + enable_annotbg = 1 + } + + if (grid_unit == "mil") { + gstep = 10000 + gmul = 1/100 + } + else { + gstep = 3937 + gmul = 1/3937 + } + + vf_data = vf_load("/usr/share/animator/romansimplexmono") +} + +### vector font ### +function vf_load(fn, s) +{ + while((getline < fn) == 1) { + if ($1 == "!") + glyphw[$2] = $3 + else if ($1 == "!font") + for(i=32; i<=127; i++) + font[$2 sprintf("%c", i)] = $(i-29) + else + s = s "\n" $0 + } + close(fn) + return s +} + +function vf_textwidth(fnt, text, x,k) { + x=0 + for(k=1; k<=length(text); k+=1) + x += glyphw[font[fnt substr(text,k,1)]] + return x +} + +function vf_show(fnt, text, k,s) { + for(k=1; k<=length(text); k+=1) + s = s "\ninvoke hf" font[fnt substr(text,k,1)] + return s +} + +### + +function directive(term ,tmp) +{ + while(!($0 ~ term "[ \t]*$")) { + if ((getline tmp) < 1) { + print "Premature end of file looking for " term " of " $1 > "/dev/stderr" + exit 1 + } + $0 = $0 " " tmp + } +# print "directive: |" term "|" $0 "|" > "/dev/stderr" +} + +function edges(x, y) +{ + if ((xmin == "") || (x < xmin)) + xmin = x + if ((ymin == "") || (y < ymin)) + ymin = y + if ((xmax == "") || (x > xmax)) + xmax = x + if ((ymax == "") || (y > ymax)) + ymax = y +} + +# draw a line with rounded ends +# do not draw end circles if omit_ends is non-zero +# extend both ends by length_bloat +function rline(x1, y1, x2, y2, width ,omit_ends , length_bloat ,nx,ny,vx,vy, len) +{ + + nx = y2-y1 + ny = -(x2-x1) + + len=sqrt(nx*nx+ny*ny) + if (len != 0) { + nx /= len + ny /= len + vx = -ny + vy = nx + + if (length_bloat != 0) { + x1 -= length_bloat * vx + x2 += length_bloat * vx + y1 -= length_bloat * vy + y2 += length_bloat * vy + } + +# if there are no end circles, we are square and should extend by extra width/2 + if (omit_ends) { + x1 -= (width/2) * vx + x2 += (width/2) * vx + y1 -= (width/2) * vy + y2 += (width/2) * vy + } + + print "poly", x1+nx*width/2, y1+ny*width/2, x2+nx*width/2, y2+ny*width/2, x2-nx*width/2, y2-ny*width/2, x1-nx*width/2, y1-ny*width/2 + edges(x1+nx*width/2, y1+ny*width/2) + edges(x2+nx*width/2, y2+ny*width/2) + edges(x2-nx*width/2, y2-ny*width/2) + edges(x1-nx*width/2, y1-ny*width/2) + } + + if (!omit_ends) { + print "fillcircle", x1, y1, width/2, width/10 + if ((x1 != x2) || (y1 != y2)) + print "fillcircle", x2, y2, width/2, width/10 + + edges(x1-width/2, y1-width/2) + edges(x2+width/2, y2+width/2) + } + + edges(x1, y1) + edges(x2, y2) +} + +function deg2rad(d) +{ + return d/180*3.141592654 +} + +function rarc(cx, cy, rx, ry, a_start, a_delta, width ,a1, a2) +{ + if ((rx < 0) || (ry < 0)) + return + + if (a_delta < 0) { + a_start = 180-a_start + a_delta = -a_delta + } + + step = a_delta * 100 * 2 / (((rx > ry) ? rx : ry) + 1) + if (step > 45) + step = 45 + + for(a1 = a_start; a1 < a_start + a_delta - step; a1 += step) { + a2 = a1+step + rline( cx - rx * cos(deg2rad(a1)), cy + ry * sin(deg2rad(a1)), + cx - rx * cos(deg2rad(a2)), cy + ry * sin(deg2rad(a2)), + width, 0) + } + + a1 = a2; + a2 = a_start+a_delta + rline( cx - rx * cos(deg2rad(a1)), cy + ry * sin(deg2rad(a1)), + cx - rx * cos(deg2rad(a2)), cy + ry * sin(deg2rad(a2)), + width, 0) + +} + +function rsquare(x1, y1, x2, y2, r ,tmp) +{ + if (x1 < x2) { + tmp=x1 + x1 = x2 + x2 = tmp + } + if (y1 < y2) { + tmp=y1 + y1 = y2 + y2 = tmp + } + + print "poly", x1, y1-r,x1-r, y1, x2+r,y1, x2, y1-r, x2, y2+r, x2+r,y2, x1-r, y2, x1, y2+r + print "fillcircle", x1-r, y1-r, r, r/10 + print "fillcircle", x2+r, y2+r, r, r/10 + print "fillcircle", x2+r, y1-r, r, r/10 + print "fillcircle", x1-r, y2+r, r, r/10 +} + +function flash(x, y, dia, square, roundr) +{ + if (square) { + if (roundr != "") + rsquare(x-dia/2, y-dia/2, x+dia/2, y+dia/2, roundr) + else + print "fillrect", x-dia/2, y-dia/2, dia, dia + } + else + print "fillcircle", x, y, dia/2, dia/10 +} + +function hole(x, y, ring, clr, mask, drill, name, square) +{ + if (photo) { + print "macro push mask" + flash(x, y, (ring+clr), square, (ring+clr)/10) + print "endmacro" + } + + print "macro push copper" + flash(x, y, ring, square) + print "endmacro" + + has_hole=1 + print "macro push hole" + flash(x, y, drill, 0) + print "endmacro" + + if (enable_pinnum) { + gsub("[\"]", "", name) + annot(x, y, name, 0, 0, 1) + } + + edges(x-(ring+clr)/2, y-(ring+clr)/2) + edges(x+(ring+clr)/2, y+(ring+clr)/2) +} + +function pad(x1, y1, x2, y2, thickness, clr, mask, name, square) +{ + if (photo) { + print "macro push mask" + rline(x1, y1, x2, y2, thickness+clr, square) + print "endmacro" + } + + + print "macro push copper" + rline(x1, y1, x2, y2, thickness, square) + print "endmacro" + + if (enable_pinnum) { + gsub("[\"]", "", name) + annot((x2+x1)/2, (y2+y1)/2, name, 0, 0, 1) + } +} + +function vf_text(x, y, txt, rot, elev, vcenter ,TXT,v,n,W,maxw,s,sep,bg,maxh) +{ + gsub("[|]", "", txt) + + v = split(txt, TXT, "[|]") + sep = " " + + s = s "\n" "push" + s = s "\n" "shift " x sep y + if (rot) + s = s "\n" "shift " (-1*elev) sep 0 + else + s = s "\n" "shift " 0 sep (-1*elev) + + s = s "\n" "scale %textscale% %textscale%" + s = s "\n" "scale 1 -1" + + for(n = 1; n <= v; n++) { + W[n] = vf_textwidth("roman-simplex-mono", TXT[n]) + if (W[n] > maxw) + maxw = W[n] + maxh++ + } + + if (vcenter) + s = s "\n" "shift 0 " (-maxh/2) + + if (rot) + s = s "\n" "rotate 90" + + for(n = v; n > 0; n--) { + s = s "\n" "!TXT " TXT[n] + s = s "\n" "push" + + s = s "\n" "shift " ((maxw - W[n])/(2)) - maxw/2 sep 0 + + if (enable_annotbg) { + s = s "\n" "color " clr_annotationbg[0] + s = s "\n" "alpha 0.2" + s = s "\n" "fillrect " W[n]*-0.1 sep -0.1 "-" sep W[n]*1.1 sep 1.1 + s = s "\n" "alpha 0.1" + s = s "\n" "fillrect " W[n]*-0.17 sep -0.17 "-" sep W[n]*1.17 sep 1.17 + s = s "\n" "alpha 1" + s = s "\n" "color " clr_annotation[0] + } + +# s = s "\n" "thick %textthick%" + s = s "\n" vf_show("roman-simplex-mono", TXT[n]) +# s = s "\n" "thick 1" + s = s "\n" "pop" + s = s "\n" "shift 0 1.15" + } + s = s "\n" "pop" + return s +} + + + +function annot(x, y, txt, rot, elev, hcenter) +{ + annot_pend = annot_pend "\n" vf_text(x, y, txt, rot, elev, hcenter) +} + + +function dimension(x1, y1, x2, y2, dist, name, value ,vx,vy,nx,ny,X1,Y1,X2,Y2,len,alen,awidth,tmp, ang,negdist,cx,cy,dx,dy,D) +{ + alen = dim_arrow_len + + vx = x2-x1 + vy = y2-y1 + len = vx*vx+vy*vy + if (len == 0) + return + len = sqrt(len) + vx = vx/len + vy = vy/len + nx = vy + ny = -vx + + if (dist ~ "^[@]") { + cx = (x1+x2)/2 + cy = (y1+y2)/2 + sub("@", "", dist) + split(dist, D, ";") + nx = D[1] - cx + ny = D[2] - cy + + X1 = x1+nx + Y1 = y1+ny + X2 = x2+nx + Y2 = y2+ny + + dist = nx*nx+ny*ny + if (dist > 0) + dist = sqrt(dist) + + nx /= dist + ny /= dist + } + else { + if (dist < 0) { + tmp = x1 + x1 = x2 + x2 = tmp + tmp = y1 + y1 = y2 + y2 = tmp + dist = -dist + + vx = -vx + vy = -vy + nx = -nx + ny = -ny + } + + X1 = x1+nx*dist + Y1 = y1+ny*dist + X2 = x2+nx*dist + Y2 = y2+ny*dist + } + + + if (alen > len/4) + alen=len/4 + + awidth=alen/6 + + ang = atan2(vx, vy) + + print "macro push annotation" + print "line", x1, y1, X1+nx*awidth, Y1+ny*awidth + print "line", x2, y2, X2+nx*awidth, Y2+ny*awidth + print "line", X1, Y1, X2, Y2 + + print "poly", X1, Y1, X1+vx*alen+nx*awidth, Y1+vy*alen+ny*awidth , X1+vx*alen-nx*awidth, Y1+vy*alen-ny*awidth + print "poly", X2, Y2, X2-vx*alen+nx*awidth, Y2-vy*alen+ny*awidth , X2-vx*alen-nx*awidth, Y2-vy*alen-ny*awidth + print "endmacro" + + if (enable_dim_value) { + if (value == "") + value = len + else if (value == "!") + value = "" + if (value != "") + value *= gmul + } + else + value = "" + + if (!enable_dim_name) + name = "" + + if ((name != "") && (value != "")) + name = name "=|" value + else if ((value != "") && (name == "")) + name = value + + if (name != "") { + if (ang < 0) + ang = -ang + if ((ang < 3.1415*3/4) && (ang > 3.1415*1/4)) + annot((X1+X2)/2, (Y1+Y2)/2, name, 0, awidth*1.1,0) + else + annot((X1+X2)/2, (Y1+Y2)/2, name, 1, awidth*1.1,0) + } + + edges(X1+nx*awidth, Y1+ny*awidth) + edges(X2+nx*awidth, Y2+ny*awidth) +} + +/^[ \t]*#dimension/ { + if ((enable_dim_name) || (enable_dim_value)) + dimension($2, $3, $4, $5, $6, $7, $8) +} + +/^[ \t]*#/ { next } + +/ElementLine[ \t]*[[]/ { + directive("]") + sub(".*ElementLine[ \t]*[[]", "", $0) + sub("]$", "", $0) + + print "macro push silk" + rline($1, $2, $3, $4, $5) + print "endmacro" + + next +} + +/ElementLine[ \t]*[(]/ { + directive(")") + sub(".*ElementLine[ \t]*[(]", "", $0) + sub(")$", "", $0) + + print "macro push silk" + rline($1*100, $2*100, $3*100, $4*100, $5*100) + print "endmacro" + + next +} + + + +/ElementArc[ \t]*[[]/ { + directive("]") + sub(".*ElementArc[ \t]*[[]", "", $0) + sub("]$", "", $0) + + print "macro push silk" + rarc($1, $2, $3, $4, $5, $6, $7) + print "endmacro" + + next +} + +# ElementArc(0 0 59 59 45 90 10) +/ElementArc[ \t]*[(]/ { + directive(")") + sub(".*ElementArc[ \t]*[(]", "", $0) + sub(")$", "", $0) + + print "macro push silk" + rarc($1*100, $2*100, $3*100, $4*100, $5, $6, $7*100) + print "endmacro" + + next +} + + +# Pin[0 0 8000 5000 8600 3937 "" "1" "square"] +/Pin[ \t]*[[]/ { + directive("]") + sub(".*Pin[ \t]*[[]", "", $0) + sub("]$", "", $0) + hole($1, $2, $3, $4, $5, $6, $8, ($9 ~ "square")) +} + +# Pin(300 800 90 60 "3" 0x01) +/Pin[ \t]*[(]/ { + directive(")") + sub(".*Pin[ \t]*[(]", "", $0) + sub("]$", "", $0) + hole($1*100, $2*100, $3*100, $4*100, 3000, 2000, $5, ($6 ~ "0x10")) +} + +# Pad[ 0 0 0 0 0 5000 8600 "" "4" ""] +/Pad[ \t]*[[]/ { + directive("]") + sub(".*Pad[ \t]*[[]", "", $0) + sub("]$", "", $0) + + pad($1, $2, $3, $4, $5, $6, $7, $9, ($10 ~ "square")) +} + +/Pad[ \t]*[(]/ { + directive(")") + sub(".*Pad[ \t]*[(]", "", $0) + sub(")$", "", $0) + + if (NF > 8) + pad($1*100, $2*100, $3*100, $4*100, $5*100, $6*100, $7*100, $9, 1) + else + pad($1*100, $2*100, $3*100, $4*100, $5*100, $6*100, $7*100, $6, 1) + +} + +/Mark[ \t]*[(]/ { + directive(")") + sub(".*Mark[ \t]*[(]", "", $0) + sub(")$", "", $0) + + diamond_x = $1*100 + diamond_y = $2*100 +} + + +function layer_3d(name, color, offs) +{ + if ((offs == "") || (offs == 1)) + offs = offs_3d + else if (offs == -1) + offs = -offs_3d + + if (1 in color) { + print "push" + print "shift", (-1*offs), (-1*offs) + print "color", color[1] + print "invoke ", name + print "pop" + } + + if (-1 in color) { + print "push" + print "shift", (offs), (offs) + print "color", color[-1] + print "invoke ", name + print "pop" + } + + if (0 in color) { + print "color", color[0] + print "invoke ", name + } +} + +function draw_grid() +{ + while ((size/gstep) > 10) + gstep=gstep*2 + + for(x = 0 - int(marg/gstep)*gstep; x < size+marg; x+=gstep) { + print "line", x, ymin-marg, x, ymin+size+marg + print "line", xmin-marg, x, xmin+size+marg, x + print "text", x, ymax+gstep/2, q x*gmul "\\n" grid_unit q + print "text", xmax+gstep/2, x, q x*gmul "\\n" grid_unit q + } + +} + +END { + print "frame" + print vf_data + +# make sure all macros exist even if the footprint does not use them + print "macro push silk\nendmacro" + print "macro push copper\nendmacro" + print "macro push mask\nendmacro" + print "macro push annotation\nendmacro" + + if (photo) { + xmin -= offs_3d*2 + ymin -= offs_3d*2 + xmax += offs_3d*2 + ymax += offs_3d*2 + } + + sx = xmax-xmin + sy = ymax-ymin + + + size = sx > sy ? sx : sy + + print "scale 1 -1" + print "viewport", xmin, ymin, "-", xmin+size, ymin+size + print "bg", clr_solderstop[0] + print "shift", (size-sx)/2, (size-sy)/2 + print "scale 0.85" + + + print "dash 0xaaaa" + print "color", clr_grid[0] + + if ((grid_unit != "") == (grid_unit != "none")) + draw_grid() + + print "dash 0xffff" + + if (diamond) { + print "macro push annotation" + print "lines", diamond_x-ds, diamond_y, diamond_x,diamond_y+ds, diamond_x+ds,diamond_y, diamond_x,diamond_y-ds, diamond_x-ds,diamond_y + print "endmacro" + } + + + if (photo) { + layer_3d("mask", clr_board, -1) + } + + + print "color", clr_plated[0] + print "invoke copper" + layer_3d("copper", clr_plated, 1) + if (has_hole) { + layer_3d("hole", clr_hole, -1) + } + + + layer_3d("silk", clr_silk) + + if (enable_annot) { + gsub("%textscale%", size/40, annot_pend) +# gsub("%textthick%", size/15000, annot_pend) + + print "macro push annotation" + print annot_pend + print "endmacro" + + print "color", clr_annotation[0] + print "invoke annotation" + } + + print "flush" +} + +' Property changes on: tags/2.1.2/util/fp2anim ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/2.1.2/util/fp2subc =================================================================== --- tags/2.1.2/util/fp2subc (nonexistent) +++ tags/2.1.2/util/fp2subc (revision 24813) @@ -0,0 +1,129 @@ +#!/bin/sh +# fp2subc - convert old pcb footprints to subcircuit +# Copyright (C) 2017 Tibor 'Igor2' Palinkas +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# http://repo.hu/projects/pcb-rnd + + +conv_custom_fp() +{ +local in_fp out_subc +in_fp=`realpath $1` +out_subc="$2" +echo ' +LoadFrom(ElementToBuffer, "'$in_fp'") +PasteBuffer(Restore) +PasteBuffer(ToLayout, 0, 0) + +# convert to subc +Select(All) +PasteBuffer(ConvertSubc) + +# save +SaveTo(PasteBuffer, "'$out_subc'", "lihata board v4") +' | $dbg "$pcb_rnd" $conf --gui batch +} + +conv_lib_fp() +{ +echo ' +LoadFootprint("'$1'") +PasteBuffer(Restore) +PasteBuffer(ToLayout, 0, 0) + +# convert to subc +Select(All) +PasteBuffer(ConvertSubc) + +# save +SaveTo(PasteBuffer, "'$2'") +' | $dbg "$pcb_rnd" $conf --gui batch +} + +help() +{ + echo "fp2subc - convert old pcb footprints to subcircuit" + echo "fp2subc [-l] [-c key=val] [-p path] fp [subc]" + echo " -l fp is not a file path, use the normal library search for fp" + echo " --lib same as -l" + echo " -p path specify the full path of the pcb-rnd executable to use" + echo " --pcb-rnd same as -p" + echo " -d path specify the the debugger to wrap pcb-rnd in (e.g. valgrind)" + echo " --debugger same as -d" + echo " -c key=val pass on a configuration setting to pcb-rnd" + echo " fp the path or library name of the footprint" + echo " subc the path of the output subc file" + echo "" +} + +lib=0 +in_fp="" +out_subc="" +pcb_rnd=pcb-rnd +dbg="" +conf="" +while test $# -gt 0 +do + cmd="$1" + shift 1 + case "$cmd" in + -d|--debugger) dbg="$1"; shift 1;; + -p|--pcb-rnd) pcb_rnd="$1"; shift 1;; + -c) conf="$conf -c $1"; shift 1;; + -l|--lib) lib=1 ;; + -h|--help) help; exit 0;; + *) + if test -z "$in_fp" + then + in_fp="$cmd" + else + if test -z "$out_subc" + then + out_subc="$out_subc" + else + echo "fp2subc error: can't use 3 filenames" >&2 + exit 1 + fi + fi + ;; + esac +done + +if test -z "$in_fp" +then + echo "fp2subc error: need at least an input file name" + exit 1 +fi + +if test -z "$out_subc" +then + if test $lib -eq 0 + then + out_subc=`echo "$in_fp" | sed "s/.fp$//;s/$/.subc.lht/"` + else + out_subc=`echo "$in_fp" | sed "s/[^A-Za-z0-9_.-]*//g;s/.fp$//;s/$/.subc.lht/"` + fi + echo "fp2subc: saving subcircuit in $out_subc" +fi + + +if test $lib -eq 0 +then + conv_custom_fp "$in_fp" "$out_subc" +else + conv_lib_fp "$in_fp" "$out_subc" +fi Property changes on: tags/2.1.2/util/fp2subc ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/2.1.2/util/gnet-pcbrndfwd.scm =================================================================== --- tags/2.1.2/util/gnet-pcbrndfwd.scm (nonexistent) +++ tags/2.1.2/util/gnet-pcbrndfwd.scm (revision 24813) @@ -0,0 +1,125 @@ +;;; gEDA - GPL Electronic Design Automation +;;; gnetlist - gEDA Netlist +;;; Copyright (C) 1998-2008 Ales Hvezda +;;; Copyright (C) 1998-2008 gEDA Contributors (see ChangeLog for details) +;;; +;;; This program is free software; you can redistribute it and/or modify +;;; it under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 2 of the License, or +;;; (at your option) any later version. +;;; +;;; This program is distributed in the hope that it will be useful, +;;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;; GNU General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with this program; if not, write to the Free Software +;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +;; PCB forward annotation script + +(use-modules (ice-9 regex)) +(use-modules (ice-9 format)) + +;; This is a list of attributes which are propogated to the pcb +;; elements. Note that refdes, value, and footprint need not be +;; listed here. +(define pcbrndfwd:element-attrs + '("device" + "manufacturer" + "manufacturer_part_number" + "vendor" + "vendor_part_number" + )) + +(define (pcbrndfwd:quote-string s) + (string-append "\"" + (regexp-substitute/global #f "\"" s 'pre "\\\"" 'post) + "\"") + ) + +(define (pcbrndfwd:pinfmt pin) + (format #f "~a-~a" (car pin) (car (cdr pin))) + ) + +(define (pcbrndfwd:each-pin net pins port) + (if (not (null? pins)) + (let ((pin (car pins))) + (format port "Netlist(Add,~a,~a)~%" net (pcbrndfwd:pinfmt pin)) + (pcbrndfwd:each-pin net (cdr pins) port)))) + +(define (pcbrndfwd:each-net netnames port) + (if (not (null? netnames)) + (let ((netname (car netnames))) + (pcbrndfwd:each-pin netname (gnetlist:get-all-connections netname) port) + (pcbrndfwd:each-net (cdr netnames) port)))) + +(define (pcbrndfwd:each-attr refdes attrs port) + (if (not (null? attrs)) + (let ((attr (car attrs))) + (format port "ElementSetAttr(~a,~a,~a)~%" + (pcbrndfwd:quote-string refdes) + (pcbrndfwd:quote-string attr) + (pcbrndfwd:quote-string (gnetlist:get-package-attribute refdes attr))) + (pcbrndfwd:each-attr refdes (cdr attrs) port)))) + +;; write out the pins for a particular component +(define pcbrndfwd:component_pins + (lambda (port package pins) + (if (and (not (null? package)) (not (null? pins))) + (begin + (let ( + (pin (car pins)) + (label #f) + (pinnum #f) + ) + (display "ChangePinName(" port) + (display (pcbrndfwd:quote-string package) port) + (display ", " port) + + (set! pinnum (gnetlist:get-attribute-by-pinnumber package pin "pinnumber")) + + (display pinnum port) + (display ", " port) + + (set! label (gnetlist:get-attribute-by-pinnumber package pin "pinlabel")) + (if (string=? label "unknown") + (set! label pinnum) + ) + (display (pcbrndfwd:quote-string label) port) + (display ")\n" port) + ) + (pcbrndfwd:component_pins port package (cdr pins)) + ) + ) + ) + ) + +(define (pcbrndfwd:each-element elements port) + (if (not (null? elements)) + (let* ((refdes (car elements)) + (value (gnetlist:get-package-attribute refdes "value")) + (footprint (gnetlist:get-package-attribute refdes "footprint")) + ) + + (format port "ElementList(Need,~a,~a,~a)~%" + (pcbrndfwd:quote-string refdes) + (pcbrndfwd:quote-string footprint) + (pcbrndfwd:quote-string value)) + (pcbrndfwd:each-attr refdes pcbrndfwd:element-attrs port) + (pcbrndfwd:component_pins port refdes (gnetlist:get-pins refdes)) + + (pcbrndfwd:each-element (cdr elements) port)))) + +(define (pcbrndfwd output-filename) + (let ((port (open-output-file output-filename))) + (format port "Netlist(Freeze)\n") + (format port "Netlist(Clear)\n") + (pcbrndfwd:each-net (gnetlist:get-all-unique-nets "dummy") port) + (format port "Netlist(Sort)\n") + (format port "Netlist(Thaw)\n") + (format port "ElementList(Start)\n") + (pcbrndfwd:each-element packages port) + (format port "ElementList(Done)\n") + (close-output-port port))) Index: tags/2.1.2/util/gnet-pcbrndfwd_elem.scm =================================================================== --- tags/2.1.2/util/gnet-pcbrndfwd_elem.scm (nonexistent) +++ tags/2.1.2/util/gnet-pcbrndfwd_elem.scm (revision 24813) @@ -0,0 +1,107 @@ +;;; gEDA - GPL Electronic Design Automation +;;; gnetlist - gEDA Netlist +;;; Copyright (C) 1998-2008 Ales Hvezda +;;; Copyright (C) 1998-2008 gEDA Contributors (see ChangeLog for details) +;;; +;;; This program is free software; you can redistribute it and/or modify +;;; it under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 2 of the License, or +;;; (at your option) any later version. +;;; +;;; This program is distributed in the hope that it will be useful, +;;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;; GNU General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with this program; if not, write to the Free Software +;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +;; PCB forward annotation script; +;; modified version of pcbrndfwd: do not do the net list, only elements, +;; this way nets can be imported in the traditional netlist-way + +(use-modules (ice-9 regex)) +(use-modules (ice-9 format)) + +;; This is a list of attributes which are propogated to the pcb +;; elements. Note that refdes, value, and footprint need not be +;; listed here. +(define pcbrndfwd:element-attrs + '("device" + "manufacturer" + "manufacturer_part_number" + "vendor" + "vendor_part_number" + )) + +(define (pcbrndfwd:quote-string s) + (string-append "\"" + (regexp-substitute/global #f "\"" s 'pre "\\\"" 'post) + "\"") + ) + + +(define (pcbrndfwd:each-attr refdes attrs port) + (if (not (null? attrs)) + (let ((attr (car attrs))) + (format port "ElementSetAttr(~a,~a,~a)~%" + (pcbrndfwd:quote-string refdes) + (pcbrndfwd:quote-string attr) + (pcbrndfwd:quote-string (gnetlist:get-package-attribute refdes attr))) + (pcbrndfwd:each-attr refdes (cdr attrs) port)))) + +;; write out the pins for a particular component +(define pcbrndfwd:component_pins + (lambda (port package pins) + (if (and (not (null? package)) (not (null? pins))) + (begin + (let ( + (pin (car pins)) + (label #f) + (pinnum #f) + ) + (display "ChangePinName(" port) + (display (pcbrndfwd:quote-string package) port) + (display ", " port) + + (set! pinnum (gnetlist:get-attribute-by-pinnumber package pin "pinnumber")) + + (display pinnum port) + (display ", " port) + + (set! label (gnetlist:get-attribute-by-pinnumber package pin "pinlabel")) + (if (string=? label "unknown") + (set! label pinnum) + ) + (display (pcbrndfwd:quote-string label) port) + (display ")\n" port) + ) + (pcbrndfwd:component_pins port package (cdr pins)) + ) + ) + ) + ) + +(define (pcbrndfwd:each-element elements port) + (if (not (null? elements)) + (let* ((refdes (car elements)) + (value (gnetlist:get-package-attribute refdes "value")) + (footprint (gnetlist:get-package-attribute refdes "footprint")) + ) + + (format port "ElementList(Need,~a,~a,~a)~%" + (pcbrndfwd:quote-string refdes) + (pcbrndfwd:quote-string footprint) + (pcbrndfwd:quote-string value)) + (pcbrndfwd:each-attr refdes pcbrndfwd:element-attrs port) + (pcbrndfwd:component_pins port refdes (gnetlist:get-pins refdes)) + + (pcbrndfwd:each-element (cdr elements) port)))) + +(define (pcbrndfwd_elem output-filename) + (let ((port (open-output-file output-filename))) + (format port "ElementList(Start)\n") + (pcbrndfwd:each-element packages port) + (format port "ElementList(Done)\n") + (close-output-port port))) Index: tags/2.1.2/util/gsch2pcb-rnd/Makefile.in =================================================================== --- tags/2.1.2/util/gsch2pcb-rnd/Makefile.in (nonexistent) +++ tags/2.1.2/util/gsch2pcb-rnd/Makefile.in (revision 24813) @@ -0,0 +1,129 @@ +put /local/pcb/CFLAGS cc/cflags +append /local/pcb/CFLAGS {-I../.. -I../../src_3rd -I../../src_3rd/liblihata -DSCMDIR="\\"$(LIBDIR_INSTALLED)\\""} +append /local/pcb/LDFLAGS cc/ldflags +include {../scconfig/template/debug.tmpasm} + +print [@ +ROOT=../.. +PLUGDIR=../../src_plugins +CFLAGS=@/local/pcb/c89flags@ @/local/pcb/CFLAGS@ +LDFLAGS=-lm @/local/pcb/LDFLAGS@ +CC=@cc/cc@ +@] + +if ?libs/script/fungw/presents +then + print {HASHOBJ=} +else +# no system installed fungw: need local hash objects + print {HASHOBJ=../../src_3rd//genht/hash.o ../../src_3rd//genht/htsp.o ../../src_3rd//genht/htpp.o ../../src_3rd//genht/htsi.o} +end + +print [@ +VECTOBJ=../../src_3rd/genvector/gds_char.o ../../src_3rd/genvector/vtp0.o ../../src_3rd/genvector/vts0.o +LISTOBJ=../../src_3rd/genlist/genadlist.o ../../src_3rd/genlist/genlistalloc.o +QPARSE=../../src_3rd/qparse/qparse.o +LHTOBJ= \ + ../../src_3rd/liblihata/parser.o \ + ../../src_3rd/liblihata/dom.o \ + ../../src_3rd/liblihata/dom_list.o \ + ../../src_3rd/liblihata/dom_hash.o \ + ../../src_3rd/liblihata/dom_table.o \ + ../../src_3rd/liblihata/lihata.o \ + ../../src_3rd/liblihata/hash_str.o \ + ../../src_3rd/liblihata/tree.o \ + ../../src_3rd/liblihata/tree_list.o \ + ../../src_3rd/liblihata/tree_hash.o \ + ../../src_3rd/liblihata/tree_table.o \ + ../../src_3rd/liblihata/tree_symlink.o \ + ../../src_3rd/liblihata/tree_path.o +@] + +put /local/pcb/tmpasm/buildin {../src_plugins/Buildin.tmpasm} +put /local/pcb/tmpasm/plugin {../src_plugins/Plugin.tmpasm} +put /local/pcb/tmpasm/disable {../src_plugins/Disable.tmpasm} + +put /local/pcb/RULES {} +put /local/pcb/OBJS {} +put /local/pcb/LDFLAGS {} +put /local/pcb/CFLAGS {} +put /local/pcb/buildin_init_code {} +put /local/pcb/buildin_init_extern {} + +uniq /local/pcb/OBJS + +print [@ + +FP_OBJS = @/local/pcb/OBJS@ ../../src/plug_footprint.o +CONF_OBJS = ../../src/vtlibrary.o ../../src/compat_fs.o ../../src/paths.o ../../src/conf.o ../../src/conf_core.o ../../src/hid_cfg.o ../../src/misc_util.o ../../src/unit.o ../../src/conf_internal.o ../../src/list_conf.o ../../src/conf_hid.o ../../src/pcb-printf.o ../../src/compat_misc.o ../../src/safe_fs.o +FP_LDFLAGS = @/local/pcb/LDFLAGS@ +FP_CFLAGS = @/local/pcb/CFLAGS@ +OBJS = \ + gsch2pcb.o \ + help.o \ + netlister.o \ + run.o \ + glue.o \ + method_import.o + +all: + $(MAKE) revcheck + $(MAKE) gsch2pcb-rnd$(EXE) + +revcheck: + cd ../../scconfig && ./revtest Rev.stamp < Rev.tab + +gsch2pcb-rnd$(EXE): $(OBJS) $(CONF_OBJS) $(HASHOBJ) $(VECTOBJ) $(LISTOBJ) $(QPARSE) $(FP_OBJS) $(LHTOBJ) + $(CC) $(OBJS) $(CONF_OBJS) $(FP_OBJS) $(HASHOBJ) $(VECTOBJ) $(LISTOBJ) $(QPARSE) $(LHTOBJ) -o gsch2pcb-rnd$(EXE) $(LDFLAGS) $(FP_LDFLAGS) + +gsch2pcb.o: gsch2pcb.c ../../config.h + $(CC) -c $(CFLAGS) $(FP_CFLAGS) gsch2pcb.c -o gsch2pcb.o + +# TODO: this should be the base lib only +# run the Makefile in src for the common objects: +$(HASHOBJ) $(QPARSE) $(LHTOBJ) \ +../../src_3rd/genvector/gds_char.o ../../src_3rd/genvector/vtp0.o \ +../../src_3rd/genvector/vts0.o ../../src_3rd/genadlist/genlist.o \ +../../src_3rd/genlist/genlistalloc.o: + cd ../../src && $(MAKE) util_deps + +$(LHTOBJ): $(HASHOBJ) + +##### module rules begin ##### +@/local/pcb/RULES@ +##### module rules end ##### +@] + +# generate explicit rules for .c -> .o +put /local/comp/OBJS /local/pcb/OBJS +include {../scconfig/template/compile.tmpasm} + +print [@ + +gsch2pcb.o: gsch2pcb_rnd_conf_fields.h + +gsch2pcb_rnd_conf_fields.h: gsch2pcb_rnd_conf.h + AWK=@/host/fstools/awk@ ../../scconfig/gen_conf.sh < gsch2pcb_rnd_conf.h > gsch2pcb_rnd_conf_fields.h + +install_all: + $(SCCBOX) mkdir -p "$(BINDIR)" "$(LIBDIR)" + $(SCCBOX) $(HOW) "gsch2pcb-rnd$(EXE)" "$(BINDIR)/gsch2pcb-rnd$(EXE)" + $(SCCBOX) $(HOW) "gnet-gsch2pcb-rnd.scm" "$(LIBDIR)/gnet-gsch2pcb-rnd.scm" + +install: + $(MAKE) install_all HOW="install" + +linstall: + $(MAKE) install_all HOW="linstall -f" + +uninstall: + $(MAKE) install_all HOW="uninstall" + +clean: + $(SCCBOX) rm -f -q gsch2pcb-rnd$(EXE) $(OBJS) gsch2pcb_rnd_conf_fields.h + +distclean: clean + +include $(ROOT)/Makefile.conf + +@] Index: tags/2.1.2/util/gsch2pcb-rnd/glue.c =================================================================== --- tags/2.1.2/util/gsch2pcb-rnd/glue.c (nonexistent) +++ tags/2.1.2/util/gsch2pcb-rnd/glue.c (revision 24813) @@ -0,0 +1,76 @@ +/* gsch2pcb-rnd + * (C) 2015..2016, Tibor 'Igor2' Palinkas + * + * This program is free software which I release under the GNU General Public + * License. You may redistribute and/or modify this program under the terms + * of that 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. Version 2 is in the + * COPYRIGHT file in the top level directory of this distribution. + * + * To get a copy of the GNU General Puplic License, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include +#include +#include +#include "../src/error.h" +#include "../src/event.h" +#include "../src/plugins.h" +#include "../src/hid.h" +#include "gsch2pcb_rnd_conf.h" + +/* glue for pcb-rnd core */ + +pcb_hid_t *pcb_gui = NULL; + +int pcb_color_load_str(pcb_color_t *dst, const char *src) +{ + memset(dst, 0, sizeof(pcb_color_t)); + return 0; +} + +void pcb_message(enum pcb_message_level level, const char *fmt, ...) +{ + va_list args; + fprintf(stderr, "gsch2pcb-rnd: "); + va_start(args, fmt); + vfprintf(stderr, fmt, args); + va_end(args); + fprintf(stderr, "\n"); +} + +void pcb_trace(const char *Format, ...) +{ +#ifndef NDEBUG + va_list args; + va_start(args, Format); + vfprintf(stderr, Format, args); + va_end(args); +#endif +} + +const char *pcb_board_get_filename(void) { return NULL; } +const char *pcb_board_get_name(void) { return NULL; } + +void pcb_event(pcb_event_id_t ev, const char *fmt, ...) +{ + +} + +int pcb_file_loaded_set_at(const char *catname, const char *name, const char *path, const char *desc) +{ + return 0; +} + +int pcb_file_loaded_del_at(const char *catname, const char *name) +{ + return 0; +} + + Index: tags/2.1.2/util/gsch2pcb-rnd/gnet-gsch2pcb-rnd.scm =================================================================== --- tags/2.1.2/util/gsch2pcb-rnd/gnet-gsch2pcb-rnd.scm (nonexistent) +++ tags/2.1.2/util/gsch2pcb-rnd/gnet-gsch2pcb-rnd.scm (revision 24813) @@ -0,0 +1,56 @@ +;;; -*-scheme-*- +;;; + +;;; gEDA - GPL Electronic Design Automation +;;; gnetlist - gEDA Netlist +;;; Copyright (C) 1998-2010 Ales Hvezda +;;; +;;; This program is free software; you can redistribute it and/or modify +;;; it under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 2 of the License, or +;;; (at your option) any later version. +;;; +;;; This program is distributed in the hope that it will be useful, +;;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;; GNU General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with this program; if not, write to the Free Software +;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +;;; MA 02111-1301 USA. + +;; gsch2pcb format (based on PCBboard format by JM Routoure & Stefan Petersen) +;; Bill Wilson billw@wt.net +;; 6/17/2003 + +;; Simplified (thrown out m4 support) specially for Igor2 by vzh + +;; Splits a string with space separated words and returns a list +;; of the words (still as strings). +(define (gsch2pcb-rnd:split-to-list the-string) + (filter! + (lambda (x) (not (string=? "" x))) + (string-split the-string #\space))) + +;; Write the footprint for the package `refdes' to `port'. +(define (gsch2pcb-rnd:write-value-footprint refdes port) + + (let ((value (gnetlist:get-package-attribute refdes "value")) + (footprint (gsch2pcb-rnd:split-to-list + (gnetlist:get-package-attribute refdes "footprint")))) + + (format port "PKG(~A,~A,~A)\n" (string-join footprint " ") refdes value))) + +;; Write the footprints for all the refdes' in `lst'. +(define (gsch2pcb-rnd:write-value-footprints port lst) + (for-each (lambda (x) (gsch2pcb-rnd:write-value-footprint x port)) lst)) + + +(define (gsch2pcb-rnd output-filename) + (begin +;; (set-current-output-port (gnetlist:output-port output-filename)) + (set-current-output-port (open-output-file output-filename)) + + ;; don't use m4 + (gsch2pcb-rnd:write-value-footprints (current-output-port) packages))) Index: tags/2.1.2/util/gsch2pcb-rnd/gsch2pcb.c =================================================================== --- tags/2.1.2/util/gsch2pcb-rnd/gsch2pcb.c (nonexistent) +++ tags/2.1.2/util/gsch2pcb-rnd/gsch2pcb.c (revision 24813) @@ -0,0 +1,482 @@ +/* gsch2pcb-rnd + * + * Original version: Bill Wilson billw@wt.net + * rnd-version: (C) 2015..2016, Tibor 'Igor2' Palinkas + * + * This program is free software which I release under the GNU General Public + * License. You may redistribute and/or modify this program under the terms + * of that 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. Version 2 is in the + * COPYRIGHT file in the top level directory of this distribution. + * + * To get a copy of the GNU General Puplic License, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + * Retrieved from the official git (2015.07.15) + + Behavior different from the original: + - use getenv() instead of g_getenv(): on windows this won't do recursive variable expansion + - use rnd-specific .scm + - use pcb-rnd's conf system + - use pcb_popen() instead of glib's spawn (stderr is always printed to stderr) + */ + +#include "config.h" + +#define LOCAL_PROJECT_FILE "project.lht" + +#include +#include +#include +#include "../src/plug_footprint.h" +#include "../src/conf.h" +#include "../src/conf_core.h" +#include "../src_3rd/qparse/qparse.h" +#include "../config.h" +#include "../src/error.h" +#include "../src/plugins.h" +#include "../src/compat_misc.h" +#include "../src/compat_fs.h" +#include "../src/misc_util.h" +#include "../src/safe_fs.h" +#include "method.h" +#include "help.h" +#include "gsch2pcb_rnd_conf.h" +#include "gsch2pcb.h" +#include "method_import.h" + +static const char *want_method_default = "import"; + +gdl_list_t pcb_element_list; /* initialized to 0 */ +gadl_list_t schematics, extra_gnetlist_arg_list, extra_gnetlist_list; + +int n_deleted, n_added_ef, n_fixed, n_PKG_removed_new, + n_PKG_removed_old, n_preserved, n_changed_value, n_not_found, + n_unknown, n_none, n_empty; + +int bak_done, need_PKG_purge; + +conf_gsch2pcb_rnd_t conf_g2pr; + +method_t *methods = NULL, *current_method; + +void method_register(method_t *method) +{ + method->next = methods; + methods = method; +} + +method_t *method_find(const char *name) +{ + method_t *m; + for(m = methods; m != NULL; m = m->next) + if (strcmp(m->name, name) == 0) + return m; + return NULL; +} + +/* Return a pointer to the suffix if inp ends in that suffix */ +static const char *loc_str_has_suffix(const char *inp, const char *suffix, int suff_len) +{ + int len = strlen(inp); + if ((len >= suff_len) && (strcmp(inp + len - suff_len, suffix) == 0)) + return inp + len - suff_len; + return NULL; +} + +char *fix_spaces(char * str) +{ + char *s; + + if (!str) + return NULL; + for (s = str; *s; ++s) + if (*s == ' ' || *s == '\t') + *s = '_'; + return str; +} + +static void add_schematic(const char *sch) +{ + char **n; + n = gadl_new(&schematics); + *n = pcb_strdup(sch); + gadl_append(&schematics, n); + if (!conf_g2pr.utils.gsch2pcb_rnd.sch_basename) { + const char *suff = loc_str_has_suffix(sch, ".sch", 4); + if (suff != NULL) { + char *tmp = pcb_strndup(sch, suff - sch); + conf_set(CFR_CLI, "utils/gsch2pcb_rnd/sch_basename", -1, tmp, POL_OVERWRITE); + free(tmp); + } + } +} + +static void add_multiple_schematics(const char * sch) +{ + /* parse the string using shell semantics */ + int count; + char **args; + char *tmp = pcb_strdup(sch); + + count = qparse(tmp, &args); + free(tmp); + if (count > 0) { + int i; + for (i = 0; i < count; ++i) + if (*args[i] != '\0') + add_schematic(args[i]); + qparse_free(count, &args); + } + else { + fprintf(stderr, "invalid `schematics' option: %s\n", sch); + } +} + +static int parse_config(char * config, char * arg) +{ + char *s; + + /* remove trailing white space otherwise strange things can happen */ + if ((arg != NULL) && (strlen(arg) >= 1)) { + s = arg + strlen(arg) - 1; + while ((*s == ' ' || *s == '\t') && (s != arg)) + s--; + s++; + *s = '\0'; + } + if (conf_g2pr.utils.gsch2pcb_rnd.verbose) + printf(" %s \"%s\"\n", config, arg ? arg : ""); + + if (!strcmp(config, "remove-unfound") || !strcmp(config, "r")) { + /* This is default behavior set in header section */ + conf_set(CFR_CLI, "utils/gsch2pcb_rnd/remove_unfound_elements", -1, "1", POL_OVERWRITE); + return 0; + } + if (!strcmp(config, "keep-unfound") || !strcmp(config, "k")) { + conf_set(CFR_CLI, "utils/gsch2pcb_rnd/remove_unfound_elements", -1, "0", POL_OVERWRITE); + return 0; + } + if (!strcmp(config, "quiet") || !strcmp(config, "q")) { + conf_set(CFR_CLI, "utils/gsch2pcb_rnd/quiet_mode", -1, "1", POL_OVERWRITE); + return 0; + } + if (!strcmp(config, "preserve") || !strcmp(config, "p")) { + conf_set(CFR_CLI, "utils/gsch2pcb_rnd/preserve", -1, "1", POL_OVERWRITE); + return 0; + } + if (!strcmp(config, "elements-shell") || !strcmp(config, "s")) + conf_set(CFR_CLI, "rc/library_shell", -1, arg, POL_OVERWRITE); + else if (!strcmp(config, "elements-dir") || !strcmp(config, "d")) { + static int warned = 0; + if (!warned) { + pcb_message(PCB_MSG_WARNING, "WARNING: using elements-dir from %s - this overrides the normal pcb-rnd configured library search paths\n", config); + warned = 1; + } + conf_set(CFR_CLI, "rc/library_search_paths", -1, arg, POL_PREPEND); + } + else if (!strcmp(config, "output-name") || !strcmp(config, "o")) + conf_set(CFR_CLI, "utils/gsch2pcb_rnd/sch_basename", -1, arg, POL_OVERWRITE); + else if (!strcmp(config, "default-pcb") || !strcmp(config, "P")) + conf_set(CFR_CLI, "utils/gsch2pcb_rnd/default_pcb", -1, arg, POL_OVERWRITE); + else if (!strcmp(config, "schematics")) + add_multiple_schematics(arg); + else if (!strcmp(config, "gnetlist")) { + char **n; + n = gadl_new(&extra_gnetlist_list); + *n = pcb_strdup(arg); + gadl_append(&extra_gnetlist_list, n); + } + else if (!strcmp(config, "empty-footprint")) + conf_set(CFR_CLI, "utils/gsch2pcb_rnd/empty_footprint_name", -1, arg, POL_OVERWRITE); + else + return -1; + + return 1; +} + +static void load_project(char * path) +{ + FILE *f; + char *s, buf[1024], config[32], arg[768]; + int n; + + f = pcb_fopen(path, "r"); + if (!f) + return; + + /* check if we have a lihata project file or config file by looking at the first 16 non-comments */ + for(n = 0; n < 16;) { + if (fgets(buf, sizeof(buf), f) == NULL) + break; + s = buf; + while(isspace(*s)) s++; + if ((*s == '#') || (*s == '\r') || (*s == '\n') || (*s == '\0')) + continue; + /* look for known lihata roots */ + if (strncmp(s, "ha:geda-project-v1", 18) == 0) + goto lihata_prj; + if (strncmp(s, "li:pcb-rnd-conf-v1", 18) == 0) + goto lihata_prj; + n++; + } + + rewind(f); + + if (conf_g2pr.utils.gsch2pcb_rnd.verbose) + printf("Reading project file: %s\n", path); + while (fgets(buf, sizeof(buf), f)) { + for (s = buf; *s == ' ' || *s == '\t' || *s == '\n'; ++s); + if (!*s || *s == '#' || *s == '/' || *s == ';') + continue; + arg[0] = '\0'; + sscanf(s, "%31s %767[^\n]", config, arg); + parse_config(config, arg); + } + fclose(f); + return; + +lihata_prj:; + fclose(f); + if (conf_load_as(CFR_PROJECT, path, 0) != 0) { + pcb_message(PCB_MSG_ERROR, "Failed to parse project file %s.\n", path); + exit(1); + } + conf_update(NULL, -1); /* because of our new project file */ +} + +static void load_extra_project_files(void) +{ + char *path; + static int done = FALSE; + + if (done) + return; + + load_project("/etc/gsch2pcb"); + load_project("/usr/local/etc/gsch2pcb"); + + path = pcb_concat(conf_core.rc.path.home, PCB_DIR_SEPARATOR_S, ".gEDA", PCB_DIR_SEPARATOR_S, "gsch2pcb", NULL); + load_project(path); + free(path); + + done = TRUE; +} + +int have_cli_project_file = 0; +int have_cli_schematics = 0; +static void get_args(int argc, char ** argv) +{ + char *opt, *arg; + int i, r; + + for (i = 1; i < argc; ++i) { + opt = argv[i]; + arg = argv[i + 1]; + if (*opt == '-') { + ++opt; + if (*opt == '-') + ++opt; + if (!strcmp(opt, "version") || !strcmp(opt, "V")) { + printf("gsch2pcb-rnd %s\n", GSCH2PCB_RND_VERSION); + exit(0); + } + else if (!strcmp(opt, "verbose") || !strcmp(opt, "v")) { + char tmp[64]; + sprintf(tmp, "%ld", conf_g2pr.utils.gsch2pcb_rnd.verbose + 1); + conf_set(CFR_CLI, "utils/gsch2pcb_rnd/verbose", -1, tmp, POL_OVERWRITE); + continue; + } + else if (!strcmp(opt, "m") || !strcmp(opt, "method")) { + if (method_find(arg) == NULL) { + pcb_message(PCB_MSG_ERROR, "Error: can't use unknown method '%s'; try --help\n", arg); + exit(1); + } + conf_set(CFR_CLI, "utils/gsch2pcb_rnd/method", -1, arg, POL_OVERWRITE); + i++; + continue; + } + else if (!strcmp(opt, "c") || !strcmp(opt, "conf")) { + const char *stmp; + if (conf_set_from_cli(NULL, arg, NULL, &stmp) != 0) { + fprintf(stderr, "Error: failed to set config %s: %s\n", arg, stmp); + exit(1); + } + i++; + continue; + } + else if (!strcmp(opt, "fix-elements")) { + conf_set(CFR_CLI, "utils/gsch2pcb_rnd/fix_elements", -1, "1", POL_OVERWRITE); + continue; + } + else if (!strcmp(opt, "gnetlist-arg")) { + char **n; + n = gadl_new(&extra_gnetlist_arg_list); + *n = pcb_strdup(arg); + gadl_append(&extra_gnetlist_arg_list, n); + i++; + continue; + } + else if (!strcmp(opt, "help") || !strcmp(opt, "h")) + usage(); + else if (i < argc && ((r = parse_config(opt, (i < argc - 1) ? arg : NULL)) + >= 0) + ) { + i += r; + continue; + } + printf("gsch2pcb: bad or incomplete arg: %s\n", argv[i]); + usage(); + } + else { + if (loc_str_has_suffix(argv[i], ".sch", 4) == NULL) { + if (have_cli_project_file) { + pcb_message(PCB_MSG_ERROR, "ERROR: multiple project files specified on the command line (last one: %s). Either use multiple schematics or a single project file. Try %s --help\n", argv[i], argv[0]); + exit(1); + } + load_extra_project_files(); + load_project(argv[i]); + have_cli_project_file = 1; + } + else { + add_schematic(argv[i]); + have_cli_schematics = 1; + } + } + } +} + +void free_strlist(gadl_list_t *lst) +{ + char **s; + + while((s = gadl_first(lst)) != NULL) { + char *str = *s; + gadl_free(s); + free(str); + } +} + +void require_gnetlist_backend(const char *dir, const char *backend) +{ + char *path = pcb_strdup_printf("%s/gnet-%s.scm", dir, backend); + if (!pcb_file_readable(path)) + pcb_message(PCB_MSG_WARNING, "WARNING: %s is not found, gnetlist will probably fail; please check your pcb-rnd installation!\n", path); + free(path); +} + + +const char *local_project_pcb_name = NULL; + +/************************ main ***********************/ +int main(int argc, char ** argv) +{ + const char *want_method; + + method_import_register(); + + conf_init(); + conf_core_init(); + conf_core_postproc(); /* to get all the paths initialized */ + + gadl_list_init(&schematics, sizeof(char *), NULL, NULL); + gadl_list_init(&extra_gnetlist_arg_list, sizeof(char *), NULL, NULL); + gadl_list_init(&extra_gnetlist_list, sizeof(char *), NULL, NULL); + +#define conf_reg(field,isarray,type_name,cpath,cname,desc,flags) \ + conf_reg_field(conf_g2pr, field,isarray,type_name,cpath,cname,desc,flags); +#include "gsch2pcb_rnd_conf_fields.h" + + get_args(argc, argv); + + conf_load_all(NULL, NULL); + conf_update(NULL, -1); + + load_extra_project_files(); + conf_update(NULL, -1); /* because of CLI changes */ + + if (!have_cli_project_file && !have_cli_schematics) { + if (!pcb_file_readable(LOCAL_PROJECT_FILE)) { + pcb_message(PCB_MSG_ERROR, "Don't know what to do: no project or schematics given, no local project file %s found. Try %s --help\n", LOCAL_PROJECT_FILE, argv[0]); + exit(1); + } + if (conf_load_as(CFR_PROJECT, LOCAL_PROJECT_FILE, 0) != 0) { + pcb_message(PCB_MSG_ERROR, "Failed to load project file %s. Try %s --help\n", LOCAL_PROJECT_FILE, argv[0]); + exit(1); + } + conf_update(NULL, -1); /* because of our new project file */ + } + else if ((local_project_pcb_name != NULL) && (!have_cli_project_file)) + conf_load_project(NULL, local_project_pcb_name); + + if (!have_cli_schematics) { /* load all schematics from the project file unless we have schematics from the cli */ + conf_native_t *nat = conf_get_field("utils/gsch2pcb_rnd/schematics"); + if (nat != NULL) { + conf_listitem_t *ci; + for (ci = conflist_first(nat->val.list); ci != NULL; ci = conflist_next(ci)) { + const char *p = ci->val.string[0]; + if (ci->type != CFN_STRING) + continue; + add_schematic(p); + } + } + else { + pcb_message(PCB_MSG_ERROR, "No schematics specified on the cli or in project files. Try %s --help\n", argv[0]); + exit(1); + } + } + + if (gadl_length(&schematics) == 0) { + pcb_message(PCB_MSG_ERROR, "No schematics specified on the cli; can't find any in the project files/configs either. Try %s --help\n", argv[0]); + exit(1); + } + + conf_update(NULL, -1); /* because of the project file */ + + want_method = conf_g2pr.utils.gsch2pcb_rnd.method; + if (want_method == NULL) { + method_t *m; + for(m = methods; m != NULL; m = m->next) { + if (m->not_by_guess) + continue; + if (m->guess_out_name()) { + current_method = m; + break; + } + } + if (current_method == NULL) { + want_method = want_method_default; + if (!conf_g2pr.utils.gsch2pcb_rnd.quiet_mode) + pcb_message(PCB_MSG_WARNING, "Warning: method not specified for a project (that has no board or project file yet); defaulting to -m %s. This warning is harmless if you are running gsch2pcb-rnd for the first time on this project and you are fine with this method.", want_method); + } + } + + if (current_method == NULL) { + current_method = method_find(want_method); + if (current_method == NULL) { + pcb_message(PCB_MSG_ERROR, "Error: can't find method %s\n", want_method); + exit(1); + } + } + + current_method->init(); + conf_update(NULL, -1); + + + current_method->go(); /* the traditional, "parse element and edit the pcb file" approach */ + + current_method->uninit(); + + conf_uninit(); + + free_strlist(&schematics); + free_strlist(&extra_gnetlist_arg_list); + free_strlist(&extra_gnetlist_list); + + return 0; +} Index: tags/2.1.2/util/gsch2pcb-rnd/gsch2pcb.h =================================================================== --- tags/2.1.2/util/gsch2pcb-rnd/gsch2pcb.h (nonexistent) +++ tags/2.1.2/util/gsch2pcb-rnd/gsch2pcb.h (revision 24813) @@ -0,0 +1,47 @@ +#include "../src_3rd/genlist/gendlist.h" +#include "../src_3rd/genlist/genadlist.h" + +#define TRUE 1 +#define FALSE 0 + +#define GSCH2PCB_RND_VERSION "2.0.0" + +#define DEFAULT_PCB_INC "pcb.inc" + +#define SEP_STRING "--------\n" + +typedef struct { + char *refdes, *value, *description, *changed_description, *changed_value; + char *flags, *tail; + char *x, *y; + char *pkg_name_fix; + char res_char; + + gdl_elem_t all_elems; + + unsigned still_exists:1; + unsigned new_format:1; + unsigned hi_res_format:1; + unsigned quoted_flags:1; + unsigned omit_PKG:1; + unsigned nonetlist:1; +} PcbElement; + +typedef struct { + char *part_number, *element_name; +} ElementMap; + +extern gdl_list_t pcb_element_list; +extern gadl_list_t schematics, extra_gnetlist_arg_list, extra_gnetlist_list; + +extern int n_deleted, n_added_ef, n_fixed, n_PKG_removed_new, + n_PKG_removed_old, n_preserved, n_changed_value, n_not_found, + n_unknown, n_none, n_empty; + +extern int bak_done, need_PKG_purge; + +const char *local_project_pcb_name; /* file name of the design from which the local project file name shall be derived */ + +char *fix_spaces(char * str); +void require_gnetlist_backend(const char *dir, const char *backend); + Index: tags/2.1.2/util/gsch2pcb-rnd/gsch2pcb_rnd_conf.h =================================================================== --- tags/2.1.2/util/gsch2pcb-rnd/gsch2pcb_rnd_conf.h (nonexistent) +++ tags/2.1.2/util/gsch2pcb-rnd/gsch2pcb_rnd_conf.h (revision 24813) @@ -0,0 +1,24 @@ +#ifndef PCB_MINCUT_CONF_H +#define PCB_MINCUT_CONF_H + +#include "../src/conf.h" + +typedef struct { + const struct utils { + const struct gsch2pcb_rnd { + CFT_BOOLEAN remove_unfound_elements; /* = TRUE */ + CFT_BOOLEAN quiet_mode; /* = FALSE */ + CFT_INTEGER verbose; + CFT_BOOLEAN preserve; + CFT_BOOLEAN fix_elements; + CFT_STRING sch_basename; + CFT_STRING default_pcb; /* override default pcb with a given file */ + CFT_STRING empty_footprint_name; + CFT_STRING method; + CFT_LIST schematics; /* use these schematics as input */ + } gsch2pcb_rnd; + } utils; +} conf_gsch2pcb_rnd_t; + +extern conf_gsch2pcb_rnd_t conf_g2pr; +#endif Index: tags/2.1.2/util/gsch2pcb-rnd/gsch2pcb_scm/Makefile =================================================================== --- tags/2.1.2/util/gsch2pcb-rnd/gsch2pcb_scm/Makefile (nonexistent) +++ tags/2.1.2/util/gsch2pcb-rnd/gsch2pcb_scm/Makefile (revision 24813) @@ -0,0 +1,17 @@ +names = c1 c2 c3 +schematics = $(names:%=%.sch) +netlists = $(names:%=%.net) +goldens = $(names:%=golden/%.net) +diffs = $(names:%=%.diff) + +.PHONY: all clean $(netlists) +all: $(diffs) + +$(diffs): %.diff: %.net golden/%.net + diff $^ > $@ + +$(netlists): %.net: %.sch + gnetlist -g gsch2pcb-rnd -o $@ -m ../gnet-gsch2pcb-rnd.scm $< + +clean: + -rm -rf $(diffs) $(netlists) Index: tags/2.1.2/util/gsch2pcb-rnd/gsch2pcb_scm/c1.sch =================================================================== --- tags/2.1.2/util/gsch2pcb-rnd/gsch2pcb_scm/c1.sch (nonexistent) +++ tags/2.1.2/util/gsch2pcb-rnd/gsch2pcb_scm/c1.sch (revision 24813) @@ -0,0 +1,13 @@ +v 20130925 2 +C 18400 56000 1 0 0 connector3-2.sym +{ +T 19100 57700 5 10 1 1 0 6 1 +refdes=CONN1 +T 18700 57650 5 10 0 0 0 0 1 +device=CONNECTOR_3 +T 18700 57850 5 10 0 0 0 0 1 +footprint=CONNECTOR 3 1 +} +N 18400 57200 17800 57200 4 +N 17800 56400 17800 57200 4 +N 17800 56400 18400 56400 4 Index: tags/2.1.2/util/gsch2pcb-rnd/gsch2pcb_scm/c2.sch =================================================================== --- tags/2.1.2/util/gsch2pcb-rnd/gsch2pcb_scm/c2.sch (nonexistent) +++ tags/2.1.2/util/gsch2pcb-rnd/gsch2pcb_scm/c2.sch (revision 24813) @@ -0,0 +1,15 @@ +v 20130925 2 +C 18400 56000 1 0 0 connector3-2.sym +{ +T 19100 57700 5 10 1 1 0 6 1 +refdes=CONN1 +T 18700 57650 5 10 0 0 0 0 1 +device=CONNECTOR_3 +T 18700 57850 5 10 0 0 0 0 1 +footprint=CONNECTOR 3 1 +T 19300 56200 5 10 1 0 90 0 1 +value=val123 +} +N 18400 57200 17800 57200 4 +N 17800 56400 17800 57200 4 +N 17800 56400 18400 56400 4 Index: tags/2.1.2/util/gsch2pcb-rnd/gsch2pcb_scm/c3.sch =================================================================== --- tags/2.1.2/util/gsch2pcb-rnd/gsch2pcb_scm/c3.sch (nonexistent) +++ tags/2.1.2/util/gsch2pcb-rnd/gsch2pcb_scm/c3.sch (revision 24813) @@ -0,0 +1,15 @@ +v 20130925 2 +C 18400 56000 1 0 0 connector3-2.sym +{ +T 19100 57700 5 10 1 1 0 6 1 +refdes=CONN1 +T 18700 57650 5 10 0 0 0 0 1 +device=CONNECTOR_3 +T 18700 57850 5 10 0 0 0 0 1 +footprint=CONNECTOR(3, 1, silkmark=external) +T 19300 56200 5 10 1 0 90 0 1 +value=val123 +} +N 18400 57200 17800 57200 4 +N 17800 56400 17800 57200 4 +N 17800 56400 18400 56400 4 Index: tags/2.1.2/util/gsch2pcb-rnd/gsch2pcb_scm/golden/c1.net =================================================================== --- tags/2.1.2/util/gsch2pcb-rnd/gsch2pcb_scm/golden/c1.net (nonexistent) +++ tags/2.1.2/util/gsch2pcb-rnd/gsch2pcb_scm/golden/c1.net (revision 24813) @@ -0,0 +1 @@ +PKG(CONNECTOR 3 1,CONN1,unknown) Index: tags/2.1.2/util/gsch2pcb-rnd/gsch2pcb_scm/golden/c2.net =================================================================== --- tags/2.1.2/util/gsch2pcb-rnd/gsch2pcb_scm/golden/c2.net (nonexistent) +++ tags/2.1.2/util/gsch2pcb-rnd/gsch2pcb_scm/golden/c2.net (revision 24813) @@ -0,0 +1 @@ +PKG(CONNECTOR 3 1,CONN1,val123) Index: tags/2.1.2/util/gsch2pcb-rnd/gsch2pcb_scm/golden/c3.net =================================================================== --- tags/2.1.2/util/gsch2pcb-rnd/gsch2pcb_scm/golden/c3.net (nonexistent) +++ tags/2.1.2/util/gsch2pcb-rnd/gsch2pcb_scm/golden/c3.net (revision 24813) @@ -0,0 +1 @@ +PKG(CONNECTOR(3, 1, silkmark=external),CONN1,val123) Index: tags/2.1.2/util/gsch2pcb-rnd/help.c =================================================================== --- tags/2.1.2/util/gsch2pcb-rnd/help.c (nonexistent) +++ tags/2.1.2/util/gsch2pcb-rnd/help.c (revision 24813) @@ -0,0 +1,156 @@ +/* gsch2pcb-rnd + * + * Original version: Bill Wilson billw@wt.net + * rnd-version: (C) 2015..2016, Tibor 'Igor2' Palinkas + * + * This program is free software which I release under the GNU General Public + * License. You may redistribute and/or modify this program under the terms + * of that 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. Version 2 is in the + * COPYRIGHT file in the top level directory of this distribution. + * + * To get a copy of the GNU General Puplic License, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + * Retrieved from the official git (2015.07.15) + + Behavior different from the original: + - use getenv() instead of g_getenv(): on windows this won't do recursive variable expansion + - use rnd-specific .scm + - use pcb_popen() instead of glib's spawn (stderr is always printed to stderr) + */ +#include "config.h" +#include "method.h" +#include +#include + + +extern char *pcb_file_name, *pcb_new_file_name, *bak_file_name, *pins_file_name, *net_file_name; + +static char *usage_string0a = + "usage: gsch2pcb [options] {project | foo.sch [foo1.sch ...]}\n" + "\n" + "Generate a PCB annotation file from a set of gschem schematics.\n" + " gnetlist -g PCB is run to generate foo.net from the schematics.\n" "\n"; +/* TODO */ +/* " gnetlist -g gsch2pcb is run to get PCB elements which\n" + " match schematic footprints. For schematic footprints which don't match\n" + " any PCB layout elements, search a set of file element directories in\n" + " an attempt to find matching PCB file elements.\n"*/ +static char *usage_string0b = + " Output to foo.cmd if it doesn't exist.\n" + " The annotation command file (to be run by the user from pcb-rnd) contains:.\n" + " If any elements with a non-empty element name on the board\n" + " have no matching schematic component, then remove those elements from\n" + " the board unless it's marked nonetlist. Load and palce the footprints\n" + " for new elements; replace elements in-place if their footprint changed;" + " update attributes, value and other metadata in-place." + "\n"; +static char *usage_string0c = + " gnetlist -g pcbpins is run to get a PCB actions file which will rename all\n" + " of the pins in a .pcb file to match pin names from the schematic.\n" + "\n" + " \"project\" is a file (not ending in .sch) containing a list of\n" + " schematics to process and some options. A schematics line is like:\n" + " schematics foo1.sch foo2.sch ...\n" + " Options in a project file are like command line args without the \"-\":\n" + " output-name myproject\n" + "\n" + "options (may be included in a project file):\n"; +static char *usage_string0d = + " -d, --elements-dir D Search D for PCB file elements. These defaults\n" + " are searched if they exist. See the default\n" + " search paths at the end of this text." + " -c, --elements-dir-clr Clear the elements dir. Useful before a series\n" + " if -d's to flush defaults.\n" + " -m, --method M Use method M for the import. See available\n" + " methods below.\n"; +static char *usage_string0e = + " -s, --elements-shell S Use S as a prefix for running parametric footrint\n" + " generators. It is useful on systems where popen()\n" + " doesn't do the right thing or the process should\n" + " be wrapped. Example -s \"/bin/sh -c\"\n" + " -P, --default-pcb Change the default PCB file's name; this file is\n" + " inserted on top of the *.new.pcb generated, for\n" + " PCB default settings\n"; +static char *usage_string0f = + " -o, --output-name N Use output file names N.net, N.pcb, and N.new.pcb\n" + " instead of foo.net, ... where foo is the basename\n" + " of the first command line .sch file.\n" + " -r, --remove-unfound Don't include references to unfound elements in\n" + " the generated .pcb files. Use if you want PCB to\n" + " be able to load the (incomplete) .pcb file.\n" + " This is the default behavior.\n"; +static char *usage_string0g = + " -k, --keep-unfound Keep include references to unfound elements in\n" + " the generated .pcb files. Use if you want to hand\n" + " edit or otherwise preprocess the generated .pcb file\n" + " before running pcb.\n"; +static char *usage_string0h = + " -p, --preserve Preserve elements in PCB files which are not found\n" + " in the schematics. Note that elements with an empty\n" + " element name (schematic refdes) are never deleted,\n" + " so you really shouldn't need this option.\n"; +static char *usage_string0i = + " -q, --quiet Don't tell the user what to do next after running\n" + " gsch2pcb-rnd.\n" "\n"; + +static char *usage_string1a = + " --gnetlist backend A convenience run of extra gnetlist -g commands.\n" + " Example: gnetlist partslist3\n" + " Creates: myproject.partslist3\n" + " --empty-footprint name See the project.sample file.\n" + "\n"; +static char *usage_string1b = + "options (not recognized in a project file):\n" + " --gnetlist-arg arg Allows additional arguments to be passed to gnetlist.\n" + " --fix-elements If a schematic component footprint is not equal\n" + " to its PCB element Description, update the\n" + " Description instead of replacing the element.\n" + " Do this the first time gsch2pcb is used with\n" + " PCB files originally created with gschem2pcb.\n"; +static char *usage_string1c = + " -v, --verbose Use -v -v for additional file element debugging.\n" + " -V, --version\n\n" + "environment variables:\n" + " GNETLIST If set, this specifies the name of the gnetlist program\n" + " to execute.\n" + "\n"; + +static char *usage_string_foot = + "Additional Resources:\n" + "\n" + " pcb-rnd homepage: http://repo.hu/projects/pcb-rnd\n" + " gnetlist user guide: http://wiki.geda-project.org/geda:gnetlist_ug\n" + " gEDA homepage: http://www.geda-project.org\n" + "\n"; + + +void usage(void) +{ + method_t *m; + printf("%s", usage_string0a); + printf("%s", usage_string0b); + printf("%s", usage_string0c); + printf("%s", usage_string0d); + printf("%s", usage_string0e); + printf("%s", usage_string0f); + printf("%s", usage_string0g); + printf("%s", usage_string0h); + printf("%s", usage_string0i); + printf("%s", usage_string1a); + printf("%s", usage_string1b); + printf("%s", usage_string1c); + + printf("\nMethods available:\n"); + for(m = methods; m != NULL; m = m->next) + printf(" %-12s %s\n", m->name, m->desc); + printf("\n"); + printf("%s", usage_string_foot); + exit(0); +} Index: tags/2.1.2/util/gsch2pcb-rnd/help.h =================================================================== --- tags/2.1.2/util/gsch2pcb-rnd/help.h (nonexistent) +++ tags/2.1.2/util/gsch2pcb-rnd/help.h (revision 24813) @@ -0,0 +1 @@ +void usage(void); Index: tags/2.1.2/util/gsch2pcb-rnd/method.h =================================================================== --- tags/2.1.2/util/gsch2pcb-rnd/method.h (nonexistent) +++ tags/2.1.2/util/gsch2pcb-rnd/method.h (revision 24813) @@ -0,0 +1,16 @@ +typedef struct method_s method_t; + +struct method_s { + const char *name; + const char *desc; + void (*init)(void); + void (*go)(void); + void (*uninit)(void); + int (*guess_out_name)(void); /* returns 1 if the output file of the format exists for the current project */ + int not_by_guess; /* if non-zero, never try to use this method automatically, guessing from file names or anything else */ + method_t *next; +}; + +extern method_t *methods; + +void method_register(method_t *fmt); Index: tags/2.1.2/util/gsch2pcb-rnd/method_import.c =================================================================== --- tags/2.1.2/util/gsch2pcb-rnd/method_import.c (nonexistent) +++ tags/2.1.2/util/gsch2pcb-rnd/method_import.c (revision 24813) @@ -0,0 +1,148 @@ +/* gsch2pcb-rnd + * + * Original version: Bill Wilson billw@wt.net + * rnd-version: (C) 2015..2016, Tibor 'Igor2' Palinkas + * + * This program is free software which I release under the GNU General Public + * License. You may redistribute and/or modify this program under the terms + * of that 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. Version 2 is in the + * COPYRIGHT file in the top level directory of this distribution. + * + * To get a copy of the GNU General Puplic License, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include +#include +#include +#include "gsch2pcb.h" +#include "gsch2pcb_rnd_conf.h" +#include "method_import.h" +#include "run.h" +#include "netlister.h" +#include "method.h" +#include "../src/conf.h" +#include "../src/conf_core.h" +#include "../src/compat_misc.h" +#include "../src/compat_fs.h" +#include "../src/misc_util.h" + +char *cmd_file_name; +char *pcb_file_name; +char *net_file_name; + +static void method_import_init(void) +{ + pcb_file_name = pcb_concat(conf_g2pr.utils.gsch2pcb_rnd.sch_basename, ".pcb", NULL); + cmd_file_name = pcb_concat(conf_g2pr.utils.gsch2pcb_rnd.sch_basename, ".cmd", NULL); + net_file_name = pcb_concat(conf_g2pr.utils.gsch2pcb_rnd.sch_basename, ".net", NULL); + local_project_pcb_name = pcb_file_name; +} + +static void import_go(int sep_net) +{ + char *verbose_str = NULL; + const char *gnetlist, *backend; + + gnetlist = gnetlist_name(); + if (!conf_g2pr.utils.gsch2pcb_rnd.verbose) + verbose_str = "-q"; + + backend = sep_net ? "pcbrndfwd_elem" : "pcbrndfwd"; + require_gnetlist_backend(SCMDIR, backend); + if (!build_and_run_command("%s %s -L %s -g %s -o %s %L %L", gnetlist, verbose_str, PCBLIBDIR, backend, cmd_file_name, &extra_gnetlist_arg_list, &schematics)) { + fprintf(stderr, "Failed to run gnetlist with backend %s to generate the elements\n", backend); + exit(1); + } + + if (sep_net) { + if (!build_and_run_command("%s %s -L %s -g PCB -o %s %L %L", gnetlist, verbose_str, PCBLIBDIR, net_file_name, &extra_gnetlist_arg_list, &schematics)) { + fprintf(stderr, "Failed to run gnetlist net file\n"); + exit(1); + } + } + + if (conf_g2pr.utils.gsch2pcb_rnd.quiet_mode) + return; + + /* Tell user what to do next */ + printf("\nNext step:\n"); + printf("1. Run pcb-rnd on your board file (or on an empty board if it's the first time).\n"); + printf("2. From within pcb-rnd, enter\n\n"); + printf(" :ExecuteFile(%s)\n\n", cmd_file_name); + + if (sep_net) { + printf(" (this will update the elements)\n\n"); + printf("3. From within pcb-rnd, select \"File -> Load netlist file\" and select \n"); + printf(" %s to load the updated netlist.\n\n", net_file_name); + } + else + printf(" (this will update the elements and the netlist)\n\n"); +} + +static void method_import_go() +{ + import_go(0); +} + +static void method_import_sep_go() +{ + import_go(1); +} + + +static int method_import_guess_out_name(void) +{ + int res; + char *name; + + name = pcb_concat(conf_g2pr.utils.gsch2pcb_rnd.sch_basename, ".lht", NULL); + res = pcb_file_readable(name); + free(name); + if (!res) { + name = pcb_concat(conf_g2pr.utils.gsch2pcb_rnd.sch_basename, ".pcb.lht", NULL); + res = pcb_file_readable(name); + free(name); + } + return res; +} + +static void method_import_uninit(void) +{ + if (pcb_file_name != NULL) + free(pcb_file_name); + if (cmd_file_name != NULL) + free(cmd_file_name); + if (net_file_name != NULL) + free(net_file_name); +} + +static method_t method_import; +static method_t method_import_sep; + +void method_import_register(void) +{ + method_import.name = "import"; + method_import.desc = "import schematics (pure action script)"; + method_import.init = method_import_init; + method_import.go = method_import_go; + method_import.uninit = method_import_uninit; + method_import.guess_out_name = method_import_guess_out_name; + method_import.not_by_guess = 0; + method_register(&method_import); + + method_import_sep.name = "importsep"; + method_import_sep.desc = "import schematics (separate action script and netlist)"; + method_import_sep.init = method_import_init; + method_import_sep.go = method_import_sep_go; + method_import_sep.uninit = method_import_uninit; + method_import_sep.guess_out_name = method_import_guess_out_name; + method_import_sep.not_by_guess = 1; + method_register(&method_import_sep); +} Index: tags/2.1.2/util/gsch2pcb-rnd/method_import.h =================================================================== --- tags/2.1.2/util/gsch2pcb-rnd/method_import.h (nonexistent) +++ tags/2.1.2/util/gsch2pcb-rnd/method_import.h (revision 24813) @@ -0,0 +1 @@ +void method_import_register(void); Index: tags/2.1.2/util/gsch2pcb-rnd/netlister.c =================================================================== --- tags/2.1.2/util/gsch2pcb-rnd/netlister.c (nonexistent) +++ tags/2.1.2/util/gsch2pcb-rnd/netlister.c (revision 24813) @@ -0,0 +1,111 @@ +/* gsch2pcb-rnd + * + * Original version: Bill Wilson billw@wt.net + * rnd-version: (C) 2015..2016, Tibor 'Igor2' Palinkas + * + * This program is free software which I release under the GNU General Public + * License. You may redistribute and/or modify this program under the terms + * of that 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. Version 2 is in the + * COPYRIGHT file in the top level directory of this distribution. + * + * To get a copy of the GNU General Puplic License, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "config.h" + +#include +#include +#include +#include +/*#include */ +#include +#include +#include +#include "../src/plug_footprint.h" +#include "../src/paths.h" +#include "../src/conf.h" +#include "../src/conf_core.h" +#include "../config.h" +#include "../src/compat_misc.h" +#include "gsch2pcb_rnd_conf.h" +#include "gsch2pcb.h" +#include "../src/misc_util.h" +#include "run.h" + +const char *gnetlist_name(void) +{ + const char *gnetlist; + /* Allow the user to specify a full path or a different name for + * the gnetlist command. Especially useful if multiple copies + * are installed at once. + */ + gnetlist = getenv("GNETLIST"); + if (gnetlist == NULL) + gnetlist = "gnetlist"; + return gnetlist; +} + +int run_gnetlist(const char *pins_file, const char *net_file, const char *pcb_file, const char * basename, const gadl_list_t *largs) +{ + struct stat st; + time_t mtime; + const char *gnetlist; + gadl_iterator_t it; + char **sp; + char *verbose_str = NULL; + + gnetlist = gnetlist_name(); + + if (!conf_g2pr.utils.gsch2pcb_rnd.verbose) + verbose_str = "-q"; + + + if (!build_and_run_command("%s %s -g pcbpins -o %s %L %L", gnetlist, verbose_str, pins_file, &extra_gnetlist_arg_list, largs)) + return FALSE; + + if (!build_and_run_command("%s %s -g PCB -o %s %L %L", gnetlist, verbose_str, net_file, &extra_gnetlist_arg_list, largs)) + return FALSE; + + mtime = (stat(pcb_file, &st) == 0) ? st.st_mtime : 0; + + require_gnetlist_backend(SCMDIR, "gsch2pcb-rnd"); + + if (!build_and_run_command("%s %s -L " SCMDIR " -g gsch2pcb-rnd -o %s %L %L", + gnetlist, verbose_str, pcb_file, &extra_gnetlist_arg_list, largs)) { + if (stat(pcb_file, &st) != 0 || mtime == st.st_mtime) { + fprintf(stderr, "gsch2pcb: gnetlist command failed, `%s' not updated\n", pcb_file); + return FALSE; + } + return FALSE; + } + + gadl_foreach(&extra_gnetlist_list, &it, sp) { + const char *s = *sp; + const char *s2 = strstr(s, " -o "); + char *out_file; + char *backend; + if (!s2) { + out_file = pcb_concat(basename, ".", s, NULL); + backend = pcb_strdup(s); + } + else { + out_file = pcb_strdup(s2 + 4); + backend = pcb_strndup(s, s2 - s); + } + + if (!build_and_run_command("%s %s -g %s -o %s %L %L", + gnetlist, verbose_str, backend, out_file, &extra_gnetlist_arg_list, largs)) + return FALSE; + free(out_file); + free(backend); + } + + return TRUE; +} Index: tags/2.1.2/util/gsch2pcb-rnd/netlister.h =================================================================== --- tags/2.1.2/util/gsch2pcb-rnd/netlister.h (nonexistent) +++ tags/2.1.2/util/gsch2pcb-rnd/netlister.h (revision 24813) @@ -0,0 +1,11 @@ +/* Run gnetlist to generate a netlist and a PCB board file. gnetlist + * has exit status of 0 even if it's given an invalid arg, so do some + * stat() hoops to decide if gnetlist successfully generated the PCB + * board file (only gnetlist >= 20030901 recognizes -m). + */ +int run_gnetlist(const char *pins_file, const char *net_file, const char *pcb_file, const char * basename, const gadl_list_t *largs); + + +/* Return the name of gnetlist that should be executed */ +const char *gnetlist_name(void); + Index: tags/2.1.2/util/gsch2pcb-rnd/run.c =================================================================== --- tags/2.1.2/util/gsch2pcb-rnd/run.c (nonexistent) +++ tags/2.1.2/util/gsch2pcb-rnd/run.c (revision 24813) @@ -0,0 +1,134 @@ +/* gsch2pcb-rnd + * + * Original version: Bill Wilson billw@wt.net + * rnd-version: (C) 2015..2016, Tibor 'Igor2' Palinkas + * + * This program is free software which I release under the GNU General Public + * License. You may redistribute and/or modify this program under the terms + * of that 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. Version 2 is in the + * COPYRIGHT file in the top level directory of this distribution. + * + * To get a copy of the GNU General Puplic License, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include +#include +#include +#include +#include +#include "gsch2pcb.h" +#include "../src_3rd/genvector/vts0.h" +#include "../src/compat_misc.h" +#include "../src/safe_fs.h" +#include "gsch2pcb_rnd_conf.h" + + +int build_and_run_command(const char * format_, ...) +{ + va_list vargs; + int result = FALSE; + vts0_t args; + char *format, *s, *start; + + /* Translate the format string; args elements point to const char *'s + within a copy of the format string. The format string is copied so + that these parts can be terminated by overwriting whitepsace with \0 */ + va_start(vargs, format_); + format = pcb_strdup(format_); + vts0_init(&args); + for(s = start = format; *s != '\0'; s++) { + /* if word separator is reached, save the previous word */ + if (isspace(s[0])) { + if (start == s) { /* empty word - skip */ + start++; + continue; + } + *s = '\0'; + vts0_append(&args, start); + start = s+1; + continue; + } + + /* check if current word is a format */ + if ((s == start) && (s[0] == '%') && (s[1] != '\0') && ((s[2] == '\0') || isspace(s[2]))) { + switch(s[1]) { + case 'L': /* append contents of char * gadl_list_t */ + { + gadl_list_t *list = va_arg(vargs, gadl_list_t *); + gadl_iterator_t it; + char **s; + gadl_foreach(list, &it, s) { + vts0_append(&args, *s); + } + } + start = s+2; + s++; + continue; + case 's': + { + char *arg = va_arg(vargs, char *); + if (arg != NULL) + vts0_append(&args, arg); + start = s+2; + s++; + } + continue; + } + } + } + va_end(vargs); + + if (args.used > 0) { + int i, l; + char *cmd, *end, line[1024]; + FILE *f; + + l = 0; + for (i = 0; i < args.used; i++) + l += strlen(args.array[i]) + 3; + + end = cmd = malloc(l+1); + for (i = 0; i < args.used; i++) { + l = strlen(args.array[i]); + *end = '"'; end++; + memcpy(end, args.array[i], l); + end += l; + *end = '"'; end++; + *end = ' '; end++; + } + end--; + *end = '\0'; + + /* we have something in the list, build & call command */ + if (conf_g2pr.utils.gsch2pcb_rnd.verbose) { + printf("Running command:\n\t%s\n", cmd); + printf("%s", SEP_STRING); + } + + f = pcb_popen(cmd, "r"); + while(fgets(line, sizeof(line), f) != NULL) { + if (conf_g2pr.utils.gsch2pcb_rnd.verbose) + fputs(line, stdout); + } + + if (pcb_pclose(f) == 0) + result = TRUE; + else + fprintf(stderr, "Failed to execute external program\n"); + free(cmd); + + if (conf_g2pr.utils.gsch2pcb_rnd.verbose) + printf("\n%s", SEP_STRING); + } + + free(format); + vts0_uninit(&args); + return result; +} Index: tags/2.1.2/util/gsch2pcb-rnd/run.h =================================================================== --- tags/2.1.2/util/gsch2pcb-rnd/run.h (nonexistent) +++ tags/2.1.2/util/gsch2pcb-rnd/run.h (revision 24813) @@ -0,0 +1,13 @@ +/** + * Build and run a command. No redirection or error handling is + * done. Format string is split on whitespace. Specifiers %l and %s + * are replaced with contents of positional args. To be recognized, + * specifiers must be separated from other arguments in the format by + * whitespace. + * - %L expects a gadl_list_t vith char * payload, contents used as separate arguments + * - %s expects a char*, contents used as a single argument (omitted if NULL) + * @param[in] format used to specify command to be executed + * @param[in] ... positional parameters + */ +int build_and_run_command(const char * format_, ...); + Index: tags/2.1.2/util/keylist.sh =================================================================== --- tags/2.1.2/util/keylist.sh (nonexistent) +++ tags/2.1.2/util/keylist.sh (revision 24813) @@ -0,0 +1,375 @@ +#!/bin/sh +# keylist - list hotkey->actions found in .lht files in a html table +# Copyright (C) 2015..2016, 2018 Tibor 'Igor2' Palinkas +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# http://repo.hu/projects/pcb-rnd + +AWK=awk + +export LANG=C + +need_lht() +{ + echo "lhtflat not found. Please install lihata to run this script. The" >&2 + echo "svn extern in src_3rd/ is not enough, this script requires a full" >&2 + echo "installation from svn://repo.hu/lihata/trunk" >&2 + exit 1 +} + +# make sure lhtflat is installed +echo "" | lhtflat || need_lht + + +if test -z "$*" +then + echo "" + echo "$0: Generate a html table from pcb menu lht files." + echo "Usage: $0 file1 [file2 [file3 ... [fileN]]]" + echo "" + exit +else + cmd="html" + while test $# -gt 0 + do + case "$1" in + --html) cmd="html";; + --boxed) cmd="boxed";; + --lst) cmd="lst";; + --dot) cmd="dot"; nodenames=$2; shift 1;; + *) res_files="$res_files $1" ;; + esac + shift 1 + done +fi + +extract_from_lht() +{ + lhtflat | $AWK -F '[\t]' -v "fn=$1" ' + +#data text //main_menu/1::Edit/submenu/11::Edit name of/submenu/1::pin on layout/a Shift Ctrln +#data text //main_menu/1::Edit/submenu/11::Edit name of/submenu/1::pin on layout/action ChangeName(Object, Number) + + { + tmp = $3 + if ($3 ~ "/a/[0-9]*::$") { + # li:a = {} + sub("/[0-9]*::$", "", tmp) + } + parent=tmp + sub("/[^/]*$","", parent) + node=tmp + sub("^.*/","", node) + } + + + (($1 == "data") && ($2 == "text")) { + # simple text node: accel key + if (node == "a") { + seq=$0 + sub("[^\t]*[\t]*[^\t]*[\t]*[^\t]*[\t]*", "", seq) + gsub(" ", "", seq) + v = split(tolower(seq), S, "[;]") + ktmp = "" + for(n = 1; n <= v; n++) { + if (S[n] ~ "") + split(S[n], K, "") + else + split(S[n], K, "") + if (K[1] != "") { + mods = "" + if (K[1] ~ "alt") mods = mods "-alt" + if (K[1] ~ "ctrl") mods = mods "-ctrl" + if (K[1] ~ "shift") mods = mods "-shift" + } + else + mods = "" + if (ktmp == "") + ktmp = K[2] mods + else + ktmp = ktmp ";" K[2] mods + } + if (KEY[parent] == "") + KEY[parent] = ktmp + else + KEY[parent] = KEY[parent] SUBSEP ktmp + } + + # simple text node: action + if (node == "action") + ACTION[parent] = $4 + + # list item: action + if ($3 ~ "/action/[0-9]+::$") { + parent = $3 + sub("/action/[^/]*$", "", parent) + if (ACTION[parent] != "") + ACTION[parent] = ACTION[parent] ";" $4 + else + ACTION[parent] = $4 + } + } + + END { + for(n in KEY) { + menuname = n + sub(".*::", "", menuname) + v = split(KEY[n], K, "[" SUBSEP "]") + for(i = 1; i <= v; i++) + print K[i] "\t" fn "\t" ACTION[n] "\t" menuname + } + } + ' +} + +# convert a "key src action" to a html table with rowspans for base keys +gen_html() +{ + $AWK -F '[\t]' ' + BEGIN { + CLR[0] = "#FFFFFF" + CLR[1] = "#DDFFFF" + key_combos = 0 + } + function to_base_key(combo) + { + sub("-.*", "", combo) + return combo + } + + function to_mods(combo) + { + if (!(combo ~ ".-")) + return "" + sub("^[^-]*[-]", "", combo) + return combo + } + + { + k = $1 + if (last != k) { + LIST[key_combos++] = k +# ROWSPAN[to_base_key(k)]++ + } + ACTION[$2, k] = $3 + MENUNAME[$2, k] = $4 + HIDS[$2]++ + last = k + + v = split(k, K, ";") + p = "" + for(n = 1; n <= v; n++) { + p = p K[n] ";" + if (($2, p) in PREFIX) { + err = err "
    " $2 ": " k " vs. " p + ERR[$2, p]++ + ERR[$2, k]++ + } + } + p = k ";" + PREFIX[$2, p]++ + } + + function cleanup(s) + { + gsub("\260", "\\°", s) + gsub("\\\\37777777660", "\\°", s) + gsub("\\\\057", "/", s) + return s + } + + END { + q="\"" + print "" + print "" + print "" + print "" + print "\t" + print "\t Key to action bindings " + print "" + print "" + print "" + print "" + print "" + print "

    Key to action bindings

    " + print "" + printf("" + + kv = split(key, K, ";") + keystr = "" + ind="" + for(kn = 1; kn <= kv; kn++) { + if (kn > 1) + keystr = keystr "
    " + keystr = keystr ind K[kn] + ind = ind " " + } + + + print "
    key") + colspan = 2 + for(h in HIDS) { + printf(" %s", h) + colspan++ + } + print "" + for(n = 0; n < key_combos; n++) { + clr_cnt++ + key = LIST[n] + print "
    " cleanup(keystr) + for(h in HIDS) { + mn = cleanup(MENUNAME[h, key]) + act = cleanup(ACTION[h, key]) + if ((act == "") && (mn == "")) + act = " " + else { + gsub(");", "); ", act) + if (mn != "") + act = "" mn "" "
    " act + } + print "
    ", act + if ((h, key) in ERR) + print "
    Error: key prefix collision" + } + last_base = base + } + print "
    " + print err + print "" + } + ' +} + +gen_list() +{ + local n + for n in $res_files + do + extract_from_lht "`basename $n`" < $n + done | sort +} + +# load node names and generate a dot drawing of the multikey bindings +gen_dot() +{ + $AWK -v "names=$nodenames" ' + BEGIN { + q="\"" + print "digraph keytree {" + print "rankdir=LR" + print "ranksep=0.2" + while((getline < names) == 1) { + path=$1 + $1="" + desc = $0 + node(path, desc, "shape=box") + } + close(names) + FS="[\t]" + } + + function arrow_(curr) + { + if (!(curr in ARROW_SEEN)) { + print curr + ARROW_SEEN[curr]=1 + } + } + + function arrow(path ,n,v,P,last,curr) + { + sub("^[/;_]", "", path) + sub("[/;_]$", "", path) + v = split(path, P, "[/;_]") + +# curr = "root -> " q P[1] q +# arrow_(curr) + last = P[1] + for(n = 2; n <= v; n++) { + curr = q last q "->" q last "_" P[n] q + arrow_(curr) + last = last "_" P[n] + } + } + + function cleanup(s) + { + gsub("\260", "\\°", s) + gsub("\\\\37777777660", "\\°", s) + gsub("\\\\057", "/", s) + return s + } + + function node(path, desc, shape, orig) + { + orig=path + desc=cleanup(desc) + sub("^[/_;]", "", orig) + sub("[/_;]$", "", orig) + gsub("[/_;]", " ", orig) + sub("^[/;]", "", path) + sub("[/;]$", "", path) + gsub("[/;]", "_", path) + gsub("[\"]", "", desc) + print q path q " [label=" q "{" orig "} \\n" desc q " " shape "]" + arrow(path) + } + + (($1 ~ "^[a-z]$") || ($1 ~ "^[a-z];[a-z];") || ($1 ~ "^[a-z];[a-z]$")) { + node($1, $4, "") + } + + END { + print "}" + } + ' +} + +gen_boxed_html() +{ + $AWK -F '[\t]' ' + /^[a-z][;]/ { + key=substr($0, 1, 1) + TBL[key] = TBL[key] "\n
    " $1 "" $4 + } + END { + print "" + print "

    pcb-rnd 2.x.x keys - cheat sheet

    " + for(n = 0; n < 26; n++) { + key = sprintf("%c", 97+n) + print "
    " + print TBL[key] + print "
    " + print "" + } + } + ' +} + +case "$cmd" in + html) gen_list | gen_html ;; + boxed) gen_list | gen_boxed_html ;; + dot) gen_list | gen_dot ;; + lst) gen_list ;; +esac + Property changes on: tags/2.1.2/util/keylist.sh ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/2.1.2/util/menu2svg.sh =================================================================== --- tags/2.1.2/util/menu2svg.sh (nonexistent) +++ tags/2.1.2/util/menu2svg.sh (revision 24813) @@ -0,0 +1,147 @@ +#!/bin/sh +# menu2svg - visualize a menu file using graphviz +# Copyright (C) 2017 Tibor 'Igor2' Palinkas +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# http://repo.hu/projects/pcb-rnd + +fn="$1" +if test -z $fn +then + fn="../src/pcb-menu-gtk.lht" +fi + +lhtflat < $fn | tee LHT | awk -F "[\t]" ' +!($3 ~ "^//main_menu/") { next } + +{ + menu_path = $3 + sub("//main_menu/", "", menu_path) + gsub("/submenu", "", menu_path) + gsub("[0-9]+::", "", menu_path) +} + +(($1 == "open") && ($2 == "hash")) { + if (current != "") + print current + current = menu_path +} + +(($1 == "data") && ($2 == "text") && (current != "")) { + if ($3 ~ "/a$") { + PROPS["key"] = $4 + sub("<[Kk]ey>", " ", PROPS["key"]) + } + else if ($3 ~ "/action$") { + PROPS["act"] = $4 + } + + +} + +(($1 == "close") && (current != "")) { + print current "\t" PROPS["key"] "\t" PROPS["act"] + current = "" + delete PROPS +} +' | tee Menu.flat | awk -F "[\t]" ' +BEGIN { + q = "\"" + print "digraph menu {" + print "rankdir=LR;" +# print "ranksep=4;" + print "node [shape=record];" + + reg_node("/") +} + +function reg_node(path) +{ + last_id++ + PATH2ID[path] = last_id + ID2PATH[last_id] = path +} + +function add_ch(parent, child) +{ + if (NUM_CH[parent] == "") + NUM_CH[parent] = 0 + if (IS_CH[parent, child]) + return + IS_CH[parent, child] = 1 + CH[parent, NUM_CH[parent]] = child + + NUM_CH[parent]++ +} + +{ + path=$1 + KEY[path] = $2 + ACT[path] = $3 + reg_node(path) + while(path ~ "/") { + parent = path + sub("/[^/]*$", "", parent) + add_ch(parent, path) + path = parent + } + add_ch("/", path) +} + +function gen_menus(parent ,n,child,short,chp) +{ + short=parent + sub(".*/", "", short) + if (!(parent in PATH2ID)) + reg_node(parent) + printf " m" PATH2ID[parent] " [label=\" [[" short "]]" + for(n = 0; n < NUM_CH[parent]; n++) { + child=CH[parent, n] + short=child + sub(".*/", "", short) + printf("| %s", PATH2ID[child], short) + } + print "\"]" + + for(n = 0; n < NUM_CH[parent]; n++) { + child=CH[parent, n] + if (NUM_CH[child] > 0) { + chp = gen_menus(child) + print " m" PATH2ID[parent] ":m" PATH2ID[child] " -> " chp ":menu" + } + } + + return "m" PATH2ID[parent] +} + + +END { + for(n = 0; n < NUM_CH["/"]; n++) { + child=CH["/", n] + curr = gen_menus(child) + if (last != NULL) { + print "tmp" n " [shape=point]" + print last ":menu -> tmp" n " [weight=10000 arrowhead=none]" + print "tmp" n " -> " curr ":menu [weight=10000 arrowhead=none]" + } + last = curr + } + print "}" +} +' > Menu.dot + +dot -Tsvg Menu.dot > Menu.svg + Property changes on: tags/2.1.2/util/menu2svg.sh ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/2.1.2/util/pcb-prj2lht =================================================================== --- tags/2.1.2/util/pcb-prj2lht (nonexistent) +++ tags/2.1.2/util/pcb-prj2lht (revision 24813) @@ -0,0 +1,158 @@ +#!/bin/sh +# pcb-prj2lht - convert an old gsch2pcb project file to geda project lht +# Copyright (C) 2016 Tibor 'Igor2' Palinkas +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# http://repo.hu/projects/pcb-rnd + +# Convert and old gsch2pcb-rnd project file to the new, multi-program +# geda project lihata file format. + +prj2lht() { + awk ' + BEGIN { + INDENT["elements-dir"] = " " + INDENT["schematics"] = " " + } + + function lht_quote(s) { + if (s ~ "[^a-zA-Z0-9_.-]") + return "{" s "}" + return s + } + + function parse() { + name = $1 + $1="" + CFG[name] = $0 + sub("^[ \t]*", "", CFG[name]) + } + + function list_add(key, val) { + CFG[key] = CFG[key] INDENT[key] lht_quote(val) "\n" + } + + function list_add_split(key, val ,n,v,T) { + v = split(val, T, "[ \t]+") + for(n = 1; n <= v; n++) + if (T[n] != "") + list_add(key, T[n]) + } + + function qparse( tmp,name) { + name = $1 + $1="" + tmp=$0 + sub("^[ \t]*", "", tmp) + while(match(tmp, "\"[^\"]*\"")) { + list_add_split(name, substr(tmp, 1, RSTART-1)) + list_add(name, substr(tmp, RSTART+1, RLENGTH-2)) + tmp = substr(tmp, RSTART+RLENGTH, length(tmp)) + } + # leftover after the last quote + list_add_split(name, tmp) + } + + ($1 == "elements-dir") { qparse() } + ($1 == "elements-shell") { parse() } + ($1 == "schematics") { qparse() } + ($1 == "output-name") { parse() } + ($1 == "remove-unfound") { CFG["remove-unfound"] = 1 } + ($1 == "keep-unfound") { CFG["remove-unfound"] = 0 } + ($1 == "quiet") { CFG[$1] = 1 } + ($1 == "preserve") { CFG[$1] = 1 } + ($1 == "default-pcb") { parse() } + ($1 == "gnetlist") { parse() } + ($1 == "enpty-footprint") { parse() } + + function print_val(cfgkey, outkey) { + if (cfgkey in CFG) + print " " outkey " = " lht_quote(CFG[cfgkey]) + } + + END { + print "ha:geda-project-v1 {" + print " li:pcb-rnd-conf-v1 {" + + print " ha:overwrite {" + print " ha:utils {" + print " ha:gsch2pcb_rnd {" + print_val("remove-unfound", "remove_unfound_elements") + print_val("quiet", "quiet_mode") + print_val("preserve", "preserve") + print_val("output-name", "sch_basename") + print_val("default-pcb", "default_pcb") + print_val("gnetlist", "gnetlist") + print_val("empty-footprint", "empty_footprint_name") + if ("schematics" in CFG) { + print " li:schematics {" + printf("%s", CFG["schematics"]) + print " }" + } + print " }" + print " }" + print " ha:rc {" + print_val("elements-shell", "library_shell") + print " }" + print " }" + + if ("elements-dir" in CFG) { + print " ha:prepend {" + print " ha:rc {" + print " li:library_search_paths {" + printf("%s", CFG["elements-dir"]) + print " }" + print " }" + print " }" + } + + print " }" + print "}" + } + ' +} + +help() +{ + echo "pcb-prj2lht - convert a gsch2pcb project file to pcb-rnd lihata project file" + echo "" + echo "Invocation: pcb-prj2lht [something.prj]" + echo "" + echo "If the project file is specified, a new file is created with the .prj" + echo "part replaced with .lht. If no file name specified, read the project" + echo "on STDIN and write the result to STDOUT." + echo "" +} + +########## main ########## + +if test "$1" = "--help" +then + help + exit +fi + +if test $# -gt 0 +then + for n in "$@" + do + out=${n%%.prj}.lht + prj2lht < $n > $out || echo "Failed to convert $n to $out" >&2 + done +else + # stdio operation + prj2lht +fi Property changes on: tags/2.1.2/util/pcb-prj2lht ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/2.1.2/util/pcb-strip =================================================================== --- tags/2.1.2/util/pcb-strip (nonexistent) +++ tags/2.1.2/util/pcb-strip (revision 24813) @@ -0,0 +1,87 @@ +#!/bin/sh +# pcb-strip - remove sections of a .pcb file +# Copyright (C) 2016 Tibor 'Igor2' Palinkas +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# http://repo.hu/projects/pcb-rnd + +pcb_strip() +{ + awk -v "strip_sym=$strip_sym" -v "strip_attr=$strip_attr" ' + BEGIN { + symst = 0 + } + + strip_attr && /^[ \t]*Attribute/ { next } + + strip_sym && (symst == 0) && /^[ \t]*Symbol/ { symst = 1 } + strip_sym && (symst == 1) && /^[ \t]*[(]/ { symst = 2 } + strip_sym && (symst == 2) && /^[ \t]*[)]/ { symst = 0; next } + + (symst == 0) { print $0 } + ' +} + +help() +{ + echo "pcb-strip - remove sections of a pcb file" + echo "Invocation:" + echo " $0 [-a] [-s] bar.pcb" + echo " or $0 [-a] [-s] foo.pcb" + echo "" + echo "Switches:" + echo " -a remove Attributes" + echo " -s remove symbols" + echo "" +} + +strip_sym=0 +strip_attr=0 +fn="" +while test $# -gt 0 +do + case "$1" + in + --help) help "$0"; exit 0;; + -s) strip_sym=1;; + -a) strip_attr=1;; + -*) echo "unknown switch $1; try --help" >&2; exit 1;; + *) + if test -z "$fn" + then + fn="$1" + else + echo "unknown switch $1; try --help" >&2 + exit + fi + ;; + esac + shift 1 +done + +if test -z "$fn" +then +# operate on stdio + pcb_strip +else +# use a file by name + tmp=`mktemp` + if test -z "$tmp" + then + tmp="$fn.strip" + fi + mv $fn $tmp && pcb_strip < $tmp > $fn && rm $tmp +fi Property changes on: tags/2.1.2/util/pcb-strip ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/2.1.2/util/pcblib-map/Makefile =================================================================== --- tags/2.1.2/util/pcblib-map/Makefile (nonexistent) +++ tags/2.1.2/util/pcblib-map/Makefile (revision 24813) @@ -0,0 +1,16 @@ +OUT = map.html conn.html parametric.html smd2.html smd3.html smdN.html \ + trh2.html trh3.html trhN.html cache + +all: $(OUT) + +map.html map.png: map.pcb + ./imgmap_page.sh map + +%.html %.png: %.pcb + ./imgmap_fp.sh $* + +cache: + ./cache.sh > cache + +clean: + rm $(OUT) Index: tags/2.1.2/util/pcblib-map/cache.sh =================================================================== --- tags/2.1.2/util/pcblib-map/cache.sh (nonexistent) +++ tags/2.1.2/util/pcblib-map/cache.sh (revision 24813) @@ -0,0 +1,51 @@ +#!/bin/sh + +digest() +{ + local fn bn + fn=$1 + + bn=${fn#./} + + if test -d "$fn" + then + echo "D $bn" + return + fi + + prm=`grep "@@purpose" $fn` + if test -z "$prm" + then + tags=`awk ' + /^##/ { + tag=$0 + sub("^##","", tag) + printf " %s", tag + } + ' < $fn` + echo "S $bn $tags" + else + tags=`awk ' + /^@@tag/ { + tag=$0 + sub("^@@tag *","", tag) + printf " %s", tag + } + ' < $fn` + echo "P $bn $tags" + fi + +} + +( +cd ../../pcblib +for n in `find .` +do + case $n in + *.svn*) ;; + .) ;; + *) + digest $n + esac +done +) Property changes on: tags/2.1.2/util/pcblib-map/cache.sh ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/2.1.2/util/pcblib-map/conn.pcb =================================================================== --- tags/2.1.2/util/pcblib-map/conn.pcb (nonexistent) +++ tags/2.1.2/util/pcblib-map/conn.pcb (revision 24813) @@ -0,0 +1,1342 @@ +# release: pcb 20110918 + +# To read pcb files, the pcb version (or the git source date) must be >= the file version +FileVersion[20070407] + +PCB["" 270000 500000] + +Grid[10000.0 0 0 1] +Cursor[0 30000 0.000000] +PolyArea[3100.006200] +Thermal[0.500000] +DRC[1200 900 1000 700 1500 1000] +Flags("nameonpcb,clearnew,snappin") +Groups("1,3,4,c:2,5,6,s:7:8") +Styles["Signal,1000,7874,3150,2000:Power,2000,8661,3937,2000:Fat,8000,13780,4724,2500:Sig-tight,1000,6400,3150,1200"] + +Symbol[' ' 1800] +( +) +Symbol['!' 1200] +( + SymbolLine[0 4500 0 5000 800] + SymbolLine[0 1000 0 3500 800] +) +Symbol['"' 1200] +( + SymbolLine[0 1000 0 2000 800] + SymbolLine[1000 1000 1000 2000 800] +) +Symbol['#' 1200] +( + SymbolLine[0 3500 2000 3500 800] + SymbolLine[0 2500 2000 2500 800] + SymbolLine[1500 2000 1500 4000 800] + SymbolLine[500 2000 500 4000 800] +) +Symbol['$' 1200] +( + SymbolLine[1500 1500 2000 2000 800] + SymbolLine[500 1500 1500 1500 800] + SymbolLine[0 2000 500 1500 800] + SymbolLine[0 2000 0 2500 800] + SymbolLine[0 2500 500 3000 800] + SymbolLine[500 3000 1500 3000 800] + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[2000 3500 2000 4000 800] + SymbolLine[1500 4500 2000 4000 800] + SymbolLine[500 4500 1500 4500 800] + SymbolLine[0 4000 500 4500 800] + SymbolLine[1000 1000 1000 5000 800] +) +Symbol['%' 1200] +( + SymbolLine[0 1500 0 2000 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 1000 1000 800] + SymbolLine[1000 1000 1500 1500 800] + SymbolLine[1500 1500 1500 2000 800] + SymbolLine[1000 2500 1500 2000 800] + SymbolLine[500 2500 1000 2500 800] + SymbolLine[0 2000 500 2500 800] + SymbolLine[0 5000 4000 1000 800] + SymbolLine[3500 5000 4000 4500 800] + SymbolLine[4000 4000 4000 4500 800] + SymbolLine[3500 3500 4000 4000 800] + SymbolLine[3000 3500 3500 3500 800] + SymbolLine[2500 4000 3000 3500 800] + SymbolLine[2500 4000 2500 4500 800] + SymbolLine[2500 4500 3000 5000 800] + SymbolLine[3000 5000 3500 5000 800] +) +Symbol['&' 1200] +( + SymbolLine[0 4500 500 5000 800] + SymbolLine[0 1500 0 2500 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[0 3500 1500 2000 800] + SymbolLine[500 5000 1000 5000 800] + SymbolLine[1000 5000 2000 4000 800] + SymbolLine[0 2500 2500 5000 800] + SymbolLine[500 1000 1000 1000 800] + SymbolLine[1000 1000 1500 1500 800] + SymbolLine[1500 1500 1500 2000 800] + SymbolLine[0 3500 0 4500 800] +) +Symbol[''' 1200] +( + SymbolLine[0 2000 1000 1000 800] +) +Symbol['(' 1200] +( + SymbolLine[0 4500 500 5000 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[0 1500 0 4500 800] +) +Symbol[')' 1200] +( + SymbolLine[0 1000 500 1500 800] + SymbolLine[500 1500 500 4500 800] + SymbolLine[0 5000 500 4500 800] +) +Symbol['*' 1200] +( + SymbolLine[0 2000 2000 4000 800] + SymbolLine[0 4000 2000 2000 800] + SymbolLine[0 3000 2000 3000 800] + SymbolLine[1000 2000 1000 4000 800] +) +Symbol['+' 1200] +( + SymbolLine[0 3000 2000 3000 800] + SymbolLine[1000 2000 1000 4000 800] +) +Symbol[',' 1200] +( + SymbolLine[0 6000 1000 5000 800] +) +Symbol['-' 1200] +( + SymbolLine[0 3000 2000 3000 800] +) +Symbol['.' 1200] +( + SymbolLine[0 5000 500 5000 800] +) +Symbol['/' 1200] +( + SymbolLine[0 4500 3000 1500 800] +) +Symbol['0' 1200] +( + SymbolLine[0 4500 500 5000 800] + SymbolLine[0 1500 0 4500 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 1500 1000 800] + SymbolLine[1500 1000 2000 1500 800] + SymbolLine[2000 1500 2000 4500 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[0 4000 2000 2000 800] +) +Symbol['1' 1200] +( + SymbolLine[0 1800 800 1000 800] + SymbolLine[800 1000 800 5000 800] + SymbolLine[0 5000 1500 5000 800] +) +Symbol['2' 1200] +( + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 2000 1000 800] + SymbolLine[2000 1000 2500 1500 800] + SymbolLine[2500 1500 2500 2500 800] + SymbolLine[0 5000 2500 2500 800] + SymbolLine[0 5000 2500 5000 800] +) +Symbol['3' 1200] +( + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 1500 1000 800] + SymbolLine[1500 1000 2000 1500 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[500 2800 1500 2800 800] + SymbolLine[2000 1500 2000 2300 800] + SymbolLine[2000 3300 2000 4500 800] + SymbolLine[2000 3300 1500 2800 800] + SymbolLine[2000 2300 1500 2800 800] +) +Symbol['4' 1200] +( + SymbolLine[0 3500 2000 1000 800] + SymbolLine[0 3500 2500 3500 800] + SymbolLine[2000 1000 2000 5000 800] +) +Symbol['5' 1200] +( + SymbolLine[0 1000 2000 1000 800] + SymbolLine[0 1000 0 3000 800] + SymbolLine[0 3000 500 2500 800] + SymbolLine[500 2500 1500 2500 800] + SymbolLine[1500 2500 2000 3000 800] + SymbolLine[2000 3000 2000 4500 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[0 4500 500 5000 800] +) +Symbol['6' 1200] +( + SymbolLine[1500 1000 2000 1500 800] + SymbolLine[500 1000 1500 1000 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[0 1500 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[1500 2800 2000 3300 800] + SymbolLine[0 2800 1500 2800 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[2000 3300 2000 4500 800] +) +Symbol['7' 1200] +( + SymbolLine[500 5000 2500 1000 800] + SymbolLine[0 1000 2500 1000 800] +) +Symbol['8' 1200] +( + SymbolLine[0 4500 500 5000 800] + SymbolLine[0 3700 0 4500 800] + SymbolLine[0 3700 700 3000 800] + SymbolLine[700 3000 1300 3000 800] + SymbolLine[1300 3000 2000 3700 800] + SymbolLine[2000 3700 2000 4500 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[0 2300 700 3000 800] + SymbolLine[0 1500 0 2300 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 1500 1000 800] + SymbolLine[1500 1000 2000 1500 800] + SymbolLine[2000 1500 2000 2300 800] + SymbolLine[1300 3000 2000 2300 800] +) +Symbol['9' 1200] +( + SymbolLine[500 5000 2000 3000 800] + SymbolLine[2000 1500 2000 3000 800] + SymbolLine[1500 1000 2000 1500 800] + SymbolLine[500 1000 1500 1000 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[0 1500 0 2500 800] + SymbolLine[0 2500 500 3000 800] + SymbolLine[500 3000 2000 3000 800] +) +Symbol[':' 1200] +( + SymbolLine[0 2500 500 2500 800] + SymbolLine[0 3500 500 3500 800] +) +Symbol[';' 1200] +( + SymbolLine[0 5000 1000 4000 800] + SymbolLine[1000 2500 1000 3000 800] +) +Symbol['<' 1200] +( + SymbolLine[0 3000 1000 2000 800] + SymbolLine[0 3000 1000 4000 800] +) +Symbol['=' 1200] +( + SymbolLine[0 2500 2000 2500 800] + SymbolLine[0 3500 2000 3500 800] +) +Symbol['>' 1200] +( + SymbolLine[0 2000 1000 3000 800] + SymbolLine[0 4000 1000 3000 800] +) +Symbol['?' 1200] +( + SymbolLine[1000 3000 1000 3500 800] + SymbolLine[1000 4500 1000 5000 800] + SymbolLine[0 1500 0 2000 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 1500 1000 800] + SymbolLine[1500 1000 2000 1500 800] + SymbolLine[2000 1500 2000 2000 800] + SymbolLine[1000 3000 2000 2000 800] +) +Symbol['@' 1200] +( + SymbolLine[0 1000 0 4000 800] + SymbolLine[0 4000 1000 5000 800] + SymbolLine[1000 5000 4000 5000 800] + SymbolLine[5000 3500 5000 1000 800] + SymbolLine[5000 1000 4000 0 800] + SymbolLine[4000 0 1000 0 800] + SymbolLine[1000 0 0 1000 800] + SymbolLine[1500 2000 1500 3000 800] + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[2000 3500 3000 3500 800] + SymbolLine[3000 3500 3500 3000 800] + SymbolLine[3500 3000 4000 3500 800] + SymbolLine[3500 3000 3500 1500 800] + SymbolLine[3500 2000 3000 1500 800] + SymbolLine[2000 1500 3000 1500 800] + SymbolLine[2000 1500 1500 2000 800] + SymbolLine[4000 3500 5000 3500 800] +) +Symbol['A' 1200] +( + SymbolLine[0 2000 0 5000 800] + SymbolLine[0 2000 700 1000 800] + SymbolLine[700 1000 1800 1000 800] + SymbolLine[1800 1000 2500 2000 800] + SymbolLine[2500 2000 2500 5000 800] + SymbolLine[0 3000 2500 3000 800] +) +Symbol['B' 1200] +( + SymbolLine[0 5000 2000 5000 800] + SymbolLine[2000 5000 2500 4500 800] + SymbolLine[2500 3300 2500 4500 800] + SymbolLine[2000 2800 2500 3300 800] + SymbolLine[500 2800 2000 2800 800] + SymbolLine[500 1000 500 5000 800] + SymbolLine[0 1000 2000 1000 800] + SymbolLine[2000 1000 2500 1500 800] + SymbolLine[2500 1500 2500 2300 800] + SymbolLine[2000 2800 2500 2300 800] +) +Symbol['C' 1200] +( + SymbolLine[700 5000 2000 5000 800] + SymbolLine[0 4300 700 5000 800] + SymbolLine[0 1700 0 4300 800] + SymbolLine[0 1700 700 1000 800] + SymbolLine[700 1000 2000 1000 800] +) +Symbol['D' 1200] +( + SymbolLine[500 1000 500 5000 800] + SymbolLine[1800 1000 2500 1700 800] + SymbolLine[2500 1700 2500 4300 800] + SymbolLine[1800 5000 2500 4300 800] + SymbolLine[0 5000 1800 5000 800] + SymbolLine[0 1000 1800 1000 800] +) +Symbol['E' 1200] +( + SymbolLine[0 2800 1500 2800 800] + SymbolLine[0 5000 2000 5000 800] + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 1000 2000 1000 800] +) +Symbol['F' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 1000 2000 1000 800] + SymbolLine[0 2800 1500 2800 800] +) +Symbol['G' 1200] +( + SymbolLine[2000 1000 2500 1500 800] + SymbolLine[500 1000 2000 1000 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[0 1500 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[500 5000 2000 5000 800] + SymbolLine[2000 5000 2500 4500 800] + SymbolLine[2500 3500 2500 4500 800] + SymbolLine[2000 3000 2500 3500 800] + SymbolLine[1000 3000 2000 3000 800] +) +Symbol['H' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[2500 1000 2500 5000 800] + SymbolLine[0 3000 2500 3000 800] +) +Symbol['I' 1200] +( + SymbolLine[0 1000 1000 1000 800] + SymbolLine[500 1000 500 5000 800] + SymbolLine[0 5000 1000 5000 800] +) +Symbol['J' 1200] +( + SymbolLine[700 1000 1500 1000 800] + SymbolLine[1500 1000 1500 4500 800] + SymbolLine[1000 5000 1500 4500 800] + SymbolLine[500 5000 1000 5000 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[0 4500 0 4000 800] +) +Symbol['K' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 3000 2000 1000 800] + SymbolLine[0 3000 2000 5000 800] +) +Symbol['L' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 5000 2000 5000 800] +) +Symbol['M' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 1000 1500 3000 800] + SymbolLine[1500 3000 3000 1000 800] + SymbolLine[3000 1000 3000 5000 800] +) +Symbol['N' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 1000 2500 5000 800] + SymbolLine[2500 1000 2500 5000 800] +) +Symbol['O' 1200] +( + SymbolLine[0 1500 0 4500 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 1500 1000 800] + SymbolLine[1500 1000 2000 1500 800] + SymbolLine[2000 1500 2000 4500 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[0 4500 500 5000 800] +) +Symbol['P' 1200] +( + SymbolLine[500 1000 500 5000 800] + SymbolLine[0 1000 2000 1000 800] + SymbolLine[2000 1000 2500 1500 800] + SymbolLine[2500 1500 2500 2500 800] + SymbolLine[2000 3000 2500 2500 800] + SymbolLine[500 3000 2000 3000 800] +) +Symbol['Q' 1200] +( + SymbolLine[0 1500 0 4500 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 1500 1000 800] + SymbolLine[1500 1000 2000 1500 800] + SymbolLine[2000 1500 2000 4000 800] + SymbolLine[1000 5000 2000 4000 800] + SymbolLine[500 5000 1000 5000 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[1000 3500 2000 5000 800] +) +Symbol['R' 1200] +( + SymbolLine[0 1000 2000 1000 800] + SymbolLine[2000 1000 2500 1500 800] + SymbolLine[2500 1500 2500 2500 800] + SymbolLine[2000 3000 2500 2500 800] + SymbolLine[500 3000 2000 3000 800] + SymbolLine[500 1000 500 5000 800] + SymbolLine[1300 3000 2500 5000 800] +) +Symbol['S' 1200] +( + SymbolLine[2000 1000 2500 1500 800] + SymbolLine[500 1000 2000 1000 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[0 1500 0 2500 800] + SymbolLine[0 2500 500 3000 800] + SymbolLine[500 3000 2000 3000 800] + SymbolLine[2000 3000 2500 3500 800] + SymbolLine[2500 3500 2500 4500 800] + SymbolLine[2000 5000 2500 4500 800] + SymbolLine[500 5000 2000 5000 800] + SymbolLine[0 4500 500 5000 800] +) +Symbol['T' 1200] +( + SymbolLine[0 1000 2000 1000 800] + SymbolLine[1000 1000 1000 5000 800] +) +Symbol['U' 1200] +( + SymbolLine[0 1000 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[2000 1000 2000 4500 800] +) +Symbol['V' 1200] +( + SymbolLine[0 1000 1000 5000 800] + SymbolLine[1000 5000 2000 1000 800] +) +Symbol['W' 1200] +( + SymbolLine[0 1000 0 3000 800] + SymbolLine[0 3000 500 5000 800] + SymbolLine[500 5000 1500 3000 800] + SymbolLine[1500 3000 2500 5000 800] + SymbolLine[2500 5000 3000 3000 800] + SymbolLine[3000 3000 3000 1000 800] +) +Symbol['X' 1200] +( + SymbolLine[0 5000 2500 1000 800] + SymbolLine[0 1000 2500 5000 800] +) +Symbol['Y' 1200] +( + SymbolLine[0 1000 1000 3000 800] + SymbolLine[1000 3000 2000 1000 800] + SymbolLine[1000 3000 1000 5000 800] +) +Symbol['Z' 1200] +( + SymbolLine[0 1000 2500 1000 800] + SymbolLine[0 5000 2500 1000 800] + SymbolLine[0 5000 2500 5000 800] +) +Symbol['[' 1200] +( + SymbolLine[0 1000 500 1000 800] + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 5000 500 5000 800] +) +Symbol['\' 1200] +( + SymbolLine[0 1500 3000 4500 800] +) +Symbol[']' 1200] +( + SymbolLine[0 1000 500 1000 800] + SymbolLine[500 1000 500 5000 800] + SymbolLine[0 5000 500 5000 800] +) +Symbol['^' 1200] +( + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 1000 1500 800] +) +Symbol['_' 1200] +( + SymbolLine[0 5000 2000 5000 800] +) +Symbol['a' 1200] +( + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[500 3000 1500 3000 800] + SymbolLine[0 3500 500 3000 800] + SymbolLine[0 3500 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[2000 3000 2000 4500 800] + SymbolLine[2000 4500 2500 5000 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[1500 5000 2000 4500 800] +) +Symbol['b' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[2000 3500 2000 4500 800] + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[500 3000 1500 3000 800] + SymbolLine[0 3500 500 3000 800] +) +Symbol['c' 1200] +( + SymbolLine[500 3000 2000 3000 800] + SymbolLine[0 3500 500 3000 800] + SymbolLine[0 3500 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[500 5000 2000 5000 800] +) +Symbol['d' 1200] +( + SymbolLine[2000 1000 2000 5000 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[0 3500 0 4500 800] + SymbolLine[0 3500 500 3000 800] + SymbolLine[500 3000 1500 3000 800] + SymbolLine[1500 3000 2000 3500 800] +) +Symbol['e' 1200] +( + SymbolLine[500 5000 2000 5000 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[0 3500 0 4500 800] + SymbolLine[0 3500 500 3000 800] + SymbolLine[500 3000 1500 3000 800] + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[0 4000 2000 4000 800] + SymbolLine[2000 4000 2000 3500 800] +) +Symbol['f' 1000] +( + SymbolLine[500 1500 500 5000 800] + SymbolLine[500 1500 1000 1000 800] + SymbolLine[1000 1000 1500 1000 800] + SymbolLine[0 3000 1000 3000 800] +) +Symbol['g' 1200] +( + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[500 3000 1500 3000 800] + SymbolLine[0 3500 500 3000 800] + SymbolLine[0 3500 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[0 6000 500 6500 800] + SymbolLine[500 6500 1500 6500 800] + SymbolLine[1500 6500 2000 6000 800] + SymbolLine[2000 3000 2000 6000 800] +) +Symbol['h' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 3500 500 3000 800] + SymbolLine[500 3000 1500 3000 800] + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[2000 3500 2000 5000 800] +) +Symbol['i' 1000] +( + SymbolLine[0 2000 0 2100 1000] + SymbolLine[0 3500 0 5000 800] +) +Symbol['j' 1000] +( + SymbolLine[500 2000 500 2100 1000] + SymbolLine[500 3500 500 6000 800] + SymbolLine[0 6500 500 6000 800] +) +Symbol['k' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 3500 1500 5000 800] + SymbolLine[0 3500 1000 2500 800] +) +Symbol['l' 1000] +( + SymbolLine[0 1000 0 4500 800] + SymbolLine[0 4500 500 5000 800] +) +Symbol['m' 1200] +( + SymbolLine[500 3500 500 5000 800] + SymbolLine[500 3500 1000 3000 800] + SymbolLine[1000 3000 1500 3000 800] + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[2000 3500 2000 5000 800] + SymbolLine[2000 3500 2500 3000 800] + SymbolLine[2500 3000 3000 3000 800] + SymbolLine[3000 3000 3500 3500 800] + SymbolLine[3500 3500 3500 5000 800] + SymbolLine[0 3000 500 3500 800] +) +Symbol['n' 1200] +( + SymbolLine[500 3500 500 5000 800] + SymbolLine[500 3500 1000 3000 800] + SymbolLine[1000 3000 1500 3000 800] + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[2000 3500 2000 5000 800] + SymbolLine[0 3000 500 3500 800] +) +Symbol['o' 1200] +( + SymbolLine[0 3500 0 4500 800] + SymbolLine[0 3500 500 3000 800] + SymbolLine[500 3000 1500 3000 800] + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[2000 3500 2000 4500 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[0 4500 500 5000 800] +) +Symbol['p' 1200] +( + SymbolLine[500 3500 500 6500 800] + SymbolLine[0 3000 500 3500 800] + SymbolLine[500 3500 1000 3000 800] + SymbolLine[1000 3000 2000 3000 800] + SymbolLine[2000 3000 2500 3500 800] + SymbolLine[2500 3500 2500 4500 800] + SymbolLine[2000 5000 2500 4500 800] + SymbolLine[1000 5000 2000 5000 800] + SymbolLine[500 4500 1000 5000 800] +) +Symbol['q' 1200] +( + SymbolLine[2000 3500 2000 6500 800] + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[500 3000 1500 3000 800] + SymbolLine[0 3500 500 3000 800] + SymbolLine[0 3500 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[1500 5000 2000 4500 800] +) +Symbol['r' 1200] +( + SymbolLine[500 3500 500 5000 800] + SymbolLine[500 3500 1000 3000 800] + SymbolLine[1000 3000 2000 3000 800] + SymbolLine[0 3000 500 3500 800] +) +Symbol['s' 1200] +( + SymbolLine[500 5000 2000 5000 800] + SymbolLine[2000 5000 2500 4500 800] + SymbolLine[2000 4000 2500 4500 800] + SymbolLine[500 4000 2000 4000 800] + SymbolLine[0 3500 500 4000 800] + SymbolLine[0 3500 500 3000 800] + SymbolLine[500 3000 2000 3000 800] + SymbolLine[2000 3000 2500 3500 800] + SymbolLine[0 4500 500 5000 800] +) +Symbol['t' 1000] +( + SymbolLine[500 1000 500 4500 800] + SymbolLine[500 4500 1000 5000 800] + SymbolLine[0 2500 1000 2500 800] +) +Symbol['u' 1200] +( + SymbolLine[0 3000 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[2000 3000 2000 4500 800] +) +Symbol['v' 1200] +( + SymbolLine[0 3000 1000 5000 800] + SymbolLine[2000 3000 1000 5000 800] +) +Symbol['w' 1200] +( + SymbolLine[0 3000 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[500 5000 1000 5000 800] + SymbolLine[1000 5000 1500 4500 800] + SymbolLine[1500 3000 1500 4500 800] + SymbolLine[1500 4500 2000 5000 800] + SymbolLine[2000 5000 2500 5000 800] + SymbolLine[2500 5000 3000 4500 800] + SymbolLine[3000 3000 3000 4500 800] +) +Symbol['x' 1200] +( + SymbolLine[0 3000 2000 5000 800] + SymbolLine[0 5000 2000 3000 800] +) +Symbol['y' 1200] +( + SymbolLine[0 3000 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[2000 3000 2000 6000 800] + SymbolLine[1500 6500 2000 6000 800] + SymbolLine[500 6500 1500 6500 800] + SymbolLine[0 6000 500 6500 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[1500 5000 2000 4500 800] +) +Symbol['z' 1200] +( + SymbolLine[0 3000 2000 3000 800] + SymbolLine[0 5000 2000 3000 800] + SymbolLine[0 5000 2000 5000 800] +) +Symbol['{' 1200] +( + SymbolLine[500 1500 1000 1000 800] + SymbolLine[500 1500 500 2500 800] + SymbolLine[0 3000 500 2500 800] + SymbolLine[0 3000 500 3500 800] + SymbolLine[500 3500 500 4500 800] + SymbolLine[500 4500 1000 5000 800] +) +Symbol['|' 1200] +( + SymbolLine[0 1000 0 5000 800] +) +Symbol['}' 1200] +( + SymbolLine[0 1000 500 1500 800] + SymbolLine[500 1500 500 2500 800] + SymbolLine[500 2500 1000 3000 800] + SymbolLine[500 3500 1000 3000 800] + SymbolLine[500 3500 500 4500 800] + SymbolLine[0 5000 500 4500 800] +) +Symbol['~' 1200] +( + SymbolLine[0 3500 500 3000 800] + SymbolLine[500 3000 1000 3000 800] + SymbolLine[1000 3000 1500 3500 800] + SymbolLine[1500 3500 2000 3500 800] + SymbolLine[2000 3500 2500 3000 800] +) +Attribute("PCB::grid::unit" "mil") +Via[270000 500000 7874 4000 0 3150 "" ""] + +Element["" "DSUB connector, female/male" "" "DB15F" 20000 50000 5600 0 3 150 ""] +( + Pin[0 0 6000 3000 6600 3500 "1" "1" "square"] + Pin[0 10800 6000 3000 6600 3500 "2" "2" ""] + Pin[0 21600 6000 3000 6600 3500 "3" "3" ""] + Pin[0 32400 6000 3000 6600 3500 "4" "4" ""] + Pin[0 43200 6000 3000 6600 3500 "5" "5" ""] + Pin[0 54000 6000 3000 6600 3500 "6" "6" ""] + Pin[0 64800 6000 3000 6600 3500 "7" "7" ""] + Pin[0 75600 6000 3000 6600 3500 "8" "8" ""] + Pin[11200 5400 6000 3000 6600 3500 "9" "9" ""] + Pin[11200 16200 6000 3000 6600 3500 "10" "10" ""] + Pin[11200 27000 6000 3000 6600 3500 "11" "11" ""] + Pin[11200 37800 6000 3000 6600 3500 "12" "12" ""] + Pin[11200 48600 6000 3000 6600 3500 "13" "13" ""] + Pin[11200 59400 6000 3000 6600 3500 "14" "14" ""] + Pin[11200 70200 6000 3000 6600 3500 "15" "15" ""] + Pin[5600 102600 25000 3000 25600 12500 "C1" "16" ""] + Pin[5600 -27000 25000 3000 25600 12500 "C2" "17" ""] + ElementLine [39100 114600 42100 114600 1000] + ElementLine [39100 -39000 39100 114600 1000] + ElementLine [39100 -39000 42100 -39000 1000] + ElementLine [42100 -39000 42100 114600 1000] + ElementLine [39100 108600 42100 108600 1000] + ElementLine [39100 96600 42100 96600 1000] + ElementLine [39100 -33000 42100 -33000 1000] + ElementLine [39100 -21000 42100 -21000 1000] + ElementLine [28600 91600 39100 91600 2000] + ElementLine [28600 -16000 28600 91600 2000] + ElementLine [28600 -16000 39100 -16000 2000] + ElementLine [39100 -16000 39100 91600 1000] + ElementLine [4000 0 28600 0 2000] + ElementLine [4000 10800 28600 10800 2000] + ElementLine [4000 21600 28600 21600 2000] + ElementLine [4000 32400 28600 32400 2000] + ElementLine [4000 43200 28600 43200 2000] + ElementLine [4000 54000 28600 54000 2000] + ElementLine [4000 64800 28600 64800 2000] + ElementLine [4000 75600 28600 75600 2000] + ElementLine [15200 5400 28600 5400 2000] + ElementLine [15200 16200 28600 16200 2000] + ElementLine [15200 27000 28600 27000 2000] + ElementLine [15200 37800 28600 37800 2000] + ElementLine [15200 48600 28600 48600 2000] + ElementLine [15200 59400 28600 59400 2000] + ElementLine [15200 70200 28600 70200 2000] + + ) + +Element["" "DSUB connector, female/male" "" "DB15M" 110000 50000 -5000 75600 1 150 ""] +( + Pin[600 0 6000 3000 6600 3500 "1" "1" "square"] + Pin[600 10800 6000 3000 6600 3500 "2" "2" ""] + Pin[600 21600 6000 3000 6600 3500 "3" "3" ""] + Pin[600 32400 6000 3000 6600 3500 "4" "4" ""] + Pin[600 43200 6000 3000 6600 3500 "5" "5" ""] + Pin[600 54000 6000 3000 6600 3500 "6" "6" ""] + Pin[600 64800 6000 3000 6600 3500 "7" "7" ""] + Pin[600 75600 6000 3000 6600 3500 "8" "8" ""] + Pin[-10600 5400 6000 3000 6600 3500 "9" "9" ""] + Pin[-10600 16200 6000 3000 6600 3500 "10" "10" ""] + Pin[-10600 27000 6000 3000 6600 3500 "11" "11" ""] + Pin[-10600 37800 6000 3000 6600 3500 "12" "12" ""] + Pin[-10600 48600 6000 3000 6600 3500 "13" "13" ""] + Pin[-10600 59400 6000 3000 6600 3500 "14" "14" ""] + Pin[-10600 70200 6000 3000 6600 3500 "15" "15" ""] + Pin[-5000 -27000 25000 3000 25600 12500 "C1" "16" ""] + Pin[-5000 102600 25000 3000 25600 12500 "C2" "17" ""] + ElementLine [-41500 -39000 -38500 -39000 1000] + ElementLine [-38500 -39000 -38500 114600 1000] + ElementLine [-38500 114600 -41500 114600 1000] + ElementLine [-41500 114600 -41500 -39000 1000] + ElementLine [-41500 -33000 -38500 -33000 1000] + ElementLine [-41500 -21000 -38500 -21000 1000] + ElementLine [-41500 108600 -38500 108600 1000] + ElementLine [-41500 96600 -38500 96600 1000] + ElementLine [-38500 -16000 -28000 -16000 2000] + ElementLine [-28000 -16000 -28000 91600 2000] + ElementLine [-28000 91600 -38500 91600 2000] + ElementLine [-38500 91600 -38500 -16000 1000] + ElementLine [-3400 0 -28000 0 2000] + ElementLine [-3400 10800 -28000 10800 2000] + ElementLine [-3400 21600 -28000 21600 2000] + ElementLine [-3400 32400 -28000 32400 2000] + ElementLine [-3400 43200 -28000 43200 2000] + ElementLine [-3400 54000 -28000 54000 2000] + ElementLine [-3400 64800 -28000 64800 2000] + ElementLine [-3400 75600 -28000 75600 2000] + ElementLine [-14600 5400 -28000 5400 2000] + ElementLine [-14600 16200 -28000 16200 2000] + ElementLine [-14600 27000 -28000 27000 2000] + ElementLine [-14600 37800 -28000 37800 2000] + ElementLine [-14600 48600 -28000 48600 2000] + ElementLine [-14600 59400 -28000 59400 2000] + ElementLine [-14600 70200 -28000 70200 2000] + + ) + +Element["" "DSUB connector, female/male" "" "DB25F" 160000 50000 5600 0 3 150 ""] +( + Pin[0 0 6000 3000 6600 3500 "1" "1" "square"] + Pin[0 10800 6000 3000 6600 3500 "2" "2" ""] + Pin[0 21600 6000 3000 6600 3500 "3" "3" ""] + Pin[0 32400 6000 3000 6600 3500 "4" "4" ""] + Pin[0 43200 6000 3000 6600 3500 "5" "5" ""] + Pin[0 54000 6000 3000 6600 3500 "6" "6" ""] + Pin[0 64800 6000 3000 6600 3500 "7" "7" ""] + Pin[0 75600 6000 3000 6600 3500 "8" "8" ""] + Pin[0 86400 6000 3000 6600 3500 "9" "9" ""] + Pin[0 97200 6000 3000 6600 3500 "10" "10" ""] + Pin[0 108000 6000 3000 6600 3500 "11" "11" ""] + Pin[0 118800 6000 3000 6600 3500 "12" "12" ""] + Pin[0 129600 6000 3000 6600 3500 "13" "13" ""] + Pin[11200 5400 6000 3000 6600 3500 "14" "14" ""] + Pin[11200 16200 6000 3000 6600 3500 "15" "15" ""] + Pin[11200 27000 6000 3000 6600 3500 "16" "16" ""] + Pin[11200 37800 6000 3000 6600 3500 "17" "17" ""] + Pin[11200 48600 6000 3000 6600 3500 "18" "18" ""] + Pin[11200 59400 6000 3000 6600 3500 "19" "19" ""] + Pin[11200 70200 6000 3000 6600 3500 "20" "20" ""] + Pin[11200 81000 6000 3000 6600 3500 "21" "21" ""] + Pin[11200 91800 6000 3000 6600 3500 "22" "22" ""] + Pin[11200 102600 6000 3000 6600 3500 "23" "23" ""] + Pin[11200 113400 6000 3000 6600 3500 "24" "24" ""] + Pin[11200 124200 6000 3000 6600 3500 "25" "25" ""] + Pin[5600 156600 25000 3000 25600 12500 "C1" "26" ""] + Pin[5600 -27000 25000 3000 25600 12500 "C2" "27" ""] + ElementLine [39100 168600 42100 168600 1000] + ElementLine [39100 -39000 39100 168600 1000] + ElementLine [39100 -39000 42100 -39000 1000] + ElementLine [42100 -39000 42100 168600 1000] + ElementLine [39100 162600 42100 162600 1000] + ElementLine [39100 150600 42100 150600 1000] + ElementLine [39100 -33000 42100 -33000 1000] + ElementLine [39100 -21000 42100 -21000 1000] + ElementLine [28600 145600 39100 145600 2000] + ElementLine [28600 -16000 28600 145600 2000] + ElementLine [28600 -16000 39100 -16000 2000] + ElementLine [39100 -16000 39100 145600 1000] + ElementLine [4000 0 28600 0 2000] + ElementLine [4000 10800 28600 10800 2000] + ElementLine [4000 21600 28600 21600 2000] + ElementLine [4000 32400 28600 32400 2000] + ElementLine [4000 43200 28600 43200 2000] + ElementLine [4000 54000 28600 54000 2000] + ElementLine [4000 64800 28600 64800 2000] + ElementLine [4000 75600 28600 75600 2000] + ElementLine [4000 86400 28600 86400 2000] + ElementLine [4000 97200 28600 97200 2000] + ElementLine [4000 108000 28600 108000 2000] + ElementLine [4000 118800 28600 118800 2000] + ElementLine [4000 129600 28600 129600 2000] + ElementLine [15200 5400 28600 5400 2000] + ElementLine [15200 16200 28600 16200 2000] + ElementLine [15200 27000 28600 27000 2000] + ElementLine [15200 37800 28600 37800 2000] + ElementLine [15200 48600 28600 48600 2000] + ElementLine [15200 59400 28600 59400 2000] + ElementLine [15200 70200 28600 70200 2000] + ElementLine [15200 81000 28600 81000 2000] + ElementLine [15200 91800 28600 91800 2000] + ElementLine [15200 102600 28600 102600 2000] + ElementLine [15200 113400 28600 113400 2000] + ElementLine [15200 124200 28600 124200 2000] + + ) + +Element["" "DSUB connector, female/male" "" "DB25M" 250000 50000 -5000 129600 1 150 ""] +( + Pin[600 0 6000 3000 6600 3500 "1" "1" "square"] + Pin[600 10800 6000 3000 6600 3500 "2" "2" ""] + Pin[600 21600 6000 3000 6600 3500 "3" "3" ""] + Pin[600 32400 6000 3000 6600 3500 "4" "4" ""] + Pin[600 43200 6000 3000 6600 3500 "5" "5" ""] + Pin[600 54000 6000 3000 6600 3500 "6" "6" ""] + Pin[600 64800 6000 3000 6600 3500 "7" "7" ""] + Pin[600 75600 6000 3000 6600 3500 "8" "8" ""] + Pin[600 86400 6000 3000 6600 3500 "9" "9" ""] + Pin[600 97200 6000 3000 6600 3500 "10" "10" ""] + Pin[600 108000 6000 3000 6600 3500 "11" "11" ""] + Pin[600 118800 6000 3000 6600 3500 "12" "12" ""] + Pin[600 129600 6000 3000 6600 3500 "13" "13" ""] + Pin[-10600 5400 6000 3000 6600 3500 "14" "14" ""] + Pin[-10600 16200 6000 3000 6600 3500 "15" "15" ""] + Pin[-10600 27000 6000 3000 6600 3500 "16" "16" ""] + Pin[-10600 37800 6000 3000 6600 3500 "17" "17" ""] + Pin[-10600 48600 6000 3000 6600 3500 "18" "18" ""] + Pin[-10600 59400 6000 3000 6600 3500 "19" "19" ""] + Pin[-10600 70200 6000 3000 6600 3500 "20" "20" ""] + Pin[-10600 81000 6000 3000 6600 3500 "21" "21" ""] + Pin[-10600 91800 6000 3000 6600 3500 "22" "22" ""] + Pin[-10600 102600 6000 3000 6600 3500 "23" "23" ""] + Pin[-10600 113400 6000 3000 6600 3500 "24" "24" ""] + Pin[-10600 124200 6000 3000 6600 3500 "25" "25" ""] + Pin[-5000 -27000 25000 3000 25600 12500 "C1" "26" ""] + Pin[-5000 156600 25000 3000 25600 12500 "C2" "27" ""] + ElementLine [-41500 -39000 -38500 -39000 1000] + ElementLine [-38500 -39000 -38500 168600 1000] + ElementLine [-38500 168600 -41500 168600 1000] + ElementLine [-41500 168600 -41500 -39000 1000] + ElementLine [-41500 -33000 -38500 -33000 1000] + ElementLine [-41500 -21000 -38500 -21000 1000] + ElementLine [-41500 162600 -38500 162600 1000] + ElementLine [-41500 150600 -38500 150600 1000] + ElementLine [-38500 -16000 -28000 -16000 2000] + ElementLine [-28000 -16000 -28000 145600 2000] + ElementLine [-28000 145600 -38500 145600 2000] + ElementLine [-38500 145600 -38500 -16000 1000] + ElementLine [-3400 0 -28000 0 2000] + ElementLine [-3400 10800 -28000 10800 2000] + ElementLine [-3400 21600 -28000 21600 2000] + ElementLine [-3400 32400 -28000 32400 2000] + ElementLine [-3400 43200 -28000 43200 2000] + ElementLine [-3400 54000 -28000 54000 2000] + ElementLine [-3400 64800 -28000 64800 2000] + ElementLine [-3400 75600 -28000 75600 2000] + ElementLine [-3400 86400 -28000 86400 2000] + ElementLine [-3400 97200 -28000 97200 2000] + ElementLine [-3400 108000 -28000 108000 2000] + ElementLine [-3400 118800 -28000 118800 2000] + ElementLine [-3400 129600 -28000 129600 2000] + ElementLine [-14600 5400 -28000 5400 2000] + ElementLine [-14600 16200 -28000 16200 2000] + ElementLine [-14600 27000 -28000 27000 2000] + ElementLine [-14600 37800 -28000 37800 2000] + ElementLine [-14600 48600 -28000 48600 2000] + ElementLine [-14600 59400 -28000 59400 2000] + ElementLine [-14600 70200 -28000 70200 2000] + ElementLine [-14600 81000 -28000 81000 2000] + ElementLine [-14600 91800 -28000 91800 2000] + ElementLine [-14600 102600 -28000 102600 2000] + ElementLine [-14600 113400 -28000 113400 2000] + ElementLine [-14600 124200 -28000 124200 2000] + + ) + +Element["" "DSUB connector, female/male" "" "DB37F" 20000 260000 5600 0 3 150 ""] +( + Pin[0 0 6000 3000 6600 3500 "1" "1" "square"] + Pin[0 10800 6000 3000 6600 3500 "2" "2" ""] + Pin[0 21600 6000 3000 6600 3500 "3" "3" ""] + Pin[0 32400 6000 3000 6600 3500 "4" "4" ""] + Pin[0 43200 6000 3000 6600 3500 "5" "5" ""] + Pin[0 54000 6000 3000 6600 3500 "6" "6" ""] + Pin[0 64800 6000 3000 6600 3500 "7" "7" ""] + Pin[0 75600 6000 3000 6600 3500 "8" "8" ""] + Pin[0 86400 6000 3000 6600 3500 "9" "9" ""] + Pin[0 97200 6000 3000 6600 3500 "10" "10" ""] + Pin[0 108000 6000 3000 6600 3500 "11" "11" ""] + Pin[0 118800 6000 3000 6600 3500 "12" "12" ""] + Pin[0 129600 6000 3000 6600 3500 "13" "13" ""] + Pin[0 140400 6000 3000 6600 3500 "14" "14" ""] + Pin[0 151200 6000 3000 6600 3500 "15" "15" ""] + Pin[0 162000 6000 3000 6600 3500 "16" "16" ""] + Pin[0 172800 6000 3000 6600 3500 "17" "17" ""] + Pin[0 183600 6000 3000 6600 3500 "18" "18" ""] + Pin[0 194400 6000 3000 6600 3500 "19" "19" ""] + Pin[11200 5400 6000 3000 6600 3500 "20" "20" ""] + Pin[11200 16200 6000 3000 6600 3500 "21" "21" ""] + Pin[11200 27000 6000 3000 6600 3500 "22" "22" ""] + Pin[11200 37800 6000 3000 6600 3500 "23" "23" ""] + Pin[11200 48600 6000 3000 6600 3500 "24" "24" ""] + Pin[11200 59400 6000 3000 6600 3500 "25" "25" ""] + Pin[11200 70200 6000 3000 6600 3500 "26" "26" ""] + Pin[11200 81000 6000 3000 6600 3500 "27" "27" ""] + Pin[11200 91800 6000 3000 6600 3500 "28" "28" ""] + Pin[11200 102600 6000 3000 6600 3500 "29" "29" ""] + Pin[11200 113400 6000 3000 6600 3500 "30" "30" ""] + Pin[11200 124200 6000 3000 6600 3500 "31" "31" ""] + Pin[11200 135000 6000 3000 6600 3500 "32" "32" ""] + Pin[11200 145800 6000 3000 6600 3500 "33" "33" ""] + Pin[11200 156600 6000 3000 6600 3500 "34" "34" ""] + Pin[11200 167400 6000 3000 6600 3500 "35" "35" ""] + Pin[11200 178200 6000 3000 6600 3500 "36" "36" ""] + Pin[11200 189000 6000 3000 6600 3500 "37" "37" ""] + Pin[5600 221400 25000 3000 25600 12500 "C1" "38" ""] + Pin[5600 -27000 25000 3000 25600 12500 "C2" "39" ""] + ElementLine [39100 233400 42100 233400 1000] + ElementLine [39100 -39000 39100 233400 1000] + ElementLine [39100 -39000 42100 -39000 1000] + ElementLine [42100 -39000 42100 233400 1000] + ElementLine [39100 227400 42100 227400 1000] + ElementLine [39100 215400 42100 215400 1000] + ElementLine [39100 -33000 42100 -33000 1000] + ElementLine [39100 -21000 42100 -21000 1000] + ElementLine [28600 210400 39100 210400 2000] + ElementLine [28600 -16000 28600 210400 2000] + ElementLine [28600 -16000 39100 -16000 2000] + ElementLine [39100 -16000 39100 210400 1000] + ElementLine [4000 0 28600 0 2000] + ElementLine [4000 10800 28600 10800 2000] + ElementLine [4000 21600 28600 21600 2000] + ElementLine [4000 32400 28600 32400 2000] + ElementLine [4000 43200 28600 43200 2000] + ElementLine [4000 54000 28600 54000 2000] + ElementLine [4000 64800 28600 64800 2000] + ElementLine [4000 75600 28600 75600 2000] + ElementLine [4000 86400 28600 86400 2000] + ElementLine [4000 97200 28600 97200 2000] + ElementLine [4000 108000 28600 108000 2000] + ElementLine [4000 118800 28600 118800 2000] + ElementLine [4000 129600 28600 129600 2000] + ElementLine [4000 140400 28600 140400 2000] + ElementLine [4000 151200 28600 151200 2000] + ElementLine [4000 162000 28600 162000 2000] + ElementLine [4000 172800 28600 172800 2000] + ElementLine [4000 183600 28600 183600 2000] + ElementLine [4000 194400 28600 194400 2000] + ElementLine [15200 5400 28600 5400 2000] + ElementLine [15200 16200 28600 16200 2000] + ElementLine [15200 27000 28600 27000 2000] + ElementLine [15200 37800 28600 37800 2000] + ElementLine [15200 48600 28600 48600 2000] + ElementLine [15200 59400 28600 59400 2000] + ElementLine [15200 70200 28600 70200 2000] + ElementLine [15200 81000 28600 81000 2000] + ElementLine [15200 91800 28600 91800 2000] + ElementLine [15200 102600 28600 102600 2000] + ElementLine [15200 113400 28600 113400 2000] + ElementLine [15200 124200 28600 124200 2000] + ElementLine [15200 135000 28600 135000 2000] + ElementLine [15200 145800 28600 145800 2000] + ElementLine [15200 156600 28600 156600 2000] + ElementLine [15200 167400 28600 167400 2000] + ElementLine [15200 178200 28600 178200 2000] + ElementLine [15200 189000 28600 189000 2000] + + ) + +Element["" "DSUB connector, female/male" "" "DB37M" 110000 260000 -5000 194400 1 150 ""] +( + Pin[600 0 6000 3000 6600 3500 "1" "1" "square"] + Pin[600 10800 6000 3000 6600 3500 "2" "2" ""] + Pin[600 21600 6000 3000 6600 3500 "3" "3" ""] + Pin[600 32400 6000 3000 6600 3500 "4" "4" ""] + Pin[600 43200 6000 3000 6600 3500 "5" "5" ""] + Pin[600 54000 6000 3000 6600 3500 "6" "6" ""] + Pin[600 64800 6000 3000 6600 3500 "7" "7" ""] + Pin[600 75600 6000 3000 6600 3500 "8" "8" ""] + Pin[600 86400 6000 3000 6600 3500 "9" "9" ""] + Pin[600 97200 6000 3000 6600 3500 "10" "10" ""] + Pin[600 108000 6000 3000 6600 3500 "11" "11" ""] + Pin[600 118800 6000 3000 6600 3500 "12" "12" ""] + Pin[600 129600 6000 3000 6600 3500 "13" "13" ""] + Pin[600 140400 6000 3000 6600 3500 "14" "14" ""] + Pin[600 151200 6000 3000 6600 3500 "15" "15" ""] + Pin[600 162000 6000 3000 6600 3500 "16" "16" ""] + Pin[600 172800 6000 3000 6600 3500 "17" "17" ""] + Pin[600 183600 6000 3000 6600 3500 "18" "18" ""] + Pin[600 194400 6000 3000 6600 3500 "19" "19" ""] + Pin[-10600 5400 6000 3000 6600 3500 "20" "20" ""] + Pin[-10600 16200 6000 3000 6600 3500 "21" "21" ""] + Pin[-10600 27000 6000 3000 6600 3500 "22" "22" ""] + Pin[-10600 37800 6000 3000 6600 3500 "23" "23" ""] + Pin[-10600 48600 6000 3000 6600 3500 "24" "24" ""] + Pin[-10600 59400 6000 3000 6600 3500 "25" "25" ""] + Pin[-10600 70200 6000 3000 6600 3500 "26" "26" ""] + Pin[-10600 81000 6000 3000 6600 3500 "27" "27" ""] + Pin[-10600 91800 6000 3000 6600 3500 "28" "28" ""] + Pin[-10600 102600 6000 3000 6600 3500 "29" "29" ""] + Pin[-10600 113400 6000 3000 6600 3500 "30" "30" ""] + Pin[-10600 124200 6000 3000 6600 3500 "31" "31" ""] + Pin[-10600 135000 6000 3000 6600 3500 "32" "32" ""] + Pin[-10600 145800 6000 3000 6600 3500 "33" "33" ""] + Pin[-10600 156600 6000 3000 6600 3500 "34" "34" ""] + Pin[-10600 167400 6000 3000 6600 3500 "35" "35" ""] + Pin[-10600 178200 6000 3000 6600 3500 "36" "36" ""] + Pin[-10600 189000 6000 3000 6600 3500 "37" "37" ""] + Pin[-5000 -27000 25000 3000 25600 12500 "C1" "38" ""] + Pin[-5000 221400 25000 3000 25600 12500 "C2" "39" ""] + ElementLine [-41500 -39000 -38500 -39000 1000] + ElementLine [-38500 -39000 -38500 233400 1000] + ElementLine [-38500 233400 -41500 233400 1000] + ElementLine [-41500 233400 -41500 -39000 1000] + ElementLine [-41500 -33000 -38500 -33000 1000] + ElementLine [-41500 -21000 -38500 -21000 1000] + ElementLine [-41500 227400 -38500 227400 1000] + ElementLine [-41500 215400 -38500 215400 1000] + ElementLine [-38500 -16000 -28000 -16000 2000] + ElementLine [-28000 -16000 -28000 210400 2000] + ElementLine [-28000 210400 -38500 210400 2000] + ElementLine [-38500 210400 -38500 -16000 1000] + ElementLine [-3400 0 -28000 0 2000] + ElementLine [-3400 10800 -28000 10800 2000] + ElementLine [-3400 21600 -28000 21600 2000] + ElementLine [-3400 32400 -28000 32400 2000] + ElementLine [-3400 43200 -28000 43200 2000] + ElementLine [-3400 54000 -28000 54000 2000] + ElementLine [-3400 64800 -28000 64800 2000] + ElementLine [-3400 75600 -28000 75600 2000] + ElementLine [-3400 86400 -28000 86400 2000] + ElementLine [-3400 97200 -28000 97200 2000] + ElementLine [-3400 108000 -28000 108000 2000] + ElementLine [-3400 118800 -28000 118800 2000] + ElementLine [-3400 129600 -28000 129600 2000] + ElementLine [-3400 140400 -28000 140400 2000] + ElementLine [-3400 151200 -28000 151200 2000] + ElementLine [-3400 162000 -28000 162000 2000] + ElementLine [-3400 172800 -28000 172800 2000] + ElementLine [-3400 183600 -28000 183600 2000] + ElementLine [-3400 194400 -28000 194400 2000] + ElementLine [-14600 5400 -28000 5400 2000] + ElementLine [-14600 16200 -28000 16200 2000] + ElementLine [-14600 27000 -28000 27000 2000] + ElementLine [-14600 37800 -28000 37800 2000] + ElementLine [-14600 48600 -28000 48600 2000] + ElementLine [-14600 59400 -28000 59400 2000] + ElementLine [-14600 70200 -28000 70200 2000] + ElementLine [-14600 81000 -28000 81000 2000] + ElementLine [-14600 91800 -28000 91800 2000] + ElementLine [-14600 102600 -28000 102600 2000] + ElementLine [-14600 113400 -28000 113400 2000] + ElementLine [-14600 124200 -28000 124200 2000] + ElementLine [-14600 135000 -28000 135000 2000] + ElementLine [-14600 145800 -28000 145800 2000] + ElementLine [-14600 156600 -28000 156600 2000] + ElementLine [-14600 167400 -28000 167400 2000] + ElementLine [-14600 178200 -28000 178200 2000] + ElementLine [-14600 189000 -28000 189000 2000] + + ) + +Element["" "DSUB connector, female/male" "" "DB9F" 160000 290000 5600 0 3 150 ""] +( + Pin[0 0 6000 3000 6600 3500 "1" "1" "square"] + Pin[0 10800 6000 3000 6600 3500 "2" "2" ""] + Pin[0 21600 6000 3000 6600 3500 "3" "3" ""] + Pin[0 32400 6000 3000 6600 3500 "4" "4" ""] + Pin[0 43200 6000 3000 6600 3500 "5" "5" ""] + Pin[11200 5400 6000 3000 6600 3500 "6" "6" ""] + Pin[11200 16200 6000 3000 6600 3500 "7" "7" ""] + Pin[11200 27000 6000 3000 6600 3500 "8" "8" ""] + Pin[11200 37800 6000 3000 6600 3500 "9" "9" ""] + Pin[5600 70200 25000 3000 25600 12500 "C1" "10" ""] + Pin[5600 -27000 25000 3000 25600 12500 "C2" "11" ""] + ElementLine [39100 82200 42100 82200 1000] + ElementLine [39100 -39000 39100 82200 1000] + ElementLine [39100 -39000 42100 -39000 1000] + ElementLine [42100 -39000 42100 82200 1000] + ElementLine [39100 76200 42100 76200 1000] + ElementLine [39100 64200 42100 64200 1000] + ElementLine [39100 -33000 42100 -33000 1000] + ElementLine [39100 -21000 42100 -21000 1000] + ElementLine [28600 59200 39100 59200 2000] + ElementLine [28600 -16000 28600 59200 2000] + ElementLine [28600 -16000 39100 -16000 2000] + ElementLine [39100 -16000 39100 59200 1000] + ElementLine [4000 0 28600 0 2000] + ElementLine [4000 10800 28600 10800 2000] + ElementLine [4000 21600 28600 21600 2000] + ElementLine [4000 32400 28600 32400 2000] + ElementLine [4000 43200 28600 43200 2000] + ElementLine [15200 5400 28600 5400 2000] + ElementLine [15200 16200 28600 16200 2000] + ElementLine [15200 27000 28600 27000 2000] + ElementLine [15200 37800 28600 37800 2000] + + ) + +Element["" "DSUB connector, female/male" "" "DB9M" 250000 290000 -5000 43200 1 150 ""] +( + Pin[600 0 6000 3000 6600 3500 "1" "1" "square"] + Pin[600 10800 6000 3000 6600 3500 "2" "2" ""] + Pin[600 21600 6000 3000 6600 3500 "3" "3" ""] + Pin[600 32400 6000 3000 6600 3500 "4" "4" ""] + Pin[600 43200 6000 3000 6600 3500 "5" "5" ""] + Pin[-10600 5400 6000 3000 6600 3500 "6" "6" ""] + Pin[-10600 16200 6000 3000 6600 3500 "7" "7" ""] + Pin[-10600 27000 6000 3000 6600 3500 "8" "8" ""] + Pin[-10600 37800 6000 3000 6600 3500 "9" "9" ""] + Pin[-5000 -27000 25000 3000 25600 12500 "C1" "10" ""] + Pin[-5000 70200 25000 3000 25600 12500 "C2" "11" ""] + ElementLine [-41500 -39000 -38500 -39000 1000] + ElementLine [-38500 -39000 -38500 82200 1000] + ElementLine [-38500 82200 -41500 82200 1000] + ElementLine [-41500 82200 -41500 -39000 1000] + ElementLine [-41500 -33000 -38500 -33000 1000] + ElementLine [-41500 -21000 -38500 -21000 1000] + ElementLine [-41500 76200 -38500 76200 1000] + ElementLine [-41500 64200 -38500 64200 1000] + ElementLine [-38500 -16000 -28000 -16000 2000] + ElementLine [-28000 -16000 -28000 59200 2000] + ElementLine [-28000 59200 -38500 59200 2000] + ElementLine [-38500 59200 -38500 -16000 1000] + ElementLine [-3400 0 -28000 0 2000] + ElementLine [-3400 10800 -28000 10800 2000] + ElementLine [-3400 21600 -28000 21600 2000] + ElementLine [-3400 32400 -28000 32400 2000] + ElementLine [-3400 43200 -28000 43200 2000] + ElementLine [-14600 5400 -28000 5400 2000] + ElementLine [-14600 16200 -28000 16200 2000] + ElementLine [-14600 27000 -28000 27000 2000] + ElementLine [-14600 37800 -28000 37800 2000] + + ) + +Element["" "right angle BNC" "" "BNC_LAY" 150000 440000 20000 0 3 100 ""] +( + Pin[0 0 6000 3000 6600 3500 "1" "1" "square"] + Pin[0 -10000 6000 3000 6600 3500 "2" "2" ""] + Pin[20000 -20000 10000 3000 10600 8100 "m1" "3" ""] + Pin[20000 20000 10000 3000 10600 8100 "m2" "4" ""] + ElementLine [-6000 -29000 49000 -29000 1000] + ElementLine [49000 -29000 49000 29000 1000] + ElementLine [49000 29000 -6000 29000 1000] + ElementLine [-6000 29000 -6000 -29000 1000] + + ) + +Element["" "" "" "pwrjack" 240000 470000 0 0 0 100 ""] +( + Pin[0 0 19685 2000 20285 11811 "" "2" ""] + Pin[0 -27559 19685 2000 20285 11811 "" "1" ""] + Pin[-17717 -13779 19685 2000 20285 11811 "" "3" ""] + ElementLine [-17717 -55118 -17717 0 1000] + ElementLine [-17717 0 17716 0 1000] + ElementLine [17716 0 17716 -55118 1000] + ElementLine [17716 -55118 -17717 -55118 1000] + ElementLine [-17717 -43307 17716 -43307 1000] + + ) +Layer(1 "component") +( +) +Layer(2 "solder") +( +) +Layer(3 "comp-GND") +( +) +Layer(4 "comp-power") +( +) +Layer(5 "sold-GND") +( +) +Layer(6 "sold-power") +( +) +Layer(7 "signal3") +( +) +Layer(8 "outline") +( +) +Layer(9 "silk") +( +) +Layer(10 "silk") +( +) Index: tags/2.1.2/util/pcblib-map/imgmap_fp.sh =================================================================== --- tags/2.1.2/util/pcblib-map/imgmap_fp.sh (nonexistent) +++ tags/2.1.2/util/pcblib-map/imgmap_fp.sh (revision 24813) @@ -0,0 +1,127 @@ +#!/bin/sh +pcb=$1.pcb + +pcb -x png --dpi 300 --photo-mode $pcb +png=$1.png +html=$1.html + +png_dims=`file $png | awk -F "[,]" '{ sub("x", " ", $2); print $2}'` + + + +awk -v "png_dims=$png_dims" -v "png_url=$png" ' +BEGIN { + q = "\"" + sub("^ *", "", png_dims) + sub(" *$", "", png_dims) + split(png_dims, A, " +") + png_sx = A[1] + png_sy = A[2] + ne = 0 +} + +function bump(idx, x, y) +{ + if ((E[idx, "minx"] == "") || (x < E[idx, "minx"])) + E[idx, "minx"] = x + if ((E[idx, "maxx"] == "") || (x > E[idx, "maxx"])) + E[idx, "maxx"] = x + if ((E[idx, "miny"] == "") || (y < E[idx, "miny"])) + E[idx, "miny"] = y + if ((E[idx, "maxy"] == "") || (y > E[idx, "maxy"])) + E[idx, "maxy"] = y +} + +# Element["" "rcy(150, bar-sign)" "C1" "acy150" 22500 95000 -2000 -4500 1 100 ""] +/^Element *[[]/ { + coords=$0 + sub("Element *[[]", "", coords) + for(n = 1; n <= 4; n++) { + match(coords, "[\"][^\"]*[\"]") + P[n] = substr(coords, RSTART+1, RLENGTH-2) + sub("[\"][^\"]*[\"]", "", coords) + } + split(coords, A, " ") + E[ne, "cmd"] = P[2] + E[ne, "cx"] = A[1] + E[ne, "cy"] = A[2] + E[ne, "file"] = P[4] + ne++ + next +} + +#ElementLine [-11811 -13006 -11811 -11250 3937] +/^[ \t]*ElementLine *[[]/ { + sub("ElementLine *[[]", "", $0) + bump(ne-1, $1, $2) + bump(ne-1, $3, $4) + next +} + +#ElementArc [-11811 -13006 -11811 -11250 3937] +/^[ \t]*ElementArc *[[]/ { + sub("ElementArc *[[]", "", $0) + x = $1 + y = $2 + rx = $3 + ry = $4 + bump(ne-1, x-rx, y-ry) + bump(ne-1, x+rx, y+ry) + next +} + +#Via[260000 120000 7874 4000 0 3150 "" ""] +/^[ \t]*Via *[[]/ { + sub("Via *[[]", "", $0) + pcb_sx = $1 + pcb_sy = $2 + next +} + + +END { + scale_x = png_sx/pcb_sx + scale_y = png_sy/pcb_sy + print "" + print "" + print "" + for(n = 0; n < ne; n++) { +# print E[n, "minx"], E[n, "maxx"], E[n, "miny"], E[n, "maxy"] + x1 = int((E[n, "minx"] + E[n, "cx"]) * scale_x) + x2 = int((E[n, "maxx"] + E[n, "cx"]) * scale_x) + y1 = int((E[n, "miny"] + E[n, "cy"]) * scale_y) + y2 = int((E[n, "maxy"] + E[n, "cy"]) * scale_y) + if (x1 < 0) + x1 = 0 + if (y1 < 0) + y1 = 0 + if (x1 > x2) { + tmp = x1 + x1 = x2 + x2 = tmp + } + if (y1 > y2) { + tmp = y1 + y1 = y2 + y2 = tmp + } + x1 -= 5 + y1 -= 5 + x2 += 5 + y2 += 5 +# print n, x1, y1, x2, y2, E[n, "cmd"] + cmd = E[n, "cmd"] + if (cmd ~ "^[^ ]*[(]") + url="http://igor2.repo.hu/cgi-bin/pcblib-param.cgi?cmd=" cmd + else + url="http://igor2.repo.hu/cgi-bin/pcblib-static.cgi?fp=" E[n, "file"] + gsub(" ", "+", url) + print " q E[n, " + } + print "" + print "" +} + +' < $pcb > $html + + Property changes on: tags/2.1.2/util/pcblib-map/imgmap_fp.sh ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/2.1.2/util/pcblib-map/imgmap_page.sh =================================================================== --- tags/2.1.2/util/pcblib-map/imgmap_page.sh (nonexistent) +++ tags/2.1.2/util/pcblib-map/imgmap_page.sh (revision 24813) @@ -0,0 +1,131 @@ +#!/bin/sh +pcb=$1.pcb + +pcb -x png --dpi 100 --photo-mode $pcb +png=$1.png + +png_dims=`file $png | awk -F "[,]" '{ sub("x", " ", $2); print $2}'` + +awk -v "png_dims=$png_dims" -v "png_url=$png" ' +BEGIN { + q = "\"" + sub("^ *", "", png_dims) + sub(" *$", "", png_dims) + split(png_dims, A, " +") + png_sx = A[1] + png_sy = A[2] + ne = 0 + te = 0 +} + + +# Polygon("clearpoly") +# ( +# [5000 2500] [277500 2500] [277500 547500] [5000 547500] +# ) + +function bump(idx, x, y) +{ + if ((E[idx, "minx"] == "") || (x < E[idx, "minx"])) + E[idx, "minx"] = x + if ((E[idx, "maxx"] == "") || (x > E[idx, "maxx"])) + E[idx, "maxx"] = x + if ((E[idx, "miny"] == "") || (y < E[idx, "miny"])) + E[idx, "miny"] = y + if ((E[idx, "maxy"] == "") || (y > E[idx, "maxy"])) + E[idx, "maxy"] = y +} + +/^[ \t]*Polygon[(]/ { + getline + getline + gsub("[[\\]]", "", $0) + for(n = 1; n < NF; n+=2) + bump(ne, $n, $(n+1)) + ne++ + next +} + +# Text[296338 119704 0 670 "PARAMETRIC" "clearline"] +/^[ \t]*Text[[]/ { + sub("^[ \t]*Text[[]", "", $0) + T[te, "x"] = $1 + T[te, "y"] = $2 + T[te, "text"] = $5 + gsub("[\"]", "", T[te, "text"]) + te++ + next +} + +#Via[260000 120000 7874 4000 0 3150 "" ""] +/^[ \t]*Via *[[]/ { + sub("Via *[[]", "", $0) + pcb_sx = $1 + pcb_sy = $2 + next +} + + +END { + scale_x = png_sx/pcb_sx + scale_y = png_sy/pcb_sy + + print "" + print "" + print "" + for(n = 0; n < ne; n++) { + x1=(E[n, "minx"] + E[n, "cx"]) + x2=(E[n, "maxx"] + E[n, "cx"]) + y1=(E[n, "miny"] + E[n, "cy"]) + y2=(E[n, "maxy"] + E[n, "cy"]) + t = "" + + + for(i = 0; i < te; i++) { + x=T[i, "x"] + y=T[i, "y"] + if ((x>=x1) && (x<=x2) && (y>=y1) && (y<=y2)) { + t = i + break; + } + } +# print n, x1, y1, x2, y2, "|", t, T[t, "x"], T[t, "y"], T[t, "text"] > "/dev/stderr" + + x1 = int(x1 * scale_x) + x2 = int(x2 * scale_x) + y1 = int(y1 * scale_y) + y2 = int(y2 * scale_y) + if (x1 < 0) + x1 = 0 + if (y1 < 0) + y1 = 0 + if (x1 > x2) { + tmp = x1 + x1 = x2 + x2 = tmp + } + if (y1 > y2) { + tmp = y1 + y1 = y2 + y2 = tmp + } + x1 -= 5 + y1 -= 5 + x2 += 5 + y2 += 5 + if (x1 < 0) + x1 = 0 + if (y1 < 0) + y1 = 0 + url="http://igor2.repo.hu/tmp/pcblib/" tolower(T[t, "text"]) ".html" + gsub(" ", "+", url) + print " q T[t, " + T[t, "text"] = "-" + } + print "" + print "" +} + +' < $pcb > map.html + + Property changes on: tags/2.1.2/util/pcblib-map/imgmap_page.sh ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/2.1.2/util/pcblib-map/map.pcb =================================================================== --- tags/2.1.2/util/pcblib-map/map.pcb (nonexistent) +++ tags/2.1.2/util/pcblib-map/map.pcb (revision 24813) @@ -0,0 +1,2737 @@ +# release: pcb 20110918 + +# To read pcb files, the pcb version (or the git source date) must be >= the file version +FileVersion[20070407] + +PCB["" 540000 1120030] + +Grid[2500.0 0 0 1] +Cursor[0 0 0.000000] +PolyArea[3100.006200] +Thermal[0.500000] +DRC[1200 900 1000 700 1500 1000] +Flags("nameonpcb,clearnew,snappin") +Groups("1,3,4,c:2,5,6,s:7:8") +Styles["Signal,1000,7874,3150,2000:Power,2000,8661,3937,2000:Fat,8000,13780,4724,2500:Sig-tight,1000,6400,3150,1200"] + +Symbol[' ' 1800] +( +) +Symbol['!' 1200] +( + SymbolLine[0 4500 0 5000 800] + SymbolLine[0 1000 0 3500 800] +) +Symbol['"' 1200] +( + SymbolLine[0 1000 0 2000 800] + SymbolLine[1000 1000 1000 2000 800] +) +Symbol['#' 1200] +( + SymbolLine[0 3500 2000 3500 800] + SymbolLine[0 2500 2000 2500 800] + SymbolLine[1500 2000 1500 4000 800] + SymbolLine[500 2000 500 4000 800] +) +Symbol['$' 1200] +( + SymbolLine[1500 1500 2000 2000 800] + SymbolLine[500 1500 1500 1500 800] + SymbolLine[0 2000 500 1500 800] + SymbolLine[0 2000 0 2500 800] + SymbolLine[0 2500 500 3000 800] + SymbolLine[500 3000 1500 3000 800] + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[2000 3500 2000 4000 800] + SymbolLine[1500 4500 2000 4000 800] + SymbolLine[500 4500 1500 4500 800] + SymbolLine[0 4000 500 4500 800] + SymbolLine[1000 1000 1000 5000 800] +) +Symbol['%' 1200] +( + SymbolLine[0 1500 0 2000 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 1000 1000 800] + SymbolLine[1000 1000 1500 1500 800] + SymbolLine[1500 1500 1500 2000 800] + SymbolLine[1000 2500 1500 2000 800] + SymbolLine[500 2500 1000 2500 800] + SymbolLine[0 2000 500 2500 800] + SymbolLine[0 5000 4000 1000 800] + SymbolLine[3500 5000 4000 4500 800] + SymbolLine[4000 4000 4000 4500 800] + SymbolLine[3500 3500 4000 4000 800] + SymbolLine[3000 3500 3500 3500 800] + SymbolLine[2500 4000 3000 3500 800] + SymbolLine[2500 4000 2500 4500 800] + SymbolLine[2500 4500 3000 5000 800] + SymbolLine[3000 5000 3500 5000 800] +) +Symbol['&' 1200] +( + SymbolLine[0 4500 500 5000 800] + SymbolLine[0 1500 0 2500 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[0 3500 1500 2000 800] + SymbolLine[500 5000 1000 5000 800] + SymbolLine[1000 5000 2000 4000 800] + SymbolLine[0 2500 2500 5000 800] + SymbolLine[500 1000 1000 1000 800] + SymbolLine[1000 1000 1500 1500 800] + SymbolLine[1500 1500 1500 2000 800] + SymbolLine[0 3500 0 4500 800] +) +Symbol[''' 1200] +( + SymbolLine[0 2000 1000 1000 800] +) +Symbol['(' 1200] +( + SymbolLine[0 4500 500 5000 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[0 1500 0 4500 800] +) +Symbol[')' 1200] +( + SymbolLine[0 1000 500 1500 800] + SymbolLine[500 1500 500 4500 800] + SymbolLine[0 5000 500 4500 800] +) +Symbol['*' 1200] +( + SymbolLine[0 2000 2000 4000 800] + SymbolLine[0 4000 2000 2000 800] + SymbolLine[0 3000 2000 3000 800] + SymbolLine[1000 2000 1000 4000 800] +) +Symbol['+' 1200] +( + SymbolLine[0 3000 2000 3000 800] + SymbolLine[1000 2000 1000 4000 800] +) +Symbol[',' 1200] +( + SymbolLine[0 6000 1000 5000 800] +) +Symbol['-' 1200] +( + SymbolLine[0 3000 2000 3000 800] +) +Symbol['.' 1200] +( + SymbolLine[0 5000 500 5000 800] +) +Symbol['/' 1200] +( + SymbolLine[0 4500 3000 1500 800] +) +Symbol['0' 1200] +( + SymbolLine[0 4500 500 5000 800] + SymbolLine[0 1500 0 4500 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 1500 1000 800] + SymbolLine[1500 1000 2000 1500 800] + SymbolLine[2000 1500 2000 4500 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[0 4000 2000 2000 800] +) +Symbol['1' 1200] +( + SymbolLine[0 1800 800 1000 800] + SymbolLine[800 1000 800 5000 800] + SymbolLine[0 5000 1500 5000 800] +) +Symbol['2' 1200] +( + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 2000 1000 800] + SymbolLine[2000 1000 2500 1500 800] + SymbolLine[2500 1500 2500 2500 800] + SymbolLine[0 5000 2500 2500 800] + SymbolLine[0 5000 2500 5000 800] +) +Symbol['3' 1200] +( + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 1500 1000 800] + SymbolLine[1500 1000 2000 1500 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[500 2800 1500 2800 800] + SymbolLine[2000 1500 2000 2300 800] + SymbolLine[2000 3300 2000 4500 800] + SymbolLine[2000 3300 1500 2800 800] + SymbolLine[2000 2300 1500 2800 800] +) +Symbol['4' 1200] +( + SymbolLine[0 3500 2000 1000 800] + SymbolLine[0 3500 2500 3500 800] + SymbolLine[2000 1000 2000 5000 800] +) +Symbol['5' 1200] +( + SymbolLine[0 1000 2000 1000 800] + SymbolLine[0 1000 0 3000 800] + SymbolLine[0 3000 500 2500 800] + SymbolLine[500 2500 1500 2500 800] + SymbolLine[1500 2500 2000 3000 800] + SymbolLine[2000 3000 2000 4500 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[0 4500 500 5000 800] +) +Symbol['6' 1200] +( + SymbolLine[1500 1000 2000 1500 800] + SymbolLine[500 1000 1500 1000 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[0 1500 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[1500 2800 2000 3300 800] + SymbolLine[0 2800 1500 2800 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[2000 3300 2000 4500 800] +) +Symbol['7' 1200] +( + SymbolLine[500 5000 2500 1000 800] + SymbolLine[0 1000 2500 1000 800] +) +Symbol['8' 1200] +( + SymbolLine[0 4500 500 5000 800] + SymbolLine[0 3700 0 4500 800] + SymbolLine[0 3700 700 3000 800] + SymbolLine[700 3000 1300 3000 800] + SymbolLine[1300 3000 2000 3700 800] + SymbolLine[2000 3700 2000 4500 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[0 2300 700 3000 800] + SymbolLine[0 1500 0 2300 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 1500 1000 800] + SymbolLine[1500 1000 2000 1500 800] + SymbolLine[2000 1500 2000 2300 800] + SymbolLine[1300 3000 2000 2300 800] +) +Symbol['9' 1200] +( + SymbolLine[500 5000 2000 3000 800] + SymbolLine[2000 1500 2000 3000 800] + SymbolLine[1500 1000 2000 1500 800] + SymbolLine[500 1000 1500 1000 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[0 1500 0 2500 800] + SymbolLine[0 2500 500 3000 800] + SymbolLine[500 3000 2000 3000 800] +) +Symbol[':' 1200] +( + SymbolLine[0 2500 500 2500 800] + SymbolLine[0 3500 500 3500 800] +) +Symbol[';' 1200] +( + SymbolLine[0 5000 1000 4000 800] + SymbolLine[1000 2500 1000 3000 800] +) +Symbol['<' 1200] +( + SymbolLine[0 3000 1000 2000 800] + SymbolLine[0 3000 1000 4000 800] +) +Symbol['=' 1200] +( + SymbolLine[0 2500 2000 2500 800] + SymbolLine[0 3500 2000 3500 800] +) +Symbol['>' 1200] +( + SymbolLine[0 2000 1000 3000 800] + SymbolLine[0 4000 1000 3000 800] +) +Symbol['?' 1200] +( + SymbolLine[1000 3000 1000 3500 800] + SymbolLine[1000 4500 1000 5000 800] + SymbolLine[0 1500 0 2000 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 1500 1000 800] + SymbolLine[1500 1000 2000 1500 800] + SymbolLine[2000 1500 2000 2000 800] + SymbolLine[1000 3000 2000 2000 800] +) +Symbol['@' 1200] +( + SymbolLine[0 1000 0 4000 800] + SymbolLine[0 4000 1000 5000 800] + SymbolLine[1000 5000 4000 5000 800] + SymbolLine[5000 3500 5000 1000 800] + SymbolLine[5000 1000 4000 0 800] + SymbolLine[4000 0 1000 0 800] + SymbolLine[1000 0 0 1000 800] + SymbolLine[1500 2000 1500 3000 800] + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[2000 3500 3000 3500 800] + SymbolLine[3000 3500 3500 3000 800] + SymbolLine[3500 3000 4000 3500 800] + SymbolLine[3500 3000 3500 1500 800] + SymbolLine[3500 2000 3000 1500 800] + SymbolLine[2000 1500 3000 1500 800] + SymbolLine[2000 1500 1500 2000 800] + SymbolLine[4000 3500 5000 3500 800] +) +Symbol['A' 1200] +( + SymbolLine[0 2000 0 5000 800] + SymbolLine[0 2000 700 1000 800] + SymbolLine[700 1000 1800 1000 800] + SymbolLine[1800 1000 2500 2000 800] + SymbolLine[2500 2000 2500 5000 800] + SymbolLine[0 3000 2500 3000 800] +) +Symbol['B' 1200] +( + SymbolLine[0 5000 2000 5000 800] + SymbolLine[2000 5000 2500 4500 800] + SymbolLine[2500 3300 2500 4500 800] + SymbolLine[2000 2800 2500 3300 800] + SymbolLine[500 2800 2000 2800 800] + SymbolLine[500 1000 500 5000 800] + SymbolLine[0 1000 2000 1000 800] + SymbolLine[2000 1000 2500 1500 800] + SymbolLine[2500 1500 2500 2300 800] + SymbolLine[2000 2800 2500 2300 800] +) +Symbol['C' 1200] +( + SymbolLine[700 5000 2000 5000 800] + SymbolLine[0 4300 700 5000 800] + SymbolLine[0 1700 0 4300 800] + SymbolLine[0 1700 700 1000 800] + SymbolLine[700 1000 2000 1000 800] +) +Symbol['D' 1200] +( + SymbolLine[500 1000 500 5000 800] + SymbolLine[1800 1000 2500 1700 800] + SymbolLine[2500 1700 2500 4300 800] + SymbolLine[1800 5000 2500 4300 800] + SymbolLine[0 5000 1800 5000 800] + SymbolLine[0 1000 1800 1000 800] +) +Symbol['E' 1200] +( + SymbolLine[0 2800 1500 2800 800] + SymbolLine[0 5000 2000 5000 800] + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 1000 2000 1000 800] +) +Symbol['F' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 1000 2000 1000 800] + SymbolLine[0 2800 1500 2800 800] +) +Symbol['G' 1200] +( + SymbolLine[2000 1000 2500 1500 800] + SymbolLine[500 1000 2000 1000 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[0 1500 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[500 5000 2000 5000 800] + SymbolLine[2000 5000 2500 4500 800] + SymbolLine[2500 3500 2500 4500 800] + SymbolLine[2000 3000 2500 3500 800] + SymbolLine[1000 3000 2000 3000 800] +) +Symbol['H' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[2500 1000 2500 5000 800] + SymbolLine[0 3000 2500 3000 800] +) +Symbol['I' 1200] +( + SymbolLine[0 1000 1000 1000 800] + SymbolLine[500 1000 500 5000 800] + SymbolLine[0 5000 1000 5000 800] +) +Symbol['J' 1200] +( + SymbolLine[700 1000 1500 1000 800] + SymbolLine[1500 1000 1500 4500 800] + SymbolLine[1000 5000 1500 4500 800] + SymbolLine[500 5000 1000 5000 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[0 4500 0 4000 800] +) +Symbol['K' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 3000 2000 1000 800] + SymbolLine[0 3000 2000 5000 800] +) +Symbol['L' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 5000 2000 5000 800] +) +Symbol['M' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 1000 1500 3000 800] + SymbolLine[1500 3000 3000 1000 800] + SymbolLine[3000 1000 3000 5000 800] +) +Symbol['N' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 1000 2500 5000 800] + SymbolLine[2500 1000 2500 5000 800] +) +Symbol['O' 1200] +( + SymbolLine[0 1500 0 4500 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 1500 1000 800] + SymbolLine[1500 1000 2000 1500 800] + SymbolLine[2000 1500 2000 4500 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[0 4500 500 5000 800] +) +Symbol['P' 1200] +( + SymbolLine[500 1000 500 5000 800] + SymbolLine[0 1000 2000 1000 800] + SymbolLine[2000 1000 2500 1500 800] + SymbolLine[2500 1500 2500 2500 800] + SymbolLine[2000 3000 2500 2500 800] + SymbolLine[500 3000 2000 3000 800] +) +Symbol['Q' 1200] +( + SymbolLine[0 1500 0 4500 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 1500 1000 800] + SymbolLine[1500 1000 2000 1500 800] + SymbolLine[2000 1500 2000 4000 800] + SymbolLine[1000 5000 2000 4000 800] + SymbolLine[500 5000 1000 5000 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[1000 3500 2000 5000 800] +) +Symbol['R' 1200] +( + SymbolLine[0 1000 2000 1000 800] + SymbolLine[2000 1000 2500 1500 800] + SymbolLine[2500 1500 2500 2500 800] + SymbolLine[2000 3000 2500 2500 800] + SymbolLine[500 3000 2000 3000 800] + SymbolLine[500 1000 500 5000 800] + SymbolLine[1300 3000 2500 5000 800] +) +Symbol['S' 1200] +( + SymbolLine[2000 1000 2500 1500 800] + SymbolLine[500 1000 2000 1000 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[0 1500 0 2500 800] + SymbolLine[0 2500 500 3000 800] + SymbolLine[500 3000 2000 3000 800] + SymbolLine[2000 3000 2500 3500 800] + SymbolLine[2500 3500 2500 4500 800] + SymbolLine[2000 5000 2500 4500 800] + SymbolLine[500 5000 2000 5000 800] + SymbolLine[0 4500 500 5000 800] +) +Symbol['T' 1200] +( + SymbolLine[0 1000 2000 1000 800] + SymbolLine[1000 1000 1000 5000 800] +) +Symbol['U' 1200] +( + SymbolLine[0 1000 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[2000 1000 2000 4500 800] +) +Symbol['V' 1200] +( + SymbolLine[0 1000 1000 5000 800] + SymbolLine[1000 5000 2000 1000 800] +) +Symbol['W' 1200] +( + SymbolLine[0 1000 0 3000 800] + SymbolLine[0 3000 500 5000 800] + SymbolLine[500 5000 1500 3000 800] + SymbolLine[1500 3000 2500 5000 800] + SymbolLine[2500 5000 3000 3000 800] + SymbolLine[3000 3000 3000 1000 800] +) +Symbol['X' 1200] +( + SymbolLine[0 5000 2500 1000 800] + SymbolLine[0 1000 2500 5000 800] +) +Symbol['Y' 1200] +( + SymbolLine[0 1000 1000 3000 800] + SymbolLine[1000 3000 2000 1000 800] + SymbolLine[1000 3000 1000 5000 800] +) +Symbol['Z' 1200] +( + SymbolLine[0 1000 2500 1000 800] + SymbolLine[0 5000 2500 1000 800] + SymbolLine[0 5000 2500 5000 800] +) +Symbol['[' 1200] +( + SymbolLine[0 1000 500 1000 800] + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 5000 500 5000 800] +) +Symbol['\' 1200] +( + SymbolLine[0 1500 3000 4500 800] +) +Symbol[']' 1200] +( + SymbolLine[0 1000 500 1000 800] + SymbolLine[500 1000 500 5000 800] + SymbolLine[0 5000 500 5000 800] +) +Symbol['^' 1200] +( + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 1000 1500 800] +) +Symbol['_' 1200] +( + SymbolLine[0 5000 2000 5000 800] +) +Symbol['a' 1200] +( + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[500 3000 1500 3000 800] + SymbolLine[0 3500 500 3000 800] + SymbolLine[0 3500 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[2000 3000 2000 4500 800] + SymbolLine[2000 4500 2500 5000 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[1500 5000 2000 4500 800] +) +Symbol['b' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[2000 3500 2000 4500 800] + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[500 3000 1500 3000 800] + SymbolLine[0 3500 500 3000 800] +) +Symbol['c' 1200] +( + SymbolLine[500 3000 2000 3000 800] + SymbolLine[0 3500 500 3000 800] + SymbolLine[0 3500 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[500 5000 2000 5000 800] +) +Symbol['d' 1200] +( + SymbolLine[2000 1000 2000 5000 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[0 3500 0 4500 800] + SymbolLine[0 3500 500 3000 800] + SymbolLine[500 3000 1500 3000 800] + SymbolLine[1500 3000 2000 3500 800] +) +Symbol['e' 1200] +( + SymbolLine[500 5000 2000 5000 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[0 3500 0 4500 800] + SymbolLine[0 3500 500 3000 800] + SymbolLine[500 3000 1500 3000 800] + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[0 4000 2000 4000 800] + SymbolLine[2000 4000 2000 3500 800] +) +Symbol['f' 1000] +( + SymbolLine[500 1500 500 5000 800] + SymbolLine[500 1500 1000 1000 800] + SymbolLine[1000 1000 1500 1000 800] + SymbolLine[0 3000 1000 3000 800] +) +Symbol['g' 1200] +( + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[500 3000 1500 3000 800] + SymbolLine[0 3500 500 3000 800] + SymbolLine[0 3500 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[0 6000 500 6500 800] + SymbolLine[500 6500 1500 6500 800] + SymbolLine[1500 6500 2000 6000 800] + SymbolLine[2000 3000 2000 6000 800] +) +Symbol['h' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 3500 500 3000 800] + SymbolLine[500 3000 1500 3000 800] + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[2000 3500 2000 5000 800] +) +Symbol['i' 1000] +( + SymbolLine[0 2000 0 2100 1000] + SymbolLine[0 3500 0 5000 800] +) +Symbol['j' 1000] +( + SymbolLine[500 2000 500 2100 1000] + SymbolLine[500 3500 500 6000 800] + SymbolLine[0 6500 500 6000 800] +) +Symbol['k' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 3500 1500 5000 800] + SymbolLine[0 3500 1000 2500 800] +) +Symbol['l' 1000] +( + SymbolLine[0 1000 0 4500 800] + SymbolLine[0 4500 500 5000 800] +) +Symbol['m' 1200] +( + SymbolLine[500 3500 500 5000 800] + SymbolLine[500 3500 1000 3000 800] + SymbolLine[1000 3000 1500 3000 800] + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[2000 3500 2000 5000 800] + SymbolLine[2000 3500 2500 3000 800] + SymbolLine[2500 3000 3000 3000 800] + SymbolLine[3000 3000 3500 3500 800] + SymbolLine[3500 3500 3500 5000 800] + SymbolLine[0 3000 500 3500 800] +) +Symbol['n' 1200] +( + SymbolLine[500 3500 500 5000 800] + SymbolLine[500 3500 1000 3000 800] + SymbolLine[1000 3000 1500 3000 800] + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[2000 3500 2000 5000 800] + SymbolLine[0 3000 500 3500 800] +) +Symbol['o' 1200] +( + SymbolLine[0 3500 0 4500 800] + SymbolLine[0 3500 500 3000 800] + SymbolLine[500 3000 1500 3000 800] + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[2000 3500 2000 4500 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[0 4500 500 5000 800] +) +Symbol['p' 1200] +( + SymbolLine[500 3500 500 6500 800] + SymbolLine[0 3000 500 3500 800] + SymbolLine[500 3500 1000 3000 800] + SymbolLine[1000 3000 2000 3000 800] + SymbolLine[2000 3000 2500 3500 800] + SymbolLine[2500 3500 2500 4500 800] + SymbolLine[2000 5000 2500 4500 800] + SymbolLine[1000 5000 2000 5000 800] + SymbolLine[500 4500 1000 5000 800] +) +Symbol['q' 1200] +( + SymbolLine[2000 3500 2000 6500 800] + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[500 3000 1500 3000 800] + SymbolLine[0 3500 500 3000 800] + SymbolLine[0 3500 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[1500 5000 2000 4500 800] +) +Symbol['r' 1200] +( + SymbolLine[500 3500 500 5000 800] + SymbolLine[500 3500 1000 3000 800] + SymbolLine[1000 3000 2000 3000 800] + SymbolLine[0 3000 500 3500 800] +) +Symbol['s' 1200] +( + SymbolLine[500 5000 2000 5000 800] + SymbolLine[2000 5000 2500 4500 800] + SymbolLine[2000 4000 2500 4500 800] + SymbolLine[500 4000 2000 4000 800] + SymbolLine[0 3500 500 4000 800] + SymbolLine[0 3500 500 3000 800] + SymbolLine[500 3000 2000 3000 800] + SymbolLine[2000 3000 2500 3500 800] + SymbolLine[0 4500 500 5000 800] +) +Symbol['t' 1000] +( + SymbolLine[500 1000 500 4500 800] + SymbolLine[500 4500 1000 5000 800] + SymbolLine[0 2500 1000 2500 800] +) +Symbol['u' 1200] +( + SymbolLine[0 3000 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[2000 3000 2000 4500 800] +) +Symbol['v' 1200] +( + SymbolLine[0 3000 1000 5000 800] + SymbolLine[2000 3000 1000 5000 800] +) +Symbol['w' 1200] +( + SymbolLine[0 3000 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[500 5000 1000 5000 800] + SymbolLine[1000 5000 1500 4500 800] + SymbolLine[1500 3000 1500 4500 800] + SymbolLine[1500 4500 2000 5000 800] + SymbolLine[2000 5000 2500 5000 800] + SymbolLine[2500 5000 3000 4500 800] + SymbolLine[3000 3000 3000 4500 800] +) +Symbol['x' 1200] +( + SymbolLine[0 3000 2000 5000 800] + SymbolLine[0 5000 2000 3000 800] +) +Symbol['y' 1200] +( + SymbolLine[0 3000 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[2000 3000 2000 6000 800] + SymbolLine[1500 6500 2000 6000 800] + SymbolLine[500 6500 1500 6500 800] + SymbolLine[0 6000 500 6500 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[1500 5000 2000 4500 800] +) +Symbol['z' 1200] +( + SymbolLine[0 3000 2000 3000 800] + SymbolLine[0 5000 2000 3000 800] + SymbolLine[0 5000 2000 5000 800] +) +Symbol['{' 1200] +( + SymbolLine[500 1500 1000 1000 800] + SymbolLine[500 1500 500 2500 800] + SymbolLine[0 3000 500 2500 800] + SymbolLine[0 3000 500 3500 800] + SymbolLine[500 3500 500 4500 800] + SymbolLine[500 4500 1000 5000 800] +) +Symbol['|' 1200] +( + SymbolLine[0 1000 0 5000 800] +) +Symbol['}' 1200] +( + SymbolLine[0 1000 500 1500 800] + SymbolLine[500 1500 500 2500 800] + SymbolLine[500 2500 1000 3000 800] + SymbolLine[500 3500 1000 3000 800] + SymbolLine[500 3500 500 4500 800] + SymbolLine[0 5000 500 4500 800] +) +Symbol['~' 1200] +( + SymbolLine[0 3500 500 3000 800] + SymbolLine[500 3000 1000 3000 800] + SymbolLine[1000 3000 1500 3500 800] + SymbolLine[1500 3500 2000 3500 800] + SymbolLine[2000 3500 2500 3000 800] +) +Attribute("PCB::grid::unit" "mil") +Via[540000 1120000 7874 4000 0 3150 "" ""] + +Element["" "DSUB connector, female/male" "" "DB15F" 30000 50000 5600 0 3 150 ""] +( + Pin[0 0 6000 3000 6600 3500 "1" "1" "square"] + Pin[0 10800 6000 3000 6600 3500 "2" "2" ""] + Pin[0 21600 6000 3000 6600 3500 "3" "3" ""] + Pin[0 32400 6000 3000 6600 3500 "4" "4" ""] + Pin[0 43200 6000 3000 6600 3500 "5" "5" ""] + Pin[0 54000 6000 3000 6600 3500 "6" "6" ""] + Pin[0 64800 6000 3000 6600 3500 "7" "7" ""] + Pin[0 75600 6000 3000 6600 3500 "8" "8" ""] + Pin[11200 5400 6000 3000 6600 3500 "9" "9" ""] + Pin[11200 16200 6000 3000 6600 3500 "10" "10" ""] + Pin[11200 27000 6000 3000 6600 3500 "11" "11" ""] + Pin[11200 37800 6000 3000 6600 3500 "12" "12" ""] + Pin[11200 48600 6000 3000 6600 3500 "13" "13" ""] + Pin[11200 59400 6000 3000 6600 3500 "14" "14" ""] + Pin[11200 70200 6000 3000 6600 3500 "15" "15" ""] + Pin[5600 102600 25000 3000 25600 12500 "C1" "16" ""] + Pin[5600 -27000 25000 3000 25600 12500 "C2" "17" ""] + ElementLine [39100 114600 42100 114600 1000] + ElementLine [39100 -39000 39100 114600 1000] + ElementLine [39100 -39000 42100 -39000 1000] + ElementLine [42100 -39000 42100 114600 1000] + ElementLine [39100 108600 42100 108600 1000] + ElementLine [39100 96600 42100 96600 1000] + ElementLine [39100 -33000 42100 -33000 1000] + ElementLine [39100 -21000 42100 -21000 1000] + ElementLine [28600 91600 39100 91600 2000] + ElementLine [28600 -16000 28600 91600 2000] + ElementLine [28600 -16000 39100 -16000 2000] + ElementLine [39100 -16000 39100 91600 1000] + ElementLine [4000 0 28600 0 2000] + ElementLine [4000 10800 28600 10800 2000] + ElementLine [4000 21600 28600 21600 2000] + ElementLine [4000 32400 28600 32400 2000] + ElementLine [4000 43200 28600 43200 2000] + ElementLine [4000 54000 28600 54000 2000] + ElementLine [4000 64800 28600 64800 2000] + ElementLine [4000 75600 28600 75600 2000] + ElementLine [15200 5400 28600 5400 2000] + ElementLine [15200 16200 28600 16200 2000] + ElementLine [15200 27000 28600 27000 2000] + ElementLine [15200 37800 28600 37800 2000] + ElementLine [15200 48600 28600 48600 2000] + ElementLine [15200 59400 28600 59400 2000] + ElementLine [15200 70200 28600 70200 2000] + + ) + +Element["" "DSUB connector, female/male" "" "DB15M" 120000 50000 -5000 75600 1 150 ""] +( + Pin[600 0 6000 3000 6600 3500 "1" "1" "square"] + Pin[600 10800 6000 3000 6600 3500 "2" "2" ""] + Pin[600 21600 6000 3000 6600 3500 "3" "3" ""] + Pin[600 32400 6000 3000 6600 3500 "4" "4" ""] + Pin[600 43200 6000 3000 6600 3500 "5" "5" ""] + Pin[600 54000 6000 3000 6600 3500 "6" "6" ""] + Pin[600 64800 6000 3000 6600 3500 "7" "7" ""] + Pin[600 75600 6000 3000 6600 3500 "8" "8" ""] + Pin[-10600 5400 6000 3000 6600 3500 "9" "9" ""] + Pin[-10600 16200 6000 3000 6600 3500 "10" "10" ""] + Pin[-10600 27000 6000 3000 6600 3500 "11" "11" ""] + Pin[-10600 37800 6000 3000 6600 3500 "12" "12" ""] + Pin[-10600 48600 6000 3000 6600 3500 "13" "13" ""] + Pin[-10600 59400 6000 3000 6600 3500 "14" "14" ""] + Pin[-10600 70200 6000 3000 6600 3500 "15" "15" ""] + Pin[-5000 -27000 25000 3000 25600 12500 "C1" "16" ""] + Pin[-5000 102600 25000 3000 25600 12500 "C2" "17" ""] + ElementLine [-41500 -39000 -38500 -39000 1000] + ElementLine [-38500 -39000 -38500 114600 1000] + ElementLine [-38500 114600 -41500 114600 1000] + ElementLine [-41500 114600 -41500 -39000 1000] + ElementLine [-41500 -33000 -38500 -33000 1000] + ElementLine [-41500 -21000 -38500 -21000 1000] + ElementLine [-41500 108600 -38500 108600 1000] + ElementLine [-41500 96600 -38500 96600 1000] + ElementLine [-38500 -16000 -28000 -16000 2000] + ElementLine [-28000 -16000 -28000 91600 2000] + ElementLine [-28000 91600 -38500 91600 2000] + ElementLine [-38500 91600 -38500 -16000 1000] + ElementLine [-3400 0 -28000 0 2000] + ElementLine [-3400 10800 -28000 10800 2000] + ElementLine [-3400 21600 -28000 21600 2000] + ElementLine [-3400 32400 -28000 32400 2000] + ElementLine [-3400 43200 -28000 43200 2000] + ElementLine [-3400 54000 -28000 54000 2000] + ElementLine [-3400 64800 -28000 64800 2000] + ElementLine [-3400 75600 -28000 75600 2000] + ElementLine [-14600 5400 -28000 5400 2000] + ElementLine [-14600 16200 -28000 16200 2000] + ElementLine [-14600 27000 -28000 27000 2000] + ElementLine [-14600 37800 -28000 37800 2000] + ElementLine [-14600 48600 -28000 48600 2000] + ElementLine [-14600 59400 -28000 59400 2000] + ElementLine [-14600 70200 -28000 70200 2000] + + ) + +Element["" "DSUB connector, female/male" "" "DB25F" 170000 50000 5600 0 3 150 ""] +( + Pin[0 0 6000 3000 6600 3500 "1" "1" "square"] + Pin[0 10800 6000 3000 6600 3500 "2" "2" ""] + Pin[0 21600 6000 3000 6600 3500 "3" "3" ""] + Pin[0 32400 6000 3000 6600 3500 "4" "4" ""] + Pin[0 43200 6000 3000 6600 3500 "5" "5" ""] + Pin[0 54000 6000 3000 6600 3500 "6" "6" ""] + Pin[0 64800 6000 3000 6600 3500 "7" "7" ""] + Pin[0 75600 6000 3000 6600 3500 "8" "8" ""] + Pin[0 86400 6000 3000 6600 3500 "9" "9" ""] + Pin[0 97200 6000 3000 6600 3500 "10" "10" ""] + Pin[0 108000 6000 3000 6600 3500 "11" "11" ""] + Pin[0 118800 6000 3000 6600 3500 "12" "12" ""] + Pin[0 129600 6000 3000 6600 3500 "13" "13" ""] + Pin[11200 5400 6000 3000 6600 3500 "14" "14" ""] + Pin[11200 16200 6000 3000 6600 3500 "15" "15" ""] + Pin[11200 27000 6000 3000 6600 3500 "16" "16" ""] + Pin[11200 37800 6000 3000 6600 3500 "17" "17" ""] + Pin[11200 48600 6000 3000 6600 3500 "18" "18" ""] + Pin[11200 59400 6000 3000 6600 3500 "19" "19" ""] + Pin[11200 70200 6000 3000 6600 3500 "20" "20" ""] + Pin[11200 81000 6000 3000 6600 3500 "21" "21" ""] + Pin[11200 91800 6000 3000 6600 3500 "22" "22" ""] + Pin[11200 102600 6000 3000 6600 3500 "23" "23" ""] + Pin[11200 113400 6000 3000 6600 3500 "24" "24" ""] + Pin[11200 124200 6000 3000 6600 3500 "25" "25" ""] + Pin[5600 156600 25000 3000 25600 12500 "C1" "26" ""] + Pin[5600 -27000 25000 3000 25600 12500 "C2" "27" ""] + ElementLine [39100 168600 42100 168600 1000] + ElementLine [39100 -39000 39100 168600 1000] + ElementLine [39100 -39000 42100 -39000 1000] + ElementLine [42100 -39000 42100 168600 1000] + ElementLine [39100 162600 42100 162600 1000] + ElementLine [39100 150600 42100 150600 1000] + ElementLine [39100 -33000 42100 -33000 1000] + ElementLine [39100 -21000 42100 -21000 1000] + ElementLine [28600 145600 39100 145600 2000] + ElementLine [28600 -16000 28600 145600 2000] + ElementLine [28600 -16000 39100 -16000 2000] + ElementLine [39100 -16000 39100 145600 1000] + ElementLine [4000 0 28600 0 2000] + ElementLine [4000 10800 28600 10800 2000] + ElementLine [4000 21600 28600 21600 2000] + ElementLine [4000 32400 28600 32400 2000] + ElementLine [4000 43200 28600 43200 2000] + ElementLine [4000 54000 28600 54000 2000] + ElementLine [4000 64800 28600 64800 2000] + ElementLine [4000 75600 28600 75600 2000] + ElementLine [4000 86400 28600 86400 2000] + ElementLine [4000 97200 28600 97200 2000] + ElementLine [4000 108000 28600 108000 2000] + ElementLine [4000 118800 28600 118800 2000] + ElementLine [4000 129600 28600 129600 2000] + ElementLine [15200 5400 28600 5400 2000] + ElementLine [15200 16200 28600 16200 2000] + ElementLine [15200 27000 28600 27000 2000] + ElementLine [15200 37800 28600 37800 2000] + ElementLine [15200 48600 28600 48600 2000] + ElementLine [15200 59400 28600 59400 2000] + ElementLine [15200 70200 28600 70200 2000] + ElementLine [15200 81000 28600 81000 2000] + ElementLine [15200 91800 28600 91800 2000] + ElementLine [15200 102600 28600 102600 2000] + ElementLine [15200 113400 28600 113400 2000] + ElementLine [15200 124200 28600 124200 2000] + + ) + +Element["" "DSUB connector, female/male" "" "DB25M" 260000 50000 -5000 129600 1 150 ""] +( + Pin[600 0 6000 3000 6600 3500 "1" "1" "square"] + Pin[600 10800 6000 3000 6600 3500 "2" "2" ""] + Pin[600 21600 6000 3000 6600 3500 "3" "3" ""] + Pin[600 32400 6000 3000 6600 3500 "4" "4" ""] + Pin[600 43200 6000 3000 6600 3500 "5" "5" ""] + Pin[600 54000 6000 3000 6600 3500 "6" "6" ""] + Pin[600 64800 6000 3000 6600 3500 "7" "7" ""] + Pin[600 75600 6000 3000 6600 3500 "8" "8" ""] + Pin[600 86400 6000 3000 6600 3500 "9" "9" ""] + Pin[600 97200 6000 3000 6600 3500 "10" "10" ""] + Pin[600 108000 6000 3000 6600 3500 "11" "11" ""] + Pin[600 118800 6000 3000 6600 3500 "12" "12" ""] + Pin[600 129600 6000 3000 6600 3500 "13" "13" ""] + Pin[-10600 5400 6000 3000 6600 3500 "14" "14" ""] + Pin[-10600 16200 6000 3000 6600 3500 "15" "15" ""] + Pin[-10600 27000 6000 3000 6600 3500 "16" "16" ""] + Pin[-10600 37800 6000 3000 6600 3500 "17" "17" ""] + Pin[-10600 48600 6000 3000 6600 3500 "18" "18" ""] + Pin[-10600 59400 6000 3000 6600 3500 "19" "19" ""] + Pin[-10600 70200 6000 3000 6600 3500 "20" "20" ""] + Pin[-10600 81000 6000 3000 6600 3500 "21" "21" ""] + Pin[-10600 91800 6000 3000 6600 3500 "22" "22" ""] + Pin[-10600 102600 6000 3000 6600 3500 "23" "23" ""] + Pin[-10600 113400 6000 3000 6600 3500 "24" "24" ""] + Pin[-10600 124200 6000 3000 6600 3500 "25" "25" ""] + Pin[-5000 -27000 25000 3000 25600 12500 "C1" "26" ""] + Pin[-5000 156600 25000 3000 25600 12500 "C2" "27" ""] + ElementLine [-41500 -39000 -38500 -39000 1000] + ElementLine [-38500 -39000 -38500 168600 1000] + ElementLine [-38500 168600 -41500 168600 1000] + ElementLine [-41500 168600 -41500 -39000 1000] + ElementLine [-41500 -33000 -38500 -33000 1000] + ElementLine [-41500 -21000 -38500 -21000 1000] + ElementLine [-41500 162600 -38500 162600 1000] + ElementLine [-41500 150600 -38500 150600 1000] + ElementLine [-38500 -16000 -28000 -16000 2000] + ElementLine [-28000 -16000 -28000 145600 2000] + ElementLine [-28000 145600 -38500 145600 2000] + ElementLine [-38500 145600 -38500 -16000 1000] + ElementLine [-3400 0 -28000 0 2000] + ElementLine [-3400 10800 -28000 10800 2000] + ElementLine [-3400 21600 -28000 21600 2000] + ElementLine [-3400 32400 -28000 32400 2000] + ElementLine [-3400 43200 -28000 43200 2000] + ElementLine [-3400 54000 -28000 54000 2000] + ElementLine [-3400 64800 -28000 64800 2000] + ElementLine [-3400 75600 -28000 75600 2000] + ElementLine [-3400 86400 -28000 86400 2000] + ElementLine [-3400 97200 -28000 97200 2000] + ElementLine [-3400 108000 -28000 108000 2000] + ElementLine [-3400 118800 -28000 118800 2000] + ElementLine [-3400 129600 -28000 129600 2000] + ElementLine [-14600 5400 -28000 5400 2000] + ElementLine [-14600 16200 -28000 16200 2000] + ElementLine [-14600 27000 -28000 27000 2000] + ElementLine [-14600 37800 -28000 37800 2000] + ElementLine [-14600 48600 -28000 48600 2000] + ElementLine [-14600 59400 -28000 59400 2000] + ElementLine [-14600 70200 -28000 70200 2000] + ElementLine [-14600 81000 -28000 81000 2000] + ElementLine [-14600 91800 -28000 91800 2000] + ElementLine [-14600 102600 -28000 102600 2000] + ElementLine [-14600 113400 -28000 113400 2000] + ElementLine [-14600 124200 -28000 124200 2000] + + ) + +Element["" "DSUB connector, female/male" "" "DB37F" 30000 260000 5600 0 3 150 ""] +( + Pin[0 0 6000 3000 6600 3500 "1" "1" "square"] + Pin[0 10800 6000 3000 6600 3500 "2" "2" ""] + Pin[0 21600 6000 3000 6600 3500 "3" "3" ""] + Pin[0 32400 6000 3000 6600 3500 "4" "4" ""] + Pin[0 43200 6000 3000 6600 3500 "5" "5" ""] + Pin[0 54000 6000 3000 6600 3500 "6" "6" ""] + Pin[0 64800 6000 3000 6600 3500 "7" "7" ""] + Pin[0 75600 6000 3000 6600 3500 "8" "8" ""] + Pin[0 86400 6000 3000 6600 3500 "9" "9" ""] + Pin[0 97200 6000 3000 6600 3500 "10" "10" ""] + Pin[0 108000 6000 3000 6600 3500 "11" "11" ""] + Pin[0 118800 6000 3000 6600 3500 "12" "12" ""] + Pin[0 129600 6000 3000 6600 3500 "13" "13" ""] + Pin[0 140400 6000 3000 6600 3500 "14" "14" ""] + Pin[0 151200 6000 3000 6600 3500 "15" "15" ""] + Pin[0 162000 6000 3000 6600 3500 "16" "16" ""] + Pin[0 172800 6000 3000 6600 3500 "17" "17" ""] + Pin[0 183600 6000 3000 6600 3500 "18" "18" ""] + Pin[0 194400 6000 3000 6600 3500 "19" "19" ""] + Pin[11200 5400 6000 3000 6600 3500 "20" "20" ""] + Pin[11200 16200 6000 3000 6600 3500 "21" "21" ""] + Pin[11200 27000 6000 3000 6600 3500 "22" "22" ""] + Pin[11200 37800 6000 3000 6600 3500 "23" "23" ""] + Pin[11200 48600 6000 3000 6600 3500 "24" "24" ""] + Pin[11200 59400 6000 3000 6600 3500 "25" "25" ""] + Pin[11200 70200 6000 3000 6600 3500 "26" "26" ""] + Pin[11200 81000 6000 3000 6600 3500 "27" "27" ""] + Pin[11200 91800 6000 3000 6600 3500 "28" "28" ""] + Pin[11200 102600 6000 3000 6600 3500 "29" "29" ""] + Pin[11200 113400 6000 3000 6600 3500 "30" "30" ""] + Pin[11200 124200 6000 3000 6600 3500 "31" "31" ""] + Pin[11200 135000 6000 3000 6600 3500 "32" "32" ""] + Pin[11200 145800 6000 3000 6600 3500 "33" "33" ""] + Pin[11200 156600 6000 3000 6600 3500 "34" "34" ""] + Pin[11200 167400 6000 3000 6600 3500 "35" "35" ""] + Pin[11200 178200 6000 3000 6600 3500 "36" "36" ""] + Pin[11200 189000 6000 3000 6600 3500 "37" "37" ""] + Pin[5600 221400 25000 3000 25600 12500 "C1" "38" ""] + Pin[5600 -27000 25000 3000 25600 12500 "C2" "39" ""] + ElementLine [39100 233400 42100 233400 1000] + ElementLine [39100 -39000 39100 233400 1000] + ElementLine [39100 -39000 42100 -39000 1000] + ElementLine [42100 -39000 42100 233400 1000] + ElementLine [39100 227400 42100 227400 1000] + ElementLine [39100 215400 42100 215400 1000] + ElementLine [39100 -33000 42100 -33000 1000] + ElementLine [39100 -21000 42100 -21000 1000] + ElementLine [28600 210400 39100 210400 2000] + ElementLine [28600 -16000 28600 210400 2000] + ElementLine [28600 -16000 39100 -16000 2000] + ElementLine [39100 -16000 39100 210400 1000] + ElementLine [4000 0 28600 0 2000] + ElementLine [4000 10800 28600 10800 2000] + ElementLine [4000 21600 28600 21600 2000] + ElementLine [4000 32400 28600 32400 2000] + ElementLine [4000 43200 28600 43200 2000] + ElementLine [4000 54000 28600 54000 2000] + ElementLine [4000 64800 28600 64800 2000] + ElementLine [4000 75600 28600 75600 2000] + ElementLine [4000 86400 28600 86400 2000] + ElementLine [4000 97200 28600 97200 2000] + ElementLine [4000 108000 28600 108000 2000] + ElementLine [4000 118800 28600 118800 2000] + ElementLine [4000 129600 28600 129600 2000] + ElementLine [4000 140400 28600 140400 2000] + ElementLine [4000 151200 28600 151200 2000] + ElementLine [4000 162000 28600 162000 2000] + ElementLine [4000 172800 28600 172800 2000] + ElementLine [4000 183600 28600 183600 2000] + ElementLine [4000 194400 28600 194400 2000] + ElementLine [15200 5400 28600 5400 2000] + ElementLine [15200 16200 28600 16200 2000] + ElementLine [15200 27000 28600 27000 2000] + ElementLine [15200 37800 28600 37800 2000] + ElementLine [15200 48600 28600 48600 2000] + ElementLine [15200 59400 28600 59400 2000] + ElementLine [15200 70200 28600 70200 2000] + ElementLine [15200 81000 28600 81000 2000] + ElementLine [15200 91800 28600 91800 2000] + ElementLine [15200 102600 28600 102600 2000] + ElementLine [15200 113400 28600 113400 2000] + ElementLine [15200 124200 28600 124200 2000] + ElementLine [15200 135000 28600 135000 2000] + ElementLine [15200 145800 28600 145800 2000] + ElementLine [15200 156600 28600 156600 2000] + ElementLine [15200 167400 28600 167400 2000] + ElementLine [15200 178200 28600 178200 2000] + ElementLine [15200 189000 28600 189000 2000] + + ) + +Element["" "DSUB connector, female/male" "" "DB37M" 120000 260000 -5000 194400 1 150 ""] +( + Pin[600 0 6000 3000 6600 3500 "1" "1" "square"] + Pin[600 10800 6000 3000 6600 3500 "2" "2" ""] + Pin[600 21600 6000 3000 6600 3500 "3" "3" ""] + Pin[600 32400 6000 3000 6600 3500 "4" "4" ""] + Pin[600 43200 6000 3000 6600 3500 "5" "5" ""] + Pin[600 54000 6000 3000 6600 3500 "6" "6" ""] + Pin[600 64800 6000 3000 6600 3500 "7" "7" ""] + Pin[600 75600 6000 3000 6600 3500 "8" "8" ""] + Pin[600 86400 6000 3000 6600 3500 "9" "9" ""] + Pin[600 97200 6000 3000 6600 3500 "10" "10" ""] + Pin[600 108000 6000 3000 6600 3500 "11" "11" ""] + Pin[600 118800 6000 3000 6600 3500 "12" "12" ""] + Pin[600 129600 6000 3000 6600 3500 "13" "13" ""] + Pin[600 140400 6000 3000 6600 3500 "14" "14" ""] + Pin[600 151200 6000 3000 6600 3500 "15" "15" ""] + Pin[600 162000 6000 3000 6600 3500 "16" "16" ""] + Pin[600 172800 6000 3000 6600 3500 "17" "17" ""] + Pin[600 183600 6000 3000 6600 3500 "18" "18" ""] + Pin[600 194400 6000 3000 6600 3500 "19" "19" ""] + Pin[-10600 5400 6000 3000 6600 3500 "20" "20" ""] + Pin[-10600 16200 6000 3000 6600 3500 "21" "21" ""] + Pin[-10600 27000 6000 3000 6600 3500 "22" "22" ""] + Pin[-10600 37800 6000 3000 6600 3500 "23" "23" ""] + Pin[-10600 48600 6000 3000 6600 3500 "24" "24" ""] + Pin[-10600 59400 6000 3000 6600 3500 "25" "25" ""] + Pin[-10600 70200 6000 3000 6600 3500 "26" "26" ""] + Pin[-10600 81000 6000 3000 6600 3500 "27" "27" ""] + Pin[-10600 91800 6000 3000 6600 3500 "28" "28" ""] + Pin[-10600 102600 6000 3000 6600 3500 "29" "29" ""] + Pin[-10600 113400 6000 3000 6600 3500 "30" "30" ""] + Pin[-10600 124200 6000 3000 6600 3500 "31" "31" ""] + Pin[-10600 135000 6000 3000 6600 3500 "32" "32" ""] + Pin[-10600 145800 6000 3000 6600 3500 "33" "33" ""] + Pin[-10600 156600 6000 3000 6600 3500 "34" "34" ""] + Pin[-10600 167400 6000 3000 6600 3500 "35" "35" ""] + Pin[-10600 178200 6000 3000 6600 3500 "36" "36" ""] + Pin[-10600 189000 6000 3000 6600 3500 "37" "37" ""] + Pin[-5000 -27000 25000 3000 25600 12500 "C1" "38" ""] + Pin[-5000 221400 25000 3000 25600 12500 "C2" "39" ""] + ElementLine [-41500 -39000 -38500 -39000 1000] + ElementLine [-38500 -39000 -38500 233400 1000] + ElementLine [-38500 233400 -41500 233400 1000] + ElementLine [-41500 233400 -41500 -39000 1000] + ElementLine [-41500 -33000 -38500 -33000 1000] + ElementLine [-41500 -21000 -38500 -21000 1000] + ElementLine [-41500 227400 -38500 227400 1000] + ElementLine [-41500 215400 -38500 215400 1000] + ElementLine [-38500 -16000 -28000 -16000 2000] + ElementLine [-28000 -16000 -28000 210400 2000] + ElementLine [-28000 210400 -38500 210400 2000] + ElementLine [-38500 210400 -38500 -16000 1000] + ElementLine [-3400 0 -28000 0 2000] + ElementLine [-3400 10800 -28000 10800 2000] + ElementLine [-3400 21600 -28000 21600 2000] + ElementLine [-3400 32400 -28000 32400 2000] + ElementLine [-3400 43200 -28000 43200 2000] + ElementLine [-3400 54000 -28000 54000 2000] + ElementLine [-3400 64800 -28000 64800 2000] + ElementLine [-3400 75600 -28000 75600 2000] + ElementLine [-3400 86400 -28000 86400 2000] + ElementLine [-3400 97200 -28000 97200 2000] + ElementLine [-3400 108000 -28000 108000 2000] + ElementLine [-3400 118800 -28000 118800 2000] + ElementLine [-3400 129600 -28000 129600 2000] + ElementLine [-3400 140400 -28000 140400 2000] + ElementLine [-3400 151200 -28000 151200 2000] + ElementLine [-3400 162000 -28000 162000 2000] + ElementLine [-3400 172800 -28000 172800 2000] + ElementLine [-3400 183600 -28000 183600 2000] + ElementLine [-3400 194400 -28000 194400 2000] + ElementLine [-14600 5400 -28000 5400 2000] + ElementLine [-14600 16200 -28000 16200 2000] + ElementLine [-14600 27000 -28000 27000 2000] + ElementLine [-14600 37800 -28000 37800 2000] + ElementLine [-14600 48600 -28000 48600 2000] + ElementLine [-14600 59400 -28000 59400 2000] + ElementLine [-14600 70200 -28000 70200 2000] + ElementLine [-14600 81000 -28000 81000 2000] + ElementLine [-14600 91800 -28000 91800 2000] + ElementLine [-14600 102600 -28000 102600 2000] + ElementLine [-14600 113400 -28000 113400 2000] + ElementLine [-14600 124200 -28000 124200 2000] + ElementLine [-14600 135000 -28000 135000 2000] + ElementLine [-14600 145800 -28000 145800 2000] + ElementLine [-14600 156600 -28000 156600 2000] + ElementLine [-14600 167400 -28000 167400 2000] + ElementLine [-14600 178200 -28000 178200 2000] + ElementLine [-14600 189000 -28000 189000 2000] + + ) + +Element["" "DSUB connector, female/male" "" "DB9F" 170000 290000 5600 0 3 150 ""] +( + Pin[0 0 6000 3000 6600 3500 "1" "1" "square"] + Pin[0 10800 6000 3000 6600 3500 "2" "2" ""] + Pin[0 21600 6000 3000 6600 3500 "3" "3" ""] + Pin[0 32400 6000 3000 6600 3500 "4" "4" ""] + Pin[0 43200 6000 3000 6600 3500 "5" "5" ""] + Pin[11200 5400 6000 3000 6600 3500 "6" "6" ""] + Pin[11200 16200 6000 3000 6600 3500 "7" "7" ""] + Pin[11200 27000 6000 3000 6600 3500 "8" "8" ""] + Pin[11200 37800 6000 3000 6600 3500 "9" "9" ""] + Pin[5600 70200 25000 3000 25600 12500 "C1" "10" ""] + Pin[5600 -27000 25000 3000 25600 12500 "C2" "11" ""] + ElementLine [39100 82200 42100 82200 1000] + ElementLine [39100 -39000 39100 82200 1000] + ElementLine [39100 -39000 42100 -39000 1000] + ElementLine [42100 -39000 42100 82200 1000] + ElementLine [39100 76200 42100 76200 1000] + ElementLine [39100 64200 42100 64200 1000] + ElementLine [39100 -33000 42100 -33000 1000] + ElementLine [39100 -21000 42100 -21000 1000] + ElementLine [28600 59200 39100 59200 2000] + ElementLine [28600 -16000 28600 59200 2000] + ElementLine [28600 -16000 39100 -16000 2000] + ElementLine [39100 -16000 39100 59200 1000] + ElementLine [4000 0 28600 0 2000] + ElementLine [4000 10800 28600 10800 2000] + ElementLine [4000 21600 28600 21600 2000] + ElementLine [4000 32400 28600 32400 2000] + ElementLine [4000 43200 28600 43200 2000] + ElementLine [15200 5400 28600 5400 2000] + ElementLine [15200 16200 28600 16200 2000] + ElementLine [15200 27000 28600 27000 2000] + ElementLine [15200 37800 28600 37800 2000] + + ) + +Element["" "DSUB connector, female/male" "" "DB9M" 260000 290000 -5000 43200 1 150 ""] +( + Pin[600 0 6000 3000 6600 3500 "1" "1" "square"] + Pin[600 10800 6000 3000 6600 3500 "2" "2" ""] + Pin[600 21600 6000 3000 6600 3500 "3" "3" ""] + Pin[600 32400 6000 3000 6600 3500 "4" "4" ""] + Pin[600 43200 6000 3000 6600 3500 "5" "5" ""] + Pin[-10600 5400 6000 3000 6600 3500 "6" "6" ""] + Pin[-10600 16200 6000 3000 6600 3500 "7" "7" ""] + Pin[-10600 27000 6000 3000 6600 3500 "8" "8" ""] + Pin[-10600 37800 6000 3000 6600 3500 "9" "9" ""] + Pin[-5000 -27000 25000 3000 25600 12500 "C1" "10" ""] + Pin[-5000 70200 25000 3000 25600 12500 "C2" "11" ""] + ElementLine [-41500 -39000 -38500 -39000 1000] + ElementLine [-38500 -39000 -38500 82200 1000] + ElementLine [-38500 82200 -41500 82200 1000] + ElementLine [-41500 82200 -41500 -39000 1000] + ElementLine [-41500 -33000 -38500 -33000 1000] + ElementLine [-41500 -21000 -38500 -21000 1000] + ElementLine [-41500 76200 -38500 76200 1000] + ElementLine [-41500 64200 -38500 64200 1000] + ElementLine [-38500 -16000 -28000 -16000 2000] + ElementLine [-28000 -16000 -28000 59200 2000] + ElementLine [-28000 59200 -38500 59200 2000] + ElementLine [-38500 59200 -38500 -16000 1000] + ElementLine [-3400 0 -28000 0 2000] + ElementLine [-3400 10800 -28000 10800 2000] + ElementLine [-3400 21600 -28000 21600 2000] + ElementLine [-3400 32400 -28000 32400 2000] + ElementLine [-3400 43200 -28000 43200 2000] + ElementLine [-14600 5400 -28000 5400 2000] + ElementLine [-14600 16200 -28000 16200 2000] + ElementLine [-14600 27000 -28000 27000 2000] + ElementLine [-14600 37800 -28000 37800 2000] + + ) + +Element["" "right angle BNC" "" "BNC_LAY" 152500 442500 20000 0 3 100 ""] +( + Pin[0 0 6000 3000 6600 3500 "1" "1" "square"] + Pin[0 -10000 6000 3000 6600 3500 "2" "2" ""] + Pin[20000 -20000 10000 3000 10600 8100 "m1" "3" ""] + Pin[20000 20000 10000 3000 10600 8100 "m2" "4" ""] + ElementLine [-6000 -29000 49000 -29000 1000] + ElementLine [49000 -29000 49000 29000 1000] + ElementLine [49000 29000 -6000 29000 1000] + ElementLine [-6000 29000 -6000 -29000 1000] + + ) + +Element["" "rcy(150, bar-sign)" "C1" "acy150" 302500 95000 -2000 -4500 1 100 ""] +( + Pin[0 0 8000 5000 8600 3937 "" "1" "square"] + Pin[0 -15000 8000 5000 8600 3937 "" "2" ""] + ElementLine [0 -28500 0 -24500 1000] + ElementLine [0 9500 0 13500 1000] + ElementLine [-2000 11500 2000 11500 1000] + ElementLine [7874 -17883 7874 -11250 3937] + ElementLine [-7874 -17883 -7874 -11250 3937] + ElementLine [9842 -16040 9842 -11250 3937] + ElementLine [-9842 -16040 -9842 -11250 3937] + ElementLine [11811 -13006 11811 -11250 3937] + ElementLine [-11811 -13006 -11811 -11250 3937] + ElementArc [0 -7500 15000 15000 90 360 1000] + + ) + +Element["" "so(8)" "" "8*250" 337500 82500 -10000 0 1 100 ""] +( + Pad[-7500 7000 -7500 13500 2000 1000 3000 "" "1" "square,edge2"] + Pad[-7500 -13500 -7500 -7000 2000 1000 3000 "" "8" "square"] + Pad[-2500 7000 -2500 13500 2000 1000 3000 "" "2" "square,edge2"] + Pad[-2500 -13500 -2500 -7000 2000 1000 3000 "" "7" "square"] + Pad[2500 7000 2500 13500 2000 1000 3000 "" "3" "square,edge2"] + Pad[2500 -13500 2500 -7000 2000 1000 3000 "" "6" "square"] + Pad[7500 7000 7500 13500 2000 1000 3000 "" "4" "square,edge2"] + Pad[7500 -13500 7500 -7000 2000 1000 3000 "" "5" "square"] + ElementLine [-10000 16000 10000 16000 1000] + ElementLine [10000 -16000 10000 16000 1000] + ElementLine [-10000 -16000 10000 -16000 1000] + ElementLine [-10000 2500 -10000 16000 1000] + ElementLine [-10000 -16000 -10000 -2500 1000] + ElementArc [-10000 0 2500 2500 90 180 1000] + + ) + +Element["" "dip(4)" "" "4*300" 365000 102500 -10000 0 1 100 ""] +( + Pin[0 0 8000 5000 8600 3937 "" "1" "square"] + Pin[0 -30000 8000 5000 8600 3937 "" "4" ""] + Pin[10000 0 8000 5000 8600 3937 "" "2" ""] + Pin[10000 -30000 8000 5000 8600 3937 "" "3" ""] + ElementLine [-5000 5000 15000 5000 1000] + ElementLine [15000 -35000 15000 5000 1000] + ElementLine [-5000 -35000 15000 -35000 1000] + ElementLine [-5000 -10000 -5000 5000 1000] + ElementLine [-5000 -35000 -5000 -20000 1000] + ElementArc [-5000 -15000 5000 5000 90 180 1000] + + ) + +Element["" "tssop(8)" "" "8*6.4mm" 397500 82500 -10000 0 1 100 ""] +( + Pad[-3838 10236 -3838 14173 1771 1000 3000 "" "1" "square,edge2"] + Pad[-3838 -14173 -3838 -10236 1771 1000 3000 "" "8" "square"] + Pad[-1278 10236 -1278 14173 1771 1000 3000 "" "2" "square,edge2"] + Pad[-1278 -14173 -1278 -10236 1771 1000 3000 "" "7" "square"] + Pad[1280 10236 1280 14173 1771 1000 3000 "" "3" "square,edge2"] + Pad[1280 -14173 1280 -10236 1771 1000 3000 "" "6" "square"] + Pad[3839 10236 3839 14173 1771 1000 3000 "" "4" "square,edge2"] + Pad[3839 -14173 3839 -10236 1771 1000 3000 "" "5" "square"] + ElementLine [-6038 15973 6039 15973 1000] + ElementLine [6039 -15973 6039 15973 1000] + ElementLine [-6038 -15973 6039 -15973 1000] + ElementLine [-6038 2500 -6038 15973 1000] + ElementLine [-6038 -15973 -6038 -2500 1000] + ElementArc [-6038 0 2500 2500 90 180 1000] + + ) + +Element["" "connector(2,3)" "" "2*3" 422500 72500 0 -10000 0 100 ""] +( + Pin[0 0 8000 5000 8600 3937 "" "1" "square"] + Pin[0 10000 8000 5000 8600 3937 "" "2" ""] + Pin[0 20000 8000 5000 8600 3937 "" "3" ""] + Pin[10000 0 8000 5000 8600 3937 "" "4" ""] + Pin[10000 10000 8000 5000 8600 3937 "" "5" ""] + Pin[10000 20000 8000 5000 8600 3937 "" "6" ""] + ElementLine [-5000 -5000 -5000 25000 1000] + ElementLine [-5000 -5000 15000 -5000 1000] + ElementLine [15000 25000 -5000 25000 1000] + ElementLine [15000 25000 15000 -5000 1000] + ElementLine [-5000 5000 5000 5000 1000] + ElementLine [5000 -5000 5000 5000 1000] + + ) + +Element["" "connector(2,3,eshift=x)" "" "2*3" 455000 72500 0 -10000 0 100 ""] +( + Pin[0 0 8000 5000 8600 3937 "" "1" "square"] + Pin[0 10000 8000 5000 8600 3937 "" "2" ""] + Pin[0 20000 8000 5000 8600 3937 "" "3" ""] + Pin[10000 5000 8000 5000 8600 3937 "" "4" ""] + Pin[10000 15000 8000 5000 8600 3937 "" "5" ""] + Pin[10000 25000 8000 5000 8600 3937 "" "6" ""] + ElementLine [-5000 -5000 -5000 30000 1000] + ElementLine [-5000 -5000 15000 -5000 1000] + ElementLine [15000 30000 -5000 30000 1000] + ElementLine [15000 30000 15000 -5000 1000] + ElementLine [-5000 5000 5000 5000 1000] + ElementLine [5000 -5000 5000 5000 1000] + + ) + +Element["" "connector(2,3,eshift=x,etrunc=1)" "" "2*3" 487500 72500 0 -10000 0 100 ""] +( + Pin[0 0 8000 5000 8600 3937 "" "1" "square"] + Pin[0 10000 8000 5000 8600 3937 "" "2" ""] + Pin[0 20000 8000 5000 8600 3937 "" "3" ""] + Pin[10000 5000 8000 5000 8600 3937 "" "4" ""] + Pin[10000 15000 8000 5000 8600 3937 "" "5" ""] + ElementLine [-5000 -5000 -5000 25000 1000] + ElementLine [-5000 -5000 15000 -5000 1000] + ElementLine [15000 25000 -5000 25000 1000] + ElementLine [15000 25000 15000 -5000 1000] + ElementLine [-5000 5000 5000 5000 1000] + ElementLine [5000 -5000 5000 5000 1000] + + ) + +Element["" "acy(300)" "" "acy300" 300000 50000 -12000 -9000 1 100 ""] +( + Pin[0 0 8000 5000 8600 3937 "" "1" "square"] + Pin[0 -30000 8000 5000 8600 3937 "" "2" ""] + ElementLine [0 -7500 0 0 1000] + ElementLine [0 -30000 0 -22500 1000] + ElementLine [-2500 -7500 2500 -7500 1000] + ElementLine [-2500 -22500 -2500 -7500 1000] + ElementLine [2500 -22500 2500 -7500 1000] + ElementLine [-2500 -22500 2500 -22500 1000] + + ) + +Element["" "acy(300, endcap)" "" "acy300" 320000 50000 -2000 -9000 1 100 ""] +( + Pin[0 0 8000 5000 8600 3937 "" "1" "square"] + Pin[0 -30000 8000 5000 8600 3937 "" "2" ""] + ElementLine [0 -7500 0 0 1000] + ElementLine [0 -30000 0 -22500 1000] + ElementLine [2500 -20625 2500 -9375 1000] + ElementLine [2500 -9375 3000 -9166 1000] + ElementLine [2500 -20625 3000 -20833 1000] + ElementLine [-2500 -20625 -2500 -9375 1000] + ElementLine [-2500 -9375 -3000 -9166 1000] + ElementLine [-2500 -20625 -3000 -20833 1000] + ElementLine [-2500 -7500 2500 -7500 1000] + ElementLine [-3000 -9166 -3000 -8000 1000] + ElementLine [3000 -9166 3000 -8000 1000] + ElementLine [-3000 -22000 -3000 -20833 1000] + ElementLine [3000 -22000 3000 -20833 1000] + ElementLine [-2500 -22500 2500 -22500 1000] + ElementArc [-2500 -8000 500 500 0 90 1000] + ElementArc [2500 -8000 500 500 90 90 1000] + ElementArc [-2500 -22000 500 500 270 90 1000] + ElementArc [2500 -22000 500 500 180 90 1000] + + ) + +Element["" "acy(300, coil, dot)" "" "acy300" 340000 50000 -2000 -9000 1 100 ""] +( + Pin[0 0 8000 5000 8600 3937 "" "1" "square"] + Pin[0 -30000 8000 5000 8600 3937 "" "2" ""] + ElementLine [0 -7500 0 0 1000] + ElementLine [0 -30000 0 -22500 1000] + ElementArc [0 -9375 1875 1875 270 180 1000] + ElementArc [0 -13125 1875 1875 270 180 1000] + ElementArc [0 -16875 1875 1875 270 180 1000] + ElementArc [0 -20625 1875 1875 270 180 1000] + ElementArc [-1250 -5500 666 666 90 360 1000] + + ) + +Element["" "acy(300, pol=bar)" "" "acy300" 360000 50000 -2000 -9000 1 100 ""] +( + Pin[0 0 8000 5000 8600 3937 "" "1" "square"] + Pin[0 -30000 8000 5000 8600 3937 "" "2" ""] + ElementLine [0 -7500 0 0 1000] + ElementLine [0 -30000 0 -22500 1000] + ElementLine [-2500 -7500 2500 -7500 1000] + ElementLine [-2500 -22500 -2500 -7500 1000] + ElementLine [2500 -22500 2500 -7500 1000] + ElementLine [-2500 -22500 2500 -22500 1000] + ElementLine [-2500 -6500 2500 -6500 1000] + ElementLine [-2500 -8500 -2500 -6500 1000] + ElementLine [2500 -8500 2500 -6500 1000] + ElementLine [-2500 -8500 2500 -8500 1000] + + ) + +Element["" "acy(300, wiper=aarrow)" "" "acy300" 380000 50000 -2000 -9000 1 100 ""] +( + Pin[0 0 9000 5000 9600 3937 "" "1" "square"] + Pin[0 -30000 8000 5000 8600 3937 "" "2" ""] + ElementLine [0 -7500 0 0 1000] + ElementLine [0 -30000 0 -22500 1000] + ElementLine [-2500 -7500 2500 -7500 1000] + ElementLine [-2500 -22500 -2500 -7500 1000] + ElementLine [2500 -22500 2500 -7500 1000] + ElementLine [-2500 -22500 2500 -22500 1000] + ElementLine [5000 -12500 -8000 -17500 1000] + ElementLine [-8000 -17500 -6492 -15848 1000] + ElementLine [-8000 -17500 -5774 -17715 1000] + ElementLine [-5774 -17715 -6492 -15848 1000] + + ) + +Element["" "acy(300, wiper=parrow)" "" "acy300" 400000 50000 -2000 -9000 1 100 ""] +( + Pin[0 0 8000 5000 8600 3937 "" "1" "square"] + Pin[0 -30000 8000 5000 8600 3937 "" "2" ""] + ElementLine [0 -7500 0 0 1000] + ElementLine [0 -30000 0 -22500 1000] + ElementLine [-2500 -7500 2500 -7500 1000] + ElementLine [-2500 -22500 -2500 -7500 1000] + ElementLine [2500 -22500 2500 -7500 1000] + ElementLine [-2500 -22500 2500 -22500 1000] + ElementLine [-8000 -15000 -2500 -15000 1000] + ElementLine [-2500 -15000 -4500 -16000 1000] + ElementLine [-2500 -15000 -4500 -14000 1000] + ElementLine [-4500 -16000 -4500 -14000 1000] + + ) + +Element["" "acy(300, wiper=looparrow)" "" "acy300" 420000 50000 -2000 -9000 1 100 ""] +( + Pin[0 0 8000 5000 8600 3937 "" "1" "square"] + Pin[0 -30000 8000 5000 8600 3937 "" "2" ""] + ElementLine [0 -7500 0 0 1000] + ElementLine [0 -30000 0 -22500 1000] + ElementLine [-2500 -7500 2500 -7500 1000] + ElementLine [-2500 -22500 -2500 -7500 1000] + ElementLine [2500 -22500 2500 -7500 1000] + ElementLine [-2500 -22500 2500 -22500 1000] + ElementLine [-8000 -15000 -2500 -15000 1000] + ElementLine [-2500 -15000 -4500 -16000 1000] + ElementLine [-2500 -15000 -4500 -14000 1000] + ElementLine [-4500 -16000 -4500 -14000 1000] + ElementLine [-8000 -24375 -8000 -15000 1000] + ElementLine [-8000 -24375 0 -24375 1000] + + ) + +Element["" "acy(300, zigzag)" "" "acy300" 440000 50000 -2000 -9000 1 100 ""] +( + Pin[0 0 8000 5000 8600 3937 "" "1" "square"] + Pin[0 -30000 8000 5000 8600 3937 "" "2" ""] + ElementLine [0 -7500 0 0 1000] + ElementLine [0 -30000 0 -22500 1000] + ElementLine [0 -7500 -2500 -8750 1000] + ElementLine [-2500 -8750 2500 -11250 1000] + ElementLine [2500 -11250 0 -12500 1000] + ElementLine [0 -12500 -2500 -13750 1000] + ElementLine [-2500 -13750 2500 -16250 1000] + ElementLine [2500 -16250 0 -17500 1000] + ElementLine [0 -17500 -2500 -18750 1000] + ElementLine [-2500 -18750 2500 -21250 1000] + ElementLine [2500 -21250 0 -22500 1000] + + ) + +Element["" "acy(300, core)" "" "acy300" 460000 50000 -2000 -9000 1 100 ""] +( + Pin[0 0 8000 5000 8600 3937 "" "1" "square"] + Pin[0 -30000 8000 5000 8600 3937 "" "2" ""] + ElementLine [0 -7500 0 0 1000] + ElementLine [0 -30000 0 -22500 1000] + ElementLine [-4875 -22500 -4875 -7500 1000] + ElementArc [0 -9375 1875 1875 270 180 1000] + ElementArc [0 -13125 1875 1875 270 180 1000] + ElementArc [0 -16875 1875 1875 270 180 1000] + ElementArc [0 -20625 1875 1875 270 180 1000] + + ) + +Element["" "acy(200, standing, pol=sign, dia=100)" "" "acy200" 520000 90000 -2000 -6000 1 100 ""] +( + Pin[0 0 8000 5000 8600 3937 "" "1" "square"] + Pin[0 -20000 8000 5000 8600 3937 "" "2" ""] + ElementLine [0 -5000 0 0 1000] + ElementLine [0 -20000 0 -15000 1000] + ElementLine [0 -20000 0 0 1000] + ElementLine [2200 -6100 2200 -4100 1000] + ElementLine [2200 -15900 2200 -13900 1000] + ElementLine [1200 -14900 3200 -14900 1000] + ElementArc [0 0 10000 10000 90 360 1000] + + ) + +Element["" "alf(300,schottky)" "" "acy300" 480000 50000 -5000 -22000 1 100 ""] +( + Pin[0 0 8000 5000 8600 3937 "" "1" "square"] + Pin[0 -30000 8000 5000 8600 3937 "" "2" ""] + ElementLine [0 -10000 0 0 1000] + ElementLine [0 -30000 0 -20000 1000] + ElementLine [-5000 -20000 5000 -20000 1000] + ElementLine [-5000 -20000 0 -10000 1000] + ElementLine [5000 -20000 0 -10000 1000] + ElementLine [-3500 -10000 3500 -10000 1000] + ElementArc [-3500 -11500 1500 1500 270 180 1000] + ElementArc [3500 -8500 1500 1500 90 180 1000] + + ) + +Element["" "alf(300,tunnel)" "" "acy300" 500000 50000 -5000 -22000 1 100 ""] +( + Pin[0 0 8000 5000 8600 3937 "" "1" "square"] + Pin[0 -30000 8000 5000 8600 3937 "" "2" ""] + ElementLine [0 -10000 0 0 1000] + ElementLine [0 -30000 0 -20000 1000] + ElementLine [-5000 -20000 5000 -20000 1000] + ElementLine [-5000 -20000 0 -10000 1000] + ElementLine [5000 -20000 0 -10000 1000] + ElementLine [-5000 -10000 5000 -10000 1000] + ElementLine [5000 -11500 5000 -10000 1000] + ElementLine [-5000 -11500 -5000 -10000 1000] + + ) + +Element["" "alf(300,zener)" "" "acy300" 520000 50000 -5000 -22000 1 100 ""] +( + Pin[0 0 8000 5000 8600 3937 "" "1" "square"] + Pin[0 -30000 8000 5000 8600 3937 "" "2" ""] + ElementLine [0 -10000 0 0 1000] + ElementLine [0 -30000 0 -20000 1000] + ElementLine [-5000 -20000 5000 -20000 1000] + ElementLine [-5000 -20000 0 -10000 1000] + ElementLine [5000 -20000 0 -10000 1000] + ElementLine [-5000 -10000 5000 -10000 1000] + ElementLine [5000 -10000 5000 -8500 1000] + ElementLine [-5000 -11500 -5000 -10000 1000] + + ) + +Element["" "SMT transistor, 3 pins" "" "SC70_3" 315000 420000 9300 -9400 3 100 ""] +( + Pad[0 -300 0 300 2900 3000 3500 "1" "1" "square,edge2"] + Pad[5100 -300 5100 300 2900 3000 3500 "2" "2" "square,edge2"] + Pad[2600 -7300 2600 -6700 2900 3000 3500 "3" "3" "square"] + ElementLine [-2100 -9400 -2100 2500 1000] + ElementLine [-2100 2500 7300 2500 1000] + ElementLine [7300 2500 7300 -9400 1000] + ElementLine [7300 -9400 -2100 -9400 1000] + + ) + +Element["" "SMT transistor, 3 pins" "" "SC90" 330000 420000 7600 -7800 3 100 ""] +( + Pad[0 -200 0 200 2400 3000 3000 "1" "1" "square,edge2"] + Pad[3900 -200 3900 200 2400 3000 3000 "2" "2" "square,edge2"] + Pad[1900 -6100 1900 -5700 2400 3000 3000 "3" "3" "square"] + ElementLine [-1700 -7800 -1700 2000 1000] + ElementLine [-1700 2000 5600 2000 1000] + ElementLine [5600 2000 5600 -7800 1000] + ElementLine [5600 -7800 -1700 -7800 1000] + + ) + +Element["" "SMT transistor, 3 pins" "" "SOT23" 311100 453200 12300 -11000 3 100 ""] +( + Pad[0 -300 0 300 3400 3000 4000 "1" "1" "square,edge2"] + Pad[7800 -300 7800 300 3400 3000 4000 "2" "2" "square,edge2"] + Pad[3900 -8500 3900 -7900 3400 3000 4000 "3" "3" "square"] + ElementLine [-2500 -11000 -2500 2900 1000] + ElementLine [-2500 2900 10300 2900 1000] + ElementLine [10300 2900 10300 -11000 1000] + ElementLine [10300 -11000 -2500 -11000 1000] + + ) + +Element["" "SMT diode (pin 1 is cathode)" "" "SOT23D" 311100 473200 12300 -11000 3 100 ""] +( + Pad[0 -300 0 300 3400 3000 4000 "2" "2" "square,edge2"] + Pad[7800 -300 7800 300 3400 3000 4000 "3" "3" "square,edge2"] + Pad[3900 -8500 3900 -7900 3400 3000 4000 "1" "1" "square"] + ElementLine [-2500 -11000 -2500 2900 1000] + ElementLine [-2500 2900 10300 2900 1000] + ElementLine [10300 2900 10300 -11000 1000] + ElementLine [10300 -11000 -2500 -11000 1000] + + ) + +Element["" "SMT transistor, 3 pins" "" "SOT323" 332400 452000 9300 -9400 3 100 ""] +( + Pad[0 -300 0 300 2900 3000 3500 "1" "1" "square,edge2"] + Pad[5100 -300 5100 300 2900 3000 3500 "2" "2" "square,edge2"] + Pad[2600 -7300 2600 -6700 2900 3000 3500 "3" "3" "square"] + ElementLine [-2100 -9400 -2100 2500 1000] + ElementLine [-2100 2500 7300 2500 1000] + ElementLine [7300 2500 7300 -9400 1000] + ElementLine [7300 -9400 -2100 -9400 1000] + + ) + +Element["" "SMT diode (pin 1 is cathode)" "" "SOT323D" 332400 472000 9300 -9400 3 100 ""] +( + Pad[0 -300 0 300 2900 3000 3500 "2" "2" "square,edge2"] + Pad[5100 -300 5100 300 2900 3000 3500 "3" "3" "square,edge2"] + Pad[2600 -7300 2600 -6700 2900 3000 3500 "1" "1" "square"] + ElementLine [-2100 -9400 -2100 2500 1000] + ElementLine [-2100 2500 7300 2500 1000] + ElementLine [7300 2500 7300 -9400 1000] + ElementLine [7300 -9400 -2100 -9400 1000] + + ) + +Element["" "SMT transistor, 4 pins" "" "SC70_4" 415000 435000 9300 -9400 3 100 ""] +( + Pad[300 0 600 0 2900 3000 3500 "1" "1" "square"] + Pad[5100 -300 5100 300 2900 3000 3500 "2" "2" "square,edge2"] + Pad[5100 -7300 5100 -6700 2900 3000 3500 "3" "3" "square"] + Pad[0 -7300 0 -6700 2900 3000 3500 "4" "4" "square"] + ElementLine [-2100 -9400 -2100 2500 1000] + ElementLine [-2100 2500 7300 2500 1000] + ElementLine [7300 2500 7300 -9400 1000] + ElementLine [7300 -9400 -2100 -9400 1000] + + ) + +Element["" "Pressure transducer" "" "MPAK" 485000 480000 20300 -49700 3 100 ""] +( + Pad[0 -2800 0 2800 3100 3000 3700 "1" "1" "square,edge2"] + Pad[5000 -2800 5000 2800 3100 3000 3700 "2" "2" "square,edge2"] + Pad[10000 -2800 10000 2800 3100 3000 3700 "3" "3" "square,edge2"] + Pad[15000 -2800 15000 2800 3100 3000 3700 "4" "4" "square,edge2"] + Pad[3800 -43700 11200 -43700 8700 3000 9300 "5" "5" "square"] + ElementLine [-3200 -49700 -3200 6100 1000] + ElementLine [-3200 6100 18300 6100 1000] + ElementLine [18300 6100 18300 -49700 1000] + ElementLine [18300 -49700 -3200 -49700 1000] + + ) + +Element["" "SMT transistor, 4 pins" "" "SOT143" 430000 435000 11900 -11000 3 100 ""] +( + Pad[300 0 600 0 3400 3000 4000 "1" "1" "square"] + Pad[7400 -300 7400 300 3400 3000 4000 "2" "2" "square,edge2"] + Pad[7400 -8500 7400 -7900 3400 3000 4000 "3" "3" "square"] + Pad[0 -8500 0 -7900 3400 3000 4000 "4" "4" "square"] + ElementLine [-2500 -11000 -2500 2900 1000] + ElementLine [-2500 2900 9900 2900 1000] + ElementLine [9900 2900 9900 -11000 1000] + ElementLine [9900 -11000 -2500 -11000 1000] + + ) + +Element["" "SMT transistor, 4 pins" "" "SOT223" 450000 480000 25300 -32900 3 100 ""] +( + Pad[0 -3300 0 3300 5600 3000 6200 "1" "1" "square,edge2"] + Pad[9000 -3300 9000 3300 5600 3000 6200 "2" "2" "square,edge2"] + Pad[18100 -3300 18100 3300 5600 3000 6200 "3" "3" "square,edge2"] + Pad[4500 -24400 13500 -24400 12200 3000 12800 "4" "4" "square"] + ElementLine [-5200 -32900 -5200 8500 1000] + ElementLine [-5200 8500 23300 8500 1000] + ElementLine [23300 8500 23300 -32900 1000] + ElementLine [23300 -32900 -5200 -32900 1000] + + ) + +Element["" "SMT transistor, 5 pins" "" "SOT25" 445000 435000 11800 -11000 3 100 ""] +( + Pad[0 -800 0 800 2400 3000 3000 "1" "1" "square,edge2"] + Pad[7800 -800 7800 800 2400 3000 3000 "2" "2" "square,edge2"] + Pad[7800 -9000 7800 -7400 2400 3000 3000 "3" "3" "square"] + Pad[3900 -9000 3900 -7400 2400 3000 3000 "4" "4" "square"] + Pad[0 -9000 0 -7400 2400 3000 3000 "5" "5" "square"] + ElementLine [-2000 -11000 -2000 2900 1000] + ElementLine [-2000 2900 9800 2900 1000] + ElementLine [9800 2900 9800 -11000 1000] + ElementLine [9800 -11000 -2000 -11000 1000] + + ) + +Element["" "SMT transistor, 6 pins" "" "SOT26" 461100 435000 11800 -11000 3 100 ""] +( + Pad[0 -800 0 800 2400 3000 3000 "1" "1" "square,edge2"] + Pad[3900 -800 3900 800 2400 3000 3000 "2" "2" "square,edge2"] + Pad[7800 -800 7800 800 2400 3000 3000 "3" "3" "square,edge2"] + Pad[7800 -9000 7800 -7400 2400 3000 3000 "4" "4" "square"] + Pad[3900 -9000 3900 -7400 2400 3000 3000 "5" "5" "square"] + Pad[0 -9000 0 -7400 2400 3000 3000 "6" "6" "square"] + ElementLine [-2000 -11000 -2000 2900 1000] + ElementLine [-2000 2900 9800 2900 1000] + ElementLine [9800 2900 9800 -11000 1000] + ElementLine [9800 -11000 -2000 -11000 1000] + + ) + +Element["" "SMT transistor, 5 pins" "" "SOT325" 419900 485000 8600 -9400 3 100 ""] +( + Pad[0 -1000 0 1000 1500 3000 2100 "1" "1" "square,edge2"] + Pad[5100 -1000 5100 1000 1500 3000 2100 "2" "2" "square,edge2"] + Pad[5100 -8000 5100 -6000 1500 3000 2100 "3" "3" "square"] + Pad[2600 -8000 2600 -6000 1500 3000 2100 "4" "4" "square"] + Pad[0 -8000 0 -6000 1500 3000 2100 "5" "5" "square"] + ElementLine [-1400 -9400 -1400 2500 1000] + ElementLine [-1400 2500 6600 2500 1000] + ElementLine [6600 2500 6600 -9400 1000] + ElementLine [6600 -9400 -1400 -9400 1000] + + ) + +Element["" "SMT transistor, 6 pins" "" "SOT326" 432400 485000 8600 -9400 3 100 ""] +( + Pad[0 -1000 0 1000 1500 3000 2100 "1" "1" "square,edge2"] + Pad[2600 -1000 2600 1000 1500 3000 2100 "2" "2" "square,edge2"] + Pad[5100 -1000 5100 1000 1500 3000 2100 "3" "3" "square,edge2"] + Pad[5100 -8000 5100 -6000 1500 3000 2100 "4" "4" "square"] + Pad[2600 -8000 2600 -6000 1500 3000 2100 "5" "5" "square"] + Pad[0 -8000 0 -6000 1500 3000 2100 "6" "6" "square"] + ElementLine [-1400 -9400 -1400 2500 1000] + ElementLine [-1400 2500 6600 2500 1000] + ElementLine [6600 2500 6600 -9400 1000] + ElementLine [6600 -9400 -1400 -9400 1000] + + ) + +Element["" "SMT transistor, 4 pins" "" "SOT89" 418900 465000 17300 -16400 3 100 ""] +( + Pad[0 -1200 0 1200 3700 3000 4300 "1" "1" "square,edge2"] + Pad[6100 -1200 6100 1200 3700 3000 4300 "2" "2" "square,edge2"] + Pad[12200 -1200 12200 1200 3700 3000 4300 "3" "3" "square,edge2"] + Pad[3100 -12200 9100 -12200 6100 3000 6700 "4" "4" "square"] + ElementLine [-3000 -16400 -3000 4300 1000] + ElementLine [-3000 4300 15300 4300 1000] + ElementLine [15300 4300 15300 -16400 1000] + ElementLine [15300 -16400 -3000 -16400 1000] + + ) + +Element["" "Crystals" "" "HC49U_3" 30000 620000 -15100 12100 1 100 ""] +( + Pin[0 0 6000 3000 6600 3200 "1" "1" "square"] + Pin[0 -9600 6000 3000 6600 3200 "2" "2" ""] + Pin[0 -19200 6000 3000 6600 3200 "3" "3" ""] + ElementLine [-9100 -22300 -9100 3000 2000] + ElementLine [9200 -22300 9200 3000 2000] + ElementArc [0 -22300 9100 9100 180 180 2000] + ElementArc [0 3000 9100 9100 0 180 2000] + + ) + +Element["" "Crystals" "" "HC49U_3H" 110000 620000 -67500 12100 1 100 ""] +( + Pin[0 0 6000 3000 6600 3200 "1" "1" "square,edge2"] + Pin[0 -9600 6000 3000 6600 3200 "2" "2" "edge2"] + Pin[0 -19200 6000 3000 6600 3200 "3" "3" "edge2"] + ElementLine [-61500 -31400 -61500 12100 2000] + ElementLine [-61500 -31400 -10000 -31400 2000] + ElementLine [-10000 -31400 -10000 12100 2000] + ElementLine [-61500 12100 -10000 12100 2000] + + ) + +Element["" "Transistor" "" "TO126" 140000 790000 -2000 -12000 1 100 ""] +( + Pin[1000 0 8000 3000 8600 5200 "1" "1" "square"] + Pin[10000 0 8000 3000 8600 5200 "2" "2" ""] + Pin[19000 0 8000 3000 8600 5200 "3" "3" ""] + Pin[10000 -43000 13000 3000 13600 11000 "4" "4" ""] + ElementLine [0 -10000 0 0 3000] + ElementLine [10000 -10000 10000 0 3000] + ElementLine [20000 -10000 20000 0 3000] + ElementLine [-5000 -10000 25000 -10000 2000] + ElementLine [25000 -53000 25000 -10000 2000] + ElementLine [-5000 -53000 25000 -53000 2000] + ElementLine [-5000 -53000 -5000 -10000 2000] + + ) + +Element["" "Transistor" "" "TO126S" 199000 790000 -2000 -12000 1 100 ""] +( + Pin[1000 0 8000 3000 8600 5200 "1" "1" "square"] + Pin[10000 10000 8000 3000 8600 5200 "2" "2" ""] + Pin[19000 0 8000 3000 8600 5200 "3" "3" ""] + Pin[10000 -43000 13000 3000 13600 11000 "4" "4" ""] + ElementLine [0 -10000 0 0 3000] + ElementLine [10000 -10000 10000 10000 3000] + ElementLine [20000 -10000 20000 0 3000] + ElementLine [-5000 -10000 25000 -10000 2000] + ElementLine [25000 -53000 25000 -10000 2000] + ElementLine [-5000 -53000 25000 -53000 2000] + ElementLine [-5000 -53000 -5000 -10000 2000] + + ) + +Element["" "Transistor" "" "TO126SW" 40000 680000 7000 -17000 1 100 ""] +( + Pin[0 -1000 8000 3000 8600 5200 "1" "1" "square"] + Pin[10000 -10000 8000 3000 8600 5200 "2" "2" ""] + Pin[0 -19000 8000 3000 8600 5200 "3" "3" ""] + ElementLine [5000 -10000 10000 -10000 3000] + ElementLine [-5000 -25000 -5000 5000 2000] + ElementLine [-5000 -25000 5000 -25000 2000] + ElementLine [5000 -25000 5000 5000 2000] + ElementLine [-5000 5000 5000 5000 2000] + ElementLine [-5000 -5000 5000 -5000 1000] + ElementLine [-5000 -15000 5000 -15000 1000] + + ) + +Element["" "Transistor" "" "TO126W" 70000 680000 7000 4000 1 100 ""] +( + Pin[0 -1000 8000 3000 8600 5200 "1" "1" "square"] + Pin[0 -10000 8000 3000 8600 5200 "2" "2" ""] + Pin[0 -19000 8000 3000 8600 5200 "3" "3" ""] + ElementLine [-5000 -25000 -5000 5000 2000] + ElementLine [-5000 -25000 5000 -25000 2000] + ElementLine [5000 -25000 5000 5000 2000] + ElementLine [-5000 5000 5000 5000 2000] + + ) + +Element["" "Transistor" "" "TO18" 165000 600000 6000 7000 0 100 ""] +( + Pin[0 -5000 5500 3000 6100 3500 "1" "1" ""] + Pin[-5000 0 5500 3000 6100 3500 "2" "2" ""] + Pin[0 5000 5500 3000 6100 3500 "3" "3" ""] + ElementLine [6700 -7900 9400 -10600 1000] + ElementLine [7300 -7300 10000 -10000 1000] + ElementLine [7900 -6700 10600 -9400 1000] + ElementLine [9400 -10600 10600 -9400 1000] + ElementArc [0 0 9800 9800 0 360 1000] + + ) + +Element["" "diode in TO220" "" "TO218" 224000 691900 -21000 -58700 0 100 ""] +( + Pin[-14000 0 10000 3000 10600 6000 "1" "1" "square"] + Pin[-14000 -21900 10000 3000 10600 6000 "2" "2" ""] + Pin[-14000 -43800 10000 3000 10600 6000 "3" "3" ""] + ElementLine [-26000 8800 -6000 8800 2000] + ElementLine [-6000 -52700 -6000 8800 2000] + ElementLine [-26000 -52700 -6000 -52700 2000] + ElementLine [-26000 -52700 -26000 8800 2000] + ElementLine [-21000 -52700 -21000 8800 1000] + ElementLine [-26000 -14400 -21000 -14400 1000] + ElementLine [-26000 -29400 -21000 -29400 1000] + + ) + +Element["" "Transistor" "" "TO220" 90000 790000 -15000 -23000 1 100 ""] +( + Pin[-10000 0 9000 3000 9600 6000 "1" "1" "square"] + Pin[0 0 9000 3000 9600 6000 "2" "2" ""] + Pin[10000 0 9000 3000 9600 6000 "3" "3" ""] + Pin[0 -67000 15000 3000 15600 13000 "4" "4" ""] + ElementLine [-10000 -18000 -10000 0 3000] + ElementLine [0 -18000 0 0 3000] + ElementLine [10000 -18000 10000 0 3000] + ElementLine [-20000 -18000 20000 -18000 2000] + ElementLine [20000 -55500 20000 -18000 2000] + ElementLine [-20000 -55500 20000 -55500 2000] + ElementLine [-20000 -55500 -20000 -18000 2000] + ElementLine [-20000 -55500 20000 -55500 2000] + ElementLine [20000 -68000 20000 -55500 2000] + ElementLine [18500 -68000 20000 -68000 2000] + ElementLine [18500 -75000 18500 -68000 2000] + ElementLine [18500 -75000 20000 -75000 2000] + ElementLine [20000 -79000 20000 -75000 2000] + ElementLine [-20000 -79000 20000 -79000 2000] + ElementLine [-20000 -79000 -20000 -75000 2000] + ElementLine [-20000 -75000 -18500 -75000 2000] + ElementLine [-18500 -75000 -18500 -68000 2000] + ElementLine [-20000 -68000 -18500 -68000 2000] + ElementLine [-20000 -68000 -20000 -55500 2000] + + ) + +Element["" "Transistor" "" "TO220S" 30000 790000 -15000 -23000 1 100 ""] +( + Pin[-10000 0 9000 3000 9600 6000 "1" "1" "square"] + Pin[0 10000 9000 3000 9600 6000 "2" "2" ""] + Pin[10000 0 9000 3000 9600 6000 "3" "3" ""] + Pin[0 -67000 15000 3000 15600 13000 "4" "4" ""] + ElementLine [-10000 -18000 -10000 0 3000] + ElementLine [0 -18000 0 10000 3000] + ElementLine [10000 -18000 10000 0 3000] + ElementLine [-20000 -18000 20000 -18000 2000] + ElementLine [20000 -55500 20000 -18000 2000] + ElementLine [-20000 -55500 20000 -55500 2000] + ElementLine [-20000 -55500 -20000 -18000 2000] + ElementLine [-20000 -55500 20000 -55500 2000] + ElementLine [20000 -68000 20000 -55500 2000] + ElementLine [18500 -68000 20000 -68000 2000] + ElementLine [18500 -75000 18500 -68000 2000] + ElementLine [18500 -75000 20000 -75000 2000] + ElementLine [20000 -79000 20000 -75000 2000] + ElementLine [-20000 -79000 20000 -79000 2000] + ElementLine [-20000 -79000 -20000 -75000 2000] + ElementLine [-20000 -75000 -18500 -75000 2000] + ElementLine [-18500 -75000 -18500 -68000 2000] + ElementLine [-20000 -68000 -18500 -68000 2000] + ElementLine [-20000 -68000 -20000 -55500 2000] + + ) + +Element["" "Transistor" "" "TO220SW" 130000 680000 -19000 10000 1 100 ""] +( + Pin[0 0 9000 3000 9600 6000 "1" "1" "square"] + Pin[10000 -10000 9000 3000 9600 6000 "2" "2" ""] + Pin[0 -20000 9000 3000 9600 6000 "3" "3" ""] + ElementLine [-12000 -30000 -12000 10000 2000] + ElementLine [-12000 -30000 6000 -30000 2000] + ElementLine [6000 -30000 6000 10000 2000] + ElementLine [-12000 10000 6000 10000 2000] + ElementLine [-12000 -30000 -12000 10000 2000] + ElementLine [-12000 -30000 -6000 -30000 2000] + ElementLine [-6000 -30000 -6000 10000 2000] + ElementLine [-12000 10000 -6000 10000 2000] + ElementLine [-12000 -3000 -6000 -3000 1000] + ElementLine [-12000 -17000 -6000 -17000 1000] + ElementLine [6000 -10000 10000 -10000 3000] + + ) + +Element["" "Transistor" "" "TO220W" 100000 680000 -19000 10000 1 100 ""] +( + Pin[0 0 9000 3000 9600 6000 "1" "1" "square"] + Pin[0 -10000 9000 3000 9600 6000 "2" "2" ""] + Pin[0 -20000 9000 3000 9600 6000 "3" "3" ""] + ElementLine [-12000 -30000 -12000 10000 2000] + ElementLine [-12000 -30000 6000 -30000 2000] + ElementLine [6000 -30000 6000 10000 2000] + ElementLine [-12000 10000 6000 10000 2000] + ElementLine [-12000 -30000 -12000 10000 2000] + ElementLine [-12000 -30000 -6000 -30000 2000] + ElementLine [-6000 -30000 -6000 10000 2000] + ElementLine [-12000 10000 -6000 10000 2000] + ElementLine [-12000 -3000 -6000 -3000 1000] + ElementLine [-12000 -17000 -6000 -17000 1000] + + ) + +Element["" "diode in TO220" "" "TO247" 184000 691900 -22000 -59400 0 100 ""] +( + Pin[-14000 0 10000 3000 10600 6000 "1" "1" "square"] + Pin[-14000 -21900 10000 3000 10600 6000 "2" "2" ""] + Pin[-14000 -43800 10000 3000 10600 6000 "3" "3" ""] + ElementLine [-27000 9600 -6000 9600 2000] + ElementLine [-6000 -53400 -6000 9600 2000] + ElementLine [-27000 -53400 -6000 -53400 2000] + ElementLine [-27000 -53400 -27000 9600 2000] + ElementLine [-22000 -53400 -22000 9600 1000] + ElementLine [-27000 -14400 -22000 -14400 1000] + ElementLine [-27000 -29400 -22000 -29400 1000] + + ) + +Element["" "diode in TO220" "" "TO251" 19000 679000 -9000 -28300 0 100 ""] +( + Pin[-9000 0 7000 3000 7600 4000 "1" "1" "square"] + Pin[-9000 -9000 7000 3000 7600 4000 "2" "2" ""] + Pin[-9000 -18000 7000 3000 7600 4000 "3" "3" ""] + ElementLine [-14000 4200 -4000 4200 2000] + ElementLine [-4000 -22300 -4000 4200 2000] + ElementLine [-14000 -22300 -4000 -22300 2000] + ElementLine [-14000 -22300 -14000 4200 2000] + ElementLine [-9000 -22300 -9000 4200 1000] + ElementLine [-14000 -1500 -9000 -1500 1000] + ElementLine [-14000 -16500 -9000 -16500 1000] + + ) + +Element["" "diode in TO220" "" "TO264" 264000 691900 -22000 -67900 0 100 ""] +( + Pin[-14000 0 10000 3000 10600 6000 "1" "1" "square"] + Pin[-14000 -21900 10000 3000 10600 6000 "2" "2" ""] + Pin[-14000 -43800 10000 3000 10600 6000 "3" "3" ""] + ElementLine [-27000 18100 -6000 18100 2000] + ElementLine [-6000 -61900 -6000 18100 2000] + ElementLine [-27000 -61900 -6000 -61900 2000] + ElementLine [-27000 -61900 -27000 18100 2000] + ElementLine [-22000 -61900 -22000 18100 1000] + ElementLine [-27000 -14400 -22000 -14400 1000] + ElementLine [-27000 -29400 -22000 -29400 1000] + + ) + +Element["" "Transistor" "" "TO39" 210000 600000 6000 7000 0 100 ""] +( + Pin[0 -10000 5500 3000 6100 3500 "1" "1" "square"] + Pin[-10000 0 5500 3000 6100 3500 "2" "2" ""] + Pin[0 10000 5500 3000 6100 3500 "3" "3" ""] + ElementLine [12700 -13900 14800 -16000 1000] + ElementLine [13300 -13300 15400 -15400 1000] + ElementLine [13900 -12700 16000 -14800 1000] + ElementLine [16000 -14800 14800 -16000 1000] + ElementArc [0 0 18300 18300 0 360 1000] + + ) + +Element["" "Transistor" "" "TO92" 250000 610000 -13000 -1000 1 100 ""] +( + Pin[0 -20000 7200 3000 7800 4200 "1" "1" "square"] + Pin[0 -10000 7200 3000 7800 4200 "2" "2" ""] + Pin[0 0 7200 3000 7800 4200 "3" "3" ""] + ElementLine [-7000 -17000 -7000 -3000 1000] + ElementArc [0 -10000 10000 10000 45 270 1000] + + ) + +Element["" "diode in TO220" "" "TO247_2" 360000 1050000 59400 -22000 3 100 ""] +( + Pin[0 -14000 10000 3000 10600 6000 "1" "1" "square,edge2"] + Pin[43800 -14000 10000 3000 10600 6000 "2" "2" "edge2"] + ElementLine [-9600 -27000 -9600 -6000 2000] + ElementLine [-9600 -6000 53400 -6000 2000] + ElementLine [53400 -6000 53400 -27000 2000] + ElementLine [53400 -27000 -9600 -27000 2000] + ElementLine [-9600 -22000 53400 -22000 1000] + ElementLine [14400 -27000 14400 -22000 1000] + ElementLine [29400 -27000 29400 -22000 1000] + + ) + +Element["" "diode in TO220" "" "TO220ACSTAND" 300000 1052000 36000 -17000 3 100 ""] +( + Pin[0 -12000 8000 3000 8600 4000 "1" "1" "square,edge2"] + Pin[20000 -12000 8000 3000 8600 4000 "2" "2" "edge2"] + ElementLine [-10000 -22000 -10000 -4000 2000] + ElementLine [-10000 -4000 30000 -4000 2000] + ElementLine [30000 -4000 30000 -22000 2000] + ElementLine [30000 -22000 -10000 -22000 2000] + ElementLine [-10000 -17000 30000 -17000 1000] + ElementLine [2500 -22000 2500 -17000 1000] + ElementLine [17500 -22000 17500 -17000 1000] + + ) + +Element["" "LED, size in mm (pin 1 is +, 2 is -)" "" "LED5" 200000 1035000 7000 -10000 1 100 ""] +( + Pin[0 5000 6500 3000 7100 4300 "1" "1" "square"] + Pin[0 -5000 6500 3000 7100 4300 "2" "2" ""] + ElementArc [0 0 11800 11800 90 360 1000] + ElementArc [0 0 13800 13800 90 360 1000] + + ) + +Element["" "LED, size in mm (pin 1 is +, 2 is -)" "" "LED3" 160000 1035000 7000 -10000 1 100 ""] +( + Pin[0 5000 6500 3000 7100 4300 "1" "1" "square"] + Pin[0 -5000 6500 3000 7100 4300 "2" "2" ""] + ElementArc [0 0 5900 5900 135 90 1000] + ElementArc [0 0 5900 5900 315 90 1000] + ElementArc [0 0 7900 7900 135 90 1000] + ElementArc [0 0 7900 7900 315 90 1000] + + ) + +Element["" "Crystals" "" "HC51UH" 420000 980000 -103500 13600 1 100 ""] +( + Pin[0 0 8000 3000 8600 4000 "1" "1" "square,edge2"] + Pin[0 -48500 8000 3000 8600 4000 "2" "2" "edge2"] + ElementLine [-97500 -62100 -97500 13600 2000] + ElementLine [-97500 -62100 -20000 -62100 2000] + ElementLine [-20000 -62100 -20000 13600 2000] + ElementLine [-97500 13600 -20000 13600 2000] + + ) + +Element["" "Crystals" "" "HC51U" 220000 978500 -23600 13600 1 100 ""] +( + Pin[0 0 8000 3000 8600 4000 "1" "1" "square"] + Pin[0 -48500 8000 3000 8600 4000 "2" "2" ""] + ElementLine [-17600 -44500 -17600 -4000 2000] + ElementLine [17600 -44500 17600 -4000 2000] + ElementArc [0 -44500 17600 17600 180 180 2000] + ElementArc [0 -4000 17600 17600 0 180 2000] + + ) + +Element["" "Crystals" "" "HC49UH" 310000 960000 -67500 12100 1 100 ""] +( + Pin[0 0 6000 3000 6600 3200 "1" "1" "square,edge2"] + Pin[0 -19200 6000 3000 6600 3200 "2" "2" "edge2"] + ElementLine [-61500 -31400 -61500 12100 2000] + ElementLine [-61500 -31400 -10000 -31400 2000] + ElementLine [-10000 -31400 -10000 12100 2000] + ElementLine [-61500 12100 -10000 12100 2000] + + ) + +Element["" "Crystals" "" "HC49U" 180000 949200 -15100 12100 1 100 ""] +( + Pin[0 0 6000 3000 6600 3200 "1" "1" "square"] + Pin[0 -19200 6000 3000 6600 3200 "2" "2" ""] + ElementLine [-9100 -22300 -9100 3000 2000] + ElementLine [9200 -22300 9200 3000 2000] + ElementArc [0 -22300 9100 9100 180 180 2000] + ElementArc [0 3000 9100 9100 0 180 2000] + + ) + +Element["" "Crystals" "" "HC49" 150000 950000 -11000 5000 1 100 ""] +( + Pin[0 0 6000 3000 6600 2800 "1" "1" "square"] + Pin[0 -20000 6000 3000 6600 2800 "2" "2" ""] + ElementLine [-5000 -20000 -5000 0 2000] + ElementLine [5000 -20000 5000 0 2000] + ElementArc [0 -20000 5000 5000 180 180 2000] + ElementArc [0 0 5000 5000 0 180 2000] + + ) + +Element["" "" "" "" 245000 467500 0 0 0 100 ""] +( + Pin[0 0 19685 2000 20285 11811 "" "2" ""] + Pin[0 -27559 19685 2000 20285 11811 "" "1" ""] + Pin[-17717 -13779 19685 2000 20285 11811 "" "3" ""] + ElementLine [-17717 -55118 -17717 0 1000] + ElementLine [-17717 0 17716 0 1000] + ElementLine [17716 0 17716 -55118 1000] + ElementLine [17716 -55118 -17717 -55118 1000] + ElementLine [-17717 -43307 17716 -43307 1000] + + ) + +Element["" "Power IC, as in MULTIWATT15" "" "HEPTAWATT" 441400 635000 -19900 -41500 0 100 ""] +( + Pin[6100 0 9000 3000 9600 6000 "1" "1" "square"] + Pin[-13900 -5000 9000 3000 9600 6000 "2" "2" ""] + Pin[6100 -10000 9000 3000 9600 6000 "3" "3" ""] + Pin[-13900 -15000 9000 3000 9600 6000 "4" "4" ""] + Pin[6100 -20000 9000 3000 9600 6000 "5" "5" ""] + Pin[-13900 -25000 9000 3000 9600 6000 "6" "6" ""] + Pin[6100 -30000 9000 3000 9600 6000 "7" "7" ""] + ElementLine [-24900 5400 -6000 5400 2000] + ElementLine [-6000 -35500 -6000 5400 2000] + ElementLine [-24900 -35500 -6000 -35500 2000] + ElementLine [-24900 -35500 -24900 5400 2000] + ElementLine [-19900 -35500 -19900 5400 1000] + ElementLine [-24900 -7500 -19900 -7500 1000] + ElementLine [-24900 -22500 -19900 -22500 1000] + + ) + +Element["" "Power IC, as in MULTIWATT15" "" "MULTIWATT11" 317500 628000 79500 -21000 3 100 ""] +( + Pin[0 12000 9000 3000 9600 6000 "1" "1" "square,edge2"] + Pin[6700 -8000 9000 3000 9600 6000 "2" "2" "edge2"] + Pin[13400 12000 9000 3000 9600 6000 "3" "3" "edge2"] + Pin[20100 -8000 9000 3000 9600 6000 "4" "4" "edge2"] + Pin[26800 12000 9000 3000 9600 6000 "5" "5" "edge2"] + Pin[33500 -8000 9000 3000 9600 6000 "6" "6" "edge2"] + Pin[40200 12000 9000 3000 9600 6000 "7" "7" "edge2"] + Pin[46900 -8000 9000 3000 9600 6000 "8" "8" "edge2"] + Pin[53600 12000 9000 3000 9600 6000 "9" "9" "edge2"] + Pin[60300 -8000 9000 3000 9600 6000 "10" "10" "edge2"] + Pin[67000 12000 9000 3000 9600 6000 "11" "11" "edge2"] + ElementLine [-6500 -26000 -6500 -6000 2000] + ElementLine [-6500 -6000 73500 -6000 2000] + ElementLine [73500 -6000 73500 -26000 2000] + ElementLine [73500 -26000 -6500 -26000 2000] + ElementLine [-6500 -21000 73500 -21000 1000] + ElementLine [26000 -26000 26000 -21000 1000] + ElementLine [41000 -26000 41000 -21000 1000] + + ) + +Element["" "Power IC, as in MULTIWATT15" "" "MULTIWATT15" 317500 688000 81000 -21000 3 100 ""] +( + Pin[0 12000 9000 3000 9600 6000 "1" "1" "square,edge2"] + Pin[5000 -8000 9000 3000 9600 6000 "2" "2" "edge2"] + Pin[10000 12000 9000 3000 9600 6000 "3" "3" "edge2"] + Pin[15000 -8000 9000 3000 9600 6000 "4" "4" "edge2"] + Pin[20000 12000 9000 3000 9600 6000 "5" "5" "edge2"] + Pin[25000 -8000 9000 3000 9600 6000 "6" "6" "edge2"] + Pin[30000 12000 9000 3000 9600 6000 "7" "7" "edge2"] + Pin[35000 -8000 9000 3000 9600 6000 "8" "8" "edge2"] + Pin[40000 12000 9000 3000 9600 6000 "9" "9" "edge2"] + Pin[45000 -8000 9000 3000 9600 6000 "10" "10" "edge2"] + Pin[50000 12000 9000 3000 9600 6000 "11" "11" "edge2"] + Pin[55000 -8000 9000 3000 9600 6000 "12" "12" "edge2"] + Pin[60000 12000 9000 3000 9600 6000 "13" "13" "edge2"] + Pin[65000 -8000 9000 3000 9600 6000 "14" "14" "edge2"] + Pin[70000 12000 9000 3000 9600 6000 "15" "15" "edge2"] + ElementLine [-5000 -26000 -5000 -6000 2000] + ElementLine [-5000 -6000 75000 -6000 2000] + ElementLine [75000 -6000 75000 -26000 2000] + ElementLine [75000 -26000 -5000 -26000 2000] + ElementLine [-5000 -21000 75000 -21000 1000] + ElementLine [27500 -26000 27500 -21000 1000] + ElementLine [42500 -26000 42500 -21000 1000] + + ) + +Element["" "Power IC, as in MULTIWATT15" "" "MULTIWATT8" 317500 754500 81000 -21000 3 100 ""] +( + Pin[0 -14500 9000 3000 9600 6000 "1" "1" "square,edge2"] + Pin[10000 -14500 9000 3000 9600 6000 "2" "2" "edge2"] + Pin[20000 -14500 9000 3000 9600 6000 "3" "3" "edge2"] + Pin[30000 -14500 9000 3000 9600 6000 "4" "4" "edge2"] + Pin[40000 -14500 9000 3000 9600 6000 "5" "5" "edge2"] + Pin[50000 -14500 9000 3000 9600 6000 "6" "6" "edge2"] + Pin[60000 -14500 9000 3000 9600 6000 "7" "7" "edge2"] + Pin[70000 -14500 9000 3000 9600 6000 "8" "8" "edge2"] + ElementLine [-5000 -26000 -5000 -6000 2000] + ElementLine [-5000 -6000 75000 -6000 2000] + ElementLine [75000 -6000 75000 -26000 2000] + ElementLine [75000 -26000 -5000 -26000 2000] + ElementLine [-5000 -21000 75000 -21000 1000] + ElementLine [27500 -26000 27500 -21000 1000] + ElementLine [42500 -26000 42500 -21000 1000] + + ) + +Element["" "Crystal oscillator" "" "OSC14" 427500 700000 20000 -17000 0 100 ""] +( + Pin[0 0 5000 3000 5600 2800 "NC" "1" "edge2"] + Pin[60000 0 5000 3000 5600 2800 "GND" "2" "edge2"] + Pin[60000 -30000 5000 3000 5600 2800 "CLK" "3" "edge2"] + Pin[0 -30000 5000 3000 5600 2800 "VCC" "4" "edge2"] + ElementLine [-9500 -30000 -9500 9500 1000] + ElementLine [0 -39500 60000 -39500 1000] + ElementLine [69500 -30000 69500 0 1000] + ElementLine [-9500 9500 60000 9500 1000] + ElementLine [-4000 -30000 -4000 0 1000] + ElementLine [0 -34000 60000 -34000 1000] + ElementLine [64000 -30000 64000 0 1000] + ElementLine [0 4000 60000 4000 1000] + ElementArc [0 -30000 9500 9500 270 90 1000] + ElementArc [60000 -30000 9500 9500 180 90 1000] + ElementArc [60000 0 9500 9500 90 90 1000] + ElementArc [0 -30000 4000 4000 270 90 1000] + ElementArc [60000 -30000 4000 4000 180 90 1000] + ElementArc [60000 0 4000 4000 90 90 1000] + ElementArc [0 0 4000 4000 0 90 1000] + + ) + +Element["" "Power IC, as in MULTIWATT15" "" "PENTAWATT" 494700 636700 -19900 -39900 0 100 ""] +( + Pin[8500 0 9000 3000 9600 6000 "1" "1" "square"] + Pin[-7200 -6700 9000 3000 9600 6000 "2" "2" ""] + Pin[8500 -13400 9000 3000 9600 6000 "3" "3" ""] + Pin[-7200 -20100 9000 3000 9600 6000 "4" "4" ""] + Pin[8500 -26800 9000 3000 9600 6000 "5" "5" ""] + ElementLine [-24900 7000 -6000 7000 2000] + ElementLine [-6000 -33900 -6000 7000 2000] + ElementLine [-24900 -33900 -6000 -33900 2000] + ElementLine [-24900 -33900 -24900 7000 2000] + ElementLine [-19900 -33900 -19900 7000 1000] + ElementLine [-24900 -5900 -19900 -5900 1000] + ElementLine [-24900 -20900 -19900 -20900 1000] + + ) + +Element["" "" "" "" 457500 740000 -12500 -9000 0 100 ""] +( + Pin[13091 9000 9000 5000 9600 3937 "" "4" "edge2,intconn(2)"] + Pin[-12500 9000 9000 5000 9600 3937 "" "3" "edge2,intconn(2)"] + Pin[13091 -9000 9000 5000 9600 3937 "" "2" "edge2,intconn(1)"] + Pin[-12500 -9000 9000 5000 9600 3937 "" "1" "edge2,intconn(1)"] + ElementLine [12181 11736 12181 -11886 787] + ElementLine [-11441 11736 12181 11736 787] + ElementLine [-11441 -11886 -11441 11736 787] + ElementLine [-11441 -11886 12181 -11886 787] + ElementArc [7815 -8031 2756 2756 90 90 787] + ElementArc [7815 -8031 2756 2756 0 90 787] + ElementArc [7815 -8031 2756 2756 270 90 787] + ElementArc [7815 -8031 2756 2756 180 90 787] + ElementArc [7815 7717 2756 2756 0 90 787] + ElementArc [7815 7717 2756 2756 270 90 787] + ElementArc [7815 7717 2756 2756 180 90 787] + ElementArc [7815 7717 2756 2756 90 90 787] + ElementArc [-7933 7717 2756 2756 270 90 787] + ElementArc [-7933 7717 2756 2756 180 90 787] + ElementArc [-7933 7717 2756 2756 90 90 787] + ElementArc [-7933 7717 2756 2756 0 90 787] + ElementArc [-7933 -8031 2756 2756 180 90 787] + ElementArc [-7933 -8031 2756 2756 90 90 787] + ElementArc [-7933 -8031 2756 2756 0 90 787] + ElementArc [-7933 -8031 2756 2756 270 90 787] + ElementArc [-59 -157 6693 6693 270 90 787] + ElementArc [-59 -157 6693 6693 180 90 787] + ElementArc [-59 -157 6693 6693 90 90 787] + ElementArc [-59 -157 6693 6693 0 90 787] + + ) + +Element["" "Standard SMT resistor, capacitor etc" "" "01005" 330000 195000 -3150 3150 1 100 ""] +( + Pad[-19 807 19 807 984 2000 1584 "1" "1" "square"] + Pad[-19 -807 19 -807 984 2000 1584 "2" "2" "square"] + + ) + +Element["" "Standard SMT resistor, capacitor etc" "" "0201" 335000 195000 -3150 3150 1 100 ""] +( + Pad[0 1181 0 1181 1574 2000 2174 "1" "1" "square"] + Pad[0 -1181 0 -1181 1574 2000 2174 "2" "2" "square"] + + ) + +Element["" "Standard SMT resistor, capacitor etc" "" "0402" 340000 195000 -3150 3150 1 100 ""] +( + Pad[-393 1574 393 1574 1968 2000 2568 "1" "1" "square"] + Pad[-393 -1574 393 -1574 1968 2000 2568 "2" "2" "square"] + + ) + +Element["" "Standard SMT resistor, capacitor etc" "" "0603" 350000 195000 -3150 3150 1 100 ""] +( + Pad[-492 2559 492 2559 2952 2000 3552 "1" "1" "square"] + Pad[-492 -2559 492 -2559 2952 2000 3552 "2" "2" "square"] + + ) + +Element["" "Standard SMT resistor, capacitor etc" "" "0805" 360000 195000 -3150 3150 1 100 ""] +( + Pad[-393 3543 393 3543 5118 2000 5718 "1" "1" "square"] + Pad[-393 -3543 393 -3543 5118 2000 5718 "2" "2" "square"] + ElementLine [-2755 -393 -2755 393 800] + ElementLine [2755 -393 2755 393 800] + + ) + +Element["" "Standard SMT resistor, capacitor etc" "" "1008" 375000 195000 -3150 3150 1 100 ""] +( + Pad[-2362 5118 2362 5118 4330 2000 4930 "1" "1" "square"] + Pad[-2362 -5118 2362 -5118 4330 2000 4930 "2" "2" "square"] + ElementLine [-4527 -1377 -4527 1377 800] + ElementLine [4527 -1377 4527 1377 800] + + ) + +Element["" "Standard SMT resistor, capacitor etc" "" "1206" 390000 195000 -3150 3150 1 100 ""] +( + Pad[-1181 5905 1181 5905 5118 2000 5718 "1" "1" "square"] + Pad[-1181 -5905 1181 -5905 5118 2000 5718 "2" "2" "square"] + ElementLine [-3740 -2362 -3740 2362 800] + ElementLine [3740 -2362 3740 2362 800] + + ) + +Element["" "Standard SMT resistor, capacitor etc" "" "1210" 405000 195000 -3150 3150 1 100 ""] +( + Pad[-2755 5905 2755 5905 5118 2000 5718 "1" "1" "square"] + Pad[-2755 -5905 2755 -5905 5118 2000 5718 "2" "2" "square"] + ElementLine [-5314 -1968 -5314 1968 800] + ElementLine [5314 -1968 5314 1968 800] + + ) + +Element["" "Standard SMT resistor, capacitor etc" "" "1806" 335000 220000 -3150 3150 1 100 ""] +( + Pad[-3543 7874 3543 7874 6299 2000 6899 "1" "1" "square"] + Pad[-3543 -7874 3543 -7874 6299 2000 6899 "2" "2" "square"] + ElementLine [-6692 -3149 -6692 3149 800] + ElementLine [6692 -3149 6692 3149 800] + + ) + +Element["" "Standard SMT resistor, capacitor etc" "" "1825" 360000 220000 -3150 3150 1 100 ""] +( + Pad[-10236 7874 10236 7874 6299 2000 6899 "1" "1" "square"] + Pad[-10236 -7874 10236 -7874 6299 2000 6899 "2" "2" "square"] + ElementLine [-13385 -3149 -13385 3149 800] + ElementLine [13385 -3149 13385 3149 800] + + ) + +Element["" "Standard SMT resistor, capacitor etc" "" "2706" 395000 220000 -17900 0 1 100 ""] +( + Pad[10800 -300 10800 300 7800 2000 8400 "1" "1" "square"] + Pad[-10800 -300 -10800 300 7800 2000 8400 "2" "2" "square"] + ElementLine [15900 -5400 15900 5400 1000] + ElementLine [-15900 -5400 15900 -5400 1000] + ElementLine [-15900 -5400 -15900 5400 1000] + ElementLine [-15900 5400 15900 5400 1000] + + ) + +Element["" "SMT diode (pin 1 is cathode)" "" "DO214" 470000 270000 0 22100 2 100 ""] +( + Pad[-1900 -10600 1900 -10600 14000 2000 14600 "1" "1" "square"] + Pad[-1900 10600 1900 10600 14000 2000 14600 "2" "2" "square"] + ElementLine [-8900 -21100 8900 -21100 2000] + ElementLine [-8900 -21100 -11400 -14100 1000] + ElementLine [-11400 -14100 -11400 20100 1000] + ElementLine [-11400 20100 11400 20100 1000] + ElementLine [11400 -14100 11400 20100 1000] + ElementLine [11400 -14100 8900 -21100 1000] + + ) + +Element["" "SMT diode (pin 1 is cathode)" "" "DO214AB" 470000 320000 0 22700 2 100 ""] +( + Pad[-2000 -10900 2000 -10900 14500 2000 15100 "1" "1" "square"] + Pad[-2000 10900 2000 10900 14500 2000 15100 "2" "2" "square"] + ElementLine [-9200 -21700 9200 -21700 2000] + ElementLine [-9200 -21700 -11800 -14500 1000] + ElementLine [-11800 -14500 -11800 20700 1000] + ElementLine [-11800 20700 11800 20700 1000] + ElementLine [11800 -14500 11800 20700 1000] + ElementLine [11800 -14500 9200 -21700 1000] + + ) + +Element["" "SMT diode (pin 1 is cathode)" "" "SOD106A" 425000 265000 0 16600 2 100 ""] +( + Pad[-1700 -7600 1700 -7600 10200 2000 10800 "1" "1" "square"] + Pad[-1700 7600 1700 7600 10200 2000 10800 "2" "2" "square"] + ElementLine [-6800 -15600 6800 -15600 2000] + ElementLine [-6800 -15600 -8700 -10500 1000] + ElementLine [-8700 -10500 -8700 14600 1000] + ElementLine [-8700 14600 8700 14600 1000] + ElementLine [8700 -10500 8700 14600 1000] + ElementLine [8700 -10500 6800 -15600 1000] + + ) + +Element["" "SMT diode (pin 1 is cathode)" "" "SOD110" 335000 265000 0 8300 2 100 ""] +( + Pad[-1500 -2900 1500 -2900 4600 2000 5200 "1" "1" "square"] + Pad[-1500 2900 1500 2900 4600 2000 5200 "2" "2" "square"] + ElementLine [-3800 -7300 3800 -7300 2000] + ElementLine [-3800 -7300 -4900 -5000 1000] + ElementLine [-4900 -5000 -4900 6300 1000] + ElementLine [-4900 6300 4900 6300 1000] + ElementLine [4900 -5000 4900 6300 1000] + ElementLine [4900 -5000 3800 -7300 1000] + + ) + +Element["" "SMT diode (pin 1 is cathode)" "" "SOD123" 380000 265000 0 12000 2 100 ""] +( + Pad[-600 -5500 600 -5500 6900 2000 7500 "1" "1" "square"] + Pad[-600 5500 600 5500 6900 2000 7500 "2" "2" "square"] + ElementLine [-4000 -11000 4000 -11000 2000] + ElementLine [-4000 -11000 -5100 -7600 1000] + ElementLine [-5100 -7600 -5100 10000 1000] + ElementLine [-5100 10000 5100 10000 1000] + ElementLine [5100 -7600 5100 10000 1000] + ElementLine [5100 -7600 4000 -11000 1000] + + ) + +Element["" "SMT diode (pin 1 is cathode)" "" "SOD323" 350000 265000 0 9300 2 100 ""] +( + Pad[-1000 -3700 1000 -3700 5100 2000 5700 "1" "1" "square"] + Pad[-1000 3700 1000 3700 5100 2000 5700 "2" "2" "square"] + ElementLine [-3500 -8300 3500 -8300 2000] + ElementLine [-3500 -8300 -4500 -5800 1000] + ElementLine [-4500 -5800 -4500 7300 1000] + ElementLine [-4500 7300 4500 7300 1000] + ElementLine [4500 -5800 4500 7300 1000] + ElementLine [4500 -5800 3500 -8300 1000] + + ) + +Element["" "SMT diode (pin 1 is cathode)" "" "SOD80" 365000 265000 0 11600 2 100 ""] +( + Pad[-1600 -5800 1600 -5800 5300 2000 5900 "1" "1" "square"] + Pad[-1600 5800 1600 5800 5300 2000 5900 "2" "2" "square"] + ElementLine [-4300 -10600 4300 -10600 2000] + ElementLine [-4300 -10600 -5500 -8000 1000] + ElementLine [-5500 -8000 -5500 9600 1000] + ElementLine [-5500 9600 5500 9600 1000] + ElementLine [5500 -8000 5500 9600 1000] + ElementLine [5500 -8000 4300 -10600 1000] + + ) + +Element["" "SMT diode (pin 1 is cathode)" "" "SOD87" 400000 265000 0 12400 2 100 ""] +( + Pad[-2600 -5800 2600 -5800 6100 2000 6700 "1" "1" "square"] + Pad[-2600 5800 2600 5800 6100 2000 6700 "2" "2" "square"] + ElementLine [-5700 -11400 5700 -11400 2000] + ElementLine [-5700 -11400 -7300 -8400 1000] + ElementLine [-7300 -8400 -7300 10400 1000] + ElementLine [-7300 10400 7300 10400 1000] + ElementLine [7300 -8400 7300 10400 1000] + ElementLine [7300 -8400 5700 -11400 1000] + + ) + +Element["" "Tantalum SMT capacitor (pin 1 is +)" "" "TANT_A" 430000 325000 0 10600 2 100 ""] +( + Pad[-1800 -5000 1800 -5000 4900 2000 5500 "1" "1" "square"] + Pad[-1800 5000 1800 5000 4900 2000 5500 "2" "2" "square"] + ElementLine [-4300 -9600 4300 -9600 2000] + ElementLine [-4300 -9600 -5500 -7200 1000] + ElementLine [-5500 -7200 -5500 8600 1000] + ElementLine [-5500 8600 5500 8600 1000] + ElementLine [5500 -7200 5500 8600 1000] + ElementLine [5500 -7200 4300 -9600 1000] + + ) + +Element["" "Tantalum SMT capacitor (pin 1 is +)" "" "TANT_B" 405000 325000 0 13200 2 100 ""] +( + Pad[-4100 -5500 4100 -5500 7100 2000 7700 "1" "1" "square"] + Pad[-4100 5500 4100 5500 7100 2000 7700 "2" "2" "square"] + ElementLine [-7700 -12200 7700 -12200 2000] + ElementLine [-7700 -12200 -9900 -8700 1000] + ElementLine [-9900 -8700 -9900 11200 1000] + ElementLine [-9900 11200 9900 11200 1000] + ElementLine [9900 -8700 9900 11200 1000] + ElementLine [9900 -8700 7700 -12200 1000] + + ) + +Element["" "Tantalum SMT capacitor (pin 1 is +)" "" "TANT_C" 375000 320000 0 18800 2 100 ""] +( + Pad[-3900 -9400 3900 -9400 9700 2000 10300 "1" "1" "square"] + Pad[-3900 9400 3900 9400 9700 2000 10300 "2" "2" "square"] + ElementLine [-8700 -17800 8700 -17800 2000] + ElementLine [-8700 -17800 -11200 -13000 1000] + ElementLine [-11200 -13000 -11200 16800 1000] + ElementLine [-11200 16800 11200 16800 1000] + ElementLine [11200 -13000 11200 16800 1000] + ElementLine [11200 -13000 8700 -17800 1000] + + ) + +Element["" "Tantalum SMT capacitor (pin 1 is +)" "" "TANT_D" 343500 316500 0 22900 2 100 ""] +( + Pad[-5600 -11500 5600 -11500 12300 2000 12900 "1" "1" "square"] + Pad[-5600 11500 5600 11500 12300 2000 12900 "2" "2" "square"] + ElementLine [-11700 -21900 11700 -21900 2000] + ElementLine [-11700 -21900 -15000 -15800 1000] + ElementLine [-15000 -15800 -15000 20900 1000] + ElementLine [-15000 20900 15000 20900 1000] + ElementLine [15000 -15800 15000 20900 1000] + ElementLine [15000 -15800 11700 -21900 1000] + + ) + +Element["" "" "" "" 455000 207500 12913 3720 1 70 ""] +( + Pad[-984 -7087 984 -7087 5118 5000 7618 "" "1" "square"] + Pad[-984 7087 984 7087 5118 5000 7618 "" "2" "square"] + ElementLine [-3150 -3937 -3150 3937 787] + ElementLine [3150 -3937 3150 3937 787] + + ) +Layer(1 "component") +( + Line[280000 400000 540000 400000 8000 5000 "clearline"] + Line[280000 0 280000 870000 8000 5000 "clearline"] + Line[0 550000 540000 550000 8000 5000 "clearline"] + Line[390000 550000 390000 400000 8000 5000 "clearline"] + Line[280000 160000 540000 160000 8000 5000 "clearline"] + Line[540000 0 540000 1120000 8000 5000 "clearline"] + Line[0 1120000 0 0 8000 5000 "clearline"] + Line[0 0 540000 0 8000 5000 "clearline"] + Line[540000 870000 0 870000 8000 5000 "clearline"] + Line[540000 1120000 0 1120000 8000 5000 "clearline"] + Text[296338 119704 0 670 "PARAMETRIC" "clearline"] + Text[108838 502204 0 670 "CONN" "clearline"] + Text[366338 349704 0 670 "SMD2" "clearline"] + Text[286338 499704 0 670 "SMD3" "clearline"] + Text[416338 499704 0 670 "SMDN" "clearline"] + Text[86338 819704 0 670 "TRH3" "clearline"] + Text[376338 809704 0 670 "TRHN" "clearline"] + Text[256338 1069704 0 670 "TRH2" "clearline"] +) +Layer(2 "solder") +( + Polygon("clearpoly") + ( + [5000 2500] [277500 2500] [277500 547500] [5000 547500] + ) + Polygon("clearpoly") + ( + [282500 2500] [537500 2500] [537500 157500] [282500 157500] + ) + Polygon("clearpoly") + ( + [282500 162500] [537500 162500] [537500 397500] [282500 397500] + ) + Polygon("clearpoly") + ( + [282500 402500] [387500 402500] [387500 547500] [282500 547500] + ) + Polygon("clearpoly") + ( + [392500 402500] [537500 402500] [537500 547500] [392500 547500] + ) + Polygon("clearpoly") + ( + [2500 552500] [277500 552500] [277500 867500] [2500 867500] + ) + Polygon("clearpoly") + ( + [282500 552500] [537500 552500] [537500 867500] [282500 867500] + ) + Polygon("clearpoly") + ( + [2500 872500] [540000 872500] [540000 1120000] [2500 1120000] + ) +) +Layer(3 "comp-GND") +( +) +Layer(4 "comp-power") +( +) +Layer(5 "sold-GND") +( +) +Layer(6 "sold-power") +( +) +Layer(7 "signal3") +( +) +Layer(8 "outline") +( +) +Layer(9 "silk") +( +) +Layer(10 "silk") +( + Line[305000 430000 360000 430000 1000 4000 "clearline"] + Line[0 640000 150000 640000 1000 4000 "clearline"] + Line[150000 640000 150000 570000 1000 4000 "clearline"] + Line[260000 1010000 260000 1060000 1000 4000 "clearline"] + Line[130000 1010000 460000 1010000 1000 4000 "clearline"] + Line[325000 240000 495000 240000 1000 4000 "clearline"] + Line[325000 285000 455000 285000 1000 4000 "clearline"] + Line[420000 185000 420000 240000 1000 4000 "clearline"] + Line[455000 240000 455000 345000 1000 4000 "clearline"] + Text[340000 410000 0 200 "SC" "clearline"] + Text[345000 465000 1 200 "SOT" "clearline"] + Text[130000 600000 0 200 "HC" "clearline"] + Text[250000 760000 0 200 "TO" "clearline"] + Text[430000 1030000 0 200 "TO" "clearline"] + Text[230000 1030000 0 200 "LED" "clearline"] + Text[440000 950000 0 200 "HC" "clearline"] + Text[440000 330000 1 200 "TANT" "clearline"] + Text[440000 275000 1 200 "SOD" "clearline"] + Text[482500 300000 1 200 "DO" "clearline"] + Text[437500 222500 0 200 "minimelf" "clearline"] +) Index: tags/2.1.2/util/pcblib-map/parametric.pcb =================================================================== --- tags/2.1.2/util/pcblib-map/parametric.pcb (nonexistent) +++ tags/2.1.2/util/pcblib-map/parametric.pcb (revision 24813) @@ -0,0 +1,1153 @@ +# release: pcb 20110918 + +# To read pcb files, the pcb version (or the git source date) must be >= the file version +FileVersion[20070407] + +PCB["" 260000 120000] + +Grid[10000.0 0 0 1] +Cursor[0 0 0.000000] +PolyArea[3100.006200] +Thermal[0.500000] +DRC[1200 900 1000 700 1500 1000] +Flags("nameonpcb,clearnew,snappin,onlynames") +Groups("1,3,4,c:2,5,6,s:7:8") +Styles["Signal,1000,7874,3150,2000:Power,2000,8661,3937,2000:Fat,8000,13780,4724,2500:Sig-tight,1000,6400,3150,1200"] + +Symbol[' ' 1800] +( +) +Symbol['!' 1200] +( + SymbolLine[0 4500 0 5000 800] + SymbolLine[0 1000 0 3500 800] +) +Symbol['"' 1200] +( + SymbolLine[0 1000 0 2000 800] + SymbolLine[1000 1000 1000 2000 800] +) +Symbol['#' 1200] +( + SymbolLine[0 3500 2000 3500 800] + SymbolLine[0 2500 2000 2500 800] + SymbolLine[1500 2000 1500 4000 800] + SymbolLine[500 2000 500 4000 800] +) +Symbol['$' 1200] +( + SymbolLine[1500 1500 2000 2000 800] + SymbolLine[500 1500 1500 1500 800] + SymbolLine[0 2000 500 1500 800] + SymbolLine[0 2000 0 2500 800] + SymbolLine[0 2500 500 3000 800] + SymbolLine[500 3000 1500 3000 800] + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[2000 3500 2000 4000 800] + SymbolLine[1500 4500 2000 4000 800] + SymbolLine[500 4500 1500 4500 800] + SymbolLine[0 4000 500 4500 800] + SymbolLine[1000 1000 1000 5000 800] +) +Symbol['%' 1200] +( + SymbolLine[0 1500 0 2000 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 1000 1000 800] + SymbolLine[1000 1000 1500 1500 800] + SymbolLine[1500 1500 1500 2000 800] + SymbolLine[1000 2500 1500 2000 800] + SymbolLine[500 2500 1000 2500 800] + SymbolLine[0 2000 500 2500 800] + SymbolLine[0 5000 4000 1000 800] + SymbolLine[3500 5000 4000 4500 800] + SymbolLine[4000 4000 4000 4500 800] + SymbolLine[3500 3500 4000 4000 800] + SymbolLine[3000 3500 3500 3500 800] + SymbolLine[2500 4000 3000 3500 800] + SymbolLine[2500 4000 2500 4500 800] + SymbolLine[2500 4500 3000 5000 800] + SymbolLine[3000 5000 3500 5000 800] +) +Symbol['&' 1200] +( + SymbolLine[0 4500 500 5000 800] + SymbolLine[0 1500 0 2500 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[0 3500 1500 2000 800] + SymbolLine[500 5000 1000 5000 800] + SymbolLine[1000 5000 2000 4000 800] + SymbolLine[0 2500 2500 5000 800] + SymbolLine[500 1000 1000 1000 800] + SymbolLine[1000 1000 1500 1500 800] + SymbolLine[1500 1500 1500 2000 800] + SymbolLine[0 3500 0 4500 800] +) +Symbol[''' 1200] +( + SymbolLine[0 2000 1000 1000 800] +) +Symbol['(' 1200] +( + SymbolLine[0 4500 500 5000 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[0 1500 0 4500 800] +) +Symbol[')' 1200] +( + SymbolLine[0 1000 500 1500 800] + SymbolLine[500 1500 500 4500 800] + SymbolLine[0 5000 500 4500 800] +) +Symbol['*' 1200] +( + SymbolLine[0 2000 2000 4000 800] + SymbolLine[0 4000 2000 2000 800] + SymbolLine[0 3000 2000 3000 800] + SymbolLine[1000 2000 1000 4000 800] +) +Symbol['+' 1200] +( + SymbolLine[0 3000 2000 3000 800] + SymbolLine[1000 2000 1000 4000 800] +) +Symbol[',' 1200] +( + SymbolLine[0 6000 1000 5000 800] +) +Symbol['-' 1200] +( + SymbolLine[0 3000 2000 3000 800] +) +Symbol['.' 1200] +( + SymbolLine[0 5000 500 5000 800] +) +Symbol['/' 1200] +( + SymbolLine[0 4500 3000 1500 800] +) +Symbol['0' 1200] +( + SymbolLine[0 4500 500 5000 800] + SymbolLine[0 1500 0 4500 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 1500 1000 800] + SymbolLine[1500 1000 2000 1500 800] + SymbolLine[2000 1500 2000 4500 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[0 4000 2000 2000 800] +) +Symbol['1' 1200] +( + SymbolLine[0 1800 800 1000 800] + SymbolLine[800 1000 800 5000 800] + SymbolLine[0 5000 1500 5000 800] +) +Symbol['2' 1200] +( + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 2000 1000 800] + SymbolLine[2000 1000 2500 1500 800] + SymbolLine[2500 1500 2500 2500 800] + SymbolLine[0 5000 2500 2500 800] + SymbolLine[0 5000 2500 5000 800] +) +Symbol['3' 1200] +( + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 1500 1000 800] + SymbolLine[1500 1000 2000 1500 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[500 2800 1500 2800 800] + SymbolLine[2000 1500 2000 2300 800] + SymbolLine[2000 3300 2000 4500 800] + SymbolLine[2000 3300 1500 2800 800] + SymbolLine[2000 2300 1500 2800 800] +) +Symbol['4' 1200] +( + SymbolLine[0 3500 2000 1000 800] + SymbolLine[0 3500 2500 3500 800] + SymbolLine[2000 1000 2000 5000 800] +) +Symbol['5' 1200] +( + SymbolLine[0 1000 2000 1000 800] + SymbolLine[0 1000 0 3000 800] + SymbolLine[0 3000 500 2500 800] + SymbolLine[500 2500 1500 2500 800] + SymbolLine[1500 2500 2000 3000 800] + SymbolLine[2000 3000 2000 4500 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[0 4500 500 5000 800] +) +Symbol['6' 1200] +( + SymbolLine[1500 1000 2000 1500 800] + SymbolLine[500 1000 1500 1000 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[0 1500 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[1500 2800 2000 3300 800] + SymbolLine[0 2800 1500 2800 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[2000 3300 2000 4500 800] +) +Symbol['7' 1200] +( + SymbolLine[500 5000 2500 1000 800] + SymbolLine[0 1000 2500 1000 800] +) +Symbol['8' 1200] +( + SymbolLine[0 4500 500 5000 800] + SymbolLine[0 3700 0 4500 800] + SymbolLine[0 3700 700 3000 800] + SymbolLine[700 3000 1300 3000 800] + SymbolLine[1300 3000 2000 3700 800] + SymbolLine[2000 3700 2000 4500 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[0 2300 700 3000 800] + SymbolLine[0 1500 0 2300 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 1500 1000 800] + SymbolLine[1500 1000 2000 1500 800] + SymbolLine[2000 1500 2000 2300 800] + SymbolLine[1300 3000 2000 2300 800] +) +Symbol['9' 1200] +( + SymbolLine[500 5000 2000 3000 800] + SymbolLine[2000 1500 2000 3000 800] + SymbolLine[1500 1000 2000 1500 800] + SymbolLine[500 1000 1500 1000 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[0 1500 0 2500 800] + SymbolLine[0 2500 500 3000 800] + SymbolLine[500 3000 2000 3000 800] +) +Symbol[':' 1200] +( + SymbolLine[0 2500 500 2500 800] + SymbolLine[0 3500 500 3500 800] +) +Symbol[';' 1200] +( + SymbolLine[0 5000 1000 4000 800] + SymbolLine[1000 2500 1000 3000 800] +) +Symbol['<' 1200] +( + SymbolLine[0 3000 1000 2000 800] + SymbolLine[0 3000 1000 4000 800] +) +Symbol['=' 1200] +( + SymbolLine[0 2500 2000 2500 800] + SymbolLine[0 3500 2000 3500 800] +) +Symbol['>' 1200] +( + SymbolLine[0 2000 1000 3000 800] + SymbolLine[0 4000 1000 3000 800] +) +Symbol['?' 1200] +( + SymbolLine[1000 3000 1000 3500 800] + SymbolLine[1000 4500 1000 5000 800] + SymbolLine[0 1500 0 2000 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 1500 1000 800] + SymbolLine[1500 1000 2000 1500 800] + SymbolLine[2000 1500 2000 2000 800] + SymbolLine[1000 3000 2000 2000 800] +) +Symbol['@' 1200] +( + SymbolLine[0 1000 0 4000 800] + SymbolLine[0 4000 1000 5000 800] + SymbolLine[1000 5000 4000 5000 800] + SymbolLine[5000 3500 5000 1000 800] + SymbolLine[5000 1000 4000 0 800] + SymbolLine[4000 0 1000 0 800] + SymbolLine[1000 0 0 1000 800] + SymbolLine[1500 2000 1500 3000 800] + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[2000 3500 3000 3500 800] + SymbolLine[3000 3500 3500 3000 800] + SymbolLine[3500 3000 4000 3500 800] + SymbolLine[3500 3000 3500 1500 800] + SymbolLine[3500 2000 3000 1500 800] + SymbolLine[2000 1500 3000 1500 800] + SymbolLine[2000 1500 1500 2000 800] + SymbolLine[4000 3500 5000 3500 800] +) +Symbol['A' 1200] +( + SymbolLine[0 2000 0 5000 800] + SymbolLine[0 2000 700 1000 800] + SymbolLine[700 1000 1800 1000 800] + SymbolLine[1800 1000 2500 2000 800] + SymbolLine[2500 2000 2500 5000 800] + SymbolLine[0 3000 2500 3000 800] +) +Symbol['B' 1200] +( + SymbolLine[0 5000 2000 5000 800] + SymbolLine[2000 5000 2500 4500 800] + SymbolLine[2500 3300 2500 4500 800] + SymbolLine[2000 2800 2500 3300 800] + SymbolLine[500 2800 2000 2800 800] + SymbolLine[500 1000 500 5000 800] + SymbolLine[0 1000 2000 1000 800] + SymbolLine[2000 1000 2500 1500 800] + SymbolLine[2500 1500 2500 2300 800] + SymbolLine[2000 2800 2500 2300 800] +) +Symbol['C' 1200] +( + SymbolLine[700 5000 2000 5000 800] + SymbolLine[0 4300 700 5000 800] + SymbolLine[0 1700 0 4300 800] + SymbolLine[0 1700 700 1000 800] + SymbolLine[700 1000 2000 1000 800] +) +Symbol['D' 1200] +( + SymbolLine[500 1000 500 5000 800] + SymbolLine[1800 1000 2500 1700 800] + SymbolLine[2500 1700 2500 4300 800] + SymbolLine[1800 5000 2500 4300 800] + SymbolLine[0 5000 1800 5000 800] + SymbolLine[0 1000 1800 1000 800] +) +Symbol['E' 1200] +( + SymbolLine[0 2800 1500 2800 800] + SymbolLine[0 5000 2000 5000 800] + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 1000 2000 1000 800] +) +Symbol['F' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 1000 2000 1000 800] + SymbolLine[0 2800 1500 2800 800] +) +Symbol['G' 1200] +( + SymbolLine[2000 1000 2500 1500 800] + SymbolLine[500 1000 2000 1000 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[0 1500 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[500 5000 2000 5000 800] + SymbolLine[2000 5000 2500 4500 800] + SymbolLine[2500 3500 2500 4500 800] + SymbolLine[2000 3000 2500 3500 800] + SymbolLine[1000 3000 2000 3000 800] +) +Symbol['H' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[2500 1000 2500 5000 800] + SymbolLine[0 3000 2500 3000 800] +) +Symbol['I' 1200] +( + SymbolLine[0 1000 1000 1000 800] + SymbolLine[500 1000 500 5000 800] + SymbolLine[0 5000 1000 5000 800] +) +Symbol['J' 1200] +( + SymbolLine[700 1000 1500 1000 800] + SymbolLine[1500 1000 1500 4500 800] + SymbolLine[1000 5000 1500 4500 800] + SymbolLine[500 5000 1000 5000 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[0 4500 0 4000 800] +) +Symbol['K' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 3000 2000 1000 800] + SymbolLine[0 3000 2000 5000 800] +) +Symbol['L' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 5000 2000 5000 800] +) +Symbol['M' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 1000 1500 3000 800] + SymbolLine[1500 3000 3000 1000 800] + SymbolLine[3000 1000 3000 5000 800] +) +Symbol['N' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 1000 2500 5000 800] + SymbolLine[2500 1000 2500 5000 800] +) +Symbol['O' 1200] +( + SymbolLine[0 1500 0 4500 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 1500 1000 800] + SymbolLine[1500 1000 2000 1500 800] + SymbolLine[2000 1500 2000 4500 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[0 4500 500 5000 800] +) +Symbol['P' 1200] +( + SymbolLine[500 1000 500 5000 800] + SymbolLine[0 1000 2000 1000 800] + SymbolLine[2000 1000 2500 1500 800] + SymbolLine[2500 1500 2500 2500 800] + SymbolLine[2000 3000 2500 2500 800] + SymbolLine[500 3000 2000 3000 800] +) +Symbol['Q' 1200] +( + SymbolLine[0 1500 0 4500 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 1500 1000 800] + SymbolLine[1500 1000 2000 1500 800] + SymbolLine[2000 1500 2000 4000 800] + SymbolLine[1000 5000 2000 4000 800] + SymbolLine[500 5000 1000 5000 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[1000 3500 2000 5000 800] +) +Symbol['R' 1200] +( + SymbolLine[0 1000 2000 1000 800] + SymbolLine[2000 1000 2500 1500 800] + SymbolLine[2500 1500 2500 2500 800] + SymbolLine[2000 3000 2500 2500 800] + SymbolLine[500 3000 2000 3000 800] + SymbolLine[500 1000 500 5000 800] + SymbolLine[1300 3000 2500 5000 800] +) +Symbol['S' 1200] +( + SymbolLine[2000 1000 2500 1500 800] + SymbolLine[500 1000 2000 1000 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[0 1500 0 2500 800] + SymbolLine[0 2500 500 3000 800] + SymbolLine[500 3000 2000 3000 800] + SymbolLine[2000 3000 2500 3500 800] + SymbolLine[2500 3500 2500 4500 800] + SymbolLine[2000 5000 2500 4500 800] + SymbolLine[500 5000 2000 5000 800] + SymbolLine[0 4500 500 5000 800] +) +Symbol['T' 1200] +( + SymbolLine[0 1000 2000 1000 800] + SymbolLine[1000 1000 1000 5000 800] +) +Symbol['U' 1200] +( + SymbolLine[0 1000 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[2000 1000 2000 4500 800] +) +Symbol['V' 1200] +( + SymbolLine[0 1000 1000 5000 800] + SymbolLine[1000 5000 2000 1000 800] +) +Symbol['W' 1200] +( + SymbolLine[0 1000 0 3000 800] + SymbolLine[0 3000 500 5000 800] + SymbolLine[500 5000 1500 3000 800] + SymbolLine[1500 3000 2500 5000 800] + SymbolLine[2500 5000 3000 3000 800] + SymbolLine[3000 3000 3000 1000 800] +) +Symbol['X' 1200] +( + SymbolLine[0 5000 2500 1000 800] + SymbolLine[0 1000 2500 5000 800] +) +Symbol['Y' 1200] +( + SymbolLine[0 1000 1000 3000 800] + SymbolLine[1000 3000 2000 1000 800] + SymbolLine[1000 3000 1000 5000 800] +) +Symbol['Z' 1200] +( + SymbolLine[0 1000 2500 1000 800] + SymbolLine[0 5000 2500 1000 800] + SymbolLine[0 5000 2500 5000 800] +) +Symbol['[' 1200] +( + SymbolLine[0 1000 500 1000 800] + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 5000 500 5000 800] +) +Symbol['\' 1200] +( + SymbolLine[0 1500 3000 4500 800] +) +Symbol[']' 1200] +( + SymbolLine[0 1000 500 1000 800] + SymbolLine[500 1000 500 5000 800] + SymbolLine[0 5000 500 5000 800] +) +Symbol['^' 1200] +( + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 1000 1500 800] +) +Symbol['_' 1200] +( + SymbolLine[0 5000 2000 5000 800] +) +Symbol['a' 1200] +( + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[500 3000 1500 3000 800] + SymbolLine[0 3500 500 3000 800] + SymbolLine[0 3500 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[2000 3000 2000 4500 800] + SymbolLine[2000 4500 2500 5000 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[1500 5000 2000 4500 800] +) +Symbol['b' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[2000 3500 2000 4500 800] + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[500 3000 1500 3000 800] + SymbolLine[0 3500 500 3000 800] +) +Symbol['c' 1200] +( + SymbolLine[500 3000 2000 3000 800] + SymbolLine[0 3500 500 3000 800] + SymbolLine[0 3500 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[500 5000 2000 5000 800] +) +Symbol['d' 1200] +( + SymbolLine[2000 1000 2000 5000 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[0 3500 0 4500 800] + SymbolLine[0 3500 500 3000 800] + SymbolLine[500 3000 1500 3000 800] + SymbolLine[1500 3000 2000 3500 800] +) +Symbol['e' 1200] +( + SymbolLine[500 5000 2000 5000 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[0 3500 0 4500 800] + SymbolLine[0 3500 500 3000 800] + SymbolLine[500 3000 1500 3000 800] + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[0 4000 2000 4000 800] + SymbolLine[2000 4000 2000 3500 800] +) +Symbol['f' 1000] +( + SymbolLine[500 1500 500 5000 800] + SymbolLine[500 1500 1000 1000 800] + SymbolLine[1000 1000 1500 1000 800] + SymbolLine[0 3000 1000 3000 800] +) +Symbol['g' 1200] +( + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[500 3000 1500 3000 800] + SymbolLine[0 3500 500 3000 800] + SymbolLine[0 3500 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[0 6000 500 6500 800] + SymbolLine[500 6500 1500 6500 800] + SymbolLine[1500 6500 2000 6000 800] + SymbolLine[2000 3000 2000 6000 800] +) +Symbol['h' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 3500 500 3000 800] + SymbolLine[500 3000 1500 3000 800] + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[2000 3500 2000 5000 800] +) +Symbol['i' 1000] +( + SymbolLine[0 2000 0 2100 1000] + SymbolLine[0 3500 0 5000 800] +) +Symbol['j' 1000] +( + SymbolLine[500 2000 500 2100 1000] + SymbolLine[500 3500 500 6000 800] + SymbolLine[0 6500 500 6000 800] +) +Symbol['k' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 3500 1500 5000 800] + SymbolLine[0 3500 1000 2500 800] +) +Symbol['l' 1000] +( + SymbolLine[0 1000 0 4500 800] + SymbolLine[0 4500 500 5000 800] +) +Symbol['m' 1200] +( + SymbolLine[500 3500 500 5000 800] + SymbolLine[500 3500 1000 3000 800] + SymbolLine[1000 3000 1500 3000 800] + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[2000 3500 2000 5000 800] + SymbolLine[2000 3500 2500 3000 800] + SymbolLine[2500 3000 3000 3000 800] + SymbolLine[3000 3000 3500 3500 800] + SymbolLine[3500 3500 3500 5000 800] + SymbolLine[0 3000 500 3500 800] +) +Symbol['n' 1200] +( + SymbolLine[500 3500 500 5000 800] + SymbolLine[500 3500 1000 3000 800] + SymbolLine[1000 3000 1500 3000 800] + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[2000 3500 2000 5000 800] + SymbolLine[0 3000 500 3500 800] +) +Symbol['o' 1200] +( + SymbolLine[0 3500 0 4500 800] + SymbolLine[0 3500 500 3000 800] + SymbolLine[500 3000 1500 3000 800] + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[2000 3500 2000 4500 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[0 4500 500 5000 800] +) +Symbol['p' 1200] +( + SymbolLine[500 3500 500 6500 800] + SymbolLine[0 3000 500 3500 800] + SymbolLine[500 3500 1000 3000 800] + SymbolLine[1000 3000 2000 3000 800] + SymbolLine[2000 3000 2500 3500 800] + SymbolLine[2500 3500 2500 4500 800] + SymbolLine[2000 5000 2500 4500 800] + SymbolLine[1000 5000 2000 5000 800] + SymbolLine[500 4500 1000 5000 800] +) +Symbol['q' 1200] +( + SymbolLine[2000 3500 2000 6500 800] + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[500 3000 1500 3000 800] + SymbolLine[0 3500 500 3000 800] + SymbolLine[0 3500 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[1500 5000 2000 4500 800] +) +Symbol['r' 1200] +( + SymbolLine[500 3500 500 5000 800] + SymbolLine[500 3500 1000 3000 800] + SymbolLine[1000 3000 2000 3000 800] + SymbolLine[0 3000 500 3500 800] +) +Symbol['s' 1200] +( + SymbolLine[500 5000 2000 5000 800] + SymbolLine[2000 5000 2500 4500 800] + SymbolLine[2000 4000 2500 4500 800] + SymbolLine[500 4000 2000 4000 800] + SymbolLine[0 3500 500 4000 800] + SymbolLine[0 3500 500 3000 800] + SymbolLine[500 3000 2000 3000 800] + SymbolLine[2000 3000 2500 3500 800] + SymbolLine[0 4500 500 5000 800] +) +Symbol['t' 1000] +( + SymbolLine[500 1000 500 4500 800] + SymbolLine[500 4500 1000 5000 800] + SymbolLine[0 2500 1000 2500 800] +) +Symbol['u' 1200] +( + SymbolLine[0 3000 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[2000 3000 2000 4500 800] +) +Symbol['v' 1200] +( + SymbolLine[0 3000 1000 5000 800] + SymbolLine[2000 3000 1000 5000 800] +) +Symbol['w' 1200] +( + SymbolLine[0 3000 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[500 5000 1000 5000 800] + SymbolLine[1000 5000 1500 4500 800] + SymbolLine[1500 3000 1500 4500 800] + SymbolLine[1500 4500 2000 5000 800] + SymbolLine[2000 5000 2500 5000 800] + SymbolLine[2500 5000 3000 4500 800] + SymbolLine[3000 3000 3000 4500 800] +) +Symbol['x' 1200] +( + SymbolLine[0 3000 2000 5000 800] + SymbolLine[0 5000 2000 3000 800] +) +Symbol['y' 1200] +( + SymbolLine[0 3000 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[2000 3000 2000 6000 800] + SymbolLine[1500 6500 2000 6000 800] + SymbolLine[500 6500 1500 6500 800] + SymbolLine[0 6000 500 6500 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[1500 5000 2000 4500 800] +) +Symbol['z' 1200] +( + SymbolLine[0 3000 2000 3000 800] + SymbolLine[0 5000 2000 3000 800] + SymbolLine[0 5000 2000 5000 800] +) +Symbol['{' 1200] +( + SymbolLine[500 1500 1000 1000 800] + SymbolLine[500 1500 500 2500 800] + SymbolLine[0 3000 500 2500 800] + SymbolLine[0 3000 500 3500 800] + SymbolLine[500 3500 500 4500 800] + SymbolLine[500 4500 1000 5000 800] +) +Symbol['|' 1200] +( + SymbolLine[0 1000 0 5000 800] +) +Symbol['}' 1200] +( + SymbolLine[0 1000 500 1500 800] + SymbolLine[500 1500 500 2500 800] + SymbolLine[500 2500 1000 3000 800] + SymbolLine[500 3500 1000 3000 800] + SymbolLine[500 3500 500 4500 800] + SymbolLine[0 5000 500 4500 800] +) +Symbol['~' 1200] +( + SymbolLine[0 3500 500 3000 800] + SymbolLine[500 3000 1000 3000 800] + SymbolLine[1000 3000 1500 3500 800] + SymbolLine[1500 3500 2000 3500 800] + SymbolLine[2000 3500 2500 3000 800] +) +Attribute("PCB::grid::unit" "mil") +Via[260000 120000 7874 4000 0 3150 "" ""] + +Element["" "rcy(150, bar-sign)" "C1" "acy150" 22500 95000 -2000 -4500 1 100 ""] +( + Pin[0 0 8000 5000 8600 3937 "" "1" "square"] + Pin[0 -15000 8000 5000 8600 3937 "" "2" ""] + ElementLine [0 -28500 0 -24500 1000] + ElementLine [0 9500 0 13500 1000] + ElementLine [-2000 11500 2000 11500 1000] + ElementLine [7874 -17883 7874 -11250 3937] + ElementLine [-7874 -17883 -7874 -11250 3937] + ElementLine [9842 -16040 9842 -11250 3937] + ElementLine [-9842 -16040 -9842 -11250 3937] + ElementLine [11811 -13006 11811 -11250 3937] + ElementLine [-11811 -13006 -11811 -11250 3937] + ElementArc [0 -7500 15000 15000 90 360 1000] + + ) + +Element["" "so(8)" "" "8*250" 57500 82500 -10000 0 1 100 ""] +( + Pad[-7500 7000 -7500 13500 2000 1000 3000 "" "1" "square,edge2"] + Pad[-7500 -13500 -7500 -7000 2000 1000 3000 "" "8" "square"] + Pad[-2500 7000 -2500 13500 2000 1000 3000 "" "2" "square,edge2"] + Pad[-2500 -13500 -2500 -7000 2000 1000 3000 "" "7" "square"] + Pad[2500 7000 2500 13500 2000 1000 3000 "" "3" "square,edge2"] + Pad[2500 -13500 2500 -7000 2000 1000 3000 "" "6" "square"] + Pad[7500 7000 7500 13500 2000 1000 3000 "" "4" "square,edge2"] + Pad[7500 -13500 7500 -7000 2000 1000 3000 "" "5" "square"] + ElementLine [-10000 16000 10000 16000 1000] + ElementLine [10000 -16000 10000 16000 1000] + ElementLine [-10000 -16000 10000 -16000 1000] + ElementLine [-10000 2500 -10000 16000 1000] + ElementLine [-10000 -16000 -10000 -2500 1000] + ElementArc [-10000 0 2500 2500 90 180 1000] + + ) + +Element["" "dip(4)" "" "4*300" 85000 102500 -10000 0 1 100 ""] +( + Pin[0 0 8000 5000 8600 3937 "" "1" "square"] + Pin[0 -30000 8000 5000 8600 3937 "" "4" ""] + Pin[10000 0 8000 5000 8600 3937 "" "2" ""] + Pin[10000 -30000 8000 5000 8600 3937 "" "3" ""] + ElementLine [-5000 5000 15000 5000 1000] + ElementLine [15000 -35000 15000 5000 1000] + ElementLine [-5000 -35000 15000 -35000 1000] + ElementLine [-5000 -10000 -5000 5000 1000] + ElementLine [-5000 -35000 -5000 -20000 1000] + ElementArc [-5000 -15000 5000 5000 90 180 1000] + + ) + +Element["" "tssop(8)" "" "8*6.4mm" 117500 82500 -10000 0 1 100 ""] +( + Pad[-3838 10236 -3838 14173 1771 1000 3000 "" "1" "square,edge2"] + Pad[-3838 -14173 -3838 -10236 1771 1000 3000 "" "8" "square"] + Pad[-1278 10236 -1278 14173 1771 1000 3000 "" "2" "square,edge2"] + Pad[-1278 -14173 -1278 -10236 1771 1000 3000 "" "7" "square"] + Pad[1280 10236 1280 14173 1771 1000 3000 "" "3" "square,edge2"] + Pad[1280 -14173 1280 -10236 1771 1000 3000 "" "6" "square"] + Pad[3839 10236 3839 14173 1771 1000 3000 "" "4" "square,edge2"] + Pad[3839 -14173 3839 -10236 1771 1000 3000 "" "5" "square"] + ElementLine [-6038 15973 6039 15973 1000] + ElementLine [6039 -15973 6039 15973 1000] + ElementLine [-6038 -15973 6039 -15973 1000] + ElementLine [-6038 2500 -6038 15973 1000] + ElementLine [-6038 -15973 -6038 -2500 1000] + ElementArc [-6038 0 2500 2500 90 180 1000] + + ) + +Element["" "connector(2,3)" "" "2*3" 142500 72500 0 -10000 0 100 ""] +( + Pin[0 0 8000 5000 8600 3937 "" "1" "square"] + Pin[0 10000 8000 5000 8600 3937 "" "2" ""] + Pin[0 20000 8000 5000 8600 3937 "" "3" ""] + Pin[10000 0 8000 5000 8600 3937 "" "4" ""] + Pin[10000 10000 8000 5000 8600 3937 "" "5" ""] + Pin[10000 20000 8000 5000 8600 3937 "" "6" ""] + ElementLine [-5000 -5000 -5000 25000 1000] + ElementLine [-5000 -5000 15000 -5000 1000] + ElementLine [15000 25000 -5000 25000 1000] + ElementLine [15000 25000 15000 -5000 1000] + ElementLine [-5000 5000 5000 5000 1000] + ElementLine [5000 -5000 5000 5000 1000] + + ) + +Element["" "connector(2,3,eshift=x)" "" "2*3" 175000 72500 0 -10000 0 100 ""] +( + Pin[0 0 8000 5000 8600 3937 "" "1" "square"] + Pin[0 10000 8000 5000 8600 3937 "" "2" ""] + Pin[0 20000 8000 5000 8600 3937 "" "3" ""] + Pin[10000 5000 8000 5000 8600 3937 "" "4" ""] + Pin[10000 15000 8000 5000 8600 3937 "" "5" ""] + Pin[10000 25000 8000 5000 8600 3937 "" "6" ""] + ElementLine [-5000 -5000 -5000 30000 1000] + ElementLine [-5000 -5000 15000 -5000 1000] + ElementLine [15000 30000 -5000 30000 1000] + ElementLine [15000 30000 15000 -5000 1000] + ElementLine [-5000 5000 5000 5000 1000] + ElementLine [5000 -5000 5000 5000 1000] + + ) + +Element["" "connector(2,3,eshift=x,etrunc=1)" "" "2*3" 207500 72500 0 -10000 0 100 ""] +( + Pin[0 0 8000 5000 8600 3937 "" "1" "square"] + Pin[0 10000 8000 5000 8600 3937 "" "2" ""] + Pin[0 20000 8000 5000 8600 3937 "" "3" ""] + Pin[10000 5000 8000 5000 8600 3937 "" "4" ""] + Pin[10000 15000 8000 5000 8600 3937 "" "5" ""] + ElementLine [-5000 -5000 -5000 25000 1000] + ElementLine [-5000 -5000 15000 -5000 1000] + ElementLine [15000 25000 -5000 25000 1000] + ElementLine [15000 25000 15000 -5000 1000] + ElementLine [-5000 5000 5000 5000 1000] + ElementLine [5000 -5000 5000 5000 1000] + + ) + +Element["" "acy(300)" "" "acy300" 20000 50000 -12000 -9000 1 100 ""] +( + Pin[0 0 8000 5000 8600 3937 "" "1" "square"] + Pin[0 -30000 8000 5000 8600 3937 "" "2" ""] + ElementLine [0 -7500 0 0 1000] + ElementLine [0 -30000 0 -22500 1000] + ElementLine [-2500 -7500 2500 -7500 1000] + ElementLine [-2500 -22500 -2500 -7500 1000] + ElementLine [2500 -22500 2500 -7500 1000] + ElementLine [-2500 -22500 2500 -22500 1000] + + ) + +Element["" "acy(300, endcap)" "" "acy300" 40000 50000 -2000 -9000 1 100 ""] +( + Pin[0 0 8000 5000 8600 3937 "" "1" "square"] + Pin[0 -30000 8000 5000 8600 3937 "" "2" ""] + ElementLine [0 -7500 0 0 1000] + ElementLine [0 -30000 0 -22500 1000] + ElementLine [2500 -20625 2500 -9375 1000] + ElementLine [2500 -9375 3000 -9166 1000] + ElementLine [2500 -20625 3000 -20833 1000] + ElementLine [-2500 -20625 -2500 -9375 1000] + ElementLine [-2500 -9375 -3000 -9166 1000] + ElementLine [-2500 -20625 -3000 -20833 1000] + ElementLine [-2500 -7500 2500 -7500 1000] + ElementLine [-3000 -9166 -3000 -8000 1000] + ElementLine [3000 -9166 3000 -8000 1000] + ElementLine [-3000 -22000 -3000 -20833 1000] + ElementLine [3000 -22000 3000 -20833 1000] + ElementLine [-2500 -22500 2500 -22500 1000] + ElementArc [-2500 -8000 500 500 0 90 1000] + ElementArc [2500 -8000 500 500 90 90 1000] + ElementArc [-2500 -22000 500 500 270 90 1000] + ElementArc [2500 -22000 500 500 180 90 1000] + + ) + +Element["" "acy(300, coil, dot)" "" "acy300" 60000 50000 -2000 -9000 1 100 ""] +( + Pin[0 0 8000 5000 8600 3937 "" "1" "square"] + Pin[0 -30000 8000 5000 8600 3937 "" "2" ""] + ElementLine [0 -7500 0 0 1000] + ElementLine [0 -30000 0 -22500 1000] + ElementArc [0 -9375 1875 1875 270 180 1000] + ElementArc [0 -13125 1875 1875 270 180 1000] + ElementArc [0 -16875 1875 1875 270 180 1000] + ElementArc [0 -20625 1875 1875 270 180 1000] + ElementArc [-1250 -5500 666 666 90 360 1000] + + ) + +Element["" "acy(300, pol=bar)" "" "acy300" 80000 50000 -2000 -9000 1 100 ""] +( + Pin[0 0 8000 5000 8600 3937 "" "1" "square"] + Pin[0 -30000 8000 5000 8600 3937 "" "2" ""] + ElementLine [0 -7500 0 0 1000] + ElementLine [0 -30000 0 -22500 1000] + ElementLine [-2500 -7500 2500 -7500 1000] + ElementLine [-2500 -22500 -2500 -7500 1000] + ElementLine [2500 -22500 2500 -7500 1000] + ElementLine [-2500 -22500 2500 -22500 1000] + ElementLine [-2500 -6500 2500 -6500 1000] + ElementLine [-2500 -8500 -2500 -6500 1000] + ElementLine [2500 -8500 2500 -6500 1000] + ElementLine [-2500 -8500 2500 -8500 1000] + + ) + +Element["" "acy(300, wiper=aarrow)" "" "acy300" 100000 50000 -2000 -9000 1 100 ""] +( + Pin[0 0 8000 5000 8600 3937 "" "1" "square"] + Pin[0 -30000 8000 5000 8600 3937 "" "2" ""] + ElementLine [0 -7500 0 0 1000] + ElementLine [0 -30000 0 -22500 1000] + ElementLine [-2500 -7500 2500 -7500 1000] + ElementLine [-2500 -22500 -2500 -7500 1000] + ElementLine [2500 -22500 2500 -7500 1000] + ElementLine [-2500 -22500 2500 -22500 1000] + ElementLine [5000 -12500 -8000 -17500 1000] + ElementLine [-8000 -17500 -6492 -15848 1000] + ElementLine [-8000 -17500 -5774 -17715 1000] + ElementLine [-5774 -17715 -6492 -15848 1000] + + ) + +Element["" "acy(300, wiper=parrow)" "" "acy300" 120000 50000 -2000 -9000 1 100 ""] +( + Pin[0 0 8000 5000 8600 3937 "" "1" "square"] + Pin[0 -30000 8000 5000 8600 3937 "" "2" ""] + ElementLine [0 -7500 0 0 1000] + ElementLine [0 -30000 0 -22500 1000] + ElementLine [-2500 -7500 2500 -7500 1000] + ElementLine [-2500 -22500 -2500 -7500 1000] + ElementLine [2500 -22500 2500 -7500 1000] + ElementLine [-2500 -22500 2500 -22500 1000] + ElementLine [-8000 -15000 -2500 -15000 1000] + ElementLine [-2500 -15000 -4500 -16000 1000] + ElementLine [-2500 -15000 -4500 -14000 1000] + ElementLine [-4500 -16000 -4500 -14000 1000] + + ) + +Element["" "acy(300, wiper=looparrow)" "" "acy300" 140000 50000 -2000 -9000 1 100 ""] +( + Pin[0 0 8000 5000 8600 3937 "" "1" "square"] + Pin[0 -30000 8000 5000 8600 3937 "" "2" ""] + ElementLine [0 -7500 0 0 1000] + ElementLine [0 -30000 0 -22500 1000] + ElementLine [-2500 -7500 2500 -7500 1000] + ElementLine [-2500 -22500 -2500 -7500 1000] + ElementLine [2500 -22500 2500 -7500 1000] + ElementLine [-2500 -22500 2500 -22500 1000] + ElementLine [-8000 -15000 -2500 -15000 1000] + ElementLine [-2500 -15000 -4500 -16000 1000] + ElementLine [-2500 -15000 -4500 -14000 1000] + ElementLine [-4500 -16000 -4500 -14000 1000] + ElementLine [-8000 -24375 -8000 -15000 1000] + ElementLine [-8000 -24375 0 -24375 1000] + + ) + +Element["" "acy(300, zigzag)" "" "acy300" 160000 50000 -2000 -9000 1 100 ""] +( + Pin[0 0 8000 5000 8600 3937 "" "1" "square"] + Pin[0 -30000 8000 5000 8600 3937 "" "2" ""] + ElementLine [0 -7500 0 0 1000] + ElementLine [0 -30000 0 -22500 1000] + ElementLine [0 -7500 -2500 -8750 1000] + ElementLine [-2500 -8750 2500 -11250 1000] + ElementLine [2500 -11250 0 -12500 1000] + ElementLine [0 -12500 -2500 -13750 1000] + ElementLine [-2500 -13750 2500 -16250 1000] + ElementLine [2500 -16250 0 -17500 1000] + ElementLine [0 -17500 -2500 -18750 1000] + ElementLine [-2500 -18750 2500 -21250 1000] + ElementLine [2500 -21250 0 -22500 1000] + + ) + +Element["" "acy(300, core)" "" "acy300" 180000 50000 -2000 -9000 1 100 ""] +( + Pin[0 0 8000 5000 8600 3937 "" "1" "square"] + Pin[0 -30000 8000 5000 8600 3937 "" "2" ""] + ElementLine [0 -7500 0 0 1000] + ElementLine [0 -30000 0 -22500 1000] + ElementLine [-4875 -22500 -4875 -7500 1000] + ElementArc [0 -9375 1875 1875 270 180 1000] + ElementArc [0 -13125 1875 1875 270 180 1000] + ElementArc [0 -16875 1875 1875 270 180 1000] + ElementArc [0 -20625 1875 1875 270 180 1000] + + ) + +Element["" "acy(200, standing, pol=sign, dia=100)" "" "acy200" 240000 90000 -2000 -6000 1 100 ""] +( + Pin[0 0 8000 5000 8600 3937 "" "1" "square"] + Pin[0 -20000 8000 5000 8600 3937 "" "2" ""] + ElementLine [0 -5000 0 0 1000] + ElementLine [0 -20000 0 -15000 1000] + ElementLine [0 -20000 0 0 1000] + ElementLine [2200 -6100 2200 -4100 1000] + ElementLine [2200 -15900 2200 -13900 1000] + ElementLine [1200 -14900 3200 -14900 1000] + ElementArc [0 0 10000 10000 90 360 1000] + + ) + +Element["" "alf(300,schottky)" "" "acy300" 200000 50000 -5000 -22000 1 100 ""] +( + Pin[0 0 8000 5000 8600 3937 "" "1" "square"] + Pin[0 -30000 8000 5000 8600 3937 "" "2" ""] + ElementLine [0 -10000 0 0 1000] + ElementLine [0 -30000 0 -20000 1000] + ElementLine [-5000 -20000 5000 -20000 1000] + ElementLine [-5000 -20000 0 -10000 1000] + ElementLine [5000 -20000 0 -10000 1000] + ElementLine [-3500 -10000 3500 -10000 1000] + ElementArc [-3500 -11500 1500 1500 270 180 1000] + ElementArc [3500 -8500 1500 1500 90 180 1000] + + ) + +Element["" "alf(300,tunnel)" "" "acy300" 220000 50000 -5000 -22000 1 100 ""] +( + Pin[0 0 8000 5000 8600 3937 "" "1" "square"] + Pin[0 -30000 8000 5000 8600 3937 "" "2" ""] + ElementLine [0 -10000 0 0 1000] + ElementLine [0 -30000 0 -20000 1000] + ElementLine [-5000 -20000 5000 -20000 1000] + ElementLine [-5000 -20000 0 -10000 1000] + ElementLine [5000 -20000 0 -10000 1000] + ElementLine [-5000 -10000 5000 -10000 1000] + ElementLine [5000 -11500 5000 -10000 1000] + ElementLine [-5000 -11500 -5000 -10000 1000] + + ) + +Element["" "alf(300,zener)" "" "acy300" 240000 50000 -5000 -22000 1 100 ""] +( + Pin[0 0 8000 5000 8600 3937 "" "1" "square"] + Pin[0 -30000 8000 5000 8600 3937 "" "2" ""] + ElementLine [0 -10000 0 0 1000] + ElementLine [0 -30000 0 -20000 1000] + ElementLine [-5000 -20000 5000 -20000 1000] + ElementLine [-5000 -20000 0 -10000 1000] + ElementLine [5000 -20000 0 -10000 1000] + ElementLine [-5000 -10000 5000 -10000 1000] + ElementLine [5000 -10000 5000 -8500 1000] + ElementLine [-5000 -11500 -5000 -10000 1000] + + ) +Layer(1 "component") +( +) +Layer(2 "solder") +( +) +Layer(3 "comp-GND") +( +) +Layer(4 "comp-power") +( +) +Layer(5 "sold-GND") +( +) +Layer(6 "sold-power") +( +) +Layer(7 "signal3") +( +) +Layer(8 "outline") +( +) +Layer(9 "silk") +( +) +Layer(10 "silk") +( +) Index: tags/2.1.2/util/pcblib-map/smd2.pcb =================================================================== --- tags/2.1.2/util/pcblib-map/smd2.pcb (nonexistent) +++ tags/2.1.2/util/pcblib-map/smd2.pcb (revision 24813) @@ -0,0 +1,1086 @@ +# release: pcb 20110918 + +# To read pcb files, the pcb version (or the git source date) must be >= the file version +FileVersion[20070407] + +PCB["" 170000 160000] + +Grid[2500.0 0 0 1] +Cursor[0 0 0.000000] +PolyArea[3100.006200] +Thermal[0.500000] +DRC[1200 900 1000 700 1500 1000] +Flags("nameonpcb,clearnew,snappin") +Groups("1,3,4,c:2,5,6,s:7:8") +Styles["Signal,1000,7874,3150,2000:Power,2000,8661,3937,2000:Fat,8000,13780,4724,2500:Sig-tight,1000,6400,3150,1200"] + +Symbol[' ' 1800] +( +) +Symbol['!' 1200] +( + SymbolLine[0 4500 0 5000 800] + SymbolLine[0 1000 0 3500 800] +) +Symbol['"' 1200] +( + SymbolLine[0 1000 0 2000 800] + SymbolLine[1000 1000 1000 2000 800] +) +Symbol['#' 1200] +( + SymbolLine[0 3500 2000 3500 800] + SymbolLine[0 2500 2000 2500 800] + SymbolLine[1500 2000 1500 4000 800] + SymbolLine[500 2000 500 4000 800] +) +Symbol['$' 1200] +( + SymbolLine[1500 1500 2000 2000 800] + SymbolLine[500 1500 1500 1500 800] + SymbolLine[0 2000 500 1500 800] + SymbolLine[0 2000 0 2500 800] + SymbolLine[0 2500 500 3000 800] + SymbolLine[500 3000 1500 3000 800] + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[2000 3500 2000 4000 800] + SymbolLine[1500 4500 2000 4000 800] + SymbolLine[500 4500 1500 4500 800] + SymbolLine[0 4000 500 4500 800] + SymbolLine[1000 1000 1000 5000 800] +) +Symbol['%' 1200] +( + SymbolLine[0 1500 0 2000 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 1000 1000 800] + SymbolLine[1000 1000 1500 1500 800] + SymbolLine[1500 1500 1500 2000 800] + SymbolLine[1000 2500 1500 2000 800] + SymbolLine[500 2500 1000 2500 800] + SymbolLine[0 2000 500 2500 800] + SymbolLine[0 5000 4000 1000 800] + SymbolLine[3500 5000 4000 4500 800] + SymbolLine[4000 4000 4000 4500 800] + SymbolLine[3500 3500 4000 4000 800] + SymbolLine[3000 3500 3500 3500 800] + SymbolLine[2500 4000 3000 3500 800] + SymbolLine[2500 4000 2500 4500 800] + SymbolLine[2500 4500 3000 5000 800] + SymbolLine[3000 5000 3500 5000 800] +) +Symbol['&' 1200] +( + SymbolLine[0 4500 500 5000 800] + SymbolLine[0 1500 0 2500 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[0 3500 1500 2000 800] + SymbolLine[500 5000 1000 5000 800] + SymbolLine[1000 5000 2000 4000 800] + SymbolLine[0 2500 2500 5000 800] + SymbolLine[500 1000 1000 1000 800] + SymbolLine[1000 1000 1500 1500 800] + SymbolLine[1500 1500 1500 2000 800] + SymbolLine[0 3500 0 4500 800] +) +Symbol[''' 1200] +( + SymbolLine[0 2000 1000 1000 800] +) +Symbol['(' 1200] +( + SymbolLine[0 4500 500 5000 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[0 1500 0 4500 800] +) +Symbol[')' 1200] +( + SymbolLine[0 1000 500 1500 800] + SymbolLine[500 1500 500 4500 800] + SymbolLine[0 5000 500 4500 800] +) +Symbol['*' 1200] +( + SymbolLine[0 2000 2000 4000 800] + SymbolLine[0 4000 2000 2000 800] + SymbolLine[0 3000 2000 3000 800] + SymbolLine[1000 2000 1000 4000 800] +) +Symbol['+' 1200] +( + SymbolLine[0 3000 2000 3000 800] + SymbolLine[1000 2000 1000 4000 800] +) +Symbol[',' 1200] +( + SymbolLine[0 6000 1000 5000 800] +) +Symbol['-' 1200] +( + SymbolLine[0 3000 2000 3000 800] +) +Symbol['.' 1200] +( + SymbolLine[0 5000 500 5000 800] +) +Symbol['/' 1200] +( + SymbolLine[0 4500 3000 1500 800] +) +Symbol['0' 1200] +( + SymbolLine[0 4500 500 5000 800] + SymbolLine[0 1500 0 4500 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 1500 1000 800] + SymbolLine[1500 1000 2000 1500 800] + SymbolLine[2000 1500 2000 4500 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[0 4000 2000 2000 800] +) +Symbol['1' 1200] +( + SymbolLine[0 1800 800 1000 800] + SymbolLine[800 1000 800 5000 800] + SymbolLine[0 5000 1500 5000 800] +) +Symbol['2' 1200] +( + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 2000 1000 800] + SymbolLine[2000 1000 2500 1500 800] + SymbolLine[2500 1500 2500 2500 800] + SymbolLine[0 5000 2500 2500 800] + SymbolLine[0 5000 2500 5000 800] +) +Symbol['3' 1200] +( + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 1500 1000 800] + SymbolLine[1500 1000 2000 1500 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[500 2800 1500 2800 800] + SymbolLine[2000 1500 2000 2300 800] + SymbolLine[2000 3300 2000 4500 800] + SymbolLine[2000 3300 1500 2800 800] + SymbolLine[2000 2300 1500 2800 800] +) +Symbol['4' 1200] +( + SymbolLine[0 3500 2000 1000 800] + SymbolLine[0 3500 2500 3500 800] + SymbolLine[2000 1000 2000 5000 800] +) +Symbol['5' 1200] +( + SymbolLine[0 1000 2000 1000 800] + SymbolLine[0 1000 0 3000 800] + SymbolLine[0 3000 500 2500 800] + SymbolLine[500 2500 1500 2500 800] + SymbolLine[1500 2500 2000 3000 800] + SymbolLine[2000 3000 2000 4500 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[0 4500 500 5000 800] +) +Symbol['6' 1200] +( + SymbolLine[1500 1000 2000 1500 800] + SymbolLine[500 1000 1500 1000 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[0 1500 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[1500 2800 2000 3300 800] + SymbolLine[0 2800 1500 2800 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[2000 3300 2000 4500 800] +) +Symbol['7' 1200] +( + SymbolLine[500 5000 2500 1000 800] + SymbolLine[0 1000 2500 1000 800] +) +Symbol['8' 1200] +( + SymbolLine[0 4500 500 5000 800] + SymbolLine[0 3700 0 4500 800] + SymbolLine[0 3700 700 3000 800] + SymbolLine[700 3000 1300 3000 800] + SymbolLine[1300 3000 2000 3700 800] + SymbolLine[2000 3700 2000 4500 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[0 2300 700 3000 800] + SymbolLine[0 1500 0 2300 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 1500 1000 800] + SymbolLine[1500 1000 2000 1500 800] + SymbolLine[2000 1500 2000 2300 800] + SymbolLine[1300 3000 2000 2300 800] +) +Symbol['9' 1200] +( + SymbolLine[500 5000 2000 3000 800] + SymbolLine[2000 1500 2000 3000 800] + SymbolLine[1500 1000 2000 1500 800] + SymbolLine[500 1000 1500 1000 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[0 1500 0 2500 800] + SymbolLine[0 2500 500 3000 800] + SymbolLine[500 3000 2000 3000 800] +) +Symbol[':' 1200] +( + SymbolLine[0 2500 500 2500 800] + SymbolLine[0 3500 500 3500 800] +) +Symbol[';' 1200] +( + SymbolLine[0 5000 1000 4000 800] + SymbolLine[1000 2500 1000 3000 800] +) +Symbol['<' 1200] +( + SymbolLine[0 3000 1000 2000 800] + SymbolLine[0 3000 1000 4000 800] +) +Symbol['=' 1200] +( + SymbolLine[0 2500 2000 2500 800] + SymbolLine[0 3500 2000 3500 800] +) +Symbol['>' 1200] +( + SymbolLine[0 2000 1000 3000 800] + SymbolLine[0 4000 1000 3000 800] +) +Symbol['?' 1200] +( + SymbolLine[1000 3000 1000 3500 800] + SymbolLine[1000 4500 1000 5000 800] + SymbolLine[0 1500 0 2000 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 1500 1000 800] + SymbolLine[1500 1000 2000 1500 800] + SymbolLine[2000 1500 2000 2000 800] + SymbolLine[1000 3000 2000 2000 800] +) +Symbol['@' 1200] +( + SymbolLine[0 1000 0 4000 800] + SymbolLine[0 4000 1000 5000 800] + SymbolLine[1000 5000 4000 5000 800] + SymbolLine[5000 3500 5000 1000 800] + SymbolLine[5000 1000 4000 0 800] + SymbolLine[4000 0 1000 0 800] + SymbolLine[1000 0 0 1000 800] + SymbolLine[1500 2000 1500 3000 800] + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[2000 3500 3000 3500 800] + SymbolLine[3000 3500 3500 3000 800] + SymbolLine[3500 3000 4000 3500 800] + SymbolLine[3500 3000 3500 1500 800] + SymbolLine[3500 2000 3000 1500 800] + SymbolLine[2000 1500 3000 1500 800] + SymbolLine[2000 1500 1500 2000 800] + SymbolLine[4000 3500 5000 3500 800] +) +Symbol['A' 1200] +( + SymbolLine[0 2000 0 5000 800] + SymbolLine[0 2000 700 1000 800] + SymbolLine[700 1000 1800 1000 800] + SymbolLine[1800 1000 2500 2000 800] + SymbolLine[2500 2000 2500 5000 800] + SymbolLine[0 3000 2500 3000 800] +) +Symbol['B' 1200] +( + SymbolLine[0 5000 2000 5000 800] + SymbolLine[2000 5000 2500 4500 800] + SymbolLine[2500 3300 2500 4500 800] + SymbolLine[2000 2800 2500 3300 800] + SymbolLine[500 2800 2000 2800 800] + SymbolLine[500 1000 500 5000 800] + SymbolLine[0 1000 2000 1000 800] + SymbolLine[2000 1000 2500 1500 800] + SymbolLine[2500 1500 2500 2300 800] + SymbolLine[2000 2800 2500 2300 800] +) +Symbol['C' 1200] +( + SymbolLine[700 5000 2000 5000 800] + SymbolLine[0 4300 700 5000 800] + SymbolLine[0 1700 0 4300 800] + SymbolLine[0 1700 700 1000 800] + SymbolLine[700 1000 2000 1000 800] +) +Symbol['D' 1200] +( + SymbolLine[500 1000 500 5000 800] + SymbolLine[1800 1000 2500 1700 800] + SymbolLine[2500 1700 2500 4300 800] + SymbolLine[1800 5000 2500 4300 800] + SymbolLine[0 5000 1800 5000 800] + SymbolLine[0 1000 1800 1000 800] +) +Symbol['E' 1200] +( + SymbolLine[0 2800 1500 2800 800] + SymbolLine[0 5000 2000 5000 800] + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 1000 2000 1000 800] +) +Symbol['F' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 1000 2000 1000 800] + SymbolLine[0 2800 1500 2800 800] +) +Symbol['G' 1200] +( + SymbolLine[2000 1000 2500 1500 800] + SymbolLine[500 1000 2000 1000 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[0 1500 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[500 5000 2000 5000 800] + SymbolLine[2000 5000 2500 4500 800] + SymbolLine[2500 3500 2500 4500 800] + SymbolLine[2000 3000 2500 3500 800] + SymbolLine[1000 3000 2000 3000 800] +) +Symbol['H' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[2500 1000 2500 5000 800] + SymbolLine[0 3000 2500 3000 800] +) +Symbol['I' 1200] +( + SymbolLine[0 1000 1000 1000 800] + SymbolLine[500 1000 500 5000 800] + SymbolLine[0 5000 1000 5000 800] +) +Symbol['J' 1200] +( + SymbolLine[700 1000 1500 1000 800] + SymbolLine[1500 1000 1500 4500 800] + SymbolLine[1000 5000 1500 4500 800] + SymbolLine[500 5000 1000 5000 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[0 4500 0 4000 800] +) +Symbol['K' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 3000 2000 1000 800] + SymbolLine[0 3000 2000 5000 800] +) +Symbol['L' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 5000 2000 5000 800] +) +Symbol['M' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 1000 1500 3000 800] + SymbolLine[1500 3000 3000 1000 800] + SymbolLine[3000 1000 3000 5000 800] +) +Symbol['N' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 1000 2500 5000 800] + SymbolLine[2500 1000 2500 5000 800] +) +Symbol['O' 1200] +( + SymbolLine[0 1500 0 4500 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 1500 1000 800] + SymbolLine[1500 1000 2000 1500 800] + SymbolLine[2000 1500 2000 4500 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[0 4500 500 5000 800] +) +Symbol['P' 1200] +( + SymbolLine[500 1000 500 5000 800] + SymbolLine[0 1000 2000 1000 800] + SymbolLine[2000 1000 2500 1500 800] + SymbolLine[2500 1500 2500 2500 800] + SymbolLine[2000 3000 2500 2500 800] + SymbolLine[500 3000 2000 3000 800] +) +Symbol['Q' 1200] +( + SymbolLine[0 1500 0 4500 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 1500 1000 800] + SymbolLine[1500 1000 2000 1500 800] + SymbolLine[2000 1500 2000 4000 800] + SymbolLine[1000 5000 2000 4000 800] + SymbolLine[500 5000 1000 5000 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[1000 3500 2000 5000 800] +) +Symbol['R' 1200] +( + SymbolLine[0 1000 2000 1000 800] + SymbolLine[2000 1000 2500 1500 800] + SymbolLine[2500 1500 2500 2500 800] + SymbolLine[2000 3000 2500 2500 800] + SymbolLine[500 3000 2000 3000 800] + SymbolLine[500 1000 500 5000 800] + SymbolLine[1300 3000 2500 5000 800] +) +Symbol['S' 1200] +( + SymbolLine[2000 1000 2500 1500 800] + SymbolLine[500 1000 2000 1000 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[0 1500 0 2500 800] + SymbolLine[0 2500 500 3000 800] + SymbolLine[500 3000 2000 3000 800] + SymbolLine[2000 3000 2500 3500 800] + SymbolLine[2500 3500 2500 4500 800] + SymbolLine[2000 5000 2500 4500 800] + SymbolLine[500 5000 2000 5000 800] + SymbolLine[0 4500 500 5000 800] +) +Symbol['T' 1200] +( + SymbolLine[0 1000 2000 1000 800] + SymbolLine[1000 1000 1000 5000 800] +) +Symbol['U' 1200] +( + SymbolLine[0 1000 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[2000 1000 2000 4500 800] +) +Symbol['V' 1200] +( + SymbolLine[0 1000 1000 5000 800] + SymbolLine[1000 5000 2000 1000 800] +) +Symbol['W' 1200] +( + SymbolLine[0 1000 0 3000 800] + SymbolLine[0 3000 500 5000 800] + SymbolLine[500 5000 1500 3000 800] + SymbolLine[1500 3000 2500 5000 800] + SymbolLine[2500 5000 3000 3000 800] + SymbolLine[3000 3000 3000 1000 800] +) +Symbol['X' 1200] +( + SymbolLine[0 5000 2500 1000 800] + SymbolLine[0 1000 2500 5000 800] +) +Symbol['Y' 1200] +( + SymbolLine[0 1000 1000 3000 800] + SymbolLine[1000 3000 2000 1000 800] + SymbolLine[1000 3000 1000 5000 800] +) +Symbol['Z' 1200] +( + SymbolLine[0 1000 2500 1000 800] + SymbolLine[0 5000 2500 1000 800] + SymbolLine[0 5000 2500 5000 800] +) +Symbol['[' 1200] +( + SymbolLine[0 1000 500 1000 800] + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 5000 500 5000 800] +) +Symbol['\' 1200] +( + SymbolLine[0 1500 3000 4500 800] +) +Symbol[']' 1200] +( + SymbolLine[0 1000 500 1000 800] + SymbolLine[500 1000 500 5000 800] + SymbolLine[0 5000 500 5000 800] +) +Symbol['^' 1200] +( + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 1000 1500 800] +) +Symbol['_' 1200] +( + SymbolLine[0 5000 2000 5000 800] +) +Symbol['a' 1200] +( + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[500 3000 1500 3000 800] + SymbolLine[0 3500 500 3000 800] + SymbolLine[0 3500 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[2000 3000 2000 4500 800] + SymbolLine[2000 4500 2500 5000 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[1500 5000 2000 4500 800] +) +Symbol['b' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[2000 3500 2000 4500 800] + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[500 3000 1500 3000 800] + SymbolLine[0 3500 500 3000 800] +) +Symbol['c' 1200] +( + SymbolLine[500 3000 2000 3000 800] + SymbolLine[0 3500 500 3000 800] + SymbolLine[0 3500 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[500 5000 2000 5000 800] +) +Symbol['d' 1200] +( + SymbolLine[2000 1000 2000 5000 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[0 3500 0 4500 800] + SymbolLine[0 3500 500 3000 800] + SymbolLine[500 3000 1500 3000 800] + SymbolLine[1500 3000 2000 3500 800] +) +Symbol['e' 1200] +( + SymbolLine[500 5000 2000 5000 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[0 3500 0 4500 800] + SymbolLine[0 3500 500 3000 800] + SymbolLine[500 3000 1500 3000 800] + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[0 4000 2000 4000 800] + SymbolLine[2000 4000 2000 3500 800] +) +Symbol['f' 1000] +( + SymbolLine[500 1500 500 5000 800] + SymbolLine[500 1500 1000 1000 800] + SymbolLine[1000 1000 1500 1000 800] + SymbolLine[0 3000 1000 3000 800] +) +Symbol['g' 1200] +( + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[500 3000 1500 3000 800] + SymbolLine[0 3500 500 3000 800] + SymbolLine[0 3500 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[0 6000 500 6500 800] + SymbolLine[500 6500 1500 6500 800] + SymbolLine[1500 6500 2000 6000 800] + SymbolLine[2000 3000 2000 6000 800] +) +Symbol['h' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 3500 500 3000 800] + SymbolLine[500 3000 1500 3000 800] + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[2000 3500 2000 5000 800] +) +Symbol['i' 1000] +( + SymbolLine[0 2000 0 2100 1000] + SymbolLine[0 3500 0 5000 800] +) +Symbol['j' 1000] +( + SymbolLine[500 2000 500 2100 1000] + SymbolLine[500 3500 500 6000 800] + SymbolLine[0 6500 500 6000 800] +) +Symbol['k' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 3500 1500 5000 800] + SymbolLine[0 3500 1000 2500 800] +) +Symbol['l' 1000] +( + SymbolLine[0 1000 0 4500 800] + SymbolLine[0 4500 500 5000 800] +) +Symbol['m' 1200] +( + SymbolLine[500 3500 500 5000 800] + SymbolLine[500 3500 1000 3000 800] + SymbolLine[1000 3000 1500 3000 800] + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[2000 3500 2000 5000 800] + SymbolLine[2000 3500 2500 3000 800] + SymbolLine[2500 3000 3000 3000 800] + SymbolLine[3000 3000 3500 3500 800] + SymbolLine[3500 3500 3500 5000 800] + SymbolLine[0 3000 500 3500 800] +) +Symbol['n' 1200] +( + SymbolLine[500 3500 500 5000 800] + SymbolLine[500 3500 1000 3000 800] + SymbolLine[1000 3000 1500 3000 800] + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[2000 3500 2000 5000 800] + SymbolLine[0 3000 500 3500 800] +) +Symbol['o' 1200] +( + SymbolLine[0 3500 0 4500 800] + SymbolLine[0 3500 500 3000 800] + SymbolLine[500 3000 1500 3000 800] + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[2000 3500 2000 4500 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[0 4500 500 5000 800] +) +Symbol['p' 1200] +( + SymbolLine[500 3500 500 6500 800] + SymbolLine[0 3000 500 3500 800] + SymbolLine[500 3500 1000 3000 800] + SymbolLine[1000 3000 2000 3000 800] + SymbolLine[2000 3000 2500 3500 800] + SymbolLine[2500 3500 2500 4500 800] + SymbolLine[2000 5000 2500 4500 800] + SymbolLine[1000 5000 2000 5000 800] + SymbolLine[500 4500 1000 5000 800] +) +Symbol['q' 1200] +( + SymbolLine[2000 3500 2000 6500 800] + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[500 3000 1500 3000 800] + SymbolLine[0 3500 500 3000 800] + SymbolLine[0 3500 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[1500 5000 2000 4500 800] +) +Symbol['r' 1200] +( + SymbolLine[500 3500 500 5000 800] + SymbolLine[500 3500 1000 3000 800] + SymbolLine[1000 3000 2000 3000 800] + SymbolLine[0 3000 500 3500 800] +) +Symbol['s' 1200] +( + SymbolLine[500 5000 2000 5000 800] + SymbolLine[2000 5000 2500 4500 800] + SymbolLine[2000 4000 2500 4500 800] + SymbolLine[500 4000 2000 4000 800] + SymbolLine[0 3500 500 4000 800] + SymbolLine[0 3500 500 3000 800] + SymbolLine[500 3000 2000 3000 800] + SymbolLine[2000 3000 2500 3500 800] + SymbolLine[0 4500 500 5000 800] +) +Symbol['t' 1000] +( + SymbolLine[500 1000 500 4500 800] + SymbolLine[500 4500 1000 5000 800] + SymbolLine[0 2500 1000 2500 800] +) +Symbol['u' 1200] +( + SymbolLine[0 3000 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[2000 3000 2000 4500 800] +) +Symbol['v' 1200] +( + SymbolLine[0 3000 1000 5000 800] + SymbolLine[2000 3000 1000 5000 800] +) +Symbol['w' 1200] +( + SymbolLine[0 3000 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[500 5000 1000 5000 800] + SymbolLine[1000 5000 1500 4500 800] + SymbolLine[1500 3000 1500 4500 800] + SymbolLine[1500 4500 2000 5000 800] + SymbolLine[2000 5000 2500 5000 800] + SymbolLine[2500 5000 3000 4500 800] + SymbolLine[3000 3000 3000 4500 800] +) +Symbol['x' 1200] +( + SymbolLine[0 3000 2000 5000 800] + SymbolLine[0 5000 2000 3000 800] +) +Symbol['y' 1200] +( + SymbolLine[0 3000 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[2000 3000 2000 6000 800] + SymbolLine[1500 6500 2000 6000 800] + SymbolLine[500 6500 1500 6500 800] + SymbolLine[0 6000 500 6500 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[1500 5000 2000 4500 800] +) +Symbol['z' 1200] +( + SymbolLine[0 3000 2000 3000 800] + SymbolLine[0 5000 2000 3000 800] + SymbolLine[0 5000 2000 5000 800] +) +Symbol['{' 1200] +( + SymbolLine[500 1500 1000 1000 800] + SymbolLine[500 1500 500 2500 800] + SymbolLine[0 3000 500 2500 800] + SymbolLine[0 3000 500 3500 800] + SymbolLine[500 3500 500 4500 800] + SymbolLine[500 4500 1000 5000 800] +) +Symbol['|' 1200] +( + SymbolLine[0 1000 0 5000 800] +) +Symbol['}' 1200] +( + SymbolLine[0 1000 500 1500 800] + SymbolLine[500 1500 500 2500 800] + SymbolLine[500 2500 1000 3000 800] + SymbolLine[500 3500 1000 3000 800] + SymbolLine[500 3500 500 4500 800] + SymbolLine[0 5000 500 4500 800] +) +Symbol['~' 1200] +( + SymbolLine[0 3500 500 3000 800] + SymbolLine[500 3000 1000 3000 800] + SymbolLine[1000 3000 1500 3500 800] + SymbolLine[1500 3500 2000 3500 800] + SymbolLine[2000 3500 2500 3000 800] +) +Attribute("PCB::grid::unit" "mil") +Via[170000 160000 7874 4000 0 3150 "" ""] + +Element["" "Standard SMT resistor, capacitor etc" "" "01005" 5000 10000 -3150 3150 1 100 ""] +( + Pad[-19 807 19 807 984 2000 1584 "1" "1" "square"] + Pad[-19 -807 19 -807 984 2000 1584 "2" "2" "square"] + + ) + +Element["" "Standard SMT resistor, capacitor etc" "" "0201" 10000 10000 -3150 3150 1 100 ""] +( + Pad[0 1181 0 1181 1574 2000 2174 "1" "1" "square"] + Pad[0 -1181 0 -1181 1574 2000 2174 "2" "2" "square"] + + ) + +Element["" "Standard SMT resistor, capacitor etc" "" "0402" 15000 10000 -3150 3150 1 100 ""] +( + Pad[-393 1574 393 1574 1968 2000 2568 "1" "1" "square"] + Pad[-393 -1574 393 -1574 1968 2000 2568 "2" "2" "square"] + + ) + +Element["" "Standard SMT resistor, capacitor etc" "" "0603" 25000 10000 -3150 3150 1 100 ""] +( + Pad[-492 2559 492 2559 2952 2000 3552 "1" "1" "square"] + Pad[-492 -2559 492 -2559 2952 2000 3552 "2" "2" "square"] + + ) + +Element["" "Standard SMT resistor, capacitor etc" "" "0805" 35000 10000 -3150 3150 1 100 ""] +( + Pad[-393 3543 393 3543 5118 2000 5718 "1" "1" "square"] + Pad[-393 -3543 393 -3543 5118 2000 5718 "2" "2" "square"] + ElementLine [-2755 -393 -2755 393 800] + ElementLine [2755 -393 2755 393 800] + + ) + +Element["" "Standard SMT resistor, capacitor etc" "" "1008" 50000 10000 -3150 3150 1 100 ""] +( + Pad[-2362 5118 2362 5118 4330 2000 4930 "1" "1" "square"] + Pad[-2362 -5118 2362 -5118 4330 2000 4930 "2" "2" "square"] + ElementLine [-4527 -1377 -4527 1377 800] + ElementLine [4527 -1377 4527 1377 800] + + ) + +Element["" "Standard SMT resistor, capacitor etc" "" "1206" 65000 10000 -3150 3150 1 100 ""] +( + Pad[-1181 5905 1181 5905 5118 2000 5718 "1" "1" "square"] + Pad[-1181 -5905 1181 -5905 5118 2000 5718 "2" "2" "square"] + ElementLine [-3740 -2362 -3740 2362 800] + ElementLine [3740 -2362 3740 2362 800] + + ) + +Element["" "Standard SMT resistor, capacitor etc" "" "1210" 80000 10000 -3150 3150 1 100 ""] +( + Pad[-2755 5905 2755 5905 5118 2000 5718 "1" "1" "square"] + Pad[-2755 -5905 2755 -5905 5118 2000 5718 "2" "2" "square"] + ElementLine [-5314 -1968 -5314 1968 800] + ElementLine [5314 -1968 5314 1968 800] + + ) + +Element["" "Standard SMT resistor, capacitor etc" "" "1806" 10000 35000 -3150 3150 1 100 ""] +( + Pad[-3543 7874 3543 7874 6299 2000 6899 "1" "1" "square"] + Pad[-3543 -7874 3543 -7874 6299 2000 6899 "2" "2" "square"] + ElementLine [-6692 -3149 -6692 3149 800] + ElementLine [6692 -3149 6692 3149 800] + + ) + +Element["" "Standard SMT resistor, capacitor etc" "" "1825" 35000 35000 -3150 3150 1 100 ""] +( + Pad[-10236 7874 10236 7874 6299 2000 6899 "1" "1" "square"] + Pad[-10236 -7874 10236 -7874 6299 2000 6899 "2" "2" "square"] + ElementLine [-13385 -3149 -13385 3149 800] + ElementLine [13385 -3149 13385 3149 800] + + ) + +Element["" "Standard SMT resistor, capacitor etc" "" "2706" 70000 35000 -17900 0 1 100 ""] +( + Pad[10800 -300 10800 300 7800 2000 8400 "1" "1" "square"] + Pad[-10800 -300 -10800 300 7800 2000 8400 "2" "2" "square"] + ElementLine [15900 -5400 15900 5400 1000] + ElementLine [-15900 -5400 15900 -5400 1000] + ElementLine [-15900 -5400 -15900 5400 1000] + ElementLine [-15900 5400 15900 5400 1000] + + ) + +Element["" "SMT diode (pin 1 is cathode)" "" "DO214" 145000 85000 0 22100 2 100 ""] +( + Pad[-1900 -10600 1900 -10600 14000 2000 14600 "1" "1" "square"] + Pad[-1900 10600 1900 10600 14000 2000 14600 "2" "2" "square"] + ElementLine [-8900 -21100 8900 -21100 2000] + ElementLine [-8900 -21100 -11400 -14100 1000] + ElementLine [-11400 -14100 -11400 20100 1000] + ElementLine [-11400 20100 11400 20100 1000] + ElementLine [11400 -14100 11400 20100 1000] + ElementLine [11400 -14100 8900 -21100 1000] + + ) + +Element["" "SMT diode (pin 1 is cathode)" "" "DO214AB" 145000 135000 0 22700 2 100 ""] +( + Pad[-2000 -10900 2000 -10900 14500 2000 15100 "1" "1" "square"] + Pad[-2000 10900 2000 10900 14500 2000 15100 "2" "2" "square"] + ElementLine [-9200 -21700 9200 -21700 2000] + ElementLine [-9200 -21700 -11800 -14500 1000] + ElementLine [-11800 -14500 -11800 20700 1000] + ElementLine [-11800 20700 11800 20700 1000] + ElementLine [11800 -14500 11800 20700 1000] + ElementLine [11800 -14500 9200 -21700 1000] + + ) + +Element["" "SMT diode (pin 1 is cathode)" "" "SOD106A" 100000 80000 0 16600 2 100 ""] +( + Pad[-1700 -7600 1700 -7600 10200 2000 10800 "1" "1" "square"] + Pad[-1700 7600 1700 7600 10200 2000 10800 "2" "2" "square"] + ElementLine [-6800 -15600 6800 -15600 2000] + ElementLine [-6800 -15600 -8700 -10500 1000] + ElementLine [-8700 -10500 -8700 14600 1000] + ElementLine [-8700 14600 8700 14600 1000] + ElementLine [8700 -10500 8700 14600 1000] + ElementLine [8700 -10500 6800 -15600 1000] + + ) + +Element["" "SMT diode (pin 1 is cathode)" "" "SOD110" 10000 80000 0 8300 2 100 ""] +( + Pad[-1500 -2900 1500 -2900 4600 2000 5200 "1" "1" "square"] + Pad[-1500 2900 1500 2900 4600 2000 5200 "2" "2" "square"] + ElementLine [-3800 -7300 3800 -7300 2000] + ElementLine [-3800 -7300 -4900 -5000 1000] + ElementLine [-4900 -5000 -4900 6300 1000] + ElementLine [-4900 6300 4900 6300 1000] + ElementLine [4900 -5000 4900 6300 1000] + ElementLine [4900 -5000 3800 -7300 1000] + + ) + +Element["" "SMT diode (pin 1 is cathode)" "" "SOD123" 55000 80000 0 12000 2 100 ""] +( + Pad[-600 -5500 600 -5500 6900 2000 7500 "1" "1" "square"] + Pad[-600 5500 600 5500 6900 2000 7500 "2" "2" "square"] + ElementLine [-4000 -11000 4000 -11000 2000] + ElementLine [-4000 -11000 -5100 -7600 1000] + ElementLine [-5100 -7600 -5100 10000 1000] + ElementLine [-5100 10000 5100 10000 1000] + ElementLine [5100 -7600 5100 10000 1000] + ElementLine [5100 -7600 4000 -11000 1000] + + ) + +Element["" "SMT diode (pin 1 is cathode)" "" "SOD323" 25000 80000 0 9300 2 100 ""] +( + Pad[-1000 -3700 1000 -3700 5100 2000 5700 "1" "1" "square"] + Pad[-1000 3700 1000 3700 5100 2000 5700 "2" "2" "square"] + ElementLine [-3500 -8300 3500 -8300 2000] + ElementLine [-3500 -8300 -4500 -5800 1000] + ElementLine [-4500 -5800 -4500 7300 1000] + ElementLine [-4500 7300 4500 7300 1000] + ElementLine [4500 -5800 4500 7300 1000] + ElementLine [4500 -5800 3500 -8300 1000] + + ) + +Element["" "SMT diode (pin 1 is cathode)" "" "SOD80" 40000 80000 0 11600 2 100 ""] +( + Pad[-1600 -5800 1600 -5800 5300 2000 5900 "1" "1" "square"] + Pad[-1600 5800 1600 5800 5300 2000 5900 "2" "2" "square"] + ElementLine [-4300 -10600 4300 -10600 2000] + ElementLine [-4300 -10600 -5500 -8000 1000] + ElementLine [-5500 -8000 -5500 9600 1000] + ElementLine [-5500 9600 5500 9600 1000] + ElementLine [5500 -8000 5500 9600 1000] + ElementLine [5500 -8000 4300 -10600 1000] + + ) + +Element["" "SMT diode (pin 1 is cathode)" "" "SOD87" 75000 80000 0 12400 2 100 ""] +( + Pad[-2600 -5800 2600 -5800 6100 2000 6700 "1" "1" "square"] + Pad[-2600 5800 2600 5800 6100 2000 6700 "2" "2" "square"] + ElementLine [-5700 -11400 5700 -11400 2000] + ElementLine [-5700 -11400 -7300 -8400 1000] + ElementLine [-7300 -8400 -7300 10400 1000] + ElementLine [-7300 10400 7300 10400 1000] + ElementLine [7300 -8400 7300 10400 1000] + ElementLine [7300 -8400 5700 -11400 1000] + + ) + +Element["" "Tantalum SMT capacitor (pin 1 is +)" "" "TANT_A" 105000 140000 0 10600 2 100 ""] +( + Pad[-1800 -5000 1800 -5000 4900 2000 5500 "1" "1" "square"] + Pad[-1800 5000 1800 5000 4900 2000 5500 "2" "2" "square"] + ElementLine [-4300 -9600 4300 -9600 2000] + ElementLine [-4300 -9600 -5500 -7200 1000] + ElementLine [-5500 -7200 -5500 8600 1000] + ElementLine [-5500 8600 5500 8600 1000] + ElementLine [5500 -7200 5500 8600 1000] + ElementLine [5500 -7200 4300 -9600 1000] + + ) + +Element["" "Tantalum SMT capacitor (pin 1 is +)" "" "TANT_B" 80000 140000 0 13200 2 100 ""] +( + Pad[-4100 -5500 4100 -5500 7100 2000 7700 "1" "1" "square"] + Pad[-4100 5500 4100 5500 7100 2000 7700 "2" "2" "square"] + ElementLine [-7700 -12200 7700 -12200 2000] + ElementLine [-7700 -12200 -9900 -8700 1000] + ElementLine [-9900 -8700 -9900 11200 1000] + ElementLine [-9900 11200 9900 11200 1000] + ElementLine [9900 -8700 9900 11200 1000] + ElementLine [9900 -8700 7700 -12200 1000] + + ) + +Element["" "Tantalum SMT capacitor (pin 1 is +)" "" "TANT_C" 50000 135000 0 18800 2 100 ""] +( + Pad[-3900 -9400 3900 -9400 9700 2000 10300 "1" "1" "square"] + Pad[-3900 9400 3900 9400 9700 2000 10300 "2" "2" "square"] + ElementLine [-8700 -17800 8700 -17800 2000] + ElementLine [-8700 -17800 -11200 -13000 1000] + ElementLine [-11200 -13000 -11200 16800 1000] + ElementLine [-11200 16800 11200 16800 1000] + ElementLine [11200 -13000 11200 16800 1000] + ElementLine [11200 -13000 8700 -17800 1000] + + ) + +Element["" "Tantalum SMT capacitor (pin 1 is +)" "" "TANT_D" 18500 131500 0 22900 2 100 ""] +( + Pad[-5600 -11500 5600 -11500 12300 2000 12900 "1" "1" "square"] + Pad[-5600 11500 5600 11500 12300 2000 12900 "2" "2" "square"] + ElementLine [-11700 -21900 11700 -21900 2000] + ElementLine [-11700 -21900 -15000 -15800 1000] + ElementLine [-15000 -15800 -15000 20900 1000] + ElementLine [-15000 20900 15000 20900 1000] + ElementLine [15000 -15800 15000 20900 1000] + ElementLine [15000 -15800 11700 -21900 1000] + + ) + +Element["" "" "" "" 130000 22500 12913 3720 1 70 ""] +( + Pad[-984 -7087 984 -7087 5118 5000 7618 "" "1" "square"] + Pad[-984 7087 984 7087 5118 5000 7618 "" "2" "square"] + ElementLine [-3150 -3937 -3150 3937 787] + ElementLine [3150 -3937 3150 3937 787] + + ) +Layer(1 "component") +( +) +Layer(2 "solder") +( +) +Layer(3 "comp-GND") +( +) +Layer(4 "comp-power") +( +) +Layer(5 "sold-GND") +( +) +Layer(6 "sold-power") +( +) +Layer(7 "signal3") +( +) +Layer(8 "outline") +( +) +Layer(9 "silk") +( +) +Layer(10 "silk") +( + Line[0 55000 170000 55000 1000 4000 "clearline"] + Line[0 100000 130000 100000 1000 4000 "clearline"] + Line[95000 0 95000 55000 1000 4000 "clearline"] + Line[130000 55000 130000 160000 1000 4000 "clearline"] + Text[115000 145000 1 200 "TANT" "clearline"] + Text[115000 90000 1 200 "SOD" "clearline"] + Text[157500 115000 1 200 "DO" "clearline"] + Text[112500 37500 0 200 "minimelf" "clearline"] +) Index: tags/2.1.2/util/pcblib-map/smd3.pcb =================================================================== --- tags/2.1.2/util/pcblib-map/smd3.pcb (nonexistent) +++ tags/2.1.2/util/pcblib-map/smd3.pcb (revision 24813) @@ -0,0 +1,895 @@ +# release: pcb 20110918 + +# To read pcb files, the pcb version (or the git source date) must be >= the file version +FileVersion[20070407] + +PCB["" 55000 75000] + +Grid[5000.0 0 0 1] +Cursor[0 0 0.000000] +PolyArea[3100.006200] +Thermal[0.500000] +DRC[1200 900 1000 700 1500 1000] +Flags("nameonpcb,clearnew,snappin") +Groups("1,3,4,c:2,5,6,s:7:8") +Styles["Signal,1000,7874,3150,2000:Power,2000,8661,3937,2000:Fat,8000,13780,4724,2500:Sig-tight,1000,6400,3150,1200"] + +Symbol[' ' 1800] +( +) +Symbol['!' 1200] +( + SymbolLine[0 4500 0 5000 800] + SymbolLine[0 1000 0 3500 800] +) +Symbol['"' 1200] +( + SymbolLine[0 1000 0 2000 800] + SymbolLine[1000 1000 1000 2000 800] +) +Symbol['#' 1200] +( + SymbolLine[0 3500 2000 3500 800] + SymbolLine[0 2500 2000 2500 800] + SymbolLine[1500 2000 1500 4000 800] + SymbolLine[500 2000 500 4000 800] +) +Symbol['$' 1200] +( + SymbolLine[1500 1500 2000 2000 800] + SymbolLine[500 1500 1500 1500 800] + SymbolLine[0 2000 500 1500 800] + SymbolLine[0 2000 0 2500 800] + SymbolLine[0 2500 500 3000 800] + SymbolLine[500 3000 1500 3000 800] + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[2000 3500 2000 4000 800] + SymbolLine[1500 4500 2000 4000 800] + SymbolLine[500 4500 1500 4500 800] + SymbolLine[0 4000 500 4500 800] + SymbolLine[1000 1000 1000 5000 800] +) +Symbol['%' 1200] +( + SymbolLine[0 1500 0 2000 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 1000 1000 800] + SymbolLine[1000 1000 1500 1500 800] + SymbolLine[1500 1500 1500 2000 800] + SymbolLine[1000 2500 1500 2000 800] + SymbolLine[500 2500 1000 2500 800] + SymbolLine[0 2000 500 2500 800] + SymbolLine[0 5000 4000 1000 800] + SymbolLine[3500 5000 4000 4500 800] + SymbolLine[4000 4000 4000 4500 800] + SymbolLine[3500 3500 4000 4000 800] + SymbolLine[3000 3500 3500 3500 800] + SymbolLine[2500 4000 3000 3500 800] + SymbolLine[2500 4000 2500 4500 800] + SymbolLine[2500 4500 3000 5000 800] + SymbolLine[3000 5000 3500 5000 800] +) +Symbol['&' 1200] +( + SymbolLine[0 4500 500 5000 800] + SymbolLine[0 1500 0 2500 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[0 3500 1500 2000 800] + SymbolLine[500 5000 1000 5000 800] + SymbolLine[1000 5000 2000 4000 800] + SymbolLine[0 2500 2500 5000 800] + SymbolLine[500 1000 1000 1000 800] + SymbolLine[1000 1000 1500 1500 800] + SymbolLine[1500 1500 1500 2000 800] + SymbolLine[0 3500 0 4500 800] +) +Symbol[''' 1200] +( + SymbolLine[0 2000 1000 1000 800] +) +Symbol['(' 1200] +( + SymbolLine[0 4500 500 5000 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[0 1500 0 4500 800] +) +Symbol[')' 1200] +( + SymbolLine[0 1000 500 1500 800] + SymbolLine[500 1500 500 4500 800] + SymbolLine[0 5000 500 4500 800] +) +Symbol['*' 1200] +( + SymbolLine[0 2000 2000 4000 800] + SymbolLine[0 4000 2000 2000 800] + SymbolLine[0 3000 2000 3000 800] + SymbolLine[1000 2000 1000 4000 800] +) +Symbol['+' 1200] +( + SymbolLine[0 3000 2000 3000 800] + SymbolLine[1000 2000 1000 4000 800] +) +Symbol[',' 1200] +( + SymbolLine[0 6000 1000 5000 800] +) +Symbol['-' 1200] +( + SymbolLine[0 3000 2000 3000 800] +) +Symbol['.' 1200] +( + SymbolLine[0 5000 500 5000 800] +) +Symbol['/' 1200] +( + SymbolLine[0 4500 3000 1500 800] +) +Symbol['0' 1200] +( + SymbolLine[0 4500 500 5000 800] + SymbolLine[0 1500 0 4500 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 1500 1000 800] + SymbolLine[1500 1000 2000 1500 800] + SymbolLine[2000 1500 2000 4500 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[0 4000 2000 2000 800] +) +Symbol['1' 1200] +( + SymbolLine[0 1800 800 1000 800] + SymbolLine[800 1000 800 5000 800] + SymbolLine[0 5000 1500 5000 800] +) +Symbol['2' 1200] +( + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 2000 1000 800] + SymbolLine[2000 1000 2500 1500 800] + SymbolLine[2500 1500 2500 2500 800] + SymbolLine[0 5000 2500 2500 800] + SymbolLine[0 5000 2500 5000 800] +) +Symbol['3' 1200] +( + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 1500 1000 800] + SymbolLine[1500 1000 2000 1500 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[500 2800 1500 2800 800] + SymbolLine[2000 1500 2000 2300 800] + SymbolLine[2000 3300 2000 4500 800] + SymbolLine[2000 3300 1500 2800 800] + SymbolLine[2000 2300 1500 2800 800] +) +Symbol['4' 1200] +( + SymbolLine[0 3500 2000 1000 800] + SymbolLine[0 3500 2500 3500 800] + SymbolLine[2000 1000 2000 5000 800] +) +Symbol['5' 1200] +( + SymbolLine[0 1000 2000 1000 800] + SymbolLine[0 1000 0 3000 800] + SymbolLine[0 3000 500 2500 800] + SymbolLine[500 2500 1500 2500 800] + SymbolLine[1500 2500 2000 3000 800] + SymbolLine[2000 3000 2000 4500 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[0 4500 500 5000 800] +) +Symbol['6' 1200] +( + SymbolLine[1500 1000 2000 1500 800] + SymbolLine[500 1000 1500 1000 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[0 1500 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[1500 2800 2000 3300 800] + SymbolLine[0 2800 1500 2800 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[2000 3300 2000 4500 800] +) +Symbol['7' 1200] +( + SymbolLine[500 5000 2500 1000 800] + SymbolLine[0 1000 2500 1000 800] +) +Symbol['8' 1200] +( + SymbolLine[0 4500 500 5000 800] + SymbolLine[0 3700 0 4500 800] + SymbolLine[0 3700 700 3000 800] + SymbolLine[700 3000 1300 3000 800] + SymbolLine[1300 3000 2000 3700 800] + SymbolLine[2000 3700 2000 4500 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[0 2300 700 3000 800] + SymbolLine[0 1500 0 2300 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 1500 1000 800] + SymbolLine[1500 1000 2000 1500 800] + SymbolLine[2000 1500 2000 2300 800] + SymbolLine[1300 3000 2000 2300 800] +) +Symbol['9' 1200] +( + SymbolLine[500 5000 2000 3000 800] + SymbolLine[2000 1500 2000 3000 800] + SymbolLine[1500 1000 2000 1500 800] + SymbolLine[500 1000 1500 1000 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[0 1500 0 2500 800] + SymbolLine[0 2500 500 3000 800] + SymbolLine[500 3000 2000 3000 800] +) +Symbol[':' 1200] +( + SymbolLine[0 2500 500 2500 800] + SymbolLine[0 3500 500 3500 800] +) +Symbol[';' 1200] +( + SymbolLine[0 5000 1000 4000 800] + SymbolLine[1000 2500 1000 3000 800] +) +Symbol['<' 1200] +( + SymbolLine[0 3000 1000 2000 800] + SymbolLine[0 3000 1000 4000 800] +) +Symbol['=' 1200] +( + SymbolLine[0 2500 2000 2500 800] + SymbolLine[0 3500 2000 3500 800] +) +Symbol['>' 1200] +( + SymbolLine[0 2000 1000 3000 800] + SymbolLine[0 4000 1000 3000 800] +) +Symbol['?' 1200] +( + SymbolLine[1000 3000 1000 3500 800] + SymbolLine[1000 4500 1000 5000 800] + SymbolLine[0 1500 0 2000 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 1500 1000 800] + SymbolLine[1500 1000 2000 1500 800] + SymbolLine[2000 1500 2000 2000 800] + SymbolLine[1000 3000 2000 2000 800] +) +Symbol['@' 1200] +( + SymbolLine[0 1000 0 4000 800] + SymbolLine[0 4000 1000 5000 800] + SymbolLine[1000 5000 4000 5000 800] + SymbolLine[5000 3500 5000 1000 800] + SymbolLine[5000 1000 4000 0 800] + SymbolLine[4000 0 1000 0 800] + SymbolLine[1000 0 0 1000 800] + SymbolLine[1500 2000 1500 3000 800] + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[2000 3500 3000 3500 800] + SymbolLine[3000 3500 3500 3000 800] + SymbolLine[3500 3000 4000 3500 800] + SymbolLine[3500 3000 3500 1500 800] + SymbolLine[3500 2000 3000 1500 800] + SymbolLine[2000 1500 3000 1500 800] + SymbolLine[2000 1500 1500 2000 800] + SymbolLine[4000 3500 5000 3500 800] +) +Symbol['A' 1200] +( + SymbolLine[0 2000 0 5000 800] + SymbolLine[0 2000 700 1000 800] + SymbolLine[700 1000 1800 1000 800] + SymbolLine[1800 1000 2500 2000 800] + SymbolLine[2500 2000 2500 5000 800] + SymbolLine[0 3000 2500 3000 800] +) +Symbol['B' 1200] +( + SymbolLine[0 5000 2000 5000 800] + SymbolLine[2000 5000 2500 4500 800] + SymbolLine[2500 3300 2500 4500 800] + SymbolLine[2000 2800 2500 3300 800] + SymbolLine[500 2800 2000 2800 800] + SymbolLine[500 1000 500 5000 800] + SymbolLine[0 1000 2000 1000 800] + SymbolLine[2000 1000 2500 1500 800] + SymbolLine[2500 1500 2500 2300 800] + SymbolLine[2000 2800 2500 2300 800] +) +Symbol['C' 1200] +( + SymbolLine[700 5000 2000 5000 800] + SymbolLine[0 4300 700 5000 800] + SymbolLine[0 1700 0 4300 800] + SymbolLine[0 1700 700 1000 800] + SymbolLine[700 1000 2000 1000 800] +) +Symbol['D' 1200] +( + SymbolLine[500 1000 500 5000 800] + SymbolLine[1800 1000 2500 1700 800] + SymbolLine[2500 1700 2500 4300 800] + SymbolLine[1800 5000 2500 4300 800] + SymbolLine[0 5000 1800 5000 800] + SymbolLine[0 1000 1800 1000 800] +) +Symbol['E' 1200] +( + SymbolLine[0 2800 1500 2800 800] + SymbolLine[0 5000 2000 5000 800] + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 1000 2000 1000 800] +) +Symbol['F' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 1000 2000 1000 800] + SymbolLine[0 2800 1500 2800 800] +) +Symbol['G' 1200] +( + SymbolLine[2000 1000 2500 1500 800] + SymbolLine[500 1000 2000 1000 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[0 1500 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[500 5000 2000 5000 800] + SymbolLine[2000 5000 2500 4500 800] + SymbolLine[2500 3500 2500 4500 800] + SymbolLine[2000 3000 2500 3500 800] + SymbolLine[1000 3000 2000 3000 800] +) +Symbol['H' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[2500 1000 2500 5000 800] + SymbolLine[0 3000 2500 3000 800] +) +Symbol['I' 1200] +( + SymbolLine[0 1000 1000 1000 800] + SymbolLine[500 1000 500 5000 800] + SymbolLine[0 5000 1000 5000 800] +) +Symbol['J' 1200] +( + SymbolLine[700 1000 1500 1000 800] + SymbolLine[1500 1000 1500 4500 800] + SymbolLine[1000 5000 1500 4500 800] + SymbolLine[500 5000 1000 5000 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[0 4500 0 4000 800] +) +Symbol['K' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 3000 2000 1000 800] + SymbolLine[0 3000 2000 5000 800] +) +Symbol['L' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 5000 2000 5000 800] +) +Symbol['M' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 1000 1500 3000 800] + SymbolLine[1500 3000 3000 1000 800] + SymbolLine[3000 1000 3000 5000 800] +) +Symbol['N' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 1000 2500 5000 800] + SymbolLine[2500 1000 2500 5000 800] +) +Symbol['O' 1200] +( + SymbolLine[0 1500 0 4500 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 1500 1000 800] + SymbolLine[1500 1000 2000 1500 800] + SymbolLine[2000 1500 2000 4500 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[0 4500 500 5000 800] +) +Symbol['P' 1200] +( + SymbolLine[500 1000 500 5000 800] + SymbolLine[0 1000 2000 1000 800] + SymbolLine[2000 1000 2500 1500 800] + SymbolLine[2500 1500 2500 2500 800] + SymbolLine[2000 3000 2500 2500 800] + SymbolLine[500 3000 2000 3000 800] +) +Symbol['Q' 1200] +( + SymbolLine[0 1500 0 4500 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 1500 1000 800] + SymbolLine[1500 1000 2000 1500 800] + SymbolLine[2000 1500 2000 4000 800] + SymbolLine[1000 5000 2000 4000 800] + SymbolLine[500 5000 1000 5000 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[1000 3500 2000 5000 800] +) +Symbol['R' 1200] +( + SymbolLine[0 1000 2000 1000 800] + SymbolLine[2000 1000 2500 1500 800] + SymbolLine[2500 1500 2500 2500 800] + SymbolLine[2000 3000 2500 2500 800] + SymbolLine[500 3000 2000 3000 800] + SymbolLine[500 1000 500 5000 800] + SymbolLine[1300 3000 2500 5000 800] +) +Symbol['S' 1200] +( + SymbolLine[2000 1000 2500 1500 800] + SymbolLine[500 1000 2000 1000 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[0 1500 0 2500 800] + SymbolLine[0 2500 500 3000 800] + SymbolLine[500 3000 2000 3000 800] + SymbolLine[2000 3000 2500 3500 800] + SymbolLine[2500 3500 2500 4500 800] + SymbolLine[2000 5000 2500 4500 800] + SymbolLine[500 5000 2000 5000 800] + SymbolLine[0 4500 500 5000 800] +) +Symbol['T' 1200] +( + SymbolLine[0 1000 2000 1000 800] + SymbolLine[1000 1000 1000 5000 800] +) +Symbol['U' 1200] +( + SymbolLine[0 1000 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[2000 1000 2000 4500 800] +) +Symbol['V' 1200] +( + SymbolLine[0 1000 1000 5000 800] + SymbolLine[1000 5000 2000 1000 800] +) +Symbol['W' 1200] +( + SymbolLine[0 1000 0 3000 800] + SymbolLine[0 3000 500 5000 800] + SymbolLine[500 5000 1500 3000 800] + SymbolLine[1500 3000 2500 5000 800] + SymbolLine[2500 5000 3000 3000 800] + SymbolLine[3000 3000 3000 1000 800] +) +Symbol['X' 1200] +( + SymbolLine[0 5000 2500 1000 800] + SymbolLine[0 1000 2500 5000 800] +) +Symbol['Y' 1200] +( + SymbolLine[0 1000 1000 3000 800] + SymbolLine[1000 3000 2000 1000 800] + SymbolLine[1000 3000 1000 5000 800] +) +Symbol['Z' 1200] +( + SymbolLine[0 1000 2500 1000 800] + SymbolLine[0 5000 2500 1000 800] + SymbolLine[0 5000 2500 5000 800] +) +Symbol['[' 1200] +( + SymbolLine[0 1000 500 1000 800] + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 5000 500 5000 800] +) +Symbol['\' 1200] +( + SymbolLine[0 1500 3000 4500 800] +) +Symbol[']' 1200] +( + SymbolLine[0 1000 500 1000 800] + SymbolLine[500 1000 500 5000 800] + SymbolLine[0 5000 500 5000 800] +) +Symbol['^' 1200] +( + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 1000 1500 800] +) +Symbol['_' 1200] +( + SymbolLine[0 5000 2000 5000 800] +) +Symbol['a' 1200] +( + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[500 3000 1500 3000 800] + SymbolLine[0 3500 500 3000 800] + SymbolLine[0 3500 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[2000 3000 2000 4500 800] + SymbolLine[2000 4500 2500 5000 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[1500 5000 2000 4500 800] +) +Symbol['b' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[2000 3500 2000 4500 800] + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[500 3000 1500 3000 800] + SymbolLine[0 3500 500 3000 800] +) +Symbol['c' 1200] +( + SymbolLine[500 3000 2000 3000 800] + SymbolLine[0 3500 500 3000 800] + SymbolLine[0 3500 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[500 5000 2000 5000 800] +) +Symbol['d' 1200] +( + SymbolLine[2000 1000 2000 5000 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[0 3500 0 4500 800] + SymbolLine[0 3500 500 3000 800] + SymbolLine[500 3000 1500 3000 800] + SymbolLine[1500 3000 2000 3500 800] +) +Symbol['e' 1200] +( + SymbolLine[500 5000 2000 5000 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[0 3500 0 4500 800] + SymbolLine[0 3500 500 3000 800] + SymbolLine[500 3000 1500 3000 800] + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[0 4000 2000 4000 800] + SymbolLine[2000 4000 2000 3500 800] +) +Symbol['f' 1000] +( + SymbolLine[500 1500 500 5000 800] + SymbolLine[500 1500 1000 1000 800] + SymbolLine[1000 1000 1500 1000 800] + SymbolLine[0 3000 1000 3000 800] +) +Symbol['g' 1200] +( + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[500 3000 1500 3000 800] + SymbolLine[0 3500 500 3000 800] + SymbolLine[0 3500 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[0 6000 500 6500 800] + SymbolLine[500 6500 1500 6500 800] + SymbolLine[1500 6500 2000 6000 800] + SymbolLine[2000 3000 2000 6000 800] +) +Symbol['h' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 3500 500 3000 800] + SymbolLine[500 3000 1500 3000 800] + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[2000 3500 2000 5000 800] +) +Symbol['i' 1000] +( + SymbolLine[0 2000 0 2100 1000] + SymbolLine[0 3500 0 5000 800] +) +Symbol['j' 1000] +( + SymbolLine[500 2000 500 2100 1000] + SymbolLine[500 3500 500 6000 800] + SymbolLine[0 6500 500 6000 800] +) +Symbol['k' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 3500 1500 5000 800] + SymbolLine[0 3500 1000 2500 800] +) +Symbol['l' 1000] +( + SymbolLine[0 1000 0 4500 800] + SymbolLine[0 4500 500 5000 800] +) +Symbol['m' 1200] +( + SymbolLine[500 3500 500 5000 800] + SymbolLine[500 3500 1000 3000 800] + SymbolLine[1000 3000 1500 3000 800] + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[2000 3500 2000 5000 800] + SymbolLine[2000 3500 2500 3000 800] + SymbolLine[2500 3000 3000 3000 800] + SymbolLine[3000 3000 3500 3500 800] + SymbolLine[3500 3500 3500 5000 800] + SymbolLine[0 3000 500 3500 800] +) +Symbol['n' 1200] +( + SymbolLine[500 3500 500 5000 800] + SymbolLine[500 3500 1000 3000 800] + SymbolLine[1000 3000 1500 3000 800] + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[2000 3500 2000 5000 800] + SymbolLine[0 3000 500 3500 800] +) +Symbol['o' 1200] +( + SymbolLine[0 3500 0 4500 800] + SymbolLine[0 3500 500 3000 800] + SymbolLine[500 3000 1500 3000 800] + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[2000 3500 2000 4500 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[0 4500 500 5000 800] +) +Symbol['p' 1200] +( + SymbolLine[500 3500 500 6500 800] + SymbolLine[0 3000 500 3500 800] + SymbolLine[500 3500 1000 3000 800] + SymbolLine[1000 3000 2000 3000 800] + SymbolLine[2000 3000 2500 3500 800] + SymbolLine[2500 3500 2500 4500 800] + SymbolLine[2000 5000 2500 4500 800] + SymbolLine[1000 5000 2000 5000 800] + SymbolLine[500 4500 1000 5000 800] +) +Symbol['q' 1200] +( + SymbolLine[2000 3500 2000 6500 800] + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[500 3000 1500 3000 800] + SymbolLine[0 3500 500 3000 800] + SymbolLine[0 3500 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[1500 5000 2000 4500 800] +) +Symbol['r' 1200] +( + SymbolLine[500 3500 500 5000 800] + SymbolLine[500 3500 1000 3000 800] + SymbolLine[1000 3000 2000 3000 800] + SymbolLine[0 3000 500 3500 800] +) +Symbol['s' 1200] +( + SymbolLine[500 5000 2000 5000 800] + SymbolLine[2000 5000 2500 4500 800] + SymbolLine[2000 4000 2500 4500 800] + SymbolLine[500 4000 2000 4000 800] + SymbolLine[0 3500 500 4000 800] + SymbolLine[0 3500 500 3000 800] + SymbolLine[500 3000 2000 3000 800] + SymbolLine[2000 3000 2500 3500 800] + SymbolLine[0 4500 500 5000 800] +) +Symbol['t' 1000] +( + SymbolLine[500 1000 500 4500 800] + SymbolLine[500 4500 1000 5000 800] + SymbolLine[0 2500 1000 2500 800] +) +Symbol['u' 1200] +( + SymbolLine[0 3000 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[2000 3000 2000 4500 800] +) +Symbol['v' 1200] +( + SymbolLine[0 3000 1000 5000 800] + SymbolLine[2000 3000 1000 5000 800] +) +Symbol['w' 1200] +( + SymbolLine[0 3000 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[500 5000 1000 5000 800] + SymbolLine[1000 5000 1500 4500 800] + SymbolLine[1500 3000 1500 4500 800] + SymbolLine[1500 4500 2000 5000 800] + SymbolLine[2000 5000 2500 5000 800] + SymbolLine[2500 5000 3000 4500 800] + SymbolLine[3000 3000 3000 4500 800] +) +Symbol['x' 1200] +( + SymbolLine[0 3000 2000 5000 800] + SymbolLine[0 5000 2000 3000 800] +) +Symbol['y' 1200] +( + SymbolLine[0 3000 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[2000 3000 2000 6000 800] + SymbolLine[1500 6500 2000 6000 800] + SymbolLine[500 6500 1500 6500 800] + SymbolLine[0 6000 500 6500 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[1500 5000 2000 4500 800] +) +Symbol['z' 1200] +( + SymbolLine[0 3000 2000 3000 800] + SymbolLine[0 5000 2000 3000 800] + SymbolLine[0 5000 2000 5000 800] +) +Symbol['{' 1200] +( + SymbolLine[500 1500 1000 1000 800] + SymbolLine[500 1500 500 2500 800] + SymbolLine[0 3000 500 2500 800] + SymbolLine[0 3000 500 3500 800] + SymbolLine[500 3500 500 4500 800] + SymbolLine[500 4500 1000 5000 800] +) +Symbol['|' 1200] +( + SymbolLine[0 1000 0 5000 800] +) +Symbol['}' 1200] +( + SymbolLine[0 1000 500 1500 800] + SymbolLine[500 1500 500 2500 800] + SymbolLine[500 2500 1000 3000 800] + SymbolLine[500 3500 1000 3000 800] + SymbolLine[500 3500 500 4500 800] + SymbolLine[0 5000 500 4500 800] +) +Symbol['~' 1200] +( + SymbolLine[0 3500 500 3000 800] + SymbolLine[500 3000 1000 3000 800] + SymbolLine[1000 3000 1500 3500 800] + SymbolLine[1500 3500 2000 3500 800] + SymbolLine[2000 3500 2500 3000 800] +) +Attribute("PCB::grid::unit" "mil") +Via[55000 75000 7874 4000 0 3150 "" ""] + +Element["" "SMT transistor, 3 pins" "" "SC70_3" 10000 15000 9300 -9400 3 100 ""] +( + Pad[0 -300 0 300 2900 3000 3500 "1" "1" "square,edge2"] + Pad[5100 -300 5100 300 2900 3000 3500 "2" "2" "square,edge2"] + Pad[2600 -7300 2600 -6700 2900 3000 3500 "3" "3" "square"] + ElementLine [-2100 -9400 -2100 2500 1000] + ElementLine [-2100 2500 7300 2500 1000] + ElementLine [7300 2500 7300 -9400 1000] + ElementLine [7300 -9400 -2100 -9400 1000] + + ) + +Element["" "SMT transistor, 3 pins" "" "SC90" 25000 15000 7600 -7800 3 100 ""] +( + Pad[0 -200 0 200 2400 3000 3000 "1" "1" "square,edge2"] + Pad[3900 -200 3900 200 2400 3000 3000 "2" "2" "square,edge2"] + Pad[1900 -6100 1900 -5700 2400 3000 3000 "3" "3" "square"] + ElementLine [-1700 -7800 -1700 2000 1000] + ElementLine [-1700 2000 5600 2000 1000] + ElementLine [5600 2000 5600 -7800 1000] + ElementLine [5600 -7800 -1700 -7800 1000] + + ) + +Element["" "SMT transistor, 3 pins" "" "SOT23" 6100 48200 12300 -11000 3 100 ""] +( + Pad[0 -300 0 300 3400 3000 4000 "1" "1" "square,edge2"] + Pad[7800 -300 7800 300 3400 3000 4000 "2" "2" "square,edge2"] + Pad[3900 -8500 3900 -7900 3400 3000 4000 "3" "3" "square"] + ElementLine [-2500 -11000 -2500 2900 1000] + ElementLine [-2500 2900 10300 2900 1000] + ElementLine [10300 2900 10300 -11000 1000] + ElementLine [10300 -11000 -2500 -11000 1000] + + ) + +Element["" "SMT diode (pin 1 is cathode)" "" "SOT23D" 6100 68200 12300 -11000 3 100 ""] +( + Pad[0 -300 0 300 3400 3000 4000 "2" "2" "square,edge2"] + Pad[7800 -300 7800 300 3400 3000 4000 "3" "3" "square,edge2"] + Pad[3900 -8500 3900 -7900 3400 3000 4000 "1" "1" "square"] + ElementLine [-2500 -11000 -2500 2900 1000] + ElementLine [-2500 2900 10300 2900 1000] + ElementLine [10300 2900 10300 -11000 1000] + ElementLine [10300 -11000 -2500 -11000 1000] + + ) + +Element["" "SMT transistor, 3 pins" "" "SOT323" 27400 47000 9300 -9400 3 100 ""] +( + Pad[0 -300 0 300 2900 3000 3500 "1" "1" "square,edge2"] + Pad[5100 -300 5100 300 2900 3000 3500 "2" "2" "square,edge2"] + Pad[2600 -7300 2600 -6700 2900 3000 3500 "3" "3" "square"] + ElementLine [-2100 -9400 -2100 2500 1000] + ElementLine [-2100 2500 7300 2500 1000] + ElementLine [7300 2500 7300 -9400 1000] + ElementLine [7300 -9400 -2100 -9400 1000] + + ) + +Element["" "SMT diode (pin 1 is cathode)" "" "SOT323D" 27400 67000 9300 -9400 3 100 ""] +( + Pad[0 -300 0 300 2900 3000 3500 "2" "2" "square,edge2"] + Pad[5100 -300 5100 300 2900 3000 3500 "3" "3" "square,edge2"] + Pad[2600 -7300 2600 -6700 2900 3000 3500 "1" "1" "square"] + ElementLine [-2100 -9400 -2100 2500 1000] + ElementLine [-2100 2500 7300 2500 1000] + ElementLine [7300 2500 7300 -9400 1000] + ElementLine [7300 -9400 -2100 -9400 1000] + + ) +Layer(1 "component") +( +) +Layer(2 "solder") +( +) +Layer(3 "comp-GND") +( +) +Layer(4 "comp-power") +( +) +Layer(5 "sold-GND") +( +) +Layer(6 "sold-power") +( +) +Layer(7 "signal3") +( +) +Layer(8 "outline") +( +) +Layer(9 "silk") +( +) +Layer(10 "silk") +( + Line[0 25000 55000 25000 1000 4000 "clearline"] + Text[35000 5000 0 200 "SC" "clearline"] + Text[40000 60000 1 200 "SOT" "clearline"] +) Index: tags/2.1.2/util/pcblib-map/smdN.pcb =================================================================== --- tags/2.1.2/util/pcblib-map/smdN.pcb (nonexistent) +++ tags/2.1.2/util/pcblib-map/smdN.pcb (revision 24813) @@ -0,0 +1,944 @@ +# release: pcb 20110918 + +# To read pcb files, the pcb version (or the git source date) must be >= the file version +FileVersion[20070407] + +PCB["" 100000 75000] + +Grid[5000.0 0 0 1] +Cursor[0 0 0.000000] +PolyArea[3100.006200] +Thermal[0.500000] +DRC[1200 900 1000 700 1500 1000] +Flags("nameonpcb,clearnew,snappin") +Groups("1,3,4,c:2,5,6,s:7:8") +Styles["Signal,1000,7874,3150,2000:Power,2000,8661,3937,2000:Fat,8000,13780,4724,2500:Sig-tight,1000,6400,3150,1200"] + +Symbol[' ' 1800] +( +) +Symbol['!' 1200] +( + SymbolLine[0 4500 0 5000 800] + SymbolLine[0 1000 0 3500 800] +) +Symbol['"' 1200] +( + SymbolLine[0 1000 0 2000 800] + SymbolLine[1000 1000 1000 2000 800] +) +Symbol['#' 1200] +( + SymbolLine[0 3500 2000 3500 800] + SymbolLine[0 2500 2000 2500 800] + SymbolLine[1500 2000 1500 4000 800] + SymbolLine[500 2000 500 4000 800] +) +Symbol['$' 1200] +( + SymbolLine[1500 1500 2000 2000 800] + SymbolLine[500 1500 1500 1500 800] + SymbolLine[0 2000 500 1500 800] + SymbolLine[0 2000 0 2500 800] + SymbolLine[0 2500 500 3000 800] + SymbolLine[500 3000 1500 3000 800] + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[2000 3500 2000 4000 800] + SymbolLine[1500 4500 2000 4000 800] + SymbolLine[500 4500 1500 4500 800] + SymbolLine[0 4000 500 4500 800] + SymbolLine[1000 1000 1000 5000 800] +) +Symbol['%' 1200] +( + SymbolLine[0 1500 0 2000 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 1000 1000 800] + SymbolLine[1000 1000 1500 1500 800] + SymbolLine[1500 1500 1500 2000 800] + SymbolLine[1000 2500 1500 2000 800] + SymbolLine[500 2500 1000 2500 800] + SymbolLine[0 2000 500 2500 800] + SymbolLine[0 5000 4000 1000 800] + SymbolLine[3500 5000 4000 4500 800] + SymbolLine[4000 4000 4000 4500 800] + SymbolLine[3500 3500 4000 4000 800] + SymbolLine[3000 3500 3500 3500 800] + SymbolLine[2500 4000 3000 3500 800] + SymbolLine[2500 4000 2500 4500 800] + SymbolLine[2500 4500 3000 5000 800] + SymbolLine[3000 5000 3500 5000 800] +) +Symbol['&' 1200] +( + SymbolLine[0 4500 500 5000 800] + SymbolLine[0 1500 0 2500 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[0 3500 1500 2000 800] + SymbolLine[500 5000 1000 5000 800] + SymbolLine[1000 5000 2000 4000 800] + SymbolLine[0 2500 2500 5000 800] + SymbolLine[500 1000 1000 1000 800] + SymbolLine[1000 1000 1500 1500 800] + SymbolLine[1500 1500 1500 2000 800] + SymbolLine[0 3500 0 4500 800] +) +Symbol[''' 1200] +( + SymbolLine[0 2000 1000 1000 800] +) +Symbol['(' 1200] +( + SymbolLine[0 4500 500 5000 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[0 1500 0 4500 800] +) +Symbol[')' 1200] +( + SymbolLine[0 1000 500 1500 800] + SymbolLine[500 1500 500 4500 800] + SymbolLine[0 5000 500 4500 800] +) +Symbol['*' 1200] +( + SymbolLine[0 2000 2000 4000 800] + SymbolLine[0 4000 2000 2000 800] + SymbolLine[0 3000 2000 3000 800] + SymbolLine[1000 2000 1000 4000 800] +) +Symbol['+' 1200] +( + SymbolLine[0 3000 2000 3000 800] + SymbolLine[1000 2000 1000 4000 800] +) +Symbol[',' 1200] +( + SymbolLine[0 6000 1000 5000 800] +) +Symbol['-' 1200] +( + SymbolLine[0 3000 2000 3000 800] +) +Symbol['.' 1200] +( + SymbolLine[0 5000 500 5000 800] +) +Symbol['/' 1200] +( + SymbolLine[0 4500 3000 1500 800] +) +Symbol['0' 1200] +( + SymbolLine[0 4500 500 5000 800] + SymbolLine[0 1500 0 4500 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 1500 1000 800] + SymbolLine[1500 1000 2000 1500 800] + SymbolLine[2000 1500 2000 4500 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[0 4000 2000 2000 800] +) +Symbol['1' 1200] +( + SymbolLine[0 1800 800 1000 800] + SymbolLine[800 1000 800 5000 800] + SymbolLine[0 5000 1500 5000 800] +) +Symbol['2' 1200] +( + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 2000 1000 800] + SymbolLine[2000 1000 2500 1500 800] + SymbolLine[2500 1500 2500 2500 800] + SymbolLine[0 5000 2500 2500 800] + SymbolLine[0 5000 2500 5000 800] +) +Symbol['3' 1200] +( + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 1500 1000 800] + SymbolLine[1500 1000 2000 1500 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[500 2800 1500 2800 800] + SymbolLine[2000 1500 2000 2300 800] + SymbolLine[2000 3300 2000 4500 800] + SymbolLine[2000 3300 1500 2800 800] + SymbolLine[2000 2300 1500 2800 800] +) +Symbol['4' 1200] +( + SymbolLine[0 3500 2000 1000 800] + SymbolLine[0 3500 2500 3500 800] + SymbolLine[2000 1000 2000 5000 800] +) +Symbol['5' 1200] +( + SymbolLine[0 1000 2000 1000 800] + SymbolLine[0 1000 0 3000 800] + SymbolLine[0 3000 500 2500 800] + SymbolLine[500 2500 1500 2500 800] + SymbolLine[1500 2500 2000 3000 800] + SymbolLine[2000 3000 2000 4500 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[0 4500 500 5000 800] +) +Symbol['6' 1200] +( + SymbolLine[1500 1000 2000 1500 800] + SymbolLine[500 1000 1500 1000 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[0 1500 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[1500 2800 2000 3300 800] + SymbolLine[0 2800 1500 2800 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[2000 3300 2000 4500 800] +) +Symbol['7' 1200] +( + SymbolLine[500 5000 2500 1000 800] + SymbolLine[0 1000 2500 1000 800] +) +Symbol['8' 1200] +( + SymbolLine[0 4500 500 5000 800] + SymbolLine[0 3700 0 4500 800] + SymbolLine[0 3700 700 3000 800] + SymbolLine[700 3000 1300 3000 800] + SymbolLine[1300 3000 2000 3700 800] + SymbolLine[2000 3700 2000 4500 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[0 2300 700 3000 800] + SymbolLine[0 1500 0 2300 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 1500 1000 800] + SymbolLine[1500 1000 2000 1500 800] + SymbolLine[2000 1500 2000 2300 800] + SymbolLine[1300 3000 2000 2300 800] +) +Symbol['9' 1200] +( + SymbolLine[500 5000 2000 3000 800] + SymbolLine[2000 1500 2000 3000 800] + SymbolLine[1500 1000 2000 1500 800] + SymbolLine[500 1000 1500 1000 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[0 1500 0 2500 800] + SymbolLine[0 2500 500 3000 800] + SymbolLine[500 3000 2000 3000 800] +) +Symbol[':' 1200] +( + SymbolLine[0 2500 500 2500 800] + SymbolLine[0 3500 500 3500 800] +) +Symbol[';' 1200] +( + SymbolLine[0 5000 1000 4000 800] + SymbolLine[1000 2500 1000 3000 800] +) +Symbol['<' 1200] +( + SymbolLine[0 3000 1000 2000 800] + SymbolLine[0 3000 1000 4000 800] +) +Symbol['=' 1200] +( + SymbolLine[0 2500 2000 2500 800] + SymbolLine[0 3500 2000 3500 800] +) +Symbol['>' 1200] +( + SymbolLine[0 2000 1000 3000 800] + SymbolLine[0 4000 1000 3000 800] +) +Symbol['?' 1200] +( + SymbolLine[1000 3000 1000 3500 800] + SymbolLine[1000 4500 1000 5000 800] + SymbolLine[0 1500 0 2000 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 1500 1000 800] + SymbolLine[1500 1000 2000 1500 800] + SymbolLine[2000 1500 2000 2000 800] + SymbolLine[1000 3000 2000 2000 800] +) +Symbol['@' 1200] +( + SymbolLine[0 1000 0 4000 800] + SymbolLine[0 4000 1000 5000 800] + SymbolLine[1000 5000 4000 5000 800] + SymbolLine[5000 3500 5000 1000 800] + SymbolLine[5000 1000 4000 0 800] + SymbolLine[4000 0 1000 0 800] + SymbolLine[1000 0 0 1000 800] + SymbolLine[1500 2000 1500 3000 800] + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[2000 3500 3000 3500 800] + SymbolLine[3000 3500 3500 3000 800] + SymbolLine[3500 3000 4000 3500 800] + SymbolLine[3500 3000 3500 1500 800] + SymbolLine[3500 2000 3000 1500 800] + SymbolLine[2000 1500 3000 1500 800] + SymbolLine[2000 1500 1500 2000 800] + SymbolLine[4000 3500 5000 3500 800] +) +Symbol['A' 1200] +( + SymbolLine[0 2000 0 5000 800] + SymbolLine[0 2000 700 1000 800] + SymbolLine[700 1000 1800 1000 800] + SymbolLine[1800 1000 2500 2000 800] + SymbolLine[2500 2000 2500 5000 800] + SymbolLine[0 3000 2500 3000 800] +) +Symbol['B' 1200] +( + SymbolLine[0 5000 2000 5000 800] + SymbolLine[2000 5000 2500 4500 800] + SymbolLine[2500 3300 2500 4500 800] + SymbolLine[2000 2800 2500 3300 800] + SymbolLine[500 2800 2000 2800 800] + SymbolLine[500 1000 500 5000 800] + SymbolLine[0 1000 2000 1000 800] + SymbolLine[2000 1000 2500 1500 800] + SymbolLine[2500 1500 2500 2300 800] + SymbolLine[2000 2800 2500 2300 800] +) +Symbol['C' 1200] +( + SymbolLine[700 5000 2000 5000 800] + SymbolLine[0 4300 700 5000 800] + SymbolLine[0 1700 0 4300 800] + SymbolLine[0 1700 700 1000 800] + SymbolLine[700 1000 2000 1000 800] +) +Symbol['D' 1200] +( + SymbolLine[500 1000 500 5000 800] + SymbolLine[1800 1000 2500 1700 800] + SymbolLine[2500 1700 2500 4300 800] + SymbolLine[1800 5000 2500 4300 800] + SymbolLine[0 5000 1800 5000 800] + SymbolLine[0 1000 1800 1000 800] +) +Symbol['E' 1200] +( + SymbolLine[0 2800 1500 2800 800] + SymbolLine[0 5000 2000 5000 800] + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 1000 2000 1000 800] +) +Symbol['F' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 1000 2000 1000 800] + SymbolLine[0 2800 1500 2800 800] +) +Symbol['G' 1200] +( + SymbolLine[2000 1000 2500 1500 800] + SymbolLine[500 1000 2000 1000 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[0 1500 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[500 5000 2000 5000 800] + SymbolLine[2000 5000 2500 4500 800] + SymbolLine[2500 3500 2500 4500 800] + SymbolLine[2000 3000 2500 3500 800] + SymbolLine[1000 3000 2000 3000 800] +) +Symbol['H' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[2500 1000 2500 5000 800] + SymbolLine[0 3000 2500 3000 800] +) +Symbol['I' 1200] +( + SymbolLine[0 1000 1000 1000 800] + SymbolLine[500 1000 500 5000 800] + SymbolLine[0 5000 1000 5000 800] +) +Symbol['J' 1200] +( + SymbolLine[700 1000 1500 1000 800] + SymbolLine[1500 1000 1500 4500 800] + SymbolLine[1000 5000 1500 4500 800] + SymbolLine[500 5000 1000 5000 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[0 4500 0 4000 800] +) +Symbol['K' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 3000 2000 1000 800] + SymbolLine[0 3000 2000 5000 800] +) +Symbol['L' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 5000 2000 5000 800] +) +Symbol['M' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 1000 1500 3000 800] + SymbolLine[1500 3000 3000 1000 800] + SymbolLine[3000 1000 3000 5000 800] +) +Symbol['N' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 1000 2500 5000 800] + SymbolLine[2500 1000 2500 5000 800] +) +Symbol['O' 1200] +( + SymbolLine[0 1500 0 4500 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 1500 1000 800] + SymbolLine[1500 1000 2000 1500 800] + SymbolLine[2000 1500 2000 4500 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[0 4500 500 5000 800] +) +Symbol['P' 1200] +( + SymbolLine[500 1000 500 5000 800] + SymbolLine[0 1000 2000 1000 800] + SymbolLine[2000 1000 2500 1500 800] + SymbolLine[2500 1500 2500 2500 800] + SymbolLine[2000 3000 2500 2500 800] + SymbolLine[500 3000 2000 3000 800] +) +Symbol['Q' 1200] +( + SymbolLine[0 1500 0 4500 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 1500 1000 800] + SymbolLine[1500 1000 2000 1500 800] + SymbolLine[2000 1500 2000 4000 800] + SymbolLine[1000 5000 2000 4000 800] + SymbolLine[500 5000 1000 5000 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[1000 3500 2000 5000 800] +) +Symbol['R' 1200] +( + SymbolLine[0 1000 2000 1000 800] + SymbolLine[2000 1000 2500 1500 800] + SymbolLine[2500 1500 2500 2500 800] + SymbolLine[2000 3000 2500 2500 800] + SymbolLine[500 3000 2000 3000 800] + SymbolLine[500 1000 500 5000 800] + SymbolLine[1300 3000 2500 5000 800] +) +Symbol['S' 1200] +( + SymbolLine[2000 1000 2500 1500 800] + SymbolLine[500 1000 2000 1000 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[0 1500 0 2500 800] + SymbolLine[0 2500 500 3000 800] + SymbolLine[500 3000 2000 3000 800] + SymbolLine[2000 3000 2500 3500 800] + SymbolLine[2500 3500 2500 4500 800] + SymbolLine[2000 5000 2500 4500 800] + SymbolLine[500 5000 2000 5000 800] + SymbolLine[0 4500 500 5000 800] +) +Symbol['T' 1200] +( + SymbolLine[0 1000 2000 1000 800] + SymbolLine[1000 1000 1000 5000 800] +) +Symbol['U' 1200] +( + SymbolLine[0 1000 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[2000 1000 2000 4500 800] +) +Symbol['V' 1200] +( + SymbolLine[0 1000 1000 5000 800] + SymbolLine[1000 5000 2000 1000 800] +) +Symbol['W' 1200] +( + SymbolLine[0 1000 0 3000 800] + SymbolLine[0 3000 500 5000 800] + SymbolLine[500 5000 1500 3000 800] + SymbolLine[1500 3000 2500 5000 800] + SymbolLine[2500 5000 3000 3000 800] + SymbolLine[3000 3000 3000 1000 800] +) +Symbol['X' 1200] +( + SymbolLine[0 5000 2500 1000 800] + SymbolLine[0 1000 2500 5000 800] +) +Symbol['Y' 1200] +( + SymbolLine[0 1000 1000 3000 800] + SymbolLine[1000 3000 2000 1000 800] + SymbolLine[1000 3000 1000 5000 800] +) +Symbol['Z' 1200] +( + SymbolLine[0 1000 2500 1000 800] + SymbolLine[0 5000 2500 1000 800] + SymbolLine[0 5000 2500 5000 800] +) +Symbol['[' 1200] +( + SymbolLine[0 1000 500 1000 800] + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 5000 500 5000 800] +) +Symbol['\' 1200] +( + SymbolLine[0 1500 3000 4500 800] +) +Symbol[']' 1200] +( + SymbolLine[0 1000 500 1000 800] + SymbolLine[500 1000 500 5000 800] + SymbolLine[0 5000 500 5000 800] +) +Symbol['^' 1200] +( + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 1000 1500 800] +) +Symbol['_' 1200] +( + SymbolLine[0 5000 2000 5000 800] +) +Symbol['a' 1200] +( + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[500 3000 1500 3000 800] + SymbolLine[0 3500 500 3000 800] + SymbolLine[0 3500 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[2000 3000 2000 4500 800] + SymbolLine[2000 4500 2500 5000 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[1500 5000 2000 4500 800] +) +Symbol['b' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[2000 3500 2000 4500 800] + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[500 3000 1500 3000 800] + SymbolLine[0 3500 500 3000 800] +) +Symbol['c' 1200] +( + SymbolLine[500 3000 2000 3000 800] + SymbolLine[0 3500 500 3000 800] + SymbolLine[0 3500 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[500 5000 2000 5000 800] +) +Symbol['d' 1200] +( + SymbolLine[2000 1000 2000 5000 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[0 3500 0 4500 800] + SymbolLine[0 3500 500 3000 800] + SymbolLine[500 3000 1500 3000 800] + SymbolLine[1500 3000 2000 3500 800] +) +Symbol['e' 1200] +( + SymbolLine[500 5000 2000 5000 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[0 3500 0 4500 800] + SymbolLine[0 3500 500 3000 800] + SymbolLine[500 3000 1500 3000 800] + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[0 4000 2000 4000 800] + SymbolLine[2000 4000 2000 3500 800] +) +Symbol['f' 1000] +( + SymbolLine[500 1500 500 5000 800] + SymbolLine[500 1500 1000 1000 800] + SymbolLine[1000 1000 1500 1000 800] + SymbolLine[0 3000 1000 3000 800] +) +Symbol['g' 1200] +( + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[500 3000 1500 3000 800] + SymbolLine[0 3500 500 3000 800] + SymbolLine[0 3500 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[0 6000 500 6500 800] + SymbolLine[500 6500 1500 6500 800] + SymbolLine[1500 6500 2000 6000 800] + SymbolLine[2000 3000 2000 6000 800] +) +Symbol['h' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 3500 500 3000 800] + SymbolLine[500 3000 1500 3000 800] + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[2000 3500 2000 5000 800] +) +Symbol['i' 1000] +( + SymbolLine[0 2000 0 2100 1000] + SymbolLine[0 3500 0 5000 800] +) +Symbol['j' 1000] +( + SymbolLine[500 2000 500 2100 1000] + SymbolLine[500 3500 500 6000 800] + SymbolLine[0 6500 500 6000 800] +) +Symbol['k' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 3500 1500 5000 800] + SymbolLine[0 3500 1000 2500 800] +) +Symbol['l' 1000] +( + SymbolLine[0 1000 0 4500 800] + SymbolLine[0 4500 500 5000 800] +) +Symbol['m' 1200] +( + SymbolLine[500 3500 500 5000 800] + SymbolLine[500 3500 1000 3000 800] + SymbolLine[1000 3000 1500 3000 800] + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[2000 3500 2000 5000 800] + SymbolLine[2000 3500 2500 3000 800] + SymbolLine[2500 3000 3000 3000 800] + SymbolLine[3000 3000 3500 3500 800] + SymbolLine[3500 3500 3500 5000 800] + SymbolLine[0 3000 500 3500 800] +) +Symbol['n' 1200] +( + SymbolLine[500 3500 500 5000 800] + SymbolLine[500 3500 1000 3000 800] + SymbolLine[1000 3000 1500 3000 800] + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[2000 3500 2000 5000 800] + SymbolLine[0 3000 500 3500 800] +) +Symbol['o' 1200] +( + SymbolLine[0 3500 0 4500 800] + SymbolLine[0 3500 500 3000 800] + SymbolLine[500 3000 1500 3000 800] + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[2000 3500 2000 4500 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[0 4500 500 5000 800] +) +Symbol['p' 1200] +( + SymbolLine[500 3500 500 6500 800] + SymbolLine[0 3000 500 3500 800] + SymbolLine[500 3500 1000 3000 800] + SymbolLine[1000 3000 2000 3000 800] + SymbolLine[2000 3000 2500 3500 800] + SymbolLine[2500 3500 2500 4500 800] + SymbolLine[2000 5000 2500 4500 800] + SymbolLine[1000 5000 2000 5000 800] + SymbolLine[500 4500 1000 5000 800] +) +Symbol['q' 1200] +( + SymbolLine[2000 3500 2000 6500 800] + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[500 3000 1500 3000 800] + SymbolLine[0 3500 500 3000 800] + SymbolLine[0 3500 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[1500 5000 2000 4500 800] +) +Symbol['r' 1200] +( + SymbolLine[500 3500 500 5000 800] + SymbolLine[500 3500 1000 3000 800] + SymbolLine[1000 3000 2000 3000 800] + SymbolLine[0 3000 500 3500 800] +) +Symbol['s' 1200] +( + SymbolLine[500 5000 2000 5000 800] + SymbolLine[2000 5000 2500 4500 800] + SymbolLine[2000 4000 2500 4500 800] + SymbolLine[500 4000 2000 4000 800] + SymbolLine[0 3500 500 4000 800] + SymbolLine[0 3500 500 3000 800] + SymbolLine[500 3000 2000 3000 800] + SymbolLine[2000 3000 2500 3500 800] + SymbolLine[0 4500 500 5000 800] +) +Symbol['t' 1000] +( + SymbolLine[500 1000 500 4500 800] + SymbolLine[500 4500 1000 5000 800] + SymbolLine[0 2500 1000 2500 800] +) +Symbol['u' 1200] +( + SymbolLine[0 3000 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[2000 3000 2000 4500 800] +) +Symbol['v' 1200] +( + SymbolLine[0 3000 1000 5000 800] + SymbolLine[2000 3000 1000 5000 800] +) +Symbol['w' 1200] +( + SymbolLine[0 3000 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[500 5000 1000 5000 800] + SymbolLine[1000 5000 1500 4500 800] + SymbolLine[1500 3000 1500 4500 800] + SymbolLine[1500 4500 2000 5000 800] + SymbolLine[2000 5000 2500 5000 800] + SymbolLine[2500 5000 3000 4500 800] + SymbolLine[3000 3000 3000 4500 800] +) +Symbol['x' 1200] +( + SymbolLine[0 3000 2000 5000 800] + SymbolLine[0 5000 2000 3000 800] +) +Symbol['y' 1200] +( + SymbolLine[0 3000 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[2000 3000 2000 6000 800] + SymbolLine[1500 6500 2000 6000 800] + SymbolLine[500 6500 1500 6500 800] + SymbolLine[0 6000 500 6500 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[1500 5000 2000 4500 800] +) +Symbol['z' 1200] +( + SymbolLine[0 3000 2000 3000 800] + SymbolLine[0 5000 2000 3000 800] + SymbolLine[0 5000 2000 5000 800] +) +Symbol['{' 1200] +( + SymbolLine[500 1500 1000 1000 800] + SymbolLine[500 1500 500 2500 800] + SymbolLine[0 3000 500 2500 800] + SymbolLine[0 3000 500 3500 800] + SymbolLine[500 3500 500 4500 800] + SymbolLine[500 4500 1000 5000 800] +) +Symbol['|' 1200] +( + SymbolLine[0 1000 0 5000 800] +) +Symbol['}' 1200] +( + SymbolLine[0 1000 500 1500 800] + SymbolLine[500 1500 500 2500 800] + SymbolLine[500 2500 1000 3000 800] + SymbolLine[500 3500 1000 3000 800] + SymbolLine[500 3500 500 4500 800] + SymbolLine[0 5000 500 4500 800] +) +Symbol['~' 1200] +( + SymbolLine[0 3500 500 3000 800] + SymbolLine[500 3000 1000 3000 800] + SymbolLine[1000 3000 1500 3500 800] + SymbolLine[1500 3500 2000 3500 800] + SymbolLine[2000 3500 2500 3000 800] +) +Attribute("PCB::grid::unit" "mil") +Via[100000 75000 7874 4000 0 3150 "" ""] + +Element["" "SMT transistor, 4 pins" "" "SC70_4" 5000 15000 9300 -9400 3 100 ""] +( + Pad[300 0 600 0 2900 3000 3500 "1" "1" "square"] + Pad[5100 -300 5100 300 2900 3000 3500 "2" "2" "square,edge2"] + Pad[5100 -7300 5100 -6700 2900 3000 3500 "3" "3" "square"] + Pad[0 -7300 0 -6700 2900 3000 3500 "4" "4" "square"] + ElementLine [-2100 -9400 -2100 2500 1000] + ElementLine [-2100 2500 7300 2500 1000] + ElementLine [7300 2500 7300 -9400 1000] + ElementLine [7300 -9400 -2100 -9400 1000] + + ) + +Element["" "Pressure transducer" "" "MPAK" 75000 60000 20300 -49700 3 100 ""] +( + Pad[0 -2800 0 2800 3100 3000 3700 "1" "1" "square,edge2"] + Pad[5000 -2800 5000 2800 3100 3000 3700 "2" "2" "square,edge2"] + Pad[10000 -2800 10000 2800 3100 3000 3700 "3" "3" "square,edge2"] + Pad[15000 -2800 15000 2800 3100 3000 3700 "4" "4" "square,edge2"] + Pad[3800 -43700 11200 -43700 8700 3000 9300 "5" "5" "square"] + ElementLine [-3200 -49700 -3200 6100 1000] + ElementLine [-3200 6100 18300 6100 1000] + ElementLine [18300 6100 18300 -49700 1000] + ElementLine [18300 -49700 -3200 -49700 1000] + + ) + +Element["" "SMT transistor, 4 pins" "" "SOT143" 20000 15000 11900 -11000 3 100 ""] +( + Pad[300 0 600 0 3400 3000 4000 "1" "1" "square"] + Pad[7400 -300 7400 300 3400 3000 4000 "2" "2" "square,edge2"] + Pad[7400 -8500 7400 -7900 3400 3000 4000 "3" "3" "square"] + Pad[0 -8500 0 -7900 3400 3000 4000 "4" "4" "square"] + ElementLine [-2500 -11000 -2500 2900 1000] + ElementLine [-2500 2900 9900 2900 1000] + ElementLine [9900 2900 9900 -11000 1000] + ElementLine [9900 -11000 -2500 -11000 1000] + + ) + +Element["" "SMT transistor, 4 pins" "" "SOT223" 40000 60000 25300 -32900 3 100 ""] +( + Pad[0 -3300 0 3300 5600 3000 6200 "1" "1" "square,edge2"] + Pad[9000 -3300 9000 3300 5600 3000 6200 "2" "2" "square,edge2"] + Pad[18100 -3300 18100 3300 5600 3000 6200 "3" "3" "square,edge2"] + Pad[4500 -24400 13500 -24400 12200 3000 12800 "4" "4" "square"] + ElementLine [-5200 -32900 -5200 8500 1000] + ElementLine [-5200 8500 23300 8500 1000] + ElementLine [23300 8500 23300 -32900 1000] + ElementLine [23300 -32900 -5200 -32900 1000] + + ) + +Element["" "SMT transistor, 5 pins" "" "SOT25" 35000 15000 11800 -11000 3 100 ""] +( + Pad[0 -800 0 800 2400 3000 3000 "1" "1" "square,edge2"] + Pad[7800 -800 7800 800 2400 3000 3000 "2" "2" "square,edge2"] + Pad[7800 -9000 7800 -7400 2400 3000 3000 "3" "3" "square"] + Pad[3900 -9000 3900 -7400 2400 3000 3000 "4" "4" "square"] + Pad[0 -9000 0 -7400 2400 3000 3000 "5" "5" "square"] + ElementLine [-2000 -11000 -2000 2900 1000] + ElementLine [-2000 2900 9800 2900 1000] + ElementLine [9800 2900 9800 -11000 1000] + ElementLine [9800 -11000 -2000 -11000 1000] + + ) + +Element["" "SMT transistor, 6 pins" "" "SOT26" 51100 15000 11800 -11000 3 100 ""] +( + Pad[0 -800 0 800 2400 3000 3000 "1" "1" "square,edge2"] + Pad[3900 -800 3900 800 2400 3000 3000 "2" "2" "square,edge2"] + Pad[7800 -800 7800 800 2400 3000 3000 "3" "3" "square,edge2"] + Pad[7800 -9000 7800 -7400 2400 3000 3000 "4" "4" "square"] + Pad[3900 -9000 3900 -7400 2400 3000 3000 "5" "5" "square"] + Pad[0 -9000 0 -7400 2400 3000 3000 "6" "6" "square"] + ElementLine [-2000 -11000 -2000 2900 1000] + ElementLine [-2000 2900 9800 2900 1000] + ElementLine [9800 2900 9800 -11000 1000] + ElementLine [9800 -11000 -2000 -11000 1000] + + ) + +Element["" "SMT transistor, 5 pins" "" "SOT325" 9900 65000 8600 -9400 3 100 ""] +( + Pad[0 -1000 0 1000 1500 3000 2100 "1" "1" "square,edge2"] + Pad[5100 -1000 5100 1000 1500 3000 2100 "2" "2" "square,edge2"] + Pad[5100 -8000 5100 -6000 1500 3000 2100 "3" "3" "square"] + Pad[2600 -8000 2600 -6000 1500 3000 2100 "4" "4" "square"] + Pad[0 -8000 0 -6000 1500 3000 2100 "5" "5" "square"] + ElementLine [-1400 -9400 -1400 2500 1000] + ElementLine [-1400 2500 6600 2500 1000] + ElementLine [6600 2500 6600 -9400 1000] + ElementLine [6600 -9400 -1400 -9400 1000] + + ) + +Element["" "SMT transistor, 6 pins" "" "SOT326" 22400 65000 8600 -9400 3 100 ""] +( + Pad[0 -1000 0 1000 1500 3000 2100 "1" "1" "square,edge2"] + Pad[2600 -1000 2600 1000 1500 3000 2100 "2" "2" "square,edge2"] + Pad[5100 -1000 5100 1000 1500 3000 2100 "3" "3" "square,edge2"] + Pad[5100 -8000 5100 -6000 1500 3000 2100 "4" "4" "square"] + Pad[2600 -8000 2600 -6000 1500 3000 2100 "5" "5" "square"] + Pad[0 -8000 0 -6000 1500 3000 2100 "6" "6" "square"] + ElementLine [-1400 -9400 -1400 2500 1000] + ElementLine [-1400 2500 6600 2500 1000] + ElementLine [6600 2500 6600 -9400 1000] + ElementLine [6600 -9400 -1400 -9400 1000] + + ) + +Element["" "SMT transistor, 4 pins" "" "SOT89" 8900 45000 17300 -16400 3 100 ""] +( + Pad[0 -1200 0 1200 3700 3000 4300 "1" "1" "square,edge2"] + Pad[6100 -1200 6100 1200 3700 3000 4300 "2" "2" "square,edge2"] + Pad[12200 -1200 12200 1200 3700 3000 4300 "3" "3" "square,edge2"] + Pad[3100 -12200 9100 -12200 6100 3000 6700 "4" "4" "square"] + ElementLine [-3000 -16400 -3000 4300 1000] + ElementLine [-3000 4300 15300 4300 1000] + ElementLine [15300 4300 15300 -16400 1000] + ElementLine [15300 -16400 -3000 -16400 1000] + + ) +Layer(1 "component") +( +) +Layer(2 "solder") +( +) +Layer(3 "comp-GND") +( +) +Layer(4 "comp-power") +( +) +Layer(5 "sold-GND") +( +) +Layer(6 "sold-power") +( +) +Layer(7 "signal3") +( +) +Layer(8 "outline") +( +) +Layer(9 "silk") +( +) +Layer(10 "silk") +( +) Index: tags/2.1.2/util/pcblib-map/trh2.pcb =================================================================== --- tags/2.1.2/util/pcblib-map/trh2.pcb (nonexistent) +++ tags/2.1.2/util/pcblib-map/trh2.pcb (revision 24813) @@ -0,0 +1,928 @@ +# release: pcb 20110918 + +# To read pcb files, the pcb version (or the git source date) must be >= the file version +FileVersion[20070407] + +PCB["" 330000 150000] + +Grid[10000.0 0 0 1] +Cursor[10000 0 0.000000] +PolyArea[3100.006200] +Thermal[0.500000] +DRC[1200 900 1000 700 1500 1000] +Flags("nameonpcb,clearnew,snappin") +Groups("1,3,4,c:2,5,6,s:7:8") +Styles["Signal,1000,7874,3150,2000:Power,2000,8661,3937,2000:Fat,8000,13780,4724,2500:Sig-tight,1000,6400,3150,1200"] + +Symbol[' ' 1800] +( +) +Symbol['!' 1200] +( + SymbolLine[0 4500 0 5000 800] + SymbolLine[0 1000 0 3500 800] +) +Symbol['"' 1200] +( + SymbolLine[0 1000 0 2000 800] + SymbolLine[1000 1000 1000 2000 800] +) +Symbol['#' 1200] +( + SymbolLine[0 3500 2000 3500 800] + SymbolLine[0 2500 2000 2500 800] + SymbolLine[1500 2000 1500 4000 800] + SymbolLine[500 2000 500 4000 800] +) +Symbol['$' 1200] +( + SymbolLine[1500 1500 2000 2000 800] + SymbolLine[500 1500 1500 1500 800] + SymbolLine[0 2000 500 1500 800] + SymbolLine[0 2000 0 2500 800] + SymbolLine[0 2500 500 3000 800] + SymbolLine[500 3000 1500 3000 800] + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[2000 3500 2000 4000 800] + SymbolLine[1500 4500 2000 4000 800] + SymbolLine[500 4500 1500 4500 800] + SymbolLine[0 4000 500 4500 800] + SymbolLine[1000 1000 1000 5000 800] +) +Symbol['%' 1200] +( + SymbolLine[0 1500 0 2000 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 1000 1000 800] + SymbolLine[1000 1000 1500 1500 800] + SymbolLine[1500 1500 1500 2000 800] + SymbolLine[1000 2500 1500 2000 800] + SymbolLine[500 2500 1000 2500 800] + SymbolLine[0 2000 500 2500 800] + SymbolLine[0 5000 4000 1000 800] + SymbolLine[3500 5000 4000 4500 800] + SymbolLine[4000 4000 4000 4500 800] + SymbolLine[3500 3500 4000 4000 800] + SymbolLine[3000 3500 3500 3500 800] + SymbolLine[2500 4000 3000 3500 800] + SymbolLine[2500 4000 2500 4500 800] + SymbolLine[2500 4500 3000 5000 800] + SymbolLine[3000 5000 3500 5000 800] +) +Symbol['&' 1200] +( + SymbolLine[0 4500 500 5000 800] + SymbolLine[0 1500 0 2500 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[0 3500 1500 2000 800] + SymbolLine[500 5000 1000 5000 800] + SymbolLine[1000 5000 2000 4000 800] + SymbolLine[0 2500 2500 5000 800] + SymbolLine[500 1000 1000 1000 800] + SymbolLine[1000 1000 1500 1500 800] + SymbolLine[1500 1500 1500 2000 800] + SymbolLine[0 3500 0 4500 800] +) +Symbol[''' 1200] +( + SymbolLine[0 2000 1000 1000 800] +) +Symbol['(' 1200] +( + SymbolLine[0 4500 500 5000 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[0 1500 0 4500 800] +) +Symbol[')' 1200] +( + SymbolLine[0 1000 500 1500 800] + SymbolLine[500 1500 500 4500 800] + SymbolLine[0 5000 500 4500 800] +) +Symbol['*' 1200] +( + SymbolLine[0 2000 2000 4000 800] + SymbolLine[0 4000 2000 2000 800] + SymbolLine[0 3000 2000 3000 800] + SymbolLine[1000 2000 1000 4000 800] +) +Symbol['+' 1200] +( + SymbolLine[0 3000 2000 3000 800] + SymbolLine[1000 2000 1000 4000 800] +) +Symbol[',' 1200] +( + SymbolLine[0 6000 1000 5000 800] +) +Symbol['-' 1200] +( + SymbolLine[0 3000 2000 3000 800] +) +Symbol['.' 1200] +( + SymbolLine[0 5000 500 5000 800] +) +Symbol['/' 1200] +( + SymbolLine[0 4500 3000 1500 800] +) +Symbol['0' 1200] +( + SymbolLine[0 4500 500 5000 800] + SymbolLine[0 1500 0 4500 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 1500 1000 800] + SymbolLine[1500 1000 2000 1500 800] + SymbolLine[2000 1500 2000 4500 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[0 4000 2000 2000 800] +) +Symbol['1' 1200] +( + SymbolLine[0 1800 800 1000 800] + SymbolLine[800 1000 800 5000 800] + SymbolLine[0 5000 1500 5000 800] +) +Symbol['2' 1200] +( + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 2000 1000 800] + SymbolLine[2000 1000 2500 1500 800] + SymbolLine[2500 1500 2500 2500 800] + SymbolLine[0 5000 2500 2500 800] + SymbolLine[0 5000 2500 5000 800] +) +Symbol['3' 1200] +( + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 1500 1000 800] + SymbolLine[1500 1000 2000 1500 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[500 2800 1500 2800 800] + SymbolLine[2000 1500 2000 2300 800] + SymbolLine[2000 3300 2000 4500 800] + SymbolLine[2000 3300 1500 2800 800] + SymbolLine[2000 2300 1500 2800 800] +) +Symbol['4' 1200] +( + SymbolLine[0 3500 2000 1000 800] + SymbolLine[0 3500 2500 3500 800] + SymbolLine[2000 1000 2000 5000 800] +) +Symbol['5' 1200] +( + SymbolLine[0 1000 2000 1000 800] + SymbolLine[0 1000 0 3000 800] + SymbolLine[0 3000 500 2500 800] + SymbolLine[500 2500 1500 2500 800] + SymbolLine[1500 2500 2000 3000 800] + SymbolLine[2000 3000 2000 4500 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[0 4500 500 5000 800] +) +Symbol['6' 1200] +( + SymbolLine[1500 1000 2000 1500 800] + SymbolLine[500 1000 1500 1000 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[0 1500 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[1500 2800 2000 3300 800] + SymbolLine[0 2800 1500 2800 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[2000 3300 2000 4500 800] +) +Symbol['7' 1200] +( + SymbolLine[500 5000 2500 1000 800] + SymbolLine[0 1000 2500 1000 800] +) +Symbol['8' 1200] +( + SymbolLine[0 4500 500 5000 800] + SymbolLine[0 3700 0 4500 800] + SymbolLine[0 3700 700 3000 800] + SymbolLine[700 3000 1300 3000 800] + SymbolLine[1300 3000 2000 3700 800] + SymbolLine[2000 3700 2000 4500 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[0 2300 700 3000 800] + SymbolLine[0 1500 0 2300 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 1500 1000 800] + SymbolLine[1500 1000 2000 1500 800] + SymbolLine[2000 1500 2000 2300 800] + SymbolLine[1300 3000 2000 2300 800] +) +Symbol['9' 1200] +( + SymbolLine[500 5000 2000 3000 800] + SymbolLine[2000 1500 2000 3000 800] + SymbolLine[1500 1000 2000 1500 800] + SymbolLine[500 1000 1500 1000 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[0 1500 0 2500 800] + SymbolLine[0 2500 500 3000 800] + SymbolLine[500 3000 2000 3000 800] +) +Symbol[':' 1200] +( + SymbolLine[0 2500 500 2500 800] + SymbolLine[0 3500 500 3500 800] +) +Symbol[';' 1200] +( + SymbolLine[0 5000 1000 4000 800] + SymbolLine[1000 2500 1000 3000 800] +) +Symbol['<' 1200] +( + SymbolLine[0 3000 1000 2000 800] + SymbolLine[0 3000 1000 4000 800] +) +Symbol['=' 1200] +( + SymbolLine[0 2500 2000 2500 800] + SymbolLine[0 3500 2000 3500 800] +) +Symbol['>' 1200] +( + SymbolLine[0 2000 1000 3000 800] + SymbolLine[0 4000 1000 3000 800] +) +Symbol['?' 1200] +( + SymbolLine[1000 3000 1000 3500 800] + SymbolLine[1000 4500 1000 5000 800] + SymbolLine[0 1500 0 2000 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 1500 1000 800] + SymbolLine[1500 1000 2000 1500 800] + SymbolLine[2000 1500 2000 2000 800] + SymbolLine[1000 3000 2000 2000 800] +) +Symbol['@' 1200] +( + SymbolLine[0 1000 0 4000 800] + SymbolLine[0 4000 1000 5000 800] + SymbolLine[1000 5000 4000 5000 800] + SymbolLine[5000 3500 5000 1000 800] + SymbolLine[5000 1000 4000 0 800] + SymbolLine[4000 0 1000 0 800] + SymbolLine[1000 0 0 1000 800] + SymbolLine[1500 2000 1500 3000 800] + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[2000 3500 3000 3500 800] + SymbolLine[3000 3500 3500 3000 800] + SymbolLine[3500 3000 4000 3500 800] + SymbolLine[3500 3000 3500 1500 800] + SymbolLine[3500 2000 3000 1500 800] + SymbolLine[2000 1500 3000 1500 800] + SymbolLine[2000 1500 1500 2000 800] + SymbolLine[4000 3500 5000 3500 800] +) +Symbol['A' 1200] +( + SymbolLine[0 2000 0 5000 800] + SymbolLine[0 2000 700 1000 800] + SymbolLine[700 1000 1800 1000 800] + SymbolLine[1800 1000 2500 2000 800] + SymbolLine[2500 2000 2500 5000 800] + SymbolLine[0 3000 2500 3000 800] +) +Symbol['B' 1200] +( + SymbolLine[0 5000 2000 5000 800] + SymbolLine[2000 5000 2500 4500 800] + SymbolLine[2500 3300 2500 4500 800] + SymbolLine[2000 2800 2500 3300 800] + SymbolLine[500 2800 2000 2800 800] + SymbolLine[500 1000 500 5000 800] + SymbolLine[0 1000 2000 1000 800] + SymbolLine[2000 1000 2500 1500 800] + SymbolLine[2500 1500 2500 2300 800] + SymbolLine[2000 2800 2500 2300 800] +) +Symbol['C' 1200] +( + SymbolLine[700 5000 2000 5000 800] + SymbolLine[0 4300 700 5000 800] + SymbolLine[0 1700 0 4300 800] + SymbolLine[0 1700 700 1000 800] + SymbolLine[700 1000 2000 1000 800] +) +Symbol['D' 1200] +( + SymbolLine[500 1000 500 5000 800] + SymbolLine[1800 1000 2500 1700 800] + SymbolLine[2500 1700 2500 4300 800] + SymbolLine[1800 5000 2500 4300 800] + SymbolLine[0 5000 1800 5000 800] + SymbolLine[0 1000 1800 1000 800] +) +Symbol['E' 1200] +( + SymbolLine[0 2800 1500 2800 800] + SymbolLine[0 5000 2000 5000 800] + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 1000 2000 1000 800] +) +Symbol['F' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 1000 2000 1000 800] + SymbolLine[0 2800 1500 2800 800] +) +Symbol['G' 1200] +( + SymbolLine[2000 1000 2500 1500 800] + SymbolLine[500 1000 2000 1000 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[0 1500 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[500 5000 2000 5000 800] + SymbolLine[2000 5000 2500 4500 800] + SymbolLine[2500 3500 2500 4500 800] + SymbolLine[2000 3000 2500 3500 800] + SymbolLine[1000 3000 2000 3000 800] +) +Symbol['H' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[2500 1000 2500 5000 800] + SymbolLine[0 3000 2500 3000 800] +) +Symbol['I' 1200] +( + SymbolLine[0 1000 1000 1000 800] + SymbolLine[500 1000 500 5000 800] + SymbolLine[0 5000 1000 5000 800] +) +Symbol['J' 1200] +( + SymbolLine[700 1000 1500 1000 800] + SymbolLine[1500 1000 1500 4500 800] + SymbolLine[1000 5000 1500 4500 800] + SymbolLine[500 5000 1000 5000 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[0 4500 0 4000 800] +) +Symbol['K' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 3000 2000 1000 800] + SymbolLine[0 3000 2000 5000 800] +) +Symbol['L' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 5000 2000 5000 800] +) +Symbol['M' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 1000 1500 3000 800] + SymbolLine[1500 3000 3000 1000 800] + SymbolLine[3000 1000 3000 5000 800] +) +Symbol['N' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 1000 2500 5000 800] + SymbolLine[2500 1000 2500 5000 800] +) +Symbol['O' 1200] +( + SymbolLine[0 1500 0 4500 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 1500 1000 800] + SymbolLine[1500 1000 2000 1500 800] + SymbolLine[2000 1500 2000 4500 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[0 4500 500 5000 800] +) +Symbol['P' 1200] +( + SymbolLine[500 1000 500 5000 800] + SymbolLine[0 1000 2000 1000 800] + SymbolLine[2000 1000 2500 1500 800] + SymbolLine[2500 1500 2500 2500 800] + SymbolLine[2000 3000 2500 2500 800] + SymbolLine[500 3000 2000 3000 800] +) +Symbol['Q' 1200] +( + SymbolLine[0 1500 0 4500 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 1500 1000 800] + SymbolLine[1500 1000 2000 1500 800] + SymbolLine[2000 1500 2000 4000 800] + SymbolLine[1000 5000 2000 4000 800] + SymbolLine[500 5000 1000 5000 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[1000 3500 2000 5000 800] +) +Symbol['R' 1200] +( + SymbolLine[0 1000 2000 1000 800] + SymbolLine[2000 1000 2500 1500 800] + SymbolLine[2500 1500 2500 2500 800] + SymbolLine[2000 3000 2500 2500 800] + SymbolLine[500 3000 2000 3000 800] + SymbolLine[500 1000 500 5000 800] + SymbolLine[1300 3000 2500 5000 800] +) +Symbol['S' 1200] +( + SymbolLine[2000 1000 2500 1500 800] + SymbolLine[500 1000 2000 1000 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[0 1500 0 2500 800] + SymbolLine[0 2500 500 3000 800] + SymbolLine[500 3000 2000 3000 800] + SymbolLine[2000 3000 2500 3500 800] + SymbolLine[2500 3500 2500 4500 800] + SymbolLine[2000 5000 2500 4500 800] + SymbolLine[500 5000 2000 5000 800] + SymbolLine[0 4500 500 5000 800] +) +Symbol['T' 1200] +( + SymbolLine[0 1000 2000 1000 800] + SymbolLine[1000 1000 1000 5000 800] +) +Symbol['U' 1200] +( + SymbolLine[0 1000 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[2000 1000 2000 4500 800] +) +Symbol['V' 1200] +( + SymbolLine[0 1000 1000 5000 800] + SymbolLine[1000 5000 2000 1000 800] +) +Symbol['W' 1200] +( + SymbolLine[0 1000 0 3000 800] + SymbolLine[0 3000 500 5000 800] + SymbolLine[500 5000 1500 3000 800] + SymbolLine[1500 3000 2500 5000 800] + SymbolLine[2500 5000 3000 3000 800] + SymbolLine[3000 3000 3000 1000 800] +) +Symbol['X' 1200] +( + SymbolLine[0 5000 2500 1000 800] + SymbolLine[0 1000 2500 5000 800] +) +Symbol['Y' 1200] +( + SymbolLine[0 1000 1000 3000 800] + SymbolLine[1000 3000 2000 1000 800] + SymbolLine[1000 3000 1000 5000 800] +) +Symbol['Z' 1200] +( + SymbolLine[0 1000 2500 1000 800] + SymbolLine[0 5000 2500 1000 800] + SymbolLine[0 5000 2500 5000 800] +) +Symbol['[' 1200] +( + SymbolLine[0 1000 500 1000 800] + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 5000 500 5000 800] +) +Symbol['\' 1200] +( + SymbolLine[0 1500 3000 4500 800] +) +Symbol[']' 1200] +( + SymbolLine[0 1000 500 1000 800] + SymbolLine[500 1000 500 5000 800] + SymbolLine[0 5000 500 5000 800] +) +Symbol['^' 1200] +( + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 1000 1500 800] +) +Symbol['_' 1200] +( + SymbolLine[0 5000 2000 5000 800] +) +Symbol['a' 1200] +( + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[500 3000 1500 3000 800] + SymbolLine[0 3500 500 3000 800] + SymbolLine[0 3500 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[2000 3000 2000 4500 800] + SymbolLine[2000 4500 2500 5000 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[1500 5000 2000 4500 800] +) +Symbol['b' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[2000 3500 2000 4500 800] + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[500 3000 1500 3000 800] + SymbolLine[0 3500 500 3000 800] +) +Symbol['c' 1200] +( + SymbolLine[500 3000 2000 3000 800] + SymbolLine[0 3500 500 3000 800] + SymbolLine[0 3500 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[500 5000 2000 5000 800] +) +Symbol['d' 1200] +( + SymbolLine[2000 1000 2000 5000 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[0 3500 0 4500 800] + SymbolLine[0 3500 500 3000 800] + SymbolLine[500 3000 1500 3000 800] + SymbolLine[1500 3000 2000 3500 800] +) +Symbol['e' 1200] +( + SymbolLine[500 5000 2000 5000 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[0 3500 0 4500 800] + SymbolLine[0 3500 500 3000 800] + SymbolLine[500 3000 1500 3000 800] + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[0 4000 2000 4000 800] + SymbolLine[2000 4000 2000 3500 800] +) +Symbol['f' 1000] +( + SymbolLine[500 1500 500 5000 800] + SymbolLine[500 1500 1000 1000 800] + SymbolLine[1000 1000 1500 1000 800] + SymbolLine[0 3000 1000 3000 800] +) +Symbol['g' 1200] +( + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[500 3000 1500 3000 800] + SymbolLine[0 3500 500 3000 800] + SymbolLine[0 3500 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[0 6000 500 6500 800] + SymbolLine[500 6500 1500 6500 800] + SymbolLine[1500 6500 2000 6000 800] + SymbolLine[2000 3000 2000 6000 800] +) +Symbol['h' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 3500 500 3000 800] + SymbolLine[500 3000 1500 3000 800] + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[2000 3500 2000 5000 800] +) +Symbol['i' 1000] +( + SymbolLine[0 2000 0 2100 1000] + SymbolLine[0 3500 0 5000 800] +) +Symbol['j' 1000] +( + SymbolLine[500 2000 500 2100 1000] + SymbolLine[500 3500 500 6000 800] + SymbolLine[0 6500 500 6000 800] +) +Symbol['k' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 3500 1500 5000 800] + SymbolLine[0 3500 1000 2500 800] +) +Symbol['l' 1000] +( + SymbolLine[0 1000 0 4500 800] + SymbolLine[0 4500 500 5000 800] +) +Symbol['m' 1200] +( + SymbolLine[500 3500 500 5000 800] + SymbolLine[500 3500 1000 3000 800] + SymbolLine[1000 3000 1500 3000 800] + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[2000 3500 2000 5000 800] + SymbolLine[2000 3500 2500 3000 800] + SymbolLine[2500 3000 3000 3000 800] + SymbolLine[3000 3000 3500 3500 800] + SymbolLine[3500 3500 3500 5000 800] + SymbolLine[0 3000 500 3500 800] +) +Symbol['n' 1200] +( + SymbolLine[500 3500 500 5000 800] + SymbolLine[500 3500 1000 3000 800] + SymbolLine[1000 3000 1500 3000 800] + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[2000 3500 2000 5000 800] + SymbolLine[0 3000 500 3500 800] +) +Symbol['o' 1200] +( + SymbolLine[0 3500 0 4500 800] + SymbolLine[0 3500 500 3000 800] + SymbolLine[500 3000 1500 3000 800] + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[2000 3500 2000 4500 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[0 4500 500 5000 800] +) +Symbol['p' 1200] +( + SymbolLine[500 3500 500 6500 800] + SymbolLine[0 3000 500 3500 800] + SymbolLine[500 3500 1000 3000 800] + SymbolLine[1000 3000 2000 3000 800] + SymbolLine[2000 3000 2500 3500 800] + SymbolLine[2500 3500 2500 4500 800] + SymbolLine[2000 5000 2500 4500 800] + SymbolLine[1000 5000 2000 5000 800] + SymbolLine[500 4500 1000 5000 800] +) +Symbol['q' 1200] +( + SymbolLine[2000 3500 2000 6500 800] + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[500 3000 1500 3000 800] + SymbolLine[0 3500 500 3000 800] + SymbolLine[0 3500 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[1500 5000 2000 4500 800] +) +Symbol['r' 1200] +( + SymbolLine[500 3500 500 5000 800] + SymbolLine[500 3500 1000 3000 800] + SymbolLine[1000 3000 2000 3000 800] + SymbolLine[0 3000 500 3500 800] +) +Symbol['s' 1200] +( + SymbolLine[500 5000 2000 5000 800] + SymbolLine[2000 5000 2500 4500 800] + SymbolLine[2000 4000 2500 4500 800] + SymbolLine[500 4000 2000 4000 800] + SymbolLine[0 3500 500 4000 800] + SymbolLine[0 3500 500 3000 800] + SymbolLine[500 3000 2000 3000 800] + SymbolLine[2000 3000 2500 3500 800] + SymbolLine[0 4500 500 5000 800] +) +Symbol['t' 1000] +( + SymbolLine[500 1000 500 4500 800] + SymbolLine[500 4500 1000 5000 800] + SymbolLine[0 2500 1000 2500 800] +) +Symbol['u' 1200] +( + SymbolLine[0 3000 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[2000 3000 2000 4500 800] +) +Symbol['v' 1200] +( + SymbolLine[0 3000 1000 5000 800] + SymbolLine[2000 3000 1000 5000 800] +) +Symbol['w' 1200] +( + SymbolLine[0 3000 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[500 5000 1000 5000 800] + SymbolLine[1000 5000 1500 4500 800] + SymbolLine[1500 3000 1500 4500 800] + SymbolLine[1500 4500 2000 5000 800] + SymbolLine[2000 5000 2500 5000 800] + SymbolLine[2500 5000 3000 4500 800] + SymbolLine[3000 3000 3000 4500 800] +) +Symbol['x' 1200] +( + SymbolLine[0 3000 2000 5000 800] + SymbolLine[0 5000 2000 3000 800] +) +Symbol['y' 1200] +( + SymbolLine[0 3000 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[2000 3000 2000 6000 800] + SymbolLine[1500 6500 2000 6000 800] + SymbolLine[500 6500 1500 6500 800] + SymbolLine[0 6000 500 6500 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[1500 5000 2000 4500 800] +) +Symbol['z' 1200] +( + SymbolLine[0 3000 2000 3000 800] + SymbolLine[0 5000 2000 3000 800] + SymbolLine[0 5000 2000 5000 800] +) +Symbol['{' 1200] +( + SymbolLine[500 1500 1000 1000 800] + SymbolLine[500 1500 500 2500 800] + SymbolLine[0 3000 500 2500 800] + SymbolLine[0 3000 500 3500 800] + SymbolLine[500 3500 500 4500 800] + SymbolLine[500 4500 1000 5000 800] +) +Symbol['|' 1200] +( + SymbolLine[0 1000 0 5000 800] +) +Symbol['}' 1200] +( + SymbolLine[0 1000 500 1500 800] + SymbolLine[500 1500 500 2500 800] + SymbolLine[500 2500 1000 3000 800] + SymbolLine[500 3500 1000 3000 800] + SymbolLine[500 3500 500 4500 800] + SymbolLine[0 5000 500 4500 800] +) +Symbol['~' 1200] +( + SymbolLine[0 3500 500 3000 800] + SymbolLine[500 3000 1000 3000 800] + SymbolLine[1000 3000 1500 3500 800] + SymbolLine[1500 3500 2000 3500 800] + SymbolLine[2000 3500 2500 3000 800] +) +Attribute("PCB::grid::unit" "mil") +Via[330000 150000 7874 4000 0 3150 "" ""] + +Element["" "Crystals" "" "HC49" 20000 40000 -11000 5000 1 100 ""] +( + Pin[0 0 6000 3000 6600 2800 "1" "1" "square"] + Pin[0 -20000 6000 3000 6600 2800 "2" "2" ""] + ElementLine [-5000 -20000 -5000 0 2000] + ElementLine [5000 -20000 5000 0 2000] + ElementArc [0 -20000 5000 5000 180 180 2000] + ElementArc [0 0 5000 5000 0 180 2000] + + ) + +Element["" "Crystals" "" "HC49U" 50000 39200 -15100 12100 1 100 ""] +( + Pin[0 0 6000 3000 6600 3200 "1" "1" "square"] + Pin[0 -19200 6000 3000 6600 3200 "2" "2" ""] + ElementLine [-9100 -22300 -9100 3000 2000] + ElementLine [9200 -22300 9200 3000 2000] + ElementArc [0 -22300 9100 9100 180 180 2000] + ElementArc [0 3000 9100 9100 0 180 2000] + + ) + +Element["" "Crystals" "" "HC49UH" 180000 50000 -67500 12100 1 100 ""] +( + Pin[0 0 6000 3000 6600 3200 "1" "1" "square,edge2"] + Pin[0 -19200 6000 3000 6600 3200 "2" "2" "edge2"] + ElementLine [-61500 -31400 -61500 12100 2000] + ElementLine [-61500 -31400 -10000 -31400 2000] + ElementLine [-10000 -31400 -10000 12100 2000] + ElementLine [-61500 12100 -10000 12100 2000] + + ) + +Element["" "Crystals" "" "HC51U" 90000 68500 -23600 13600 1 100 ""] +( + Pin[0 0 8000 3000 8600 4000 "1" "1" "square"] + Pin[0 -48500 8000 3000 8600 4000 "2" "2" ""] + ElementLine [-17600 -44500 -17600 -4000 2000] + ElementLine [17600 -44500 17600 -4000 2000] + ElementArc [0 -44500 17600 17600 180 180 2000] + ElementArc [0 -4000 17600 17600 0 180 2000] + + ) + +Element["" "Crystals" "" "HC51UH" 290000 70000 -103500 13600 1 100 ""] +( + Pin[0 0 8000 3000 8600 4000 "1" "1" "square,edge2"] + Pin[0 -48500 8000 3000 8600 4000 "2" "2" "edge2"] + ElementLine [-97500 -62100 -97500 13600 2000] + ElementLine [-97500 -62100 -20000 -62100 2000] + ElementLine [-20000 -62100 -20000 13600 2000] + ElementLine [-97500 13600 -20000 13600 2000] + + ) + +Element["" "LED, size in mm (pin 1 is +, 2 is -)" "" "LED3" 30000 125000 7000 -10000 1 100 ""] +( + Pin[0 5000 6500 3000 7100 4300 "1" "1" "square"] + Pin[0 -5000 6500 3000 7100 4300 "2" "2" ""] + ElementArc [0 0 5900 5900 135 90 1000] + ElementArc [0 0 5900 5900 315 90 1000] + ElementArc [0 0 7900 7900 135 90 1000] + ElementArc [0 0 7900 7900 315 90 1000] + + ) + +Element["" "LED, size in mm (pin 1 is +, 2 is -)" "" "LED5" 70000 125000 7000 -10000 1 100 ""] +( + Pin[0 5000 6500 3000 7100 4300 "1" "1" "square"] + Pin[0 -5000 6500 3000 7100 4300 "2" "2" ""] + ElementArc [0 0 11800 11800 90 360 1000] + ElementArc [0 0 13800 13800 90 360 1000] + + ) + +Element["" "diode in TO220" "" "TO220ACSTAND" 170000 142000 36000 -17000 3 100 ""] +( + Pin[0 -12000 8000 3000 8600 4000 "1" "1" "square,edge2"] + Pin[20000 -12000 8000 3000 8600 4000 "2" "2" "edge2"] + ElementLine [-10000 -22000 -10000 -4000 2000] + ElementLine [-10000 -4000 30000 -4000 2000] + ElementLine [30000 -4000 30000 -22000 2000] + ElementLine [30000 -22000 -10000 -22000 2000] + ElementLine [-10000 -17000 30000 -17000 1000] + ElementLine [2500 -22000 2500 -17000 1000] + ElementLine [17500 -22000 17500 -17000 1000] + + ) + +Element["" "diode in TO220" "" "TO247_2" 230000 140000 59400 -22000 3 100 ""] +( + Pin[0 -14000 10000 3000 10600 6000 "1" "1" "square,edge2"] + Pin[43800 -14000 10000 3000 10600 6000 "2" "2" "edge2"] + ElementLine [-9600 -27000 -9600 -6000 2000] + ElementLine [-9600 -6000 53400 -6000 2000] + ElementLine [53400 -6000 53400 -27000 2000] + ElementLine [53400 -27000 -9600 -27000 2000] + ElementLine [-9600 -22000 53400 -22000 1000] + ElementLine [14400 -27000 14400 -22000 1000] + ElementLine [29400 -27000 29400 -22000 1000] + + ) +Layer(1 "component") +( +) +Layer(2 "solder") +( +) +Layer(3 "comp-GND") +( +) +Layer(4 "comp-power") +( +) +Layer(5 "sold-GND") +( +) +Layer(6 "sold-power") +( +) +Layer(7 "signal3") +( +) +Layer(8 "outline") +( +) +Layer(9 "silk") +( +) +Layer(10 "silk") +( + Line[0 100000 330000 100000 1000 4000 "clearline"] + Line[130000 100000 130000 150000 1000 4000 "clearline"] + Text[310000 40000 0 200 "HC" "clearline"] + Text[100000 120000 0 200 "LED" "clearline"] + Text[300000 120000 0 200 "TO" "clearline"] +) Index: tags/2.1.2/util/pcblib-map/trh3.pcb =================================================================== --- tags/2.1.2/util/pcblib-map/trh3.pcb (nonexistent) +++ tags/2.1.2/util/pcblib-map/trh3.pcb (revision 24813) @@ -0,0 +1,1096 @@ +# release: pcb 20110918 + +# To read pcb files, the pcb version (or the git source date) must be >= the file version +FileVersion[20070407] + +PCB["" 270000 240000] + +Grid[10000.0 0 0 1] +Cursor[0 0 0.000000] +PolyArea[3100.006200] +Thermal[0.500000] +DRC[1200 900 1000 700 1500 1000] +Flags("nameonpcb,clearnew,snappin") +Groups("1,3,4,c:2,5,6,s:7:8") +Styles["Signal,1000,7874,3150,2000:Power,2000,8661,3937,2000:Fat,8000,13780,4724,2500:Sig-tight,1000,6400,3150,1200"] + +Symbol[' ' 1800] +( +) +Symbol['!' 1200] +( + SymbolLine[0 4500 0 5000 800] + SymbolLine[0 1000 0 3500 800] +) +Symbol['"' 1200] +( + SymbolLine[0 1000 0 2000 800] + SymbolLine[1000 1000 1000 2000 800] +) +Symbol['#' 1200] +( + SymbolLine[0 3500 2000 3500 800] + SymbolLine[0 2500 2000 2500 800] + SymbolLine[1500 2000 1500 4000 800] + SymbolLine[500 2000 500 4000 800] +) +Symbol['$' 1200] +( + SymbolLine[1500 1500 2000 2000 800] + SymbolLine[500 1500 1500 1500 800] + SymbolLine[0 2000 500 1500 800] + SymbolLine[0 2000 0 2500 800] + SymbolLine[0 2500 500 3000 800] + SymbolLine[500 3000 1500 3000 800] + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[2000 3500 2000 4000 800] + SymbolLine[1500 4500 2000 4000 800] + SymbolLine[500 4500 1500 4500 800] + SymbolLine[0 4000 500 4500 800] + SymbolLine[1000 1000 1000 5000 800] +) +Symbol['%' 1200] +( + SymbolLine[0 1500 0 2000 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 1000 1000 800] + SymbolLine[1000 1000 1500 1500 800] + SymbolLine[1500 1500 1500 2000 800] + SymbolLine[1000 2500 1500 2000 800] + SymbolLine[500 2500 1000 2500 800] + SymbolLine[0 2000 500 2500 800] + SymbolLine[0 5000 4000 1000 800] + SymbolLine[3500 5000 4000 4500 800] + SymbolLine[4000 4000 4000 4500 800] + SymbolLine[3500 3500 4000 4000 800] + SymbolLine[3000 3500 3500 3500 800] + SymbolLine[2500 4000 3000 3500 800] + SymbolLine[2500 4000 2500 4500 800] + SymbolLine[2500 4500 3000 5000 800] + SymbolLine[3000 5000 3500 5000 800] +) +Symbol['&' 1200] +( + SymbolLine[0 4500 500 5000 800] + SymbolLine[0 1500 0 2500 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[0 3500 1500 2000 800] + SymbolLine[500 5000 1000 5000 800] + SymbolLine[1000 5000 2000 4000 800] + SymbolLine[0 2500 2500 5000 800] + SymbolLine[500 1000 1000 1000 800] + SymbolLine[1000 1000 1500 1500 800] + SymbolLine[1500 1500 1500 2000 800] + SymbolLine[0 3500 0 4500 800] +) +Symbol[''' 1200] +( + SymbolLine[0 2000 1000 1000 800] +) +Symbol['(' 1200] +( + SymbolLine[0 4500 500 5000 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[0 1500 0 4500 800] +) +Symbol[')' 1200] +( + SymbolLine[0 1000 500 1500 800] + SymbolLine[500 1500 500 4500 800] + SymbolLine[0 5000 500 4500 800] +) +Symbol['*' 1200] +( + SymbolLine[0 2000 2000 4000 800] + SymbolLine[0 4000 2000 2000 800] + SymbolLine[0 3000 2000 3000 800] + SymbolLine[1000 2000 1000 4000 800] +) +Symbol['+' 1200] +( + SymbolLine[0 3000 2000 3000 800] + SymbolLine[1000 2000 1000 4000 800] +) +Symbol[',' 1200] +( + SymbolLine[0 6000 1000 5000 800] +) +Symbol['-' 1200] +( + SymbolLine[0 3000 2000 3000 800] +) +Symbol['.' 1200] +( + SymbolLine[0 5000 500 5000 800] +) +Symbol['/' 1200] +( + SymbolLine[0 4500 3000 1500 800] +) +Symbol['0' 1200] +( + SymbolLine[0 4500 500 5000 800] + SymbolLine[0 1500 0 4500 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 1500 1000 800] + SymbolLine[1500 1000 2000 1500 800] + SymbolLine[2000 1500 2000 4500 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[0 4000 2000 2000 800] +) +Symbol['1' 1200] +( + SymbolLine[0 1800 800 1000 800] + SymbolLine[800 1000 800 5000 800] + SymbolLine[0 5000 1500 5000 800] +) +Symbol['2' 1200] +( + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 2000 1000 800] + SymbolLine[2000 1000 2500 1500 800] + SymbolLine[2500 1500 2500 2500 800] + SymbolLine[0 5000 2500 2500 800] + SymbolLine[0 5000 2500 5000 800] +) +Symbol['3' 1200] +( + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 1500 1000 800] + SymbolLine[1500 1000 2000 1500 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[500 2800 1500 2800 800] + SymbolLine[2000 1500 2000 2300 800] + SymbolLine[2000 3300 2000 4500 800] + SymbolLine[2000 3300 1500 2800 800] + SymbolLine[2000 2300 1500 2800 800] +) +Symbol['4' 1200] +( + SymbolLine[0 3500 2000 1000 800] + SymbolLine[0 3500 2500 3500 800] + SymbolLine[2000 1000 2000 5000 800] +) +Symbol['5' 1200] +( + SymbolLine[0 1000 2000 1000 800] + SymbolLine[0 1000 0 3000 800] + SymbolLine[0 3000 500 2500 800] + SymbolLine[500 2500 1500 2500 800] + SymbolLine[1500 2500 2000 3000 800] + SymbolLine[2000 3000 2000 4500 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[0 4500 500 5000 800] +) +Symbol['6' 1200] +( + SymbolLine[1500 1000 2000 1500 800] + SymbolLine[500 1000 1500 1000 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[0 1500 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[1500 2800 2000 3300 800] + SymbolLine[0 2800 1500 2800 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[2000 3300 2000 4500 800] +) +Symbol['7' 1200] +( + SymbolLine[500 5000 2500 1000 800] + SymbolLine[0 1000 2500 1000 800] +) +Symbol['8' 1200] +( + SymbolLine[0 4500 500 5000 800] + SymbolLine[0 3700 0 4500 800] + SymbolLine[0 3700 700 3000 800] + SymbolLine[700 3000 1300 3000 800] + SymbolLine[1300 3000 2000 3700 800] + SymbolLine[2000 3700 2000 4500 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[0 2300 700 3000 800] + SymbolLine[0 1500 0 2300 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 1500 1000 800] + SymbolLine[1500 1000 2000 1500 800] + SymbolLine[2000 1500 2000 2300 800] + SymbolLine[1300 3000 2000 2300 800] +) +Symbol['9' 1200] +( + SymbolLine[500 5000 2000 3000 800] + SymbolLine[2000 1500 2000 3000 800] + SymbolLine[1500 1000 2000 1500 800] + SymbolLine[500 1000 1500 1000 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[0 1500 0 2500 800] + SymbolLine[0 2500 500 3000 800] + SymbolLine[500 3000 2000 3000 800] +) +Symbol[':' 1200] +( + SymbolLine[0 2500 500 2500 800] + SymbolLine[0 3500 500 3500 800] +) +Symbol[';' 1200] +( + SymbolLine[0 5000 1000 4000 800] + SymbolLine[1000 2500 1000 3000 800] +) +Symbol['<' 1200] +( + SymbolLine[0 3000 1000 2000 800] + SymbolLine[0 3000 1000 4000 800] +) +Symbol['=' 1200] +( + SymbolLine[0 2500 2000 2500 800] + SymbolLine[0 3500 2000 3500 800] +) +Symbol['>' 1200] +( + SymbolLine[0 2000 1000 3000 800] + SymbolLine[0 4000 1000 3000 800] +) +Symbol['?' 1200] +( + SymbolLine[1000 3000 1000 3500 800] + SymbolLine[1000 4500 1000 5000 800] + SymbolLine[0 1500 0 2000 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 1500 1000 800] + SymbolLine[1500 1000 2000 1500 800] + SymbolLine[2000 1500 2000 2000 800] + SymbolLine[1000 3000 2000 2000 800] +) +Symbol['@' 1200] +( + SymbolLine[0 1000 0 4000 800] + SymbolLine[0 4000 1000 5000 800] + SymbolLine[1000 5000 4000 5000 800] + SymbolLine[5000 3500 5000 1000 800] + SymbolLine[5000 1000 4000 0 800] + SymbolLine[4000 0 1000 0 800] + SymbolLine[1000 0 0 1000 800] + SymbolLine[1500 2000 1500 3000 800] + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[2000 3500 3000 3500 800] + SymbolLine[3000 3500 3500 3000 800] + SymbolLine[3500 3000 4000 3500 800] + SymbolLine[3500 3000 3500 1500 800] + SymbolLine[3500 2000 3000 1500 800] + SymbolLine[2000 1500 3000 1500 800] + SymbolLine[2000 1500 1500 2000 800] + SymbolLine[4000 3500 5000 3500 800] +) +Symbol['A' 1200] +( + SymbolLine[0 2000 0 5000 800] + SymbolLine[0 2000 700 1000 800] + SymbolLine[700 1000 1800 1000 800] + SymbolLine[1800 1000 2500 2000 800] + SymbolLine[2500 2000 2500 5000 800] + SymbolLine[0 3000 2500 3000 800] +) +Symbol['B' 1200] +( + SymbolLine[0 5000 2000 5000 800] + SymbolLine[2000 5000 2500 4500 800] + SymbolLine[2500 3300 2500 4500 800] + SymbolLine[2000 2800 2500 3300 800] + SymbolLine[500 2800 2000 2800 800] + SymbolLine[500 1000 500 5000 800] + SymbolLine[0 1000 2000 1000 800] + SymbolLine[2000 1000 2500 1500 800] + SymbolLine[2500 1500 2500 2300 800] + SymbolLine[2000 2800 2500 2300 800] +) +Symbol['C' 1200] +( + SymbolLine[700 5000 2000 5000 800] + SymbolLine[0 4300 700 5000 800] + SymbolLine[0 1700 0 4300 800] + SymbolLine[0 1700 700 1000 800] + SymbolLine[700 1000 2000 1000 800] +) +Symbol['D' 1200] +( + SymbolLine[500 1000 500 5000 800] + SymbolLine[1800 1000 2500 1700 800] + SymbolLine[2500 1700 2500 4300 800] + SymbolLine[1800 5000 2500 4300 800] + SymbolLine[0 5000 1800 5000 800] + SymbolLine[0 1000 1800 1000 800] +) +Symbol['E' 1200] +( + SymbolLine[0 2800 1500 2800 800] + SymbolLine[0 5000 2000 5000 800] + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 1000 2000 1000 800] +) +Symbol['F' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 1000 2000 1000 800] + SymbolLine[0 2800 1500 2800 800] +) +Symbol['G' 1200] +( + SymbolLine[2000 1000 2500 1500 800] + SymbolLine[500 1000 2000 1000 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[0 1500 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[500 5000 2000 5000 800] + SymbolLine[2000 5000 2500 4500 800] + SymbolLine[2500 3500 2500 4500 800] + SymbolLine[2000 3000 2500 3500 800] + SymbolLine[1000 3000 2000 3000 800] +) +Symbol['H' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[2500 1000 2500 5000 800] + SymbolLine[0 3000 2500 3000 800] +) +Symbol['I' 1200] +( + SymbolLine[0 1000 1000 1000 800] + SymbolLine[500 1000 500 5000 800] + SymbolLine[0 5000 1000 5000 800] +) +Symbol['J' 1200] +( + SymbolLine[700 1000 1500 1000 800] + SymbolLine[1500 1000 1500 4500 800] + SymbolLine[1000 5000 1500 4500 800] + SymbolLine[500 5000 1000 5000 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[0 4500 0 4000 800] +) +Symbol['K' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 3000 2000 1000 800] + SymbolLine[0 3000 2000 5000 800] +) +Symbol['L' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 5000 2000 5000 800] +) +Symbol['M' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 1000 1500 3000 800] + SymbolLine[1500 3000 3000 1000 800] + SymbolLine[3000 1000 3000 5000 800] +) +Symbol['N' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 1000 2500 5000 800] + SymbolLine[2500 1000 2500 5000 800] +) +Symbol['O' 1200] +( + SymbolLine[0 1500 0 4500 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 1500 1000 800] + SymbolLine[1500 1000 2000 1500 800] + SymbolLine[2000 1500 2000 4500 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[0 4500 500 5000 800] +) +Symbol['P' 1200] +( + SymbolLine[500 1000 500 5000 800] + SymbolLine[0 1000 2000 1000 800] + SymbolLine[2000 1000 2500 1500 800] + SymbolLine[2500 1500 2500 2500 800] + SymbolLine[2000 3000 2500 2500 800] + SymbolLine[500 3000 2000 3000 800] +) +Symbol['Q' 1200] +( + SymbolLine[0 1500 0 4500 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 1500 1000 800] + SymbolLine[1500 1000 2000 1500 800] + SymbolLine[2000 1500 2000 4000 800] + SymbolLine[1000 5000 2000 4000 800] + SymbolLine[500 5000 1000 5000 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[1000 3500 2000 5000 800] +) +Symbol['R' 1200] +( + SymbolLine[0 1000 2000 1000 800] + SymbolLine[2000 1000 2500 1500 800] + SymbolLine[2500 1500 2500 2500 800] + SymbolLine[2000 3000 2500 2500 800] + SymbolLine[500 3000 2000 3000 800] + SymbolLine[500 1000 500 5000 800] + SymbolLine[1300 3000 2500 5000 800] +) +Symbol['S' 1200] +( + SymbolLine[2000 1000 2500 1500 800] + SymbolLine[500 1000 2000 1000 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[0 1500 0 2500 800] + SymbolLine[0 2500 500 3000 800] + SymbolLine[500 3000 2000 3000 800] + SymbolLine[2000 3000 2500 3500 800] + SymbolLine[2500 3500 2500 4500 800] + SymbolLine[2000 5000 2500 4500 800] + SymbolLine[500 5000 2000 5000 800] + SymbolLine[0 4500 500 5000 800] +) +Symbol['T' 1200] +( + SymbolLine[0 1000 2000 1000 800] + SymbolLine[1000 1000 1000 5000 800] +) +Symbol['U' 1200] +( + SymbolLine[0 1000 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[2000 1000 2000 4500 800] +) +Symbol['V' 1200] +( + SymbolLine[0 1000 1000 5000 800] + SymbolLine[1000 5000 2000 1000 800] +) +Symbol['W' 1200] +( + SymbolLine[0 1000 0 3000 800] + SymbolLine[0 3000 500 5000 800] + SymbolLine[500 5000 1500 3000 800] + SymbolLine[1500 3000 2500 5000 800] + SymbolLine[2500 5000 3000 3000 800] + SymbolLine[3000 3000 3000 1000 800] +) +Symbol['X' 1200] +( + SymbolLine[0 5000 2500 1000 800] + SymbolLine[0 1000 2500 5000 800] +) +Symbol['Y' 1200] +( + SymbolLine[0 1000 1000 3000 800] + SymbolLine[1000 3000 2000 1000 800] + SymbolLine[1000 3000 1000 5000 800] +) +Symbol['Z' 1200] +( + SymbolLine[0 1000 2500 1000 800] + SymbolLine[0 5000 2500 1000 800] + SymbolLine[0 5000 2500 5000 800] +) +Symbol['[' 1200] +( + SymbolLine[0 1000 500 1000 800] + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 5000 500 5000 800] +) +Symbol['\' 1200] +( + SymbolLine[0 1500 3000 4500 800] +) +Symbol[']' 1200] +( + SymbolLine[0 1000 500 1000 800] + SymbolLine[500 1000 500 5000 800] + SymbolLine[0 5000 500 5000 800] +) +Symbol['^' 1200] +( + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 1000 1500 800] +) +Symbol['_' 1200] +( + SymbolLine[0 5000 2000 5000 800] +) +Symbol['a' 1200] +( + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[500 3000 1500 3000 800] + SymbolLine[0 3500 500 3000 800] + SymbolLine[0 3500 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[2000 3000 2000 4500 800] + SymbolLine[2000 4500 2500 5000 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[1500 5000 2000 4500 800] +) +Symbol['b' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[2000 3500 2000 4500 800] + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[500 3000 1500 3000 800] + SymbolLine[0 3500 500 3000 800] +) +Symbol['c' 1200] +( + SymbolLine[500 3000 2000 3000 800] + SymbolLine[0 3500 500 3000 800] + SymbolLine[0 3500 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[500 5000 2000 5000 800] +) +Symbol['d' 1200] +( + SymbolLine[2000 1000 2000 5000 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[0 3500 0 4500 800] + SymbolLine[0 3500 500 3000 800] + SymbolLine[500 3000 1500 3000 800] + SymbolLine[1500 3000 2000 3500 800] +) +Symbol['e' 1200] +( + SymbolLine[500 5000 2000 5000 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[0 3500 0 4500 800] + SymbolLine[0 3500 500 3000 800] + SymbolLine[500 3000 1500 3000 800] + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[0 4000 2000 4000 800] + SymbolLine[2000 4000 2000 3500 800] +) +Symbol['f' 1000] +( + SymbolLine[500 1500 500 5000 800] + SymbolLine[500 1500 1000 1000 800] + SymbolLine[1000 1000 1500 1000 800] + SymbolLine[0 3000 1000 3000 800] +) +Symbol['g' 1200] +( + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[500 3000 1500 3000 800] + SymbolLine[0 3500 500 3000 800] + SymbolLine[0 3500 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[0 6000 500 6500 800] + SymbolLine[500 6500 1500 6500 800] + SymbolLine[1500 6500 2000 6000 800] + SymbolLine[2000 3000 2000 6000 800] +) +Symbol['h' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 3500 500 3000 800] + SymbolLine[500 3000 1500 3000 800] + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[2000 3500 2000 5000 800] +) +Symbol['i' 1000] +( + SymbolLine[0 2000 0 2100 1000] + SymbolLine[0 3500 0 5000 800] +) +Symbol['j' 1000] +( + SymbolLine[500 2000 500 2100 1000] + SymbolLine[500 3500 500 6000 800] + SymbolLine[0 6500 500 6000 800] +) +Symbol['k' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 3500 1500 5000 800] + SymbolLine[0 3500 1000 2500 800] +) +Symbol['l' 1000] +( + SymbolLine[0 1000 0 4500 800] + SymbolLine[0 4500 500 5000 800] +) +Symbol['m' 1200] +( + SymbolLine[500 3500 500 5000 800] + SymbolLine[500 3500 1000 3000 800] + SymbolLine[1000 3000 1500 3000 800] + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[2000 3500 2000 5000 800] + SymbolLine[2000 3500 2500 3000 800] + SymbolLine[2500 3000 3000 3000 800] + SymbolLine[3000 3000 3500 3500 800] + SymbolLine[3500 3500 3500 5000 800] + SymbolLine[0 3000 500 3500 800] +) +Symbol['n' 1200] +( + SymbolLine[500 3500 500 5000 800] + SymbolLine[500 3500 1000 3000 800] + SymbolLine[1000 3000 1500 3000 800] + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[2000 3500 2000 5000 800] + SymbolLine[0 3000 500 3500 800] +) +Symbol['o' 1200] +( + SymbolLine[0 3500 0 4500 800] + SymbolLine[0 3500 500 3000 800] + SymbolLine[500 3000 1500 3000 800] + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[2000 3500 2000 4500 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[0 4500 500 5000 800] +) +Symbol['p' 1200] +( + SymbolLine[500 3500 500 6500 800] + SymbolLine[0 3000 500 3500 800] + SymbolLine[500 3500 1000 3000 800] + SymbolLine[1000 3000 2000 3000 800] + SymbolLine[2000 3000 2500 3500 800] + SymbolLine[2500 3500 2500 4500 800] + SymbolLine[2000 5000 2500 4500 800] + SymbolLine[1000 5000 2000 5000 800] + SymbolLine[500 4500 1000 5000 800] +) +Symbol['q' 1200] +( + SymbolLine[2000 3500 2000 6500 800] + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[500 3000 1500 3000 800] + SymbolLine[0 3500 500 3000 800] + SymbolLine[0 3500 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[1500 5000 2000 4500 800] +) +Symbol['r' 1200] +( + SymbolLine[500 3500 500 5000 800] + SymbolLine[500 3500 1000 3000 800] + SymbolLine[1000 3000 2000 3000 800] + SymbolLine[0 3000 500 3500 800] +) +Symbol['s' 1200] +( + SymbolLine[500 5000 2000 5000 800] + SymbolLine[2000 5000 2500 4500 800] + SymbolLine[2000 4000 2500 4500 800] + SymbolLine[500 4000 2000 4000 800] + SymbolLine[0 3500 500 4000 800] + SymbolLine[0 3500 500 3000 800] + SymbolLine[500 3000 2000 3000 800] + SymbolLine[2000 3000 2500 3500 800] + SymbolLine[0 4500 500 5000 800] +) +Symbol['t' 1000] +( + SymbolLine[500 1000 500 4500 800] + SymbolLine[500 4500 1000 5000 800] + SymbolLine[0 2500 1000 2500 800] +) +Symbol['u' 1200] +( + SymbolLine[0 3000 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[2000 3000 2000 4500 800] +) +Symbol['v' 1200] +( + SymbolLine[0 3000 1000 5000 800] + SymbolLine[2000 3000 1000 5000 800] +) +Symbol['w' 1200] +( + SymbolLine[0 3000 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[500 5000 1000 5000 800] + SymbolLine[1000 5000 1500 4500 800] + SymbolLine[1500 3000 1500 4500 800] + SymbolLine[1500 4500 2000 5000 800] + SymbolLine[2000 5000 2500 5000 800] + SymbolLine[2500 5000 3000 4500 800] + SymbolLine[3000 3000 3000 4500 800] +) +Symbol['x' 1200] +( + SymbolLine[0 3000 2000 5000 800] + SymbolLine[0 5000 2000 3000 800] +) +Symbol['y' 1200] +( + SymbolLine[0 3000 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[2000 3000 2000 6000 800] + SymbolLine[1500 6500 2000 6000 800] + SymbolLine[500 6500 1500 6500 800] + SymbolLine[0 6000 500 6500 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[1500 5000 2000 4500 800] +) +Symbol['z' 1200] +( + SymbolLine[0 3000 2000 3000 800] + SymbolLine[0 5000 2000 3000 800] + SymbolLine[0 5000 2000 5000 800] +) +Symbol['{' 1200] +( + SymbolLine[500 1500 1000 1000 800] + SymbolLine[500 1500 500 2500 800] + SymbolLine[0 3000 500 2500 800] + SymbolLine[0 3000 500 3500 800] + SymbolLine[500 3500 500 4500 800] + SymbolLine[500 4500 1000 5000 800] +) +Symbol['|' 1200] +( + SymbolLine[0 1000 0 5000 800] +) +Symbol['}' 1200] +( + SymbolLine[0 1000 500 1500 800] + SymbolLine[500 1500 500 2500 800] + SymbolLine[500 2500 1000 3000 800] + SymbolLine[500 3500 1000 3000 800] + SymbolLine[500 3500 500 4500 800] + SymbolLine[0 5000 500 4500 800] +) +Symbol['~' 1200] +( + SymbolLine[0 3500 500 3000 800] + SymbolLine[500 3000 1000 3000 800] + SymbolLine[1000 3000 1500 3500 800] + SymbolLine[1500 3500 2000 3500 800] + SymbolLine[2000 3500 2500 3000 800] +) +Attribute("PCB::grid::unit" "mil") +Via[270000 240000 7874 4000 0 3150 "" ""] + +Element["" "Crystals" "" "HC49U_3" 30000 50000 -15100 12100 1 100 ""] +( + Pin[0 0 6000 3000 6600 3200 "1" "1" "square"] + Pin[0 -9600 6000 3000 6600 3200 "2" "2" ""] + Pin[0 -19200 6000 3000 6600 3200 "3" "3" ""] + ElementLine [-9100 -22300 -9100 3000 2000] + ElementLine [9200 -22300 9200 3000 2000] + ElementArc [0 -22300 9100 9100 180 180 2000] + ElementArc [0 3000 9100 9100 0 180 2000] + + ) + +Element["" "Crystals" "" "HC49U_3H" 110000 50000 -67500 12100 1 100 ""] +( + Pin[0 0 6000 3000 6600 3200 "1" "1" "square,edge2"] + Pin[0 -9600 6000 3000 6600 3200 "2" "2" "edge2"] + Pin[0 -19200 6000 3000 6600 3200 "3" "3" "edge2"] + ElementLine [-61500 -31400 -61500 12100 2000] + ElementLine [-61500 -31400 -10000 -31400 2000] + ElementLine [-10000 -31400 -10000 12100 2000] + ElementLine [-61500 12100 -10000 12100 2000] + + ) + +Element["" "Transistor" "" "TO126" 140000 220000 -2000 -12000 1 100 ""] +( + Pin[1000 0 8000 3000 8600 5200 "1" "1" "square"] + Pin[10000 0 8000 3000 8600 5200 "2" "2" ""] + Pin[19000 0 8000 3000 8600 5200 "3" "3" ""] + Pin[10000 -43000 13000 3000 13600 11000 "4" "4" ""] + ElementLine [0 -10000 0 0 3000] + ElementLine [10000 -10000 10000 0 3000] + ElementLine [20000 -10000 20000 0 3000] + ElementLine [-5000 -10000 25000 -10000 2000] + ElementLine [25000 -53000 25000 -10000 2000] + ElementLine [-5000 -53000 25000 -53000 2000] + ElementLine [-5000 -53000 -5000 -10000 2000] + + ) + +Element["" "Transistor" "" "TO126S" 199000 220000 -2000 -12000 1 100 ""] +( + Pin[1000 0 8000 3000 8600 5200 "1" "1" "square"] + Pin[10000 10000 8000 3000 8600 5200 "2" "2" ""] + Pin[19000 0 8000 3000 8600 5200 "3" "3" ""] + Pin[10000 -43000 13000 3000 13600 11000 "4" "4" ""] + ElementLine [0 -10000 0 0 3000] + ElementLine [10000 -10000 10000 10000 3000] + ElementLine [20000 -10000 20000 0 3000] + ElementLine [-5000 -10000 25000 -10000 2000] + ElementLine [25000 -53000 25000 -10000 2000] + ElementLine [-5000 -53000 25000 -53000 2000] + ElementLine [-5000 -53000 -5000 -10000 2000] + + ) + +Element["" "Transistor" "" "TO126SW" 40000 110000 7000 -17000 1 100 ""] +( + Pin[0 -1000 8000 3000 8600 5200 "1" "1" "square"] + Pin[10000 -10000 8000 3000 8600 5200 "2" "2" ""] + Pin[0 -19000 8000 3000 8600 5200 "3" "3" ""] + ElementLine [5000 -10000 10000 -10000 3000] + ElementLine [-5000 -25000 -5000 5000 2000] + ElementLine [-5000 -25000 5000 -25000 2000] + ElementLine [5000 -25000 5000 5000 2000] + ElementLine [-5000 5000 5000 5000 2000] + ElementLine [-5000 -5000 5000 -5000 1000] + ElementLine [-5000 -15000 5000 -15000 1000] + + ) + +Element["" "Transistor" "" "TO126W" 70000 110000 7000 4000 1 100 ""] +( + Pin[0 -1000 8000 3000 8600 5200 "1" "1" "square"] + Pin[0 -10000 8000 3000 8600 5200 "2" "2" ""] + Pin[0 -19000 8000 3000 8600 5200 "3" "3" ""] + ElementLine [-5000 -25000 -5000 5000 2000] + ElementLine [-5000 -25000 5000 -25000 2000] + ElementLine [5000 -25000 5000 5000 2000] + ElementLine [-5000 5000 5000 5000 2000] + + ) + +Element["" "Transistor" "" "TO18" 165000 30000 6000 7000 0 100 ""] +( + Pin[0 -5000 5500 3000 6100 3500 "1" "1" ""] + Pin[-5000 0 5500 3000 6100 3500 "2" "2" ""] + Pin[0 5000 5500 3000 6100 3500 "3" "3" ""] + ElementLine [6700 -7900 9400 -10600 1000] + ElementLine [7300 -7300 10000 -10000 1000] + ElementLine [7900 -6700 10600 -9400 1000] + ElementLine [9400 -10600 10600 -9400 1000] + ElementArc [0 0 9800 9800 0 360 1000] + + ) + +Element["" "diode in TO220" "" "TO218" 224000 121900 -21000 -58700 0 100 ""] +( + Pin[-14000 0 10000 3000 10600 6000 "1" "1" "square"] + Pin[-14000 -21900 10000 3000 10600 6000 "2" "2" ""] + Pin[-14000 -43800 10000 3000 10600 6000 "3" "3" ""] + ElementLine [-26000 8800 -6000 8800 2000] + ElementLine [-6000 -52700 -6000 8800 2000] + ElementLine [-26000 -52700 -6000 -52700 2000] + ElementLine [-26000 -52700 -26000 8800 2000] + ElementLine [-21000 -52700 -21000 8800 1000] + ElementLine [-26000 -14400 -21000 -14400 1000] + ElementLine [-26000 -29400 -21000 -29400 1000] + + ) + +Element["" "Transistor" "" "TO220" 90000 220000 -15000 -23000 1 100 ""] +( + Pin[-10000 0 9000 3000 9600 6000 "1" "1" "square"] + Pin[0 0 9000 3000 9600 6000 "2" "2" ""] + Pin[10000 0 9000 3000 9600 6000 "3" "3" ""] + Pin[0 -67000 15000 3000 15600 13000 "4" "4" ""] + ElementLine [-10000 -18000 -10000 0 3000] + ElementLine [0 -18000 0 0 3000] + ElementLine [10000 -18000 10000 0 3000] + ElementLine [-20000 -18000 20000 -18000 2000] + ElementLine [20000 -55500 20000 -18000 2000] + ElementLine [-20000 -55500 20000 -55500 2000] + ElementLine [-20000 -55500 -20000 -18000 2000] + ElementLine [-20000 -55500 20000 -55500 2000] + ElementLine [20000 -68000 20000 -55500 2000] + ElementLine [18500 -68000 20000 -68000 2000] + ElementLine [18500 -75000 18500 -68000 2000] + ElementLine [18500 -75000 20000 -75000 2000] + ElementLine [20000 -79000 20000 -75000 2000] + ElementLine [-20000 -79000 20000 -79000 2000] + ElementLine [-20000 -79000 -20000 -75000 2000] + ElementLine [-20000 -75000 -18500 -75000 2000] + ElementLine [-18500 -75000 -18500 -68000 2000] + ElementLine [-20000 -68000 -18500 -68000 2000] + ElementLine [-20000 -68000 -20000 -55500 2000] + + ) + +Element["" "Transistor" "" "TO220S" 30000 220000 -15000 -23000 1 100 ""] +( + Pin[-10000 0 9000 3000 9600 6000 "1" "1" "square"] + Pin[0 10000 9000 3000 9600 6000 "2" "2" ""] + Pin[10000 0 9000 3000 9600 6000 "3" "3" ""] + Pin[0 -67000 15000 3000 15600 13000 "4" "4" ""] + ElementLine [-10000 -18000 -10000 0 3000] + ElementLine [0 -18000 0 10000 3000] + ElementLine [10000 -18000 10000 0 3000] + ElementLine [-20000 -18000 20000 -18000 2000] + ElementLine [20000 -55500 20000 -18000 2000] + ElementLine [-20000 -55500 20000 -55500 2000] + ElementLine [-20000 -55500 -20000 -18000 2000] + ElementLine [-20000 -55500 20000 -55500 2000] + ElementLine [20000 -68000 20000 -55500 2000] + ElementLine [18500 -68000 20000 -68000 2000] + ElementLine [18500 -75000 18500 -68000 2000] + ElementLine [18500 -75000 20000 -75000 2000] + ElementLine [20000 -79000 20000 -75000 2000] + ElementLine [-20000 -79000 20000 -79000 2000] + ElementLine [-20000 -79000 -20000 -75000 2000] + ElementLine [-20000 -75000 -18500 -75000 2000] + ElementLine [-18500 -75000 -18500 -68000 2000] + ElementLine [-20000 -68000 -18500 -68000 2000] + ElementLine [-20000 -68000 -20000 -55500 2000] + + ) + +Element["" "Transistor" "" "TO220SW" 130000 110000 -19000 10000 1 100 ""] +( + Pin[0 0 9000 3000 9600 6000 "1" "1" "square"] + Pin[10000 -10000 9000 3000 9600 6000 "2" "2" ""] + Pin[0 -20000 9000 3000 9600 6000 "3" "3" ""] + ElementLine [-12000 -30000 -12000 10000 2000] + ElementLine [-12000 -30000 6000 -30000 2000] + ElementLine [6000 -30000 6000 10000 2000] + ElementLine [-12000 10000 6000 10000 2000] + ElementLine [-12000 -30000 -12000 10000 2000] + ElementLine [-12000 -30000 -6000 -30000 2000] + ElementLine [-6000 -30000 -6000 10000 2000] + ElementLine [-12000 10000 -6000 10000 2000] + ElementLine [-12000 -3000 -6000 -3000 1000] + ElementLine [-12000 -17000 -6000 -17000 1000] + ElementLine [6000 -10000 10000 -10000 3000] + + ) + +Element["" "Transistor" "" "TO220W" 100000 110000 -19000 10000 1 100 ""] +( + Pin[0 0 9000 3000 9600 6000 "1" "1" "square"] + Pin[0 -10000 9000 3000 9600 6000 "2" "2" ""] + Pin[0 -20000 9000 3000 9600 6000 "3" "3" ""] + ElementLine [-12000 -30000 -12000 10000 2000] + ElementLine [-12000 -30000 6000 -30000 2000] + ElementLine [6000 -30000 6000 10000 2000] + ElementLine [-12000 10000 6000 10000 2000] + ElementLine [-12000 -30000 -12000 10000 2000] + ElementLine [-12000 -30000 -6000 -30000 2000] + ElementLine [-6000 -30000 -6000 10000 2000] + ElementLine [-12000 10000 -6000 10000 2000] + ElementLine [-12000 -3000 -6000 -3000 1000] + ElementLine [-12000 -17000 -6000 -17000 1000] + + ) + +Element["" "diode in TO220" "" "TO247" 184000 121900 -22000 -59400 0 100 ""] +( + Pin[-14000 0 10000 3000 10600 6000 "1" "1" "square"] + Pin[-14000 -21900 10000 3000 10600 6000 "2" "2" ""] + Pin[-14000 -43800 10000 3000 10600 6000 "3" "3" ""] + ElementLine [-27000 9600 -6000 9600 2000] + ElementLine [-6000 -53400 -6000 9600 2000] + ElementLine [-27000 -53400 -6000 -53400 2000] + ElementLine [-27000 -53400 -27000 9600 2000] + ElementLine [-22000 -53400 -22000 9600 1000] + ElementLine [-27000 -14400 -22000 -14400 1000] + ElementLine [-27000 -29400 -22000 -29400 1000] + + ) + +Element["" "diode in TO220" "" "TO251" 19000 109000 -9000 -28300 0 100 ""] +( + Pin[-9000 0 7000 3000 7600 4000 "1" "1" "square"] + Pin[-9000 -9000 7000 3000 7600 4000 "2" "2" ""] + Pin[-9000 -18000 7000 3000 7600 4000 "3" "3" ""] + ElementLine [-14000 4200 -4000 4200 2000] + ElementLine [-4000 -22300 -4000 4200 2000] + ElementLine [-14000 -22300 -4000 -22300 2000] + ElementLine [-14000 -22300 -14000 4200 2000] + ElementLine [-9000 -22300 -9000 4200 1000] + ElementLine [-14000 -1500 -9000 -1500 1000] + ElementLine [-14000 -16500 -9000 -16500 1000] + + ) + +Element["" "diode in TO220" "" "TO264" 264000 121900 -22000 -67900 0 100 ""] +( + Pin[-14000 0 10000 3000 10600 6000 "1" "1" "square"] + Pin[-14000 -21900 10000 3000 10600 6000 "2" "2" ""] + Pin[-14000 -43800 10000 3000 10600 6000 "3" "3" ""] + ElementLine [-27000 18100 -6000 18100 2000] + ElementLine [-6000 -61900 -6000 18100 2000] + ElementLine [-27000 -61900 -6000 -61900 2000] + ElementLine [-27000 -61900 -27000 18100 2000] + ElementLine [-22000 -61900 -22000 18100 1000] + ElementLine [-27000 -14400 -22000 -14400 1000] + ElementLine [-27000 -29400 -22000 -29400 1000] + + ) + +Element["" "Transistor" "" "TO39" 210000 30000 6000 7000 0 100 ""] +( + Pin[0 -10000 5500 3000 6100 3500 "1" "1" "square"] + Pin[-10000 0 5500 3000 6100 3500 "2" "2" ""] + Pin[0 10000 5500 3000 6100 3500 "3" "3" ""] + ElementLine [12700 -13900 14800 -16000 1000] + ElementLine [13300 -13300 15400 -15400 1000] + ElementLine [13900 -12700 16000 -14800 1000] + ElementLine [16000 -14800 14800 -16000 1000] + ElementArc [0 0 18300 18300 0 360 1000] + + ) + +Element["" "Transistor" "" "TO92" 250000 40000 -13000 -1000 1 100 ""] +( + Pin[0 -20000 7200 3000 7800 4200 "1" "1" "square"] + Pin[0 -10000 7200 3000 7800 4200 "2" "2" ""] + Pin[0 0 7200 3000 7800 4200 "3" "3" ""] + ElementLine [-7000 -17000 -7000 -3000 1000] + ElementArc [0 -10000 10000 10000 45 270 1000] + + ) +Layer(1 "component") +( +) +Layer(2 "solder") +( +) +Layer(3 "comp-GND") +( +) +Layer(4 "comp-power") +( +) +Layer(5 "sold-GND") +( +) +Layer(6 "sold-power") +( +) +Layer(7 "signal3") +( +) +Layer(8 "outline") +( +) +Layer(9 "silk") +( +) +Layer(10 "silk") +( + Line[0 70000 150000 70000 1000 4000 "clearline"] + Line[150000 70000 150000 0 1000 4000 "clearline"] + Text[130000 30000 0 200 "HC" "clearline"] + Text[250000 190000 0 200 "TO" "clearline"] +) Index: tags/2.1.2/util/pcblib-map/trhN.pcb =================================================================== --- tags/2.1.2/util/pcblib-map/trhN.pcb (nonexistent) +++ tags/2.1.2/util/pcblib-map/trhN.pcb (revision 24813) @@ -0,0 +1,983 @@ +# release: pcb 20110918 + +# To read pcb files, the pcb version (or the git source date) must be >= the file version +FileVersion[20070407] + +PCB["" 220000 170000] + +Grid[10000.0 0 0 1] +Cursor[0 0 0.000000] +PolyArea[3100.006200] +Thermal[0.500000] +DRC[1200 900 1000 700 1500 1000] +Flags("nameonpcb,clearnew,snappin") +Groups("1,3,4,c:2,5,6,s:7:8") +Styles["Signal,1000,7874,3150,2000:Power,2000,8661,3937,2000:Fat,8000,13780,4724,2500:Sig-tight,1000,6400,3150,1200"] + +Symbol[' ' 1800] +( +) +Symbol['!' 1200] +( + SymbolLine[0 4500 0 5000 800] + SymbolLine[0 1000 0 3500 800] +) +Symbol['"' 1200] +( + SymbolLine[0 1000 0 2000 800] + SymbolLine[1000 1000 1000 2000 800] +) +Symbol['#' 1200] +( + SymbolLine[0 3500 2000 3500 800] + SymbolLine[0 2500 2000 2500 800] + SymbolLine[1500 2000 1500 4000 800] + SymbolLine[500 2000 500 4000 800] +) +Symbol['$' 1200] +( + SymbolLine[1500 1500 2000 2000 800] + SymbolLine[500 1500 1500 1500 800] + SymbolLine[0 2000 500 1500 800] + SymbolLine[0 2000 0 2500 800] + SymbolLine[0 2500 500 3000 800] + SymbolLine[500 3000 1500 3000 800] + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[2000 3500 2000 4000 800] + SymbolLine[1500 4500 2000 4000 800] + SymbolLine[500 4500 1500 4500 800] + SymbolLine[0 4000 500 4500 800] + SymbolLine[1000 1000 1000 5000 800] +) +Symbol['%' 1200] +( + SymbolLine[0 1500 0 2000 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 1000 1000 800] + SymbolLine[1000 1000 1500 1500 800] + SymbolLine[1500 1500 1500 2000 800] + SymbolLine[1000 2500 1500 2000 800] + SymbolLine[500 2500 1000 2500 800] + SymbolLine[0 2000 500 2500 800] + SymbolLine[0 5000 4000 1000 800] + SymbolLine[3500 5000 4000 4500 800] + SymbolLine[4000 4000 4000 4500 800] + SymbolLine[3500 3500 4000 4000 800] + SymbolLine[3000 3500 3500 3500 800] + SymbolLine[2500 4000 3000 3500 800] + SymbolLine[2500 4000 2500 4500 800] + SymbolLine[2500 4500 3000 5000 800] + SymbolLine[3000 5000 3500 5000 800] +) +Symbol['&' 1200] +( + SymbolLine[0 4500 500 5000 800] + SymbolLine[0 1500 0 2500 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[0 3500 1500 2000 800] + SymbolLine[500 5000 1000 5000 800] + SymbolLine[1000 5000 2000 4000 800] + SymbolLine[0 2500 2500 5000 800] + SymbolLine[500 1000 1000 1000 800] + SymbolLine[1000 1000 1500 1500 800] + SymbolLine[1500 1500 1500 2000 800] + SymbolLine[0 3500 0 4500 800] +) +Symbol[''' 1200] +( + SymbolLine[0 2000 1000 1000 800] +) +Symbol['(' 1200] +( + SymbolLine[0 4500 500 5000 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[0 1500 0 4500 800] +) +Symbol[')' 1200] +( + SymbolLine[0 1000 500 1500 800] + SymbolLine[500 1500 500 4500 800] + SymbolLine[0 5000 500 4500 800] +) +Symbol['*' 1200] +( + SymbolLine[0 2000 2000 4000 800] + SymbolLine[0 4000 2000 2000 800] + SymbolLine[0 3000 2000 3000 800] + SymbolLine[1000 2000 1000 4000 800] +) +Symbol['+' 1200] +( + SymbolLine[0 3000 2000 3000 800] + SymbolLine[1000 2000 1000 4000 800] +) +Symbol[',' 1200] +( + SymbolLine[0 6000 1000 5000 800] +) +Symbol['-' 1200] +( + SymbolLine[0 3000 2000 3000 800] +) +Symbol['.' 1200] +( + SymbolLine[0 5000 500 5000 800] +) +Symbol['/' 1200] +( + SymbolLine[0 4500 3000 1500 800] +) +Symbol['0' 1200] +( + SymbolLine[0 4500 500 5000 800] + SymbolLine[0 1500 0 4500 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 1500 1000 800] + SymbolLine[1500 1000 2000 1500 800] + SymbolLine[2000 1500 2000 4500 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[0 4000 2000 2000 800] +) +Symbol['1' 1200] +( + SymbolLine[0 1800 800 1000 800] + SymbolLine[800 1000 800 5000 800] + SymbolLine[0 5000 1500 5000 800] +) +Symbol['2' 1200] +( + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 2000 1000 800] + SymbolLine[2000 1000 2500 1500 800] + SymbolLine[2500 1500 2500 2500 800] + SymbolLine[0 5000 2500 2500 800] + SymbolLine[0 5000 2500 5000 800] +) +Symbol['3' 1200] +( + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 1500 1000 800] + SymbolLine[1500 1000 2000 1500 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[500 2800 1500 2800 800] + SymbolLine[2000 1500 2000 2300 800] + SymbolLine[2000 3300 2000 4500 800] + SymbolLine[2000 3300 1500 2800 800] + SymbolLine[2000 2300 1500 2800 800] +) +Symbol['4' 1200] +( + SymbolLine[0 3500 2000 1000 800] + SymbolLine[0 3500 2500 3500 800] + SymbolLine[2000 1000 2000 5000 800] +) +Symbol['5' 1200] +( + SymbolLine[0 1000 2000 1000 800] + SymbolLine[0 1000 0 3000 800] + SymbolLine[0 3000 500 2500 800] + SymbolLine[500 2500 1500 2500 800] + SymbolLine[1500 2500 2000 3000 800] + SymbolLine[2000 3000 2000 4500 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[0 4500 500 5000 800] +) +Symbol['6' 1200] +( + SymbolLine[1500 1000 2000 1500 800] + SymbolLine[500 1000 1500 1000 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[0 1500 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[1500 2800 2000 3300 800] + SymbolLine[0 2800 1500 2800 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[2000 3300 2000 4500 800] +) +Symbol['7' 1200] +( + SymbolLine[500 5000 2500 1000 800] + SymbolLine[0 1000 2500 1000 800] +) +Symbol['8' 1200] +( + SymbolLine[0 4500 500 5000 800] + SymbolLine[0 3700 0 4500 800] + SymbolLine[0 3700 700 3000 800] + SymbolLine[700 3000 1300 3000 800] + SymbolLine[1300 3000 2000 3700 800] + SymbolLine[2000 3700 2000 4500 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[0 2300 700 3000 800] + SymbolLine[0 1500 0 2300 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 1500 1000 800] + SymbolLine[1500 1000 2000 1500 800] + SymbolLine[2000 1500 2000 2300 800] + SymbolLine[1300 3000 2000 2300 800] +) +Symbol['9' 1200] +( + SymbolLine[500 5000 2000 3000 800] + SymbolLine[2000 1500 2000 3000 800] + SymbolLine[1500 1000 2000 1500 800] + SymbolLine[500 1000 1500 1000 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[0 1500 0 2500 800] + SymbolLine[0 2500 500 3000 800] + SymbolLine[500 3000 2000 3000 800] +) +Symbol[':' 1200] +( + SymbolLine[0 2500 500 2500 800] + SymbolLine[0 3500 500 3500 800] +) +Symbol[';' 1200] +( + SymbolLine[0 5000 1000 4000 800] + SymbolLine[1000 2500 1000 3000 800] +) +Symbol['<' 1200] +( + SymbolLine[0 3000 1000 2000 800] + SymbolLine[0 3000 1000 4000 800] +) +Symbol['=' 1200] +( + SymbolLine[0 2500 2000 2500 800] + SymbolLine[0 3500 2000 3500 800] +) +Symbol['>' 1200] +( + SymbolLine[0 2000 1000 3000 800] + SymbolLine[0 4000 1000 3000 800] +) +Symbol['?' 1200] +( + SymbolLine[1000 3000 1000 3500 800] + SymbolLine[1000 4500 1000 5000 800] + SymbolLine[0 1500 0 2000 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 1500 1000 800] + SymbolLine[1500 1000 2000 1500 800] + SymbolLine[2000 1500 2000 2000 800] + SymbolLine[1000 3000 2000 2000 800] +) +Symbol['@' 1200] +( + SymbolLine[0 1000 0 4000 800] + SymbolLine[0 4000 1000 5000 800] + SymbolLine[1000 5000 4000 5000 800] + SymbolLine[5000 3500 5000 1000 800] + SymbolLine[5000 1000 4000 0 800] + SymbolLine[4000 0 1000 0 800] + SymbolLine[1000 0 0 1000 800] + SymbolLine[1500 2000 1500 3000 800] + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[2000 3500 3000 3500 800] + SymbolLine[3000 3500 3500 3000 800] + SymbolLine[3500 3000 4000 3500 800] + SymbolLine[3500 3000 3500 1500 800] + SymbolLine[3500 2000 3000 1500 800] + SymbolLine[2000 1500 3000 1500 800] + SymbolLine[2000 1500 1500 2000 800] + SymbolLine[4000 3500 5000 3500 800] +) +Symbol['A' 1200] +( + SymbolLine[0 2000 0 5000 800] + SymbolLine[0 2000 700 1000 800] + SymbolLine[700 1000 1800 1000 800] + SymbolLine[1800 1000 2500 2000 800] + SymbolLine[2500 2000 2500 5000 800] + SymbolLine[0 3000 2500 3000 800] +) +Symbol['B' 1200] +( + SymbolLine[0 5000 2000 5000 800] + SymbolLine[2000 5000 2500 4500 800] + SymbolLine[2500 3300 2500 4500 800] + SymbolLine[2000 2800 2500 3300 800] + SymbolLine[500 2800 2000 2800 800] + SymbolLine[500 1000 500 5000 800] + SymbolLine[0 1000 2000 1000 800] + SymbolLine[2000 1000 2500 1500 800] + SymbolLine[2500 1500 2500 2300 800] + SymbolLine[2000 2800 2500 2300 800] +) +Symbol['C' 1200] +( + SymbolLine[700 5000 2000 5000 800] + SymbolLine[0 4300 700 5000 800] + SymbolLine[0 1700 0 4300 800] + SymbolLine[0 1700 700 1000 800] + SymbolLine[700 1000 2000 1000 800] +) +Symbol['D' 1200] +( + SymbolLine[500 1000 500 5000 800] + SymbolLine[1800 1000 2500 1700 800] + SymbolLine[2500 1700 2500 4300 800] + SymbolLine[1800 5000 2500 4300 800] + SymbolLine[0 5000 1800 5000 800] + SymbolLine[0 1000 1800 1000 800] +) +Symbol['E' 1200] +( + SymbolLine[0 2800 1500 2800 800] + SymbolLine[0 5000 2000 5000 800] + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 1000 2000 1000 800] +) +Symbol['F' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 1000 2000 1000 800] + SymbolLine[0 2800 1500 2800 800] +) +Symbol['G' 1200] +( + SymbolLine[2000 1000 2500 1500 800] + SymbolLine[500 1000 2000 1000 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[0 1500 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[500 5000 2000 5000 800] + SymbolLine[2000 5000 2500 4500 800] + SymbolLine[2500 3500 2500 4500 800] + SymbolLine[2000 3000 2500 3500 800] + SymbolLine[1000 3000 2000 3000 800] +) +Symbol['H' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[2500 1000 2500 5000 800] + SymbolLine[0 3000 2500 3000 800] +) +Symbol['I' 1200] +( + SymbolLine[0 1000 1000 1000 800] + SymbolLine[500 1000 500 5000 800] + SymbolLine[0 5000 1000 5000 800] +) +Symbol['J' 1200] +( + SymbolLine[700 1000 1500 1000 800] + SymbolLine[1500 1000 1500 4500 800] + SymbolLine[1000 5000 1500 4500 800] + SymbolLine[500 5000 1000 5000 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[0 4500 0 4000 800] +) +Symbol['K' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 3000 2000 1000 800] + SymbolLine[0 3000 2000 5000 800] +) +Symbol['L' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 5000 2000 5000 800] +) +Symbol['M' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 1000 1500 3000 800] + SymbolLine[1500 3000 3000 1000 800] + SymbolLine[3000 1000 3000 5000 800] +) +Symbol['N' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 1000 2500 5000 800] + SymbolLine[2500 1000 2500 5000 800] +) +Symbol['O' 1200] +( + SymbolLine[0 1500 0 4500 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 1500 1000 800] + SymbolLine[1500 1000 2000 1500 800] + SymbolLine[2000 1500 2000 4500 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[0 4500 500 5000 800] +) +Symbol['P' 1200] +( + SymbolLine[500 1000 500 5000 800] + SymbolLine[0 1000 2000 1000 800] + SymbolLine[2000 1000 2500 1500 800] + SymbolLine[2500 1500 2500 2500 800] + SymbolLine[2000 3000 2500 2500 800] + SymbolLine[500 3000 2000 3000 800] +) +Symbol['Q' 1200] +( + SymbolLine[0 1500 0 4500 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 1500 1000 800] + SymbolLine[1500 1000 2000 1500 800] + SymbolLine[2000 1500 2000 4000 800] + SymbolLine[1000 5000 2000 4000 800] + SymbolLine[500 5000 1000 5000 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[1000 3500 2000 5000 800] +) +Symbol['R' 1200] +( + SymbolLine[0 1000 2000 1000 800] + SymbolLine[2000 1000 2500 1500 800] + SymbolLine[2500 1500 2500 2500 800] + SymbolLine[2000 3000 2500 2500 800] + SymbolLine[500 3000 2000 3000 800] + SymbolLine[500 1000 500 5000 800] + SymbolLine[1300 3000 2500 5000 800] +) +Symbol['S' 1200] +( + SymbolLine[2000 1000 2500 1500 800] + SymbolLine[500 1000 2000 1000 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[0 1500 0 2500 800] + SymbolLine[0 2500 500 3000 800] + SymbolLine[500 3000 2000 3000 800] + SymbolLine[2000 3000 2500 3500 800] + SymbolLine[2500 3500 2500 4500 800] + SymbolLine[2000 5000 2500 4500 800] + SymbolLine[500 5000 2000 5000 800] + SymbolLine[0 4500 500 5000 800] +) +Symbol['T' 1200] +( + SymbolLine[0 1000 2000 1000 800] + SymbolLine[1000 1000 1000 5000 800] +) +Symbol['U' 1200] +( + SymbolLine[0 1000 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[2000 1000 2000 4500 800] +) +Symbol['V' 1200] +( + SymbolLine[0 1000 1000 5000 800] + SymbolLine[1000 5000 2000 1000 800] +) +Symbol['W' 1200] +( + SymbolLine[0 1000 0 3000 800] + SymbolLine[0 3000 500 5000 800] + SymbolLine[500 5000 1500 3000 800] + SymbolLine[1500 3000 2500 5000 800] + SymbolLine[2500 5000 3000 3000 800] + SymbolLine[3000 3000 3000 1000 800] +) +Symbol['X' 1200] +( + SymbolLine[0 5000 2500 1000 800] + SymbolLine[0 1000 2500 5000 800] +) +Symbol['Y' 1200] +( + SymbolLine[0 1000 1000 3000 800] + SymbolLine[1000 3000 2000 1000 800] + SymbolLine[1000 3000 1000 5000 800] +) +Symbol['Z' 1200] +( + SymbolLine[0 1000 2500 1000 800] + SymbolLine[0 5000 2500 1000 800] + SymbolLine[0 5000 2500 5000 800] +) +Symbol['[' 1200] +( + SymbolLine[0 1000 500 1000 800] + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 5000 500 5000 800] +) +Symbol['\' 1200] +( + SymbolLine[0 1500 3000 4500 800] +) +Symbol[']' 1200] +( + SymbolLine[0 1000 500 1000 800] + SymbolLine[500 1000 500 5000 800] + SymbolLine[0 5000 500 5000 800] +) +Symbol['^' 1200] +( + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 1000 1500 800] +) +Symbol['_' 1200] +( + SymbolLine[0 5000 2000 5000 800] +) +Symbol['a' 1200] +( + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[500 3000 1500 3000 800] + SymbolLine[0 3500 500 3000 800] + SymbolLine[0 3500 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[2000 3000 2000 4500 800] + SymbolLine[2000 4500 2500 5000 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[1500 5000 2000 4500 800] +) +Symbol['b' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[2000 3500 2000 4500 800] + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[500 3000 1500 3000 800] + SymbolLine[0 3500 500 3000 800] +) +Symbol['c' 1200] +( + SymbolLine[500 3000 2000 3000 800] + SymbolLine[0 3500 500 3000 800] + SymbolLine[0 3500 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[500 5000 2000 5000 800] +) +Symbol['d' 1200] +( + SymbolLine[2000 1000 2000 5000 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[0 3500 0 4500 800] + SymbolLine[0 3500 500 3000 800] + SymbolLine[500 3000 1500 3000 800] + SymbolLine[1500 3000 2000 3500 800] +) +Symbol['e' 1200] +( + SymbolLine[500 5000 2000 5000 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[0 3500 0 4500 800] + SymbolLine[0 3500 500 3000 800] + SymbolLine[500 3000 1500 3000 800] + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[0 4000 2000 4000 800] + SymbolLine[2000 4000 2000 3500 800] +) +Symbol['f' 1000] +( + SymbolLine[500 1500 500 5000 800] + SymbolLine[500 1500 1000 1000 800] + SymbolLine[1000 1000 1500 1000 800] + SymbolLine[0 3000 1000 3000 800] +) +Symbol['g' 1200] +( + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[500 3000 1500 3000 800] + SymbolLine[0 3500 500 3000 800] + SymbolLine[0 3500 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[0 6000 500 6500 800] + SymbolLine[500 6500 1500 6500 800] + SymbolLine[1500 6500 2000 6000 800] + SymbolLine[2000 3000 2000 6000 800] +) +Symbol['h' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 3500 500 3000 800] + SymbolLine[500 3000 1500 3000 800] + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[2000 3500 2000 5000 800] +) +Symbol['i' 1000] +( + SymbolLine[0 2000 0 2100 1000] + SymbolLine[0 3500 0 5000 800] +) +Symbol['j' 1000] +( + SymbolLine[500 2000 500 2100 1000] + SymbolLine[500 3500 500 6000 800] + SymbolLine[0 6500 500 6000 800] +) +Symbol['k' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 3500 1500 5000 800] + SymbolLine[0 3500 1000 2500 800] +) +Symbol['l' 1000] +( + SymbolLine[0 1000 0 4500 800] + SymbolLine[0 4500 500 5000 800] +) +Symbol['m' 1200] +( + SymbolLine[500 3500 500 5000 800] + SymbolLine[500 3500 1000 3000 800] + SymbolLine[1000 3000 1500 3000 800] + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[2000 3500 2000 5000 800] + SymbolLine[2000 3500 2500 3000 800] + SymbolLine[2500 3000 3000 3000 800] + SymbolLine[3000 3000 3500 3500 800] + SymbolLine[3500 3500 3500 5000 800] + SymbolLine[0 3000 500 3500 800] +) +Symbol['n' 1200] +( + SymbolLine[500 3500 500 5000 800] + SymbolLine[500 3500 1000 3000 800] + SymbolLine[1000 3000 1500 3000 800] + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[2000 3500 2000 5000 800] + SymbolLine[0 3000 500 3500 800] +) +Symbol['o' 1200] +( + SymbolLine[0 3500 0 4500 800] + SymbolLine[0 3500 500 3000 800] + SymbolLine[500 3000 1500 3000 800] + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[2000 3500 2000 4500 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[0 4500 500 5000 800] +) +Symbol['p' 1200] +( + SymbolLine[500 3500 500 6500 800] + SymbolLine[0 3000 500 3500 800] + SymbolLine[500 3500 1000 3000 800] + SymbolLine[1000 3000 2000 3000 800] + SymbolLine[2000 3000 2500 3500 800] + SymbolLine[2500 3500 2500 4500 800] + SymbolLine[2000 5000 2500 4500 800] + SymbolLine[1000 5000 2000 5000 800] + SymbolLine[500 4500 1000 5000 800] +) +Symbol['q' 1200] +( + SymbolLine[2000 3500 2000 6500 800] + SymbolLine[1500 3000 2000 3500 800] + SymbolLine[500 3000 1500 3000 800] + SymbolLine[0 3500 500 3000 800] + SymbolLine[0 3500 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[1500 5000 2000 4500 800] +) +Symbol['r' 1200] +( + SymbolLine[500 3500 500 5000 800] + SymbolLine[500 3500 1000 3000 800] + SymbolLine[1000 3000 2000 3000 800] + SymbolLine[0 3000 500 3500 800] +) +Symbol['s' 1200] +( + SymbolLine[500 5000 2000 5000 800] + SymbolLine[2000 5000 2500 4500 800] + SymbolLine[2000 4000 2500 4500 800] + SymbolLine[500 4000 2000 4000 800] + SymbolLine[0 3500 500 4000 800] + SymbolLine[0 3500 500 3000 800] + SymbolLine[500 3000 2000 3000 800] + SymbolLine[2000 3000 2500 3500 800] + SymbolLine[0 4500 500 5000 800] +) +Symbol['t' 1000] +( + SymbolLine[500 1000 500 4500 800] + SymbolLine[500 4500 1000 5000 800] + SymbolLine[0 2500 1000 2500 800] +) +Symbol['u' 1200] +( + SymbolLine[0 3000 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[2000 3000 2000 4500 800] +) +Symbol['v' 1200] +( + SymbolLine[0 3000 1000 5000 800] + SymbolLine[2000 3000 1000 5000 800] +) +Symbol['w' 1200] +( + SymbolLine[0 3000 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[500 5000 1000 5000 800] + SymbolLine[1000 5000 1500 4500 800] + SymbolLine[1500 3000 1500 4500 800] + SymbolLine[1500 4500 2000 5000 800] + SymbolLine[2000 5000 2500 5000 800] + SymbolLine[2500 5000 3000 4500 800] + SymbolLine[3000 3000 3000 4500 800] +) +Symbol['x' 1200] +( + SymbolLine[0 3000 2000 5000 800] + SymbolLine[0 5000 2000 3000 800] +) +Symbol['y' 1200] +( + SymbolLine[0 3000 0 4500 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[2000 3000 2000 6000 800] + SymbolLine[1500 6500 2000 6000 800] + SymbolLine[500 6500 1500 6500 800] + SymbolLine[0 6000 500 6500 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[1500 5000 2000 4500 800] +) +Symbol['z' 1200] +( + SymbolLine[0 3000 2000 3000 800] + SymbolLine[0 5000 2000 3000 800] + SymbolLine[0 5000 2000 5000 800] +) +Symbol['{' 1200] +( + SymbolLine[500 1500 1000 1000 800] + SymbolLine[500 1500 500 2500 800] + SymbolLine[0 3000 500 2500 800] + SymbolLine[0 3000 500 3500 800] + SymbolLine[500 3500 500 4500 800] + SymbolLine[500 4500 1000 5000 800] +) +Symbol['|' 1200] +( + SymbolLine[0 1000 0 5000 800] +) +Symbol['}' 1200] +( + SymbolLine[0 1000 500 1500 800] + SymbolLine[500 1500 500 2500 800] + SymbolLine[500 2500 1000 3000 800] + SymbolLine[500 3500 1000 3000 800] + SymbolLine[500 3500 500 4500 800] + SymbolLine[0 5000 500 4500 800] +) +Symbol['~' 1200] +( + SymbolLine[0 3500 500 3000 800] + SymbolLine[500 3000 1000 3000 800] + SymbolLine[1000 3000 1500 3500 800] + SymbolLine[1500 3500 2000 3500 800] + SymbolLine[2000 3500 2500 3000 800] +) +Attribute("PCB::grid::unit" "mil") +Via[220000 170000 7874 4000 0 3150 "" ""] + +Element["" "Power IC, as in MULTIWATT15" "" "HEPTAWATT" 143900 45000 -19900 -41500 0 100 ""] +( + Pin[6100 0 9000 3000 9600 6000 "1" "1" "square"] + Pin[-13900 -5000 9000 3000 9600 6000 "2" "2" ""] + Pin[6100 -10000 9000 3000 9600 6000 "3" "3" ""] + Pin[-13900 -15000 9000 3000 9600 6000 "4" "4" ""] + Pin[6100 -20000 9000 3000 9600 6000 "5" "5" ""] + Pin[-13900 -25000 9000 3000 9600 6000 "6" "6" ""] + Pin[6100 -30000 9000 3000 9600 6000 "7" "7" ""] + ElementLine [-24900 5400 -6000 5400 2000] + ElementLine [-6000 -35500 -6000 5400 2000] + ElementLine [-24900 -35500 -6000 -35500 2000] + ElementLine [-24900 -35500 -24900 5400 2000] + ElementLine [-19900 -35500 -19900 5400 1000] + ElementLine [-24900 -7500 -19900 -7500 1000] + ElementLine [-24900 -22500 -19900 -22500 1000] + + ) + +Element["" "Power IC, as in MULTIWATT15" "" "MULTIWATT11" 20000 38000 79500 -21000 3 100 ""] +( + Pin[0 12000 9000 3000 9600 6000 "1" "1" "square,edge2"] + Pin[6700 -8000 9000 3000 9600 6000 "2" "2" "edge2"] + Pin[13400 12000 9000 3000 9600 6000 "3" "3" "edge2"] + Pin[20100 -8000 9000 3000 9600 6000 "4" "4" "edge2"] + Pin[26800 12000 9000 3000 9600 6000 "5" "5" "edge2"] + Pin[33500 -8000 9000 3000 9600 6000 "6" "6" "edge2"] + Pin[40200 12000 9000 3000 9600 6000 "7" "7" "edge2"] + Pin[46900 -8000 9000 3000 9600 6000 "8" "8" "edge2"] + Pin[53600 12000 9000 3000 9600 6000 "9" "9" "edge2"] + Pin[60300 -8000 9000 3000 9600 6000 "10" "10" "edge2"] + Pin[67000 12000 9000 3000 9600 6000 "11" "11" "edge2"] + ElementLine [-6500 -26000 -6500 -6000 2000] + ElementLine [-6500 -6000 73500 -6000 2000] + ElementLine [73500 -6000 73500 -26000 2000] + ElementLine [73500 -26000 -6500 -26000 2000] + ElementLine [-6500 -21000 73500 -21000 1000] + ElementLine [26000 -26000 26000 -21000 1000] + ElementLine [41000 -26000 41000 -21000 1000] + + ) + +Element["" "Power IC, as in MULTIWATT15" "" "MULTIWATT15" 20000 98000 81000 -21000 3 100 ""] +( + Pin[0 12000 9000 3000 9600 6000 "1" "1" "square,edge2"] + Pin[5000 -8000 9000 3000 9600 6000 "2" "2" "edge2"] + Pin[10000 12000 9000 3000 9600 6000 "3" "3" "edge2"] + Pin[15000 -8000 9000 3000 9600 6000 "4" "4" "edge2"] + Pin[20000 12000 9000 3000 9600 6000 "5" "5" "edge2"] + Pin[25000 -8000 9000 3000 9600 6000 "6" "6" "edge2"] + Pin[30000 12000 9000 3000 9600 6000 "7" "7" "edge2"] + Pin[35000 -8000 9000 3000 9600 6000 "8" "8" "edge2"] + Pin[40000 12000 9000 3000 9600 6000 "9" "9" "edge2"] + Pin[45000 -8000 9000 3000 9600 6000 "10" "10" "edge2"] + Pin[50000 12000 9000 3000 9600 6000 "11" "11" "edge2"] + Pin[55000 -8000 9000 3000 9600 6000 "12" "12" "edge2"] + Pin[60000 12000 9000 3000 9600 6000 "13" "13" "edge2"] + Pin[65000 -8000 9000 3000 9600 6000 "14" "14" "edge2"] + Pin[70000 12000 9000 3000 9600 6000 "15" "15" "edge2"] + ElementLine [-5000 -26000 -5000 -6000 2000] + ElementLine [-5000 -6000 75000 -6000 2000] + ElementLine [75000 -6000 75000 -26000 2000] + ElementLine [75000 -26000 -5000 -26000 2000] + ElementLine [-5000 -21000 75000 -21000 1000] + ElementLine [27500 -26000 27500 -21000 1000] + ElementLine [42500 -26000 42500 -21000 1000] + + ) + +Element["" "Power IC, as in MULTIWATT15" "" "MULTIWATT8" 20000 164500 81000 -21000 3 100 ""] +( + Pin[0 -14500 9000 3000 9600 6000 "1" "1" "square,edge2"] + Pin[10000 -14500 9000 3000 9600 6000 "2" "2" "edge2"] + Pin[20000 -14500 9000 3000 9600 6000 "3" "3" "edge2"] + Pin[30000 -14500 9000 3000 9600 6000 "4" "4" "edge2"] + Pin[40000 -14500 9000 3000 9600 6000 "5" "5" "edge2"] + Pin[50000 -14500 9000 3000 9600 6000 "6" "6" "edge2"] + Pin[60000 -14500 9000 3000 9600 6000 "7" "7" "edge2"] + Pin[70000 -14500 9000 3000 9600 6000 "8" "8" "edge2"] + ElementLine [-5000 -26000 -5000 -6000 2000] + ElementLine [-5000 -6000 75000 -6000 2000] + ElementLine [75000 -6000 75000 -26000 2000] + ElementLine [75000 -26000 -5000 -26000 2000] + ElementLine [-5000 -21000 75000 -21000 1000] + ElementLine [27500 -26000 27500 -21000 1000] + ElementLine [42500 -26000 42500 -21000 1000] + + ) + +Element["" "Crystal oscillator" "" "OSC14" 130000 110000 20000 -17000 0 100 ""] +( + Pin[0 0 5000 3000 5600 2800 "NC" "1" "edge2"] + Pin[60000 0 5000 3000 5600 2800 "GND" "2" "edge2"] + Pin[60000 -30000 5000 3000 5600 2800 "CLK" "3" "edge2"] + Pin[0 -30000 5000 3000 5600 2800 "VCC" "4" "edge2"] + ElementLine [-9500 -30000 -9500 9500 1000] + ElementLine [0 -39500 60000 -39500 1000] + ElementLine [69500 -30000 69500 0 1000] + ElementLine [-9500 9500 60000 9500 1000] + ElementLine [-4000 -30000 -4000 0 1000] + ElementLine [0 -34000 60000 -34000 1000] + ElementLine [64000 -30000 64000 0 1000] + ElementLine [0 4000 60000 4000 1000] + ElementArc [0 -30000 9500 9500 270 90 1000] + ElementArc [60000 -30000 9500 9500 180 90 1000] + ElementArc [60000 0 9500 9500 90 90 1000] + ElementArc [0 -30000 4000 4000 270 90 1000] + ElementArc [60000 -30000 4000 4000 180 90 1000] + ElementArc [60000 0 4000 4000 90 90 1000] + ElementArc [0 0 4000 4000 0 90 1000] + + ) + +Element["" "Power IC, as in MULTIWATT15" "" "PENTAWATT" 197200 46700 -19900 -39900 0 100 ""] +( + Pin[8500 0 9000 3000 9600 6000 "1" "1" "square"] + Pin[-7200 -6700 9000 3000 9600 6000 "2" "2" ""] + Pin[8500 -13400 9000 3000 9600 6000 "3" "3" ""] + Pin[-7200 -20100 9000 3000 9600 6000 "4" "4" ""] + Pin[8500 -26800 9000 3000 9600 6000 "5" "5" ""] + ElementLine [-24900 7000 -6000 7000 2000] + ElementLine [-6000 -33900 -6000 7000 2000] + ElementLine [-24900 -33900 -6000 -33900 2000] + ElementLine [-24900 -33900 -24900 7000 2000] + ElementLine [-19900 -33900 -19900 7000 1000] + ElementLine [-24900 -5900 -19900 -5900 1000] + ElementLine [-24900 -20900 -19900 -20900 1000] + + ) + +Element["" "" "" "" 160000 150000 -12500 -9000 0 100 ""] +( + Pin[13091 9000 9000 5000 9600 3937 "" "4" "edge2,intconn(2)"] + Pin[-12500 9000 9000 5000 9600 3937 "" "3" "edge2,intconn(2)"] + Pin[13091 -9000 9000 5000 9600 3937 "" "2" "edge2,intconn(1)"] + Pin[-12500 -9000 9000 5000 9600 3937 "" "1" "edge2,intconn(1)"] + ElementLine [12181 11736 12181 -11886 787] + ElementLine [-11441 11736 12181 11736 787] + ElementLine [-11441 -11886 -11441 11736 787] + ElementLine [-11441 -11886 12181 -11886 787] + ElementArc [7815 -8031 2756 2756 90 90 787] + ElementArc [7815 -8031 2756 2756 0 90 787] + ElementArc [7815 -8031 2756 2756 270 90 787] + ElementArc [7815 -8031 2756 2756 180 90 787] + ElementArc [7815 7717 2756 2756 0 90 787] + ElementArc [7815 7717 2756 2756 270 90 787] + ElementArc [7815 7717 2756 2756 180 90 787] + ElementArc [7815 7717 2756 2756 90 90 787] + ElementArc [-7933 7717 2756 2756 270 90 787] + ElementArc [-7933 7717 2756 2756 180 90 787] + ElementArc [-7933 7717 2756 2756 90 90 787] + ElementArc [-7933 7717 2756 2756 0 90 787] + ElementArc [-7933 -8031 2756 2756 180 90 787] + ElementArc [-7933 -8031 2756 2756 90 90 787] + ElementArc [-7933 -8031 2756 2756 0 90 787] + ElementArc [-7933 -8031 2756 2756 270 90 787] + ElementArc [-59 -157 6693 6693 270 90 787] + ElementArc [-59 -157 6693 6693 180 90 787] + ElementArc [-59 -157 6693 6693 90 90 787] + ElementArc [-59 -157 6693 6693 0 90 787] + + ) +Layer(1 "component") +( +) +Layer(2 "solder") +( +) +Layer(3 "comp-GND") +( +) +Layer(4 "comp-power") +( +) +Layer(5 "sold-GND") +( +) +Layer(6 "sold-power") +( +) +Layer(7 "signal3") +( +) +Layer(8 "outline") +( +) +Layer(9 "silk") +( +) +Layer(10 "silk") +( +) Index: tags/2.1.2/util/pcblib-param.cgi =================================================================== --- tags/2.1.2/util/pcblib-param.cgi (nonexistent) +++ tags/2.1.2/util/pcblib-param.cgi (revision 24813) @@ -0,0 +1,480 @@ +#!/bin/bash + +ulimit -t 5 +ulimit -v 80000 + +# read the config +. /etc/pcblib.cgi.conf +CGI=$CGI_param + +# import the lib +. $pcb_rnd_util/cgi_common.sh + +gen() +{ + cd $gendir + params=`echo $QS_cmd | sed "s/.*[(]//;s/[)]//" ` + ./$gen "$params" +} + +help_params() +{ +awk -v "CGI=$CGI" "$@" ' +BEGIN { + prm=0 + q="\"" + fp_base=fp + sub("[(].*", "", fp_base) + thumbsize=1 +} + +function urlencode(s) +{ + gsub("[#]", "%23", s) + return s +} + +function proc_include(fn) +{ + close(fn) + while(getline < fn) + proc_line() + close(fn) +} + +function proc_line() +{ + if (/^[^\"]*@@include/) { + proc_include(gendir $2) + return + } + + if ((match($0, "@@desc") || match($0, "@@params") || match($0, "@@purpose") || match($0, "@@example"))) { + txt=$0 + key=substr($0, RSTART, RLENGTH) + sub(".*" key "[ \t]*", "", txt) + HELP[key] = HELP[key] " " txt + next + } + + if (/@@thumbsize/) { + sub(".*@@thumbsize", "", $0) + if ($1 ~ ":") { + sub("^:", "", $1) + PDATA[$1,"thumbsize"] = $2 + } + else + thumbsize=$1 + return + } + + if (/@@thumbnum/) { + sub(".*@@thumbnum", "", $0) + if ($1 ~ ":") { + sub("^:", "", $1) + PDATA[$1,"thumbnum"] = $2 + } + return + } + + if (/@@param:/) { + sub(".*@@param:", "", $0) + p=$1 + sub(p "[\t ]*", "", $0) + PARAM[prm] = p + PDESC[prm] = $0 + prm++ + return + } + +# build PPROP[paramname,propname], e.g. PPROP[pin_mask, dim]=1 + if (/@@optional:/ || /@@dim:/ || /@@bool:/) { + key = $0 + sub("^.*@@", "", key) + val = key + sub(":.*", "", key) + sub("^[^:]*:", "", val) + PPROP[val,key] = 1 + return + } + +# build PDATA[paramname,propname], e.g. PDATA[pin_mask, default]=123 + if ((/@@default:/) || (/@@preview_args:/)) { + key = $1 + + txt = $0 + txt = substr(txt, length(key)+1, length(txt)) + sub("^[ \t]*", "", txt) + + sub("^.*@@", "", key) + val = key + sub(":.*", "", key) + sub("^[^:]*:", "", val) + PDATA[val,key] = txt + return + } + +# build: +# PDATAK[paramname,n]=key (name of the value) +# PDATAV[paramname,n]=description (of the given value) +# PDATAN[paramname]=n number of parameter values + if (/@@enum:/) { + key = $1 + + txt = $0 + txt = substr(txt, length(key)+1, length(txt)) + sub("^[ \t]*", "", txt) + + sub("^.*@@enum:", "", key) + val = key + sub(":.*", "", key) + sub("^[^:]*:", "", val) + idx = int(PDATAN[key]) + PDATAK[key,idx] = val + PDATAV[key,idx] = txt + PDATAN[key]++ + return + } +} + +{ proc_line() } + +function thumb(prv, gthumbsize, lthumbsize, thumbnum ,lnk,lnk_gen, thumbsize,ann) +{ + if (lthumbsize != "") + thumbsize = lthumbsize + else + thumbsize = gthumbsize + if (!thumbnum) + ann="&annotation=none" + lnk=q CGI "?cmd=" prv "&output=png&grid=none" ann "&thumb=" thumbsize q + lnk_gen=q CGI "?cmd=" prv q + print "" + print "" + print "" +} + +END { + if (header) { + print "" HELP["@@purpose"] "" + print "

    " + print HELP["@@desc"] + } + + if (content) + print "

    " content "

    " + + if ((print_params) && (HELP["@@params"] != "")) + print "

    Ordered list (positions): " HELP["@@params"] + + + if (content) { + print "" + print "
    name man
    dat
    ory
    description value (bold: default)" + for(p = 0; p < prm; p++) { + name=PARAM[p] + print "
    " name + if (PPROP[name, "optional"]) + print "  " + else + print " yes" + print "" PDESC[p] + print "" + vdone=0 + if (PDATAN[name] > 0) { + print "" + for(v = 0; v < PDATAN[name]; v++) { + print "
    " + isdef = (PDATA[name, "default"] == PDATAK[name, v]) + if (isdef) + print "" + print PDATAK[name, v] + if (isdef) + print "" + + print "" PDATAV[name, v] + if (PDATA[name, "preview_args"] != "") { + prv= fp_base "(" PDATA[name, "preview_args"] "," name "=" PDATAK[name, v] ")" + print "" + thumb(prv, thumbsize, PDATA[name, "thumbsize"], PDATA[name, "thumbnum"]) + } + } + print "
    " + vdone++ + } + if (PPROP[name, "dim"]) { + print "Dimension: a number with an optional unit (mm or mil, default is mil)" + if (PDATA[name, "default"] != "") + print "
    Default: " PDATA[name, "default"] "" + vdone++ + } + if (PPROP[name, "bool"]) { + print "Boolean: yes/no, true/false, 1/0" + if (PDATA[name, "default"] != "") + print "; Default: " PDATA[name, "default"] "" + if (PDATA[name, "preview_args"] != "") { + print "
    " + print "" + print "
    true:" + thumb(fp_base "(" PDATA[name, "preview_args"] "," name "=" 1 ")", thumbsize, PDATA[name, "thumbsize"], PDATA[name, "thumbnum"]) + print "false:" + thumb(fp_base "(" PDATA[name, "preview_args"] "," name "=" 0 ")", thumbsize, PDATA[name, "thumbsize"], PDATA[name, "thumbnum"]) + print "
    " + } + } + if (!vdone) + print " " + } + print "
    " + } + + if (footer) { + print "

    Example

    " + print "" + print HELP["@@example"] + print "" + print "" + } +} +' +} + +help() +{ + local incl n + echo " + + +

    pcblib-param help for $QS_cmd()

    +" + + incl=`tempfile` + + +# generate the table + help_params -v "fp=$QS_cmd" -v "header=1" -v "content=$gen parameters" -v "print_params=1" -v "gendir=$gendir" < $gendir/$gen + +# generate the footer + help_params -v "fp=$QS_cmd" -v "footer=1" -v "gendir=$gendir" < $gendir/$gen 2>/dev/null + +} + +list_gens() +{ + awk -v "CGI=$CGI" ' + BEGIN { + q="\"" + } + /@@purpose/ { + sub(".*@@purpose", "", $0) + PURPOSE[FILENAME] = PURPOSE[FILENAME] $0 + next + } + /@@example/ { + sub(".*@@example", "", $0) + EXAMPLE[FILENAME] = EXAMPLE[FILENAME] $0 + next + } + + /@@params/ { + sub(".*@@params", "", $0) + PARAMS[FILENAME] = PARAMS[FILENAME] $0 + next + } + + function urlencode(s) + { + gsub("[#]", "%23", s) + return s + } + + END { + for(fn in PURPOSE) { + gn=fn + sub(".*/", "", gn) + params=PARAMS[fn] + sub("^[ \t]*", "", params) + sub("[ \t]*$", "", params) + print "
  • " gn "(" params ") - " PURPOSE[fn] + print "- HELP " + } + } + ' $gendir/* +} + +qs=`echo "$QUERY_STRING" | tr "&" "\n"` + +for n in $qs +do + exp="QS_$n" + export $exp +done + +export QS_cmd=`echo "$QS_cmd" | url_decode` + +if test -z "$QS_cmd" +then + export QS_cmd='connector(2,3)' + export QS_diamond=1 + gen=connector +else + gen=`awk -v "n=$QS_cmd" ' + BEGIN { + sub("[(].*", "", n) + gsub("[^a-zA-Z0-9_]", "", n) + print n + } + '` + + ptmp=`grep "@@purpose" $gendir/$gen` + if test -z "$ptmp" + then + error "Invalid generator \"$gen\" (file)" + fi +fi + + +if test "$QS_output" = "help" +then + echo "Content-type: text/html" + echo "" + help + exit +fi + +fptext=`gen` +if test ! "$?" = 0 +then + echo "Content-type: text/plain" + echo "" + echo "Error generating the footprint:" + gen 2>&1 | grep -i error + exit +fi + +if test "$QS_output" = "text" +then + echo "Content-type: text/plain" + echo "" + gen + exit +fi + +if test "$QS_output" = "png" +then + cgi_png + exit +fi + +echo "Content-type: text/html" +echo "" + +echo "" +echo "" +echo "

    pcblib-param test page

    " +echo ' + + +
    + +"Do you remember the good old days? When I was +
    young, I said footprint=CONNECTOR 2 13 +
    in gschem and got a 2*13 pin connector in PCB."
    +
    + +
     
      +

    + + + +
    +

    Syntax

    +

    +In pcb-rnd, +automatic footprint generation on the fly is called "parametric +footprints". It is a smaller and more generic infrastructure compared +to the m4 footprints in pcb. The goal was to fix three problems. +

      +
    • 1. Languages: m4 should not be mandatory for footprint generators - the user should be free to choose any language +
    • 2. Simplicity: references to m4 should not be hardwired in pcb, gsch2pcb and gsch2pcb.scm, but footprint generation should be generic, transparent and external +
    • 3. Unambiguity: gsch2pcb should not be guessing whether to use file elements or call a generator. Instead of complex heuristics, there should be a simple, distinct syntax for parametric footprints. +
    +

    +The new syntax is that if a footprint attribute contains parenthesis, it is +a parametric footprint, else it is a file footprint. Parametric footprints +are sort of a function call. The actual syntax is similar to the one in + openscad : +parameters are separated by commas, and they are either positional (value) +or named (name=value). +

    +For example a simple pin-grid +connector has the "prototype" of connector(nx, ny, spacing), where +nx and ny are the number of pins needed in X and Y directions, spacing is +the distance between pin centers, with a default of 100 mil. The following +calls will output the same 2*3 pin, 100 mil footprint: +

      +
    • connector(2, 3) +
    • connector(2, 3, 100) +
    • connector(nx=2, ny=3, spacing=100) +
    • connector(spacing=100, nx=2, ny=3) +
    • connector(ny=3, spacing=100, nx=2) +
    + +
        + +

    Generators available

    +
      +' +list_gens +echo ' +
    +
    +' + + +echo "

    Try it online

    " +echo "source:" + +echo "
    " +echo "" +echo "
      " +echo "
    • draw grid in mm" +echo "
    • draw in \"photo mode\"" +echo "
    • diamond at origin" +echo "
    • annotate pin names" +echo "
    • annotate dimension names" +echo "
    • annotate dimension values (in grid units)" +echo "
    • lighten annotataion background" +echo "
    " +echo "

    " +echo "" +echo "

    " + + + +QS_format=${QS_cmd##*_} +QS_cmd_=${QS_cmd%%_*} + +if test ! -z "$QS_cmd" +then +echo "

    Result

    " + echo "

    $QS_cmd

    " + + echo "" + echo "
    " + echo "" + + echo "     " + + echo "" + echo "
    "
    +	echo "$fptext"
    +	echo "
    " + echo "

    Downloads:" + echo "
    footprint file" + echo "

    " +fi + + +echo "" +echo "" Property changes on: tags/2.1.2/util/pcblib-param.cgi ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/2.1.2/util/pcblib-static.cgi =================================================================== --- tags/2.1.2/util/pcblib-static.cgi (nonexistent) +++ tags/2.1.2/util/pcblib-static.cgi (revision 24813) @@ -0,0 +1,237 @@ +#!/bin/bash + +ulimit -t 5 +ulimit -v 80000 + +# read the config +. /etc/pcblib.cgi.conf +CGI=$CGI_static + +# import the lib +. $pcb_rnd_util/cgi_common.sh + +find_fp() +{ + awk -v "fp=$QS_fp" -v "fpdir=$fpdir" ' + BEGIN { + fp=tolower(fp) + } + ($1 == "S") { + n=tolower($2) + sub("^.*/", "", n) + sub(".fp$", "", n) + sub(".ele$", "", n) + if (n == fp) { + print fpdir $2 + exit + } + } + ' < $sdir/cache +} + +list_fps() +{ + find $fpdir | awk -v "fpdir=$fpdir" -v "CGI=$CGI" ' + /.svn/ { next } + /parametric/ { next } + + { + name=$0 + sub(fpdir, "", name) + if (!(name ~ "/")) + next + dir=name + fn=name + sub("/.*", "", dir) + sub("^[^/]*/", "", fn) + vfn = fn + sub(".fp$", "", vfn) + + LLEN[dir] += length(vfn) + + vfn = "" vfn "" + + if (LLEN[dir] > 8) { + LLEN[dir] = 0 + sep = "
    " + } + else + sep = " " + if (DIR[dir] != "") + DIR[dir] = DIR[dir] sep vfn + else + DIR[dir] = vfn + } + + END { + print "" + print "" + for(n in DIR) + print "" + for(n in DIR) + print "
    " n + print "
    " DIR[n] + print "
    " + } + ' +} + +qs=`echo "$QUERY_STRING" | tr "&" "\n"` + +for n in $qs +do + exp="QS_$n" + export $exp +done + +export QS_cmd=`echo "$QS_cmd" | url_decode` + +if test -z "$QS_fp" +then + export QS_fp='TO220' + export QS_diamond=1 + gen=connector +fi + +fn=`find_fp` +if test ! "$?" = 0 +then + echo "Content-type: text/plain" + echo "" + echo "Error: couldn't find $QS_fp" + exit +fi + +fptext=`cat $fn` +if test ! "$?" = 0 +then + echo "Content-type: text/plain" + echo "" + echo "Error reading footprint file for $QS_fp $fn" + exit +fi + +if test "$QS_output" = "text" +then + echo "Content-type: text/plain" + echo "" + echo "$fptext" + exit +fi + +if test "$QS_output" = "png" +then + echo "Content-type: image/png" + echo "" + cparm="" + if test ! -z "$QS_mm" + then + cparm="$cparm --mm" + fi + if test ! -z "$QS_diamond" + then + cparm="$cparm --diamond" + fi + if test ! -z "$QS_photo" + then + cparm="$cparm --photo" + fi + (echo "$fptext" | $fp2anim $cparm; echo 'screenshot "/dev/stdout"') | $animator -H + exit +fi + +echo "Content-type: text/html" +echo "" + +echo "" +echo "" +echo "

    pcblib-static browse page

    " +echo ' + + +
    + +An outburst while looking for a powerjack connector
    +footprint in the stock library:
    +"What on earth is an MSP430F1121 footprint and
    +why do I need it in the default library?!"
    +
    + +
     
      +

    + + + +
    +

    pcblib

    +

    +The default library in pcb-rnd +is called the "pcblib" (lib and newlib are already used by vanilla pcb). +Pcblib content consists of +parametric (generated) footprints +and static footprints ("file elements"). This page queries static footprints. +

    +The goal of pcblib is to ship a minimalistic library of the real essential +parts, targeting small projects and hobbysts. Pcblib assumes users can +grow their own library by downloading footprints from various online sources +(e.g. gedasymbols) or draw their own +as needed. Thus instead of trying to be a complete collection of footprints +ever drawn, it tries to collect the common base so that it is likely that 90% +of pcblib users will use 90% of the footprints in their projects. + +

        + +

    List of static footprints

    +
      +' + + +list_fps + +echo ' +
    +
    +' + + +echo "

    Search and preview

    " + +echo "
    " +echo "name: " +echo "
      " +echo "
    • draw grid in mm" +echo "
    • draw in \"photo mode\"" +echo "
    • diamond at origin" +echo "
    " +echo "

    " +echo "" +echo "

    " + + + +QS_format=${QS_cmd##*_} +QS_fp_=${QS_cmd%%_*} + +if test ! -z "$QS_fp" +then +echo "

    Result

    " + echo "

    $QS_fp

    " + + echo "" + echo "
    " + echo "" + + echo "     " + + echo "" + echo "
    "
    +	echo "$fptext"
    +	echo "
    " + echo "

    Downloads:" + echo "
    footprint file" + echo "

    " +fi + + +echo "" +echo "" Property changes on: tags/2.1.2/util/pcblib-static.cgi ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/2.1.2/util/pcblib.cgi.conf =================================================================== --- tags/2.1.2/util/pcblib.cgi.conf (nonexistent) +++ tags/2.1.2/util/pcblib.cgi.conf (revision 24813) @@ -0,0 +1,34 @@ +# shell syntax + +### change these to reflect your installation ### + +# absolute path to the trunk directory of the pcb-rnd checkout from +# svn://repo.hu/pcb-rnd/trunk +pcb_rnd_trunk=/home/igor2/C/pcb-rnd + +# CGI url to use for self-reference when generating html pages; +# this should be a relative URL +CGI_param=/cgi-bin/pcblib-param.cgi +CGI_static=/cgi-bin/pcblib-static.cgi + +# the executable file name of animator +animator=/usr/local/bin/animator + +# pcblib-static.cgi: absolute path to the map directory that is put +# online (svn://repo.hu/pcb-rnd/trunk/util/pcblib-map) +# NOTE: run make there after the checkout or an update +sdir=/var/www/tmp/pcblib + +### these are less likely to change ### + +# absolute path to util/ under the trunk checkout +pcb_rnd_util=$pcb_rnd_trunk/util + +# absolute path to the footprint generators - has to end with / +gendir=$pcb_rnd_trunk/pcblib/parametric/ + +# absolute path to the root of the static footprint tree - has to end with / +fpdir=$pcb_rnd_trunk/pcblib/ + +# absolute path to the fp2anim script +fp2anim=$pcb_rnd_util/fp2anim Property changes on: tags/2.1.2/util/pcblib.cgi.conf ___________________________________________________________________ Added: svn:mergeinfo ## -0,0 +0,0 ## Index: tags/2.1.2/util/workarounds/unwarn.sh =================================================================== --- tags/2.1.2/util/workarounds/unwarn.sh (nonexistent) +++ tags/2.1.2/util/workarounds/unwarn.sh (revision 24813) @@ -0,0 +1,15 @@ +#!/bin/sh + +# This file is placed in the Public Domain. + +# Comment all #warnings in a file given as $1. +# Useful on systems with CC with no support for #warning. + +sed ' + /^#[ \t]*warning.*/ { + s@^@TODO("@ + s@$@")@ + s@ *TODO:@:@ + s@#[ \t]*warning *@@ + } +' < "$1" > "$1.tmp" && mv "$1.tmp" "$1" Property changes on: tags/2.1.2/util/workarounds/unwarn.sh ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/2.1.2/util/workarounds/unwarn_all.sh =================================================================== --- tags/2.1.2/util/workarounds/unwarn_all.sh (nonexistent) +++ tags/2.1.2/util/workarounds/unwarn_all.sh (revision 24813) @@ -0,0 +1,10 @@ +#!/bin/sh + +# This file is placed in the Public Domain. + +# Comment all #warnings in all .h and .c files, recursively. +# Useful on systems with CC with no support for #warning. + +action=`echo "$0" | sed "s/_all//"` + +find . -name '*.[ch]' -exec $action {} \; Property changes on: tags/2.1.2/util/workarounds/unwarn_all.sh ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property